-- Details: wind, humidity, UV and air quality, with a wind compass as the -- big value. -- -- Adapted from the Conky-Mirage theme's details tiles by alexsson-xexpanderx -- (see lib/weather.lua). UV and AQI are the measured quantities here, so they -- carry the ok / warning / critical roles. local card = require 'lib.card' local data = require 'lib.data' local weather = require 'lib.weather' local M = {} -- The compass fills the big value's slot: `size` square, its right edge at -- `right`, its top at `top`. local function draw_compass(cr, right, top, size, colors, deg) local r = size / 2 local cx, cy = right - r, top + r card.rgba(cr, colors.rule, 0.8) cairo_set_line_width(cr, 1) cairo_new_path(cr) cairo_arc(cr, cx, cy, r, 0, math.pi * 2) cairo_stroke(cr) local size = r * 0.28 card.font(cr, card.FONT_MONO, size, false) card.rgba(cr, colors.label) for i, p in ipairs({ 'N', 'E', 'S', 'W' }) do local a = (i - 1) * math.pi / 2 card.text_centre(cr, cx + (r - size) * math.sin(a), cy - (r - size) * math.cos(a) + size * 0.35, p) end if type(deg) ~= 'number' then return end -- Open-Meteo gives where the wind comes FROM; the needle points where it goes. local a = math.rad(deg + 180) local tip = r - size * 1.6 local sa, ca = math.sin(a), math.cos(a) -- A filled arrowhead at the tip, so the needle reads one way only. The shaft -- stops at the head's base: a stroke run to the apex would blunt it. local head, half = r * 0.22, r * 0.11 local bx, by = cx + (tip - head) * sa, cy - (tip - head) * ca card.rgba(cr, colors.highlight) cairo_set_line_width(cr, math.max(2, r * 0.04)) cairo_move_to(cr, cx - tip * 0.6 * sa, cy + tip * 0.6 * ca) cairo_line_to(cr, bx, by) cairo_stroke(cr) cairo_move_to(cr, cx + tip * sa, cy - tip * ca) cairo_line_to(cr, bx + half * ca, by + half * sa) cairo_line_to(cr, bx - half * ca, by - half * sa) cairo_close_path(cr) cairo_fill(cr) end function M.draw(cr, rect, colors) local inner = card.card(cr, rect, colors) local w = weather.parse(data.slurp(weather.CACHE)) if not w then card.notice(cr, inner, colors, 'DETAILS', 'no weather data', 'bin/weather-fetch.sh') return end local c = w.current -- UV is the forecast for the current hour; Open-Meteo's current block has none. local uv = (w.hours[1] or {}).uv local aqi = w.air and w.air.aqi local wind = '--' if type(c.wind) == 'number' then wind = weather.num(c.wind) .. ' ' .. weather.wind_unit(w.units) .. ' ' .. (weather.compass(c.wind_deg) or '') end local rows = { { 'WIND', wind }, { 'HUMIDITY', weather.num(c.humidity, '%') }, { 'UV', type(uv) == 'number' and string.format('%.1f', uv) or '--', colors[weather.uv_role(uv)] }, { 'AIR (EAQI)', weather.num(aqi), colors[weather.aqi_role(aqi)] }, } card.standard(cr, inner, colors, { icon = card.ICON.details, title = 'DETAILS', rows = rows, big = function(cr, right, top, size) draw_compass(cr, right, top, size, colors, c.wind_deg) end, }) end return M