TypeScript 97.6%
SQL 1.4%
JavaScript 0.5%
1/**2 * Spinza economy constants. Everything here is fictional: Spinza Credits (SC)3 * have no monetary value, cannot be bought and cannot be withdrawn.4 */56export const CURRENCY_NAME = "Spinza Credits";7export const CURRENCY_SHORT = "SC";89/** Granted to every new account. */10export const STARTING_BALANCE = 10_000;1112/** Bet levels available in every game (games may restrict via minBet/maxBet). */13export const BET_LEVELS = [10, 20, 50, 100, 200, 500, 1_000] as const;14export const DEFAULT_MIN_BET = 10;15export const DEFAULT_MAX_BET = 1_000;1617/** Daily reward streak progression (index = streak day - 1). */18export const DAILY_REWARDS = [1_000, 1_250, 1_500, 1_750, 2_000, 2_500, 5_000] as const;19/** Missing more than this many days resets the streak. Missing one day soft-resets (goes back 2 steps). */20export const DAILY_STREAK_GRACE_DAYS = 1;2122/** Rescue credits for players who hit 0 SC. */23export const RESCUE_CREDITS_AMOUNT = 2_500;24export const RESCUE_CREDITS_COOLDOWN_HOURS = 12;25/** Balance under which rescue credits become available (0 = exactly zero). */26export const RESCUE_CREDITS_THRESHOLD = 0;2728/** Auto-spin counts. */29export const AUTO_SPIN_OPTIONS = [10, 25, 50, 100] as const;3031/** Win presentation classes, by multiplier of bet (inclusive lower bound). */32export const WIN_CLASSES = [33 { id: "legendary", label: "LEGENDARY WIN", min: 500 },34 { id: "epic", label: "EPIC WIN", min: 100 },35 { id: "mega", label: "MEGA WIN", min: 50 },36 { id: "big", label: "BIG WIN", min: 20 },37 { id: "win", label: "WIN", min: 5 },38] as const;3940export type WinClassId = (typeof WIN_CLASSES)[number]["id"] | "regular" | "none";4142export function classifyWin(multiplier: number): WinClassId {43 if (multiplier <= 0) return "none";44 for (const c of WIN_CLASSES) if (multiplier >= c.min) return c.id;45 return "regular";46}4748/** Session/break reminder options in minutes (0 = off). */49export const SESSION_REMINDER_OPTIONS = [0, 30, 60, 90, 120] as const;5051/** XP economy. */52export const XP_PER_SPIN = 2;53export const XP_PER_BONUS = 50;54export const XP_PER_NEW_GAME = 100;55export const MAX_LEVEL = 100;5657/** XP required to go from level L to L+1. Smooth curve, ~level 100 at ~1M XP. */58export function xpForLevel(level: number): number {59 return Math.round(100 * Math.pow(level, 1.55) + 200 * level);60}6162/** Cumulative XP threshold to reach `level` (level 1 = 0). */63export function xpThreshold(level: number): number {64 let total = 0;65 for (let l = 1; l < level; l++) total += xpForLevel(l);66 return total;67}6869export function levelForXp(xp: number): { level: number; current: number; next: number; progress: number } {70 let level = 1;71 let remaining = xp;72 while (level < MAX_LEVEL && remaining >= xpForLevel(level)) {73 remaining -= xpForLevel(level);74 level++;75 }76 const next = level >= MAX_LEVEL ? 0 : xpForLevel(level);77 return { level, current: remaining, next, progress: next ? remaining / next : 1 };78}7980/** Credits granted on level-up (fictional). */81export function levelUpReward(level: number): number {82 if (level % 25 === 0) return 25_000;83 if (level % 10 === 0) return 10_000;84 if (level % 5 === 0) return 4_000;85 return 1_000;86}8788export const RESERVED_USERNAMES = new Set([89 "admin", "administrator", "root", "system", "support", "spenza", "spinza", "staff", "moderator", "mod",90 "api", "www", "security", "help", "official", "team", "null", "undefined", "me", "you", "guest", "anonymous",91 "owner", "dev", "developer", "bot", "test", "info", "contact", "billing", "payments", "casino", "webmaster",92]);9394/** Small default profanity list — the admin can extend it via the `profanity_words` setting. */95export const DEFAULT_PROFANITY = [96 "fuck", "shit", "bitch", "cunt", "nigger", "nigga", "faggot", "retard", "whore", "slut", "dick", "cock", "pussy",97 "asshole", "nazi", "hitler", "rape", "kike", "spic", "chink",98];99100export const SESSION_COOKIE = "spinza_session";101export const ADMIN_COOKIE = "spinza_admin";102export const SESSION_TTL_DAYS = 30;103export const ADMIN_SESSION_TTL_HOURS = 12;104105export const ROUND_ID_PREFIX = "spz_rnd_";106export const RECOVERY_CODE_PREFIX = "SPZ";107108export const GAME_LIFECYCLE = ["draft", "simulation", "approved", "staging", "published", "disabled"] as const;109export type GameLifecycle = (typeof GAME_LIFECYCLE)[number];110111export const TRANSACTION_TYPES = [112 "INITIAL_GRANT",113 "BET",114 "WIN",115 "DAILY_REWARD",116 "ACHIEVEMENT",117 "MISSION",118 "LEVEL_UP",119 "RESCUE_CREDITS",120 "ADMIN_ADJUSTMENT",121] as const;122export type TransactionType = (typeof TRANSACTION_TYPES)[number];123