mirror of
https://github.com/zkldi/Tachi.git
synced 2026-10-14 10:09:09 +03:00
[maimaidx] Move to BUDDiES PLUS (#1131)
* [maimaidx] Move to BUDDiES PLUS * Add alias for THE RHYTHM SENSE TEST * Make BUDDiES+ table the default
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -33586,6 +33586,19 @@
|
||||
"title": "Level 9+ (FiNALE)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "1",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "Fef2e84ea3c606f9276e059649901ba85b6b142a974e7de2f9d6ba59282843630",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 1 (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "1",
|
||||
@@ -33593,7 +33606,7 @@
|
||||
},
|
||||
"folderID": "F6368ee35170f27874d3869158e738981a5dc8e2a0c0ca74d783d8006269bd1dd",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 1 (BUDDiES)",
|
||||
@@ -33638,6 +33651,19 @@
|
||||
"title": "Level 1 (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "10",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "Fa117b16d37438d927d47801e1bf1ddd215d28016d14c0d133d67546e0809a3cd",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 10 (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "10",
|
||||
@@ -33645,7 +33671,7 @@
|
||||
},
|
||||
"folderID": "F6aecc2187c5cd1dfe30b908442648d1b7869bb67289433332a6c70175d370ec0",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 10 (BUDDiES)",
|
||||
@@ -33690,6 +33716,19 @@
|
||||
"title": "Level 10 (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "10+",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "F9925170992bdec8794b7d13a843c52630a442ee63293e8d23b2f3bf37bdef652",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 10+ (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "10+",
|
||||
@@ -33697,7 +33736,7 @@
|
||||
},
|
||||
"folderID": "F642ad377715ff93d029411bc63370283d6a2f36d0f5633df1c6e3b20c6e3cab8",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 10+ (BUDDiES)",
|
||||
@@ -33742,6 +33781,19 @@
|
||||
"title": "Level 10+ (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "11",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "F09843bf05a7113bb2fc7c758659269d8a9ccbb6e7adde1ce1be0809f8afb2511",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 11 (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "11",
|
||||
@@ -33749,7 +33801,7 @@
|
||||
},
|
||||
"folderID": "F081c0cc40019fd901337698f6505f5467b370c72eaac53e06bce77b5c0e03e11",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 11 (BUDDiES)",
|
||||
@@ -33794,6 +33846,19 @@
|
||||
"title": "Level 11 (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "11+",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "F51e05a887207012ebde7865a85ec6f2481628fea23e8734f4692f983a041e100",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 11+ (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "11+",
|
||||
@@ -33801,7 +33866,7 @@
|
||||
},
|
||||
"folderID": "Fc49208811a0ca9564d5cb155c1b28304aae0be18c21063ea23de8a73114c2c2d",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 11+ (BUDDiES)",
|
||||
@@ -33846,6 +33911,19 @@
|
||||
"title": "Level 11+ (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "12",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "Fdc9bc25d76b268e48b24964c4db5193dc405874ea593ba6ce71ca35ad9d143be",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 12 (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "12",
|
||||
@@ -33853,7 +33931,7 @@
|
||||
},
|
||||
"folderID": "Fdfb1de2d66b33089de5d61d115c7736848d309feda17d5358e026ea7b3bdeb28",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 12 (BUDDiES)",
|
||||
@@ -33898,6 +33976,19 @@
|
||||
"title": "Level 12 (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "12+",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "F1fa7dd4ca7ec86afb9459c170c1a80a4c456624fa8a906ba86bf347e966adf8b",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 12+ (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "12+",
|
||||
@@ -33905,7 +33996,7 @@
|
||||
},
|
||||
"folderID": "F0465da9514b6b0c2d68ceca7175bbc3dd1b06daa8ef311c44d15f56b05bf9baa",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 12+ (BUDDiES)",
|
||||
@@ -33950,6 +34041,19 @@
|
||||
"title": "Level 12+ (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "13",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "Ff411e0c8e8ebeb3bba69ff93ced04760cbf7557b62cb833d143d4c5878d5718c",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 13 (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "13",
|
||||
@@ -33957,7 +34061,7 @@
|
||||
},
|
||||
"folderID": "Fc637e835fed1b11d9539f357771c4a774abcaed76dc7d210bbaf0ee7a3812179",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 13 (BUDDiES)",
|
||||
@@ -34002,6 +34106,19 @@
|
||||
"title": "Level 13 (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "13+",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "Fa09dcc2155876643750834faea81f2a881b14badea5531ea47f201634e0a156d",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 13+ (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "13+",
|
||||
@@ -34009,7 +34126,7 @@
|
||||
},
|
||||
"folderID": "F111ec00e7fcd5d79055eb1898f109eebe42e0ac592bc05208e7635b1977ac6e0",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 13+ (BUDDiES)",
|
||||
@@ -34054,6 +34171,19 @@
|
||||
"title": "Level 13+ (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "14",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "Ff76d7681a0d04f8e52e9b5dd306ad9b996ef50d7e05673e8cf13a40f4b6951b9",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 14 (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "14",
|
||||
@@ -34061,7 +34191,7 @@
|
||||
},
|
||||
"folderID": "F98d753fb4b81e7e9f6bcc39f97999bc25563c0476fa2794984ab7318de1e983c",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 14 (BUDDiES)",
|
||||
@@ -34106,6 +34236,19 @@
|
||||
"title": "Level 14 (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "14+",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "F47e93c31737047e344feddb1c3ff4038f66536bcfe7fa29a548568e9fd580060",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 14+ (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "14+",
|
||||
@@ -34113,7 +34256,7 @@
|
||||
},
|
||||
"folderID": "Fa0f3c5ec11cfcb42c3360f736e22aa4e311723d7e7e118a071af9a148f5f3a1d",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 14+ (BUDDiES)",
|
||||
@@ -34158,6 +34301,19 @@
|
||||
"title": "Level 14+ (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "15",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "Fd85a7efb82e9080d09ec23e458cc708bb4983e779168d51af7cea02f96ec1ef4",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 15 (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "15",
|
||||
@@ -34165,7 +34321,7 @@
|
||||
},
|
||||
"folderID": "F27358f4f2d040acfe4fa4994e2764ff9e980f4fd3d68e5af2d2e6e38484b444a",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 15 (BUDDiES)",
|
||||
@@ -34210,6 +34366,19 @@
|
||||
"title": "Level 15 (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "2",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "F74b6493bfd7ea5da6943e96a5931278fc7d6fc28b9077703892f507dcc5dc57d",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 2 (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "2",
|
||||
@@ -34217,7 +34386,7 @@
|
||||
},
|
||||
"folderID": "Fc5b103397b1ff0db69c2971b7a243af218468a189b6a34521ec586d23cd4786d",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 2 (BUDDiES)",
|
||||
@@ -34262,6 +34431,19 @@
|
||||
"title": "Level 2 (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "3",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "F0fc01c632ea6da2ea0d749d68ed3e584bbc1b2c5c5849e117deda4510fea3549",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 3 (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "3",
|
||||
@@ -34269,7 +34451,7 @@
|
||||
},
|
||||
"folderID": "F46d9183887727748b93fa0cd876945e1019e75de0c5a2ce366e3163a3f2fb72f",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 3 (BUDDiES)",
|
||||
@@ -34314,6 +34496,19 @@
|
||||
"title": "Level 3 (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "4",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "F45117e65389a9cfe946265f1a9c337c14cc70874d1e9086310bcc6ecc5bd6266",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 4 (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "4",
|
||||
@@ -34321,7 +34516,7 @@
|
||||
},
|
||||
"folderID": "Fb15edb32fad5af468bb2bc3fa066d0d488d9b05fd81a3327fa32e0ab1a07cbd5",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 4 (BUDDiES)",
|
||||
@@ -34366,6 +34561,19 @@
|
||||
"title": "Level 4 (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "5",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "Fdde7542d0215cffea61437e2427f9084dc47e6b1bf8e8b4af4a795f394cda954",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 5 (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "5",
|
||||
@@ -34373,7 +34581,7 @@
|
||||
},
|
||||
"folderID": "Fdc6000db2761ef641da81d4776213147a824cd5b0fed7d047d3b8cac9b6ffb89",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 5 (BUDDiES)",
|
||||
@@ -34418,6 +34626,19 @@
|
||||
"title": "Level 5 (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "6",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "F9b0bd0bd2d7f2df3cf898ee1239eb2f83e94958386650d2355feb6b336c2568e",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 6 (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "6",
|
||||
@@ -34425,7 +34646,7 @@
|
||||
},
|
||||
"folderID": "F7e4758cbbb6bc5551e4d3606a7c4948744a9451913a5ab9ac09f84884b307bdd",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 6 (BUDDiES)",
|
||||
@@ -34470,6 +34691,19 @@
|
||||
"title": "Level 6 (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "7",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "Fd82cdb730ee281616accc5a1195b6fbbe532b8fd96fccd4856fc2d29e89020db",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 7 (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "7",
|
||||
@@ -34477,7 +34711,7 @@
|
||||
},
|
||||
"folderID": "Fba7a1cf6300906989c72be6bc77866995a2cfe6e243fd4dbb0ea2498297a5d6b",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 7 (BUDDiES)",
|
||||
@@ -34522,6 +34756,19 @@
|
||||
"title": "Level 7 (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "7+",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "F75c3d6ac386e7e85dd6dc4c6638b877de1a82f8ce7f653a53538827667283b2f",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 7+ (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "7+",
|
||||
@@ -34529,7 +34776,7 @@
|
||||
},
|
||||
"folderID": "F711c04281259d8a6d2a573babd40b97e4097a036147444e82553a989657dd912",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 7+ (BUDDiES)",
|
||||
@@ -34574,6 +34821,19 @@
|
||||
"title": "Level 7+ (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "8",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "F18a62c4ea18e3b94a19110bcc4831bca51e6cb8834808fc689199c47aa7415df",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 8 (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "8",
|
||||
@@ -34581,7 +34841,7 @@
|
||||
},
|
||||
"folderID": "F2254693dd4dd780baab128512a5b9ce8ed68e97c865d430e307bec63a00ec15a",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 8 (BUDDiES)",
|
||||
@@ -34626,6 +34886,19 @@
|
||||
"title": "Level 8 (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "8+",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "Fa34aef19a4453b76485f9079be7cdf8bd8a6cb9b3cc0942ac35867cff71d8243",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 8+ (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "8+",
|
||||
@@ -34633,7 +34906,7 @@
|
||||
},
|
||||
"folderID": "Fceb713055431ec52fa4c8ecbb7ab2869440a764612ae74a485e162453a73bd7d",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 8+ (BUDDiES)",
|
||||
@@ -34678,6 +34951,19 @@
|
||||
"title": "Level 8+ (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "9",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "Fd136268d1daefafce66c0703d4cb8af0571b0ac5083048f5529cda07e65cb84d",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 9 (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "9",
|
||||
@@ -34685,7 +34971,7 @@
|
||||
},
|
||||
"folderID": "F7e2d733286bdc0c6264e4163e6014948bb6bb1f05b810119f317f5a57985d077",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 9 (BUDDiES)",
|
||||
@@ -34730,6 +35016,19 @@
|
||||
"title": "Level 9 (UNiVERSE PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "9+",
|
||||
"versions": "buddiesplus"
|
||||
},
|
||||
"folderID": "Fc78dea6db6604fd646428a49cf9de6791e385e7003942522d88976d5123069c3",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 9+ (BUDDiES PLUS)",
|
||||
"type": "charts"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"level": "9+",
|
||||
@@ -34737,7 +35036,7 @@
|
||||
},
|
||||
"folderID": "F9d069cb37a49c2dd33eab44d72e7f45d36b059c0ec826b9272ece746559c47f3",
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"searchTerms": [],
|
||||
"title": "Level 9+ (BUDDiES)",
|
||||
|
||||
@@ -15568,5 +15568,18 @@
|
||||
"id": 1230,
|
||||
"searchTerms": [],
|
||||
"title": "Bloody Trail"
|
||||
},
|
||||
{
|
||||
"altTitles": [],
|
||||
"artist": "☆リズムに合わせてボタンを叩き達成率を競うゲームです☆",
|
||||
"data": {
|
||||
"displayVersion": "Splash",
|
||||
"genre": "maimai"
|
||||
},
|
||||
"id": 1231,
|
||||
"searchTerms": [
|
||||
"THE RHYTHM SENSE TEST"
|
||||
],
|
||||
"title": "全世界共通リズム感テスト"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -3831,6 +3831,40 @@
|
||||
},
|
||||
{
|
||||
"default": true,
|
||||
"description": "Levels for maimai DX in BUDDiES PLUS.",
|
||||
"folders": [
|
||||
"Fef2e84ea3c606f9276e059649901ba85b6b142a974e7de2f9d6ba59282843630",
|
||||
"F74b6493bfd7ea5da6943e96a5931278fc7d6fc28b9077703892f507dcc5dc57d",
|
||||
"F0fc01c632ea6da2ea0d749d68ed3e584bbc1b2c5c5849e117deda4510fea3549",
|
||||
"F45117e65389a9cfe946265f1a9c337c14cc70874d1e9086310bcc6ecc5bd6266",
|
||||
"Fdde7542d0215cffea61437e2427f9084dc47e6b1bf8e8b4af4a795f394cda954",
|
||||
"F9b0bd0bd2d7f2df3cf898ee1239eb2f83e94958386650d2355feb6b336c2568e",
|
||||
"Fd82cdb730ee281616accc5a1195b6fbbe532b8fd96fccd4856fc2d29e89020db",
|
||||
"F75c3d6ac386e7e85dd6dc4c6638b877de1a82f8ce7f653a53538827667283b2f",
|
||||
"F18a62c4ea18e3b94a19110bcc4831bca51e6cb8834808fc689199c47aa7415df",
|
||||
"Fa34aef19a4453b76485f9079be7cdf8bd8a6cb9b3cc0942ac35867cff71d8243",
|
||||
"Fd136268d1daefafce66c0703d4cb8af0571b0ac5083048f5529cda07e65cb84d",
|
||||
"Fc78dea6db6604fd646428a49cf9de6791e385e7003942522d88976d5123069c3",
|
||||
"Fa117b16d37438d927d47801e1bf1ddd215d28016d14c0d133d67546e0809a3cd",
|
||||
"F9925170992bdec8794b7d13a843c52630a442ee63293e8d23b2f3bf37bdef652",
|
||||
"F09843bf05a7113bb2fc7c758659269d8a9ccbb6e7adde1ce1be0809f8afb2511",
|
||||
"F51e05a887207012ebde7865a85ec6f2481628fea23e8734f4692f983a041e100",
|
||||
"Fdc9bc25d76b268e48b24964c4db5193dc405874ea593ba6ce71ca35ad9d143be",
|
||||
"F1fa7dd4ca7ec86afb9459c170c1a80a4c456624fa8a906ba86bf347e966adf8b",
|
||||
"Ff411e0c8e8ebeb3bba69ff93ced04760cbf7557b62cb833d143d4c5878d5718c",
|
||||
"Fa09dcc2155876643750834faea81f2a881b14badea5531ea47f201634e0a156d",
|
||||
"Ff76d7681a0d04f8e52e9b5dd306ad9b996ef50d7e05673e8cf13a40f4b6951b9",
|
||||
"F47e93c31737047e344feddb1c3ff4038f66536bcfe7fa29a548568e9fd580060",
|
||||
"Fd85a7efb82e9080d09ec23e458cc708bb4983e779168d51af7cea02f96ec1ef4"
|
||||
],
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"playtype": "Single",
|
||||
"tableID": "maimaidx-Single-buddiesplus-levels",
|
||||
"title": "maimai DX (BUDDiES PLUS)"
|
||||
},
|
||||
{
|
||||
"default": false,
|
||||
"description": "Levels for maimai DX in BUDDiES.",
|
||||
"folders": [
|
||||
"F6368ee35170f27874d3869158e738981a5dc8e2a0c0ca74d783d8006269bd1dd",
|
||||
@@ -3858,7 +3892,7 @@
|
||||
"F27358f4f2d040acfe4fa4994e2764ff9e980f4fd3d68e5af2d2e6e38484b444a"
|
||||
],
|
||||
"game": "maimaidx",
|
||||
"inactive": false,
|
||||
"inactive": true,
|
||||
"playtype": "Single",
|
||||
"tableID": "maimaidx-Single-buddies-levels",
|
||||
"title": "maimai DX (BUDDiES)"
|
||||
@@ -4996,4 +5030,4 @@
|
||||
"tableID": "wacca-Single-reverse-levels",
|
||||
"title": "WACCA Reverse Levels"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
/**
|
||||
* Run parse-maimaidx-dataset.js first.
|
||||
*
|
||||
* Internal levels for BUDDiES songs are at
|
||||
* https://docs.google.com/spreadsheets/d/1vSqx2ghJKjWwCLrDEyZTUMSy5wkq_gY4i0GrJgSreQc/edit
|
||||
* Internal levels for BUDDiES+ songs are at
|
||||
* https://docs.google.com/spreadsheets/d/1d1AjO92Hj-iay10MsqdR_5TswEaikzC988aEOtFyybo/edit
|
||||
*
|
||||
* Download sheets as CSV and use `-f <CSV filename>`.
|
||||
*
|
||||
* If you have a `music` folder from a current maimai DX dump, pass it with `-d path/to/music`.
|
||||
*/
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
@@ -250,8 +248,8 @@ function addOtherSheet(csvData: string[][], headerRow: number, options: AddOther
|
||||
const {
|
||||
parseCategory = false,
|
||||
hasCategoryColumn = false,
|
||||
markLatest = false,
|
||||
markLatestExceptions = [],
|
||||
// markLatest = false,
|
||||
// markLatestExceptions = [],
|
||||
} = options;
|
||||
|
||||
const songs = ReadCollection("songs-maimaidx.json");
|
||||
|
||||
@@ -4,8 +4,8 @@ const { MutateCollection, CreateFolderID } = require("../../util");
|
||||
const GAME = "maimaidx";
|
||||
const PLAYTYPES = ["Single"];
|
||||
const PREFIX = "Level";
|
||||
const VERSION = "BUDDiES";
|
||||
const VERSIONID = "buddies";
|
||||
const VERSION = "BUDDiES PLUS";
|
||||
const VERSIONID = "buddiesplus";
|
||||
const TITLE = `maimai DX (${VERSION})`;
|
||||
const SHORTTITLE = `${VERSIONID}-levels`; // this is used in the tableID
|
||||
const DESCRIPTION = `Levels for maimai DX in ${VERSION}.`;
|
||||
|
||||
@@ -39,13 +39,7 @@ const VERSION_DISPLAY_NAMES = [
|
||||
"BUDDiES",
|
||||
"BUDDiES PLUS",
|
||||
];
|
||||
const DIFFICULTIES = [
|
||||
"Basic",
|
||||
"Advanced",
|
||||
"Expert",
|
||||
"Master",
|
||||
"Re:Master",
|
||||
];
|
||||
const DIFFICULTIES = ["Basic", "Advanced", "Expert", "Master", "Re:Master"];
|
||||
|
||||
interface IDWithDisplayName {
|
||||
id: number;
|
||||
@@ -72,6 +66,7 @@ interface MusicXML {
|
||||
artistName: IDWithDisplayName;
|
||||
AddVersion: IDWithDisplayName;
|
||||
genreName: IDWithDisplayName;
|
||||
eventName: IDWithDisplayName;
|
||||
|
||||
notesData: {
|
||||
Notes: NotesData[];
|
||||
@@ -95,7 +90,10 @@ if (require.main !== module) {
|
||||
|
||||
const program = new Command();
|
||||
program
|
||||
.requiredOption("-i, --input <OPTIONS DIRS...>", "The options directories of your maimai DX install.")
|
||||
.requiredOption(
|
||||
"-i, --input <OPTIONS DIRS...>",
|
||||
"The options directories of your maimai DX install."
|
||||
)
|
||||
.requiredOption("-v, --version <VERSION>", "The version of this maimai DX install.")
|
||||
.option("-f, --force", "Forces inGameID overwrites where it shouldn't be automatically done.");
|
||||
program.parse(process.argv);
|
||||
@@ -105,9 +103,9 @@ const versions = Object.keys(GetGamePTConfig("maimaidx", "Single").versions);
|
||||
|
||||
if (versions.indexOf(options.version) === -1) {
|
||||
throw new Error(
|
||||
`Invalid version of '${options.version}'. Expected any of ${
|
||||
versions.join(",")
|
||||
}. If you're adding a new version, go update common/src/config/game-config/maimai-dx.ts.`
|
||||
`Invalid version of '${options.version}'. Expected any of ${versions.join(
|
||||
","
|
||||
)}. If you're adding a new version, go update common/src/config/game-config/maimai-dx.ts.`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -186,17 +184,16 @@ for (const optionsDir of options.input) {
|
||||
|
||||
// Manual override since the song's title is empty in the dataset and not
|
||||
// IDEOGRAPHIC SPACE (U+3000).
|
||||
let tachiSongID = inGameID === 11422
|
||||
? 959
|
||||
: songTitleArtistMap.get(`${musicData.name.str}-${musicData.artistName.str}`);
|
||||
|
||||
let tachiSongID =
|
||||
inGameID === 11422
|
||||
? 959
|
||||
: songTitleArtistMap.get(`${musicData.name.str}-${musicData.artistName.str}`);
|
||||
|
||||
// Has this song been disabled in-game?
|
||||
if (musicData.disable) {
|
||||
if (musicData.disable || musicData.eventName.id === 0) {
|
||||
if (tachiSongID !== undefined) {
|
||||
logger.info(
|
||||
`Removing charts of song ID ${tachiSongID} from version ${
|
||||
options.version
|
||||
}, because the disable flag in Music.xml is enabled.`
|
||||
`Removing charts of song ID ${tachiSongID} from version ${options.version}, because the disable flag in Music.xml is enabled.`
|
||||
);
|
||||
|
||||
// Songs are removed mid-version by marking the `disable` flag,
|
||||
@@ -211,19 +208,17 @@ for (const optionsDir of options.input) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// New song?
|
||||
if (tachiSongID === undefined) {
|
||||
const displayVersion = VERSION_DISPLAY_NAMES[musicData.AddVersion.id];
|
||||
|
||||
if (!displayVersion) {
|
||||
throw new Error(
|
||||
`Unknown version ID ${
|
||||
musicData.AddVersion.id
|
||||
}. Update database-seeds/scripts/rerunners/maimaidx/merge-options.ts.`
|
||||
`Unknown version ID ${musicData.AddVersion.id}. Update database-seeds/scripts/rerunners/maimaidx/merge-options.ts.`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -248,7 +243,10 @@ for (const optionsDir of options.input) {
|
||||
}
|
||||
|
||||
for (const [index, difficulty] of musicData.notesData.Notes.entries()) {
|
||||
if (!difficulty.isEnable || !existsSync(path.join(musicDir, difficulty.file.path))) {
|
||||
if (
|
||||
!difficulty.isEnable ||
|
||||
!existsSync(path.join(musicDir, difficulty.file.path))
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -256,18 +254,16 @@ for (const optionsDir of options.input) {
|
||||
|
||||
if (difficultyName === undefined) {
|
||||
throw new Error(
|
||||
`Unknown difficulty ID ${
|
||||
index
|
||||
}. Update database-seeds/scripts/rerunners/maimaidx/merge-options.ts and possibly common/src/config/game-support/maimai-dx.ts.`
|
||||
`Unknown difficulty ID ${index}. Update database-seeds/scripts/rerunners/maimaidx/merge-options.ts and possibly common/src/config/game-support/maimai-dx.ts.`
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if (inGameID > 10000) {
|
||||
difficultyName = `DX ${difficultyName}`;
|
||||
}
|
||||
|
||||
|
||||
let exists: ChartDocument<"maimaidx:Single"> | undefined;
|
||||
|
||||
|
||||
if (inGameID === 11422) {
|
||||
exists = chartMap.get(`-x0o0x_-${difficultyName}`);
|
||||
} else {
|
||||
@@ -275,10 +271,10 @@ for (const optionsDir of options.input) {
|
||||
`${musicData.name.str}-${musicData.artistName.str}-${difficultyName}`
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const level = calculateLevel(difficulty);
|
||||
const levelNum = calculateLevelNum(difficulty);
|
||||
|
||||
|
||||
if (exists) {
|
||||
const displayName = `${musicData.artistName.str} - ${musicData.name.str} [${exists.difficulty}] (${exists.chartID})`;
|
||||
|
||||
@@ -287,40 +283,44 @@ for (const optionsDir of options.input) {
|
||||
exists.data.inGameID = inGameID;
|
||||
} else if (exists.data.inGameID !== inGameID) {
|
||||
logger.warn(
|
||||
`The chart ${displayName} already exists in charts-maimaidx under a different inGameID (${
|
||||
exists.data.inGameID
|
||||
} != ${inGameID}). Is this a duplicate with a different inGameID?`
|
||||
`The chart ${displayName} already exists in charts-maimaidx under a different inGameID (${exists.data.inGameID} != ${inGameID}). Is this a duplicate with a different inGameID?`
|
||||
);
|
||||
|
||||
if (options.force) {
|
||||
logger.warn("Overwriting anyways, because --force has been requested.");
|
||||
exists.data.inGameID = inGameID;
|
||||
} else {
|
||||
logger.warn("Must be resolved manually. Use --force to overwrite anyways.");
|
||||
logger.warn(
|
||||
"Must be resolved manually. Use --force to overwrite anyways."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const versionIndex = exists.versions.indexOf(options.version);
|
||||
|
||||
|
||||
if (versionIndex === -1) {
|
||||
exists.versions.push(options.version);
|
||||
}
|
||||
|
||||
|
||||
if (isLatestVersion) {
|
||||
if (exists.level !== level) {
|
||||
logger.info(`Chart ${displayName} has had a level change: ${exists.level} -> ${level}.`);
|
||||
logger.info(
|
||||
`Chart ${displayName} has had a level change: ${exists.level} -> ${level}.`
|
||||
);
|
||||
exists.level = level;
|
||||
}
|
||||
|
||||
if (exists.levelNum !== levelNum) {
|
||||
logger.info(`Chart ${displayName} has had a levelNum change: ${exists.levelNum} -> ${levelNum}.`);
|
||||
logger.info(
|
||||
`Chart ${displayName} has had a levelNum change: ${exists.levelNum} -> ${levelNum}.`
|
||||
);
|
||||
exists.levelNum = levelNum;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
const chartDoc: ChartDocument<"maimaidx:Single"> = {
|
||||
chartID: CreateChartID(),
|
||||
songID: tachiSongID,
|
||||
@@ -334,14 +334,16 @@ for (const optionsDir of options.input) {
|
||||
inGameID,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
newCharts.push(chartDoc);
|
||||
|
||||
logger.info(`Inserted new chart ${musicData.artistName.str} - ${musicData.name.str} [${chartDoc.difficulty}] (${chartDoc.chartID}).`);
|
||||
logger.info(
|
||||
`Inserted new chart ${musicData.artistName.str} - ${musicData.name.str} [${chartDoc.difficulty}] (${chartDoc.chartID}).`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MutateCollection("songs-maimaidx.json", (songs: Array<SongDocument<"maimaidx">>) => [
|
||||
...songs,
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
const fetch = require("node-fetch");
|
||||
const { CreateChartID, ReadCollection, WriteCollection, GetFreshSongIDGenerator } = require("../../util");
|
||||
const { CreateLogger } = require("mei-logger");
|
||||
|
||||
const logger = CreateLogger("parse-maimaidx-dataset");
|
||||
|
||||
const CURRENT_VERSION = "buddiesplus";
|
||||
const CURRENT_VERSION_NUM = 245;
|
||||
const DATA_URL = "https://maimai.sega.jp/data/maimai_songs.json";
|
||||
const ALIAS_URL =
|
||||
"https://raw.githubusercontent.com/lomotos10/GCM-bot/main/data/aliases/en/maimai.tsv";
|
||||
|
||||
const versionMap = new Map([
|
||||
[0, null],
|
||||
[100, "maimai"],
|
||||
[110, "maimai PLUS"],
|
||||
[120, "GreeN"],
|
||||
[130, "GreeN PLUS"],
|
||||
[140, "ORANGE"],
|
||||
[150, "ORANGE PLUS"],
|
||||
[160, "PiNK"],
|
||||
[170, "PiNK PLUS"],
|
||||
[180, "MURASAKi"],
|
||||
[185, "MURASAKi PLUS"],
|
||||
[190, "MiLK"],
|
||||
[195, "MiLK PLUS"],
|
||||
[199, "FiNALE"],
|
||||
[200, "maimaiでらっくす"],
|
||||
[205, "maimaiでらっくす PLUS"],
|
||||
[210, "Splash"],
|
||||
[215, "Splash PLUS"],
|
||||
[220, "UNiVERSE"],
|
||||
[225, "UNiVERSE PLUS"],
|
||||
[230, "FESTiVAL"],
|
||||
[235, "FESTiVAL PLUS"],
|
||||
[240, "BUDDiES"],
|
||||
]);
|
||||
|
||||
const diffNames = ["bas", "adv", "exp", "mas", "remas"];
|
||||
|
||||
const diffMap = new Map([
|
||||
["bas", "Basic"],
|
||||
["adv", "Advanced"],
|
||||
["exp", "Expert"],
|
||||
["mas", "Master"],
|
||||
["remas", "Re:Master"],
|
||||
]);
|
||||
|
||||
// Songs that are released in different versions in international and Japanese regions.
|
||||
// The key is the title in the dataset, and the value is the version to use (refer to versionMap).
|
||||
const versionOverrides = {
|
||||
"INTERNET OVERDOSE": 230,
|
||||
"Knight Rider": 230,
|
||||
"Let you DIVE!": 230,
|
||||
"Trrricksters!!": 230,
|
||||
"Λzure Vixen": 240,
|
||||
};
|
||||
|
||||
(async () => {
|
||||
const songs = ReadCollection("songs-maimaidx.json");
|
||||
const charts = ReadCollection("charts-maimaidx.json");
|
||||
|
||||
const existingSongs = new Map(songs.map((e) => [`${e.title}-${e.artist}`, e.id]));
|
||||
const existingCharts = new Map(charts.map((e) => [`${e.songID}-${e.difficulty}`, e.chartID]));
|
||||
|
||||
logger.info(`Fetching official song information from ${DATA_URL}...`);
|
||||
|
||||
const datum = await fetch(DATA_URL).then((r) => r.json());
|
||||
const aliases = new Map();
|
||||
|
||||
logger.info(`Fetching aliases from ${ALIAS_URL}...`);
|
||||
|
||||
const aliasesRaw = await fetch(ALIAS_URL).then((r) => r.text());
|
||||
|
||||
for (const line of aliasesRaw.split("\n")) {
|
||||
const [title, ...alias] = line.split("\t");
|
||||
aliases.set(title, alias);
|
||||
}
|
||||
|
||||
// not properly implemented yet as i can't find romaji titles for
|
||||
// japanese titled songs
|
||||
const altTitles = [];
|
||||
|
||||
const getFreshSongID = GetFreshSongIDGenerator("maimaidx");
|
||||
let chartsWithLevelChanges = 0;
|
||||
|
||||
for (const data of datum) {
|
||||
// We don't support UTAGE charts, which are similar to CHUNITHM's WORLD'S END.
|
||||
if (data.lev_utage) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const version = versionOverrides[data.title] ?? Number(data.version.substring(0, 3));
|
||||
|
||||
if (version > CURRENT_VERSION_NUM && !Object.keys(versionOverrides).includes(data.title)) {
|
||||
// Skipping songs that are newer than currently supported version.
|
||||
logger.warn(`Ignoring song ${data.artist} - ${data.title}, which is newer than CURRENT_VERSION_NUM.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
let tachiSongID = existingSongs.get(`${data.title}-${data.artist}`);
|
||||
|
||||
if (data.title === " " && data.artist === "x0o0x_") {
|
||||
// Manual override since the song's title is "" (empty) in the dataset.
|
||||
tachiSongID = 959;
|
||||
}
|
||||
|
||||
if (tachiSongID !== undefined) {
|
||||
const song = songs.find((e) => e.id === tachiSongID);
|
||||
|
||||
song.searchTerms = aliases.get(data.title.trim()) ?? [];
|
||||
} else {
|
||||
tachiSongID = getFreshSongID();
|
||||
|
||||
songs.push({
|
||||
id: tachiSongID,
|
||||
title: data.title.trim(),
|
||||
artist: data.artist.trim(),
|
||||
searchTerms: aliases.get(data.title.trim()) ?? [],
|
||||
altTitles,
|
||||
data: {
|
||||
displayVersion: versionMap.get(version),
|
||||
genre: data.catcode.trim(),
|
||||
},
|
||||
});
|
||||
|
||||
logger.info(`Added new song ${data.artist.trim()} - ${data.title.trim()}.`);
|
||||
}
|
||||
|
||||
diffNames.forEach((diff) => {
|
||||
// check for existence of difficulty
|
||||
if (!data[`dx_lev_${diff}`]) {
|
||||
return;
|
||||
}
|
||||
|
||||
const chartID = existingCharts.get(`${tachiSongID}-DX ${diffMap.get(diff)}`);
|
||||
const chart = charts.find((e) => e.chartID === chartID);
|
||||
const lvNum = Number(data[`dx_lev_${diff}`].replace(/\+/u, ".6"));
|
||||
|
||||
if (chartID) {
|
||||
if (!chart.versions.includes(CURRENT_VERSION)) {
|
||||
chart.versions.push(CURRENT_VERSION);
|
||||
}
|
||||
|
||||
if (chart.level !== data[`dx_lev_${diff}`]) {
|
||||
logger.info(`Chart ${data.artist} - ${data.title} [DX ${diffMap.get(diff)}] (${chartID}) has had a level change: ${chart.level} -> ${data[`dx_lev_${diff}`]}.`);
|
||||
|
||||
chart.level = data[`dx_lev_${diff}`];
|
||||
chart.levelNum = lvNum;
|
||||
|
||||
chartsWithLevelChanges++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
charts.push({
|
||||
songID: tachiSongID,
|
||||
chartID: CreateChartID(),
|
||||
level: data[`dx_lev_${diff}`],
|
||||
levelNum: lvNum,
|
||||
isPrimary: true,
|
||||
difficulty: `DX ${diffMap.get(diff)}`,
|
||||
playtype: "Single",
|
||||
data: {
|
||||
inGameID: null,
|
||||
},
|
||||
versions: [CURRENT_VERSION],
|
||||
});
|
||||
|
||||
logger.info(`Added new chart ${data.artist} - ${data.title} [DX ${diffMap.get(diff)}].`);
|
||||
});
|
||||
|
||||
diffNames.forEach((diff) => {
|
||||
// check for existence of difficulty
|
||||
if (!data[`lev_${diff}`]) {
|
||||
return;
|
||||
}
|
||||
|
||||
const chartID = existingCharts.get(`${tachiSongID}-${diffMap.get(diff)}`);
|
||||
const chart = charts.find((e) => e.chartID === chartID);
|
||||
|
||||
const lvNum = Number(data[`lev_${diff}`].replace(/\+/u, ".6"));
|
||||
|
||||
if (chartID) {
|
||||
if (!chart.versions.includes(CURRENT_VERSION)) {
|
||||
chart.versions.push(CURRENT_VERSION);
|
||||
}
|
||||
|
||||
if (chart.level !== data[`lev_${diff}`]) {
|
||||
logger.info(`Chart ${data.artist} - ${data.title} [${diffMap.get(diff)}] (${chartID}) has had a level change: ${chart.level} -> ${data[`lev_${diff}`]}.`);
|
||||
|
||||
chart.level = data[`lev_${diff}`];
|
||||
chart.levelNum = lvNum;
|
||||
|
||||
chartsWithLevelChanges++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
charts.push({
|
||||
songID: tachiSongID,
|
||||
chartID: CreateChartID(),
|
||||
level: data[`lev_${diff}`],
|
||||
levelNum: lvNum,
|
||||
isPrimary: true,
|
||||
difficulty: diffMap.get(diff),
|
||||
playtype: "Single",
|
||||
data: {},
|
||||
versions: [CURRENT_VERSION],
|
||||
});
|
||||
|
||||
logger.info(`Added new chart ${data.artist} - ${data.title} [${diffMap.get(diff)}].`);
|
||||
});
|
||||
}
|
||||
|
||||
if (chartsWithLevelChanges > 0) {
|
||||
logger.warn(`${chartsWithLevelChanges} chart(s) has had level changes, and their levelNum has been adjusted to default values. You should obtain the new levelNum for this chart using merge-options.ts or add-maimaidx-internal-levels.ts.`);
|
||||
}
|
||||
|
||||
WriteCollection("charts-maimaidx.json", charts);
|
||||
WriteCollection("songs-maimaidx.json", songs);
|
||||
})();
|
||||
@@ -0,0 +1,302 @@
|
||||
import { CreateLogger } from "mei-logger";
|
||||
import { ChartDocument, Difficulties, SongDocument } from "tachi-common";
|
||||
import {
|
||||
CreateChartID,
|
||||
GetFreshSongIDGenerator,
|
||||
ReadCollection,
|
||||
WriteCollection,
|
||||
} from "../../util";
|
||||
|
||||
const logger = CreateLogger("parse-maimaidx-dataset");
|
||||
|
||||
type BaseDifficulty = "bas" | "adv" | "exp" | "mas" | "remas";
|
||||
type MaimaiDXDifficulty = `${"dx_" | ""}lev_${BaseDifficulty}`;
|
||||
|
||||
type MaimaiDXSong = {
|
||||
artist: string;
|
||||
catcode: string;
|
||||
image_url: string;
|
||||
release: string;
|
||||
sort: string;
|
||||
title: string;
|
||||
title_kana: string;
|
||||
version: string;
|
||||
kanji?: string;
|
||||
comment?: string;
|
||||
lev_utage?: string;
|
||||
} & Record<MaimaiDXDifficulty, string | undefined>;
|
||||
|
||||
interface InternalLevelEntry {
|
||||
dx: boolean;
|
||||
lv: Record<Exclude<BaseDifficulty, "remas">, number> & { remas?: number };
|
||||
ico: string;
|
||||
}
|
||||
|
||||
const DATA_URL = "https://maimai.sega.jp/data/maimai_songs.json";
|
||||
const INTERNAL_LEVEL_URL =
|
||||
"https://sgimera.github.io/mai_RatingAnalyzer/scripts_maimai/maidx_in_lv_buddiesplus.js";
|
||||
|
||||
const VERSION_OVERRIDES = {
|
||||
"INTERNET OVERDOSE": 230,
|
||||
"Knight Rider": 230,
|
||||
"Let you DIVE!": 230,
|
||||
"Trrricksters!!": 230,
|
||||
"Λzure Vixen": 240,
|
||||
};
|
||||
const VERSION_MAP = new Map([
|
||||
[0, null],
|
||||
[100, "maimai"],
|
||||
[110, "maimai PLUS"],
|
||||
[120, "GreeN"],
|
||||
[130, "GreeN PLUS"],
|
||||
[140, "ORANGE"],
|
||||
[150, "ORANGE PLUS"],
|
||||
[160, "PiNK"],
|
||||
[170, "PiNK PLUS"],
|
||||
[180, "MURASAKi"],
|
||||
[185, "MURASAKi PLUS"],
|
||||
[190, "MiLK"],
|
||||
[195, "MiLK PLUS"],
|
||||
[199, "FiNALE"],
|
||||
[200, "maimaiでらっくす"],
|
||||
[205, "maimaiでらっくす PLUS"],
|
||||
[210, "Splash"],
|
||||
[215, "Splash PLUS"],
|
||||
[220, "UNiVERSE"],
|
||||
[225, "UNiVERSE PLUS"],
|
||||
[230, "FESTiVAL"],
|
||||
[235, "FESTiVAL PLUS"],
|
||||
[240, "BUDDiES"],
|
||||
[245, "BUDDiES PLUS"],
|
||||
]);
|
||||
const CURRENT_VERSION_NUM = 245;
|
||||
const CURRENT_VERSION = "buddiesplus";
|
||||
const DIFFICULTY_TO_TACHI_DIFFICULTY: Record<MaimaiDXDifficulty, Difficulties["maimaidx:Single"]> =
|
||||
{
|
||||
lev_bas: "Basic",
|
||||
lev_adv: "Advanced",
|
||||
lev_exp: "Expert",
|
||||
lev_mas: "Master",
|
||||
lev_remas: "Re:Master",
|
||||
dx_lev_bas: "DX Basic",
|
||||
dx_lev_adv: "DX Advanced",
|
||||
dx_lev_exp: "DX Expert",
|
||||
dx_lev_mas: "DX Master",
|
||||
dx_lev_remas: "DX Re:Master",
|
||||
} as const;
|
||||
|
||||
const DX_REGEX = /dx\s*:\s*([01])/u;
|
||||
const LV_REGEX = /lv\s*:\s*(\[(?:-?[\d.]+\s*,?\s*)+\])/u;
|
||||
const JACKET_FILENAME_REGEX = /ico\s*:\s*['"`]([0-9a-f]+)['"`]/u;
|
||||
|
||||
async function ParseInternalLevelData(
|
||||
url: string = INTERNAL_LEVEL_URL
|
||||
): Promise<InternalLevelEntry[]> {
|
||||
const text = await fetch(url).then((r) => r.text());
|
||||
const data: InternalLevelEntry[] = [];
|
||||
|
||||
for (const line of text.split("\n")) {
|
||||
const dxMatch = line.match(DX_REGEX);
|
||||
const lvMatch = line.match(LV_REGEX);
|
||||
const jacketMatch = line.match(JACKET_FILENAME_REGEX);
|
||||
|
||||
if (!dxMatch || !lvMatch || !jacketMatch) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const dx = Number(dxMatch[1]!);
|
||||
|
||||
if (dx !== 0 && dx !== 1) {
|
||||
logger.warn(`DX should be 0 or 1, found ${dxMatch[1]} in ${line}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
let lv: InternalLevelEntry["lv"];
|
||||
|
||||
try {
|
||||
const tmp = JSON.parse(lvMatch[1]!);
|
||||
|
||||
if (!Array.isArray(tmp) || tmp.some((c) => typeof c !== "number")) {
|
||||
logger.warn(`lv should be an array of numbers, found ${lvMatch[1]} in ${line}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tmp.length > 5) {
|
||||
tmp[4] = tmp.pop();
|
||||
}
|
||||
|
||||
lv = {
|
||||
bas: tmp[0],
|
||||
adv: tmp[1],
|
||||
exp: tmp[2],
|
||||
mas: tmp[3],
|
||||
};
|
||||
|
||||
if (tmp[4] !== 0) {
|
||||
lv.remas = tmp[4];
|
||||
}
|
||||
} catch (e) {
|
||||
logger.warn(`lv should be an array of numbers, found ${lvMatch[1]} in ${line}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
data.push({
|
||||
dx: dx === 1,
|
||||
lv,
|
||||
ico: jacketMatch[1]!,
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async function ParseMaimaiDXDataset() {
|
||||
const songs: Array<SongDocument<"maimaidx">> = ReadCollection("songs-maimaidx.json");
|
||||
const charts: Array<ChartDocument<"maimaidx:Single">> = ReadCollection("charts-maimaidx.json");
|
||||
|
||||
const existingSongMap = new Map(songs.map((s) => [`${s.title}-${s.artist}`, s]));
|
||||
const existingChartMap = new Map(charts.map((c) => [`${c.songID}-${c.difficulty}`, c]));
|
||||
|
||||
logger.info(`Fetching official song information from ${DATA_URL}...`);
|
||||
|
||||
const datum: Array<MaimaiDXSong> = await fetch(DATA_URL).then((r) => r.json());
|
||||
|
||||
logger.info(`Fetching internal level information from ${INTERNAL_LEVEL_URL}...`);
|
||||
|
||||
const internalLevelData = await ParseInternalLevelData(INTERNAL_LEVEL_URL);
|
||||
const internalLevelDataMap = new Map(
|
||||
internalLevelData.map((d) => [`${d.dx ? "DX" : "ST"}-${d.ico}`, d])
|
||||
);
|
||||
|
||||
const getFreeSongID = GetFreshSongIDGenerator("maimaidx");
|
||||
|
||||
for (const data of datum) {
|
||||
if (data.lev_utage) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const version = VERSION_OVERRIDES[data.title] ?? Number(data.version.substring(0, 3));
|
||||
const displayVersion = VERSION_MAP.get(version);
|
||||
|
||||
if (version > CURRENT_VERSION_NUM) {
|
||||
// Skipping songs that are newer than currently supported version.
|
||||
logger.warn(
|
||||
`Ignoring song ${data.artist} - ${data.title}, which is newer than CURRENT_VERSION_NUM.`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (displayVersion === null || displayVersion === undefined) {
|
||||
throw new Error(
|
||||
`Unknown version number ${version} (from ${data.version}). Update database-seeds/scripts/rerunners/maimaidx/parse-maimaidx-dataset.ts.`
|
||||
);
|
||||
}
|
||||
|
||||
let tachiSongID: number | undefined;
|
||||
|
||||
if (data.title === " " && data.artist === "x0o0x_") {
|
||||
tachiSongID = 959;
|
||||
} else if (data.title === "ぽっぴっぽー" && data.artist === " ") {
|
||||
tachiSongID = 154;
|
||||
} else {
|
||||
tachiSongID = existingSongMap.get(`${data.title}-${data.artist}`)?.id;
|
||||
}
|
||||
|
||||
if (!tachiSongID) {
|
||||
tachiSongID = getFreeSongID();
|
||||
|
||||
const songDoc: SongDocument<"maimaidx"> = {
|
||||
id: tachiSongID,
|
||||
title: data.title.trim(),
|
||||
artist: data.artist.trim(),
|
||||
searchTerms: [],
|
||||
altTitles: [],
|
||||
data: {
|
||||
displayVersion,
|
||||
genre: data.catcode.trim(),
|
||||
},
|
||||
};
|
||||
|
||||
songs.push(songDoc);
|
||||
|
||||
logger.info(`Added new song ${songDoc.artist} - ${songDoc.title} (ID ${tachiSongID}).`);
|
||||
}
|
||||
|
||||
for (const [key, difficulty] of Object.entries(DIFFICULTY_TO_TACHI_DIFFICULTY) as [
|
||||
MaimaiDXDifficulty,
|
||||
Difficulties["maimaidx:Single"]
|
||||
][]) {
|
||||
const level = data[key];
|
||||
|
||||
if (level === undefined || level.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const existingChart = existingChartMap.get(`${tachiSongID}-${difficulty}`);
|
||||
const internalLevelEntry = internalLevelDataMap.get(
|
||||
`${key.startsWith("dx_") ? "DX" : "ST"}-${data.image_url.split(".")[0]}`
|
||||
);
|
||||
|
||||
const defaultLevelNum = Number(level.replace(/\+$/u, ".6"));
|
||||
let levelNum = existingChart?.levelNum ?? defaultLevelNum;
|
||||
|
||||
if (internalLevelEntry) {
|
||||
const baseDifficultyKey = key.split("_").pop() as BaseDifficulty;
|
||||
const internalLevel = internalLevelEntry.lv[baseDifficultyKey];
|
||||
|
||||
// Positive internal levels mean that they have been confirmed.
|
||||
if (internalLevel && internalLevel > 0) {
|
||||
levelNum = internalLevel;
|
||||
}
|
||||
}
|
||||
|
||||
if (existingChart) {
|
||||
const displayName = `${data.artist} - ${data.title} [${difficulty}] (${existingChart.chartID})`;
|
||||
|
||||
if (!existingChart.versions.includes(CURRENT_VERSION)) {
|
||||
existingChart.versions.push(CURRENT_VERSION);
|
||||
}
|
||||
|
||||
if (existingChart.level !== level) {
|
||||
logger.info(
|
||||
`Chart ${displayName} has had a level change: ${existingChart.level} -> ${level}.`
|
||||
);
|
||||
existingChart.level = level;
|
||||
levelNum = defaultLevelNum;
|
||||
}
|
||||
|
||||
if (existingChart.levelNum !== levelNum) {
|
||||
logger.info(
|
||||
`Chart ${displayName} has had a levelNum change: ${existingChart.levelNum} -> ${levelNum}.`
|
||||
);
|
||||
existingChart.levelNum = levelNum;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
const chartDoc: ChartDocument<"maimaidx:Single"> = {
|
||||
songID: tachiSongID,
|
||||
chartID: CreateChartID(),
|
||||
level,
|
||||
levelNum,
|
||||
isPrimary: true,
|
||||
difficulty,
|
||||
playtype: "Single",
|
||||
data: {
|
||||
inGameID: null,
|
||||
},
|
||||
versions: [CURRENT_VERSION],
|
||||
};
|
||||
|
||||
charts.push(chartDoc);
|
||||
|
||||
logger.info(`Added new chart ${data.artist} - ${data.title} [${difficulty}].`);
|
||||
}
|
||||
}
|
||||
|
||||
WriteCollection("charts-maimaidx.json", charts);
|
||||
WriteCollection("songs-maimaidx.json", songs);
|
||||
}
|
||||
|
||||
ParseMaimaiDXDataset();
|
||||
Reference in New Issue
Block a user