export class ScoreEntry { constructor(score, total, foul, wasOverflow, wasWin) { this.score = score; this.total = total; this.fouls = foul; this.wasOverflow = wasOverflow; this.wasWin = wasWin; } }; export class Scorecard { constructor(rules) { this.rules = rules; this.reset(); } reset() { this._player1Scores = []; this._player2Scores = []; } addPlayer1Score(newScore) { this._addScore(this._player1Scores, newScore); } removeLastPlayer1Score() { this._player1Scores.pop(); } addPlayer2Score(newScore) { this._addScore(this._player2Scores, newScore); } removeLastPlayer2Score() { this._player2Scores.pop(); } _addScore(playerScores, newScore) { let lastEntry; if (playerScores.length === 0) { lastEntry = new ScoreEntry(0, 0, 0, false, false); } else { lastEntry = playerScores[playerScores.length - 1]; } let newEntry = this._newEntryFromPrevious(newScore, lastEntry); playerScores.push(newEntry); } length() { return Math.max(this._player1Scores.length, this._player2Scores.length); } pairs() { let pairs = []; for (let i = 0; i < this.length(); i++) { pairs.push({ p1: (i < this._player1Scores.length ? this._player1Scores[i] : null), p2: (i < this._player2Scores.length ? this._player2Scores[i] : null), }) } return pairs; } _newEntryFromPrevious(score, previousScoreEntry) { if (previousScoreEntry === null) { return new ScoreEntry(score, score, (score === 0 ? 1 : 0)); } let wasOverflow = false, wasWin = false; let newTotal = previousScoreEntry.total + score; if (newTotal === this.rules.maxScore) { wasWin = true; } else if (newTotal > this.rules.maxScore) { newTotal = this.rules.overflowScoreTo; wasOverflow = true; } let newFouls = previousScoreEntry.foul; if (score === 0) { newFouls++; } return new ScoreEntry(score, newTotal, newFouls, wasOverflow, wasWin); } toJson() { return { "version": 1, "rules": this.rules, "p1": { "scores": this._player1Scores.map(p => p.score) }, "p2": { "scores": this._player2Scores.map(p => p.score) }, }; } static fromJson(o) { let scorecard = new Scorecard(o.rules); o["p1"]["scores"].forEach(x => scorecard.addPlayer1Score(x)); o["p2"]["scores"].forEach(x => scorecard.addPlayer2Score(x)); return scorecard; } } class StoreDAO { constructor(localStorage) { this._localStorage = localStorage; } save(scoreCard) { this._localStorage.setItem('score_card', JSON.stringify(scoreCard.toJson())); } loadOrCreate(rules) { try { console.log("Loading scorecard"); let scoreCardJson = this._localStorage.getItem('score_card'); if (scoreCardJson !== null) { return Scorecard.fromJson(JSON.parse(scoreCardJson)); } } catch (e) { console.log(`Could not restore game: ${e}`); } return new Scorecard(rules); } clear() { this._localStorage.clear(); } } class DummyStoreDAO { save(scoreCard) { } loadOrCreate(rules) { return new Scorecard(rules); } clear() { } } export function getStoreDAO() { if (!!window.localStorage) { return new StoreDAO(window.localStorage); } else { return new DummyStoreDAO(); } }