Skip to content

Commit 3207a20

Browse files
committed
refactor: reduce indentation by extracting code to a function
1 parent 33857d4 commit 3207a20

File tree

3 files changed

+416
-377
lines changed

3 files changed

+416
-377
lines changed

frontend/src/ts/controllers/challenge-controller.ts

Lines changed: 157 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)