mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-05-08 06:37:26 -05:00
* Add DB tables
* Toggle TO Tools in new calendar event page
* TO tools page initial
* Add counter pick map pool UI
* Save tie breaker map pool
* Save team name
* Layout initial
* Load users own team
* Make team name input required
* Rename team
* Divide to sections
* Submit team map pool
* New style for counter pick map pool section expand
* Fix tiebreaker map pool not saved when new event made
* Split to many forms
* According for team name
* Small UI consistency tweaks
* Add explanation to tie breaker maps
* Remove redundant prop
* Fix new calendar event todos
* Use required hidden input component in new build page
* Fix to tools page showing even when toToolsEnabled = 0
* Delete team
* Map list generation tests initial
* Add tournament map list generation tests
* First version of map list generation
* Add seeded RNG
* Rearrange files
* Generation with strats initial
* Default map pool + allow one team not to have any maps
* Implement map generation via backtracking
* Make order of stages irrelevant
* Add one more TODO
* Seed
* Fixes
* Tournament map list generator initial
* More functional maplist
* Fix any
* Persist in search params initial
* Add date to calendar seed
* Revert "Persist in search params initial"
This reverts commit f01a9e6982.
* Allow admin to start tournament
* Rate maplist instead of optimal / suboptimal
* Add fallback if map list generation errors out
* Hide TO Tools if not admin
* Submit team roster and delete members
* Teams page
* Give roster s p a c e
* Clear user combobox on sent + layout tweaks
* Gracefully handle updating after tournament has started
* Add title
* Persist map list in search params
* Add i18n
151 lines
3.4 KiB
TypeScript
151 lines
3.4 KiB
TypeScript
import {
|
|
mapPoolToSerializedString,
|
|
serializedStringToMapPool,
|
|
} from "./serializer";
|
|
import type { ReadonlyMapPoolObject, MapPoolObject } from "./types";
|
|
import clone from "just-clone";
|
|
import type { MapPoolMap } from "~/db/types";
|
|
import { mapPoolListToMapPoolObject } from "~/modules/map-list-generator";
|
|
import {
|
|
type ModeShort,
|
|
type StageId,
|
|
stageIds,
|
|
} from "~/modules/in-game-lists";
|
|
|
|
type DbMapPoolList = Array<Pick<MapPoolMap, "stageId" | "mode">>;
|
|
|
|
export class MapPool {
|
|
private source: string | ReadonlyMapPoolObject;
|
|
private asSerialized?: string;
|
|
private asObject?: ReadonlyMapPoolObject;
|
|
|
|
constructor(init: ReadonlyMapPoolObject | string | DbMapPoolList) {
|
|
this.source = Array.isArray(init) ? mapPoolListToMapPoolObject(init) : init;
|
|
}
|
|
|
|
static serialize(init: ReadonlyMapPoolObject | string | DbMapPoolList) {
|
|
return new MapPool(init).serialized;
|
|
}
|
|
|
|
static parse(init: MapPoolObject | string | DbMapPoolList) {
|
|
return new MapPool(init).parsed;
|
|
}
|
|
|
|
static toDbList(init: MapPoolObject | string | DbMapPoolList) {
|
|
return new MapPool(init).dbList;
|
|
}
|
|
|
|
get serialized(): string {
|
|
if (this.asSerialized !== undefined) {
|
|
return this.asSerialized;
|
|
}
|
|
|
|
return (this.asSerialized =
|
|
typeof this.source === "string"
|
|
? this.source
|
|
: mapPoolToSerializedString(this.source));
|
|
}
|
|
|
|
get parsed(): ReadonlyMapPoolObject {
|
|
if (this.asObject !== undefined) {
|
|
return this.asObject;
|
|
}
|
|
|
|
return (this.asObject =
|
|
typeof this.source === "string"
|
|
? serializedStringToMapPool(this.source)
|
|
: this.source);
|
|
}
|
|
|
|
get dbList(): DbMapPoolList {
|
|
return Object.entries(this.parsed).flatMap(([mode, stages]) =>
|
|
stages.flatMap((stageId) => ({ mode: mode as ModeShort, stageId }))
|
|
);
|
|
}
|
|
|
|
get stages() {
|
|
return Object.values(this.parsed).flat();
|
|
}
|
|
|
|
get stageModePairs() {
|
|
return Object.entries(this.parsed).flatMap(([mode, stages]) =>
|
|
stages.map((stageId) => ({ mode: mode as ModeShort, stageId }))
|
|
);
|
|
}
|
|
|
|
has({ stageId, mode }: { stageId: StageId; mode: ModeShort }) {
|
|
return this.parsed[mode].includes(stageId);
|
|
}
|
|
|
|
hasMode(mode: ModeShort): boolean {
|
|
return this.parsed[mode].length > 0;
|
|
}
|
|
|
|
hasStage(stageId: StageId): boolean {
|
|
return Object.values(this.parsed).some((stages) =>
|
|
stages.includes(stageId)
|
|
);
|
|
}
|
|
|
|
isEmpty(): boolean {
|
|
return Object.values(this.parsed).every((stages) => stages.length === 0);
|
|
}
|
|
|
|
getClonedObject(): MapPoolObject {
|
|
return clone(this.parsed) as MapPoolObject;
|
|
}
|
|
|
|
toString() {
|
|
return this.serialized;
|
|
}
|
|
|
|
toJSON() {
|
|
return this.parsed;
|
|
}
|
|
|
|
static EMPTY = new MapPool({
|
|
SZ: [],
|
|
TC: [],
|
|
CB: [],
|
|
RM: [],
|
|
TW: [],
|
|
});
|
|
|
|
static ALL = new MapPool({
|
|
SZ: [...stageIds],
|
|
TC: [...stageIds],
|
|
CB: [...stageIds],
|
|
RM: [...stageIds],
|
|
TW: [...stageIds],
|
|
});
|
|
|
|
static ANARCHY = new MapPool({
|
|
SZ: [...stageIds],
|
|
TC: [...stageIds],
|
|
CB: [...stageIds],
|
|
RM: [...stageIds],
|
|
TW: [],
|
|
});
|
|
|
|
static SZ = new MapPool({
|
|
...MapPool.EMPTY.parsed,
|
|
SZ: [...stageIds],
|
|
});
|
|
static TC = new MapPool({
|
|
...MapPool.EMPTY.parsed,
|
|
TC: [...stageIds],
|
|
});
|
|
static CB = new MapPool({
|
|
...MapPool.EMPTY.parsed,
|
|
CB: [...stageIds],
|
|
});
|
|
static RM = new MapPool({
|
|
...MapPool.EMPTY.parsed,
|
|
RM: [...stageIds],
|
|
});
|
|
static TW = new MapPool({
|
|
...MapPool.EMPTY.parsed,
|
|
TW: [...stageIds],
|
|
});
|
|
}
|