Skip to main content
5Stack automatically tracks detailed statistics throughout every match, providing deep insights into player and team performance.

Statistics Overview

All statistics are collected in real-time from the game server and stored permanently for analysis.

Player Stats

Individual performance metrics for every player

Team Stats

Aggregate team performance and comparisons

Round Stats

Round-by-round breakdowns and analysis

Player Statistics

The LineupOverview.vue component displays comprehensive player statistics:
<Table>
  <TableHeader>
    <TableRow>
      <TableHead>Player</TableHead>
      <!-- Responsive stat columns -->
      <TableHead class="xl:hidden">K</TableHead>  <!-- Mobile: K -->
      <TableHead class="hidden xl:inline">Kills</TableHead>  <!-- Desktop: Kills -->
      <TableHead class="hidden md:table-cell">A</TableHead>  <!-- Assists -->
      <TableHead>D</TableHead>  <!-- Deaths -->
      <TableHead class="hidden md:table-cell">K/D</TableHead>
      <TableHead class="hidden lg:table-cell">HS%</TableHead>
      <TableHead class="hidden 2xl:table-cell">Team Damage</TableHead>
      <TableHead class="hidden xl:table-cell">MKR</TableHead>  <!-- Multi-kill rounds -->
      <TableHead class="hidden 2xl:table-cell">2K</TableHead>
      <TableHead class="hidden 2xl:table-cell">3K</TableHead>
      <TableHead class="hidden 2xl:table-cell">4K</TableHead>
      <TableHead class="hidden 2xl:table-cell">5K</TableHead>
      <TableHead class="hidden 2xl:table-cell">Knifes</TableHead>
      <TableHead class="hidden 2xl:table-cell">Zeus</TableHead>
      <TableHead>Total Damage</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    <LineupOverviewRow
      v-for="member of lineup.lineup_players"
      :member="member"
      :lineup="lineup"
      :show-stats="showStats"
    />
  </TableBody>
</Table>

Core Statistics

Total enemy eliminations:
member.kills // Total kills in the match
  • Includes all weapon types
  • Tracked per round
  • Used for K/D ratio calculation
Damage contribution to teammate kills:
member.assists // Total assists
  • Awarded for significant damage (typically 40+ HP)
  • “Flash assists” for blinding enemies before kill
  • Important for support players
Times eliminated:
member.deaths // Total deaths
  • Tracked per round
  • Affects team economy
  • Used for K/D ratio
Kills divided by deaths:
const kd = member.kills / (member.deaths || 1);
// Display: "1.25" or "0.80"
  • Primary performance indicator
  • 1.0 is positive
  • Displayed to 2 decimal places

Advanced Statistics

Headshot Percentage (HS%)

const headshotPercentage = (member.headshot_kills / member.kills) * 100;
// Display: "52%"
Indicates:
  • Aim accuracy
  • Weapon usage patterns
  • Skill level
AWP players typically have lower HS% since the weapon is a one-hit kill to the body.

Multi-Kill Rounds (MKR)

Rounds where player got multiple kills:
Two kills in one round:
member.rounds_with_2k // Count of 2K rounds

Damage Statistics

// All damage dealt to enemies
member.total_damage
// Higher values indicate consistent damage output

Weapon-Specific Stats

// Knife kills
member.knife_kills

// Zeus (Taser) kills
member.zeus_kills

// Both are highlight plays
// Tracked separately for bragging rights

Clutch Statistics

The LineupClutches.vue component tracks clutch situations:
interface ClutchStat {
  player: Player;
  clutches_won: number;
  clutches_lost: number;
  clutch_rate: number; // Win percentage
  situations: {
    '1v1': { won: number; lost: number };
    '1v2': { won: number; lost: number };
    '1v3': { won: number; lost: number };
    '1v4': { won: number; lost: number };
    '1v5': { won: number; lost: number };
  };
}
Clutch statistics identify players who perform well under pressure.

Opening Duels

The LineupOpeningDuels.vue component tracks first blood:
interface OpeningDuelStat {
  player: Player;
  opening_kills: number;    // First blood secured
  opening_deaths: number;   // Died first
  opening_success_rate: number;  // Win rate
  impact: number;           // Net contribution (+kills -deaths)
}

Entry Fraggers

Players with high opening kill counts are effective entry fraggers.

Opening Death Penalty

Opening deaths put the team at immediate disadvantage.

Utility Usage

The LineupUtility.vue component tracks utility effectiveness:
interface UtilityStat {
  player: Player;
  enemies_flashed: number;      // Opponents blinded
  teammates_flashed: number;    // Friendly fire flashes
  flash_assists: number;        // Kills from flashed enemies
  he_damage: number;           // HE grenade damage
  molotov_damage: number;      // Fire damage
  smoke_usage: number;         // Smokes thrown
  utility_damage_total: number; // All nade damage
}
Flashing teammates is penalized. High teammate flash counts indicate poor utility usage.

