diff --git a/src/roast.css b/src/roast.css index 386a91b..149f30a 100644 --- a/src/roast.css +++ b/src/roast.css @@ -117,6 +117,14 @@ body { background-color: #ddd; } +.used-temp { + background-color: #ccc !important; + color: #333; + border: 2px solid #888; + cursor: default; +} + + #log-table { width: 100%; border-collapse: collapse; diff --git a/src/roast.ts b/src/roast.ts index 1a5898e..4a6c297 100644 --- a/src/roast.ts +++ b/src/roast.ts @@ -7,6 +7,7 @@ let targets: number[] = []; let currentTargetIndex = 0; let interval: NodeJS.Timeout | null = null; let firstCrackTime: number | null = null; +let loggedTemps = new Set(); declare global { interface Window { @@ -23,7 +24,6 @@ declare global { } } - function startTimer(): void { if (isRunning) { alert("Timer is already running. Click again to reset."); @@ -39,7 +39,7 @@ function startTimer(): void { } function stopTimer(): void { - if(interval !== null){ + if (interval !== null) { clearInterval(interval); } isRunning = false; @@ -48,7 +48,7 @@ function stopTimer(): void { function updateTimerDisplay(): void { const roastTimeEl = document.getElementById("roastTime")!; const devPercentEl = document.getElementById("devPercent")!; - + const minutes = Math.floor(timer / 60); const seconds = timer % 60; roastTimeEl.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`; @@ -63,11 +63,8 @@ function updateTimerDisplay(): void { } const timerEl = document.getElementById("timer")!; - - // Reset classes timerEl.className = ""; - // Determine phase if (!log.some(e => e.event === "Charge")) { timerEl.classList.add("initial-phase"); } else if (!log.some(e => e.event === "Yellow")) { @@ -75,26 +72,20 @@ function updateTimerDisplay(): void { } else if (firstCrackTime === null) { timerEl.classList.add("yellow-phase"); } else { - // Development phase timerEl.classList.add("dev-phase"); - const devTime = timer - firstCrackTime; - const devRatio = Math.min(devTime / timer, 0.4); // clamp to 0–0.4 - - // Interpolate from yellow (255,255,208) to muddy brown (215,195,158) + const devRatio = Math.min(devTime / timer, 0.4); const r = Math.round(255 - devRatio * 100); const g = Math.round(255 - devRatio * 150); const b = Math.round(208 - devRatio * 125); - timerEl.style.backgroundColor = `rgb(${r},${g},${b})`; } - } function logEvent(eventName: string): void { if (eventName === "Charge") { if (log.length > 0 || isRunning) { - if(isRunning){ + if (isRunning) { stopTimer(); } log = []; @@ -111,8 +102,7 @@ function logEvent(eventName: string): void { log.push({ time: formatTime(timer), event: eventName }); updateLog(); document.getElementById("create-plan")!.classList.remove("hidden"); - const tempButtons = document.getElementById("temp-buttons")!; - tempButtons.innerHTML = ""; + document.getElementById("temp-buttons")!.innerHTML = ""; updateEventButtons(eventName); return; } @@ -125,19 +115,18 @@ function logEvent(eventName: string): void { updateEventButtons(eventName); } -function updateEventButtons(eventName: string){ - if (eventName === "Charge" || eventName === "Yellow" || eventName === "First Crack" || eventName === "Second Crack" || eventName === "Drop") { - const eventSequence = ["Charge", "Yellow", "First Crack", "Second Crack", "Drop"]; +function updateEventButtons(eventName: string): void { + const eventSequence = ["Charge", "Yellow", "First Crack", "Second Crack", "Drop"]; + if (eventSequence.includes(eventName)) { const pressedIndex = eventSequence.indexOf(eventName); - for (let i = 0; i <= pressedIndex; i++) { const btn = document.querySelector(`#event-buttons button:nth-child(${i + 1})`) as HTMLButtonElement; if (btn) btn.classList.add("activated"); } - } - else if (eventName === "Reset") { - const eventButtons = document.querySelectorAll("#event-buttons button"); - eventButtons.forEach(btn => btn.classList.remove("activated")); + } else if (eventName === "Reset") { + document.querySelectorAll("#event-buttons button").forEach(btn => + btn.classList.remove("activated") + ); } } @@ -146,6 +135,7 @@ function resetSystem(): void { log = []; timer = 0; firstCrackTime = null; + loggedTemps.clear(); updateLog(); updateTimerDisplay(); @@ -153,12 +143,11 @@ function resetSystem(): void { devPercentEl.style.display = "none"; const timerEl = document.getElementById("timer")!; - timerEl.className = "initial-phase"; // back to white background - timerEl.style.backgroundColor = ""; // clear inline style + timerEl.className = "initial-phase"; + timerEl.style.backgroundColor = ""; document.getElementById("create-plan")!.classList.remove("hidden"); - const tempButtons = document.getElementById("temp-buttons")!; - tempButtons.innerHTML = ""; + document.getElementById("temp-buttons")!.innerHTML = ""; updateEventButtons("Reset"); } @@ -181,17 +170,24 @@ function setPlan(): void { function generateTempButtons(): void { const container = document.getElementById("temp-buttons")!; container.innerHTML = ""; + if (targets.length === 0) { container.innerHTML = "

No temperature plan set.

"; return; } + const currentTarget = targets[currentTargetIndex]; const buttons: string[] = []; + buttons.push(''); + for (let i = -2; i <= 2; i++) { const temp = currentTarget + i; - buttons.push(``); + const used = loggedTemps.has(temp); + const classStr = used ? 'used-temp' : ''; + buttons.push(``); } + buttons.push(''); container.innerHTML = buttons.join(" "); } @@ -208,6 +204,7 @@ function navigateTemp(direction: number): void { function logTemp(temp: number): void { log.push({ time: formatTime(timer), event: "Temp", temp }); + loggedTemps.add(temp); updateLog(); currentTargetIndex++; if (currentTargetIndex >= targets.length) { @@ -227,22 +224,16 @@ function updateLog(): void { `).join(""); } -// src/roast.ts - -/** - * Generates an array of CSV strings line by line from log data. - */ function createCSVData(): string[] { - const header = "Time,Event,Temperature"; - const logEntries = log.map(entry => `${entry.time},${entry.event}${entry.temp !== null ? `,${entry.temp}` : ''}`); - return [header].concat(logEntries); + const header = "Time,Event,Temperature"; + const logEntries = log.map(entry => + `${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 { - return createCSVData().join("\n"); + return createCSVData().join("\n"); } function exportCSV(): void { @@ -288,4 +279,4 @@ if (typeof window !== 'undefined') { window.hideGraph = hideGraph; } -export {}; \ No newline at end of file +export {};