brackets-manager
Version:
A simple library to manage tournament brackets (round-robin, single elimination, double elimination)
151 lines • 6.94 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BracketsManager = void 0;
const create_1 = require("./create");
const get_1 = require("./get");
const update_1 = require("./update");
const delete_1 = require("./delete");
const find_1 = require("./find");
const reset_1 = require("./reset");
const uuid_1 = require("uuid");
const helpers = require("./helpers");
/**
* A class to handle tournament management at those levels: `stage`, `group`, `round`, `match` and `match_game`.
*/
class BracketsManager {
/**
* Creates an instance of BracketsManager, which will handle all the stuff from the library.
*
* @param storageInterface An implementation of CrudInterface.
* @param verbose Whether to log CRUD operations.
*/
constructor(storageInterface, verbose) {
this.verbose = false;
this.verbose = verbose !== null && verbose !== void 0 ? verbose : false;
this.storage = storageInterface;
this.instrumentStorage();
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
this.storage.selectFirst = async (table, filter, assertUnique = true) => {
var _a;
const results = await this.storage.select(table, filter);
if (!results || results.length === 0)
return null;
if (assertUnique && results.length > 1)
throw Error(`Selecting ${JSON.stringify(filter)} on table "${table}" must return a unique value.`);
return (_a = results[0]) !== null && _a !== void 0 ? _a : null;
};
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
this.storage.selectLast = async (table, filter, assertUnique = true) => {
var _a;
const results = await this.storage.select(table, filter);
if (!results || results.length === 0)
return null;
if (assertUnique && results.length > 1)
throw Error(`Selecting ${JSON.stringify(filter)} on table "${table}" must return a unique value.`);
return (_a = results[results.length - 1]) !== null && _a !== void 0 ? _a : null;
};
const create = new create_1.Create(this.storage);
const createStageFunction = create.stage.bind(this);
this.create = Object.assign(createStageFunction, { stage: createStageFunction });
this.get = new get_1.Get(this.storage);
this.update = new update_1.Update(this.storage);
this.delete = new delete_1.Delete(this.storage);
this.find = new find_1.Find(this.storage);
this.reset = new reset_1.Reset(this.storage);
}
/**
* Imports data in the database.
*
* @param data Data to import.
* @param normalizeIds Enable ID normalization: all IDs (and references to them) are remapped to consecutive IDs starting from 0.
*/
async import(data, normalizeIds = false) {
if (normalizeIds)
data = helpers.normalizeIds(data);
if (!await this.storage.delete('participant'))
throw Error('Could not empty the participant table.');
if (!await this.storage.insert('participant', data.participant))
throw Error('Could not import participants.');
if (!await this.storage.delete('stage'))
throw Error('Could not empty the stage table.');
if (!await this.storage.insert('stage', data.stage))
throw Error('Could not import stages.');
if (!await this.storage.delete('group'))
throw Error('Could not empty the group table.');
if (!await this.storage.insert('group', data.group))
throw Error('Could not import groups.');
if (!await this.storage.delete('round'))
throw Error('Could not empty the round table.');
if (!await this.storage.insert('round', data.round))
throw Error('Could not import rounds.');
if (!await this.storage.delete('match'))
throw Error('Could not empty the match table.');
if (!await this.storage.insert('match', data.match))
throw Error('Could not import matches.');
if (!await this.storage.delete('match_game'))
throw Error('Could not empty the match_game table.');
if (!await this.storage.insert('match_game', data.match_game))
throw Error('Could not import match games.');
}
/**
* Exports data from the database.
*/
async export() {
const participants = await this.storage.select('participant');
if (!participants)
throw Error('Error getting participants.');
const stages = await this.storage.select('stage');
if (!stages)
throw Error('Error getting stages.');
const groups = await this.storage.select('group');
if (!groups)
throw Error('Error getting groups.');
const rounds = await this.storage.select('round');
if (!rounds)
throw Error('Error getting rounds.');
const matches = await this.storage.select('match');
if (!matches)
throw Error('Error getting matches.');
const matchGames = await this.get.matchGames(matches);
return {
participant: participants,
stage: stages,
group: groups,
round: rounds,
match: matches,
match_game: matchGames,
};
}
/**
* Add `console.log()` to storage methods in verbose mode.
*/
instrumentStorage() {
const storage = this.storage;
const instrumentedMethods = ['insert', 'select', 'update', 'delete'];
for (const method of Object.getOwnPropertyNames(Object.getPrototypeOf(storage))) {
if (!instrumentedMethods.includes(method))
continue;
const originalMethod = storage[method].bind(storage);
storage[method] = async (table, ...args) => {
const verbose = this.verbose;
let id;
let start;
if (verbose) {
id = (0, uuid_1.v4)();
start = Date.now();
console.log(`${id} ${method.toUpperCase()} "${table}" args: ${JSON.stringify(args)}`);
}
const result = await originalMethod(table, ...args);
if (verbose) {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
const duration = Date.now() - start;
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
console.log(`${id} ${duration}ms - Returned ${JSON.stringify(result)}`);
}
return result;
};
}
}
}
exports.BracketsManager = BracketsManager;
//# sourceMappingURL=manager.js.map