Skip to content

Commit b36ec1b

Browse files
authored
v1.26.1 - Fix protest matters calculation (#275)
- Fix protest matters calculation (#266) - Fix issue with debugging unit tests - Bump version to 1.26.1
1 parent 32c796c commit b36ec1b

File tree

5 files changed

+127
-8
lines changed

5 files changed

+127
-8
lines changed

.vscode/launch.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@
1919
"-r",
2020
"tsconfig-paths/register"
2121
],
22-
"internalConsoleOptions": "openOnSessionStart",
22+
"internalConsoleOptions": "neverOpen",
2323
"name": "Mocha Tests",
2424
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
2525
"request": "launch",
2626
"skipFiles": ["<node_internals>/**"],
27-
"type": "pwa-node"
27+
"type": "node",
28+
"console": "integratedTerminal"
2829
},
2930
{
3031
"type": "chrome",

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"editor.formatOnSave": true,
33
"editor.codeActionsOnSave": {
4-
"source.fixAll.eslint": true
4+
"source.fixAll.eslint": "explicit"
55
},
66
"editor.defaultFormatter": "esbenp.prettier-vscode",
77
"[javascript]": {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "modaq",
3-
"version": "1.26.0",
3+
"version": "1.26.1",
44
"description": "Quiz Bowl Reader using TypeScript, React, and MobX",
55
"repository": {
66
"type": "git",

src/state/GameState.ts

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,11 +206,48 @@ export class GameState {
206206
const tossup: Tossup | undefined = this.packet.tossups[tossupProtest.questionIndex];
207207

208208
if (tossup != undefined) {
209-
const tossupTeamIndex: number = tossupProtest.teamName === this.teamNames[0] ? 0 : 1;
209+
let tossupTeamIndex: number = tossupProtest.teamName === this.teamNames[0] ? 0 : 1;
210+
if (cycle.correctBuzz) {
211+
// If the correct buzz is for the protesting team, then this should be for "against"
212+
if (
213+
cycle.correctBuzz.tossupIndex === tossupProtest.questionIndex &&
214+
cycle.correctBuzz.marker.player.teamName === tossupProtest.teamName
215+
) {
216+
tossupTeamIndex = 1 - tossupTeamIndex;
217+
}
218+
219+
// We have a correct buzz... we need to discount this buzz for the other team, plus any
220+
// bonus they got
221+
const correctTossupPoints = tossup.getPointsAtPosition(
222+
this.gameFormat,
223+
tossupProtest.position,
224+
/* isCorrect */ true
225+
);
226+
227+
// Need to include correct parts and bouncebacks (the -1 * current.points part)
228+
const bonusPoints =
229+
cycle.bonusAnswer?.parts.reduce(
230+
(previous, current) =>
231+
(cycle.correctBuzz?.marker.player.teamName === current.teamName
232+
? current.points
233+
: -1 * current.points) + previous,
234+
0
235+
) ?? 0;
236+
237+
swings[1 - tossupTeamIndex].against += correctTossupPoints + bonusPoints;
238+
}
239+
240+
const bonusIndex: number = this.getBonusIndex(i);
241+
const potentialBonusPoints = this.packet.bonuses[bonusIndex].parts.reduce(
242+
(previous, current) => current.value + previous,
243+
0
244+
);
245+
210246
// Need to remove the neg (subtract) and add what the correct value would be
211247
swings[tossupTeamIndex].for +=
212248
tossup.getPointsAtPosition(this.gameFormat, tossupProtest.position, /* isCorrect */ true) -
213-
tossup.getPointsAtPosition(this.gameFormat, tossupProtest.position, /* isCorrect */ false);
249+
tossup.getPointsAtPosition(this.gameFormat, tossupProtest.position, /* isCorrect */ false) +
250+
potentialBonusPoints;
214251
}
215252
}
216253
}
@@ -230,11 +267,11 @@ export class GameState {
230267
swings[bonusTeamIndex].against += value;
231268
}
232269
}
233-
bonusProtest.partIndex;
234270
}
235271
}
236272
}
237273

