- Introduce Vitest per Unit e Integration Test. - Introduce Playwright per End-to-End Test. - Aggiuge documentazione dettagliata in tests/README.md. - Aggiorna .gitignore per escludere i report di coverage
207 lines
6.0 KiB
JavaScript
207 lines
6.0 KiB
JavaScript
/**
|
|
* 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
|
|
}
|