aboutsummaryrefslogtreecommitdiff
path: root/api/user/games.py
blob: 1cd19f26790444d4719b05b8188aeff414fb1c91 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
from flask import Blueprint, request
from functools import reduce
from mergedeep import merge
from db import cursor
from auth.login_token import token_login
from user.info import format_user
from ruleset import resolve_ruleset
import json

def outcome(outcome_str, player_1):
    outcome_int = { "w": 1, "l": -1, "d": 0 }[outcome_str]
    if not player_1: outcome_int *= -1
    return { 1: "w", -1: "l", 0: "d" }[outcome_int]

def game_info(game_id, user_id = None):
    game = cursor.execute("select " + ", ".join([
        "game_id",               # 0
        "parent_game",           # 1
        "moves",                 # 2
        "player_1_id",           # 3
        "player_2_id",           # 4
        "outcome",               # 5
        "created",               # 6
        "started",               # 7
        "duration",              # 8
        "rating_delta_player_1", # 9
        "rating_delta_player_2", # 10
        "ruleset",               # 11
        "status",                # 12
        "private",               # 13
        ]) + " from games where game_id = ?", [game_id]).fetchone()
    is_player_1 = game[4] != user_id
    opponent = game[4] if is_player_1 else game[3]
    return {
        "id": game[0],
        "parent": game[1],
        "moves": [] if len(game[2]) == 0 else [int(move) for move in str(game[2] + "0").split(",")],
        "opponent": None if not opponent else format_user(opponent),
        "outcome": None if not game[5] else outcome(game[5], is_player_1),
        "created": game[6],
        "started": game[7],
        "duration": game[8],
        "rating": game[9] if is_player_1 else game[10],
        "rating_opponent": game[10] if is_player_1 else game[9],
        "ruleset": resolve_ruleset(game[11]),
        "status": game[12],
        "private": bool(game[13]),
    }

def sum_games(user_id): #! SANITIZE USER_ID FIRST
    wld_querys = [' '.join([
        "select count(game_id)",
        "from games",
        "where",
        f"player_{x[0]}_id = \"{user_id}\" and",
        f"outcome = \"{x[1]}\"",
    ]) for x in [(1, "w"), (1, "l"), (2, "w"), (2, "l")]]
    wld_querys.insert(0, ' '.join([
        "select count(game_id)",
        "from games",
        "where",
        f"(player_1_id = \"{user_id}\" or player_2_id = \"{user_id}\") and",
        "outcome = \"d\"",
    ]))

    big_query = "select " + ", ".join([f"({query})" for query in wld_querys])

    results = cursor.execute(big_query).fetchone()

    return {
            "draw": results[0],
            "win": results[1] + results[4],
            "lose": results[2] + results[3],
            "games": reduce(lambda a, b: a + b, results)
    }

def fetch_games(user_id, count):
    game_ids = cursor.execute("select game_id from games where player_1_id = ? or player_2_id = ? order by created desc", [user_id, user_id]).fetchmany(count)
    export = []

    for game_id in game_ids:
        export.append(game_info(game_id[0], user_id))

    return export

games = Blueprint('games', __name__)

@games.route('/games', methods = ['GET', 'POST'])
def index():
    data_string = request.data or "{}"
    data = json.loads(data_string)

    user_id = data.get("id") or ""
    token = request.cookies.get("token") or ""

    if not user_id and \
       not token:
           return "", 400

    if token and not user_id:
        user_id = token_login(token)

    if not cursor.execute("select user_id from users where user_id = ?", [user_id]).fetchone(): return "", 403

    export = {}
    merge(export,
          {"totals": sum_games(user_id)},
          {"games": fetch_games(user_id, 20)})

    return export, 200

dynamic_route = ["/user", games]