diff --git a/common/src/config/game-support/iidx.ts b/common/src/config/game-support/iidx.ts index 44ae84e3b..1bad6c74e 100644 --- a/common/src/config/game-support/iidx.ts +++ b/common/src/config/game-support/iidx.ts @@ -1,4 +1,5 @@ import { FAST_SLOW_MAXCOMBO } from "./_common"; +import { ExtractMetrics } from "../../types/metrics"; import { ClassValue } from "../config-utils"; import type { INTERNAL_GAME_CONFIG, diff --git a/common/src/types/game-support.ts b/common/src/types/game-support.ts index fe915bc1c..0c616b159 100644 --- a/common/src/types/game-support.ts +++ b/common/src/types/game-support.ts @@ -1,6 +1,6 @@ import type { GAME_CONFIGS, GAME_PT_CONFIGS } from "../config/config"; import type { FixedDifficulties } from "./_TEMPNAME-game-config-inner"; -import type { ExtractMetrics } from "./metrics"; +import type { ExtractEnumMetricNames, ExtractMetrics } from "./metrics"; import type { ExtractArrayElementType } from "./utils"; /** @@ -93,12 +93,30 @@ export type ProfileRatingAlgorithms = { [G in GPTString]: keyof typeof GAME_PT_CONFIGS[G]["profileRatingAlgs"]; }; -export type ScoreMetrics = { +export type ProvidedMetrics = { + [G in GPTString]: typeof GAME_PT_CONFIGS[G]["providedMetrics"]; +}; + +export type DerivedMetrics = { + [G in GPTString]: typeof GAME_PT_CONFIGS[G]["derivedMetrics"]; +}; + +export type AdditionalMetrics = { + [G in GPTString]: typeof GAME_PT_CONFIGS[G]["additionalMetrics"]; +}; + +/** + * What metrics are available on a score for this GPT? This includes derivedMetrics + * and providedMetrics. + */ +export type ExtractedScoreMetrics = { [G in GPTString]: ExtractMetrics & ExtractMetrics; }; -const m: ScoreMetrics["iidx:SP"] = {}; +export type ExtractedAdditionalMetrics = { + [G in GPTString]: ExtractMetrics; +}; /** * Configuration for a GPT. This declares *almost everything* about how this game is @@ -115,7 +133,7 @@ export interface GamePTConfig { * This is intended for things like Score, Lamp, etc. Things that quite fundamentally * *are* the metrics of the score. */ - providedMetrics: Record; + providedMetrics: ProvidedMetrics[GPT]; /** * What metrics do we want to exist on score documents, but don't need to be @@ -137,7 +155,7 @@ export interface GamePTConfig { * Another good example would be "Grade" for most games, as a grade is often just * cutoffs applied on score values. */ - derivedMetrics: Record; + derivedMetrics: DerivedMetrics[GPT]; /** * What's the default metric for this GPT? @@ -146,7 +164,7 @@ export interface GamePTConfig { * * @note This **MUST** be one of the mandatory or derived keys. */ - defaultMetric: string; + defaultMetric: keyof DerivedMetrics[GPT] | keyof ProvidedMetrics[GPT]; /** * What's the preferred default enum for this GPT? @@ -156,7 +174,7 @@ export interface GamePTConfig { * * @note This **MUST** be one of the mandatory or derived keys. */ - preferredDefaultEnum: string; + preferredDefaultEnum: ExtractEnumMetricNames; /** * What metrics *can* we store about scores, but don't necessarily *need*? @@ -299,3 +317,8 @@ export interface GamePTConfig { */ supportedMatchTypes: ReadonlyArray; } + +const gptConf: ExtractEnumMetricNames = { + lamp: "a", + asdf: 213, +}; diff --git a/common/src/types/metrics.ts b/common/src/types/metrics.ts index d92727a5a..e07fa0c21 100644 --- a/common/src/types/metrics.ts +++ b/common/src/types/metrics.ts @@ -54,11 +54,29 @@ export type ExtractMetricType = M extends DecimalScoreMet : M extends IntegerScoreMetric ? integer : M extends EnumScoreMetric - ? M["values"][number] + ? { + string: M["values"][number]; + index: integer; // technically incorrect, but whatever + } : M extends GraphScoreMetric ? Array : never; +/** + * Extract all the names of enum types from this record of score metrics. + * + * @example + * ExtractEnumMetricNames<{ score: { type: "INTEGER" } }, grade: { type: "ENUM" ... }> + * would return a type of "grade" + */ +export type ExtractEnumMetricNames> = Omit< + R, + keyof { + // vvvv this is stupid + [K in keyof R]: R[K] extends EnumScoreMetric ? never : K; + } +>; + type PossibleMetrics = ExtractMetricType; /**