@@ -33,170 +33,176 @@ export function clearActive(): void {
3333 }
3434}
3535
36- export function verify ( result : CompletedEvent ) : string | null {
37- try {
38- if ( TestState . activeChallenge ) {
39- const afk = ( result . afkDuration / result . testDuration ) * 100 ;
36+ function verifyRequirement (
37+ result : CompletedEvent ,
38+ requirements : Record < string , Record < string , string | number | boolean > > ,
39+ requirementType : string
40+ ) : [ boolean , string [ ] ] {
41+ let requirementsMet = true ;
42+ let failReasons : string [ ] = [ ] ;
4043
41- if ( afk > 10 ) {
42- Notifications . add ( `Challenge failed: AFK time is greater than 10%` , 0 ) ;
43- return null ;
44+ const afk = ( result . afkDuration / result . testDuration ) * 100 ;
45+
46+ const requirementValue = requirements [ requirementType ] ;
47+
48+ if ( requirementValue === undefined ) {
49+ throw new Error ( "Requirement value is undefined" ) ;
50+ }
51+
52+ if ( requirementType === "wpm" ) {
53+ const wpmMode = Object . keys ( requirementValue ) [ 0 ] ;
54+ if ( wpmMode === "exact" ) {
55+ if ( Math . round ( result . wpm ) !== requirementValue [ "exact" ] ) {
56+ requirementsMet = false ;
57+ failReasons . push ( `WPM not ${ requirementValue [ "exact" ] } ` ) ;
58+ }
59+ } else if ( wpmMode === "min" ) {
60+ if ( result . wpm < Number ( requirementValue [ "min" ] ) ) {
61+ requirementsMet = false ;
62+ failReasons . push ( `WPM below ${ requirementValue [ "min" ] } ` ) ;
63+ }
64+ }
65+ } else if ( requirementType === "acc" ) {
66+ const accMode = Object . keys ( requirementValue ) [ 0 ] ;
67+ if ( accMode === "exact" ) {
68+ if ( result . acc !== requirementValue [ "exact" ] ) {
69+ requirementsMet = false ;
70+ failReasons . push ( `Accuracy not ${ requirementValue [ "exact" ] } ` ) ;
71+ }
72+ } else if ( accMode === "min" ) {
73+ if ( result . acc < Number ( requirementValue [ "min" ] ) ) {
74+ requirementsMet = false ;
75+ failReasons . push ( `Accuracy below ${ requirementValue [ "min" ] } ` ) ;
4476 }
77+ }
78+ } else if ( requirementType === "afk" ) {
79+ const afkMode = Object . keys ( requirementValue ) [ 0 ] ;
80+ if ( afkMode === "max" ) {
81+ if ( Math . round ( afk ) > Number ( requirementValue [ "max" ] ) ) {
82+ requirementsMet = false ;
83+ failReasons . push ( `AFK percentage above ${ requirementValue [ "max" ] } ` ) ;
84+ }
85+ }
86+ } else if ( requirementType === "time" ) {
87+ const timeMode = Object . keys ( requirementValue ) [ 0 ] ;
88+ if ( timeMode === "min" ) {
89+ if ( Math . round ( result . testDuration ) < Number ( requirementValue [ "min" ] ) ) {
90+ requirementsMet = false ;
91+ failReasons . push ( `Test time below ${ requirementValue [ "min" ] } ` ) ;
92+ }
93+ }
94+ } else if ( requirementType === "funbox" ) {
95+ const funboxMode = requirementValue [ "exact" ]
96+ ?. toString ( )
97+ . split ( "#" )
98+ . sort ( )
99+ . join ( "#" ) ;
45100
46- if ( TestState . activeChallenge . requirements === undefined ) {
47- Notifications . add (
48- `${ TestState . activeChallenge . display } challenge passed!` ,
49- 1
50- ) ;
51- return TestState . activeChallenge . name ;
52- } else {
53- let requirementsMet = true ;
54- const failReasons = [ ] ;
55- for ( const requirementType in TestState . activeChallenge . requirements ) {
56- if ( ! requirementsMet ) return null ;
57- const requirementValue =
58- TestState . activeChallenge . requirements [ requirementType ] ;
101+ if ( funboxMode === undefined ) {
102+ throw new Error ( "Funbox mode is undefined" ) ;
103+ }
59104
60- if ( requirementValue === undefined ) {
61- throw new Error ( "Requirement value is undefined" ) ;
105+ if ( funboxMode !== result . funbox ) {
106+ requirementsMet = false ;
107+ for ( const f of funboxMode . split ( "#" ) ) {
108+ if (
109+ result . funbox ?. split ( "#" ) . find ( ( rf : string ) => rf === f ) === undefined
110+ ) {
111+ failReasons . push ( `${ f } funbox not active` ) ;
112+ }
113+ }
114+ const funboxSplit = result . funbox ?. split ( "#" ) ;
115+ if ( funboxSplit !== undefined && funboxSplit . length > 0 ) {
116+ for ( const f of funboxSplit ) {
117+ if ( funboxMode . split ( "#" ) . find ( ( rf ) => rf === f ) === undefined ) {
118+ failReasons . push ( `${ f } funbox active` ) ;
62119 }
120+ }
121+ }
122+ }
123+ } else if ( requirementType === "raw" ) {
124+ const rawMode = Object . keys ( requirementValue ) [ 0 ] ;
125+ if ( rawMode === "exact" ) {
126+ if ( Math . round ( result . rawWpm ) !== requirementValue [ "exact" ] ) {
127+ requirementsMet = false ;
128+ failReasons . push ( `Raw WPM not ${ requirementValue [ "exact" ] } ` ) ;
129+ }
130+ }
131+ } else if ( requirementType === "con" ) {
132+ const conMode = Object . keys ( requirementValue ) [ 0 ] ;
133+ if ( conMode === "exact" ) {
134+ if ( Math . round ( result . consistency ) !== requirementValue [ "exact" ] ) {
135+ requirementsMet = false ;
136+ failReasons . push ( `Consistency not ${ requirementValue [ "exact" ] } ` ) ;
137+ }
138+ }
139+ } else if ( requirementType === "config" ) {
140+ for ( const configKey in requirementValue ) {
141+ const configValue = requirementValue [ configKey ] ;
142+ if ( Config [ configKey as keyof ConfigType ] !== configValue ) {
143+ requirementsMet = false ;
144+ failReasons . push ( `${ configKey } not set to ${ configValue } ` ) ;
145+ }
146+ }
147+ }
148+ return [ requirementsMet , failReasons ] ;
149+ }
63150
64- if ( requirementType === "wpm" ) {
65- const wpmMode = Object . keys ( requirementValue ) [ 0 ] ;
66- if ( wpmMode === "exact" ) {
67- if ( Math . round ( result . wpm ) !== requirementValue [ "exact" ] ) {
68- requirementsMet = false ;
69- failReasons . push ( `WPM not ${ requirementValue [ "exact" ] } ` ) ;
70- }
71- } else if ( wpmMode === "min" ) {
72- if ( result . wpm < Number ( requirementValue [ "min" ] ) ) {
73- requirementsMet = false ;
74- failReasons . push ( `WPM below ${ requirementValue [ "min" ] } ` ) ;
75- }
76- }
77- } else if ( requirementType === "acc" ) {
78- const accMode = Object . keys ( requirementValue ) [ 0 ] ;
79- if ( accMode === "exact" ) {
80- if ( result . acc !== requirementValue [ "exact" ] ) {
81- requirementsMet = false ;
82- failReasons . push ( `Accuracy not ${ requirementValue [ "exact" ] } ` ) ;
83- }
84- } else if ( accMode === "min" ) {
85- if ( result . acc < Number ( requirementValue [ "min" ] ) ) {
86- requirementsMet = false ;
87- failReasons . push ( `Accuracy below ${ requirementValue [ "min" ] } ` ) ;
88- }
89- }
90- } else if ( requirementType === "afk" ) {
91- const afkMode = Object . keys ( requirementValue ) [ 0 ] ;
92- if ( afkMode === "max" ) {
93- if ( Math . round ( afk ) > Number ( requirementValue [ "max" ] ) ) {
94- requirementsMet = false ;
95- failReasons . push (
96- `AFK percentage above ${ requirementValue [ "max" ] } `
97- ) ;
98- }
99- }
100- } else if ( requirementType === "time" ) {
101- const timeMode = Object . keys ( requirementValue ) [ 0 ] ;
102- if ( timeMode === "min" ) {
103- if (
104- Math . round ( result . testDuration ) <
105- Number ( requirementValue [ "min" ] )
106- ) {
107- requirementsMet = false ;
108- failReasons . push ( `Test time below ${ requirementValue [ "min" ] } ` ) ;
109- }
110- }
111- } else if ( requirementType === "funbox" ) {
112- const funboxMode = requirementValue [ "exact" ]
113- ?. toString ( )
114- . split ( "#" )
115- . sort ( )
116- . join ( "#" ) ;
151+ export function verify ( result : CompletedEvent ) : string | null {
152+ if ( ! TestState . activeChallenge ) return null ;
117153
118- if ( funboxMode === undefined ) {
119- throw new Error ( "Funbox mode is undefined" ) ;
120- }
154+ try {
155+ const afk = ( result . afkDuration / result . testDuration ) * 100 ;
121156
122- if ( funboxMode !== result . funbox ) {
123- requirementsMet = false ;
124- for ( const f of funboxMode . split ( "#" ) ) {
125- if (
126- result . funbox ?. split ( "#" ) . find ( ( rf : string ) => rf === f ) ===
127- undefined
128- ) {
129- failReasons . push ( `${ f } funbox not active` ) ;
130- }
131- }
132- const funboxSplit = result . funbox ?. split ( "#" ) ;
133- if ( funboxSplit !== undefined && funboxSplit . length > 0 ) {
134- for ( const f of funboxSplit ) {
135- if (
136- funboxMode . split ( "#" ) . find ( ( rf ) => rf === f ) === undefined
137- ) {
138- failReasons . push ( `${ f } funbox active` ) ;
139- }
140- }
141- }
142- }
143- } else if ( requirementType === "raw" ) {
144- const rawMode = Object . keys ( requirementValue ) [ 0 ] ;
145- if ( rawMode === "exact" ) {
146- if ( Math . round ( result . rawWpm ) !== requirementValue [ "exact" ] ) {
147- requirementsMet = false ;
148- failReasons . push ( `Raw WPM not ${ requirementValue [ "exact" ] } ` ) ;
149- }
150- }
151- } else if ( requirementType === "con" ) {
152- const conMode = Object . keys ( requirementValue ) [ 0 ] ;
153- if ( conMode === "exact" ) {
154- if (
155- Math . round ( result . consistency ) !== requirementValue [ "exact" ]
156- ) {
157- requirementsMet = false ;
158- failReasons . push (
159- `Consistency not ${ requirementValue [ "exact" ] } `
160- ) ;
161- }
162- }
163- } else if ( requirementType === "config" ) {
164- for ( const configKey in requirementValue ) {
165- const configValue = requirementValue [ configKey ] ;
166- if ( Config [ configKey as keyof ConfigType ] !== configValue ) {
167- requirementsMet = false ;
168- failReasons . push ( `${ configKey } not set to ${ configValue } ` ) ;
169- }
170- }
171- }
157+ if ( afk > 10 ) {
158+ Notifications . add ( `Challenge failed: AFK time is greater than 10%` , 0 ) ;
159+ return null ;
160+ }
161+
162+ if ( TestState . activeChallenge . requirements === undefined ) {
163+ Notifications . add (
164+ `${ TestState . activeChallenge . display } challenge passed!` ,
165+ 1
166+ ) ;
167+ return TestState . activeChallenge . name ;
168+ } else {
169+ let requirementsMet = true ;
170+ const failReasons : string [ ] = [ ] ;
171+ for ( const requirementType in TestState . activeChallenge . requirements ) {
172+ const [ passed , requirementFailReasons ] = verifyRequirement (
173+ result ,
174+ TestState . activeChallenge . requirements ,
175+ requirementType
176+ ) ;
177+ if ( ! passed ) {
178+ requirementsMet = false ;
172179 }
173- if ( requirementsMet ) {
174- if ( TestState . activeChallenge . autoRole ) {
175- Notifications . add (
176- "You will receive a role shortly. Please don't post a screenshot in challenge submissions." ,
177- 1 ,
178- {
179- duration : 5 ,
180- }
181- ) ;
182- }
183- Notifications . add (
184- `${ TestState . activeChallenge . display } challenge passed!` ,
185- 1
186- ) ;
187- return TestState . activeChallenge . name ;
188- } else {
180+ failReasons . push ( ...requirementFailReasons ) ;
181+ }
182+ if ( requirementsMet ) {
183+ if ( TestState . activeChallenge . autoRole ) {
189184 Notifications . add (
190- `${
191- TestState . activeChallenge . display
192- } challenge failed: ${ failReasons . join ( ", " ) } `,
193- 0
185+ "You will receive a role shortly. Please don't post a screenshot in challenge submissions." ,
186+ 1 ,
187+ {
188+ duration : 5 ,
189+ }
194190 ) ;
195- return null ;
196191 }
192+ Notifications . add (
193+ `${ TestState . activeChallenge . display } challenge passed!` ,
194+ 1
195+ ) ;
196+ return TestState . activeChallenge . name ;
197+ } else {
198+ Notifications . add (
199+ `${
200+ TestState . activeChallenge . display
201+ } challenge failed: ${ failReasons . join ( ", " ) } `,
202+ 0
203+ ) ;
204+ return null ;
197205 }
198- } else {
199- return null ;
200206 }
201207 } catch ( e ) {
202208 console . error ( e ) ;
0 commit comments