192 lines
5.0 KiB
TypeScript
192 lines
5.0 KiB
TypeScript
import { api } from '@/lib/api/api-client'
|
|
|
|
import type {
|
|
AnnouncementItem,
|
|
AnnouncementState,
|
|
BetSelection,
|
|
ConnectionState,
|
|
DashboardState,
|
|
GameBootstrapSnapshot,
|
|
GameCell,
|
|
HistoryEntry,
|
|
RoundSnapshot,
|
|
TrendEntry,
|
|
} from '../shared'
|
|
import { createMockGameBootstrapSnapshot } from '../shared'
|
|
import type {
|
|
AnnouncementStateDto,
|
|
BetSelectionDto,
|
|
ChipDto,
|
|
ConnectionStateDto,
|
|
DashboardStateDto,
|
|
GameAnnouncementsDto,
|
|
GameBootstrapDto,
|
|
GameCellDto,
|
|
GameRoundFeedDto,
|
|
HistoryEntryDto,
|
|
RoundSnapshotDto,
|
|
TrendEntryDto,
|
|
} from './types'
|
|
|
|
export const GAME_API_ENDPOINTS = {
|
|
announcements: 'game/announcements',
|
|
bootstrap: 'game/bootstrap',
|
|
roundFeed: 'game/round-feed',
|
|
} as const
|
|
|
|
function normalizeGameCell(dto: GameCellDto) {
|
|
return dto satisfies GameCell
|
|
}
|
|
|
|
function normalizeChip(dto: ChipDto) {
|
|
return {
|
|
amount: dto.amount,
|
|
color: dto.color,
|
|
id: dto.id,
|
|
isDefault: dto.is_default,
|
|
label: dto.label,
|
|
}
|
|
}
|
|
|
|
function normalizeBetSelection(dto: BetSelectionDto) {
|
|
return {
|
|
amount: dto.amount,
|
|
cellId: dto.cell_id,
|
|
chipId: dto.chip_id,
|
|
id: dto.id,
|
|
placedAt: dto.placed_at,
|
|
source: dto.source,
|
|
} satisfies BetSelection
|
|
}
|
|
|
|
function normalizeRoundSnapshot(dto: RoundSnapshotDto) {
|
|
return {
|
|
bettingClosesAt: dto.betting_closes_at,
|
|
id: dto.id,
|
|
phase: dto.phase,
|
|
revealingAt: dto.revealing_at,
|
|
settledAt: dto.settled_at,
|
|
startedAt: dto.started_at,
|
|
winningCellId: dto.winning_cell_id,
|
|
} satisfies RoundSnapshot
|
|
}
|
|
|
|
function normalizeHistoryEntry(dto: HistoryEntryDto) {
|
|
return {
|
|
payoutMultiplier: dto.payout_multiplier,
|
|
roundId: dto.round_id,
|
|
settledAt: dto.settled_at,
|
|
totalPoolAmount: dto.total_pool_amount,
|
|
winningCellId: dto.winning_cell_id,
|
|
} satisfies HistoryEntry
|
|
}
|
|
|
|
function normalizeTrendEntry(dto: TrendEntryDto) {
|
|
return {
|
|
cellId: dto.cell_id,
|
|
currentStreak: dto.current_streak,
|
|
direction: dto.direction,
|
|
hitCount: dto.hit_count,
|
|
lastHitRoundId: dto.last_hit_round_id,
|
|
missCount: dto.miss_count,
|
|
} satisfies TrendEntry
|
|
}
|
|
|
|
function normalizeAnnouncementState(dto: AnnouncementStateDto) {
|
|
return {
|
|
activeAnnouncementId: dto.active_announcement_id,
|
|
items: dto.items.map(
|
|
(item) =>
|
|
({
|
|
createdAt: item.created_at,
|
|
expiresAt: item.expires_at,
|
|
id: item.id,
|
|
isPinned: item.is_pinned,
|
|
isRead: item.is_read,
|
|
message: item.message,
|
|
title: item.title,
|
|
tone: item.tone,
|
|
}) satisfies AnnouncementItem,
|
|
),
|
|
lastUpdatedAt: dto.last_updated_at,
|
|
} satisfies AnnouncementState
|
|
}
|
|
|
|
function normalizeDashboardState(dto: DashboardStateDto) {
|
|
return {
|
|
countdownMs: dto.countdown_ms,
|
|
featuredCellId: dto.featured_cell_id,
|
|
onlinePlayers: dto.online_players,
|
|
tableLimitMax: dto.table_limit_max,
|
|
tableLimitMin: dto.table_limit_min,
|
|
totalPoolAmount: dto.total_pool_amount,
|
|
updatedAt: dto.updated_at,
|
|
} satisfies DashboardState
|
|
}
|
|
|
|
function normalizeConnectionState(dto: ConnectionStateDto) {
|
|
return {
|
|
connectedAt: dto.connected_at,
|
|
lastError: dto.last_error,
|
|
lastMessageAt: dto.last_message_at,
|
|
latencyMs: dto.latency_ms,
|
|
reconnectAttempt: dto.reconnect_attempt,
|
|
status: dto.status,
|
|
transport: dto.transport,
|
|
} satisfies ConnectionState
|
|
}
|
|
|
|
export function normalizeGameBootstrap(dto: GameBootstrapDto) {
|
|
return {
|
|
announcements: normalizeAnnouncementState(dto.announcements),
|
|
cells: dto.cells.map(normalizeGameCell),
|
|
chips: dto.chips.map(normalizeChip),
|
|
connection: normalizeConnectionState(dto.connection),
|
|
dashboard: normalizeDashboardState(dto.dashboard),
|
|
history: dto.history.map(normalizeHistoryEntry),
|
|
round: normalizeRoundSnapshot(dto.round),
|
|
selections: dto.selections.map(normalizeBetSelection),
|
|
trends: dto.trends.map(normalizeTrendEntry),
|
|
} satisfies GameBootstrapSnapshot
|
|
}
|
|
|
|
export function normalizeGameRoundFeed(dto: GameRoundFeedDto) {
|
|
return {
|
|
history: dto.history.map(normalizeHistoryEntry),
|
|
round: normalizeRoundSnapshot(dto.round),
|
|
selections: dto.selections.map(normalizeBetSelection),
|
|
trends: dto.trends.map(normalizeTrendEntry),
|
|
} satisfies Pick<
|
|
GameBootstrapSnapshot,
|
|
'history' | 'round' | 'selections' | 'trends'
|
|
>
|
|
}
|
|
|
|
export async function getGameBootstrap() {
|
|
const response = await api.get<GameBootstrapDto>(GAME_API_ENDPOINTS.bootstrap)
|
|
|
|
return normalizeGameBootstrap(response.data)
|
|
}
|
|
|
|
export async function getGameRoundFeed() {
|
|
const response = await api.get<GameRoundFeedDto>(GAME_API_ENDPOINTS.roundFeed)
|
|
|
|
return normalizeGameRoundFeed(response.data)
|
|
}
|
|
|
|
export async function getGameAnnouncements() {
|
|
const response = await api.get<GameAnnouncementsDto>(
|
|
GAME_API_ENDPOINTS.announcements,
|
|
)
|
|
|
|
return normalizeAnnouncementState(response.data.announcements)
|
|
}
|
|
|
|
export async function getMockGameBootstrap(latencyMs = 120) {
|
|
await new Promise((resolve) => {
|
|
setTimeout(resolve, latencyMs)
|
|
})
|
|
|
|
return createMockGameBootstrapSnapshot()
|
|
}
|