viz improvements

This commit is contained in:
Brennan Wilkes (Text Groove) 2026-02-11 19:17:11 -08:00
parent d78936a3bc
commit 4276cb6228

View file

@ -247,11 +247,7 @@ function makeLimiter(max) {
}); });
} }
/* ---------------- History helpers ---------------- */ function findMinPricesForSkuGroupInDb(obj, wantRealSkus, skuKeys, storeLabel, wantUrls) {
// Returns BOTH mins, so we can show a dot on removal day using removed price.
// Optimized: pass prebuilt wantRealSkus Set + skuKeys. Keeps behavior identical.
function findMinPricesForSkuGroupInDb(obj, wantRealSkus, skuKeys, storeLabel) {
const items = Array.isArray(obj?.items) ? obj.items : []; const items = Array.isArray(obj?.items) ? obj.items : [];
let liveMin = null; let liveMin = null;
let removedMin = null; let removedMin = null;
@ -263,29 +259,34 @@ function findMinPricesForSkuGroupInDb(obj, wantRealSkus, skuKeys, storeLabel) {
else removedMin = removedMin === null ? p : Math.min(removedMin, p); else removedMin = removedMin === null ? p : Math.min(removedMin, p);
}; };
const urlSet = wantUrls instanceof Set ? wantUrls : new Set();
const skuKeySet = new Set((Array.isArray(skuKeys) ? skuKeys : []).map((s) => String(s || "")));
for (const it of items) { for (const it of items) {
if (!it) continue; if (!it) continue;
const isRemoved = Boolean(it.removed); const isRemoved = Boolean(it.removed);
const url = String(it.url || "");
const real = String(it.sku || "").trim(); // 0) URL match (critical for u: keys when storeLabel changes over time)
if (real && wantRealSkus.has(real)) { if (url && urlSet.size && urlSet.has(url)) {
consider(isRemoved, it.price); consider(isRemoved, it.price);
continue; continue;
} }
// synthetic match (only relevant if a caller passes u: keys) // 1) Real SKU match (fast path)
if (!real) { const real = String(it.sku || "").trim();
const url = String(it.url || ""); if (real && wantRealSkus && wantRealSkus.has(real)) {
for (const skuKey of skuKeys) {
const k = String(skuKey || "");
if (!k.startsWith("u:")) continue;
const row = { sku: "", url, storeLabel: storeLabel || "", store: "" };
const kk = keySkuForRow(row);
if (kk === k) {
consider(isRemoved, it.price); consider(isRemoved, it.price);
break; continue;
} }
// 2) Fallback: keySkuForRow match (still useful for real SKUs and stable labels)
if (skuKeySet.size) {
const row = { sku: real, url, storeLabel: storeLabel || "", store: "" };
const kk = keySkuForRow(row);
if (skuKeySet.has(String(kk || ""))) {
consider(isRemoved, it.price);
} }
} }
} }
@ -293,6 +294,7 @@ function findMinPricesForSkuGroupInDb(obj, wantRealSkus, skuKeys, storeLabel) {
return { liveMin, removedMin }; return { liveMin, removedMin };
} }
function lastFiniteFromEnd(arr) { function lastFiniteFromEnd(arr) {
if (!Array.isArray(arr)) return null; if (!Array.isArray(arr)) return null;
for (let i = arr.length - 1; i >= 0; i--) { for (let i = arr.length - 1; i >= 0; i--) {
@ -638,6 +640,17 @@ export async function renderItem($app, skuInput) {
), ),
).sort(); ).sort();
const wantUrlsByVar = new Map(); // vk -> Set(urls)
for (const vk of variantKeys) wantUrlsByVar.set(vk, new Set());
for (const r of rowsAll) {
const vk = String(keySkuForRow(r) || "").trim();
if (!vk || !wantUrlsByVar.has(vk)) continue;
const u = String(r?.url || "").trim();
if (u) wantUrlsByVar.get(vk).add(u);
}
// Split rows by variant for "today" point // Split rows by variant for "today" point
const rowsLiveByVar = new Map(); const rowsLiveByVar = new Map();
for (const r of rowsAll) { for (const r of rowsAll) {
@ -801,7 +814,8 @@ export async function renderItem($app, skuInput) {
const wantRealSkus = new Set([vk].filter((x) => x && !String(x).startsWith("u:"))); const wantRealSkus = new Set([vk].filter((x) => x && !String(x).startsWith("u:")));
const skuKeysOne = [vk]; const skuKeysOne = [vk];
const lastMin = findMinPricesForSkuGroupInDb(objLast, wantRealSkus, skuKeysOne, storeLabel); const wantUrls = wantUrlsByVar.get(vk) || new Set();
const lastMin = findMinPricesForSkuGroupInDb(objLast, wantRealSkus, skuKeysOne, storeLabel, wantUrls);
const lastLive = lastMin.liveMin; const lastLive = lastMin.liveMin;
const lastRemoved = lastMin.removedMin; const lastRemoved = lastMin.removedMin;
@ -815,7 +829,7 @@ export async function renderItem($app, skuInput) {
if (firstSha) { if (firstSha) {
try { try {
const objFirst = await loadAtSha(firstSha); const objFirst = await loadAtSha(firstSha);
const firstMin = findMinPricesForSkuGroupInDb(objFirst, wantRealSkus, skuKeysOne, storeLabel); const firstMin = findMinPricesForSkuGroupInDb(objFirst, wantRealSkus, skuKeysOne, storeLabel, wantUrls);
if (firstMin.liveMin !== null) { if (firstMin.liveMin !== null) {
const candidates = []; const candidates = [];
for (let i = 0; i < dayCommits.length - 1; i++) { for (let i = 0; i < dayCommits.length - 1; i++) {
@ -829,7 +843,7 @@ export async function renderItem($app, skuInput) {
if (!sha) continue; if (!sha) continue;
try { try {
const obj = await loadAtSha(sha); const obj = await loadAtSha(sha);
const m = findMinPricesForSkuGroupInDb(obj, wantRealSkus, skuKeysOne, storeLabel); const m = findMinPricesForSkuGroupInDb(obj, wantRealSkus, skuKeysOne, storeLabel, wantUrls);
if (m.liveMin !== null) { if (m.liveMin !== null) {
sameDayLastLive = m.liveMin; sameDayLastLive = m.liveMin;
break; break;