Add explicit per-plan gauge temperature offset
Test and deploy / test-and-deploy (push) Successful in 1m23s
Test and deploy / test-and-deploy (push) Successful in 1m23s
This commit is contained in:
1 parent
d96ed22de1
commit
eda3d8e77f
8 files changed
+90
-7
No files matched your search
+8
-5
@@ -9,11 +9,14 @@ const numeric = (v) =>
|
||||
? Number(v)
|
||||
: null;
|
||||
|
||||
// No roaster selection, learned median, or override changes these illustrative points.
|
||||
// An explicit per-plan gauge offset is a temperature difference: no +32 conversion.
|
||||
// Legacy roaster selection, learned medians, and machine overrides remain ignored.
|
||||
export const planTemperatureOffsetF = (plan) => numeric(plan?.temperatureOffsetF) ?? 0;
|
||||
export function buildPlanCurve(plan, ledger) {
|
||||
const t = plan.temps ?? {};
|
||||
const fc = numeric(t.fc?.tempC) ?? 200;
|
||||
const yellow = numeric(t.yellow?.tempC) ?? 160;
|
||||
const offsetC = planTemperatureOffsetF(plan) / 1.8;
|
||||
const fc = numeric(t.fc?.tempC) ?? (200 + offsetC);
|
||||
const yellow = numeric(t.yellow?.tempC) ?? (160 + offsetC);
|
||||
const maillardRate =
|
||||
ledger.maillard > 0 ? Math.max(0, (fc - yellow) / ledger.maillard) : 0;
|
||||
// Development's mean rise is lower than Maillard's, even for a short development.
|
||||
@@ -23,13 +26,13 @@ export function buildPlanCurve(plan, ledger) {
|
||||
key: "charge",
|
||||
label: "Charge",
|
||||
timeS: 0,
|
||||
tempC: numeric(t.charge?.tempC) ?? 200,
|
||||
tempC: numeric(t.charge?.tempC) ?? (200 + offsetC),
|
||||
},
|
||||
{
|
||||
key: "tp",
|
||||
label: "Turning point",
|
||||
timeS: t.tp?.time ? parseDuration(t.tp.time) : 60,
|
||||
tempC: numeric(t.tp?.tempC) ?? 95,
|
||||
tempC: numeric(t.tp?.tempC) ?? (95 + offsetC),
|
||||
},
|
||||
{
|
||||
key: "yellow",
|
||||
|
||||
@@ -19,6 +19,7 @@ export function blankPlan() {
|
||||
return {
|
||||
schemaVersion: 1,
|
||||
sourceUrl: "",
|
||||
temperatureOffsetF: "",
|
||||
fields,
|
||||
blendComponents: [
|
||||
{ cultivar: "", group: "", process: "", sharePct: "", fcAnchor: "" },
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { computeLedger } from "./ledger.js?v=__ASSET_VERSION__";
|
||||
import {
|
||||
buildPlanCurve,
|
||||
planTemperatureOffsetF,
|
||||
pointsToPathD,
|
||||
curveWarnings,
|
||||
} from "./curve.js?v=__ASSET_VERSION__";
|
||||
@@ -121,6 +122,7 @@ export function renderReportBody(plan, name = "") {
|
||||
<h2>Coffee & roast intent</h2><p><b>Origin:</b> ${e(fields["1.3"] || "—")} · <b>Cultivar:</b> ${e(fields["1.1"] || "—")} · <b>Density:</b> ${e(fields["5.2"] || "—")} g/L</p><p><b>Weight-loss target:</b> ${e(fields["4.2"] || "—")}% · <b>Development:</b> ${time(l.C)} · <b>DTR:</b> ${l.checks.dtr.pct?.toFixed(1) ?? "—"}%</p>
|
||||
<div class="callout">Use this as a starting hypothesis. Light, fruity coffee depends on the green coffee, roast progression and cup results. Machine selection never changes this plan. * Blank temperatures use an illustrative reference curve, not measured or calibrated targets.</div>
|
||||
${warnings.length ? `<div class="callout">${warnings.map((w) => `<p>${e(w)}</p>`).join("")}</div>` : ""}
|
||||
${planTemperatureOffsetF(plan) ? `<p><b>Gauge temperature offset:</b> ${planTemperatureOffsetF(plan) > 0 ? "+" : ""}${e(planTemperatureOffsetF(plan))}°F. Applied to illustrative temperature references; drop follows adjusted milestones. Entered targets, preheat and actual readings are unchanged.</p>` : ""}
|
||||
<h2>Milestone plan</h2><table><thead><tr><th>Milestone</th><th>Time</th><th>BT (°F)</th><th>What to look for</th></tr></thead><tbody>${rows}</tbody></table>
|
||||
<h2>Roast curve</h2><div class="chart">${renderReportCurve(p, l)}</div><p>The smooth line interpolates milestones; it is not a predicted sensor trace. Aim for controlled progression after recovery. Phase averages cannot rule out a brief crash or flick.</p><div class="footer">Roast plan · Grams & Fahrenheit</div></section>
|
||||
<section class="sheet"><div class="record-intro"><h1>Roast schedule & record</h1><div class="subtitle">${e(name || fields["0.1"] || "Roast plan")} · Use at the roaster</div>
|
||||
|
||||
Reference in new issue
Block a user