+
question_mark
Will the stateManager be out-of-date? The stateManager automatically updates its state when a packet is received or sent, so no, you do not have to worry about out-of-date information being stored.
diff --git a/src/lib/taDocs/2-stateManager-allFunctions.md b/src/lib/taDocs/2-stateManager-allFunctions.md
new file mode 100644
index 0000000..38ab6cc
--- /dev/null
+++ b/src/lib/taDocs/2-stateManager-allFunctions.md
@@ -0,0 +1,38 @@
+# All of the methods of the StateManager
+
+Below you can find a table that shows all of the methods of the stateManager.
+| taClient.stateManager. (method) | Purpose and functionality | Is Async |
+|:----------------------------------:|:--------------------------|:--------:|
+|emit()|Emit a custom event. Only use this if you know what you are doing.|True|
+|getKnownServers()|Get the known servers which have been sent in the connect state. **This is a cached list.**|False|
+|getMatch()|Get the details of a match.|False|
+|getMatches()|Get an array of all of the matches in a tournament.|False|
+|getQualifier()|Get the details of a qualifier event.|False|
+|getQualifiers()|Get an array of all of the qualifiers in a tournament.|False|
+|getSelfGuid()|Get the `.guid` property of the currently logged in user or bot token.|False|
+|getTournament()|Get the information about a tournament.|False|
+|getTournaments()|Get an array of all of the tournaments of a Core Server|False|
+|getUser()|Get all of the details of a user in a tournament.|False|
+|getUsers()|Get an array of all of the users in a tournament.|False|
+|handlePacket()|Handle the response to a packet sent to you by the TA Core Server. Only use if you know what you are doing.|False|
+|on()|Standard listener for the taClient. This is how real time score can be subscribed to.|False|
+|once()|This is essentially the same as `taClient.stateManager.on()` except it unsubscribes after the first event.|False|
+|removeListener()|Unsibscribe from the events that you have started to listen to.|False|
+
+## How to listen, what is the general schema?
+Generally, the format is just:
+```ts
+taClient.stateManager.on('eventType', () => {
+ // callback function
+})
+```
+or
+```ts
+async function handleEvent(params) {
+ // code here
+}
+
+taClient.stateManager.on('eventType', handleEvent);
+```
+
+All of the event types and how to handle them are within this State Manager section.
\ No newline at end of file
diff --git a/src/lib/taDocs/2-stateManager-emit.md b/src/lib/taDocs/2-stateManager-emit.md
new file mode 100644
index 0000000..ae6be89
--- /dev/null
+++ b/src/lib/taDocs/2-stateManager-emit.md
@@ -0,0 +1,15 @@
+# The stateManager.emit() method
+
+
+
info
+
+ Async: This is a method you would want to use await with
+
+
+
+## General usage:
+```ts
+await taClient.stateManager.emit('eventType', params);
+```
+
+I will not proide further documentation for this method, as it should NOT be used. Every way you could use it exists with another method.
\ No newline at end of file
diff --git a/src/lib/taDocs/2-stateManager-getKnownServers.md b/src/lib/taDocs/2-stateManager-getKnownServers.md
new file mode 100644
index 0000000..f186197
--- /dev/null
+++ b/src/lib/taDocs/2-stateManager-getKnownServers.md
@@ -0,0 +1,31 @@
+# The stateManager.getKnownServers() method
+This documents the `stateManager.getKnownServers() method.`
+
+## General usage:
+```ts
+const servers: CoreServer[] = taClient.stateManager.getKnownServers();
+```
+
+This method will return an array of the known `CoreServer`s. A `CoreServer` can be described by the following TypeScript Interface:
+```ts
+interface CoreServer {
+ /**
+ * @generated from protobuf field: string name = 1;
+ */
+ name: string;
+ /**
+ * @generated from protobuf field: string address = 2;
+ */
+ address: string;
+ /**
+ * @generated from protobuf field: int32 port = 3;
+ */
+ port: number;
+ /**
+ * @generated from protobuf field: int32 websocket_port = 4;
+ */
+ websocketPort: number;
+}
+```
+
+This means that a `CoreServer` has a `name`(such as 'Default Server' in the case of the default server), an `address`('server.tournamentassistant.net' in the case of the default server), a `port` which the players connect to(8675 by default), and a `websocketPort` to which coordinators, overlays and the client connects to(by default 8676)
\ No newline at end of file
diff --git a/src/lib/taDocs/2-stateManager-getMatch.md b/src/lib/taDocs/2-stateManager-getMatch.md
new file mode 100644
index 0000000..59d9103
--- /dev/null
+++ b/src/lib/taDocs/2-stateManager-getMatch.md
@@ -0,0 +1,84 @@
+# The stateManager.getMatch() method
+This documents the `stateManager.getMatch()` method.
+
+This method has input parameters. The function could easily be defined as:
+```ts
+function getMatch(tournamentGuid: string, matchGuid: string): Match | undefined {
+ // backend logic
+}
+```
+## General usage:
+```ts
+const matchResponse: Match | undefined = taClient.stateManager.getMatch(tournamentGuid, matchGuid);
+```
+
+This method will return either the `Match` object or undefined. A `Match` can be described by the following TypeScript Interface:
+```ts
+interface Match {
+ /**
+ * @generated from protobuf field: string guid = 1;
+ */
+ guid: string;
+ /**
+ * @generated from protobuf field: repeated string associated_users = 2;
+ */
+ associatedUsers: string[];
+ /**
+ * @generated from protobuf field: string leader = 3;
+ */
+ leader: string;
+ /**
+ * @generated from protobuf field: proto.models.Map selected_map = 4;
+ */
+ selectedMap?: Map;
+}
+```
+
+For the definition of a Map please look at the [Modals -> Map page](/documentation#Modals/4-Map)
+
+A direct implementation:
+```ts
+try {
+ // Check if the client is connected, connect to the server if not
+ if(!client.isConnected) {
+ // Connec to the server
+ const connectResult = await client.connect($TAServerUrl, $TAServerPort);
+ // Check if the connection is successful
+ if (connectResult.details.oneofKind === "connect" && connectResult.type === Response_ResponseType.Fail) {
+ throw new Error(connectResult.details.connect.message);
+ }
+ }
+
+ // Get tournament and match data
+ tournament = client.stateManager.getTournament(tournamentGuid);
+
+ // This is the implementation, we just set the match object to the one we neem
+ match = client.stateManager.getMatch(tournamentGuid, matchGuid);
+
+ // Check if the logged in coordinator or user is added to the match properly
+ if(!match?.associatedUsers.includes(client.stateManager.getSelfGuid())) {
+ // If not, add the user to the match
+ await addSelfToMatch();
+ }
+
+ // Check to see if we are actually viewing a valid match
+ if (!match) {
+ throw new Error('Match not found');
+ }
+
+ // This function just does some magic with the beatsaver data of the currently selected map
+ await refreshMatchDetails(match);
+} catch (err) {
+ console.error('Error fetching match data:', err);
+ error = err instanceof Error ? err.message : 'An unknown error occurred';
+} finally {
+ // Stop loading the page and allow everything to show data without errors
+ isLoading = false;
+}
+```
+
+
info
+
+ Example: This is an example from the page of ShyyTAUI within the match coorination page.
+
+
\ No newline at end of file
diff --git a/src/lib/taDocs/2-stateManager-getMatches.md b/src/lib/taDocs/2-stateManager-getMatches.md
new file mode 100644
index 0000000..c67c8f6
--- /dev/null
+++ b/src/lib/taDocs/2-stateManager-getMatches.md
@@ -0,0 +1,37 @@
+# The stateManager.getMatches() method
+This documents the `stateManager.getMatches()` method.
+
+This method has input parameters. The function could easily be defined as:
+```ts
+function getMatches(tournamentGuid: string,): Match[] | undefined {
+ // backend logic
+}
+```
+## General usage:
+```ts
+const matchesResponse: Match[] | undefined = taClient.stateManager.getMatches(tournamentGuid);
+```
+
+This method will return either an array of the `Match` object or undefined. A `Match` can be described by the following TypeScript Interface:
+```ts
+interface Match {
+ /**
+ * @generated from protobuf field: string guid = 1;
+ */
+ guid: string;
+ /**
+ * @generated from protobuf field: repeated string associated_users = 2;
+ */
+ associatedUsers: string[];
+ /**
+ * @generated from protobuf field: string leader = 3;
+ */
+ leader: string;
+ /**
+ * @generated from protobuf field: proto.models.Map selected_map = 4;
+ */
+ selectedMap?: Map;
+}
+```
+
+For the definition of a Map please look at the [Modals -> Map page](/documentation#Modals/4-Map)
\ No newline at end of file
diff --git a/src/lib/taDocs/2-stateManager-getQualifier.md b/src/lib/taDocs/2-stateManager-getQualifier.md
new file mode 100644
index 0000000..ec8e6e8
--- /dev/null
+++ b/src/lib/taDocs/2-stateManager-getQualifier.md
@@ -0,0 +1,65 @@
+# The stateManager.getQualifier() method
+This documents the `stateManager.getQualifier()` method.
+
+This method has input parameters. The function could easily be defined as:
+```ts
+function getQualifier(tournamentGuid: string, qualifierGuid: string): QualifierEvent | undefined {
+ // backend logic
+}
+```
+## General usage:
+```ts
+const qualifier: QualifierEvent | undefined = taClient.stateManager.getQualifier(tournamentGuid, qualifierGuid);
+```
+
+This method will return either the `QualifierEvent` object or undefined. A `QualifierEvent` can be described by the following TypeScript Interface:
+```ts
+interface QualifierEvent {
+ /**
+ * @generated from protobuf field: string guid = 1;
+ */
+ guid: string;
+ /**
+ * @generated from protobuf field: string name = 2;
+ */
+ name: string;
+ /**
+ * @generated from protobuf field: bytes image = 3;
+ */
+ image: Uint8Array;
+ /**
+ * @generated from protobuf field: proto.discord.Channel info_channel = 4;
+ */
+ infoChannel?: {
+ /**
+ * @generated from protobuf field: string id = 1;
+ */
+ id: string;
+ /**
+ * @generated from protobuf field: string name = 2;
+ */
+ name: string;
+ };
+ /**
+ * @generated from protobuf field: repeated proto.models.Map qualifier_maps = 5;
+ */
+ qualifierMaps: Map[];
+ /**
+ * @generated from protobuf field: proto.models.QualifierEvent.EventSettings flags = 6;
+ */
+ flags: QualifierEvent_EventSettings;
+ /**
+ * @generated from protobuf field: proto.models.QualifierEvent.LeaderboardSort sort = 7;
+ */
+ sort: QualifierEvent_LeaderboardSort;
+}
+```
+
+For the definition of the `QualifierEvent_EventSettings` look at the [Enums -> QualifierEvent_EventSettings](/documentation#Enums/5-QualifierEvent_EventSettings) and for the `QualifierEvent_LeaderboardSort` look at the [Enums -> QualifierEvent_EventSettings](/documentation#Enums/5-QualifierEvent_LeaderboardSort) page.
+
+
+
info
+
+ Example: A direct implementation example is not present, since this method is not used in ShyyTAUI.
+
+
\ No newline at end of file
diff --git a/src/lib/taDocs/2-stateManager-getQualifiers.md b/src/lib/taDocs/2-stateManager-getQualifiers.md
new file mode 100644
index 0000000..e495043
--- /dev/null
+++ b/src/lib/taDocs/2-stateManager-getQualifiers.md
@@ -0,0 +1,71 @@
+# The stateManager.getQualifiers() method
+This documents the `stateManager.getQualifiers()` method.
+
+This method has input parameters. The function could easily be defined as:
+```ts
+function getQualifiers(tournamentGuid: string): QualifierEvent[] | undefined {
+ // backend logic
+}
+```
+## General usage:
+```ts
+const qualifiers: QualifierEvent[] | undefined = taClient.stateManager.getQualifiers(tournamentGuid);
+```
+
+This method will return either an array of the `QualifierEvent` object or undefined. A `QualifierEvent` can be described by the following TypeScript Interface:
+```ts
+interface QualifierEvent {
+ /**
+ * @generated from protobuf field: string guid = 1;
+ */
+ guid: string;
+ /**
+ * @generated from protobuf field: string name = 2;
+ */
+ name: string;
+ /**
+ * @generated from protobuf field: bytes image = 3;
+ */
+ image: Uint8Array;
+ /**
+ * @generated from protobuf field: proto.discord.Channel info_channel = 4;
+ */
+ infoChannel?: {
+ /**
+ * @generated from protobuf field: string id = 1;
+ */
+ id: string;
+ /**
+ * @generated from protobuf field: string name = 2;
+ */
+ name: string;
+ };
+ /**
+ * @generated from protobuf field: repeated proto.models.Map qualifier_maps = 5;
+ */
+ qualifierMaps: Map[];
+ /**
+ * @generated from protobuf field: proto.models.QualifierEvent.EventSettings flags = 6;
+ */
+ flags: QualifierEvent_EventSettings;
+ /**
+ * @generated from protobuf field: proto.models.QualifierEvent.LeaderboardSort sort = 7;
+ */
+ sort: QualifierEvent_LeaderboardSort;
+}
+```
+
+
info
+
+
Good to know: For the sake of simplification, the type of
infoChannel has been substituted. Find the documentation on the original type
here: Modals -> Channel
+
+
+
+For the definition of the `QualifierEvent_EventSettings` look at the [Enums -> QualifierEvent_EventSettings](/documentation#Enums/5-QualifierEvent_EventSettings) and for the `QualifierEvent_LeaderboardSort` look at the [Enums -> QualifierEvent_EventSettings](/documentation#Enums/5-QualifierEvent_LeaderboardSort) page.
+
+
+
info
+
+ Example: A direct implementation example is not present, since this method is not used in ShyyTAUI.
+
+
\ No newline at end of file
diff --git a/src/lib/taDocs/2-stateManager-getSelfGuid.md b/src/lib/taDocs/2-stateManager-getSelfGuid.md
new file mode 100644
index 0000000..24379ee
--- /dev/null
+++ b/src/lib/taDocs/2-stateManager-getSelfGuid.md
@@ -0,0 +1,28 @@
+# The stateManager.getSelfGuid() method
+This documents the `stateManager.getSelfGuid()` method.
+
+This is perhaps the simplest method of the `stateManager`, as its response is a simple string which is the guid of the currently connected client.
+## General usage:
+```ts
+const myGuid: string = taClient.stateManager.getSelfGuid();
+```
+
+There is not much more to explain here. This method will simply return the currently connected client's GUID.
+
+It can be useful in scenarios such as:
+```ts
+async function addSelfToMatch() {
+ if(!match?.associatedUsers.includes(client.stateManager.getSelfGuid())) {
+ const response = await client.addUserToMatch(tournamentGuid, matchGuid, client.stateManager.getSelfGuid());
+ console.log("Added Self to match!", response);
+ }
+}
+```
+
+
info
+
+ Example: This is an example from the page of ShyyTAUI within the match coorination page.
+
+
+
+The example above demonstrates the `addSelfToMatch` method used in ShyyTAUI in order to ensure that the coordinator is correctly connected and associated to the match.
\ No newline at end of file
diff --git a/src/lib/taDocs/2-stateManager-getTournament.md b/src/lib/taDocs/2-stateManager-getTournament.md
new file mode 100644
index 0000000..26861a3
--- /dev/null
+++ b/src/lib/taDocs/2-stateManager-getTournament.md
@@ -0,0 +1,69 @@
+# The stateManager.getTournament() method
+This documents the `stateManager.getTournament()` method.
+
+This method has input parameters. The function could easily be defined as:
+```ts
+function getTournament(tournamentGuid: string): Tournament | undefined {
+ // backend logic
+}
+```
+## General usage:
+```ts
+const tournament: Tournament | undefined = taClient.stateManager.getTournament(tournamentGuid);
+```
+
+This method will return either the `Tournament` object or undefined. A `Tournament` can be described by the following TypeScript Interface:
+```ts
+interface Tournament {
+ /**
+ * @generated from protobuf field: string guid = 1;
+ */
+ guid: string;
+ /**
+ * @generated from protobuf field: proto.models.Tournament.TournamentSettings settings = 2;
+ */
+ settings?: Tournament_TournamentSettings;
+ /**
+ * @generated from protobuf field: repeated proto.models.User users = 3;
+ */
+ users: User[];
+ /**
+ * @generated from protobuf field: repeated proto.models.Match matches = 4;
+ */
+ matches: Match[];
+ /**
+ * @generated from protobuf field: repeated proto.models.QualifierEvent qualifiers = 5;
+ */
+ qualifiers: QualifierEvent[];
+ /**
+ * @generated from protobuf field: proto.models.CoreServer server = 6;
+ */
+ server?: CoreServer;
+}
+```
+
+- For the definition of a Tournament_TournamentSettings please look at the [Modals -> Tournament_TournamentSettings page](/documentation#Modals/4-Tournament_TournamentSettings)
+- For the definition of a User please look at the [Modals -> User page](/documentation#Modals/4-User)
+- For the definition of a Match please look at the [Modals -> Match page](/documentation#Modals/4-Match)
+- For the definition of a QualifierEvent please look at the [Modals -> QualifierEvent page](/documentation#Modals/4-QualifierEvent)
+- For the definition of a CoreServer please look at the [Modals -> CoreServer page](/documentation#Modals/4-CoreServer)
+
+A direct implementation:
+```ts
+// Get the tournament data, and check if the current user is within the users that are currently in the touranament
+if(!client.stateManager.getTournament(tournamentGuid)!.users.some(user => user.guid == client.stateManager.getSelfGuid())) {
+ // If the user is not in the tournament, join it
+ const joinResult = await client.joinTournament(tournamentGuid);
+ // Check if the join was successful
+ if (joinResult.details.oneofKind !== 'join' || joinResult.type === Response_ResponseType.Fail) {
+ // Throw an error if not
+ throw new Error('Could not join tournament');
+ }
+}
+```
+
+
info
+
+ Example: This is an example from the page of ShyyTAUI within the qualifiers page.
+
+
\ No newline at end of file
diff --git a/src/lib/taDocs/2-stateManager-getTournaments.md b/src/lib/taDocs/2-stateManager-getTournaments.md
new file mode 100644
index 0000000..06d3ad7
--- /dev/null
+++ b/src/lib/taDocs/2-stateManager-getTournaments.md
@@ -0,0 +1,60 @@
+# The stateManager.getTournamenst() method
+This documents the `stateManager.getTournaments()` method.
+
+```ts
+function getTournaments(): Tournament[] | undefined {
+ // backend logic
+}
+```
+## General usage:
+```ts
+const tournaments: Tournament[] | undefined = taClient.stateManager.getTournaments();
+```
+
+This method will return either an array of the `Tournament` object or undefined. A `Tournament` can be described by the following TypeScript Interface:
+```ts
+interface Tournament {
+ /**
+ * @generated from protobuf field: string guid = 1;
+ */
+ guid: string;
+ /**
+ * @generated from protobuf field: proto.models.Tournament.TournamentSettings settings = 2;
+ */
+ settings?: Tournament_TournamentSettings;
+ /**
+ * @generated from protobuf field: repeated proto.models.User users = 3;
+ */
+ users: User[];
+ /**
+ * @generated from protobuf field: repeated proto.models.Match matches = 4;
+ */
+ matches: Match[];
+ /**
+ * @generated from protobuf field: repeated proto.models.QualifierEvent qualifiers = 5;
+ */
+ qualifiers: QualifierEvent[];
+ /**
+ * @generated from protobuf field: proto.models.CoreServer server = 6;
+ */
+ server?: CoreServer;
+}
+```
+
+- For the definition of a Tournament_TournamentSettings please look at the [Modals -> Tournament_TournamentSettings page](/documentation#Modals/4-Tournament_TournamentSettings)
+- For the definition of a User please look at the [Modals -> User page](/documentation#Modals/4-User)
+- For the definition of a Match please look at the [Modals -> Match page](/documentation#Modals/4-Match)
+- For the definition of a QualifierEvent please look at the [Modals -> QualifierEvent page](/documentation#Modals/4-QualifierEvent)
+- For the definition of a CoreServer please look at the [Modals -> CoreServer page](/documentation#Modals/4-CoreServer)
+
+A direct implementation:
+```ts
+// Get tournaments from the client
+const tournamentsList = client.stateManager.getTournaments();
+```
+
+
info
+
+ Example: This is an example from the page of ShyyTAUI within the tournament list / select page.
+
+
\ No newline at end of file
diff --git a/src/lib/taDocs/2-stateManager-getUser.md b/src/lib/taDocs/2-stateManager-getUser.md
new file mode 100644
index 0000000..d1a69ff
--- /dev/null
+++ b/src/lib/taDocs/2-stateManager-getUser.md
@@ -0,0 +1,116 @@
+# The stateManager.getUser() method
+This documents the `stateManager.getUser()` method.
+
+This method has input parameters. The function could easily be defined as:
+```ts
+function getUser(tournamentGuid: string, userGuid: string): User | undefined {
+ // backend logic
+}
+```
+## General usage:
+```ts
+const user: User | undefined = taClient.stateManager.getUser(tournamentGuid, userGuid);
+```
+
+This method will return either the `User` object or undefined. A `User` can be described by the following TypeScript Interface:
+```ts
+interface User {
+ /**
+ * @generated from protobuf field: string guid = 1;
+ */
+ guid: string;
+ /**
+ * @generated from protobuf field: string name = 2;
+ */
+ name: string;
+ /**
+ * @generated from protobuf field: string platform_id = 3;
+ */
+ platformId: string;
+ /**
+ * @generated from protobuf field: proto.models.User.ClientTypes client_type = 4;
+ */
+ clientType: User_ClientTypes;
+ /**
+ * @generated from protobuf field: string team_id = 5;
+ */
+ teamId: string;
+ /**
+ * @generated from protobuf field: proto.models.User.PlayStates play_state = 6;
+ */
+ playState: User_PlayStates;
+ /**
+ * @generated from protobuf field: proto.models.User.DownloadStates download_state = 7;
+ */
+ downloadState: User_DownloadStates;
+ /**
+ * @generated from protobuf field: repeated string mod_list = 8;
+ */
+ modList: string[];
+ /**
+ * @generated from protobuf field: proto.models.User.Point stream_screen_coordinates = 9;
+ */
+ streamScreenCoordinates?: User_Point;
+ /**
+ * @generated from protobuf field: int64 stream_delay_ms = 10;
+ */
+ streamDelayMs: bigint;
+ /**
+ * @generated from protobuf field: int64 stream_sync_start_ms = 11;
+ */
+ streamSyncStartMs: bigint;
+ /**
+ * @generated from protobuf field: proto.models.User.DiscordInfo discord_info = 12;
+ */
+ discordInfo?: User_DiscordInfo;
+ /**
+ * @generated from protobuf field: bytes user_image = 13;
+ */
+ userImage: Uint8Array;
+ /**
+ * @generated from protobuf field: proto.models.Permissions permissions = 14;
+ */
+ permissions: Permissions;
+}
+```
+
+- For the definition of a User_ClientTypes please look at the [Enums -> User_ClientTypes page](/documentation#Enums/5-User_ClientTypes)
+- For the definition of a User_PlayStates please look at the [Enums -> User_PlayStates page](/documentation#Enums/5-User_PlayStates)
+- For the definition of a User_DownloadStates please look at the [Enums -> User_DownloadStates page](/documentation#Enums/5-User_DownloadStates)
+- For the definition of a User_Point please look at the [Modals -> User_Point page](/documentation#Modals/4-User_Point)
+- For the definition of a User_DiscordInfo please look at the [Modals -> User_DiscordInfo page](/documentation#Modals/4-User_DiscordInfo)
+- For the definition of a Permissions please look at the [Enums -> Permissions page](/documentation#Enums/5-Permissions)
+
+A direct implementation:
+```ts
+async function refreshMatchDetails(match: Match) {
+ // Get match players
+ // Fetch each of the players in the match my using map on the associated users array which contains the connected user's guid
+ matchPlayers = match.associatedUsers
+ .map(userGuid => client.stateManager.getUser(tournamentGuid, userGuid))
+ // Make sure that the client is a player(0) and not a websocket or REST connection (1 or 2)
+ .filter(user => user && user.clientType === 0) as User[];
+
+ // Remaining logic in the function
+ // Get current song if available
+ currentSong = match.selectedMap?.gameplayParameters || null;
+ if(currentSong) {
+ try {
+ // Fetch the map beatsaver data
+ const tempMapData = await fetchMapByLevelId(currentSong.beatmap.levelId);
+
+ if(tempMapData) {
+ currentSongData = tempMapData;
+ }
+ } catch (error) {
+ console.log('Current song beatsaver data fetch failed');
+ }
+ }
+}
+```
+
+
info
+
+ Example: This is an example from the page of ShyyTAUI within the match cordination page.
+
+
\ No newline at end of file
diff --git a/src/lib/taDocs/2-stateManager-getUsers.md b/src/lib/taDocs/2-stateManager-getUsers.md
new file mode 100644
index 0000000..d4e4085
--- /dev/null
+++ b/src/lib/taDocs/2-stateManager-getUsers.md
@@ -0,0 +1,89 @@
+# The stateManager.getUsers() method
+This documents the `stateManager.getUsers()` method.
+
+This method has input parameters. The function could easily be defined as:
+```ts
+function getUsers(tournamentGuid: string): User[] | undefined {
+ // backend logic
+}
+```
+## General usage:
+```ts
+const users: User[] | undefined = taClient.stateManager.getUsers(tournamentGuid);
+```
+
+This method will return either an array of the `User` object or undefined. A `User` can be described by the following TypeScript Interface:
+```ts
+interface User {
+ /**
+ * @generated from protobuf field: string guid = 1;
+ */
+ guid: string;
+ /**
+ * @generated from protobuf field: string name = 2;
+ */
+ name: string;
+ /**
+ * @generated from protobuf field: string platform_id = 3;
+ */
+ platformId: string;
+ /**
+ * @generated from protobuf field: proto.models.User.ClientTypes client_type = 4;
+ */
+ clientType: User_ClientTypes;
+ /**
+ * @generated from protobuf field: string team_id = 5;
+ */
+ teamId: string;
+ /**
+ * @generated from protobuf field: proto.models.User.PlayStates play_state = 6;
+ */
+ playState: User_PlayStates;
+ /**
+ * @generated from protobuf field: proto.models.User.DownloadStates download_state = 7;
+ */
+ downloadState: User_DownloadStates;
+ /**
+ * @generated from protobuf field: repeated string mod_list = 8;
+ */
+ modList: string[];
+ /**
+ * @generated from protobuf field: proto.models.User.Point stream_screen_coordinates = 9;
+ */
+ streamScreenCoordinates?: User_Point;
+ /**
+ * @generated from protobuf field: int64 stream_delay_ms = 10;
+ */
+ streamDelayMs: bigint;
+ /**
+ * @generated from protobuf field: int64 stream_sync_start_ms = 11;
+ */
+ streamSyncStartMs: bigint;
+ /**
+ * @generated from protobuf field: proto.models.User.DiscordInfo discord_info = 12;
+ */
+ discordInfo?: User_DiscordInfo;
+ /**
+ * @generated from protobuf field: bytes user_image = 13;
+ */
+ userImage: Uint8Array;
+ /**
+ * @generated from protobuf field: proto.models.Permissions permissions = 14;
+ */
+ permissions: Permissions;
+}
+```
+
+- For the definition of a User_ClientTypes please look at the [Enums -> User_ClientTypes page](/documentation#Enums/5-User_ClientTypes)
+- For the definition of a User_PlayStates please look at the [Enums -> User_PlayStates page](/documentation#Enums/5-User_PlayStates)
+- For the definition of a User_DownloadStates please look at the [Enums -> User_DownloadStates page](/documentation#Enums/5-User_DownloadStates)
+- For the definition of a User_Point please look at the [Modals -> User_Point page](/documentation#Modals/4-User_Point)
+- For the definition of a User_DiscordInfo please look at the [Modals -> User_DiscordInfo page](/documentation#Modals/4-User_DiscordInfo)
+- For the definition of a Permissions please look at the [Enums -> Permissions page](/documentation#Enums/5-Permissions)
+
+
+
info
+
+ Example: A direct example is not available, as this function is not used in ShyyTAUI.
+
+
\ No newline at end of file
diff --git a/src/lib/taDocs/2-stateManager-handlePacket.md b/src/lib/taDocs/2-stateManager-handlePacket.md
new file mode 100644
index 0000000..529cc92
--- /dev/null
+++ b/src/lib/taDocs/2-stateManager-handlePacket.md
@@ -0,0 +1,11 @@
+# The stateManager.handlePacket() method
+This method should NOT be used, as it is already handled, just exists.
+
+## General usage:
+```ts
+await taClient.stateManager.handlePacket(packet: Packet);
+```
+
+For the definition of a `Packet` please refer to [Modals -> Packet](/documentation#Modals/Packet)
+
+I will not proide further documentation for this method, as it should NOT be used. Every way you could use it exists with another method.
\ No newline at end of file
diff --git a/src/lib/taDocs/2-stateManager-intro.md b/src/lib/taDocs/2-stateManager-intro.md
new file mode 100644
index 0000000..9b2f510
--- /dev/null
+++ b/src/lib/taDocs/2-stateManager-intro.md
@@ -0,0 +1,48 @@
+# An Introduction to the StateManager
+The `client.stateManager`(`stateManager` for short), is the simple way of communicating and syncing with the state on the `CoreServer`. If you alrady understand what 'state-based' means, then you may skip this page.
+
+The `stateManager` is the way you would fetch tournaments, get matches, or do anything related to getting specific data that does not require a database query. It is best if you are familiar with what methods it has and how you can use them.
+
+For the ease of this explanation let me provide an example:
+```ts
+onMount(async() => {
+ // Check if the user is logged in
+ if ($authTokenStore) {
+ // Fetch the match data that we need to display (current map etc. This function will appear later in docs too)
+ await fetchMatchData();
+ // Using stateManger listen to global changes to our match
+ client.stateManager.on('matchDeleted', handleMatchDeleted);
+ client.stateManager.on('matchUpdated', handleMatchUpdated);
+ client.stateManager.on('userDisconnected', handleUserDisconnected);
+ client.stateManager.on('userUpdated', handleUserUpdated);
+ // Using the client listen to events that will not be stored in the state, such as scores and song finish events
+ client.on('realtimeScore', handleRealtimeScoreUpdate);
+ client.on('songFinished', handleSongFinished);
+
+ // This is a helper function you can ignore, it just prevents the user from reloading the page while in the match
+ window.addEventListener('beforeunload', beforeUnloadHandler);
+ } else {
+ // If the user is not authenticated, they will be thrown to the discord authentication page
+ window.location.href = "/discordAuth"
+ }
+});
+
+onDestroy(() => {
+ // Remove the listeners that were added on mount
+ client.stateManager.removeListener('matchUpdated', handleMatchUpdated);
+ client.stateManager.removeListener('matchDeleted', handleMatchDeleted);
+ client.stateManager.removeListener('userDisconnected', handleUserDisconnected);
+ client.stateManager.removeListener('userUpdated', handleUserUpdated);
+ client.removeListener('realtimeScore', handleRealtimeScoreUpdate);
+ client.removeListener('songFinished', handleSongFinished);
+
+ // Remove the no-refresh behaviour
+ window.removeEventListener('beforeunload', beforeUnloadHandler);
+});
+```
+
+
info
+
+ Example: This is an example from the page of ShyyTAUI within the match coorination page.
+
+
\ No newline at end of file
diff --git a/src/lib/taDocs/client.md b/src/lib/taDocs/3-client.md
similarity index 82%
rename from src/lib/taDocs/client.md
rename to src/lib/taDocs/3-client.md
index 45a4c88..ad01ea3 100644
--- a/src/lib/taDocs/client.md
+++ b/src/lib/taDocs/3-client.md
@@ -76,20 +76,3 @@ The table below shows all of the functions of the taClient. From this point onwa
These are the main functions of the taClient. It is important to note that these are mostly asyncronous and must be awaited for if you wish to use the response they provide. There is however another important part of the taClient, which is the `taClient.stateManger`. This `stateManger` also has more functions which I have also provided in a table below. The `stateManger` loads its data once it connects to the TA CoreServer.
-| taClient.stateManager. (function) | Purpose and functionality | Is Async |
-|:----------------------------------:|:--------------------------|:--------:|
-|emit()|Emit a custom event. Only use this if you know what you are doing.|True|
-|getKnownServers()|Get the known servers which have been sent in the connect state. **This is a cached list.**|False|
-|getMatch()|Get the details of a match.|False|
-|getMatches()|Get an array of all of the matches in a tournament.|False|
-|getQualifier()|Get the details of a qualifier event.|False|
-|getQualifiers()|Get an array of all of the qualifiers in a tournament.|False|
-|getSelfGuid()|Get the `.guid` property of the currently logged in user or bot token.|False|
-|getTournament()|Get the information about a tournament.|False|
-|getTournaments()|Get an array of all of the tournaments of a Core Server|False|
-|getUser()|Get all of the details of a user in a tournament.|False|
-|getUsers()|Get an array of all of the users in a tournament.|False|
-|handlePacket()|Handle the response to a packet sent to you by the TA Core Server. Only use if you know what you are doing.|False|
-|**on()**|Standard listener for the taClient. This is how real time score can be subscribed to.|False|
-|once()|**SAME AS ON? WHAT IS THE DIFFERENCE BETWEEN TACLIENT.NO AND STATEMANAGER.ON????**|False|
-|removeListener()|**why can I subscribe to events in the statemanager? I am quite unclear about this hehe**|False|
\ No newline at end of file
diff --git a/src/lib/taDocs/4-models-Map.md b/src/lib/taDocs/4-models-Map.md
new file mode 100644
index 0000000..e69de29
diff --git a/src/lib/taDocs/qualifierLeaderboardSort.md b/src/lib/taDocs/qualifierLeaderboardSort.md
new file mode 100644
index 0000000..08e94f8
--- /dev/null
+++ b/src/lib/taDocs/qualifierLeaderboardSort.md
@@ -0,0 +1,267 @@
+# QualifierEvent_LeaderboardSort Enum
+
+This enum defines all supported leaderboard sorting strategies for qualifier events in the TournamentAssistant Client.
+
+Each sort type allows leaderboard data to be ranked according to specific gameplay metrics, with different sorting modes available.
+
+## Sorting Modes
+
+- **Default (Descending)**
+ Sorts scores from highest to lowest. This is the default for most metrics where higher numbers are better (e.g., ModifiedScore, MaxCombo).
+
+- **Ascending**
+ Sorts scores from lowest to highest. Ideal for metrics where fewer is better (e.g., NotesMissed, BadCuts).
+
+- **Target**
+ Sorts based on how close a score is to a predefined target value. The absolute difference is used for ranking (i.e., `|target - playerValue|`), with the smallest difference ranked highest.
+
+---
+
+## Enum Values
+
+### ModifiedScore
+```protobuf
+ModifiedScore = 0;
+````
+
+Sorts by Modified Score, descending (highest first).
+
+### ModifiedScoreAscending
+
+```protobuf
+ModifiedScoreAscending = 1;
+```
+
+Sorts by Modified Score, ascending (lowest first).
+
+### ModifiedScoreTarget
+
+```protobuf
+ModifiedScoreTarget = 2;
+```
+
+Sorts by proximity to a target Modified Score.
+Example with target = 107000:
+
+```
+Player A: 107114 → 114
+Player B: 107310 → 310
+Player C: 103851 → 3149
+```
+
+---
+
+### NotesMissed
+
+```protobuf
+NotesMissed = 3;
+```
+
+Sorts by number of missed notes, descending.
+
+### NotesMissedAscending
+
+```protobuf
+NotesMissedAscending = 4;
+```
+
+Sorts by number of missed notes, ascending.
+
+### NotesMissedTarget
+
+```protobuf
+NotesMissedTarget = 5;
+```
+
+Sorts by proximity to a target missed notes value.
+
+---
+
+### BadCuts
+
+```protobuf
+BadCuts = 6;
+```
+
+Sorts by number of bad cuts, descending.
+
+### BadCutsAscending
+
+```protobuf
+BadCutsAscending = 7;
+```
+
+Sorts by number of bad cuts, ascending.
+Example:
+
+```
+28
+39
+43
+```
+
+### BadCutsTarget
+
+```protobuf
+BadCutsTarget = 8;
+```
+
+Sorts by proximity to a target bad cuts value.
+Example with target = 40:
+
+```
+Player A: 39 → 1
+Player B: 43 → 3
+Player C: 28 → 12
+```
+
+---
+
+### MaxCombo
+
+```protobuf
+MaxCombo = 9;
+```
+
+Sorts by max combo achieved, descending.
+
+### MaxComboAscending
+
+```protobuf
+MaxComboAscending = 10;
+```
+
+Sorts by max combo, ascending.
+
+### MaxComboTarget
+
+```protobuf
+MaxComboTarget = 11;
+```
+
+Sorts by proximity to a target max combo value.
+
+---
+
+### GoodCuts
+
+```protobuf
+GoodCuts = 12;
+```
+
+Sorts by number of good cuts, descending.
+
+### GoodCutsAscending
+
+```protobuf
+GoodCutsAscending = 13;
+```
+
+Sorts by number of good cuts, ascending.
+
+### GoodCutsTarget
+
+```protobuf
+GoodCutsTarget = 14;
+```
+
+Sorts by proximity to a target good cuts value.
+
+---
+
+## Summary Table
+
+| Enum Value | Bit Value | Sort Type | Description |
+| ---------------------- | --------- | ---------- | ----------------------------------- |
+| ModifiedScore | 0 | Descending | Standard leaderboard score |
+| ModifiedScoreAscending | 1 | Ascending | Inverse score order |
+| ModifiedScoreTarget | 2 | Target | Closeness to target score |
+| NotesMissed | 3 | Descending | More missed notes = worse |
+| NotesMissedAscending | 4 | Ascending | Fewer missed notes = better |
+| NotesMissedTarget | 5 | Target | Closeness to target missed notes |
+| BadCuts | 6 | Descending | More bad cuts = worse |
+| BadCutsAscending | 7 | Ascending | Fewer bad cuts = better |
+| BadCutsTarget | 8 | Target | Closeness to target bad cuts |
+| MaxCombo | 9 | Descending | Highest combo achieved |
+| MaxComboAscending | 10 | Ascending | Lowest combo achieved |
+| MaxComboTarget | 11 | Target | Closeness to target combo count |
+| GoodCuts | 12 | Descending | Most good cuts = better |
+| GoodCutsAscending | 13 | Ascending | Fewest good cuts = better |
+| GoodCutsTarget | 14 | Target | Closeness to target good cuts count |
+
+
+# New DB fileserver idea:
+
+4 columns:
+- uploader (discordid)
+- file_name (guid identifier)
+- file (Unit8Array)
+- created_at (time)
+
+PostgreSQL:
+```sql
+CREATE TABLE files (
+ id SERIAL PRIMARY KEY,
+ uploader TEXT NOT NULL,
+ file_name TEXT NOT NULL UNIQUE,
+ file BYTEA NOT NULL, -- BYTEA stores binary data
+ created_at TIMESTAMP DEFAULT NOW()
+);
+```
+
+MySQL:
+```sql
+CREATE TABLE files (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ uploader VARCHAR(64) NOT NULL,
+ file_name VARCHAR(255) NOT NULL UNIQUE,
+ file LONGBLOB NOT NULL, -- LONGBLOB supports up to 4GB of binary data
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+```
+
+## Implementation example (using my beloved Drizzle ORM and a postgres database):
+
+```ts
+export const files = pgTable("files", {
+ id: serial("id").primaryKey(),
+ uploader: text("uploader").notNull(),
+ fileName: text("file_name").notNull().unique(),
+ file: blob("file").notNull(), // Drizzle handles BYTEA for pg as blob
+ createdAt: timestamp("created_at").defaultNow(),
+});
+```
+
+```ts
+import { db } from "./db"; // drizzle db setup
+import { files } from "./schema"; // import the table
+
+const uploadFile = async (uploader: string, fileName: string, binaryData: Uint8Array) => {
+ await db.insert(files).values({
+ uploader,
+ fileName,
+ file: Buffer.from(binaryData), // Convert Uint8Array to Buffer for insertion
+ });
+};
+```
+
+```ts
+async function getFile(fileName: string) {
+ const result = await db.select().from(files).where(eq(files.fileName, fileName));
+ if (!result.length) return null;
+
+ const fileRecord = result[0];
+ const uint8Array = new Uint8Array(fileRecord.file); // convert Buffer to Uint8Array
+ return uint8Array;
+};
+
+app.get("/files/:fileName", async (req, res) => {
+ const fileName = req.params.fileName;
+ const file = await getFile(fileName);
+ if (!file) return res.status(404).send("File not found");
+
+ res.setHeader("Content-Type", "application/octet-stream");
+ res.send(Buffer.from(file));
+});
+
+```
\ No newline at end of file
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index b1b5eb5..4d6fbcd 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -121,7 +121,7 @@
code
GitHub
-
+
sports_esports
Tournament Assistant
@@ -168,6 +168,14 @@
--border-color: #333333;
--navbar-height: 4rem;
--footer-bg: #191919;
+ --success-color: #22c55e;
+ --warning-color: #f59e0b;
+ --error-color: #ef4444;
+
+ --comfortable-red: #d9534f;
+ --comfortable-red-hover: #c9302c;
+ --pick-green: #28a745;
+ --pick-green-hover: #218838;
}
/* Global styles */
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index ddf1a93..a6d8488 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -68,8 +68,8 @@ onMount(() => {
devices
-
Fully Responsive
-
Hopefully works seamlessly across all devices, from desktop to mobile. (Although I am very much working...)
+
Reliable
+
ShyyTAUI is built to be safe and reliable. This means you don't have to worry about accidentally ending a match, or refreshing when you shouldn't.
Use moons-ta-client to build what you need! Overlays, casting panels, think of anything!
Use moons-ta-client to build what you need! This site has the official TournamentAssistant Client documentation.