From 2215cab77f7f08e5e47c8bba807f763c1ac2314c Mon Sep 17 00:00:00 2001 From: vikingowl Date: Wed, 12 Nov 2025 19:39:38 +0100 Subject: [PATCH] feat: Add comprehensive weapons statistics tab for matches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement detailed weapon performance tracking and visualization. ## New Features ### Weapons Tab - Added "Weapons" tab to match layout navigation - Created `/match/[id]/weapons` route with server-side data loading - Displays weapon statistics for all players in the match ### Statistics Displayed **Overview Cards:** - Total kills across all weapons - Total damage dealt - Total hits landed **Charts & Visualizations:** - Bar chart: Top 10 most-used weapons by kills - Pie chart: Hit location distribution (head, chest, stomach, arms, legs) - Legend with exact hit counts for each body part **Player Performance Table:** - Player name (with team color coding) - Top weapon for each player - Total kills per player - Total damage per player - Total hits per player - Sortable columns for easy comparison ### Technical Implementation - **Data Loading**: Server-side fetch of weapons data via `getMatchWeapons()` API - **Type Safety**: Full TypeScript types with WeaponStats, PlayerWeaponStats, MatchWeaponsResponse - **Error Handling**: Graceful fallback when weapons data unavailable - **Aggregation**: Weapon stats aggregated across all players for match-wide insights - **Team Colors**: Player names colored by team (terrorist/CT) ### UX Improvements - Empty state with helpful message when no weapons data exists - Responsive grid layouts for cards and charts - Consistent styling with existing tabs - Interactive data table with hover states and sorting This completes Phase 1 feature 5 of 6 - comprehensive weapon performance analysis gives players insight into their weapon choices and accuracy. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/routes/match/[id]/+layout.svelte | 1 + src/routes/match/[id]/weapons/+page.svelte | 318 +++++++++++++++++++++ src/routes/match/[id]/weapons/+page.ts | 23 ++ 3 files changed, 342 insertions(+) create mode 100644 src/routes/match/[id]/weapons/+page.svelte create mode 100644 src/routes/match/[id]/weapons/+page.ts diff --git a/src/routes/match/[id]/+layout.svelte b/src/routes/match/[id]/+layout.svelte index 3a41be5..422c928 100644 --- a/src/routes/match/[id]/+layout.svelte +++ b/src/routes/match/[id]/+layout.svelte @@ -19,6 +19,7 @@ { label: 'Overview', href: `/match/${match.match_id}` }, { label: 'Economy', href: `/match/${match.match_id}/economy` }, { label: 'Details', href: `/match/${match.match_id}/details` }, + { label: 'Weapons', href: `/match/${match.match_id}/weapons` }, { label: 'Flashes', href: `/match/${match.match_id}/flashes` }, { label: 'Damage', href: `/match/${match.match_id}/damage` }, { label: 'Chat', href: `/match/${match.match_id}/chat` } diff --git a/src/routes/match/[id]/weapons/+page.svelte b/src/routes/match/[id]/weapons/+page.svelte new file mode 100644 index 0000000..d88def1 --- /dev/null +++ b/src/routes/match/[id]/weapons/+page.svelte @@ -0,0 +1,318 @@ + + + + Match Weapons - CS2.WTF + + +{#if !hasWeaponsData} + +
+ +

No Weapons Data Available

+

Weapon statistics are not available for this match.

+ Weapons data unavailable +
+
+{:else} +
+ +
+ +
+ +

Total Kills

+
+
+ {topWeapons.reduce((sum, w) => sum + w.kills, 0)} +
+
Across all weapons
+
+ + +
+ +

Total Damage

+
+
+ {topWeapons.reduce((sum, w) => sum + w.damage, 0).toLocaleString()} +
+
Across all weapons
+
+ + +
+ +

Total Hits

+
+
+ {topWeapons.reduce((sum, w) => sum + w.hits, 0).toLocaleString()} +
+
Across all weapons
+
+
+ + + +
+

Most Used Weapons

+

Weapons ranked by total kills

+
+ +
+ + + +
+

Hit Location Distribution

+

Where shots landed across all weapons

+
+
+ +
+
+
+ +
+ Head +
+ {hitGroupTotals.head} +
+
+ +
+ Chest +
+ {hitGroupTotals.chest} +
+
+ +
+ Stomach +
+ {hitGroupTotals.stomach} +
+
+ +
+ Arms +
+ {hitGroupTotals.left_arm + hitGroupTotals.right_arm} +
+
+ +
+ Legs +
+ {hitGroupTotals.left_leg + hitGroupTotals.right_leg} +
+
+
+
+
+ + + +
+

Player Weapon Performance

+

Individual player weapon statistics

+
+ + +
+
+{/if} diff --git a/src/routes/match/[id]/weapons/+page.ts b/src/routes/match/[id]/weapons/+page.ts new file mode 100644 index 0000000..cbf1d62 --- /dev/null +++ b/src/routes/match/[id]/weapons/+page.ts @@ -0,0 +1,23 @@ +import type { PageLoad } from './$types'; +import { matchesAPI } from '$lib/api/matches'; + +export const load: PageLoad = async ({ parent, params }) => { + const { match } = await parent(); + + try { + // Fetch weapons statistics for this match + const weapons = await matchesAPI.getMatchWeapons(params.id); + + return { + match, + weapons + }; + } catch (error) { + console.error('Failed to load weapons data:', error); + // Return match without weapons data on error + return { + match, + weapons: { match_id: parseInt(params.id), weapons: [] } + }; + } +};