move dashboard script block content into own files with new classes to update, render to have a better code overview
Build and Push Docker Container / build-and-push (push) Successful in 3m55s
Build and Push Docker Container / build-and-push (push) Successful in 3m55s
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
class ThinkingPanel {
|
||||
constructor(thinkingEl) {
|
||||
this._el = thinkingEl;
|
||||
}
|
||||
|
||||
get element() { return this._el; }
|
||||
|
||||
render(turn, replay) {
|
||||
if (!turn) {
|
||||
this._el.innerHTML = "<p class=\"section-title\">Select a game to inspect reasoning.</p>";
|
||||
this._syncMonoOffset();
|
||||
return;
|
||||
}
|
||||
|
||||
const reasoning = turn.my_thinking;
|
||||
const reasons = this._extractReasoningList(reasoning);
|
||||
const reasonList = reasons.map((item) => `<li>${item}</li>`).join("");
|
||||
const gameMeta = replay && replay.game ? replay.game : {};
|
||||
const snakeType = Utils.safeString(gameMeta.your_snake_type);
|
||||
const snakeVersion = Utils.safeString(gameMeta.your_snake_version);
|
||||
|
||||
this._el.innerHTML = `
|
||||
<div class="think-grid">
|
||||
<div class="chip"><span class="k">Chosen Move</span><span class="v">${Utils.safeString(turn.my_move)}</span></div>
|
||||
<div class="chip"><span class="k">Snake Type</span><span class="v">${snakeType}</span></div>
|
||||
<div class="chip"><span class="k">Snake Version</span><span class="v">${snakeVersion}</span></div>
|
||||
<div class="chip"><span class="k">Observed At</span><span class="v">${Utils.formatObservedAtLocal(turn.observed_at)}</span></div>
|
||||
<div class="chip"><span class="k">Food Count</span><span class="v">${Array.isArray(turn.food) ? turn.food.length : 0}</span></div>
|
||||
<div class="chip"><span class="k">Hazard Count</span><span class="v">${Array.isArray(turn.hazards) ? turn.hazards.length : 0}</span></div>
|
||||
</div>
|
||||
|
||||
<section class="snakes-section">
|
||||
<table class="score-table">
|
||||
<colgroup>
|
||||
<col style="width:32%">
|
||||
<col style="width:10%">
|
||||
<col style="width:10%">
|
||||
<col style="width:20%">
|
||||
<col style="width:6%">
|
||||
<col style="width:7%">
|
||||
<col style="width:7%">
|
||||
</colgroup>
|
||||
<thead><tr><th>Snake</th><th>Latency</th><th>Move</th><th>Health</th><th>Length</th><th>Head</th><th>Tail</th></tr></thead>
|
||||
<tbody>${SnakeTable.buildSnakesRows(turn, replay)}</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="scores-section">
|
||||
<p class="section-title">Move Scores</p>
|
||||
<table class="score-table">
|
||||
<colgroup><col style="width:50%"><col style="width:50%"></colgroup>
|
||||
<thead><tr><th>Move</th><th>Score</th></tr></thead>
|
||||
<tbody>${MoveTable.buildScoresRows(reasoning)}</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p class="section-title">Decision Summary</p>
|
||||
<ul class="reason-list">${reasonList}</ul>
|
||||
</section>
|
||||
|
||||
<section class="raw-block">
|
||||
<p class="section-title">Raw Reasoning Payload</p>
|
||||
<pre class="mono">${JSON.stringify(reasoning, null, 2)}</pre>
|
||||
</section>
|
||||
`;
|
||||
this._syncMonoOffset();
|
||||
}
|
||||
|
||||
highlightSnake(snakeId) {
|
||||
const section = this._el.querySelector(".snakes-section");
|
||||
if (!section) return;
|
||||
section.querySelectorAll(".snake-row.highlighted").forEach((r) => r.classList.remove("highlighted"));
|
||||
section.classList.remove("has-highlight");
|
||||
if (!snakeId) return;
|
||||
const row = section.querySelector(`[data-snake-id="${CSS.escape(snakeId)}"]`);
|
||||
if (row) {
|
||||
row.classList.add("highlighted");
|
||||
section.classList.add("has-highlight");
|
||||
}
|
||||
}
|
||||
|
||||
syncMonoOffset() {
|
||||
this._syncMonoOffset();
|
||||
}
|
||||
|
||||
_syncMonoOffset() {
|
||||
const mono = this._el.querySelector(".mono");
|
||||
if (!mono) return;
|
||||
const rect = mono.getBoundingClientRect();
|
||||
const bottomPaddingPx = 36;
|
||||
const offset = Math.max(120, Math.round(rect.top + bottomPaddingPx));
|
||||
document.documentElement.style.setProperty("--mono-vh-offset", `${offset}px`);
|
||||
}
|
||||
|
||||
_extractReasoningList(reasoning) {
|
||||
const parts = [];
|
||||
if (!reasoning || typeof reasoning !== "object") {
|
||||
return ["No reasoning recorded by this snake implementation."];
|
||||
}
|
||||
if (reasoning.reason) parts.push(`Reason: ${reasoning.reason}`);
|
||||
if (reasoning.mode) parts.push(`Mode: ${reasoning.mode}`);
|
||||
if (reasoning.health !== undefined) parts.push(`Health: ${reasoning.health}`);
|
||||
if (reasoning.length !== undefined) parts.push(`Length: ${reasoning.length}`);
|
||||
if (reasoning.occupancy !== undefined) parts.push(`Occupancy: ${reasoning.occupancy}`);
|
||||
if (reasoning.ms_remaining !== undefined) parts.push(`Time left: ${reasoning.ms_remaining}ms`);
|
||||
if (parts.length === 0) parts.push("Structured reasoning not provided; showing raw payload below.");
|
||||
return parts;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user