feat: Add player profile performance charts and visualizations

Implemented comprehensive performance analysis for player profiles with interactive charts
and detailed statistics visualization.

Key Features:
- Performance Trend Chart (K/D and KAST over last 15 matches)
- Map Performance Chart (win rate per map with color coding)
- Utility Effectiveness Stats (flash assists, enemies blinded, HE/flame damage)
- Responsive charts using Chart.js LineChart and BarChart components

Technical Updates:
- Enhanced page loader to fetch 15 detailed matches with player stats
- Fixed DataTable Svelte 5 compatibility and type safety
- Updated MatchCard and PlayerCard to use PlayerMeta properties
- Proper error handling and typed data structures

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-04 21:49:36 +01:00
parent 274f5b3b53
commit 8b73a68a6b
6 changed files with 328 additions and 96 deletions

View File

@@ -13,19 +13,50 @@ export const load: PageLoad = async ({ params }) => {
// Fetch player profile and recent matches in parallel
const [profile, matchesData] = await Promise.all([
api.players.getPlayerMeta(playerId),
api.matches.getMatches({ player_id: playerId, limit: 10 })
api.matches.getMatches({ player_id: playerId, limit: 20 })
]);
// Fetch full match details with player stats for performance charts
// Limit to first 15 matches to avoid too many API calls
const matchDetailsPromises = matchesData.matches
.slice(0, 15)
.map((match) => api.matches.getMatch(match.match_id));
const matchesWithDetails = await Promise.all(matchDetailsPromises);
// Extract player stats from each match
const playerStats = matchesWithDetails
.map((match) => {
const playerData = match.players?.find((p) => p.id === playerId);
if (!playerData) return null;
return {
match_id: match.match_id,
map: match.map,
date: match.date,
...playerData,
// Add match result (did player win?)
won:
(playerData.team_id === 2 && match.score_team_a > match.score_team_b) ||
(playerData.team_id === 3 && match.score_team_b > match.score_team_a)
};
})
.filter((stat): stat is NonNullable<typeof stat> => stat !== null);
return {
profile,
recentMatches: matchesData.matches,
recentMatches: matchesData.matches.slice(0, 10), // Show 10 in recent matches section
playerStats, // Full stats for charts
meta: {
title: `${profile.name} - Player Profile | CS2.WTF`,
description: `View ${profile.name}'s CS2 statistics, match history, and performance metrics.`
}
};
} catch (err) {
console.error(`Failed to load player ${playerId}:`, err);
console.error(
`Failed to load player ${playerId}:`,
err instanceof Error ? err.message : String(err)
);
throw error(404, `Player ${playerId} not found`);
}
};