diff --git a/bot/src/utils/misc.ts b/bot/src/utils/misc.ts index 894fe2d9c..30257be97 100644 --- a/bot/src/utils/misc.ts +++ b/bot/src/utils/misc.ts @@ -70,7 +70,7 @@ export function ParseGPT(str: string) { // this is an interesting way of game checking noah const gameConfig = GetGameConfig(game) as GameConfig | undefined; - if (!gameConfig || !gameConfig.validPlaytypes.includes(playtype)) { + if (!gameConfig || !gameConfig.playtypes.includes(playtype)) { throw new Error(`Invalid GPT Combination '${str}'.`); } diff --git a/bot/src/utils/options.ts b/bot/src/utils/options.ts index 41e42fefe..3be1a8ba2 100644 --- a/bot/src/utils/options.ts +++ b/bot/src/utils/options.ts @@ -11,7 +11,7 @@ const GPTChoices: Array<[string, string]> = []; for (const game of ServerConfig.games) { const gameConfig = GetGameConfig(game); - for (const playtype of gameConfig.validPlaytypes) { + for (const playtype of gameConfig.playtypes) { GPTChoices.push([FormatGame(game, playtype), `${game}:${playtype}`]); } } diff --git a/bot/src/webhookHandlers/goalsAchieved.ts b/bot/src/webhookHandlers/goalsAchieved.ts index d30ca4491..c2ba5202a 100644 --- a/bot/src/webhookHandlers/goalsAchieved.ts +++ b/bot/src/webhookHandlers/goalsAchieved.ts @@ -36,7 +36,7 @@ export async function HandleGoalAchievedV1( const gameConfig = GetGameConfig(game); - const shouldShowPlaytype = gameConfig.validPlaytypes.length !== 1; + const shouldShowPlaytype = gameConfig.playtypes.length !== 1; const embed = CreateEmbed(userDoc.id) .setTitle( diff --git a/bot/src/webhookHandlers/questAchieved.ts b/bot/src/webhookHandlers/questAchieved.ts index 4b6a2d841..87d66e77a 100644 --- a/bot/src/webhookHandlers/questAchieved.ts +++ b/bot/src/webhookHandlers/questAchieved.ts @@ -27,7 +27,7 @@ export async function HandleQuestAchievedV1( const quest = await GetQuestWithID(event.questID, game, playtype); const gameConfig = GetGameConfig(game); - const shouldShowPlaytype = gameConfig.validPlaytypes.length > 1 ? ` (${playtype})` : ""; + const shouldShowPlaytype = gameConfig.playtypes.length > 1 ? ` (${playtype})` : ""; const embed = CreateEmbed(userDoc.id).setTitle( `${userDoc.username} just completed the ${quest.name}${shouldShowPlaytype} quest!` diff --git a/client/src/app/pages/dashboard/games/_game/PlaytypeSelect.tsx b/client/src/app/pages/dashboard/games/_game/PlaytypeSelect.tsx index 72e6bc8e7..54ab67933 100644 --- a/client/src/app/pages/dashboard/games/_game/PlaytypeSelect.tsx +++ b/client/src/app/pages/dashboard/games/_game/PlaytypeSelect.tsx @@ -29,7 +29,7 @@ export default function PlaytypeSelect({
{ - internalName: string; - name: string; - defaultPlaytype: P; - validPlaytypes: Array
; -} - -interface BaseGamePTConfig { - idString: I; - - percentMax: number; - - defaultScoreRatingAlg: ScoreCalculatedDataLookup[I]; - defaultSessionRatingAlg: SessionCalculatedDataLookup[I]; - defaultProfileRatingAlg: ProfileRatingLookup[I]; - - scoreRatingAlgs: Array; - sessionRatingAlgs: Array; - profileRatingAlgs: Array; - - scoreRatingAlgDescriptions: Record; - sessionRatingAlgDescriptions: Record; - profileRatingAlgDescriptions: Record; - - scoreRatingAlgFormatters: Partial string>>; - sessionRatingAlgFormatters: Partial< - Record string> - >; - profileRatingAlgFormatters: Partial string>>; - - difficulties: Array; - shortDifficulties: Partial>; - defaultDifficulty: Difficulties[I]; - difficultyColours: Record; - - orderedGrades: Array; - gradeColours: Record; - minimumRelevantGrade: Grades[I]; - gradeBoundaries: Array; - - orderedLamps: Array; - lampColours: Record; - minimumRelevantLamp: Lamps[I]; - - classHumanisedFormat: Record>; - classProperties: Record< - GameClassSets[I], - { - /** - * If a worse thing comes in for this, should this metric go down? - * I.e. if a user is 4th dan and they submit 3rd dan, should it go - * down to 3rd dan? (Hopefully not). This makes the most sense for - * metrics like "colour" in games, which are a function of some profile - * skill. If said profile skill goes down, it should reflect in that - * colour. - */ - downgradable: boolean; - - /** - * Can this class be sent in `batchManual.classes`? This only makes sense - * for classes that aren't a function of existing state, so things like - * submitting dan rank makes sense, but submitting things like "Colour" - * makes no sense (as it's a function of profile skill). - */ - canBeBatchManualSubmitted: boolean; - } - >; - - orderedJudgements: Array; - - scoreBucket: "grade" | "lamp"; - - supportedVersions: Array; - - tierlists: Array; - tierlistDescriptions: Record; - - /** - * What "matchTypes" should this game support for batch-manual imports? This - * allows us to disable things like "songTitle" resolutions for games like BMS, - * where song titles are absolutely not guaranteed to be unique. - */ - supportedMatchTypes: Array; -} - -const GAME_PT_CONFIGS = { - "iidx:SP": { - defaultScoreRatingAlg: "ktLampRating", - defaultSessionRatingAlg: "ktLampRating", - defaultProfileRatingAlg: "ktLampRating", - - scoreRatingAlgs: ["ktLampRating", "BPI"], - sessionRatingAlgs: ["ktLampRating", "BPI"], - profileRatingAlgs: ["ktLampRating", "BPI"], - - scoreRatingAlgDescriptions: { - ktLampRating: `A rating system that values your clear lamps on charts. Tierlist information is taken into account.`, - BPI: `A rating system for Kaiden level play. Only applies to 11s and 12s. A BPI of 0 states the score is equal to the Kaiden Average for that chart. A BPI of 100 is equal to the world record.`, - }, - profileRatingAlgDescriptions: { - ktLampRating: `An average of your best 20 ktLampRatings.`, - BPI: `An average of your best 20 BPIs.`, - }, - sessionRatingAlgDescriptions: { - ktLampRating: `An average of the best 10 ktLampRatings this session.`, - BPI: `An average of the best 10 BPIs this session.`, - }, - - scoreRatingAlgFormatters: {}, - profileRatingAlgFormatters: {}, - sessionRatingAlgFormatters: {}, - - difficultyOrder: [ - "BEGINNER", - "NORMAL", - "HYPER", - "ANOTHER", - "LEGGENDARIA", - "All Scratch BEGINNER", - "All Scratch NORMAL", - "All Scratch HYPER", - "All Scratch ANOTHER", - "All Scratch LEGGENDARIA", - "Kichiku BEGINNER", - "Kichiku NORMAL", - "Kichiku HYPER", - "Kichiku ANOTHER", - "Kichiku LEGGENDARIA", - "Kiraku BEGINNER", - "Kiraku NORMAL", - "Kiraku HYPER", - "Kiraku ANOTHER", - "Kiraku LEGGENDARIA", - ], - difficultyShorthand: { - BEGINNER: "B", - NORMAL: "N", - HYPER: "H", - ANOTHER: "A", - LEGGENDARIA: "L", - "All Scratch BEGINNER": "B (Scr.)", - "All Scratch NORMAL": "N (Scr.)", - "All Scratch HYPER": "H (Scr.)", - "All Scratch ANOTHER": "A (Scr.)", - "All Scratch LEGGENDARIA": "L (Scr.)", - "Kichiku BEGINNER": "B (Kc.)", - "Kichiku NORMAL": "N (Kc.)", - "Kichiku HYPER": "H (Kc.)", - "Kichiku ANOTHER": "A (Kc.)", - "Kichiku LEGGENDARIA": "L (Kc.)", - "Kiraku BEGINNER": "B (Kr.)", - "Kiraku NORMAL": "N (Kr.)", - "Kiraku HYPER": "H (Kr.)", - "Kiraku ANOTHER": "A (Kr.)", - "Kiraku LEGGENDARIA": "L (Kr.)", - }, - defaultDifficulty: "ANOTHER", - difficultyColours: { - BEGINNER: COLOUR_SET.paleGreen, - NORMAL: COLOUR_SET.blue, - HYPER: COLOUR_SET.orange, - ANOTHER: COLOUR_SET.red, - LEGGENDARIA: COLOUR_SET.purple, - "All Scratch BEGINNER": COLOUR_SET.paleGreen, - "All Scratch NORMAL": COLOUR_SET.blue, - "All Scratch HYPER": COLOUR_SET.orange, - "All Scratch ANOTHER": COLOUR_SET.red, - "All Scratch LEGGENDARIA": COLOUR_SET.purple, - "Kichiku BEGINNER": COLOUR_SET.paleGreen, - "Kichiku NORMAL": COLOUR_SET.blue, - "Kichiku HYPER": COLOUR_SET.orange, - "Kichiku ANOTHER": COLOUR_SET.red, - "Kichiku LEGGENDARIA": COLOUR_SET.purple, - "Kiraku BEGINNER": COLOUR_SET.paleGreen, - "Kiraku NORMAL": COLOUR_SET.blue, - "Kiraku HYPER": COLOUR_SET.orange, - "Kiraku ANOTHER": COLOUR_SET.red, - "Kiraku LEGGENDARIA": COLOUR_SET.purple, - }, - - orderedGrades: ["F", "E", "D", "C", "B", "A", "AA", "AAA", "MAX-", "MAX"], - gradeColours: { - F: COLOUR_SET.gray, - E: COLOUR_SET.red, - D: COLOUR_SET.maroon, - C: COLOUR_SET.purple, - B: COLOUR_SET.paleBlue, - A: COLOUR_SET.green, - AA: COLOUR_SET.blue, - AAA: COLOUR_SET.gold, - "MAX-": COLOUR_SET.teal, - MAX: COLOUR_SET.white, - }, - minimumRelevantGrade: "A", - - orderedLamps: [ - "NO PLAY", - "FAILED", - "ASSIST CLEAR", - "EASY CLEAR", - "CLEAR", - "HARD CLEAR", - "EX HARD CLEAR", - "FULL COMBO", - ], - lampColours: { - "NO PLAY": COLOUR_SET.gray, - FAILED: COLOUR_SET.red, - "ASSIST CLEAR": COLOUR_SET.purple, - "EASY CLEAR": COLOUR_SET.green, - CLEAR: COLOUR_SET.blue, - "HARD CLEAR": COLOUR_SET.orange, - "EX HARD CLEAR": COLOUR_SET.gold, - "FULL COMBO": COLOUR_SET.teal, - }, - minimumRelevantLamp: "CLEAR", - - supportedClasses: { - dan: { - downgradable: false, - canBeBatchManualSubmitted: true, - values: IIDXDans, - }, - }, - - orderedJudgements: ["pgreat", "great", "good", "bad", "poor"], - - scoreBucket: "lamp", - - supportedVersions: [ - "3-cs", - "4-cs", - "5-cs", - "6-cs", - "7-cs", - "8-cs", - "9-cs", - "10-cs", - "11-cs", - "12-cs", - "13-cs", - "14-cs", - "15-cs", - "16-cs", - "20", - "21", - "22", - "23", - "24", - "25", - "26", - "27", - "28", - "29", - "30", - "26-omni", - "27-omni", - "28-omni", - "29-omni", - "27-2dxtra", - "28-2dxtra", - "bmus", - "inf", - ], - - supportedTierlists: { - "kt-NC": { - description: - "The Normal Clear tiers for Kamaitachi. These are adapted from multiple sources.", - }, - "kt-HC": { - description: - "The Hard Clear tiers for Kamaitachi. These are adapted from multiple sources.", - }, - "kt-EXHC": { - description: - "The EX-HARD Clear tiers for Kamaitachi. These are adapted from multiple sources.", - }, - }, - - supportedMatchTypes: ["inGameID", "tachiSongID", "songTitle"], - }, - "iidx:DP": { - defaultScoreRatingAlg: "ktLampRating", - defaultSessionRatingAlg: "ktLampRating", - defaultProfileRatingAlg: "ktLampRating", - - scoreRatingAlgs: ["ktLampRating", "BPI"], - sessionRatingAlgs: ["ktLampRating", "BPI"], - profileRatingAlgs: ["ktLampRating", "BPI"], - - scoreRatingAlgDescriptions: { - ktLampRating: `A rating system that values your clear lamps on charts. Tierlist information is taken into account.`, - BPI: `A rating system for Kaiden level play. Only applies to 11s and 12s. A BPI of 0 states the score is equal to the Kaiden Average for that chart. A BPI of 100 is equal to the world record.`, - }, - profileRatingAlgDescriptions: { - ktLampRating: `An average of your best 20 ktLampRatings.`, - BPI: `An average of your best 20 BPIs.`, - }, - sessionRatingAlgDescriptions: { - ktLampRating: `An average of the best 10 ktLampRatings this session.`, - BPI: `An average of the best 10 BPIs this session.`, - }, - - scoreRatingAlgFormatters: {}, - profileRatingAlgFormatters: {}, - sessionRatingAlgFormatters: {}, - - difficultyOrder: [ - "NORMAL", - "HYPER", - "ANOTHER", - "LEGGENDARIA", - "All Scratch NORMAL", - "All Scratch HYPER", - "All Scratch ANOTHER", - "All Scratch LEGGENDARIA", - "Kichiku NORMAL", - "Kichiku HYPER", - "Kichiku ANOTHER", - "Kichiku LEGGENDARIA", - "Kiraku NORMAL", - "Kiraku HYPER", - "Kiraku ANOTHER", - "Kiraku LEGGENDARIA", - ], - difficultyShorthand: { - NORMAL: "N", - HYPER: "H", - ANOTHER: "A", - LEGGENDARIA: "L", - "All Scratch NORMAL": "N (Scr.)", - "All Scratch HYPER": "H (Scr.)", - "All Scratch ANOTHER": "A (Scr.)", - "All Scratch LEGGENDARIA": "L (Scr.)", - "Kichiku NORMAL": "N (Kc.)", - "Kichiku HYPER": "H (Kc.)", - "Kichiku ANOTHER": "A (Kc.)", - "Kichiku LEGGENDARIA": "L (Kc.)", - "Kiraku NORMAL": "N (Kr.)", - "Kiraku HYPER": "H (Kr.)", - "Kiraku ANOTHER": "A (Kr.)", - "Kiraku LEGGENDARIA": "L (Kr.)", - }, - defaultDifficulty: "ANOTHER", - difficultyColours: { - NORMAL: COLOUR_SET.blue, - HYPER: COLOUR_SET.orange, - ANOTHER: COLOUR_SET.red, - LEGGENDARIA: COLOUR_SET.purple, - "All Scratch NORMAL": COLOUR_SET.blue, - "All Scratch HYPER": COLOUR_SET.orange, - "All Scratch ANOTHER": COLOUR_SET.red, - "All Scratch LEGGENDARIA": COLOUR_SET.purple, - "Kichiku NORMAL": COLOUR_SET.blue, - "Kichiku HYPER": COLOUR_SET.orange, - "Kichiku ANOTHER": COLOUR_SET.red, - "Kichiku LEGGENDARIA": COLOUR_SET.purple, - "Kiraku NORMAL": COLOUR_SET.blue, - "Kiraku HYPER": COLOUR_SET.orange, - "Kiraku ANOTHER": COLOUR_SET.red, - "Kiraku LEGGENDARIA": COLOUR_SET.purple, - }, - - orderedGrades: ["F", "E", "D", "C", "B", "A", "AA", "AAA", "MAX-", "MAX"], - gradeColours: { - F: COLOUR_SET.gray, - E: COLOUR_SET.red, - D: COLOUR_SET.maroon, - C: COLOUR_SET.purple, - B: COLOUR_SET.paleBlue, - A: COLOUR_SET.green, - AA: COLOUR_SET.blue, - AAA: COLOUR_SET.gold, - "MAX-": COLOUR_SET.teal, - MAX: COLOUR_SET.white, - }, - minimumRelevantGrade: "A", - - // see iidx:SP for an explaination of why this is wrote like this. - gradeBoundaries: [ - 0, - (100 * 2) / 9, - (100 * 3) / 9, - (100 * 4) / 9, - (100 * 5) / 9, - (100 * 6) / 9, - (100 * 7) / 9, - (100 * 8) / 9, - (100 * 17) / 18, - (100 * 9) / 9, - ], - - orderedLamps: [ - "NO PLAY", - "FAILED", - "ASSIST CLEAR", - "EASY CLEAR", - "CLEAR", - "HARD CLEAR", - "EX HARD CLEAR", - "FULL COMBO", - ], - lampColours: { - "NO PLAY": COLOUR_SET.gray, - FAILED: COLOUR_SET.red, - "ASSIST CLEAR": COLOUR_SET.purple, - "EASY CLEAR": COLOUR_SET.green, - CLEAR: COLOUR_SET.blue, - "HARD CLEAR": COLOUR_SET.orange, - "EX HARD CLEAR": COLOUR_SET.gold, - "FULL COMBO": COLOUR_SET.teal, - }, - minimumRelevantLamp: "CLEAR", - - classHumanisedFormat: { - dan: IIDXDans, - }, - classProperties: { - dan: { downgradable: false, canBeBatchManualSubmitted: true }, - }, - - supportsESD: true, - judgementWindows: [ - { name: "PGREAT", msBorder: 16.667, value: 2 }, - { name: "GREAT", msBorder: 33.333, value: 1 }, - { name: "GOOD", msBorder: 116.667, value: 0 }, - ], - orderedJudgements: ["pgreat", "great", "good", "bad", "poor"], - - scoreBucket: "lamp", - - supportedVersions: [ - "3-cs", - "4-cs", - "5-cs", - "6-cs", - "7-cs", - "8-cs", - "9-cs", - "10-cs", - "11-cs", - "12-cs", - "13-cs", - "14-cs", - "15-cs", - "16-cs", - "20", - "21", - "22", - "23", - "24", - "25", - "26", - "27", - "28", - "29", - "30", - "26-omni", - "27-omni", - "28-omni", - "29-omni", - "27-2dxtra", - "28-2dxtra", - "bmus", - "inf", - ], - - tierlists: ["dp-tier"], - tierlistDescriptions: { - "dp-tier": "The unofficial DP tiers, taken from https://zasa.sakura.ne.jp/dp/run.php.", - }, - supportedMatchTypes: ["inGameID", "tachiSongID", "songTitle"], - }, - "chunithm:Single": { - idString: "chunithm:Single", - percentMax: 101, - - defaultScoreRatingAlg: "rating", - defaultSessionRatingAlg: "naiveRating", - defaultProfileRatingAlg: "naiveRating", - - scoreRatingAlgs: ["rating"], - sessionRatingAlgs: ["naiveRating"], - profileRatingAlgs: ["naiveRating"], - - scoreRatingAlgDescriptions: { - rating: "The rating value of this score. This is identical to the system used in game.", - }, - profileRatingAlgDescriptions: { - naiveRating: - "The average of your best 20 ratings. This is different to in-game, as it does not take into account your recent scores in any way.", - }, - sessionRatingAlgDescriptions: { - naiveRating: "The average of your best 10 ratings this session.", - }, - - scoreRatingAlgFormatters: {}, - profileRatingAlgFormatters: {}, - sessionRatingAlgFormatters: {}, - - difficultyOrder: ["BASIC", "ADVANCED", "EXPERT", "MASTER"], - difficultyShorthand: { - BASIC: "B", - ADVANCED: "A", - EXPERT: "E", - MASTER: "M", - }, - defaultDifficulty: "MASTER", - difficultyColours: { - BASIC: COLOUR_SET.blue, - ADVANCED: COLOUR_SET.orange, - EXPERT: COLOUR_SET.red, - MASTER: COLOUR_SET.purple, - }, - - orderedGrades: ["D", "C", "B", "BB", "BBB", "A", "AA", "AAA", "S", "SS", "SSS"], - gradeColours: { - D: COLOUR_SET.red, - C: COLOUR_SET.purple, - B: COLOUR_SET.paleBlue, - BB: COLOUR_SET.blue, - BBB: COLOUR_SET.vibrantBlue, - A: COLOUR_SET.paleGreen, - AA: COLOUR_SET.green, - AAA: COLOUR_SET.vibrantGreen, - S: COLOUR_SET.vibrantOrange, - SS: COLOUR_SET.vibrantYellow, - SSS: COLOUR_SET.teal, - }, - minimumRelevantGrade: "A", - gradeBoundaries: [0, 50, 60, 70, 80, 90, 92.5, 95.0, 97.5, 100, 100.75], - - orderedLamps: ["FAILED", "CLEAR", "FULL COMBO", "ALL JUSTICE", "ALL JUSTICE CRITICAL"], - lampColours: { - FAILED: COLOUR_SET.red, - CLEAR: COLOUR_SET.paleGreen, - "FULL COMBO": COLOUR_SET.paleBlue, - "ALL JUSTICE": COLOUR_SET.gold, - "ALL JUSTICE CRITICAL": COLOUR_SET.white, - }, - minimumRelevantLamp: "CLEAR", - - classHumanisedFormat: { - colour: CHUNITHMColours, - }, - classProperties: { - colour: { downgradable: true, canBeBatchManualSubmitted: false }, - }, - - supportsESD: false, - orderedJudgements: ["jcrit", "justice", "attack", "miss"], - - scoreBucket: "grade", - - supportedVersions: ["paradiselost"], - - tierlists: [], - tierlistDescriptions: {}, - - supportedMatchTypes: ["inGameID", "songTitle", "tachiSongID"], - }, - "sdvx:Single": { - idString: "sdvx:Single", - percentMax: 100, - - defaultScoreRatingAlg: "VF6", - defaultSessionRatingAlg: "ProfileVF6", - defaultProfileRatingAlg: "VF6", - - scoreRatingAlgs: ["VF6"], - sessionRatingAlgs: ["ProfileVF6", "VF6"], - profileRatingAlgs: ["VF6"], - - scoreRatingAlgDescriptions: { - VF6: "VOLFORCE as it is implemented in SDVX6.", - }, - profileRatingAlgDescriptions: { - VF6: "Your best 50 VF6 values added together.", - }, - sessionRatingAlgDescriptions: { - VF6: "The average of your best 10 VF6s this session.", - ProfileVF6: - "The average of your best 10 VF6s this session, multiplied to be on the same scale as profile VOLFORCE.", - }, - - scoreRatingAlgFormatters: { - VF6: (v) => v.toFixed(3), - }, - profileRatingAlgFormatters: { - VF6: (v) => v.toFixed(3), - }, - sessionRatingAlgFormatters: { - VF6: (v) => v.toFixed(3), - ProfileVF6: (v) => v.toFixed(3), - }, - - difficultyOrder: ["NOV", "ADV", "EXH", "INF", "GRV", "HVN", "VVD", "XCD", "MXM"], - difficultyShorthand: {}, // they're all fine - defaultDifficulty: "EXH", - difficultyColours: { - NOV: COLOUR_SET.purple, // colour set dark purple - ADV: COLOUR_SET.vibrantYellow, - EXH: COLOUR_SET.red, - INF: COLOUR_SET.vibrantPink, - GRV: COLOUR_SET.orange, - HVN: COLOUR_SET.teal, - VVD: COLOUR_SET.pink, - XCD: COLOUR_SET.blue, - MXM: COLOUR_SET.white, - }, - - orderedGrades: ["D", "C", "B", "A", "A+", "AA", "AA+", "AAA", "AAA+", "S", "PUC"], - gradeColours: { - D: COLOUR_SET.gray, - C: COLOUR_SET.red, - B: COLOUR_SET.maroon, - A: COLOUR_SET.paleBlue, - "A+": COLOUR_SET.blue, - AA: COLOUR_SET.paleGreen, - "AA+": COLOUR_SET.green, - AAA: COLOUR_SET.gold, - "AAA+": COLOUR_SET.vibrantOrange, - S: COLOUR_SET.teal, - PUC: COLOUR_SET.pink, - }, - minimumRelevantGrade: "A", - gradeBoundaries: [0, 70, 80, 87, 90, 93, 95, 97, 98, 99, 100], - - orderedLamps: [ - "FAILED", - "CLEAR", - "EXCESSIVE CLEAR", - "ULTIMATE CHAIN", - "PERFECT ULTIMATE CHAIN", - ], - lampColours: { - FAILED: COLOUR_SET.red, - CLEAR: COLOUR_SET.green, - "EXCESSIVE CLEAR": COLOUR_SET.purple, - "ULTIMATE CHAIN": COLOUR_SET.teal, - "PERFECT ULTIMATE CHAIN": COLOUR_SET.gold, - }, - minimumRelevantLamp: "CLEAR", - - classHumanisedFormat: { - dan: SDVXDans, - vfClass: SDVXVFClasses, - }, - classProperties: { - dan: { downgradable: false, canBeBatchManualSubmitted: true }, - vfClass: { downgradable: true, canBeBatchManualSubmitted: false }, - }, - - supportsESD: false, - orderedJudgements: ["critical", "near", "miss"], - - scoreBucket: "grade", - - supportedVersions: ["booth", "inf", "gw", "heaven", "vivid", "exceed", "konaste"], - - tierlists: ["clear"], - tierlistDescriptions: { - clear: "Clearing values taken from the unofficial SDVX spreadsheet tierlists.", - }, - - supportedMatchTypes: ["sdvxInGameID", "songTitle", "tachiSongID"], - }, - "usc:Controller": { - idString: "usc:Controller", - percentMax: 100, - - defaultScoreRatingAlg: "VF6", - defaultSessionRatingAlg: "ProfileVF6", - defaultProfileRatingAlg: "VF6", - - scoreRatingAlgs: ["VF6"], - sessionRatingAlgs: ["ProfileVF6", "VF6"], - profileRatingAlgs: ["VF6"], - - scoreRatingAlgDescriptions: { - VF6: "VOLFORCE as it is implemented in SDVX6.", - }, - profileRatingAlgDescriptions: { - VF6: "Your best 50 VF6 values added together.", - }, - sessionRatingAlgDescriptions: { - VF6: "The average of your best 10 VF6s this session.", - ProfileVF6: - "The average of your best 10 VF6s this session, multiplied to be on the same scale as profile VOLFORCE.", - }, - - scoreRatingAlgFormatters: { - VF6: (v) => v.toFixed(3), - }, - profileRatingAlgFormatters: { - VF6: (v) => v.toFixed(3), - }, - sessionRatingAlgFormatters: { - VF6: (v) => v.toFixed(3), - ProfileVF6: (v) => v.toFixed(3), - }, - - difficultyOrder: ["NOV", "ADV", "EXH", "INF"], - difficultyShorthand: {}, // all fine - defaultDifficulty: "EXH", - difficultyColours: { - NOV: COLOUR_SET.purple, // colour set dark purple - ADV: COLOUR_SET.vibrantYellow, - EXH: COLOUR_SET.red, - INF: COLOUR_SET.vibrantPink, - }, - - orderedGrades: ["D", "C", "B", "A", "A+", "AA", "AA+", "AAA", "AAA+", "S", "PUC"], - gradeColours: { - D: COLOUR_SET.gray, - C: COLOUR_SET.red, - B: COLOUR_SET.maroon, - A: COLOUR_SET.paleBlue, - "A+": COLOUR_SET.blue, - AA: COLOUR_SET.paleGreen, - "AA+": COLOUR_SET.green, - AAA: COLOUR_SET.gold, - "AAA+": COLOUR_SET.vibrantOrange, - S: COLOUR_SET.teal, - PUC: COLOUR_SET.pink, - }, - minimumRelevantGrade: "A", - gradeBoundaries: [0, 70, 80, 87, 90, 93, 95, 97, 98, 99, 100], - - orderedLamps: [ - "FAILED", - "CLEAR", - "EXCESSIVE CLEAR", - "ULTIMATE CHAIN", - "PERFECT ULTIMATE CHAIN", - ], - lampColours: { - FAILED: COLOUR_SET.red, - CLEAR: COLOUR_SET.green, - "EXCESSIVE CLEAR": COLOUR_SET.orange, - "ULTIMATE CHAIN": COLOUR_SET.teal, - "PERFECT ULTIMATE CHAIN": COLOUR_SET.gold, - }, - minimumRelevantLamp: "CLEAR", - - classHumanisedFormat: {}, - classProperties: {}, - - supportsESD: false, - orderedJudgements: ["critical", "near", "miss"], - - scoreBucket: "grade", - - supportedVersions: [], - - tierlists: [], - tierlistDescriptions: {}, - - supportedMatchTypes: ["uscChartHash", "tachiSongID"], - }, - "usc:Keyboard": { - idString: "usc:Keyboard", - percentMax: 100, - - defaultScoreRatingAlg: "VF6", - defaultSessionRatingAlg: "ProfileVF6", - defaultProfileRatingAlg: "VF6", - - scoreRatingAlgs: ["VF6"], - sessionRatingAlgs: ["ProfileVF6", "VF6"], - profileRatingAlgs: ["VF6"], - - scoreRatingAlgDescriptions: { - VF6: "VOLFORCE as it is implemented in SDVX6.", - }, - profileRatingAlgDescriptions: { - VF6: "Your best 50 VF6 values added together.", - }, - sessionRatingAlgDescriptions: { - VF6: "The average of your best 10 VF6s this session.", - ProfileVF6: - "The average of your best 10 VF6s this session, multiplied to be on the same scale as profile VOLFORCE.", - }, - - scoreRatingAlgFormatters: { - VF6: (v) => v.toFixed(3), - }, - profileRatingAlgFormatters: { - VF6: (v) => v.toFixed(3), - }, - sessionRatingAlgFormatters: { - VF6: (v) => v.toFixed(3), - ProfileVF6: (v) => v.toFixed(3), - }, - - difficultyOrder: ["NOV", "ADV", "EXH", "INF"], - difficultyShorthand: {}, // all fine - defaultDifficulty: "EXH", - difficultyColours: { - NOV: COLOUR_SET.purple, // colour set dark purple - ADV: COLOUR_SET.vibrantYellow, - EXH: COLOUR_SET.red, - INF: COLOUR_SET.vibrantPink, - }, - - orderedGrades: ["D", "C", "B", "A", "A+", "AA", "AA+", "AAA", "AAA+", "S", "PUC"], - gradeColours: { - D: COLOUR_SET.gray, - C: COLOUR_SET.red, - B: COLOUR_SET.maroon, - A: COLOUR_SET.paleBlue, - "A+": COLOUR_SET.blue, - AA: COLOUR_SET.paleGreen, - "AA+": COLOUR_SET.green, - AAA: COLOUR_SET.gold, - "AAA+": COLOUR_SET.vibrantOrange, - S: COLOUR_SET.teal, - PUC: COLOUR_SET.pink, - }, - minimumRelevantGrade: "A", - gradeBoundaries: [0, 70, 80, 87, 90, 93, 95, 97, 98, 99, 100], - - orderedLamps: [ - "FAILED", - "CLEAR", - "EXCESSIVE CLEAR", - "ULTIMATE CHAIN", - "PERFECT ULTIMATE CHAIN", - ], - lampColours: { - FAILED: COLOUR_SET.red, - CLEAR: COLOUR_SET.green, - "EXCESSIVE CLEAR": COLOUR_SET.orange, - "ULTIMATE CHAIN": COLOUR_SET.teal, - "PERFECT ULTIMATE CHAIN": COLOUR_SET.gold, - }, - minimumRelevantLamp: "CLEAR", - - classHumanisedFormat: {}, - classProperties: {}, - - supportsESD: false, - orderedJudgements: ["critical", "near", "miss"], - - scoreBucket: "grade", - - supportedVersions: [], - - tierlists: [], - tierlistDescriptions: {}, - - supportedMatchTypes: ["uscChartHash", "tachiSongID"], - }, - "museca:Single": { - idString: "museca:Single", - percentMax: 100, - - defaultScoreRatingAlg: "curatorSkill", - defaultSessionRatingAlg: "curatorSkill", - defaultProfileRatingAlg: "curatorSkill", - - scoreRatingAlgs: ["curatorSkill"], - sessionRatingAlgs: ["curatorSkill"], - profileRatingAlgs: ["curatorSkill"], - - scoreRatingAlgDescriptions: { - curatorSkill: "A custom rating system that combines score and the chart level.", - }, - profileRatingAlgDescriptions: { - curatorSkill: "The sum of your best 20 Curator Skills.", - }, - sessionRatingAlgDescriptions: { - curatorSkill: "The average of your best 10 curator skills this session.", - }, - - scoreRatingAlgFormatters: { - curatorSkill: (v) => v.toFixed(0), - }, - profileRatingAlgFormatters: { - curatorSkill: (v) => v.toFixed(0), - }, - sessionRatingAlgFormatters: { - curatorSkill: (v) => v.toFixed(0), - }, - - difficultyOrder: ["Green", "Yellow", "Red"], - difficultyShorthand: { Green: "G", Yellow: "Y", Red: "R" }, - defaultDifficulty: "Red", - difficultyColours: { - Green: COLOUR_SET.green, - Yellow: COLOUR_SET.vibrantYellow, - Red: COLOUR_SET.red, - }, - - orderedGrades: ["没", "拙", "凡", "佳", "良", "優", "秀", "傑", "傑G"], - gradeColours: { - 没: COLOUR_SET.gray, - 拙: COLOUR_SET.maroon, - 凡: COLOUR_SET.red, - 佳: COLOUR_SET.paleGreen, - 良: COLOUR_SET.paleBlue, - 優: COLOUR_SET.green, - 秀: COLOUR_SET.blue, - 傑: COLOUR_SET.teal, - 傑G: COLOUR_SET.gold, - }, - minimumRelevantGrade: "良", - gradeBoundaries: [0, 60, 70, 80, 85, 90, 95, 97.5, 100], - - orderedLamps: ["FAILED", "CLEAR", "CONNECT ALL", "PERFECT CONNECT ALL"], - lampColours: { - FAILED: COLOUR_SET.red, - CLEAR: COLOUR_SET.green, - "CONNECT ALL": COLOUR_SET.teal, - "PERFECT CONNECT ALL": COLOUR_SET.gold, - }, - minimumRelevantLamp: "CLEAR", - - classHumanisedFormat: {}, - classProperties: {}, - - supportsESD: true, - judgementWindows: [ - { name: "CRITICAL", msBorder: 33.333, value: 2 }, - { name: "NEAR", msBorder: 66.667, value: 1 }, - ], - orderedJudgements: ["critical", "near", "miss"], - - scoreBucket: "grade", - - supportedVersions: ["1.5", "1.5-b"], - - tierlists: [], - tierlistDescriptions: {}, - - supportedMatchTypes: ["songTitle", "tachiSongID", "inGameID"], - }, - "bms:7K": { - idString: "bms:7K", - percentMax: 100, - - defaultScoreRatingAlg: "sieglinde", - defaultSessionRatingAlg: "sieglinde", - defaultProfileRatingAlg: "sieglinde", - - scoreRatingAlgs: ["sieglinde"], - sessionRatingAlgs: ["sieglinde"], - profileRatingAlgs: ["sieglinde"], - - scoreRatingAlgDescriptions: { - sieglinde: - "A clearing algorithm that rewards you points based on how difficult an easy clear or hard clear was.", - }, - profileRatingAlgDescriptions: { - sieglinde: "The average of your best 20 sieglinde ratings.", - }, - sessionRatingAlgDescriptions: { - sieglinde: "The average of your best 10 sieglinde ratings this session.", - }, - - scoreRatingAlgFormatters: { - sieglinde: FormatSieglindeBMS, - }, - profileRatingAlgFormatters: { - sieglinde: FormatSieglindeBMS, - }, - sessionRatingAlgFormatters: { - sieglinde: FormatSieglindeBMS, - }, - - difficultyOrder: ["CHART"], - difficultyShorthand: {}, // not real - defaultDifficulty: "CHART", - difficultyColours: { - CHART: null, - }, - - orderedGrades: ["F", "E", "D", "C", "B", "A", "AA", "AAA", "MAX-", "MAX"], - gradeColours: { - F: COLOUR_SET.gray, - E: COLOUR_SET.red, - D: COLOUR_SET.maroon, - C: COLOUR_SET.purple, - B: COLOUR_SET.paleBlue, - A: COLOUR_SET.green, - AA: COLOUR_SET.blue, - AAA: COLOUR_SET.gold, - "MAX-": COLOUR_SET.teal, - MAX: COLOUR_SET.white, - }, - minimumRelevantGrade: "A", - - // see iidx:SP for an explaination of why this is wrote like this. - gradeBoundaries: [ - 0, - (100 * 2) / 9, - (100 * 3) / 9, - (100 * 4) / 9, - (100 * 5) / 9, - (100 * 6) / 9, - (100 * 7) / 9, - (100 * 8) / 9, - (100 * 17) / 18, - (100 * 9) / 9, - ], - - orderedLamps: [ - "NO PLAY", - "FAILED", - "ASSIST CLEAR", - "EASY CLEAR", - "CLEAR", - "HARD CLEAR", - "EX HARD CLEAR", - "FULL COMBO", - ], - lampColours: { - "NO PLAY": COLOUR_SET.gray, - FAILED: COLOUR_SET.red, - "ASSIST CLEAR": COLOUR_SET.purple, - "EASY CLEAR": COLOUR_SET.green, - CLEAR: COLOUR_SET.blue, - "HARD CLEAR": COLOUR_SET.orange, - "EX HARD CLEAR": COLOUR_SET.gold, - "FULL COMBO": COLOUR_SET.teal, - }, - minimumRelevantLamp: "CLEAR", - - classHumanisedFormat: { - genocideDan: BMSGenocideDans, - stslDan: BMSStSlDans, - lnDan: BMSLNDans, - scratchDan: BMSScratchDans, - }, - classProperties: { - genocideDan: { downgradable: false, canBeBatchManualSubmitted: true }, - stslDan: { downgradable: false, canBeBatchManualSubmitted: true }, - lnDan: { downgradable: false, canBeBatchManualSubmitted: true }, - scratchDan: { downgradable: false, canBeBatchManualSubmitted: true }, - }, - - supportsESD: false, - orderedJudgements: ["pgreat", "great", "good", "bad", "poor"], - - scoreBucket: "lamp", - - supportedVersions: [], - - tierlists: ["sgl-EC", "sgl-HC"], - tierlistDescriptions: { - "sgl-EC": "Sieglinde Easy Clear ratings.", - "sgl-HC": "Sieglinde Hard Clear ratings.", - }, - - supportedMatchTypes: ["bmsChartHash", "tachiSongID"], - }, - "bms:14K": { - idString: "bms:14K", - - percentMax: 100, - - defaultScoreRatingAlg: "sieglinde", - defaultSessionRatingAlg: "sieglinde", - defaultProfileRatingAlg: "sieglinde", - - scoreRatingAlgs: ["sieglinde"], - sessionRatingAlgs: ["sieglinde"], - profileRatingAlgs: ["sieglinde"], - - scoreRatingAlgDescriptions: { - sieglinde: - "A clearing algorithm that rewards you points based on how difficult an easy clear or hard clear was.", - }, - profileRatingAlgDescriptions: { - sieglinde: "The average of your best 20 sieglinde ratings.", - }, - sessionRatingAlgDescriptions: { - sieglinde: "The average of your best 10 sieglinde ratings this session.", - }, - - scoreRatingAlgFormatters: { - sieglinde: FormatSieglindeBMS, - }, - profileRatingAlgFormatters: { - sieglinde: FormatSieglindeBMS, - }, - sessionRatingAlgFormatters: { - sieglinde: FormatSieglindeBMS, - }, - - difficultyOrder: ["CHART"], - difficultyShorthand: {}, // not real - defaultDifficulty: "CHART", - difficultyColours: { - CHART: null, - }, - - orderedGrades: ["F", "E", "D", "C", "B", "A", "AA", "AAA", "MAX-", "MAX"], - gradeColours: { - F: COLOUR_SET.gray, - E: COLOUR_SET.red, - D: COLOUR_SET.maroon, - C: COLOUR_SET.purple, - B: COLOUR_SET.paleBlue, - A: COLOUR_SET.green, - AA: COLOUR_SET.blue, - AAA: COLOUR_SET.gold, - "MAX-": COLOUR_SET.teal, - MAX: COLOUR_SET.white, - }, - minimumRelevantGrade: "A", - - // see iidx:SP for an explaination of why this is wrote like this. - gradeBoundaries: [ - 0, - (100 * 2) / 9, - (100 * 3) / 9, - (100 * 4) / 9, - (100 * 5) / 9, - (100 * 6) / 9, - (100 * 7) / 9, - (100 * 8) / 9, - (100 * 17) / 18, - (100 * 9) / 9, - ], - - orderedLamps: [ - "NO PLAY", - "FAILED", - "ASSIST CLEAR", - "EASY CLEAR", - "CLEAR", - "HARD CLEAR", - "EX HARD CLEAR", - "FULL COMBO", - ], - lampColours: { - "NO PLAY": COLOUR_SET.gray, - FAILED: COLOUR_SET.red, - "ASSIST CLEAR": COLOUR_SET.purple, - "EASY CLEAR": COLOUR_SET.green, - CLEAR: COLOUR_SET.blue, - "HARD CLEAR": COLOUR_SET.orange, - "EX HARD CLEAR": COLOUR_SET.gold, - "FULL COMBO": COLOUR_SET.teal, - }, - minimumRelevantLamp: "CLEAR", - - classHumanisedFormat: { - genocideDan: BMSGenocideDans, - stslDan: BMSDPSlDans, - }, - classProperties: { - genocideDan: { downgradable: false, canBeBatchManualSubmitted: true }, - stslDan: { downgradable: false, canBeBatchManualSubmitted: true }, - }, - - supportsESD: false, - orderedJudgements: ["pgreat", "great", "good", "bad", "poor"], - - scoreBucket: "lamp", - - supportedVersions: [], - - tierlists: ["sgl-EC", "sgl-HC"], - tierlistDescriptions: { - "sgl-EC": "Sieglinde Easy Clear ratings.", - "sgl-HC": "Sieglinde Hard Clear ratings.", - }, - - supportedMatchTypes: ["bmsChartHash", "tachiSongID"], - }, - "maimaidx:Single": { - idString: "maimaidx:Single", - - percentMax: 101, - - defaultScoreRatingAlg: "rate", - defaultSessionRatingAlg: "rate", - defaultProfileRatingAlg: "naiveRate", - - scoreRatingAlgs: ["rate"], - sessionRatingAlgs: ["rate"], - profileRatingAlgs: ["naiveRate", "rate"], - - scoreRatingAlgDescriptions: { - rate: "Rating as it's implemented in game.", - }, - profileRatingAlgDescriptions: { - naiveRate: "A naive rating algorithm that just sums your 50 best scores.", - rate: "Rating as it's implemented in game, taking 15 scores from the latest version and 35 from all old versions.", - }, - sessionRatingAlgDescriptions: { - rate: "The average of your best 10 ratings this session.", - }, - - scoreRatingAlgFormatters: { - rate: FormatMaimaiDXRating, - }, - profileRatingAlgFormatters: { - naiveRate: FormatMaimaiDXRating, - rate: FormatMaimaiDXRating, - }, - sessionRatingAlgFormatters: { - rate: FormatMaimaiDXRating, - }, - - difficultyOrder: [ - "Basic", - "Advanced", - "Expert", - "Master", - "Re:Master", - "DX Basic", - "DX Advanced", - "DX Expert", - "DX Master", - "DX Re:Master", - ], - difficultyShorthand: { - Basic: "BAS", - Advanced: "ADV", - Expert: "EXP", - Master: "MAS", - "Re:Master": "Re:MAS", - "DX Basic": "DX BAS", - "DX Advanced": "DX ADV", - "DX Expert": "DX EXP", - "DX Master": "DX MAS", - "DX Re:Master": "DX Re:MAS", - }, - defaultDifficulty: "Master", - difficultyColours: { - Basic: COLOUR_SET.green, - Advanced: COLOUR_SET.orange, - Expert: COLOUR_SET.red, - Master: COLOUR_SET.purple, - "Re:Master": COLOUR_SET.white, - "DX Basic": COLOUR_SET.green, - "DX Advanced": COLOUR_SET.orange, - "DX Expert": COLOUR_SET.red, - "DX Master": COLOUR_SET.purple, - "DX Re:Master": COLOUR_SET.white, - }, - - orderedGrades: [ - "D", - "C", - "B", - "BB", - "BBB", - "A", - "AA", - "AAA", - "S", - "S+", - "SS", - "SS+", - "SSS", - "SSS+", - ], - gradeColours: { - D: COLOUR_SET.gray, - C: COLOUR_SET.red, - B: COLOUR_SET.maroon, - BB: COLOUR_SET.purple, - BBB: COLOUR_SET.paleGreen, - A: COLOUR_SET.green, - AA: COLOUR_SET.paleBlue, - AAA: COLOUR_SET.blue, - S: COLOUR_SET.gold, - "S+": COLOUR_SET.vibrantYellow, - SS: COLOUR_SET.paleOrange, - "SS+": COLOUR_SET.orange, - SSS: COLOUR_SET.teal, - "SSS+": COLOUR_SET.white, - }, - minimumRelevantGrade: "A", - - gradeBoundaries: [0, 10, 20, 40, 60, 80, 90, 94, 97, 98, 99, 99.5, 100, 100.5], - - orderedLamps: [ - "FAILED", - "CLEAR", - "FULL COMBO", - "FULL COMBO+", - "ALL PERFECT", - "ALL PERFECT+", - ], - lampColours: { - FAILED: COLOUR_SET.red, - CLEAR: COLOUR_SET.green, - "FULL COMBO": COLOUR_SET.blue, - "FULL COMBO+": COLOUR_SET.paleBlue, - "ALL PERFECT": COLOUR_SET.gold, - "ALL PERFECT+": COLOUR_SET.teal, - }, - minimumRelevantLamp: "CLEAR", - - classHumanisedFormat: { - colour: MaimaiDXColours, - dan: MaimaiDXDans, - }, - classProperties: { - colour: { downgradable: true, canBeBatchManualSubmitted: false }, - dan: { downgradable: false, canBeBatchManualSubmitted: true }, - }, - - supportsESD: false, - orderedJudgements: ["pcrit", "perfect", "great", "good", "miss"], - - scoreBucket: "grade", - - supportedVersions: ["universeplus"], - - tierlists: [], - tierlistDescriptions: {}, - - supportedMatchTypes: ["songTitle", "tachiSongID"], - }, - "gitadora:Gita": { - idString: "gitadora:Gita", - - percentMax: 100, - - defaultScoreRatingAlg: "skill", - defaultSessionRatingAlg: "skill", - defaultProfileRatingAlg: "skill", - - scoreRatingAlgs: ["skill"], - sessionRatingAlgs: ["skill"], - profileRatingAlgs: ["skill"], - - scoreRatingAlgDescriptions: { - skill: "Skill Rating as it's implemented in game.", - }, - profileRatingAlgDescriptions: { - skill: "Your profile skill as it's implemented in game -- 25 HOT and 25 not HOT.", - naiveSkill: - "Your best 50 skill levels added together, regardless of whether the chart is HOT or not.", - }, - sessionRatingAlgDescriptions: { - skill: "The average of your best 10 skill ratings this session.", - }, - - scoreRatingAlgFormatters: {}, - profileRatingAlgFormatters: {}, - sessionRatingAlgFormatters: {}, - - difficultyOrder: [ - "BASIC", - "ADVANCED", - "EXTREME", - "MASTER", - "BASS BASIC", - "BASS ADVANCED", - "BASS EXTREME", - "BASS MASTER", - ], - difficultyShorthand: { - BASIC: "G-BSC", - ADVANCED: "G-ADV", - EXTREME: "G-EXT", - MASTER: "G-MAS", - "BASS BASIC": "B-BSC", - "BASS ADVANCED": "B-ADV", - "BASS EXTREME": "B-EXT", - "BASS MASTER": "B-MAS", - }, - defaultDifficulty: "EXTREME", - difficultyColours: { - BASIC: COLOUR_SET.blue, - ADVANCED: COLOUR_SET.orange, - EXTREME: COLOUR_SET.red, - MASTER: COLOUR_SET.purple, - "BASS BASIC": COLOUR_SET.vibrantBlue, - "BASS ADVANCED": COLOUR_SET.vibrantOrange, - "BASS EXTREME": COLOUR_SET.vibrantRed, - "BASS MASTER": COLOUR_SET.vibrantPurple, - }, - - orderedGrades: ["C", "B", "A", "S", "SS", "MAX"], - gradeColours: { - C: COLOUR_SET.purple, - B: COLOUR_SET.blue, - A: COLOUR_SET.green, - S: COLOUR_SET.orange, - SS: COLOUR_SET.gold, - MAX: COLOUR_SET.white, - }, - minimumRelevantGrade: "A", - gradeBoundaries: [0, 63, 73, 80, 95, 100], - - orderedLamps: ["FAILED", "CLEAR", "FULL COMBO", "EXCELLENT"], - lampColours: { - FAILED: COLOUR_SET.red, - CLEAR: COLOUR_SET.blue, - "FULL COMBO": COLOUR_SET.teal, - EXCELLENT: COLOUR_SET.gold, - }, - minimumRelevantLamp: "CLEAR", - - classHumanisedFormat: { - colour: GitadoraColours, - }, - classProperties: { - colour: { downgradable: true, canBeBatchManualSubmitted: false }, - }, - - supportsESD: false, - orderedJudgements: ["perfect", "great", "good", "ok", "miss"], - - scoreBucket: "grade", - - supportedVersions: ["konaste"], - - tierlists: [], - tierlistDescriptions: {}, - - supportedMatchTypes: ["inGameID", "songTitle", "tachiSongID"], - }, - "gitadora:Dora": { - idString: "gitadora:Dora", - - percentMax: 100, - - defaultScoreRatingAlg: "skill", - defaultSessionRatingAlg: "skill", - defaultProfileRatingAlg: "skill", - - scoreRatingAlgs: ["skill"], - sessionRatingAlgs: ["skill"], - profileRatingAlgs: ["skill"], - - scoreRatingAlgDescriptions: { - skill: "Skill Rating as it's implemented in game.", - }, - profileRatingAlgDescriptions: { - skill: "Your profile skill as it's implemented in game -- 25 HOT and 25 not HOT.", - naiveSkill: - "Your best 50 skill levels added together, regardless of whether the chart is HOT or not.", - }, - sessionRatingAlgDescriptions: { - skill: "The average of your best 10 skill ratings this session.", - }, - - scoreRatingAlgFormatters: {}, - profileRatingAlgFormatters: {}, - sessionRatingAlgFormatters: {}, - - difficultyOrder: ["BASIC", "ADVANCED", "EXTREME", "MASTER"], - difficultyShorthand: { - BASIC: "D-BSC", - ADVANCED: "D-ADV", - EXTREME: "D-EXT", - MASTER: "D-MAS", - }, - defaultDifficulty: "EXTREME", - difficultyColours: { - BASIC: COLOUR_SET.blue, - ADVANCED: COLOUR_SET.orange, - EXTREME: COLOUR_SET.red, - MASTER: COLOUR_SET.purple, - }, - - orderedGrades: ["C", "B", "A", "S", "SS", "MAX"], - gradeColours: { - C: COLOUR_SET.purple, - B: COLOUR_SET.blue, - A: COLOUR_SET.green, - S: COLOUR_SET.orange, - SS: COLOUR_SET.gold, - MAX: COLOUR_SET.white, - }, - minimumRelevantGrade: "A", - gradeBoundaries: [0, 63, 73, 80, 95, 100], - - orderedLamps: ["FAILED", "CLEAR", "FULL COMBO", "EXCELLENT"], - lampColours: { - FAILED: COLOUR_SET.red, - CLEAR: COLOUR_SET.blue, - "FULL COMBO": COLOUR_SET.teal, - EXCELLENT: COLOUR_SET.gold, - }, - minimumRelevantLamp: "CLEAR", - - classHumanisedFormat: { - colour: GitadoraColours, - }, - classProperties: { - colour: { downgradable: true, canBeBatchManualSubmitted: false }, - }, - - supportsESD: false, - orderedJudgements: ["perfect", "great", "good", "ok", "miss"], - - scoreBucket: "grade", - - supportedVersions: ["konaste"], - - tierlists: [], - tierlistDescriptions: {}, - - supportedMatchTypes: ["inGameID", "songTitle", "tachiSongID"], - }, - "wacca:Single": { - idString: "wacca:Single", - - percentMax: 100, - - defaultScoreRatingAlg: "rate", - defaultSessionRatingAlg: "rate", - defaultProfileRatingAlg: "naiveRate", - - scoreRatingAlgs: ["rate"], - sessionRatingAlgs: ["rate"], - profileRatingAlgs: ["naiveRate", "rate"], - - scoreRatingAlgDescriptions: { - rate: "Rating as it's implemented in game.", - }, - profileRatingAlgDescriptions: { - naiveRate: "A naive rating algorithm that just sums your 50 best scores.", - rate: "Rating as it's implemented in game, taking 15 scores from the latest version and 35 from all old versions.", - }, - sessionRatingAlgDescriptions: { - rate: "The average of your best 10 ratings this session.", - }, - - scoreRatingAlgFormatters: {}, - profileRatingAlgFormatters: {}, - sessionRatingAlgFormatters: {}, - - difficultyOrder: ["NORMAL", "HARD", "EXPERT", "INFERNO"], - difficultyShorthand: { - NORMAL: "NRM", - HARD: "HRD", - EXPERT: "EXP", - INFERNO: "INF", - }, - defaultDifficulty: "EXPERT", - difficultyColours: { - NORMAL: COLOUR_SET.blue, - HARD: COLOUR_SET.gold, - EXPERT: COLOUR_SET.pink, - INFERNO: COLOUR_SET.purple, - }, - - orderedGrades: [ - "D", - "C", - "B", - "A", - "AA", - "AAA", - "S", - "S+", - "SS", - "SS+", - "SSS", - "SSS+", - "MASTER", - ], - gradeColours: { - D: COLOUR_SET.gray, - C: COLOUR_SET.maroon, - B: COLOUR_SET.red, - A: COLOUR_SET.paleGreen, - AA: COLOUR_SET.green, - AAA: COLOUR_SET.vibrantGreen, - S: COLOUR_SET.gold, - "S+": COLOUR_SET.vibrantYellow, - SS: COLOUR_SET.paleOrange, - "SS+": COLOUR_SET.orange, - SSS: COLOUR_SET.pink, - "SSS+": COLOUR_SET.vibrantPink, - MASTER: COLOUR_SET.white, - }, - minimumRelevantGrade: "S", - - // i'm pretty sure the first grade is below the limit of reliable FPA accuracy - gradeBoundaries: [0, 0.0001, 3.0001, 70, 80, 85, 90, 93, 95, 97, 98, 99, 100], - - orderedLamps: ["FAILED", "CLEAR", "MISSLESS", "FULL COMBO", "ALL MARVELOUS"], - lampColours: { - FAILED: COLOUR_SET.red, - CLEAR: COLOUR_SET.blue, - MISSLESS: COLOUR_SET.orange, - "FULL COMBO": COLOUR_SET.pink, - "ALL MARVELOUS": COLOUR_SET.gold, - }, - minimumRelevantLamp: "CLEAR", - - classHumanisedFormat: { - stageUp: WaccaStageUps, - colour: WaccaColours, - }, - classProperties: { - stageUp: { downgradable: false, canBeBatchManualSubmitted: true }, - colour: { downgradable: true, canBeBatchManualSubmitted: false }, - }, - - supportsESD: false, - orderedJudgements: ["marvelous", "great", "good", "miss"], - - scoreBucket: "grade", - - supportedVersions: ["reverse"], - - tierlists: [], - tierlistDescriptions: {}, - - supportedMatchTypes: ["songTitle", "tachiSongID"], - }, - "popn:9B": { - idString: "popn:9B", - - percentMax: 100, - - defaultScoreRatingAlg: "classPoints", - defaultSessionRatingAlg: "classPoints", - defaultProfileRatingAlg: "naiveClassPoints", - - scoreRatingAlgs: ["classPoints"], - sessionRatingAlgs: ["classPoints"], - profileRatingAlgs: ["naiveClassPoints"], - - scoreRatingAlgDescriptions: { - classPoints: "Class Points as they're implemented in game.", - }, - profileRatingAlgDescriptions: { - naiveClassPoints: - "A naive average of your best 20 scores. This is different to in game class points, as that is affected by recent scores, and not just your best scores.", - }, - sessionRatingAlgDescriptions: { - classPoints: "The average of your best 10 class points this session.", - }, - - scoreRatingAlgFormatters: {}, - profileRatingAlgFormatters: {}, - sessionRatingAlgFormatters: {}, - - difficultyOrder: ["Easy", "Normal", "Hyper", "EX"], - difficultyShorthand: { - Easy: "E", - Normal: "N", - Hyper: "H", - EX: "EX", - }, - defaultDifficulty: "EX", - difficultyColours: { - Easy: COLOUR_SET.blue, - Normal: COLOUR_SET.green, - Hyper: COLOUR_SET.orange, - EX: COLOUR_SET.red, - }, - - orderedGrades: ["E", "D", "C", "B", "A", "AA", "AAA", "S"], - gradeColours: { - E: COLOUR_SET.gray, - D: COLOUR_SET.maroon, - C: COLOUR_SET.red, - B: COLOUR_SET.blue, - A: COLOUR_SET.green, - AA: COLOUR_SET.orange, - AAA: COLOUR_SET.gold, - S: COLOUR_SET.teal, - }, - minimumRelevantGrade: "A", - - // TECHNICALLY THIS IS NOT CORRECT - // A Fail is capped at A rank (82%), no matter what! - gradeBoundaries: [0, 50, 62, 72, 82, 90, 95, 98], - - orderedLamps: ["FAILED", "EASY CLEAR", "CLEAR", "FULL COMBO", "PERFECT"], - lampColours: { - FAILED: COLOUR_SET.red, - "EASY CLEAR": COLOUR_SET.green, - CLEAR: COLOUR_SET.blue, - "FULL COMBO": COLOUR_SET.teal, - PERFECT: COLOUR_SET.gold, - }, - minimumRelevantLamp: "CLEAR", - - classHumanisedFormat: { - class: PopnClasses, - }, - classProperties: { - class: { downgradable: true, canBeBatchManualSubmitted: false }, - }, - - supportsESD: false, - orderedJudgements: ["cool", "great", "good", "bad"], - - scoreBucket: "lamp", - - supportedVersions: ["peace", "kaimei"], - - tierlists: [], - tierlistDescriptions: {}, - - supportedMatchTypes: ["inGameID", "tachiSongID", "popnChartHash"], - }, - "jubeat:Single": { - idString: "jubeat:Single", - - percentMax: 120, - - defaultScoreRatingAlg: "jubility", - defaultSessionRatingAlg: "jubility", - defaultProfileRatingAlg: "jubility", - - scoreRatingAlgs: ["jubility"], - sessionRatingAlgs: ["jubility"], - profileRatingAlgs: ["jubility", "naiveJubility"], - - scoreRatingAlgDescriptions: { - jubility: "Jubility as it's implemented in game.", - }, - profileRatingAlgDescriptions: { - jubility: - "Your profile jubility. This takes your best 30 scores on PICK UP songs, and your best 30 elsewhere.", - naiveJubility: - "A naive version of jubility which just adds together your best 60 scores.", - }, - sessionRatingAlgDescriptions: { - jubility: "The average of your best 10 jubilities this session.", - }, - - scoreRatingAlgFormatters: {}, - profileRatingAlgFormatters: {}, - sessionRatingAlgFormatters: {}, - - difficultyOrder: ["BSC", "ADV", "EXT", "HARD BSC", "HARD ADV", "HARD EXT"], - difficultyShorthand: { - BSC: "BSC", - ADV: "ADV", - EXT: "EXT", - "HARD BSC": "H. BSC", - "HARD ADV": "H. ADV", - "HARD EXT": "H. EXT", - }, - defaultDifficulty: "EXT", - difficultyColours: { - BSC: COLOUR_SET.green, - ADV: COLOUR_SET.gold, - EXT: COLOUR_SET.red, - "HARD BSC": COLOUR_SET.darkGreen, - "HARD ADV": COLOUR_SET.orange, - "HARD EXT": COLOUR_SET.vibrantRed, - }, - - orderedGrades: ["E", "D", "C", "B", "A", "S", "SS", "SSS", "EXC"], - gradeColours: { - E: COLOUR_SET.gray, - D: COLOUR_SET.maroon, - C: COLOUR_SET.red, - B: COLOUR_SET.blue, - A: COLOUR_SET.green, - S: COLOUR_SET.gold, - SS: COLOUR_SET.orange, - SSS: COLOUR_SET.teal, - EXC: COLOUR_SET.white, - }, - minimumRelevantGrade: "A", - gradeBoundaries: [0, 50, 70, 80, 85, 90, 95, 98, 100], - - orderedLamps: ["FAILED", "CLEAR", "FULL COMBO", "EXCELLENT"], - lampColours: { - FAILED: COLOUR_SET.red, - CLEAR: COLOUR_SET.blue, - "FULL COMBO": COLOUR_SET.teal, - EXCELLENT: COLOUR_SET.white, - }, - minimumRelevantLamp: "CLEAR", - - classHumanisedFormat: { - colour: JubeatColours, - }, - classProperties: { - colour: { downgradable: true, canBeBatchManualSubmitted: false }, - }, - - supportsESD: false, - orderedJudgements: ["perfect", "great", "good", "poor", "miss"], - - scoreBucket: "grade", - - supportedVersions: [ - "jubeat", - "ripples", - "knit", - "copious", - "saucer", - "prop", - "qubell", - "clan", - "festo", - ], - - tierlists: [], - tierlistDescriptions: {}, - - supportedMatchTypes: ["inGameID", "tachiSongID"], - }, - "pms:Controller": { - idString: "pms:Controller", - percentMax: 100, - - defaultScoreRatingAlg: "sieglinde", - defaultSessionRatingAlg: "sieglinde", - defaultProfileRatingAlg: "sieglinde", - - scoreRatingAlgs: ["sieglinde"], - sessionRatingAlgs: ["sieglinde"], - profileRatingAlgs: ["sieglinde"], - - scoreRatingAlgFormatters: { - sieglinde: FormatSieglindePMS, - }, - profileRatingAlgFormatters: { - sieglinde: FormatSieglindePMS, - }, - sessionRatingAlgFormatters: { - sieglinde: FormatSieglindePMS, - }, - - scoreRatingAlgDescriptions: { - sieglinde: - "A clearing algorithm that rewards you points based on how difficult an easy clear or hard clear was.", - }, - profileRatingAlgDescriptions: { - sieglinde: "The average of your best 20 sieglinde ratings.", - }, - sessionRatingAlgDescriptions: { - sieglinde: "The average of your best 10 sieglinde ratings this session.", - }, - - difficultyOrder: ["CHART"], - difficultyShorthand: {}, - defaultDifficulty: "CHART", - difficultyColours: { - CHART: null, - }, - - orderedGrades: ["F", "E", "D", "C", "B", "A", "AA", "AAA", "MAX-", "MAX"], - gradeColours: { - F: COLOUR_SET.gray, - E: COLOUR_SET.red, - D: COLOUR_SET.maroon, - C: COLOUR_SET.purple, - B: COLOUR_SET.paleBlue, - A: COLOUR_SET.green, - AA: COLOUR_SET.blue, - AAA: COLOUR_SET.gold, - "MAX-": COLOUR_SET.teal, - MAX: COLOUR_SET.white, - }, - minimumRelevantGrade: "A", - - // see iidx:SP for an explaination of why this is wrote like this. - gradeBoundaries: [ - 0, - (100 * 2) / 9, - (100 * 3) / 9, - (100 * 4) / 9, - (100 * 5) / 9, - (100 * 6) / 9, - (100 * 7) / 9, - (100 * 8) / 9, - (100 * 17) / 18, - (100 * 9) / 9, - ], - - orderedLamps: [ - "NO PLAY", - "FAILED", - "ASSIST CLEAR", - "EASY CLEAR", - "CLEAR", - "HARD CLEAR", - "EX HARD CLEAR", - "FULL COMBO", - ], - lampColours: { - "NO PLAY": COLOUR_SET.gray, - FAILED: COLOUR_SET.red, - "ASSIST CLEAR": COLOUR_SET.purple, - "EASY CLEAR": COLOUR_SET.green, - CLEAR: COLOUR_SET.blue, - "HARD CLEAR": COLOUR_SET.orange, - "EX HARD CLEAR": COLOUR_SET.gold, - "FULL COMBO": COLOUR_SET.teal, - }, - minimumRelevantLamp: "CLEAR", - - classHumanisedFormat: { - dan: PMSDans, - }, - classProperties: { - dan: { downgradable: false, canBeBatchManualSubmitted: true }, - }, - - supportsESD: false, - orderedJudgements: ["cool", "great", "good", "bad", "poor"], - - scoreBucket: "lamp", - - supportedVersions: [], - - tierlists: ["sgl-EC", "sgl-HC"], - tierlistDescriptions: { - "sgl-EC": "Sieglinde Easy Clear ratings.", - "sgl-HC": "Sieglinde Hard Clear ratings.", - }, - - supportedMatchTypes: ["bmsChartHash", "tachiSongID"], - }, - "pms:Keyboard": { - idString: "pms:Keyboard", - percentMax: 100, - - defaultScoreRatingAlg: "sieglinde", - defaultSessionRatingAlg: "sieglinde", - defaultProfileRatingAlg: "sieglinde", - - scoreRatingAlgs: ["sieglinde"], - sessionRatingAlgs: ["sieglinde"], - profileRatingAlgs: ["sieglinde"], - - scoreRatingAlgFormatters: { - sieglinde: FormatSieglindePMS, - }, - profileRatingAlgFormatters: { - sieglinde: FormatSieglindePMS, - }, - sessionRatingAlgFormatters: { - sieglinde: FormatSieglindePMS, - }, - - scoreRatingAlgDescriptions: { - sieglinde: - "A clearing algorithm that rewards you points based on how difficult an easy clear or hard clear was.", - }, - profileRatingAlgDescriptions: { - sieglinde: "The average of your best 20 sieglinde ratings.", - }, - sessionRatingAlgDescriptions: { - sieglinde: "The average of your best 10 sieglinde ratings this session.", - }, - - difficultyOrder: ["CHART"], - difficultyShorthand: {}, - defaultDifficulty: "CHART", - difficultyColours: { - CHART: null, - }, - - orderedGrades: ["F", "E", "D", "C", "B", "A", "AA", "AAA", "MAX-", "MAX"], - gradeColours: { - F: COLOUR_SET.gray, - E: COLOUR_SET.red, - D: COLOUR_SET.maroon, - C: COLOUR_SET.purple, - B: COLOUR_SET.paleBlue, - A: COLOUR_SET.green, - AA: COLOUR_SET.blue, - AAA: COLOUR_SET.gold, - "MAX-": COLOUR_SET.teal, - MAX: COLOUR_SET.white, - }, - minimumRelevantGrade: "A", - - // see iidx:SP for an explaination of why this is wrote like this. - gradeBoundaries: [ - 0, - (100 * 2) / 9, - (100 * 3) / 9, - (100 * 4) / 9, - (100 * 5) / 9, - (100 * 6) / 9, - (100 * 7) / 9, - (100 * 8) / 9, - (100 * 17) / 18, - (100 * 9) / 9, - ], - - orderedLamps: [ - "NO PLAY", - "FAILED", - "ASSIST CLEAR", - "EASY CLEAR", - "CLEAR", - "HARD CLEAR", - "EX HARD CLEAR", - "FULL COMBO", - ], - lampColours: { - "NO PLAY": COLOUR_SET.gray, - FAILED: COLOUR_SET.red, - "ASSIST CLEAR": COLOUR_SET.purple, - "EASY CLEAR": COLOUR_SET.green, - CLEAR: COLOUR_SET.blue, - "HARD CLEAR": COLOUR_SET.orange, - "EX HARD CLEAR": COLOUR_SET.gold, - "FULL COMBO": COLOUR_SET.teal, - }, - minimumRelevantLamp: "CLEAR", - - classHumanisedFormat: { - dan: PMSDans, - }, - classProperties: { - dan: { downgradable: false, canBeBatchManualSubmitted: true }, - }, - - supportsESD: false, - orderedJudgements: ["cool", "great", "good", "bad", "poor"], - - scoreBucket: "lamp", - - supportedVersions: [], - - tierlists: ["sgl-EC", "sgl-HC"], - tierlistDescriptions: { - "sgl-EC": "Sieglinde Easy Clear ratings.", - "sgl-HC": "Sieglinde Hard Clear ratings.", - }, - - supportedMatchTypes: ["bmsChartHash", "tachiSongID"], - }, - "itg:Stamina": { - idString: "itg:Stamina", - - percentMax: 100, - - defaultScoreRatingAlg: "blockRating", - defaultSessionRatingAlg: "blockRating", - defaultProfileRatingAlg: "highestBlock", - - scoreRatingAlgs: ["blockRating", "highest32", "highest256"], - sessionRatingAlgs: ["blockRating", "average32Speed"], - profileRatingAlgs: ["highest32", "highestBlock", "highest256"], - - scoreRatingAlgDescriptions: { - blockRating: "How much this clear is worth.", - highest32: "The highest BPM this score streamed 32 measures straight for.", - highest256: "The highest BPM this score streamed 256 measures straight for.", - }, - profileRatingAlgDescriptions: { - highest32: "The highest BPM this user has streamed 32 unbroken measures at.", - highest256: "The highest BPM this user has streamed 256 unbroken measures at.", - highestBlock: "The highest block level this player has cleared.", - }, - sessionRatingAlgDescriptions: { - blockRating: "An average of your best 5 blsock levels cleared this session.", - average32Speed: "An average of your fastest 5 32 measure runs this session.", - }, - - // always round these - scoreRatingAlgFormatters: { - highest256: (k) => k.toFixed(0), - highest32: (k) => k.toFixed(0), - blockRating: (k) => k.toFixed(0), - }, - profileRatingAlgFormatters: { - highest256: (k) => k.toFixed(0), - highest32: (k) => k.toFixed(0), - highestBlock: (k) => k.toFixed(0), - }, - sessionRatingAlgFormatters: {}, - - // This is quirky (lol) - // ITG difficulties can be any string they want to be. We just support some - // hardcoded defaults. - difficultyOrder: ["Beginner", "Easy", "Medium", "Hard", "Challenge"], - difficultyShorthand: { - Beginner: "B", - Easy: "E", - Medium: "M", - Hard: "H", - Challenge: "C", - }, - defaultDifficulty: "Challenge", - difficultyColours: { - Beginner: COLOUR_SET.paleBlue, - Easy: COLOUR_SET.green, - Medium: COLOUR_SET.vibrantYellow, - Hard: COLOUR_SET.red, - Challenge: COLOUR_SET.pink, - }, - - orderedGrades: ["D", "C", "B", "A", "S-", "S", "S+", "★", "★★", "★★★", "★★★★"], - gradeColours: { - D: COLOUR_SET.red, - C: COLOUR_SET.maroon, - B: COLOUR_SET.purple, - A: COLOUR_SET.green, - "S-": COLOUR_SET.paleOrange, - S: COLOUR_SET.orange, - "S+": COLOUR_SET.vibrantOrange, - "★": COLOUR_SET.pink, - "★★": COLOUR_SET.vibrantPink, - "★★★": COLOUR_SET.teal, - "★★★★": COLOUR_SET.white, - }, - minimumRelevantGrade: "C", - gradeBoundaries: [0, 55, 68, 80, 89, 92, 94, 96, 98, 99, 100], - - orderedLamps: ["FAILED", "CLEAR", "FULL COMBO", "FULL EXCELLENT COMBO", "QUAD"], - lampColours: { - FAILED: COLOUR_SET.red, - CLEAR: COLOUR_SET.blue, - "FULL COMBO": COLOUR_SET.pink, - "FULL EXCELLENT COMBO": COLOUR_SET.gold, - QUAD: COLOUR_SET.white, - }, - minimumRelevantLamp: "CLEAR", - - classHumanisedFormat: {}, - classProperties: {}, - - supportsESD: false, - orderedJudgements: ["fantastic", "excellent", "great", "decent", "wayoff", "miss"], - - scoreBucket: "lamp", - - supportedVersions: [], - - tierlists: [], - tierlistDescriptions: {}, - - supportedMatchTypes: ["itgChartHash", "tachiSongID"], - }, -} as const satisfies Record; diff --git a/common/src/constants/bms-tables.test.ts b/common/src/constants/bms-tables.test.ts index 7031f313d..e5315f77a 100644 --- a/common/src/constants/bms-tables.test.ts +++ b/common/src/constants/bms-tables.test.ts @@ -4,7 +4,7 @@ import t from "tap"; t.test("BMS Tables should be unique.", (t) => { const allKeys = BMS_TABLES.map((e) => `${e.playtype}-${e.prefix}`); - t.strictSame(allKeys, [...new Set(allKeys)], "There should be no duplicate tables prefixes."); + t.strictSame(allKeys, [...new Set(allKeys)], "There should be no duplicate table prefixes."); t.end(); }); diff --git a/common/src/index.test.ts b/common/src/index.test.ts index ed41de5f8..3f346d657 100644 --- a/common/src/index.test.ts +++ b/common/src/index.test.ts @@ -5,7 +5,6 @@ import t from "tap"; t.test("Property Checks", (t) => { t.type(tachiCommon.GetGameConfig, "function"); t.type(tachiCommon.GetGamePTConfig, "function"); - t.type(tachiCommon.gameClasses, "object"); t.type(tachiCommon.COLOUR_SET, "object"); t.end(); diff --git a/common/src/index.ts b/common/src/index.ts index a893f0e84..0e6279ca6 100644 --- a/common/src/index.ts +++ b/common/src/index.ts @@ -1,8 +1,6 @@ export * from "./types"; -export * from "./config/old-config"; -export * as gameClasses from "./config/game-classes"; -export * as ESDCore from "./lib/esd"; +export * from "./config/config"; export * as StaticConfig from "./constants/import-types"; export * from "./utils/util"; export * from "./webhooks"; diff --git a/common/src/lib/schemas.ts b/common/src/lib/schemas.ts index 14cb10ae8..279715bf7 100644 --- a/common/src/lib/schemas.ts +++ b/common/src/lib/schemas.ts @@ -2,15 +2,15 @@ // their name in the database to the object they schemaify. // The schemas themselves are wrapped in functions that throw on error. -import { GetGameConfig, GetGamePTConfig } from "../config/old-config"; -import { allIDStrings, allImportTypes, allSupportedGames } from "../constants/import-types"; +import { GetGameConfig, allSupportedGames, GetGamePTConfig, allGPTStrings } from "../config/config"; +import { allImportTypes } from "../constants/import-types"; import { ALL_PERMISSIONS } from "../constants/permissions"; import { UserAuthLevels } from "../types"; import deepmerge from "deepmerge"; import { p } from "prudence"; -import type { GamePTConfig } from "../config/old-config"; -import type { AllClassSets } from "../config/game-classes"; -import type { Game, IDStrings, NotificationBody, Playtype, Playtypes } from "../types"; +import type { Game, Playtypes, Playtype } from "../types/game-config"; +import type { GamePTConfig } from "../types/internals"; +import type { NotificationBody } from "../types/notifications"; import type { PrudenceSchema, ValidationFunctionParentOptionsKeychain, @@ -219,7 +219,7 @@ const GetScoreMeta = (game: Game, playtype: Playtypes[Game]): PrudenceSchema => }; function IsValidPlaytype(game: Game, str: string): str is Playtypes[Game] { - return GetGameConfig(game).validPlaytypes.includes(str as Playtypes[Game]); + return GetGameConfig(game).playtypes.includes(str as Playtypes[Game]); } function IsValidGame(str: string): str is Game { @@ -238,7 +238,7 @@ const getPlaytype = (game: Game, self: unknown): Playtypes[Game] => { const playtype = s.playtype as string; if (!IsValidPlaytype(game, playtype)) { - throw new Error(`Expected any of ${gameConfig.validPlaytypes.join(", ")}`); + throw new Error(`Expected any of ${gameConfig.playtypes.join(", ")}`); } return playtype; @@ -811,13 +811,13 @@ const PRE_SCHEMAS = { userID: p.isPositiveNonZeroInteger, timeStarted: p.isPositive, timeFinished: p.isPositive, - idStrings: [p.isIn(allIDStrings)], + idStrings: [p.isIn(allGPTStrings)], importID: "string", scoreIDs: ["string"], game: p.isIn(games), // @ts-expect-error We've asserted this is definitely a game. - playtypes: [(self) => p.isIn(GetGameConfig(self.game).validPlaytypes)(self)], + playtypes: [(self) => p.isIn(GetGameConfig(self.game).playtypes)(self)], errors: [ { type: "string", @@ -1024,7 +1024,7 @@ const PRE_SCHEMAS = { const { game } = extractGPTIDString(self); return prSchemaFnWrap({ - idString: p.isIn(allIDStrings), + idString: p.isIn(allGPTStrings), chartDoc: PR_CHART_DOCUMENT(game), songDoc: PR_SONG_DOCUMENT(game), userIDs: [p.isPositiveNonZeroInteger], diff --git a/common/src/seeds/types.ts b/common/src/seeds/types.ts index bd12d3c46..644ab1f08 100644 --- a/common/src/seeds/types.ts +++ b/common/src/seeds/types.ts @@ -1,7 +1,8 @@ +import { allSupportedGames } from "../config/config"; import type { Game, ChartDocument, - GameToIDStrings, + GameToGPTStrings, SongDocument, BMSCourseDocument, FolderDocument, @@ -15,7 +16,7 @@ import type { // note that TS won't let you do this multiple times within an object // so, we have to join them ourselves. Ah well, not that bad. type ChartDBSeeds = { - [G in Game as `charts-${G}.json`]: Array>; + [G in Game as `charts-${G}.json`]: Array>; }; type SongDBSeeds = { @@ -34,41 +35,23 @@ interface OtherDBSeeds { export type AllDatabaseSeeds = ChartDBSeeds & OtherDBSeeds & SongDBSeeds; // Nifty trick to enforce that we always specify all database seeds :) -const CURRENT_DATABASE_SEEDS: Record = { +const CURRENT_DATABASE_SEEDS: Record = { "bms-course-lookup.json": true, - "charts-bms.json": true, - "charts-chunithm.json": true, - "charts-gitadora.json": true, - "charts-iidx.json": true, - "charts-itg.json": true, - "charts-jubeat.json": true, - "charts-maimaidx.json": true, - "charts-museca.json": true, - "charts-pms.json": true, - "charts-popn.json": true, - "charts-sdvx.json": true, - "charts-usc.json": true, - "charts-wacca.json": true, "folders.json": true, "goals.json": true, "questlines.json": true, "quests.json": true, - "songs-bms.json": true, - "songs-chunithm.json": true, - "songs-gitadora.json": true, - "songs-iidx.json": true, - "songs-itg.json": true, - "songs-jubeat.json": true, - "songs-maimaidx.json": true, - "songs-museca.json": true, - "songs-pms.json": true, - "songs-popn.json": true, - "songs-sdvx.json": true, - "songs-usc.json": true, - "songs-wacca.json": true, "tables.json": true, }; +for (const game of allSupportedGames) { + // @ts-expect-error define all games' seeds on the object. + CURRENT_DATABASE_SEEDS[`songs-${game}`] = true; + + // @ts-expect-error define all games' seeds on the object. + CURRENT_DATABASE_SEEDS[`charts-${game}`] = true; +} + export const DatabaseSeedNames = Object.keys(CURRENT_DATABASE_SEEDS) as Array< keyof AllDatabaseSeeds >; diff --git a/common/src/types.ts b/common/src/types.ts index 5705a2c90..cde496b25 100644 --- a/common/src/types.ts +++ b/common/src/types.ts @@ -12,9 +12,9 @@ export enum UserAuthLevels { ADMIN = 3, } -// export * from "./types/api"; -// export * from "./types/batch-manual"; -// export * from "./types/documents"; -// export * from "./types/game-implementations"; -// export * from "./types/import-types"; -// export * from "./types/notifications"; +export * from "./types/api"; +export * from "./types/batch-manual"; +export * from "./types/documents"; +export * from "./types/game-config"; +export * from "./types/import-types"; +export * from "./types/notifications"; diff --git a/common/src/types/documents.ts b/common/src/types/documents.ts index 7d252764f..5ae64bfa2 100644 --- a/common/src/types/documents.ts +++ b/common/src/types/documents.ts @@ -1,4 +1,26 @@ -import type { UserAuthLevels, integer } from "../types"; +import type { + ChartDocumentData, + ChartSets, + Classes, + Difficulties, + ExtractedAdditionalMetrics, + ExtractedScoreMetrics, + GPTString, + GPTStringToGame, + GPTStringToPlaytype, + Game, + Judgements, + Playtype, + Playtypes, + Preferences, + ProfileRatingAlgorithms, + ScoreMeta, + ScoreRatingAlgorithms, + SessionRatingAlgorithms, + SongDocumentData, + UserAuthLevels, + integer, +} from "../types"; import type { APIPermissions } from "./api"; import type { ImportTypes } from "./import-types"; import type { BaseNotification, NotificationBody } from "./notifications"; @@ -112,7 +134,7 @@ interface SessionScoreNewInfo { export type SessionScoreInfo = SessionScoreNewInfo | SessionScorePBInfo; -export interface SessionDocument { +export interface SessionDocument { userID: integer; sessionID: string; scoreIDs: Array; @@ -140,8 +162,8 @@ export interface ImportDocument { timeStarted: number; timeFinished: number; - // Contains an array of GPTStrings, which dictates what (game:playtype)s were involved in this import. - gptStrings: Array; + // Contains an array of GPTString, which dictates what (game:playtype)s were involved in this import. + GPTString: Array; importID: string; scoreIDs: Array; game: Game; @@ -290,12 +312,12 @@ export interface UserDocument { authLevel: UserAuthLevels; } -export interface UserGameStats { +export interface UserGameStats { userID: integer; game: GPTStringToGame[GPT]; playtype: GPTStringToPlaytype[GPT]; ratings: Partial>; - classes: Partial>; + classes: Partial; } export interface ChartTierlistInfo { @@ -304,7 +326,7 @@ export interface ChartTierlistInfo { individualDifference?: boolean; } -export interface ChartDocument { +export interface ChartDocument { chartID: string; songID: integer; level: string; @@ -312,8 +334,8 @@ export interface ChartDocument { isPrimary: boolean; difficulty: Difficulties[GPT]; playtype: GPTStringToPlaytype[GPT]; - data: ChartData[GPT]; - chartSets: Array; + data: ChartDocumentData[GPT]; + chartSets: Array; } export interface SongDocument { @@ -322,7 +344,7 @@ export interface SongDocument { artist: string; searchTerms: Array; altTitles: Array; - data: SongData[G]; + data: SongDocumentData[G]; } export interface TableDocument { @@ -391,22 +413,17 @@ export type QuestSubscriptionDocument = { } ); -export interface ScoreDocument { +export type ScoreData = ExtractedScoreMetrics[GPT] & { + judgements: Partial>; + additionalMetrics: Partial; +}; + +export interface ScoreDocument { service: string; game: GPTStringToGame[GPT]; playtype: GPTStringToPlaytype[GPT]; userID: integer; - scoreData: { - score: number; - lamp: Lamps[GPT]; - percent: number; - grade: Grades[GPT]; - lampIndex: integer; - gradeIndex: integer; - esd: number | null; - judgements: Partial>; - additionalMetrics: Partial; - }; + scoreData: ScoreData; scoreMeta: Partial; calculatedData: Partial>; timeAchieved: integer | null; @@ -425,7 +442,7 @@ export interface PBScoreComposedReference { scoreID: string; } -export interface PBScoreDocument { +export interface PBScoreDocument { composedFrom: { scorePB: string; lampPB: string; @@ -449,17 +466,7 @@ export interface PBScoreDocument { highlight: boolean; isPrimary: boolean; timeAchieved: number | null; - scoreData: { - score: number; - lamp: Lamps[GPT]; - percent: number; - grade: Grades[GPT]; - lampIndex: integer; - gradeIndex: integer; - esd: number | null; - judgements: Partial>; - additionalMetrics: Partial; - }; + scoreData: ScoreData; calculatedData: Partial>; } @@ -479,7 +486,7 @@ export interface ImportProcessInfoInvalidDatapoint { content: Record; } -export interface ImportProcessInfoScoreImported { +export interface ImportProcessInfoScoreImported { success: true; type: "ScoreImported"; message: string; @@ -500,13 +507,14 @@ export interface ImportProcessInfoSongOrChartNotFound { type: "SongOrChartNotFound"; message: string; content: { + // these are too complex to type. Not bothering. data: unknown; - context: unknown; // @TODO Type these properly. + context: unknown; orphanID: string; }; } -export type ImportProcessingInfo = +export type ImportProcessingInfo = | ImportProcessInfoInternalError | ImportProcessInfoInvalidDatapoint | ImportProcessInfoOrphanExists @@ -582,7 +590,7 @@ export interface ShowcaseStatChart { property: "grade" | "lamp" | "percent" | "playcount" | "score"; } -export interface UGPTSettingsDocument { +export interface UGPTSettingsDocument { userID: integer; game: GPTStringToGame[GPT]; playtype: GPTStringToPlaytype[GPT]; @@ -594,12 +602,12 @@ export interface UGPTSettingsDocument { scoreBucket: "grade" | "lamp" | null; defaultTable: string | null; preferredRanking: "global" | "rival" | null; - gameSpecific: UGPTSpecificPreferences[GPT]; + gameSpecific: Preferences[GPT]; }; rivals: Array; } -export interface UserGameStatsSnapshotDocument +export interface UserGameStatsSnapshotDocument extends UserGameStats { rankings: Record; playcount: integer; @@ -641,7 +649,7 @@ export interface KsHookSettingsDocument { forceStaticImport: boolean; } -export interface OrphanChartDocument { +export interface OrphanChartDocument { gptString: GPT; chartDoc: ChartDocument; songDoc: SongDocument; @@ -650,16 +658,16 @@ export interface OrphanChartDocument { export interface ClassDelta { game: Game; - set: AllClassSets; + set: Classes[GPTString]; playtype: Playtype; old: integer | null; new: integer; } -export interface ClassAchievementDocument { +export interface ClassAchievementDocument { game: GPTStringToGame[GPT]; playtype: GPTStringToPlaytype[GPT]; - classSet: AllClassSets; + classSet: Classes[GPT]; classOldValue: integer | null; classValue: integer; timeAchieved: number; diff --git a/common/src/types/game-config.ts b/common/src/types/game-config.ts index c05611bff..e2e187f57 100644 --- a/common/src/types/game-config.ts +++ b/common/src/types/game-config.ts @@ -7,7 +7,7 @@ import type { } from "./game-config-utils"; import type { ExtractEnumMetricNames, ExtractMetrics } from "./metrics"; import type { ExtractArrayElementType } from "./utils"; -import type { z } from "zod"; +import type { AnyZodObject, z } from "zod"; /** * All the games Tachi supports. @@ -30,7 +30,7 @@ export type Game = keyof typeof GAME_CONFIGS; * is the go-to. */ export type Playtypes = { - [G in Game]: typeof GAME_CONFIGS[G]["validPlaytypes"][number]; + [G in Game]: typeof GAME_CONFIGS[G]["playtypes"][number]; }; /** @@ -49,13 +49,13 @@ export type SongDocumentData = { export interface GameConfig { readonly name: string; readonly defaultPlaytype: Playtypes[G]; - readonly validPlaytypes: ReadonlyArray; + readonly playtypes: ReadonlyArray; /** * Song documents get their own game-specific record that they use for whatever * they want. IIDX song documents store genres, etc. */ - readonly songData: SongDocumentData[G]; + readonly songData: AnyZodObject; } /** @@ -71,7 +71,7 @@ export type GPTString = keyof { [G in Game as `${G}:${Playtypes[G]}`]: never; }; -export type GameToGPTStrings = { +export type GPTStrings = { [G in Game]: `${G}:${Playtypes[G]}`; }; @@ -145,7 +145,7 @@ export type ExtractedClasses = { }; export type Classes = { - [G in GPTString]: typeof GAME_PT_CONFIGS[G]["classes"]; + [G in GPTString]: keyof typeof GAME_PT_CONFIGS[G]["classes"]; }; export type ChartDocumentData = { @@ -357,13 +357,16 @@ export interface SpecificGamePTConfig { * Chart documents get their own GPT-specific record that they use for whatever * they want. IIDX documents store BPI information like kaiden averages, BMS * charts store sha256/md5 hashes, etc. + * + * This is a zod schema that can be used to validate that input. */ - chartData: ChartDocumentData[GPT]; + chartData: AnyZodObject; /** - * What game-specific user-settings exist for this GPT? + * This is a zod schema that can be used to validate provided GPT-specific + * preferences. */ - preferences: Preferences[GPT]; + preferences: AnyZodObject; /** * What game-specific metadata should be stored on scores for this GPT? @@ -371,7 +374,7 @@ export interface SpecificGamePTConfig { * These are for things like what options were used (RANDOM, MIRROR etc.) * and don't exist on PBs. */ - scoreMeta: ScoreMeta[GPT]; + scoreMeta: AnyZodObject; /** * What "matchTypes" should this game support for batch-manual imports? This diff --git a/common/src/types/internals.ts b/common/src/types/internals.ts index 5a1e5f5a3..64047e6db 100644 --- a/common/src/types/internals.ts +++ b/common/src/types/internals.ts @@ -56,7 +56,7 @@ export type GamePTConfig = Readonly<{ */ export type INTERNAL_GAME_CONFIG = Readonly<{ name: string; - validPlaytypes: ReadonlyArray; + playtypes: ReadonlyArray; defaultPlaytype: PT; songData: AnyZodObject; }>; diff --git a/common/src/utils/util.ts b/common/src/utils/util.ts index 07b9f4ae7..52d53d939 100644 --- a/common/src/utils/util.ts +++ b/common/src/utils/util.ts @@ -1,6 +1,16 @@ -import { GetGameConfig, GetGamePTConfig } from "../config/old-config"; -import type { ChartDocument, Game, IDStrings, Playtypes, SongDocument } from ".."; -import type { Grades, integer, PBScoreDocument } from "../types"; +import { GetGameConfig, GetGamePTConfig, GetSpecificGPTConfig } from "../config/config"; +import type { + integer, + PBScoreDocument, + ChartDocument, + Game, + Playtypes, + SongDocument, + GameToGPTStrings, + SpecificGamePTConfig, + GPTString, + GPTStrings, +} from "../types"; import type { PrudenceError } from "prudence"; export function FormatInt(v: number): string { @@ -23,9 +33,21 @@ export function FormatDifficulty(chart: ChartDocument, game: Game): string { } if (game === "gitadora") { - const gptConfig = GetGamePTConfig(game, chart.playtype); + const ch = chart as ChartDocument; - const shortDiff = gptConfig.shortDifficulties[chart.difficulty] ?? chart.difficulty; + const gptConfig = GetSpecificGPTConfig( + game, + chart.playtype as Playtypes["gitadora"] + ); + + // @ts-expect-error maybe this new config format was a mistake. + // it's complaining that since the dora config doesn't have shorthand for + // "BASS BASIC", this assignment may fail. + // it's technically correct, but in the worst way, since this isn't + // actually possible. + // todo: come up with something better. + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const shortDiff = gptConfig.difficultyConfig.difficultyShorthand[ch.difficulty]; // gitadora should always use short diffs. they just look better. return `${shortDiff} ${chart.level}`; @@ -33,7 +55,7 @@ export function FormatDifficulty(chart: ChartDocument, game: Game): string { const gameConfig = GetGameConfig(game); - if (gameConfig.validPlaytypes.length > 1) { + if (gameConfig.playtypes.length > 1) { return `${chart.playtype} ${chart.difficulty} ${chart.level}`; } @@ -54,9 +76,15 @@ export function FormatDifficultyShort(chart: ChartDocument, game: Game): string return `S${itgChart.data.difficultyTag} ${chart.level}`; } - const shortDiff = gptConfig.shortDifficulties[chart.difficulty] ?? chart.difficulty; + if (gptConfig.difficultyConfig.type === "DYNAMIC") { + // TODO cap string length + return `${chart.difficulty} ${chart.level}`; + } - if (gameConfig.validPlaytypes.length === 1 || game === "gitadora") { + const shortDiff = + gptConfig.difficultyConfig.difficultyShorthand[chart.difficulty] ?? chart.difficulty; + + if (gameConfig.playtypes.length === 1 || game === "gitadora") { return `${shortDiff} ${chart.level}`; } @@ -70,7 +98,7 @@ export function FormatDifficultyShort(chart: ChartDocument, game: Game): string export function FormatGame(game: Game, playtype: Playtypes[Game]): string { const gameConfig = GetGameConfig(game); - if (gameConfig.validPlaytypes.length === 1) { + if (gameConfig.playtypes.length === 1) { return gameConfig.name; } @@ -84,7 +112,7 @@ export function FormatChart( short = false ): string { if (game === "bms") { - const tables = (chart as ChartDocument<"bms:7K" | "bms:14K">).data.tableFolders; + const tables = (chart as ChartDocument).data.tableFolders; const bmsSong = song as SongDocument<"bms">; @@ -104,7 +132,7 @@ export function FormatChart( return `${realTitle} (${tables.map((e) => `${e.table}${e.level}`).join(", ")})`; } else if (game === "usc") { - const uscChart = chart as ChartDocument<"usc:Controller" | "usc:Keyboard">; + const uscChart = chart as ChartDocument; // If this chart isn't an official, render it differently if (!uscChart.data.isOfficial) { @@ -136,15 +164,19 @@ export function FormatChart( let playtypeStr = `${chart.playtype}`; - if (gameConfig.validPlaytypes.length === 1) { + if (gameConfig.playtypes.length === 1) { playtypeStr = ""; } const gptConfig = GetGamePTConfig(game, chart.playtype); - const diff = short - ? gptConfig.shortDifficulties[chart.difficulty] ?? chart.difficulty - : chart.difficulty; + let diff: string; + + if (gptConfig.difficultyConfig.type === "DYNAMIC") { + diff = chart.difficulty; + } else { + diff = gptConfig.difficultyConfig.difficultyShorthand[chart.difficulty] ?? chart.difficulty; + } // iidx formats things like SPA instead of SP A. // this is a hack, this should be part of the gptConfig, tbh. @@ -156,16 +188,16 @@ export function FormatChart( space = " "; } - // return the most recent version this chart appeared in if it + // return the most recent chartSet this chart appeared in if it // is not primary. if (!chart.isPrimary) { - return `${song.title} (${playtypeStr}${space}${diff} ${chart.level} ${chart.versions[0]})`; + return `${song.title} (${playtypeStr}${space}${diff} ${chart.level} ${chart.chartSets[0]})`; } return `${song.title} (${playtypeStr}${space}${diff} ${chart.level})`; } -export function AbsoluteGradeDelta( +export function AbsoluteGradeDelta( game: Game, playtype: Playtypes[Game], score: number, @@ -190,12 +222,12 @@ export function AbsoluteGradeDelta( return score - gradeScore; } -export function RelativeGradeDelta( +export function RelativeGradeDelta( game: Game, playtype: Playtypes[Game], score: number, percent: number, - grade: Grades[I], + grade: Grades[GPT], relativeIndex: integer ): { grade: string; delta: number } | null { const gptConfig = GetGamePTConfig(game, playtype); @@ -240,7 +272,7 @@ type FormatGradeDeltaReturns = closer: "lower"; }; -export function GenericFormatGradeDelta( +export function GenericFormatGradeDelta( game: Game, playtype: Playtypes[Game], score: number, @@ -278,7 +310,7 @@ export function GenericFormatGradeDelta( }; } -export function GetCloserGradeDelta( +export function GetCloserGradeDelta( game: Game, playtype: Playtypes[Game], score: number, @@ -315,7 +347,7 @@ export function CreateSongMap(songs: Array(charts: Array>) { +export function CreateChartMap(charts: Array>) { const chartMap = new Map>(); for (const chart of charts) { @@ -395,8 +427,8 @@ export function GradeGoalFormatter(pb: PBScoreDocument) { // For games with 'BP', show that next to the clear. export function IIDXBMSLampGoalFormatter(pb: PBScoreDocument) { - if (typeof pb.scoreData.hitMeta.bp === "number") { - return `${pb.scoreData.lamp} (BP: ${pb.scoreData.hitMeta.bp})`; + if (typeof pb.scoreData.additionalMetrics.bp === "number") { + return `${pb.scoreData.lamp.string} (BP: ${pb.scoreData.additionalMetrics.bp})`; } return pb.scoreData.lamp; diff --git a/server/src/lib/score-import/framework/score-importing/score-import-main.ts b/server/src/lib/score-import/framework/score-importing/score-import-main.ts index ac0662984..e1563deca 100644 --- a/server/src/lib/score-import/framework/score-importing/score-import-main.ts +++ b/server/src/lib/score-import/framework/score-importing/score-import-main.ts @@ -392,7 +392,7 @@ async function UpdateUsersGameStats( // Instead of using the provided playtypes, run the classHandler on all // playtypes. This should only happen if a classHandler is provided, and is // a hack fix for things like #480. - const allPlaytypes = GetGameConfig(game).validPlaytypes; + const allPlaytypes = GetGameConfig(game).playtypes; const playtypes = classHandler ? allPlaytypes : modifiedPlaytypes; diff --git a/server/src/lib/score-import/import-types/common/batch-manual/parser.ts b/server/src/lib/score-import/import-types/common/batch-manual/parser.ts index deb4db144..f9c1340b7 100644 --- a/server/src/lib/score-import/import-types/common/batch-manual/parser.ts +++ b/server/src/lib/score-import/import-types/common/batch-manual/parser.ts @@ -71,7 +71,7 @@ export function ParseBatchManualFromObject( if (!(typeof maybePlaytype === "string" && IsValidPlaytype(game, maybePlaytype))) { throw new ScoreImportFatalError( 400, - `Invalid playtype '${maybePlaytype}' - expected any of ${gameConfig.validPlaytypes.join( + `Invalid playtype '${maybePlaytype}' - expected any of ${gameConfig.playtypes.join( ", " )}.` ); diff --git a/server/src/server/router/api/v1/activity/router.ts b/server/src/server/router/api/v1/activity/router.ts index 7376d0a15..f382ef436 100644 --- a/server/src/server/router/api/v1/activity/router.ts +++ b/server/src/server/router/api/v1/activity/router.ts @@ -29,7 +29,7 @@ router.get("/", async (req, res) => { const gpts = []; for (const game of TachiConfig.GAMES) { - const playtypes = GetGameConfig(game).validPlaytypes; + const playtypes = GetGameConfig(game).playtypes; for (const playtype of playtypes) { gpts.push({ game, playtype, query: {} }); diff --git a/server/src/server/router/api/v1/games/_game/_playtype/middleware.ts b/server/src/server/router/api/v1/games/_game/_playtype/middleware.ts index 914c7d05a..3667fef40 100644 --- a/server/src/server/router/api/v1/games/_game/_playtype/middleware.ts +++ b/server/src/server/router/api/v1/games/_game/_playtype/middleware.ts @@ -8,7 +8,7 @@ export const ValidatePlaytypeFromParam: RequestHandler = (req, res, next) => { const gameConfig = GetGameConfig(game); - if (!gameConfig.validPlaytypes.includes(req.params.playtype as Playtype)) { + if (!gameConfig.playtypes.includes(req.params.playtype as Playtype)) { return res.status(400).json({ success: false, description: `The playtype ${req.params.playtype} is not supported.`, @@ -25,7 +25,7 @@ export const ValidatePlaytypeFromParamFor = (req, res, next) => { const gameConfig = GetGameConfig(game); - if (!gameConfig.validPlaytypes.includes(req.params.playtype as Playtype)) { + if (!gameConfig.playtypes.includes(req.params.playtype as Playtype)) { return res.status(400).json({ success: false, description: `The playtype ${req.params.playtype} is not supported.`, diff --git a/server/src/utils/calculations/recalc-scores.ts b/server/src/utils/calculations/recalc-scores.ts index c6f09ebc1..e277014a1 100644 --- a/server/src/utils/calculations/recalc-scores.ts +++ b/server/src/utils/calculations/recalc-scores.ts @@ -100,7 +100,7 @@ export async function UpdateAllPBs(userIDs?: Array, filter = {}) { for (const game of TachiConfig.GAMES) { const gameConfig = GetGameConfig(game); - for (const playtype of gameConfig.validPlaytypes) { + for (const playtype of gameConfig.playtypes) { const scores = await db.scores.find( deepmerge({ userID: user.id, game, playtype }, filter), { diff --git a/server/src/utils/misc.ts b/server/src/utils/misc.ts index d5bb5f194..57adc1337 100644 --- a/server/src/utils/misc.ts +++ b/server/src/utils/misc.ts @@ -79,7 +79,7 @@ export function IsValidGame(str: string): str is Game { } export function IsValidPlaytype(game: Game, str: string): str is Playtype { - return GetGameConfig(game).validPlaytypes.includes(str as Playtype); + return GetGameConfig(game).playtypes.includes(str as Playtype); } export function IsValidScoreAlg(