Compare commits

...

3 Commits

Author SHA1 Message Date
24dda41b0d Aggiunge selezione modalità partita (2/3 o 3/5)
- UI per scegliere la modalità partita nella Home
- Logica set decisivo adattata al best-of selezionato
- README aggiornato con nuove regole e descrizione feature
2026-01-28 14:57:14 +01:00
4cbb5fb48d Corregge ripristino servizio quando si annulla un punto
Risolve il bug dove l'indicatore del servizio (palla) non veniva
ripristinato correttamente quando si tornava indietro nel punteggio.

Implementa uno storico completo che salva lo stato del servizio prima
di ogni punto, permettendo di ripristinare esattamente la situazione
precedente quando si annulla un punto (incluso servizio e rotazioni)
2026-01-28 14:35:40 +01:00
eae5cbf964 Fissa dimensioni riquadri punteggio per evitare spostamenti 2026-01-28 14:30:17 +01:00
4 changed files with 73 additions and 17 deletions

View File

@@ -12,7 +12,7 @@ Applicazione web **Progressive Web App (PWA)** per tracciare i punteggi di parti
- **Gestione Completa Partite** - **Gestione Completa Partite**
- Tracciamento punti in tempo reale per entrambe le squadre - Tracciamento punti in tempo reale per entrambe le squadre
- Conteggio automatico dei set (fino a 5 set) - Conteggio automatico dei set (modalità 2/3 o 3/5)
- Indicatore visivo del servizio - Indicatore visivo del servizio
- Cronologia punti con striscia visiva - Cronologia punti con striscia visiva
@@ -20,7 +20,7 @@ Applicazione web **Progressive Web App (PWA)** per tracciare i punteggi di parti
- Visualizzazione interattiva dei 6 giocatori in campo - Visualizzazione interattiva dei 6 giocatori in campo
- Rotazione automatica regolamentare al cambio palla - Rotazione automatica regolamentare al cambio palla
- Configurazione manuale dei numeri di maglia - Configurazione manuale dei numeri di maglia
- Supporto logica pallavolo ufficiale (25 punti + 2 di vantaggio, 5° set a 15) - Supporto logica pallavolo ufficiale (25 punti + 2 di vantaggio, tie-break a 15 nel set decisivo)
- **Controlli Multimodali** - **Controlli Multimodali**
- Scorciatoie da tastiera complete (vedi sezione [Shortcuts](#shortcuts)) - Scorciatoie da tastiera complete (vedi sezione [Shortcuts](#shortcuts))
@@ -28,6 +28,7 @@ Applicazione web **Progressive Web App (PWA)** per tracciare i punteggi di parti
- **Personalizzazione** - **Personalizzazione**
- Configurazione dinamica nomi squadre - Configurazione dinamica nomi squadre
- Selettore modalità partita: al meglio di 3 o al meglio di 5
- Toggle layout orizzontale (inverti home/guest) - Toggle layout orizzontale (inverti home/guest)
- Modalità visualizzazione: punteggio semplice o formazioni complete - Modalità visualizzazione: punteggio semplice o formazioni complete
- Nascondi/mostra controlli e cronologia - Nascondi/mostra controlli e cronologia
@@ -219,7 +220,9 @@ VitePWA({
### Vittoria Set ### Vittoria Set
- **Set regolari (1-4)**: Primo a 25 punti con almeno 2 di vantaggio - **Set regolari (1-4)**: Primo a 25 punti con almeno 2 di vantaggio
- **Set decisivo (5°)**: Primo a 15 punti con almeno 2 di vantaggio - **Set decisivo**:
- Modalità 2/3: 3° set a 15 punti con almeno 2 di vantaggio
- Modalità 3/5: 5° set a 15 punti con almeno 2 di vantaggio
- **Blocco automatico**: Non consente assegnare punti oltre la vittoria - **Blocco automatico**: Non consente assegnare punti oltre la vittoria
### Rotazione Formazione ### Rotazione Formazione
@@ -246,4 +249,3 @@ Visualizzazione a 6 posizioni standard:
``` ```
La rotazione avviene in senso orario: 1→2→3→4→5→6→1 La rotazione avviene in senso orario: 1→2→3→4→5→6→1

View File

@@ -3,6 +3,24 @@
<w-input v-model="sp.nomi.home" type="text" class="pa3">Nome Home</w-input> <w-input v-model="sp.nomi.home" type="text" class="pa3">Nome Home</w-input>
<w-input v-model="sp.nomi.guest" type="text" class="pa3">Nome Guest</w-input> <w-input v-model="sp.nomi.guest" type="text" class="pa3">Nome Guest</w-input>
<w-flex justify-center align-center class="pa3">
<span class="mr3">Modalità partita:</span>
<w-button
@click="modalitaPartita = '2/3'"
:bg-color="modalitaPartita === '2/3' ? 'success' : 'grey-light4'"
:dark="modalitaPartita === '2/3'"
class="ma1">
2/3
</w-button>
<w-button
@click="modalitaPartita = '3/5'"
:bg-color="modalitaPartita === '3/5' ? 'success' : 'grey-light4'"
:dark="modalitaPartita === '3/5'"
class="ma1">
3/5
</w-button>
</w-flex>
<w-flex justify-space-around class="pa3"> <w-flex justify-space-around class="pa3">
<div class="campo-config"> <div class="campo-config">
<div class="text-bold mb3 text-center">Formazione Home</div> <div class="text-bold mb3 text-center">Formazione Home</div>
@@ -83,8 +101,10 @@
</div> </div>
</span> </span>
<span v-else> <span v-else>
<div class="col punt home" @click="incPunt('home')">{{ sp.punt.home }}</div> <w-flex class="punteggio-container">
<div class="col punt guest" @click="incPunt('guest')">{{ sp.punt.guest }}</div> <w-flex justify-center align-center class="col punt home" @click="incPunt('home')">{{ sp.punt.home }}</w-flex>
<w-flex justify-center align-center class="col punt guest" @click="incPunt('guest')">{{ sp.punt.guest }}</w-flex>
</w-flex>
</span> </span>
</span> </span>
@@ -120,8 +140,10 @@
</div> </div>
</span> </span>
<span v-else> <span v-else>
<div class="col punt guest" @click="incPunt('guest')">{{ sp.punt.guest }}</div> <w-flex class="punteggio-container">
<div class="col punt home" @click="incPunt('home')">{{ sp.punt.home }}</div> <w-flex justify-center align-center class="col punt guest" @click="incPunt('guest')">{{ sp.punt.guest }}</w-flex>
<w-flex justify-center align-center class="col punt home" @click="incPunt('home')">{{ sp.punt.home }}</w-flex>
</w-flex>
</span> </span>
</span> </span>

View File

@@ -14,6 +14,7 @@ export default {
visuForm: false, visuForm: false,
visuButt: true, visuButt: true,
visuStriscia: true, visuStriscia: true,
modalitaPartita: "3/5", // "2/3" o "3/5"
sp: { sp: {
striscia: { home: [0], guest: [0] }, striscia: { home: [0], guest: [0] },
servHome: true, servHome: true,
@@ -24,7 +25,7 @@ export default {
home: ["1", "2", "3", "4", "5", "6"], home: ["1", "2", "3", "4", "5", "6"],
guest: ["1", "2", "3", "4", "5", "6"], guest: ["1", "2", "3", "4", "5", "6"],
}, },
servizioPrecedente: [], // Stack per tracciare i cambi palla storicoServizio: [], // Stack per tracciare lo stato del servizio prima di ogni punto
}, },
} }
}, },
@@ -72,7 +73,7 @@ export default {
guest: ["1", "2", "3", "4", "5", "6"], guest: ["1", "2", "3", "4", "5", "6"],
} }
this.sp.striscia = { home: [0], guest: [0] } this.sp.striscia = { home: [0], guest: [0] }
this.sp.servizioPrecedente = [] this.sp.storicoServizio = []
}, },
cambiaPalla() { cambiaPalla() {
if (!this.isPunteggioZeroZero) { if (!this.isPunteggioZeroZero) {
@@ -95,6 +96,12 @@ export default {
return; return;
} }
// Salva lo stato del servizio PRIMA di modificarlo
this.sp.storicoServizio.push({
servHome: this.sp.servHome,
cambioPalla: (team == "home" && !this.sp.servHome) || (team == "guest" && this.sp.servHome)
});
this.sp.punt[team]++; this.sp.punt[team]++;
if (team == 'home') { if (team == 'home') {
this.sp.striscia.home.push(this.sp.punt.home) this.sp.striscia.home.push(this.sp.punt.home)
@@ -106,7 +113,6 @@ export default {
// Ruota la formazione solo se c'è cambio palla (conquista del servizio) // Ruota la formazione solo se c'è cambio palla (conquista del servizio)
const cambioPalla = (team == "home" && !this.sp.servHome) || (team == "guest" && this.sp.servHome); const cambioPalla = (team == "home" && !this.sp.servHome) || (team == "guest" && this.sp.servHome);
this.sp.servizioPrecedente.push(cambioPalla); // Salva se c'è stato cambio palla
if (cambioPalla) { if (cambioPalla) {
this.sp.form[team].push(this.sp.form[team].shift()); this.sp.form[team].push(this.sp.form[team].shift());
@@ -121,8 +127,16 @@ export default {
const setGuest = this.sp.set.guest; const setGuest = this.sp.set.guest;
const totSet = setHome + setGuest; const totSet = setHome + setGuest;
// Determina se siamo nel set decisivo (5° set) // Determina se siamo nel set decisivo in base alla modalità partita
const isSetDecisivo = totSet >= 4; let isSetDecisivo = false;
if (this.modalitaPartita === "2/3") {
// Tie-break al 3° set (quando totSet >= 2)
isSetDecisivo = totSet >= 2;
} else {
// Tie-break al 5° set (quando totSet >= 4)
isSetDecisivo = totSet >= 4;
}
const punteggioVittoria = isSetDecisivo ? 15 : 25; const punteggioVittoria = isSetDecisivo ? 15 : 25;
// Vittoria con punteggio >= 25 (o 15 per set decisivo) e almeno 2 punti di vantaggio // Vittoria con punteggio >= 25 (o 15 per set decisivo) e almeno 2 punti di vantaggio
@@ -136,24 +150,27 @@ export default {
return false; return false;
}, },
decPunt() { decPunt() {
if (this.sp.striscia.home.length > 1) { if (this.sp.striscia.home.length > 1 && this.sp.storicoServizio.length > 0) {
var tmpHome = this.sp.striscia.home.pop() var tmpHome = this.sp.striscia.home.pop()
var tmpGuest = this.sp.striscia.guest.pop() var tmpGuest = this.sp.striscia.guest.pop()
var cambioPalla = this.sp.servizioPrecedente.pop() // Recupera se c'era stato cambio palla var statoServizio = this.sp.storicoServizio.pop() // Recupera lo stato completo del servizio
if (tmpHome == ' ') { if (tmpHome == ' ') {
this.sp.punt.guest-- this.sp.punt.guest--
// Ruota indietro solo se c'era stato un cambio palla // Ruota indietro solo se c'era stato un cambio palla
if (cambioPalla) { if (statoServizio.cambioPalla) {
this.sp.form.guest.unshift(this.sp.form.guest.pop()); this.sp.form.guest.unshift(this.sp.form.guest.pop());
} }
} else { } else {
this.sp.punt.home-- this.sp.punt.home--
// Ruota indietro solo se c'era stato un cambio palla // Ruota indietro solo se c'era stato un cambio palla
if (cambioPalla) { if (statoServizio.cambioPalla) {
this.sp.form.home.unshift(this.sp.form.home.pop()); this.sp.form.home.unshift(this.sp.form.home.pop());
} }
} }
// Ripristina il servizio allo stato precedente
this.sp.servHome = statoServizio.servHome;
} }
}, },
// decPunt(team) { // decPunt(team) {

View File

@@ -80,8 +80,23 @@ button:focus-visible {
float: left; float: left;
width: 50%; width: 50%;
} }
.punteggio-container {
width: 100%;
height: 100%;
display: flex;
}
.punt { .punt {
font-size: 60vh; font-size: 60vh;
flex: 1;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
min-height: 50vh;
min-width: 50vw;
max-width: 50vw;
overflow: hidden;
box-sizing: border-box;
} }
.form { .form {
font-size: 5vh; font-size: 5vh;