Commit graph

82 commits

Author SHA1 Message Date
Paul van Tilburg f00537d5f3
Add more lints; fix issues 2022-10-17 20:02:54 +02:00
Paul van Tilburg d749233b24 Merge uses 2022-08-12 09:44:08 +02:00
Paul van Tilburg 712b3a9acf
Check sample coordinate bounds (closes: #24) 2022-06-06 19:51:07 +02:00
Paul van Tilburg 2b23885692
Default to now if Last-Modified header missing
As a result, if the header is missing, it is no longer considered an
error.
2022-06-06 19:39:32 +02:00
Paul van Tilburg 014ca5a151
Handle errors on the API side
* The map endpoints return an HTTP 404 error in case of unknown or
  out-of-bound locations
* The forecast endpoint with an address returns an HTTP 404 with error
  JSON in case geocoding fails
* The forecast endpoints return the errors per metric in the `errors`
  field of the forecast
* Implement `Display` for `Metric`
* Use a `BTreeMap` to have an ordered `errors` field/object
* Also log the errors to the console
* Update the tests
* Document the errors that can occur
2022-06-06 16:46:52 +02:00
Paul van Tilburg 8a2a6d769d
Log errors of the map refresher task separately 2022-06-06 15:38:38 +02:00
Paul van Tilburg 69ef08002c
Introduce error types, switch to Results everywhere
* Add dependency on the `thiserror` crate
* Add a global `Error` type, but also `maps::Error` and
  `providers::combined::MergeError` for convenience
* Add matching `Result` types that default to the respective `Error`
  type
* Refactor code to yield all kinds of error variants
* Add FIXMEs where library errors still need to be handled
* Remove documentation that explained why `None` was returned, this is
  captured in the error now
2022-06-06 15:37:54 +02:00
Paul van Tilburg 7d0cd4a822
Drop pollen and AQI max for PAQI metric
* This was introduced as per #20 but no longer deemed necessary
* Fix up some comments
* Keep the PAQI documentation in `README.md`
2022-06-05 21:47:12 +02:00
Paul van Tilburg fb8236696d
Use world map emoji! 2022-06-05 21:29:12 +02:00
Paul van Tilburg aab3b737be
Run map refresher as an ad hoc liftoff fairing
* Simplify the library `setup()` method
* Simplify launching Rocket
* Drop dependency on color-eyre
2022-06-05 21:25:56 +02:00
Paul van Tilburg 705ffae249
Fix typo in map key color for level 8 2022-05-21 09:47:23 +02:00
Paul van Tilburg bd2344beb6
Transform map key colors to hexadecimal format 2022-05-21 09:47:01 +02:00
Paul van Tilburg bad20b803a
Don't set unnecessary status 2022-05-10 15:47:37 +02:00
Paul van Tilburg fc4672328f
Fix missing type for tests
This was introduced by the changes in commit e204e79.
2022-05-10 15:47:08 +02:00
Paul van Tilburg e204e7905c
Update to Rocket 0.5-rc.2 2022-05-10 14:55:57 +02:00
Paul van Tilburg 89395f21f6
Introduce RetrievedMaps; refactor around it
The `RetrievedMaps` struct captures the image and its metadata:
the last modification time and the base timestamp for the maps.

* No longer store the last modification time, called "stamp" before,
  separately in the `Maps` struct
* Update methods on `Maps` to use the `RetrievedMaps` structs and
  the timestamp base in particular for sampling and map marking
* Update the `MapsRefresh` implemention to use the last modification
  time
* Rename some variables from `map` to `image` in the helper functions
  for consistency
* Update tests and documentation
2022-05-10 14:19:09 +02:00
Paul van Tilburg ff9f1ac371
Parse timestamp base from filename 2022-05-10 13:21:21 +02:00
Paul van Tilburg 4a6eeab787
Fix sample/item being out of the combined series time range
For example, if there are 24 valid pollen samples and 20 valid air
quality items, the maximum pollen sample could be de 23th, but the
resulting combined series will only cover 20 items. So, it is should not
return that, but only look in the first 20 pollen samples for the
maximum sample.
2022-05-10 12:26:10 +02:00
Paul van Tilburg ab4b0bba72
Fix valid samples/items being discarded too early
A forecasted sample/item may be for example timestamped at 14:00.
For hourly forecasts, it will still be valid until 14:59:59, not
14:29:59.
2022-05-10 12:24:26 +02:00
Paul van Tilburg a0c4e0da77
Don't use Option for the max sample/item return values
If the sample/item series are empty, the function already returns
`None`, so the tuple values are always `Some(_)` which makes the
`Option` type redundant.
2022-05-08 14:01:22 +02:00
Paul van Tilburg 34b63ec94d
Compact merge tests by using constructors
Add the constructors to sample/item structs for testing purposes.
2022-05-08 14:00:12 +02:00
Paul van Tilburg 5a23e83b7f
Extend tests for combined provider merge function
* Check that merging fails if the samples/items are too far apart
* Check that nothing is returned if either of the lists is empty
* Check that if either series is shifted, they are merged correctly
2022-05-08 13:48:09 +02:00
Paul van Tilburg e2d1a1d9df
Filter out old item/samples in combined provider
* Only retain samples/items that have timestamps that are at least half
  an hour ago
* Add a test to verify that the merge discards them
2022-05-08 12:53:32 +02:00
Paul van Tilburg 29b79c720d
Derive PartialEq for most item/sample structs 2022-05-08 12:53:09 +02:00
Paul van Tilburg 5972697cf1
Yield pollen and AQI max for PAQI metric (closes: #20)
* Make the combined provider keep track of the AQI and pollen maximum
  value
* Extend the `Forecast` struct with the `aqi_max` and `pollen_max`
  fields
* Fill the `aqi_max` and `pollen_max` fields when the PAQI metric is
  selected
* Update the documentation
* Extend the tests
2022-05-07 21:43:35 +02:00
Paul van Tilburg 0bf07bd134
Split off all functionality to a library crate
This way we can build Rockets from outside the crate and run benchmarks,
for example.

* Add top-level `setup()` function to create a Rocket and set up the
  maps refresher task
* Change the type of `maps::run` since `!` is still an unstable type
* Fix HTTP code blocks in `README.md` so they don't appear as doctests
  to rustdoc
2022-03-15 09:54:02 +01:00
Paul van Tilburg 32964cea21
Add basic top-level tests
This starts to address #14 but didn't turn into a full MR yet.

* Use crates `assert_float_eq` and `assert_matches` for extra assertions
* Split off a function to build a Rocket `rocket()` that can be used
  in the tests
2022-03-11 16:03:56 +01:00
Paul van Tilburg 738409c3a8
Fix bound check using constant value
It should use the actual count instead!
2022-03-07 19:19:14 +01:00
Paul van Tilburg d33b5f1dbb
Hook up the combined metric in the forecast 2022-02-24 20:40:35 +01:00
Paul van Tilburg 95f30751c6
Add the combined provider 2022-02-24 20:40:07 +01:00
Paul van Tilburg 1ae6c896dd
Make item/sample fields available to the crate 2022-02-24 20:23:33 +01:00
Paul van Tilburg d0ace275ec
Filter out items that are older than 1h before now
Luchtmeetnet seems to yield some results that are in the past some
times?
2022-02-24 20:21:55 +01:00
Paul van Tilburg a78c55332f Refactor the API for the maps module
* Move the function `draw_position` to the maps module and split it up
* Replace and refactor `pollen_at` and `uvi_at` methods on `Maps`
  by `pollen_mark` and `uvi_mark`
* Drop the `pollen_project` and `uvi_project` methods on `Maps`,
  just call the `project` helper method directly
* Add `map_at` and `mark` helper methods that handle maps slicing
  and drawing
* Rename `pollen_sample` and `uvi_sample` methods on `Maps` to their
  plural forms
* Also, rename the map handlers to `map_address` and `map_geo`
2022-02-22 12:49:42 +01:00
Paul van Tilburg 84a434268f
Add README.md and LICENSE file (closes: #6)
Also link the files from the crate and include `README.md` as main crate
documentation.
2022-02-21 17:48:28 +01:00
Paul van Tilburg 7432fb3cd3 Fix Buienradar timestamp madness (closes: #3)
* Use the `Europe::Amsterdam` time zone from `chrono_tz` to determine
  what date/time it is in that time zone
* Parse timestamps in the rain text API relative to this date/time
* Add the `fix_items_day_boundary` function to fix up stuff if
  the series of timestamps in the rain text cross the day boundary
2022-02-20 17:39:49 +01:00
Paul van Tilburg 17d5daeabc Use chrono (UTC) timestamps for maps (closes: #12)
* Adapt `retrieve_image` to also return a timestamp based on the
  CDN's last modified time; adapt other methods accordingly
* For the maps module, use `chrono::Utc` instead of
  `tokio::time::Instant` and use `chrono::Duration` instead of
  `tokio::time::Duration`
* Pass the maps timestamp to the `sample` function so it can use
  that timestamp as base
2022-02-19 16:45:37 +01:00
Paul van Tilburg 46531a76bd Add retrieval of pollen and UVI metrics for Buienradar provider 2022-02-19 15:33:00 +01:00
Paul van Tilburg 5dc51b4c02 Implement map sampling using a map key
* Define the map key for Buienradar as `MAP_KEY` (colors used on
  Buienradar maps)
* Define a `MapkeyHistogram` type and add the `map_key_historgram()`
  function to construct one
* Define the sample size to look for pixels around the sampling
  coordinate
* Introduce a separata `sample` function that returns the samples
  for a map and the provided coordinates and starting timestamp
* Implement `Maps::pollen_sample` and Maps::uvi_sample`
2022-02-19 15:32:55 +01:00
Paul van Tilburg eb9951dbce Distinguish between a map and maps
* A map is a view into the image of concatenated maps
* Ensure that projection only happens on the first map
* Make `project` generic over all generic image views
2022-02-19 15:08:05 +01:00
Paul van Tilburg 0df30b695f Split off precipitation get code
This is necessary so that the Buienradar provider can support more
metrics using the maps.
2022-02-19 09:41:11 +01:00
Paul van Tilburg 7c24f73937 Add an extra map handler for showing lat/lon
* Split of the positioning and drawing code to the `draw_position`
  helper method
* Move the positioning and drawing code to a Tokia task
2022-02-18 23:18:50 +01:00
Paul van Tilburg a03573d20d Allow dead code for not-yet-implemented methods (for now) 2022-02-18 23:04:49 +01:00
Paul van Tilburg 7895b5afc9 Hook up the map projection in the map debug handler
Also change how the resulting coordinate is marked on the map
(2 line guides instead of a square).
2022-02-18 23:00:58 +01:00
Paul van Tilburg 4b80121187 Implement map projection using reference points
* Use the Mercator projection to get the image coordinates
* Fix errors in the reference points
* Tweak documentation
2022-02-18 22:59:21 +01:00
Paul van Tilburg 7d1a1a1c0d Add helper methods that calculate lat/lon in radians 2022-02-18 22:58:39 +01:00
Paul van Tilburg 6b62cc7797 Add some unimplemented API for map project and sampling
* Add map reference point constants `*_MAP_REF_POINTS `that can be used
  for map projections
* Add (unimplemented )`*_project` and `*_sample` methods to the `Maps`
  implementation
* Add `PollenSample` and `UviSample` structs
* Make `Position::new` const
2022-02-18 21:25:06 +01:00
Paul van Tilburg f1a303edc0
Use address instead of position for map debug handler 2022-02-17 22:25:13 +01:00
Paul van Tilburg 4920ab4abd
Drop Weerplaza precipitation maps (closes: #8) 2022-02-17 21:47:01 +01:00
Paul van Tilburg f67f3dfe82
Only update the cache if retrieval yielded maps
* Add `is_*_stale` methods to the `MapRefresh` trait
* Only update the maps of a type if `retrieve_image` yielded something
  or if the maps are stale
* Also only then bump the timestamp for the map type

This means if there is nothing in the cache, it will retry each refresh
to get something because the timestamp is not bumped until there is
something. Once there are maps, it will only update it and bump the
timestamp if there is an image, that or, it has become stale and it
can be set to `None` and we end up in the initial state.
2022-02-17 21:38:41 +01:00
Paul van Tilburg 8d2717b392
Provide not the first map but an instant-relative map
This calculates which offset to use in the maps series with respect to
the instant of caching. It assumes the first map is current for the
instant it was retrieved.

* Rename `*_first` to `*_at` methods
* For convenience, change the types of `*_MAP_COUNT` to `u32`
* Introduce `*_MAP_INTERVAL` constants to indicate the number of
  seconds each map in the series applies to
* Return `None` if the provided instant is too far in the future
2022-02-17 21:38:16 +01:00