Changed the definition of the rulesets so there are no arrays.

This commit is contained in:
Daniel Ledda
2020-05-26 11:11:01 +02:00
parent 5342b7a48e
commit 166ec7525a
7 changed files with 298 additions and 304 deletions

View File

@@ -15,10 +15,10 @@ class PlayerScoreCard implements Originator {
this.blocks = PlayerScoreCard.generateBlocks(gameSchema.blocks); this.blocks = PlayerScoreCard.generateBlocks(gameSchema.blocks);
} }
private static generateBlocks(blockDefs: BlockDef[]): ScoreBlock[] { private static generateBlocks(blockDefs: Record<string, BlockDef>): ScoreBlock[] {
const blocks = []; const blocks = [];
for (const blockDef of blockDefs) { for (const blockId in blockDefs) {
blocks.push(createBlockFromDef(blockDef)); blocks.push(createBlockFromDef(blockId, blockDefs[blockId]));
} }
return blocks; return blocks;
} }

View File

@@ -7,12 +7,12 @@ import ScoreCell, {
import {CellDef, BlockDef, BonusBlockDef, NoBonusBlockDef } from "../static/rulesets"; import {CellDef, BlockDef, BonusBlockDef, NoBonusBlockDef } from "../static/rulesets";
import {CellFlag} from "../static/enums"; import {CellFlag} from "../static/enums";
export const createBlockFromDef = (blockDef: BlockDef) : ScoreBlock => { export const createBlockFromDef = (blockId: string, blockDef: BlockDef) : ScoreBlock => {
if (blockDef.hasBonus) { if (blockDef.hasBonus) {
return new ScoreBlockWithBonus(blockDef); return new ScoreBlockWithBonus(blockId, blockDef);
} }
else { else {
return new ScoreBlockNoBonus(blockDef); return new ScoreBlockNoBonus(blockId, blockDef);
} }
}; };
@@ -30,15 +30,15 @@ abstract class ScoreBlock {
protected cells: ScoreCell[]; protected cells: ScoreCell[];
protected id: string; protected id: string;
protected constructor(blockDef: BlockDef) { protected constructor(blockId: string, blockDef: BlockDef) {
this.cells = ScoreBlock.generateCells(blockDef.cells); this.cells = ScoreBlock.generateCells(blockDef.cells);
this.id = blockDef.id; this.id = blockId;
} }
private static generateCells(cellDefs: CellDef[]): ScoreCell[] { private static generateCells(cellDefs: Record<string, CellDef>): ScoreCell[] {
const cells = []; const cells = [];
for (const cellDef of cellDefs) { for (const cellId in cellDefs) {
cells.push(createCellFromDef(cellDef)); cells.push(createCellFromDef(cellId, cellDefs[cellId]));
} }
return cells; return cells;
} }
@@ -120,8 +120,8 @@ class ScoreBlockWithBonus extends ScoreBlock {
protected readonly bonus: number; protected readonly bonus: number;
protected readonly bonusFor: number; protected readonly bonusFor: number;
constructor(blockDef: BonusBlockDef) { constructor(blockId: string, blockDef: BonusBlockDef) {
super(blockDef); super(blockId, blockDef);
this.bonus = blockDef.bonusScore; this.bonus = blockDef.bonusScore;
this.bonusFor = blockDef.bonusFor; this.bonusFor = blockDef.bonusFor;
} }
@@ -137,8 +137,8 @@ class ScoreBlockWithBonus extends ScoreBlock {
} }
class ScoreBlockNoBonus extends ScoreBlock { class ScoreBlockNoBonus extends ScoreBlock {
constructor(blockDef: NoBonusBlockDef) { constructor(blockId: string, blockDef: NoBonusBlockDef) {
super(blockDef); super(blockId, blockDef);
} }
getTotal(): number { getTotal(): number {

View File

@@ -1,16 +1,16 @@
import {CellFlag, FieldType} from "../static/enums"; import {CellFlag, FieldType} from "../static/enums";
import {BoolCellDef, CellDef, MultiplierCellDef, NumberCellDef, YahtzeeCellDef} from "../static/rulesets" import {BoolCellDef, CellDef, MultiplierCellDef, NumberCellDef, YahtzeeCellDef} from "../static/rulesets"
export const createCellFromDef = (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(cellDef); return new NumberScoreCell(cellId, cellDef);
case FieldType.bool: case FieldType.bool:
return new BoolScoreCell(cellDef); return new BoolScoreCell(cellId, cellDef);
case FieldType.multiplier: case FieldType.multiplier:
return new MultiplierScoreCell(cellDef); return new MultiplierScoreCell(cellId, cellDef);
case FieldType.yahtzee: case FieldType.yahtzee:
return new YahtzeeScoreCell(cellDef); return new YahtzeeScoreCell(cellId, cellDef);
} }
}; };
@@ -34,8 +34,8 @@ abstract class ScoreCell {
protected struck: boolean; protected struck: boolean;
protected value: number | boolean; protected value: number | boolean;
protected constructor(cellDef: CellDef) { protected constructor(cellId: string, cellDef: CellDef) {
this.id = cellDef.id; this.id = cellId;
this.struck = false; this.struck = false;
this.value = 0; this.value = 0;
} }
@@ -89,8 +89,8 @@ abstract class IterableScoreCell extends ScoreCell {
protected iteratedSequence: IterableSequenceValues[]; protected iteratedSequence: IterableSequenceValues[];
protected currentIteratorIndex: number; protected currentIteratorIndex: number;
protected constructor(cellDef: CellDef) { protected constructor(cellId: string, cellDef: CellDef) {
super(cellDef); super(cellId, cellDef);
this.iteratedSequence = []; this.iteratedSequence = [];
this.currentIteratorIndex = 0; this.currentIteratorIndex = 0;
} }
@@ -156,8 +156,8 @@ abstract class IterableScoreCell extends ScoreCell {
class NumberScoreCell extends ScoreCell { class NumberScoreCell extends ScoreCell {
protected static readonly fieldType = FieldType.number; protected static readonly fieldType = FieldType.number;
constructor(cellDef: NumberCellDef) { constructor(cellId: string, cellDef: NumberCellDef) {
super(cellDef); super(cellId, cellDef);
this.value = 0; this.value = 0;
} }
@@ -185,8 +185,8 @@ class BoolScoreCell extends IterableScoreCell {
private readonly score: number; private readonly score: number;
protected value: boolean; protected value: boolean;
constructor(cellDef: BoolCellDef) { constructor(cellId: string, cellDef: BoolCellDef) {
super(cellDef); super(cellId, cellDef);
this.score = cellDef.score; this.score = cellDef.score;
this.value = false; this.value = false;
this.iteratedSequence = [false, true]; this.iteratedSequence = [false, true];
@@ -207,8 +207,8 @@ class YahtzeeScoreCell extends IterableScoreCell {
private readonly score: number; private readonly score: number;
protected value: number; protected value: number;
constructor(cellDef: YahtzeeCellDef) { constructor(cellId: string, cellDef: YahtzeeCellDef) {
super(cellDef); super(cellId, cellDef);
this.score = cellDef.score; this.score = cellDef.score;
this.value = 0; this.value = 0;
@@ -232,8 +232,8 @@ class MultiplierScoreCell extends IterableScoreCell {
protected readonly multiplier: number; protected readonly multiplier: number;
protected value: number; protected value: number;
constructor(cellDef: MultiplierCellDef) { constructor(cellId: string, cellDef: MultiplierCellDef) {
super(cellDef); super(cellId, cellDef);
this.multiplier = cellDef.multiplier; this.multiplier = cellDef.multiplier;
this.value = 0; this.value = 0;

View File

@@ -12,27 +12,30 @@ import KadiBlockBonusRow from "./KadiBlockBonusRow";
import LocaleContext from "../LocaleContext"; import LocaleContext from "../LocaleContext";
interface BlockRendererProps { interface BlockRendererProps {
blockId: string;
blockSchema: BlockDef; blockSchema: BlockDef;
showResults: boolean; showResults: boolean;
onCellEdit(res: CellEventResponse): void; onCellEdit(res: CellEventResponse): void;
scores: BlockScores; scores: BlockScores;
} }
const KadiBlockRenderer: React.FunctionComponent<BlockRendererProps> = ({ blockSchema , showResults, scores, onCellEdit}) => { const KadiBlockRenderer: React.FunctionComponent<BlockRendererProps> = (props) => {
const { blockSchema, showResults, scores, onCellEdit, blockId} = props;
const rowsInBlock: ReactElement[] = []; const rowsInBlock: ReactElement[] = [];
const Locale = React.useContext(LocaleContext).strings; const Locale = React.useContext(LocaleContext).strings;
for (const cell of blockSchema.cells) { for (const cell in blockSchema.cells) {
const cellSchema = blockSchema.cells[cell];
rowsInBlock.push(( rowsInBlock.push((
<GenericKadiRowContainer <GenericKadiRowContainer
key={"rowCont" + cell.id + blockSchema.id} key={"rowCont" + cell + blockId}
label={cell.label} label={cellSchema.label}
cellCssClassName={cell.fieldType} cellCssClassName={cellSchema.fieldType}
> >
<KadiEditableRowCells <KadiEditableRowCells
location={{blockId: blockSchema.id, cellId: cell.id}} location={{blockId, cellId: cell}}
fieldType={cell.fieldType} fieldType={cellSchema.fieldType}
scores={scores[cell.id]} scores={scores[cell]}
onCellEdit={onCellEdit} onCellEdit={onCellEdit}
/> />
</GenericKadiRowContainer> </GenericKadiRowContainer>
@@ -41,24 +44,24 @@ const KadiBlockRenderer: React.FunctionComponent<BlockRendererProps> = ({ blockS
if (blockSchema.hasBonus) { if (blockSchema.hasBonus) {
rowsInBlock.push( rowsInBlock.push(
<GenericKadiRowContainer <GenericKadiRowContainer
key={"rowContSubtotal" + blockSchema.id} key={"rowContSubtotal" + blockId}
label={Locale.rowLabels.subtotal} label={Locale.rowLabels.subtotal}
cellCssClassName={FieldType.subtotal + (showResults ? "" : " hideResults")} cellCssClassName={FieldType.subtotal + (showResults ? "" : " hideResults")}
> >
<KadiBlockSubtotalRow <KadiBlockSubtotalRow
blockId={blockSchema.id} blockId={blockId}
scores={scores.subtotals} scores={scores.subtotals}
/> />
</GenericKadiRowContainer> </GenericKadiRowContainer>
); );
rowsInBlock.push( rowsInBlock.push(
<GenericKadiRowContainer <GenericKadiRowContainer
key={"rowContBonus" + blockSchema.id} key={"rowContBonus" + blockId}
label={Locale.rowLabels.bonus} label={Locale.rowLabels.bonus}
cellCssClassName={FieldType.bonus + (showResults ? "" : " hideResults")} cellCssClassName={FieldType.bonus + (showResults ? "" : " hideResults")}
> >
<KadiBlockBonusRow <KadiBlockBonusRow
blockId={blockSchema.id} blockId={blockId}
bonusScore={blockSchema.bonusScore} bonusScore={blockSchema.bonusScore}
scores={scores.bonuses} scores={scores.bonuses}
/> />
@@ -67,12 +70,12 @@ const KadiBlockRenderer: React.FunctionComponent<BlockRendererProps> = ({ blockS
} }
rowsInBlock.push( rowsInBlock.push(
<GenericKadiRowContainer <GenericKadiRowContainer
key={"rowContTotal" + blockSchema.id} key={"rowContTotal" + blockId}
label={formatUnicorn(Locale.rowLabels.blockTotal, blockSchema.label)} label={formatUnicorn(Locale.rowLabels.blockTotal, blockSchema.label)}
cellCssClassName={FieldType.total + (showResults ? "" : " hideResults")} cellCssClassName={FieldType.total + (showResults ? "" : " hideResults")}
> >
<KadiBlockTotalRow <KadiBlockTotalRow
blockId={blockSchema.id} blockId={blockId}
scores={scores.totals} scores={scores.totals}
/> />
</GenericKadiRowContainer> </GenericKadiRowContainer>

View File

@@ -144,7 +144,7 @@ class KadiBoard extends React.Component<KadiBoardProps, KadiBoardState> {
JSONScoreCards.push(this.state.scoreSheet[playerId].getJSONRepresentation()); JSONScoreCards.push(this.state.scoreSheet[playerId].getJSONRepresentation());
} }
return JSON.stringify({ return JSON.stringify({
//rulesetUsed: this.gameSchema.id, ruleset: this.gameSchema.id,
players: this.state.players, players: this.state.players,
results: JSONScoreCards results: JSONScoreCards
}); });
@@ -186,24 +186,26 @@ class KadiBoard extends React.Component<KadiBoardProps, KadiBoardState> {
const Locale = this.context.strings; const Locale = this.context.strings;
const rows: ReactElement[] = []; const rows: ReactElement[] = [];
for (const block of this.gameSchema.blocks) { for (const block in this.gameSchema.blocks) {
const blockSchema = this.gameSchema.blocks[block];
const scores: BlockScores = {subtotals: {}, bonuses: {}, totals: {}}; const scores: BlockScores = {subtotals: {}, bonuses: {}, totals: {}};
for (const cell of block.cells) { for (const cell in blockSchema.cells) {
scores[cell.id] = {}; scores[cell] = {};
} }
this.state.players.forEach(player => { this.state.players.forEach(player => {
scores.totals[player.id] = this.getBlockTotalByPlayerId(block.id, player.id); scores.totals[player.id] = this.getBlockTotalByPlayerId(block, player.id);
scores.bonuses[player.id] = this.playerHasBonusForBlock(player.id, block.id); scores.bonuses[player.id] = this.playerHasBonusForBlock(player.id, block);
scores.subtotals[player.id] = this.getBlockSubtotalByPlayerId(block.id, player.id); scores.subtotals[player.id] = this.getBlockSubtotalByPlayerId(block, player.id);
for (const cell of block.cells) { for (const cell in blockSchema.cells) {
scores[cell.id][player.id] = this.getCellDisplayValueByPlayerIdAndLocation( scores[cell][player.id] = this.getCellDisplayValueByPlayerIdAndLocation(
player.id, { blockId: block.id, cellId: cell.id }); player.id, { blockId: block, cellId: cell});
} }
}); });
rows.push( rows.push(
<KadiBlockRenderer <KadiBlockRenderer
key={"block" + block.id} key={"block" + block}
blockSchema={block} blockId={block}
blockSchema={blockSchema}
showResults={this.state.showResults} showResults={this.state.showResults}
onCellEdit={this.onCellEdit} onCellEdit={this.onCellEdit}
scores={scores} scores={scores}

View File

@@ -14,7 +14,7 @@ export const defaultCellValues = {
export interface GameSchema { export interface GameSchema {
id: string; id: string;
label: string; label: string;
blocks: BlockDef[]; blocks: Record<string, BlockDef>;
} }
export type BlockDef = BonusBlockDef | NoBonusBlockDef; export type BlockDef = BonusBlockDef | NoBonusBlockDef;
@@ -30,12 +30,15 @@ export interface BonusBlockDef extends DefaultBlockDef {
} }
interface DefaultBlockDef { interface DefaultBlockDef {
id: string;
label: string; label: string;
cells: CellDef[]; cells: Record<string, CellDef>;
} }
export type CellDef = BoolCellDef | MultiplierCellDef | NumberCellDef | YahtzeeCellDef; export type CellDef =
| BoolCellDef
| MultiplierCellDef
| NumberCellDef
| YahtzeeCellDef;
export interface BoolCellDef extends DefaultCellDef { export interface BoolCellDef extends DefaultCellDef {
fieldType: FieldType.bool; fieldType: FieldType.bool;
@@ -59,222 +62,208 @@ export interface NumberCellDef extends DefaultCellDef {
} }
interface DefaultCellDef { interface DefaultCellDef {
id: string;
label: string; label: string;
} }
// ----- Predefined sets // ----- Predefined sets
const defaultDiceCount = 5; const defaultDiceCount = 5;
const DEFAULT_RULESET = "DEFAULT_RULESET";
const gameSchemas: GameSchema[] = [ const gameSchemas: GameSchema[] = [
{ {
id: "default_en", id: DEFAULT_RULESET,
label: "Standard Kadi Rules (en)", label: "Standard Kadi Rules (en)",
blocks: [ blocks: {
{ top: {
id: "top",
label: "Upper", label: "Upper",
hasBonus: true, hasBonus: true,
bonusScore: 35, bonusScore: 35,
bonusFor: 63, bonusFor: 63,
cells: [ cells: {
{ aces: {
id: "aces",
fieldType: FieldType.multiplier, fieldType: FieldType.multiplier,
label: "Aces", label: "Aces",
multiplier: 1, multiplier: 1,
maxMultiples: defaultDiceCount, maxMultiples: defaultDiceCount,
}, },
{
id: "twos", twos: {
fieldType: FieldType.multiplier, fieldType: FieldType.multiplier,
label: "Twos", label: "Twos",
multiplier: 2, multiplier: 2,
maxMultiples: defaultDiceCount, maxMultiples: defaultDiceCount,
}, },
{
id: "threes", threes: {
fieldType: FieldType.multiplier, fieldType: FieldType.multiplier,
label: "Threes", label: "Threes",
multiplier: 3, multiplier: 3,
maxMultiples: defaultDiceCount, maxMultiples: defaultDiceCount,
}, },
{
id: "fours", fours: {
fieldType: FieldType.multiplier, fieldType: FieldType.multiplier,
label: "Fours", label: "Fours",
multiplier: 4, multiplier: 4,
maxMultiples: defaultDiceCount, maxMultiples: defaultDiceCount,
}, },
{
id: "fives", fives: {
fieldType: FieldType.multiplier, fieldType: FieldType.multiplier,
label: "Fives", label: "Fives",
multiplier: 5, multiplier: 5,
maxMultiples: defaultDiceCount, maxMultiples: defaultDiceCount,
}, },
{
id: "sixes", sixes: {
fieldType: FieldType.multiplier, fieldType: FieldType.multiplier,
label: "Sixes", label: "Sixes",
multiplier: 6, multiplier: 6,
maxMultiples: defaultDiceCount, maxMultiples: defaultDiceCount,
}
]
}, },
{ },
id: "bottom", },
bottom: {
label: "Lower", label: "Lower",
hasBonus: false, hasBonus: false,
cells: [ cells: {
{ three_kind: {
id: "three_kind",
fieldType: FieldType.number, fieldType: FieldType.number,
label: "Three of a Kind", label: "Three of a Kind",
}, },
{
id: "four_kind", four_kind: {
fieldType: FieldType.number, fieldType: FieldType.number,
label: "Four of a Kind", label: "Four of a Kind",
}, },
{
id: "full_house", full_house: {
fieldType: FieldType.bool, fieldType: FieldType.bool,
label: "Full House", label: "Full House",
score: 25, score: 25,
}, },
{
id: "sml_straight", sml_straight: {
fieldType: FieldType.bool, fieldType: FieldType.bool,
label: "Small Straight", label: "Small Straight",
score: 30, score: 30,
}, },
{
id: "lg_straight", lg_straight: {
fieldType: FieldType.bool, fieldType: FieldType.bool,
label: "Large Straight", label: "Large Straight",
score: 40, score: 40,
}, },
{
id: "yahtzee", yahtzee: {
fieldType: FieldType.yahtzee, fieldType: FieldType.yahtzee,
label: "Kadi", label: "Kadi",
score: 50, score: 50,
maxYahtzees: 5, maxYahtzees: 5,
}, },
{
id: "chance", chance: {
fieldType: FieldType.number, fieldType: FieldType.number,
label: "Chance", label: "Chance",
} },
] },
} },
] },
}, },
{ {
id: "default_de", id: DEFAULT_RULESET,
label: "Standard-Kadi-Regelwerk (de)", label: "Standard-Kadi-Regelwerk (de)",
blocks: [ blocks: {
{ top: {
id: "top",
label: "Oben", label: "Oben",
hasBonus: true, hasBonus: true,
bonusScore: 35, bonusScore: 35,
bonusFor: 63, bonusFor: 63,
cells: [ cells: {
{ aces: {
id: "aces",
fieldType: FieldType.multiplier, fieldType: FieldType.multiplier,
label: "Einser", label: "Einser",
multiplier: 1, multiplier: 1,
maxMultiples: defaultDiceCount, maxMultiples: defaultDiceCount,
}, },
{
id: "twos", twos: {
fieldType: FieldType.multiplier, fieldType: FieldType.multiplier,
label: "Zweier", label: "Zweier",
multiplier: 2, multiplier: 2,
maxMultiples: defaultDiceCount, maxMultiples: defaultDiceCount,
}, },
{
id: "threes", threes: {
fieldType: FieldType.multiplier, fieldType: FieldType.multiplier,
label: "Dreier", label: "Dreier",
multiplier: 3, multiplier: 3,
maxMultiples: defaultDiceCount, maxMultiples: defaultDiceCount,
}, },
{
id: "fours", fours: {
fieldType: FieldType.multiplier, fieldType: FieldType.multiplier,
label: "Vierer", label: "Vierer",
multiplier: 4, multiplier: 4,
maxMultiples: defaultDiceCount, maxMultiples: defaultDiceCount,
}, },
{
id: "fives", fives: {
fieldType: FieldType.multiplier, fieldType: FieldType.multiplier,
label: "Fünfer", label: "Fünfer",
multiplier: 5, multiplier: 5,
maxMultiples: defaultDiceCount, maxMultiples: defaultDiceCount,
}, },
{
id: "sixes", sixes: {
fieldType: FieldType.multiplier, fieldType: FieldType.multiplier,
label: "Sechser", label: "Sechser",
multiplier: 6, multiplier: 6,
maxMultiples: defaultDiceCount, maxMultiples: defaultDiceCount,
}
]
}, },
{ },
id: "bottom", },
bottom: {
label: "Unten", label: "Unten",
hasBonus: false, hasBonus: false,
cells: [ cells: {
{ three_kind: {
id: "three_kind",
fieldType: FieldType.number, fieldType: FieldType.number,
label: "Dreierpasch", label: "Dreierpasch",
}, },
{ four_kind: {
id: "four_kind",
fieldType: FieldType.number, fieldType: FieldType.number,
label: "Viererpasch", label: "Viererpasch",
}, },
{ full_house: {
id: "full_house",
fieldType: FieldType.bool, fieldType: FieldType.bool,
label: "Full House", label: "Full House",
score: 25, score: 25,
}, },
{ sml_straight: {
id: "sml_straight",
fieldType: FieldType.bool, fieldType: FieldType.bool,
label: "Kleine Straße", label: "Kleine Straße",
score: 30, score: 30,
}, },
{ lg_straight: {
id: "lg_straight",
fieldType: FieldType.bool, fieldType: FieldType.bool,
label: "Große Straße", label: "Große Straße",
score: 40, score: 40,
}, },
{ yahtzee: {
id: "yahtzee",
fieldType: FieldType.yahtzee, fieldType: FieldType.yahtzee,
label: "Kadi", label: "Kadi",
score: 50, score: 50,
maxYahtzees: 5, maxYahtzees: 5,
}, },
{ change: {
id: "chance",
fieldType: FieldType.number, fieldType: FieldType.number,
label: "Chance", label: "Chance",
} },
] },
} },
] },
} },
]; ];
export function getGameSchemaById(schemaId: string): GameSchema { export function getGameSchemaById(schemaId: string): GameSchema {
@@ -292,5 +281,5 @@ export interface SchemaListing {
} }
export function getSchemaListings(): SchemaListing[] { export function getSchemaListings(): SchemaListing[] {
return gameSchemas.map(s => ({ id: s.id, label: s.label })); return gameSchemas.map((s) => ({ id: s.id, label: s.label }));
} }

View File

@@ -1,4 +1,4 @@
{ {
"ruleset": "default_en", "ruleset": "DEFAULT_RULESET",
"maxHistoryLength": 256 "maxHistoryLength": 256
} }