feat: Display win/loss/tie statistics on player profiles
Add comprehensive match record breakdown showing wins, losses, and ties. ## Changes ### Data Calculation (+ page.ts) - Enhanced playerStats mapping to detect tied matches - Calculate `isTie` by comparing team scores (score_team_a === score_team_b) - Add `tied` boolean field alongside existing `won` field - Ensure wins exclude tied matches for accurate statistics ### Statistics Display (+page.svelte) - Added "Match Record" card to Career Statistics section - Calculate wins, losses, and ties from playerStats - Display in compact format: "XW / YL / ZT" - Color-coded: wins (green), losses (red), ties (blue) - Show total matches analyzed below the record ### UI Improvements - Expanded Career Statistics grid from 4 to 5 columns - Responsive: 2 columns on mobile, 5 on desktop - Consistent card styling with other career stats - Trophy icon for Match Record card ## Implementation Details **Tie Detection Logic:** ```typescript const isTie = match.score_team_a === match.score_team_b; const won = !isTie && ((playerData.team_id === 2 && match.score_team_a > match.score_team_b) || (playerData.team_id === 3 && match.score_team_b > match.score_team_a)); ``` **Record Format:** - Wins: Green text, "W" suffix - Losses: Red text, "L" suffix - Ties: Blue text, "T" suffix - Separators: Gray "/" The statistics are calculated from the last 15 matches with full details, providing accurate win/loss/tie breakdown for performance tracking. This completes Phase 3 Feature 2 - match records now fully visible. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -66,6 +66,12 @@
|
|||||||
const hsPercent =
|
const hsPercent =
|
||||||
totalHeadshots > 0 && totalKills > 0 ? ((totalHeadshots / totalKills) * 100).toFixed(1) : '0.0';
|
totalHeadshots > 0 && totalKills > 0 ? ((totalHeadshots / totalKills) * 100).toFixed(1) : '0.0';
|
||||||
|
|
||||||
|
// Calculate win/loss/tie statistics from playerStats
|
||||||
|
const wins = playerStats.filter((stat) => stat.won).length;
|
||||||
|
const ties = playerStats.filter((stat) => stat.tied).length;
|
||||||
|
const totalMatchesWithStats = playerStats.length;
|
||||||
|
const losses = totalMatchesWithStats - wins - ties;
|
||||||
|
|
||||||
// Check if player is favorited
|
// Check if player is favorited
|
||||||
const isFavorite = $derived($preferences.favoritePlayers.includes(profile.id));
|
const isFavorite = $derived($preferences.favoritePlayers.includes(profile.id));
|
||||||
|
|
||||||
@@ -320,7 +326,7 @@
|
|||||||
<!-- Career Statistics -->
|
<!-- Career Statistics -->
|
||||||
<div>
|
<div>
|
||||||
<h2 class="mb-4 text-2xl font-bold text-base-content">Career Statistics</h2>
|
<h2 class="mb-4 text-2xl font-bold text-base-content">Career Statistics</h2>
|
||||||
<div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
|
<div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-5">
|
||||||
<Card padding="lg">
|
<Card padding="lg">
|
||||||
<div class="mb-2 flex items-center gap-2">
|
<div class="mb-2 flex items-center gap-2">
|
||||||
<Target class="h-5 w-5 text-primary" />
|
<Target class="h-5 w-5 text-primary" />
|
||||||
@@ -343,6 +349,23 @@
|
|||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
<Card padding="lg">
|
||||||
|
<div class="mb-2 flex items-center gap-2">
|
||||||
|
<Trophy class="h-5 w-5 text-primary" />
|
||||||
|
<span class="text-sm font-medium text-base-content/70">Match Record</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-baseline gap-1 text-lg font-bold text-base-content">
|
||||||
|
<span class="text-success">{wins}W</span>
|
||||||
|
<span class="text-base-content/40">/</span>
|
||||||
|
<span class="text-error">{losses}L</span>
|
||||||
|
<span class="text-base-content/40">/</span>
|
||||||
|
<span class="text-info">{ties}T</span>
|
||||||
|
</div>
|
||||||
|
<div class="mt-1 text-xs text-base-content/60">
|
||||||
|
Last {totalMatchesWithStats} matches
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
|
||||||
<Card padding="lg">
|
<Card padding="lg">
|
||||||
<div class="mb-2 flex items-center gap-2">
|
<div class="mb-2 flex items-center gap-2">
|
||||||
<Trophy class="h-5 w-5 text-warning" />
|
<Trophy class="h-5 w-5 text-warning" />
|
||||||
|
|||||||
@@ -30,15 +30,20 @@ export const load: PageLoad = async ({ params }) => {
|
|||||||
const playerData = match.players?.find((p) => p.id === playerId);
|
const playerData = match.players?.find((p) => p.id === playerId);
|
||||||
if (!playerData) return null;
|
if (!playerData) return null;
|
||||||
|
|
||||||
|
const isTie = match.score_team_a === match.score_team_b;
|
||||||
|
const won =
|
||||||
|
!isTie &&
|
||||||
|
((playerData.team_id === 2 && match.score_team_a > match.score_team_b) ||
|
||||||
|
(playerData.team_id === 3 && match.score_team_b > match.score_team_a));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
match_id: match.match_id,
|
match_id: match.match_id,
|
||||||
map: match.map,
|
map: match.map,
|
||||||
date: match.date,
|
date: match.date,
|
||||||
...playerData,
|
...playerData,
|
||||||
// Add match result (did player win?)
|
// Add match results
|
||||||
won:
|
won,
|
||||||
(playerData.team_id === 2 && match.score_team_a > match.score_team_b) ||
|
tied: isTie
|
||||||
(playerData.team_id === 3 && match.score_team_b > match.score_team_a)
|
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter((stat): stat is NonNullable<typeof stat> => stat !== null);
|
.filter((stat): stat is NonNullable<typeof stat> => stat !== null);
|
||||||
|
|||||||
Reference in New Issue
Block a user