From a0242818e0074b79374eca88bb11a6dfae009d6f Mon Sep 17 00:00:00 2001 From: Charles OuGuo Date: Sat, 20 Jul 2024 16:24:44 -0400 Subject: [PATCH] Pull log parser out of API (#260) --- ark_nova_stats/api/gql/types/BUILD.bazel | 1 + ark_nova_stats/api/gql/types/game_log.py | 5 +- ark_nova_stats/api/tests/BUILD.bazel | 7 +-- ark_nova_stats/api/tests/game_log_test.py | 2 +- ark_nova_stats/bga_log_parser/BUILD.bazel | 24 +++++++++ ark_nova_stats/bga_log_parser/__init__.py | 0 .../fixtures/sample_game.log.json | 0 ark_nova_stats/bga_log_parser/game_log.py | 54 +++++++++++++++++++ .../bga_log_parser/game_log_test.py | 23 ++++++++ ark_nova_stats/models.py | 49 ----------------- 10 files changed, 107 insertions(+), 58 deletions(-) create mode 100644 ark_nova_stats/bga_log_parser/BUILD.bazel create mode 100644 ark_nova_stats/bga_log_parser/__init__.py rename ark_nova_stats/{api/tests => bga_log_parser}/fixtures/sample_game.log.json (100%) create mode 100644 ark_nova_stats/bga_log_parser/game_log.py create mode 100644 ark_nova_stats/bga_log_parser/game_log_test.py diff --git a/ark_nova_stats/api/gql/types/BUILD.bazel b/ark_nova_stats/api/gql/types/BUILD.bazel index aabd7d6f..d0243c21 100644 --- a/ark_nova_stats/api/gql/types/BUILD.bazel +++ b/ark_nova_stats/api/gql/types/BUILD.bazel @@ -7,6 +7,7 @@ py_library( deps = [ "//ark_nova_stats:config_py", "//ark_nova_stats:models_py", + "//ark_nova_stats/bga_log_parser:game_log", "@py_deps//flask", "@py_deps//graphql_core", ], diff --git a/ark_nova_stats/api/gql/types/game_log.py b/ark_nova_stats/api/gql/types/game_log.py index e24e20b9..81ab37be 100644 --- a/ark_nova_stats/api/gql/types/game_log.py +++ b/ark_nova_stats/api/gql/types/game_log.py @@ -11,8 +11,9 @@ GraphQLString, ) +from ark_nova_stats.bga_log_parser.game_log import GameLog as ParsedGameLog from ark_nova_stats.config import app, db -from ark_nova_stats.models import GameLog, GameLogContainerJSON +from ark_nova_stats.models import GameLog def game_log_fields() -> dict[str, GraphQLField]: @@ -62,7 +63,7 @@ def submit_game_logs( args: dict[str, Any], ) -> GameLog: json_logs = json.loads(args["logs"]) - parsed_logs = GameLogContainerJSON(**json_logs) + parsed_logs = ParsedGameLog(**json_logs) # For now, just store the literal log string. log = GameLog(log=args["logs"]) diff --git a/ark_nova_stats/api/tests/BUILD.bazel b/ark_nova_stats/api/tests/BUILD.bazel index ad02764e..86dea046 100644 --- a/ark_nova_stats/api/tests/BUILD.bazel +++ b/ark_nova_stats/api/tests/BUILD.bazel @@ -11,16 +11,11 @@ py_library( ], ) -filegroup( - name = "fixture_files", - srcs = glob(["fixtures/*"]), -) - py_test( name = "game_log_test", srcs = ["game_log_test.py"], data = [ - ":fixture_files", + "//ark_nova_stats/bga_log_parser:fixtures", ], deps = [ ":fixtures", diff --git a/ark_nova_stats/api/tests/game_log_test.py b/ark_nova_stats/api/tests/game_log_test.py index 8ecb8956..f8c3a70f 100644 --- a/ark_nova_stats/api/tests/game_log_test.py +++ b/ark_nova_stats/api/tests/game_log_test.py @@ -11,7 +11,7 @@ def test_submit_game_logs(client: FlaskClient) -> None: r = Runfiles.Create() sample_game_fixture = r.Rlocation( - "_main/ark_nova_stats/api/tests/fixtures/sample_game.log.json" + "_main/ark_nova_stats/bga_log_parser/fixtures/sample_game.log.json" ) with open(sample_game_fixture, "r") as sample_game_logfile: game_log = sample_game_logfile.read().strip() diff --git a/ark_nova_stats/bga_log_parser/BUILD.bazel b/ark_nova_stats/bga_log_parser/BUILD.bazel new file mode 100644 index 00000000..284f53d2 --- /dev/null +++ b/ark_nova_stats/bga_log_parser/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_python//python:defs.bzl", "py_library", "py_test") + +filegroup( + name = "fixtures", + srcs = glob(["fixtures/*"]), + visibility = ["//ark_nova_stats:__subpackages__"], +) + +py_library( + name = "game_log", + srcs = ["game_log.py"], + visibility = ["//:__subpackages__"], +) + +py_test( + name = "game_log_test", + srcs = ["game_log_test.py"], + data = [":fixtures"], + deps = [ + ":game_log", + "@py_deps//pytest", + "@rules_python//python/runfiles", + ], +) diff --git a/ark_nova_stats/bga_log_parser/__init__.py b/ark_nova_stats/bga_log_parser/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ark_nova_stats/api/tests/fixtures/sample_game.log.json b/ark_nova_stats/bga_log_parser/fixtures/sample_game.log.json similarity index 100% rename from ark_nova_stats/api/tests/fixtures/sample_game.log.json rename to ark_nova_stats/bga_log_parser/fixtures/sample_game.log.json diff --git a/ark_nova_stats/bga_log_parser/game_log.py b/ark_nova_stats/bga_log_parser/game_log.py new file mode 100644 index 00000000..3b162583 --- /dev/null +++ b/ark_nova_stats/bga_log_parser/game_log.py @@ -0,0 +1,54 @@ +from dataclasses import dataclass +from typing import Optional + + +@dataclass +class GameLogEntryData: + uid: str + type: str + log: str + args: dict + lock_uuid: Optional[str] = None + synchro: Optional[int] = None + h: Optional[str] = None + + +@dataclass +class GameLogEntry: + channel: str + table_id: str + packet_id: str + packet_type: str + move_id: str + time: str + data: list[GameLogEntryData] + + def __post_init__(self): + self.data = [GameLogEntryData(**x) for x in self.data] # type: ignore + + +@dataclass +class GameLogPlayer: + id: int + color: str + name: str + avatar: str + + +@dataclass +class GameLogData: + logs: list[GameLogEntry] + players: list[GameLogPlayer] + + def __post_init__(self): + self.players = [GameLogPlayer(**x) for x in self.players] # type: ignore + self.logs = [GameLogEntry(**x) for x in self.logs] # type: ignore + + +@dataclass +class GameLog: + status: int + data: GameLogData + + def __post_init__(self): + self.data = GameLogData(**self.data) # type: ignore diff --git a/ark_nova_stats/bga_log_parser/game_log_test.py b/ark_nova_stats/bga_log_parser/game_log_test.py new file mode 100644 index 00000000..76847f85 --- /dev/null +++ b/ark_nova_stats/bga_log_parser/game_log_test.py @@ -0,0 +1,23 @@ +import json +import sys + +import pytest +from python.runfiles import Runfiles + +from ark_nova_stats.bga_log_parser.game_log import GameLog + + +class TestGameLog: + def test_parses_sample_game(self): + r = Runfiles.Create() + sample_game_fixture = r.Rlocation( + "_main/ark_nova_stats/bga_log_parser/fixtures/sample_game.log.json" + ) + with open(sample_game_fixture, "r") as sample_game_logfile: + game_log = json.loads(sample_game_logfile.read().strip()) + + x = GameLog(**game_log) + + +if __name__ == "__main__": + sys.exit(pytest.main([__file__] + sys.argv[1:])) diff --git a/ark_nova_stats/models.py b/ark_nova_stats/models.py index 730c7144..d7cdf8af 100644 --- a/ark_nova_stats/models.py +++ b/ark_nova_stats/models.py @@ -15,55 +15,6 @@ from ark_nova_stats.config import db -@dataclasses.dataclass -class GameLogDataLogDataJSON: - uid: str - type: str - log: str - synchro: int - args: dict - - -@dataclasses.dataclass -class GameLogDataLogJSON: - channel: str - table_id: str - packet_id: str - packet_type: str - move_id: str - time: str - data: list[GameLogDataLogDataJSON] - - def __post_init__(self): - self.data = [GameLogDataLogDataJSON(**x) for x in self.data] # type: ignore - - -@dataclasses.dataclass -class GameLogDataPlayerJSON: - id: int - color: str - name: str - avatar: str - - -@dataclasses.dataclass -class GameLogDataJSON: - logs: list - players: list[GameLogDataPlayerJSON] - - def __post_init__(self): - self.players = [GameLogDataPlayerJSON(**x) for x in self.players] # type: ignore - - -@dataclasses.dataclass -class GameLogContainerJSON: - status: int - data: GameLogDataJSON - - def __post_init__(self): - self.data = GameLogDataJSON(**self.data) # type: ignore - - class GameLog(db.Model): __tablename__ = "game_logs"