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 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 {CellFlag} from "../static/enums";
export type CellLocation = { blockId: string, cellId: string };
@@ -10,9 +9,23 @@ class PlayerScoreCard implements Originator {
private readonly playerId: string;
private readonly blocks: ScoreBlock[];
constructor(playerId: string, gameSchema: GameSchema) {
this.playerId = playerId;
this.blocks = PlayerScoreCard.generateBlocks(gameSchema.blocks);
constructor(jsonRep: PlayerScoreCardJSONRepresentation, gameSchema: Ruleset);
constructor(playerId: string, gameSchema: Ruleset)
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[] {
@@ -97,9 +110,9 @@ class PlayerScoreCard implements Originator {
getJSONRepresentation(): PlayerScoreCardJSONRepresentation {
const JSONRepresentation: PlayerScoreCardJSONRepresentation = {
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;
}
}
@@ -110,7 +123,7 @@ interface PlayerScoreCardState {
export interface PlayerScoreCardJSONRepresentation {
playerId: string;
blocks: ScoreBlockJSONRepresentation[];
blocks: Record<string, ScoreBlockJSONRepresentation>;
}
class PlayerScoreCardMemento implements Memento {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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