Skip to content

Latest commit

 

History

History
232 lines (215 loc) · 7.05 KB

README.md

File metadata and controls

232 lines (215 loc) · 7.05 KB

ctm-stats-import

This repository imports CTM CSV stats to a Database structure in your local supabase.

This is the database schema you need to import. You can do it in the SQL Editor.

create table
  public.players (
    id serial,
    name character varying(255) not null,
    profile_picture_url text null,
    twitch_url text null,
    constraint players_pkey primary key (id),
    constraint players_name_key unique (name)
  ) tablespace pg_default;

create table
  public.events (
    id serial,
    name character varying(255) not null,
    year smallint not null,
    constraint events_pkey primary key (id),
    constraint unique_event_name unique (name)
  ) tablespace pg_default;

create table
  public.matches (
    id serial,
    event_id integer not null,
    winner_id integer not null,
    loser_id integer not null,
    constraint matches_pkey primary key (id),
    constraint matches_loser_id_fkey foreign key (loser_id) references players (id),
    constraint matches_winner_id_fkey foreign key (winner_id) references players (id),
    constraint matches_event_id_fkey foreign key (event_id) references events (id)
  ) tablespace pg_default;

create table
  public.tetris_games (
    id serial,
    match_id integer not null,
    player_id integer not null,
    game_number integer not null,
    playstyle character varying(50) not null,
    game_result boolean not null,
    total_lines integer null,
    final_score integer null,
    start_19l integer null,
    trans_19 integer null,
    post_score_19 integer null,
    start_29l integer null,
    trans_29 integer null,
    lines_29 integer null,
    score_29 integer null,
    no_m_lines integer null,
    no_m_score integer null,
    topout_type character varying(255) not null,
    cap character varying(10) not null,
    sps boolean not null,
    level_start integer not null,
    round character varying(255) not null,
    game_link text null,
    match_pairing character varying(10) not null,
    opponent_id integer null,
    constraint tetris_games_pkey primary key (id),
    constraint tetris_games_match_id_fkey foreign key (match_id) references matches (id),
    constraint tetris_games_player_id_fkey foreign key (player_id) references players (id),
    constraint tetris_games_opponent_id_fkey foreign key (opponent_id) references players (id)
  ) tablespace pg_default;

You also need to create these Functions.

-- lifetime_stats
CREATE OR REPLACE FUNCTION lifetime_stats()
RETURNS TABLE (
  id INT,
  name VARCHAR(255),
  profile_picture_url TEXT,
  twitch_url TEXT,
  games_won INT,
  total_games INT,
  maxout_games INT,
  winning_percentage NUMERIC
) AS $$
BEGIN
  RETURN QUERY
  SELECT
      p.id,
      p.name,
      p.profile_picture_url,
      p.twitch_url,
      COUNT(tg.game_result = true or NULL)::integer AS games_won,
      SUM(CASE WHEN tg.final_score >= 1000000 THEN 1 ELSE 0 END)::integer AS maxout_games,
      COUNT(*)::integer AS total_games,
      CASE
        WHEN COUNT(*) > 0 THEN COUNT(tg.game_result = true or NULL) * 100.0 / NULLIF(COUNT(*), 0)
        ELSE 0
      END AS winning_percentage
    FROM
      players p
      LEFT JOIN tetris_games tg ON p.id = tg.player_id
    GROUP BY
      p.id, p.name, p.profile_picture_url, p.twitch_url;
  RETURN;
