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
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.
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.
* 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
* 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
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
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
* 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`
* 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
* 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
* 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`
* 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
* 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