neiam
/apollos_crib
It's Apollo's Crib
public · Issues · Pulls 1 · Labels · Forks · Compare · Actions failure · Badges · Packages
Log in to mark this repository.
Ask the weather where you are
54a26e2 · Gabriel Morell · 2026-09-03 18:18
Message
{commit_body(@commit)}
Files changed
modified
PLANI.md
+9
−8
| 76 | 76 | out of the Ecto schema. |
| 77 | 77 | |
| 78 | 78 | **Sources answered *at* a point rather than *near* one.** Weather, sunrise, |
| 79 | −pollen, the tide at the nearest station: there is one answer and it is | |
| 80 | −computed for wherever you are. These already take a `foci_id` in their query | |
| 81 | −config (`weather`, `ephem`, `pollen`, `calendar`, `cronos`, `icarus`), so the | |
| 82 | −change is to accept a point instead — the smallest useful stage, and it needs | |
| 83 | −no spatial indexing at all. | |
| 79 | +pollen, what is overhead: there is one answer and it is computed for wherever | |
| 80 | +you are. Done, via `Configuration.place_for!/1` — every one of them resolved a | |
| 81 | +foci with the same two lines, so they now take a place when one is handed over | |
| 82 | +and a foci id otherwise. `weather`, `ephem`, `pollen` and `icarus` relocate; | |
| 83 | +`cronos` uses its foci for a timezone rather than a position, and `calendar` | |
| 84 | +for filtering, so neither moves. | |
| 84 | 85 | |
| 85 | 86 | **Sources with no location.** `github`, `gitlab`, `packages`, `mailbox`, |
| 86 | 87 | `treasury`, `bourse`. A Plani should either refuse these or pass them through |
| 94 | 95 | home foci. Publishes nothing yet — but the resolution, the expiry and the |
| 95 | 96 | fallback are the part with the design risk in it, and it can be watched on |
| 96 | 97 | a page before anything depends on it. |
| 97 | −2. **Relocatable point sources.** Give the query workers that take a `foci_id` | |
| 98 | − a way to take a `%Geo.Point{}`. Weather and ephem where you are. No schema | |
| 99 | − changes. | |
| 98 | +2. ~~**Relocatable point sources.**~~ Done: `place_for!/1` is the one helper | |
| 99 | + they all use, so a Plani relocates weather, sunrise, pollen and aircraft | |
| 100 | + without any of them knowing what a Plani is. | |
| 100 | 101 | 3. **Nearest-N for what is already indexed.** GBFS stations and bikes, AQI |
| 101 | 102 | monitors. The queries exist; they need a limit and a caller. |
| 102 | 103 | 4. ~~**GTFS stops.**~~ Done: `gtfs_stops.place` is generated and GiST indexed, |
modified
apps/room_cronos/lib/room_cronos/cronos_worker.ex
+1
−1
| 12 | 12 | # @decorate cacheable(cache: RoomZeus.Cache, opts: [ttl: @ttl]) |
| 13 | 13 | def query_cronos(name, query) do |
| 14 | 14 | q = Configuration.get_query!(name) |
| 15 | − foci = Configuration.get_foci!(query.foci_id) | |
| 15 | + foci = %{place: Configuration.place_for!(query)} | |
| 16 | 16 | {lon, lat} = foci.place.coordinates |
| 17 | 17 | tz = WhereTZ.lookup(lat, lon) |
| 18 | 18 | now = DateTime.now!(tz) |
modified
apps/room_ephem/lib/room_ephem/ephem_worker.ex
+2
−3
| 97 | 97 | @decorate cacheable(cache: RoomZeus.Cache, opts: [ttl: @ttl]) |
| 98 | 98 | def query_ephem(_name, query) do |
| 99 | 99 | IO.inspect("QEPH") |
| 100 | − foci = Configuration.get_foci!(query.foci_id) | |
| 101 | − {lon, lat} = foci.place.coordinates | |
| 100 | + {lon, lat} = Configuration.place_for!(query).coordinates | |
| 102 | 101 | lat = normalize_ll(lat) |
| 103 | 102 | lon = normalize_ll(lon) |
| 104 | 103 |
| 136 | 135 | |> DateTime.to_time() |
| 137 | 136 | }, |
| 138 | 137 | %{period: :phase, result: phase}, |
| 139 | − %{name: foci.name} | |
| 138 | + %{name: Configuration.place_name(query)} | |
| 140 | 139 | ] ++ moon_entries |
| 141 | 140 | end |
| 142 | 141 | end |
modified
apps/room_icarus/lib/room_icarus/worker.ex
+7
−1
| 317 | 317 | defp via_tuple(name), do: {:via, Registry, {@registry, name}} |
| 318 | 318 | |
| 319 | 319 | defp target_from_query(query) do |
| 320 | − case resolve_foci(field(query, :foci_id)) do | |
| 320 | + case resolve_foci(RoomSanctum.Configuration.place_for!(query) || field(query, :foci_id)) do | |
| 321 | 321 | {lat, lon} -> {lat, lon, clamp_dist(field(query, :dist))} |
| 322 | 322 | nil -> nil |
| 323 | 323 | end |
| 325 | 325 | |
| 326 | 326 | defp resolve_foci(nil), do: nil |
| 327 | 327 | |
| 328 | + # A Plani asks from wherever its client is, which is not a foci and has no | |
| 329 | + # row to look up. | |
| 330 | + # Matched by shape rather than as a %Geo.Point{}: this app does not | |
| 331 | + # depend on geo, and the only thing here with coordinates is a place. | |
| 332 | + defp resolve_foci(%{coordinates: {lon, lat}}), do: {lat, lon} | |
| 333 | + | |
| 328 | 334 | defp resolve_foci(foci_id) do |
| 329 | 335 | try do |
| 330 | 336 | case Configuration.get_foci!(foci_id) do |
modified
apps/room_pollen/lib/room_pollen/worker.ex
+11
−2
| 131 | 131 | defp creds(_), do: :no_creds |
| 132 | 132 | |
| 133 | 133 | defp target_from_query(query) do |
| 134 | − foci_id = Map.get(query, :foci_id) || Map.get(query, "foci_id") | |
| 134 | + # A place if one was handed over, otherwise the foci named in the query. | |
| 135 | + anchor = | |
| 136 | + RoomSanctum.Configuration.place_for!(query) || | |
| 137 | + Map.get(query, :foci_id) || Map.get(query, "foci_id") | |
| 135 | 138 | |
| 136 | 139 | days = |
| 137 | 140 | case Map.get(query, :days) || Map.get(query, "days") do |
| 140 | 143 | _ -> 3 |
| 141 | 144 | end |
| 142 | 145 | |
| 143 | − case resolve_foci(foci_id) do | |
| 146 | + case resolve_foci(anchor) do | |
| 144 | 147 | {lat, lng} -> {lat, lng, days} |
| 145 | 148 | nil -> nil |
| 146 | 149 | end |
| 148 | 151 | |
| 149 | 152 | defp resolve_foci(nil), do: nil |
| 150 | 153 | |
| 154 | + # A Plani asks from wherever its client is, which is not a foci and has no | |
| 155 | + # row to look up. | |
| 156 | + # Matched by shape rather than as a %Geo.Point{}: this app does not | |
| 157 | + # depend on geo, and the only thing here with coordinates is a place. | |
| 158 | + defp resolve_foci(%{coordinates: {lng, lat}}), do: {lat, lng} | |
| 159 | + | |
| 151 | 160 | defp resolve_foci(foci_id) do |
| 152 | 161 | try do |
| 153 | 162 | case Configuration.get_foci!(foci_id) do |
modified
?
+0
−0
Click to load diff…
modified
?
+0
−0
Click to load diff…
modified
apps/room_sanctum/lib/room_sanctum/configuration.ex
+35
−0
Click to load diff…
modified
apps/room_sanctum/lib/room_sanctum/workers/plani_worker.ex
+33
−2
Click to load diff…
modified
apps/room_sanctum/lib/room_sanctum_web/live/cfg_plani_live/form_component.ex
+22
−6
Click to load diff…
added
apps/room_sanctum/test/room_sanctum/place_for_test.exs
+55
−0
Click to load diff…
modified
apps/room_weather/lib/room_weather/weather_worker.ex
+1
−2
Click to load diff…
Parents: 7b6b5ac