frontend tweaks
This commit is contained in:
parent
2e50f61e57
commit
9866af07d3
1 changed files with 65 additions and 16 deletions
81
index.html
81
index.html
|
|
@ -185,6 +185,26 @@
|
|||
opacity: .8;
|
||||
border-bottom: 1px solid #8886;
|
||||
}
|
||||
|
||||
/* Solution cards: each solve gets its own collapsible block so older
|
||||
solutions stay viewable, newest on top. */
|
||||
details.solution {
|
||||
border: 1px solid #8884;
|
||||
border-radius: 8px;
|
||||
padding: .3rem .8rem;
|
||||
margin-top: .8rem;
|
||||
}
|
||||
|
||||
details.solution>summary {
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
padding: .3rem 0;
|
||||
}
|
||||
|
||||
.pending {
|
||||
opacity: .75;
|
||||
margin-top: .8rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
|
|
@ -445,8 +465,20 @@
|
|||
[upBoxes[u], " " + u]));
|
||||
}
|
||||
}
|
||||
type.onchange = renderUpgrades;
|
||||
// Vat amounts only matter for Foundries; hide them otherwise and keep
|
||||
// them as the card's last fields (before the actions).
|
||||
const vatFields = [
|
||||
field("Vat steel", vs),
|
||||
field("Vat brass", vb),
|
||||
field("Vat electrum", ve),
|
||||
];
|
||||
function renderVats() {
|
||||
const show = type.value === "foundry";
|
||||
for (const f of vatFields) f.style.display = show ? "" : "none";
|
||||
}
|
||||
type.onchange = () => {renderUpgrades(); renderVats();};
|
||||
renderUpgrades();
|
||||
renderVats();
|
||||
|
||||
card._get = () => {
|
||||
const o = {name: name.value, type: type.value};
|
||||
|
|
@ -469,14 +501,12 @@
|
|||
field("Name", name),
|
||||
field("Type", type),
|
||||
field("Renown", renown),
|
||||
field("Vat steel", vs),
|
||||
field("Vat brass", vb),
|
||||
field("Vat electrum", ve),
|
||||
field("Upgrades (already installed)", upWrap),
|
||||
checkField("Can renovate", reno),
|
||||
field("Adjacent cities (csv of names)", adjacent),
|
||||
field("Forced actions (turn:action, csv)", forced),
|
||||
field("Avail turns (csv, blank=all)", avail),
|
||||
...vatFields,
|
||||
el("div", {class: "card-actions"}, removeBtn(card)));
|
||||
document.getElementById("cities").append(card);
|
||||
}
|
||||
|
|
@ -497,11 +527,13 @@
|
|||
const forced = el("input", {value: "", placeholder: "0:Aridias"});
|
||||
const avail = el("input", {value: ""});
|
||||
|
||||
const bastionsField = field("Bastions (Baron only)", bastions);
|
||||
|
||||
let nameEdited = !!a.name;
|
||||
name.oninput = () => {nameEdited = true;};
|
||||
function syncType() {
|
||||
if (!nameEdited) name.value = type.value;
|
||||
bastions.disabled = (type.value !== "Baron");
|
||||
bastionsField.style.display = (type.value === "Baron") ? "" : "none";
|
||||
desc.textContent = AGENT_DESC[type.value] || "";
|
||||
}
|
||||
type.onchange = syncType;
|
||||
|
|
@ -519,9 +551,9 @@
|
|||
card.append(
|
||||
field("Agent", type),
|
||||
field("Effect", desc),
|
||||
field("Bastions (Baron only)", bastions),
|
||||
field("Forced city (turn:city, csv)", forced),
|
||||
field("Avail turns (csv, blank=all)", avail),
|
||||
bastionsField,
|
||||
el("div", {class: "card-actions"}, removeBtn(card)));
|
||||
document.getElementById("agents").append(card);
|
||||
}
|
||||
|
|
@ -645,16 +677,24 @@
|
|||
};
|
||||
}
|
||||
|
||||
// Each solve produces its own collapsible <details> card; older ones are
|
||||
// kept (collapsed) so previous solutions stay viewable. solutionCount labels
|
||||
// them in request order.
|
||||
let solutionCount = 0;
|
||||
|
||||
async function run() {
|
||||
const errBox = document.getElementById("error");
|
||||
const out = document.getElementById("output");
|
||||
errBox.textContent = ""; out.innerHTML = "";
|
||||
errBox.textContent = "";
|
||||
// A placeholder card for this request, prepended so the newest is on top.
|
||||
// It's replaced by the solution on success, or removed on error.
|
||||
const pending = el("p", {class: "pending"}, "Solving…");
|
||||
out.prepend(pending);
|
||||
let problem, time;
|
||||
try {
|
||||
problem = buildProblem();
|
||||
time = +document.getElementById("time").value;
|
||||
} catch (e) {errBox.textContent = e.message; return;}
|
||||
out.textContent = "Solving…";
|
||||
} catch (e) {errBox.textContent = e.message; pending.remove(); return;}
|
||||
try {
|
||||
const resp = await fetch("/solve", {
|
||||
method: "POST",
|
||||
|
|
@ -662,15 +702,20 @@
|
|||
body: JSON.stringify({problem, max_time_seconds: time}),
|
||||
});
|
||||
const data = await resp.json();
|
||||
if (!resp.ok) {out.innerHTML = ""; errBox.textContent = data.error || "Server error"; return;}
|
||||
renderSolution(data);
|
||||
} catch (e) {out.innerHTML = ""; errBox.textContent = e.message;}
|
||||
if (!resp.ok) {pending.remove(); errBox.textContent = data.error || "Server error"; return;}
|
||||
renderSolution(data, pending);
|
||||
} catch (e) {pending.remove(); errBox.textContent = e.message;}
|
||||
}
|
||||
|
||||
function renderSolution(s) {
|
||||
const out = document.getElementById("output");
|
||||
out.innerHTML = "";
|
||||
out.append(el("h2", {}, "Solution"));
|
||||
function renderSolution(s, placeholder) {
|
||||
// Collapse any previously-shown solutions so the new one is the focus.
|
||||
for (const d of document.querySelectorAll("#output details.solution")) d.open = false;
|
||||
|
||||
const n = ++solutionCount;
|
||||
const details = el("details", {class: "solution", open: ""});
|
||||
details.append(el("summary", {},
|
||||
`Solution ${n} — ${s.status}, objective ${s.objective_value ?? "—"}`));
|
||||
const out = details;
|
||||
out.append(el("p", {
|
||||
html:
|
||||
`<b>Status:</b> ${s.status} <b>Objective:</b> ${s.objective_value ?? "—"} ` +
|
||||
|
|
@ -709,6 +754,10 @@
|
|||
["Turn", "Converted into", "Amount"],
|
||||
s.trade_conversions.map(c => [c.turn, c.resource, fmtNum(c.amount)])));
|
||||
}
|
||||
|
||||
// Swap the finished card in for this request's placeholder.
|
||||
if (placeholder) placeholder.replaceWith(details);
|
||||
else document.getElementById("output").prepend(details);
|
||||
}
|
||||
|
||||
// Trim trailing ".0" so whole numbers read cleanly.
|
||||
|
|
|
|||
Loading…
Reference in a new issue