{"release_id":"01a1c502-4ad1-0000-ec62-adc54d3c69aa","chunk_id":"01a1c502-4c4d-7311-8433-ddcb4b09750e","file":"emW1WNeF.mjs","mappings":"wVAUO,MAAMA,EAAyB,CAAC,cAAe,UAAW,MAAO,OAAO,EAGlEC,EAAiC,CAAC,cAAe,MAAO,OAAO,EAE/DC,EAA8B,cAWpC,SAASC,EAAiBC,EAA0B,CAC1D,OAAOJ,EAAW,SAASI,CAAiB,EAAKA,EAAqBF,CACvE,CA4DO,SAASG,EAAmBD,EAA4B,CAC9D,OAAOA,IAAU,OAASA,IAAU,MAAQA,EAAQ,KACrD,CAKO,MAAME,EAA0C,CAAC,MAAO,MAAO,MAAO,KAAK,EAY5EC,EAAgD,CACrD,IAAKC,EAAkB,IACvB,MAAOA,EAAkB,KAC1B,EAGO,SAASC,EAAcC,EAAgBC,EAAkC,CAC/E,MAAMC,EAAOL,EAAWG,CAAI,EACtBG,EAA2B,GACjC,GAAID,QAAa,GAAGA,CAAI,QACxB,GAAIF,IAASR,EAAmB,OAAOW,EAAK,MAAMA,CAAE,GAAK,KACzD,MAAMC,EAAM,IAAI,gBAAgBH,CAAM,EACtC,OAAAG,EAAI,IAAI,OAAQJ,CAAI,EACb,MAAMI,EAAI,SAAA,CAAU,EAC5B","names":["BEAT_KINDS","VISIBLE_BEAT_KINDS","DEFAULT_BEAT_KIND","sanitizeBeatKind","input","sanitizeBeatFormat","BEAT_FORMAT_FILTERS","KIND_LOBBY","RATE_SUBJECT_PATH","beatLobbyHref","kind","params","page","qs","all"],"sources":["../../../../../../src/lib/types/beat.ts"],"sourcesContent":["// RAT-380: beat me category split. A challenge's `kind` discriminator —\n// `cockcompare` is the classic 1v1 (default for every existing + new row);\n// `cumshot` is the second category. Client-safe (no server imports) so the\n// upload/lobby Svelte and the server `beat.ts` share one source of truth,\n// mirroring how `arena.ts` carries its categories.\n\nimport { RATE_SUBJECT_PATH } from '$lib/rate-subjects';\n\nexport type BeatKind = 'cockcompare' | 'cumshot' | 'ass' | 'boobs';\n\nexport const BEAT_KINDS: BeatKind[] = ['cockcompare', 'cumshot', 'ass', 'boobs'];\n\n// The categories the lobby switcher shows, in order. `cumshot` stays hidden.\nexport const VISIBLE_BEAT_KINDS: BeatKind[] = ['cockcompare', 'ass', 'boobs'];\n\nexport const DEFAULT_BEAT_KIND: BeatKind = 'cockcompare';\n\nexport const BEAT_KIND_LABELS: Record<BeatKind, string> = {\n\tcockcompare: 'cock compare',\n\tcumshot: 'cumshot',\n\tass: 'ass',\n\tboobs: 'boobs'\n};\n\n/** Coerce untrusted input (upload form field) to a valid kind. Falls back to\n *  the default (`cockcompare`) on anything unrecognised. */\nexport function sanitizeBeatKind(input: unknown): BeatKind {\n\treturn BEAT_KINDS.includes(input as BeatKind) ? (input as BeatKind) : DEFAULT_BEAT_KIND;\n}\n\n// The lobby filter adds an \"all\" pseudo-value on top of the real kinds.\nexport type BeatKindFilter = 'all' | BeatKind;\n\nexport const BEAT_KIND_FILTERS: BeatKindFilter[] = ['all', ...BEAT_KINDS];\n\nexport const BEAT_KIND_FILTER_LABELS: Record<BeatKindFilter, string> = {\n\tall: 'all',\n\tcockcompare: 'cock compare',\n\tcumshot: 'cumshot',\n\tass: 'ass',\n\tboobs: 'boobs'\n};\n\n/** Parse the lobby's `?kind=` param. A real kind narrows the feed; `all`\n *  means no filter; anything else (incl. a missing param) → `fallback`. */\nexport function parseBeatKindFilter(input: unknown, fallback: BeatKindFilter = 'all'): BeatKindFilter {\n\tif (input === 'all') return 'all';\n\tif (BEAT_KINDS.includes(input as BeatKind)) return input as BeatKind;\n\treturn fallback;\n}\n\n// ─── RAT-419: match format (1v1 / team battles) ──────────────────────────────\n// Orthogonal to `kind` — a match has both a category (kind) and a format. '1v1'\n// is the classic path (creator + accepter on the challenge row); '2v2' / '4v4'\n// are team battles routed through beat_participant. Client-safe so the create\n// form, lobby, and server share one source of truth.\n\nexport type BeatFormat = '1v1' | '2v2' | '4v4';\n\nexport const BEAT_FORMATS: BeatFormat[] = ['1v1', '2v2', '4v4'];\n\nexport const DEFAULT_BEAT_FORMAT: BeatFormat = '1v1';\n\nexport const BEAT_FORMAT_LABELS: Record<BeatFormat, string> = {\n\t'1v1': '1v1',\n\t'2v2': '2v2',\n\t'4v4': '4v4'\n};\n\n/** People on EACH team for a format. 1v1 → 1, 2v2 → 2, 4v4 → 4. */\nexport function beatTeamSize(format: BeatFormat): number {\n\treturn format === '4v4' ? 4 : format === '2v2' ? 2 : 1;\n}\n\n/** How many beat_participant (JOINER) rows a full team roster needs. The creator\n *  is implicit team 'a' slot 0, so it's (teamSize - 1) more on 'a' plus teamSize\n *  on 'b' = teamSize*2 - 1. 1v1 → 1 (but 1v1 never uses beat_participant). */\nexport function beatMaxEntries(format: BeatFormat): number {\n\treturn beatTeamSize(format) * 2 - 1;\n}\n\n/** True for the team battle formats (everything but 1v1). */\nexport function isBeatTeamFormat(format: BeatFormat): boolean {\n\treturn format === '2v2' || format === '4v4';\n}\n\n/** Coerce untrusted input (create form field) to a valid format. Falls back to\n *  the default ('1v1') on anything unrecognised. */\nexport function sanitizeBeatFormat(input: unknown): BeatFormat {\n\treturn input === '2v2' || input === '4v4' ? input : '1v1';\n}\n\n// The lobby filter adds an \"all\" pseudo-value on top of the real formats.\nexport type BeatFormatFilter = 'all' | BeatFormat;\n\nexport const BEAT_FORMAT_FILTERS: BeatFormatFilter[] = ['all', '1v1', '2v2', '4v4'];\n\n/** Parse the lobby's `?format=` param. `all` (or anything unknown) → 'all' (no\n *  filter); only the three real formats narrow the feed. */\nexport function parseBeatFormatFilter(input: unknown): BeatFormatFilter {\n\treturn input === '1v1' || input === '2v2' || input === '4v4' ? input : 'all';\n}\n\n// ─── Epic R: where a category's lobby lives ──────────────────────────────────\n// The ass and boobs lobbies moved onto their AI rater's page (/rate-my-ass,\n// /rate-my-boobs), under #beat; the dick lobby and the hidden cumshot one stay\n// on /b. Every \"back to the lobby\" link goes through here.\nconst KIND_LOBBY: Partial<Record<BeatKind, string>> = {\n\tass: RATE_SUBJECT_PATH.ass,\n\tboobs: RATE_SUBJECT_PATH.boobs\n};\n\n/** The lobby of `kind`, with any query (sort, filters) kept. */\nexport function beatLobbyHref(kind: BeatKind, params?: URLSearchParams): string {\n\tconst page = KIND_LOBBY[kind];\n\tconst qs = params?.toString() ?? '';\n\tif (page) return `${page}${qs ? `?${qs}` : ''}#beat`;\n\tif (kind === DEFAULT_BEAT_KIND) return qs ? `/b?${qs}` : '/b';\n\tconst all = new URLSearchParams(params);\n\tall.set('kind', kind);\n\treturn `/b?${all.toString()}`;\n}\n"],"version":3}