diff --git a/checks/food-trend.mjs b/checks/food-trend.mjs index baa23a1..1b6046f 100644 --- a/checks/food-trend.mjs +++ b/checks/food-trend.mjs @@ -147,6 +147,7 @@ suite("what the sentence is allowed to say"); "foodTrendMoves", "foodSeriesSentences", "foodSeriesFor"], stubs: { liveFoodKinds: () => kinds, + loadFoodKinds: () => kinds, foodKindNames: () => new Map(kinds.map(k => [k.id, k.name])), }, }); @@ -203,12 +204,16 @@ suite("what the sentence is allowed to say"); names: ["NO_KIND", "FOOD_COLORS", "foodTrend", "foodSeriesFor"], stubs: { liveFoodKinds: () => [], - foodKindNames: () => new Map([["gone", "Old recipe"]]), + // The tombstone: gone from the picker, still carrying name and colour. + loadFoodKinds: () => [{ id: "gone", name: "Old recipe", colorIndex: 2, deleted: true }], }, }); const days = byKind([{ gone: 100 }, { gone: 110 }, { gone: 120 }, { gone: 130 }, { gone: 0 }]); - eq(namesOnly.foodSeriesFor(days).map(s => s.name), ["Old recipe"], + const series = namesOnly.foodSeriesFor(days); + eq(series.map(s => s.name), ["Old recipe"], "it keeps its name rather than vanishing or reading as 'No kind'"); + eq(series[0].colorIndex, 2, + "…and its colour, which grey would confuse with the 'No kind' series"); } suite("the caption stays bounded as kinds are added"); diff --git a/src/app.js b/src/app.js index 35aacd6..b5b8219 100644 --- a/src/app.js +++ b/src/app.js @@ -2068,7 +2068,9 @@ // With no kinds defined this returns a single unnamed series, which is what // makes the whole feature invisible to anyone not using it. function foodSeriesFor(days) { - const names = foodKindNames(); + // Every kind ever, tombstones included — a deleted one keeps both its name + // and its colour, which is what lets its food stay identifiable below. + const all = new Map(loadFoodKinds().map(k => [k.id, k])); const used = (id) => days.some(d => (d.gramsByKind?.[id] || 0) > 0); const out = []; for (const k of liveFoodKinds()) { @@ -2079,13 +2081,19 @@ }); } // Kinds deleted since, but still on meals in this window: their food is - // real and has to appear somewhere, under the name the tombstone kept. + // real and has to appear somewhere, under the name and colour the tombstone + // kept. Falling back to grey here would be wrong twice over — it is also + // "No kind"'s colour, so the two series would be indistinguishable in both + // the stack and the legend. for (const d of days) { for (const id of Object.keys(d.gramsByKind || {})) { if (id === NO_KIND || out.some(s => s.id === id)) continue; if (!used(id)) continue; + const gone = all.get(id); out.push({ - id, name: names.get(id) || "Deleted kind", colorIndex: null, + id, + name: gone?.name || "Deleted kind", + colorIndex: gone ? (gone.colorIndex ?? 0) : null, of: (dd) => dd.gramsByKind?.[id] || 0, }); }