Refactor series handling in backend to include player context in Toss, Ban, Pick, and Record actions. Update service methods to accept player parameters, enhancing authorization checks and ensuring proper team actions. Modify integration tests to reflect new method signatures and improve tournament hydration logic in the store. Enhance frontend components to support new series features and improve user experience with live match navigation.
This commit is contained in:
@@ -82,6 +82,7 @@ export interface DraftAction {
|
||||
}
|
||||
export interface Series {
|
||||
id: string
|
||||
eventId: string
|
||||
tournamentId?: string
|
||||
status: 'scheduled' | 'coin_toss' | 'map_draft' | 'hero_draft' | 'playing' | 'completed'
|
||||
roundLabel: string
|
||||
@@ -97,6 +98,7 @@ export interface Series {
|
||||
version: number
|
||||
}
|
||||
options: DraftOption[]
|
||||
heroBanHistory: Record<TeamSide, string[]>
|
||||
maps: Array<{
|
||||
number: number
|
||||
name: string
|
||||
@@ -109,7 +111,7 @@ export interface Series {
|
||||
}
|
||||
export interface BracketMatch {
|
||||
id: string; round: number; slot: number; label: string
|
||||
teamAlpha?: string; teamBeta?: string; scoreAlpha?: number; scoreBeta?: number
|
||||
teamAlpha?: string; teamBeta?: string; teamAlphaId?: string; teamBetaId?: string; scoreAlpha?: number; scoreBeta?: number
|
||||
winner?: TeamSide; seriesId?: string; status: 'pending' | 'ready' | 'live' | 'completed'
|
||||
}
|
||||
export interface Bracket { id: string; title: string; rounds: string[]; matches: BracketMatch[] }
|
||||
@@ -164,6 +166,7 @@ export interface RawSeries {
|
||||
mapDraft?: { pool: string[] | null; banned: string[] | null; firstTeamId: string; teamIds: [string, string]; actions: RawDraftAction[] | null }
|
||||
heroDraft?: { heroes: Array<{ name: string; role: 'Tank' | 'Damage' | 'Support' }> | null; teamIds: [string, string]; firstTeamId: string; bansPerTeam: number; currentBans: RawDraftAction[] | null }
|
||||
currentMap: string; playedMaps: string[] | null; nextMapPickerId: string; availableMaps: string[] | null
|
||||
seriesBans?: Record<string, string[]> | null
|
||||
maps: Array<{ number: number; name: string; heroBans: RawDraftAction[] | null; result?: RawMapResult }> | null
|
||||
audit: Array<{ kind: DraftAction['kind']; summary: string; teamId?: string; actorAccountId: string; at: string }> | null
|
||||
results: RawMapResult[] | null; version: number
|
||||
@@ -345,10 +348,14 @@ export function adaptSeries(raw: RawSeries, teams: Team[] = []): Series {
|
||||
: phase === 'MapPick'
|
||||
? (raw.availableMaps ?? []).map((name) => ({ id: name, name }))
|
||||
: phase === 'HeroBan' && raw.heroDraft
|
||||
? (raw.heroDraft.heroes ?? []).filter((hero) => !(raw.heroDraft?.currentBans ?? []).some((ban) => ban.value === hero.name)).map((hero) => ({ id: hero.name, name: hero.name, role: roleFromRaw(hero.role) }))
|
||||
? (raw.heroDraft.heroes ?? []).filter((hero) => !(raw.heroDraft?.currentBans ?? []).some((ban) => ban.value === hero.name)).map((hero) => {
|
||||
const repeated = (raw.seriesBans?.[nextHeroTeam ?? ''] ?? []).includes(hero.name)
|
||||
return { id: hero.name, name: hero.name, role: roleFromRaw(hero.role), disabled: repeated, disabledReason: repeated ? 'Already banned by this team in this Bo3' : undefined }
|
||||
})
|
||||
: []
|
||||
return {
|
||||
id: raw.id,
|
||||
eventId: raw.eventId,
|
||||
tournamentId: raw.tournamentId,
|
||||
status,
|
||||
roundLabel: 'Tournament series',
|
||||
@@ -364,13 +371,20 @@ export function adaptSeries(raw: RawSeries, teams: Team[] = []): Series {
|
||||
version: raw.version,
|
||||
},
|
||||
options,
|
||||
heroBanHistory: {
|
||||
alpha: raw.seriesBans?.[raw.teamAId] ?? [],
|
||||
beta: raw.seriesBans?.[raw.teamBId] ?? [],
|
||||
},
|
||||
maps: (raw.maps ?? activeResults.map((result, index) => ({ number: index + 1, name: result.mapName, heroBans: [], result }))).map((map) => ({
|
||||
number: map.number,
|
||||
name: map.name,
|
||||
mode: 'Map',
|
||||
status: map.result ? 'completed' : phase === 'Playing' ? 'playing' : phase === 'HeroBan' ? 'ready' : 'drafting',
|
||||
winner: map.result ? (map.result.outcome === 'TeamAWin' ? 'alpha' : map.result.outcome === 'TeamBWin' ? 'beta' : 'draw') : undefined,
|
||||
heroBans: (map.heroBans ?? []).map((ban) => ({ hero: ban.value, team: ban.teamId === raw.teamAId ? 'alpha' : 'beta', role: 'damage' as PlayerRole })),
|
||||
heroBans: (map.heroBans ?? []).map((ban) => {
|
||||
const heroRole = raw.heroDraft?.heroes?.find((hero) => hero.name === ban.value)?.role
|
||||
return { hero: ban.value, team: ban.teamId === raw.teamAId ? 'alpha' : 'beta', role: heroRole ? roleFromRaw(heroRole) : 'damage' as PlayerRole }
|
||||
}),
|
||||
})),
|
||||
audit: (raw.audit ?? []).map((action, index) => ({ id: `action-${index}`, kind: action.kind, summary: action.summary, actorName: action.actorAccountId, createdAt: action.at })),
|
||||
}
|
||||
@@ -390,11 +404,13 @@ export function adaptTournament(raw: RawTournament, teams: Team[] = []): Bracket
|
||||
label: `Match ${slot + 1}`,
|
||||
teamAlpha: names.get(series.teamAId) ?? (series.teamAId || undefined),
|
||||
teamBeta: names.get(series.teamBId) ?? (series.teamBId || undefined),
|
||||
teamAlphaId: series.teamAId || undefined,
|
||||
teamBetaId: series.teamBId || undefined,
|
||||
scoreAlpha: adapted.score.alpha,
|
||||
scoreBeta: adapted.score.beta,
|
||||
winner: series.winnerTeamId ? (series.winnerTeamId === series.teamAId ? 'alpha' : 'beta') : undefined,
|
||||
seriesId: series.id,
|
||||
status: series.winnerTeamId ? 'completed' : series.teamAId && series.teamBId ? 'ready' : 'pending',
|
||||
status: series.winnerTeamId ? 'completed' : series.teamAId && series.teamBId && series.phase ? 'live' : series.teamAId && series.teamBId ? 'ready' : 'pending',
|
||||
} satisfies BracketMatch
|
||||
})),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user