/** * Outcome Flow Constants * * Defines the hierarchical structure for the progressive disclosure * outcome selection wizard. Three top-level categories branch into * specific outcome types. * * Categories: * - ON_BASE: Hits and walks that result in batter reaching base * - OUT: Various types of outs * - X_CHECK: Defensive X-Check resolution (errors result from this) */ import type { PlayOutcome } from '~/types/game' /** * Top-level outcome categories for step 1 selection */ export type OutcomeCategory = 'ON_BASE' | 'OUT' | 'X_CHECK' /** * Sub-categories for ON_BASE outcomes */ export type OnBaseSubCategory = 'SINGLE' | 'DOUBLE' | 'TRIPLE' | 'HOME_RUN' | 'WALK' | 'HBP' /** * Sub-categories for OUT outcomes */ export type OutSubCategory = 'STRIKEOUT' | 'GROUNDOUT' | 'FLYOUT' | 'LINEOUT' | 'POPOUT' /** * Category configuration with display info */ export interface CategoryConfig { label: string description: string color: string bgColor: string borderColor: string } /** * Sub-category configuration with outcomes */ export interface SubCategoryConfig { label: string outcomes: PlayOutcome[] } /** * Category display configuration */ export const CATEGORY_CONFIG: Record = { ON_BASE: { label: 'On Base', description: 'Hit, walk, or HBP', color: 'text-green-700', bgColor: 'bg-green-50 hover:bg-green-100', borderColor: 'border-green-300', }, OUT: { label: 'Out', description: 'Strikeout, groundout, flyout', color: 'text-red-700', bgColor: 'bg-red-50 hover:bg-red-100', borderColor: 'border-red-300', }, X_CHECK: { label: 'X-Check', description: 'Defensive play check', color: 'text-orange-700', bgColor: 'bg-orange-50 hover:bg-orange-100', borderColor: 'border-orange-300', }, } /** * ON_BASE sub-categories and their specific outcomes */ export const ON_BASE_OUTCOMES: Record = { SINGLE: { label: 'Single', outcomes: ['single_1', 'single_2', 'single_uncapped'], }, DOUBLE: { label: 'Double', outcomes: ['double_2', 'double_3', 'double_uncapped'], }, TRIPLE: { label: 'Triple', outcomes: ['triple'], }, HOME_RUN: { label: 'Home Run', outcomes: ['homerun'], }, WALK: { label: 'Walk', outcomes: ['walk', 'intentional_walk'], }, HBP: { label: 'Hit By Pitch', outcomes: ['hbp'], }, } /** * OUT sub-categories and their specific outcomes */ export const OUT_OUTCOMES: Record = { STRIKEOUT: { label: 'Strikeout', outcomes: ['strikeout'], }, GROUNDOUT: { label: 'Groundout', outcomes: ['groundball_a', 'groundball_b', 'groundball_c'], }, FLYOUT: { label: 'Flyout', outcomes: ['flyout_a', 'flyout_b', 'flyout_bq', 'flyout_c'], }, LINEOUT: { label: 'Lineout', outcomes: ['lineout'], }, POPOUT: { label: 'Popout', outcomes: ['popout'], }, } /** * X-CHECK outcome (singular - error is a result, not input) */ export const X_CHECK_OUTCOMES: PlayOutcome[] = ['x_check'] /** * Outcome display labels for final selection */ export const OUTCOME_LABELS: Partial> = { // Singles single_1: 'Single (1 base)', single_2: 'Single (2 bases)', single_uncapped: 'Single (uncapped)', // Doubles double_2: 'Double (2 bases)', double_3: 'Double (3 bases)', double_uncapped: 'Double (uncapped)', // Other hits triple: 'Triple', homerun: 'Home Run', // Walks walk: 'Walk', intentional_walk: 'Intentional Walk', hbp: 'Hit By Pitch', // Outs strikeout: 'Strikeout', groundball_a: 'Groundball A', groundball_b: 'Groundball B', groundball_c: 'Groundball C', flyout_a: 'Flyout A', flyout_b: 'Flyout B', flyout_bq: 'Flyout B*', flyout_c: 'Flyout C', lineout: 'Lineout', popout: 'Popout', // X-Check x_check: 'X-Check', } /** * Hit location positions for location selection step */ export const HIT_LOCATIONS = [ { id: 'P', label: 'P', position: 'Pitcher' }, { id: 'C', label: 'C', position: 'Catcher' }, { id: '1B', label: '1B', position: 'First Base' }, { id: '2B', label: '2B', position: 'Second Base' }, { id: 'SS', label: 'SS', position: 'Shortstop' }, { id: '3B', label: '3B', position: 'Third Base' }, { id: 'LF', label: 'LF', position: 'Left Field' }, { id: 'CF', label: 'CF', position: 'Center Field' }, { id: 'RF', label: 'RF', position: 'Right Field' }, ] as const /** * Outcomes that require hit location selection */ export const OUTCOMES_REQUIRING_LOCATION: PlayOutcome[] = [ 'groundball_a', 'groundball_b', 'groundball_c', 'flyout_a', 'flyout_b', 'flyout_bq', 'flyout_c', 'lineout', 'popout', 'x_check', ] /** * Check if an outcome requires a hit location */ export function requiresHitLocation(outcome: PlayOutcome): boolean { return OUTCOMES_REQUIRING_LOCATION.includes(outcome) } /** * Get the display label for an outcome */ export function getOutcomeLabel(outcome: PlayOutcome): string { return OUTCOME_LABELS[outcome] || outcome }