From 0b8e01256923abe09588f89e3d5fee81a1aaec7e Mon Sep 17 00:00:00 2001 From: hermes-explorigin Date: Tue, 18 Aug 2026 17:44:42 +0000 Subject: [PATCH] Show light drizzle icon on 7-day forecast when rain/storm chance is low --- src/components/DailyForecast.svelte | 2 +- src/lib/api/weather-codes.js | 21 +++++++++++++++++++-- tests/lib/api/weather-codes.test.js | 17 +++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/components/DailyForecast.svelte b/src/components/DailyForecast.svelte index 8a23a62..3fe8ae2 100644 --- a/src/components/DailyForecast.svelte +++ b/src/components/DailyForecast.svelte @@ -29,7 +29,7 @@
{#each daily.time as day, i} {#if i < 7} - {@const info = getWeatherInfo(daily.weather_code[i])} + {@const info = getWeatherInfo(daily.weather_code[i], precip)} {@const tempMax = Math.round(daily.temperature_2m_max[i])} {@const tempMin = Math.round(daily.temperature_2m_min[i])} {@const precip = daily.precipitation_probability_max?.[i] || 0} diff --git a/src/lib/api/weather-codes.js b/src/lib/api/weather-codes.js index 9eb1d6e..809d5aa 100644 --- a/src/lib/api/weather-codes.js +++ b/src/lib/api/weather-codes.js @@ -39,8 +39,25 @@ const CODE_MAP = { * @param {number} code - WMO weather code (0-99) * @returns {{ icon: string, label: string, desc: string }} */ -export function getWeatherInfo(code) { - return CODE_MAP[code] || { icon: '❓', label: 'Unknown', desc: 'Unknown conditions' } +// Codes that render as a rain/storm icon but are downgraded to light drizzle +// when the forecast's precipitation chance is low — a 17% "chance of rain" +// shouldn't display as a full rain icon. +const RAIN_CODES = new Set([56, 57, 61, 63, 65, 66, 67, 80, 81, 82, 95, 96, 99]) +const LOW_CHANCE_PRECIP = 35 + +/** + * Get weather display info for a WMO code. + * @param {number} code - WMO weather code (0-99) + * @param {number|null} prob - precipitation chance (%) for the period. When a + * rain/storm code has only a low chance, show light drizzle instead. + * @returns {{ icon: string, label: string, desc: string }} + */ +export function getWeatherInfo(code, prob = null) { + const info = CODE_MAP[code] || { icon: '❓', label: 'Unknown', desc: 'Unknown conditions' } + if (prob != null && prob < LOW_CHANCE_PRECIP && RAIN_CODES.has(code)) { + return { icon: CODE_MAP[51].icon, label: 'Light Drizzle', desc: 'Chance of light rain' } + } + return info } /** diff --git a/tests/lib/api/weather-codes.test.js b/tests/lib/api/weather-codes.test.js index 4db1a75..3656751 100644 --- a/tests/lib/api/weather-codes.test.js +++ b/tests/lib/api/weather-codes.test.js @@ -56,6 +56,23 @@ describe('weather-codes', () => { expect(getWeatherInfo(81).icon).toBe('🌧️') expect(getWeatherInfo(82).icon).toBe('⛈️') }) + + it('downgrades rain to light drizzle when precip chance is low', () => { + const info = getWeatherInfo(63, 17) + expect(info.icon).toBe('🌦️') + expect(info.label).toBe('Light Drizzle') + expect(info.desc).toBe('Chance of light rain') + }) + + it('keeps full rain/storm icon when precip chance is high', () => { + expect(getWeatherInfo(63, 60).icon).toBe('🌧️') + expect(getWeatherInfo(95, 70).icon).toBe('⛈️') + }) + + it('does not downgrade when no probability is provided', () => { + expect(getWeatherInfo(63).icon).toBe('🌧️') + expect(getWeatherInfo(82).icon).toBe('⛈️') + }) }) describe('getWeatherSeverity', () => {