From 83d9f22bbd8336edba8eb508a490a728ddd97085 Mon Sep 17 00:00:00 2001 From: Per Magnus Petersen Date: Sat, 14 Feb 2026 14:35:39 +0100 Subject: [PATCH] Add hourly price rank (#1 = cheapest) based on total price Co-Authored-By: Claude Opus 4.6 --- src/clj/pmagnus/elprice/web/routes/ui.clj | 24 +++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/clj/pmagnus/elprice/web/routes/ui.clj b/src/clj/pmagnus/elprice/web/routes/ui.clj index 94aee3b..0bf6741 100644 --- a/src/clj/pmagnus/elprice/web/routes/ui.clj +++ b/src/clj/pmagnus/elprice/web/routes/ui.clj @@ -54,7 +54,7 @@ (when (seq vals) (/ (reduce + 0.0 (map double vals)) (count vals) 10.0)))) -(defn- hour-block [hour quarters] +(defn- hour-block [hour quarters rank] (let [sorted (sort-by #(.getMinute (->ldt (:time_dk %))) quarters) avg (avg-ore quarters) month (.getMonthValue (->ldt (:time_dk (first quarters)))) @@ -63,6 +63,7 @@ [:summary {:class "flex justify-between py-2 px-3 cursor-pointer hover:bg-gray-50 font-medium text-gray-900"} [:span (format "%02d:00" hour)] + [:span {:class "text-gray-500 text-sm"} (str "#" rank)] [:span {:class "font-mono"} (if avg (format "%.1f(%.1f)" (+ avg tariff) avg) "-")]] [:div {:class "border-t-2 border-blue-400 px-3 pb-2"} @@ -71,12 +72,27 @@ [:span (format "%02d:%02d" hour (.getMinute (->ldt (:time_dk q))))] [:span {:class "font-mono"} (format-ore (:price_dkk q) tariff)]])]])) +(defn- hour-ranks + "Compute a map of hour -> rank (1 = cheapest) based on total price (avg + tariff)." + [grouped-hours] + (let [totals (for [[hour quarters] grouped-hours] + (let [avg (avg-ore quarters) + month (.getMonthValue (->ldt (:time_dk (first quarters)))) + tariff (tariffs/tariff-for-hour month hour)] + [hour (if avg (+ avg tariff) Double/MAX_VALUE)]))] + (->> totals + (sort-by second) + (map-indexed (fn [i [hour _]] [hour (inc i)])) + (into {})))) + (defn- price-table [prices] [:div (if (seq prices) - [:div - (for [[hour quarters] (group-by-hour prices)] - (hour-block hour quarters))] + (let [grouped (group-by-hour prices) + ranks (hour-ranks grouped)] + [:div + (for [[hour quarters] grouped] + (hour-block hour quarters (get ranks hour)))]) [:p {:class "mt-2 text-sm text-gray-400"} "Not available yet"])]) (def ^:private tab-base