Skip to content

Commit

Permalink
Winner and score computation
Browse files Browse the repository at this point in the history
  • Loading branch information
jenglamlow committed May 19, 2019
1 parent 6608656 commit 83c20a3
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 76 deletions.
135 changes: 59 additions & 76 deletions src/Wiser.ts
Original file line number Diff line number Diff line change
@@ -1,77 +1,9 @@
import deepDiff from 'deep-diff';

import { CommandManager, ICommand, ICommandManager } from './CommandManager';
import { CommandManager, ICommandManager } from './CommandManager';
import { BallStatus } from './Constant';
import { IBall, IGameRules, IGameState, IRescueBall, nullifyType } from './typings';
import { isMissHittSequence, isNormalHitSequence, removeFirstTeamBall } from './utils';
interface ISequence {
action: string;
nullified: boolean;
}

interface IBallstate {
label: string;
status: BallStatus;
foul: number;
hits: string[];
activeHits: string[];
hitBy: string[];
}

interface ITeamState {
score: number;
pendingRescue: string[];
balls: IBallstate[];
}

type TeamKeys = 'r' | 'w';
interface IMatchInfo {
winner: string;
r: ITeamState;
w: ITeamState;
sequences: ISequence[];
}

interface IGameTeamInfo {
name: string;
}

type MissHitType = 'MY' | 'WWSC';
interface IGameRules {
name: string;
config: {
points: {
contesting: number;
firstLocked: number;
secondLocked: number;
eliminated: number;
};
missHitType: MissHitType;
};
}

interface IGameInfo {
rules: IGameRules;
r: IGameTeamInfo;
w: IGameTeamInfo;
}

interface IBall {
team: TeamKeys;
idx: number;
}

type RescueType = 'normal' | 'missHit';
interface IRescueBall {
type: RescueType;
ball: IBall;
}

type nullifyType = 'rescue' | 'eliminate' | 'rescueMissHit';

export interface IGameState {
info: IGameInfo;
match: IMatchInfo;
}

