Skip to content

Commit

Permalink
Merged PR 315: v1.32.2 - Add support for serialized QBJ tournament fi…
Browse files Browse the repository at this point in the history
…le rosters

- Add support for the serialized form of a QBJ tournament file with roster registrations
- Bump version to 1.32.2
  • Loading branch information
alopezlago committed Aug 27, 2024
1 parent 940e84e commit 06d9431
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 4 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "modaq",
"version": "1.32.1",
"version": "1.32.2",
"description": "Quiz Bowl Reader using TypeScript, React, and MobX",
"repository": {
"type": "git",
Expand Down
48 changes: 45 additions & 3 deletions src/qbj/QBJ.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,23 @@ import { IGameFormat } from "../state/IGameFormat";
import { IBuzzMarker } from "../state/IBuzzMarker";

export function parseRegistration(json: string): IResult<Player[]> {
// Either it's a JSON object with "name" or a JSON array
const parsedInput: IRegistration[] | ITournament = JSON.parse(json);
// Either it's a serialized tournament with an objects and version field, a JSON object with "name" or a JSON array
const parsedInput: IRegistration[] | ITournament | ISerializedTournament = JSON.parse(json);
let registrations: IRegistration[];
if (isTournament(parsedInput)) {
registrations = parsedInput.registrations;
} else if (isSerializedTournament(parsedInput)) {
const serializedTournament: ISerializedTournamentObject | undefined = parsedInput.objects.find((object) =>
isTournament(object)
);
if (serializedTournament == undefined) {
return {
success: false,
message: "Objects doesn't have a valid Tournament in it.",
};
}

registrations = serializedTournament.registrations;
} else {
registrations = parsedInput;
}
Expand Down Expand Up @@ -85,10 +97,32 @@ export function parseRegistration(json: string): IResult<Player[]> {
return { success: true, value: players };
}

// Needed for the type guard
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function isSerializedTournament(parsedJson: any): parsedJson is ISerializedTournament {
if (parsedJson.version == undefined || parsedJson.objects == undefined) {
return false;
}

// Needed for the type guard
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const objects: any[] = parsedJson.objects;

if (!Array.isArray(objects)) {
return false;
}

return objects.some((object) => object.type === "Tournament" && isTournament(object));
}

// Needed for the type guard
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function isTournament(registrations: any): registrations is ITournament {
return registrations.name != undefined && registrations.registrations != undefined;
return (
registrations.name != undefined &&
registrations.registrations != undefined &&
Array.isArray(registrations.registrations)
);
}

export function fromQBJ(qbj: IMatch, packet: PacketState, gameFormat: IGameFormat): IResult<GameState> {
Expand Down Expand Up @@ -922,6 +956,14 @@ export interface IMatchQuestionBonusPart {
bounceback_points?: number;
}

// Follow https://schema.quizbowl.technology/serialization/
export interface ISerializedTournament {
version: string;
objects: ISerializedTournamentObject[];
}

export type ISerializedTournamentObject = ITournament & { type: "Tournament" };

// Follow https://schema.quizbowl.technology/tournament
export interface ITournament {
name: string;
Expand Down
51 changes: 51 additions & 0 deletions tests/QBJTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1613,6 +1613,57 @@ describe("QBJTests", () => {
expect(fifthPlayer.isStarter).to.be.true;
});
});

it("Parse serialized registration", () => {
const teamName = "Washington A";
const tournament: QBJ.ISerializedTournament = {
version: "2.1.1",
objects: [
{
type: "Tournament",
name: "My Tournament",
registrations: [
{
name: "Washington",
teams: [
{
name: teamName,
players: [
{
name: "Alice",
},
{
name: "Bob",
},
],
},
],
},
],
},
],
};

const playersResult: IResult<Player[]> = QBJ.parseRegistration(JSON.stringify(tournament));
if (!playersResult.success) {
assert.fail("First result should've succeeded");
}

const players: Player[] = playersResult.value;

expect(players.length).to.equal(2);

const firstPlayer: Player = players[0];
expect(firstPlayer.name).to.equal("Alice");
expect(firstPlayer.teamName).to.equal(teamName);
expect(firstPlayer.isStarter).to.be.true;

const secondPlayer: Player = players[1];
expect(secondPlayer.name).to.equal("Bob");
expect(secondPlayer.teamName).to.equal(teamName);
expect(secondPlayer.isStarter).to.be.true;
});

it("Fifth player in registered team isn't a starter", () => {
const teamName = "Washington A";
const tournament: ITournament = {
Expand Down

0 comments on commit 06d9431

Please sign in to comment.