refactor: deriva punt/set/servHome dalla striscia, estrai mixin WebSocket

La striscia è ora l'unica source of truth: punt, set vinti e servizio
vengono calcolati via helper puri (punteggio/servizio/setVinti) invece
di essere mantenuti come campi ridondanti nello stato.

Il boilerplate WebSocket (~150 righe identiche in entrambi i componenti)
è estratto in src/wsMixin.js con createWsMixin(role); i componenti
diventano solo logica specifica del loro ruolo.
This commit is contained in:
2026-06-20 15:23:53 +02:00
parent 8e2f3d759d
commit 38703116ff
4 changed files with 274 additions and 561 deletions
+44 -37
View File
@@ -1,3 +1,21 @@
export function punteggio(striscia) {
let home = 0, guest = 0
for (const c of striscia.at(-1).ris) c === 'h' ? home++ : guest++
return { home, guest }
}
export function servizio(striscia) {
const set = striscia.at(-1)
return set.ris.length === 0 ? set.serv === 'h' : set.ris.at(-1) === 'h'
}
export function setVinti(striscia) {
return {
home: striscia.filter(s => s.vinc === 'h').length,
guest: striscia.filter(s => s.vinc === 'g').length,
}
}
export function createInitialState() {
return {
order: true,
@@ -5,10 +23,7 @@ export function createInitialState() {
visuStriscia: true,
modalitaPartita: "3/5",
sp: {
striscia: [{ serv: 'h', ris: '' }],
servHome: true,
punt: { home: 0, guest: 0 },
set: { home: 0, guest: 0 },
striscia: [{ serv: 'h', ris: '', vinc: null }],
nomi: { home: "Antoniana", guest: "Guest" },
form: {
home: ["1", "2", "3", "4", "5", "6"],
@@ -19,12 +34,9 @@ export function createInitialState() {
}
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
const { home: puntHome, guest: puntGuest } = punteggio(state.sp.striscia)
const sv = setVinti(state.sp.striscia)
const totSet = sv.home + sv.guest
const isSetDecisivo = state.modalitaPartita === "2/3" ? totSet >= 2 : totSet >= 4
const punteggioVittoria = isSetDecisivo ? 15 : 25
@@ -35,7 +47,8 @@ export function checkVittoria(state) {
export function checkVittoriaPartita(state) {
const setsToWin = state.modalitaPartita === "2/3" ? 2 : 3
return state.sp.set.home >= setsToWin || state.sp.set.guest >= setsToWin
const sv = setVinti(state.sp.striscia)
return sv.home >= setsToWin || sv.guest >= setsToWin
}
export function applyAction(state, action) {
@@ -46,15 +59,13 @@ export function applyAction(state, action) {
const team = action.team
if (checkVittoria(s)) break
const cambioPalla = (team === "home") !== s.sp.servHome
s.sp.punt[team]++
const servHome = servizio(s.sp.striscia)
const cambioPalla = (team === "home") !== servHome
s.sp.striscia.at(-1).ris += team === 'home' ? 'h' : 'g'
if (cambioPalla) {
s.sp.form[team].push(s.sp.form[team].shift())
}
s.sp.servHome = team === "home"
break
}
@@ -72,10 +83,6 @@ export function applyAction(state, action) {
currentSet.ris = currentSet.ris.slice(0, -1)
const lastScorer = lastScorerShort === 'h' ? 'home' : 'guest'
const prevServer = prevServerShort === 'h' ? 'home' : 'guest'
s.sp.punt[lastScorer]--
s.sp.servHome = prevServerShort === 'h'
if (wasCambioPalla) {
s.sp.form[lastScorer].unshift(s.sp.form[lastScorer].pop())
@@ -85,10 +92,17 @@ export function applyAction(state, action) {
case "incSet": {
const team = action.team
if (s.sp.set[team] === 2) {
s.sp.set[team] = 0
const sv = setVinti(s.sp.striscia)
const count = sv[team]
const teamShort = team === 'home' ? 'h' : 'g'
if (count >= 2) {
// cicla a 0: rimuove le voci fantasma per questo team
s.sp.striscia = s.sp.striscia.filter(
entry => !(entry._phantom && entry.vinc === teamShort)
)
} else {
s.sp.set[team]++
// inserisce una voce fantasma prima dell'ultimo set (quello in corso)
s.sp.striscia.splice(-1, 0, { serv: teamShort, ris: '', vinc: teamShort, _phantom: true })
}
break
}
@@ -97,13 +111,9 @@ export function applyAction(state, action) {
const team = action.team
if (team !== 'home' && team !== 'guest') break
if (checkVittoriaPartita(s)) break
const setsToWin = s.modalitaPartita === "2/3" ? 2 : 3
s.sp.set[team]++
if (s.sp.set[team] >= setsToWin) break
s.sp.punt.home = 0
s.sp.punt.guest = 0
s.sp.servHome = team === 'home'
s.sp.striscia.push({ serv: team === 'home' ? 'h' : 'g', ris: '' })
s.sp.striscia.at(-1).vinc = team === 'home' ? 'h' : 'g'
if (checkVittoriaPartita(s)) break
s.sp.striscia.push({ serv: team === 'home' ? 'h' : 'g', ris: '', vinc: null })
s.sp.form = {
home: ["1", "2", "3", "4", "5", "6"],
guest: ["1", "2", "3", "4", "5", "6"],
@@ -112,24 +122,21 @@ export function applyAction(state, action) {
}
case "cambiaPalla": {
if (s.sp.punt.home === 0 && s.sp.punt.guest === 0) {
s.sp.servHome = !s.sp.servHome
s.sp.striscia.at(-1).serv = s.sp.servHome ? 'h' : 'g'
const currentSet = s.sp.striscia.at(-1)
if (currentSet.ris.length === 0) {
currentSet.serv = currentSet.serv === 'h' ? 'g' : 'h'
}
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
const servIniziale = s.sp.striscia[0]?.serv ?? 'h'
s.sp.striscia = [{ serv: servIniziale, ris: '', vinc: null }]
s.sp.form = {
home: ["1", "2", "3", "4", "5", "6"],
guest: ["1", "2", "3", "4", "5", "6"],
}
s.sp.striscia = [{ serv: s.sp.servHome ? 'h' : 'g', ris: '' }]
break
}