feedback on temp buttons

This commit is contained in:
2025-07-13 16:41:35 -04:00
parent 15f74335c7
commit af68e8923c
2 changed files with 41 additions and 42 deletions

View File

@@ -117,6 +117,14 @@ body {
background-color: #ddd; background-color: #ddd;
} }
.used-temp {
background-color: #ccc !important;
color: #333;
border: 2px solid #888;
cursor: default;
}
#log-table { #log-table {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;

View File

@@ -7,6 +7,7 @@ let targets: number[] = [];
let currentTargetIndex = 0; let currentTargetIndex = 0;
let interval: NodeJS.Timeout | null = null; let interval: NodeJS.Timeout | null = null;
let firstCrackTime: number | null = null; let firstCrackTime: number | null = null;
let loggedTemps = new Set<number>();
declare global { declare global {
interface Window { interface Window {
@@ -23,7 +24,6 @@ declare global {
} }
} }
function startTimer(): void { function startTimer(): void {
if (isRunning) { if (isRunning) {
alert("Timer is already running. Click again to reset."); alert("Timer is already running. Click again to reset.");
@@ -39,7 +39,7 @@ function startTimer(): void {
} }
function stopTimer(): void { function stopTimer(): void {
if(interval !== null){ if (interval !== null) {
clearInterval(interval); clearInterval(interval);
} }
isRunning = false; isRunning = false;
@@ -48,7 +48,7 @@ function stopTimer(): void {
function updateTimerDisplay(): void { function updateTimerDisplay(): void {
const roastTimeEl = document.getElementById("roastTime")!; const roastTimeEl = document.getElementById("roastTime")!;
const devPercentEl = document.getElementById("devPercent")!; const devPercentEl = document.getElementById("devPercent")!;
const minutes = Math.floor(timer / 60); const minutes = Math.floor(timer / 60);
const seconds = timer % 60; const seconds = timer % 60;
roastTimeEl.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`; roastTimeEl.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
@@ -63,11 +63,8 @@ function updateTimerDisplay(): void {
} }
const timerEl = document.getElementById("timer")!; const timerEl = document.getElementById("timer")!;
// Reset classes
timerEl.className = ""; timerEl.className = "";
// Determine phase
if (!log.some(e => e.event === "Charge")) { if (!log.some(e => e.event === "Charge")) {
timerEl.classList.add("initial-phase"); timerEl.classList.add("initial-phase");
} else if (!log.some(e => e.event === "Yellow")) { } else if (!log.some(e => e.event === "Yellow")) {
@@ -75,26 +72,20 @@ function updateTimerDisplay(): void {
} else if (firstCrackTime === null) { } else if (firstCrackTime === null) {
timerEl.classList.add("yellow-phase"); timerEl.classList.add("yellow-phase");
} else { } else {
// Development phase
timerEl.classList.add("dev-phase"); timerEl.classList.add("dev-phase");
const devTime = timer - firstCrackTime; const devTime = timer - firstCrackTime;
const devRatio = Math.min(devTime / timer, 0.4); // clamp to 00.4 const devRatio = Math.min(devTime / timer, 0.4);
// Interpolate from yellow (255,255,208) to muddy brown (215,195,158)
const r = Math.round(255 - devRatio * 100); const r = Math.round(255 - devRatio * 100);
const g = Math.round(255 - devRatio * 150); const g = Math.round(255 - devRatio * 150);
const b = Math.round(208 - devRatio * 125); const b = Math.round(208 - devRatio * 125);
timerEl.style.backgroundColor = `rgb(${r},${g},${b})`; timerEl.style.backgroundColor = `rgb(${r},${g},${b})`;
} }
} }
function logEvent(eventName: string): void { function logEvent(eventName: string): void {
if (eventName === "Charge") { if (eventName === "Charge") {
if (log.length > 0 || isRunning) { if (log.length > 0 || isRunning) {
if(isRunning){ if (isRunning) {
stopTimer(); stopTimer();
} }
log = []; log = [];
@@ -111,8 +102,7 @@ function logEvent(eventName: string): void {
log.push({ time: formatTime(timer), event: eventName }); log.push({ time: formatTime(timer), event: eventName });
updateLog(); updateLog();
document.getElementById("create-plan")!.classList.remove("hidden"); document.getElementById("create-plan")!.classList.remove("hidden");
const tempButtons = document.getElementById("temp-buttons")!; document.getElementById("temp-buttons")!.innerHTML = "";
tempButtons.innerHTML = "";
updateEventButtons(eventName); updateEventButtons(eventName);
return; return;
} }
@@ -125,19 +115,18 @@ function logEvent(eventName: string): void {
updateEventButtons(eventName); updateEventButtons(eventName);
} }
function updateEventButtons(eventName: string){ function updateEventButtons(eventName: string): void {
if (eventName === "Charge" || eventName === "Yellow" || eventName === "First Crack" || eventName === "Second Crack" || eventName === "Drop") { const eventSequence = ["Charge", "Yellow", "First Crack", "Second Crack", "Drop"];
const eventSequence = ["Charge", "Yellow", "First Crack", "Second Crack", "Drop"]; if (eventSequence.includes(eventName)) {
const pressedIndex = eventSequence.indexOf(eventName); const pressedIndex = eventSequence.indexOf(eventName);
for (let i = 0; i <= pressedIndex; i++) { for (let i = 0; i <= pressedIndex; i++) {
const btn = document.querySelector(`#event-buttons button:nth-child(${i + 1})`) as HTMLButtonElement; const btn = document.querySelector(`#event-buttons button:nth-child(${i + 1})`) as HTMLButtonElement;
if (btn) btn.classList.add("activated"); if (btn) btn.classList.add("activated");
} }
} } else if (eventName === "Reset") {
else if (eventName === "Reset") { document.querySelectorAll("#event-buttons button").forEach(btn =>
const eventButtons = document.querySelectorAll("#event-buttons button"); btn.classList.remove("activated")
eventButtons.forEach(btn => btn.classList.remove("activated")); );
} }
} }
@@ -146,6 +135,7 @@ function resetSystem(): void {
log = []; log = [];
timer = 0; timer = 0;
firstCrackTime = null; firstCrackTime = null;
loggedTemps.clear();
updateLog(); updateLog();
updateTimerDisplay(); updateTimerDisplay();
@@ -153,12 +143,11 @@ function resetSystem(): void {
devPercentEl.style.display = "none"; devPercentEl.style.display = "none";
const timerEl = document.getElementById("timer")!; const timerEl = document.getElementById("timer")!;
timerEl.className = "initial-phase"; // back to white background timerEl.className = "initial-phase";
timerEl.style.backgroundColor = ""; // clear inline style timerEl.style.backgroundColor = "";
document.getElementById("create-plan")!.classList.remove("hidden"); document.getElementById("create-plan")!.classList.remove("hidden");
const tempButtons = document.getElementById("temp-buttons")!; document.getElementById("temp-buttons")!.innerHTML = "";
tempButtons.innerHTML = "";
updateEventButtons("Reset"); updateEventButtons("Reset");
} }
@@ -181,17 +170,24 @@ function setPlan(): void {
function generateTempButtons(): void { function generateTempButtons(): void {
const container = document.getElementById("temp-buttons")!; const container = document.getElementById("temp-buttons")!;
container.innerHTML = ""; container.innerHTML = "";
if (targets.length === 0) { if (targets.length === 0) {
container.innerHTML = "<p>No temperature plan set.</p>"; container.innerHTML = "<p>No temperature plan set.</p>";
return; return;
} }
const currentTarget = targets[currentTargetIndex]; const currentTarget = targets[currentTargetIndex];
const buttons: string[] = []; const buttons: string[] = [];
buttons.push('<button class="nav-btn" onclick="navigateTemp(-1);">&lt;&lt;</button>'); buttons.push('<button class="nav-btn" onclick="navigateTemp(-1);">&lt;&lt;</button>');
for (let i = -2; i <= 2; i++) { for (let i = -2; i <= 2; i++) {
const temp = currentTarget + i; const temp = currentTarget + i;
buttons.push(`<button onclick="logTemp(${temp})">${temp}</button>`); const used = loggedTemps.has(temp);
const classStr = used ? 'used-temp' : '';
buttons.push(`<button onclick="logTemp(${temp})" class="${classStr}">${temp}</button>`);
} }
buttons.push('<button class="nav-btn" onclick="navigateTemp(1);">&gt;&gt;</button>'); buttons.push('<button class="nav-btn" onclick="navigateTemp(1);">&gt;&gt;</button>');
container.innerHTML = buttons.join(" "); container.innerHTML = buttons.join(" ");
} }
@@ -208,6 +204,7 @@ function navigateTemp(direction: number): void {
function logTemp(temp: number): void { function logTemp(temp: number): void {
log.push({ time: formatTime(timer), event: "Temp", temp }); log.push({ time: formatTime(timer), event: "Temp", temp });
loggedTemps.add(temp);
updateLog(); updateLog();
currentTargetIndex++; currentTargetIndex++;
if (currentTargetIndex >= targets.length) { if (currentTargetIndex >= targets.length) {
@@ -227,22 +224,16 @@ function updateLog(): void {
`).join(""); `).join("");
} }
// src/roast.ts
/**
* Generates an array of CSV strings line by line from log data.
*/
function createCSVData(): string[] { function createCSVData(): string[] {
const header = "Time,Event,Temperature"; const header = "Time,Event,Temperature";
const logEntries = log.map(entry => `${entry.time},${entry.event}${entry.temp !== null ? `,${entry.temp}` : ''}`); const logEntries = log.map(entry =>
return [header].concat(logEntries); `${entry.time},${entry.event}${entry.temp !== null ? `,${entry.temp}` : ''}`
);
return [header, ...logEntries];
} }
/**
* Creates CSV format content as a single string from the array returned by createCSVData().
*/
function generateCSVContent(): string { function generateCSVContent(): string {
return createCSVData().join("\n"); return createCSVData().join("\n");
} }
function exportCSV(): void { function exportCSV(): void {
@@ -288,4 +279,4 @@ if (typeof window !== 'undefined') {
window.hideGraph = hideGraph; window.hideGraph = hideGraph;
} }
export {}; export {};