UNPKG

brackets-manager

Version:

A simple library to manage tournament brackets (round-robin, single elimination, double elimination)

251 lines 10.2 kB
"use strict"; 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