123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- type PlayerOne = {
- kind: "playerOne";
- name: string;
- };
- type PlayerTwo = {
- kind: "playerTwo";
- name: string;
- };
- type Player = PlayerOne | PlayerTwo;
- type Point = "love" | "15" | "30";
- type Deuce = {
- kind: "deuce";
- };
- type PointsData = {
- kind: "points";
- playerOnePoint: Point;
- playerTwoPoint: Point;
- };
- type FortyData = {
- kind: "forty";
- player: Player;
- otherPlayerPoint: Point;
- };
- type Advantage = {
- kind: "advantage",
- player: Player
- };
- type Game = {
- kind: "game",
- player: Player
- };
- type Score = Deuce | PointsData | FortyData | Advantage | Game;
- function scoreWhenDeuce(_score: Deuce, player: Player): Advantage {
- return {
- kind: "advantage",
- player
- };
- }
- function scoreWhenAdvantage(score: Advantage, player: Player): Game | Deuce {
- return player.kind === score.player.kind ?
- {
- kind: "game",
- player: score.player
- } :
- {
- kind: "deuce"
- };
- }
- function incrementPoint(point: Point): "15" | "30" | undefined {
- switch (point) {
- case "love":
- return "15";
- case "15":
- return "30";
- case "30":
- return undefined;
- }
- }
- function scoreWhenForty(score: FortyData, player: Player): Game | Deuce | FortyData {
- if (score.player.kind === player.kind) {
- return {
- kind: "game",
- player: player
- };
- } else {
- const newPoints: Point | undefined = incrementPoint(score.otherPlayerPoint);
- return (newPoints === undefined) ?
- { kind: "deuce" } :
- {...score, otherPlayerPoint: newPoints};
- }
- }
- function updatePointsData(score: PointsData, newPoints: Point, player: Player): PointsData {
- switch (player.kind) {
- case "playerOne":
- return {...score, playerOnePoint: newPoints};
- case "playerTwo":
- return {...score, playerTwoPoint: newPoints};
- }
- }
- function createFortyData(score: PointsData, player: Player): FortyData {
- const otherPlayerPoint: Point = player.kind === "playerOne" ? score.playerTwoPoint : score.playerOnePoint;
- return {
- kind: "forty",
- player,
- otherPlayerPoint
- };
- }
- function scoreWhenPoints(score: PointsData, player: Player): PointsData | FortyData {
- const newPoints: Point | undefined = player.kind === "playerOne" ?
- incrementPoint(score.playerOnePoint) :
- incrementPoint(score.playerTwoPoint);
- return newPoints === undefined ?
- createFortyData(score, player) :
- updatePointsData(score, newPoints, player);
- }
- function score(score: Score, player: Player): Score {
- switch (score.kind) {
- case "points":
- return scoreWhenPoints(score, player);
- case "forty":
- return scoreWhenForty(score, player);
- case "deuce":
- return scoreWhenDeuce(score, player);
- case "advantage":
- return scoreWhenAdvantage(score, player);
- case "game":
- return score;
- }
- }
|