strat-gameplay-webapp/frontend-sba/composables/useDefensiveSetup.ts

64 lines
1.8 KiB
TypeScript

import { ref, computed } from 'vue'
import type { DefensiveDecision } from '~/types/game'
// Module-level singleton state (shared across all consumers)
const holdRunners = ref<Set<number>>(new Set())
const infieldDepth = ref<'infield_in' | 'normal' | 'corners_in'>('normal')
const outfieldDepth = ref<'normal' | 'shallow'>('normal')
export function useDefensiveSetup() {
/** Reactive array of held base numbers (for prop passing) */
const holdRunnersArray = computed<number[]>(() => Array.from(holdRunners.value).sort())
/** Check if a specific base is held */
function isHeld(base: number): boolean {
return holdRunners.value.has(base)
}
/** Toggle hold on a base (1, 2, or 3) */
function toggleHold(base: number) {
const next = new Set(holdRunners.value)
if (next.has(base)) {
next.delete(base)
} else {
next.add(base)
}
holdRunners.value = next
}
/** Reset all defensive setup to defaults */
function reset() {
holdRunners.value = new Set()
infieldDepth.value = 'normal'
outfieldDepth.value = 'normal'
}
/** Sync state from an existing DefensiveDecision (e.g. from props/server) */
function syncFromDecision(decision: DefensiveDecision) {
holdRunners.value = new Set(decision.hold_runners)
infieldDepth.value = decision.infield_depth
outfieldDepth.value = decision.outfield_depth
}
/** Build a DefensiveDecision from current working state */
function getDecision(): DefensiveDecision {
return {
infield_depth: infieldDepth.value,
outfield_depth: outfieldDepth.value,
hold_runners: holdRunnersArray.value,
}
}
return {
holdRunners,
holdRunnersArray,
infieldDepth,
outfieldDepth,
isHeld,
toggleHold,
reset,
syncFromDecision,
getDecision,
}
}