@ethlete/bracket 1.0.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +9 -0
- package/fesm2022/ethlete-bracket.mjs +3723 -0
- package/fesm2022/ethlete-bracket.mjs.map +1 -0
- package/package.json +21 -0
- package/types/ethlete-bracket.d.ts +1021 -0
|
@@ -0,0 +1,1021 @@
|
|
|
1
|
+
import * as _ethlete_bracket from '@ethlete/bracket';
|
|
2
|
+
|
|
3
|
+
declare const BRACKET_ERROR_CODES: {
|
|
4
|
+
/** The source has no rounds/matches to render. */
|
|
5
|
+
readonly SOURCE_EMPTY: 3401;
|
|
6
|
+
/** An integration received a tournament mode it does not support. */
|
|
7
|
+
readonly MODE_UNSUPPORTED: 3402;
|
|
8
|
+
/** Two rounds in the source share an id. */
|
|
9
|
+
readonly DUPLICATE_ROUND: 3403;
|
|
10
|
+
/** Two matches in the source share an id. */
|
|
11
|
+
readonly DUPLICATE_MATCH: 3404;
|
|
12
|
+
/** A round-to-round relation could not be resolved (malformed round structure). */
|
|
13
|
+
readonly ROUND_RELATION_INVALID: 3405;
|
|
14
|
+
/** A match-to-match relation could not be resolved (match counts don't line up). */
|
|
15
|
+
readonly MATCH_RELATION_INVALID: 3406;
|
|
16
|
+
/** The computed layout grid is in an inconsistent state. */
|
|
17
|
+
readonly GRID_INVALID: 3407;
|
|
18
|
+
/** Swiss groups could not be generated from the source. */
|
|
19
|
+
readonly SWISS_GROUPING_FAILED: 3408;
|
|
20
|
+
/** A Swiss group ended up without any matches while headers are enabled. */
|
|
21
|
+
readonly SWISS_GROUP_EMPTY: 3409;
|
|
22
|
+
/** A match's resolved winner id is not among its participants. */
|
|
23
|
+
readonly WINNER_NOT_FOUND: 3410;
|
|
24
|
+
/** A required key was missing from an internal bracket lookup map. */
|
|
25
|
+
readonly DATA_LOOKUP_FAILED: 3411;
|
|
26
|
+
/** The default cards are rendering but no `matchNormalizer` was registered to feed them. */
|
|
27
|
+
readonly MISSING_MATCH_NORMALIZER: 3412;
|
|
28
|
+
/** No registered {@link BracketLayout} matches the source's tournament `mode`. */
|
|
29
|
+
readonly LAYOUT_NOT_REGISTERED: 3413;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
type BracketSlotSourceKind = 'match-outcome' | 'standing-rank' | 'seed' | 'swiss-bucket' | 'bye' | 'external';
|
|
33
|
+
type BracketSlotSource = {
|
|
34
|
+
kind: BracketSlotSourceKind;
|
|
35
|
+
role: 'winner' | 'loser' | null;
|
|
36
|
+
matchId: string | null;
|
|
37
|
+
standingId: string | null;
|
|
38
|
+
rank: number | null;
|
|
39
|
+
label: string | null;
|
|
40
|
+
/** The seeding position this slot is reserved for. Optional - a source may carry no seeding at all. */
|
|
41
|
+
seed?: number | null;
|
|
42
|
+
/** What {@link standingId} is called, for a slot that has to be worded without a lookup. */
|
|
43
|
+
standingName?: string | null;
|
|
44
|
+
};
|
|
45
|
+
type BracketMatchSlot = {
|
|
46
|
+
participantId: string | null;
|
|
47
|
+
source: BracketSlotSource | null;
|
|
48
|
+
};
|
|
49
|
+
type BracketMatchSource<TMatchData> = {
|
|
50
|
+
data: TMatchData;
|
|
51
|
+
id: string;
|
|
52
|
+
roundId: string;
|
|
53
|
+
home: string | null;
|
|
54
|
+
away: string | null;
|
|
55
|
+
/** Where the home participant comes from. Omit for legacy sources that do not carry provenance. */
|
|
56
|
+
homeSource?: BracketSlotSource | null;
|
|
57
|
+
/** Where the away participant comes from. Omit for legacy sources that do not carry provenance. */
|
|
58
|
+
awaySource?: BracketSlotSource | null;
|
|
59
|
+
winner: MatchParticipantSide | null;
|
|
60
|
+
status: BracketMatchStatus;
|
|
61
|
+
};
|
|
62
|
+
type BracketDataSource<TRoundData, TMatchData> = {
|
|
63
|
+
rounds: BracketRoundSource<TRoundData>[];
|
|
64
|
+
matches: BracketMatchSource<TMatchData>[];
|
|
65
|
+
mode: TournamentMode;
|
|
66
|
+
};
|
|
67
|
+
type BracketRoundSource<TRoundData> = {
|
|
68
|
+
type: BracketRoundType;
|
|
69
|
+
id: string;
|
|
70
|
+
data: TRoundData;
|
|
71
|
+
name: string;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
declare class BracketMap<TKey, TValue> extends Map<TKey, TValue> {
|
|
75
|
+
constructor();
|
|
76
|
+
getOrThrow(key: TKey): TValue;
|
|
77
|
+
first(): TValue | undefined;
|
|
78
|
+
last(): TValue | undefined;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
declare const BRACKET_DATA_LAYOUT: {
|
|
82
|
+
readonly LEFT_TO_RIGHT: "left-to-right";
|
|
83
|
+
/**
|
|
84
|
+
* Folded in half: each round up to the first one too small to halve is drawn twice, once on each
|
|
85
|
+
* side, converging on that round and the ones after it. Halves the height and roughly doubles the
|
|
86
|
+
* width, which is what a poster or a broadcast graphic wants.
|
|
87
|
+
*
|
|
88
|
+
* Carried by the mirrored layout factories - a layout that has no fold to make (swiss) simply has no
|
|
89
|
+
* mirrored variant.
|
|
90
|
+
*/
|
|
91
|
+
readonly MIRRORED: "mirrored";
|
|
92
|
+
};
|
|
93
|
+
type BracketDataLayout = (typeof BRACKET_DATA_LAYOUT)[keyof typeof BRACKET_DATA_LAYOUT];
|
|
94
|
+
|
|
95
|
+
type MatchParticipantId = string & {
|
|
96
|
+
_brand: 'MatchParticipantId';
|
|
97
|
+
};
|
|
98
|
+
type MatchParticipantShortId = string & {
|
|
99
|
+
_brand: 'MatchParticipantShortId';
|
|
100
|
+
};
|
|
101
|
+
type BracketParticipantBase = {
|
|
102
|
+
id: MatchParticipantId;
|
|
103
|
+
shortId: MatchParticipantShortId;
|
|
104
|
+
};
|
|
105
|
+
type BracketParticipantWithRelationsBase = BracketParticipantBase & {
|
|
106
|
+
matchIds: BracketMatchId[];
|
|
107
|
+
};
|
|
108
|
+
declare const createParticipantsMapBase: <TRoundData, TMatchData>(source: BracketDataSource<TRoundData, TMatchData>) => BracketMap<MatchParticipantId, BracketParticipantWithRelationsBase>;
|
|
109
|
+
|
|
110
|
+
type BracketRoundId = string & {
|
|
111
|
+
_brand: 'BracketRoundId';
|
|
112
|
+
};
|
|
113
|
+
type BracketRoundShortId = string & {
|
|
114
|
+
_brand: 'BracketRoundShortId';
|
|
115
|
+
};
|
|
116
|
+
type BracketRoundPosition = number & {
|
|
117
|
+
_brand: 'BracketRoundPosition';
|
|
118
|
+
};
|
|
119
|
+
type BracketRoundMirrorType = (typeof BRACKET_ROUND_MIRROR_TYPE)[keyof typeof BRACKET_ROUND_MIRROR_TYPE];
|
|
120
|
+
declare const BRACKET_ROUND_MIRROR_TYPE: {
|
|
121
|
+
readonly LEFT: "left";
|
|
122
|
+
readonly RIGHT: "right";
|
|
123
|
+
};
|
|
124
|
+
declare const COMMON_BRACKET_ROUND_TYPE: {
|
|
125
|
+
readonly THIRD_PLACE: "third-place";
|
|
126
|
+
readonly FINAL: "final";
|
|
127
|
+
};
|
|
128
|
+
declare const SINGLE_ELIMINATION_BRACKET_ROUND_TYPE: {
|
|
129
|
+
readonly SINGLE_ELIMINATION_BRACKET: "single-elimination-bracket";
|
|
130
|
+
};
|
|
131
|
+
declare const DOUBLE_ELIMINATION_BRACKET_ROUND_TYPE: {
|
|
132
|
+
readonly UPPER_BRACKET: "upper-bracket";
|
|
133
|
+
readonly LOWER_BRACKET: "lower-bracket";
|
|
134
|
+
readonly REVERSE_FINAL: "reverse-final";
|
|
135
|
+
};
|
|
136
|
+
declare const SWISS_BRACKET_ROUND_TYPE: {
|
|
137
|
+
readonly SWISS: "swiss";
|
|
138
|
+
};
|
|
139
|
+
declare const GROUP_BRACKET_ROUND_TYPE: {
|
|
140
|
+
readonly GROUP: "group";
|
|
141
|
+
};
|
|
142
|
+
type CommonBracketRoundType = (typeof COMMON_BRACKET_ROUND_TYPE)[keyof typeof COMMON_BRACKET_ROUND_TYPE];
|
|
143
|
+
type SingleEliminationBracketRoundType = CommonBracketRoundType | (typeof SINGLE_ELIMINATION_BRACKET_ROUND_TYPE)[keyof typeof SINGLE_ELIMINATION_BRACKET_ROUND_TYPE];
|
|
144
|
+
type DoubleEliminationBracketRoundType = CommonBracketRoundType | (typeof DOUBLE_ELIMINATION_BRACKET_ROUND_TYPE)[keyof typeof DOUBLE_ELIMINATION_BRACKET_ROUND_TYPE];
|
|
145
|
+
type SwissBracketRoundType = (typeof SWISS_BRACKET_ROUND_TYPE)[keyof typeof SWISS_BRACKET_ROUND_TYPE];
|
|
146
|
+
type GroupBracketRoundType = (typeof GROUP_BRACKET_ROUND_TYPE)[keyof typeof GROUP_BRACKET_ROUND_TYPE];
|
|
147
|
+
type BracketRoundType = SingleEliminationBracketRoundType | DoubleEliminationBracketRoundType | SwissBracketRoundType | GroupBracketRoundType;
|
|
148
|
+
type BracketRoundBase<TRoundData> = {
|
|
149
|
+
/**
|
|
150
|
+
* How deep this round sits in its own bracket - 0 for the opening round, counted separately for the
|
|
151
|
+
* upper and lower halves of a double elimination.
|
|
152
|
+
*
|
|
153
|
+
* **Both halves of a mirrored round share it.** That is what makes it the fold's coordinate: a
|
|
154
|
+
* mirrored layout draws each depth twice, once on each side, so the depth is the only thing that says
|
|
155
|
+
* which right-hand column belongs opposite which left-hand one.
|
|
156
|
+
*/
|
|
157
|
+
logicalIndex: number;
|
|
158
|
+
type: BracketRoundType;
|
|
159
|
+
id: BracketRoundId;
|
|
160
|
+
shortId: BracketRoundShortId;
|
|
161
|
+
data: TRoundData;
|
|
162
|
+
position: BracketRoundPosition;
|
|
163
|
+
name: string;
|
|
164
|
+
matchCount: number;
|
|
165
|
+
mirrorRoundType: BracketRoundMirrorType | null;
|
|
166
|
+
isFirstRound: boolean;
|
|
167
|
+
isLastRound: boolean;
|
|
168
|
+
isFirstOfType: boolean;
|
|
169
|
+
isLastOfType: boolean;
|
|
170
|
+
};
|
|
171
|
+
type BracketRoundWithRelationsBase<TRoundData> = BracketRoundBase<TRoundData> & {
|
|
172
|
+
matchIds: BracketMatchId[];
|
|
173
|
+
};
|
|
174
|
+
declare const createRoundsMapBase: <TRoundData, TMatchData>(source: BracketDataSource<TRoundData, TMatchData>, options: GenerateBracketDataOptions) => BracketMap<BracketRoundId, BracketRoundWithRelationsBase<TRoundData>>;
|
|
175
|
+
|
|
176
|
+
type ParticipantMatchResult = 'win' | 'loss' | 'tie';
|
|
177
|
+
type MatchParticipantSide = 'home' | 'away';
|
|
178
|
+
type BracketMatchParticipantBase = BracketParticipantBase & {
|
|
179
|
+
result: ParticipantMatchResult | null;
|
|
180
|
+
isEliminated: boolean;
|
|
181
|
+
isEliminationMatch: boolean;
|
|
182
|
+
tieCount: number;
|
|
183
|
+
winCount: number;
|
|
184
|
+
lossCount: number;
|
|
185
|
+
side: MatchParticipantSide;
|
|
186
|
+
};
|
|
187
|
+
type BracketMatchParticipantWithRelationsBase = BracketMatchParticipantBase & BracketParticipantWithRelationsBase;
|
|
188
|
+
declare const createNewMatchParticipantBase: <TRoundData, TMatchData>(source: BracketDataSource<TRoundData, TMatchData>, participantId: MatchParticipantId | null, match: BracketMatchSource<TMatchData>, rounds: BracketMap<BracketRoundId, BracketRoundWithRelationsBase<TRoundData>>, matchRoundId: BracketRoundId, participants: BracketMap<MatchParticipantId, BracketParticipantWithRelationsBase>) => BracketMatchParticipantWithRelationsBase | null;
|
|
189
|
+
|
|
190
|
+
type BracketMatchId = string & {
|
|
191
|
+
_brand: 'BracketMatchId';
|
|
192
|
+
};
|
|
193
|
+
type BracketMatchShortId = string & {
|
|
194
|
+
_brand: 'BracketMatchShortId';
|
|
195
|
+
};
|
|
196
|
+
type BracketMatchPosition = number & {
|
|
197
|
+
_brand: 'BracketMatchPosition';
|
|
198
|
+
};
|
|
199
|
+
type BracketMatchStatus = 'completed' | 'pending';
|
|
200
|
+
type BracketMatchBase<TMatchData> = {
|
|
201
|
+
data: TMatchData;
|
|
202
|
+
indexInRound: number;
|
|
203
|
+
id: BracketMatchId;
|
|
204
|
+
shortId: BracketMatchShortId;
|
|
205
|
+
position: BracketMatchPosition;
|
|
206
|
+
winnerSide: MatchParticipantSide | null;
|
|
207
|
+
status: BracketMatchStatus;
|
|
208
|
+
homeSource: BracketSlotSource | null;
|
|
209
|
+
awaySource: BracketSlotSource | null;
|
|
210
|
+
};
|
|
211
|
+
type BracketMatchWithRelationsBase<TMatchData> = BracketMatchBase<TMatchData> & {
|
|
212
|
+
roundId: BracketRoundId;
|
|
213
|
+
home: BracketMatchParticipantWithRelationsBase | null;
|
|
214
|
+
away: BracketMatchParticipantWithRelationsBase | null;
|
|
215
|
+
winner: BracketMatchParticipantWithRelationsBase | null;
|
|
216
|
+
};
|
|
217
|
+
declare const createMatchesMapBase: <TRoundData, TMatchData>(source: BracketDataSource<TRoundData, TMatchData>, rounds: BracketMap<BracketRoundId, BracketRoundWithRelationsBase<TRoundData>>, participants: BracketMap<MatchParticipantId, BracketParticipantWithRelationsBase>) => BracketMap<BracketMatchId, BracketMatchWithRelationsBase<TMatchData>>;
|
|
218
|
+
|
|
219
|
+
declare const TOURNAMENT_MODE: {
|
|
220
|
+
readonly SINGLE_ELIMINATION: "single-elimination";
|
|
221
|
+
readonly DOUBLE_ELIMINATION: "double-elimination";
|
|
222
|
+
readonly SWISS_WITH_ELIMINATION: "swiss-with-elimination";
|
|
223
|
+
};
|
|
224
|
+
type TournamentMode = (typeof TOURNAMENT_MODE)[keyof typeof TOURNAMENT_MODE];
|
|
225
|
+
/** Wins that advance a participant out of a swiss stage. */
|
|
226
|
+
declare const SWISS_ADVANCE_WINS = 3;
|
|
227
|
+
/** Losses that eliminate a participant from a swiss stage. */
|
|
228
|
+
declare const SWISS_ELIMINATE_LOSSES = 3;
|
|
229
|
+
|
|
230
|
+
type BracketBase<TRoundData, TMatchData> = {
|
|
231
|
+
rounds: BracketMap<BracketRoundId, BracketRoundWithRelationsBase<TRoundData>>;
|
|
232
|
+
matches: BracketMap<BracketMatchId, BracketMatchWithRelationsBase<TMatchData>>;
|
|
233
|
+
participants: BracketMap<MatchParticipantId, BracketParticipantWithRelationsBase>;
|
|
234
|
+
mode: TournamentMode;
|
|
235
|
+
};
|
|
236
|
+
type GenerateBracketDataOptions = {
|
|
237
|
+
layout: BracketDataLayout;
|
|
238
|
+
};
|
|
239
|
+
type CreateBracketOptions<TMatchData> = GenerateBracketDataOptions & {
|
|
240
|
+
/** The matches feeding this one, upper arm first. Slot provenance is used when omitted. */
|
|
241
|
+
previousMatchIds?: (match: BracketMatchSource<TMatchData>) => string[];
|
|
242
|
+
};
|
|
243
|
+
declare const createBracketBase: <TRoundData, TMatchData>(source: BracketDataSource<TRoundData, TMatchData>, options: GenerateBracketDataOptions) => BracketBase<TRoundData, TMatchData>;
|
|
244
|
+
|
|
245
|
+
type BracketPosition = {
|
|
246
|
+
inline: {
|
|
247
|
+
start: number;
|
|
248
|
+
end: number;
|
|
249
|
+
center: number;
|
|
250
|
+
};
|
|
251
|
+
block: {
|
|
252
|
+
start: number;
|
|
253
|
+
end: number;
|
|
254
|
+
center: number;
|
|
255
|
+
};
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
/** One connector between two cards, ready for an SVG `<path>`. */
|
|
259
|
+
type BracketEdge = {
|
|
260
|
+
/**
|
|
261
|
+
* Stable while only the geometry changes, so a template's `@for` moves the same `<path>` instead of
|
|
262
|
+
* replacing it - which is what lets the `d` transition run. Unique within one drawing.
|
|
263
|
+
*/
|
|
264
|
+
id: string;
|
|
265
|
+
/** The `d` attribute, which is what draws the line. */
|
|
266
|
+
d: string;
|
|
267
|
+
/** The same path as a value for the CSS `d` property - the one a transition can animate. */
|
|
268
|
+
cssPath: string;
|
|
269
|
+
/** The participant short ids the journey highlight matches on, space separated. */
|
|
270
|
+
cssClass: string;
|
|
271
|
+
strokeWidth: number;
|
|
272
|
+
dashArray: number;
|
|
273
|
+
dashOffset: number;
|
|
274
|
+
/** A color, or `url(#id)` naming one of the drawing's {@link BracketGradient}s. */
|
|
275
|
+
stroke: string;
|
|
276
|
+
};
|
|
277
|
+
/** A box drawn behind the connectors - a swiss layout's group border. */
|
|
278
|
+
type BracketRect = {
|
|
279
|
+
id: string;
|
|
280
|
+
x: number;
|
|
281
|
+
y: number;
|
|
282
|
+
width: number;
|
|
283
|
+
height: number;
|
|
284
|
+
/** The corner radius, as the `rx` attribute. */
|
|
285
|
+
radius: number;
|
|
286
|
+
cssClass: string;
|
|
287
|
+
stroke: string;
|
|
288
|
+
strokeWidth: number;
|
|
289
|
+
};
|
|
290
|
+
type BracketGradientStop = {
|
|
291
|
+
/** A CSS/SVG offset, e.g. `'50%'`. */
|
|
292
|
+
offset: string;
|
|
293
|
+
color: string;
|
|
294
|
+
};
|
|
295
|
+
/** A horizontal gradient in user space, which an edge's `stroke` names by `url(#id)`. */
|
|
296
|
+
type BracketGradient = {
|
|
297
|
+
id: string;
|
|
298
|
+
fromX: number;
|
|
299
|
+
toX: number;
|
|
300
|
+
stops: BracketGradientStop[];
|
|
301
|
+
};
|
|
302
|
+
/**
|
|
303
|
+
* Everything a layout draws between the cells, as data rather than as SVG markup: the host renders it
|
|
304
|
+
* with `@for`, so nothing has to be trusted past the sanitizer and a connector can animate.
|
|
305
|
+
*/
|
|
306
|
+
type BracketDrawing = {
|
|
307
|
+
edges: BracketEdge[];
|
|
308
|
+
rects: BracketRect[];
|
|
309
|
+
gradients: BracketGradient[];
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
type PathOptions = {
|
|
313
|
+
/** Unique within one drawing - see {@link BracketEdge.id}. */
|
|
314
|
+
id: string;
|
|
315
|
+
width: number;
|
|
316
|
+
dashArray: number;
|
|
317
|
+
dashOffset: number;
|
|
318
|
+
className: string;
|
|
319
|
+
stroke?: string;
|
|
320
|
+
};
|
|
321
|
+
declare const path: (d: string, options: PathOptions) => BracketEdge;
|
|
322
|
+
|
|
323
|
+
type CurveOptions = {
|
|
324
|
+
lineStartingCurveAmount: number;
|
|
325
|
+
lineEndingCurveAmount: number;
|
|
326
|
+
path: PathOptions;
|
|
327
|
+
inverted?: boolean;
|
|
328
|
+
};
|
|
329
|
+
declare const curvePath: (from: BracketPosition, to: BracketPosition, direction: "up" | "down", options: CurveOptions) => _ethlete_bracket.BracketEdge;
|
|
330
|
+
|
|
331
|
+
type BracketRoundRelationNothingToOne<TRoundData, TMatchData> = {
|
|
332
|
+
type: 'nothing-to-one';
|
|
333
|
+
currentRound: BracketRound<TRoundData, TMatchData>;
|
|
334
|
+
nextRound: BracketRound<TRoundData, TMatchData>;
|
|
335
|
+
nextRoundMatchFactor: number;
|
|
336
|
+
};
|
|
337
|
+
type BracketRoundRelationOneToNothing<TRoundData, TMatchData> = {
|
|
338
|
+
type: 'one-to-nothing';
|
|
339
|
+
currentRound: BracketRound<TRoundData, TMatchData>;
|
|
340
|
+
previousRound: BracketRound<TRoundData, TMatchData>;
|
|
341
|
+
previousRoundMatchFactor: number;
|
|
342
|
+
rootRoundMatchFactor: number;
|
|
343
|
+
};
|
|
344
|
+
type BracketRoundRelationOneToOne<TRoundData, TMatchData> = {
|
|
345
|
+
type: 'one-to-one';
|
|
346
|
+
currentRound: BracketRound<TRoundData, TMatchData>;
|
|
347
|
+
previousRound: BracketRound<TRoundData, TMatchData>;
|
|
348
|
+
nextRound: BracketRound<TRoundData, TMatchData>;
|
|
349
|
+
nextRoundMatchFactor: number;
|
|
350
|
+
previousRoundMatchFactor: number;
|
|
351
|
+
rootRoundMatchFactor: number;
|
|
352
|
+
};
|
|
353
|
+
type BracketRoundRelationTwoToOne<TRoundData, TMatchData> = {
|
|
354
|
+
type: 'two-to-one';
|
|
355
|
+
currentRound: BracketRound<TRoundData, TMatchData>;
|
|
356
|
+
previousUpperRound: BracketRound<TRoundData, TMatchData>;
|
|
357
|
+
previousLowerRound: BracketRound<TRoundData, TMatchData>;
|
|
358
|
+
nextRound: BracketRound<TRoundData, TMatchData>;
|
|
359
|
+
nextRoundMatchFactor: number;
|
|
360
|
+
previousUpperRoundMatchFactor: number;
|
|
361
|
+
previousLowerRoundMatchFactor: number;
|
|
362
|
+
upperRootRoundMatchFactor: number;
|
|
363
|
+
lowerRootRoundMatchFactor: number;
|
|
364
|
+
};
|
|
365
|
+
type BracketRoundRelationTwoToNothing<TRoundData, TMatchData> = {
|
|
366
|
+
type: 'two-to-nothing';
|
|
367
|
+
currentRound: BracketRound<TRoundData, TMatchData>;
|
|
368
|
+
previousUpperRound: BracketRound<TRoundData, TMatchData>;
|
|
369
|
+
previousLowerRound: BracketRound<TRoundData, TMatchData>;
|
|
370
|
+
previousUpperRoundMatchFactor: number;
|
|
371
|
+
previousLowerRoundMatchFactor: number;
|
|
372
|
+
upperRootRoundMatchFactor: number;
|
|
373
|
+
lowerRootRoundMatchFactor: number;
|
|
374
|
+
};
|
|
375
|
+
type BracketRoundRelation<TRoundData, TMatchData> = BracketRoundRelationNothingToOne<TRoundData, TMatchData> | BracketRoundRelationOneToNothing<TRoundData, TMatchData> | BracketRoundRelationOneToOne<TRoundData, TMatchData> | BracketRoundRelationTwoToOne<TRoundData, TMatchData> | BracketRoundRelationTwoToNothing<TRoundData, TMatchData>;
|
|
376
|
+
declare const generateRoundRelationsNew: <TRoundData, TMatchData>(bracketData: Bracket<TRoundData, TMatchData>) => BracketRoundRelation<TRoundData, TMatchData>[];
|
|
377
|
+
|
|
378
|
+
type BracketMatchFactor = number;
|
|
379
|
+
type BracketMatchRelationOneToOne<TRoundData, TMatchData> = {
|
|
380
|
+
type: 'one-to-one';
|
|
381
|
+
currentMatch: BracketMatch<TRoundData, TMatchData>;
|
|
382
|
+
currentRound: BracketRound<TRoundData, TMatchData>;
|
|
383
|
+
previousMatch: BracketMatch<TRoundData, TMatchData>;
|
|
384
|
+
previousRound: BracketRound<TRoundData, TMatchData>;
|
|
385
|
+
nextMatch: BracketMatch<TRoundData, TMatchData>;
|
|
386
|
+
nextRound: BracketRound<TRoundData, TMatchData>;
|
|
387
|
+
};
|
|
388
|
+
type BracketMatchRelationNothingToOne<TRoundData, TMatchData> = {
|
|
389
|
+
type: 'nothing-to-one';
|
|
390
|
+
currentMatch: BracketMatch<TRoundData, TMatchData>;
|
|
391
|
+
currentRound: BracketRound<TRoundData, TMatchData>;
|
|
392
|
+
nextMatch: BracketMatch<TRoundData, TMatchData>;
|
|
393
|
+
nextRound: BracketRound<TRoundData, TMatchData>;
|
|
394
|
+
};
|
|
395
|
+
type BracketMatchRelationOneToNothing<TRoundData, TMatchData> = {
|
|
396
|
+
type: 'one-to-nothing';
|
|
397
|
+
currentMatch: BracketMatch<TRoundData, TMatchData>;
|
|
398
|
+
currentRound: BracketRound<TRoundData, TMatchData>;
|
|
399
|
+
previousMatch: BracketMatch<TRoundData, TMatchData>;
|
|
400
|
+
previousRound: BracketRound<TRoundData, TMatchData>;
|
|
401
|
+
};
|
|
402
|
+
type BracketMatchRelationTwoToOne<TRoundData, TMatchData> = {
|
|
403
|
+
type: 'two-to-one';
|
|
404
|
+
currentMatch: BracketMatch<TRoundData, TMatchData>;
|
|
405
|
+
currentRound: BracketRound<TRoundData, TMatchData>;
|
|
406
|
+
previousUpperMatch: BracketMatch<TRoundData, TMatchData>;
|
|
407
|
+
previousUpperRound: BracketRound<TRoundData, TMatchData>;
|
|
408
|
+
previousLowerMatch: BracketMatch<TRoundData, TMatchData>;
|
|
409
|
+
previousLowerRound: BracketRound<TRoundData, TMatchData>;
|
|
410
|
+
nextMatch: BracketMatch<TRoundData, TMatchData>;
|
|
411
|
+
nextRound: BracketRound<TRoundData, TMatchData>;
|
|
412
|
+
};
|
|
413
|
+
type BracketMatchRelationTwoToNothing<TRoundData, TMatchData> = {
|
|
414
|
+
type: 'two-to-nothing';
|
|
415
|
+
currentMatch: BracketMatch<TRoundData, TMatchData>;
|
|
416
|
+
currentRound: BracketRound<TRoundData, TMatchData>;
|
|
417
|
+
previousUpperMatch: BracketMatch<TRoundData, TMatchData>;
|
|
418
|
+
previousUpperRound: BracketRound<TRoundData, TMatchData>;
|
|
419
|
+
previousLowerMatch: BracketMatch<TRoundData, TMatchData>;
|
|
420
|
+
previousLowerRound: BracketRound<TRoundData, TMatchData>;
|
|
421
|
+
};
|
|
422
|
+
type BracketMatchRelation<TRoundData, TMatchData> = BracketMatchRelationOneToOne<TRoundData, TMatchData> | BracketMatchRelationTwoToOne<TRoundData, TMatchData> | BracketMatchRelationNothingToOne<TRoundData, TMatchData> | BracketMatchRelationOneToNothing<TRoundData, TMatchData> | BracketMatchRelationTwoToNothing<TRoundData, TMatchData>;
|
|
423
|
+
type MatchPositionMaps<TRoundData, TMatchData> = Map<BracketRoundId, Map<BracketMatchPosition, BracketMatch<TRoundData, TMatchData>>>;
|
|
424
|
+
declare const generateMatchPosition: (match: BracketMatch<unknown, unknown>, factor: BracketMatchFactor) => BracketMatchPosition;
|
|
425
|
+
declare const generateMatchRelationPositions: <TRoundData, TMatchData>(relation: BracketRoundRelation<TRoundData, TMatchData>, match: BracketMatch<TRoundData, TMatchData>) => {
|
|
426
|
+
nextRoundMatchPosition: BracketMatchPosition;
|
|
427
|
+
previousUpperRoundMatchPosition: BracketMatchPosition;
|
|
428
|
+
previousLowerRoundMatchPosition: BracketMatchPosition;
|
|
429
|
+
};
|
|
430
|
+
declare const generateMatchRelationsNew: <TRoundData, TMatchData>(bracketData: Bracket<TRoundData, TMatchData>, options?: {
|
|
431
|
+
source?: {
|
|
432
|
+
matches: BracketMatchSource<TMatchData>[];
|
|
433
|
+
};
|
|
434
|
+
previousMatchIds?: (match: BracketMatchSource<TMatchData>) => string[];
|
|
435
|
+
}) => BracketMatchRelation<TRoundData, TMatchData>[];
|
|
436
|
+
|
|
437
|
+
type Bracket<TRoundData, TMatchData> = {
|
|
438
|
+
rounds: BracketMap<BracketRoundId, BracketRound<TRoundData, TMatchData>>;
|
|
439
|
+
roundsByType: BracketMap<BracketRoundType, BracketMap<BracketRoundId, BracketRound<TRoundData, TMatchData>>>;
|
|
440
|
+
matches: BracketMap<BracketMatchId, BracketMatch<TRoundData, TMatchData>>;
|
|
441
|
+
participants: BracketMap<MatchParticipantId, BracketParticipant<TRoundData, TMatchData>>;
|
|
442
|
+
mode: TournamentMode;
|
|
443
|
+
};
|
|
444
|
+
type BracketRound<TRoundData, TMatchData> = BracketRoundBase<TRoundData> & {
|
|
445
|
+
matches: BracketMap<BracketMatchId, BracketMatch<TRoundData, TMatchData>>;
|
|
446
|
+
relation: BracketRoundRelation<TRoundData, TMatchData>;
|
|
447
|
+
};
|
|
448
|
+
type BracketMatch<TRoundData, TMatchData> = BracketMatchBase<TMatchData> & {
|
|
449
|
+
round: BracketRound<TRoundData, TMatchData>;
|
|
450
|
+
home: BracketMatchParticipant<TRoundData, TMatchData> | null;
|
|
451
|
+
away: BracketMatchParticipant<TRoundData, TMatchData> | null;
|
|
452
|
+
winner: BracketMatchParticipant<TRoundData, TMatchData> | null;
|
|
453
|
+
relation: BracketMatchRelation<TRoundData, TMatchData>;
|
|
454
|
+
};
|
|
455
|
+
type BracketParticipantMatch<TRoundData, TMatchData> = BracketMatch<TRoundData, TMatchData> & {
|
|
456
|
+
me: BracketMatchParticipant<TRoundData, TMatchData>;
|
|
457
|
+
opponent: BracketMatchParticipant<TRoundData, TMatchData> | null;
|
|
458
|
+
};
|
|
459
|
+
type BracketParticipant<TRoundData, TMatchData> = BracketParticipantBase & {
|
|
460
|
+
matches: BracketMap<BracketMatchId, BracketParticipantMatch<TRoundData, TMatchData>>;
|
|
461
|
+
};
|
|
462
|
+
type BracketMatchParticipant<TRoundData, TMatchData> = BracketMatchParticipantBase & {
|
|
463
|
+
matches: BracketMap<BracketMatchId, BracketMatch<TRoundData, TMatchData>>;
|
|
464
|
+
};
|
|
465
|
+
declare const createBracket: <TRoundData, TMatchData>(source: BracketDataSource<TRoundData, TMatchData>, options: CreateBracketOptions<TMatchData>) => Bracket<TRoundData, TMatchData>;
|
|
466
|
+
|
|
467
|
+
type BracketPickSet = {
|
|
468
|
+
/** The participant the viewer picked to win a match. */
|
|
469
|
+
matchWinner: (matchId: string) => string | null;
|
|
470
|
+
/** The participant the viewer put on a table position. */
|
|
471
|
+
standingRank: (options: {
|
|
472
|
+
standingId: string;
|
|
473
|
+
rank: number;
|
|
474
|
+
}) => string | null;
|
|
475
|
+
};
|
|
476
|
+
declare const isBracketSlotPredictable: (source: BracketSlotSource | null) => boolean;
|
|
477
|
+
/** How a resolution weighs a prediction against what is already known. Both parts default to the stricter answer. */
|
|
478
|
+
type BracketSlotResolutionPolicy = {
|
|
479
|
+
/**
|
|
480
|
+
* Whether the participant really standing on a slot of the given match outranks whatever the picks
|
|
481
|
+
* predict for it. Must answer from the match alone, and answer the same way throughout one
|
|
482
|
+
* resolution: the walk memoizes per slot.
|
|
483
|
+
*
|
|
484
|
+
* `true` answers with the real participant wherever one is known - the pairing a pick was made
|
|
485
|
+
* against, which is what an open round should show. `false`, the default, answers with the
|
|
486
|
+
* prediction even where reality already disagrees, which is what a locked round should show: the
|
|
487
|
+
* record of the guess.
|
|
488
|
+
*/
|
|
489
|
+
realParticipantOutranksPick?: (match: BracketMatch<unknown, unknown>) => boolean;
|
|
490
|
+
/**
|
|
491
|
+
* Whether a predicted winner still counts while one side of the match it was made on is unknown.
|
|
492
|
+
* `false`, the default, drops it until both sides resolve. `true` keeps it until both sides are
|
|
493
|
+
* known and it is neither of them - until then nothing contradicts it.
|
|
494
|
+
*/
|
|
495
|
+
keepPickWhileFeederSideIsOpen?: boolean;
|
|
496
|
+
};
|
|
497
|
+
type ResolveBracketSlotOptions = BracketSlotResolutionPolicy & {
|
|
498
|
+
bracket: Bracket<unknown, unknown>;
|
|
499
|
+
picks: BracketPickSet;
|
|
500
|
+
matchId: string;
|
|
501
|
+
side: MatchParticipantSide;
|
|
502
|
+
};
|
|
503
|
+
/** Who the viewer's own picks put in a slot, or `null` while their picks do not reach it. */
|
|
504
|
+
declare const resolveBracketSlot: (options: ResolveBracketSlotOptions) => string | null;
|
|
505
|
+
|
|
506
|
+
type BracketPickMigrationOptions = BracketSlotResolutionPolicy & {
|
|
507
|
+
bracket: Bracket<unknown, unknown>;
|
|
508
|
+
/** The participant the viewer picked on a match, on the match they picked it on. */
|
|
509
|
+
pickAsMade: (matchId: string) => string | null;
|
|
510
|
+
/** The participant the viewer put on a table position, for the `standing-rank` slots a round resolves from. */
|
|
511
|
+
standingRank?: (options: {
|
|
512
|
+
standingId: string;
|
|
513
|
+
rank: number;
|
|
514
|
+
}) => string | null;
|
|
515
|
+
/** Matches whose picks the backend already keeps. Their picks neither travel out nor take one in. */
|
|
516
|
+
lockedMatchIds?: ReadonlySet<string>;
|
|
517
|
+
};
|
|
518
|
+
type BracketPickMigration = {
|
|
519
|
+
/** The pick that counts on a match: the one made on it, or the one that followed its participant here. */
|
|
520
|
+
pickByMatchId: Record<string, string | undefined>;
|
|
521
|
+
/** For a match that took a pick in, the match that pick was made on. */
|
|
522
|
+
movedFromByMatchId: Record<string, string | undefined>;
|
|
523
|
+
/** For a match whose pick nothing in its round can honour, that pick. Such a match holds no selection. */
|
|
524
|
+
strandedByMatchId: Record<string, string | undefined>;
|
|
525
|
+
};
|
|
526
|
+
/**
|
|
527
|
+
* Where every pick stands once each one has followed its participant into whichever match of its own
|
|
528
|
+
* round that participant now plays. A pick nothing in the round can honour comes back stranded.
|
|
529
|
+
*/
|
|
530
|
+
declare const migrateBracketPicks: (options: BracketPickMigrationOptions) => BracketPickMigration;
|
|
531
|
+
|
|
532
|
+
type BracketRoundSwissGroupId = string & {
|
|
533
|
+
_brand: 'BracketRoundSwissGroupId';
|
|
534
|
+
};
|
|
535
|
+
type BracketRoundSwissGroup<TRoundData, TMatchData> = {
|
|
536
|
+
id: BracketRoundSwissGroupId;
|
|
537
|
+
name: string;
|
|
538
|
+
matches: BracketMap<BracketMatchId, BracketMatch<TRoundData, TMatchData>>;
|
|
539
|
+
allowedMatchCount: number;
|
|
540
|
+
};
|
|
541
|
+
type BracketRoundSwissGroupMap<TRoundData, TMatchData> = Map<BracketRoundSwissGroupId, BracketRoundSwissGroup<TRoundData, TMatchData>>;
|
|
542
|
+
type BracketRoundSwissData<TRoundData, TMatchData> = {
|
|
543
|
+
groups: BracketRoundSwissGroupMap<TRoundData, TMatchData>;
|
|
544
|
+
};
|
|
545
|
+
type BracketRoundMapWithSwissData<TRoundData, TMatchData> = Map<BracketRoundId, BracketRoundSwissData<TRoundData, TMatchData>>;
|
|
546
|
+
declare const BRACKET_SWISS_GROUP_COLOR_TYPE: {
|
|
547
|
+
/** The starting group (0-0) */
|
|
548
|
+
readonly NEUTRAL: "neutral";
|
|
549
|
+
/** The group has more wins than losses */
|
|
550
|
+
readonly POSITIVE: "positive";
|
|
551
|
+
/** The group is one loss away from elimination */
|
|
552
|
+
readonly NEGATIVE: "negative";
|
|
553
|
+
/** Everything in between */
|
|
554
|
+
readonly WARNING: "warning";
|
|
555
|
+
};
|
|
556
|
+
type BracketSwissGroupColorType = (typeof BRACKET_SWISS_GROUP_COLOR_TYPE)[keyof typeof BRACKET_SWISS_GROUP_COLOR_TYPE];
|
|
557
|
+
/**
|
|
558
|
+
* Colors for the swiss group borders and connection lines, keyed by the group color type
|
|
559
|
+
* (see {@link getSwissGroupColorType}). Connection lines are drawn in the neutral color and fade
|
|
560
|
+
* into the target group color on the last portion before touching its border.
|
|
561
|
+
* Any CSS color value is allowed. Missing entries fall back to the connector/border color
|
|
562
|
+
* (the `--et-bracket-line-color` / `--et-bracket-swiss-group-border-color` custom properties,
|
|
563
|
+
* which default to `--et-surface-border-solid`).
|
|
564
|
+
*/
|
|
565
|
+
type BracketSwissColors = Partial<Record<BracketSwissGroupColorType, string>>;
|
|
566
|
+
declare const getSwissGroupColorType: (wins: number, losses: number) => BracketSwissGroupColorType;
|
|
567
|
+
declare const getAvailableSwissGroupsForRound: (roundNumber: number, totalMatchesInRound: number) => {
|
|
568
|
+
id: BracketRoundSwissGroupId;
|
|
569
|
+
name: string;
|
|
570
|
+
matchesInGroup: number;
|
|
571
|
+
}[];
|
|
572
|
+
declare const generateBracketRoundSwissGroupMaps: <TRoundData, TMatchData>(bracketData: Bracket<TRoundData, TMatchData>) => BracketRoundMapWithSwissData<TRoundData, TMatchData> | null;
|
|
573
|
+
|
|
574
|
+
type BracketComponentType<TInputs> = new (...args: never[]) => TInputs;
|
|
575
|
+
type BracketComponentInput<TValue> = () => TValue;
|
|
576
|
+
type Dimensions = {
|
|
577
|
+
width: number;
|
|
578
|
+
height: number;
|
|
579
|
+
top: number;
|
|
580
|
+
left: number;
|
|
581
|
+
};
|
|
582
|
+
type Spacing = {
|
|
583
|
+
top: number;
|
|
584
|
+
bottom: number;
|
|
585
|
+
left: number;
|
|
586
|
+
right: number;
|
|
587
|
+
};
|
|
588
|
+
type BracketRoundHeaderComponent<TRoundData, TMatchData> = BracketComponentType<{
|
|
589
|
+
bracketRound: BracketComponentInput<BracketRound<TRoundData, TMatchData>>;
|
|
590
|
+
}>;
|
|
591
|
+
type ComponentInputValue<T> = () => {
|
|
592
|
+
[P in keyof T]: T[P] extends BracketComponentInput<infer TValue> ? TValue : never;
|
|
593
|
+
};
|
|
594
|
+
type BracketMatchComponent<TRoundData, TMatchData> = BracketComponentType<{
|
|
595
|
+
bracketRound: BracketComponentInput<BracketRound<TRoundData, TMatchData>>;
|
|
596
|
+
bracketMatch: BracketComponentInput<BracketMatch<TRoundData, TMatchData>>;
|
|
597
|
+
}>;
|
|
598
|
+
type BracketContinueComponent<TRoundData, TMatchData> = BracketComponentType<{
|
|
599
|
+
/** The matches whose winners advance to the next competition stage */
|
|
600
|
+
bracketMatches: BracketComponentInput<BracketMatch<TRoundData, TMatchData>[]>;
|
|
601
|
+
}>;
|
|
602
|
+
type BracketComponents<TRoundData, TMatchData> = {
|
|
603
|
+
roundHeader: BracketRoundHeaderComponent<TRoundData, TMatchData>;
|
|
604
|
+
match: BracketMatchComponent<TRoundData, TMatchData>;
|
|
605
|
+
finalMatch: BracketMatchComponent<TRoundData, TMatchData>;
|
|
606
|
+
continue?: BracketContinueComponent<TRoundData, TMatchData>;
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
type CreateBracketElementPartConfig = {
|
|
610
|
+
elementPartHeight: number;
|
|
611
|
+
};
|
|
612
|
+
/**
|
|
613
|
+
* A row is a part of an element.
|
|
614
|
+
*/
|
|
615
|
+
type BracketElementPart = {
|
|
616
|
+
dimensions: Dimensions;
|
|
617
|
+
};
|
|
618
|
+
declare const createBracketElementPart: (config: CreateBracketElementPartConfig) => {
|
|
619
|
+
elementPart: BracketElementPart;
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* An element is a slice of a section.
|
|
624
|
+
* It can be a match, a header, a gap, etc.
|
|
625
|
+
*/
|
|
626
|
+
type BracketElementBase = {
|
|
627
|
+
area: string;
|
|
628
|
+
/** The dimensions of the actual element */
|
|
629
|
+
dimensions: Dimensions;
|
|
630
|
+
/** The dimensions of the container that holds the element */
|
|
631
|
+
containerDimensions: Dimensions;
|
|
632
|
+
parts: ReadonlyArray<BracketElementPart>;
|
|
633
|
+
span?: BracketElementSpanCoordinates;
|
|
634
|
+
isHidden?: boolean;
|
|
635
|
+
};
|
|
636
|
+
type HeaderBracketElement<TRoundData, TMatchData> = BracketElementBase & HeaderBracketElementDetails<TRoundData, TMatchData>;
|
|
637
|
+
type MatchBracketElement<TRoundData, TMatchData> = BracketElementBase & MatchBracketElementDetails<TRoundData, TMatchData>;
|
|
638
|
+
type GapBracketElement = BracketElementBase & GapBracketElementDetails;
|
|
639
|
+
type ContinueBracketElement<TRoundData, TMatchData> = BracketElementBase & ContinueBracketElementDetails<TRoundData, TMatchData>;
|
|
640
|
+
type BracketElement<TRoundData, TMatchData> = HeaderBracketElement<TRoundData, TMatchData> | MatchBracketElement<TRoundData, TMatchData> | GapBracketElement | ContinueBracketElement<TRoundData, TMatchData>;
|
|
641
|
+
type BracketElementSpanCoordinates = {
|
|
642
|
+
masterColumnStart: number;
|
|
643
|
+
masterColumnEnd: number;
|
|
644
|
+
sectionStart: number;
|
|
645
|
+
sectionEnd: number;
|
|
646
|
+
subColumnStart: number;
|
|
647
|
+
subColumnEnd: number;
|
|
648
|
+
};
|
|
649
|
+
type BracketElementToCreateBase = {
|
|
650
|
+
area: string;
|
|
651
|
+
partHeights: number[];
|
|
652
|
+
elementHeight: number;
|
|
653
|
+
};
|
|
654
|
+
type HeaderBracketElementDetails<TRoundData, TMatchData> = {
|
|
655
|
+
type: 'header';
|
|
656
|
+
component: BracketRoundHeaderComponent<TRoundData, TMatchData>;
|
|
657
|
+
round: BracketRound<TRoundData, TMatchData>;
|
|
658
|
+
roundSwissGroup: BracketRoundSwissGroup<TRoundData, TMatchData> | null;
|
|
659
|
+
};
|
|
660
|
+
type HeaderBracketElementToCreate<TRoundData, TMatchData> = BracketElementToCreateBase & HeaderBracketElementDetails<TRoundData, TMatchData>;
|
|
661
|
+
type MatchBracketElementDetails<TRoundData, TMatchData> = {
|
|
662
|
+
type: 'match';
|
|
663
|
+
component: BracketMatchComponent<TRoundData, TMatchData>;
|
|
664
|
+
match: BracketMatch<TRoundData, TMatchData>;
|
|
665
|
+
round: BracketRound<TRoundData, TMatchData>;
|
|
666
|
+
roundSwissGroup: BracketRoundSwissGroup<TRoundData, TMatchData> | null;
|
|
667
|
+
};
|
|
668
|
+
type MatchBracketElementToCreate<TRoundData, TMatchData> = BracketElementToCreateBase & MatchBracketElementDetails<TRoundData, TMatchData>;
|
|
669
|
+
type GapBracketElementDetails = {
|
|
670
|
+
type: 'matchGap' | 'roundHeaderGap' | 'roundGap' | 'colGap';
|
|
671
|
+
};
|
|
672
|
+
type GapBracketElementToCreate = BracketElementToCreateBase & GapBracketElementDetails;
|
|
673
|
+
type ContinueBracketElementDetails<TRoundData, TMatchData> = {
|
|
674
|
+
type: 'continue';
|
|
675
|
+
component: BracketContinueComponent<TRoundData, TMatchData>;
|
|
676
|
+
matches: BracketMatch<TRoundData, TMatchData>[];
|
|
677
|
+
};
|
|
678
|
+
type ContinueBracketElementToCreate<TRoundData, TMatchData> = BracketElementToCreateBase & ContinueBracketElementDetails<TRoundData, TMatchData>;
|
|
679
|
+
type BracketElementToCreate<TRoundData, TMatchData> = HeaderBracketElementToCreate<TRoundData, TMatchData> | MatchBracketElementToCreate<TRoundData, TMatchData> | GapBracketElementToCreate | ContinueBracketElementToCreate<TRoundData, TMatchData>;
|
|
680
|
+
type BracketElementType = HeaderBracketElementToCreate<unknown, unknown>['type'] | MatchBracketElementToCreate<unknown, unknown>['type'] | GapBracketElementToCreate['type'] | ContinueBracketElementToCreate<unknown, unknown>['type'];
|
|
681
|
+
type MutableBracketElement<TRoundData, TMatchData> = {
|
|
682
|
+
element: BracketElement<TRoundData, TMatchData>;
|
|
683
|
+
};
|
|
684
|
+
declare const createBracketElement: <TRoundData, TMatchData>(config: BracketElementToCreate<TRoundData, TMatchData>) => MutableBracketElement<TRoundData, TMatchData>;
|
|
685
|
+
|
|
686
|
+
type BracketSubColumn<TRoundData, TMatchData> = {
|
|
687
|
+
dimensions: Dimensions;
|
|
688
|
+
elements: ReadonlyArray<BracketElement<TRoundData, TMatchData>>;
|
|
689
|
+
span: BracketSubColumnSpan;
|
|
690
|
+
};
|
|
691
|
+
type BracketSubColumnSpan = {
|
|
692
|
+
isStart: boolean;
|
|
693
|
+
isEnd: boolean;
|
|
694
|
+
};
|
|
695
|
+
type CreateBracketSubColumnConfig = {
|
|
696
|
+
span: BracketSubColumnSpan;
|
|
697
|
+
};
|
|
698
|
+
type MutableBracketSubColumn<TRoundData, TMatchData> = {
|
|
699
|
+
subColumn: BracketSubColumn<TRoundData, TMatchData>;
|
|
700
|
+
pushElement: (...elements: BracketElement<TRoundData, TMatchData>[]) => void;
|
|
701
|
+
};
|
|
702
|
+
declare const createBracketSubColumn: <TRoundData, TMatchData>(config: CreateBracketSubColumnConfig) => MutableBracketSubColumn<TRoundData, TMatchData>;
|
|
703
|
+
|
|
704
|
+
type BracketMasterColumnSectionType = 'round' | 'gap';
|
|
705
|
+
type BracketMasterColumnSection<TRoundData, TMatchData> = {
|
|
706
|
+
subColumns: ReadonlyArray<BracketSubColumn<TRoundData, TMatchData>>;
|
|
707
|
+
dimensions: Dimensions;
|
|
708
|
+
type: BracketMasterColumnSectionType;
|
|
709
|
+
/** Overrides the master column padding for this section */
|
|
710
|
+
padding?: Spacing;
|
|
711
|
+
};
|
|
712
|
+
type CreateBracketMasterColumnSectionConfig = {
|
|
713
|
+
type: BracketMasterColumnSectionType;
|
|
714
|
+
padding?: Spacing;
|
|
715
|
+
};
|
|
716
|
+
type MutableBracketMasterColumnSection<TRoundData, TMatchData> = {
|
|
717
|
+
masterColumnSection: BracketMasterColumnSection<TRoundData, TMatchData>;
|
|
718
|
+
pushSubColumn: (...subColumns: BracketSubColumn<TRoundData, TMatchData>[]) => void;
|
|
719
|
+
};
|
|
720
|
+
declare const createBracketMasterColumnSection: <TRoundData, TMatchData>(config: CreateBracketMasterColumnSectionConfig) => MutableBracketMasterColumnSection<TRoundData, TMatchData>;
|
|
721
|
+
|
|
722
|
+
type BracketMasterColumn<TRoundData, TMatchData> = {
|
|
723
|
+
sections: ReadonlyArray<BracketMasterColumnSection<TRoundData, TMatchData>>;
|
|
724
|
+
dimensions: Dimensions;
|
|
725
|
+
padding: Spacing;
|
|
726
|
+
};
|
|
727
|
+
type CreateBracketMasterColumnConfig = {
|
|
728
|
+
columnWidth: number;
|
|
729
|
+
padding: Spacing;
|
|
730
|
+
};
|
|
731
|
+
type MutableBracketMasterColumn<TRoundData, TMatchData> = {
|
|
732
|
+
masterColumn: BracketMasterColumn<TRoundData, TMatchData>;
|
|
733
|
+
pushSection: (...sections: BracketMasterColumnSection<TRoundData, TMatchData>[]) => void;
|
|
734
|
+
};
|
|
735
|
+
declare const createBracketMasterColumn: <TRoundData, TMatchData>(config: CreateBracketMasterColumnConfig) => MutableBracketMasterColumn<TRoundData, TMatchData>;
|
|
736
|
+
|
|
737
|
+
type BracketGrid<TRoundData, TMatchData> = {
|
|
738
|
+
masterColumns: ReadonlyArray<BracketMasterColumn<TRoundData, TMatchData>>;
|
|
739
|
+
dimensions: Dimensions;
|
|
740
|
+
};
|
|
741
|
+
type MutableBracketGrid<TRoundData, TMatchData> = {
|
|
742
|
+
grid: BracketGrid<TRoundData, TMatchData>;
|
|
743
|
+
pushMasterColumn: (...masterColumns: BracketMasterColumn<TRoundData, TMatchData>[]) => void;
|
|
744
|
+
calculateDimensions: () => void;
|
|
745
|
+
setupElementSpans: () => void;
|
|
746
|
+
};
|
|
747
|
+
declare const createBracketGrid: <TRoundData, TMatchData>(config: {
|
|
748
|
+
spanElementWidth: number;
|
|
749
|
+
}) => MutableBracketGrid<TRoundData, TMatchData>;
|
|
750
|
+
|
|
751
|
+
type FinalizedBracketColumn<TRoundData = unknown, TMatchData = unknown> = {
|
|
752
|
+
dimensions: Dimensions;
|
|
753
|
+
elements: FinalizedBracketElement<TRoundData, TMatchData>[];
|
|
754
|
+
};
|
|
755
|
+
type FinalizedHeaderBracketElement<TRoundData, TMatchData> = {
|
|
756
|
+
type: 'header';
|
|
757
|
+
dimensions: Dimensions;
|
|
758
|
+
component: BracketRoundHeaderComponent<TRoundData, TMatchData>;
|
|
759
|
+
round: BracketRound<TRoundData, TMatchData>;
|
|
760
|
+
roundSwissGroup: BracketRoundSwissGroup<TRoundData, TMatchData> | null;
|
|
761
|
+
};
|
|
762
|
+
type FinalizedMatchBracketElement<TRoundData, TMatchData> = {
|
|
763
|
+
type: 'match';
|
|
764
|
+
dimensions: Dimensions;
|
|
765
|
+
component: BracketMatchComponent<TRoundData, TMatchData>;
|
|
766
|
+
match: BracketMatch<TRoundData, TMatchData>;
|
|
767
|
+
round: BracketRound<TRoundData, TMatchData>;
|
|
768
|
+
roundSwissGroup: BracketRoundSwissGroup<TRoundData, TMatchData> | null;
|
|
769
|
+
classes: string;
|
|
770
|
+
};
|
|
771
|
+
type FinalizedContinueBracketElement<TRoundData, TMatchData> = {
|
|
772
|
+
type: 'continue';
|
|
773
|
+
dimensions: Dimensions;
|
|
774
|
+
component: BracketContinueComponent<TRoundData, TMatchData>;
|
|
775
|
+
matches: BracketMatch<TRoundData, TMatchData>[];
|
|
776
|
+
};
|
|
777
|
+
type FinalizedBracketElement<TRoundData = unknown, TMatchData = unknown> = FinalizedHeaderBracketElement<TRoundData, TMatchData> | FinalizedMatchBracketElement<TRoundData, TMatchData> | FinalizedContinueBracketElement<TRoundData, TMatchData>;
|
|
778
|
+
type FinalizedBracketMatchElementMap<TRoundData, TMatchData> = BracketMap<string, FinalizedMatchBracketElement<TRoundData, TMatchData>>;
|
|
779
|
+
declare const finalizeBracketGrid: <TRoundData, TMatchData>(grid: MutableBracketGrid<TRoundData, TMatchData>) => {
|
|
780
|
+
columns: FinalizedBracketColumn<TRoundData, TMatchData>[];
|
|
781
|
+
elementMap: FinalizedBracketMatchElementMap<TRoundData, TMatchData>;
|
|
782
|
+
};
|
|
783
|
+
|
|
784
|
+
type ComputedBracketGrid<TRoundData, TMatchData> = {
|
|
785
|
+
raw: MutableBracketGrid<TRoundData, TMatchData>;
|
|
786
|
+
columns: FinalizedBracketColumn<TRoundData, TMatchData>[];
|
|
787
|
+
matchElementMap: FinalizedBracketMatchElementMap<TRoundData, TMatchData>;
|
|
788
|
+
};
|
|
789
|
+
/** Returns the width needed to render a computed bracket grid without horizontal clipping. */
|
|
790
|
+
declare const bracketGridNaturalWidth: <TRoundData, TMatchData>(grid: ComputedBracketGrid<TRoundData, TMatchData>) => number;
|
|
791
|
+
type CreateBracketGridConfig = {
|
|
792
|
+
includeRoundHeaders: boolean;
|
|
793
|
+
columnWidth: number;
|
|
794
|
+
matchHeight: number;
|
|
795
|
+
roundHeaderHeight: number;
|
|
796
|
+
roundHeaderGap: number;
|
|
797
|
+
columnGap: number;
|
|
798
|
+
rowRoundGap: number;
|
|
799
|
+
rowGap: number;
|
|
800
|
+
rowSpanRoundId: string | null;
|
|
801
|
+
/** @internal Resolved by a grid builder from `rowSpanRoundId`. */
|
|
802
|
+
rowSpanMatchCount?: number;
|
|
803
|
+
finalMatchHeight: number;
|
|
804
|
+
finalColumnWidth: number;
|
|
805
|
+
/**
|
|
806
|
+
* What the final keeps between its round header and its card, in px, where that is more than
|
|
807
|
+
* `roundHeaderGap`. The room goes to the final's column alone. Unset gives it the same gap as every
|
|
808
|
+
* other round.
|
|
809
|
+
*/
|
|
810
|
+
finalRoundHeaderGap?: number | null;
|
|
811
|
+
/**
|
|
812
|
+
* How far below the top of the final's card a third place match sits, in px, when the two share a
|
|
813
|
+
* column. Unset (or `null`) gives the third place a column of its own.
|
|
814
|
+
*/
|
|
815
|
+
thirdPlaceTopOffset?: number | null;
|
|
816
|
+
swissGroupPadding: number;
|
|
817
|
+
swissGroupBorderWidth: number;
|
|
818
|
+
layout: BracketDataLayout;
|
|
819
|
+
continueElement?: {
|
|
820
|
+
columnWidth: number;
|
|
821
|
+
elementHeight: number;
|
|
822
|
+
} | null;
|
|
823
|
+
};
|
|
824
|
+
|
|
825
|
+
type DrawManDimensions<TRoundData, TMatchData> = {
|
|
826
|
+
columnWidth: number;
|
|
827
|
+
matchHeight: number;
|
|
828
|
+
roundHeaderHeight: number;
|
|
829
|
+
columnGap: number;
|
|
830
|
+
upperLowerGap: number;
|
|
831
|
+
rowGap: number;
|
|
832
|
+
bracketGrid: ComputedBracketGrid<TRoundData, TMatchData>;
|
|
833
|
+
path: Omit<PathOptions, 'className' | 'id'>;
|
|
834
|
+
curve: Omit<CurveOptions, 'path' | 'inverted'>;
|
|
835
|
+
/** Path options for the lines connecting the continuing matches to the continue element */
|
|
836
|
+
continuePath?: Omit<PathOptions, 'className' | 'id'>;
|
|
837
|
+
};
|
|
838
|
+
declare const drawMan: <TRoundData, TMatchData>(dimensions: DrawManDimensions<TRoundData, TMatchData>) => BracketDrawing;
|
|
839
|
+
|
|
840
|
+
type DrawSwissManDimensions<TRoundData, TMatchData> = {
|
|
841
|
+
bracketGrid: ComputedBracketGrid<TRoundData, TMatchData>;
|
|
842
|
+
path: Omit<PathOptions, 'className' | 'stroke' | 'id'>;
|
|
843
|
+
curve: {
|
|
844
|
+
lineStartingCurveAmount: number;
|
|
845
|
+
};
|
|
846
|
+
groupBorder: {
|
|
847
|
+
padding: number;
|
|
848
|
+
radius: number;
|
|
849
|
+
width: number;
|
|
850
|
+
};
|
|
851
|
+
colors?: BracketSwissColors;
|
|
852
|
+
/** Used to create document wide unique ids for the connection line gradients */
|
|
853
|
+
idPrefix: string;
|
|
854
|
+
};
|
|
855
|
+
declare const drawSwissMan: <TRoundData, TMatchData>(dimensions: DrawSwissManDimensions<TRoundData, TMatchData>) => BracketDrawing;
|
|
856
|
+
|
|
857
|
+
declare const createDoubleEliminationGrid: <TRoundData, TMatchData>(bracketData: Bracket<TRoundData, TMatchData>, options: CreateBracketGridConfig, components: BracketComponents<TRoundData, TMatchData>) => ComputedBracketGrid<TRoundData, TMatchData>;
|
|
858
|
+
|
|
859
|
+
/**
|
|
860
|
+
* Draws a double elimination as two mirrored blocks, one above the other: the winners bracket folded
|
|
861
|
+
* around its own centre, the losers bracket folded around its own, and nothing but a gap between them.
|
|
862
|
+
* Each block's deciding rounds hang vertically below the round its two halves converge on.
|
|
863
|
+
*
|
|
864
|
+
* @internal
|
|
865
|
+
*/
|
|
866
|
+
declare const createStackedDoubleEliminationGrid: <TRoundData, TMatchData>(bracketData: Bracket<TRoundData, TMatchData>, options: CreateBracketGridConfig, components: BracketComponents<TRoundData, TMatchData>) => ComputedBracketGrid<TRoundData, TMatchData>;
|
|
867
|
+
|
|
868
|
+
declare const calculateUpperLowerRatio: (upperRoundsCount: number, lowerRoundsCount: number) => number;
|
|
869
|
+
declare const calculateColumnSplitFactor: (upperToLowerRatio: number) => 1 | 2;
|
|
870
|
+
declare const calculateLowerRoundIndex: (subColumnIndex: number, splitFactor: number) => number;
|
|
871
|
+
declare const calculateUpperRoundIndex: (subColumnIndex: number, upperToLowerRatio: number, splitFactor: number) => number;
|
|
872
|
+
|
|
873
|
+
declare const isBracketContinueMatch: <TRoundData, TMatchData>(match: BracketMatch<TRoundData, TMatchData>) => boolean;
|
|
874
|
+
declare const getBracketContinueMatches: <TRoundData, TMatchData>(bracketData: Bracket<TRoundData, TMatchData>) => BracketMatch<TRoundData, TMatchData>[];
|
|
875
|
+
type CreateBracketContinueMasterColumnConfig<TRoundData, TMatchData> = {
|
|
876
|
+
existingMasterColumns: ReadonlyArray<BracketMasterColumn<TRoundData, TMatchData>>;
|
|
877
|
+
columnWidth: number;
|
|
878
|
+
elementHeight: number;
|
|
879
|
+
/** Vertical space taken by the round header block (header + gap). 0 if headers are hidden. */
|
|
880
|
+
headerOffset: number;
|
|
881
|
+
component: BracketContinueComponent<TRoundData, TMatchData>;
|
|
882
|
+
matches: BracketMatch<TRoundData, TMatchData>[];
|
|
883
|
+
};
|
|
884
|
+
declare const createBracketContinueMasterColumn: <TRoundData, TMatchData>(config: CreateBracketContinueMasterColumnConfig<TRoundData, TMatchData>) => BracketMasterColumn<TRoundData, TMatchData>;
|
|
885
|
+
|
|
886
|
+
type CreateFoldedThirdPlaceSectionConfig<TRoundData, TMatchData> = {
|
|
887
|
+
/** The sub column holding the final, which the folded round is placed relative to. */
|
|
888
|
+
finalSubColumn: BracketSubColumn<TRoundData, TMatchData>;
|
|
889
|
+
round: BracketRound<TRoundData, TMatchData>;
|
|
890
|
+
/** How far below the top of the final's card the third place card sits, in px. */
|
|
891
|
+
topOffset: number;
|
|
892
|
+
options: CreateBracketGridConfig;
|
|
893
|
+
components: BracketComponents<TRoundData, TMatchData>;
|
|
894
|
+
};
|
|
895
|
+
/**
|
|
896
|
+
* The third place match as a second section of the final's master column: one card the given number of
|
|
897
|
+
* px below the top of the final's, with its own round header above it.
|
|
898
|
+
*
|
|
899
|
+
* @internal
|
|
900
|
+
*/
|
|
901
|
+
declare const createFoldedThirdPlaceSection: <TRoundData, TMatchData>(config: CreateFoldedThirdPlaceSectionConfig<TRoundData, TMatchData>) => BracketMasterColumnSection<TRoundData, TMatchData>;
|
|
902
|
+
|
|
903
|
+
type CreateBracketGapMasterColumnConfig<TRoundData, TMatchData> = {
|
|
904
|
+
existingMasterColumns: ReadonlyArray<BracketMasterColumn<TRoundData, TMatchData>>;
|
|
905
|
+
columnGap: number;
|
|
906
|
+
};
|
|
907
|
+
declare const createBracketGapMasterColumn: <TRoundData, TMatchData>(config: CreateBracketGapMasterColumnConfig<TRoundData, TMatchData>) => BracketMasterColumn<TRoundData, TMatchData>;
|
|
908
|
+
|
|
909
|
+
type CreateRoundBracketSubColumnRelativeToFirstRoundConfig<TRoundData, TMatchData> = {
|
|
910
|
+
firstRound: BracketRound<TRoundData, TMatchData>;
|
|
911
|
+
round: BracketRound<TRoundData, TMatchData>;
|
|
912
|
+
span: BracketSubColumnSpan;
|
|
913
|
+
hasReverseFinal: boolean;
|
|
914
|
+
options: CreateBracketGridConfig;
|
|
915
|
+
components: BracketComponents<TRoundData, TMatchData>;
|
|
916
|
+
/**
|
|
917
|
+
* Reserved space below the last match, for a layout whose columns are taller than the first round
|
|
918
|
+
* needs - a stacked bracket's centre chain hanging past the bottom of its block.
|
|
919
|
+
*/
|
|
920
|
+
bottomPadding?: number;
|
|
921
|
+
/**
|
|
922
|
+
* How many first-round rows each of this round's matches owns. Derived from the round's own match
|
|
923
|
+
* count when unset; a folded round is placed by its offset instead and takes `1`.
|
|
924
|
+
*/
|
|
925
|
+
matchFactor?: number;
|
|
926
|
+
};
|
|
927
|
+
declare const createRoundBracketSubColumnRelativeToFirstRound: <TRoundData, TMatchData>(config: CreateRoundBracketSubColumnRelativeToFirstRoundConfig<TRoundData, TMatchData>) => _ethlete_bracket.BracketSubColumn<TRoundData, TMatchData>;
|
|
928
|
+
|
|
929
|
+
declare const resolveBracketGridRowSpan: <TRoundData, TMatchData>(bracket: Bracket<TRoundData, TMatchData>, options: CreateBracketGridConfig) => CreateBracketGridConfig;
|
|
930
|
+
|
|
931
|
+
declare const createSingleEliminationGrid: <TRoundData, TMatchData>(bracketData: Bracket<TRoundData, TMatchData>, options: CreateBracketGridConfig, components: BracketComponents<TRoundData, TMatchData>) => ComputedBracketGrid<TRoundData, TMatchData>;
|
|
932
|
+
|
|
933
|
+
declare const createSwissGrid: <TRoundData, TMatchData>(bracketData: Bracket<TRoundData, TMatchData>, options: CreateBracketGridConfig, components: BracketComponents<TRoundData, TMatchData>) => ComputedBracketGrid<TRoundData, TMatchData>;
|
|
934
|
+
|
|
935
|
+
type LineOptions = {
|
|
936
|
+
path: PathOptions;
|
|
937
|
+
/** Draw right to left - the flow direction of a mirrored bracket's way back. */
|
|
938
|
+
inverted?: boolean;
|
|
939
|
+
};
|
|
940
|
+
declare const linePath: (from: BracketPosition, to: BracketPosition, options: LineOptions) => _ethlete_bracket.BracketEdge;
|
|
941
|
+
/**
|
|
942
|
+
* The connector between two cards sharing a column, where {@link linePath} and `curvePath` both
|
|
943
|
+
* degenerate to a zero-width horizontal run: straight down (or up) the column, edge to edge.
|
|
944
|
+
*/
|
|
945
|
+
declare const verticalPath: (from: BracketPosition, to: BracketPosition, options: LineOptions) => _ethlete_bracket.BracketEdge;
|
|
946
|
+
type GutterLineOptions = LineOptions & {
|
|
947
|
+
/** How far past the column's edge the vertical run sits - half a column gap keeps it clear of both. */
|
|
948
|
+
gutter: number;
|
|
949
|
+
};
|
|
950
|
+
/**
|
|
951
|
+
* A same-column connector for two cards with others stacked between them: out sideways, along the
|
|
952
|
+
* empty strip beside the column, and back in. {@link verticalPath} would run through everything in
|
|
953
|
+
* its way.
|
|
954
|
+
*/
|
|
955
|
+
declare const gutterPath: (from: BracketPosition, to: BracketPosition, options: GutterLineOptions) => _ethlete_bracket.BracketEdge;
|
|
956
|
+
|
|
957
|
+
type BracketLayoutRegistration = {
|
|
958
|
+
name: string;
|
|
959
|
+
mode: TournamentMode;
|
|
960
|
+
};
|
|
961
|
+
/** Returns the first registered layout matching the tournament mode. */
|
|
962
|
+
declare const resolveBracketLayout: <TLayout extends BracketLayoutRegistration>(layouts: readonly TLayout[] | undefined, mode: TournamentMode) => TLayout;
|
|
963
|
+
|
|
964
|
+
/** How a group-table prediction scored on one position, once the real order is in. */
|
|
965
|
+
declare const STANDING_PICK_OUTCOME: {
|
|
966
|
+
/** The participant finished on exactly the predicted position. */
|
|
967
|
+
readonly EXACT: "exact";
|
|
968
|
+
/** They finished on the predicted side of the advancing line, on another position. */
|
|
969
|
+
readonly PARTIAL: "partial";
|
|
970
|
+
/** They finished on the other side of the advancing line. */
|
|
971
|
+
readonly WRONG: "wrong";
|
|
972
|
+
};
|
|
973
|
+
type StandingPickOutcome = (typeof STANDING_PICK_OUTCOME)[keyof typeof STANDING_PICK_OUTCOME];
|
|
974
|
+
/**
|
|
975
|
+
* How the participant predicted on `predictedPosition` scored, given where they really finished.
|
|
976
|
+
*
|
|
977
|
+
* `advancingCount` is how many positions advance, so a position is on the advancing side while it is
|
|
978
|
+
* `<= advancingCount`. Ending up on the other side of that line is `WRONG` whatever the distance; the
|
|
979
|
+
* predicted side of it is `EXACT` on the predicted position and `PARTIAL` on any other.
|
|
980
|
+
*
|
|
981
|
+
* `EXACT` is awarded below the line as well. An app whose API stores only the advancing positions holds no
|
|
982
|
+
* prediction for the rest - the order there is whatever its UI happened to draw - and should narrow the
|
|
983
|
+
* result to `PARTIAL`/`WRONG` itself for those positions.
|
|
984
|
+
*
|
|
985
|
+
* Returns the outcome and no points: what an outcome is worth is a rule of the competition, and
|
|
986
|
+
* `POINTS[outcome]` is a lookup the app already owns.
|
|
987
|
+
*/
|
|
988
|
+
declare const standingPickOutcome: (options: {
|
|
989
|
+
/** The position the participant was predicted to finish on, 1-based. */
|
|
990
|
+
predictedPosition: number;
|
|
991
|
+
/** The position they really finished on, 1-based. */
|
|
992
|
+
actualPosition: number;
|
|
993
|
+
/** How many positions advance. */
|
|
994
|
+
advancingCount: number;
|
|
995
|
+
}) => StandingPickOutcome;
|
|
996
|
+
|
|
997
|
+
/** A prediction already stored for one position of a group table. */
|
|
998
|
+
type StandingPick = {
|
|
999
|
+
/** The position it was stored on, 1-based. */
|
|
1000
|
+
position: number;
|
|
1001
|
+
/** The participant predicted to finish there. */
|
|
1002
|
+
participantId: string;
|
|
1003
|
+
};
|
|
1004
|
+
/**
|
|
1005
|
+
* The order to show a group table in before anyone moves a row: every stored pick takes the position it was
|
|
1006
|
+
* stored on, and the participants without one follow in the order the backend listed them, filling the gaps.
|
|
1007
|
+
*
|
|
1008
|
+
* A pick the field cannot hold is dropped rather than drawn - a position outside
|
|
1009
|
+
* `1..participantIds.length`, an id that is not in the field, a second pick for a position or for a
|
|
1010
|
+
* participant already placed (the lowest position keeps it). The result is therefore always a permutation
|
|
1011
|
+
* of `participantIds`.
|
|
1012
|
+
*/
|
|
1013
|
+
declare const standingPickStartOrder: (options: {
|
|
1014
|
+
/** The participants, in the order the backend listed them. */
|
|
1015
|
+
participantIds: readonly string[];
|
|
1016
|
+
/** What is already stored, in any order. */
|
|
1017
|
+
picks: readonly StandingPick[];
|
|
1018
|
+
}) => string[];
|
|
1019
|
+
|
|
1020
|
+
export { BRACKET_DATA_LAYOUT, BRACKET_ERROR_CODES, BRACKET_ROUND_MIRROR_TYPE, BRACKET_SWISS_GROUP_COLOR_TYPE, BracketMap, COMMON_BRACKET_ROUND_TYPE, DOUBLE_ELIMINATION_BRACKET_ROUND_TYPE, GROUP_BRACKET_ROUND_TYPE, SINGLE_ELIMINATION_BRACKET_ROUND_TYPE, STANDING_PICK_OUTCOME, SWISS_ADVANCE_WINS, SWISS_BRACKET_ROUND_TYPE, SWISS_ELIMINATE_LOSSES, TOURNAMENT_MODE, bracketGridNaturalWidth, calculateColumnSplitFactor, calculateLowerRoundIndex, calculateUpperLowerRatio, calculateUpperRoundIndex, createBracket, createBracketBase, createBracketContinueMasterColumn, createBracketElement, createBracketElementPart, createBracketGapMasterColumn, createBracketGrid, createBracketMasterColumn, createBracketMasterColumnSection, createBracketSubColumn, createDoubleEliminationGrid, createFoldedThirdPlaceSection, createMatchesMapBase, createNewMatchParticipantBase, createParticipantsMapBase, createRoundBracketSubColumnRelativeToFirstRound, createRoundsMapBase, createSingleEliminationGrid, createStackedDoubleEliminationGrid, createSwissGrid, curvePath, drawMan, drawSwissMan, finalizeBracketGrid, generateBracketRoundSwissGroupMaps, generateMatchPosition, generateMatchRelationPositions, generateMatchRelationsNew, generateRoundRelationsNew, getAvailableSwissGroupsForRound, getBracketContinueMatches, getSwissGroupColorType, gutterPath, isBracketContinueMatch, isBracketSlotPredictable, linePath, migrateBracketPicks, path, resolveBracketGridRowSpan, resolveBracketLayout, resolveBracketSlot, standingPickOutcome, standingPickStartOrder, verticalPath };
|
|
1021
|
+
export type { Bracket, BracketBase, BracketComponentInput, BracketComponentType, BracketComponents, BracketContinueComponent, BracketDataLayout, BracketDataSource, BracketDrawing, BracketEdge, BracketElement, BracketElementBase, BracketElementPart, BracketElementSpanCoordinates, BracketElementToCreate, BracketElementToCreateBase, BracketElementType, BracketGradient, BracketGradientStop, BracketGrid, BracketLayoutRegistration, BracketMasterColumn, BracketMasterColumnSection, BracketMasterColumnSectionType, BracketMatch, BracketMatchBase, BracketMatchComponent, BracketMatchFactor, BracketMatchId, BracketMatchParticipant, BracketMatchParticipantBase, BracketMatchParticipantWithRelationsBase, BracketMatchPosition, BracketMatchRelation, BracketMatchRelationNothingToOne, BracketMatchRelationOneToNothing, BracketMatchRelationOneToOne, BracketMatchRelationTwoToNothing, BracketMatchRelationTwoToOne, BracketMatchShortId, BracketMatchSlot, BracketMatchSource, BracketMatchStatus, BracketMatchWithRelationsBase, BracketParticipant, BracketParticipantBase, BracketParticipantMatch, BracketParticipantWithRelationsBase, BracketPickMigration, BracketPickMigrationOptions, BracketPickSet, BracketPosition, BracketRect, BracketRound, BracketRoundBase, BracketRoundHeaderComponent, BracketRoundId, BracketRoundMapWithSwissData, BracketRoundMirrorType, BracketRoundPosition, BracketRoundRelation, BracketRoundRelationNothingToOne, BracketRoundRelationOneToNothing, BracketRoundRelationOneToOne, BracketRoundRelationTwoToNothing, BracketRoundRelationTwoToOne, BracketRoundShortId, BracketRoundSource, BracketRoundSwissData, BracketRoundSwissGroup, BracketRoundSwissGroupId, BracketRoundSwissGroupMap, BracketRoundType, BracketRoundWithRelationsBase, BracketSlotResolutionPolicy, BracketSlotSource, BracketSlotSourceKind, BracketSubColumn, BracketSubColumnSpan, BracketSwissColors, BracketSwissGroupColorType, CommonBracketRoundType, ComponentInputValue, ComputedBracketGrid, ContinueBracketElement, ContinueBracketElementDetails, ContinueBracketElementToCreate, CreateBracketContinueMasterColumnConfig, CreateBracketElementPartConfig, CreateBracketGapMasterColumnConfig, CreateBracketGridConfig, CreateBracketMasterColumnConfig, CreateBracketMasterColumnSectionConfig, CreateBracketOptions, CreateBracketSubColumnConfig, CreateFoldedThirdPlaceSectionConfig, CreateRoundBracketSubColumnRelativeToFirstRoundConfig, CurveOptions, Dimensions, DoubleEliminationBracketRoundType, DrawManDimensions, DrawSwissManDimensions, FinalizedBracketColumn, FinalizedBracketElement, FinalizedBracketMatchElementMap, FinalizedContinueBracketElement, FinalizedHeaderBracketElement, FinalizedMatchBracketElement, GapBracketElement, GapBracketElementDetails, GapBracketElementToCreate, GenerateBracketDataOptions, GroupBracketRoundType, GutterLineOptions, HeaderBracketElement, HeaderBracketElementDetails, HeaderBracketElementToCreate, LineOptions, MatchBracketElement, MatchBracketElementToCreate, MatchParticipantId, MatchParticipantShortId, MatchParticipantSide, MatchPositionMaps, MutableBracketElement, MutableBracketGrid, MutableBracketMasterColumn, MutableBracketMasterColumnSection, MutableBracketSubColumn, ParticipantMatchResult, PathOptions, SingleEliminationBracketRoundType, Spacing, StandingPick, StandingPickOutcome, SwissBracketRoundType, TournamentMode };
|