feat(#28): add break rule & order to games and UI
- Types: add BreakRule, break metadata to StandardGame, extend NewGameData/steps - NewGame: add BreakRule and BreakOrder steps with auto-advance - NewGameScreen: wire new steps into flow - GameService: set up defaults, persist break order, compute next breaker on +1 - GameDetail: show breaker indicator; treat -1 as undo equivalent Backfill defaults for existing games via service logic. Refs #28
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import type { Game, GameType, StandardGame, EndlosGame, NewGameData } from '../types/game';
|
||||
import type { Game, GameType, StandardGame, EndlosGame, NewGameData, BreakRule } from '../types/game';
|
||||
import { IndexedDBService } from './indexedDBService';
|
||||
|
||||
const LOCAL_STORAGE_KEY = 'bscscore_games';
|
||||
@@ -163,6 +163,25 @@ export class GameService {
|
||||
player2: gameData.player2,
|
||||
score1: 0,
|
||||
score2: 0,
|
||||
breakRule: (gameData.breakRule as BreakRule) || 'winnerbreak',
|
||||
breakOrder: (() => {
|
||||
// Determine break order from inputs, fallback defaults
|
||||
const players: number[] = [1, 2];
|
||||
if (gameData.player3?.trim()) players.push(3);
|
||||
const first = (typeof gameData.breakFirst === 'number' ? gameData.breakFirst : 1) as number;
|
||||
const second = (typeof gameData.breakSecond === 'number' ? gameData.breakSecond : (players.includes(2) && first !== 2 ? 2 : (players.includes(3) ? 3 : 2))) as number;
|
||||
const order = [first];
|
||||
if (players.length === 2) {
|
||||
order.push(first === 1 ? 2 : 1);
|
||||
} else {
|
||||
// 3 players: add chosen second, then the remaining third
|
||||
order.push(second);
|
||||
const third = [1,2,3].find(p => p !== first && p !== second)!;
|
||||
order.push(third);
|
||||
}
|
||||
return order;
|
||||
})(),
|
||||
currentBreakerIdx: 0,
|
||||
};
|
||||
|
||||
if (gameData.player3) {
|
||||
@@ -185,6 +204,23 @@ export class GameService {
|
||||
updated.score3 = Math.max(0, updated.score3 + change);
|
||||
}
|
||||
|
||||
// Breaker logic
|
||||
if (change > 0) {
|
||||
if ((updated.breakRule || 'winnerbreak') === 'winnerbreak') {
|
||||
// Winner keeps break: set breaker to this player
|
||||
const order = updated.breakOrder || [1,2].concat(updated.score3 !== undefined ? [3] : []);
|
||||
updated.breakOrder = order;
|
||||
const idx = order.findIndex(p => p === player);
|
||||
updated.currentBreakerIdx = idx >= 0 ? idx : 0;
|
||||
} else {
|
||||
// Wechselbreak: rotate to next
|
||||
const order = updated.breakOrder || [1,2].concat(updated.score3 !== undefined ? [3] : []);
|
||||
updated.breakOrder = order;
|
||||
const curr = typeof updated.currentBreakerIdx === 'number' ? updated.currentBreakerIdx : 0;
|
||||
updated.currentBreakerIdx = (curr + 1) % order.length;
|
||||
}
|
||||
}
|
||||
|
||||
updated.updatedAt = new Date().toISOString();
|
||||
return updated;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user