(self, raw: bytes, players=None)
| 77 | DRAW_JS = DRAW_JS |
| 78 | |
| 79 | def parse(self, raw: bytes, players=None) -> ReplayData: |
| 80 | d = json.loads(raw.decode()) |
| 81 | np_ = d.get("num_players", 4) |
| 82 | goal = d.get("goal_suit") |
| 83 | init = d.get("initial_hands", {}) |
| 84 | names = {i: (players[i]["name"] if players and len(players) > i else f"P{i + 1}") for i in range(np_)} |
| 85 | ante = 50 if np_ == 4 else 40 |
| 86 | |
| 87 | holdings = {i: dict(init.get(str(i), {})) for i in range(np_)} |
| 88 | cash = {i: 350 - ante for i in range(np_)} |
| 89 | frames = [] |
| 90 | for idx, e in enumerate(d.get("events", [])): |
| 91 | trade = actions = None |
| 92 | if e.get("type") == "trade": |
| 93 | b, s, su, pr = e["buyer"], e["seller"], e["suit"], e["price"] |
| 94 | holdings[b][su] = holdings[b].get(su, 0) + 1 |
| 95 | holdings[s][su] = holdings[s].get(su, 0) - 1 |
| 96 | cash[b] -= pr |
| 97 | cash[s] += pr |
| 98 | trade = {"buyer": b, "seller": s, "suit": su, "price": pr} |
| 99 | else: |
| 100 | actions = [ |
| 101 | {"p": a["player"], "valid": a.get("valid", True), **a.get("action", {})} |
| 102 | for a in e.get("actions", []) |
| 103 | ] |
| 104 | frames.append( |
| 105 | { |
| 106 | "turn": idx, |
| 107 | "tick": e.get("tick"), |
| 108 | "kind": e.get("type"), |
| 109 | "holdings": {i: dict(holdings[i]) for i in range(np_)}, |
| 110 | "cash": dict(cash), |
| 111 | "trade": trade, |
| 112 | "actions": actions, |
| 113 | } |
| 114 | ) |
| 115 | |
| 116 | scores = {int(k): v for k, v in d.get("scores", {}).items()} |
| 117 | ranked = sorted(scores.items(), key=lambda kv: kv[1], reverse=True) |
| 118 | if not ranked or (len(ranked) > 1 and ranked[0][1] == ranked[1][1]): |
| 119 | winner, draw = None, bool(ranked) |
| 120 | else: |
| 121 | winner, draw = names.get(ranked[0][0], f"P{ranked[0][0] + 1}"), False |
| 122 | |
| 123 | return ReplayData( |
| 124 | w=1, |
| 125 | h=1, |
| 126 | frames=frames, |
| 127 | winner=winner, |
| 128 | draw=draw, |
| 129 | extra={"names": names, "goal": goal, "scores": scores, "np": np_}, |
| 130 | ) |
nothing calls this directly
no test coverage detected