ledger: openmeteo per-city summary extract (2026-11-02)

This commit is contained in:
ledger committed 2026-11-02 00:06:28 +00:00
1 parent 87ddf66863
commit 6a5d938976
2 files changed
+91

No files matched your search

@@ -0,0 +1,7 @@
city,country,temperature_2m_C,apparent_temperature_C,apparent_minus_actual_C,relative_humidity_pct,weather_code,condition,wind_speed_10m_kmh
Cape Town,South Africa,16.1,14.1,-2.0,85,1,Mainly clear,21.8
London,United Kingdom,8.9,6.9,-2.0,84,2,Partly cloudy,7.9
New York,United States,12.7,9.9,-2.8,58,0,Clear sky,10.5
Sydney,Australia,20.2,21.0,0.8,74,1,Mainly clear,6.6
São Paulo,Brazil,21.7,24.1,2.4,87,3,Overcast,7.0
Tokyo,Japan,11.9,11.7,-0.2,91,3,Overcast,2.3
1 city country temperature_2m_C apparent_temperature_C apparent_minus_actual_C relative_humidity_pct weather_code condition wind_speed_10m_kmh
2 Cape Town South Africa 16.1 14.1 -2.0 85 1 Mainly clear 21.8
3 London United Kingdom 8.9 6.9 -2.0 84 2 Partly cloudy 7.9
4 New York United States 12.7 9.9 -2.8 58 0 Clear sky 10.5
5 Sydney Australia 20.2 21.0 0.8 74 1 Mainly clear 6.6
6 São Paulo Brazil 21.7 24.1 2.4 87 3 Overcast 7.0
7 Tokyo Japan 11.9 11.7 -0.2 91 3 Overcast 2.3
@@ -0,0 +1,84 @@
#!/usr/bin/env python3
"""Verify wizard-work/ledger/2026-11-02-openmeteo-summary.csv against the
source JSON it was derived from. Exit code is the verdict.
EXIT CODES
0 committed CSV matches the source-derived table (header + all rows)
1 mismatch (header, row count, or per-cell value)
2 ungradable (source JSON or CSV unreadable/malformed)
"""
import json
import sys
HERE = '/root/troupe-standup/wizard-work/ledger'
SRC = HERE + '/openmeteo-source-2026-11-01.json'
CSV = HERE + '/2026-11-02-openmeteo-summary.csv'
EXPECTED_HEADER = ['city', 'country', 'temperature_2m_C', 'apparent_temperature_C',
'apparent_minus_actual_C', 'relative_humidity_pct', 'weather_code',
'condition', 'wind_speed_10m_kmh']
def recompute():
d = json.load(open(SRC))
rows = []
for c in sorted(d):
g = d[c]['geocode']
w = d[c]['weather']
rows.append({
'city': c,
'country': g['country'],
'temperature_2m_C': w['temperature_2m'],
'apparent_temperature_C': w['apparent_temperature'],
'apparent_minus_actual_C': round(w['apparent_temperature'] - w['temperature_2m'], 1),
'relative_humidity_pct': w['relative_humidity_2m'],
'weather_code': w['weather_code'],
'condition': w['weather_desc'],
'wind_speed_10m_kmh': w['wind_speed_10m'],
})
return rows
def close(a, b, tol=1e-9):
try:
return abs(float(a) - float(b)) <= tol
except (TypeError, ValueError):
return a == b
def main():
try:
expected = recompute()
except Exception as e:
print('UNGRADABLE: cannot recompute from source: ' + str(e))
return 2
try:
with open(CSV) as f:
lines = [ln.rstrip('\n') for ln in f]
except Exception as e:
print('UNGRADABLE: cannot read CSV: ' + str(e))
return 2
if not lines:
print('FAIL: CSV is empty')
return 1
header = lines[0].split(',')
if header != EXPECTED_HEADER:
print('FAIL: header mismatch: ' + repr(header))
return 1
body = [ln.split(',') for ln in lines[1:]]
if len(body) != len(expected):
print('FAIL: row count %d != expected %d' % (len(body), len(expected)))
return 1
ok = True
for i, (act, exp) in enumerate(zip(body, expected)):
for col in EXPECTED_HEADER:
if not close(act[EXPECTED_HEADER.index(col)], exp[col]):
print('FAIL row %d col %s: %r != %r' % (i, col, act[EXPECTED_HEADER.index(col)], exp[col]))
ok = False
if ok:
print('PASS: %d rows match source-derived table; header exact' % len(body))
return 0
return 1
if __name__ == '__main__':
sys.exit(main())