brackets-manager
Version:
A simple library to manage tournament brackets (round-robin, single elimination, double elimination)
251 lines • 10.2 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.Update = void 0;
const brackets_model_1 = require("brackets-model");
const ordering_1 = require("./ordering");
const updater_1 = require("./base/updater");
const helpers = require("./helpers");
class Update extends updater_1.BaseUpdater {
/**
* Updates partial information of a match. Its id must be given.
*
* This will update related matches accordingly.
*
* @param match Values to change in a match.
*/
async match(match) {
if (match.id === undefined)
throw Error('No match id given.');
const stored = await this.storage.select('match', match.id);
if (!stored)
throw Error('Match not found.');
await this.updateMatch(stored, match);
}
/**
* Updates partial information of a match game. Its id must be given.
*
* This will update the parent match accordingly.
*
* @param game Values to change in a match game.
*/
async matchGame(game) {
const stored = await this.findMatchGame(game);
await this.updateMatchGame(stored, game);
}
/**
* Updates the seed ordering of every ordered round in a stage.
*
* @param stageId ID of the stage.
* @param seedOrdering A list of ordering methods.
*/
async ordering(stageId, seedOrdering) {
const stage = await this.storage.select('stage', stageId);
if (!stage)
throw Error('Stage not found.');
helpers.ensureNotRoundRobin(stage);
const roundsToOrder = await this.getOrderedRounds(stage);
if (seedOrdering.length !== roundsToOrder.length)
throw Error('The count of seed orderings is incorrect.');
for (let i = 0; i < roundsToOrder.length; i++)
await this.updateRoundOrdering(roundsToOrder[i], seedOrdering[i]);
}
/**
* Updates the seed ordering of a round.
*
* @param roundId ID of the round.
* @param method Seed ordering method.
*/
async roundOrdering(roundId, method) {
const round = await this.storage.select('round', roundId);
if (!round)
throw Error('This round does not exist.');
const stage = await this.storage.select('stage', round.stage_id);
if (!stage)
throw Error('Stage not found.');
helpers.ensureNotRoundRobin(stage);
await this.updateRoundOrdering(round, method);
}
/**
* Updates child count of all matches of a given level.
*
* @param level The level at which to act.
* @param id ID of the chosen level.
* @param childCount The target child count.
*/
async matchChildCount(level, id, childCount) {
switch (level) {
case 'stage':
await this.updateStageMatchChildCount(id, childCount);
break;
case 'group':
await this.updateGroupMatchChildCount(id, childCount);
break;
case 'round':
await this.updateRoundMatchChildCount(id, childCount);
break;
case 'match':
const match = await this.storage.select('match', id);
if (!match)
throw Error('Match not found.');
await this.adjustMatchChildGames(match, childCount);
break;
default:
throw Error('Unknown child count level.');
}
}
/**
* Updates the seeding of a stage.
*
* @param stageId ID of the stage.
* @param seeding The new seeding.
* @param keepSameSize Whether to keep the same size as before for the stage. **Default:** false.
*/
async seeding(stageId, seeding, keepSameSize = false) {
await this.updateSeeding(stageId, { seeding }, keepSameSize);
}
/**
* Updates the seeding of a stage (with a list of IDs).
*
* @param stageId ID of the stage.
* @param seedingIds The new seeding, containing only IDs.
* @param keepSameSize Whether to keep the same size as before for the stage. **Default:** false.
*/
async seedingIds(stageId, seedingIds, keepSameSize = false) {
await this.updateSeeding(stageId, { seedingIds }, keepSameSize);
}
/**
* Confirms the seeding of a stage.
*
* This will convert TBDs to BYEs and propagate them.
*
* @param stageId ID of the stage.
*/
async confirmSeeding(stageId) {
await this.confirmCurrentSeeding(stageId);
}
/**
* Update the seed ordering of a round.
*
* @param round The round of which to update the ordering.
* @param method The new ordering method.
*/
async updateRoundOrdering(round, method) {
const matches = await this.storage.select('match', { round_id: round.id });
if (!matches)
throw Error('This round has no match.');
if (matches.some(match => match.status > brackets_model_1.Status.Ready))
throw Error('At least one match has started or is completed.');
const stage = await this.storage.select('stage', round.stage_id);
if (!stage)
throw Error('Stage not found.');
if (stage.settings.size === undefined)
throw Error('Undefined stage size.');
const group = await this.storage.select('group', round.group_id);
if (!group)
throw Error('Group not found.');
const inLoserBracket = helpers.isLoserBracket(stage.type, group.number);
const roundCountLB = helpers.getLowerBracketRoundCount(stage.settings.size);
const seeds = helpers.getSeeds(inLoserBracket, round.number, roundCountLB, matches.length);
const positions = ordering_1.ordering[method](seeds);
await this.applyRoundOrdering(round.number, matches, positions);
}
/**
* Updates child count of all matches of a stage.
*
* @param stageId ID of the stage.
* @param childCount The target child count.
*/
async updateStageMatchChildCount(stageId, childCount) {
if (!await this.storage.update('match', { stage_id: stageId }, { child_count: childCount }))
throw Error('Could not update the match.');
const matches = await this.storage.select('match', { stage_id: stageId });
if (!matches)
throw Error('This stage has no match.');
for (const match of matches)
await this.adjustMatchChildGames(match, childCount);
}
/**
* Updates child count of all matches of a group.
*
* @param groupId ID of the group.
* @param childCount The target child count.
*/
async updateGroupMatchChildCount(groupId, childCount) {
if (!await this.storage.update('match', { group_id: groupId }, { child_count: childCount }))
throw Error('Could not update the match.');
const matches = await this.storage.select('match', { group_id: groupId });
if (!matches)
throw Error('This group has no match.');
for (const match of matches)
await this.adjustMatchChildGames(match, childCount);
}
/**
* Updates child count of all matches of a round.
*
* @param roundId ID of the round.
* @param childCount The target child count.
*/
async updateRoundMatchChildCount(roundId, childCount) {
if (!await this.storage.update('match', { round_id: roundId }, { child_count: childCount }))
throw Error('Could not update the match.');
const matches = await this.storage.select('match', { round_id: roundId });
if (!matches)
throw Error('This round has no match.');
for (const match of matches)
await this.adjustMatchChildGames(match, childCount);
}
/**
* Updates the ordering of participants in a round's matches.
*
* @param roundNumber The number of the round.
* @param matches The matches of the round.
* @param positions The new positions.
*/
async applyRoundOrdering(roundNumber, matches, positions) {
for (const match of matches) {
const updated = { ...match };
updated.opponent1 = helpers.findPosition(matches, positions.shift());
// The only rounds where we have a second ordered participant are first rounds of brackets (upper and lower).
if (roundNumber === 1)
updated.opponent2 = helpers.findPosition(matches, positions.shift());
if (!await this.storage.update('match', updated.id, updated))
throw Error('Could not update the match.');
}
}
/**
* Adds or deletes match games of a match based on a target child count.
*
* @param match The match of which child games need to be adjusted.
* @param targetChildCount The target child count.
*/
async adjustMatchChildGames(match, targetChildCount) {
const games = await this.storage.select('match_game', { parent_id: match.id });
let childCount = games ? games.length : 0;
while (childCount < targetChildCount) {
const id = await this.storage.insert('match_game', {
number: childCount + 1,
stage_id: match.stage_id,
parent_id: match.id,
status: match.status,
opponent1: { id: null },
opponent2: { id: null },
});
if (id === -1)
throw Error('Could not adjust the match games when inserting.');
childCount++;
}
while (childCount > targetChildCount) {
const deleted = await this.storage.delete('match_game', {
parent_id: match.id,
number: childCount,
});
if (!deleted)
throw Error('Could not adjust the match games when deleting.');
childCount--;
}
if (!await this.storage.update('match', match.id, { ...match, child_count: targetChildCount }))
throw Error('Could not update the match.');
}
}
exports.Update = Update;
//# sourceMappingURL=update.js.map
;