This commit is contained in:
NotSoToothless
2026-06-18 02:39:21 -07:00
committed by GitHub
parent 32e747212f
commit d490c1c8d5
4 changed files with 41 additions and 11 deletions
+27 -5
View File
@@ -27,11 +27,11 @@ CREATE TABLE IF NOT EXISTS match_logs (
session_id TEXT PRIMARY KEY, session_id TEXT PRIMARY KEY,
chat_log_json TEXT, chat_log_json TEXT,
battle_log_json TEXT, battle_log_json TEXT,
event_log_json TEXT,
built_unix INTEGER built_unix INTEGER
) )
""" """
def _fmt_time(ms: int) -> str: def _fmt_time(ms: int) -> str:
total_s = int(ms) // 1000 total_s = int(ms) // 1000
return f"{total_s // 60:02d}:{total_s % 60:02d}" return f"{total_s // 60:02d}:{total_s % 60:02d}"
@@ -49,6 +49,17 @@ def _decompress_events(raw_events: Any) -> dict:
return raw_events or {} return raw_events or {}
def build_event_log(game: dict[str, Any]) -> dict[str, Any]:
"""Return the raw event slices the website needs for per-unit state."""
events = _decompress_events(game.get("events", {}))
if not isinstance(events, dict):
return {"kills": [], "damage": []}
return {
"kills": list(events.get("kills") or []),
"damage": list(events.get("damage") or []),
}
def _strip_tag(tag: str) -> str: def _strip_tag(tag: str) -> str:
s = (tag or "").strip() s = (tag or "").strip()
if len(s) >= 3 and not s[0].isalnum() and not s[-1].isalnum(): if len(s) >= 3 and not s[0].isalnum() and not s[-1].isalnum():
@@ -166,19 +177,30 @@ def build_match_logs(game: dict[str, Any]) -> tuple[list[str], list[str]]:
async def upsert_match_logs( async def upsert_match_logs(
db_path, session_id: str, chat_log: list[str], battle_log: list[str] db_path,
session_id: str,
chat_log: list[str],
battle_log: list[str],
event_log: dict[str, Any] | None = None,
) -> None: ) -> None:
import time import time
async with aiosqlite.connect(db_path) as conn: async with aiosqlite.connect(db_path) as conn:
await conn.execute(MATCH_LOGS_SQL) await conn.execute(MATCH_LOGS_SQL)
try:
await conn.execute("ALTER TABLE match_logs ADD COLUMN event_log_json TEXT")
except Exception:
pass
await conn.execute( await conn.execute(
"""INSERT INTO match_logs (session_id, chat_log_json, battle_log_json, built_unix) """INSERT INTO match_logs (session_id, chat_log_json, battle_log_json, event_log_json, built_unix)
VALUES (?, ?, ?, ?) VALUES (?, ?, ?, ?, ?)
ON CONFLICT(session_id) DO UPDATE SET ON CONFLICT(session_id) DO UPDATE SET
chat_log_json=excluded.chat_log_json, chat_log_json=excluded.chat_log_json,
battle_log_json=excluded.battle_log_json, battle_log_json=excluded.battle_log_json,
event_log_json=excluded.event_log_json,
built_unix=excluded.built_unix""", built_unix=excluded.built_unix""",
(str(session_id), json.dumps(chat_log, ensure_ascii=False), (str(session_id), json.dumps(chat_log, ensure_ascii=False),
json.dumps(battle_log, ensure_ascii=False), int(time.time())), json.dumps(battle_log, ensure_ascii=False),
json.dumps(event_log or {"kills": [], "damage": []}, ensure_ascii=False),
int(time.time())),
) )
await conn.commit() await conn.commit()
+4 -3
View File
@@ -13,7 +13,7 @@ ROOT = pathlib.Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT)) sys.path.insert(0, str(ROOT))
sys.path.insert(0, str(ROOT.parent / "SHARED")) sys.path.insert(0, str(ROOT.parent / "SHARED"))
from BOT.match_logs import build_match_logs, upsert_match_logs, MATCH_LOGS_SQL from BOT.match_logs import build_event_log, build_match_logs, upsert_match_logs, MATCH_LOGS_SQL
from BOT.storage import TSS_BATTLES_DB_PATH from BOT.storage import TSS_BATTLES_DB_PATH
REPLAYS = pathlib.Path(os.environ["STORAGE_VOL_PATH"]) / "REPLAYS" / "TSS" REPLAYS = pathlib.Path(os.environ["STORAGE_VOL_PATH"]) / "REPLAYS" / "TSS"
@@ -36,10 +36,11 @@ async def main(dry_run: bool) -> None:
print(f" skip {sid}: {exc}") print(f" skip {sid}: {exc}")
continue continue
chat, battle = build_match_logs(game) chat, battle = build_match_logs(game)
event_log = build_event_log(game)
if dry_run: if dry_run:
print(f" {sid}: chat={len(chat)} battle={len(battle)}") print(f" {sid}: chat={len(chat)} battle={len(battle)} kills={len(event_log.get('kills') or [])}")
else: else:
await upsert_match_logs(TSS_BATTLES_DB_PATH, sid, chat, battle) await upsert_match_logs(TSS_BATTLES_DB_PATH, sid, chat, battle, event_log)
done += 1 done += 1
print(f"{'Would backfill' if dry_run else 'Backfilled'} " print(f"{'Would backfill' if dry_run else 'Backfilled'} "
f"{len(files) if dry_run else done} sessions") f"{len(files) if dry_run else done} sessions")
+8 -1
View File
@@ -4,7 +4,7 @@ import pathlib
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1])) sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1]))
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[2] / "SHARED")) sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[2] / "SHARED"))
from BOT.match_logs import build_match_logs from BOT.match_logs import build_event_log, build_match_logs
def _game(): def _game():
@@ -53,8 +53,15 @@ def test_events_base85_zstd_compressed():
assert battle and "destroyed" in battle[0] assert battle and "destroyed" in battle[0]
def test_event_log_preserves_kill_victim_unit():
event_log = build_event_log(_game())
assert event_log["kills"][0]["offended_uid"] == 2
assert event_log["kills"][0]["offended_unit"] == "germ_pz_iv"
if __name__ == "__main__": if __name__ == "__main__":
test_chat_log_format() test_chat_log_format()
test_battle_log_kill_prefix_and_text() test_battle_log_kill_prefix_and_text()
test_events_base85_zstd_compressed() test_events_base85_zstd_compressed()
test_event_log_preserves_kill_victim_unit()
print("ALL TESTS PASSED") print("ALL TESTS PASSED")
+2 -2
View File
@@ -164,10 +164,10 @@ async def _handle_game(game: Dict[str, Any]) -> None:
await insert_match(game) await insert_match(game)
await insert_player_games(game) await insert_player_games(game)
await upsert_tss_teams(game) await upsert_tss_teams(game)
from BOT.match_logs import build_match_logs, upsert_match_logs from BOT.match_logs import build_event_log, build_match_logs, upsert_match_logs
from BOT.storage import TSS_BATTLES_DB_PATH from BOT.storage import TSS_BATTLES_DB_PATH
chat_log, battle_log = build_match_logs(game) chat_log, battle_log = build_match_logs(game)
await upsert_match_logs(TSS_BATTLES_DB_PATH, sid, chat_log, battle_log) await upsert_match_logs(TSS_BATTLES_DB_PATH, sid, chat_log, battle_log, build_event_log(game))
log.info("Stored game %s in DB", sid) log.info("Stored game %s in DB", sid)
except Exception as exc: except Exception as exc:
log.error("DB insert failed for %s: %s", sid, exc) log.error("DB insert failed for %s: %s", sid, exc)