import type { BalanceCandidate, Bracket, MixEvent, Player, Registration, Series, Session, Team, } from './client' import type { RankOrdinal } from '../ranks' // Fixtures keep local development and visual review useful without a backend. // Production builds always use the real API. export const demoMode = import.meta.env.DEV && import.meta.env.VITE_DEMO_MODE !== 'false' const now = new Date() const daysFromNow = (days: number, hour = 19) => { const date = new Date(now) date.setDate(date.getDate() + days) date.setHours(hour, 0, 0, 0) return date.toISOString() } const makePlayer = ( id: string, displayName: string, tank: RankOrdinal, damage: RankOrdinal, support: RankOrdinal, ): Player => ({ id, displayName, battleTag: `${displayName.replace(/\s/g, '')}#${1000 + Number(id.replace(/\D/g, '') || 0)}`, ratings: { tank, damage, support, updatedAt: daysFromNow(-4) }, preferredRoles: tank >= damage && tank >= support ? ['tank'] : damage >= support ? ['damage'] : ['support'], preferredPlayerIds: [], }) export const demoProfile: Player = { ...makePlayer('p1', 'Lemintare', 30, 33, 27), preferredRoles: ['damage', 'tank'], preferredPlayerIds: ['p2', 'p5'], } export const demoSession: Session = { account: { id: 'account-1', discordId: '125661705720381444', displayName: 'Lemintare', role: 'admin', }, player: demoProfile, } export const demoEvents: MixEvent[] = [ { id: 'event-1', title: 'Saturday Night Scrim', description: 'Community draft night · 4 teams · Bo3 single elimination', startsAt: daysFromNow(2), endsAt: daysFromNow(2, 23), registrationDeadline: daysFromNow(1, 21), status: 'registration', rulesetName: 'Community Bo3 v2', counts: { going: 18, maybe: 4, not_going: 3 }, myRsvp: 'going', }, { id: 'event-2', title: 'Midweek Mix', description: 'Fast queue with two balanced teams', startsAt: daysFromNow(5), endsAt: daysFromNow(5, 23), registrationDeadline: daysFromNow(4), status: 'registration', rulesetName: 'Quick Mix v1', counts: { going: 9, maybe: 6, not_going: 2 }, myRsvp: 'maybe', }, { id: 'event-3', title: 'Summer Clash #4', description: 'Live playoff bracket', startsAt: daysFromNow(0, 20), endsAt: daysFromNow(1, 1), registrationDeadline: daysFromNow(-1), status: 'live', rulesetName: 'Tournament Bo3 v2', counts: { going: 22, maybe: 0, not_going: 4 }, myRsvp: 'going', }, ] const players = [ demoProfile, makePlayer('p2', 'Nova', 36, 28, 29), makePlayer('p3', 'Kairo', 24, 35, 26), makePlayer('p4', 'MercyMain', 18, 27, 37), makePlayer('p5', 'Pulse', 25, 34, 29), makePlayer('p6', 'Astra', 31, 25, 36), makePlayer('p7', 'Hex', 35, 29, 23), makePlayer('p8', 'Orbit', 22, 34, 30), makePlayer('p9', 'Miko', 27, 30, 36), makePlayer('p10', 'Rook', 37, 26, 24), makePlayer('p11', 'Echo', 26, 32, 31), makePlayer('p12', 'Zenith', 28, 30, 35), ] players[1].preferredPlayerIds = ['p1'] players[4].preferredPlayerIds = ['p1'] export const demoRegistrations: Registration[] = players.map((player, index) => ({ id: `reg-${index + 1}`, player, status: index < 9 ? 'going' : index < 11 ? 'maybe' : 'not_going', updatedAt: daysFromNow(-(index % 4)), changedBy: index === 4 ? { id: 'account-1', displayName: 'Lemintare', source: 'admin' } : { id: player.id, displayName: player.displayName, source: 'self' }, })) const alpha: Team = { id: 'team-alpha', name: 'Ember Wolves', side: 'alpha', captainId: 'p2', averageRating: 35.6, members: [ { player: players[1], assignedRole: 'tank' }, { player: players[2], assignedRole: 'damage' }, { player: players[4], assignedRole: 'damage' }, { player: players[3], assignedRole: 'support' }, { player: players[5], assignedRole: 'support' }, ], } const beta: Team = { id: 'team-beta', name: 'Azure Phantoms', side: 'beta', captainId: 'p7', averageRating: 34.4, members: [ { player: players[6], assignedRole: 'tank' }, { player: players[7], assignedRole: 'damage' }, { player: players[10], assignedRole: 'damage' }, { player: players[8], assignedRole: 'support' }, { player: players[11], assignedRole: 'support' }, ], } export const demoBalanceCandidates: BalanceCandidate[] = [ { id: 'candidate-1', score: 4, teams: [alpha, beta], reserve: [players[0], players[9]], explanations: ['9 preferred role assignments', '2 preferred teammate pairs kept together'], }, { id: 'candidate-2', score: 9, teams: [ { ...alpha, averageRating: 35.2 }, { ...beta, averageRating: 34.6 }, ], reserve: [players[0], players[9]], explanations: ['8 preferred role assignments', '2 preferred teammate pairs kept together'], }, { id: 'candidate-3', score: 13, teams: [ { ...alpha, averageRating: 35.4 }, { ...beta, averageRating: 34.5 }, ], reserve: [players[0], players[9]], explanations: ['10 preferred role assignments', '1 preferred teammate pair kept together'], }, ] export const demoSeries: Series = { id: 'series-1', status: 'hero_draft', roundLabel: 'Semifinal 1', teamAlpha: alpha, teamBeta: beta, score: { alpha: 1, beta: 0 }, version: 12, currentStep: { title: 'Hero ban 2 of 4', instruction: 'Azure Phantoms choose a hero to remove for Map 2.', activeTeam: 'beta', kind: 'hero_ban', version: 12, }, options: [ { id: 'hero-1', name: 'Ana', role: 'support' }, { id: 'hero-2', name: 'Kiriko', role: 'support' }, { id: 'hero-3', name: 'Tracer', role: 'damage' }, { id: 'hero-4', name: 'Sojourn', role: 'damage' }, { id: 'hero-5', name: 'Winston', role: 'tank', disabled: true, disabledReason: 'Already banned by this team' }, { id: 'hero-6', name: 'Sigma', role: 'tank' }, ], maps: [ { number: 1, name: 'Lijiang Tower', mode: 'Control', status: 'completed', winner: 'alpha', heroBans: [ { hero: 'Sombra', team: 'alpha', role: 'damage' }, { hero: 'Winston', team: 'beta', role: 'tank' }, { hero: 'Ana', team: 'alpha', role: 'support' }, { hero: 'Tracer', team: 'beta', role: 'damage' }, ], }, { number: 2, name: 'King’s Row', mode: 'Hybrid', status: 'drafting', heroBans: [{ hero: 'D.Va', team: 'alpha', role: 'tank' }], }, { number: 3, name: 'TBD', mode: 'Control', status: 'ready', heroBans: [] }, ], audit: [ { id: 'a1', kind: 'coin_toss', summary: 'Ember Wolves won the toss', actorName: 'System', createdAt: daysFromNow(0, 20) }, { id: 'a2', kind: 'map_selected', summary: 'Lijiang Tower selected', actorName: 'Nova', createdAt: daysFromNow(0, 20) }, { id: 'a3', kind: 'result', summary: 'Map 1 won by Ember Wolves', actorName: 'Lemintare', createdAt: daysFromNow(0, 21) }, { id: 'a4', kind: 'map_selected', summary: 'King’s Row selected', actorName: 'Hex', createdAt: daysFromNow(0, 21) }, { id: 'a5', kind: 'hero_ban', summary: 'D.Va banned by Ember Wolves', actorName: 'Nova', createdAt: daysFromNow(0, 21) }, ], } export const demoBracket: Bracket = { id: 'bracket-1', title: 'Summer Clash #4', rounds: ['Semifinals', 'Grand Final'], matches: [ { id: 'm1', round: 0, slot: 0, label: 'Semifinal 1', teamAlpha: 'Ember Wolves', teamBeta: 'Azure Phantoms', scoreAlpha: 1, scoreBeta: 0, status: 'live', seriesId: 'series-1' }, { id: 'm2', round: 0, slot: 1, label: 'Semifinal 2', teamAlpha: 'Neon Foxes', teamBeta: 'Void Runners', scoreAlpha: 2, scoreBeta: 1, winner: 'alpha', status: 'completed', seriesId: 'series-2' }, { id: 'm3', round: 1, slot: 0, label: 'Grand Final', teamBeta: 'Neon Foxes', status: 'pending' }, ], }