Skip to content

Commit 3e1bae0

Browse files
committed
Add hints for position
1 parent f8d83ee commit 3e1bae0

File tree

3 files changed

+96
-29
lines changed

3 files changed

+96
-29
lines changed

demo/db.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,8 @@
777777
"id": null
778778
},
779779
"opponent2": {
780-
"id": null
780+
"id": null,
781+
"position": 1
781782
}
782783
}
783784
],

src/helpers.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ const headers: Headers = {
8282
},
8383
}
8484

85+
export function isMajorRound(roundNumber: number) {
86+
return roundNumber === 1 || roundNumber % 2 === 0;
87+
}
88+
8589
export function rankingHeader(name: keyof Ranking): Header {
8690
return headers[name];
8791
}

src/main.ts

Lines changed: 90 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import './style.scss';
22
import { Participant, Match, MatchResults, ParticipantResult, ViewerData } from "brackets-model";
3-
import { splitBy, getRanking, rankingHeader } from "./helpers";
3+
import { splitBy, getRanking, rankingHeader, isMajorRound } from "./helpers";
44

55
type ConnectionType = 'square' | 'straight' | false;
66
type Placement = 'none' | 'before' | 'after';
7+
type FinalType = 'consolation_final' | 'grand_final';
8+
type MatchHint = ((i: number) => string) | undefined;
79

