mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-04-24 23:19:39 -05:00
Take ownership of brackets-model
This commit is contained in:
parent
0a346175b6
commit
0e28189336
|
|
@ -6,7 +6,7 @@ import type {
|
|||
Group as GroupType,
|
||||
Round as RoundType,
|
||||
Match as MatchType,
|
||||
} from "brackets-model";
|
||||
} from "~/modules/brackets-model";
|
||||
import { sql } from "~/db/sql";
|
||||
import type {
|
||||
Tournament,
|
||||
|
|
|
|||
|
|
@ -6,5 +6,4 @@ const globalForEmitter = global as unknown as {
|
|||
|
||||
export const emitter = globalForEmitter.emitter ?? new EventEmitter();
|
||||
|
||||
// xxx: test behavior when deployed, do we need if (process.env.NODE_ENV !== 'production') ?
|
||||
globalForEmitter.emitter = emitter;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { Match } from "brackets-model";
|
||||
import type { Match } from "~/modules/brackets-model";
|
||||
import { sql } from "~/db/sql";
|
||||
import type { TournamentMatch } from "~/db/types";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { Stage } from "brackets-model";
|
||||
import type { Stage } from "~/modules/brackets-model";
|
||||
import type {
|
||||
TournamentFormat,
|
||||
TournamentMatch,
|
||||
|
|
@ -86,7 +86,7 @@ export function resolveTournamentStageSettings(
|
|||
case "DE":
|
||||
return {
|
||||
grandFinal: "double",
|
||||
seedOrdering: ["space_between"] as any,
|
||||
seedOrdering: ["space_between"],
|
||||
};
|
||||
default: {
|
||||
assertUnreachable(format);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import type {
|
|||
Stage,
|
||||
StageType,
|
||||
GroupType,
|
||||
} from "brackets-model";
|
||||
} from "~/modules/brackets-model";
|
||||
import type { RoundPositionalInfo } from "../types";
|
||||
import type { Create } from "../create";
|
||||
import * as helpers from "../helpers";
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import type {
|
|||
Seeding,
|
||||
Stage,
|
||||
GroupType,
|
||||
} from "brackets-model";
|
||||
import { Status } from "brackets-model";
|
||||
} from "~/modules/brackets-model";
|
||||
import { Status } from "~/modules/brackets-model";
|
||||
import type { DeepPartial, ParticipantSlot, Side } from "../types";
|
||||
import type { SetNextOpponent } from "../helpers";
|
||||
import { ordering } from "../ordering";
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import type {
|
|||
Seeding,
|
||||
SeedOrdering,
|
||||
Stage,
|
||||
} from "brackets-model";
|
||||
} from "~/modules/brackets-model";
|
||||
import { defaultMinorOrdering, ordering } from "./ordering";
|
||||
import type {
|
||||
Duel,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { Group, Match, MatchGame } from "brackets-model";
|
||||
import type { Group, Match, MatchGame } from "~/modules/brackets-model";
|
||||
import { BaseGetter } from "./base/getter";
|
||||
import * as helpers from "./helpers";
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import type {
|
|||
Match,
|
||||
MatchGame,
|
||||
Participant,
|
||||
} from "brackets-model";
|
||||
import { Status } from "brackets-model";
|
||||
} from "~/modules/brackets-model";
|
||||
import { Status } from "~/modules/brackets-model";
|
||||
import type { Database, FinalStandingsItem, ParticipantSlot } from "./types";
|
||||
import { BaseGetter } from "./base/getter";
|
||||
import * as helpers from "./helpers";
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ import type {
|
|||
Stage,
|
||||
StageType,
|
||||
GroupType,
|
||||
} from "brackets-model";
|
||||
import { Status } from "brackets-model";
|
||||
} from "~/modules/brackets-model";
|
||||
import { Status } from "~/modules/brackets-model";
|
||||
|
||||
import type {
|
||||
Database,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import type {
|
|||
Storage,
|
||||
Table,
|
||||
} from "./types";
|
||||
import type { InputStage, Stage } from "brackets-model";
|
||||
import type { InputStage, Stage } from "~/modules/brackets-model";
|
||||
import { create } from "./create";
|
||||
import { Get } from "./get";
|
||||
import { Update } from "./update";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// https://web.archive.org/web/20200601102344/https://tl.net/forum/sc2-tournaments/202139-superior-double-elimination-losers-bracket-seeding
|
||||
|
||||
import type { SeedOrdering } from "brackets-model";
|
||||
import type { SeedOrdering } from "~/modules/brackets-model";
|
||||
import type { OrderingMap } from "./types";
|
||||
import invariant from "tiny-invariant";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Status } from "brackets-model";
|
||||
import { Status } from "~/modules/brackets-model";
|
||||
import { BaseUpdater } from "./base/updater";
|
||||
import * as helpers from "./helpers";
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import type {
|
|||
Round,
|
||||
SeedOrdering,
|
||||
Stage,
|
||||
} from "brackets-model";
|
||||
} from "~/modules/brackets-model";
|
||||
|
||||
/**
|
||||
* Type of an object implementing every ordering method.
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import type {
|
|||
Round,
|
||||
Seeding,
|
||||
SeedOrdering,
|
||||
} from "brackets-model";
|
||||
import { Status } from "brackets-model";
|
||||
} from "~/modules/brackets-model";
|
||||
import { Status } from "~/modules/brackets-model";
|
||||
import { ordering } from "./ordering";
|
||||
import { BaseUpdater } from "./base/updater";
|
||||
import type { ChildCountLevel, DeepPartial } from "./types";
|
||||
|
|
|
|||
4
app/modules/brackets-model/index.ts
Normal file
4
app/modules/brackets-model/index.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export * from "./unions";
|
||||
export * from "./input";
|
||||
export * from "./storage";
|
||||
export * from "./other";
|
||||
131
app/modules/brackets-model/input.ts
Normal file
131
app/modules/brackets-model/input.ts
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
/*------------------------------------------------------------|
|
||||
* Contains everything which is given by the user as input.
|
||||
*-----------------------------------------------------------*/
|
||||
|
||||
import type { Participant } from "./storage";
|
||||
import type {
|
||||
GrandFinalType,
|
||||
RoundRobinMode,
|
||||
SeedOrdering,
|
||||
StageType,
|
||||
} from "./unions";
|
||||
|
||||
/**
|
||||
* A participant as it would be persisted in the storage, but with extra fields.
|
||||
*/
|
||||
export type CustomParticipant<ExtraFields = Record<string, unknown>> =
|
||||
Participant & ExtraFields;
|
||||
|
||||
/**
|
||||
* The seeding for a stage.
|
||||
*
|
||||
* Each element represents a participant, which can be:
|
||||
* - A full object, with possibly extra fields.
|
||||
* - Its name.
|
||||
* - Its ID.
|
||||
* - Or a BYE: `null`.
|
||||
*/
|
||||
export type Seeding = (CustomParticipant | string | number | null)[];
|
||||
|
||||
/**
|
||||
* Used to create a stage.
|
||||
*/
|
||||
export interface InputStage {
|
||||
/**
|
||||
* ID of the parent tournament.
|
||||
*
|
||||
* Used to determine the `number` property of a stage related to a tournament.
|
||||
*/
|
||||
tournamentId: number;
|
||||
|
||||
/** Name of the stage. */
|
||||
name: string;
|
||||
|
||||
/** Type of stage. */
|
||||
type: StageType;
|
||||
|
||||
/** The number of the stage in its tournament. Is determined if not given. */
|
||||
number?: number;
|
||||
|
||||
/** Contains participants or `null` for BYEs. */
|
||||
seeding?: Seeding;
|
||||
|
||||
/** Contains optional settings specific to each stage type. */
|
||||
settings?: StageSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* The possible settings for a stage.
|
||||
*/
|
||||
export interface StageSettings {
|
||||
/**
|
||||
* The number of participants.
|
||||
*/
|
||||
size?: number;
|
||||
|
||||
/**
|
||||
* A list of ordering methods to apply to the seeding.
|
||||
*
|
||||
* - For a round-robin stage: 1 item required (**with** `"groups."` prefix).
|
||||
* - Used to distribute in groups.
|
||||
* - For a simple elimination stage, 1 item required (**without** `"groups."` prefix).
|
||||
* - Used to distribute in round 1.
|
||||
* - For a double elimination stage, 1 item required, 3+ items supported (**without** `"groups."` prefix).
|
||||
* - Item 1 (required) - Used to distribute in WB round 1.
|
||||
* - Item 2 - Used to distribute WB losers in LB round 1.
|
||||
* - Items 3+ - Used to distribute WB losers in LB minor rounds (1 per round).
|
||||
*/
|
||||
seedOrdering?: SeedOrdering[];
|
||||
|
||||
/**
|
||||
* Whether to balance BYEs in the seeding of an elimination stage.
|
||||
*
|
||||
* This prevents having BYE against BYE in matches.
|
||||
*/
|
||||
balanceByes?: boolean;
|
||||
|
||||
/**
|
||||
* All matches of the stage will have this child count. This can later be overridden for certain groups, rounds or matches.
|
||||
*/
|
||||
matchesChildCount?: number;
|
||||
|
||||
/**
|
||||
* Number of groups in a round-robin stage.
|
||||
*/
|
||||
groupCount?: number;
|
||||
|
||||
/**
|
||||
* The mode for the round-robin stage.
|
||||
*
|
||||
* - If `simple`, each participant plays each opponent once.
|
||||
* - If `double`, each participant plays each opponent twice, once at home and once away.
|
||||
*/
|
||||
roundRobinMode?: RoundRobinMode;
|
||||
|
||||
/**
|
||||
* A list of seeds per group for a round-robin stage to be manually ordered.
|
||||
*
|
||||
* Seed ordering is ignored if this property is given.
|
||||
*/
|
||||
manualOrdering?: number[][];
|
||||
|
||||
/**
|
||||
* Optional final between semi-final losers.
|
||||
*/
|
||||
consolationFinal?: boolean;
|
||||
|
||||
/**
|
||||
* Whether to skip the first round of the WB of a double elimination stage.
|
||||
*/
|
||||
skipFirstRound?: boolean;
|
||||
|
||||
/**
|
||||
* Optional grand final between WB and LB winners.
|
||||
*
|
||||
* - If `none`, there is no grand final.
|
||||
* - If `simple`, the final is a single match. The winner is the winner of the stage.
|
||||
* - If `double`, if the WB winner wins, he's the winner of the stage. But if he loses, the final is reset and there is a very last match.
|
||||
* It might be fairer since it gives the WB winner the right to lose once during the stage...
|
||||
*/
|
||||
grandFinal?: GrandFinalType;
|
||||
}
|
||||
62
app/modules/brackets-model/other.ts
Normal file
62
app/modules/brackets-model/other.ts
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*---------------------------------------------------------------------------|
|
||||
* Contains the rest of the types which doesn't belong to the other files.
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
import type { Result } from "./unions";
|
||||
|
||||
/**
|
||||
* The possible status for a match.
|
||||
*/
|
||||
export enum Status {
|
||||
/** The two matches leading to this one are not completed yet. */
|
||||
Locked = 0,
|
||||
|
||||
/** One participant is ready and waiting for the other one. */
|
||||
Waiting = 1,
|
||||
|
||||
/** Both participants are ready to start. */
|
||||
Ready = 2,
|
||||
|
||||
/** The match is running. */
|
||||
Running = 3,
|
||||
|
||||
/** The match is completed. */
|
||||
Completed = 4,
|
||||
|
||||
/** At least one participant completed his following match. */
|
||||
Archived = 5,
|
||||
}
|
||||
|
||||
/**
|
||||
* The results of a participant in a match.
|
||||
*/
|
||||
export interface ParticipantResult {
|
||||
/** If `null`, the participant is to be determined. */
|
||||
id: number | null;
|
||||
|
||||
/** Indicates where the participant comes from. */
|
||||
position?: number;
|
||||
|
||||
/** If this participant forfeits, the other automatically wins. */
|
||||
forfeit?: boolean;
|
||||
|
||||
/** The current score of the participant. */
|
||||
score?: number;
|
||||
|
||||
/** Tells what is the result of a duel for this participant. */
|
||||
result?: Result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only contains information about match status and results.
|
||||
*/
|
||||
export interface MatchResults {
|
||||
/** Status of the match. */
|
||||
status: Status;
|
||||
|
||||
/** First opponent of the match. */
|
||||
opponent1: ParticipantResult | null;
|
||||
|
||||
/** Second opponent of the match. */
|
||||
opponent2: ParticipantResult | null;
|
||||
}
|
||||
117
app/modules/brackets-model/storage.ts
Normal file
117
app/modules/brackets-model/storage.ts
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*-----------------------------------------------------------------|
|
||||
* Contains the types which are persisted in the chosen storage.
|
||||
*----------------------------------------------------------------*/
|
||||
|
||||
import type { StageSettings } from "./input";
|
||||
import type { MatchResults } from "./other";
|
||||
import type { StageType } from "./unions";
|
||||
|
||||
/**
|
||||
* A participant of a stage (team or individual).
|
||||
*/
|
||||
export interface Participant {
|
||||
/** ID of the participant. */
|
||||
id: number;
|
||||
|
||||
/** ID of the tournament this participant belongs to. */
|
||||
tournament_id: number;
|
||||
|
||||
/** Name of the participant. */
|
||||
name: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A stage, which can be a round-robin stage or a single/double elimination stage.
|
||||
*/
|
||||
export interface Stage {
|
||||
/** ID of the stage. */
|
||||
id: number;
|
||||
|
||||
/** ID of the tournament this stage belongs to. */
|
||||
tournament_id: number;
|
||||
|
||||
/** Name of the stage. */
|
||||
name: string;
|
||||
|
||||
/** Type of the stage. */
|
||||
type: StageType;
|
||||
|
||||
/** Settings of the stage. */
|
||||
settings: StageSettings;
|
||||
|
||||
/** The number of the stage in its tournament. */
|
||||
number: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* A group of a stage.
|
||||
*/
|
||||
export interface Group {
|
||||
/** ID of the group. */
|
||||
id: number;
|
||||
|
||||
/** ID of the parent stage. */
|
||||
stage_id: number;
|
||||
|
||||
/** The number of the group in its stage. */
|
||||
number: number;
|
||||
}
|
||||
|
||||
// The next levels don't have a `name` property. They are automatically named with their `number` and their context (parent levels).
|
||||
|
||||
/**
|
||||
* A round of a group.
|
||||
*/
|
||||
export interface Round {
|
||||
/** ID of the round. */
|
||||
id: number;
|
||||
|
||||
/** ID of the parent stage. */
|
||||
stage_id: number;
|
||||
|
||||
/** ID of the parent group. */
|
||||
group_id: number;
|
||||
|
||||
/** The number of the round in its group. */
|
||||
number: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* A match of a round.
|
||||
*/
|
||||
export interface Match extends MatchResults {
|
||||
/** ID of the match. */
|
||||
id: number;
|
||||
|
||||
/** ID of the parent stage. */
|
||||
stage_id: number;
|
||||
|
||||
/** ID of the parent group. */
|
||||
group_id: number;
|
||||
|
||||
/** ID of the parent round. */
|
||||
round_id: number;
|
||||
|
||||
/** The number of the match in its round. */
|
||||
number: number;
|
||||
|
||||
/** The count of match games this match has. Can be `0` if it's a simple match, or a positive number for "Best Of" matches. */
|
||||
child_count: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* A game of a match.
|
||||
*/
|
||||
export interface MatchGame extends MatchResults {
|
||||
/** ID of the match game. */
|
||||
id: number;
|
||||
|
||||
/** ID of the parent stage. */
|
||||
stage_id: number;
|
||||
|
||||
/** ID of the parent match. */
|
||||
parent_id: number;
|
||||
|
||||
/** The number of the match game in its parent match. */
|
||||
number: number;
|
||||
}
|
||||
59
app/modules/brackets-model/unions.ts
Normal file
59
app/modules/brackets-model/unions.ts
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*----------------------------------------|
|
||||
* Contains all the string union types.
|
||||
*---------------------------------------*/
|
||||
|
||||
/**
|
||||
* The only supported types of stage.
|
||||
*/
|
||||
export type StageType =
|
||||
| "round_robin"
|
||||
| "single_elimination"
|
||||
| "double_elimination";
|
||||
|
||||
/**
|
||||
* All the possible types of group in an elimination stage.
|
||||
*
|
||||
* - `single_bracket` for single elimination.
|
||||
* - `winner_bracket` and `loser_bracket` for double elimination.
|
||||
* - `final_group` for both single and double elimination.
|
||||
*/
|
||||
export type GroupType =
|
||||
| "single_bracket"
|
||||
| "winner_bracket"
|
||||
| "loser_bracket"
|
||||
| "final_group";
|
||||
|
||||
/**
|
||||
* The possible types for a double elimination stage's grand final.
|
||||
*/
|
||||
export type GrandFinalType = "none" | "simple" | "double";
|
||||
|
||||
/**
|
||||
* The possible types of final for an elimination stage.
|
||||
*/
|
||||
export type FinalType = "consolation_final" | "grand_final";
|
||||
|
||||
/**
|
||||
* The possible modes for a round-robin stage.
|
||||
*/
|
||||
export type RoundRobinMode = "simple" | "double";
|
||||
|
||||
/**
|
||||
* Used to order seeds.
|
||||
*/
|
||||
export type SeedOrdering =
|
||||
| "natural"
|
||||
| "reverse"
|
||||
| "half_shift"
|
||||
| "reverse_half_shift"
|
||||
| "pair_flip"
|
||||
| "inner_outer"
|
||||
| "space_between"
|
||||
| "groups.effort_balanced"
|
||||
| "groups.seed_optimized"
|
||||
| "groups.bracket_optimized";
|
||||
|
||||
/**
|
||||
* The possible results of a duel for a participant.
|
||||
*/
|
||||
export type Result = "win" | "draw" | "loss";
|
||||
11
package-lock.json
generated
11
package-lock.json
generated
|
|
@ -20,7 +20,6 @@
|
|||
"@tldraw/tldraw": "^1.29.2",
|
||||
"aws-sdk": "^2.1354.0",
|
||||
"better-sqlite3": "^8.3.0",
|
||||
"brackets-model": "^1.4.0",
|
||||
"cachified": "^3.1.0",
|
||||
"clsx": "^1.2.1",
|
||||
"compressorjs": "^1.2.1",
|
||||
|
|
@ -5732,11 +5731,6 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/brackets-model": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/brackets-model/-/brackets-model-1.4.0.tgz",
|
||||
"integrity": "sha512-bDsM2VTLkhkCZPis7vXNhVB96gYmjO5P7qJg81+7DF0c2OygwqLm5XSeogV+w2i2rVFFjLoUCQEkBI2lr7qZhA=="
|
||||
},
|
||||
"node_modules/browser-fs-access": {
|
||||
"version": "0.31.1",
|
||||
"license": "Apache-2.0"
|
||||
|
|
@ -19937,11 +19931,6 @@
|
|||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"brackets-model": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/brackets-model/-/brackets-model-1.4.0.tgz",
|
||||
"integrity": "sha512-bDsM2VTLkhkCZPis7vXNhVB96gYmjO5P7qJg81+7DF0c2OygwqLm5XSeogV+w2i2rVFFjLoUCQEkBI2lr7qZhA=="
|
||||
},
|
||||
"browser-fs-access": {
|
||||
"version": "0.31.1"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@
|
|||
"@tldraw/tldraw": "^1.29.2",
|
||||
"aws-sdk": "^2.1354.0",
|
||||
"better-sqlite3": "^8.3.0",
|
||||
"brackets-model": "^1.4.0",
|
||||
"cachified": "^3.1.0",
|
||||
"clsx": "^1.2.1",
|
||||
"compressorjs": "^1.2.1",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user