Skip to content

Commit

Permalink
feat: basic winner detection for 1on1 games (#98)
Browse files Browse the repository at this point in the history
* feat: basic winner detection for 1on1 games

* improvement: winner detection test cases

* test: more test replays

* test: naming and schema description
  • Loading branch information
PBug90 authored Apr 12, 2022
1 parent 947cecc commit 031bf52
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 1 deletion.
29 changes: 28 additions & 1 deletion src/W3GReplay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export default class W3GReplay extends EventEmitter {
msElapsed = 0;
slotToPlayerId = new Map<number, number>();
knownPlayerIds: Set<string>;
winningTeamId = -1;

constructor() {
super();
Expand Down Expand Up @@ -129,11 +130,37 @@ export default class W3GReplay extends EventEmitter {

this.generateID();
this.determineMatchup();
this.determineWinningTeam();
this.cleanup();

return this.finalize();
}

private determineWinningTeam() {
if (this.gametype === "1on1") {
let winningTeamId = -1;
this.leaveEvents.forEach((event, index) => {
if (
this.isObserver(this.players[event.playerId]) === true ||
winningTeamId !== -1
) {
return;
}
if (event.result === "09000000") {
winningTeamId = this.players[event.playerId].teamid;
return;
}
if (event.reason === "0c000000") {
winningTeamId = this.players[event.playerId].teamid;
}
if (index === this.leaveEvents.length - 1) {
winningTeamId = this.players[event.playerId].teamid;
}
});
this.winningTeamId = winningTeamId;
}
}

handleBasicReplayInformation(info: BasicReplayInformation): void {
this.info = info;
this.slots = info.metadata.slotRecords;
Expand Down Expand Up @@ -366,7 +393,6 @@ export default class W3GReplay extends EventEmitter {

cleanup(): void {
this.observers = [];

Object.values(this.players).forEach((p) => {
p.newActionTrackingSegment(this.playerActionTrackInterval);
p.cleanup();
Expand Down Expand Up @@ -444,6 +470,7 @@ export default class W3GReplay extends EventEmitter {
expansion: this.info.subheader.gameIdentifier === "PX3W",
settings,
parseTime: Math.round(performance.now() - this.parseStartTime),
winningTeamId: this.winningTeamId,
};
return root;
}
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export interface ParserOutput {
duration: number;
expansion: boolean;
parseTime: number;
winningTeamId: number;
settings: {
observerMode: ObserverMode;
fixedTeams: boolean;
Expand Down
Binary file added test/replays/132/1448202825.w3g
Binary file not shown.
Binary file added test/replays/132/1640262494.w3g
Binary file not shown.
Binary file not shown.
Binary file added test/replays/132/esl_cup_vs_changer_1.w3g
Binary file not shown.
47 changes: 47 additions & 0 deletions test/replays/132/replays.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,50 @@ it("should parse kotg as level 6", async () => {
const test = await Parser.parse(path.resolve(__dirname, "706266088.w3g"));
expect(test.players[1].heroes[0].level).toBe(6);
});

describe("winner detection", () => {
it("should set winningTeamId to teamId of winner of game 1640262494.w3g", async () => {
const test = await Parser.parse(path.resolve(__dirname, "1640262494.w3g"));
expect(test.winningTeamId).toBe(0);
expect(
test.players.find((player) => player.teamid === test.winningTeamId)!.name
).toBe("Happie");
});

it("should set winningTeamId to teamId of winner of game 1448202825.w3g", async () => {
const test = await Parser.parse(path.resolve(__dirname, "1448202825.w3g"));
expect(test.winningTeamId).toBe(1);
expect(
test.players.find((player) => player.teamid === test.winningTeamId)!.name
).toBe("ThundeR#31281");
});

it("should set winningTeamId to teamId of winner of game wan_vs_trunks.w3g", async () => {
const test = await Parser.parse(
path.resolve(__dirname, "wan_vs_trunks.w3g")
);
expect(test.winningTeamId).toBe(0);
expect(
test.players.find((player) => player.teamid === test.winningTeamId)!.name
).toBe("WaN#1734");
});
it("should set winningTeamId to teamId of winner of game benjiii_vs_Scars_Concealed_Hill.w3g", async () => {
const test = await Parser.parse(
path.resolve(__dirname, "benjiii_vs_Scars_Concealed_Hill.w3g")
);
expect(test.winningTeamId).toBe(1);
expect(
test.players.find((player) => player.teamid === test.winningTeamId)!.name
).toBe("benjiii#1588");
});

it("should set winningTeamId to teamId of winner of game esl_cup_vs_changer_1.w3g", async () => {
const test = await Parser.parse(
path.resolve(__dirname, "esl_cup_vs_changer_1.w3g")
);
expect(test.winningTeamId).toBe(0);
expect(
test.players.find((player) => player.teamid === test.winningTeamId)!.name
).toBe("TapioN#2351");
});
});
Binary file added test/replays/132/wan_vs_trunks.w3g
Binary file not shown.
5 changes: 5 additions & 0 deletions test/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,11 @@
"type": "integer",
"title": "The amount of time it took to parse the replay, in ms."
},
"winningTeamId": {
"$id": "#/properties/winningTeamId",
"type": "integer",
"title": "Identifier of the best guess of which team id has won the game. -1 if it could not be determined. Currently only evaluated if type is \"1on1\""
},
"observers": {
"$id": "#/properties/observers",
"type": "array",
Expand Down

0 comments on commit 031bf52

Please sign in to comment.