even more drop stuff

This commit is contained in:
Your Name
2026-06-13 17:24:19 -04:00
parent 1367eab480
commit 32df06f583
3 changed files with 129 additions and 3 deletions
+92 -1
View File
@@ -16,6 +16,8 @@
},
};
const RARE_MODIFIER_VERSIONS = new Set(["v2", "bb"]);
function esc(value) {
return String(value ?? "")
.replaceAll("&", "&")
@@ -38,6 +40,88 @@
box.innerHTML = `<div class="drops-status ${kind ? `drops-status--${kind}` : ""}">${esc(message)}</div>`;
}
function currentVersion() {
return qs("#drops-version")?.value || "v1";
}
function rareModifierEnabled() {
return RARE_MODIFIER_VERSIONS.has(currentVersion());
}
function currentRareModifier() {
const select = qs("#drops-rare-modifier");
const pct = rareModifierEnabled() ? Number(select?.value || 0) : 0;
const label = select?.selectedOptions?.[0]?.textContent || "No modifier";
return { pct, label, multiplier: 1 + (pct / 100) };
}
function modifierMultiplierLabel(modifier) {
return `x${modifier.multiplier.toFixed(3).replace(/0+$/, "").replace(/\.$/, "")}`;
}
function updateRareModifierControls() {
const wrap = qs("#drops-rare-modifier-wrap");
const v2Note = qs("#drops-v2-note");
const select = qs("#drops-rare-modifier");
const enabled = rareModifierEnabled();
if (wrap) wrap.hidden = !enabled;
if (v2Note) v2Note.hidden = currentVersion() !== "v2";
if (!enabled && select) {
select.value = "0";
}
}
function formatOddsDenominator(value) {
if (!Number.isFinite(value) || value <= 0) return "—";
if (value >= 1000) {
return Math.round(value).toLocaleString();
}
if (value >= 100) {
return value.toFixed(1).replace(/\.0$/, "");
}
return value.toFixed(2).replace(/0+$/, "").replace(/\.$/, "");
}
function adjustedRate(rate) {
const text = String(rate || "");
const match = text.match(/^(\d+)\/(\d+)$/);
if (!match) return text || "—";
const num = Number(match[1]);
const den = Number(match[2]);
const modifier = currentRareModifier();
if (!rareModifierEnabled() || modifier.pct <= 0) {
return text;
}
const baseProbability = num / den;
const adjustedProbability = Math.min(1, baseProbability * modifier.multiplier);
if (adjustedProbability >= 1) {
return "1/1";
}
return `1/${formatOddsDenominator(1 / adjustedProbability)}`;
}
function rateCellHtml(rate) {
const base = String(rate || "—");
const adjusted = adjustedRate(base);
const modifier = currentRareModifier();
if (!rareModifierEnabled() || modifier.pct <= 0 || adjusted === base) {
return esc(base);
}
return esc(adjusted);
}
async function fetchJson(path) {
const res = await fetch(path, { cache: "no-store" });
if (!res.ok) throw new Error(`${path}: HTTP ${res.status}`);
@@ -149,7 +233,7 @@
<td data-label="Source">${esc(labelValue(row.source || "—"))}</td>
<td data-label="Item">${esc(item)}</td>
<td data-label="Item Code">${esc(itemCode)}</td>
<td data-label="Rate">${esc(row.rate || "—")}</td>
<td data-label="Rate">${rateCellHtml(row.rate || "—")}</td>
</tr>
`;
}).join("");
@@ -157,12 +241,17 @@
const truncation = rows.length > shown.length
? ` Showing first ${shown.length.toLocaleString()}.`
: "";
const modifier = currentRareModifier();
const modifierNote = rareModifierEnabled() && modifier.pct > 0
? `<span>Rate modifier: ${esc(modifier.label)} / ${esc(modifierMultiplierLabel(modifier))}</span>`
: "";
box.innerHTML = `
<div class="drops-summary">
<div>
<strong>Peeps ${esc(tableLabel)} drop table</strong>
<span>${rows.length.toLocaleString()} matching rows.${truncation}</span>
${modifierNote}
</div>
<span>${state.rows.length.toLocaleString()} total rows</span>
</div>
@@ -214,6 +303,7 @@
if (qs("#drops-search")) qs("#drops-search").value = "";
populateFilters(state.rows);
updateRareModifierControls();
if (qs("#drops-rare-mode")) qs("#drops-rare-mode").value = "";
if (qs("#drops-episode")) qs("#drops-episode").value = "";
@@ -245,6 +335,7 @@
document.addEventListener("DOMContentLoaded", () => {
qs("#drops-mode")?.addEventListener("change", updateMode);
qs("#drops-version")?.addEventListener("change", loadPeeps);
qs("#drops-rare-modifier")?.addEventListener("change", renderTable);
qs("#drops-rare-mode")?.addEventListener("change", (event) => {
state.filters.mode = event.target.value;