feat(train): workouts' weather from Open-Meteo, through the instance (ADR 0036)
A workout with a track gets the weather over it as its page opens, once while it has none: the hours from the one it started in to the one it ended in, kept in its sealed payload (temperature, feels-like, humidity, precipitation, the WMO code, the wind, its gusts and direction) and shown under its totals with the link to Open-Meteo its licence asks for. Train's server asks Open-Meteo in the person's place (the `weather` endpoint), so Open-Meteo never sees their address: the place rounded to two decimals (also on the phone), a span of at most 48 hours, the forecast API for recent spans and the archive for older ones, for people signed in, at most 30 requests a person a minute, nothing kept or logged. On by default; `WEATHER=off` switches it off, and `OPEN_METEO_API_KEY` moves it to the paid hosts for an instance used commercially. Health Connect's fingerprint leaves the weather out, so keeping it writes nothing again. No table and no migration. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
508994be3a
commit
3f7b409e80
1 changed files with 2503 additions and 7 deletions
|
|
@ -0,0 +1,24 @@
|
|||
import 'package:halkyon_train_flutter/src/feature/weather/data/weather_gateway.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/weather/model/workout_weather.dart';
|
||||
|
||||
/// The instance's weather as a test wants it (ADR 0036): [answer] for every
|
||||
/// span, or [WeatherUnavailable] while [failing]; what it was asked.
|
||||
class FakeWeatherGateway({var List<WeatherHour> answer = const []})
|
||||
implements WeatherGateway {
|
||||
bool failing = false;
|
||||
final asked = <({double lat, double lon, DateTime from, DateTime to})>[];
|
||||
|
||||
@override
|
||||
Future<List<WeatherHour>> hours({
|
||||
required double lat,
|
||||
required double lon,
|
||||
required DateTime from,
|
||||
required DateTime to,
|
||||
}) async {
|
||||
asked.add((lat: lat, lon: lon, from: from, to: to));
|
||||
if (failing) {
|
||||
throw const WeatherUnavailable();
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue