strat-gameplay-webapp/frontend-sba/types/websocket.ts
Cal Corum 4e7ea9e514 CLAUDE: Remove alignment field from frontend - complete Session 1 cleanup
Removed all references to the defensive alignment field across frontend codebase
after backend removal in Session 1. The alignment field was determined to be unused
and was removed from DefensiveDecision model.

Changes:
- types/websocket.ts: Removed alignment from DefensiveDecisionRequest interface
- composables/useGameActions.ts: Removed alignment from submit handler
- pages/demo-decisions.vue: Updated demo state and summary text (alignment → depths)
- pages/games/[id].vue: Updated decision history text for both defensive and offensive
  * Defensive: Now shows "infield depth, outfield depth" instead of "alignment, infield"
  * Offensive: Updated to use new action field with proper labels (swing_away, hit_and_run, etc.)
- Test files (3): Updated all test cases to remove alignment references
  * tests/unit/composables/useGameActions.spec.ts
  * tests/unit/store/game-decisions.spec.ts
  * tests/unit/components/Decisions/DefensiveSetup.spec.ts

Also updated offensive decision handling to match Session 2 changes (approach/hit_and_run/bunt_attempt → action field).

Total: 7 files modified, all alignment references removed
Verified: Zero remaining alignment references in .ts/.vue/.js files

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 15:34:59 -06:00

361 lines
7.8 KiB
TypeScript

