Changed all occurrences of 'yahtzee' to 'superkadi', allowed the gameboards to be hydrated by JSON data upon instantiation (also after).

This commit is contained in:
Daniel Ledda
2020-06-28 13:21:06 +02:00
parent 166ec7525a
commit bc0b4cfe4d
14 changed files with 108 additions and 86 deletions

View File

@@ -1,8 +1,7 @@
import {ScoreCellValue} from "./ScoreCell"; import {ScoreCellValue} from "./ScoreCell";
import ScoreBlock, {createBlockFromDef, BlockState, ScoreBlockJSONRepresentation} from "./ScoreBlock"; import ScoreBlock, {createBlockFromDef, BlockState, ScoreBlockJSONRepresentation} from "./ScoreBlock";
import {BlockDef, GameSchema} from "../static/rulesets"; import {BlockDef, Ruleset, CellFlag} from "../../../shared/rulesets";
import { Memento, Originator } from "./Caretaker"; import { Memento, Originator } from "./Caretaker";
import {CellFlag} from "../static/enums";
export type CellLocation = { blockId: string, cellId: string }; export type CellLocation = { blockId: string, cellId: string };
@@ -10,9 +9,23 @@ class PlayerScoreCard implements Originator {
private readonly playerId: string; private readonly playerId: string;
private readonly blocks: ScoreBlock[]; private readonly blocks: ScoreBlock[];
constructor(playerId: string, gameSchema: GameSchema) { constructor(jsonRep: PlayerScoreCardJSONRepresentation, gameSchema: Ruleset);
this.playerId = playerId; constructor(playerId: string, gameSchema: Ruleset)
this.blocks = PlayerScoreCard.generateBlocks(gameSchema.blocks); constructor(...args: any[]) {
this.blocks = PlayerScoreCard.generateBlocks(args[1].blocks);
if (typeof args[0] === "string") {
this.playerId = args[0];
}
else {
this.playerId = (args[0] as PlayerScoreCardJSONRepresentation).playerId;
this.restoreFromJSON(args[0]);
}
}
private restoreFromJSON(jsonRep: PlayerScoreCardJSONRepresentation): void {
for (const block of this.blocks) {
block.restoreFromJSON(jsonRep.blocks[block.getId()]);
}
} }
private static generateBlocks(blockDefs: Record<string, BlockDef>): ScoreBlock[] { private static generateBlocks(blockDefs: Record<string, BlockDef>): ScoreBlock[] {
@@ -97,9 +110,9 @@ class PlayerScoreCard implements Originator {
getJSONRepresentation(): PlayerScoreCardJSONRepresentation { getJSONRepresentation(): PlayerScoreCardJSONRepresentation {
const JSONRepresentation: PlayerScoreCardJSONRepresentation = { const JSONRepresentation: PlayerScoreCardJSONRepresentation = {
playerId: this.playerId, playerId: this.playerId,
blocks: [] blocks: {}
}; };
this.blocks.forEach(block => JSONRepresentation.blocks.push(block.getJSONRepresentation())); this.blocks.forEach(block => JSONRepresentation.blocks[block.getId()] = block.getJSONRepresentation());
return JSONRepresentation; return JSONRepresentation;
} }
} }
@@ -110,7 +123,7 @@ interface PlayerScoreCardState {
export interface PlayerScoreCardJSONRepresentation { export interface PlayerScoreCardJSONRepresentation {
playerId: string; playerId: string;
blocks: ScoreBlockJSONRepresentation[]; blocks: Record<string, ScoreBlockJSONRepresentation>;
} }
class PlayerScoreCardMemento implements Memento { class PlayerScoreCardMemento implements Memento {

View File

@@ -4,8 +4,7 @@ import ScoreCell, {
CellState, CellState,
ScoreCellJSONRepresentation ScoreCellJSONRepresentation
} from "./ScoreCell"; } from "./ScoreCell";
import {CellDef, BlockDef, BonusBlockDef, NoBonusBlockDef } from "../static/rulesets"; import {CellDef, BlockDef, BonusBlockDef, NoBonusBlockDef, CellFlag } from "../../../shared/rulesets";
import {CellFlag} from "../static/enums";
export const createBlockFromDef = (blockId: string, blockDef: BlockDef) : ScoreBlock => { export const createBlockFromDef = (blockId: string, blockDef: BlockDef) : ScoreBlock => {
if (blockDef.hasBonus) { if (blockDef.hasBonus) {
@@ -22,8 +21,7 @@ export interface BlockState {
} }
export interface ScoreBlockJSONRepresentation { export interface ScoreBlockJSONRepresentation {
id: string; cells: Record<string, ScoreCellJSONRepresentation>;
cells: ScoreCellJSONRepresentation[];
} }
abstract class ScoreBlock { abstract class ScoreBlock {
@@ -108,12 +106,17 @@ abstract class ScoreBlock {
getJSONRepresentation(): ScoreBlockJSONRepresentation { getJSONRepresentation(): ScoreBlockJSONRepresentation {
const JSONRepresentation: ScoreBlockJSONRepresentation = { const JSONRepresentation: ScoreBlockJSONRepresentation = {
id: this.id, cells: {}
cells: []
}; };
this.cells.forEach(cell => JSONRepresentation.cells.push(cell.getJSONRepresentation())); this.cells.forEach(cell => JSONRepresentation.cells[cell.getId()] = cell.getJSONRepresentation());
return JSONRepresentation; return JSONRepresentation;
} }
restoreFromJSON(jsonRep: ScoreBlockJSONRepresentation): void {
for (const cell of this.cells) {
cell.restoreFromJSON(jsonRep.cells[cell.getId()]);
}
}
} }
class ScoreBlockWithBonus extends ScoreBlock { class ScoreBlockWithBonus extends ScoreBlock {

View File

@@ -1,7 +1,14 @@
import {CellFlag, FieldType} from "../static/enums"; import {
import {BoolCellDef, CellDef, MultiplierCellDef, NumberCellDef, YahtzeeCellDef} from "../static/rulesets" BoolCellDef,
CellDef,
CellFlag,
FieldType,
MultiplierCellDef,
NumberCellDef,
SuperkadiCellDef
} from "../../../shared/rulesets";
export const createCellFromDef = (cellId: string, cellDef: CellDef) : ScoreCell => { export const createCellFromDef = (cellId: string, cellDef: CellDef): ScoreCell => {
switch (cellDef.fieldType) { switch (cellDef.fieldType) {
case FieldType.number: case FieldType.number:
return new NumberScoreCell(cellId, cellDef); return new NumberScoreCell(cellId, cellDef);
@@ -9,8 +16,8 @@ export const createCellFromDef = (cellId: string, cellDef: CellDef) : ScoreCell
return new BoolScoreCell(cellId, cellDef); return new BoolScoreCell(cellId, cellDef);
case FieldType.multiplier: case FieldType.multiplier:
return new MultiplierScoreCell(cellId, cellDef); return new MultiplierScoreCell(cellId, cellDef);
case FieldType.yahtzee: case FieldType.superkadi:
return new YahtzeeScoreCell(cellId, cellDef); return new SuperkadiScoreCell(cellId, cellDef);
} }
}; };
@@ -24,7 +31,6 @@ export interface CellState {
} }
export interface ScoreCellJSONRepresentation { export interface ScoreCellJSONRepresentation {
id: string;
value: number | boolean | CellFlag.strike; value: number | boolean | CellFlag.strike;
} }
@@ -79,7 +85,11 @@ abstract class ScoreCell {
} }
getJSONRepresentation(): ScoreCellJSONRepresentation { getJSONRepresentation(): ScoreCellJSONRepresentation {
return { id: this.id, value: this.isStruck() ? CellFlag.strike : this.value }; return { value: this.isStruck() ? CellFlag.strike : this.value };
}
restoreFromJSON(jsonRep: ScoreCellJSONRepresentation): void {
this.update(jsonRep.value);
} }
} }
@@ -202,17 +212,17 @@ class BoolScoreCell extends IterableScoreCell {
} }
} }
class YahtzeeScoreCell extends IterableScoreCell { class SuperkadiScoreCell extends IterableScoreCell {
protected static readonly fieldType = FieldType.yahtzee; protected static readonly fieldType = FieldType.superkadi;
private readonly score: number; private readonly score: number;
protected value: number; protected value: number;
constructor(cellId: string, cellDef: YahtzeeCellDef) { constructor(cellId: string, cellDef: SuperkadiCellDef) {
super(cellId, cellDef); super(cellId, cellDef);
this.score = cellDef.score; this.score = cellDef.score;
this.value = 0; this.value = 0;
for (let i = 0; i <= cellDef.maxYahtzees; i++) { for (let i = 0; i <= cellDef.maxSuperkadis; i++) {
this.iteratedSequence.push(i); this.iteratedSequence.push(i);
} }
} }

View File

@@ -1,7 +1,7 @@
import React, {ReactNode} from "react"; import React, {ReactNode} from "react";
import KadiCell from "./KadiCell"; import KadiCell from "./KadiCell";
import {FieldType} from "../static/enums";
import {CellScores} from "./KadiBoard"; import {CellScores} from "./KadiBoard";
import {FieldType} from "../../../shared/rulesets";
interface KadiBlockBonusRowProps { interface KadiBlockBonusRowProps {
blockId: string; blockId: string;

View File

@@ -1,8 +1,5 @@
import {BlockDef} from "../static/rulesets";
import {CellLocation} from "../Classes/PlayerScoreCard";
import React, {ReactElement} from "react"; import React, {ReactElement} from "react";
import {formatUnicorn} from "../static/strings"; import {formatUnicorn} from "../static/strings";
import {FieldType} from "../static/enums";
import {BlockScores, CellEventResponse} from "./KadiBoard"; import {BlockScores, CellEventResponse} from "./KadiBoard";
import GenericKadiRowContainer from "./GenericKadiRowContainer"; import GenericKadiRowContainer from "./GenericKadiRowContainer";
import KadiEditableRowCells from "./KadiEditableRowCells"; import KadiEditableRowCells from "./KadiEditableRowCells";
@@ -10,6 +7,7 @@ import KadiBlockTotalRow from "./KadiBlockTotalRow";
import KadiBlockSubtotalRow from "./KadiBlockSubtotalRow"; import KadiBlockSubtotalRow from "./KadiBlockSubtotalRow";
import KadiBlockBonusRow from "./KadiBlockBonusRow"; import KadiBlockBonusRow from "./KadiBlockBonusRow";
import LocaleContext from "../LocaleContext"; import LocaleContext from "../LocaleContext";
import {BlockDef, FieldType} from "../../../shared/rulesets";
interface BlockRendererProps { interface BlockRendererProps {
blockId: string; blockId: string;

View File

@@ -1,7 +1,7 @@
import React, {ReactNode} from "react"; import React, {ReactNode} from "react";
import KadiCell from "./KadiCell"; import KadiCell from "./KadiCell";
import {FieldType} from "../static/enums";
import {CellScores} from "./KadiBoard"; import {CellScores} from "./KadiBoard";
import {FieldType} from "../../../shared/rulesets";
interface KadiBlockSubtotalRowProps { interface KadiBlockSubtotalRowProps {
blockId: string; blockId: string;

View File

@@ -1,7 +1,7 @@
import React, {ReactNode} from "react"; import React, {ReactNode} from "react";
import KadiCell from "./KadiCell"; import KadiCell from "./KadiCell";
import {FieldType} from "../static/enums";
import {CellScores} from "./KadiBoard"; import {CellScores} from "./KadiBoard";
import {FieldType} from "../../../shared/rulesets";
interface KadiBlockTotalRowProps { interface KadiBlockTotalRowProps {
blockId: string; blockId: string;

View File

@@ -1,8 +1,7 @@
import React, {ReactElement, ReactNode, useContext} from "react"; import React, {ReactElement, ReactNode, useContext} from "react";
import PlayerScoreCard, {CellLocation, PlayerScoreCardJSONRepresentation} from "../Classes/PlayerScoreCard"; import PlayerScoreCard, {CellLocation, PlayerScoreCardJSONRepresentation} from "../Classes/PlayerScoreCard";
import {GameSchema, getGameSchemaById} from "../static/rulesets"; import {getGameSchemaById} from "../static/rulesets";
import LocaleContext from "../LocaleContext"; import LocaleContext from "../LocaleContext";
import {CellFlag} from "../static/enums";
import {ScoreCellValue} from "../Classes/ScoreCell"; import {ScoreCellValue} from "../Classes/ScoreCell";
import {CaretakerSet} from "../Classes/Caretaker"; import {CaretakerSet} from "../Classes/Caretaker";
import {GameSettings} from "./GameSetup"; import {GameSettings} from "./GameSetup";
@@ -15,6 +14,7 @@ import KadiBlockRenderer from "./KadiBlockRenderer";
import {KadiCellDisplayValue} from "./KadiCell"; import {KadiCellDisplayValue} from "./KadiCell";
import {Player} from "./Game"; import {Player} from "./Game";
import {SERVER_BASE_NAME} from "../index"; import {SERVER_BASE_NAME} from "../index";
import {CellFlag, Ruleset} from "../../../shared/rulesets";
export interface CellScores { export interface CellScores {
@@ -53,7 +53,7 @@ interface ScoreSheet {
} }
class KadiBoard extends React.Component<KadiBoardProps, KadiBoardState> { class KadiBoard extends React.Component<KadiBoardProps, KadiBoardState> {
private readonly gameSchema: GameSchema; private readonly gameSchema: Ruleset;
private readonly caretaker: CaretakerSet; private readonly caretaker: CaretakerSet;
state: KadiBoardState; state: KadiBoardState;

View File

@@ -1,9 +1,9 @@
import React, {ChangeEvent, FocusEvent, ReactNode, KeyboardEvent} from "react"; import React, {ChangeEvent, FocusEvent, ReactNode, KeyboardEvent} from "react";
import {CellFlag, FieldType} from "../static/enums";
import {ScoreCellValue} from "../Classes/ScoreCell"; import {ScoreCellValue} from "../Classes/ScoreCell";
import {CellEventResponse} from "./KadiBoard"; import {CellEventResponse} from "./KadiBoard";
import {CellLocation} from "../Classes/PlayerScoreCard"; import {CellLocation} from "../Classes/PlayerScoreCard";
import {useLongPress} from "./useLongPress"; import {useLongPress} from "./useLongPress";
import {CellFlag, FieldType} from "../../../shared/rulesets";
export type KadiCellDisplayValue = ScoreCellValue | CellFlag.strike; export type KadiCellDisplayValue = ScoreCellValue | CellFlag.strike;
@@ -93,8 +93,8 @@ class KadiCell extends React.Component<KadiCellProps, KadiCellState> {
return <MultipleKadiCell {...propsForEditableCell}/>; return <MultipleKadiCell {...propsForEditableCell}/>;
case FieldType.number: case FieldType.number:
return <NumberKadiCell {...propsForEditableCell}/>; return <NumberKadiCell {...propsForEditableCell}/>;
case FieldType.yahtzee: case FieldType.superkadi:
return <YahtzeeKadiCell {...propsForEditableCell}/>; return <SuperkadiKadiCell {...propsForEditableCell}/>;
} }
} }
} }
@@ -185,16 +185,16 @@ const NumberKadiCell: React.FunctionComponent<EditableKadiCellProps> = ({ strike
) )
}; };
const YahtzeeKadiCell: React.FunctionComponent<EditableKadiCellProps> = ({value, timeoutMs, strikeCell, updateCell}) => { const SuperkadiKadiCell: React.FunctionComponent<EditableKadiCellProps> = ({value, timeoutMs, strikeCell, updateCell}) => {
const handleClick = (): void => updateCell(true); const handleClick = (): void => updateCell(true);
const strikeCellOnLongPress = useLongPress(strikeCell, timeoutMs); const strikeCellOnLongPress = useLongPress(strikeCell, timeoutMs);
return ( return (
<td <td
className={"kadiCell editable yahtzeeField"} className={"kadiCell editable superkadiField"}
onClick={handleClick} onClick={handleClick}
{...strikeCellOnLongPress} {...strikeCellOnLongPress}
> >
<div className={"yahtzeeField"}> <div className={"superkadiField"}>
{value} {value}
</div> </div>
</td> </td>

View File

@@ -1,8 +1,8 @@
import {CellLocation} from "../Classes/PlayerScoreCard"; import {CellLocation} from "../Classes/PlayerScoreCard";
import {FieldType} from "../static/enums";
import React, {ReactElement} from "react"; import React, {ReactElement} from "react";
import KadiCell from "./KadiCell"; import KadiCell from "./KadiCell";
import {CellEventResponse, CellScores} from "./KadiBoard"; import {CellEventResponse, CellScores} from "./KadiBoard";
import {FieldType} from "../../../shared/rulesets";
interface KadiEditableRowCellsProps { interface KadiEditableRowCellsProps {
location: CellLocation; location: CellLocation;

View File

@@ -1,9 +1,9 @@
import React, {ReactNode} from "react"; import React, {ReactNode} from "react";
import LocaleContext from "../LocaleContext"; import LocaleContext from "../LocaleContext";
import KadiCell from "./KadiCell"; import KadiCell from "./KadiCell";
import {FieldType} from "../static/enums";
import {Icon} from "semantic-ui-react"; import {Icon} from "semantic-ui-react";
import {CellScores} from "./KadiBoard"; import {CellScores} from "./KadiBoard";
import {FieldType} from "../../../shared/rulesets";
interface KadiGrandTotalRowProps { interface KadiGrandTotalRowProps {
showResults: boolean; showResults: boolean;

View File

@@ -125,7 +125,7 @@ div.subtotalField,
div.totalField, div.totalField,
div.bonusField, div.bonusField,
div.globalTotalField, div.globalTotalField,
div.yahtzeeField, div.superkadiField,
div.multipleField, div.multipleField,
div.numberField { div.numberField {
width: var(--default-field-width); width: var(--default-field-width);

View File

@@ -1,14 +1,3 @@
export enum FieldType {
number = "numberField",
bool = "boolField",
bonus = "bonusField",
subtotal = "subtotalField",
globalTotal = "globalTotalField",
total = "totalField",
yahtzee = "yahtzeeField",
multiplier = "multiplierField",
}
export enum CellFlag { export enum CellFlag {
strike = "cellFlagStrike", strike = "cellFlagStrike",
unstrike = "cellFlagUnstrike", unstrike = "cellFlagUnstrike",

View File

@@ -1,4 +1,13 @@
import { FieldType } from "./enums"; export enum FieldType {
number = "numberField",
bool = "boolField",
bonus = "bonusField",
subtotal = "subtotalField",
globalTotal = "globalTotalField",
total = "totalField",
superkadi = "superkadiField",
multiplier = "multiplierField",
}
export const defaultCellValues = { export const defaultCellValues = {
[FieldType.number]: 0, [FieldType.number]: 0,
@@ -6,12 +15,11 @@ export const defaultCellValues = {
[FieldType.subtotal]: 0, [FieldType.subtotal]: 0,
[FieldType.total]: 0, [FieldType.total]: 0,
[FieldType.bonus]: 0, [FieldType.bonus]: 0,
[FieldType.yahtzee]: 0, [FieldType.superkadi]: 0,
[FieldType.multiplier]: 0, [FieldType.multiplier]: 0,
}; };
// ----- gameSchema interface definitions export interface Ruleset {
export interface GameSchema {
id: string; id: string;
label: string; label: string;
blocks: Record<string, BlockDef>; blocks: Record<string, BlockDef>;
@@ -35,10 +43,10 @@ interface DefaultBlockDef {
} }
export type CellDef = export type CellDef =
| BoolCellDef | BoolCellDef
| MultiplierCellDef | MultiplierCellDef
| NumberCellDef | NumberCellDef
| YahtzeeCellDef; | SuperkadiCellDef;
export interface BoolCellDef extends DefaultCellDef { export interface BoolCellDef extends DefaultCellDef {
fieldType: FieldType.bool; fieldType: FieldType.bool;
@@ -51,10 +59,10 @@ export interface MultiplierCellDef extends DefaultCellDef {
maxMultiples: number; maxMultiples: number;
} }
export interface YahtzeeCellDef extends DefaultCellDef { export interface SuperkadiCellDef extends DefaultCellDef {
fieldType: FieldType.yahtzee; fieldType: FieldType.superkadi;
score: number; score: number;
maxYahtzees: number; maxSuperkadis: number;
} }
export interface NumberCellDef extends DefaultCellDef { export interface NumberCellDef extends DefaultCellDef {
@@ -65,11 +73,12 @@ interface DefaultCellDef {
label: string; label: string;
} }
// ----- Predefined sets // ----- Predefined sets
const defaultDiceCount = 5; const defaultDiceCount = 5;
const DEFAULT_RULESET = "DEFAULT_RULESET"; const DEFAULT_RULESET = "DEFAULT_RULESET";
const gameSchemas: GameSchema[] = [ const gameSchemas: Ruleset[] = [
{ {
id: DEFAULT_RULESET, id: DEFAULT_RULESET,
label: "Standard Kadi Rules (en)", label: "Standard Kadi Rules (en)",
@@ -127,39 +136,39 @@ const gameSchemas: GameSchema[] = [
label: "Lower", label: "Lower",
hasBonus: false, hasBonus: false,
cells: { cells: {
three_kind: { threeKind: {
fieldType: FieldType.number, fieldType: FieldType.number,
label: "Three of a Kind", label: "Three of a Kind",
}, },
four_kind: { fourKind: {
fieldType: FieldType.number, fieldType: FieldType.number,
label: "Four of a Kind", label: "Four of a Kind",
}, },
full_house: { fullHouse: {
fieldType: FieldType.bool, fieldType: FieldType.bool,
label: "Full House", label: "Full House",
score: 25, score: 25,
}, },
sml_straight: { smlStraight: {
fieldType: FieldType.bool, fieldType: FieldType.bool,
label: "Small Straight", label: "Small Straight",
score: 30, score: 30,
}, },
lg_straight: { lgSraight: {
fieldType: FieldType.bool, fieldType: FieldType.bool,
label: "Large Straight", label: "Large Straight",
score: 40, score: 40,
}, },
yahtzee: { kadi: {
fieldType: FieldType.yahtzee, fieldType: FieldType.superkadi,
label: "Kadi", label: "Super Kadis",
score: 50, score: 50,
maxYahtzees: 5, maxSuperkadis: 5,
}, },
chance: { chance: {
@@ -227,34 +236,34 @@ const gameSchemas: GameSchema[] = [
label: "Unten", label: "Unten",
hasBonus: false, hasBonus: false,
cells: { cells: {
three_kind: { threeKind: {
fieldType: FieldType.number, fieldType: FieldType.number,
label: "Dreierpasch", label: "Dreierpasch",
}, },
four_kind: { fourKind: {
fieldType: FieldType.number, fieldType: FieldType.number,
label: "Viererpasch", label: "Viererpasch",
}, },
full_house: { fullSouse: {
fieldType: FieldType.bool, fieldType: FieldType.bool,
label: "Full House", label: "Full House",
score: 25, score: 25,
}, },
sml_straight: { smlStraight: {
fieldType: FieldType.bool, fieldType: FieldType.bool,
label: "Kleine Straße", label: "Kleine Straße",
score: 30, score: 30,
}, },
lg_straight: { lgStraight: {
fieldType: FieldType.bool, fieldType: FieldType.bool,
label: "Große Straße", label: "Große Straße",
score: 40, score: 40,
}, },
yahtzee: { kadi: {
fieldType: FieldType.yahtzee, fieldType: FieldType.superkadi,
label: "Kadi", label: "Ultrakadi",
score: 50, score: 50,
maxYahtzees: 5, maxSuperkadis: 5,
}, },
change: { change: {
fieldType: FieldType.number, fieldType: FieldType.number,
@@ -266,7 +275,7 @@ const gameSchemas: GameSchema[] = [
}, },
]; ];
export function getGameSchemaById(schemaId: string): GameSchema { export function getGameSchemaById(schemaId: string): Ruleset {
for (const schema of gameSchemas) { for (const schema of gameSchemas) {
if (schema.id === schemaId) { if (schema.id === schemaId) {
return schema; return schema;