const template: IGameRules = {
name: 'Malaysia',
Expand Down Expand Up @@ -99,12 +31,24 @@ const gameState: IGameState = {
match: {
winner: '',
r: {
score: 0,
score: {
point: 0,
contesting: 0,
firstLocked: 0,
secondLocked: 0,
eliminated: 0,
},
pendingRescue: [],
balls: [],
},
w: {
score: 0,
score: {
point: 0,
contesting: 0,
firstLocked: 0,
secondLocked: 0,
eliminated: 0,
},
pendingRescue: [],
balls: [],
},
Expand Down Expand Up @@ -157,6 +101,9 @@ export class Wiser {
this.rescue(rescue as IRescueBall);
}

// Compute score and check for winner
this.computeScore();

// Insert the command to command manager
const command = {
command: 'r1r2',
Expand Down Expand Up @@ -186,14 +133,52 @@ export class Wiser {

public reset() {
this.state.match.sequences = [];
this.state.match.r.score = 0;
this.state.match.r.score = {
point: 0,
contesting: 0,
firstLocked: 0,
secondLocked: 0,
eliminated: 0,
};
this.state.match.r.pendingRescue = [];
this.state.match.w.score = 0;
this.state.match.w.score = {
point: 0,
contesting: 0,
firstLocked: 0,
secondLocked: 0,
eliminated: 0,
};
this.state.match.w.pendingRescue = [];
this.state.match.winner = '';

this.initBallState(this.state.match.r.balls.length);
}

private computeScore() {
const team = ['r', 'w'];
const points = this.state.info.rules.config.points;

team.forEach(t => {
const teamScore = this.state.match[t].score;
const teamBalls = this.state.match[t].balls;
teamScore.contesting = teamBalls.filter(b => b.status === BallStatus.Contesting).length;
teamScore.firstLocked = teamBalls.filter(b => b.status === BallStatus.FirstLocked).length;
teamScore.secondLocked = teamBalls.filter(b => b.status === BallStatus.SecondLocked).length;
teamScore.eliminated = teamBalls.filter(b => b.status === BallStatus.Eliminated).length;
teamScore.point =
teamScore.contesting * points.contesting +
teamScore.firstLocked * points.firstLocked +
teamScore.secondLocked * points.secondLocked +
teamScore.eliminated * points.eliminated;
});

if (this.state.match.r.score.contesting === 0) {
this.state.match.winner = 'w';
} else if (this.state.match.w.score.contesting === 0) {
this.state.match.winner = 'r';
}
}

private initBallState(numOfBalls: number) {
this.state.match.r.balls = Array(numOfBalls)
.fill(0)
Expand Down Expand Up @@ -396,8 +381,6 @@ export class Wiser {
}
}

// const cm = new CommandManager();

// const wiser = new Wiser();

// wiser.state.info.rules.config.missHitType = 'WWSC';
Expand Down
35 changes: 35 additions & 0 deletions src/__tests__/Wiser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,41 @@ describe('Sequence', () => {
});
});

describe('Score Info', () => {
test('Compute Score', () => {
wiser.process('r1w3');

expect(wiser.state.match.r.score.point).toBe(35);
expect(wiser.state.match.w.score.contesting).toBe(6);
expect(wiser.state.match.w.score.firstLocked).toBe(1);
expect(wiser.state.match.w.score.point).toBe(32);

wiser.process('w2r1');
expect(wiser.state.match.w.score.point).toBe(35);
expect(wiser.state.match.r.score.contesting).toBe(6);
expect(wiser.state.match.r.score.firstLocked).toBe(1);
expect(wiser.state.match.r.score.point).toBe(32);
});

test('Winner', () => {
wiser.process('r1w1');
wiser.process('r1w2');
wiser.process('r1w3');
wiser.process('r1w4');
wiser.process('r1w5');
wiser.process('r1w6');
expect(wiser.state.match.winner).toBe('');
wiser.process('r1w7');
expect(wiser.state.match.winner).toBe('r');
expect(wiser.state.match.w.score.contesting).toBe(0);

// Throw error if the match already has winner
expect(() => {
wiser.process('r1w7');
}).toThrow('The match already ended');
});
});

describe('Undo/Redo', () => {
test('Basic Undo/Redo', () => {
const s0 = JSON.parse(JSON.stringify(wiser.state.match));
Expand Down
80 changes: 80 additions & 0 deletions src/typings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { BallStatus } from './Constant';

interface ISequence {
action: string;
nullified: boolean;
}

export interface IBallstate {
label: string;
status: BallStatus;
foul: number;
hits: string[];
activeHits: string[];
hitBy: string[];
}

interface IScoreInfo {
point: number;
contesting: number;
firstLocked: number;
secondLocked: number;
eliminated: number;
}

interface ITeamState {
score: IScoreInfo;
pendingRescue: string[];
balls: IBallstate[];
}

type TeamKeys = 'r' | 'w';
interface IMatchInfo {
winner: string;
r: ITeamState;
w: ITeamState;
sequences: ISequence[];
}

interface IGameTeamInfo {
name: string;
}

type MissHitType = 'MY' | 'WWSC';

export interface IGameRules {
name: string;
config: {
points: {
contesting: number;
firstLocked: number;
secondLocked: number;
eliminated: number;
};
missHitType: MissHitType;
};
}

interface IGameInfo {
rules: IGameRules;
r: IGameTeamInfo;
w: IGameTeamInfo;
}

export interface IBall {
team: TeamKeys;
idx: number;
}

type RescueType = 'normal' | 'missHit';
export interface IRescueBall {
type: RescueType;
ball: IBall;
}

export type nullifyType = 'rescue' | 'eliminate' | 'rescueMissHit';

export interface IGameState {
info: IGameInfo;
match: IMatchInfo;
}

0 comments on commit 83c20a3

Please sign in to comment.