91 lines
3.4 KiB
Python
91 lines
3.4 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""Take screenshots of specific game states by writing synthetic game-state.json."""
|
||
|
|
import json, os, sys, time, subprocess
|
||
|
|
from datetime import datetime, timezone
|
||
|
|
from playwright.sync_api import sync_playwright
|
||
|
|
|
||
|
|
SITE_DIR = os.path.join(os.path.dirname(__file__), "site")
|
||
|
|
STATE_PATH = os.path.join(SITE_DIR, "game-state.json")
|
||
|
|
SCREENSHOTS_DIR = os.path.join(os.path.dirname(__file__), "screenshots")
|
||
|
|
os.makedirs(SCREENSHOTS_DIR, exist_ok=True)
|
||
|
|
sys.path.insert(0, os.path.dirname(__file__))
|
||
|
|
|
||
|
|
from monop_parser import MonopParser
|
||
|
|
_p = MonopParser()
|
||
|
|
_p.parse_line("2026-01-01 00:00:00\tmonop\tHow many players? ")
|
||
|
|
_p.parse_line("2026-01-01 00:00:00\talice\t3")
|
||
|
|
SQUARES = _p.get_state()["squares"]
|
||
|
|
|
||
|
|
def make_player(name, number, money, location, properties=None, inJail=False, bankrupt=False):
|
||
|
|
d = {
|
||
|
|
"name": name, "number": number, "money": money, "location": location,
|
||
|
|
"inJail": inJail, "jailTurns": 0, "doublesCount": 0,
|
||
|
|
"getOutOfJailFreeCards": 0, "properties": properties or [],
|
||
|
|
}
|
||
|
|
if bankrupt:
|
||
|
|
d["bankrupt"] = True
|
||
|
|
return d
|
||
|
|
|
||
|
|
def write_state(state):
|
||
|
|
state["lastUpdated"] = datetime.now(timezone.utc).isoformat()
|
||
|
|
state.setdefault("squares", SQUARES)
|
||
|
|
with open(STATE_PATH, "w") as f:
|
||
|
|
json.dump(state, f, indent=2)
|
||
|
|
|
||
|
|
def take_screenshot(page, name):
|
||
|
|
page.goto("http://localhost:9998")
|
||
|
|
page.wait_for_timeout(4000)
|
||
|
|
path = os.path.join(SCREENSHOTS_DIR, f"{name}.png")
|
||
|
|
page.screenshot(path=path, full_page=True)
|
||
|
|
print(f"[screenshot] {path}")
|
||
|
|
|
||
|
|
def main():
|
||
|
|
server = subprocess.Popen(
|
||
|
|
[sys.executable, "-m", "http.server", "9998", "--directory", SITE_DIR],
|
||
|
|
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
|
||
|
|
)
|
||
|
|
time.sleep(1)
|
||
|
|
|
||
|
|
try:
|
||
|
|
with sync_playwright() as p:
|
||
|
|
browser = p.chromium.launch()
|
||
|
|
page = browser.new_page(viewport={"width": 1280, "height": 1600})
|
||
|
|
|
||
|
|
# 1: Single player joined during setup
|
||
|
|
write_state({
|
||
|
|
"players": [make_player("alice", 1, 1500, 0)],
|
||
|
|
"currentPlayer": None,
|
||
|
|
"log": [
|
||
|
|
{"text": "Game for 3 players", "player": None, "timestamp": "2026-01-01 00:00:00"},
|
||
|
|
{"text": "alice joined the game", "player": "alice", "timestamp": "2026-01-01 00:00:01"},
|
||
|
|
],
|
||
|
|
"phase": "setup",
|
||
|
|
"numPlayersExpected": 3,
|
||
|
|
})
|
||
|
|
take_screenshot(page, "single_player_joined")
|
||
|
|
|
||
|
|
# 2: Game over — players bankrupt
|
||
|
|
write_state({
|
||
|
|
"players": [
|
||
|
|
make_player("alice", 1, 4200, 24, [1, 3, 5, 11, 13, 14, 15, 21, 23, 24, 25, 37, 39]),
|
||
|
|
make_player("bob", 2, 0, 18, bankrupt=True),
|
||
|
|
make_player("charlie", 3, 0, 6, bankrupt=True),
|
||
|
|
],
|
||
|
|
"currentPlayer": 1,
|
||
|
|
"log": [
|
||
|
|
{"text": "bob is bankrupt!", "player": "bob", "timestamp": "2026-01-01 01:30:00"},
|
||
|
|
{"text": "charlie is bankrupt!", "player": "charlie", "timestamp": "2026-01-01 01:45:00"},
|
||
|
|
{"text": "alice WINS!", "player": "alice", "timestamp": "2026-01-01 01:45:01"},
|
||
|
|
],
|
||
|
|
"phase": "over",
|
||
|
|
})
|
||
|
|
take_screenshot(page, "player_bankrupt_game_over")
|
||
|
|
|
||
|
|
browser.close()
|
||
|
|
finally:
|
||
|
|
server.terminate()
|
||
|
|
server.wait()
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
main()
|