index.ts 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. type PlayerOne = {
  2. kind: "playerOne";
  3. name: string;
  4. };
  5. type PlayerTwo = {
  6. kind: "playerTwo";
  7. name: string;
  8. };
  9. type Player = PlayerOne | PlayerTwo;
  10. type Point = "love" | "15" | "30";
  11. type Deuce = {
  12. kind: "deuce";
  13. };
  14. type PointsData = {
  15. kind: "points";
  16. playerOnePoint: Point;
  17. playerTwoPoint: Point;
  18. };
  19. type FortyData = {
  20. kind: "forty";
  21. player: Player;
  22. otherPlayerPoint: Point;
  23. };
  24. type Advantage = {
  25. kind: "advantage",
  26. player: Player
  27. };
  28. type Game = {
  29. kind: "game",
  30. player: Player
  31. // otherPlayerPoint: ? Not representable here.
  32. };
  33. type Score = Deuce | PointsData | FortyData | Advantage | Game;
  34. function scoreWhenDeuce(player: Player): Advantage {
  35. return {
  36. kind: "advantage",
  37. player,
  38. }
  39. }
  40. function scoreWhenAdvantage(score: Advantage, player: Player): Game | Deuce {
  41. return score.player.kind === player.kind ? {
  42. kind: "game",
  43. player,
  44. } :
  45. {
  46. kind: "deuce",
  47. };
  48. }
  49. function incrementPoints(point: Point): "15" | "30" | undefined {
  50. switch (point) {
  51. case "love":
  52. return "15";
  53. case "15":
  54. return "30";
  55. case "30":
  56. return undefined;
  57. }
  58. }
  59. function scoreWhenForty(score: FortyData, player: Player): Game | Deuce | FortyData {
  60. if (score.player.kind === player.kind) {
  61. return {
  62. kind: "game",
  63. player,
  64. }
  65. }
  66. else {
  67. // "15" | "30" | undefined is a subset of Point | undefined
  68. const newPoints: Point | undefined = incrementPoints(score.otherPlayerPoint);
  69. return newPoints === undefined ?
  70. { kind: "deuce" } :
  71. { ...score, otherPlayerPoint: newPoints };
  72. }
  73. }