274+
// [Best outcome for team 1, best outcome for team 2]
238275
return [
239276
[this.finalScore[0] + swings[0].for, this.finalScore[1] - swings[1].against],
240277
[this.finalScore[0] - swings[0].against, this.finalScore[1] + swings[1].for],

tests/ProtestsMatterTests.ts

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { expect } from "chai";
33
import { Player } from "src/state/TeamState";
44
import { GameState } from "src/state/GameState";
55
import { PacketState, Tossup, Bonus } from "src/state/PacketState";
6+
import { Cycle } from "src/state/Cycle";
67

78
const firstTeamPlayer: Player = new Player("Alice", "A", /* isStarter */ true);
89
const secondTeamPlayer: Player = new Player("Bob", "B", /* isStarter */ true);
@@ -62,6 +63,7 @@ describe("GameStateTests", () => {
6263
});
6364
it("Uneven game, protests don't matter", () => {
6465
const game: GameState = createDefaultGame();
66+
// 20-0
6567
game.cycles[0].addCorrectBuzz(
6668
{ player: firstTeamPlayer, points: 10, position: 2, isLastWord: false },
6769
0,
@@ -71,6 +73,7 @@ describe("GameStateTests", () => {
7173
);
7274
game.cycles[0].setBonusPartAnswer(0, firstTeamPlayer.teamName, 10);
7375

76+
// 60-0
7477
game.cycles[1].addCorrectBuzz(
7578
{ player: firstTeamPlayer, points: 10, position: 1, isLastWord: false },
7679
0,
@@ -79,8 +82,10 @@ describe("GameStateTests", () => {
7982
1
8083
);
8184
game.cycles[1].setBonusPartAnswer(0, firstTeamPlayer.teamName, 10);
85+
game.cycles[1].setBonusPartAnswer(1, firstTeamPlayer.teamName, 10);
86+
game.cycles[1].setBonusPartAnswer(2, firstTeamPlayer.teamName, 10);
8287

83-
// 40-0, so 15 points here and 10 points shouldn't make up for 40-10
88+
// 60-0, so 10 + 30 points here and 10 points shouldn't make up for 60-0
8489
game.cycles[2].addWrongBuzz(
8590
{ player: secondTeamPlayer, points: -5, position: 1, isLastWord: false },
8691
2,
@@ -180,6 +185,8 @@ describe("GameStateTests", () => {
180185
});
181186
it("Uneven game, bonus protest matters (against)", () => {
182187
const game: GameState = createDefaultGame();
188+
189+
// 20-0, one protest
183190
game.cycles[0].addCorrectBuzz(
184191
{ player: firstTeamPlayer, points: 10, position: 2, isLastWord: false },
185192
0,
@@ -190,6 +197,7 @@ describe("GameStateTests", () => {
190197
game.cycles[0].setBonusPartAnswer(0, firstTeamPlayer.teamName, 10);
191198
game.cycles[0].addBonusProtest(0, 0, "My answer", "My reason", secondTeamPlayer.teamName);
192199

200+
// 20-10, one bonus protest (should tie since protest against correctness)
193201
game.cycles[1].addCorrectBuzz(
194202
{ player: secondTeamPlayer, points: 10, position: 1, isLastWord: false },
195203
0,
@@ -220,6 +228,79 @@ describe("GameStateTests", () => {
220228
game.cycles[3].addTossupProtest(secondTeamPlayer.teamName, 2, 1, "My answer", "My reason");
221229
expect(game.protestsMatter).to.be.true;
222230
});
231+
it("Uneven game, tossup with bonus for other team would swing it", () => {
232+
const packet: PacketState = new PacketState();
233+
packet.setTossups([
234+
new Tossup("first q", "first a"),
235+
new Tossup("second q", "second a"),
236+
new Tossup("third q", "third a"),
237+
new Tossup("fourth q", "fourth a"),
238+
]);
239+
packet.setBonuses([
240+
new Bonus("first leadin", [
241+
{ question: "first q", answer: "first a", value: 10 },
242+
{ question: "first q2", answer: "first a2", value: 10 },
243+
{ question: "first q3", answer: "first a3", value: 10 },
244+
]),
245+
new Bonus("second leadin", [
246+
{ question: "second q", answer: "second a", value: 10 },
247+
{ question: "second q2", answer: "second a2", value: 10 },
248+
{ question: "second q3", answer: "second a3", value: 10 },
249+
]),
250+
new Bonus("third leadin", [
251+
{ question: "third q", answer: "third a", value: 10 },
252+
{ question: "third q2", answer: "third a2", value: 10 },
253+
{ question: "third q3", answer: "third a3", value: 10 },
254+
]),
255+
]);
256+
257+
const game: GameState = new GameState();
258+
game.addNewPlayers(players);
259+
game.loadPacket(defaultPacket);
260+
261+
// 30-0
262+
const firstCycle: Cycle = game.cycles[0];
263+
firstCycle.addCorrectBuzz(
264+
{ player: firstTeamPlayer, points: 10, position: 2, isLastWord: false },
265+
0,
266+
game.gameFormat,
267+
0,
268+
3
269+
);
270+
firstCycle.setBonusPartAnswer(0, firstTeamPlayer.teamName, 10);
271+
firstCycle.setBonusPartAnswer(1, firstTeamPlayer.teamName, 10);
272+
expect(game.protestsMatter).to.be.false;
273+
274+
// 25-40, but protest neg
275+
const secondCycle: Cycle = game.cycles[1];
276+
secondCycle.addWrongBuzz(
277+
{ player: firstTeamPlayer, points: -5, position: 1, isLastWord: false },
278+
1,
279+
game.gameFormat
280+
);
281+
secondCycle.addTossupProtest(firstTeamPlayer.teamName, 2, 1, "My answer", "My reason");
282+
secondCycle.addCorrectBuzz(
283+
{ player: secondTeamPlayer, points: 10, position: 2, isLastWord: false },
284+
1,
285+
game.gameFormat,
286+
1,
287+
3
288+
);
289+
secondCycle.setBonusPartAnswer(0, secondTeamPlayer.teamName, 10);
290+
secondCycle.setBonusPartAnswer(1, secondTeamPlayer.teamName, 10);
291+
expect(game.protestsMatter).to.be.true;
292+
293+
// 25-50... protestMatter should still be true, since the protest in the second question should flip it
294+
const thirdCycle: Cycle = game.cycles[2];
295+
thirdCycle.addCorrectBuzz(
296+
{ player: secondTeamPlayer, points: 10, position: 2, isLastWord: false },
297+
2,
298+
game.gameFormat,
299+
2,
300+
3
301+
);
302+
expect(game.protestsMatter).to.be.true;
303+
});
223304
});
224305
});
225306

0 commit comments

Comments
 (0)