master @ 471 LINES
[ HISTORY ] [ UP ]
┌─ TS ───────────────────────────────────────────────────────────────────────┐
│ // core data types for the application │
│ export interface Player { │
│ id: number; │
│ player_id?: number; │
│ name: string; │
│ realm_slug: string; │
│ realm_name: string; │
│ region: string; │
│ class_name: string; │
│ active_spec_name: string; │
│ main_spec_id?: number; │
│ race_name?: string; │
│ gender?: string; │
│ guild_name?: string; │
│ level?: number; │
│ average_item_level?: number; │
│ equipped_item_level?: number; │
│ avatar_url?: string; │
│ global_ranking?: number; │
│ regional_ranking?: number; │
│ realm_ranking?: number; │
│ global_ranking_bracket?: string; │
│ regional_ranking_bracket?: string; │
│ realm_ranking_bracket?: string; │
│ ranking_percentile?: string; // contextual bracket based on leaderboard scope │
│ combined_best_time?: number; │
│ dungeons_completed?: number; │
│ total_runs?: number; │
│ } │
│ │
│ export interface TeamMember { │
│ id: number; │
│ name: string; │
│ spec_id: number; │
│ faction: string; │
│ realm_slug: string; │
│ region: string; │
│ } │
│ │
│ export interface ChallengeRun { │
│ id: number; │
│ duration: number; │
│ completed_timestamp: number; │
│ keystone_level: number; │
│ dungeon_name: string; │
│ realm_name: string; │
│ region: string; │
│ ranking?: number; │
│ percentile_bracket?: string; │
│ ranking_percentile?: string; // contextual bracket based on leaderboard scope │
│ members: TeamMember[]; │
│ } │
│ │
│ export interface BestRun { │
│ dungeon_id: number; │
│ dungeon_name: string; │
│ dungeon_slug: string; │
│ duration: number; │
│ global_ranking?: number; │
│ global_ranking_filtered?: number; │
│ regional_ranking?: number; │
│ regional_ranking_filtered?: number; │
│ realm_ranking?: number; │
│ realm_ranking_filtered?: number; │
│ percentile_bracket?: string; │
│ global_percentile_bracket?: string; │
│ regional_percentile_bracket?: string; │
│ realm_percentile_bracket?: string; │
│ completed_timestamp: number; │
│ keystone_level: number; │
│ all_members: TeamMember[]; │
│ } │
│ │
│ export interface Equipment { │
│ [slot: string]: EquipmentItem; │
│ } │
│ │
│ export interface ScalingOption { │
│ stats?: Record<string, number>; │
│ ilvl?: number; │
│ weaponDamageMin?: number; │
│ weaponDamageMax?: number; │
│ } │
│ │
│ export interface EquipmentItem { │
│ id: number; │
│ slot_type: string; │
│ item_id: number; │
│ item_name: string; │
│ quality: string; │
│ item_icon_slug?: string; │
│ enchantments?: Enchantment[]; │
│ scaling_options?: Record<string, ScalingOption>; │
│ } │
│ │
│ export interface Enchantment { │
│ enchantment_id: number; │
│ slot_id: number; │
│ slot_type?: string; │
│ display_string: string; │
│ source_item_id?: number; │
│ gem_icon_slug?: string; │
│ gem_name?: string; │
│ } │
│ │
│ export interface LeaderboardData { │
│ leading_groups: ChallengeRun[]; │
│ pagination: { │
│ currentPage: number; │
│ pageSize: number; │
│ totalPages: number; │
│ hasNextPage: boolean; │
│ hasPrevPage: boolean; │
│ totalRuns: number; │
│ }; │
│ } │
│ │
│ export interface PlayerLeaderboardData { │
│ leaderboard: Player[]; │
│ pagination: { │
│ currentPage: number; │
│ pageSize: number; │
│ totalPages: number; │
│ hasNextPage: boolean; │
│ hasPrevPage: boolean; │
│ totalPlayers: number; │
│ totalRuns: number; │
│ }; │
│ } │
│ │
│ // Per-account row from /api/leaderboard/season/{N}/accounts/... │
│ // Used by both the per-season combined-time account leaderboard and the │
│ // cross-season account total-runs leaderboard. Combined-time-specific fields │
│ // (bracket, account_combined_best_time, dungeons_completed, per_dungeon_best) │
│ // are optional so the type covers both feeds. │
│ export interface AccountLeaderboardEntry { │
│ rank: number; │
│ bracket?: string; // artifact | excellent | legendary | epic | rare | uncommon | │
│ common │
│ account_id: number; │
│ region: string; │
│ account_combined_best_time?: number; │
│ dungeons_completed?: number; │
│ total_runs: number; │
│ character_count?: number; │
│ main: AccountCharSummary; │
│ alts: AccountCharSummary[]; │
│ // dungeon_id (string) -> per-dungeon best inside this account │
│ per_dungeon_best?: Record<string, AccountPerDungeonBest>; │
│ } │
│ │
│ export interface AccountCharSummary { │
│ player_id: number; │
│ name: string; │
│ realm_slug: string; │
│ realm_name?: string; │
│ region: string; │
│ class_name?: string; │
│ active_spec_name?: string; │
│ main_spec_id?: number; │
│ combined_best_time?: number; │
│ total_runs?: number; │
│ has_full_coverage?: boolean; │
│ } │
│ │
│ export interface AccountPerDungeonBest { │
│ duration_ms: number; │
│ by_character: string; │
│ by_character_realm: string; │
│ } │
│ │
│ export interface AccountLeaderboardData { │
│ leaderboard: AccountLeaderboardEntry[]; │
│ title?: string; │
│ pagination: { │
│ currentPage: number; │
│ pageSize: number; │
│ totalPages: number; │
│ hasNextPage: boolean; │
│ hasPrevPage: boolean; │
│ totalAccounts: number; │
│ totalRuns: number; // legacy compat for shared Pagination component │
│ }; │
│ } │
│ │
│ export interface PlayerSeasonData { │
│ main_spec_id?: number; │
│ dungeons_completed: number; │
│ total_runs: number; │
│ combined_best_time?: number; │
│ global_ranking?: number; │
│ regional_ranking?: number; │
│ realm_ranking?: number; │
│ global_ranking_bracket?: string; │
│ regional_ranking_bracket?: string; │
│ realm_ranking_bracket?: string; │
│ last_updated?: number; │
│ best_runs: Record<string, BestRun>; │
│ } │
│ │
│ // Per-season account totals + rankings. Mirrors PlayerSeasonData stats but │
│ // for the whole account (sum across all alts, ranked among other accounts). │
│ // Keep in sync with `AccountSeasonJSON` in nix/.../generator/players.go. │
│ export interface AccountSeasonData { │
│ account_id: number; │
│ combined_best_time?: number; │
│ dungeons_completed: number; │
│ total_runs: number; │
│ character_count: number; │
│ has_full_coverage: boolean; │
│ global_ranking?: number; │
│ regional_ranking?: number; │
│ realm_ranking?: number; │
│ global_ranking_bracket?: string; │
│ regional_ranking_bracket?: string; │
│ realm_ranking_bracket?: string; │
│ region?: string; │
│ realm_slug?: string; // main char's parent realm │
│ realm_name?: string; │
│ main_player_id?: number; │
│ } │
│ │
│ export interface PlayerWithSeasons { │
│ id: number; │
│ name: string; │
│ realm_slug: string; │
│ realm_name: string; │
│ region: string; │
│ class_name?: string; │
│ active_spec_name?: string; │
│ race_name?: string; │
│ avatar_url?: string; │
│ guild_name?: string; │
│ average_item_level?: number; │
│ equipped_item_level?: number; │
│ all_time_total_runs?: number; │
│ seasons: Record<string, PlayerSeasonData>; │
│ alts?: AccountCharSummary[]; │
│ account?: Record<string, AccountSeasonData>; │
│ // Cross-season sum of total_runs across every alt on the account. Same on │
│ // every alt's profile and matches the value the Total Runs leaderboard │
│ // ranks accounts by. │
│ account_lifetime_total_runs?: number; │
│ } │
│ │
│ export interface PlayerProfileData { │
│ player: PlayerWithSeasons | null; │
│ equipment: Equipment; │
│ generated_at: number; │
│ version: string; │
│ } │
│ │
│ // API Response types │
│ export interface APIResponse<T> { │
│ data?: T; │
│ error?: string; │
│ } │
│ │
│ // mirror nix/pkgs/ookstats/src/internal/generator/home.go - keep in sync │
│ │
│ export interface HomeRunEntry { │
│ rank?: number; │
│ bracket?: string; │
│ run_id: number; │
│ dungeon_id: number; │
│ dungeon_name: string; │
│ dungeon_slug: string; │
│ duration_ms: number; │
│ completed_timestamp: number; │
│ // Only set on entries in `recent_top_runs` (cross-season feed): │
│ season_id?: number; │
│ rankings?: { global?: number }; │
│ team_members: TeamMember[]; │
│ } │
│ │
│ export interface HomePlayerEntry { │
│ rank: number; │
│ player_id: number; │
│ name: string; │
│ realm_slug: string; │
│ realm_name?: string; │
│ region: string; │
│ class_name?: string; │
│ active_spec_id?: number; │
│ active_spec_name?: string; │
│ combined_best_time_ms: number; │
│ global_ranking?: number; │
│ global_ranking_bracket?: string; │
│ regional_ranking?: number; │
│ regional_ranking_bracket?: string; │
│ avatar_url?: string; │
│ } │
│ │
│ // mirror nix/pkgs/ookstats/src/internal/generator/stats.go - keep in sync │
│ │
│ export interface StatsJSON { │
│ generated_at: number; │
│ // Outer key: region ("global" | "us" | "eu" | "kr" | "tw"). │
│ // Inner key: season key ("all_time" | "season_1" | "season_2"). │
│ scopes: Record<string, Record<string, StatsScope>>; │
│ } │
│ │
│ export interface StatsScope { │
│ total_runs: number; │
│ total_players: number; │
│ nine_of_nine_players: number; │
│ completion_tiers: { │
│ "9_of_9_gold": StatsCompletionTier; │
│ "9_of_9_platinum": StatsCompletionTier; │
│ "9_of_9_title": StatsCompletionTier; │
│ }; │
│ spec_counts: Record<string, StatsSpecCountBucket>; // keys: "all_runs" | "gold_r │
│ uns" | "platinum_runs" | "title_runs" | "top_50_runs" │
│ weekly_activity: StatsWeeklyActivityEntry[]; │
│ } │
│ │
│ export interface StatsSpecCountBucket { │
│ // Distinct runs in this bucket (denominator for the "runs with spec" metric). │
│ total_runs: number; │
│ entries: StatsSpecCountEntry[]; │
│ // per-dungeon breakdown, keyed by numeric dungeon_id │
│ by_dungeon: Record<string, StatsDungeonSpecBucket>; │
│ } │
│ │
│ export interface StatsDungeonSpecBucket { │
│ total_runs: number; │
│ entries: StatsSpecCountEntry[]; │
│ } │
│ │
│ export interface StatsCompletionTier { │
│ count: number; │
│ percentile_of_all_players: number; │
│ percentile_of_completed_players: number; │
│ percentile_of_all_time_players: number; │
│ } │
│ │
│ export interface StatsSpecCountEntry { │
│ spec_id: number; │
│ class_name: string; │
│ spec_name: string; │
│ // Total spec slot occurrences (e.g. 2 Combat Rogues in one run = 2). │
│ count: number; │
│ // Distinct runs containing this spec (e.g. 2 Combat Rogues in one run = 1). │
│ runs_with_spec: number; │
│ } │
│ │
│ // gear.json - mirror nix/.../generator/gear.go, keep in sync │
│ export interface GearJSON { │
│ generated_at: number; │
│ // Outer key: season key ("season_1" | "season_2"). Inner key: spec_id (string). │
│ scopes: Record<string, Record<string, GearSpecBucket>>; │
│ } │
│ │
│ export interface GearSpecBucket { │
│ // Number of qualifying players whose gear contributed to this bucket. │
│ total_players: number; │
│ // Keyed by canonical slot name (HEAD, CHEST, FINGER, TRINKET, ...). │
│ slots: Record<string, GearSlotBucket>; │
│ } │
│ │
│ export interface GearSlotBucket { │
│ // Number of qualifying players who had any item in this slot. │
│ players_with_slot: number; │
│ items: GearItemEntry[]; │
│ } │
│ │
│ export interface GearItemEntry { │
│ item_id: number; │
│ name: string; │
│ icon?: string; │
│ quality: number; │
│ count: number; │
│ } │
│ │
│ export interface StatsWeeklyActivityEntry { │
│ week_start: string; // ISO date or YYYY-MM-DD │
│ run_count: number; │
│ } │
│ │
│ // frontend component props │
│ export interface LeaderboardTableProps { │
│ initialData?: LeaderboardData; │
│ region: string; │
│ realm: string; │
│ dungeon: string; │
│ } │
│ │
│ export interface PlayerSearchProps { │
│ onPlayerSelect: (player: Player) => void; │
│ } │
│ │
│ export interface FilterPanelProps { │
│ initialRegion?: string; │
│ initialRealm?: string; │
│ initialDungeon?: string; │
│ onFilterChange: (filters: FilterState) => void; │
│ } │
│ │
│ export interface FilterState { │
│ region: string; │
│ realm: string; │
│ dungeon: string; │
│ teamFilter: boolean; │
│ } │
│ │
│ // player Search types │
│ export interface PlayerSearchResult { │
│ id: number; │
│ name: string; │
│ realm_slug: string; │
│ realm_name: string; │
│ region: string; │
│ class_name: string; │
│ active_spec_name: string; │
│ global_ranking?: number; │
│ regional_ranking?: number; │
│ realm_ranking?: number; │
│ global_ranking_bracket?: string; │
│ regional_ranking_bracket?: string; │
│ realm_ranking_bracket?: string; │
│ combined_best_time?: number; │
│ last_seen?: string; │
│ } │
│ │
│ export interface PlayerSearchIndex { │
│ players: PlayerSearchResult[]; │
│ metadata: { │
│ total_players: number; │
│ last_updated: string; │
│ version: string; │
│ }; │
│ } │
│ │
│ export interface FuseSearchResult<T> { │
│ item: T; │
│ refIndex: number; │
│ score?: number; │
│ } │
│ │
│ // Status page types │
│ export type CoverageHealth = "ok" | "some_missing" | "no_data"; │
│ │
│ export interface DungeonCoverage { │
│ dungeon_id: number; │
│ dungeon_slug: string; │
│ dungeon_name: string; │
│ status: CoverageHealth; │
│ periods: number[]; │
│ missing_periods: number[]; │
│ error_periods: number[]; │
│ } │
│ │
│ export interface RealmCoverage { │
│ region: string; │
│ realm_slug: string; │
│ realm_name: string; │
│ health: CoverageHealth; │
│ total_periods: number; │
│ missing_periods: number; │
│ error_periods: number; │
│ dungeons: DungeonCoverage[]; │
│ } │
│ │
│ export interface StatusApiResponse { │
│ generated_at: string; │
│ realms: RealmCoverage[]; │
│ } │
│ │
│ export interface RealmStatusApiResponse { │
│ generated_at: string; │
│ realm: RealmCoverage; │
│ } │
└────────────────────────────────────────────────────────────────────────────────────┘
┌─ TS ─────────────────────────────────┐
│ // core data types for the application │
│ export interface Player { │
│ id: number; │
│ player_id?: number; │
│ name: string; │
│ realm_slug: string; │
│ realm_name: string; │
│ region: string; │
│ class_name: string; │
│ active_spec_name: string; │
│ main_spec_id?: number; │
│ race_name?: string; │
│ gender?: string; │
│ guild_name?: string; │
│ level?: number; │
│ average_item_level?: number; │
│ equipped_item_level?: number; │
│ avatar_url?: string; │
│ global_ranking?: number; │
│ regional_ranking?: number; │
│ realm_ranking?: number; │
│ global_ranking_bracket?: string; │
│ regional_ranking_bracket?: string; │
│ realm_ranking_bracket?: string; │
│ ranking_percentile?: string; // contextual │
│ bracket based on leaderboard scope │
│ combined_best_time?: number; │
│ dungeons_completed?: number; │
│ total_runs?: number; │
│ } │
│ │
│ export interface TeamMember { │
│ id: number; │
│ name: string; │
│ spec_id: number; │
│ faction: string; │
│ realm_slug: string; │
│ region: string; │
│ } │
│ │
│ export interface ChallengeRun { │
│ id: number; │
│ duration: number; │
│ completed_timestamp: number; │
│ keystone_level: number; │
│ dungeon_name: string; │
│ realm_name: string; │
│ region: string; │
│ ranking?: number; │
│ percentile_bracket?: string; │
│ ranking_percentile?: string; // contextual │
│ bracket based on leaderboard scope │
│ members: TeamMember[]; │
│ } │
│ │
│ export interface BestRun { │
│ dungeon_id: number; │
│ dungeon_name: string; │
│ dungeon_slug: string; │
│ duration: number; │
│ global_ranking?: number; │
│ global_ranking_filtered?: number; │
│ regional_ranking?: number; │
│ regional_ranking_filtered?: number; │
│ realm_ranking?: number; │
│ realm_ranking_filtered?: number; │
│ percentile_bracket?: string; │
│ global_percentile_bracket?: string; │
│ regional_percentile_bracket?: string; │
│ realm_percentile_bracket?: string; │
│ completed_timestamp: number; │
│ keystone_level: number; │
│ all_members: TeamMember[]; │
│ } │
│ │
│ export interface Equipment { │
│ [slot: string]: EquipmentItem; │
│ } │
│ │
│ export interface ScalingOption { │
│ stats?: Record<string, number>; │
│ ilvl?: number; │
│ weaponDamageMin?: number; │
│ weaponDamageMax?: number; │
│ } │
│ │
│ export interface EquipmentItem { │
│ id: number; │
│ slot_type: string; │
│ item_id: number; │
│ item_name: string; │
│ quality: string; │
│ item_icon_slug?: string; │
│ enchantments?: Enchantment[]; │
│ scaling_options?: Record<string, ScalingOp │
│ tion>; │
│ } │
│ │
│ export interface Enchantment { │
│ enchantment_id: number; │
│ slot_id: number; │
│ slot_type?: string; │
│ display_string: string; │
│ source_item_id?: number; │
│ gem_icon_slug?: string; │
│ gem_name?: string; │
│ } │
│ │
│ export interface LeaderboardData { │
│ leading_groups: ChallengeRun[]; │
│ pagination: { │
│ currentPage: number; │
│ pageSize: number; │
│ totalPages: number; │
│ hasNextPage: boolean; │
│ hasPrevPage: boolean; │
│ totalRuns: number; │
│ }; │
│ } │
│ │
│ export interface PlayerLeaderboardData { │
│ leaderboard: Player[]; │
│ pagination: { │
│ currentPage: number; │
│ pageSize: number; │
│ totalPages: number; │
│ hasNextPage: boolean; │
│ hasPrevPage: boolean; │
│ totalPlayers: number; │
│ totalRuns: number; │
│ }; │
│ } │
│ │
│ // Per-account row from /api/leaderboard/sea │
│ son/{N}/accounts/... │
│ // Used by both the per-season combined-time │
│ account leaderboard and the │
│ // cross-season account total-runs leaderboa │
│ rd. Combined-time-specific fields │
│ // (bracket, account_combined_best_time, dun │
│ geons_completed, per_dungeon_best) │
│ // are optional so the type covers both feed │
│ s. │
│ export interface AccountLeaderboardEntry { │
│ rank: number; │
│ bracket?: string; // artifact | excellent │
│ | legendary | epic | rare | uncommon | commo │
│ n │
│ account_id: number; │
│ region: string; │
│ account_combined_best_time?: number; │
│ dungeons_completed?: number; │
│ total_runs: number; │
│ character_count?: number; │
│ main: AccountCharSummary; │
│ alts: AccountCharSummary[]; │
│ // dungeon_id (string) -> per-dungeon best │
│ inside this account │
│ per_dungeon_best?: Record<string, AccountP │
│ erDungeonBest>; │
│ } │
│ │
│ export interface AccountCharSummary { │
│ player_id: number; │
│ name: string; │
│ realm_slug: string; │
│ realm_name?: string; │
│ region: string; │
│ class_name?: string; │
│ active_spec_name?: string; │
│ main_spec_id?: number; │
│ combined_best_time?: number; │
│ total_runs?: number; │
│ has_full_coverage?: boolean; │
│ } │
│ │
│ export interface AccountPerDungeonBest { │
│ duration_ms: number; │
│ by_character: string; │
│ by_character_realm: string; │
│ } │
│ │
│ export interface AccountLeaderboardData { │
│ leaderboard: AccountLeaderboardEntry[]; │
│ title?: string; │
│ pagination: { │
│ currentPage: number; │
│ pageSize: number; │
│ totalPages: number; │
│ hasNextPage: boolean; │
│ hasPrevPage: boolean; │
│ totalAccounts: number; │
│ totalRuns: number; // legacy compat for │
│ shared Pagination component │
│ }; │
│ } │
│ │
│ export interface PlayerSeasonData { │
│ main_spec_id?: number; │
│ dungeons_completed: number; │
│ total_runs: number; │
│ combined_best_time?: number; │
│ global_ranking?: number; │
│ regional_ranking?: number; │
│ realm_ranking?: number; │
│ global_ranking_bracket?: string; │
│ regional_ranking_bracket?: string; │
│ realm_ranking_bracket?: string; │
│ last_updated?: number; │
│ best_runs: Record<string, BestRun>; │
│ } │
│ │
│ // Per-season account totals + rankings. Mir │
│ rors PlayerSeasonData stats but │
│ // for the whole account (sum across all alt │
│ s, ranked among other accounts). │
│ // Keep in sync with `AccountSeasonJSON` in │
│ nix/.../generator/players.go. │
│ export interface AccountSeasonData { │
│ account_id: number; │
│ combined_best_time?: number; │
│ dungeons_completed: number; │
│ total_runs: number; │
│ character_count: number; │
│ has_full_coverage: boolean; │
│ global_ranking?: number; │
│ regional_ranking?: number; │
│ realm_ranking?: number; │
│ global_ranking_bracket?: string; │
│ regional_ranking_bracket?: string; │
│ realm_ranking_bracket?: string; │
│ region?: string; │
│ realm_slug?: string; // main char's parent │
│ realm │
│ realm_name?: string; │
│ main_player_id?: number; │
│ } │
│ │
│ export interface PlayerWithSeasons { │
│ id: number; │
│ name: string; │
│ realm_slug: string; │
│ realm_name: string; │
│ region: string; │
│ class_name?: string; │
│ active_spec_name?: string; │
│ race_name?: string; │
│ avatar_url?: string; │
│ guild_name?: string; │
│ average_item_level?: number; │
│ equipped_item_level?: number; │
│ all_time_total_runs?: number; │
│ seasons: Record<string, PlayerSeasonData>; │
│ alts?: AccountCharSummary[]; │
│ account?: Record<string, AccountSeasonData │
│ >; │
│ // Cross-season sum of total_runs across e │
│ very alt on the account. Same on │
│ // every alt's profile and matches the val │
│ ue the Total Runs leaderboard │
│ // ranks accounts by. │
│ account_lifetime_total_runs?: number; │
│ } │
│ │
│ export interface PlayerProfileData { │
│ player: PlayerWithSeasons | null; │
│ equipment: Equipment; │
│ generated_at: number; │
│ version: string; │
│ } │
│ │
│ // API Response types │
│ export interface APIResponse<T> { │
│ data?: T; │
│ error?: string; │
│ } │
│ │
│ // mirror nix/pkgs/ookstats/src/internal/gen │
│ erator/home.go - keep in sync │
│ │
│ export interface HomeRunEntry { │
│ rank?: number; │
│ bracket?: string; │
│ run_id: number; │
│ dungeon_id: number; │
│ dungeon_name: string; │
│ dungeon_slug: string; │
│ duration_ms: number; │
│ completed_timestamp: number; │
│ // Only set on entries in `recent_top_runs │
│ ` (cross-season feed): │
│ season_id?: number; │
│ rankings?: { global?: number }; │
│ team_members: TeamMember[]; │
│ } │
│ │
│ export interface HomePlayerEntry { │
│ rank: number; │
│ player_id: number; │
│ name: string; │
│ realm_slug: string; │
│ realm_name?: string; │
│ region: string; │
│ class_name?: string; │
│ active_spec_id?: number; │
│ active_spec_name?: string; │
│ combined_best_time_ms: number; │
│ global_ranking?: number; │
│ global_ranking_bracket?: string; │
│ regional_ranking?: number; │
│ regional_ranking_bracket?: string; │
│ avatar_url?: string; │
│ } │
│ │
│ // mirror nix/pkgs/ookstats/src/internal/gen │
│ erator/stats.go - keep in sync │
│ │
│ export interface StatsJSON { │
│ generated_at: number; │
│ // Outer key: region ("global" | "us" | "e │
│ u" | "kr" | "tw"). │
│ // Inner key: season key ("all_time" | "se │
│ ason_1" | "season_2"). │
│ scopes: Record<string, Record<string, Stat │
│ sScope>>; │
│ } │
│ │
│ export interface StatsScope { │
│ total_runs: number; │
│ total_players: number; │
│ nine_of_nine_players: number; │
│ completion_tiers: { │
│ "9_of_9_gold": StatsCompletionTier; │
│ "9_of_9_platinum": StatsCompletionTier; │
│ "9_of_9_title": StatsCompletionTier; │
│ }; │
│ spec_counts: Record<string, StatsSpecCount │
│ Bucket>; // keys: "all_runs" | "gold_runs" | │
│ "platinum_runs" | "title_runs" | "top_50_ru │
│ ns" │
│ weekly_activity: StatsWeeklyActivityEntry[ │
│ ]; │
│ } │
│ │
│ export interface StatsSpecCountBucket { │
│ // Distinct runs in this bucket (denominat │
│ or for the "runs with spec" metric). │
│ total_runs: number; │
│ entries: StatsSpecCountEntry[]; │
│ // per-dungeon breakdown, keyed by numeric │
│ dungeon_id │
│ by_dungeon: Record<string, StatsDungeonSpe │
│ cBucket>; │
│ } │
│ │
│ export interface StatsDungeonSpecBucket { │
│ total_runs: number; │
│ entries: StatsSpecCountEntry[]; │
│ } │
│ │
│ export interface StatsCompletionTier { │
│ count: number; │
│ percentile_of_all_players: number; │
│ percentile_of_completed_players: number; │
│ percentile_of_all_time_players: number; │
│ } │
│ │
│ export interface StatsSpecCountEntry { │
│ spec_id: number; │
│ class_name: string; │
│ spec_name: string; │
│ // Total spec slot occurrences (e.g. 2 Com │
│ bat Rogues in one run = 2). │
│ count: number; │
│ // Distinct runs containing this spec (e.g │
│ . 2 Combat Rogues in one run = 1). │
│ runs_with_spec: number; │
│ } │
│ │
│ // gear.json - mirror nix/.../generator/gear │
│ .go, keep in sync │
│ export interface GearJSON { │
│ generated_at: number; │
│ // Outer key: season key ("season_1" | "se │
│ ason_2"). Inner key: spec_id (string). │
│ scopes: Record<string, Record<string, Gear │
│ SpecBucket>>; │
│ } │
│ │
│ export interface GearSpecBucket { │
│ // Number of qualifying players whose gear │
│ contributed to this bucket. │
│ total_players: number; │
│ // Keyed by canonical slot name (HEAD, CHE │
│ ST, FINGER, TRINKET, ...). │
│ slots: Record<string, GearSlotBucket>; │
│ } │
│ │
│ export interface GearSlotBucket { │
│ // Number of qualifying players who had an │
│ y item in this slot. │
│ players_with_slot: number; │
│ items: GearItemEntry[]; │
│ } │
│ │
│ export interface GearItemEntry { │
│ item_id: number; │
│ name: string; │
│ icon?: string; │
│ quality: number; │
│ count: number; │
│ } │
│ │
│ export interface StatsWeeklyActivityEntry { │
│ week_start: string; // ISO date or YYYY-MM │
│ -DD │
│ run_count: number; │
│ } │
│ │
│ // frontend component props │
│ export interface LeaderboardTableProps { │
│ initialData?: LeaderboardData; │
│ region: string; │
│ realm: string; │
│ dungeon: string; │
│ } │
│ │
│ export interface PlayerSearchProps { │
│ onPlayerSelect: (player: Player) => void; │
│ } │
│ │
│ export interface FilterPanelProps { │
│ initialRegion?: string; │
│ initialRealm?: string; │
│ initialDungeon?: string; │
│ onFilterChange: (filters: FilterState) => │
│ void; │
│ } │
│ │
│ export interface FilterState { │
│ region: string; │
│ realm: string; │
│ dungeon: string; │
│ teamFilter: boolean; │
│ } │
│ │
│ // player Search types │
│ export interface PlayerSearchResult { │
│ id: number; │
│ name: string; │
│ realm_slug: string; │
│ realm_name: string; │
│ region: string; │
│ class_name: string; │
│ active_spec_name: string; │
│ global_ranking?: number; │
│ regional_ranking?: number; │
│ realm_ranking?: number; │
│ global_ranking_bracket?: string; │
│ regional_ranking_bracket?: string; │
│ realm_ranking_bracket?: string; │
│ combined_best_time?: number; │
│ last_seen?: string; │
│ } │
│ │
│ export interface PlayerSearchIndex { │
│ players: PlayerSearchResult[]; │
│ metadata: { │
│ total_players: number; │
│ last_updated: string; │
│ version: string; │
│ }; │
│ } │
│ │
│ export interface FuseSearchResult<T> { │
│ item: T; │
│ refIndex: number; │
│ score?: number; │
│ } │
│ │
│ // Status page types │
│ export type CoverageHealth = "ok" | "some_mi │
│ ssing" | "no_data"; │
│ │
│ export interface DungeonCoverage { │
│ dungeon_id: number; │
│ dungeon_slug: string; │
│ dungeon_name: string; │
│ status: CoverageHealth; │
│ periods: number[]; │
│ missing_periods: number[]; │
│ error_periods: number[]; │
│ } │
│ │
│ export interface RealmCoverage { │
│ region: string; │
│ realm_slug: string; │
│ realm_name: string; │
│ health: CoverageHealth; │
│ total_periods: number; │
│ missing_periods: number; │
│ error_periods: number; │
│ dungeons: DungeonCoverage[]; │
│ } │
│ │
│ export interface StatusApiResponse { │
│ generated_at: string; │
│ realms: RealmCoverage[]; │
│ } │
│ │
│ export interface RealmStatusApiResponse { │
│ generated_at: string; │
│ realm: RealmCoverage; │
│ } │
└──────────────────────────────────────────────┘
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET