diff --git a/package.json b/package.json index ee7a6ba..af47c7f 100644 --- a/package.json +++ b/package.json @@ -40,9 +40,9 @@ ], "homepage": "https://github.com/Drarig29/brackets-viewer.js#readme", "dependencies": { - "brackets-manager": "^1.6.2", - "brackets-memory-db": "^1.0.4", - "brackets-model": "^1.5.0", + "brackets-manager": "^1.8.0", + "brackets-memory-db": "^1.0.5", + "brackets-model": "^1.6.0", "i18next": "^21.6.14", "i18next-browser-languagedetector": "^6.1.4", "path-browserify": "^1.0.1", diff --git a/src/dom.ts b/src/dom.ts index 32be806..37a35f2 100644 --- a/src/dom.ts +++ b/src/dom.ts @@ -1,5 +1,5 @@ -import { Match, ParticipantResult, FinalType, GroupType, Id, MatchGame } from 'brackets-model'; -import { Connection, Placement, Ranking, RankingItem } from './types'; +import { Match, ParticipantResult, FinalType, GroupType, Id, MatchGame, type RankingItem } from 'brackets-model'; +import { Connection, Placement } from './types'; import { isMatchGame, rankingHeader } from './helpers'; import { t } from './lang'; @@ -239,7 +239,7 @@ export function createCell(data: string | number): HTMLElement { * * @param ranking The object containing the ranking. */ -export function createRankingHeaders(ranking: Ranking): HTMLElement { +export function createRankingHeaders(ranking: RankingItem[]): HTMLElement { const headers = document.createElement('tr'); const firstItem = ranking[0]; diff --git a/src/helpers.ts b/src/helpers.ts index ba263e6..836fdae 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -1,5 +1,5 @@ -import { Match, ParticipantResult, GroupType, MatchGame } from 'brackets-model'; -import { RankingHeader, Ranking, RankingFormula, RankingItem, RankingMap, Side, MatchWithMetadata } from './types'; +import { Match, GroupType, MatchGame, RankingItem } from 'brackets-model'; +import { RankingHeader, Side, MatchWithMetadata } from './types'; import { t } from './lang'; /** @@ -171,103 +171,6 @@ export function rankingHeader(itemName: keyof RankingItem): RankingHeader { return t(`ranking.${itemName}`, { returnObjects: true }) as RankingHeader; } -/** - * Calculates the ranking based on a list of matches and a formula. - * - * @param matches The list of matches. - * @param formula The points formula to apply. - */ -export function getRanking(matches: Match[], formula?: RankingFormula): Ranking { - formula = formula || ( - (item: RankingItem): number => 3 * item.wins + 1 * item.draws + 0 * item.losses - ); - - const rankingMap: RankingMap = {}; - - for (const match of matches) { - processParticipant(rankingMap, formula, match.opponent1, match.opponent2); - processParticipant(rankingMap, formula, match.opponent2, match.opponent1); - } - - return createRanking(rankingMap); -} - -/** - * Processes a participant and edits the ranking map. - * - * @param rankingMap The ranking map to edit. - * @param formula The points formula to apply. - * @param current The current participant. - * @param other The opponent. - */ -function processParticipant(rankingMap: RankingMap, formula: RankingFormula, current: ParticipantResult | null, other: ParticipantResult | null): void { - if (!current || current.id === null) return; - - const state = rankingMap[current.id] || { - rank: 0, - id: 0, - played: 0, - wins: 0, - draws: 0, - losses: 0, - forfeits: 0, - scoreFor: 0, - scoreAgainst: 0, - scoreDifference: 0, - points: 0, - }; - - state.id = current.id; - - if (current.forfeit || current.result) - state.played++; - - if (current.result === 'win') - state.wins++; - - if (current.result === 'draw') - state.draws++; - - if (current.result === 'loss') - state.losses++; - - if (current.forfeit) - state.forfeits++; - - state.scoreFor += current.score || 0; - state.scoreAgainst += other && other.score || 0; - state.scoreDifference = state.scoreFor - state.scoreAgainst; - - state.points = formula(state); - - rankingMap[current.id] = state; -} - -/** - * Creates the final ranking based on a ranking map. (Sort + Total points) - * - * @param rankingMap The ranking map (object). - */ -function createRanking(rankingMap: RankingMap): RankingItem[] { - const ranking = Object.values(rankingMap).sort((a, b) => a.points !== b.points - ? b.points - a.points - : a.played !== b.played - ? b.played - a.played - : b.scoreDifference - a.scoreDifference); - - const rank = { - value: 0, - lastPoints: -1, - }; - - for (const item of ranking) { - item.rank = rank.lastPoints !== item.points ? ++rank.value : rank.value; - rank.lastPoints = item.points; - } - - return ranking; -} - /** * Indicates whether the input is a match. * diff --git a/src/main.ts b/src/main.ts index c0563c7..62ac248 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,6 @@ import './style.scss'; -import { Participant, Match, ParticipantResult, Stage, Status, GroupType, FinalType, Id } from 'brackets-model'; -import { splitBy, getRanking, getOriginAbbreviation, findRoot, completeWithBlankMatches, sortBy, isMatchGame, isMatch, splitByWithLeftovers } from './helpers'; +import { Participant, Match, ParticipantResult, Stage, Status, GroupType, FinalType, Id, type RankingItem } from 'brackets-model'; +import { splitBy, getOriginAbbreviation, findRoot, completeWithBlankMatches, sortBy, isMatchGame, isMatch, splitByWithLeftovers } from './helpers'; import * as dom from './dom'; import * as lang from './lang'; import { Locale } from './lang'; @@ -9,7 +9,6 @@ import { Config, OriginHint, ParticipantContainers, - RankingItem, RoundNameGetter, ViewerData, ParticipantImage, @@ -78,7 +77,7 @@ export class BracketsViewer { showPopoverOnMatchLabelClick: config?.showPopoverOnMatchLabelClick ?? true, highlightParticipantOnHover: config?.highlightParticipantOnHover ?? true, showRankingTable: config?.showRankingTable ?? true, - rankingFormula: config?.rankingFormula, + rankingFormula: config?.rankingFormula ?? ((item): number => 3 * item.wins + 1 * item.draws + 0 * item.losses), }; if (config?.onMatchClick) @@ -482,13 +481,13 @@ export class BracketsViewer { } /** - * Creates a ranking table based on matches of a round-robin stage. + * Creates a ranking table for a group of a round-robin stage. * - * @param matches The list of matches. + * @param matches The list of matches in the group. */ private createRanking(matches: Match[]): HTMLElement { const table = dom.createTable(); - const ranking = getRanking(matches, this.config.rankingFormula); + const ranking = helpers.getRanking(matches, this.config.rankingFormula!); table.append(dom.createRankingHeaders(ranking)); diff --git a/src/types.ts b/src/types.ts index a5375f9..1d13d59 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,4 @@ -import { Stage, Match, MatchGame, Participant, GroupType, FinalType, Id, StageType } from 'brackets-model'; +import { Stage, Match, MatchGame, Participant, GroupType, FinalType, StageType, RankingItem, RankingFormula } from 'brackets-model'; import { CallbackFunction, FormConfiguration } from './form'; import { InMemoryDatabase } from 'brackets-memory-db'; import { BracketsViewer } from './main'; @@ -190,7 +190,7 @@ export interface Config { highlightParticipantOnHover?: boolean, /** - * Whether to show a ranking table on round-robin stages. + * Whether to show a ranking table in each group of a round-robin stage. * * @default true */ @@ -263,23 +263,6 @@ export interface Connection { connectNext?: ConnectionType, } -/** - * An item of the ranking. - */ -export interface RankingItem { - rank: number, - id: Id, - played: number, - wins: number, - draws: number, - losses: number, - forfeits: number, - scoreFor: number, - scoreAgainst: number, - scoreDifference: number, - points: number, -} - /** * Contains information about a header of the ranking and its tooltip. */ @@ -288,26 +271,11 @@ export interface RankingHeader { tooltip: string, } -/** - * A formula which computes points given a ranking row. - */ -export type RankingFormula = (ranking: RankingItem) => number; - /** * An object mapping ranking properties to their header. */ export type RankingHeaders = Record; -/** - * An object mapping a participant id to its row in the ranking. - */ -export type RankingMap = Record; - -/** - * Definition of a ranking. - */ -export type Ranking = RankingItem[]; - /** * Structure containing all the containers for a participant. */