{"release_id":"01a1998d-9802-0000-b0f7-33a23307f4ed","chunk_id":"01a1998d-992c-7590-86fb-8fd27175601b","file":"DJDb3rV3.mjs","mappings":"qTASO,MAAMA,EAAoB,GAKpBC,EAAsB,kCAGtBC,EAAqB,CAGjC,CAAE,OAAQ,EAAG,QAAS,EAAA,EACtB,CAAE,OAAQ,GAAI,QAAS,EAAA,EACvB,CAAE,OAAQ,GAAI,QAAS,GAAA,CACxB,EAGaC,EAA0BD,EAAmBA,EAAmB,OAAS,CAAC,EAAE,OAGjDA,EAAmBA,EAAmB,OAAS,CAAC,EAAE,QAmB1F,MAAME,EAAe,kDAGd,SAASC,EAAgBC,EAA6B,CAC5D,MAAMC,EAAIH,EAAa,KAAKE,CAAI,EAChC,OAAOC,EAAIA,EAAE,CAAC,EAAE,cAAgB,IACjC","names":["DUEL_FREE_CREATES","DUEL_LIMIT_HEADLINE","DUEL_FEATURE_TIERS","DUEL_FEATURE_CUSTOM_MIN","DUEL_LINK_RE","extractDuelCode","text","m"],"sources":["../../../../../../src/lib/duel-feature.ts"],"sourcesContent":["// Client-safe duel-featuring config + helpers. Lives in $lib (not $lib/server) so\n// both the create form and the chat link-nudge can import the tiers. The server\n// (tokens.ts) re-exports these so there's a single source of truth.\n\n/** RAT-569: duels a free account may CREATE, lifetime. From the next one on,\n *  creating needs Pro. Joining someone else's duel is never counted — that's\n *  the side new users come in through. Client-safe so the pricing perks, the\n *  /d hints and the walls all quote the same number the server enforces\n *  (getDuelCreateQuota). */\nexport const DUEL_FREE_CREATES = 10;\n\n/** The free-duel wall's headline, shared by every surface that shows it (/d,\n *  the rate result, the chat + menu) so the rule reads the same everywhere. The\n *  modal's perk list leads with \"unlimited duels\" right under it. */\nexport const DUEL_LIMIT_HEADLINE = `You've used your ${DUEL_FREE_CREATES} free duels.`;\n\n/** Three fixed tiers: token spend → minutes on the public /d board. */\nexport const DUEL_FEATURE_TIERS = [\n\t// 5-token floor bumped 10→30 min: a 10-min window left the board empty most\n\t// of the time (liquidity death spiral). 30 min keeps it populated.\n\t{ tokens: 5, minutes: 30 },\n\t{ tokens: 15, minutes: 60 },\n\t{ tokens: 30, minutes: 120 }\n] as const;\n\n/** Custom-spend floor = the top tier. Anything ≥ this is valid and ranks by amount. */\nexport const DUEL_FEATURE_CUSTOM_MIN = DUEL_FEATURE_TIERS[DUEL_FEATURE_TIERS.length - 1].tokens;\n\n/** Custom spend never buys more time than the top tier — it only buys rank. */\nexport const DUEL_FEATURE_MAX_MINUTES = DUEL_FEATURE_TIERS[DUEL_FEATURE_TIERS.length - 1].minutes;\n\n/**\n * Validate a featured-spend amount and resolve how long it keeps the duel on the\n * board. Valid amounts: an exact tier (5/15/30) → that tier's minutes, OR any\n * whole amount ≥ the top tier (30) → the top-tier duration (rank-only top-up).\n * Returns null for anything else (e.g. 7, 20, 0, fractional).\n */\nexport function resolveDuelFeatureMinutes(tokens: number): number | null {\n\tif (!Number.isInteger(tokens) || tokens <= 0) return null;\n\tconst tier = DUEL_FEATURE_TIERS.find((t) => t.tokens === tokens);\n\tif (tier) return tier.minutes;\n\tif (tokens >= DUEL_FEATURE_CUSTOM_MIN) return DUEL_FEATURE_MAX_MINUTES;\n\treturn null;\n}\n\n// Duel codes: 6 chars from ABCDEFGHJKLMNPQRSTUVWXYZ23456789 (no I/O/0/1), always\n// stored uppercase. Match a /d/<CODE> path inside any pasted URL (absolute or\n// relative), case-insensitively, then uppercase the capture.\nconst DUEL_LINK_RE = /\\/d\\/([abcdefghjklmnpqrstuvwxyz23456789]{6})\\b/i;\n\n/** Pull the first duel code out of a chat message, or null if there isn't one. */\nexport function extractDuelCode(text: string): string | null {\n\tconst m = DUEL_LINK_RE.exec(text);\n\treturn m ? m[1].toUpperCase() : null;\n}\n"],"version":3}