Map-Specific Statistics

Each map in a match tracks separate statistics:
interface MatchMap {
  id: string;
  order: number;
  map: Map;
  status: e_match_map_status_enum;
  lineup_1_score: number;
  lineup_2_score: number;
  winning_lineup_id: string | null;
  rounds: Round[];
  demos: Demo[];  // Downloadable demo files
}

Round Data

interface Round {
  round: number;              // Round number (1-30+)
  lineup_1_score: number;     // Running score
  lineup_2_score: number;
  lineup_1_side: 'CT' | 'T';  // Side assignments
  lineup_2_side: 'CT' | 'T';
  winning_side: 'CT' | 'T' | null;
  has_backup_file: boolean;   // Server backup exists
  kills: Kill[];              // All kills in round
}

Kill Events

interface Kill {
  player: Player;           // Killer
  attacked_player: Player;  // Victim
  weapon: string;          // Weapon used
  headshot: boolean;       // Was it a headshot?
  penetrated: boolean;     // Wallbang?
  time: number;           // Timestamp in round
}

Match Statistics Query

Statistics are loaded via GraphQL subscription:
match_maps: [
  {
    order_by: { order: order_by.asc },
  },
  {
    id: true,
    order: true,
    lineup_1_score: true,
    lineup_2_score: true,
    winning_lineup_id: true,
    status: true,
    rounds: [
      {
        order_by: { round: order_by.asc },
      },
      {
        round: true,
        lineup_1_score: true,
        lineup_2_score: true,
        lineup_1_side: true,
        lineup_2_side: true,
        winning_side: true,
        kills: [
          {
            order_by: { time: order_by.asc },
          },
          {
            player: { steam_id: true },
            attacked_player: { steam_id: true },
            weapon: true,
            headshot: true,
          },
        ],
      },
    ],
  },
]

Demo Files

Matches include downloadable demo files:
interface Demo {
  size: number;              // File size in bytes
  download_url: string;      // Direct download link
}

// Aggregate demo info on match map
match_map.demos_total_size    // Total size of all demos
match_map.demos_download_url  // ZIP of all demos
1

Download

Click the demo download link on the match page.
2

Extract

Extract the .dem file from the ZIP archive.
3

Review

Open in CS2 using playdemo filename.dem.
4

Analyze

Use demo review tools for detailed analysis.

Scoreboard Display

The match page shows a live scoreboard:
<MatchLineupScoreDisplay
  :match="match"
  :lineup="match.lineup_1"
/>
Displays:
  • Current map score
  • Total maps won (for BO3/BO5)
  • Round-by-round progression
  • Side indicators (CT/T)

Statistics Tabs

The MatchTabs.vue component organizes statistics:
  • Lineup rosters with K/D/A
  • Overall match summary
  • Map scores

Real-Time Updates

Statistics update in real-time during live matches:
apollo: {
  $subscribe: {
    matches_by_pk: {
      query: typedGql('subscription')({
        matches_by_pk: [
          { id: matchId },
          {
            // ... match fields including stats
            lineup_1: matchLineups,  // Includes player stats
            lineup_2: matchLineups,
            match_maps: {            // Includes round data
              rounds: {
                kills: true,
              },
            },
          },
        ],
      }),
      result({ data }) {
        // Statistics automatically update in UI
        this.match = data.matches_by_pk;
      },
    },
  },
}
Statistics are updated every round. Use real-time data to track match progress and player performance.

Responsive Statistics Display

The statistics table is responsive:
<!-- Mobile: Show only essential stats -->
<TableHead class="xl:hidden">K</TableHead>
<TableHead>D</TableHead>

<!-- Tablet: Add assists and K/D -->
<TableHead class="hidden md:table-cell">A</TableHead>
<TableHead class="hidden md:table-cell">K/D</TableHead>

<!-- Desktop: Add headshot % -->
<TableHead class="hidden lg:table-cell">HS%</TableHead>

<!-- Large screens: Show all stats -->
<TableHead class="hidden xl:table-cell">MKR</TableHead>
<TableHead class="hidden 2xl:table-cell">2K</TableHead>
<TableHead class="hidden 2xl:table-cell">Team Damage</TableHead>

Exporting Statistics

Future feature: Export match statistics to CSV/JSON for external analysis.

Statistics API

Access statistics programmatically:
// Get player stats for a match
const playerStats = await getPlayerMatchStats({
  match_id: 'match-uuid',
  player_steam_id: '76561198XXXXXXXX',
});

// Get team aggregate stats
const teamStats = await getTeamMatchStats({
  match_id: 'match-uuid',
  lineup_id: 'lineup-uuid',
});

Next Steps

Creating Matches

Create matches to start collecting statistics

Match Options

Configure matches for optimal stat tracking

Overview

Return to match system overview

Build docs developers (and LLMs) love