Skip to content

Commit

Permalink
Start an emu cup analysis script (#265)
Browse files Browse the repository at this point in the history
- **Add emu cup analysis script**
- **Only include play actions**
- **Pull logic into GameLogEventData**
  • Loading branch information
shaldengeki authored Jul 21, 2024
1 parent 557b5af commit 782c6bf
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"uid": "669cd9fd255eb",
"type": "chooseActionCard",
"log": "${player_name} chooses action card ${action_card_name}${action_card_icon}${action_card_level} with strength ${strength_icon}${strength}",
"args": {"actionCard": {"id": 4, "strength": 5, "pId": 93481498, "extraDatas": null, "type": "Association", "status": 1, "level": 1}, "strength": 5, "player_name": "Darcelmaw", "player_id": 93481498, "i18n": ["action_card_name"], "action_card_name": "Association", "action_card_level": "I", "action_card_icon": "", "action_card_type": "Association", "preserve": ["action_card_type"], "strength_icon": ""},
"lock_uuid": null,
"synchro": null,
"h": "939340"
}
12 changes: 12 additions & 0 deletions ark_nova_stats/bga_log_parser/fixtures/play_event.log.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"uid": "669cd3629ee68",
"type": "buyAnimal",
"log": "${player_name} plays ${card_name} for ${amount_money} and places it in ${building_name}",
"args": {"card": {"id": "A445_CrestedPorcupine", "location": "inPlay", "state": 19, "pId": 94929538, "extraDatas": null}, "amount": 8, "amount_money": 8, "total": 5, "building": {"id": 8, "location": "board", "state": 1, "pId": 94929538, "type": "size-1", "x": 1, "y": 8, "rotation": 0}, "icons": {"Bird": 1, "Predator": 1, "Herbivore": 1, "Bear": 1, "Reptile": 1, "Pet": 0, "Primate": 0, "Africa": 0, "Europe": 1, "Asia": 1, "Americas": 1, "Australia": 0, "Partner-Zoo": 0, "AnimalsII": 0, "CardsII": 0, "Science": 1, "Fac": 0, "Rock": 2, "Water": 2, "SeaAnimal": 0}, "fromDisplay": false, "player_name": "Duci9", "player_id": 94929538, "i18n": ["building_name", "card_name"], "building_name": {"log": "a size-${n} enclosure", "args": {"n": 1}},
"card_id": "A445_CrestedPorcupine",
"card_name": "Crested Porcupine",
"preserve": ["card_id"]},
"lock_uuid": "one",
"synchro": "one",
"h": "08137c"
}
19 changes: 17 additions & 2 deletions ark_nova_stats/bga_log_parser/game_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,35 @@ class GameLogEventData:
synchro: Optional[int] = None
h: Optional[str] = None

PLAY_LOGS = [
"plays",
"supports a conservation project",
"and places it in",
"buys",
]

@property
def is_play_action(self) -> bool:
if "card_name" not in self.args:
return False

return any(play_log in self.log for play_log in self.PLAY_LOGS)


@dataclass
class GameLogEvent:
channel: str
table_id: int
packet_id: str
packet_type: str
move_id: int
time: int
data: list[GameLogEventData]
move_id: Optional[int] = None

def __post_init__(self):
self.table_id = int(self.table_id)
self.move_id = int(self.move_id)
if self.move_id is not None:
self.move_id = int(self.move_id)
self.time = int(self.time)
self.data = [GameLogEventData(**x) for x in self.data] # type: ignore

Expand Down
26 changes: 25 additions & 1 deletion ark_nova_stats/bga_log_parser/game_log_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import pytest
from python.runfiles import Runfiles

from ark_nova_stats.bga_log_parser.game_log import GameLog
from ark_nova_stats.bga_log_parser.game_log import GameLog, GameLogEventData


class TestGameLog:
Expand All @@ -28,5 +28,29 @@ def test_parses_sample_game(self):
assert x.winner is not None and "sorryimlikethis" == x.winner.name


class TestGameLogEventData:
def test_is_play_event_returns_true_for_play_action(self):
r = Runfiles.Create()
play_event_fixture = r.Rlocation(
"_main/ark_nova_stats/bga_log_parser/fixtures/play_event.log.json"
)
with open(play_event_fixture, "r") as play_event_logfile:
play_log = json.loads(play_event_logfile.read().strip())

x = GameLogEventData(**play_log)
assert x.is_play_action

def test_is_play_event_returns_false_for_other_actions(self):
r = Runfiles.Create()
non_play_event_fixture = r.Rlocation(
"_main/ark_nova_stats/bga_log_parser/fixtures/non_play_event.log.json"
)
with open(non_play_event_fixture, "r") as non_play_event_logfile:
non_play_log = json.loads(non_play_event_logfile.read().strip())

x = GameLogEventData(**non_play_log)
assert not x.is_play_action


if __name__ == "__main__":
sys.exit(pytest.main([__file__] + sys.argv[1:]))
17 changes: 17 additions & 0 deletions ark_nova_stats/emu_cup/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
load("@rules_python//python:defs.bzl", "py_binary")

filegroup(
name = "game_data",
srcs = glob(["data/*.json"]),
)

py_binary(
name = "analyze_games",
srcs = ["analyze_games.py"],
data = [":game_data"],
visibility = ["//:__subpackages__"],
deps = [
"//ark_nova_stats/bga_log_parser:game_log",
"@rules_python//python/runfiles",
],
)
51 changes: 51 additions & 0 deletions ark_nova_stats/emu_cup/analyze_games.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env python3

import json
from collections import Counter
from pathlib import Path
from typing import Iterator

from python.runfiles import Runfiles

from ark_nova_stats.bga_log_parser.game_log import GameLog


def list_game_datafiles() -> Iterator[Path]:
r = Runfiles.Create()
known_game = Path(
r.Rlocation(
"_main/ark_nova_stats/emu_cup/data/539682665_sorryimlikethis_darcelmaw.json"
)
)
return known_game.parent.glob("*.json")


def main() -> int:
all_cards: Counter[str] = Counter()
event_logs: set[str] = set()
skipped_event_logs: set[str] = set()

for p in list_game_datafiles():
# print(p)
with open(p, "r") as f:
log = GameLog(**json.loads(f.read().strip()))

game_cards = set()
for event in log.data.logs:
for event_data in event.data:
if not event_data.is_play_action:
continue

game_cards.add(event_data.args["card_name"])

all_cards.update(game_cards)

print("Most common cards:")
for card, count in all_cards.most_common(10):
print(f" - {card}: {count}")

return 0


if __name__ == "__main__":
raise SystemExit(main())
1 change: 1 addition & 0 deletions ark_nova_stats/emu_cup/data/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.json
Empty file.

0 comments on commit 782c6bf

Please sign in to comment.