/**
* WebSocket Event Types
*
* TypeScript definitions for all Socket.io events between client and server.
* Ensures type safety for real-time communication.
*
* Backend Reference: app/websocket/handlers.py
*/
import type {
GameState,
PlayResult,
DecisionPrompt,
RollData,
DefensiveDecision,
OffensiveDecision,
ManualOutcomeSubmission,
} from './game'
import type {
SubstitutionRequest,
SubstitutionResult,
SubstitutionError,
LineupDataResponse,
} from './player'
/**
* WebSocket connection auth
*/
export interface SocketAuth {
token: string
}
/**
* Client → Server Events (what client can emit)
*/
export interface ClientToServerEvents {
// Connection management
join_game: (data: JoinGameRequest) => void
leave_game: (data: LeaveGameRequest) => void
heartbeat: () => void
// Strategic decisions
submit_defensive_decision: (data: DefensiveDecisionRequest) => void
submit_offensive_decision: (data: OffensiveDecisionRequest) => void
// Manual outcome workflow
roll_dice: (data: RollDiceRequest) => void
submit_manual_outcome: (data: SubmitManualOutcomeRequest) => void
// Substitutions
request_pinch_hitter: (data: PinchHitterRequest) => void
request_defensive_replacement: (data: DefensiveReplacementRequest) => void
request_pitching_change: (data: PitchingChangeRequest) => void
// Data requests
get_lineup: (data: GetLineupRequest) => void
get_box_score: (data: GetBoxScoreRequest) => void
request_game_state: (data: RequestGameStateRequest) => void
}
/**
* Server → Client Events (what client can receive)
*/
export interface ServerToClientEvents {
// Connection events
connected: (data: ConnectedEvent) => void
game_joined: (data: GameJoinedEvent) => void
user_connected: (data: UserConnectedEvent) => void
user_disconnected: (data: UserDisconnectedEvent) => void
heartbeat_ack: () => void
// Decision events
defensive_decision_submitted: (data: DefensiveDecisionSubmittedEvent) => void
offensive_decision_submitted: (data: OffensiveDecisionSubmittedEvent) => void
decision_required: (data: DecisionPrompt) => void
// Game state events
game_state_update: (data: GameState) => void
game_state_sync: (data: GameStateSyncEvent) => void
play_completed: (data: PlayResult) => void
inning_change: (data: InningChangeEvent) => void
game_ended: (data: GameEndedEvent) => void
// Manual workflow events
dice_rolled: (data: DiceRolledEvent) => void
outcome_accepted: (data: OutcomeAcceptedEvent) => void
// Substitution events
player_substituted: (data: SubstitutionResult) => void
substitution_confirmed: (data: SubstitutionConfirmedEvent) => void
// Data responses
lineup_data: (data: LineupDataResponse) => void
box_score_data: (data: BoxScoreDataEvent) => void
// Error events
error: (data: ErrorEvent) => void
outcome_rejected: (data: OutcomeRejectedEvent) => void
substitution_error: (data: SubstitutionError) => void
invalid_action: (data: InvalidActionEvent) => void
connection_error: (data: ConnectionErrorEvent) => void
}
// ============================================================================
// Client → Server Request Types
// ============================================================================
export interface JoinGameRequest {
game_id: string
role: 'player' | 'spectator'
}
export interface LeaveGameRequest {
game_id: string
}
export interface DefensiveDecisionRequest {
game_id: string
infield_depth: DefensiveDecision['infield_depth']
outfield_depth: DefensiveDecision['outfield_depth']
hold_runners: number[]
}
export interface OffensiveDecisionRequest {
game_id: string
action: OffensiveDecision['action']
steal_attempts: number[]
}
export interface RollDiceRequest {
game_id: string
}
export interface SubmitManualOutcomeRequest {
game_id: string
outcome: string
hit_location?: string
}
export interface PinchHitterRequest {
game_id: string
player_out_lineup_id: number
player_in_card_id: number
team_id: number
}
export interface DefensiveReplacementRequest {
game_id: string
player_out_lineup_id: number
player_in_card_id: number
new_position: string
team_id: number
}
export interface PitchingChangeRequest {
game_id: string
player_out_lineup_id: number
player_in_card_id: number
team_id: number
}
export interface GetLineupRequest {
game_id: string
team_id: number
}
export interface GetBoxScoreRequest {
game_id: string
}
export interface RequestGameStateRequest {
game_id: string
}
// ============================================================================
// Server → Client Event Types
// ============================================================================
export interface ConnectedEvent {
user_id: string
}
export interface GameJoinedEvent {
game_id: string
role: 'player' | 'spectator'
}
export interface UserConnectedEvent {
user_id: string
game_id: string
}
export interface UserDisconnectedEvent {
user_id: string
game_id: string
}
export interface DefensiveDecisionSubmittedEvent {
game_id: string
decision: DefensiveDecision
pending_decision: 'offensive' | 'resolution' | null
}
export interface OffensiveDecisionSubmittedEvent {
game_id: string
decision: OffensiveDecision
pending_decision: 'resolution' | null
}
export interface DiceRolledEvent {
game_id: string
roll_id: string
d6_one: number
d6_two_total: number
chaos_d20: number
resolution_d20: number
check_wild_pitch: boolean
check_passed_ball: boolean
timestamp: string
message: string
}
export interface OutcomeAcceptedEvent {
outcome: string
hit_location?: string
}
export interface InningChangeEvent {
inning: number
half: 'top' | 'bottom'
}
export interface GameEndedEvent {
game_id: string
winner_team_id: number
final_score: {
home: number
away: number
}
completed_at: string
}
export interface SubstitutionConfirmedEvent {
type: string
new_lineup_id: number
message: string
}
export interface BoxScoreDataEvent {
game_id: string
box_score: {
game_stats: {
home_runs: number
away_runs: number
home_hits: number
away_hits: number
home_errors: number
away_errors: number
linescore_home: number[]
linescore_away: number[]
}
batting_stats: BattingStatLine[]
pitching_stats: PitchingStatLine[]
}
}
export interface BattingStatLine {
lineup_id: number
player_card_id: number
pa: number
ab: number
run: number
hit: number
rbi: number
double: number
triple: number
hr: number
bb: number
so: number
hbp: number
sac: number
sb: number
cs: number
gidp: number
}
export interface PitchingStatLine {
lineup_id: number
player_card_id: number
batters_faced: number
ip: number
hit_allowed: number
run_allowed: number
erun: number
bb: number
so: number
hbp: number
hr_allowed: number
wp: number
}
export interface GameStateSyncEvent {
state: GameState
recent_plays: PlayResult[]
timestamp: string
}
export interface ErrorEvent {
message: string
code?: string
field?: string
hint?: string
}
export interface OutcomeRejectedEvent {
message: string
field: string
errors?: Array<{
loc: string[]
msg: string
type: string
}>
}
export interface InvalidActionEvent {
action: string
reason: string
}
export interface ConnectionErrorEvent {
error: string
details?: string
}
/**
* Type-safe Socket.io instance
*/
export interface TypedSocket {
on<K extends keyof ServerToClientEvents>(
event: K,
listener: ServerToClientEvents[K]
): void
emit<K extends keyof ClientToServerEvents>(
event: K,
...args: Parameters<ClientToServerEvents[K]>
): void
off<K extends keyof ServerToClientEvents>(
event: K,
listener?: ServerToClientEvents[K]
): void
connect(): void
disconnect(): void
readonly connected: boolean
readonly id: string
}