diff --git a/docs/docs/api/auth.md b/docs/docs/api/auth.md index 7bac0da76..94e381d69 100644 --- a/docs/docs/api/auth.md +++ b/docs/docs/api/auth.md @@ -23,8 +23,8 @@ Where API_KEY is the api key you wish to use. The other way to authorise a request is with your session cookie. This **MUST NOT** be used by code, and is instead a way for logged-in users to interact with the API as themselves. -To use authentication in this way, simply make a request with your `ktchi_production_session` or -`btchi_production_session` cookie. +To use authentication in this way, simply make a request with your `Kamaitachi_SESSION` or +`Bokutachi_SESSION` cookie. The reason for this second authentication method is so that, when a user logs in, they can use the cookie they were set to also interact with the API. diff --git a/docs/docs/api/overview.md b/docs/docs/api/overview.md index d3287994e..f2209675d 100644 --- a/docs/docs/api/overview.md +++ b/docs/docs/api/overview.md @@ -68,7 +68,7 @@ As the name implies, the Success Response is returned on a successful request. | Property | Type | Description | | :: | :: | :: | | `success` | true | Always true for a successful response. | -| `description` | string | Information about what happened with the request. | +| `description` | String | Information about what happened with the request. | | `body` | Endpoint Dependent | Any data that the endpoint needs to return, such as a user's document from a profile request. | The HTTP Status Code for any Success Response will always be of 2XX form. @@ -80,10 +80,14 @@ As the name implies, the Failed Response is returned when a request fails. | Property | Type | Description | | :: | :: | :: | | `success` | false | Always false for a failed response. | -| `description` | string | Information about what went wrong with the request. | +| `description` | String | Information about what went wrong with the request. | The HTTP Status Code for any Failed Response will always be of either 4XX or 5XX form. +!!! warning + The `description` property is **NOT** intended for program usage. You should **NEVER** depend + on the output of `description`, as it may be changed at any time for any reason. + !!! note Any API request can fail for any reason. You should always account for the case where the request fails. diff --git a/docs/docs/api/routes/admin.md b/docs/docs/api/routes/admin.md index 8e9c07abf..9e12a2d8c 100644 --- a/docs/docs/api/routes/admin.md +++ b/docs/docs/api/routes/admin.md @@ -1,6 +1,7 @@ # Admin Endpoints -These endpoints are for adminstrator use. +These endpoints are for adminstrator use. As such, they all +require an `authLevel` of atleast 3. For more information, see the [UserDocument](/tachi-server/documents/user). ***** @@ -42,32 +43,6 @@ Empty Object. ***** -## Remove the isPrimary status from a chart - -This also uncalcs all score data for scores on the chart. - -`POST /api/v1/admin/deprimarify` - -### Permissions - -- Admin - -### Parameters - -| Property | Type | Description | -| :: | :: | :: | -| `chartID` | String | The chartID to deprimarify. | -| `game` | Game | The game this chart is on. | -| `songID` | Integer | Alternatively to chartID, you can specify this to deprimarify all charts on this songID. | - -### Response - -| Property | Type | Description | -| :: | :: | :: | -| `charts` | Array<ChartDocument> | The array of charts that were deprimarified | - -***** - ## Delete any Score This performs all the necessary checks to remove a score document aswell. @@ -88,3 +63,175 @@ This performs all the necessary checks to remove a score document aswell. Empty Object. +***** + +## Resynchronise all PBs that match the given query or users. + +`POST /api/v1/admin/resync-pbs` + +!!! info + This is intended to be used in the case that PBs fall out of + sync with what they should be. This could be due to a + database migration going awry, or anything else. + +### Permissions + +- Admin + +### Parameters + +| Property | Type | Description | +| :: | :: | :: | +| `userIDs` | Array<Integer> (Optional) | The list of userIDs to resynchronise PBs for. | +| `filters` | Mongo Query for the PBs Collection. (Optional) | A query to reduce the amount of PBs that get reprocessed. | + +### Response + +Empty Object. + +### Example + +#### Request +``` +POST /api/v1/admin/resync-pbs +``` + +```js +{ + "filter": { + "game": {$in: ["iidx","sdvx"]} + }, + "userIDs": [1,2,3,4] +} +``` + +#### Response + +Nothing. + +***** + +## Destroy a users GPT Profile and forces a leaderboard recalc. + +`POST /api/v1/admin/destroy-ugpt` + +!!! warning + This is intended to completely remove a users GPT profile. + You should use this **only** if a user has irrevocably screwed + their account. Preferably early on! + +### Permissions + +- Admin + +### Parameters + +| Property | Type | Description | +| :: | :: | :: | +| `userID` | Integer | The user part of the UGPT. | +| `game` | Game | The game part of the UGPT. | +| `playtype` | Playtype | The PT part of the UGPT. Must be for the above game. | + +### Response + +Empty Object. + +### Example + +#### Request +``` +POST /api/v1/admin/destroy-ugpt +``` + +```js +{ + "userID": 1, + "game": "iidx", + "playtype": "DP" +} +``` + +#### Response + +Empty Object. + +***** + +## Destroy a chart and all of its scores. + +`POST /api/v1/admin/destroy-chart` + +### Permissions + +- Admin + +### Parameters + +| Property | Type | Description | +| :: | :: | :: | +| `chartID` | String | The chartID you wish to destroy. | +| `game` | Game | The game this chart belongs to (Necessary for lookups). | + +### Response + +Empty Object. + +### Example + +#### Request +``` +POST /api/v1/admin/destroy-chart +``` +```js +{ + "chartID": "SomeChartID", + "game": "iidx" +} +``` + +#### Response + +Empty Object. + +***** + +## Perform a site recalc on this set of scores. + +`POST /api/v1/admin/recalc` + +### Permissions + +- Admin + +### Parameters + +| Property | Type | Description | +| :: | :: | :: | +| `` | Mongo Query for scores | Filters the amount of scores recalced. If not provided, defaults to every score on the site. | + +### Response + +| Property | Type | Description | +| :: | :: | :: | +| `scoresRecalced` | Integer | The amount of scores recalced. | + +### Example + +#### Request +``` +POST /api/v1/admin/recalc +``` +```js +{ + "game": "iidx", + "scoreData.percent": {$gt: 90}, +} +``` + +#### Response + +```js +{ + "scoresRecalced": 174 +} +``` diff --git a/docs/docs/api/routes/auth.md b/docs/docs/api/routes/auth.md index 569840212..3f05bb5a2 100644 --- a/docs/docs/api/routes/auth.md +++ b/docs/docs/api/routes/auth.md @@ -9,7 +9,11 @@ These endpoints relate to internal authentication methods. Read the warning belo Furthermore, interacting with this programmatically is near-impossible because you need to complete a CAPTCHA. - This is documented for completeness' sake. + Nevertheless, This is documented for completeness' sake. + +!!! warning + All of these endpoints are aggressively rate limited. If you fire a bot at this, you will probably get + your IP blacklisted. Don't do that. ***** @@ -23,15 +27,21 @@ Logs a user in and returns a session cookie. | Property | Type | Description | | :: | :: | :: | -| `username` | string | The user's username. This is compared case-insensitively. -| `password` | string | The user's password. | -| `captcha` | string | | +| `username` | String | The user's username. This is compared case-insensitively. +| `!password` | String | The user's password. | +| `captcha` | String | Information about the captcha filled out by the user. We use a Google ReCaptcha instance. | + +!!! info + The `!` prefix is special in that anything with it is assumed to be private and is **always** + ignored by our request logger. + + Without it, we would log passwords! ### Response | Property | Type | Description | | :: | :: | :: | -| `userID` | integer | The ID of the user you authenticated as. | +| `userID` | Integer | The ID of the user you authenticated as. | | HTTP Header | Description | | :: | :: | @@ -48,7 +58,7 @@ POST /api/v1/auth/login ```json { "username": "zkldi", - "password": "my_password", + "!password": "my_password", "captcha": "herebedragons" } ``` @@ -70,19 +80,18 @@ POST /api/v1/auth/login | Property | Type | Description | | :: | :: | :: | -| `username` | string | A string between 3 and 20 characters. The first character must be A-Z, _ or -. The other 19 may be A-Z, 0-9, _ or -. | -| `password` | string | An 8 character or longer string. | -| `email` | string | | -| `inviteCode` (Kamaitachi Only) | string | If on Kamaitachi, this is the user's invitation code. | -| `captcha` | string | | +| `username` | String | A string between 3 and 20 characters. The first character must be A-Z, _ or -. The other 19 may be A-Z, 0-9, _ or -. | +| `!password` | String | An 8 character or longer string. | +| `email` | String | | +| `inviteCode` (Kamaitachi Only) | String (Undefined/Unused on Bokutachi) | If on Kamaitachi, this is the user's invitation code. | +| `captcha` | String | | ### Response | Property | Type | Description | | :: | :: | :: | -| `id` | integer | The newly-created user's ID. | -| `username` | string | The newly-created user's name. | +| `` | [UserDocument](/tachi-server/documents/user)| The newly-created user's User Document. | ### Example @@ -93,8 +102,8 @@ POST /api/v1/auth/register ```json { - "username": "newguy", - "password": "my_password", + "username": "newGuy", + "!password": "my_password", "captcha": "herebedragons", "email": "test@example.com" } @@ -105,10 +114,78 @@ POST /api/v1/auth/register ```json { "id": 2, - "username": "newguy" + "username": "newGuy", + "usernameLowercase": "newguy", + "socialMedia": { + "discord": null, + "twitter": null, + "github": null, + "steam": null, + "youtube": null, + "twitch": null + }, + "joinDate": 1639628634978, + "lastSeen": 1639628634978, + "about": "I'm a fairly nondescript person.", + "status": null, + "customPfpLocation": null, + "customBannerLocation": null, + "clan": null, + "badges": [], + "authLevel": 1 } ``` +***** + +## Verify an email from the code that was sent to it. + +`POST /api/v1/auth/verify-email` + +### Parameters + +| Property | Type | Description | +| :: | :: | :: | +| `code` | String | The Code that was sent to the users mailbox. | + +### Response + +Empty Object + +### Example + +#### Request +``` +{ + "code": "abcdef1234567890" +} +``` + +#### Response + +Empty Object. + +***** + +## Resend a verification email to the requesting user's email address. + +`POST /api/v1/auth/resend-verify-email` + +**Requires Self-Key Level Auth** + +### Parameters + +None, This endpoint reads the requesting user from their session. + +### Response + +Empty object. + +### Example + +N/A + + ***** ## Log Out. @@ -135,3 +212,68 @@ POST /api/v1/auth/logout #### Response Nothing. + +***** + +## Create a password reset code and send it to the provided email. + +`POST /api/v1/auth/forgot-password` + +!!! note + This endpoint sends the password reset code pretty-printed to the email, and is **NOT** + returned as part of the HTTP request. + +### Parameters + +| Property | Type | Description | +| :: | :: | :: | +| `email` | String | A user's email. If the email does not correspond to any accounts, 202 is returned anyway as a security measure. | + +### Response + +Empty Object. The endpoint immediately returns 202 to avoid giving away information about registered emails. + +### Example + +#### Request +```js +{ + "email": "zkldi.dev@gmail.com" +} +``` + +#### Response + +Although the request body returns nothing, `zkldi.dev@gmail.com` will have recieved an email with +a URL containing the password reset code. + +***** + +## Reset a user's password with a password reset code. + +`POST /api/v1/auth/reset-password` + +### Parameters + +| Property | Type | Description | +| :: | :: | :: | +| `code` | String | A password reset code. This is provided in a password reset email. | +| `!password` | String | The password to change to. | + +### Response + +Empty Object. + +### Example + +#### Request +```js +{ + "code": "1234567890abcdef", + "!password": "zkldi_is_so_cool", +} +``` + +#### Response + +Empty Object. diff --git a/docs/docs/api/routes/clients.md b/docs/docs/api/routes/clients.md index 44d125f88..651e75b6b 100644 --- a/docs/docs/api/routes/clients.md +++ b/docs/docs/api/routes/clients.md @@ -6,7 +6,7 @@ For a detailed explaination on how to use the OAuth2 flow, you can check [Using ***** -!!! warn +!!! warning All endpoints on this list require [Self Key](./user-integrations.md) level authentication. That is to say, it cannot be performed using Bearer tokens, and must be done by the user themselves. @@ -198,7 +198,7 @@ PATCH /api/v1/clients/some_client_id `POST /api/v1/clients/:clientID/reset-secret` -!!! warn +!!! warning This does **NOT** reset api keys created by this client as per OAuth2 spec. If you need that functionality, you will need to delete diff --git a/docs/docs/api/routes/config.md b/docs/docs/api/routes/config.md new file mode 100644 index 000000000..6a205c416 --- /dev/null +++ b/docs/docs/api/routes/config.md @@ -0,0 +1,33 @@ +# Config Endpoints + +These endpoints display certain properties about the Tachi [config file](../../tachi-server/setup/config.md). + +***** + +## Return the value of the BEATORAJA_QUEUE_SIZE + +`GET /api/v1/config/beatoraja-queue-size` + +**Bokutachi Only** + +### Response + +| Property | Type | Description | +| :: | :: | :: | +| `` | Integer | The value in `conf.json5` for BEATORAJA_QUEUE_SIZE. | + + +## Return the value of the USC_QUEUE_SIZE + +`GET /api/v1/config/usc-queue-size` + +**Bokutachi Only** + +### Response + +| Property | Type | Description | +| :: | :: | :: | +| `` | Integer | The value in `conf.json5` for USC_QUEUE_SIZE. | + + + diff --git a/docs/docs/api/routes/example.md b/docs/docs/api/routes/example.md index 6b95808fe..b758caa5b 100644 --- a/docs/docs/api/routes/example.md +++ b/docs/docs/api/routes/example.md @@ -1,6 +1,6 @@ # Example Endpoint -*Endpoints will be formatted like this.* +*Endpoints will be formatted like this. - These are not real endpoints!* ***** @@ -27,8 +27,8 @@ This endpoint greets the user. | Property | Type | Description | | :: | :: | :: | -| `name` | string | The name of the user to greet. | -| `birthday` (optional) | presence | Whether it is the user's birthday or not. | +| `name` | String | The name of the user to greet. | +| `birthday` (optional) | Presence | Whether it is the user's birthday or not. | Not providing required parameters will result in a 400 error. @@ -55,8 +55,8 @@ Not providing required parameters will result in a 400 error. | Property | Type | Description | | :: | :: | :: | -| `greeting` | string | A greeting for the user. | -| `wasBirthday` | boolean | Whether today is the users birthday or not. | +| `greeting` | String | A greeting for the user. | +| `wasBirthday` | Boolean | Whether today is the users birthday or not. | !!! info Since the above table corresponds to keys in the `body` @@ -67,7 +67,7 @@ Not providing required parameters will result in a 400 error. | Property | Type | Description | | :: | :: | :: | - | `` | string | The greeting. | + | `` | String | The greeting. | Corresponds to: ```json @@ -110,4 +110,5 @@ GET /greet?name=zkldi } ``` - This is omitted, because it's redundant all of the time. \ No newline at end of file + This is omitted, because it's redundant all of the time. -- That is to say, + You should never depend on parsing the content of `description`. \ No newline at end of file diff --git a/docs/docs/api/routes/gpt.md b/docs/docs/api/routes/gpt.md index 03a03d8e7..2d8282f49 100644 --- a/docs/docs/api/routes/gpt.md +++ b/docs/docs/api/routes/gpt.md @@ -65,8 +65,8 @@ GET /api/v1/games/iidx/SP | Property | Type | Description | | :: | :: | :: | -| `gameStats` | GameStats[] | The sorted statistics for the leaderboards. | -| `users` | UserDocument[] | All of the related users for the above statistics. | +| `gameStats` | Array<GameStats> | The sorted statistics for the leaderboards. | +| `users` | Array<[UserDocument](/tachi-server/documents/user)gt; | All of the related users for the above statistics. | ### Example @@ -258,7 +258,7 @@ GET /api/v1/games/iidx/SP/charts/some_chart_id Retrieve the tierlist information for this chart. If no tierlistID is provided, this falls back to the GPT's default. -!!! warn +!!! warning If the GPT has no default tierlist, then the server will return a 501. ### Parameters @@ -589,10 +589,10 @@ GET /api/v1/games/bms/7K/tableID/insane | Property | Type | Description | | :: | :: | :: | -| `pbs` | Array<PBScoreDocument> | The array of pbs part of the score leaderboard. | +| `pbs` | Array<PBDocument> | The array of pbs part of the score leaderboard. | | `songs` | Array<SongDocument> | The array of songs part of the PBs. | | `charts` | Array<ChartDocument> | The array of charts part of the PBs. | -| `users` | Array<UserDocument> | The array of users part of the PBs. | +| `users` | Array<[UserDocument](/tachi-server/documents/user)gt; | The array of users part of the PBs. | ***** @@ -655,7 +655,7 @@ GET /api/v1/games/bms/7K/player-distribution?class=stslDan | Property | Type | Description | | :: | :: | :: | -| `users` | Array<UserDocument> | Array of the users who achieved the courses. | +| `users` | Array<[UserDocument](/tachi-server/documents/user)gt; | Array of the users who achieved the courses. | | `classes` | Array<ClassAchievementDocument> | Data about the recently achieved classes. | ***** @@ -674,7 +674,7 @@ GET /api/v1/games/bms/7K/player-distribution?class=stslDan | Property | Type | Description | | :: | :: | :: | -| `scores` | Array<ScoreDocument> | The highlighted scores. | -| `users` | Array<UserDocument> | The users who own the scores. | +| `scores` | Array<[ScoreDocument](/tachi-server/documents/score)> | The highlighted scores. | +| `users` | Array<[UserDocument](/tachi-server/documents/user)gt; | The users who own the scores. | | `songs` | Array<SongDocument> | The songs the scores are on. | | `charts` | Array<ChartDocument> | The charts the scores are on. | diff --git a/docs/docs/api/routes/import.md b/docs/docs/api/routes/import.md index 7e70b9fb8..326cf0a35 100644 --- a/docs/docs/api/routes/import.md +++ b/docs/docs/api/routes/import.md @@ -6,8 +6,6 @@ ```POST /api/v1/import/file``` -**Kamaitachi Only**. - Perform a score import that depends on a file, such as a .csv import. ### Permissions @@ -22,8 +20,8 @@ appropriate way to send files. | Property | Type | Description | | :: | :: | :: | -| `importType` | string | The ImportType this import is for. This only accepts `file/` ImportTypes. | -| `scoreData` | file | The file to import scores from. | +| `importType` | String | The ImportType this import is for. This only accepts `file/` [ImportTypes](../../tachi-server/import/import-types.md). | +| `scoreData` | File | The file to import scores from. | | HTTP Header | Description | | :: | :: | @@ -32,13 +30,29 @@ appropriate way to send files. !!! info It's the responsibility of the API user to use the X-User-Intent header properly. It should only be used when the user - has explicitly requested this import (i.e. not an automated script). + has explicitly requested this import (i.e. not sent by an automated script). ### Response +**Implementation Dependent**. +There are two reponse scenarios for this endpoint, depending on whether the server uses an external score processor or not. + +#### External Score Processor Response + +If an external score processor is being used, **202** is returned as a status code, and you are given the following: + | Property | Type | Description | | :: | :: | :: | -| `` | ImportDocument | The Import Document created as a result of this import. | +| `url` | String | A URL to poll for information about this import, while it's being processed. | +| `importID` | String | The ID of the import currently being processed. | + +#### Internal Score Processor Response + +If score processing is not done externally, the following is returned: + +| Property | Type | Description | +| :: | :: | :: | +| `` | ImportDocument | The import document created as a result of this import. | ### Example @@ -84,6 +98,15 @@ scoreData= } ``` +**OR** + +```js +{ + url: "https://bokutachi.xyz/api/v1/imports/SOME_IMPORT_ID/poll-status", + importID: "SOME_IMPORT_ID" +} +``` + ***** ## Synchronise scores up with an API. @@ -108,9 +131,25 @@ be performed programmatically, as long as the key has `submit_score` permissions ### Response +**Implementation Dependent**. +There are two reponse scenarios for this endpoint, depending on whether the server uses an external score processor or not. + +#### External Score Processor Response + +If an external score processor is being used, **202** is returned as a status code, and you are given the following: + | Property | Type | Description | | :: | :: | :: | -| `` | ImportDocument | Information about this import. | +| `url` | String | A URL to poll for information about this import, while it's being processed. | +| `importID` | String | The ID of the import currently being processed. | + +#### Internal Score Processor Response + +If score processing is not done externally, the following is returned: + +| Property | Type | Description | +| :: | :: | :: | +| `` | ImportDocument | The import document created as a result of this import. | ### Example @@ -126,4 +165,51 @@ POST /api/v1/import/from-api #### Response -See previous big example. +See previous example. + +***** + +## Force Tachi to reprocess your orphanned scores. + +`POST /api/v1/import/orphans` + + +This endpoint goes through all of the requesting user's [Orphanned Scores](../../tachi-server/import/orphans.md) and attempts to find them a parent song & chart. + +!!! note + Scores automatically attempt de-orphaning every day on Kamaitachi and Bokutachi, + this endpoint just allows you to force a deorphaning, should you wish to. + +### Permissions + +- submit_score + +### Parameters + +None. + +### Response + +| Property | Type | Description | +| :: | :: | :: | +| `processed` | Integer | The amount of orphans processed. | +| `failed` | Integer | The amount of orphans that did not find a parent chart, and were kept as orphans. | +| `success` | Integer | The amount of orphans that successfully found a parent chart, and were turned into real scores. | +| `removed` | Integer | The amount of orphans removed -- They found a parent chart, but were rejected by the converter for being invalid scores, such as having unsupported options or impossible score values. | + +### Example + +#### Request + +N/A + +#### Response + +```js +{ + "processed": 100, + "failed": 95, + "success": 2, + "removed": 3 +} +``` diff --git a/docs/docs/api/routes/oauth2.md b/docs/docs/api/routes/oauth2.md index 0ab88f752..d92f19f90 100644 --- a/docs/docs/api/routes/oauth2.md +++ b/docs/docs/api/routes/oauth2.md @@ -81,7 +81,7 @@ None. | `userID` | Integer | The user this code belongs to. | | `createdOn` | Number | The time in unix milliseconds that this code was created. | -!!! warn +!!! warning These codes expire around 30 minutes from their creation. ### Example diff --git a/docs/docs/api/routes/search.md b/docs/docs/api/routes/search.md index b17916efb..fa1437c36 100644 --- a/docs/docs/api/routes/search.md +++ b/docs/docs/api/routes/search.md @@ -10,7 +10,7 @@ | Property | Type | Description | | :: | :: | :: | -| `search` | string | What to search for. | +| `search` | String | What to search for. | ### Response diff --git a/docs/docs/api/routes/sessions.md b/docs/docs/api/routes/sessions.md index 89cda6f55..46a429960 100644 --- a/docs/docs/api/routes/sessions.md +++ b/docs/docs/api/routes/sessions.md @@ -18,7 +18,7 @@ None. | `scores` | ScoreDocument[] | The score documents involved in this session. | | `songs` | SongDocument[] | The songs these score documents belong to. | | `charts` | ChartDocument[] | The charts these score documents belong to. | -| `user` | UserDocument | The user that made this session. | +| `user` | [UserDocument](/tachi-server/documents/user)| The user that made this session. | ### Example diff --git a/docs/docs/api/routes/status.md b/docs/docs/api/routes/status.md index 58ca241db..d6d0342d7 100644 --- a/docs/docs/api/routes/status.md +++ b/docs/docs/api/routes/status.md @@ -16,18 +16,19 @@ It's a good way of sanity checking whether your code works. | Property | Type | Description | | :: | :: | :: | -| `echo` | string | A string to echo. This is useful for checking whether parameters are sending over properly. | +| `echo` | String | A string to echo. This is useful for checking whether parameters are sending over properly. | ### Response | Property | Type | Description | | :: | :: | :: | -| `serverTime` | integer | The current time of the server in Unix Milliseconds. | -| `whoami` | integer \| null | The userID you are authenticated as. If you are not authenticated, this is null. | -| `version` | string | The current version of Tachi-Server running. | +| `serverTime` | Integer | The current time of the server in Unix Milliseconds. | +| `startTime` | Integer | The time this server was booted in Unix Milliseconds. | +| `whoami` | Integer \| null | The userID you are authenticated as. If you are not authenticated, this is null. | +| `version` | String | The current version of Tachi-Server running. | | `permissions` | Array<string> | The permissions this request had. | -| `echo` (Conditional) | string | If an `echo` parameter was provided, this is that exact parameter. | +| `echo` (Conditional) | String | If an `echo` parameter was provided, this is that exact parameter. | ### Example @@ -57,8 +58,9 @@ bodies properly. ### Example ```json -POST /status ---- +POST /api/v1/status +``` +``` { "echo": "hello world" } diff --git a/docs/docs/api/routes/user-gamept.md b/docs/docs/api/routes/user-gamept.md index 4f3951b20..b28885a44 100644 --- a/docs/docs/api/routes/user-gamept.md +++ b/docs/docs/api/routes/user-gamept.md @@ -21,7 +21,7 @@ None. | `gameStats` | UserGameStatsDocument | The User's GameStats for this game + playtype. | | `firstScore` | ScoreDocument or Null | The user's first score for this game + playtype. This is null if the user has no scores with timestamps. | | `mostRecentScore` | ScoreDocument or Null | The user's most recent score. This is null if the user has no scores with timestamps. | -| `totalScores` | integer | The total amount of scores this user has. | +| `totalScores` | Integer | The total amount of scores this user has. | | `rankingData` | Record<Rating Algorithm, { ranking: integer, outOf: integer }> | The position of this player on the default leaderboards for this game, and how many players it is out of. | ### Example @@ -297,6 +297,59 @@ GET /api/v1/users/zkldi/games/iidx/SP/pbs/best?alg=BPI ***** +## Returns all of a users personal bests. + +`GET /api/v1/users/:userID/games/:game/:playtype/pbs/all` + +### Parameters + +None. + +### Response + +| Property | Type | Description | +| :: | :: | :: | +| `pbs` | Array<PBDocument> | All of the users PB Documents | +| `songs` | Array<SongDocument> | All of the relevant songs. | +| `charts` | Array<ChartDocument> | All of the relevant charts. | + +### Example + +#### Request +``` +GET /api/v1/users/zkldi/games/iidx/SP/pbs/all +``` + +#### Response + +```js +{ + pbs: [{ + userID: 1, + scoreData: { + score: 123, + // ... + } + }], + songs: [{ + title: "Verflucht", + // ... + }], + charts: [{ + songID: 123, + playtype: "SP", + difficulty: "ANOTHER", + // ... + }, { + songID: 123, + playtype: "SP", + difficulty: "HYPER", + }] +} +``` + +***** + ## Get A User's PB for a given chart. `GET /api/v1/users/:userID/games/:game/:playtype/pbs/:chartID` @@ -467,7 +520,7 @@ song titles of played songs inside sessions. | Property | Type | Description | | :: | :: | :: | -| `search` | string | The session name to search for. | +| `search` | String | The session name to search for. | ### Response @@ -510,7 +563,7 @@ These are returned in descending order. | Property | Type | Description | | :: | :: | :: | -| `alg` (Optional) | string | The name of the algorithm to use instead of the default. | +| `alg` (Optional) | String | The name of the algorithm to use instead of the default. | ### Response @@ -572,6 +625,44 @@ None. | :: | :: | :: | | `` | Array<SessionDocument> | The array of the users sessions. | +***** + +## Get a user's most recent session. + +`GET /api/v1/users/:userID/games/:game/:playtype/sessions/last` + +!!! info + This endpoint will return 404 if the user has never had a + session for this game. + +### Parameters + +None. + +### Response + +| Property | Type | Description | +| :: | :: | :: | +| `` | SessionDocument | The user's most recent session. | + +### Example + +#### Request +``` +GET /api/v1/users/zkldi/games/iidx/SP/sessions/last +``` + +#### Response + +```js +{ + "name": "foo", + "desc": "My most recent session", + // ... +} +``` + + ## Get a user's most recent 100 highlighted sessions. `GET /api/v1/users/:userID/games/:game/:playtype/sessions/highlighted` @@ -609,7 +700,8 @@ GET /api/v1/users/zkldi/games/iidx/SP/sessions/highlighted ktRating: 14, bpi: 3 } - highlight: true + highlight: true, + // ... more props }, ] ``` @@ -698,7 +790,7 @@ GET /api/v1/users/zkldi/games/iidx/SP/most-played | :: | :: | :: | | `above` | Array<UserGameStats> | Up to 5 users' game stats better than this user. | | `below` | Array<UserGameStats> | Same as above, but below the user. | -| `users` | Array<UserDocument> | The user documents related to the above statistics. | +| `users` | Array<[UserDocument](/tachi-server/documents/user)gt; | The user documents related to the above statistics. | | `thisUsersStats` | UserGameStats | The requested user's stats for this GPT. | | `thisUsersRanking` | {outOf: integer, ranking: integer} | The requested user's ranking for this GPT. | @@ -810,7 +902,7 @@ GET /api/v1/users/1/games/iidx/SP/history `GET /api/v1/users/:userID/games/:game/:playtype/settings` -!!! warn +!!! warning Unlike most other applications, your settings are completely public. GPT Settings only concern cosmetic things, like what rating algorithms to prefer. diff --git a/docs/docs/api/routes/user-integrations.md b/docs/docs/api/routes/user-integrations.md index df1f01617..9c46ca301 100644 --- a/docs/docs/api/routes/user-integrations.md +++ b/docs/docs/api/routes/user-integrations.md @@ -46,6 +46,8 @@ GET /api/v1/users/1/integrations/kai/flo `POST /api/v1/users/:userID/integrations/kai/:kaiType/oauth2callback` +**Kamaitachi Only** + !!! info This is used as part of an [OAuth2 Flow](https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2). @@ -60,7 +62,7 @@ GET /api/v1/users/1/integrations/kai/flo | Property | Type | Description | | :: | :: | :: | -| `code` | string | The intermediate code to use to get the access_token and refresh_token. | +| `code` | String | The intermediate code to use to get the access_token and refresh_token. | ### Response @@ -174,7 +176,7 @@ PATCH /api/v1/users/1/integrations/arc } ``` -!!! warn +!!! warning This endpoint doesn't do any checking on the `accountID` parameter to check whether it actually works with ARC. There is also no checking to see whether you're the owner of this account. diff --git a/docs/docs/api/routes/users.md b/docs/docs/api/routes/users.md index 6fb317faa..e2fc83229 100644 --- a/docs/docs/api/routes/users.md +++ b/docs/docs/api/routes/users.md @@ -19,7 +19,10 @@ These endpoints are related to users in general. | Property | Type | Description | | :: | :: | :: | -| `` | Array<UserDocument> | The array of up to 100 users returned. | +| `` | Array<[UserDocument](/tachi-server/documents/user)gt; | The array of up to 100 users returned. | + +!!! note + Users are guaranteeably returned in order of when they were `lastSeen`. ### Example @@ -45,28 +48,25 @@ GET /api/v1/users `GET /api/v1/users/:userID` -### Parameters - -| Property | Type | Description | -| :: | :: | :: | - - !!! note The :userID param has some special functionality, and any time you see it in these docs, that functionality is supported. You may pass the integer userID for this user - 1. - You may also pass the username - zkldi. + You may also pass the username - zkldi (This is also case-insensitive, so you could pass ZkLDi). You may also pass the special string - `me` - which - will select whatever user this authentication token - is for. + will select whatever user you are authenticated as. + +### Parameters + +None. ### Response | Property | Type | Description | | :: | :: | :: | -| `` | UserDocument | The user this ID/username corresponds to. | +| `` | [UserDocument](/tachi-server/documents/user)| The user this ID/username corresponds to. | ### Example @@ -82,7 +82,9 @@ GET /api/v1/users/zkldi OR GET /api/v1/users/1 OR -GET /api/v1/users/me WHEN authenticated as userID 1. +GET /api/v1/users/zkLDI (It's case insensitive!) +OR +GET /api/v1/users/me IF authenticated as userID 1. ``` #### Response @@ -97,6 +99,61 @@ GET /api/v1/users/me WHEN authenticated as userID 1. ***** +## Modify this user document. + +`PATCH /api/v1/users/:userID` + +### Permissions + +- Self-Key level authentication as this user. + +### Parameters + +| Property | Type | Description | +| :: | :: | :: | +| `about` | String | An about me. This is rendered as markdown. | +| `status` | String \| Null | The users status. If null, this will be unset. | +| `discord`, `twitter`, `github`, `steam`, `youtube`, `twitch` | String \| Null | Information about this users social media. If null, this field will be unset. | + +### Response + +| Property | Type | Description | +| :: | :: | :: | +| `` | [UserDocument](/tachi-server/documents/user)| The user document with all of those changes applied. | + +### Example + +#### Request +```js +{ + "about": "#Hello!**I'm zkldi**", + "status": "I'm cool!", + "twitter": null, + "steam": "zkldi" +} +``` + +#### Response + +```js +{ + "id": 1, + "username": "zkldi", + "usernameLowercase": "zkldi", + "socialMedia": { + "twitter": null, + "steam": "zkldi", + // this property was already here, and not modified by the request. + "discord": "zkldi#2965", + }, + "about": "#Hello!**I'm zkldi**", + "status": "I'm cool!", + // and other user props... +} +``` + +***** + ## Retrieve user's statistics on all games. `GET /api/v1/users/:userID/game-stats` @@ -228,7 +285,7 @@ None. ### Response -Not JSON. This returns the actual JPG or PNG stored for +**Not JSON**. This returns the actual JPG or PNG stored for this user. ### Example @@ -237,14 +294,12 @@ N/A ***** -***** - ## Unset your profile picture. `DELETE /api/v1/users/:userID/pfp` !!! note - If you do not have a profile picture set, this is + If you do not have a profile picture set, this will be a 404 error. ### Permissions diff --git a/docs/docs/images/advanced-search.png b/docs/docs/images/advanced-search.png new file mode 100644 index 000000000..cafb1d796 Binary files /dev/null and b/docs/docs/images/advanced-search.png differ diff --git a/docs/docs/images/basic-search.png b/docs/docs/images/basic-search.png new file mode 100644 index 000000000..24d2fd14c Binary files /dev/null and b/docs/docs/images/basic-search.png differ diff --git a/docs/docs/images/title-search.png b/docs/docs/images/title-search.png new file mode 100644 index 000000000..4d40ea6f0 Binary files /dev/null and b/docs/docs/images/title-search.png differ diff --git a/docs/docs/tachi-server/batch-manual/overview.md b/docs/docs/tachi-server/batch-manual/overview.md index 082db71af..00e207afe 100644 --- a/docs/docs/tachi-server/batch-manual/overview.md +++ b/docs/docs/tachi-server/batch-manual/overview.md @@ -46,8 +46,8 @@ The fields have the following values: | :: | :: | :: | | `game` | Any Game Identifier | The game this import is for. | | `playtype` | Any Playtype for the above game. | The playtype this import is for. | -| `service` | string | A humanised string to explain where these scores are from. This must be between 2 and 15 characters. | -| `version` (Optional) | string | Optionally, you can specify a version of the game this import is for. This should be used when conflicting versions of songs exist, or when this import is rather old. Most of the time, this does not need to be present. | +| `service` | String | A humanised string to explain where these scores are from. This must be between 2 and 15 characters. | +| `version` (Optional) | String | Optionally, you can specify a version of the game this import is for. This should be used when conflicting versions of songs exist, or when this import is rather old. Most of the time, this does not need to be present. | ### Scores @@ -72,8 +72,8 @@ The properties are described as this: | `score` | Number | The score for this, well, score. This should use the default scoring algorithm for this game. | | `lamp` | Lamp | The lamp for this score. This should be one of the lamps as described in the config for your game + playtype. | | `matchType` | "songTitle" \| "ddrSongHash" \| "tachiSongID" \| "bmsChartHash" \| "inGameID" \| "uscChartHash" | This determines how `identifier` will be used to match your scores' chart with Tachi's database of songs and charts. | -| `identifier` | string | A string that Tachi uses to identify what chart this is for. How this is used depends on the `matchType`. | -| `difficulty` (Conditional) | string | If `matchType` is "tachiSongID", "inGameID", "ddrSongHash" or "songTitle", this field must be present, and describe the difficulty of the chart this score is for. | +| `identifier` | String | A string that Tachi uses to identify what chart this is for. How this is used depends on the `matchType`. | +| `difficulty` (Conditional) | String | If `matchType` is "tachiSongID", "inGameID", "ddrSongHash" or "songTitle", this field must be present, and describe the difficulty of the chart this score is for. | | `timeAchieved` (Optional) | integer \| null | This is *when* the score was achieved in unix milliseconds. This should be provided if possible, as Tachi uses it for a LOT of features. | | `comment` (Optional) | string \| null | A comment from the user about this score. | | `judgements` (Optional) | Record<Game Judgement, integer> | This should be a record of the judgements for your game + playtype, and the integer indicating how often they occured. | diff --git a/docs/docs/tachi-server/contributing.md b/docs/docs/tachi-server/contributing.md index 86081adf7..461e56021 100644 --- a/docs/docs/tachi-server/contributing.md +++ b/docs/docs/tachi-server/contributing.md @@ -29,6 +29,6 @@ I am trying to keep the codebase well organised and tidy. This only works on git 2.23 or greater. Your package manager may not have a version this recent. See [Git Installation for Linux](https://git-scm.com/download/linux). -!!! warn +!!! warning Your code should follow the branching setup we have. You can read about it [here](../infrastructure/branches). diff --git a/docs/docs/tachi-server/documents/score.md b/docs/docs/tachi-server/documents/score.md index b96534dba..08c9f3a90 100644 --- a/docs/docs/tachi-server/documents/score.md +++ b/docs/docs/tachi-server/documents/score.md @@ -15,7 +15,7 @@ ## Definition ```ts -interface PublicUserDocument { +interface Public[UserDocument](/tachi-server/documents/user){ service: string; game: "iidx" | "bms" // ...etc; playtype: __GameSpecific; @@ -33,12 +33,12 @@ interface PublicUserDocument { }; scoreMeta: __GameSpecific; calculatedData: __GameSpecific; - timeAchieved: integer | null; + timeAchieved: Integer | null; songID: integer; chartID: string; isPrimary: boolean; highlight: boolean; - comment: string | null; + comment: String | null; timeAdded: integer; scoreID: string; importType: ImportTypes | null; @@ -57,8 +57,8 @@ The base score document is structured as follows: | `game` | This is the game this score is for. | | `service` | This is a humanised string for representing the place this score came from. This is primarily used by [Batch-Manual](../batch-manual/overview.md) formats to declare where the scores are coming from. | | `userID` | The user that got this score. | -| `timeAchieved` | This is the time this score was actually achieved. This is **NOT NECESSARILY** the time this score was inserted into the database. If this is not known, it can be set to null. | -| `timeAdded` | This is the time the score was added to the Tachi database. This is **NOT NECESSARILY** the time the score was achieved. | +| `timeAchieved` | This is the time this score was actually achieved. This is **NOT** the time this score was inserted into the database. If this is not known, it can be set to null. | +| `timeAdded` | This is the time the score was added to the Tachi database. This is **NOT** the time the score was achieved by the player. | | `songID` | The song this score is on. Even though this can be derived from `chartID`, it's kept next to the score for certain query optimisations. You can read on the difference between charts and songs [here](../implementation-details/songs-charts.md). | | `chartID` | The chart this score was achieved on. | | `isPrimary` | Whether this score is was achieved on a "primary" chart or not. You can read more on what a primary chart is [here](../implementation-details/songs-charts.md#isPrimary). | @@ -88,7 +88,7 @@ sub-document. | `lampIndex`, `gradeIndex` | While `lamp` and `grade` are both strings, these are the raw enum values for those fields. This can be used for filters (select scores where lampIndex > lamps.HARD_CLEAR), or other query methods. | | `esd` | Some games support ESD. This field contains the ESD for that score. For more information on what ESD is, see [What is ESD?](../../user/stats/esd.md) | `judgements` | A record of Judgement->Integer values. The keys for this property depend on the game the score is for. | -| `hitMeta` | 'Meta' information about the user's *hits*. That is, things that aren't *literally* about the score, but are related to how well the user played. This contains properties such as `maxCombo` and `fast` and `slow` counts. All the fields here are optional and nullable. Some games extend this to provide things like `gauge`. | +| `hitMeta` | 'Meta' information about the user's *hits*. That is, things that aren't *literally* about the score, but are related to how the user played. This contains properties such as `maxCombo` and `fast` and `slow` counts. All the fields here are optional and nullable. Some games extend this to provide things like `gauge`. | ### `scoreMeta` @@ -108,6 +108,11 @@ about how the play was achieved. about the **PLAY** the user made, such as the mods and options they had on when playing. + A better name for `scoreMeta` would perhaps have been + `playMeta`, since it is meta information about the play, not the score. + + This is too late to change now, though. + Since `scoreMeta`'s properties are entirely game-specific, they will be covered in more detail in the below section. @@ -144,7 +149,6 @@ The below document is an example IIDX - SP score. "userID": 1, "calculatedData": { "BPI": null, - "K%": null, "ktRating": 9.110264135494702, "ktLampRating": 8 }, @@ -171,7 +175,7 @@ For all games, the following changes are applied: !!! info All games implicitly have `fast`, `slow` and `maxCombo` - as `integer | null` in their hitMeta. + as `Integer | null` in their hitMeta. !!! warning As mentioned above, all properties inside ScoreMeta @@ -181,11 +185,11 @@ For all games, the following changes are applied: ```ts interface HitMeta { - bp: integer | null; + bp: Integer | null; gauge: number | null; gaugeHistory: (number | null)[] | null; scoreHistory: number[] | null; - comboBreak: integer | null; + comboBreak: Integer | null; gsm: { EASY: (number | null)[]; NORMAL: (number | null)[]; @@ -233,16 +237,12 @@ Same as IIDX:SP, but with the following changes to Hit Meta: ```ts interface HitMeta { gauge: number | null; - btnRate: number | null; - holdRate: number | null; - laserRate: number | null; } ``` | Property | Description | | :: | :: | | `gauge` | The gauge the user had when the chart finished. | -| `btnRate`, `holdRate`, `laserRate` | The values the user had for the "rate" bars. These are not of much interest to anyone. | ```ts interface ScoreMeta { @@ -254,26 +254,25 @@ interface ScoreMeta { | :: | :: | | `inSkillAnalyser` | Whether or whether not this score was achieved inside the skill analyser mode. | +!!! warning + The british spelling of the word `analyser` is used here. + ### USC ```ts interface HitMeta { gauge: number | null; - btnRate: number | null; - holdRate: number | null; - laserRate: number | null; } ``` | Property | Description | | :: | :: | | `gauge` | The gauge the user had when the chart finished. | -| `btnRate`, `holdRate`, `laserRate` | The values the user had for the "rate" bars. These are not of much interest to anyone. | ```ts interface ScoreMeta { noteMod: "NORMAL" | "MIRROR" | "RANDOM" | "MIR-RAN" | null; - gaugeMod: "NORMAL" | "HARD" | null; + gaugeMod: "NORMAL" | "HARD" | "PERMISSIVE" | null; } ``` @@ -291,7 +290,7 @@ type BMSHitMeta = BASE_VALID_HIT_META & { [K in BMSJudgePermutations]: integer; } & { - bp: integer | null; + bp: Integer | null; gauge: number | null; }; ``` @@ -306,8 +305,7 @@ type BMSHitMeta = BASE_VALID_HIT_META & interface ScoreMeta { random: "NONRAN" | "RANDOM" | "R-RANDOM" | "S-RANDOM" | "MIRROR" | null; inputDevice: "KEYBOARD" | "BM_CONTROLLER" | null; - client: "LR2" | "beatoraja" | "lr2oraja"; - lntype: null | "LN" | "CN"; + client: "LR2" | "lr2oraja"; } ``` @@ -315,8 +313,7 @@ interface ScoreMeta { | :: | :: | | `random` | The random option this user selected. | | `inputDevice` | Whether this score was achieved on a keyboard or a beatmania controller. If null, this is not known. | -| `client` | What client this score was performed on. Scores achieved on beatoraja have a warning next to them indicating differences in their gauge implementation. | -| `lnType` | What type of LNs this user was using. This only applies to beatoraja and lr2oraja, where CNs are an option. | +| `client` | What client this score was performed on. | ### DDR, maimai, MÚSECA, CHUNITHM diff --git a/docs/docs/tachi-server/documents/user-goal.md b/docs/docs/tachi-server/documents/user-goal.md index c7d540cf9..c9d0b6927 100644 --- a/docs/docs/tachi-server/documents/user-goal.md +++ b/docs/docs/tachi-server/documents/user-goal.md @@ -19,8 +19,8 @@ interface UserGoalDocument { playtype: Playtypes[Game]; achieved: boolean; timeSet: integer; - timeAchieved: integer | null; - lastInteraction: integer | null; + timeAchieved: Integer | null; + lastInteraction: Integer | null; progress: number | null; progressHuman: string; outOf: number; diff --git a/docs/docs/tachi-server/documents/user.md b/docs/docs/tachi-server/documents/user.md index 9577a8934..d9798195e 100644 --- a/docs/docs/tachi-server/documents/user.md +++ b/docs/docs/tachi-server/documents/user.md @@ -7,25 +7,25 @@ ## Definition ```ts -interface PublicUserDocument { +interface Public[UserDocument](/tachi-server/documents/user){ username: string; usernameLowercase: string; id: integer; socialMedia: { - discord?: string | null; - twitter?: string | null; - github?: string | null; - steam?: string | null; - youtube?: string | null; - twitch?: string | null; + discord?: String | null; + twitter?: String | null; + github?: String | null; + steam?: String | null; + youtube?: String | null; + twitch?: String | null; }; joinDate: integer; lastSeen: integer; about: string; - status: string | null; + status: String | null; customPfp: boolean; customBanner: boolean; - clan: string | null; // todo + clan: String | null; // Clans are not implemented yet, so this field is null for everyone. badges: UserBadges[]; authLevel: UserAuthLevels; } @@ -44,7 +44,7 @@ interface PublicUserDocument { | `customPfp`, `customBanner` | Whether this user has a custom profile picture and banner. | | `clan` | Currently unused. This will store a users clan tag if they are in a clan. | | `badges` | An array of badges for this user. This contains things like "beta" and "alpha" tester indicators. | -| `authLevel` | This users auth level. This is an enum stored inside tachi-common, where 0 states the user is banned. | +| `authLevel` | This users auth level. This is an enum stored inside tachi-common. 0 = Banned, 1 = Normal User, 2 = Moderator, 3 = Admin. | ## Example diff --git a/docs/docs/tachi-server/import/importing.md b/docs/docs/tachi-server/import/importing.md index 81d48454a..9e874d21c 100644 --- a/docs/docs/tachi-server/import/importing.md +++ b/docs/docs/tachi-server/import/importing.md @@ -30,7 +30,7 @@ As a rough outline: // ScoreImported implies success: true, and all others imply success: false. type: "ScoreImported" | "KTDataNotFound" // ... and more; // An error message. - message: string | null; + message: String | null; // Some errors return some data about the error, or things like scoreImported returns the score that was imported. content: see_implementation } diff --git a/docs/docs/tachi-server/import/main.md b/docs/docs/tachi-server/import/main.md index f61773435..9d9cf2cbc 100644 --- a/docs/docs/tachi-server/import/main.md +++ b/docs/docs/tachi-server/import/main.md @@ -11,7 +11,7 @@ This function can be found at `src/lib/score-import/framework/score-import-main. | Argument | Type | Description | | :: | :: | :: | -| `user` | PublicUserDocument | The user that is making this import request. | +| `user` | [UserDocument](/tachi-server/documents/user)| The user that is making this import request. | | `userIntent` | boolean | Whether this import was performed with User Intent - See [Import Types](./import-types.md#user-intent) | | `importType` | ImportType | What kind of import "type" this is. For more on this, see [Import Types](./import-types.md) | `InputParser` | Function | The parser function to call. For more info, see [Parsing and Converting](./parse-conv.md) diff --git a/docs/docs/tachi-server/structure/testing.md b/docs/docs/tachi-server/structure/testing.md index 3101f8fdd..a10112094 100644 --- a/docs/docs/tachi-server/structure/testing.md +++ b/docs/docs/tachi-server/structure/testing.md @@ -60,5 +60,5 @@ The hack part here is **not** an understatement, and it is genuinely rather dirt As a downside, this makes error messages *way* more cryptic, but for a 20x performance gain, it can be lived with. -!!! warn +!!! warning If you are getting failures like "Child test left in suite", one of your test files is *crashing* the entire process, leaving all other tests just dangling. diff --git a/docs/docs/user/filter-directives.md b/docs/docs/user/filter-directives.md index 8c667cd72..da5d4abfa 100644 --- a/docs/docs/user/filter-directives.md +++ b/docs/docs/user/filter-directives.md @@ -20,6 +20,10 @@ you search for `AA`, You will get a list of all the scores that were on a song that contains `AA` (such as `AA -rebuild-`) and all of the scores that have the grade `AA` (OR `AAA`, as it's a loose match!). +!!! example + ![](../images/basic-search.png) + Note the inclusion of AAAs and AAs? That's because it tries to match with as much as it can, as loosely as it can! + This isn't always what we want, though! What if I wanted to see only scores on the song `AA`? @@ -31,6 +35,10 @@ title:AA Simple enough, right! +!!! example + ![](../images/title-search.png) + Now, it only loosely matches on the title! + Now, depending on *where* you actually are, different filter directives are available. The above example makes sense for filtering scores, but makes *no* sense for filtering a table of users! @@ -56,13 +64,15 @@ change that behaviour! | Less Than Equal | `percent:<=50` | Matches any percent that is less than or equal to 50. | | Greater Than | `percent:>50` | Matches any percent that is greater than 50. | | Greater Than Equal | `percent:>=50` | Matches any percent that is greater than or equal to 50. | -| Regex | `title:~^[a-z]*$` | Matches any title that matches the regex `^[a-z]*$` | - + + ## Other Things @@ -70,15 +80,25 @@ You can use multiple directives in one filter! `title:$AA percent:>50` - Find all scores on AA where the percent is greater than 50. +!!! example + ![](../images/advanced-search.png) + Here's me combining a lot of directives to find all the charts where I have: + + - A server ranking lower than 10 + - A BPI that is non-zero + - On a chart who's level is greater than 10. + + Pretty powerful stuff! + Multiple directives are separated by spaces. However, if you need to use a space inside a value, you should quote it, like this: -`title:$"FREEDOM DiVE" percent:>50`. +`title:"FREEDOM DiVE" percent:>50`. !!! tip If you need quotes *inside* that, you should escape them, like this: - `artist:!"A Tribe Called \"Quest\"" percent:>50` + `artist:"A Tribe Called \"Quest\"" percent:>50` However, it is likely you will never need to use this. diff --git a/docs/docs/user/games.md b/docs/docs/user/games.md index 5d99d1e94..0c2cbc467 100644 --- a/docs/docs/user/games.md +++ b/docs/docs/user/games.md @@ -44,13 +44,13 @@ The following games are supported on [Kamaitachi](https://kamaitachi.xyz). | :: | :: | :: | | beatmania IIDX | `iidx` | `SP`, `DP` | | MÚSECA | `museca` | `Single` | -| maimai | `maimai` | `Single` | | SOUND VOLTEX | `sdvx` | `Single` | -| Dance Dance Revolution | `ddr` | `SP`, `DP` | | CHUNITHM | `chunithm` | `Single` | -| GITADORA | `gitadora` | `Gita`, `Dora` | -| jubeat | `jubeat` | `Single` | -| pop'n music | `popn` | `9B`[^1] | +| jubeat (In Development) | `jubeat` | `Single` | +| pop'n music (In Development) | `popn` | `9B`[^1] | + + + ### Bokutachi @@ -59,8 +59,9 @@ The following games are supported on [Bokutachi](https://bokutachi.xyz). | Name | Internal Name | Playtypes | | :: | :: | :: | | BMS | `bms` | `7K`, `14K` | -| unnamed_sdvx_clone | `usc` | `Single` | +| unnamed_sdvx_clone | `usc` | `Controller` `Keyboard`[^2] | -[^1]: Pop'n *had* some other playtypes, namely a 5-Button mode, but it seems to be removed now. 9B is used instead of single here for futureproofing. \ No newline at end of file +[^1]: Pop'n *had* some other playtypes, namely a 5-Button mode, but it seems to be removed now. 9B is used instead of single here for futureproofing. +[^2]: This use of playtypes is a small hack to make separate leaderboards for keyboard and controller players. The split is necessary because the two input mechanisms are *very* different at high levels, but there are still a lot of keyboard players. It's a compromise! \ No newline at end of file diff --git a/docs/docs/user/lamps.md b/docs/docs/user/lamps.md index 954c6d096..801eb3c86 100644 --- a/docs/docs/user/lamps.md +++ b/docs/docs/user/lamps.md @@ -4,7 +4,7 @@ Lamps are a term borrowed mainly from Arcade rhythm games. Their name is derived from the visual implementation in IIDX and DDR, where a lamp would light up a specific -colour depending on your, well, lamp. +colour depending on how you cleared the chart. A synonym for this that might make more sense is "clear type", and some games use this name internally. @@ -14,7 +14,16 @@ A synonym for this that might make more sense is "clear type", and some games us In most games, you have a "FULL COMBO", which means you didn't miss. That would be a different lamp to a "CLEAR", -which would be - well - a clear. +which would generally refer to clearing the chart normally. Another common lamp is "FAILED", which is exactly what -you think it would be. \ No newline at end of file +you think it would be. + +## Why Bother? + +Some players like to go for lamps, especially in games like BMS +and IIDX, where scoring and lamping[^1] are fairly separate skills. +Keeping track of your lamps is important for a lot of games, and generally +a cool thing! + +[^1]: Lamping is the colloquial term for 'going for lamps' rather than going for score. \ No newline at end of file diff --git a/docs/docs/user/pbs-scores.md b/docs/docs/user/pbs-scores.md index 18bd69be0..2f6db0e08 100644 --- a/docs/docs/user/pbs-scores.md +++ b/docs/docs/user/pbs-scores.md @@ -2,8 +2,10 @@ A PB is all of your best scores on that chart joined together. In most games, this means joining your best score with your best lamp. -Some games have some additional properties - like BP in IIDX and BMS - that -also need to be joined. + +!!! note + Some games have some additional properties - like BP in IIDX and BMS - that + also need to be joined. ## Why bother? @@ -12,3 +14,19 @@ and people would **NEVER** agree on what the primary metric for a games was. If you got a better lamp on a chart in BMS, and it ruined your existing *sick* score, that would be terrible! + +!!! example + As an example, consider the following scores. + + | Score | Lamp | + | :: | :: | + | 5000 | CLEAR | + | 4000 | HARD CLEAR | + + Your PB on this chart would then therefore be: + + | Score | Lamp | + | :: | :: | + | 5000 | HARD CLEAR| + + As it joins the best score with the best lamp! diff --git a/docs/docs/user/rules.md b/docs/docs/user/rules.md index aefea1992..213dbd25d 100644 --- a/docs/docs/user/rules.md +++ b/docs/docs/user/rules.md @@ -138,7 +138,7 @@ show it to your mother, it doesn't belong here. Uploading illegal (under international common or EU law) material will result in an immediate permanent ban. -!!! warn +!!! warning This rule **especially** applies to loli or shota stuff. I don't want to see that garbage, don't upload it, you'll get in trouble. diff --git a/docs/docs/user/score-oddities.md b/docs/docs/user/score-oddities.md index f72353578..9993aa8e1 100644 --- a/docs/docs/user/score-oddities.md +++ b/docs/docs/user/score-oddities.md @@ -46,3 +46,34 @@ ARC will send HARD CLEAR, 88% and Tachi will have to assume that is a single score. ``` + +## E-Amusement IIDX Resets (0EX Lamps) + +E-Amusement resets scores for IIDX every version. This would be fine under a normal interpretation of 'resets score', but the emphasis here is on the word *score*, not *reset*. + +E-Amusement IIDX Score Resets only reset your EX Score, you actually get to keep your lamp. +For exported E-Amusement CSVs, this means that you submit scores with 0EX, but with lamps. +For sanities sake, scores with 0EX are rejected so that you don't accidentally flood the server with fake scores because... + +## E-Amusement IIDX Resets (Timestamps) + +The timestamp for all your scores is also changed to the point when you first carded in on +the new version of the game, meaning that if you were to import all those 0EX scores, you +would create a session of every single chart you've ever lamped at that exact moment. + +## E-Amusement IIDX Timestamps + +Timestamps in E-Amusement IIDX CSVs are also only on a per-song basis, rather than a per-chart basis. +If you play V (Another) and V (Hyper) in the same session, the data in the CSV says that you +played both of those charts at the same time (since all charts of V have to share a timestamp). + +## Legacy LEGGENDARIA Formats (IIDX) + +From IIDX 21 to IIDX 26, Leggendarias were not their own difficulty. Instead they were +just anothers with the special quantifier that the song title ended in † or †LEGGENDARIA exactly. +To handle this, Tachi will automatically convert song titles ending in † or †LEGGENDARIA +into their original form, changing the difficulty from ANOTHER to LEGGENDARIA. + +!!! note + This only applies to legacy imports -- This has been fixed since IIDX 27 (2019). + diff --git a/docs/docs/user/stats/esd.md b/docs/docs/user/stats/esd.md index 64cd2a701..9a33d9d89 100644 --- a/docs/docs/user/stats/esd.md +++ b/docs/docs/user/stats/esd.md @@ -5,6 +5,10 @@ ESD is short for "Estimated Standard Deviation". Standard deviation is a way of measuring how *dispersed* data is. [Wikipedia](https://en.wikipedia.org/wiki/Standard_deviation) explains what this is and why it works. +!!! warning + ESD is not publically displayed on Tachi at the moment for any game. + This page is technically redundant. + ***** ## Motivation diff --git a/docs/docs/user/stats/tachi.md b/docs/docs/user/stats/tachi.md index 150bdc9d1..76f83db8d 100644 --- a/docs/docs/user/stats/tachi.md +++ b/docs/docs/user/stats/tachi.md @@ -34,10 +34,10 @@ The below statistics apply to individual scores. Every game needs to have a default rating algorithm. A default rating algorithm needs to work well on all scores from all skill levels. - This means that some more 'pro' oriented statistics cannot be the default. + This means that some more 'top player' oriented statistics cannot be the default. Some games might not have *any* rating algorithms. If we dont have - a good built-in contender for a default rating algorithm, we have to invent our own. + a good built-in contender for a default rating algorithm, we will have to invent our own. ***** @@ -54,24 +54,26 @@ Pros: Cons: - Has a poor understanding of high acc levels (MAX- and beyond). +- Generally terrible for high level play. Boils down to getting the best score on easy 12s. KtRating (Kamaitachi Rating) is our custom rolled rating algorithm for IIDX. The issue we have is that IIDX doesn't have any metrics that are a good contender for our default rating algorithm. -DJ Points is worthless because it depends on the notecount of the chart instead of its level -and BPI only really has any meaning to kaidens, so we're stuck having to roll our own statistic. +BPI only really has any meaning to kaidens, so we're stuck having to roll our own statistic. -KtRating was designed to be a generic **timing** rating algorithm for IIDX. It isn't perfect -by any means, and is generally worse than BPI at 12s. It also struggles with things like +KtRating was designed to be a generic **timing** rating algorithm for IIDX. It isn't good +by any means, and is significantly worse than BPI at 12s, 11s and 10s. It also struggles with things like MAX- and stronger scores. -Regardless, it works decently for most charts and most players. It uses a curve such that +Regardless, it works decently for lower level players. It uses a curve such that an AA on a chart rated X will be worth X points. !!! note - X will be influenced by the tierlist. For example, mosaic SPA is rated a 12 internally, - but has a lower tierlist timing rating value of around 10.5. + This is slated to be replaced with DJ Points. An in-built metric in IIDX. + Although that metric is broken for many reasons, it is more immediately understandable, and saves us having to maintain a broken metric. + + See [This GitHub Issue](https://github.com/TNG-dev/tachi-server/issues/597) ***** @@ -85,7 +87,7 @@ Pros: Cons: - Depends on Kaiden Average and World Record, which can be highly fluctuative. -- Not able to accurately cross-compare values (i.e. 20BPI on one song is often not equivalent in 'skill' to 20BPI on another.) +- Not able to accurately cross-compare values (i.e. 20BPI on one song is often not equivalent in 'skill'[^1] to 20BPI on another.) - Only practically works on 12s. It can be extended to 11s, but it doesn't work as well. It does not work at all below 11. There are two implementations of BPI - We'll call them Nori BPI and Poyashi BPI, Tachi uses the @@ -99,7 +101,7 @@ more recent Poyashi BPI. Namely, reducing the impact of high WRs on average BPI. As a consequence, Poyashi BPI is significantly easier than Nori BPI in every circumstance. - Whether this is an issue or not is up to you, and I think most players enjoy seeing the + Whether this is an issue or not is up to you, but I think most players enjoy seeing the larger number. BPI looks at the kaiden average and world record for a chart, and constructs an exponential @@ -108,7 +110,7 @@ equivalent to the world record. !!! info For scores less than the Kaiden Average, Poyashi BPI uses a negative extension that caps - at -15. This appears to be arbitrary. + at -15. This capping decision appears to be arbitrary. For Nori BPI, scores less than the Kaiden Average become [Complex Numbers](https://en.wikipedia.org/wiki/Complex_number). @@ -117,7 +119,8 @@ decently. As mentioned above in the cons, BPI is not very cross-comparable. 20BP is not necessarily as good as 20BPI on another. !!! example - 20BPI on Verflucht Leggendaria is AAA+66. 20BPI on FAKE TIME is also AAA+66. + At the time of writing, 20BPI on Verflucht Leggendaria is AAA+66. 20BPI on FAKE TIME is also AAA+66. + Experienced players will notice a problem here. ***** @@ -143,6 +146,8 @@ BP is not taken into account, and the only lamps that give rating are Normal, Ha !!! note In the scenario where, say, a NC is worth more than a HC, HCing the chart will give the NC rating. + This also applies to EXHCs. + ***** ### VF6 (SDVX, USC) @@ -174,11 +179,8 @@ given score, which made the function painfully discrete. VF4 is deprecated because it's 4 years old at this point, and its flaws make it incredibly abusable. - An implementation of them is still in the - codebase, but is unused and commented out. - ***** - + + ### KtRating (MÚSECA) @@ -328,11 +330,7 @@ respectively. - Stella - Overjoy - For 14K, the currently supported tables are: - - - Normal - - Insane - - Satellite + For 14K, no tables are currently supported. ### Rating (CHUNITHM) @@ -356,9 +354,6 @@ at the accuracy of the provided score. implementation flaws of this algorithm for individual scores. - I imagine it probably overrates fails on high level - charts. - ### Skill (Gitadora) - **Default for GITADORA** @@ -429,7 +424,7 @@ of making VF6 not a small decimal, and is generally how people talk about their volforce. ***** - + -### maimai, museca +### MUSECA The below statistics apply to maimai and museca. @@ -498,7 +493,7 @@ These are almost always derived from individual score statistics as listed above. If a session has less than 10 scores, all of the below -statistics are marked as N/A[^1] except for MFCP. +statistics are marked as N/A except for MFCP. ***** @@ -582,4 +577,4 @@ The average of the highest 10 skills achieved that session. free to report it as an issue if you think it should be added. -[^1]: Internally, they are marked as `null`. \ No newline at end of file +[^1]: Skill is obviously very loosely used here. If there was a consensus on what "skill" something was, we would already have a perfect rating algorithm. diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 781a5f580..b9fca07f5 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -63,6 +63,7 @@ nav: - "api/routes/api-tokens.md" - "api/routes/oauth2.md" - "api/routes/clients.md" + - "api/routes/config.md" - Webhooks: - "api/webhooks/main.md"