Compare commits

..

2 Commits

Author SHA1 Message Date
Andrei Stoica 7c21d724e4 api 2024-02-03 20:45:32 -05:00
Andrei Stoica 480c1f4725 refactor db interactions 2024-02-03 13:43:35 -05:00
4 changed files with 140 additions and 45 deletions

View File

@ -3,3 +3,5 @@ click
psycopg2-binary psycopg2-binary
ratelimit ratelimit
backoff backoff
fastapi
python-multipart

55
src/api.py Normal file
View File

@ -0,0 +1,55 @@
from fastapi import FastAPI, status
from transform import get_db_cols
from datetime import datetime
import db
app = FastAPI()
@app.get("/players")
async def get_players():
cols = get_db_cols("profile_meta")
profiles = db.get_all_profiles()
profiles = map(
lambda profile: {cols[i]: profile[i] for i, _ in enumerate(profile)},
profiles,
)
return list(profiles)
@app.get("/players/{player_id}/games")
async def get_player_games(
player_id,
begin: datetime | None = None,
end: datetime | None = None,
):
print(begin)
print(end)
game_ids = db.get_profile_game_ids(player_id, begin=begin, end=end)
print(len(game_ids))
if len(game_ids) == 0:
return status.HTTP_404_NOT_FOUND
return {"game_ids": game_ids}
@app.get("/players/{player_id}/player_stats/")
async def get_player_stats(player_id: str, game_ids_param: str | None = None):
if not game_ids_param or len(game_ids_param) == 0:
game_ids = db.get_profile_game_ids(player_id)
else:
game_ids = [id.strip('" ') for id in game_ids_param.split(",")]
print(len(game_ids))
cols = get_db_cols("player_stats")
stats = db.get_player_stats(game_ids)
print(len(stats))
stats = map(
lambda stat: {cols[i]: stat[i] for i, _ in enumerate(stat)},
stats,
)
return {"player_id": player_id, "player_stats": list(stats)}

View File

@ -32,6 +32,15 @@ def get_all_profile_names(conn=None):
return data return data
@connect_by_default
def get_all_profiles(conn=None):
with conn.cursor() as curs:
curs.execute("SELECT * from data.profile_meta;")
data = curs.fetchall()
return data
@connect_by_default @connect_by_default
def get_profile_game_count(user_id, conn=None): def get_profile_game_count(user_id, conn=None):
with conn.cursor() as curs: with conn.cursor() as curs:
@ -48,18 +57,79 @@ def get_profile_game_count(user_id, conn=None):
@connect_by_default @connect_by_default
def get_profile_game_ids(user_id, conn=None): def get_profile_game_ids(user_id, begin=None, end=None, conn=None):
sql = """
SELECT game_id FROM data.profile_game
WHERE leetify_user_id = %s"""
vals = [user_id]
if begin:
sql += """
AND game_finished_at >= (%s)
"""
vals.append(begin)
if end:
sql += """
AND game_finished_at < (%s)
"""
vals.append(end)
sql += ";"
with conn.cursor() as curs: with conn.cursor() as curs:
curs.execute( curs.execute(sql, (*vals,))
"""SELECT game_id FROM data.profile_game
WHERE leetify_user_id = %s;""",
(user_id,),
)
data = curs.fetchall() data = curs.fetchall()
return [row[0] for row in data] return [row[0] for row in data]
@connect_by_default
def get_player_stats(game_ids, conn=None):
sql = """
SELECT * FROM data.player_stats
WHERE game_id = ANY(%s);
"""
with conn.cursor() as curs:
curs.execute(sql, (game_ids,))
data = curs.fetchall()
return data
@connect_by_default
def insert_player_stats(stats, conn=None):
cols_api, cols_db = get_cols("player_stats")
if type(cols_api) != list or type(cols_db) != list:
raise Exception(
"could not get columns for player_stats:", cols_api, cols_db
)
vals = map(lambda game: vals_in_order(game, cols_api), stats)
with conn.cursor() as curs:
sql = f"""
INSERT into data.player_stats ({', '.join(cols_db)})
VALUES ({', '.join(['%s'] * len(cols_db))}); """
curs.executemany(sql, vals)
conn.commit()
@connect_by_default
def insert_profile_meta(meta, conn=None):
cols_api, cols_db = get_cols("profile_meta")
if type(cols_api) != list or type(cols_db) != list:
raise Exception(
"could not get columns for profile_meta:", cols_api, cols_db
)
vals = vals_in_order(meta, cols_api)
sql = f"""
INSERT INTO data.profile_meta ({', '.join(cols_db)})
VALUES ({', '.join(['%s'] * len(cols_db))});
"""
with conn.cursor() as curs:
curs.execute(sql, vals)
conn.commit()
@connect_by_default @connect_by_default
def insert_profile_games(games, conn=None): def insert_profile_games(games, conn=None):
cols_api, cols_db = get_cols("profile_game") cols_api, cols_db = get_cols("profile_game")
@ -69,11 +139,11 @@ def insert_profile_games(games, conn=None):
) )
vals = map(lambda game: vals_in_order(game, cols_api), games) vals = map(lambda game: vals_in_order(game, cols_api), games)
sql = f"""
INSERT into data.profile_game ({', '.join(cols_db)})
VALUES ({', '.join(['%s'] * len(cols_db))});
"""
with conn.cursor() as curs: with conn.cursor() as curs:
sql = f"""
INSERT into data.profile_game ({', '.join(cols_db)})
VALUES ({', '.join(['%s'] * len(cols_db))});
"""
curs.executemany(sql, vals) curs.executemany(sql, vals)
conn.commit() conn.commit()

