The benedict (day 22) + the kitchen's memory: regulars and streaks

THE BENEDICT — the first toast+poach composition: day 22 toasts the
bread in the kitchen, then onPopped routes to the poach pot instead of
the drawer (the bruschetta's oven trick, generalized); judgeBenedict
reads THE BREAD off the slice (browning/evenness/char) and THE POACH off
the egg (white/wobble/form), and The Plate sogs BOTH if you serve the
egg undrained — 'You put a wet egg on good toast. Now it is neither.'
Also in the endless rotation (electric pot past day 28).

THE KITCHEN REMEMBERS — recordVerdict on every serve path:
- Streaks: consecutive S grades tracked in the save; the judge notices
  at 3 ('I am beginning to suspect competence.'), 5 ('I have started a
  file.'), every 5 after, and eulogizes a broken one ('It was 7. We do
  not speak of it.').
- The regulars: per-customer visits/last/best in the save. Return
  tickets read 'visit №3 — last time: S' (or '...F. they came BACK.'),
  and the judge compares: worse-than-last-time and redemption both get
  a line. Delivered via JudgeView.extraLines, one-shot per verdict.

Verified live: day 22 starts at the kitchen, poaches after the pop,
combined card 9.1/10 with the architecture line; streak 1->2->3 fires
the line at three; day-20 rebooking shows the visit note.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
type-two 2026-07-20 04:52:36 +10:00
parent bffee40c6f
commit 9c4e366b65
6 changed files with 247 additions and 5 deletions

View File

@ -637,6 +637,37 @@ export function installDevHarness(app: App, game: Game): void {
return { floats: s.eggs.map((e) => e.floatWord), rottenIn: s.rottenIn, dumped: s.bowlsDumped, rows }; return { floats: s.eggs.map((e) => e.floatWord), rottenIn: s.rottenIn, dumped: s.bowlsDumped, rows };
}, },
/** Play the day-22 benedict: toast the bread, then poach the egg for it. */
benedictDay() {
game.setDay(22);
run(6);
harness.toast(10, 6); // golden-ish; pops -> routes to the poach
run(10);
const pv = game.poachView as unknown as { session: import('./sim/poach').PoachSession };
const s = pv.session;
if (!s) return { error: 'not at poach after toast', view: app.currentView === game.poachView ? 'poach' : 'other' };
s.src.target = 7;
let g = 0;
while (s.src.output < 6 && g++ < 1200) run(1);
for (let k = 0; k < 3 * 24; k++) {
const a = (k / 24) * Math.PI * 2;
point(Math.cos(a) * 0.7, 0.7, Math.sin(a) * 0.7, true);
run(1);
}
point(1.6, 0.7, 1.6, false);
run(2);
tap('Space');
g = 0;
while ((s.whiteSet < 0.86 || s.yolkSet > 0.35) && s.yolkSet <= 0.3 && g++ < 60 * 40) run(1);
tap('KeyL');
for (let i = 0; i < 60 * 4; i++) run(1);
tap('Enter');
run(6);
const rows = [...document.querySelectorAll('.crit')].map((e) => e.textContent);
const lines = [...document.querySelectorAll('.judge-lines p')].map((e) => e.textContent);
return { rows, lines };
},
/** Play the day-21 poach with REAL input. good=true: shiver + vortex + drop /** Play the day-21 poach with REAL input. good=true: shiver + vortex + drop
* + lift-at-set + drain. false: still water, rolling boil, overstay, no drain. */ * + lift-at-set + drain. false: still water, rolling boil, overstay, no drain. */
poachDay(good = true) { poachDay(good = true) {

View File

@ -19,7 +19,7 @@ import { juiceCriteria, type JuiceResult } from '../sim/juicing';
import { TempClock } from '../sim/tempclock'; import { TempClock } from '../sim/tempclock';
import type { RoastResult } from '../sim/roasting'; import type { RoastResult } from '../sim/roasting';
import type { AssemblyResult } from '../sim/assembly'; import type { AssemblyResult } from '../sim/assembly';
import { judgeBruschetta, judgeGrill, judgePan, judgeFridge, judgeSteak, judgeEggs, judgePoach, type BruschettaResult, type PrepResult, type Verdict } from './judging'; import { judgeBruschetta, judgeGrill, judgePan, judgeFridge, judgeSteak, judgeEggs, judgePoach, judgeBenedict, type BruschettaResult, type PrepResult, type Verdict } from './judging';
import { JudgeView } from '../scenes/judge'; import { JudgeView } from '../scenes/judge';
import { DrawerView } from '../scenes/drawer'; import { DrawerView } from '../scenes/drawer';
import { TOOLS, type ToolId } from '../sim/cutlery'; import { TOOLS, type ToolId } from '../sim/cutlery';
@ -46,6 +46,10 @@ interface Save {
/** The cold store, persisted: what you stocked on a fridge day is still there /** The cold store, persisted: what you stocked on a fridge day is still there
* (and older) when a later cook reaches in for it. */ * (and older) when a later cook reaches in for it. */
fridge?: StoredItemSave[]; fridge?: StoredItemSave[];
/** Consecutive S grades. The judge notices. Breaking it, he notices more. */
streak?: number;
/** The regulars remember: per-customer visit count and how last time went. */
customers?: Record<string, { visits: number; last: Grade; best: number }>;
} }
/** /**
@ -148,6 +152,7 @@ export class Game {
// the drawer as it always did. // the drawer as it always did.
this.kitchen.onPopped = () => { this.kitchen.onPopped = () => {
if (this.order.bruschetta) this.enterOven(); if (this.order.bruschetta) this.enterOven();
else if (this.order.benedict) this.enterBenedictPoach();
else this.openDrawer(); else this.openDrawer();
}; };
this.kitchen.onServed = () => this.serve(); this.kitchen.onServed = () => this.serve();
@ -398,6 +403,7 @@ export class Game {
}; };
const v = judgeBruschetta(slice, this.order, this.kitchen.toolId, seconds, result); const v = judgeBruschetta(slice, this.order, this.kitchen.toolId, seconds, result);
this.lastBruschetta = { result, verdict: v }; this.lastBruschetta = { result, verdict: v };
this.recordVerdict(v);
this.save.total += v.total; this.save.total += v.total;
const key = `day${this.order.day}`; const key = `day${this.order.day}`;
this.save.best[key] = Math.max(this.save.best[key] ?? 0, v.total); this.save.best[key] = Math.max(this.save.best[key] ?? 0, v.total);
@ -588,6 +594,37 @@ export class Game {
this.enterToastFlow(); this.enterToastFlow();
} }
/** The benedict's second act: the toast is made — now poach the egg for it. */
private enterBenedictPoach(): void {
this.poach.reset(this.order.benedict!.fuel, 'now the egg — poach it and land it on the toast');
this.hideAllScenes();
this.poach.root.visible = true;
this.app.setView(this.poach);
this.ticket.show();
this.poach.onDone = (result) => {
this.poach.root.visible = false;
this.serveBenedict(result);
};
}
private serveBenedict(poach: ReturnType<PoachView['result']>): void {
this.timing = false;
const seconds = this.orderSeconds;
const slice = this.kitchen.currentSlice;
const v = judgeBenedict(slice, this.order, poach, seconds);
this.recordVerdict(v);
this.save.total += v.total;
const key = `day${this.order.day}`;
this.save.best[key] = Math.max(this.save.best[key] ?? 0, v.total);
writeSave(this.save);
this.hideAllScenes();
this.judgeView.root.visible = true;
this.judgeView.show(slice, v, this.order, this.kitchen.toolId, () => this.rng.next());
audio.stamp();
this.app.setView(this.judgeView);
this.ticket.hide();
}
/** The poach pot: spin it, drop it, lift it, drain it, serve it. */ /** The poach pot: spin it, drop it, lift it, drain it, serve it. */
private enterPoach(): void { private enterPoach(): void {
this.poach.reset(this.order.poach!.fuel); this.poach.reset(this.order.poach!.fuel);
@ -606,6 +643,7 @@ export class Game {
const seconds = this.orderSeconds; const seconds = this.orderSeconds;
const slice = this.kitchen.currentSlice; const slice = this.kitchen.currentSlice;
const v = judgePoach(result, this.order, seconds); const v = judgePoach(result, this.order, seconds);
this.recordVerdict(v);
this.save.total += v.total; this.save.total += v.total;
const key = `day${this.order.day}`; const key = `day${this.order.day}`;
this.save.best[key] = Math.max(this.save.best[key] ?? 0, v.total); this.save.best[key] = Math.max(this.save.best[key] ?? 0, v.total);
@ -637,6 +675,7 @@ export class Game {
const seconds = this.orderSeconds; const seconds = this.orderSeconds;
const slice = this.kitchen.currentSlice; const slice = this.kitchen.currentSlice;
const v = judgeEggs(result, this.order, seconds); const v = judgeEggs(result, this.order, seconds);
this.recordVerdict(v);
this.save.total += v.total; this.save.total += v.total;
const key = `day${this.order.day}`; const key = `day${this.order.day}`;
this.save.best[key] = Math.max(this.save.best[key] ?? 0, v.total); this.save.best[key] = Math.max(this.save.best[key] ?? 0, v.total);
@ -679,6 +718,7 @@ export class Game {
const seconds = this.orderSeconds; const seconds = this.orderSeconds;
const slice = this.kitchen.currentSlice; const slice = this.kitchen.currentSlice;
const v = judgeSteak(result, this.order, seconds); const v = judgeSteak(result, this.order, seconds);
this.recordVerdict(v);
this.save.total += v.total; this.save.total += v.total;
const key = `day${this.order.day}`; const key = `day${this.order.day}`;
this.save.best[key] = Math.max(this.save.best[key] ?? 0, v.total); this.save.best[key] = Math.max(this.save.best[key] ?? 0, v.total);
@ -712,6 +752,7 @@ export class Game {
// fridge, at whatever freshness your storage (and the days) left each item. // fridge, at whatever freshness your storage (and the days) left each item.
this.save.fridge = serializeStore(result.store); this.save.fridge = serializeStore(result.store);
const v = judgeFridge(result, this.order, seconds); const v = judgeFridge(result, this.order, seconds);
this.recordVerdict(v);
this.save.total += v.total; this.save.total += v.total;
const key = `day${this.order.day}`; const key = `day${this.order.day}`;
this.save.best[key] = Math.max(this.save.best[key] ?? 0, v.total); this.save.best[key] = Math.max(this.save.best[key] ?? 0, v.total);
@ -763,6 +804,7 @@ export class Game {
const seconds = this.orderSeconds; const seconds = this.orderSeconds;
const slice = this.kitchen.currentSlice; const slice = this.kitchen.currentSlice;
const v = judgePan(result, this.order, seconds, this.panIngredient ?? undefined); const v = judgePan(result, this.order, seconds, this.panIngredient ?? undefined);
this.recordVerdict(v);
this.save.total += v.total; this.save.total += v.total;
const key = `day${this.order.day}`; const key = `day${this.order.day}`;
this.save.best[key] = Math.max(this.save.best[key] ?? 0, v.total); this.save.best[key] = Math.max(this.save.best[key] ?? 0, v.total);
@ -793,6 +835,7 @@ export class Game {
const seconds = this.orderSeconds; const seconds = this.orderSeconds;
const slice = this.kitchen.currentSlice; const slice = this.kitchen.currentSlice;
const v = judgeGrill(result, this.order, seconds); const v = judgeGrill(result, this.order, seconds);
this.recordVerdict(v);
this.save.total += v.total; this.save.total += v.total;
const key = `day${this.order.day}`; const key = `day${this.order.day}`;
this.save.best[key] = Math.max(this.save.best[key] ?? 0, v.total); this.save.best[key] = Math.max(this.save.best[key] ?? 0, v.total);
@ -830,11 +873,48 @@ export class Game {
this.ticket.show(); this.ticket.show();
} }
/**
* The kitchen's memory: streaks the judge acknowledges, and regulars who
* remember how last time went. Runs before the verdict shows, so its lines
* ride the judge screen via extraLines.
*/
private recordVerdict(v: Verdict): void {
const extras: string[] = [];
// The streak. He notices. He hates that he notices.
const prev = this.save.streak ?? 0;
if (v.grade === 'S') {
this.save.streak = prev + 1;
if (this.save.streak === 3) extras.push('Three in a row. I am beginning to suspect competence.');
else if (this.save.streak === 5) extras.push('Five. I have started a file.');
else if (this.save.streak > 5 && this.save.streak % 5 === 0) extras.push(`${this.save.streak} straight. This is no longer luck and we both know it.`);
} else {
if (prev >= 3) extras.push(`The streak is dead. It was ${prev}. We do not speak of it.`);
this.save.streak = 0;
}
// The regulars remember.
const who = this.order.who;
const book = (this.save.customers ??= {});
const c = book[who] ?? { visits: 0, last: v.grade, best: 0 };
if (c.visits > 0) {
if (c.last === 'S' && v.grade !== 'S') extras.push(`${who} remembers last time being better. So do I.`);
else if ((c.last === 'C' || c.last === 'F') && (v.grade === 'S' || v.grade === 'A')) extras.push(`An improvement on ${who}'s last visit. It was noted. It was needed.`);
}
c.visits++;
c.last = v.grade;
c.best = Math.max(c.best, v.total);
book[who] = c;
this.judgeView.extraLines = extras;
}
private renderTicket(): void { private renderTicket(): void {
const o = this.order; const o = this.order;
this.ticketEl.innerHTML = ''; this.ticketEl.innerHTML = '';
el('div', 'ticket-day', this.ticketEl, `DAY ${o.day}`); el('div', 'ticket-day', this.ticketEl, `DAY ${o.day}`);
el('div', 'ticket-who', this.ticketEl, o.who); el('div', 'ticket-who', this.ticketEl, o.who);
const knownAs = this.save.customers?.[o.who];
if (knownAs && knownAs.visits > 0) {
el('div', 'ticket-hint', this.ticketEl, `visit №${knownAs.visits + 1} — last time: ${knownAs.last}${knownAs.last === 'F' ? '. they came BACK.' : ''}`);
}
el('div', 'ticket-text', this.ticketEl, `${o.text}`); el('div', 'ticket-text', this.ticketEl, `${o.text}`);
const spec = el('div', 'ticket-spec', this.ticketEl); const spec = el('div', 'ticket-spec', this.ticketEl);
el('span', 'chip brand', spec, o.brand); el('span', 'chip brand', spec, o.brand);
@ -900,6 +980,7 @@ export class Game {
// one verdict covers the toast and everything the order asked beside it. // one verdict covers the toast and everything the order asked beside it.
const extra = this.juiceResult ? juiceCriteria(this.juiceResult) : []; const extra = this.juiceResult ? juiceCriteria(this.juiceResult) : [];
const v = judge(slice, this.order, this.kitchen.toolId, seconds, this.prepResult ?? undefined, extra); const v = judge(slice, this.order, this.kitchen.toolId, seconds, this.prepResult ?? undefined, extra);
this.recordVerdict(v);
this.save.total += v.total; this.save.total += v.total;
const key = `day${this.order.day}`; const key = `day${this.order.day}`;
this.save.best[key] = Math.max(this.save.best[key] ?? 0, v.total); this.save.best[key] = Math.max(this.save.best[key] ?? 0, v.total);
@ -956,13 +1037,13 @@ function loadSave(): Save {
if (raw) { if (raw) {
const s = JSON.parse(raw) as Partial<Save>; const s = JSON.parse(raw) as Partial<Save>;
if (typeof s.day === 'number' && s.day >= 1) { if (typeof s.day === 'number' && s.day >= 1) {
return { day: s.day, maxDay: Math.max(s.day, s.maxDay ?? s.day), total: s.total ?? 0, best: s.best ?? {}, fridge: s.fridge }; return { day: s.day, maxDay: Math.max(s.day, s.maxDay ?? s.day), total: s.total ?? 0, best: s.best ?? {}, fridge: s.fridge, streak: s.streak ?? 0, customers: s.customers ?? {} };
} }
} }
} catch { } catch {
/* a corrupt save is not worth a crash */ /* a corrupt save is not worth a crash */
} }
return { day: 1, maxDay: 1, total: 0, best: {} }; return { day: 1, maxDay: 1, total: 0, best: {}, streak: 0, customers: {} };
} }
function writeSave(s: Save): void { function writeSave(s: Save): void {

View File

@ -616,6 +616,91 @@ export function judgePoach(r: PoachResult, order: Order, seconds: number): Verdi
return { criteria, total, grade: gradeOf(total), best: sorted[sorted.length - 1], worst: sorted[0], lines: [] }; return { criteria, total, grade: gradeOf(total), best: sorted[sorted.length - 1], worst: sorted[0], lines: [] };
} }
// =====================================================================
// The benedict — two crafts, one plate. The Bread rows read the slice the
// toaster made; The Poach rows read the egg; the cling sogs the toast beneath.
export function judgeBenedict(slice: Slice, order: Order, r: PoachResult, seconds: number): Verdict {
const b = slice.browning.stats(slice.mask);
const charFrac = slice.browning.fraction(slice.mask, (v) => v > CHAR_THRESHOLD);
const criteria: Criterion[] = [
{
key: 'browning',
group: 'bread',
label: 'Browning',
score: clamp01(1 - Math.abs(b.mean - order.browning) / 0.3),
weight: 1.1,
detail: `${b.mean.toFixed(2)} against ${order.browning.toFixed(2)} asked`,
},
{
key: 'evenness',
group: 'bread',
label: 'Evenness',
score: clamp01(1 - b.stdev / 0.2),
weight: 0.8,
detail: `variation ${b.stdev.toFixed(3)}`,
},
{
key: 'char',
group: 'bread',
label: 'Char',
score: order.noChar ? clamp01(1 - charFrac / 0.12) : clamp01(1 - charFrac / 0.45),
weight: 0.6,
detail: charFrac < 0.005 ? 'none' : `${Math.round(charFrac * 100)}% burnt`,
},
{
key: 'poachwhite',
group: 'poach',
label: 'The White',
score: clamp01(r.whiteScore),
weight: 1.1,
detail: r.whiteSet >= 0.85 ? 'set, not snotty' : r.whiteSet >= 0.55 ? 'soft in the middle' : 'raw — it never set',
},
{
key: 'poachwobble',
group: 'poach',
label: 'The Wobble',
score: clamp01(r.yolkScore),
weight: 1.3,
detail: r.wobbleWord,
},
{
key: 'poachform',
group: 'poach',
label: 'The Form',
score: clamp01(r.formScore),
weight: 0.9,
detail: r.rags > 0.5 ? 'a pot of rags' : r.rags > 0.15 ? 'trailing ribbons' : 'one neat comet',
},
{
key: 'benedictsog',
group: 'bench',
label: 'The Plate',
// An undrained egg sogs the toast under it — both crafts pay.
score: clamp01(1 - r.cling * 1.1),
weight: 0.8,
detail: r.cling > 0.3 ? 'poach water soaking the toast' : 'dry underneath — drained properly',
},
{
key: 'time',
label: 'Service',
score: clamp01(1 - (seconds - 75) / 100),
weight: 0.3,
detail: `${Math.round(seconds)}s`,
},
];
let sum = 0;
let wsum = 0;
for (const c of criteria) {
sum += c.score * c.weight;
wsum += c.weight;
}
const total = (sum / wsum) * 10;
const rankable = criteria.filter((c) => c.key !== 'time');
const sorted = [...rankable].sort((a, b2) => a.score - b2.score);
return { criteria, total, grade: gradeOf(total), best: sorted[sorted.length - 1], worst: sorted[0], lines: [] };
}
// ===================================================================== // =====================================================================
// The rib eye — cook it, rest it, cut it. The Rest is the nerve test: it reads // The rib eye — cook it, rest it, cut it. The Rest is the nerve test: it reads
// the flood, so cutting a hot steak bleeds points onto the board. // the flood, so cutting a hot steak bleeds points onto the board.

View File

@ -436,6 +436,16 @@ Object.assign(BANK, {
}, },
}); });
Object.assign(BANK, {
benedictsog: {
bad: [
'You put a wet egg on good toast. Now it is neither.',
'The bread beneath is a sponge. The spoon has holes, use them.',
],
good: ['Dry toast under a trembling egg. That is the whole architecture.'],
},
});
// The rib eye — the steakhouse grandfather who has watched a thousand cooks panic. // The rib eye — the steakhouse grandfather who has watched a thousand cooks panic.
Object.assign(BANK, { Object.assign(BANK, {
steakcook: { steakcook: {

View File

@ -116,6 +116,9 @@ export interface Order {
eggs?: { need: number; cartonAge: number }; eggs?: { need: number; cartonAge: number };
/** The poach: fuel under the pot. The vortex, the shiver, the drop, the wobble. */ /** The poach: fuel under the pot. The vortex, the shiver, the drop, the wobble. */
poach?: { fuel: string }; poach?: { fuel: string };
/** Eggs benedict: toast the bread, then poach the egg and land it ON the
* toast one plate, two crafts, one verdict. */
benedict?: { fuel: string };
} }
export const BROWNING_NAMES: [number, string][] = [ export const BROWNING_NAMES: [number, string][] = [
@ -472,6 +475,21 @@ export const DAYS: Order[] = [
text: 'One poached egg, proper. Bring the water to a SHIVER — not a boil, it will tear. Spin a vortex, drop it in the eye, and lift it when the white sets and the yolk still trembles. I am going to press it.', text: 'One poached egg, proper. Bring the water to a SHIVER — not a boil, it will tear. Spin a vortex, drop it in the eye, and lift it when the white sets and the yolk still trembles. I am going to press it.',
poach: { fuel: 'gas' }, poach: { fuel: 'gas' },
}, },
{
day: 22,
brand: 'WONDERSLICE',
bread: 'white',
spread: 'butter',
amount: 'normal',
browning: 0.55,
browningName: 'golden',
noChar: true,
tool: 'butter_knife',
butterSoftness: 0.5,
who: 'the benedict table, again',
text: 'The full benedict. Golden toast — THEN the egg: shiver, vortex, drop, lift it trembling, drain it, and land it on the bread. Two crafts, one plate. Ruin either and the other dies with it.',
benedict: { fuel: 'gas' },
},
]; ];
/** Days beyond the script — keep going, with everything cranked. */ /** Days beyond the script — keep going, with everything cranked. */
@ -490,8 +508,9 @@ export function proceduralOrder(day: number, rand: () => number): Order {
if (roll < 0.64) return proceduralGrill(day, rand); if (roll < 0.64) return proceduralGrill(day, rand);
if (roll < 0.75) return proceduralPan(day, rand); if (roll < 0.75) return proceduralPan(day, rand);
if (roll < 0.84) return proceduralSteak(day, rand); if (roll < 0.84) return proceduralSteak(day, rand);
if (roll < 0.91) return proceduralEggs(day, rand); if (roll < 0.90) return proceduralEggs(day, rand);
if (roll < 0.96) return proceduralPoach(day, rand); if (roll < 0.94) return proceduralPoach(day, rand);
if (roll < 0.97) return proceduralBenedict(day, rand);
return proceduralFridge(day, rand); return proceduralFridge(day, rand);
} }
@ -598,6 +617,16 @@ function proceduralPoach(day: number, rand: () => number): Order {
return o; return o;
} }
function proceduralBenedict(day: number, rand: () => number): Order {
const fuel = day > 28 && rand() < 0.4 ? 'electric' : 'gas';
const o = baseOrder(day, pickOf(rand, ['the benedict table, again', 'a hollandaise denialist', 'brunch, incarnate']), '');
o.browning = 0.45 + rand() * 0.2;
o.browningName = nameBrowning(o.browning);
o.benedict = { fuel };
o.text = `The full benedict — ${o.browningName} toast, then the poach on top. White set, yolk trembling, bread not soggy. Two crafts, one plate.`;
return o;
}
function proceduralFridge(day: number, rand: () => number): Order { function proceduralFridge(day: number, rand: () => number): Order {
const o = baseOrder(day, 'the delivery, at 6am', ''); const o = baseOrder(day, 'the delivery, at 6am', '');
void rand(); void rand();

View File

@ -30,6 +30,8 @@ export class JudgeView implements View {
private viewBtn!: HTMLButtonElement; private viewBtn!: HTMLButtonElement;
onNext: (() => void) | null = null; onNext: (() => void) | null = null;
/** One-shot lines the game adds to this verdict (streaks, regulars' memory). */
extraLines: string[] = [];
constructor(private app: App) { constructor(private app: App) {
this.pedestal = new THREE.Group(); this.pedestal = new THREE.Group();
@ -107,6 +109,8 @@ export class JudgeView implements View {
// asked and what for, not the unread toast defaults. // asked and what for, not the unread toast defaults.
this.orderEl.textContent = order.grill this.orderEl.textContent = order.grill
? `Day ${order.day} · ${order.who} asked for the barbie` ? `Day ${order.day} · ${order.who} asked for the barbie`
: order.benedict
? `Day ${order.day} · ${order.who} asked for the full benedict`
: order.poach : order.poach
? `Day ${order.day} · ${order.who} asked for the poached egg` ? `Day ${order.day} · ${order.who} asked for the poached egg`
: order.eggs : order.eggs
@ -170,6 +174,8 @@ export class JudgeView implements View {
clear(this.linesEl); clear(this.linesEl);
const lines = verdictLines(verdict, order, TOOLS[tool].name, rand); const lines = verdictLines(verdict, order, TOOLS[tool].name, rand);
for (const l of lines) el('p', undefined, this.linesEl, l); for (const l of lines) el('p', undefined, this.linesEl, l);
for (const l of this.extraLines) el('p', 'judge-extra', this.linesEl, l);
this.extraLines = [];
this.faceEl.src = assetUrl(`/assets/img/judge_${judgeFace(verdict.grade)}.png`); this.faceEl.src = assetUrl(`/assets/img/judge_${judgeFace(verdict.grade)}.png`);
this.stampEl.textContent = verdict.grade; this.stampEl.textContent = verdict.grade;