Screen toggle option for tournaments Closes #1686

This commit is contained in:
Kalle
2024-03-16 14:11:37 +02:00
parent 67f5a99fb5
commit 8c3e78c2ba
20 changed files with 248 additions and 7 deletions

View File

@@ -893,6 +893,7 @@ function calendarEventWithToTools(
sources: [{ bracketIdx: 0, placements: [4] }],
},
],
enableNoScreenToggle: true,
}
: event === "PP"
? {

View File

@@ -389,6 +389,7 @@ export interface TournamentSettings {
thirdPlaceMatch?: boolean;
isRanked?: boolean;
autoCheckInAll?: boolean;
enableNoScreenToggle?: boolean;
}
export interface CastedMatchesInfo {
@@ -514,6 +515,7 @@ export interface TournamentTeam {
inviteCode: string;
name: string;
prefersNotToHost: Generated<number>;
noScreen: Generated<number>;
seed: number | null;
tournamentId: number;
}

View File

@@ -388,6 +388,7 @@ type CreateArgs = Pick<
thirdPlaceMatch?: boolean;
autoCheckInAll?: boolean;
isRanked?: boolean;
enableNoScreenToggle?: boolean;
};
export async function create(args: CreateArgs) {
return db.transaction().execute(async (trx) => {
@@ -399,6 +400,7 @@ export async function create(args: CreateArgs) {
teamsPerGroup: args.teamsPerGroup,
thirdPlaceMatch: args.thirdPlaceMatch,
isRanked: args.isRanked,
enableNoScreenToggle: args.enableNoScreenToggle,
autoCheckInAll: args.autoCheckInAll,
};
@@ -474,6 +476,7 @@ export async function update(args: UpdateArgs) {
teamsPerGroup: args.teamsPerGroup,
thirdPlaceMatch: args.thirdPlaceMatch,
isRanked: args.isRanked,
enableNoScreenToggle: args.enableNoScreenToggle,
autoCheckInAll: args.autoCheckInAll,
};

View File

@@ -71,6 +71,10 @@ export const newCalendarEventActionSchema = z
toToolsEnabled: z.preprocess(checkboxValueToBoolean, z.boolean()),
toToolsMode: z.enum(["ALL", "TO", "SZ", "TC", "RM", "CB"]).optional(),
isRanked: z.preprocess(checkboxValueToBoolean, z.boolean().nullish()),
enableNoScreenToggle: z.preprocess(
checkboxValueToBoolean,
z.boolean().nullish(),
),
//
// tournament format related fields
//

View File

@@ -118,6 +118,7 @@ export const action: ActionFunction = async ({ request }) => {
teamsPerGroup: data.teamsPerGroup ?? undefined,
thirdPlaceMatch: data.thirdPlaceMatch ?? undefined,
isRanked: data.isRanked ?? undefined,
enableNoScreenToggle: data.enableNoScreenToggle ?? undefined,
autoCheckInAll: data.autoCheckInAll ?? undefined,
};
validate(
@@ -263,6 +264,7 @@ export default function CalendarNewEventPage() {
<>
<Divider>Tournament settings</Divider>
<RankedToggle />
<EnableNoScreenToggle />
</>
) : null}
{isTournament ? (
@@ -647,6 +649,33 @@ function RankedToggle() {
);
}
function EnableNoScreenToggle() {
const data = useLoaderData<typeof loader>();
const [enableNoScreen, setEnableNoScreen] = React.useState(
data.tournamentCtx?.settings.enableNoScreenToggle ?? true,
);
const id = React.useId();
return (
<div>
<label htmlFor={id} className="w-max">
Splattercolor Screen toggle
</label>
<Toggle
name="enableNoScreenToggle"
id={id}
tiny
checked={enableNoScreen}
setChecked={setEnableNoScreen}
/>
<FormMessage type="info">
When registering ask teams if they want to play without Splattercolor
Screen.
</FormMessage>
</div>
);
}
const mapPickingStyleToShort: Record<
Tables["Tournament"]["mapPickingStyle"],
"ALL" | "TO" | RankedModeShort

View File

@@ -1269,7 +1269,7 @@ function BottomSection({
}
function ScreenLegalityInfo({ ban }: { ban: boolean }) {
const { t } = useTranslation(["q", "weapons", "weapons"]);
const { t } = useTranslation(["q", "weapons"]);
return (
<div className="q-match__screen-legality">
@@ -1282,7 +1282,7 @@ function ScreenLegalityInfo({ ban }: { ban: boolean }) {
path={specialWeaponImageUrl(SPLATTERCOLOR_SCREEN_ID)}
width={30}
height={30}
alt={`weapons:SPECIAL_${SPLATTERCOLOR_SCREEN_ID}`}
alt={t(`weapons:SPECIAL_${SPLATTERCOLOR_SCREEN_ID}`)}
/>
</div>
</Alert>

View File

@@ -14,7 +14,11 @@ import type { ModeShort, StageId } from "~/modules/in-game-lists";
import type { TournamentMapListMap } from "~/modules/tournament-map-list-generator";
import { databaseTimestampToDate } from "~/utils/dates";
import type { Unpacked } from "~/utils/types";
import { modeImageUrl, stageImageUrl } from "~/utils/urls";
import {
modeImageUrl,
specialWeaponImageUrl,
stageImageUrl,
} from "~/utils/urls";
import { type TournamentMatchLoaderData } from "../routes/to.$id.matches.$mid";
import {
mapCountPlayedInSetWithCertainty,
@@ -24,6 +28,9 @@ import {
} from "../tournament-bracket-utils";
import { ScoreReporterRosters } from "./ScoreReporterRosters";
import type { TournamentDataTeam } from "../core/Tournament.server";
import { CrossIcon } from "~/components/icons/Cross";
import { CheckmarkIcon } from "~/components/icons/Checkmark";
import { SPLATTERCOLOR_SCREEN_ID } from "~/modules/in-game-lists/weapon-ids";
export type Result = Unpacked<
SerializeFrom<TournamentMatchLoaderData>["results"]
@@ -107,6 +114,9 @@ export function ScoreReporter({
bestOf: data.match.bestOf,
})}
</>,
tournament.ctx.settings.enableNoScreenToggle ? (
<ScreenBanIcons banned={teams.some((team) => team.noScreen)} />
) : null,
];
return (
@@ -497,3 +507,24 @@ function ActionSectionWrapper({
</section>
);
}
function ScreenBanIcons({ banned }: { banned: boolean }) {
const { t } = useTranslation(["weapons"]);
return (
<div
className={clsx("tournament-bracket__no-screen", {
"tournament-bracket__no-screen__banned": banned,
})}
data-testid={`screen-${banned ? "banned" : "allowed"}`}
>
{banned ? <CrossIcon /> : <CheckmarkIcon />}
<Image
path={specialWeaponImageUrl(SPLATTERCOLOR_SCREEN_ID)}
width={24}
height={24}
alt={t(`weapons:SPECIAL_${SPLATTERCOLOR_SCREEN_ID}`)}
/>
</div>
);
}

View File

@@ -27,6 +27,7 @@ const createTeam = (teamId: number, userIds: number[]): TournamentDataTeam => ({
})),
name: "Team " + teamId,
prefersNotToHost: 0,
noScreen: 0,
seed: 1,
});

View File

@@ -2345,6 +2345,7 @@ export const PADDLING_POOL_257 = () =>
name: "Le classique à Cam",
seed: 1,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709743534,
members: [
@@ -2447,6 +2448,7 @@ export const PADDLING_POOL_257 = () =>
name: "New Generation",
seed: 2,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709737918,
members: [
@@ -2561,6 +2563,7 @@ export const PADDLING_POOL_257 = () =>
name: "Mafia mbappe",
seed: 3,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709743523,
members: [
@@ -2663,6 +2666,7 @@ export const PADDLING_POOL_257 = () =>
name: "better gaming chair",
seed: 4,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709743262,
members: [
@@ -2765,6 +2769,7 @@ export const PADDLING_POOL_257 = () =>
name: "Seaya",
seed: 5,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709741396,
members: [
@@ -2879,6 +2884,7 @@ export const PADDLING_POOL_257 = () =>
name: "NEVER BACK DOWN NEVER WHAT?",
seed: 6,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709711811,
members: [
@@ -2993,6 +2999,7 @@ export const PADDLING_POOL_257 = () =>
name: "Hazard",
seed: 7,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709738831,
members: [
@@ -3107,6 +3114,7 @@ export const PADDLING_POOL_257 = () =>
name: "ASC Shokkai ",
seed: 8,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709737837,
members: [
@@ -3209,6 +3217,7 @@ export const PADDLING_POOL_257 = () =>
name: "Naw, I’d win",
seed: 9,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709741719,
members: [
@@ -3335,6 +3344,7 @@ export const PADDLING_POOL_257 = () =>
name: "Chippeur arrête de Chipper",
seed: 10,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709730354,
members: [
@@ -3449,6 +3459,7 @@ export const PADDLING_POOL_257 = () =>
name: "There’s a snake in my boot 🐍",
seed: 11,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709745630,
members: [
@@ -3689,6 +3700,7 @@ export const PADDLING_POOL_257 = () =>
name: "ASC Niji",
seed: 13,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709723749,
members: [
@@ -3803,6 +3815,7 @@ export const PADDLING_POOL_257 = () =>
name: "Smoking Moais ",
seed: 14,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709668399,
members: [
@@ -3929,6 +3942,7 @@ export const PADDLING_POOL_257 = () =>
name: "SAN DIMAS HS FOOTBALL RULES!",
seed: 15,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709735267,
members: [
@@ -4035,6 +4049,7 @@ export const PADDLING_POOL_257 = () =>
name: "Pickup oder so ig",
seed: 16,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709745849,
members: [
@@ -4141,6 +4156,7 @@ export const PADDLING_POOL_257 = () =>
name: "DistInkt",
seed: 17,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709742258,
members: [
@@ -4369,6 +4385,7 @@ export const PADDLING_POOL_257 = () =>
name: "Blaze",
seed: 19,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709746054,
members: [
@@ -4577,6 +4594,7 @@ export const PADDLING_POOL_257 = () =>
name: "Squid Emoji",
seed: 21,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709728278,
members: [
@@ -4679,6 +4697,7 @@ export const PADDLING_POOL_257 = () =>
name: "Müll🚮",
seed: 22,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709715006,
members: [
@@ -4781,6 +4800,7 @@ export const PADDLING_POOL_257 = () =>
name: "Rogueport Rascals",
seed: 23,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709660578,
members: [
@@ -4887,6 +4907,7 @@ export const PADDLING_POOL_257 = () =>
name: "Shade",
seed: 24,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709721869,
members: [
@@ -5111,6 +5132,7 @@ export const PADDLING_POOL_257 = () =>
name: "Second Try",
seed: 26,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709738747,
members: [
@@ -5229,6 +5251,7 @@ export const PADDLING_POOL_257 = () =>
name: "1HP",
seed: 27,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709626047,
members: [
@@ -5343,6 +5366,7 @@ export const PADDLING_POOL_257 = () =>
name: "Préférence Pêche ",
seed: 28,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709727951,
members: [
@@ -5445,6 +5469,7 @@ export const PADDLING_POOL_257 = () =>
name: "AquaSonix",
seed: 29,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709741482,
members: [
@@ -5677,6 +5702,7 @@ export const PADDLING_POOL_257 = () =>
name: "Intrusive thoughts ",
seed: 31,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709726536,
members: [
@@ -5779,6 +5805,7 @@ export const PADDLING_POOL_257 = () =>
name: "Heaven sent Lunatics",
seed: 32,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709558706,
members: [
@@ -5885,6 +5912,7 @@ export const PADDLING_POOL_257 = () =>
name: "<_>Placeholder",
seed: 33,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709744323,
members: [
@@ -6003,6 +6031,7 @@ export const PADDLING_POOL_257 = () =>
name: "Big Tommy and the Flops",
seed: 34,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709677397,
members: [
@@ -6105,6 +6134,7 @@ export const PADDLING_POOL_257 = () =>
name: "G Gaming Gaming",
seed: 35,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1709618711,
members: [
@@ -8199,6 +8229,7 @@ export const PADDLING_POOL_255 = () =>
name: "Enperries 200p",
seed: 2,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708535137,
members: [
@@ -8301,6 +8332,7 @@ export const PADDLING_POOL_255 = () =>
name: "allo kayora ?",
seed: 3,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708533764,
members: [
@@ -8529,6 +8561,7 @@ export const PADDLING_POOL_255 = () =>
name: "Rule them",
seed: 5,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708533309,
members: [
@@ -8631,6 +8664,7 @@ export const PADDLING_POOL_255 = () =>
name: "NEVER BACK DOWN NEVER WHAT",
seed: 6,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708430641,
members: [
@@ -8745,6 +8779,7 @@ export const PADDLING_POOL_255 = () =>
name: "iPad jaune",
seed: 7,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708536306,
members: [
@@ -8949,6 +8984,7 @@ export const PADDLING_POOL_255 = () =>
name: "Hazard",
seed: 9,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708506060,
members: [
@@ -9075,6 +9111,7 @@ export const PADDLING_POOL_255 = () =>
name: "ASC Shokkai ",
seed: 10,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708526814,
members: [
@@ -9291,6 +9328,7 @@ export const PADDLING_POOL_255 = () =>
name: "Smoking Moais ",
seed: 12,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708377426,
members: [
@@ -9531,6 +9569,7 @@ export const PADDLING_POOL_255 = () =>
name: "https://youtu.be/Euq7uTeYCP0?si=",
seed: 14,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708532602,
members: [
@@ -9633,6 +9672,7 @@ export const PADDLING_POOL_255 = () =>
name: "Gambawaffeln",
seed: 15,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708535205,
members: [
@@ -9747,6 +9787,7 @@ export const PADDLING_POOL_255 = () =>
name: "ici ça bzzz",
seed: 16,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708515945,
members: [
@@ -9849,6 +9890,7 @@ export const PADDLING_POOL_255 = () =>
name: "Amoura",
seed: 17,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708453334,
members: [
@@ -10065,6 +10107,7 @@ export const PADDLING_POOL_255 = () =>
name: "Grandma Sicko Mode",
seed: 19,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708375443,
members: [
@@ -10179,6 +10222,7 @@ export const PADDLING_POOL_255 = () =>
name: "youtube.com/watch?v=dQw4w9WgXcQ",
seed: 20,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708532665,
members: [
@@ -10285,6 +10329,7 @@ export const PADDLING_POOL_255 = () =>
name: "Müll🚮",
seed: 21,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708364254,
members: [
@@ -10403,6 +10448,7 @@ export const PADDLING_POOL_255 = () =>
name: "Hisense RL170D4BWE Freestanding ",
seed: 22,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708464101,
members: [
@@ -10635,6 +10681,7 @@ export const PADDLING_POOL_255 = () =>
name: "Blaze",
seed: 24,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708535804,
members: [
@@ -10737,6 +10784,7 @@ export const PADDLING_POOL_255 = () =>
name: "Squid Emoji",
seed: 25,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708535891,
members: [
@@ -10851,6 +10899,7 @@ export const PADDLING_POOL_255 = () =>
name: "DistInkt",
seed: 26,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708521749,
members: [
@@ -10965,6 +11014,7 @@ export const PADDLING_POOL_255 = () =>
name: "We Are Innocent Caterpillars",
seed: 27,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708536584,
members: [
@@ -11067,6 +11117,7 @@ export const PADDLING_POOL_255 = () =>
name: "Ink Souls Maria",
seed: 28,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708537772,
members: [
@@ -11197,6 +11248,7 @@ export const PADDLING_POOL_255 = () =>
name: "Yoghurt Party",
seed: 29,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708379916,
members: [
@@ -11311,6 +11363,7 @@ export const PADDLING_POOL_255 = () =>
name: "Second Try",
seed: 30,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708519753,
members: [
@@ -11429,6 +11482,7 @@ export const PADDLING_POOL_255 = () =>
name: "ASC Niji~K",
seed: 31,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708534312,
members: [
@@ -11649,6 +11703,7 @@ export const PADDLING_POOL_255 = () =>
name: "Stream easy by lesserafim",
seed: 33,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708477155,
members: [
@@ -11755,6 +11810,7 @@ export const PADDLING_POOL_255 = () =>
name: "Bloody Wave",
seed: 34,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708531564,
members: [
@@ -11897,6 +11953,7 @@ export const PADDLING_POOL_255 = () =>
name: "Fresh takos ",
seed: 35,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1708503356,
members: [
@@ -14157,6 +14214,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Starburst",
seed: 1,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707443313,
members: [
@@ -14247,6 +14305,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Jackpot",
seed: 2,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707366405,
members: [
@@ -14337,6 +14396,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Grougrou ",
seed: 3,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1706912643,
members: [
@@ -14427,6 +14487,7 @@ export const IN_THE_ZONE_32 = () =>
name: "atomic bomb ",
seed: 4,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707359335,
members: [
@@ -14541,6 +14602,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Celeste",
seed: 5,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707171426,
members: [
@@ -14643,6 +14705,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Moonlight",
seed: 6,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707342696,
members: [
@@ -14745,6 +14808,7 @@ export const IN_THE_ZONE_32 = () =>
name: "BEt",
seed: 7,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707513942,
members: [
@@ -14859,6 +14923,7 @@ export const IN_THE_ZONE_32 = () =>
name: "As you wish",
seed: 8,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707526815,
members: [
@@ -14973,6 +15038,7 @@ export const IN_THE_ZONE_32 = () =>
name: "UK MAFIA",
seed: 9,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707583385,
members: [
@@ -15063,6 +15129,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Black Lotus ",
seed: 10,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707486395,
members: [
@@ -15153,6 +15220,7 @@ export const IN_THE_ZONE_32 = () =>
name: "ASC Tenshi",
seed: 11,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707513290,
members: [
@@ -15243,6 +15311,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Hypernova",
seed: 12,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707531084,
members: [
@@ -15333,6 +15402,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Zenith",
seed: 13,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707568466,
members: [
@@ -15435,6 +15505,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Yaotl Teotl",
seed: 14,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707481625,
members: [
@@ -15525,6 +15596,7 @@ export const IN_THE_ZONE_32 = () =>
name: "FOAMS 34",
seed: 15,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707530166,
members: [
@@ -15615,6 +15687,7 @@ export const IN_THE_ZONE_32 = () =>
name: "New Generation ",
seed: 16,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707181792,
members: [
@@ -15717,6 +15790,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Gen BOB Ten-Piece Chicken Nugget",
seed: 17,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707550321,
members: [
@@ -15823,6 +15897,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Joga Bonito",
seed: 18,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707575096,
members: [
@@ -15925,6 +16000,7 @@ export const IN_THE_ZONE_32 = () =>
name: "JumpingCatapult ",
seed: 19,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707569490,
members: [
@@ -16039,6 +16115,7 @@ export const IN_THE_ZONE_32 = () =>
name: "metal pipe",
seed: 20,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707537425,
members: [
@@ -16129,6 +16206,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Gentlemates",
seed: 21,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707564691,
members: [
@@ -16247,6 +16325,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Hades",
seed: 22,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707145818,
members: [
@@ -16344,6 +16423,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Hazard",
seed: 23,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707558330,
members: [
@@ -16434,6 +16514,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Reputation (Taylor's Version)",
seed: 24,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707586842,
members: [
@@ -16524,6 +16605,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Smoking Moais ",
seed: 25,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707583597,
members: [
@@ -16638,6 +16720,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Zoneando",
seed: 26,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707429804,
members: [
@@ -16740,6 +16823,7 @@ export const IN_THE_ZONE_32 = () =>
name: "OVERTIME!!",
seed: 27,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707539973,
members: [
@@ -16846,6 +16930,7 @@ export const IN_THE_ZONE_32 = () =>
name: "11:11; Make a Wish",
seed: 28,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707507831,
members: [
@@ -16948,6 +17033,7 @@ export const IN_THE_ZONE_32 = () =>
name: "delulu ",
seed: 29,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707586297,
members: [
@@ -17164,6 +17250,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Peaky P-Key ",
seed: 31,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707578076,
members: [
@@ -17360,6 +17447,7 @@ export const IN_THE_ZONE_32 = () =>
name: "all my homie hate pencil ",
seed: 33,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707575330,
members: [
@@ -17462,6 +17550,7 @@ export const IN_THE_ZONE_32 = () =>
name: "Whaa",
seed: 34,
prefersNotToHost: 0,
noScreen: 0,
inviteCode: null,
createdAt: 1707527645,
members: [

View File

@@ -16,6 +16,7 @@ const tournamentCtxTeam = (
members: [],
name: "Team " + teamId,
prefersNotToHost: 0,
noScreen: 0,
seed: teamId + 1,
...partial,
};

View File

@@ -114,6 +114,20 @@
}
}
.tournament-bracket__no-screen {
display: flex;
gap: var(--s-0-5);
}
.tournament-bracket__no-screen > svg {
width: 24px;
fill: var(--theme-success);
}
.tournament-bracket__no-screen__banned > svg {
fill: var(--theme-error);
}
.tournament-bracket__during-match-actions {
display: grid;
grid-template-areas:

View File

@@ -68,6 +68,7 @@ export async function findById(id: number) {
"TournamentTeam.name",
"TournamentTeam.seed",
"TournamentTeam.prefersNotToHost",
"TournamentTeam.noScreen",
"TournamentTeam.inviteCode",
"TournamentTeam.createdAt",
jsonArrayFrom(

View File

@@ -8,12 +8,14 @@ const createTeamStm = sql.prepare(/*sql*/ `
"tournamentId",
"inviteCode",
"name",
"prefersNotToHost"
"prefersNotToHost",
"noScreen"
) values (
@tournamentId,
@inviteCode,
@name,
@prefersNotToHost
@prefersNotToHost,
@noScreen
) returning *
`);
@@ -35,17 +37,20 @@ export const createTeam = sql.transaction(
name,
ownerId,
prefersNotToHost,
noScreen,
}: {
tournamentId: TournamentTeam["tournamentId"];
name: TournamentTeam["name"];
ownerId: User["id"];
prefersNotToHost: TournamentTeam["prefersNotToHost"];
noScreen: number;
}) => {
const team = createTeamStm.get({
tournamentId,
name,
inviteCode: nanoid(INVITE_CODE_LENGTH),
prefersNotToHost,
noScreen,
}) as TournamentTeam;
createMemberStm.run({ tournamentTeamId: team.id, userId: ownerId });

View File

@@ -6,7 +6,8 @@ const stm = sql.prepare(/*sql*/ `
"TournamentTeam"
set
"name" = @name,
"prefersNotToHost" = @prefersNotToHost
"prefersNotToHost" = @prefersNotToHost,
"noScreen" = @noScreen
where
"id" = @id
`);
@@ -15,14 +16,17 @@ export function updateTeamInfo({
id,
name,
prefersNotToHost,
noScreen,
}: {
id: TournamentTeam["id"];
name: TournamentTeam["name"];
prefersNotToHost: TournamentTeam["prefersNotToHost"];
noScreen: number;
}) {
stm.run({
id,
name,
prefersNotToHost,
noScreen,
});
}

View File

@@ -71,6 +71,7 @@ export const action: ActionFunction = async ({ request, params }) => {
tournamentId: tournamentId,
ownerId: data.userId,
prefersNotToHost: 0,
noScreen: 0,
});
break;

View File

@@ -119,6 +119,7 @@ export const action: ActionFunction = async ({ request, params }) => {
name: data.teamName,
id: ownTeam.id,
prefersNotToHost: booleanToInt(data.prefersNotToHost),
noScreen: booleanToInt(data.noScreen),
});
} else {
validate(!HACKY_isInviteOnlyEvent(event), "Event is invite only");
@@ -136,6 +137,7 @@ export const action: ActionFunction = async ({ request, params }) => {
tournamentId: tournamentId,
ownerId: user.id,
prefersNotToHost: booleanToInt(data.prefersNotToHost),
noScreen: booleanToInt(data.noScreen),
});
}
break;
@@ -387,6 +389,7 @@ function RegistrationForms() {
<TeamInfo
name={ownTeam?.name}
prefersNotToHost={ownTeam?.prefersNotToHost}
noScreen={ownTeam?.noScreen}
canUnregister={Boolean(ownTeam && !ownTeamCheckedIn)}
/>
) : null}
@@ -579,14 +582,17 @@ function CheckIn({
function TeamInfo({
name,
prefersNotToHost = 0,
noScreen = 0,
canUnregister,
}: {
name?: string;
prefersNotToHost?: number;
noScreen?: number;
canUnregister: boolean;
}) {
const { t } = useTranslation(["tournament", "common"]);
const fetcher = useFetcher();
const tournament = useTournament();
return (
<div>
@@ -624,7 +630,7 @@ function TeamInfo({
defaultValue={name ?? undefined}
/>
</div>
<div>
<div className="stack sm">
<div className="text-lighter text-sm stack horizontal sm items-center">
<input
id="no-host"
@@ -636,6 +642,21 @@ function TeamInfo({
{t("tournament:pre.info.noHost")}
</label>
</div>
{tournament.ctx.settings.enableNoScreenToggle ? (
<div className="text-lighter text-sm stack horizontal sm items-center">
<input
id="no-screen"
type="checkbox"
name="noScreen"
defaultChecked={Boolean(noScreen)}
data-testid="no-screen-checkbox"
/>
<label htmlFor="no-screen" className="mb-0">
{t("tournament:pre.info.noScreen")}
</label>
</div>
) : null}
</div>
</div>
<SubmitButton

View File

@@ -15,6 +15,7 @@ export const registerSchema = z.union([
_action: _action("UPSERT_TEAM"),
teamName: z.string().min(1).max(TOURNAMENT.TEAM_NAME_MAX_LENGTH),
prefersNotToHost: z.preprocess(checkboxValueToBoolean, z.boolean()),
noScreen: z.preprocess(checkboxValueToBoolean, z.boolean()),
}),
z.object({
_action: _action("UPDATE_MAP_POOL"),

View File

@@ -12,6 +12,7 @@ import {
tournamentAdminPage,
tournamentBracketsPage,
tournamentPage,
tournamentRegisterPage,
userResultsPage,
} from "~/utils/urls";
import { startBracket } from "./shared";
@@ -616,4 +617,30 @@ test.describe("Tournament bracket", () => {
// bye is gone
await expect(page.locator('[data-match-id="1"]')).toBeVisible();
});
test("tournament no screen toggle works", async ({ page }) => {
const tournamentId = 4;
await seed(page);
await impersonate(page);
await navigate({
page,
url: tournamentRegisterPage(tournamentId),
});
await page.getByTestId("no-screen-checkbox").click();
await page.getByTestId("save-team-button").click();
await page.getByTestId("brackets-tab").click();
await page.getByTestId("finalize-bracket-button").click();
await page.getByTestId("confirm-finalize-bracket-button").click();
await page.locator('[data-match-id="7"]').click();
await expect(page.getByTestId("screen-allowed")).toBeVisible();
await backToBracket(page);
await page.locator('[data-match-id="8"]').click();
await expect(page.getByTestId("screen-banned")).toBeVisible();
});
});

View File

@@ -28,6 +28,7 @@
"pre.info.unregister": "Unregister",
"pre.info.unregister.confirm": "Unregister from the tournament and delete team info?",
"pre.info.noHost": "My team prefers not to host rooms",
"pre.info.noScreen": "My team prefers to avoid Splattercolor Screen",
"pre.roster.header": "Fill roster",
"pre.roster.footer": "At least {{atLeastCount}} members are required to participate. Max roster size is {{maxCount}}",

View File

@@ -0,0 +1,5 @@
export function up(db) {
db.prepare(
/* sql */ `alter table "TournamentTeam" add "noScreen" integer not null default 0`,
).run();
}