fix(14-1): re-rack logic, turn button label, and foul input

- Re-rack logic fixed to accumulate and score correctly
- Turn switch button now shows two opposing arrows (⇄)
- Two foul buttons replaced by a single 'Foul -1' button styled like re-rack, can be pressed multiple times

Refs #26
This commit is contained in:
Frank Schwenk
2025-06-24 11:06:20 +02:00
parent e6a5dcebbe
commit bcf793b9e3

View File

@@ -123,41 +123,32 @@ const GameDetail141 = ({ game, onUpdate, onUndo, onForfeit, onBack }) => {
setPendingBallsLeft(num); setPendingBallsLeft(num);
}; };
const handleFoul = (foulType) => { // Foul: each press adds 1 foul point
let foulPoints = 0; const handleFoul = () => {
let penalty = 0; setPendingFouls(pendingFouls + 1);
let newConsecutiveFouls = (currentPlayer.consecutiveFouls || 0) + 1;
if (foulType === 'standard') foulPoints = 1;
else if (foulType === 'break') foulPoints = 2;
if (newConsecutiveFouls === 3) penalty = 15;
setPendingFouls(pendingFouls + foulPoints + penalty);
}; };
// Re-rack: accumulate total balls added
const handleReRack = (ballsToAdd) => { const handleReRack = (ballsToAdd) => {
setPendingReRack(pendingReRack + ballsToAdd); setPendingReRack(pendingReRack + ballsToAdd);
}; };
// Turn change button handler // Turn change button handler
const handleTurnChange = () => { const handleTurnChange = () => {
// Calculate balls potted
const ballsOnTableBefore = game.ballsOnTable; const ballsOnTableBefore = game.ballsOnTable;
const ballsLeft = pendingBallsLeft !== null ? pendingBallsLeft : ballsOnTableBefore; const ballsLeft = pendingBallsLeft !== null ? pendingBallsLeft : ballsOnTableBefore;
const ballsPotted = ballsOnTableBefore - ballsLeft; const ballsPotted = ballsOnTableBefore - ballsLeft;
// Calculate score
let newScore = currentPlayer.score + ballsPotted - pendingFouls; let newScore = currentPlayer.score + ballsPotted - pendingFouls;
// Handle re-rack scoring // Re-rack logic: if any re-rack, add correct points and set balls on table to 15
if (pendingReRack > 0) { if (pendingReRack > 0) {
const scoreIncrement = ballsLeft + pendingReRack - 15; const scoreIncrement = ballsLeft + pendingReRack - 15;
newScore += scoreIncrement; newScore += scoreIncrement;
} }
// Update player state
const updatedPlayers = game.players.map((p, idx) => const updatedPlayers = game.players.map((p, idx) =>
idx === game.currentPlayer ? { ...p, score: newScore, consecutiveFouls: pendingFouls > 0 ? 0 : (p.consecutiveFouls || 0) } : p idx === game.currentPlayer ? { ...p, score: newScore, consecutiveFouls: pendingFouls > 0 ? 0 : (p.consecutiveFouls || 0) } : p
); );
// Update balls on table
let newBallsOnTable = ballsLeft; let newBallsOnTable = ballsLeft;
if (pendingReRack > 0) newBallsOnTable = 15; if (pendingReRack > 0) newBallsOnTable = 15;
// Log turn
const newLog = [...(game.log || []), { const newLog = [...(game.log || []), {
type: 'turn', type: 'turn',
player: currentPlayer.name, player: currentPlayer.name,
@@ -167,7 +158,6 @@ const GameDetail141 = ({ game, onUpdate, onUndo, onForfeit, onBack }) => {
ballsOnTable: newBallsOnTable, ballsOnTable: newBallsOnTable,
reRack: pendingReRack > 0 ? pendingReRack : undefined reRack: pendingReRack > 0 ? pendingReRack : undefined
}]; }];
// Advance player
const nextPlayer = (game.currentPlayer + 1) % game.players.length; const nextPlayer = (game.currentPlayer + 1) % game.players.length;
onUpdate({ onUpdate({
...game, ...game,
@@ -176,7 +166,6 @@ const GameDetail141 = ({ game, onUpdate, onUndo, onForfeit, onBack }) => {
currentPlayer: nextPlayer, currentPlayer: nextPlayer,
log: newLog, log: newLog,
}); });
// Reset local state
setPendingBallsLeft(null); setPendingBallsLeft(null);
setPendingFouls(0); setPendingFouls(0);
setPendingReRack(0); setPendingReRack(0);
@@ -228,17 +217,13 @@ const GameDetail141 = ({ game, onUpdate, onUndo, onForfeit, onBack }) => {
<div className={styles['rerack-controls']}> <div className={styles['rerack-controls']}>
<button onClick={() => handleReRack(14)} className={styles['rerack-btn'] + (pendingReRack === 14 ? ' ' + styles['selected'] : '')}>+14 Re-Rack</button> <button onClick={() => handleReRack(14)} className={styles['rerack-btn'] + (pendingReRack === 14 ? ' ' + styles['selected'] : '')}>+14 Re-Rack</button>
<button onClick={() => handleReRack(15)} className={styles['rerack-btn'] + (pendingReRack === 15 ? ' ' + styles['selected'] : '')}>+15 Re-Rack</button> <button onClick={() => handleReRack(15)} className={styles['rerack-btn'] + (pendingReRack === 15 ? ' ' + styles['selected'] : '')}>+15 Re-Rack</button>
</div> <button onClick={handleFoul} className={styles['rerack-btn'] + (pendingFouls > 0 ? ' ' + styles['selected'] : '')}>Foul -1</button>
<div className={styles['foul-controls']}>
<button onClick={() => handleFoul('standard')} className={styles['foul-btn']}>Standard Foul (-1)</button>
<button onClick={() => handleFoul('break')} className={styles['foul-btn']}>Break Foul (-2)</button>
{pendingFouls > 0 && <span className={styles['pending-foul-info']}>Foulpunkte: {pendingFouls}</span>} {pendingFouls > 0 && <span className={styles['pending-foul-info']}>Foulpunkte: {pendingFouls}</span>}
</div> </div>
<div className={styles['turn-change-controls']}> <div className={styles['turn-change-controls']}>
<button className={styles['turn-change-btn']} onClick={handleTurnChange}> <button className={styles['turn-change-btn']} onClick={handleTurnChange}>
Aufnahme beenden / Turn wechseln
</button> </button>
</div> </div>