/** * Logica di gioco condivisa per il segnapunti. * Utilizzata sia dal server WebSocket sia dal client per l'anteprima locale. */ export function createInitialState() { return { order: true, visuForm: false, visuStriscia: true, modalitaPartita: "3/5", sp: { striscia: { home: [0], guest: [0] }, servHome: true, punt: { home: 0, guest: 0 }, set: { home: 0, guest: 0 }, nomi: { home: "Antoniana", guest: "Guest" }, form: { home: ["1", "2", "3", "4", "5", "6"], guest: ["1", "2", "3", "4", "5", "6"], }, storicoServizio: [], }, } } export function checkVittoria(state) { const puntHome = state.sp.punt.home const puntGuest = state.sp.punt.guest const setHome = state.sp.set.home const setGuest = state.sp.set.guest const totSet = setHome + setGuest let isSetDecisivo = false if (state.modalitaPartita === "2/3") { isSetDecisivo = totSet >= 2 } else { isSetDecisivo = totSet >= 4 } const punteggioVittoria = isSetDecisivo ? 15 : 25 if (puntHome >= punteggioVittoria && puntHome - puntGuest >= 2) { return true } if (puntGuest >= punteggioVittoria && puntGuest - puntHome >= 2) { return true } return false } export function applyAction(state, action) { // Esegue un deep clone per evitare mutazioni indesiderate dello stato lato server. // Restituisce sempre un nuovo oggetto di stato. const s = JSON.parse(JSON.stringify(state)) switch (action.type) { case "incPunt": { const team = action.team if (checkVittoria(s)) break s.sp.storicoServizio.push({ servHome: s.sp.servHome, cambioPalla: (team === "home" && !s.sp.servHome) || (team === "guest" && s.sp.servHome), }) s.sp.punt[team]++ if (team === "home") { s.sp.striscia.home.push(s.sp.punt.home) s.sp.striscia.guest.push(" ") } else { s.sp.striscia.guest.push(s.sp.punt.guest) s.sp.striscia.home.push(" ") } const cambioPalla = (team === "home" && !s.sp.servHome) || (team === "guest" && s.sp.servHome) if (cambioPalla) { s.sp.form[team].push(s.sp.form[team].shift()) } s.sp.servHome = team === "home" break } case "decPunt": { if (s.sp.striscia.home.length > 1 && s.sp.storicoServizio.length > 0) { const tmpHome = s.sp.striscia.home.pop() s.sp.striscia.guest.pop() const statoServizio = s.sp.storicoServizio.pop() if (tmpHome === " ") { s.sp.punt.guest-- if (statoServizio.cambioPalla) { s.sp.form.guest.unshift(s.sp.form.guest.pop()) } } else { s.sp.punt.home-- if (statoServizio.cambioPalla) { s.sp.form.home.unshift(s.sp.form.home.pop()) } } s.sp.servHome = statoServizio.servHome } break } case "incSet": { const team = action.team if (s.sp.set[team] === 2) { s.sp.set[team] = 0 } else { s.sp.set[team]++ } break } case "cambiaPalla": { if (s.sp.punt.home === 0 && s.sp.punt.guest === 0) { s.sp.servHome = !s.sp.servHome } break } case "resetta": { s.visuForm = false s.sp.punt.home = 0 s.sp.punt.guest = 0 s.sp.set.home = 0 s.sp.set.guest = 0 s.sp.form = { home: ["1", "2", "3", "4", "5", "6"], guest: ["1", "2", "3", "4", "5", "6"], } s.sp.striscia = { home: [0], guest: [0] } s.sp.storicoServizio = [] break } case "toggleFormazione": { s.visuForm = !s.visuForm break } case "toggleStriscia": { s.visuStriscia = !s.visuStriscia break } case "toggleOrder": { s.order = !s.order break } case "setNomi": { if (action.home !== undefined) s.sp.nomi.home = action.home if (action.guest !== undefined) s.sp.nomi.guest = action.guest break } case "setModalita": { s.modalitaPartita = action.modalita break } case "setFormazione": { if (action.team && action.form) { s.sp.form[action.team] = [...action.form] } break } case "confermaCambi": { const team = action.team const cambi = action.cambi || [] const form = s.sp.form[team].map((val) => String(val).trim()) const formAggiornata = [...form] let valid = true for (const cambio of cambi) { const cin = (cambio.in || "").trim() const cout = (cambio.out || "").trim() if (!cin || !cout) continue if (!/^\d+$/.test(cin) || !/^\d+$/.test(cout)) { valid = false; break } if (cin === cout) { valid = false; break } if (formAggiornata.includes(cin)) { valid = false; break } if (!formAggiornata.includes(cout)) { valid = false; break } const idx = formAggiornata.findIndex((val) => String(val).trim() === cout) if (idx !== -1) { formAggiornata.splice(idx, 1, cin) } } if (valid) { s.sp.form[team] = formAggiornata } break } default: break } return s }