All files / web/src/arcade-games/matching types.ts

0% Statements 0/109
0% Branches 0/1
0% Functions 0/1
0% Lines 0/109

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110                                                                                                                                                                                                                           
/**
 * Abacus Matching Game - Variant-Specific Type Definitions
 *
 * Base types (GamePhase, Difficulty, BaseMatchingCard, etc.) live in the
 * matching-pairs-framework. This file defines only the abacus-specific
 * extensions and re-exports for backwards compatibility.
 */

import { z } from 'zod'
import type { BaseMatchingCard, BaseMatchingConfig } from '@/lib/arcade/matching-pairs-framework'

// ============================================================================
// Variant-Specific Schemas & Types
// ============================================================================

export const GameTypeSchema = z.enum(['abacus-numeral', 'complement-pairs'])
export type GameType = z.infer<typeof GameTypeSchema>

export const CardTypeSchema = z.enum(['abacus', 'number', 'complement'])
export type CardType = z.infer<typeof CardTypeSchema>

export const TargetSumSchema = z.union([z.literal(5), z.literal(10), z.literal(20)])
export type TargetSum = z.infer<typeof TargetSumSchema>

export const DifficultySchema = z.union([z.literal(6), z.literal(8), z.literal(12), z.literal(15)])
export type Difficulty = z.infer<typeof DifficultySchema>

// ============================================================================
// AbacusCard — extends BaseMatchingCard
// ============================================================================

export const AbacusCardSchema = z.object({
  id: z.string(),
  type: CardTypeSchema,
  number: z.number(),
  complement: z.number().optional(),
  targetSum: TargetSumSchema.optional(),
  matched: z.boolean(),
  matchedBy: z.string().optional(),
})

export type AbacusCard = z.infer<typeof AbacusCardSchema> & {
  element?: HTMLElement | null // runtime-only
}

// Verify AbacusCard extends BaseMatchingCard at the type level
const _cardCheck: BaseMatchingCard = {} as AbacusCard
void _cardCheck

// ============================================================================
// AbacusConfig — extends BaseMatchingConfig
// ============================================================================

export const AbacusConfigSchema = z.object({
  gameType: GameTypeSchema,
  difficulty: DifficultySchema,
  turnTimer: z.number(),
  skipSetupPhase: z.boolean().optional(),
})

export type AbacusConfig = z.infer<typeof AbacusConfigSchema>

// Verify AbacusConfig extends BaseMatchingConfig at the type level
const _configCheck: BaseMatchingConfig = {} as AbacusConfig
void _configCheck

// ============================================================================
// Match Validation Result
// ============================================================================

export interface MatchValidationResult {
  isValid: boolean
  reason?: string
  type: 'abacus-numeral' | 'complement' | 'invalid'
}

// ============================================================================
// Backwards Compatibility Aliases
// ============================================================================

// GameCard is the old name for AbacusCard
export type GameCard = AbacusCard
export const GameCardSchema = AbacusCardSchema

// MatchingConfig is the old name for AbacusConfig
export type MatchingConfig = AbacusConfig
export const MatchingConfigSchema = AbacusConfigSchema

// Re-export framework types under old names for external consumers
// IMPORTANT: Use concrete type aliases (not bare re-exports) so that
// AbacusConfig fields (e.g. gameType) appear on the state type.
import type {
  MatchingPairsState as _MatchingPairsState,
  MatchingPairsMove as _MatchingPairsMove,
} from '@/lib/arcade/matching-pairs-framework'

export type MatchingState = _MatchingPairsState<AbacusCard, AbacusConfig> & AbacusConfig
export type MemoryPairsState = MatchingState
export type MatchingMove = _MatchingPairsMove<AbacusCard>

export type {
  GamePhase,
  GameMode,
  PlayerMetadata,
  GameStatistics,
} from '@/lib/arcade/matching-pairs-framework'

// Player is just a string
export type Player = string