From c690e2d908185d09597610be69850dee6c9c3820 Mon Sep 17 00:00:00 2001 From: zkldi Date: Fri, 3 Sep 2021 13:20:57 +0100 Subject: [PATCH] Proofread 1. --- docs/docs/api/auth.md | 11 ++-- docs/docs/api/overview.md | 16 ++--- docs/docs/api/routes/auth.md | 10 +-- docs/docs/api/routes/example.md | 2 +- docs/docs/api/routes/import.md | 2 +- docs/docs/api/routes/status.md | 4 +- docs/docs/api/routes/ugpt-showcase.md | 6 +- docs/docs/api/routes/user-gamept.md | 6 +- docs/docs/api/routes/users.md | 21 ++++++- docs/docs/codebase/batch-manual/overview.md | 8 +-- docs/docs/codebase/contributing.md | 2 +- docs/docs/codebase/documents/score.md | 2 +- .../implementation-details/goal-id.md | 2 +- .../implementation-details/score-id.md | 2 +- docs/docs/codebase/setup/config.md | 61 ++++++++++++++++--- docs/docs/codebase/setup/setup.md | 5 +- docs/docs/codebase/structure/style.md | 4 +- docs/docs/codebase/structure/testing.md | 21 ++++++- docs/docs/index.md | 2 +- docs/docs/user/features.md | 5 +- docs/docs/user/filter-directives.md | 2 +- docs/docs/user/{terminology => }/lamps.md | 0 docs/docs/user/pbs-scores.md | 1 - docs/docs/user/rules.md | 4 +- docs/mkdocs.yml | 4 +- 25 files changed, 144 insertions(+), 59 deletions(-) rename docs/docs/user/{terminology => }/lamps.md (100%) diff --git a/docs/docs/api/auth.md b/docs/docs/api/auth.md index 041cb9f15..d7ee3fcb7 100644 --- a/docs/docs/api/auth.md +++ b/docs/docs/api/auth.md @@ -9,6 +9,8 @@ This page covers how to present your permissions to the server, and what those p There are two ways to authorise a request. The first one involves API keys. +### Token Authentication + To use authentication with a request, you should set a HTTP header of: ``` @@ -17,8 +19,9 @@ Authorization: Bearer API_KEY Where API_KEY is the api key you wish to use. -The other way to authorise a request is with your session cookie. This is **NOT** recommended -for non-user use, and is instead a way for logged-in users to interact with the API as themselves. +### Self-Key Authentication + +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. @@ -27,11 +30,11 @@ The reason for this second authentication method is so that, when a user logs in the cookie they were set to also interact with the API. This type of authentication is referred to as "Self-Key" or "Session-Key" authentication, and it grants special -permissions, such as being able to change your password. +permissions over API Tokens, such as being able to change your password. ## Getting Tokens -Users may create API tokens at Settings > API Tokens. They may also revoke these tokens. +[Our OAuth2 Flow](../codebase/infrastructure/oauth2.md) should be used to acquire API Tokens. ## Permissions diff --git a/docs/docs/api/overview.md b/docs/docs/api/overview.md index 3aec41aaa..d3287994e 100644 --- a/docs/docs/api/overview.md +++ b/docs/docs/api/overview.md @@ -26,10 +26,10 @@ cool things, and used responsibly. Abuse of this API will result in your ability to use it being banned. -The API has a rate limit of 100 requests every minute. This is a rather -generous rate limit, and you should not be close to hitting it. +The API has a rate limit of 500 requests every minute. This is a very +generous rate limit, and you should not even be close to hitting it. -If you are in a scenario where you might be hitting 100 requests a minute, +If you are in a scenario where you might be hitting even 100 requests a minute consistently, please contact me at `zkldi#2965`. Otherwise, you might have your tokens revoked for API abuse. @@ -67,9 +67,9 @@ 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. | -| body | Endpoint Dependent | Any data that the endpoint needs to return, such as a user's document from a profile request. | +| `success` | true | Always true for a successful response. | +| `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. @@ -79,8 +79,8 @@ 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. | +| `success` | false | Always false for a failed response. | +| `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. diff --git a/docs/docs/api/routes/auth.md b/docs/docs/api/routes/auth.md index fd549b6dc..569840212 100644 --- a/docs/docs/api/routes/auth.md +++ b/docs/docs/api/routes/auth.md @@ -23,19 +23,19 @@ 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 | | ### 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 | | :: | :: | -| Set-Cookie | Contains a session cookie for future authentication. | +| `Set-Cookie` | Contains a session cookie for future authentication. | ### Example diff --git a/docs/docs/api/routes/example.md b/docs/docs/api/routes/example.md index 28fb1a049..6b95808fe 100644 --- a/docs/docs/api/routes/example.md +++ b/docs/docs/api/routes/example.md @@ -14,7 +14,7 @@ This endpoint greets the user. *If permissions are required, they will be listed here.* -- example:permission +- example_permission ### Parameters diff --git a/docs/docs/api/routes/import.md b/docs/docs/api/routes/import.md index 68ca76ea9..6af3c7453 100644 --- a/docs/docs/api/routes/import.md +++ b/docs/docs/api/routes/import.md @@ -12,7 +12,7 @@ Perform a score import that depends on a file, such as a .csv import. ### Permissions -- `submit:score` +- `submit_score` ### Parameters diff --git a/docs/docs/api/routes/status.md b/docs/docs/api/routes/status.md index fe951e049..58ca241db 100644 --- a/docs/docs/api/routes/status.md +++ b/docs/docs/api/routes/status.md @@ -37,7 +37,7 @@ It's a good way of sanity checking whether your code works. { "serverTime": 1623331110661, "version": "v2.0.0 (Mysterons)", - "permissions": ["score:submit", "example:permission"], + "permissions": ["score_submit", "example_permission"], "echo": "helloworld" } ``` @@ -68,7 +68,7 @@ POST /status { "serverTime": 1623331110662, "version": "v2.0.0 (Mysterons)", - "permissions": ["score:submit", "example:permission"], + "permissions": ["score_submit", "example_permission"], "echo": "hello world" } ``` \ No newline at end of file diff --git a/docs/docs/api/routes/ugpt-showcase.md b/docs/docs/api/routes/ugpt-showcase.md index 970f2dc9a..40d608806 100644 --- a/docs/docs/api/routes/ugpt-showcase.md +++ b/docs/docs/api/routes/ugpt-showcase.md @@ -108,7 +108,7 @@ PATCH /api/v1/users/1/games/iidx/SP/showcase | Property | Type | Description | | :: | :: | :: | | `mode` | "folder" \| "chart" | Whether the stat to evaluate is on a folder or a chart. | -| `prop` | "grade" \| "lamp" \| "score" \| "percent" or "playcount" if mode is chart. | What property to evaluate on the given criteria. | +| `property` | "grade" \| "lamp" \| "score" \| "percent" or "playcount" if mode is chart. | What property to evaluate on the given criteria. | | `chartID` | string, if mode === "chart" | If mode is chart, this should contain the relevant chartID. | | `folderID` | string, if mode === "folder" | If mode is folder, this should contain the relevant folderID. | | `gte` | number, if mode === "folder" | If mode is folder, this must contain the value the property must be greater than, i.e. lamp >= 6, or percent >= 90 | @@ -125,7 +125,7 @@ PATCH /api/v1/users/1/games/iidx/SP/showcase #### Request ``` -GET /api/v1/users/1/games/iidx/SP/showcase/custom?mode=chart&prop=percent&chartID=some_chart_id +GET /api/v1/users/1/games/iidx/SP/showcase/custom?mode=chart&property=percent&chartID=some_chart_id ``` #### Response @@ -133,7 +133,7 @@ GET /api/v1/users/1/games/iidx/SP/showcase/custom?mode=chart&prop=percent&chartI { stat: { mode: "chart", - prop: "percent", + property: "percent", chartID: "some_chart_id", }, result: { diff --git a/docs/docs/api/routes/user-gamept.md b/docs/docs/api/routes/user-gamept.md index 1f0dfd13f..2a5d056f0 100644 --- a/docs/docs/api/routes/user-gamept.md +++ b/docs/docs/api/routes/user-gamept.md @@ -2,6 +2,8 @@ This endpoints are for specific users information on specific game + playtype combinations. +This scenario appears frequently, and is typically shortened to UGPT. + ***** ## Get information about a user's plays on a game + playtype. @@ -311,7 +313,7 @@ GET /api/v1/users/zkldi/games/iidx/SP/pbs/best?alg=BPI | :: | :: | :: | | `pb` | PBDocument | The user's PB for this chart. | | `chart` | ChartDocument | The chart this PB is on. | -| `scores` (Conditional) | ScoreDocument[] | If `getComposition` is present, then this field contains the array of score documents that composed this PB. | +| `scores` (Conditional) | Array<ScoreDocument> | If `getComposition` is present, then this field contains the array of score documents that composed this PB. | ### Example @@ -863,7 +865,7 @@ GET /api/v1/users/1/games/iidx/SP/settings | Property | Type | Description | | :: | :: | :: | -| `` | UGPTSettingsDocument | The new UGPTSettingsDocument | +| `` | UGPTSettingsDocument | The new UGPTSettingsDocument. | ### Example diff --git a/docs/docs/api/routes/users.md b/docs/docs/api/routes/users.md index 0b06e09db..6fb317faa 100644 --- a/docs/docs/api/routes/users.md +++ b/docs/docs/api/routes/users.md @@ -109,7 +109,10 @@ None. | Property | Type | Description | | :: | :: | :: | -| `` | Array<UserGameStatsDocument> | The array of User Game Stats this user has. | +| `` | Array<UserGameStatsDocument & __rankingData> | The array of User Game Stats this user has. | + +!!! info + For UI reasons, the UserGameStatsDocuments here have an additional `__rankingData` property, which contains leaderboard ranking information for this user. ### Example @@ -133,6 +136,16 @@ GET /api/v1/users/1/game-stats classes: { dan: 14 }, + __rankingData: { + ktRating: { + ranking: 15, + outOf: 74 + }, + BPI: { + ranking: 12, + outOf: 74 + } + } }, { userID: 1, game: "gitadora", @@ -142,6 +155,12 @@ GET /api/v1/users/1/game-stats }, classes: { skillColour: 1 + }, + __rankingData: { + skill: { + ranking: 199, + outOf: 202 + } } }] ``` diff --git a/docs/docs/codebase/batch-manual/overview.md b/docs/docs/codebase/batch-manual/overview.md index bdbb5b895..4226b0df9 100644 --- a/docs/docs/codebase/batch-manual/overview.md +++ b/docs/docs/codebase/batch-manual/overview.md @@ -3,7 +3,7 @@ BATCH-MANUAL is a JSON format that Tachi accepts. This format can be submitted as [a file](../../api/routes/import.md#import-scores-from-a-file) using the `file/batch-manual` [Import Type](../import/import-types.md), or it can be submitted as a -[HTTP request body](todo) +[HTTP request body](todo). ***** @@ -24,9 +24,9 @@ The format is incredibly simple JSON. It is comprised of two base keys, `meta` and `scores`. -!!! question +!!! note These keys were originally called `head` and `body` in Kamaitachi. You will have to update - batch-manual code. + existing batch-manual code. ### Meta @@ -121,7 +121,7 @@ This match type can only be used for BMS. - uscChartHash This looks for the chart SHA1 that USC uses. As expected, this -can only be used for BMS. +can only be used for USC. - ddrSongHash diff --git a/docs/docs/codebase/contributing.md b/docs/docs/codebase/contributing.md index c82c5c634..78a9a1510 100644 --- a/docs/docs/codebase/contributing.md +++ b/docs/docs/codebase/contributing.md @@ -91,7 +91,7 @@ looks like it belongs. - Follow the branching rules. Your code should follow the branching setup we have. -You can read about it [here](./infrastructure/branches) +You can read about it [here](./infrastructure/branches). - Your PR should fix an issue. diff --git a/docs/docs/codebase/documents/score.md b/docs/docs/codebase/documents/score.md index de42a3e98..c4508b5c7 100644 --- a/docs/docs/codebase/documents/score.md +++ b/docs/docs/codebase/documents/score.md @@ -82,7 +82,7 @@ sub-document. | Property | Description | | :: | :: | | `score` | A number describing the "score" the user got. Depending on the game, this may be bounded between various numbers. | -| `lamp` | The lamp the user got. For more information on what a lamp is, see [What are Lamps?](../../user/terminology/lamps.md) +| `lamp` | The lamp the user got. For more information on what a lamp is, see [What are Lamps?](../../user/lamps.md) | `percent` | The 'percent' the user got. That is, their score scaled to the total amount of score they could have possibly got. There are some oddities with this field.[^1]. | | `grade` | The grade the user got. For most games, this is a set of discrete cutoffs for the score's `percent`.[^2] | | `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. | diff --git a/docs/docs/codebase/implementation-details/goal-id.md b/docs/docs/codebase/implementation-details/goal-id.md index f99d25f41..ac578acac 100644 --- a/docs/docs/codebase/implementation-details/goal-id.md +++ b/docs/docs/codebase/implementation-details/goal-id.md @@ -1,4 +1,4 @@ -# Goal ID implementation. +# Goal ID implementation Goal IDs exist to dedupe goals when a user creates a new goal. For example, if a user wants to create a diff --git a/docs/docs/codebase/implementation-details/score-id.md b/docs/docs/codebase/implementation-details/score-id.md index 9c7a3a40f..242dfd7e9 100644 --- a/docs/docs/codebase/implementation-details/score-id.md +++ b/docs/docs/codebase/implementation-details/score-id.md @@ -1,4 +1,4 @@ -# Score ID implementation. +# Score ID implementation Score IDs exist to dedupe scores when a user re-submits the same scores. This happens frequently with `file/` diff --git a/docs/docs/codebase/setup/config.md b/docs/docs/codebase/setup/config.md index e7b73ae38..c371ab604 100644 --- a/docs/docs/codebase/setup/config.md +++ b/docs/docs/codebase/setup/config.md @@ -26,7 +26,14 @@ the main benefits for us are as follows: SESSION_SECRET: "other_secret_key", FLO_API_URL: "https://flo.example.com", EAG_API_URL: "https://eag.example.com", + MIN_API_URL: "https://min.example.com", ARC_API_URL: "https://arc.example.com", + FLO_OAUTH2_INFO: { + CLIENT_ID: "OUR_CLIENT_ID", + CLIENT_SECRET: "OUR_CLIENT_SECRET", + REDIRECT_URI: "https://tachi.example.com/callback" + }, + // FLO_OAUTH2_INFO, EAG_OAUTH2_INFO and MIN_OAUTH2_INFO are all optional. ARC_AUTH_TOKEN: "unused", CDN_FILE_ROOT: "../tachi-cdn", PORT: 8080, @@ -143,15 +150,6 @@ names. "omni" will run the server without any route restrictions. This is used for testing. -### CLIENT_INDEX_HTML_PATH - -- Type: File Path - -The location of `index.html` to serve when any non-server route is hit. - -Since we use a react app for client navigation, the server does not concern itself -with routing the user around, so this is just the react-app index.html to send. - ### ENABLE_SERVER_HTTPS - Type: Boolean @@ -180,3 +178,48 @@ This uses `CDN_FILE_ROOT` to determine where the CDN's content should be. If present, and a string, this points to the webpack dev server for a react app. Having this option set results in CORS being enabled for *that* specific URL. This is useful for local development, but should not be used in production. + +### FLO/MIN/EAG_OAUTH2_INFO + +- Type: OAuth2Info | undefined + +If present, these define our OAuth2 Client data for interacting with these services. These look like this: +```js +{ + FLO_OAUTH2_INFO: { + CLIENT_ID: "OUR_CLIENT_ID", + CLIENT_SECRET: "OUR_CLIENT_SECRET", + REDIRECT_URI: "https://tachi.example.com" + } +} +``` + +### RATE_LIMIT + +- Type: Positive Integer +- Default: 500 + +Determines how many requests an APIKey OR IP can make every minute. + +The default is set to the very generous 500, as it's possible for users to accidentally hit 100 requests/min by refreshing very fast. + +### OAUTH_CLIENT_CAP + +- Type: Positive Integer +- Default: 15 + +The amount of OAuth2Clients one user can create at any one time. Defaults to 15. + +### OPTIONS_ALWAYS_SUCCEEDS + +- Type: Boolean +- Default: false + +If true, all `OPTIONS` requests to the server will return `200`, no matter what. This is a hack used for development CORS. + +### NO_CONSOLE + +- Type: Boolean +- Default: false + +If true, logging to the console will be disabled, and only filesystem logging will be on. diff --git a/docs/docs/codebase/setup/setup.md b/docs/docs/codebase/setup/setup.md index e7eef852f..8f5e2cc92 100644 --- a/docs/docs/codebase/setup/setup.md +++ b/docs/docs/codebase/setup/setup.md @@ -4,8 +4,7 @@ This page documents how to get the `tachi-server` up and running. This guide assumes that you are running on some flavour of Linux. -`tachi-server` is not tested on Windows, but it is likely -to work, as we don't depend on any OS specific calls. +`tachi-server` does not work out of the box on windows, as it depends on Redis (See [How do I run Redis on Windows?](https://stackoverflow.com/questions/6476945/how-do-i-run-redis-on-windows)). That said, the `tachi-server` code does not depend on any os-specific calls, and likely will work if you can fix the redis thing. ## Externals @@ -68,7 +67,7 @@ server. The config file we use for running tests can be found in `.github/test.conf.json5` -You can read more on how this config file works at [Configuration Info](./config.md) +You can read more on how this config file works at [Configuration Info](./config.md). ### 7. Run! diff --git a/docs/docs/codebase/structure/style.md b/docs/docs/codebase/structure/style.md index 564ee76bd..799b80886 100644 --- a/docs/docs/codebase/structure/style.md +++ b/docs/docs/codebase/structure/style.md @@ -51,7 +51,7 @@ CRLF and LF. The Tachi-Server codebase handles code comments against these rules: 1. Do not write redundant comments. -2. Return signatures are obvious from TypeScript most of the time. If they aren't, declare them. +2. Return signatures are obvious from TypeScript most of the time. If they aren't, declare them with TypeScript rather than commenting them. 3. Most of the time, comments should describe *why* code does something. 4. The exception is when a line or function **needs** to do something complicated - in which case, comments can be *how*. 5. That said, code should be self-explanatory. @@ -93,7 +93,7 @@ function CalculateStandardDeviation(dataset: number[]) { } ``` -Now that is much cleaner, but it's still perfect. +Now that is much cleaner, but it's still not perfect. For example, what if someone didn't know what the standard deviation was? Standard Deviation is *external knowledge*, and as such, we should document what this is. diff --git a/docs/docs/codebase/structure/testing.md b/docs/docs/codebase/structure/testing.md index 8ca115be5..3101f8fdd 100644 --- a/docs/docs/codebase/structure/testing.md +++ b/docs/docs/codebase/structure/testing.md @@ -12,7 +12,7 @@ Tests are ran with [node-tap](https://node-tap.org). You can run the server test suite with the following script: ``` -pnpm fulltest +pnpm test ``` This will execute every test, and also perform coverage @@ -44,4 +44,21 @@ the same filename as the file they are testing. Coverage should be kept above 80%. New code should be tested. Pull Requests will be rejected if they contain significant -changes that are untested! \ No newline at end of file +changes that are untested! + +## Single Process TAP + +Since we don't mock our MongoDB install out, we run a real instance of Mongo for our tests, and run against it. + +TAP runs every test file in isolation. This is a good idea normally, as it means state is never shared across files, and nothing bad is generally going to happen. + +*However*, it takes around 2 seconds to connect to the MongoDB server when a new test file is started. These 2 seconds add up over the course of a ~1500 test file suite, and result in tests taking over 15-20 minutes. + +To get around this, we use a Single Process TAP hack, which rolls all of our test files up into one test file. + +The hack part here is **not** an understatement, and it is genuinely rather dirty. **BUT**, it runs in ~40-50 seconds, works the same for coverage, and can just generally be ignored as an abstraction layer. + +As a downside, this makes error messages *way* more cryptic, but for a 20x performance gain, it can be lived with. + +!!! warn + 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/index.md b/docs/docs/index.md index cc8969fe9..b5fc71ae4 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -42,7 +42,7 @@ If you want to contribute to this documentation, you can find the repository [he If you want to contribute to the Tachi backend code, you can find the repository [here!](https://github.com/zkldi/tachi-server) !!! note - You should read the [Contributing To Tachi-Server](./codebase/contributing.md) page beforehand. + You should really read the [Contributing To Tachi](./codebase/contributing.md) page beforehand! ## Acknowledgements diff --git a/docs/docs/user/features.md b/docs/docs/user/features.md index 66b558758..26dcf280a 100644 --- a/docs/docs/user/features.md +++ b/docs/docs/user/features.md @@ -125,8 +125,11 @@ You can set goals for Lamps, Grades, Percents and score. !!! example Get 950'000 on FREEDOM DiVE. + SS FREEDOM DiVE. + Clear FREEDOM DiVE + Get 95% on FREEDOM DiVE. We can also control *how many* scores need to match the @@ -200,7 +203,7 @@ aiming for, or is just lazy and doesn't like setting goals? In general, we're bad at setting our own goals. How can we fix that? -### Why Milestones? +### What are Milestones? Milestones are **pre-made groups of goals**. As an example, we might bundle together some goals aimed at SOUND VOLTEX diff --git a/docs/docs/user/filter-directives.md b/docs/docs/user/filter-directives.md index 77814c99b..a2758b548 100644 --- a/docs/docs/user/filter-directives.md +++ b/docs/docs/user/filter-directives.md @@ -77,7 +77,7 @@ space inside a value, you should quote it, like this: !!! tip If you need quotes *inside* that, you should escape them, like this: - `title:!"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/terminology/lamps.md b/docs/docs/user/lamps.md similarity index 100% rename from docs/docs/user/terminology/lamps.md rename to docs/docs/user/lamps.md diff --git a/docs/docs/user/pbs-scores.md b/docs/docs/user/pbs-scores.md index ff9d13f45..18bd69be0 100644 --- a/docs/docs/user/pbs-scores.md +++ b/docs/docs/user/pbs-scores.md @@ -1,5 +1,4 @@ # What's the difference between a PB and a Score? - 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. diff --git a/docs/docs/user/rules.md b/docs/docs/user/rules.md index 9d3d60687..bdd04bad9 100644 --- a/docs/docs/user/rules.md +++ b/docs/docs/user/rules.md @@ -46,7 +46,7 @@ may be warned. ## R3: You **MUST NOT** play on invalid input devices. Games on Tachi have specific requirements for what kind of -setups are 'legitimate'. That means that you **SHOULD NOT** +setups are 'legitimate'. That means that you **MUST NOT** submit scores on input devices that aren't fair for that game, such as playing pop'n on a keyboard. @@ -77,6 +77,8 @@ The valid input devices are listed below. | BMS (7K) | Keyboard, any IIDX Controller | Keyboard play is allowed for BMS 7K. | | BMS (14K) | any two IIDX Controllers | Keyboard play is **NOT** allowed for BMS 14K. | +!!! info + As always though, exercise some common sense. I'm not going to whitelist controllers on here, because that's asking for trouble. Use your head as for whether something is fair or not, and if you're not certain still, ask in the discord. ## R4: Do not harm other people in the community. diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index e09fd0aa0..4465d5725 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -32,9 +32,7 @@ nav: - "user/features.md" - "user/pbs-scores.md" - "user/filter-directives.md" - - - Terminology: - - "user/terminology/lamps.md" + - "user/lamps.md" - Statistics: - "user/stats/tachi.md"