UNPKG

modaq

Version:

Quiz Bowl Reader using TypeScript, React, and MobX

933 lines 71.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const chai_1 = require("chai"); const GameFormats = __importStar(require("src/state/GameFormats")); const QBJ = __importStar(require("src/qbj/QBJ")); require("src/qbj/QBJ"); const GameState_1 = require("src/state/GameState"); const PacketState_1 = require("src/state/PacketState"); const TeamState_1 = require("src/state/TeamState"); require("src/state/IGameFormat"); require("src/IResult"); require("src/state/Cycle"); const firstTeamPlayers = [ new TeamState_1.Player("Alice", "A", /* isStarter */ true), new TeamState_1.Player("Alan", "A", /* isStarter */ true), new TeamState_1.Player("Anna", "A", /* isStarter */ false), ]; const secondTeamPlayer = new TeamState_1.Player("Bob", "B", /* isStarter */ true); const players = firstTeamPlayers.concat(secondTeamPlayer); const defaultPacket = new PacketState_1.PacketState(); defaultPacket.setTossups([ new PacketState_1.Tossup("first q", "first a"), new PacketState_1.Tossup("second q", "second a"), new PacketState_1.Tossup("third q (*) has a power marker", "third a"), new PacketState_1.Tossup("fourth q", "fourth a"), ]); defaultPacket.setBonuses([ new PacketState_1.Bonus("first leadin", [ { question: "first q", answer: "first a", value: 10 }, { question: "first q 2", answer: "first a 2", value: 10 }, { question: "first q 3", answer: "first a 3", value: 10 }, ]), new PacketState_1.Bonus("second leadin", [ { question: "second q", answer: "second a", value: 10 }, { question: "second q 2", answer: "second a 2", value: 10 }, { question: "second q 3", answer: "second a 3", value: 10 }, ]), new PacketState_1.Bonus("third leadin", [ { question: "third q", answer: "third a", value: 10 }, { question: "third q 2", answer: "third a 2", value: 10 }, { question: "third q 3", answer: "third a 3", value: 10 }, ]), new PacketState_1.Bonus("fourth leadin", [ { question: "fourth q", answer: "fourth a", value: 10 }, { question: "fourth q 2", answer: "fourth a 2", value: 10 }, { question: "fourth q 3", answer: "fourth a 3", value: 10 }, ]), ]); function createDefaultMatch() { const game = new GameState_1.GameState(); game.loadPacket(defaultPacket); game.setPlayers(players); game.setGameFormat(GameFormats.ACFGameFormat); return QBJ.toQBJ(game, "Packet", 1); } function verifyBuzz(buzz, player, position, points) { chai_1.expect(buzz.buzz_position.word_index).to.equal(position); chai_1.expect(buzz.team.name).to.equal(player.teamName); chai_1.expect(buzz.player.name).to.equal(player.name); chai_1.expect(buzz.result.value).to.equal(points); } function verifyFromQBJ(match, verifyGame) { const result = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); if (!result.success) { chai_1.assert.fail(`Failed to parse the QBJ file into a game. Error: '${result.message}'`); } verifyGame(result.value); } function verifyToQBJ(updateGame, verifyMatch) { const game = new GameState_1.GameState(); game.loadPacket(defaultPacket); game.addNewPlayers(players); updateGame(game); const qbj = QBJ.toQBJString(game); chai_1.expect(qbj).to.not.be.undefined; const match = JSON.parse(qbj); verifyMatch(match, game); } function verifyFromQBJRoundtrip(game) { const qbj = QBJ.toQBJ(game, "Packet", 1); const roundtrippedGameResult = QBJ.fromQBJ(qbj, game.packet, game.gameFormat); if (!roundtrippedGameResult.success) { chai_1.assert.fail(`Failed to parse the QBJ. Error: '${roundtrippedGameResult.message}'`); } const roundtrippedGame = roundtrippedGameResult.value; chai_1.expect(roundtrippedGame).to.not.be.undefined; chai_1.expect(roundtrippedGame.players).to.deep.equal(game.players); chai_1.expect(roundtrippedGame.packet).to.deep.equal(game.packet); // We can't use deep equal aganist cycles because protests aren't preserved. So compare individual fields chai_1.expect(roundtrippedGame.cycles.length).to.equal(game.cycles.length, "Cycle lengths don't match"); for (let i = 0; i < game.cycles.length; i++) { const expectedCycle = game.cycles[i]; const roundtrippedCycle = roundtrippedGame.cycles[i]; chai_1.expect(roundtrippedCycle.bonusAnswer).to.deep.equal(expectedCycle.bonusAnswer, `Bonus answer mismatch at index ${i}`); chai_1.expect(roundtrippedCycle.correctBuzz).to.deep.equal(expectedCycle.correctBuzz, `Correct buzz mismatch at index ${i}`); chai_1.expect(roundtrippedCycle.thrownOutBonuses).to.deep.equal(expectedCycle.thrownOutBonuses, `Thrown out bonuses mismatch at index ${i}`); chai_1.expect(roundtrippedCycle.thrownOutTossups).to.deep.equal(expectedCycle.thrownOutTossups, `Thrown out tossups mismatch at index ${i}`); // Player order for subs and join/leave differ, so just make sure that the names are in each others sets for (const teamName of game.teamNames) { const roundtrippedActivePlayers = roundtrippedGame.getActivePlayers(teamName, i); const originalActivePlayers = game.getActivePlayers(teamName, i); chai_1.expect(roundtrippedActivePlayers.size).to.equal(originalActivePlayers.size, `Active players size different at index ${i}`); for (const player of originalActivePlayers.values()) { chai_1.expect(roundtrippedActivePlayers.has(player), `Player '${player.name}' of team '${player.teamName}' not found in roundtripped players at index ${i}`); } } } } describe("QBJTests", () => { describe("fromQBJ", () => { it("No buzz game", () => { const firstTeamPlayers = [{ name: "Alice" }, { name: "Andy" }]; const secondTeamPlayers = [{ name: "Bob" }]; const match = { match_questions: [ { buzzes: [], question_number: 1, tossup_question: { question_number: 1, type: "tossup", parts: 1 }, }, ], match_teams: [ { bonus_points: 0, team: { name: "Alpha", players: firstTeamPlayers, }, lineups: [{ first_question: 0, players: firstTeamPlayers }], match_players: firstTeamPlayers.map((player) => { return { player, answer_counts: [], tossups_heard: defaultPacket.tossups.length }; }), }, { bonus_points: 0, team: { name: "Beta", players: secondTeamPlayers, }, lineups: [{ first_question: 0, players: secondTeamPlayers }], match_players: secondTeamPlayers.map((player) => { return { player, answer_counts: [], tossups_heard: defaultPacket.tossups.length }; }), }, ], tossups_read: 2, }; verifyFromQBJ(match, (game) => { chai_1.expect(game.finalScore).to.deep.equal([0, 0]); chai_1.expect(game.cycles.length).to.equal(defaultPacket.tossups.length); for (let i = 0; i < defaultPacket.tossups.length; i++) { if (game.cycles[i].correctBuzz != undefined) { chai_1.assert.fail("Correct buzz found at index " + i); } } }); }); it("Game->QBJ->Game round trip", () => { const game = new GameState_1.GameState(); game.loadPacket(defaultPacket); game.setPlayers(players); game.setGameFormat(GameFormats.ACFGameFormat); // Add a variety of events // - Team 1 negs on question 1, team 2 gets it, gets the second and third bonus parts. Bonus protest 1st one, tossup protest 1st one // - Leave/join for team 1. TU 2 is thrown out. TU is answered by team 1 // - Team 1 gets first part of bonus // - Sub for team 2. The sub gets TU 3 // - Bonus 3 is thrown out. Parts 1 gotten. const firstCycle = game.cycles[0]; firstCycle.addWrongBuzz({ player: firstTeamPlayers[0], points: -5, position: 0, isLastWord: false }, 0, GameFormats.ACFGameFormat); firstCycle.addCorrectBuzz({ player: secondTeamPlayer, points: 10, position: 1 }, 0, GameFormats.ACFGameFormat, 0, 3); firstCycle.setBonusPartAnswer(1, secondTeamPlayer.teamName, 10); firstCycle.setBonusPartAnswer(2, secondTeamPlayer.teamName, 10); firstCycle.addBonusProtest(0, 0, "Right", "Reason", secondTeamPlayer.teamName); const secondCycle = game.cycles[1]; secondCycle.addThrownOutTossup(1); secondCycle.addCorrectBuzz({ player: firstTeamPlayers[1], points: 10, position: 1, }, 2, GameFormats.ACFGameFormat, 1, 3); secondCycle.setBonusPartAnswer(0, firstTeamPlayers[0].teamName, 10); const thirdCycle = game.cycles[2]; const newPlayer = new TeamState_1.Player("Brenda", secondTeamPlayer.teamName, /* isStarter */ false); game.addNewPlayer(newPlayer); thirdCycle.addPlayerJoins(newPlayer); thirdCycle.addPlayerLeaves(secondTeamPlayer); thirdCycle.addCorrectBuzz({ player: newPlayer, points: 10, position: 0 }, 3, GameFormats.ACFGameFormat, 2, 3); thirdCycle.addThrownOutBonus(2); thirdCycle.setBonusPartAnswer(0, secondTeamPlayer.teamName, 10); verifyFromQBJRoundtrip(game); }); it("Roundtrip game with multiple thrown out tossups", () => { const game = new GameState_1.GameState(); game.loadPacket(defaultPacket); game.setPlayers(players); game.setGameFormat(GameFormats.ACFGameFormat); const firstCycle = game.cycles[0]; firstCycle.addThrownOutTossup(0); firstCycle.addThrownOutTossup(1); firstCycle; firstCycle.addWrongBuzz({ player: firstTeamPlayers[0], points: -5, position: 0, isLastWord: false }, 2, GameFormats.ACFGameFormat); firstCycle.addCorrectBuzz({ player: secondTeamPlayer, points: 10, position: 1 }, 2, GameFormats.ACFGameFormat, 0, 3); firstCycle.setBonusPartAnswer(0, secondTeamPlayer.teamName, 10); verifyFromQBJRoundtrip(game); }); it("Roundtrip game with multiple thrown out bonuses", () => { const game = new GameState_1.GameState(); game.loadPacket(defaultPacket); game.setPlayers(players); game.setGameFormat(GameFormats.ACFGameFormat); const firstCycle = game.cycles[0]; firstCycle.addCorrectBuzz({ player: secondTeamPlayer, points: 10, position: 1 }, 0, GameFormats.ACFGameFormat, 0, 3); firstCycle.addThrownOutBonus(0); firstCycle.addThrownOutBonus(1); firstCycle.setBonusPartAnswer(2, secondTeamPlayer.teamName, 10); verifyFromQBJRoundtrip(game); }); it("Invalid QBJ - undefined and empty match_players", () => { const match = createDefaultMatch(); if (match.match_teams) { match.match_teams[1].match_players = undefined; } const result = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(result.success).to.be.false; match.match_teams[1].match_players = []; const secondResult = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(secondResult.success).to.be.false; }); it("Invalid QBJ - less than 2 teams", () => { const match = createDefaultMatch(); match.match_teams = [ { bonus_points: 0, team: { name: "Alpha", players: firstTeamPlayers, }, lineups: [{ first_question: 0, players: firstTeamPlayers }], match_players: firstTeamPlayers.map((player) => { return { player, answer_counts: [], tossups_heard: defaultPacket.tossups.length }; }), }, ]; const result = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(result.success).to.be.false; }); it("Invalid QBJ - more than 2 teams", () => { const match = createDefaultMatch(); match.match_teams = ["Alpha", "Beta", "Gamma"].map((teamName) => { return { bonus_points: 0, team: { name: teamName, players: firstTeamPlayers, }, lineups: [{ first_question: 0, players: firstTeamPlayers }], match_players: firstTeamPlayers.map((player) => { return { player, answer_counts: [], tossups_heard: defaultPacket.tossups.length }; }), }; }); const result = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(result.success).to.be.false; }); it("Invalid QBJ - undefined and empty lineup", () => { const match = createDefaultMatch(); if (match.match_teams) { match.match_teams[0].lineups = undefined; } const result = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(result.success).to.be.false; match.match_teams[0].lineups = []; const secondResult = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(secondResult.success).to.be.false; }); it("Invalid QBJ - undefined and empty match questoins", () => { const match = createDefaultMatch(); if (match.match_questions) { match.match_questions = undefined; } const result = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(result.success).to.be.false; match.match_questions = []; const secondResult = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(secondResult.success).to.be.false; }); it("Invalid QBJ - negative bonus points", () => { const match = createDefaultMatch(); if (match.match_teams) { match.match_teams[0].bonus_points = -5; } const result = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(result.success).to.be.false; }); it("Invalid QBJ - same team name", () => { const match = createDefaultMatch(); const name = "Same"; if (match.match_teams) { match.match_teams[0].team.name = name; match.match_teams[1].team.name = name; } const result = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(result.success).to.be.false; }); it("Invalid QBJ - empty player name", () => { const match = createDefaultMatch(); if (match.match_teams) { match.match_teams[0].match_players[0].player.name = ""; } const result = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(result.success).to.be.false; }); it("Invalid QBJ - duplicate player name", () => { const match = createDefaultMatch(); const name = "Same"; if (match.match_teams) { match.match_teams[0].match_players[0].player.name = name; match.match_teams[0].match_players[1].player.name = name; } const result = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(result.success).to.be.false; }); it("Invalid QBJ - buzz by undefined player", () => { const match = createDefaultMatch(); if (match.match_questions) { match.match_questions[0].buzzes = [ { buzz_position: { word_index: 0 }, team: match.match_teams[0].team, player: undefined, result: { value: -5 }, }, ]; } const result = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(result.success).to.be.false; }); it("Invalid QBJ - buzz by unknown player", () => { const match = createDefaultMatch(); if (match.match_questions) { const player = Object.assign({}, match.match_teams[0].match_players[0].player); player.name = "Some other guy"; match.match_questions[0].buzzes = [ { buzz_position: { word_index: 0 }, team: match.match_teams[0].team, player, result: { value: -5 }, }, ]; } const result = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(result.success).to.be.false; }); it("Invalid QBJ - lineups at invalid time", () => { const game = new GameState_1.GameState(); game.loadPacket(defaultPacket); game.setPlayers(players); game.setGameFormat(GameFormats.ACFGameFormat); const newPlayer = new TeamState_1.Player("Arthur", game.teamNames[0], /* isStarter */ false); game.cycles[1].addSwapSubstitution(newPlayer, firstTeamPlayers[0]); const match = QBJ.toQBJ(game, "Packet", 1); if (match.match_teams) { match.match_teams[0].lineups[0].first_question = -1; } const result = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(result.success).to.be.false; match.match_teams[0].lineups[0].first_question = game.packet.tossups.length + 1; const secondResult = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(secondResult.success).to.be.false; }); it("Invalid QBJ - lineups in wrong order", () => { const game = new GameState_1.GameState(); game.loadPacket(defaultPacket); game.setPlayers(players); game.setGameFormat(GameFormats.ACFGameFormat); const newPlayer = new TeamState_1.Player("Arthur", game.teamNames[0], /* isStarter */ false); game.cycles[1].addSwapSubstitution(newPlayer, firstTeamPlayers[0]); const match = QBJ.toQBJ(game, "Packet", 1); if (match.match_teams) { match.match_teams[0].lineups[0].first_question = 2; } const result = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(result.success).to.be.false; }); it("Invalid QBJ - buzz at invalid time", () => { const match = createDefaultMatch(); if (match.match_questions) { match.match_questions[0].buzzes = [ { buzz_position: { word_index: -1 }, team: match.match_teams[0].team, player: match.match_teams[0].match_players[0].player, result: { value: -5 }, }, ]; } const result = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(result.success).to.be.false; match.match_questions[0].buzzes = [ { buzz_position: { word_index: defaultPacket.tossups[0].getWords(GameFormats.ACFGameFormat).length + 1, }, team: match.match_teams[0].team, player: match.match_teams[0].match_players[0].player, result: { value: -5 }, }, ]; const secondResult = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(secondResult.success).to.be.false; }); it("Invalid QBJ - tossup answered during thrown out tossup", () => { const game = new GameState_1.GameState(); game.loadPacket(defaultPacket); game.setPlayers(players); game.setGameFormat(GameFormats.ACFGameFormat); const match = QBJ.toQBJ(game, "Packet", 1); if (match.match_questions) { match.match_questions[0].buzzes = [ { buzz_position: { word_index: 0 }, team: match.match_teams[0].team, player: match.match_teams[0].match_players[0].player, result: { value: 10 }, }, ]; match.match_questions[0].tossup_question.question_number = 2; match.match_questions[1].buzzes = [ { buzz_position: { word_index: 1 }, team: match.match_teams[0].team, player: match.match_teams[0].match_players[0].player, result: { value: 10 }, }, ]; match.match_questions[1].tossup_question.question_number = 1; } const result = QBJ.fromQBJ(match, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(result.success).to.be.false; }); it("Invalid QBJ - undefined passed in", () => { const result = QBJ.fromQBJ(undefined, defaultPacket, GameFormats.ACFGameFormat); chai_1.expect(result.success).to.be.false; }); }); describe("toQBJ", () => { it("No buzz game", () => { verifyToQBJ( // eslint-disable-next-line @typescript-eslint/no-empty-function () => { }, (match) => { chai_1.expect(match.tossups_read).to.equal(4); chai_1.expect(match.match_teams.length).to.equal(2); chai_1.expect(match.match_teams[0].lineups).to.deep.equal([ { first_question: 1, players: firstTeamPlayers .filter((p) => p.isStarter) .map((p) => { return { name: p.name, }; }), }, ]); chai_1.expect(match.match_teams[1].lineups).to.deep.equal([ { first_question: 1, players: [{ name: "Bob" }], }, ]); chai_1.expect(match.match_questions.map((q) => q.buzzes).every((buzzes) => buzzes.length === 0)).to.be .true; chai_1.expect(match.match_questions.map((q) => q.question_number)).to.deep.equal([1, 2, 3, 4]); }); }); it("Four buzzes (-5, 0, 10, 15)", () => { verifyToQBJ((game) => { game.setGameFormat(GameFormats.StandardPowersMACFGameFormat); game.cycles[0].addWrongBuzz({ player: firstTeamPlayers[0], points: -5, position: 0, isLastWord: false, }, 0, game.gameFormat); game.cycles[0].addWrongBuzz({ player: secondTeamPlayer, points: 0, position: 1, isLastWord: true, }, 0, game.gameFormat); game.cycles[1].addCorrectBuzz({ player: firstTeamPlayers[1], points: 10, position: 1, isLastWord: true, }, 1, game.gameFormat, 0, 3); game.cycles[1].setBonusPartAnswer(1, firstTeamPlayers[1].teamName, 10); game.cycles[2].addCorrectBuzz({ player: secondTeamPlayer, points: 15, position: 0, isLastWord: false, }, 2, game.gameFormat, 1, 3); }, (match) => { chai_1.expect(match.tossups_read).to.equal(4); chai_1.expect(match.match_questions.map((q) => q.question_number)).to.deep.equal([1, 2, 3, 4]); const firstCycleBuzzes = match.match_questions[0].buzzes; chai_1.expect(firstCycleBuzzes.length).to.equal(2); verifyBuzz(firstCycleBuzzes[0], firstTeamPlayers[0], 0, -5); verifyBuzz(firstCycleBuzzes[1], secondTeamPlayer, 1, 0); const secondCycleBuzzes = match.match_questions[1].buzzes; chai_1.expect(secondCycleBuzzes.length).to.equal(1); verifyBuzz(secondCycleBuzzes[0], firstTeamPlayers[1], 1, 10); const thirdCycleBuzzes = match.match_questions[2].buzzes; chai_1.expect(thirdCycleBuzzes.length).to.equal(1); verifyBuzz(thirdCycleBuzzes[0], secondTeamPlayer, 0, 15); }); }); it("Bonuses (0, 10, 30)", () => { verifyToQBJ((game) => { // 0 on the bonus game.cycles[0].addCorrectBuzz({ player: firstTeamPlayers[0], points: 10, position: 1, isLastWord: true, }, 1, game.gameFormat, 0, 3); // 10 game.cycles[1].addCorrectBuzz({ player: secondTeamPlayer, points: 10, position: 1, isLastWord: true, }, 2, game.gameFormat, 1, 3); game.cycles[1].setBonusPartAnswer(1, secondTeamPlayer.teamName, 10); // 30 on the bonus game.cycles[2].addCorrectBuzz({ player: secondTeamPlayer, points: 15, position: 0, isLastWord: true, }, 3, game.gameFormat, 2, 3); for (let i = 0; i < 3; i++) { game.cycles[2].setBonusPartAnswer(i, secondTeamPlayer.teamName, 10); } }, (match) => { var _a, _b, _c, _d, _e, _f, _g, _h, _j; chai_1.expect(match.tossups_read).to.equal(4); chai_1.expect(match.match_questions.map((q) => q.question_number)).to.deep.equal([1, 2, 3, 4]); const firstCycleBonus = match.match_questions[0].bonus; if (firstCycleBonus == undefined) { chai_1.assert.fail("First bonus wasn't found"); } chai_1.expect((_a = firstCycleBonus.question) === null || _a === void 0 ? void 0 : _a.parts).to.equal(3); chai_1.expect((_b = firstCycleBonus.question) === null || _b === void 0 ? void 0 : _b.question_number).to.equal(1); chai_1.expect((_c = firstCycleBonus.question) === null || _c === void 0 ? void 0 : _c.type).to.equal("bonus"); chai_1.expect(firstCycleBonus.parts.map((p) => p.controlled_points)).deep.equals([0, 0, 0]); const secondCycleBonus = match.match_questions[1].bonus; if (secondCycleBonus == undefined) { chai_1.assert.fail("Second bonus wasn't found"); } chai_1.expect((_d = secondCycleBonus.question) === null || _d === void 0 ? void 0 : _d.parts).to.equal(3); chai_1.expect((_e = secondCycleBonus.question) === null || _e === void 0 ? void 0 : _e.question_number).to.equal(2); chai_1.expect((_f = secondCycleBonus.question) === null || _f === void 0 ? void 0 : _f.type).to.equal("bonus"); chai_1.expect(secondCycleBonus.parts.map((p) => p.controlled_points)).deep.equals([0, 10, 0]); const thirdCycleBonus = match.match_questions[2].bonus; if (thirdCycleBonus == undefined) { chai_1.assert.fail("Third bonus wasn't found"); } chai_1.expect((_g = thirdCycleBonus.question) === null || _g === void 0 ? void 0 : _g.parts).to.equal(3); chai_1.expect((_h = thirdCycleBonus.question) === null || _h === void 0 ? void 0 : _h.question_number).to.equal(3); chai_1.expect((_j = thirdCycleBonus.question) === null || _j === void 0 ? void 0 : _j.type).to.equal("bonus"); chai_1.expect(thirdCycleBonus.parts.map((p) => p.controlled_points)).deep.equals([10, 10, 10]); chai_1.expect(match.match_teams.length).to.equal(2); chai_1.expect(match.match_teams[0].bonus_points).to.equal(0); chai_1.expect(match.match_teams[1].bonus_points).to.equal(40); }); }); it("Bonus bouncebacks", () => { verifyToQBJ((game) => { game.setGameFormat(Object.assign(Object.assign({}, game.gameFormat), { bonusesBounceBack: true })); // 0 on the bonus game.cycles[0].addCorrectBuzz({ player: firstTeamPlayers[0], points: 10, position: 1, isLastWord: true, }, 1, game.gameFormat, 0, 3); // Receiving team get 10, other team gets 10 game.cycles[0].setBonusPartAnswer(0, firstTeamPlayers[0].teamName, 10); game.cycles[0].setBonusPartAnswer(2, secondTeamPlayer.teamName, 10); // Receiving team gets 0, other team gets 20 game.cycles[1].addCorrectBuzz({ player: secondTeamPlayer, points: 10, position: 1, isLastWord: true, }, 2, game.gameFormat, 1, 3); game.cycles[1].setBonusPartAnswer(0, firstTeamPlayers[0].teamName, 10); game.cycles[1].setBonusPartAnswer(1, firstTeamPlayers[0].teamName, 10); }, (match) => { var _a, _b, _c, _d, _e, _f; chai_1.expect(match.tossups_read).to.equal(4); chai_1.expect(match.match_questions.map((q) => q.question_number)).to.deep.equal([1, 2, 3, 4]); const firstCycleBonus = match.match_questions[0].bonus; if (firstCycleBonus == undefined) { chai_1.assert.fail("First bonus wasn't found"); } chai_1.expect((_a = firstCycleBonus.question) === null || _a === void 0 ? void 0 : _a.parts).to.equal(3); chai_1.expect((_b = firstCycleBonus.question) === null || _b === void 0 ? void 0 : _b.question_number).to.equal(1); chai_1.expect((_c = firstCycleBonus.question) === null || _c === void 0 ? void 0 : _c.type).to.equal("bonus"); chai_1.expect(firstCycleBonus.parts.map((p) => p.controlled_points)).deep.equals([10, 0, 0]); chai_1.expect(firstCycleBonus.parts.map((p) => p.bounceback_points)).deep.equals([0, 0, 10]); const secondCycleBonus = match.match_questions[1].bonus; if (secondCycleBonus == undefined) { chai_1.assert.fail("Second bonus wasn't found"); } chai_1.expect((_d = secondCycleBonus.question) === null || _d === void 0 ? void 0 : _d.parts).to.equal(3); chai_1.expect((_e = secondCycleBonus.question) === null || _e === void 0 ? void 0 : _e.question_number).to.equal(2); chai_1.expect((_f = secondCycleBonus.question) === null || _f === void 0 ? void 0 : _f.type).to.equal("bonus"); chai_1.expect(secondCycleBonus.parts.map((p) => p.controlled_points)).deep.equals([0, 0, 0]); chai_1.expect(secondCycleBonus.parts.map((p) => p.bounceback_points)).deep.equals([10, 10, 0]); chai_1.expect(match.match_teams.length).to.equal(2); chai_1.expect(match.match_teams[0].bonus_points).to.equal(10); chai_1.expect(match.match_teams[0].bonus_bounceback_points).to.equal(20); chai_1.expect(match.match_teams[1].bonus_points).to.equal(0); chai_1.expect(match.match_teams[1].bonus_bounceback_points).to.equal(10); }); }); it("Sub-in player", () => { verifyToQBJ((game) => { game.cycles[1].addSwapSubstitution(firstTeamPlayers[2], firstTeamPlayers[0]); game.cycles[1].addWrongBuzz({ player: firstTeamPlayers[2], points: -5, position: 0, isLastWord: false, }, 0, game.gameFormat); }, (match) => { chai_1.expect(match.tossups_read).to.equal(4); chai_1.expect(match.match_questions.map((q) => q.question_number)).to.deep.equal([1, 2, 3, 4]); const secondCycleBuzzes = match.match_questions[1].buzzes; chai_1.expect(secondCycleBuzzes.length).to.equal(1); verifyBuzz(secondCycleBuzzes[0], firstTeamPlayers[2], 0, -5); chai_1.expect(match.match_teams.length).to.equal(2); chai_1.expect(match.match_teams[0].match_players.length).to.equal(3); const outFirstTeamPlayer = match.match_teams[0].match_players[0]; chai_1.expect(outFirstTeamPlayer.player.name).to.equal(firstTeamPlayers[0].name); chai_1.expect(outFirstTeamPlayer.tossups_heard).to.equal(1); const inFirstTeamPlayer = match.match_teams[0].match_players[2]; chai_1.expect(inFirstTeamPlayer.player.name).to.equal(firstTeamPlayers[2].name); chai_1.expect(inFirstTeamPlayer.tossups_heard).to.equal(3); // Verify the lineups const firstTeam = match.match_teams[0]; chai_1.expect(firstTeam.lineups.length).to.equal(2); chai_1.expect(firstTeam.lineups[0]).to.deep.equal({ first_question: 1, players: firstTeamPlayers .filter((p) => p.isStarter) .map((p) => { return { name: p.name }; }), }); chai_1.expect(firstTeam.lineups[1]).to.deep.equal({ first_question: 2, players: [{ name: "Alan" }, { name: "Anna" }], }); }); }); it("Player leaves", () => { verifyToQBJ((game) => { game.cycles[2].addPlayerLeaves(firstTeamPlayers[0]); }, (match) => { chai_1.expect(match.tossups_read).to.equal(4); chai_1.expect(match.match_questions.map((q) => q.question_number)).to.deep.equal([1, 2, 3, 4]); chai_1.expect(match.match_teams.length).to.equal(2); chai_1.expect(match.match_teams[0].match_players.length).to.equal(3); const outFirstTeamPlayer = match.match_teams[0].match_players[0]; chai_1.expect(outFirstTeamPlayer.player.name).to.equal(firstTeamPlayers[0].name); chai_1.expect(outFirstTeamPlayer.tossups_heard).to.equal(2); // Verify the lineups const firstTeam = match.match_teams[0]; chai_1.expect(firstTeam.lineups.length).to.equal(2); chai_1.expect(firstTeam.lineups[0]).to.deep.equal({ first_question: 1, players: firstTeamPlayers .filter((p) => p.isStarter) .map((p) => { return { name: p.name }; }), }); chai_1.expect(firstTeam.lineups[1]).to.deep.equal({ first_question: 3, players: [{ name: "Alan" }], }); }); }); it("Player joins", () => { const newPlayerName = "Bianca"; verifyToQBJ((game) => { const newPlayer = new TeamState_1.Player(newPlayerName, secondTeamPlayer.teamName, /* isStarter */ false); game.addNewPlayer(newPlayer); game.cycles[3].addPlayerJoins(newPlayer); }, (match) => { chai_1.expect(match.tossups_read).to.equal(4); chai_1.expect(match.match_questions.map((q) => q.question_number)).to.deep.equal([1, 2, 3, 4]); chai_1.expect(match.match_teams.length).to.equal(2); chai_1.expect(match.match_teams[1].match_players.length).to.equal(2); const secondTeam = match.match_teams[1]; const inSecondTeamPlayer = secondTeam.match_players[1]; chai_1.expect(inSecondTeamPlayer.player.name).to.equal(newPlayerName); chai_1.expect(inSecondTeamPlayer.tossups_heard).to.equal(1); // Verify the lineups chai_1.expect(secondTeam.lineups.length).to.equal(2); chai_1.expect(secondTeam.lineups[0]).to.deep.equal({ first_question: 1, players: [ { name: secondTeamPlayer.name, }, ], }); chai_1.expect(secondTeam.lineups[1]).to.deep.equal({ first_question: 4, players: [{ name: secondTeamPlayer.name }, { name: newPlayerName }], }); }); }); it("Player stats", () => { verifyToQBJ((game) => { game.setGameFormat(GameFormats.StandardPowersMACFGameFormat); const packet = new PacketState_1.PacketState(); const tossups = []; for (let i = 0; i < 6; i++) { tossups.push(new PacketState_1.Tossup(`Power (*) question ${i}`, `A${i}`)); } packet.setTossups(tossups); game.loadPacket(packet); game.cycles[0].addWrongBuzz({ player: secondTeamPlayer, points: -5, position: 0, isLastWord: false, }, 0, game.gameFormat); game.cycles[1].addWrongBuzz({ player: secondTeamPlayer, points: 0, position: 3, isLastWord: true, }, 1, game.gameFormat); game.cycles[2].addCorrectBuzz({ player: secondTeamPlayer, points: 10, position: 2, isLastWord: true, }, 2, game.gameFormat, 0, 3); game.cycles[3].addCorrectBuzz({ player: secondTeamPlayer, points: 15, position: 0, isLastWord: true, }, 3, game.gameFormat, 1, 3); game.cycles[4].addCorrectBuzz({ player: secondTeamPlayer, points: 15, position: 0, isLastWord: false, }, 4, game.gameFormat, 1, 3); game.cycles[5].addCorrectBuzz({ player: firstTeamPlayers[0], points: 10, position: 2, isLastWord: true, }, 5, game.gameFormat, 1, 3); }, (match) => { chai_1.expect(match.tossups_read).to.equal(6); chai_1.expect(match.match_questions.map((q) => q.question_number)).to.deep.equal([1, 2, 3, 4, 5, 6]); chai_1.expect(match.match_teams.length).to.equal(2); chai_1.expect(match.match_teams[0].match_players.length).to.equal(3); const firstFirstTeamPlayer = match.match_teams[0].match_players[0]; chai_1.expect(firstFirstTeamPlayer.player.name).to.equal(firstTeamPlayers[0].name); chai_1.expect(firstFirstTeamPlayer.tossups_heard).to.equal(6); chai_1.expect(firstFirstTeamPlayer.answer_counts.length).to.equal(1); chai_1.expect(firstFirstTeamPlayer.answer_counts[0]).to.deep.equal({ number: 1, answer: { value: 10, }, }); const lastFirstTeamPlayer = match.match_teams[0].match_players[2]; chai_1.expect(lastFirstTeamPlayer.tossups_heard).to.equal(0); chai_1.expect(lastFirstTeamPlayer.player.name).to.equal(firstTeamPlayers[2].name); chai_1.expect(match.match_teams[1].match_players.length).to.equal(1); const secondPlayer = match.match_teams[1].match_players[0]; chai_1.expect(secondPlayer.player.name).to.equal(secondTeamPlayer.name); chai_1.expect(secondPlayer.tossups_heard).to.equal(6); // expect(secondPlayer.answer_counts.length).to.equal(4); chai_1.expect(secondPlayer.answer_counts).to.deep.equal([ { number: 1, answer: { value: -5, }, }, { number: 1, answer: { value: 0, }, }, { number: 1, answer: { value: 10, }, }, { number: 2, answer: { value: 15, }, }, ]); }); }); it("Tossup protest", () => { const firstProtestReason = "First protest"; const firstProtestAnswer = "First answer"; const secondProtestReason = "Second protest"; const secondProtestAnswer = "Second answer"; verifyToQBJ((game) => { game.cycles[0].addWrongBuzz({ player: firstTeamPlayers[0], points: -5, position: 0, isLastWord: false, }, 0, game.gameFormat); game.cycles[0].addTossupProtest(firstTeamPlayers[0].teamName, 0, 0, firstProtestAnswer, firstProtestReason); game.cycles[1].addWrongBuzz({ player: secondTeamPlayer, points: 0, position: 1, isLastWord: true, }, 1, game.gameFormat); game.cycles[1].addTossupProtest(secondTeamPlayer.teamName, 1, 1, secondProtestAnswer, secondProtestReason); }, (match) => { chai_1.expect(match.tossups_read).to.equal(4); chai_1.expect(match.match_questions.map((q) => q.question_number)).to.deep.equal([1, 2, 3, 4]); if (match.notes == undefined) { chai_1.assert.fail("match.notes should be defined."); } const lines = match.notes.split("\n"); chai_1.expect(lines.length).to.equal(2); chai_1.expect(lines[0]).to.equal(`Tossup protest on question 1. Team "${firstTeamPlayers[0].teamName}" protested because of this reason: "${firstProtestReason}".`); chai_1.expect(lines[1]).to.equal(`Tossup protest on question 2. Team "${secondTeamPlayer.teamName}" protested because of this reason: "${secondProtestReason}".`); }); }); it("Bonus protest", () => { const firstProtestReason = "First protest"; const firstProtestAnswer = "First answer"; const secondProtestReason = "Second protest"; const secondProtestAnswer = "Second answer"; verifyToQBJ((game) => { game.cycles[0].addCorrectBuzz({ player: firstTeamPlayers[0], points: 10, position: 0, isLastWord: false, }, 0, game.gameFormat, 0, 3); game.cycles[0].addBonusProtest(0, 0, firstProtestAnswer, firstProtestReason, firstTeamPlayers[0].teamName); game.cycles[1].addCorrectBuzz({ player: firstTeamPlayers[0], points: 10, position: 1, isLastWord: true, }, 1, game.gameFormat, 1, 3); game.cycles[1].setBonusPartAnswer(2, firstTeamPlayers[0].teamName, 10); game.cycles[1].addBonusProtest(1, 2, secondProtestAnswer, secondProtestReason, secondTeamPlayer.teamName); }, (match) => { chai_1.expect(match.tossups_read).to.equal(4); chai_1.expect(match.match_questions.map((q) => q.question_number)).to.deep.equal([1, 2, 3, 4]); if (match.notes == undefined) { chai_1.assert.fail("match.notes should be defined."); } const lines = match.notes.split("\n"); chai_1.expect(lines.length).to.equal(2); chai_1.expect(lines[0]).to.equal(`Bonus protest on question 1. Team "${firstTeamPlayers[0].teamName}" protested part 1 because of this reason: "${firstProtestReason}".`); chai_1.expect(lines[1]).to.equal(`Bonus protest on question 2. Team "${secondTeamPlayer.teamName}" protested part 3 because of this reason: "${secondProtestReason}".`); }); }); it("Thrown out tossup", () => { verifyToQBJ((game) => { game.cycles[0].addThrownOutTossup(0); game.cycles[0].addCorrectBuzz({ player: firstTeamPlayers[0], points: 10, position: 1, isLastWord: true, }, 1, game.gameFormat, 0, 3); }, (match) => { chai_1.expect(match.tossups_read).to.equal(4); chai_1.expect(match.match_questions.map((q) => q.question_number)).to.deep.equal([1, 2, 3, 4]); if (match.notes == undefined) { chai_1.assert.fail("match.notes should be defined."); } const lines = match.notes.split("\n"); chai_1.expect(lines.length).to.equal(1); chai_1.expect(lines[0]).to.equal("Tossup thrown out on question 1"); const replacementTossup = match.match_questions[0].replacement_tossup_question; if (replacementTossup == undefined) { chai_1.ass