Skip to content

Commit

Permalink
Fix bug with get.nextMatches() for winner of WB final
Browse files Browse the repository at this point in the history
  • Loading branch information
Drarig29 committed Aug 7, 2023
1 parent 3083119 commit 0069cae
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 11 deletions.
78 changes: 67 additions & 11 deletions src/find.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,27 +105,42 @@ export class Find extends BaseGetter {
);

if (participantId !== undefined) {
if (!helpers.isParticipantInMatch(match, participantId))
throw Error('The participant does not belong to this match.');

if (!helpers.isMatchStale(match))
throw Error('The match is not stale yet, so it is not possible to conclude the next matches for this participant.');

const loser = helpers.getLoser(match);
if (stage.type === 'single_elimination' && loser?.id === participantId)
return []; // Eliminated.

if (stage.type === 'double_elimination') {
const [upperBracketMatch, lowerBracketMatch] = nextMatches;
const { winnerBracketMatch, loserBracketMatch, finalGroupMatch } = await this.getMatchesByGroupDoubleElimination(nextMatches, new Map([[group.id, group]]));
const winner = helpers.getWinner(match);

if (loser?.id === participantId) {
if (lowerBracketMatch)
return [lowerBracketMatch];
else
if (matchLocation === 'loser_bracket') {
if (participantId === loser?.id)
return []; // Eliminated from lower bracket.
}

const winner = helpers.getWinner(match);
if (winner?.id === participantId)
return [upperBracketMatch];
if (participantId === winner?.id)
return loserBracketMatch ? [loserBracketMatch] : [];
} else if (matchLocation === 'winner_bracket') {
if (!loserBracketMatch)
throw Error('All matches of winner bracket should lead to loser bracket.');

throw Error('The participant does not belong to this match.');
}
if (participantId === loser?.id)
return [loserBracketMatch]; // Eliminated from upper bracket, going to lower bracket.

if (participantId === winner?.id)
return winnerBracketMatch ? [winnerBracketMatch] : [];
} else if (matchLocation === 'final_group') {
if (!finalGroupMatch)
throw Error('All matches of a final group should also lead to the final group.');

return [finalGroupMatch];
}
}
}

return nextMatches;
Expand All @@ -152,4 +167,45 @@ export class Find extends BaseGetter {
public async matchGame(game: Partial<MatchGame>): Promise<MatchGame> {
return this.findMatchGame(game);
}

/**
* Returns an object with 1 match per group type. Only supports double elimination.
*
* @param matches A list of matches.
* @param fetchedGroups A map of groups which were already fetched.
*/
private async getMatchesByGroupDoubleElimination(matches: Match[], fetchedGroups: Map<Id, Group>): Promise<{
winnerBracketMatch?: Match;
loserBracketMatch?: Match;
finalGroupMatch?: Match;
}> {
const getGroup = async (groupId: Id): Promise<Group> => {
const existing = fetchedGroups.get(groupId);
if (existing)
return existing;

const group = await this.storage.select('group', groupId);
if (!group) throw Error('Group not found.');
fetchedGroups.set(groupId, group);
return group;
};

let matchByGroupType: {
winnerBracketMatch?: Match
loserBracketMatch?: Match
finalGroupMatch?: Match
} = {};

for (const match of matches) {
const group = await getGroup(match.group_id);

matchByGroupType = {
winnerBracketMatch: matchByGroupType['winnerBracketMatch'] ?? (helpers.isWinnerBracket('double_elimination', group.number) ? match : undefined),
loserBracketMatch: matchByGroupType['loserBracketMatch'] ?? (helpers.isLoserBracket('double_elimination', group.number) ? match : undefined),
finalGroupMatch: matchByGroupType['finalGroupMatch'] ?? (helpers.isFinalGroup('double_elimination', group.number) ? match : undefined),
};
}

return matchByGroupType;
}
}
11 changes: 11 additions & 0 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,17 @@ export function isMatchOngoing(match: MatchResults): boolean {
return [Status.Ready, Status.Running].includes(match.status);
}

/**
* Checks if a match is stale (i.e. it should not change anymore).
*
* [Locked - BYE] > Waiting > Ready > Running > [Completed > Archived]
*
* @param match Partial match results.
*/
export function isMatchStale(match: MatchResults): boolean {
return match.status >= Status.Completed || isMatchByeCompleted(match);
}

/**
* Checks if a match is completed because of a forfeit.
*
Expand Down
9 changes: 9 additions & 0 deletions test/find.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,15 @@ describe('Find previous and next matches in double elimination', () => {
assert.strictEqual(afterLowerBracketContinued.length, 1);
assert.strictEqual(afterLowerBracketContinued[0].id, 4);

await assert.isRejected(manager.find.nextMatches(2, 1), 'The match is not stale yet, so it is not possible to conclude the next matches for this participant.');

await manager.update.match({ id: 2, opponent1: { result: 'win' } });
const afterFinalWBForWinner = await manager.find.nextMatches(2, 1);
assert.strictEqual(afterFinalWBForWinner.length, 0);
const afterFinalWBForLoser = await manager.find.nextMatches(2, 2);
assert.strictEqual(afterFinalWBForLoser.length, 1);
assert.strictEqual(afterFinalWBForLoser[0].id, 4);

await assert.isRejected(manager.find.nextMatches(3, 42), 'The participant does not belong to this match.');
});
});

0 comments on commit 0069cae

Please sign in to comment.