mirror of
https://github.com/zkldi/Tachi.git
synced 2026-09-26 17:07:58 +03:00
* docs: migrate from mkdocs to mdbook - Rename old mkdocs docs/ to old-docs/ for reference - Set up new docs/ with mdbook (book.toml + src/ tree) - Mirror full nav structure from mkdocs.yml into SUMMARY.md - Add Justfile-docs with docs-serve, docs-build, docs-check, docs-install recipes - Import Justfile-docs from root Justfile - Rewrite .github/workflows/docs.yml: build step uses taiki-e/install-action to install mdbook, split into separate build + deploy jobs, PR builds run the check step too * ci(docs): pin actions to SHAs, install mdbook via release binary * ci(docs): install mdbook from apt instead of curling a release binary * dev: replace mkdocs python stack with mdbook in dev image * ci(docs): apt only works on Debian; restore release binary install for Ubuntu CI * docs: fix duplicate file entries in SUMMARY.md * docs: remove docs-install recipe * docs: remove site-url from book.toml to fix asset loading * dev: install mdbook from upstream release binary, not Debian apt The Debian package (0.4.x+ds) strips bundled font assets, leaving the built site without fonts/fonts.css. Use the upstream tarball (same as CI) so the theme is complete. Handles x86_64 and aarch64. * docs: vendor mdbook tarballs in dev/mdbook/, install from there Dockerfile.dev uses COPY + tar to install the right arch at build time. CI extracts the x86_64 tarball directly from the checkout. No network access required for either — and no stripped-fonts Debian package. * fix: unwritten
211 lines
6.8 KiB
Markdown
211 lines
6.8 KiB
Markdown
# What is BATCH-MANUAL?
|
|
|
|
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](./direct-manual.md).
|
|
|
|
*****
|
|
|
|
## Motivation
|
|
|
|
Instead of Tachi writing new support for every kind of
|
|
possible export, and bothering other service providers
|
|
to write exports, we could write a generic format we accept
|
|
and then users with a bit of scripting knowledge can import
|
|
their own scores.
|
|
|
|
This has the additional advantage of allowing extremely
|
|
obscure imports, and reduces the workload on Tachi.
|
|
|
|
## Format
|
|
|
|
The format is incredibly simple JSON.
|
|
|
|
It is comprised of two base keys, `meta` and `scores`.
|
|
|
|
!!! note
|
|
These keys were originally called `head` and `body` in Kamaitachi. You will have to update
|
|
existing batch-manual code.
|
|
|
|
### Meta
|
|
|
|
The `meta` key contains metadata, and looks like this:
|
|
|
|
```json
|
|
{
|
|
"game": "iidx",
|
|
"playtype": "SP",
|
|
"service": "foobar"
|
|
}
|
|
```
|
|
|
|
The fields have the following values:
|
|
|
|
| Property | Type | Description |
|
|
| :: | :: | :: |
|
|
| `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. |
|
|
|
|
### Scores
|
|
|
|
The `scores` property is an array of Batch Manual Scores. An example
|
|
score is as follows:
|
|
|
|
```json
|
|
{
|
|
"score": 500,
|
|
"lamp": "HARD CLEAR",
|
|
"matchType": "songTitle",
|
|
"identifier": "5.1.1.",
|
|
"difficulty": "ANOTHER",
|
|
"timeAchieved": 1624324467489
|
|
}
|
|
```
|
|
|
|
The properties are described as this:
|
|
|
|
| Property | Type | Description |
|
|
| :: | :: | :: |
|
|
| `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. |
|
|
| `percent` (Conditional) | Number | Only appears for `jubeat`. This should be set to the Percent for this score. In jubeat's case, this is your Music Rate. |
|
|
| `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. |
|
|
| `artist` (Conditional) | String | If `matchType` is "songTitle", this field can be present, and describe the artist name for less equivocal matching. This field is optional for legacy purposes. |
|
|
| `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 occurred. |
|
|
| `optional` (Optional) | See [Game Specific Optional Metrics](../../schemas/score.md#game-specific) | Any optional metrics you wish to provide for this game. |
|
|
| `scoreMeta` (Optional) | See [Game Specific Score Meta](../../schemas/score.md#game-specific) | This can be a partial record of various `scoreMeta` props for this game. |
|
|
|
|
!!! warning
|
|
`identifier` should always be a string. Even if it's something like a numeric ID! Tachi will handle this.
|
|
|
|
!!! warning
|
|
`timeAchieved` is in **UNIX MILLISECONDS**. Most programming languages use unix seconds. You might have to
|
|
multiply your timestamps by 1000.
|
|
|
|
#### Match Type
|
|
|
|
There are many match types, and they all use identifier
|
|
in a different way.
|
|
|
|
- songTitle
|
|
|
|
As the name implies, this searches for a song whose title
|
|
is exactly `identifier`. **THIS IS NOT FUZZY MATCHING**,
|
|
and is by far the least reliable way to send scores to
|
|
Tachi. This is kept for compatibility purposes with poor quality APIs.
|
|
|
|
This match type *necessitates* that `difficulty` be defined
|
|
and set to a valid difficulty for this game + playtype.
|
|
|
|
This match type can be augmented with a secondary identifier `artist`
|
|
which resolves title clashes:
|
|
|
|
```json
|
|
{
|
|
"score": 500,
|
|
"lamp": "HARD CLEAR",
|
|
"matchType": "songTitle",
|
|
"identifier": "5.1.1.",
|
|
"artist": "dj nagureo",
|
|
"difficulty": "ANOTHER",
|
|
"timeAchieved": 1624324467489
|
|
}
|
|
```
|
|
|
|
- tachiSongID
|
|
|
|
This uses `identifier` as if it were an integer, to match
|
|
songs based on the `id` field of a tachi song.
|
|
|
|
This match type *necessitates* that `difficulty` be defined
|
|
and set to a valid difficulty for this game + playtype.
|
|
|
|
- bmsChartHash
|
|
|
|
As the name implies, this looks for the chart hash BMS
|
|
uses. This can be either the MD5 hash or the SHA256 hash,
|
|
both will match.
|
|
|
|
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 USC.
|
|
|
|
- inGameID
|
|
|
|
This uses the in-game-ID for this **SONG**. You, therefore,
|
|
**MUST** specify the difficulty for this chart as well.
|
|
|
|
This is supported for the following games:
|
|
|
|
- IIDX
|
|
- Pop'n Music
|
|
- Jubeat
|
|
- CHUNITHM
|
|
- GITADORA
|
|
- maimai
|
|
- maimai DX
|
|
- WACCA
|
|
- MUSECA
|
|
|
|
- sdvxInGameID
|
|
|
|
This uses the in-game-ID for this SDVX song. You must specify
|
|
the difficulty for this chart as well.
|
|
|
|
The reason SDVX gets its own special `matchType` is because this
|
|
matchType supports `difficulty: "ANY_INF"`. This special difficulty
|
|
means that it will check for any of `INF/GRV/HVN/VVD/XCD` for this song.
|
|
|
|
This is useful for services that store all of those as the same difficulty.
|
|
|
|
- ddrSongHash
|
|
|
|
This is a 32-character hash used by the official DDR e-amusement website to
|
|
identify a song; you must specify the difficulty for this chart as well.
|
|
|
|
## Example
|
|
|
|
A final example of a simple BATCH MANUAL format
|
|
looks like this:
|
|
|
|
```json
|
|
{
|
|
"meta": {
|
|
"game": "iidx",
|
|
"playtype": "SP",
|
|
"service": "My Service"
|
|
},
|
|
"scores": [{
|
|
"score": 500,
|
|
"lamp": "HARD CLEAR",
|
|
"matchType": "songTitle",
|
|
"identifier": "5.1.1.",
|
|
"artist": "dj nagureo",
|
|
"difficulty": "ANOTHER"
|
|
}, {
|
|
"score": 123,
|
|
"lamp": "FAILED",
|
|
"matchType": "tachiSongID",
|
|
"identifier": "1",
|
|
"difficulty": "HYPER",
|
|
"comment": "This score sucked!",
|
|
"optional": {
|
|
"bp": 5
|
|
},
|
|
"scoreMeta": {
|
|
"random": "MIRROR"
|
|
}
|
|
}]
|
|
}
|
|
```
|