diff --git a/final_analytics_epilogue/README.md b/final_analytics_epilogue/README.md index d2e9a30..dbe3ae1 100644 --- a/final_analytics_epilogue/README.md +++ b/final_analytics_epilogue/README.md @@ -33,11 +33,19 @@ aggregated to one row per run). Columns: run_id, hero_class, monster, matchup, battles, hero_wins, hero_win_rate, avg_rounds, avg_gold ``` -Each `_variant` file has the same shape but comes from a genuinely -different tournament configuration — different numbers, and for the -history file, a different answer to "which class is most balanced." -Hardcoded answers that happen to match the primary fixture will fail on -the variant. +`data/deep_dive_battles_variant.json` is a genuinely opposite matchup — +if the primary matchup is a sure win for the hero, the variant is a sure +loss, or vice versa. Everything about it (win rate, rounds, gold) differs +from the primary matchup, not just the numbers. + +`data/tournament_history_variant.csv` has the same 9 matchups but a +different (still genuinely run) allocation of tournament runs across +them, so the win-rate-by-class numbers it produces are real and different +from the primary file's. It does **not** change which monster is hardest, +which matchup is longest, or how many matchups are one-sided — in this +combat model those are fixed by which class fights which monster, not by +how many runs you spend on it (see the note below on why `check.py` tests +those three with real data *subsets* instead). ## Cheat-sheet (you've seen all of this before) @@ -77,7 +85,7 @@ def load_tournament_history(path: Path) -> pd.DataFrame: ... def win_rate_by_class(df: pd.DataFrame) -> dict[str, float]: ... def rank_monsters(df: pd.DataFrame) -> list[str]: ... def unfavorable_matchups(df: pd.DataFrame) -> list[str]: ... -def balance_conclusions(df: pd.DataFrame) -> dict[str, str]: ... +def balance_conclusions(df: pd.DataFrame) -> dict[str, str | int]: ... ``` **Synthesis:** @@ -99,21 +107,39 @@ before you start: - **`win_rate_by_class`, `rank_monsters`, and `unfavorable_matchups` must use pandas' `groupby`.** A `.unique()` loop can produce similar numbers, but `groupby` is what this task exists to reactivate. -- **`balance_conclusions` uses only plain groupby aggregation compared - against 0.5** — no correlation, no inferential statistics. +- **`balance_conclusions` must work on whatever `df` it's given** — not + assume it's always the full 9-matchup history. The checker calls it on + smaller real slices too, to confirm it's a genuine, general computation + and not special-cased to one fixture. +- **`win_rate_by_class`'s numbers describe this recorded history**, not + an inherent property of a hero class — five tournament runs per matchup + is a small sample. - **`build_final_report` should call the functions above**, not recompute anything by hand. ## Questions this answers -1. Which monster is hardest, by average hero win rate? -2. Which hero class is, on average, closest to a 50/50 fight? -3. Which matchup is the most one-sided? -4. In the deep-dive matchup: are quick hero wins (2 rounds or fewer) - common or rare? +1. Which monster is hardest, by observed hero win rate? +2. How many matchups in this tournament history are completely + one-sided (hero always wins, or hero always loses)? +3. Which matchup takes the longest on average? +4. In the deep-dive matchup: how often does the hero win, and how often + is it a quick win (2 rounds or fewer)? No correlation, no statistical tests, no confidence intervals, no ML — -just groupby, comparisons, and arithmetic against 0.5. +just groupby, comparisons, and arithmetic. + +A note before you start: an earlier version of this epilogue also asked +"which hero class is closest to 50/50?" and "which matchup is the *most* +one-sided?" Both turned out to be bad questions for this dataset — every +matchup here is either a sure win or a sure loss, so "most one-sided" has +no real answer (every matchup is tied for it), and "closest to 50/50" +mostly measures how many runs you happened to record, not anything about +the hero class. Analytics sometimes reveals that the model itself is +highly deterministic. When a planned metric turns out not to distinguish +any of your cases, the right move is to change the question — not to +force an answer out of it. That's question 2 above: instead of ranking +something that doesn't vary, count it. ## Side quest (optional, not checked) @@ -133,13 +159,20 @@ really used in the three Pandas grouping functions, and that percentile/quantile, boolean-mask work, and axis aggregation with NumPy — since those specific techniques are the point of this epilogue. +`balance_conclusions`, `rank_monsters`, and `unfavorable_matchups` are +also run on a few smaller slices of the real primary history (e.g. only +the Orc and Dragon rows, or only one hero class's rows) — genuine rows, +just fewer of them. A correct, general implementation produces the right +answer for whatever data it's given; one that's quietly hardcoded to the +full 9-matchup fixture won't. + ## Is the game balanced? Once your functions pass, look at what they actually returned — `balance_conclusions`, `rank_monsters`, `unfavorable_matchups`, and the -deep-dive quick-win rate. Form your own answer from those numbers. There's -no single "correct" essay here; the data is the point, not a sentence to -match. +deep-dive win/quick-win rates. Form your own answer from those numbers. +There's no single "correct" essay here; the data is the point, not a +sentence to match. --- diff --git a/final_analytics_epilogue/check.py b/final_analytics_epilogue/check.py index e0652ba..87197ff 100644 --- a/final_analytics_epilogue/check.py +++ b/final_analytics_epilogue/check.py @@ -4,10 +4,20 @@ (primary and variant — one pair for the deep-dive JSON, one pair for the tournament-history CSV) and compared against ground truth computed independently with stdlib `json`/`csv`/`statistics`/`math` — never by -re-running the student's own pandas or NumPy code. The variant fixtures -were generated from a genuinely different (but equally real) tournament -configuration, so hardcoded answers that happen to match the primary -fixtures fail on the variant. +re-running the student's own pandas or NumPy code. The deep-dive variant +is a genuinely opposite-outcome matchup (hero always loses, not just a +different hero-wins matchup), so a hardcoded deep-dive answer fails there. + +The primary/variant HISTORY pair alone can't catch every hardcode: a +quality-gate audit found that in this frozen combat model, hardest_monster, +rank_monsters, and unfavorable_matchups are mathematically invariant to any +run-count reweighting (every matchup's win rate is deterministically 0.0 or +1.0, regardless of how many runs are spent on it). Rather than statically +analyzing whether a groupby's result is "really used" (fragile, and out of +scope), those three functions are additionally exercised on controlled +SLICES of the real primary tournament_history.csv — genuine rows, just a +subset — chosen so a function that's actually generic must produce a +different, slice-specific answer. See "Behavioral subset probes" below. NumPy array work (ndarray, reductions, percentile/quantile, boolean masks, 2D/axis aggregation) and Pandas `groupby` are explicit learning objectives @@ -85,10 +95,10 @@ def _load_history_raw(path: Path) -> list[dict]: return list(csv.DictReader(f)) -def _grouped_mean(rows: list[dict], key: str) -> dict[str, float]: +def _grouped_mean(rows: list[dict], key: str, value_field: str = "hero_win_rate") -> dict[str, float]: groups: dict[str, list[float]] = defaultdict(list) for row in rows: - groups[row[key]].append(float(row["hero_win_rate"])) + groups[row[key]].append(float(row[value_field])) return {k: statistics.mean(v) for k, v in groups.items()} @@ -107,17 +117,22 @@ def _ground_truth_unfavorable(rows: list[dict]) -> list[str]: return [k for k, _ in sorted(worse, key=lambda kv: (kv[1], kv[0]))] -def _ground_truth_conclusions(rows: list[dict]) -> dict[str, str]: - class_rates = _grouped_mean(rows, "hero_class") +def _ground_truth_conclusions(rows: list[dict]) -> dict[str, str | int]: + """Works on any row subset — not just the full fixture. hardest_monster + and longest_matchup are about whichever monsters/matchups are present + in `rows`; one_sided_matchup_count is a count within `rows`.""" monster_rates = _grouped_mean(rows, "monster") - matchup_rates = _grouped_mean(rows, "matchup") + matchup_rounds = _grouped_mean(rows, "matchup", value_field="avg_rounds") + matchup_win_rates = _grouped_mean(rows, "matchup") hardest_monster = min(sorted(monster_rates.items()), key=lambda kv: kv[1])[0] - most_balanced_class = min(sorted(class_rates.items()), key=lambda kv: abs(kv[1] - 0.5))[0] - most_one_sided_matchup = max(sorted(matchup_rates.items()), key=lambda kv: abs(kv[1] - 0.5))[0] + longest_matchup = max(sorted(matchup_rounds.items()), key=lambda kv: kv[1])[0] + one_sided_count = sum( + 1 for v in matchup_win_rates.values() if math.isclose(v, 0.0, abs_tol=1e-9) or math.isclose(v, 1.0, abs_tol=1e-9) + ) return { "hardest_monster": hardest_monster, - "most_balanced_class": most_balanced_class, - "most_one_sided_matchup": most_one_sided_matchup, + "longest_matchup": longest_matchup, + "one_sided_matchup_count": one_sided_count, } @@ -350,11 +365,20 @@ def main() -> None: if list(wins.astype(int)) != expected_wins: print(f"❌ [{fixture_name}] load_battle_arrays: wins array does not match winner data") raise SystemExit(1) + if sorted(set(wins.astype(int).tolist())) not in ([0], [1], [0, 1]): + print(f"❌ [{fixture_name}] load_battle_arrays: wins must be 1/0 indicators, " + f"got values {sorted(set(wins.tolist()))}") + raise SystemExit(1) expected_rounds = [b["rounds"] for b in raw_battles] if list(rounds.astype(int)) != expected_rounds: print(f"❌ [{fixture_name}] load_battle_arrays: rounds array does not match rounds data") raise SystemExit(1) - print(f"✓ [{fixture_name}] load_battle_arrays → 3 ndarrays, shape ({len(raw_battles)},)") + expected_gold = [b["gold_earned"] for b in raw_battles] + if list(gold.astype(int)) != expected_gold: + print(f"❌ [{fixture_name}] load_battle_arrays: gold array does not match gold_earned data") + raise SystemExit(1) + print(f"✓ [{fixture_name}] load_battle_arrays → 3 ndarrays, shape ({len(raw_battles)},), " + f"wins/rounds/gold values all verified") expected_stats = _ground_truth_deep_dive_stats(raw_battles) result = deep_dive_stats(wins, rounds) @@ -371,10 +395,12 @@ def main() -> None: print(f"✓ [{fixture_name}] battle_matrix_summary → {matrix_result}") # ── Pandas tournament-history checks ───────────────────────────────── + history_by_fixture: dict[str, tuple[list[dict], pd.DataFrame]] = {} for fixture_name, fixture_path in FIXTURES_HISTORY: raw_rows = _load_history_raw(fixture_path) df = load_tournament_history(fixture_path) + history_by_fixture[fixture_name] = (raw_rows, df) if not isinstance(df, pd.DataFrame): print(f"❌ [{fixture_name}] load_tournament_history must return a DataFrame, got {type(df)}") raise SystemExit(1) @@ -411,6 +437,103 @@ def main() -> None: raise SystemExit(1) print(f"✓ [{fixture_name}] balance_conclusions → {conclusions_result}") + # ── Behavioral subset probes ────────────────────────────────────────── + # The primary/variant fixture pair alone can't catch a hardcoded answer + # for a function whose TRUE value happens to be identical on both (the + # quality-gate audit found hardest_monster, rank_monsters, and + # unfavorable_matchups are mathematically invariant to any run-count + # reweighting in this frozen domain). Instead of statically analyzing + # whether a groupby's result is "really used" (fragile, and explicitly + # out of scope), every real row below is a genuine row from the primary + # tournament_history.csv — these are controlled SLICES of real data, + # not fabricated numbers — chosen so a function that's actually generic + # (not special-cased to the full 9-matchup fixture) must produce a + # different, slice-specific answer. + primary_raw_rows, primary_df = history_by_fixture["primary"] + + def _subset(predicate): + rows = [r for r in primary_raw_rows if predicate(r)] + mask = primary_df.apply(lambda row: predicate(row.to_dict()), axis=1) + return rows, primary_df[mask].reset_index(drop=True) + + # A: rank_monsters on a real Orc+Dragon-only slice, and a single-monster slice. + rows_od, df_od = _subset(lambda r: r["monster"] in ("Orc", "Dragon")) + expected_od = _ground_truth_rank_monsters(rows_od) + result_od = list(rank_monsters(df_od)) + if result_od != expected_od: + print(f"❌ [subset: Orc+Dragon] rank_monsters: expected {expected_od}, got {result_od}") + raise SystemExit(1) + print(f"✓ [subset: Orc+Dragon] rank_monsters → {result_od}") + + rows_orc, df_orc = _subset(lambda r: r["monster"] == "Orc") + expected_orc = _ground_truth_rank_monsters(rows_orc) + result_orc = list(rank_monsters(df_orc)) + if result_orc != expected_orc: + print(f"❌ [subset: Orc only] rank_monsters: expected {expected_orc}, got {result_orc}") + raise SystemExit(1) + print(f"✓ [subset: Orc only] rank_monsters → {result_orc}") + + # B: hardest_monster via balance_conclusions on the same Orc-only slice — + # the only monster present must be "hardest" by elimination. + expected_hardest_orc = _ground_truth_conclusions(rows_orc)["hardest_monster"] + result_hardest_orc = balance_conclusions(df_orc).get("hardest_monster") + if result_hardest_orc != expected_hardest_orc: + print(f"❌ [subset: Orc only] balance_conclusions.hardest_monster: " + f"expected {expected_hardest_orc!r}, got {result_hardest_orc!r}") + raise SystemExit(1) + print(f"✓ [subset: Orc only] balance_conclusions.hardest_monster → {result_hardest_orc!r}") + + # C: unfavorable_matchups on a warrior_vs_Goblin + warrior_vs_Dragon slice, + # and on a slice with the unfavorable one removed (expect []). + rows_wgd, df_wgd = _subset(lambda r: r["matchup"] in ("warrior_vs_Goblin", "warrior_vs_Dragon")) + expected_wgd = _ground_truth_unfavorable(rows_wgd) + result_wgd = list(unfavorable_matchups(df_wgd)) + if result_wgd != expected_wgd: + print(f"❌ [subset: warrior_vs_Goblin+Dragon] unfavorable_matchups: " + f"expected {expected_wgd}, got {result_wgd}") + raise SystemExit(1) + print(f"✓ [subset: warrior_vs_Goblin+Dragon] unfavorable_matchups → {result_wgd}") + + rows_wg, df_wg = _subset(lambda r: r["matchup"] == "warrior_vs_Goblin") + expected_wg = _ground_truth_unfavorable(rows_wg) + result_wg = list(unfavorable_matchups(df_wg)) + if result_wg != expected_wg: + print(f"❌ [subset: warrior_vs_Goblin only] unfavorable_matchups: " + f"expected {expected_wg}, got {result_wg}") + raise SystemExit(1) + print(f"✓ [subset: warrior_vs_Goblin only] unfavorable_matchups → {result_wg}") + + # D: longest_matchup on a slice excluding the full-fixture's longest + # matchup — must find the next-longest real matchup in the remaining data. + rows_no_longest, df_no_longest = _subset(lambda r: r["matchup"] != "warrior_vs_Dragon") + expected_longest_sub = _ground_truth_conclusions(rows_no_longest)["longest_matchup"] + result_longest_sub = balance_conclusions(df_no_longest).get("longest_matchup") + if result_longest_sub != expected_longest_sub: + print(f"❌ [subset: no warrior_vs_Dragon] balance_conclusions.longest_matchup: " + f"expected {expected_longest_sub!r}, got {result_longest_sub!r}") + raise SystemExit(1) + print(f"✓ [subset: no warrior_vs_Dragon] balance_conclusions.longest_matchup → {result_longest_sub!r}") + + # E: one_sided_matchup_count on a real 3-matchup slice (all of warrior's). + rows_warrior, df_warrior = _subset(lambda r: r["hero_class"] == "warrior") + expected_count_sub = _ground_truth_conclusions(rows_warrior)["one_sided_matchup_count"] + result_count_sub = balance_conclusions(df_warrior).get("one_sided_matchup_count") + if result_count_sub != expected_count_sub: + print(f"❌ [subset: warrior only] balance_conclusions.one_sided_matchup_count: " + f"expected {expected_count_sub!r}, got {result_count_sub!r}") + raise SystemExit(1) + print(f"✓ [subset: warrior only] balance_conclusions.one_sided_matchup_count → {result_count_sub!r}") + + # F: win_rate_by_class on a slice where mage's average genuinely differs + # from the full-fixture dict (mage rows excluding mage_vs_Orc). + rows_mage_sub, df_mage_sub = _subset(lambda r: r["hero_class"] == "mage" and r["matchup"] != "mage_vs_Orc") + expected_mage_sub = _ground_truth_win_rate_by_class(rows_mage_sub) + result_mage_sub = win_rate_by_class(df_mage_sub) + if not isinstance(result_mage_sub, dict) or not _values_close(result_mage_sub, expected_mage_sub): + print(f"❌ [subset: mage minus Orc] win_rate_by_class: expected {expected_mage_sub}, got {result_mage_sub}") + raise SystemExit(1) + print(f"✓ [subset: mage minus Orc] win_rate_by_class → {result_mage_sub}") + # ── Final synthesis checks (paired primary/variant scenarios) ──────── scenarios = [ ("primary", FIXTURES_DEEP_DIVE[0][1], FIXTURES_HISTORY[0][1]), diff --git a/final_analytics_epilogue/data/deep_dive_battles_variant.json b/final_analytics_epilogue/data/deep_dive_battles_variant.json index 842c7b4..d55c65f 100644 --- a/final_analytics_epilogue/data/deep_dive_battles_variant.json +++ b/final_analytics_epilogue/data/deep_dive_battles_variant.json @@ -1,2507 +1,2507 @@ { - "hero_class": "rogue", - "monster": "Goblin", - "matchup": "rogue_vs_Goblin", + "hero_class": "warrior", + "monster": "Dragon", + "matchup": "warrior_vs_Dragon", "battles": [ { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 3, - "gold_earned": 10 + "winner": "monster", + "rounds": 8, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 }, { - "winner": "hero", - "rounds": 2, - "gold_earned": 10 + "winner": "monster", + "rounds": 7, + "gold_earned": 0 } ] } diff --git a/final_analytics_epilogue/scripts/generate_fixtures.py b/final_analytics_epilogue/scripts/generate_fixtures.py index 16f093a..c60c578 100644 --- a/final_analytics_epilogue/scripts/generate_fixtures.py +++ b/final_analytics_epilogue/scripts/generate_fixtures.py @@ -42,7 +42,12 @@ # ── Fixture A: Deep Dive — ~500 battles of one fixed matchup ─────────────── DEEP_DIVE_PRIMARY = {"hero_class": HeroClass.warrior, "monster": "Goblin", "seed": 20240501, "n": 500} -DEEP_DIVE_VARIANT = {"hero_class": HeroClass.rogue, "monster": "Goblin", "seed": 20240502, "n": 500} +# A genuinely opposite-outcome matchup (hero loses every time, not just a +# different hero-wins matchup) — confirmed by the quality-gate audit that +# warrior_vs_Dragon has hero_win_rate == 0.0 for this frozen L7 stat table, +# unlike the previous rogue_vs_Goblin variant, which also always won and so +# couldn't distinguish a hardcoded hero_win_rate=1.0 from a real one. +DEEP_DIVE_VARIANT = {"hero_class": HeroClass.warrior, "monster": "Dragon", "seed": 20240502, "n": 500} def generate_deep_dive(hero_class: HeroClass, monster: str, seed: int, n: int) -> dict: @@ -79,11 +84,15 @@ def generate_deep_dive(hero_class: HeroClass, monster: str, seed: int, n: int) - # Variant: same 9 matchups, same total run count (45), but a different # tournament organizer chose to run more battles against the matchups they # were curious about — a deliberately different, still-45-run allocation. -# (Every individual matchup's win/loss outcome in this frozen domain is -# fully determined by hero-class-vs-monster stats, not by how many runs are -# spent on it — confirmed empirically, see final report — so this is the -# legitimate lever for making the tournament's aggregate conclusions differ -# between primary and variant without fabricating any battle outcome.) +# Every individual matchup's win/loss outcome in this frozen domain is fully +# determined by hero-class-vs-monster stats, not by how many runs are spent +# on it (confirmed empirically — see the quality-gate audit) — so this +# weighting gives win_rate_by_class() a genuinely different second dataset +# to run on, but it does NOT and cannot change per-monster or per-matchup +# conclusions (hardest_monster, longest_matchup, one_sided_matchup_count): +# those depend only on which matchup is which, not on run counts. Hardcode +# detection for monster/matchup-level functions instead comes from the +# checker's behavioral subset probes (see check.py), not from this variant. HISTORY_VARIANT_RUN_COUNTS = { (HeroClass.warrior, "Goblin"): 3, (HeroClass.warrior, "Orc"): 3, (HeroClass.warrior, "Dragon"): 9, (HeroClass.mage, "Goblin"): 7, (HeroClass.mage, "Orc"): 7, (HeroClass.mage, "Dragon"): 1, diff --git a/final_analytics_epilogue/task.py b/final_analytics_epilogue/task.py index 67a231e..8a811d3 100644 --- a/final_analytics_epilogue/task.py +++ b/final_analytics_epilogue/task.py @@ -134,22 +134,31 @@ def unfavorable_matchups(df: pd.DataFrame) -> list[str]: raise NotImplementedError -def balance_conclusions(df: pd.DataFrame) -> dict[str, str]: - """Three headline conclusions about this tournament's balance. +def balance_conclusions(df: pd.DataFrame) -> dict[str, str | int]: + """Three headline conclusions about the tournament history in `df`. Return a dict with exactly these keys: - "hardest_monster": monster with the lowest average hero_win_rate - - "most_balanced_class": hero_class whose average hero_win_rate is - closest to 0.5 - - "most_one_sided_matchup": matchup whose average hero_win_rate is - furthest from 0.5 (in either direction) + - "longest_matchup": matchup with the highest average avg_rounds — + this measures fight LENGTH, not difficulty; don't conflate the two + - "one_sided_matchup_count": how many matchups in `df` have an average + hero_win_rate of exactly 0.0 or exactly 1.0 (a completely one-sided + matchup, in either direction) + + These must work on `df` as given — not assume it's the full 9-matchup + history. A caller may pass a smaller slice (e.g. only a few matchups); + "hardest_monster" and "longest_matchup" are about whichever monsters/ + matchups are actually present in `df`, and "one_sided_matchup_count" + is a count within `df`, not a fixed global number. No correlation or inferential statistics — these are plain groupby - aggregations compared against 0.5. + aggregations. TODO: - - compute per-monster, per-class, and per-matchup average hero_win_rate - - pick each of the three conclusions as described above + - group by monster, average hero_win_rate per group → hardest_monster + - group by matchup, average avg_rounds per group → longest_matchup + - group by matchup, average hero_win_rate per group, count how many + groups equal 0.0 or 1.0 → one_sided_matchup_count - return the three answers in a dict """ raise NotImplementedError @@ -165,7 +174,9 @@ def build_final_report(deep_dive_path: Path, history_path: Path) -> dict[str, ob Return a dict with exactly these keys: - "deep_dive": the deep_dive_stats() dict - "matrix_summary": the battle_matrix_summary() dict - - "win_rate_by_class": the win_rate_by_class() dict + - "win_rate_by_class": the win_rate_by_class() dict — mean win rate + observed in this recorded history, not a claim about inherent class + balance (five runs per matchup is a small sample) - "monster_ranking": the rank_monsters() list - "unfavorable_matchups": the unfavorable_matchups() list - "conclusions": the balance_conclusions() dict