View File

@ -4,14 +4,10 @@ from transform import (
meta_from_profile, meta_from_profile,
games_from_profile, games_from_profile,
player_stats_from_game, player_stats_from_game,
vals_in_order,
) )
import db import db
import logging import logging
## TODO seperate out loading from extraction
## this currently handles getting data from api and loading into db
@db.connect_by_default @db.connect_by_default
def extract_profile_meta(id, api=Leetify(), conn=None): def extract_profile_meta(id, api=Leetify(), conn=None):
@ -23,15 +19,8 @@ def extract_profile_meta(id, api=Leetify(), conn=None):
profile = api.get_profile(id) profile = api.get_profile(id)
meta = meta_from_profile(profile) meta = meta_from_profile(profile)
vals = vals_in_order(meta, cols_api)
with conn.cursor() as curs: db.insert_profile_meta(meta, conn=conn)
sql = f"""
INSERT INTO data.profile_meta ({', '.join(cols_db)})
VALUES ({', '.join(['%s'] * len(cols_db))});
"""
curs.execute(sql, vals)
conn.commit()
@db.connect_by_default @db.connect_by_default
@ -43,36 +32,15 @@ def extract_profile_games(profile, conn=None):
) )
games = games_from_profile(profile) games = games_from_profile(profile)
games = map(lambda game: vals_in_order(game, cols_api), games)
with conn.cursor() as curs: db.insert_profile_games(games, conn)
curs.executemany(
f"""
INSERT into data.profile_game ({', '.join(cols_db)})
VALUES ({', '.join(['%s'] * len(cols_db))});
""",
games,
)
conn.commit()
@db.connect_by_default @db.connect_by_default
def extract_player_stats(game, conn=None): def extract_player_stats(game, conn=None):
cols_api, cols_db = get_cols("player_stats")
if type(cols_api) != list or type(cols_db) != list:
raise Exception(
"could not get columns for player_stats:", cols_api, cols_db
)
stats = player_stats_from_game(game) stats = player_stats_from_game(game)
vals = map(lambda game: vals_in_order(game, cols_api), stats)
with conn.cursor() as curs: db.insert_player_stats(stats, conn=conn)
sql = f"""
INSERT into data.player_stats ({', '.join(cols_db)})
VALUES ({', '.join(['%s'] * len(cols_db))}); """
curs.executemany(sql, vals)
conn.commit()
@db.connect_by_default @db.connect_by_default