diff --git a/calculator/index.html b/calculator/index.html
index 3360bb8..a5be37e 100644
--- a/calculator/index.html
+++ b/calculator/index.html
@@ -92,91 +92,160 @@
// Reload data every hour (3600000 milliseconds)
setInterval(loadAllData, 3600000);
};
+ async function createTableRows() {
+ const tbody = document.getElementById('prices-table-body');
+ tbody.innerHTML = '';
+ const today = new Date();
+ const tomorrow = new Date(today);
+ tomorrow.setDate(today.getDate() + 1);
+ const tomorrowString = formatDate(tomorrow);
+ // Check if tomorrow's data is available
+ let tomorrowAvailable = false;
+ try {
+ const resp = await fetch('/price/day/' + tomorrowString + '?num_cheapest_hours=8');
+ const data = await resp.json();
+ if (!data.detail || data.detail !== "prices not found") {
+ tomorrowAvailable = true;
+ }
+ } catch (e) {}
+
+ let rowCount = tomorrowAvailable ? 15 : 14;
+ for (let offset = 0; offset < rowCount; offset++) {
+ let date;
+ let label;
+ if (tomorrowAvailable && offset === 0) {
+ date = tomorrow;
+ label = `Zítra (${tomorrowString})`;
+ } else {
+ date = new Date(today);
+ date.setDate(today.getDate() - (tomorrowAvailable ? offset - 1 : offset));
+ const dateString = formatDate(date);
+ label = offset === (tomorrowAvailable ? 1 : 0) ? `Dnes (${dateString})` : dateString;
+ }
+ const dateString = formatDate(date);
+ const rowId = `row-${dateString}`;
+ const tr = document.createElement('tr');
+ tr.id = rowId;
+ // Date cell
+ const dateCell = document.createElement('td');
+ dateCell.className = 'px-1 bg-neutral-200 w-16';
+ dateCell.id = `date-${dateString}`;
+ dateCell.innerText = label;
+ tr.appendChild(dateCell);
+ // Hour cells
+ for (let i = 0; i < 24; i++) {
+ const td = document.createElement('td');
+ td.className = 'px-1';
+ td.id = `${dateString}-${i}`;
+ td.innerText = '-';
+ tr.appendChild(td);
+ }
+ tbody.appendChild(tr);
+ }
+ }
+
+ function loadData(date, isToday) {
+ fetch('/price/day/' + date + '?num_cheapest_hours=8')
+ .then(response => response.json())
+ .then(data => {
+ if (data.detail == "prices not found") {
+ for (let i = 0; i < 24; i++) {
+ document.getElementById(`${date}-${i}`).innerText = "-";
+ }
+ return;
+ }
+ for (let i = 0; i < 24; i++) {
+ let extra_class = "";
+ let border = "border-dotted";
+ if (isToday && i == new Date().getHours()) {
+ extra_class = " font-bold text-xl";
+ border = "border-solid";
+ }
+ let value = Math.round(data.total.hours[i] * 100) / 100;
+ let td = document.getElementById(`${date}-${i}`);
+ if (data.cheapest_hours_by_average.hours.includes(i)) {
+ td.className = `px-1 ${border} border-4 border-lime-400 ${getBgColor(value)}${extra_class}`;
+ } else if (data.most_expensive_hours_by_average.hours.includes(i)) {
+ td.className = `px-1 ${border} border-4 border-rose-400 ${getBgColor(value)}${extra_class}`;
+ } else {
+ if (extra_class != "") {
+ extra_class = " border-4 border-solid border-gray-500";
+ }
+ td.className = `px-1 ${getBgColor(value)}${extra_class}`;
+ }
+ td.innerText = value;
+ }
+ });
+ }
+
+ async function loadAllData() {
+ await createTableRows();
+ const today = new Date();
+ const tomorrow = new Date(today);
+ tomorrow.setDate(today.getDate() + 1);
+ const tomorrowString = formatDate(tomorrow);
+ // Check if tomorrow's data is available
+ let tomorrowAvailable = false;
+ try {
+ const resp = await fetch('/price/day/' + tomorrowString + '?num_cheapest_hours=8');
+ const data = await resp.json();
+ if (!data.detail || data.detail !== "prices not found") {
+ tomorrowAvailable = true;
+ }
+ } catch (e) {}
+ let rowCount = tomorrowAvailable ? 15 : 14;
+ for (let offset = 0; offset < rowCount; offset++) {
+ let date;
+ if (tomorrowAvailable && offset === 0) {
+ date = tomorrow;
+ } else {
+ date = new Date(today);
+ date.setDate(today.getDate() - (tomorrowAvailable ? offset - 1 : offset));
+ }
+ const dateString = formatDate(date);
+ loadData(dateString, (tomorrowAvailable ? offset === 1 : offset === 0));
+ }
+ }
+
+ window.onload = function() {
+ loadAllData();
+ setInterval(loadAllData, 3600000);
+ };
-
-
- |
- 00 |
- 01 |
- 02 |
- 03 |
- 04 |
- 05 |
- 06 |
- 07 |
- 08 |
- 09 |
- 10 |
- 11 |
- 12 |
- 13 |
- 14 |
- 15 |
- 16 |
- 17 |
- 18 |
- 19 |
- 20 |
- 21 |
- 22 |
- 23 |
-
-
- Dnes |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
-
-
- Zítra |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
- - |
-
+
+
+
+ Datum |
+ 00 |
+ 01 |
+ 02 |
+ 03 |
+ 04 |
+ 05 |
+ 06 |
+ 07 |
+ 08 |
+ 09 |
+ 10 |
+ 11 |
+ 12 |
+ 13 |
+ 14 |
+ 15 |
+ 16 |
+ 17 |
+ 18 |
+ 19 |
+ 20 |
+ 21 |
+ 22 |
+ 23 |
+
+
+
+
diff --git a/calculator/miner.py b/calculator/miner.py
index b3bd988..c2c656c 100644
--- a/calculator/miner.py
+++ b/calculator/miner.py
@@ -33,15 +33,17 @@ def get_energy_prices(d: datetime.date=datetime.date.today(), no_cache:bool=Fals
if not hours or no_cache:
r = requests.get(url_energy.format(date_str))
-
try:
for raw in r.json()["data"]["dataLine"][1]["point"]:
hours[str(int(raw["x"])-1)] = raw["y"]
except IndexError:
raise PriceNotFound()
-
- with open(cache_file, "w") as f:
- f.write(json.dumps(hours))
+
+ # Only cache if all 24 hours are present
+ if len(hours) == 24:
+ with open(cache_file, "w") as f:
+ f.write(json.dumps(hours))
+ # If incomplete, do not cache, but return what is available
return hours