From b162f63ab2e6fa263d7b07ae005f8a07e979f9b5 Mon Sep 17 00:00:00 2001 From: xeals Date: Mon, 27 Mar 2023 23:07:38 +1100 Subject: [PATCH] track indirect knockouts --- main.py | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/main.py b/main.py index 06d7182..d836f7c 100755 --- a/main.py +++ b/main.py @@ -70,6 +70,10 @@ def _init_db(conn: sqlite3.Connection): game, turn, player, name, UNIQUE(game, turn, player) ); + CREATE TABLE IF NOT EXISTS indirect_knockouts( + game, turn, player, name, source, source_user, + UNIQUE(game, turn, player) + ); CREATE TABLE IF NOT EXISTS games( id, p1, p2, format, uploadtime, UNIQUE(id) @@ -84,6 +88,17 @@ def parse_log(game: str, log: str, into: sqlite3.Connection): turn = 0 players = {} + # ("p2a: Edward", "p1a: Meteo") + # memorises the user of the move that causes environment setting or status, + # and its target + last_move: t.Optional[tuple[str, str]] + + # ("p1", "Spikes") => "p2a: Frosslas" + last_env_set: dict[tuple[str, str], str] = {} + + # ("p1a: Meteo", "brn") => "p2a: Edward" + last_status_set: dict[tuple[str, str], str] = {} + def resolve_mon(user: str) -> tuple[str, str]: [player, name] = user.split(": ") return players[player.strip("ab")], name @@ -99,6 +114,7 @@ def parse_log(game: str, log: str, into: sqlite3.Connection): case ["turn", turn]: turn = int(turn) case ["move", user, move, target]: + last_move = (user, target) player, user = resolve_mon(user) _, target = resolve_mon(target) conn.execute( @@ -137,6 +153,53 @@ def parse_log(game: str, log: str, into: sqlite3.Connection): """, (game, turn, player, mon), ) + case ["-sidestart", side, env]: + if not last_move: + LOG.warning(f"missing previous move for {line}") + continue + LOG.debug(f"{line} <- {last_move}") + last_env_set[(side[0:1], env.replace("move: ", ""))] = last_move[0] + case ["-status", mon, cond]: + if not last_move or last_move[1] != mon: + LOG.warning(f"missing previous move for {line}") + continue + LOG.debug(f"{line} <- {last_move}") + last_status_set[(mon, cond)] = last_move[0] + case ["-damage", mon, *rest]: + # rest is new_hp and sometimes a source (if not from a move) + # in a knockout, new_hp is "0 fnt" + if rest[0] == "0 fnt" and len(rest) > 1: + LOG.debug(f"tracing source for {line}") + source = rest[1].replace("[from] ", "") + source_user = None + + if source == "Recoil" or source.startswith("item: "): + source_user = source.replace("item: ", "") + + if source_user: + LOG.debug(f"identified special source {source_user}") + else: + source_user = last_env_set.get((mon[0:1], source)) + + if source_user: + LOG.debug(f"identified hazard source {source_user}") + else: + source_user = last_status_set.get((mon, source)) + + if source_user: + LOG.debug(f"identified move source {source_user}") + else: + LOG.error(f"missing source for {line}") + continue + + conn.execute( + """ + INSERT INTO indirect_knockouts(game, turn, player, name, source, source_user) + VALUES(?, ?, ?, ?, ?, ?) + ON CONFLICT DO NOTHING + """, + (game, turn, player, mon, source, source_user), + ) case _: # LOG.debug(f"unhandled message {chunks[0]}") pass