@@ -3,24 +3,51 @@ import { Participant, Match, MatchResults, ParticipantResult, ViewerData } from
3
3
import { splitBy , getRanking , rankingHeader } from "./helpers" ;
4
4
5
5
type ConnectionType = 'square' | 'straight' | false ;
6
+ type Placement = 'before' | 'after' ;
6
7
7
8
interface Connection {
8
9
connectPrevious ?: ConnectionType ,
9
10
connectNext ?: ConnectionType ,
10
11
}
11
12
13
+ interface Config {
14
+ /**
15
+ * Where the position of a participant is placed.
16
+ * - If `before`, the position is prepended before the team name. "#1 Team"
17
+ * - If `after`, the position is appended after the team name, in parentheses. "Team (#1)"
18
+ */
19
+ participantPositionPlacement : Placement ,
20
+
21
+ /**
22
+ * Whether to show the position of a participant wherever possible.
23
+ */
24
+ showParticipantPosition : boolean ,
25
+
26
+ /**
27
+ * Whether to show the position of a participant in the lower bracket of an elimination stage.
28
+ */
29
+ showLowerBracketParticipantPosition : boolean ,
30
+ }
31
+
12
32
class BracketsViewer {
13
33
14
34
readonly teamRefsDOM : { [ key : number ] : HTMLElement [ ] } = { } ;
15
35
private participants ! : Participant [ ] ;
36
+ private config ! : Config ;
16
37
17
- public render ( rootSelector : string , data : ViewerData ) {
38
+ public render ( rootSelector : string , data : ViewerData , config ?: Config ) {
18
39
const root = $ ( rootSelector ) ;
19
40
20
41
if ( root . length === 0 ) {
21
42
throw Error ( 'Root not found. You must have a root element with id "root"' )
22
43
}
23
44
45
+ this . config = {
46
+ participantPositionPlacement : config && config . participantPositionPlacement || 'before' ,
47
+ showParticipantPosition : config && config . showParticipantPosition || true ,
48
+ showLowerBracketParticipantPosition : config && config . showLowerBracketParticipantPosition || false ,
49
+ } ;
50
+
24
51
switch ( data . stage . type ) {
25
52
case 'round_robin' :
26
53
this . renderRoundRobin ( root , data ) ;
@@ -162,7 +189,7 @@ class BracketsViewer {
162
189
} ;
163
190
}
164
191
165
- roundDOM . append ( this . renderMatch ( match , connection , `M ${ roundNumber } .${ match . number } ` ) ) ;
192
+ roundDOM . append ( this . renderMatch ( match , connection , `M ${ roundNumber } .${ match . number } ` , lowerBracket ) ) ;
166
193
}
167
194
168
195
bracket . append ( roundDOM ) ;
@@ -189,9 +216,9 @@ class BracketsViewer {
189
216
}
190
217
}
191
218
192
- private renderMatch ( results : MatchResults , connection ?: Connection , label ?: string ) {
193
- const team1 = this . renderTeam ( results . opponent1 ) ;
194
- const team2 = this . renderTeam ( results . opponent2 ) ;
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 ) ;
195
222
196
223
const teams = $ ( '<div class="teams">' ) ;
197
224
if ( label ) teams . append ( $ ( '<span>' ) . text ( label ) ) ;
@@ -215,7 +242,7 @@ class BracketsViewer {
215
242
return match ;
216
243
}
217
244
218
- private renderTeam ( team : ParticipantResult | null ) {
245
+ private renderTeam ( team : ParticipantResult | null , lowerBracket : boolean ) {
219
246
const teamDOM = $ ( `<div class="team">` ) ;
220
247
const nameDOM = $ ( '<div class="name">' ) ;
221
248
const resultDOM = $ ( '<div class="result">' ) ;
@@ -228,8 +255,7 @@ class BracketsViewer {
228
255
nameDOM . text ( participant === undefined ? 'TBD' : participant . name ) ;
229
256
resultDOM . text ( team . score === undefined ? '-' : team . score ) ;
230
257
231
- if ( team . position !== undefined )
232
- nameDOM . append ( $ ( '<span>' ) . text ( ` (#${ team . position } )` ) ) ;
258
+ this . renderTeamPosition ( nameDOM , team , lowerBracket ) ;
233
259
234
260
if ( team . result && team . result === 'win' ) {
235
261
nameDOM . addClass ( 'win' ) ;
@@ -263,6 +289,24 @@ class BracketsViewer {
263
289
264
290
return teamDOM ;
265
291
}
292
+
293
+ private renderTeamPosition ( name : JQuery , team : ParticipantResult , lowerBracket : boolean ) {
294
+ if ( team . position === undefined ) return ;
295
+ if ( ! this . config . showParticipantPosition ) return ;
296
+ if ( ! this . config . showLowerBracketParticipantPosition && lowerBracket ) return ;
297
+
298
+ // 'P' for position (where the participant comes from) and '#' for actual seeding.
299
+ const text = lowerBracket ? `P${ team . position } ` : `#${ team . position } ` ;
300
+
301
+ this . addPosition ( name , text , this . config . participantPositionPlacement ) ;
302
+ }
303
+
304
+ private addPosition ( name : JQuery , text : string , placement : Placement , ) {
305
+ if ( placement === 'before' )
306
+ name . prepend ( $ ( '<span>' ) . text ( `${ text } ` ) ) ;
307
+ else
308
+ name . append ( $ ( '<span>' ) . text ( ` (${ text } )` ) ) ;
309
+ }
266
310
}
267
311
268
312
( window as any ) . bracketsViewer = new BracketsViewer ( ) ;
0 commit comments