Code viewer for World: Generate Images from Audio...
document.write(`
  <h1>Forecasting Accuracy Demo</h1>
  <label>Enter API key: <input id="apikey" style="width:300px;"></label>
  <button onclick="runForecast()">Run Forecast</button>
  <br><br>
  <canvas id="forecastCanvas" width="800" height="400" style="border:1px solid black;"></canvas>
  <p id="rmseOutput"></p>
`);

const actual = [17.1, 19.8, 21.1, 20.2, 21.5, 19.3, 21.5];
const weatherData = [
  { date: "2025-06-01", value: 18.5 }, { date: "2025-06-02", value: 17.9 },
  { date: "2025-06-03", value: 17.1 }, { date: "2025-06-04", value: 16.1 },
  { date: "2025-06-05", value: 17.7 }, { date: "2025-06-06", value: 17.0 },
  { date: "2025-06-07", value: 15.2 }, { date: "2025-06-08", value: 16.5 },
  { date: "2025-06-09", value: 16.2 }, { date: "2025-06-10", value: 19.0 },
  { date: "2025-06-11", value: 22.3 }, { date: "2025-06-12", value: 16.0 },
  { date: "2025-06-13", value: 21.0 }, { date: "2025-06-14", value: 16.8 },
  { date: "2025-06-15", value: 19.7 }, { date: "2025-06-16", value: 22.8 },
  { date: "2025-06-17", value: 23.4 }, { date: "2025-06-18", value: 20.1 },
  { date: "2025-06-19", value: 23.2 }, { date: "2025-06-20", value: 25.8 },
  { date: "2025-06-21", value: 25.3 }, { date: "2025-06-22", value: 19.7 },
  { date: "2025-06-23", value: 19.7 }, { date: "2025-06-24", value: 21.5 },
  { date: "2025-06-25", value: 21.9 }, { date: "2025-06-26", value: 19.3 },
  { date: "2025-06-27", value: 23.9 }, { date: "2025-06-28", value: 22.8 },
  { date: "2025-06-29", value: 25.1 }, { date: "2025-06-30", value: 23.0 }
];

function calculateRMSE(actual, predicted) {
  let sum = 0;
  for (let i = 0; i < actual.length; i++) {
    sum += Math.pow(actual[i] - predicted[i], 2);
  }
  return Math.sqrt(sum / actual.length);
}

function callForecastAPI(apiName, apiKey) {
  const url = apiName === "Time Door"
    ? "https://api.timedoor.ai/forecast"
    : "https://api.unplugg.io/forecast";

  return fetch(url, {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${apiKey}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({ historical: weatherData })
  })
  .then(res => res.json())
  .then(json => json.forecast.slice(0, 7)) // Adjust if needed
  .catch(err => {
    console.error(`Error calling ${apiName}:`, err);
    return [0, 0, 0, 0, 0, 0, 0]; // fallback
  });
}

function drawChart(timeDoor, unplugg) {
  const canvas = document.getElementById("forecastCanvas");
  const ctx = canvas.getContext("2d");
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  const maxY = 25;
  const minY = 15;
  const spacing = canvas.width / (actual.length - 1);

  function scaleY(val) {
    return canvas.height - ((val - minY) / (maxY - minY)) * canvas.height;
  }

  function drawLine(data, color) {
    ctx.strokeStyle = color;
    ctx.beginPath();
    data.forEach((val, i) => {
      const x = i * spacing;
      const y = scaleY(val);
      i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
    });
    ctx.stroke();
  }

  drawLine(actual, "black");
  drawLine(timeDoor, "blue");
  drawLine(unplugg, "green");

  const rmseTimeDoor = calculateRMSE(actual, timeDoor).toFixed(2);
  const rmseUnplugg = calculateRMSE(actual, unplugg).toFixed(2);
  document.getElementById("rmseOutput").innerHTML = `
    <strong>RMSE (Time Door):</strong> ${rmseTimeDoor}<br>
    <strong>RMSE (Unplugg):</strong> ${rmseUnplugg}
  `;
}

function runForecast() {
  const apiKey = document.getElementById("apikey").value.trim();
  if (!apiKey) {
    alert("Please enter your API key.");
    return;
  }

  Promise.all([
    callForecastAPI("Time Door", apiKey),
    callForecastAPI("Unplugg", apiKey)
  ]).then(([timeDoor, unplugg]) => {
    drawChart(timeDoor, unplugg);
  });
}