feat: Add team average Premier rating badges to match header

Display average Premier rating for each team in match statistics cards.

## Changes

### Average Rating Calculation
- Calculate average rank_new across all ranked players on each team
- Filter out unranked players (rating = 0 or null/undefined)
- Round to nearest integer for clean display

### UI Display
- Add PremierRatingBadge below team name in statistics cards
- Small size badge with trophy icon
- Automatically styled with tier colors (gray/blue/purple/pink/red/gold)
- Only show badge if team has at least one ranked player

## Implementation Details

Extended `calcTeamStats()` function to compute `avgRating` by:
1. Filtering players with valid rank_new > 0
2. Computing average if any ranked players exist
3. Returning undefined if no players are ranked

The PremierRatingBadge component handles all tier styling automatically based
on the rating value using the existing formatPremierRating utility.

Team badges provide quick visual indication of match skill level and help
identify skill disparities between teams.

This completes Phase 2 Feature 2 - team ratings now prominently displayed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-12 20:07:59 +01:00
parent 05ef985851
commit b1284bad71

View File

@@ -30,12 +30,22 @@
const avgKAST = const avgKAST =
players.length > 0 ? players.reduce((sum, p) => sum + (p.kast || 0), 0) / players.length : 0; players.length > 0 ? players.reduce((sum, p) => sum + (p.kast || 0), 0) / players.length : 0;
// Calculate average Premier rating
const rankedPlayers = players.filter((p) => p.rank_new && p.rank_new > 0);
const avgRating =
rankedPlayers.length > 0
? Math.round(
rankedPlayers.reduce((sum, p) => sum + (p.rank_new || 0), 0) / rankedPlayers.length
)
: undefined;
return { return {
kills: totalKills, kills: totalKills,
deaths: totalDeaths, deaths: totalDeaths,
kd: totalDeaths > 0 ? (totalKills / totalDeaths).toFixed(2) : totalKills.toFixed(2), kd: totalDeaths > 0 ? (totalKills / totalDeaths).toFixed(2) : totalKills.toFixed(2),
adr: (totalADR / players.length).toFixed(1), adr: (totalADR / players.length).toFixed(1),
kast: avgKAST.toFixed(1) kast: avgKAST.toFixed(1),
avgRating
}; };
}; };
@@ -48,7 +58,12 @@
<div class="grid gap-6 md:grid-cols-2"> <div class="grid gap-6 md:grid-cols-2">
<Card padding="lg"> <Card padding="lg">
<div class="mb-4 flex items-center justify-between"> <div class="mb-4 flex items-center justify-between">
<h2 class="text-2xl font-bold text-terrorist">Terrorists</h2> <div class="flex flex-col gap-2">
<h2 class="text-2xl font-bold text-terrorist">Terrorists</h2>
{#if teamAStats.avgRating}
<PremierRatingBadge rating={teamAStats.avgRating} size="sm" showIcon={true} />
{/if}
</div>
<div class="font-mono text-3xl font-bold text-terrorist">{match.score_team_a}</div> <div class="font-mono text-3xl font-bold text-terrorist">{match.score_team_a}</div>
</div> </div>
<div class="grid grid-cols-2 gap-4"> <div class="grid grid-cols-2 gap-4">
@@ -73,7 +88,12 @@
<Card padding="lg"> <Card padding="lg">
<div class="mb-4 flex items-center justify-between"> <div class="mb-4 flex items-center justify-between">
<h2 class="text-2xl font-bold text-ct">Counter-Terrorists</h2> <div class="flex flex-col gap-2">
<h2 class="text-2xl font-bold text-ct">Counter-Terrorists</h2>
{#if teamBStats.avgRating}
<PremierRatingBadge rating={teamBStats.avgRating} size="sm" showIcon={true} />
{/if}
</div>
<div class="font-mono text-3xl font-bold text-ct">{match.score_team_b}</div> <div class="font-mono text-3xl font-bold text-ct">{match.score_team_b}</div>
</div> </div>
<div class="grid grid-cols-2 gap-4"> <div class="grid grid-cols-2 gap-4">