Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
table:
name: player_season_performance_v
schema: public
object_relationships:
- name: season
using:
manual_configuration:
column_mapping:
season_id: id
insertion_order: null
remote_table:
name: seasons
schema: public
select_permissions:
- role: guest
permission:
columns:
- steam_id
- season_id
- season_starts_at
- rounds
- aim_rating
- positioning_rating
- utility_rating
- accuracy_score
- hs_score
- spotted_score
- crosshair_score
- ttd_score
- counter_strafe_score
- survival_score
- traded_score
- kast_score
- flash_assists_score
- blind_score
- util_eff_score
filter: {}
allow_aggregations: true
comment: ""
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
table:
name: v_player_weapon_match_damage
schema: public
object_relationships:
- name: match
using:
manual_configuration:
column_mapping:
match_id: id
insertion_order: null
remote_table:
name: matches
schema: public
select_permissions:
- role: guest
permission:
columns:
- player_steam_id
- match_id
- with
- damage
- hits
filter: {}
allow_aggregations: true
comment: ""
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
table:
name: v_player_weapon_match_kills
schema: public
object_relationships:
- name: match
using:
manual_configuration:
column_mapping:
match_id: id
insertion_order: null
remote_table:
name: matches
schema: public
select_permissions:
- role: guest
permission:
columns:
- player_steam_id
- match_id
- with
- kill_count
- rounds
filter: {}
allow_aggregations: true
comment: ""
3 changes: 3 additions & 0 deletions hasura/metadata/databases/default/tables/tables.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@
- "!include public_player_objectives.yaml"
- "!include public_player_premier_rank_history.yaml"
- "!include public_player_sanctions.yaml"
- "!include public_player_season_performance_v.yaml"
- "!include public_player_season_stats.yaml"
- "!include public_player_stats.yaml"
- "!include public_player_steam_bot_friend.yaml"
Expand Down Expand Up @@ -244,6 +245,8 @@
- "!include public_v_player_multi_kills.yaml"
- "!include public_v_player_weapon_damage.yaml"
- "!include public_v_player_weapon_kills.yaml"
- "!include public_v_player_weapon_match_damage.yaml"
- "!include public_v_player_weapon_match_kills.yaml"
- "!include public_v_pool_maps.yaml"
- "!include public_v_role_permissions.yaml"
- "!include public_v_steam_account_pool_status.yaml"
Expand Down
88 changes: 88 additions & 0 deletions hasura/views/v_player_perf_season.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
-- Season split of player_career_stats_v + player_performance_v: the same 0-100
-- sub-scores, each a cume_dist percentile within that season's pool of players
-- with >= 30 rounds in it. A match belongs to the season its end time falls in.
DROP VIEW IF EXISTS public.player_season_performance_v;
CREATE VIEW public.player_season_performance_v AS
WITH base AS (
SELECT
s.steam_id,
se.id AS season_id,
se.starts_at AS season_starts_at,
SUM(s.rounds_played)::int AS rounds,
SUM(s.deaths)::int AS deaths,
SUM(s.hits)::int AS hits,
SUM(s.shots_fired)::int AS shots_fired,
SUM(s.headshot_hits)::int AS headshot_hits,
SUM(s.traded_death_successes)::int AS traded_death_successes,
SUM(s.traded_death_opportunities)::int AS traded_death_opportunities,
SUM(s.flash_assists)::int AS flash_assists,
SUM(s.flash_duration_sum)::numeric AS enemy_blind_duration,
SUM(s.he_damage + s.molotov_damage)::int AS util_damage,
SUM(s.he_throws + s.molotov_throws)::int AS util_thrown,
SUM(s.hits_at_spotted)::int AS hits_at_spotted,
SUM(s.shots_at_spotted)::int AS shots_at_spotted,
SUM(s.crosshair_angle_sum_deg)::numeric AS crosshair_angle_sum_deg,
SUM(s.crosshair_angle_count)::int AS crosshair_angle_count,
SUM(s.time_to_damage_sum_s)::numeric AS time_to_damage_sum_s,
SUM(s.time_to_damage_count)::int AS time_to_damage_count,
SUM(s.counter_strafed_shots)::int AS counter_strafed_shots,
SUM(s.counter_strafe_eligible_shots)::int AS counter_strafe_eligible_shots,
SUM(s.kast_rounds)::int AS kast_rounds,
SUM(s.kast_total_rounds)::int AS kast_total_rounds
FROM public.player_match_map_stats s
JOIN public.matches m ON m.id = s.match_id
JOIN public.seasons se
ON m.ended_at >= se.starts_at
AND (se.ends_at IS NULL OR m.ended_at < se.ends_at)
GROUP BY s.steam_id, se.id, se.starts_at
),
pool AS (
SELECT
b.steam_id, b.season_id, b.season_starts_at, b.rounds,
-- Aim
CASE WHEN b.shots_fired > 0 THEN 100.0 * b.hits / b.shots_fired END AS accuracy,
CASE WHEN b.hits > 0 THEN 100.0 * b.headshot_hits / b.hits END AS hs_pct,
CASE WHEN b.shots_at_spotted > 0 THEN 100.0 * b.hits_at_spotted / b.shots_at_spotted END AS accuracy_spotted,
CASE WHEN b.crosshair_angle_count > 0 THEN b.crosshair_angle_sum_deg / b.crosshair_angle_count END AS crosshair_deg,
CASE WHEN b.time_to_damage_count > 0 THEN b.time_to_damage_sum_s / b.time_to_damage_count END AS time_to_damage_s,
CASE WHEN b.counter_strafe_eligible_shots > 0 THEN 100.0 * b.counter_strafed_shots / b.counter_strafe_eligible_shots END AS counter_strafe_pct,
-- Positioning
CASE WHEN b.rounds > 0 THEN 100.0 * (1.0 - b.deaths::numeric / b.rounds) END AS survival_pct,
CASE WHEN b.traded_death_opportunities > 0 THEN 100.0 * b.traded_death_successes / b.traded_death_opportunities END AS traded_death_pct,
CASE WHEN b.kast_total_rounds > 0 THEN 100.0 * b.kast_rounds / b.kast_total_rounds END AS kast_pct,
-- Utility (quality, not volume)
CASE WHEN b.rounds > 0 THEN b.flash_assists::numeric / b.rounds END AS flash_assists_pr,
CASE WHEN b.rounds > 0 THEN b.enemy_blind_duration / b.rounds END AS enemy_blind_pr,
CASE WHEN b.util_thrown > 0 THEN b.util_damage::numeric / b.util_thrown END AS util_efficiency
FROM base b
WHERE b.rounds >= 30
),
-- Partitioning on IS NULL ranks each metric only among the players who have
-- it, like the per-metric CTEs in player_performance_v.
scored AS (
SELECT
p.steam_id, p.season_id, p.season_starts_at, p.rounds,
CASE WHEN p.accuracy IS NOT NULL THEN round(100.0 * cume_dist() OVER (PARTITION BY p.season_id, p.accuracy IS NULL ORDER BY p.accuracy)) END AS accuracy_score,
CASE WHEN p.hs_pct IS NOT NULL THEN round(100.0 * cume_dist() OVER (PARTITION BY p.season_id, p.hs_pct IS NULL ORDER BY p.hs_pct)) END AS hs_score,
CASE WHEN p.accuracy_spotted IS NOT NULL THEN round(100.0 * cume_dist() OVER (PARTITION BY p.season_id, p.accuracy_spotted IS NULL ORDER BY p.accuracy_spotted)) END AS spotted_score,
CASE WHEN p.crosshair_deg IS NOT NULL THEN round(100.0 * cume_dist() OVER (PARTITION BY p.season_id, p.crosshair_deg IS NULL ORDER BY p.crosshair_deg DESC)) END AS crosshair_score,
CASE WHEN p.time_to_damage_s IS NOT NULL THEN round(100.0 * cume_dist() OVER (PARTITION BY p.season_id, p.time_to_damage_s IS NULL ORDER BY p.time_to_damage_s DESC)) END AS ttd_score,
CASE WHEN p.counter_strafe_pct IS NOT NULL THEN round(100.0 * cume_dist() OVER (PARTITION BY p.season_id, p.counter_strafe_pct IS NULL ORDER BY p.counter_strafe_pct)) END AS counter_strafe_score,
CASE WHEN p.survival_pct IS NOT NULL THEN round(100.0 * cume_dist() OVER (PARTITION BY p.season_id, p.survival_pct IS NULL ORDER BY p.survival_pct)) END AS survival_score,
CASE WHEN p.traded_death_pct IS NOT NULL THEN round(100.0 * cume_dist() OVER (PARTITION BY p.season_id, p.traded_death_pct IS NULL ORDER BY p.traded_death_pct)) END AS traded_score,
CASE WHEN p.kast_pct IS NOT NULL THEN round(100.0 * cume_dist() OVER (PARTITION BY p.season_id, p.kast_pct IS NULL ORDER BY p.kast_pct)) END AS kast_score,
CASE WHEN p.flash_assists_pr IS NOT NULL THEN round(100.0 * cume_dist() OVER (PARTITION BY p.season_id, p.flash_assists_pr IS NULL ORDER BY p.flash_assists_pr)) END AS flash_assists_score,
CASE WHEN p.enemy_blind_pr IS NOT NULL THEN round(100.0 * cume_dist() OVER (PARTITION BY p.season_id, p.enemy_blind_pr IS NULL ORDER BY p.enemy_blind_pr)) END AS blind_score,
CASE WHEN p.util_efficiency IS NOT NULL THEN round(100.0 * cume_dist() OVER (PARTITION BY p.season_id, p.util_efficiency IS NULL ORDER BY p.util_efficiency)) END AS util_eff_score
FROM pool p
)
SELECT
s.steam_id, s.season_id, s.season_starts_at, s.rounds,
(SELECT round(avg(x)) FROM unnest(ARRAY[s.accuracy_score, s.hs_score, s.spotted_score,
s.crosshair_score, s.ttd_score, s.counter_strafe_score]) x) AS aim_rating,
(SELECT round(avg(x)) FROM unnest(ARRAY[s.survival_score, s.traded_score, s.kast_score]) x) AS positioning_rating,
(SELECT round(avg(x)) FROM unnest(ARRAY[s.flash_assists_score, s.blind_score, s.util_eff_score]) x) AS utility_rating,
s.accuracy_score, s.hs_score, s.spotted_score, s.crosshair_score, s.ttd_score, s.counter_strafe_score,
s.survival_score, s.traded_score, s.kast_score,
s.flash_assists_score, s.blind_score, s.util_eff_score
FROM scored s;
27 changes: 27 additions & 0 deletions hasura/views/v_player_weapon_match.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-- Per-(player, match, weapon) kills and damage, so weapon stats can follow a
-- date range or season through the `match` relationship. v_player_weapon_kills
-- and v_player_weapon_damage stay the career rollups.
CREATE OR REPLACE VIEW public.v_player_weapon_match_kills AS
SELECT
pk.attacker_steam_id AS player_steam_id,
pk.match_id,
pk."with" AS "with",
COUNT(*)::bigint AS kill_count,
COUNT(DISTINCT (pk.match_map_id, pk.round))::bigint AS rounds
FROM player_kills pk
WHERE pk.attacker_steam_id IS NOT NULL
AND pk."with" IS NOT NULL
GROUP BY pk.attacker_steam_id, pk.match_id, pk."with";

CREATE OR REPLACE VIEW public.v_player_weapon_match_damage AS
SELECT
pd.attacker_steam_id AS player_steam_id,
pd.match_id,
pd."with" AS "with",
SUM(pd.damage)::bigint AS damage,
COUNT(*)::bigint AS hits
FROM player_damages pd
WHERE pd.attacker_steam_id IS NOT NULL
AND pd."with" IS NOT NULL
AND pd.attacker_team <> pd.attacked_team
GROUP BY pd.attacker_steam_id, pd.match_id, pd."with";
Loading