Skip to content

Commit c7d021f

Browse files
committed
Add sim wins per round graph
1 parent 158bd97 commit c7d021f

3 files changed

Lines changed: 145 additions & 0 deletions

File tree

codeclash/viewer/app.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,41 @@ def analyze_line_counts(self) -> dict[str, Any]:
612612

613613
return {"all_files": all_files_list, "line_counts_by_round": line_counts_by_round}
614614

615+
def analyze_sim_wins_per_round(self) -> dict[str, Any]:
616+
"""Analyze number of simulations won per round for each competitor from round_stats in metadata.json"""
617+
metadata_file = self.log_dir / "metadata.json"
618+
if not metadata_file.exists():
619+
return {"players": [], "rounds": [], "wins_by_player": {}}
620+
621+
try:
622+
metadata = json.loads(metadata_file.read_text())
623+
round_stats = metadata.get("round_stats", {})
624+
# Collect all player names from all rounds
625+
player_names = set()
626+
for round_data in round_stats.values():
627+
scores = round_data.get("scores", {})
628+
player_names.update([k for k in scores.keys() if k != "Tie"])
629+
player_names = sorted(player_names)
630+
631+
# Collect all round numbers (sorted)
632+
round_nums = sorted([int(k) for k in round_stats.keys()])
633+
634+
# Build wins_by_player: {player: [wins_per_round]}
635+
wins_by_player = {p: [] for p in player_names}
636+
for round_num in round_nums:
637+
round_data = round_stats.get(str(round_num), {})
638+
scores = round_data.get("scores", {})
639+
for p in player_names:
640+
wins_by_player[p].append(scores.get(p, 0))
641+
642+
return {
643+
"players": player_names,
644+
"rounds": round_nums,
645+
"wins_by_player": wins_by_player,
646+
}
647+
except Exception:
648+
return {"players": [], "rounds": [], "wins_by_player": {}}
649+
615650
def load_matrix_analysis(self) -> dict[str, Any] | None:
616651
"""Load and process matrix.json if it exists"""
617652
matrix_file = self.log_dir / "matrix.json"
@@ -790,6 +825,7 @@ def index():
790825

791826
# Get analysis data
792827
analysis_data = parser.analyze_line_counts()
828+
sim_wins_data = parser.analyze_sim_wins_per_round()
793829

794830
# Get matrix analysis data
795831
matrix_data = parser.load_matrix_analysis()
@@ -804,6 +840,7 @@ def index():
804840
metadata=metadata,
805841
trajectories_by_round=trajectories_by_round,
806842
analysis_data=analysis_data,
843+
sim_wins_data=sim_wins_data,
807844
matrix_data=matrix_data,
808845
is_static=STATIC_MODE,
809846
)

codeclash/viewer/static/js/analysis.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,97 @@ function prepareChartData(fileName) {
184184
}
185185

186186
// Initialize when DOM is loaded
187+
// --- Sim Wins Per Round Chart ---
188+
let simWinsChart = null;
189+
let simWinsData = null;
190+
191+
function initializeSimWinsChart() {
192+
const simWinsDataElement = document.getElementById("sim-wins-data");
193+
if (!simWinsDataElement) return;
194+
try {
195+
simWinsData = JSON.parse(simWinsDataElement.textContent);
196+
if (
197+
simWinsData &&
198+
simWinsData.players &&
199+
simWinsData.players.length > 0 &&
200+
simWinsData.rounds &&
201+
simWinsData.rounds.length > 0
202+
) {
203+
createSimWinsChart();
204+
}
205+
} catch (error) {
206+
console.error("Error parsing sim wins data:", error);
207+
}
208+
}
209+
210+
function createSimWinsChart() {
211+
const canvas = document.getElementById("sim-wins-chart");
212+
if (!canvas || !simWinsData) return;
213+
const ctx = canvas.getContext("2d");
214+
if (simWinsChart) simWinsChart.destroy();
215+
216+
// Prepare datasets
217+
const colors = [
218+
"#FF6384",
219+
"#36A2EB",
220+
"#FFCE56",
221+
"#4BC0C0",
222+
"#9966FF",
223+
"#FF9F40",
224+
"#C9CBCF",
225+
"#4BC0C0",
226+
"#FF6384",
227+
];
228+
let colorIndex = 0;
229+
const datasets = simWinsData.players.map((player) => {
230+
const data = simWinsData.rounds.map((round, i) => ({ x: round, y: simWinsData.wins_by_player[player][i] }));
231+
const color = colors[colorIndex % colors.length];
232+
colorIndex++;
233+
return {
234+
label: player,
235+
data: data,
236+
borderColor: color,
237+
backgroundColor: color + "20",
238+
borderWidth: 2,
239+
fill: false,
240+
tension: 0.1,
241+
};
242+
});
243+
244+
simWinsChart = new Chart(ctx, {
245+
type: "line",
246+
data: { datasets },
247+
options: {
248+
responsive: true,
249+
maintainAspectRatio: false,
250+
plugins: {
251+
title: {
252+
display: true,
253+
text: `Simulations Won Per Round`,
254+
},
255+
legend: {
256+
display: true,
257+
position: "top",
258+
},
259+
},
260+
scales: {
261+
x: {
262+
title: { display: true, text: "Round" },
263+
type: "linear",
264+
position: "bottom",
265+
},
266+
y: {
267+
title: { display: true, text: "Simulations Won" },
268+
beginAtZero: true,
269+
},
270+
},
271+
interaction: { intersect: false, mode: "index" },
272+
},
273+
});
274+
}
275+
276+
// Initialize both analyses when DOM is loaded
187277
document.addEventListener("DOMContentLoaded", function () {
188278
initializeAnalysis();
279+
initializeSimWinsChart();
189280
});

codeclash/viewer/templates/includes/analysis.html

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,23 @@
22
<section class="analysis-section">
33
<h2><i class="bi bi-graph-up"></i> Analysis</h2>
44

5+
<!-- Sim Wins Per Round Analysis -->
6+
<details class="foldout">
7+
<summary><i class="bi bi-bar-chart-line"></i> Sim Wins Per Round</summary>
8+
<div class="log-content-container">
9+
{% if sim_wins_data and sim_wins_data.players and sim_wins_data.rounds %}
10+
<div class="sim-wins-analysis-container">
11+
<div class="chart-container">
12+
<canvas id="sim-wins-chart" width="800" height="400"></canvas>
13+
</div>
14+
<script type="application/json" id="sim-wins-data">{{ sim_wins_data | tojson }}</script>
15+
</div>
16+
{% else %}
17+
<p>No simulation win data available. This analysis requires games with round stats.</p>
18+
{% endif %}
19+
</div>
20+
</details>
21+
522
<!-- Line Counting Analysis -->
623
<details class="foldout">
724
<summary><i class="bi bi-graph-up-arrow"></i> Line Counting Analysis</summary>

0 commit comments

Comments
 (0)