ai generated solutions to our ai generated problems

This commit is contained in:
2026-06-15 07:53:33 +01:00
parent 5cd95cf78f
commit 0db73d669d
4 changed files with 271 additions and 181 deletions
+16 -127
View File
@@ -19,17 +19,17 @@ const apiEndpoints = {
songOfDay: '/api/song-of-day',
teams: '/api/tss/leaderboard/teams?limit=100',
teamsHealth: '/api/tss/leaderboard/teams?limit=1',
recentGames: '/api/tss/games/recent?limit=50',
resolve: (name) => `/api/tss/teams/resolve?name=${encodeURIComponent(name)}`,
searchTeams: (name) => `/api/tss/teams/search?q=${encodeURIComponent(name)}&limit=10`,
detail: (name) => `/api/tss/teams/${encodeURIComponent(name)}`,
history: (name) => `/api/tss/teams/${encodeURIComponent(name)}/history`,
games: (name) => `/api/tss/teams/${encodeURIComponent(name)}/games`,
player: (uid) => `/api/tss/player/${encodeURIComponent(uid)}`,
}
const navItems = [
{ path: '/', label: 'Home' },
{ path: '/teams', label: 'Team leaderboard' },
{ path: '/teams', label: 'Team Leaderboard' },
{ path: '/battle-logs', label: 'Battle Logs' },
{ path: '/viewers', label: 'Viewers' },
{ path: '/docs', label: 'Setup' },
@@ -355,7 +355,7 @@ function deviceType() {
function routeLabel(route) {
if (route.page === 'team' && route.teamName) return `Team: ${route.teamName}`
if (route.page === 'teams') return 'Team leaderboard'
if (route.page === 'teams') return 'Team Leaderboard'
if (route.page === 'battle-logs') return 'Battle Logs'
if (route.page === 'uptime') return 'Uptime'
if (route.page === 'viewers') return 'viewers'
@@ -539,41 +539,8 @@ function applySeo(route, profileDetail = null) {
structuredData.textContent = structuredDataForSeo(seo, canonicalUrl)
}
async function fetchRecentTssGames(teams, signal) {
const teamNames = teams.map(bestTeamName).filter(Boolean).slice(0, 12)
if (!teamNames.length) {
return { matches: [] }
}
const responses = await Promise.allSettled(
teamNames.map((name) => fetchJson(apiEndpoints.games(name), signal).then((data) => ({ name, data }))),
)
const bySession = new Map()
responses.forEach((result) => {
if (result.status !== 'fulfilled') return
const { name, data } = result.value
;(data.games || []).forEach((game) => {
if (!game.session_id) return
const existing = bySession.get(game.session_id)
const currentTimestamp = Number(game.timestamp || 0)
if (existing && Number(existing.timestamp || 0) >= currentTimestamp) return
bySession.set(game.session_id, {
...game,
team_name: data.name || name,
})
})
})
return {
matches: Array.from(bySession.values())
.sort((a, b) => Number(b.timestamp || 0) - Number(a.timestamp || 0))
.slice(0, 50),
}
async function fetchRecentTssGames(signal) {
return fetchJson(apiEndpoints.recentGames, signal)
}
function Stat({ label, value }) {
@@ -861,7 +828,6 @@ function AppContent() {
const [profile, setProfile] = useState({
teamName: '',
detail: { status: 'idle', data: null, error: null },
history: { status: 'idle', data: null, error: null },
games: { status: 'idle', data: null, error: null },
})
const teams = useMemo(
@@ -1138,7 +1104,6 @@ function AppContent() {
useEffect(() => {
if (!['home', 'battle-logs'].includes(route.page)) return
if (!teams.length) return
const currentLive = liveRef.current
if (currentLive.status === 'ready' && Date.now() - currentLive.updatedAt < liveRefreshMs) return
@@ -1149,7 +1114,7 @@ function AppContent() {
: { status: 'loading', data: null, error: null, updatedAt: current.updatedAt || 0 },
)
fetchRecentTssGames(teams, controller.signal)
fetchRecentTssGames(controller.signal)
.then((data) => setLive({ status: 'ready', data, error: null, updatedAt: Date.now() }))
.catch((error) => {
if (!controller.signal.aborted) {
@@ -1158,15 +1123,14 @@ function AppContent() {
})
return () => controller.abort()
}, [route.page, teams])
}, [route.page])
useEffect(() => {
if (!['home', 'battle-logs'].includes(route.page)) return
if (!teams.length) return
const controller = new AbortController()
const timer = window.setInterval(() => {
fetchRecentTssGames(teams, controller.signal)
fetchRecentTssGames(controller.signal)
.then((data) => setLive({ status: 'ready', data, error: null, updatedAt: Date.now() }))
.catch((error) => {
if (!controller.signal.aborted) {
@@ -1179,7 +1143,7 @@ function AppContent() {
window.clearInterval(timer)
controller.abort()
}
}, [route.page, teams])
}, [route.page])
useEffect(() => {
if (route.page !== 'home') return
@@ -1219,7 +1183,6 @@ function AppContent() {
setProfile({
teamName: route.teamName,
detail: { status: 'loading', data: null, error: null },
history: { status: 'loading', data: null, error: null },
games: { status: 'loading', data: null, error: null },
})
@@ -1232,18 +1195,13 @@ function AppContent() {
}
return Promise.allSettled([
fetchJson(apiEndpoints.history(route.teamName), controller.signal),
fetchJson(apiEndpoints.games(route.teamName), controller.signal),
]).then(([historyResult, gamesResult]) => {
]).then(([gamesResult]) => {
if (controller.signal.aborted) return
setProfile({
teamName: route.teamName,
detail: { status: 'ready', data: detail, error: null },
history:
historyResult.status === 'fulfilled'
? { status: 'ready', data: historyResult.value, error: null }
: { status: 'error', data: null, error: historyResult.reason.message },
games:
gamesResult.status === 'fulfilled'
? { status: 'ready', data: gamesResult.value, error: null }
@@ -1402,9 +1360,8 @@ function AppContent() {
const timer = window.setInterval(() => {
Promise.allSettled([
fetchJson(apiEndpoints.detail(route.teamName), controller.signal),
fetchJson(apiEndpoints.history(route.teamName), controller.signal),
fetchJson(apiEndpoints.games(route.teamName), controller.signal),
]).then(([detailResult, historyResult, gamesResult]) => {
]).then(([detailResult, gamesResult]) => {
if (controller.signal.aborted) return
setProfile((current) => ({
@@ -1413,10 +1370,6 @@ function AppContent() {
detailResult.status === 'fulfilled'
? { status: 'ready', data: detailResult.value, error: null }
: current.detail,
history:
historyResult.status === 'fulfilled'
? { status: 'ready', data: historyResult.value, error: null }
: current.history,
games:
gamesResult.status === 'fulfilled'
? { status: 'ready', data: gamesResult.value, error: null }
@@ -2111,7 +2064,7 @@ function Landing({
onClick={() => navigate('/teams')}
type="button"
>
Team leaderboard
Team Leaderboard
</button>
<button
className="min-h-15 rounded-lg border-2 border-ring px-5 py-4 text-base font-semibold text-fury-cyan transition hover:bg-surface hover:text-text"
@@ -2824,7 +2777,7 @@ function TeamsPage({ leaderboard, navigate, teams }) {
return (
<section className="space-y-6 pt-24 sm:pt-28">
<div>
<h1 className="text-3xl font-bold">Team leaderboard</h1>
<h1 className="text-3xl font-bold">Team Leaderboard</h1>
<p className="mt-2 text-sm text-text-soft">
{leaderboard.status === 'loading'
? 'Loading leaderboard'
@@ -2871,9 +2824,6 @@ function TeamProfilePage({ navigate, profile, requestedTeam, teams }) {
const summary = detail?.team_summary || detail?.squadron_summary
const players = detail?.players || []
const games = profile.games.data?.games || []
const history = profile.history.data?.history || []
const ratingHourly = profile.history.data?.rating_hourly || []
const latestRating = ratingHourly.at(-1)?.rating || summary?.points?.total_points
const leaderboardTeam = teams.find((team) => bestTeamName(team) === requestedTeam)
const displayName = detail?.name || bestTeamName(leaderboardTeam) || requestedTeam
@@ -2888,7 +2838,7 @@ function TeamProfilePage({ navigate, profile, requestedTeam, teams }) {
</button>
<div className="rounded-lg border border-border bg-fury-white p-6 shadow-sm">
<div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
<div>
<div>
<p className="text-sm font-semibold uppercase tracking-wide text-fury-cyan">
Team profile
@@ -2898,32 +2848,17 @@ function TeamProfilePage({ navigate, profile, requestedTeam, teams }) {
{profile.detail.error || ''}
</p>
</div>
<div className="grid grid-cols-2 gap-3 text-sm sm:grid-cols-3">
<span className="rounded-md bg-surface px-3 py-2 font-semibold">
Rating {formatNumber(latestRating)}
</span>
<span className="rounded-md bg-surface px-3 py-2 font-semibold">
Clan {detail?.clan_id || leaderboardTeam?.clan_id || 'n/a'}
</span>
<span className="rounded-md bg-surface px-3 py-2 font-semibold">
{detail?.data_set || 'tss'}
</span>
</div>
</div>
<div className="mt-6 grid gap-5 sm:grid-cols-2 xl:grid-cols-5">
<div className="mt-6 grid gap-5 sm:grid-cols-2 xl:grid-cols-4">
<Stat label="Roster" value={formatNumber(summary?.player_count)} />
<Stat label="Battles" value={formatNumber(summary?.total_battles)} />
<Stat label="Wins" value={formatNumber(summary?.wins)} />
<Stat label="Win rate" value={`${Number(summary?.win_rate || 0).toFixed(1)}%`} />
<Stat label="KDR" value={Number(summary?.kdr || 0).toFixed(1)} />
</div>
</div>
<div className="grid gap-6 xl:grid-cols-[1.15fr_0.85fr]">
<RosterTable players={players} status={profile.detail.status} />
<RatingPanel history={history} ratingHourly={ratingHourly} status={profile.history.status} />
</div>
<RosterTable players={players} status={profile.detail.status} />
<BattleResults games={games} status={profile.games.status} />
</section>
@@ -2970,51 +2905,6 @@ function RosterTable({ players, status }) {
)
}
function RatingPanel({ history, ratingHourly, status }) {
const recentHistory = history.slice(-8)
const firstRating = ratingHourly[0]?.rating || 0
const latestRating = ratingHourly.at(-1)?.rating || 0
const ratingChange = latestRating - firstRating
return (
<div className="rounded-lg border border-border bg-fury-white shadow-sm">
<div className="border-b border-surface px-5 py-4">
<h2 className="text-lg font-semibold">History</h2>
<p className="mt-1 text-sm text-text-soft">
{ratingHourly.length ? `${formatNumber(ratingHourly.length)} rating snapshots` : status}
</p>
</div>
<div className="space-y-5 p-5">
<div className="grid gap-5 sm:grid-cols-2">
<Stat label="Latest rating" value={formatNumber(latestRating)} />
<Stat
label="Rating change"
value={`${ratingChange >= 0 ? '+' : ''}${formatNumber(ratingChange)}`}
/>
</div>
<div className="space-y-2">
{recentHistory.map((item) => (
<div
className="grid grid-cols-[1fr_auto_auto] gap-3 rounded-md bg-surface px-3 py-2 text-sm"
key={item.period}
>
<span className="font-semibold">{item.period}</span>
<span>{formatNumber(item.battles)} battles</span>
<span>{Number(item.win_rate || 0).toFixed(1)}% WR</span>
</div>
))}
{!recentHistory.length ? (
<p className="text-sm text-text-soft">
{status === 'loading' ? 'Loading history' : 'No history rows returned'}
</p>
) : null}
</div>
</div>
</div>
)
}
function BattleResults({ games, status }) {
return (
<div className="rounded-lg border border-border bg-fury-white shadow-sm">
@@ -3085,7 +2975,6 @@ function BattleLogsPage({ live, matches }) {
<p className="truncate font-semibold text-fury-cyan">
{match.team_name || 'TSS team'}
</p>
<p className="truncate text-xs text-text-soft">TSS battle record</p>
</div>
<p
className={`w-fit rounded-md px-3 py-1 text-sm font-semibold ${String(match.result).toLowerCase() === 'win'