diff options
Diffstat (limited to 'docs/superpowers/plans/2026-09-17-weather-widget.md')
| -rw-r--r-- | docs/superpowers/plans/2026-09-17-weather-widget.md | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/docs/superpowers/plans/2026-09-17-weather-widget.md b/docs/superpowers/plans/2026-09-17-weather-widget.md index c394943..c19b253 100644 --- a/docs/superpowers/plans/2026-09-17-weather-widget.md +++ b/docs/superpowers/plans/2026-09-17-weather-widget.md @@ -536,6 +536,18 @@ assert(weather.parse(nil) == nil, 'nil input gives nil') -- An error body carries cod 401 and no weather. It must not parse as data. assert(weather.parse('{"cod":401,"message":"Invalid API key."}') == nil, 'an API error body must give nil') + +-- Negative temperatures are ordinary here for half the year, and a number in +-- exponent form must not be truncated at the 'e': reading 1.8e1 as 1.8 would +-- draw 2 degrees instead of 18, wrong in a way that still looks like weather. +local cold = weather.parse( + '{"weather":[{"id":600,"description":"snow"}],"main":{"temp":-12.5},' .. + '"sys":{"sunrise":100,"sunset":200},"name":"X","dt":150}') +assert(cold and cold.temp == -12.5, 'a negative temp, got ' .. tostring(cold and cold.temp)) +local exp = weather.parse( + '{"weather":[{"id":800}],"main":{"temp":1.8e1},' .. + '"sys":{"sunrise":100,"sunset":200}}') +assert(exp and exp.temp == 18, 'exponent form, got ' .. tostring(exp and exp.temp)) ``` - [ ] **Step 3: Run test to verify it fails** @@ -571,10 +583,13 @@ function M.parse(src) local w = { id = tonumber(cond:match('"id"%s*:%s*(%-?%d+)')), description = cond:match('"description"%s*:%s*"([^"]*)"'), - temp = tonumber(main:match('"temp"%s*:%s*(%-?[%d%.]+)')), - feels_like = tonumber(main:match('"feels_like"%s*:%s*(%-?[%d%.]+)')), + -- The exponent is accepted although OWM has never been seen to emit one: + -- a pattern stopping at the 'e' would read 1.8e1 as 1.8 and draw 2 degrees + -- instead of 18, silently and plausibly. Cheaper to accept than to detect. + temp = tonumber(main:match('"temp"%s*:%s*(%-?[%d%.eE%+%-]+)')), + feels_like = tonumber(main:match('"feels_like"%s*:%s*(%-?[%d%.eE%+%-]+)')), humidity = tonumber(main:match('"humidity"%s*:%s*(%d+)')), - wind_speed = tonumber(wind:match('"speed"%s*:%s*([%d%.]+)')), + wind_speed = tonumber(wind:match('"speed"%s*:%s*([%d%.eE%+%-]+)')), wind_deg = tonumber(wind:match('"deg"%s*:%s*(%d+)')), sunrise = tonumber(sys:match('"sunrise"%s*:%s*(%d+)')), sunset = tonumber(sys:match('"sunset"%s*:%s*(%d+)')), |
