@@ -4,34 +4,54 @@ import getRandomElement from "../util/getRandomElement";
44import normalizeString from "../util/normalizeString" ;
55import scrambleString from "../util/scrambleString" ;
66
7- function getGoalAndScrambledGoal ( wordPack : readonly string [ ] ) : {
8- goal : string ;
9- scrambledGoal : string ;
10- } {
11- const goal = getRandomElement ( wordPack ) ;
12- const scrambledGoal = scrambleString ( goal ) ;
13- return { goal, scrambledGoal } ;
7+ type Round = Readonly < {
8+ wordUnscrambled : string ;
9+ wordScrambled : string ;
10+ didGuess : boolean ;
11+ } > ;
12+
13+ function getNewRound ( wordPack : readonly string [ ] ) : Round {
14+ const word = getRandomElement ( wordPack ) ;
15+
16+ return {
17+ wordUnscrambled : word ,
18+ wordScrambled : scrambleString ( word ) ,
19+ didGuess : false ,
20+ } ;
1421}
1522
16- export type State = Readonly <
17- | {
18- phase : "pre-game" ;
19- wordPack : readonly string [ ] | null ;
20- }
21- | {
22- phase : "in-game" ;
23- goal : string ;
24- scrambledGoal : string ;
25- guess : string ;
26- wordsGuessed : number ;
27- wordPack : readonly string [ ] ;
28- }
29- | {
30- phase : "post-game" ;
31- wordsGuessed : number ;
32- wordPack : readonly string [ ] ;
33- }
34- > ;
23+ type PreGameState = Readonly < {
24+ phase : "pre-game" ;
25+ wordPack : readonly string [ ] | null ;
26+ } > ;
27+
28+ type InGameState = Readonly < {
29+ phase : "in-game" ;
30+ currentRound : Round ;
31+ finishedRounds : readonly Round [ ] ;
32+ guess : string ;
33+ wordPack : readonly string [ ] ;
34+ } > ;
35+
36+ type PostGameState = {
37+ phase : "post-game" ;
38+ finishedRounds : readonly Round [ ] ;
39+ wordPack : readonly string [ ] ;
40+ } ;
41+
42+ export type State = PreGameState | InGameState | PostGameState ;
43+
44+ function getNewRoundState ( state : InGameState , didGuess : boolean ) : InGameState {
45+ return {
46+ ...state ,
47+ currentRound : getNewRound ( state . wordPack ) ,
48+ finishedRounds : [
49+ ...state . finishedRounds ,
50+ didGuess ? { ...state . currentRound , didGuess : true } : state . currentRound ,
51+ ] ,
52+ guess : "" ,
53+ } ;
54+ }
3555
3656export function getInitialState ( ) : State {
3757 return { phase : "pre-game" , wordPack : null } ;
@@ -41,6 +61,7 @@ export type Action =
4161 | { type : "load-data" ; wordPack : readonly string [ ] }
4262 | { type : "start-game" }
4363 | { type : "update-guess" ; newGuess : string }
64+ | { type : "skip-word" }
4465 | { type : "end-game" } ;
4566
4667export function reducer ( state : State , action : Action ) : State {
@@ -53,7 +74,7 @@ export function reducer(state: State, action: Action): State {
5374
5475 return {
5576 phase : "post-game" ,
56- wordsGuessed : state . wordsGuessed ,
77+ finishedRounds : [ ... state . finishedRounds , state . currentRound ] ,
5778 wordPack : state . wordPack ,
5879 } ;
5980 }
@@ -67,6 +88,15 @@ export function reducer(state: State, action: Action): State {
6788 return { ...state , wordPack : action . wordPack } ;
6889 }
6990
91+ case "skip-word" : {
92+ // No-op if not in a game.
93+ if ( state . phase !== "in-game" ) {
94+ return state ;
95+ }
96+
97+ return getNewRoundState ( state , false ) ;
98+ }
99+
70100 case "start-game" : {
71101 // No-op if already in a game.
72102 if ( state . phase === "in-game" ) {
@@ -81,10 +111,10 @@ export function reducer(state: State, action: Action): State {
81111
82112 return {
83113 phase : "in-game" ,
114+ currentRound : getNewRound ( wordPack ) ,
115+ finishedRounds : [ ] ,
84116 guess : "" ,
85- wordsGuessed : 0 ,
86117 wordPack,
87- ...getGoalAndScrambledGoal ( wordPack ) ,
88118 } ;
89119 }
90120
@@ -94,13 +124,10 @@ export function reducer(state: State, action: Action): State {
94124 return state ;
95125 }
96126
97- if ( normalizeString ( action . newGuess ) === state . goal ) {
98- return {
99- ...state ,
100- wordsGuessed : state . wordsGuessed + 1 ,
101- guess : "" ,
102- ...getGoalAndScrambledGoal ( state . wordPack ) ,
103- } ;
127+ if (
128+ normalizeString ( action . newGuess ) === state . currentRound . wordUnscrambled
129+ ) {
130+ return getNewRoundState ( state , true ) ;
104131 }
105132
106133 return { ...state , guess : action . newGuess } ;
0 commit comments