diff --git a/main.py b/main.py index d9ffabd..944941a 100755 --- a/main.py +++ b/main.py @@ -7,6 +7,7 @@ from pathlib import Path import argparse import json import logging +import re import requests import sqlite3 import sys @@ -100,7 +101,12 @@ def _init_db(conn: sqlite3.Connection): CREATE TABLE IF NOT EXISTS games( id, p1, p2, format, uploadtime, winner, UNIQUE(id) - ) + ); + -- No good way to ensure idempotence for damage; just re-build it. + DROP TABLE IF EXISTS damage; + CREATE TABLE damage(game, player, name, value); + DROP TABLE IF EXISTS indirect_damage; + CREATE TABLE indirect_damage(game, player, name, value); """ ) @@ -110,6 +116,7 @@ def parse_log(game: str, log: str, into: sqlite3.Connection): turn = 0 players = {} + hp = {} # ("p2a: Edward", "p1a: Meteo") # memorises the user of the move that causes environment setting or status, @@ -153,7 +160,12 @@ def parse_log(game: str, log: str, into: sqlite3.Connection): (game, turn, team(player), move, user, target), ) - case ["switch", name, specie, *rest]: + case ["drag", name, specie, status, *rest]: + hp[name] = int(status.split("/")[0]) + + case ["switch", name, specie, status, *rest]: + hp[name] = int(status.split("/")[0]) + player, name = resolve_mon(name) conn.execute( """ @@ -207,8 +219,43 @@ def parse_log(game: str, log: str, into: sqlite3.Connection): LOG.debug(f"{line} <- {last_move}") last_status_set[(mon, cond)] = last_move[0] - case ["-damage", mon, "0 fnt", from_]: + case ["-damage", mon, status]: + # mon takes direct (non-hazard/condition) damage + # status can be a percentage 70/100 with or without condition, + # or "0 fnt" + new_hp = int(re.split("[/ ]", status)[0]) + LOG.debug(f"{mon} dropped to {new_hp} from {hp[mon]}") + LOG.debug(f"source: {last_move}") + + # resolve to damage source + if last_move[1] != mon: + LOG.warn( + f"{mon} took direct damage but last move was not targeted at them" + ) + continue + user = last_move[0] + source_player, source_mon = resolve_mon(user) + + conn.execute( + """ + INSERT INTO damage(game, player, name, value) + VALUES(?, ?, ?, ?) + ON CONFLICT DO NOTHING + """, + (game, team(source_player), source_mon, hp[mon] - new_hp), + ) + + hp[mon] = new_hp + + case ["-damage", mon, status, from_]: + # mon takes indirect damage + # status can be a percentage 70/100 with or without condition, + # or "0 fnt" # mon has fainted from an indirect damage source + # + new_hp = int(re.split("[/ ]", status)[0]) + LOG.debug(f"{mon} dropped to {new_hp} from {from_}") + LOG.debug(f"tracing source for {line}") source = from_.replace("[from] ", "") source_user = None @@ -232,28 +279,41 @@ def parse_log(game: str, log: str, into: sqlite3.Connection): LOG.error(f"missing source for {line}") continue - player, mon = resolve_mon(mon) + player, pkmn = resolve_mon(mon) if source_user.startswith("p1") or source_user.startswith("p2"): - source_player, source_user = resolve_mon(source_user) + source_player, source_mon = resolve_mon(source_user) else: source_player = None - conn.execute( - """ - INSERT INTO indirect_knockouts(game, turn, player, name, source, source_user, source_player) - VALUES(?, ?, ?, ?, ?, ?, ?) - ON CONFLICT DO NOTHING - """, - ( - game, - turn, - team(player), - mon, - source, - source_user, - team(source_player), - ), - ) + if source_player: + conn.execute( + """ + INSERT INTO indirect_damage(game, player, name, value) + VALUES(?, ?, ?, ?) + """, + (game, team(source_player), source_mon, hp[mon] - new_hp), + ) + + if status == "0 fnt": + conn.execute( + """ + INSERT INTO indirect_knockouts(game, turn, player, name, source, source_user, source_player) + VALUES(?, ?, ?, ?, ?, ?, ?) + ON CONFLICT DO NOTHING + """, + ( + game, + turn, + team(player), + pkmn, + source, + source_mon, + team(source_player), + ), + ) + + case ["-heal", mon, status, *rest]: + hp[mon] = int(status.split("/")[0]) case _: # LOG.debug(f"unhandled message {chunks[0]}")