Ajuste le mode Time et met en valeur les chronos
This commit is contained in:
148
app.js
148
app.js
@@ -13,17 +13,17 @@ const PRESETS = {
|
|||||||
fast: {
|
fast: {
|
||||||
label: "FAST",
|
label: "FAST",
|
||||||
quota: 6,
|
quota: 6,
|
||||||
description: "6 coups par joueur et par partie.",
|
description: "6 coups par joueur.",
|
||||||
},
|
},
|
||||||
freeze: {
|
freeze: {
|
||||||
label: "FREEZE",
|
label: "FREEZE",
|
||||||
quota: 8,
|
quota: 8,
|
||||||
description: "8 coups par joueur et par partie.",
|
description: "8 coups par joueur.",
|
||||||
},
|
},
|
||||||
masters: {
|
masters: {
|
||||||
label: "MASTERS",
|
label: "MASTERS",
|
||||||
quota: 10,
|
quota: 10,
|
||||||
description: "10 coups par joueur et par partie.",
|
description: "10 coups par joueur.",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,6 +114,8 @@ function initSetupPage() {
|
|||||||
const summary = document.querySelector("#setupSummary");
|
const summary = document.querySelector("#setupSummary");
|
||||||
const loadDemoButton = document.querySelector("#loadDemoButton");
|
const loadDemoButton = document.querySelector("#loadDemoButton");
|
||||||
const resumeCard = document.querySelector("#resumeCard");
|
const resumeCard = document.querySelector("#resumeCard");
|
||||||
|
const moveSecondsField = document.querySelector("#moveSecondsField");
|
||||||
|
const moveSecondsInput = form?.querySelector('[name="moveSeconds"]');
|
||||||
|
|
||||||
if (!form || !summary || !loadDemoButton || !resumeCard) {
|
if (!form || !summary || !loadDemoButton || !resumeCard) {
|
||||||
return;
|
return;
|
||||||
@@ -125,17 +127,34 @@ function initSetupPage() {
|
|||||||
const quota = PRESETS[preset].quota;
|
const quota = PRESETS[preset].quota;
|
||||||
const blockDurationMs = getDurationInputMs(form, "blockSeconds", DEFAULT_BLOCK_DURATION_MS);
|
const blockDurationMs = getDurationInputMs(form, "blockSeconds", DEFAULT_BLOCK_DURATION_MS);
|
||||||
const moveLimitMs = getDurationInputMs(form, "moveSeconds", DEFAULT_MOVE_LIMIT_MS);
|
const moveLimitMs = getDurationInputMs(form, "moveSeconds", DEFAULT_MOVE_LIMIT_MS);
|
||||||
|
const moveLimitActive = usesMoveLimit(mode);
|
||||||
const timeImpact =
|
const timeImpact =
|
||||||
mode === "time"
|
mode === "time"
|
||||||
? "Chronos cumules de 10 minutes, ajustes apres chaque phase cube avec plafond de 120 s pris en compte."
|
? "Chronos cumules de 10 minutes par joueur, ajustes apres chaque phase cube avec plafond de 120 s pris en compte. Aucun temps par coup en mode Time."
|
||||||
: "Le gagnant du cube commence la partie suivante, avec double coup V2 possible.";
|
: "Le gagnant du cube commence la partie suivante, avec double coup V2 possible.";
|
||||||
|
const timingText = moveLimitActive
|
||||||
|
? `Temps configures : partie ${formatClock(blockDurationMs)}, coup ${formatClock(moveLimitMs)}.`
|
||||||
|
: `Temps configure : Block ${formatClock(blockDurationMs)}.`;
|
||||||
|
const quotaText = moveLimitActive
|
||||||
|
? `Quota actif : ${quota} coups par joueur.`
|
||||||
|
: `Quota actif : ${quota} coups par joueur et par Block.`;
|
||||||
|
|
||||||
|
if (moveSecondsField instanceof HTMLElement) {
|
||||||
|
moveSecondsField.hidden = !moveLimitActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moveSecondsInput instanceof HTMLInputElement) {
|
||||||
|
moveSecondsInput.disabled = !moveLimitActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.body.classList.toggle("time-setup-mode", !moveLimitActive);
|
||||||
|
|
||||||
summary.innerHTML = `
|
summary.innerHTML = `
|
||||||
<strong>${MODES[mode].label}</strong>
|
<strong>${MODES[mode].label}</strong>
|
||||||
<span>${PRESETS[preset].description}</span>
|
<span>${PRESETS[preset].description}</span>
|
||||||
<span>Temps configures : partie ${formatClock(blockDurationMs)}, coup ${formatClock(moveLimitMs)}.</span>
|
<span>${timingText}</span>
|
||||||
<span>${timeImpact}</span>
|
<span>${timeImpact}</span>
|
||||||
<span>Quota actif : ${quota} coups par joueur.</span>
|
<span>${quotaText}</span>
|
||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -228,7 +247,9 @@ function initChronoPage() {
|
|||||||
title: document.querySelector("#chronoTitle"),
|
title: document.querySelector("#chronoTitle"),
|
||||||
subtitle: document.querySelector("#chronoSubtitle"),
|
subtitle: document.querySelector("#chronoSubtitle"),
|
||||||
blockTimer: document.querySelector("#blockTimer"),
|
blockTimer: document.querySelector("#blockTimer"),
|
||||||
|
blockTimerLabel: document.querySelector("#blockTimerLabel"),
|
||||||
moveTimer: document.querySelector("#moveTimer"),
|
moveTimer: document.querySelector("#moveTimer"),
|
||||||
|
moveTimerCard: document.querySelector("#moveTimerCard"),
|
||||||
centerLabel: document.querySelector("#chronoCenterLabel"),
|
centerLabel: document.querySelector("#chronoCenterLabel"),
|
||||||
centerValue: document.querySelector("#chronoCenterValue"),
|
centerValue: document.querySelector("#chronoCenterValue"),
|
||||||
spineLabel: document.querySelector("#spineLabel"),
|
spineLabel: document.querySelector("#spineLabel"),
|
||||||
@@ -299,7 +320,7 @@ function initChronoPage() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
requestBlockClosure(match, "Cloture manuelle de la partie demandee par l'arbitre.");
|
requestBlockClosure(match, `Cloture manuelle ${getBlockGenitivePhrase(match)} demandee par l'arbitre.`);
|
||||||
dirty = true;
|
dirty = true;
|
||||||
if (!match.result && match.phase === "cube") {
|
if (!match.result && match.phase === "cube") {
|
||||||
goToCubePage();
|
goToCubePage();
|
||||||
@@ -310,7 +331,7 @@ function initChronoPage() {
|
|||||||
|
|
||||||
refs.arbiterTimeoutButton?.addEventListener("click", () => {
|
refs.arbiterTimeoutButton?.addEventListener("click", () => {
|
||||||
syncRunningState(match);
|
syncRunningState(match);
|
||||||
if (match.result || match.phase !== "block") {
|
if (match.result || match.phase !== "block" || !usesMoveLimit(match)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,7 +347,9 @@ function initChronoPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match.currentTurn = opponentOf(match.currentTurn);
|
match.currentTurn = opponentOf(match.currentTurn);
|
||||||
match.moveRemainingMs = getMoveLimitMs(match);
|
if (usesMoveLimit(match)) {
|
||||||
|
match.moveRemainingMs = getMoveLimitMs(match);
|
||||||
|
}
|
||||||
logEvent(match, "Trait corrige manuellement par l'arbitre.");
|
logEvent(match, "Trait corrige manuellement par l'arbitre.");
|
||||||
dirty = true;
|
dirty = true;
|
||||||
render();
|
render();
|
||||||
@@ -416,17 +439,20 @@ function initChronoPage() {
|
|||||||
const clock = isWhite ? refs.whiteClock : refs.blackClock;
|
const clock = isWhite ? refs.whiteClock : refs.blackClock;
|
||||||
const hint = isWhite ? refs.whiteHint : refs.blackHint;
|
const hint = isWhite ? refs.whiteHint : refs.blackHint;
|
||||||
const zone = isWhite ? refs.whiteZone : refs.blackZone;
|
const zone = isWhite ? refs.whiteZone : refs.blackZone;
|
||||||
const actorName = playerName(match, color);
|
|
||||||
const active = match.currentTurn === color;
|
const active = match.currentTurn === color;
|
||||||
|
const unitLabel = getBlockLabel(match);
|
||||||
|
const unitPhrase = getBlockPhrase(match);
|
||||||
|
|
||||||
name.textContent = actorName;
|
name.textContent = playerName(match, color);
|
||||||
moves.textContent = `${match.moves[color]} / ${match.quota}`;
|
moves.textContent = `${match.moves[color]} / ${match.quota}`;
|
||||||
clock.textContent = match.clocks
|
clock.textContent = match.clocks ? formatSignedClock(match.clocks[color]) : `Dernier cube ${renderLastCube(match, color)}`;
|
||||||
? `Chrono ${formatSignedClock(match.clocks[color])}`
|
|
||||||
: `Dernier cube ${renderLastCube(match, color)}`;
|
|
||||||
|
|
||||||
button.classList.toggle("active-turn", active && !match.result);
|
button.classList.toggle("active-turn", active && !match.result);
|
||||||
zone.classList.toggle("active-zone", active && !match.result);
|
zone.classList.toggle("active-zone", active && !match.result);
|
||||||
|
zone.classList.toggle("has-player-clock", Boolean(match.clocks));
|
||||||
|
clock.classList.toggle("player-clock", Boolean(match.clocks));
|
||||||
|
clock.classList.toggle("negative-clock", Boolean(match.clocks) && match.clocks[color] < 0);
|
||||||
|
clock.classList.toggle("active-clock", Boolean(match.clocks) && active && !match.result);
|
||||||
|
|
||||||
if (match.result) {
|
if (match.result) {
|
||||||
button.textContent = resultText(match);
|
button.textContent = resultText(match);
|
||||||
@@ -436,10 +462,10 @@ function initChronoPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!match.running) {
|
if (!match.running) {
|
||||||
button.textContent = "Partie en pause";
|
button.textContent = `${unitLabel} en pause`;
|
||||||
button.disabled = true;
|
button.disabled = true;
|
||||||
hint.textContent = active
|
hint.textContent = active
|
||||||
? "La partie n'a pas encore demarre ou a ete mise en pause."
|
? `${unitPhrase} n'a pas encore demarre ou a ete mis en pause.`
|
||||||
: `${playerName(match, match.currentTurn)} reprendra au demarrage.`;
|
: `${playerName(match, match.currentTurn)} reprendra au demarrage.`;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -480,11 +506,21 @@ function initChronoPage() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const timeMode = isTimeMode(match);
|
||||||
|
const blockHeading = formatBlockHeading(match, match.blockNumber);
|
||||||
|
|
||||||
|
document.body.classList.toggle("time-mode", timeMode);
|
||||||
refs.title.textContent = match.config.matchLabel;
|
refs.title.textContent = match.config.matchLabel;
|
||||||
refs.subtitle.textContent = `Partie ${match.blockNumber} - ${MODES[match.config.mode].label} - ${renderModeContext(match)}`;
|
refs.subtitle.textContent = `${blockHeading} - ${MODES[match.config.mode].label} - ${renderModeContext(match)}`;
|
||||||
|
refs.blockTimerLabel.textContent = timeMode ? "Temps Block" : "Temps partie";
|
||||||
refs.blockTimer.textContent = formatClock(match.blockRemainingMs);
|
refs.blockTimer.textContent = formatClock(match.blockRemainingMs);
|
||||||
refs.moveTimer.textContent = formatClock(match.moveRemainingMs);
|
refs.moveTimer.textContent = usesMoveLimit(match) ? formatClock(match.moveRemainingMs) : "--:--";
|
||||||
refs.arbiterTimeoutButton.textContent = `Depassement ${formatClock(getMoveLimitMs(match))}`;
|
refs.moveTimerCard.hidden = timeMode;
|
||||||
|
refs.arbiterTimeoutButton.hidden = timeMode;
|
||||||
|
refs.arbiterTimeoutButton.disabled = timeMode;
|
||||||
|
if (usesMoveLimit(match)) {
|
||||||
|
refs.arbiterTimeoutButton.textContent = `Depassement ${formatClock(getMoveLimitMs(match))}`;
|
||||||
|
}
|
||||||
|
|
||||||
if (match.result) {
|
if (match.result) {
|
||||||
refs.centerLabel.textContent = "Resultat";
|
refs.centerLabel.textContent = "Resultat";
|
||||||
@@ -498,20 +534,20 @@ function initChronoPage() {
|
|||||||
refs.centerLabel.textContent = "Trait";
|
refs.centerLabel.textContent = "Trait";
|
||||||
refs.centerValue.textContent = playerName(match, match.currentTurn);
|
refs.centerValue.textContent = playerName(match, match.currentTurn);
|
||||||
refs.spineLabel.textContent = "Chrono en cours";
|
refs.spineLabel.textContent = "Chrono en cours";
|
||||||
refs.spineHeadline.textContent = `Partie ${match.blockNumber} active`;
|
refs.spineHeadline.textContent = `${blockHeading} actif`;
|
||||||
refs.spineText.textContent =
|
refs.spineText.textContent =
|
||||||
"Chaque joueur tape sur sa grande zone quand son coup est termine. La page cube s'ouvrira automatiquement a la fin de la phase chess.";
|
"Chaque joueur tape sur sa grande zone quand son coup est termine. La page cube s'ouvrira automatiquement a la fin de la phase chess.";
|
||||||
refs.primaryButton.textContent = "Pause arbitre";
|
refs.primaryButton.textContent = "Pause arbitre";
|
||||||
refs.arbiterStatus.textContent = `Partie en cours. Joueur au trait : ${playerName(match, match.currentTurn)}.`;
|
refs.arbiterStatus.textContent = `${blockHeading} en cours. Joueur au trait : ${playerName(match, match.currentTurn)}.`;
|
||||||
} else {
|
} else {
|
||||||
refs.centerLabel.textContent = "Trait";
|
refs.centerLabel.textContent = "Trait";
|
||||||
refs.centerValue.textContent = playerName(match, match.currentTurn);
|
refs.centerValue.textContent = playerName(match, match.currentTurn);
|
||||||
refs.spineLabel.textContent = "Pret";
|
refs.spineLabel.textContent = timeMode ? "Etat du Block" : "Pret";
|
||||||
refs.spineHeadline.textContent = `Partie ${match.blockNumber}`;
|
refs.spineHeadline.textContent = blockHeading;
|
||||||
refs.spineText.textContent =
|
refs.spineText.textContent =
|
||||||
"Demarrez la partie, puis laissez uniquement les deux grandes zones aux joueurs. La page cube prendra automatiquement le relais.";
|
"Demarrez la partie, puis laissez uniquement les deux grandes zones aux joueurs. La page cube prendra automatiquement le relais.";
|
||||||
refs.primaryButton.textContent = "Demarrer la partie";
|
refs.primaryButton.textContent = timeMode ? "Demarrer le Block" : "Demarrer la partie";
|
||||||
refs.arbiterStatus.textContent = `Partie prete. ${playerName(match, match.currentTurn)} commencera.`;
|
refs.arbiterStatus.textContent = `${blockHeading} pret. ${playerName(match, match.currentTurn)} commencera.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
refs.arbiterCloseBlockButton.textContent = "Passer au cube";
|
refs.arbiterCloseBlockButton.textContent = "Passer au cube";
|
||||||
@@ -555,6 +591,7 @@ function initCubePage() {
|
|||||||
const refs = {
|
const refs = {
|
||||||
title: document.querySelector("#cubeTitle"),
|
title: document.querySelector("#cubeTitle"),
|
||||||
subtitle: document.querySelector("#cubeSubtitle"),
|
subtitle: document.querySelector("#cubeSubtitle"),
|
||||||
|
blockLabelText: document.querySelector("#cubeBlockLabelText"),
|
||||||
blockLabel: document.querySelector("#cubeBlockLabel"),
|
blockLabel: document.querySelector("#cubeBlockLabel"),
|
||||||
elapsed: document.querySelector("#cubeElapsed"),
|
elapsed: document.querySelector("#cubeElapsed"),
|
||||||
centerLabel: document.querySelector("#cubeCenterLabel"),
|
centerLabel: document.querySelector("#cubeCenterLabel"),
|
||||||
@@ -892,8 +929,11 @@ function initCubePage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function render() {
|
function render() {
|
||||||
|
const blockHeading = formatBlockHeading(match, match.blockNumber);
|
||||||
|
|
||||||
refs.title.textContent = match.cube.number ? `Cube n${match.cube.number}` : "Phase cube";
|
refs.title.textContent = match.cube.number ? `Cube n${match.cube.number}` : "Phase cube";
|
||||||
refs.subtitle.textContent = `Partie ${match.blockNumber} - ${MODES[match.config.mode].label} - ${renderModeContext(match)}`;
|
refs.subtitle.textContent = `${blockHeading} - ${MODES[match.config.mode].label} - ${renderModeContext(match)}`;
|
||||||
|
refs.blockLabelText.textContent = getBlockLabel(match);
|
||||||
refs.blockLabel.textContent = `${match.blockNumber}`;
|
refs.blockLabel.textContent = `${match.blockNumber}`;
|
||||||
refs.elapsed.textContent = renderCubeElapsed(match);
|
refs.elapsed.textContent = renderCubeElapsed(match);
|
||||||
|
|
||||||
@@ -923,7 +963,9 @@ function initCubePage() {
|
|||||||
refs.centerValue.textContent = "Phase cube complete";
|
refs.centerValue.textContent = "Phase cube complete";
|
||||||
refs.spineLabel.textContent = "Suite";
|
refs.spineLabel.textContent = "Suite";
|
||||||
refs.spineHeadline.textContent = "Ouvrir la page chrono";
|
refs.spineHeadline.textContent = "Ouvrir la page chrono";
|
||||||
refs.spineText.textContent = "Appliquer le resultat du cube pour preparer la partie suivante.";
|
refs.spineText.textContent = isTimeMode(match)
|
||||||
|
? "Appliquer le resultat du cube pour preparer le Block suivant."
|
||||||
|
: "Appliquer le resultat du cube pour preparer la partie suivante.";
|
||||||
refs.primaryButton.textContent = "Appliquer et ouvrir la page chrono";
|
refs.primaryButton.textContent = "Appliquer et ouvrir la page chrono";
|
||||||
refs.helpStatus.textContent = refs.spineText.textContent;
|
refs.helpStatus.textContent = refs.spineText.textContent;
|
||||||
} else if (match.cube.running) {
|
} else if (match.cube.running) {
|
||||||
@@ -1033,9 +1075,11 @@ function createMatch(config) {
|
|||||||
|
|
||||||
logEvent(
|
logEvent(
|
||||||
newMatch,
|
newMatch,
|
||||||
`Match cree en mode ${MODES[config.mode].label}, cadence ${PRESETS[config.preset].label}, partie ${formatClock(config.blockDurationMs)} et coup ${formatClock(config.moveLimitMs)}.`,
|
usesMoveLimit(config.mode)
|
||||||
|
? `Match cree en mode ${MODES[config.mode].label}, cadence ${PRESETS[config.preset].label}, partie ${formatClock(config.blockDurationMs)} et coup ${formatClock(config.moveLimitMs)}.`
|
||||||
|
: `Match cree en mode ${MODES[config.mode].label}, cadence ${PRESETS[config.preset].label}, Block ${formatClock(config.blockDurationMs)} sans temps par coup.`,
|
||||||
);
|
);
|
||||||
logEvent(newMatch, "Les Blancs commencent la partie 1.");
|
logEvent(newMatch, `Les Blancs commencent ${formatBlockHeading(config, 1)}.`);
|
||||||
return newMatch;
|
return newMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1163,7 +1207,9 @@ function syncRunningState(storedMatch) {
|
|||||||
|
|
||||||
storedMatch.lastTickAt = now;
|
storedMatch.lastTickAt = now;
|
||||||
storedMatch.blockRemainingMs = Math.max(0, storedMatch.blockRemainingMs - delta);
|
storedMatch.blockRemainingMs = Math.max(0, storedMatch.blockRemainingMs - delta);
|
||||||
storedMatch.moveRemainingMs = Math.max(0, storedMatch.moveRemainingMs - delta);
|
if (usesMoveLimit(storedMatch)) {
|
||||||
|
storedMatch.moveRemainingMs = Math.max(0, storedMatch.moveRemainingMs - delta);
|
||||||
|
}
|
||||||
|
|
||||||
if (storedMatch.clocks) {
|
if (storedMatch.clocks) {
|
||||||
storedMatch.clocks[storedMatch.currentTurn] -= delta;
|
storedMatch.clocks[storedMatch.currentTurn] -= delta;
|
||||||
@@ -1172,9 +1218,9 @@ function syncRunningState(storedMatch) {
|
|||||||
if (storedMatch.blockRemainingMs === 0) {
|
if (storedMatch.blockRemainingMs === 0) {
|
||||||
requestBlockClosure(
|
requestBlockClosure(
|
||||||
storedMatch,
|
storedMatch,
|
||||||
`Le temps de partie ${formatClock(getBlockDurationMs(storedMatch))} est ecoule.`,
|
`Le temps ${getBlockGenitivePhrase(storedMatch)} ${formatClock(getBlockDurationMs(storedMatch))} est ecoule.`,
|
||||||
);
|
);
|
||||||
} else if (storedMatch.moveRemainingMs === 0) {
|
} else if (usesMoveLimit(storedMatch) && storedMatch.moveRemainingMs === 0) {
|
||||||
registerMoveTimeout(storedMatch, true);
|
registerMoveTimeout(storedMatch, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1193,8 +1239,8 @@ function startBlock(storedMatch) {
|
|||||||
logEvent(
|
logEvent(
|
||||||
storedMatch,
|
storedMatch,
|
||||||
storedMatch.blockNumber === 1 && storedMatch.moves.white === 0 && storedMatch.moves.black === 0
|
storedMatch.blockNumber === 1 && storedMatch.moves.white === 0 && storedMatch.moves.black === 0
|
||||||
? "Partie 1 demarre."
|
? `${formatBlockHeading(storedMatch, 1)} demarre.`
|
||||||
: `Partie ${storedMatch.blockNumber} relance.`,
|
: `${formatBlockHeading(storedMatch, storedMatch.blockNumber)} relance.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1205,7 +1251,7 @@ function pauseBlock(storedMatch) {
|
|||||||
|
|
||||||
storedMatch.running = false;
|
storedMatch.running = false;
|
||||||
storedMatch.lastTickAt = null;
|
storedMatch.lastTickAt = null;
|
||||||
logEvent(storedMatch, `Partie ${storedMatch.blockNumber} mise en pause.`);
|
logEvent(storedMatch, `${formatBlockHeading(storedMatch, storedMatch.blockNumber)} passe en pause.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function requestBlockClosure(storedMatch, reason) {
|
function requestBlockClosure(storedMatch, reason) {
|
||||||
@@ -1388,7 +1434,7 @@ function prepareNextTimeBlock(storedMatch) {
|
|||||||
storedMatch.cube.number = null;
|
storedMatch.cube.number = null;
|
||||||
logEvent(
|
logEvent(
|
||||||
storedMatch,
|
storedMatch,
|
||||||
`Partie ${storedMatch.blockNumber} prete. Le trait est conserve : ${playerName(
|
`${formatBlockHeading(storedMatch, storedMatch.blockNumber)} pret. Le trait est conserve : ${playerName(
|
||||||
storedMatch,
|
storedMatch,
|
||||||
storedMatch.currentTurn,
|
storedMatch.currentTurn,
|
||||||
)} reprend.`,
|
)} reprend.`,
|
||||||
@@ -1489,7 +1535,7 @@ function registerFreeDoubleMove(storedMatch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function registerMoveTimeout(storedMatch, automatic) {
|
function registerMoveTimeout(storedMatch, automatic) {
|
||||||
if (!storedMatch || storedMatch.phase !== "block") {
|
if (!storedMatch || storedMatch.phase !== "block" || !usesMoveLimit(storedMatch)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1718,6 +1764,34 @@ function getDurationInputMs(form, name, fallbackMs) {
|
|||||||
return seconds * 1000;
|
return seconds * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isTimeMode(matchOrConfig) {
|
||||||
|
const mode =
|
||||||
|
typeof matchOrConfig === "string"
|
||||||
|
? matchOrConfig
|
||||||
|
: matchOrConfig?.config?.mode ?? matchOrConfig?.mode;
|
||||||
|
return mode === "time";
|
||||||
|
}
|
||||||
|
|
||||||
|
function usesMoveLimit(matchOrConfig) {
|
||||||
|
return !isTimeMode(matchOrConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBlockLabel(matchOrConfig) {
|
||||||
|
return isTimeMode(matchOrConfig) ? "Block" : "Partie";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBlockPhrase(matchOrConfig) {
|
||||||
|
return isTimeMode(matchOrConfig) ? "Le Block" : "La partie";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBlockGenitivePhrase(matchOrConfig) {
|
||||||
|
return isTimeMode(matchOrConfig) ? "du Block" : "de la partie";
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatBlockHeading(matchOrConfig, blockNumber) {
|
||||||
|
return `${getBlockLabel(matchOrConfig)} ${blockNumber}`;
|
||||||
|
}
|
||||||
|
|
||||||
function playerName(storedMatch, color) {
|
function playerName(storedMatch, color) {
|
||||||
return color === "white" ? storedMatch.config.whiteName : storedMatch.config.blackName;
|
return color === "white" ? storedMatch.config.whiteName : storedMatch.config.blackName;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
<li>Configurer la rencontre</li>
|
<li>Configurer la rencontre</li>
|
||||||
<li>Passer à la page chrono</li>
|
<li>Passer à la page chrono</li>
|
||||||
<li>Basculer automatiquement sur la page cube</li>
|
<li>Basculer automatiquement sur la page cube</li>
|
||||||
<li>Revenir sur la page chrono pour la partie suivante</li>
|
<li>Revenir sur la page chrono pour le Block suivant</li>
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
@@ -90,7 +90,7 @@
|
|||||||
<input type="radio" name="mode" value="time" />
|
<input type="radio" name="mode" value="time" />
|
||||||
<strong>ChessCubing Time</strong>
|
<strong>ChessCubing Time</strong>
|
||||||
<span>
|
<span>
|
||||||
Même structure de parties, avec chronos cumulés et alternance
|
Même structure de Blocks, avec chronos cumulés et alternance
|
||||||
bloc - / bloc +.
|
bloc - / bloc +.
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset class="field span-2">
|
<fieldset class="field span-2">
|
||||||
<legend>Cadence de la partie</legend>
|
<legend>Cadence du match</legend>
|
||||||
<div class="option-grid preset-grid">
|
<div class="option-grid preset-grid">
|
||||||
<label class="option-card">
|
<label class="option-card">
|
||||||
<input type="radio" name="preset" value="fast" checked />
|
<input type="radio" name="preset" value="fast" checked />
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
<legend>Temps personnalisés</legend>
|
<legend>Temps personnalisés</legend>
|
||||||
<div class="timing-grid">
|
<div class="timing-grid">
|
||||||
<label class="field">
|
<label class="field">
|
||||||
<span>Temps partie (secondes)</span>
|
<span>Temps du Block (secondes)</span>
|
||||||
<input
|
<input
|
||||||
name="blockSeconds"
|
name="blockSeconds"
|
||||||
type="number"
|
type="number"
|
||||||
@@ -132,7 +132,7 @@
|
|||||||
value="180"
|
value="180"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<label class="field">
|
<label class="field" id="moveSecondsField">
|
||||||
<span>Temps coup (secondes)</span>
|
<span>Temps coup (secondes)</span>
|
||||||
<input
|
<input
|
||||||
name="moveSeconds"
|
name="moveSeconds"
|
||||||
@@ -218,7 +218,7 @@
|
|||||||
<p>
|
<p>
|
||||||
Chaque joueur dispose d'une grande zone tactile pour signaler la
|
Chaque joueur dispose d'une grande zone tactile pour signaler la
|
||||||
fin de son coup, puis l'app ouvre automatiquement la phase cube
|
fin de son coup, puis l'app ouvre automatiquement la phase cube
|
||||||
quand la partie d'échecs est terminée.
|
quand le Block d'échecs est terminé.
|
||||||
</p>
|
</p>
|
||||||
</article>
|
</article>
|
||||||
<article class="rule-card">
|
<article class="rule-card">
|
||||||
|
|||||||
14
chrono.html
14
chrono.html
@@ -29,7 +29,7 @@
|
|||||||
</a>
|
</a>
|
||||||
<div class="phase-title">
|
<div class="phase-title">
|
||||||
<p class="eyebrow">Phase chrono</p>
|
<p class="eyebrow">Phase chrono</p>
|
||||||
<h1 id="chronoTitle">Partie 1</h1>
|
<h1 id="chronoTitle">Block 1</h1>
|
||||||
<p id="chronoSubtitle" class="phase-subtitle"></p>
|
<p id="chronoSubtitle" class="phase-subtitle"></p>
|
||||||
</div>
|
</div>
|
||||||
<button class="button ghost small utility-button" id="openArbiterButton" type="button">
|
<button class="button ghost small utility-button" id="openArbiterButton" type="button">
|
||||||
@@ -39,10 +39,10 @@
|
|||||||
|
|
||||||
<section class="status-strip">
|
<section class="status-strip">
|
||||||
<article class="status-card">
|
<article class="status-card">
|
||||||
<span>Temps partie</span>
|
<span id="blockTimerLabel">Temps Block</span>
|
||||||
<strong id="blockTimer">03:00</strong>
|
<strong id="blockTimer">03:00</strong>
|
||||||
</article>
|
</article>
|
||||||
<article class="status-card">
|
<article class="status-card" id="moveTimerCard">
|
||||||
<span>Temps coup</span>
|
<span>Temps coup</span>
|
||||||
<strong id="moveTimer">00:20</strong>
|
<strong id="moveTimer">00:20</strong>
|
||||||
</article>
|
</article>
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="zone-stats">
|
<div class="zone-stats">
|
||||||
<strong id="blackMovesChrono">0 / 6</strong>
|
<strong id="blackMovesChrono">0 / 6</strong>
|
||||||
<span id="blackClockChrono"></span>
|
<span class="player-clock" id="blackClockChrono"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -76,13 +76,13 @@
|
|||||||
|
|
||||||
<article class="phase-spine">
|
<article class="phase-spine">
|
||||||
<div class="spine-card">
|
<div class="spine-card">
|
||||||
<p class="micro-label" id="spineLabel">État de la partie</p>
|
<p class="micro-label" id="spineLabel">État du Block</p>
|
||||||
<strong id="spineHeadline">Prêt à démarrer</strong>
|
<strong id="spineHeadline">Prêt à démarrer</strong>
|
||||||
<p id="spineText"></p>
|
<p id="spineText"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="button primary spine-button" id="primaryChronoButton" type="button">
|
<button class="button primary spine-button" id="primaryChronoButton" type="button">
|
||||||
Démarrer la partie
|
Démarrer le Block
|
||||||
</button>
|
</button>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="zone-stats">
|
<div class="zone-stats">
|
||||||
<strong id="whiteMovesChrono">0 / 6</strong>
|
<strong id="whiteMovesChrono">0 / 6</strong>
|
||||||
<span id="whiteClockChrono"></span>
|
<span class="player-clock" id="whiteClockChrono"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
<section class="status-strip">
|
<section class="status-strip">
|
||||||
<article class="status-card">
|
<article class="status-card">
|
||||||
<span>Partie</span>
|
<span id="cubeBlockLabelText">Block</span>
|
||||||
<strong id="cubeBlockLabel">1</strong>
|
<strong id="cubeBlockLabel">1</strong>
|
||||||
</article>
|
</article>
|
||||||
<article class="status-card">
|
<article class="status-card">
|
||||||
|
|||||||
@@ -264,16 +264,16 @@
|
|||||||
|
|
||||||
<div class="format-badges">
|
<div class="format-badges">
|
||||||
<span>Temps initial : 10 min / joueur</span>
|
<span>Temps initial : 10 min / joueur</span>
|
||||||
<span>Partie : 180 s</span>
|
<span>Block : 180 s</span>
|
||||||
<span>Cap cube pris en compte : 120 s</span>
|
<span>Cap cube pris en compte : 120 s</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="format-section">
|
<div class="format-section">
|
||||||
<h4>Structure temporelle</h4>
|
<h4>Structure temporelle</h4>
|
||||||
<ul class="rule-list compact">
|
<ul class="rule-list compact">
|
||||||
<li>La structure des parties est identique à celle du Twice.</li>
|
<li>La structure des Blocks est identique à celle du Twice.</li>
|
||||||
<li>Les quotas de coups restent les mêmes : 6, 8 ou 10.</li>
|
<li>Les quotas de coups restent les mêmes : 6, 8 ou 10.</li>
|
||||||
<li>Chaque partie est suivie d'une phase cube obligatoire.</li>
|
<li>Chaque Block est suivi d'une phase cube obligatoire.</li>
|
||||||
<li>Le trait est conservé après la phase cube.</li>
|
<li>Le trait est conservé après la phase cube.</li>
|
||||||
<li>Aucun système de priorité ou de double coup n'existe.</li>
|
<li>Aucun système de priorité ou de double coup n'existe.</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -281,7 +281,7 @@
|
|||||||
|
|
||||||
<div class="split-callouts">
|
<div class="split-callouts">
|
||||||
<article class="split-card minus-card">
|
<article class="split-card minus-card">
|
||||||
<span class="micro-label">Partie impaire</span>
|
<span class="micro-label">Block impair</span>
|
||||||
<strong>Bloc -</strong>
|
<strong>Bloc -</strong>
|
||||||
<p>
|
<p>
|
||||||
Le temps de résolution du cube est retiré du chrono du
|
Le temps de résolution du cube est retiré du chrono du
|
||||||
@@ -289,7 +289,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</article>
|
</article>
|
||||||
<article class="split-card plus-card">
|
<article class="split-card plus-card">
|
||||||
<span class="micro-label">Partie paire</span>
|
<span class="micro-label">Block pair</span>
|
||||||
<strong>Bloc +</strong>
|
<strong>Bloc +</strong>
|
||||||
<p>
|
<p>
|
||||||
Le temps de résolution du cube est ajouté au chrono adverse,
|
Le temps de résolution du cube est ajouté au chrono adverse,
|
||||||
|
|||||||
69
styles.css
69
styles.css
@@ -2389,3 +2389,72 @@ body[data-page="chrono"] .spine-button {
|
|||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.time-setup-mode .timing-grid {
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-page="chrono"].time-mode .status-strip {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-page="chrono"] .has-player-clock .zone-stats {
|
||||||
|
gap: 0.45rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-page="chrono"] .has-player-clock .zone-stats strong {
|
||||||
|
color: var(--muted);
|
||||||
|
font-size: 0.92rem;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-page="chrono"] .player-clock {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
justify-self: end;
|
||||||
|
min-width: min(100%, 10ch);
|
||||||
|
padding: 0.55rem 0.8rem;
|
||||||
|
border: 1px solid var(--panel-border-strong);
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(255, 255, 255, 0.06);
|
||||||
|
color: var(--text);
|
||||||
|
font-size: clamp(1.3rem, 3.6vw, 2.35rem);
|
||||||
|
font-weight: 900;
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
line-height: 1;
|
||||||
|
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.03);
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-page="chrono"] #whiteClockChrono.player-clock {
|
||||||
|
color: var(--white-seat);
|
||||||
|
background: rgba(255, 177, 58, 0.12);
|
||||||
|
border-color: rgba(255, 177, 58, 0.28);
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-page="chrono"] #blackClockChrono.player-clock {
|
||||||
|
color: var(--dark-seat);
|
||||||
|
background: rgba(23, 98, 255, 0.12);
|
||||||
|
border-color: rgba(23, 98, 255, 0.28);
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-page="chrono"] .player-clock.active-clock {
|
||||||
|
box-shadow:
|
||||||
|
0 0 0 1px rgba(255, 255, 255, 0.08),
|
||||||
|
0 0 24px rgba(255, 255, 255, 0.06);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-page="chrono"] .player-clock.negative-clock {
|
||||||
|
color: #ffd6dc;
|
||||||
|
background: rgba(255, 100, 127, 0.16);
|
||||||
|
border-color: rgba(255, 100, 127, 0.34);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
body[data-page="chrono"] .player-clock {
|
||||||
|
min-width: 7.7ch;
|
||||||
|
padding: 0.45rem 0.68rem;
|
||||||
|
font-size: clamp(1.05rem, 5.8vw, 1.7rem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user