[maimaidx] Update seeds to 2026-05-15 (#1536)

* [maimaidx] Update seeds to 2026-05-15

* aliases and remove duplicate break the speakers

* What happened here?
This commit is contained in:
beerpsi
2026-05-21 17:40:02 +01:00
committed by GitHub
parent a5f139ce0a
commit e2152cb5d4
4 changed files with 2726 additions and 47 deletions
File diff suppressed because it is too large Load Diff
+435
View File
@@ -19019,5 +19019,440 @@
"legacySongID": 1561,
"searchTerms": ["shoujo a", "young girl a"],
"title": "少女A"
},
{
"altTitles": [],
"artist": "吉田夜世 feat.ちっく。",
"data": {
"duration": 137.581,
"genre": "maimai"
},
"id": "S19e48709576055e2c4c",
"legacySongID": 1562,
"searchTerms": ["the ruin in the woods", "haikyo ni imasu campaign"],
"title": "廃墟にいますキャンペーン"
},
{
"altTitles": [],
"artist": "ぱりぱりさらうどん",
"data": {
"duration": 111.25,
"genre": "niconico&ボーカロイド"
},
"id": "S19e487095784ccd0ca8",
"legacySongID": 1564,
"searchTerms": ["inochi test test", "life test, test"],
"title": "命テステス"
},
{
"altTitles": [],
"artist": "YOFUKASHi Sound Team feat.編井うも",
"data": {
"duration": 154.667,
"genre": "niconico&ボーカロイド"
},
"id": "S19e48709578940632af",
"legacySongID": 1563,
"searchTerms": ["shuushin henshin hakaishin zzz"],
"title": "しゅ~しん?変身☆ハカイシンzzZ"
},
{
"altTitles": [],
"artist": "ヤレギノ",
"data": {
"duration": 143.71,
"genre": "niconico&ボーカロイド"
},
"id": "S19e48709578f0d13d43",
"legacySongID": 1565,
"searchTerms": ["haikei, saikou no omoidetachi", "dear my best memories"],
"title": "拝啓、最高の思い出たち"
},
{
"altTitles": [],
"artist": "ちから",
"data": {
"duration": 125,
"genre": "niconico&ボーカロイド"
},
"id": "S19e487095793aaa217d",
"legacySongID": 1567,
"searchTerms": ["rurou ranru"],
"title": "るろうらんる"
},
{
"altTitles": [],
"artist": "litmus*",
"data": {
"duration": 151.636,
"genre": "niconico&ボーカロイド"
},
"id": "S19e48709579d2c1d5a4",
"legacySongID": 1566,
"searchTerms": ["obenkyou time"],
"title": "おべんきょうたいむ"
},
{
"altTitles": [],
"artist": "40mP × sasakure.UK / 初音ミク「劇場版プロジェクトセカイ 壊れたセカイと歌えないミク」",
"data": {
"duration": 132.692,
"genre": "niconico&ボーカロイド"
},
"id": "S19e4870957a15051840",
"legacySongID": 1568,
"searchTerms": ["hajimari no mirai", "the future of beginning"],
"title": "はじまりの未来"
},
{
"altTitles": [],
"artist": "じん / バーチャル・シンガー、Leo/need、MORE MORE JUMP!、Vivid BAD SQUAD、ワンダーランズ×ショウタイム、25時、ナイトコードで。「劇場版プロジェクトセカイ 壊れたセカイと歌えないミク」",
"data": {
"duration": 133.091,
"genre": "niconico&ボーカロイド"
},
"id": "S19e4870957aa9ea6944",
"legacySongID": 1569,
"searchTerms": [],
"title": "Worlders"
},
{
"altTitles": [],
"artist": "かめりあ",
"data": {
"duration": 159.403,
"genre": "niconico&ボーカロイド"
},
"id": "S19e4870957b459a08e7",
"legacySongID": 1570,
"searchTerms": ["hiasobi", "playing with fire"],
"title": "ヒアソビ"
},
{
"altTitles": [],
"artist": "Kai",
"data": {
"duration": 142.144,
"genre": "niconico&ボーカロイド"
},
"id": "S19e4870957b722a8e5e",
"legacySongID": 1571,
"searchTerms": [],
"title": "ラプラスショコラ"
},
{
"altTitles": [],
"artist": "Kobaryo",
"data": {
"duration": 140.548,
"genre": "maimai"
},
"id": "S19e4870957e9065cd32",
"legacySongID": 1572,
"searchTerms": [],
"title": "Customized Justice"
},
{
"altTitles": [],
"artist": "ナナツカゼ",
"data": {
"duration": 150.649,
"genre": "maimai"
},
"id": "S19e4870957eda0aa0aa",
"legacySongID": 1573,
"searchTerms": ["shinkuu toshi"],
"title": "真空都市"
},
{
"altTitles": [],
"artist": "Tatsunoshin & Aira Arere",
"data": {
"duration": 142.667,
"genre": "maimai"
},
"id": "S19e4870957f172028ef",
"legacySongID": 1574,
"searchTerms": [],
"title": "Eternal Return"
},
{
"altTitles": [],
"artist": "ぱぱぱらビーチ",
"data": {
"duration": 139.594,
"genre": "maimai"
},
"id": "S19e4870957fd100f215",
"legacySongID": 1575,
"searchTerms": ["papapara beach"],
"title": "ぱぱぱらビーチ"
},
{
"altTitles": [],
"artist": "削除",
"data": {
"duration": 153.214,
"genre": "maimai"
},
"id": "S19e48709580e5b12ff6",
"legacySongID": 1577,
"searchTerms": [],
"title": "7 Wonders"
},
{
"altTitles": [],
"artist": "Ryo Fukuda",
"data": {
"duration": 135.512,
"genre": "maimai"
},
"id": "S19e48709580fa8c0dd6",
"legacySongID": 1576,
"searchTerms": ["get u back"],
"title": "Get U ♭ack"
},
{
"altTitles": [],
"artist": "かめりあ",
"data": {
"duration": 141.159,
"genre": "niconico&ボーカロイド"
},
"id": "S19e4870958155be32ba",
"legacySongID": 1578,
"searchTerms": ["denko sekka", "denkou sekka"],
"title": "電光刹歌"
},
{
"altTitles": [],
"artist": "Ponchi♪",
"data": {
"duration": 159.948,
"genre": "niconico&ボーカロイド"
},
"id": "S19e487095820418ea7c",
"legacySongID": 1581,
"searchTerms": ["treasure garden"],
"title": "トレジャーガーデン"
},
{
"altTitles": [],
"artist": "cosMo@暴走P",
"data": {
"duration": 146.436,
"genre": "niconico&ボーカロイド"
},
"id": "S19e4870958280fbf57f",
"legacySongID": 1579,
"searchTerms": ["we are pico pico hammers"],
"title": "ウィーアーピコピコハンマーズ!!!!"
},
{
"altTitles": [],
"artist": "雄之助",
"data": {
"duration": 153.882,
"genre": "niconico&ボーカロイド"
},
"id": "S19e48709582dc475303",
"legacySongID": 1580,
"searchTerms": ["jet black"],
"title": "ジェットブラック"
},
{
"altTitles": [],
"artist": "かいりきベア",
"data": {
"duration": 159,
"genre": "niconico&ボーカロイド"
},
"id": "S19e487095834ec8ee16",
"legacySongID": 1582,
"searchTerms": ["saiai jinsei runner", "sai love jinsei runner"],
"title": "最愛人生ランナー"
},
{
"altTitles": [],
"artist": "ああああ",
"data": {
"duration": 145.952,
"genre": "オンゲキ&CHUNITHM"
},
"id": "S19e48709584824b3772",
"legacySongID": 1584,
"searchTerms": [],
"title": "Galaxy Blaster"
},
{
"altTitles": [],
"artist": "DJ Myosuke",
"data": {
"duration": 135,
"genre": "maimai"
},
"id": "S19e48709584f1679c4d",
"legacySongID": 1585,
"searchTerms": [],
"title": "Break The Speakers"
},
{
"altTitles": [],
"artist": "cosMo@暴走P",
"data": {
"duration": 168,
"genre": "オンゲキ&CHUNITHM"
},
"id": "S19e487095866a0c48da",
"legacySongID": 1586,
"searchTerms": [
"Last Piece ni Shukufuku to Eikou wo",
"Finding Blessing and Glory in the Last Piece"
],
"title": "ラストピースに祝福と栄光を"
},
{
"altTitles": [],
"artist": "cosMo@暴走P「Fit Boxing feat. 初音ミク -ミクといっしょにエクササイズ-」",
"data": {
"duration": 165.69,
"genre": "niconico&ボーカロイド"
},
"id": "S19e487095872b0130d6",
"legacySongID": 1588,
"searchTerms": ["let's mikusercise"],
"title": "Let's ミクササイズ!!"
},
{
"altTitles": [],
"artist": "cosMo@暴走P",
"data": {
"duration": 145.548,
"genre": "niconico&ボーカロイド"
},
"id": "S19e48709587b2861c34",
"legacySongID": 1587,
"searchTerms": ["hatsune miku no bousou", "the rampage of hatsune miku"],
"title": "初音ミクの暴走"
},
{
"altTitles": [],
"artist": "halyosy",
"data": {
"duration": 158.74,
"genre": "niconico&ボーカロイド"
},
"id": "S19e48709587e249c09f",
"legacySongID": 1589,
"searchTerms": ["snowman"],
"title": "スノーマン (Rerec)"
},
{
"altTitles": [],
"artist": "DJ Myosuke & Gram",
"data": {
"duration": 144.133,
"genre": "ゲーム&バラエティ"
},
"id": "S19e4870958847e035b4",
"legacySongID": 1590,
"searchTerms": [],
"title": "JINGLE DEATH"
},
{
"altTitles": [],
"artist": "テヅカ",
"data": {
"duration": 143.448,
"genre": "maimai"
},
"id": "S19e487095899995f9eb",
"legacySongID": 1591,
"searchTerms": ["mikumari"],
"title": "ミクマリ"
},
{
"altTitles": [],
"artist": "adaptor vs DRIVE.",
"data": {
"duration": 142.875,
"genre": "maimai"
},
"id": "S19e4870958a2c729236",
"legacySongID": 1592,
"searchTerms": ["dreaming voltage", "ungaisouten"],
"title": "雲外蒼電 -Dreaming Voltage-"
},
{
"altTitles": [],
"artist": "Earliri",
"data": {
"duration": 129.5,
"genre": "maimai"
},
"id": "S19e4870958a842a20a2",
"legacySongID": 1593,
"searchTerms": ["kijokouyou"],
"title": "鬼女紅妖"
},
{
"altTitles": [],
"artist": "satella feat.Risa Yuzuki",
"data": {
"duration": 149.664,
"genre": "maimai"
},
"id": "S19e4870958a988bc132",
"legacySongID": 1594,
"searchTerms": ["katengetto"],
"title": "華天月兎"
},
{
"altTitles": [],
"artist": "しぐれうい",
"data": {
"duration": 158.571,
"genre": "POPS&アニメ"
},
"id": "S19e4870958b057fc422",
"legacySongID": 1595,
"searchTerms": ["catcher in the ui", "ui mugibatake de tsukamaete"],
"title": "うい麦畑でつかまえて"
},
{
"altTitles": [],
"artist": "しぐれうい",
"data": {
"duration": 163.977,
"genre": "POPS&アニメ"
},
"id": "S19e4870958baad9527b",
"legacySongID": 1596,
"searchTerms": ["let's live willfully", "katte ni ikimasho"],
"title": "勝手に生きましょ"
},
{
"altTitles": [],
"artist": "ハム feat. 雨衣",
"data": {
"duration": 150,
"genre": "niconico&ボーカロイド"
},
"id": "S19e4870958c92b11ca4",
"legacySongID": 1597,
"searchTerms": ["aiaikasa", "aye aye umbrella"],
"title": "アイアイ傘"
},
{
"altTitles": [],
"artist": "cosMo@暴走P",
"data": {
"duration": 130.99,
"genre": "niconico&ボーカロイド"
},
"id": "S19e4870958c9f6f6902",
"legacySongID": 1598,
"searchTerms": ["yaminabe"],
"title": "ヤミナベ!!!!"
}
]
@@ -11,14 +11,8 @@ S1\d{5}$
# not normally playable.
S11879$
S10077$
S11883$
S11921$
S11922$
S11923$
S11924$
S11925$
S11926$
S11927$
S11929$
S11950$
S11915$
S11928$
S11943$
S1200$
@@ -1,14 +1,17 @@
import { log } from "#log";
import { log } from "../../log";
import { execFileSync } from "child_process";
import { Command } from "commander";
import crypto from "crypto";
import { XMLParser } from "fast-xml-parser";
import { existsSync, readdirSync, readFileSync, statSync } from "fs";
import path from "path";
import {
type ChartDocument,
GetGameConfig,
type SEEDS_ChartDocument,
type Difficulties,
LEGACY_GetGamePTConfig,
type SongDocument,
type SEEDS_SongDocument,
integer,
CreateSongID,
} from "tachi-common";
import {
@@ -47,7 +50,7 @@ const VERSION_DISPLAY_NAMES = [
"maimaiでらっくす CiRCLE",
];
const DIFFICULTIES = ["Basic", "Advanced", "Expert", "Master", "Re:Master"];
const GENRE_MAP = {
const GENRE_MAP: Record<integer, string> = {
101: "POPS&アニメ",
102: "niconico&ボーカロイド",
103: "東方Project",
@@ -126,7 +129,7 @@ if (!options.vgmsBinary) {
}
}
const versions = Object.keys(LEGACY_GetGamePTConfig("maimaidx", "Single").versions);
const versions = Object.keys(GetGameConfig("maimaidx").versions);
if (versions.indexOf(options.version) === -1) {
throw new Error(
@@ -138,19 +141,20 @@ if (versions.indexOf(options.version) === -1) {
const isLatestVersion =
versions.indexOf(options.version.replace(/(-intl|-omni)$/u, "")) === versions.length - 1;
const existingSongs: Array<SongDocument<"maimaidx">> = ReadCollection("songs-maimaidx.json");
const existingCharts: Array<ChartDocument<"maimaidx">> = ReadCollection("charts-maimaidx.json");
const existingSongs: Array<SEEDS_SongDocument<"maimaidx">> = ReadCollection("songs-maimaidx.json");
const existingCharts: Array<SEEDS_ChartDocument<"maimaidx">> =
ReadCollection("charts-maimaidx.json");
const songMap = new Map(existingSongs.map((s) => [s.id, s]));
const chartMap = new Map<string, ChartDocument<"maimaidx">>();
const songTitleArtistMap = new Map<string, number>();
const chartMap = new Map<string, SEEDS_ChartDocument<"maimaidx">>();
const songTitleArtistMap = new Map<string, string>();
const durationMap = new Map<string, number>();
for (const chart of existingCharts) {
const song = songMap.get(chart.song.id);
const song = songMap.get(chart.songID);
if (song === undefined) {
log.error(
`CONSISTENCY ERROR: Chart ID ${chart.chartID} does not belong to any songs! (songID was ${chart.song.id})`,
`CONSISTENCY ERROR: Chart ID ${chart.id} does not belong to any songs! (songID was ${chart.songID})`,
);
process.exit(1);
}
@@ -231,8 +235,8 @@ const parser = new XMLParser({
},
});
const newSongs: Array<SongDocument<"maimaidx">> = [];
const newCharts: Array<ChartDocument<"maimaidx">> = [];
const newSongs: Array<SEEDS_SongDocument<"maimaidx">> = [];
const newCharts: Array<SEEDS_ChartDocument<"maimaidx">> = [];
const songIDGenerator = GetFreshSongIDGenerator("maimaidx");
@@ -281,12 +285,19 @@ for (const optionsDir of options.input) {
continue;
}
// 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: string | undefined;
if (inGameID === 11422) {
// Manual override since the song's title is empty in the dataset and not
// IDEOGRAPHIC SPACE (U+3000).
tachiSongID = "S19d35e0d843641538f4";
} else if (inGameID === 11956) {
// Manual override because the song's title changed from Break the Speaker
// to Break The Speakers, breaking title matching.
tachiSongID = "S19e48709584f1679c4d";
} else {
tachiSongID = songTitleArtistMap.get(`${musicData.name.str}-${musicData.artistName.str}`);
}
// Has this song been disabled in-game?
if (musicData.disable || Number(musicData.eventName.id) === 0) {
@@ -311,7 +322,7 @@ for (const optionsDir of options.input) {
continue;
}
const displayVersion = VERSION_DISPLAY_NAMES[musicData.AddVersion.id];
const displayVersion = VERSION_DISPLAY_NAMES[Number(musicData.AddVersion.id)];
if (!displayVersion) {
throw new Error(
@@ -319,7 +330,7 @@ for (const optionsDir of options.input) {
);
}
const genre = GENRE_MAP[musicData.genreName.id];
const genre = GENRE_MAP[Number(musicData.genreName.id)];
if (!genre) {
throw new Error(
@@ -337,16 +348,16 @@ for (const optionsDir of options.input) {
// New song?
if (tachiSongID === undefined) {
const newSongID = songIDGenerator();
tachiSongID = CreateSongID();
const newLegacySongID = songIDGenerator();
tachiSongID = newSongID;
const songDoc: SongDocument<"maimaidx"> = {
const songDoc: SEEDS_SongDocument<"maimaidx"> = {
title: musicData.name.str,
altTitles: [],
searchTerms: [],
artist: musicData.artistName.str,
id: newSongID,
id: tachiSongID,
legacySongID: newLegacySongID,
data: {
genre,
duration,
@@ -354,8 +365,8 @@ for (const optionsDir of options.input) {
};
newSongs.push(songDoc);
songTitleArtistMap.set(`${songDoc.title}-${songDoc.artist}`, newSongID);
songMap.set(newSongID, songDoc);
songTitleArtistMap.set(`${songDoc.title}-${songDoc.artist}`, tachiSongID);
songMap.set(tachiSongID, songDoc);
log.info(
`Added new song ${songDoc.artist} - ${songDoc.title} (inGameID ${inGameID}, tachiSongID ${tachiSongID}).`,
@@ -395,7 +406,7 @@ for (const optionsDir of options.input) {
difficultyName = `DX ${difficultyName}`;
}
let exists: ChartDocument<"maimaidx"> | undefined;
let exists: SEEDS_ChartDocument<"maimaidx"> | undefined;
if (inGameID === 11422) {
exists = chartMap.get(`-x0o0x_-${difficultyName}`);
@@ -409,7 +420,7 @@ for (const optionsDir of options.input) {
const levelNum = calculateLevelNum(difficulty);
if (exists) {
const displayName = `${musicData.artistName.str} - ${musicData.name.str} [${exists.difficulty}] (${exists.chartID})`;
const displayName = `${musicData.artistName.str} - ${musicData.name.str} [${exists.difficulty}] (${exists.id})`;
if (exists.data.inGameID === null) {
log.info(`Adding inGameID ${inGameID} for chart ${displayName}.`);
@@ -456,16 +467,15 @@ for (const optionsDir of options.input) {
continue;
}
const chartDoc: ChartDocument<"maimaidx"> = {
chartID: CreateChartID(),
const chartDoc: SEEDS_ChartDocument<"maimaidx"> = {
id: CreateChartID(),
legacyChartID: crypto.randomBytes(20).toString("hex"),
songID: tachiSongID!,
game: "maimaidx",
difficulty: difficultyName as Difficulties["maimaidx"],
isPrimary: true,
level,
levelNum,
versions: [options.version],
playtype: "Single",
data: {
displayVersion,
inGameID,
@@ -475,7 +485,7 @@ for (const optionsDir of options.input) {
newCharts.push(chartDoc);
log.info(
`Inserted new chart ${musicData.artistName.str} - ${musicData.name.str} [${chartDoc.difficulty}] (${chartDoc.chartID}).`,
`Inserted new chart ${musicData.artistName.str} - ${musicData.name.str} [${chartDoc.difficulty}] (${chartDoc.id}).`,
);
}
}