END;
$$ LANGUAGE plpgsql;
--- year stats, sames as previous one but with a year filter
CREATE OR REPLACE FUNCTION year_stats(
  IN event_year_param INT
)
RETURNS TABLE (
  id INT,
  name VARCHAR(255),
  profile_picture_url TEXT,
  twitch_url TEXT,
  games_won INT,
  total_games INT,
  maxout_games INT,
  winning_percentage NUMERIC
) AS $$
BEGIN
  RETURN QUERY
  SELECT
      p.id,
      p.name,
      p.profile_picture_url,
      p.twitch_url,
      COUNT(tg.game_result = true or NULL)::integer AS games_won,
      SUM(CASE WHEN tg.final_score >= 1000000 THEN 1 ELSE 0 END)::integer AS maxout_games,
      COUNT(*)::integer AS total_games,
      CASE
        WHEN COUNT(*) > 0 THEN COUNT(tg.game_result = true or NULL) * 100.0 / NULLIF(COUNT(*), 0)
        ELSE 0
      END AS winning_percentage
    FROM
      players p
      LEFT JOIN tetris_games tg ON p.id = tg.player_id
      LEFT JOIN matches m ON m.id = tg.match_id
      LEFT JOIN events e ON e.id = m.event_id
    WHERE
      e.year = event_year_param
    GROUP BY
      p.id, p.name, p.profile_picture_url, p.twitch_url;
  RETURN;
END;
$$ LANGUAGE plpgsql;
-- player vs player function
CREATE OR REPLACE FUNCTION get_player_v_player_results(
    player1_id INT,
    player2_id INT
)
RETURNS TABLE (
    match_id INT,
    game_number INT,
    round_max TEXT,
    event_name TEXT,
    player1_style TEXT,
    player1_topout TEXT,
    player1_score INT,
    player1_result TEXT,
    player2_result TEXT,
    player2_score INT,
    player2_topout TEXT,
    player2_style TEXT
)
AS $$
BEGIN
    RETURN QUERY
    SELECT
        tg.match_id,
        tg.game_number,
        MAX(tg.round) AS round_max,
        MAX(e.name) AS event_name,
        MAX(CASE WHEN player_id = 88 THEN playstyle END) AS player1_style,
        MAX(CASE WHEN tg.player_id = player1_id THEN tg.topout_type END) AS player1_topout,
        MAX(CASE WHEN tg.player_id = player1_id THEN tg.final_score END)::integer AS player1_score,
        MAX(CASE WHEN tg.player_id = player1_id THEN CASE WHEN tg.game_result = true THEN 'Win' ELSE 'Loss' END END) AS player1_result,
        MAX(CASE WHEN tg.player_id = player2_id THEN CASE WHEN tg.game_result = true THEN 'Win' ELSE 'Loss' END END) AS player2_result,
        MAX(CASE WHEN tg.player_id = player2_id THEN tg.final_score END)::integer AS player2_score,
        MAX(CASE WHEN tg.player_id = player2_id THEN tg.topout_type END) AS player2_topout,
        MAX(CASE WHEN tg.player_id = player2_id THEN tg.playstyle END) AS player2_style
    FROM
        tetris_games tg
        LEFT JOIN matches m ON m.id = tg.match_id
        LEFT JOIN events e ON e.id = m.event_id
    WHERE
        (tg.player_id = player1_id OR tg.opponent_id = player1_id)
        AND (tg.player_id = player2_id OR tg.opponent_id = player2_id)
    GROUP BY
        tg.match_id, tg.game_number
    ORDER BY
        tg.match_id DESC, tg.game_number DESC;

    RETURN;
END;
$$ LANGUAGE plpgsql;

After your create that structure you have to download the All games CSV and place it in the stats folder with the name Public CTM Masters Match Statistics - All Games.csv.

Execute script

You need to include this .env file in the source of the project.

# these values appear after you run the npx supabase start command
API_URL=http://localhost:54321
GRAPHQL_URL=http://localhost:54321/graphql/v1
DB_URL=postgresql://postgres:postgres@localhost:54322/postgres
STUDIO_URL=http://localhost:54323
INBUCKET_URL=http://localhost:54324
JWT_SECRET=<JWT_SECRET>
SERVICE_ROLE_KEY=<SERVICE_ROLE_KEY>

Once you include that .env file you can execute:

# install dependencies
npm install
# import all data
npm run importData