810
interface Connection {
911
connectPrevious?: ConnectionType,
@@ -166,30 +168,21 @@ class BracketsViewer {
166168
/**
167169
* Renders a bracket.
168170
*/
169-
private renderBracket(root: JQuery, matchesByRound: Match[][], roundName: (roundNumber: number) => string, lowerBracket?: boolean, connectFinal?: boolean) {
171+
private renderBracket(root: JQuery, matchesByRound: Match[][], roundName: (roundNumber: number) => string, inLowerBracket?: boolean, connectFinal?: boolean) {
170172
const bracket = $('<section class="bracket">');
173+
const roundCount = matchesByRound.length;
171174

172175
let roundNumber = 1;
173176

174177
for (const matches of matchesByRound) {
175178
const roundDOM = $('<article class="round">').append($('<h3>').text(roundName(roundNumber)));
176179

177180
for (const match of matches) {
178-
let connection: Connection;
179-
180-
if (lowerBracket) {
181-
connection = {
182-
connectPrevious: roundNumber > 1 && (roundNumber % 2 === 1 ? 'square' : 'straight'),
183-
connectNext: roundNumber < matchesByRound.length && (roundNumber % 2 === 0 ? 'square' : 'straight'),
184-
};
185-
} else {
186-
connection = {
187-
connectPrevious: roundNumber > 1 && 'square',
188-
connectNext: roundNumber < matchesByRound.length ? 'square' : (connectFinal ? 'straight' : false),
189-
};
190-
}
181+
const connection = this.getConnection(inLowerBracket, roundNumber, matchesByRound, connectFinal);
182+
const matchLabel = this.getMatchLabel(match, roundNumber, roundCount, inLowerBracket);
183+
const matchHint = this.getMatchHint(inLowerBracket, roundNumber, roundCount);
191184

192-
roundDOM.append(this.renderMatch(match, connection, `M ${roundNumber}.${match.number}`, lowerBracket));
185+
roundDOM.append(this.renderMatch(match, connection, matchLabel, matchHint, inLowerBracket));
193186
}
194187

195188
bracket.append(roundDOM);
@@ -199,26 +192,89 @@ class BracketsViewer {
199192
root.append(bracket);
200193
}
201194

202-
private renderFinal(type: 'consolation_final' | 'grand_final', matches: Match[]) {
195+
private getMatchHint(inLowerBracket: boolean | undefined, roundNumber: number, roundCount: number): MatchHint {
196+
if (!inLowerBracket && roundNumber === 1)
197+
return (i: number) => `Seed ${i}`;
198+
199+
if (inLowerBracket && isMajorRound(roundNumber)) {
200+
const roundNumberWB = Math.ceil((roundNumber + 1) / 2);
201+
202+
let hint = (i: number) => `Loser of WB ${roundNumberWB}.${i}`;
203+
204+
if (roundNumber === roundCount - 2)
205+
hint = (i: number) => `Loser of WB Semi ${i}`;
206+
207+
if (roundNumber === roundCount)
208+
hint = () => 'Loser of WB Final';
209+
210+
return hint;
211+
}
212+
213+
return undefined;
214+
}
215+
216+
private getConnection(inLowerBracket: boolean | undefined, roundNumber: number, matchesByRound: Match[][], connectFinal: boolean | undefined): Connection {
217+
if (inLowerBracket) {
218+
return {
219+
connectPrevious: roundNumber > 1 && (roundNumber % 2 === 1 ? 'square' : 'straight'),
220+
connectNext: roundNumber < matchesByRound.length && (roundNumber % 2 === 0 ? 'square' : 'straight'),
221+
};
222+
}
223+
224+
return {
225+
connectPrevious: roundNumber > 1 && 'square',
226+
connectNext: roundNumber < matchesByRound.length ? 'square' : (connectFinal ? 'straight' : false),
227+
}
228+
}
229+
230+
private getMatchLabel(match: Match, roundNumber: number, roundCount: number, inLowerBracket: boolean | undefined) {
231+
let matchPrefix = 'M';
232+
233+
if (inLowerBracket)
234+
matchPrefix = 'LB';
235+
else if (inLowerBracket === false)
236+
matchPrefix = 'WB';
237+
238+
const semiFinalRound = roundNumber === roundCount - 1;
239+
const finalRound = roundNumber === roundCount;
240+
241+
let matchLabel = `${matchPrefix} ${roundNumber}.${match.number}`;
242+
243+
if (!inLowerBracket && semiFinalRound)
244+
matchLabel = `Semi ${match.number}`;
245+
246+
if (finalRound)
247+
matchLabel = 'Final';
248+
249+
return matchLabel;
250+
}
251+
252+
private renderFinal(type: FinalType, matches: Match[]) {
203253
const upperBracket = $('.bracket').eq(0);
204-
const grandFinalName = matches.length === 1 ? () => 'Grand Final' : (i: number) => `Grand Final R${i + 1}`;
254+
const grandFinalName = matches.length === 1 ? () => 'Grand Final' : (i: number) => `GF Round ${i + 1}`;
255+
const grandFinalMatchHint = (i: number) => i === 0 ? () => 'Winner of LB Final' : undefined;
205256

206257
for (let i = 0; i < matches.length; i++) {
258+
const matchLabel = type === 'consolation_final' ? 'Consolation Final' : grandFinalName(i);
259+
const matchHint = type === 'consolation_final' ? (i: number) => `Loser of Semi ${i}` : grandFinalMatchHint(i);
260+
207261
const matchDOM = this.renderMatch(matches[i], {
208262
connectPrevious: type === 'grand_final' && (i === 0 && 'straight'),
209263
connectNext: matches.length === 2 && i === 0 && 'straight',
210-
});
264+
}, matchLabel, matchHint, undefined);
211265

212-
const roundDOM = $('<article class="round">').append($('<h3>').text(type === 'grand_final' ? grandFinalName(i) : 'Consolation Final'));
266+
const roundDOM = $('<article class="round">').append($('<h3>').text(matchLabel));
213267
roundDOM.append(matchDOM);
214268

215269
upperBracket.append(roundDOM);
216270
}
217271
}
218272

219-
private renderMatch(results: MatchResults, connection?: Connection, label?: string, lowerBracket?: boolean) {
220-
const team1 = this.renderTeam(results.opponent1, lowerBracket || false);
221-
const team2 = this.renderTeam(results.opponent2, lowerBracket || false);
273+
private renderMatch(results: MatchResults, connection?: Connection, label?: string, hint?: MatchHint, inLowerBracket?: boolean) {
274+
inLowerBracket = inLowerBracket || false;
275+
276+
const team1 = this.renderTeam(results.opponent1, hint, inLowerBracket);
277+
const team2 = this.renderTeam(results.opponent2, hint, inLowerBracket);
222278

223279
const teams = $('<div class="teams">');
224280
if (label) teams.append($('<span>').text(label));
@@ -242,7 +298,7 @@ class BracketsViewer {
242298
return match;
243299
}
244300

245-
private renderTeam(team: ParticipantResult | null, lowerBracket: boolean) {
301+
private renderTeam(team: ParticipantResult | null, hint: MatchHint, inLowerBracket: boolean) {
246302
const teamDOM = $(`<div class="team">`);
247303
const nameDOM = $('<div class="name">');
248304
const resultDOM = $('<div class="result">');
@@ -254,7 +310,9 @@ class BracketsViewer {
254310

255311
if (participant) {
256312
nameDOM.text(participant.name);
257-
this.renderTeamOrigin(nameDOM, team, lowerBracket);
313+
this.renderTeamOrigin(nameDOM, team, inLowerBracket);
314+
} else if (hint && team.position) {
315+
this.renderHint(nameDOM, hint(team.position));
258316
}
259317

260318
resultDOM.text(team.score === undefined ? '-' : team.score);
@@ -292,14 +350,18 @@ class BracketsViewer {
292350
return teamDOM;
293351
}
294352

295-
private renderTeamOrigin(name: JQuery, team: ParticipantResult, lowerBracket: boolean) {
353+
private renderHint(name: JQuery, hint: string) {
354+
name.text(hint);
355+
}
356+
357+
private renderTeamOrigin(name: JQuery, team: ParticipantResult, inLowerBracket: boolean) {
296358
if (team.position === undefined) return;
297359
if (this.config.participantOriginPlacement === 'none') return;
298360
if (!this.config.showSlotsOrigin) return;
299-
if (!this.config.showLowerBracketSlotsOrigin && lowerBracket) return;
361+
if (!this.config.showLowerBracketSlotsOrigin && inLowerBracket) return;
300362

301363
// 'P' for position (where the participant comes from) and '#' for actual seeding.
302-
const text = lowerBracket ? `P${team.position}` : `#${team.position}`;
364+
const text = inLowerBracket ? `P${team.position}` : `#${team.position}`;
303365

304366
this.addTeamOrigin(name, text, this.config.participantOriginPlacement);
305367
}

0 commit comments

Comments
 (0)