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.
gbfs worker splitbrain via parent + basic gtfs-rt support trip-update only for now + fix for the 11pm problem via conditionals in piped queries, keeping the atom based one for a bit for lols
d7b8847 · gmorell · 2022-10-17 03:53
Files changed
modified
.idea/misc.xml
+1
−1
@@ -3,7 +3,7 @@
| 3 | 3 | <component name="FrameworkDetectionExcludesConfiguration"> |
| 4 | 4 | <file type="MicroPython" url="file://$PROJECT_DIR$/clients" /> |
| 5 | 5 | </component> |
| 6 | − <component name="ProjectRootManager" version="2" languageLevel="JDK_18"> | |
| 6 | + <component name="ProjectRootManager" version="2" languageLevel="JDK_18" project-jdk-name="Elixir at /usr/lib/elixir" project-jdk-type="Elixir SDK"> | |
| 7 | 7 | <output url="file://$PROJECT_DIR$/classes" /> |
| 8 | 8 | </component> |
| 9 | 9 | </project> |
modified
apollos_crib.iml
+1
−2
@@ -2,7 +2,7 @@
| 2 | 2 | <module type="ELIXIR_MODULE" version="4"> |
| 3 | 3 | <component name="FacetManager"> |
| 4 | 4 | <facet type="Python" name="Python"> |
| 5 | − <configuration sdkName="Python 3.8" /> | |
| 5 | + <configuration sdkName="" /> | |
| 6 | 6 | </facet> |
| 7 | 7 | </component> |
| 8 | 8 | <component name="NewModuleRootManager"> |
@@ -98,6 +98,5 @@
| 98 | 98 | <excludeFolder url="file://$MODULE_DIR$/_build/dev/lib/credentials_obfuscation" /> |
| 99 | 99 | </content> |
| 100 | 100 | <orderEntry type="sourceFolder" forTests="false" /> |
| 101 | − <orderEntry type="library" name="Python 3.8 interpreter library" level="application" /> | |
| 102 | 101 | </component> |
| 103 | 102 | </module> |
modified
apps/room_gbfs/lib/room_gbfs/gbfs_worker.ex
+2
−2
@@ -15,7 +15,7 @@ defmodule RoomGbfs.Worker do
| 15 | 15 | end |
| 16 | 16 | |
| 17 | 17 | def init(opts) do |
| 18 | − {:ok, %{id: opts[:name]}} | |
| 18 | + {:ok, %{id: opts[:name], inst: nil}} | |
| 19 | 19 | end |
| 20 | 20 | |
| 21 | 21 | # public |
@@ -47,7 +47,7 @@ defmodule RoomGbfs.Worker do
| 47 | 47 | |
| 48 | 48 | def handle_cast(:refresh_db_cfg, state) do |
| 49 | 49 | IO.puts("rerere") |
| 50 | − {:noreply, state} | |
| 50 | + {:noreply, state |> Map.put(:inst, nil)} | |
| 51 | 51 | end |
| 52 | 52 | |
| 53 | 53 | defp bcast(id, file, complete, total) do |
modified
apps/room_gtfs/lib/room_gtfs/gtfs_worker.ex
+229
−12
@@ -1,6 +1,6 @@
| 1 | 1 | defmodule RoomGtfs.Worker do |
| 2 | 2 | @moduledoc false |
| 3 | − use GenServer | |
| 3 | + use Parent.GenServer | |
| 4 | 4 | |
| 5 | 5 | require Logger |
| 6 | 6 |
@@ -11,7 +11,7 @@ defmodule RoomGtfs.Worker do
| 11 | 11 | @registry :zeus |
| 12 | 12 | |
| 13 | 13 | def start_link(opts) do |
| 14 | − GenServer.start_link(__MODULE__, opts, name: via_tuple("gtfs" <> opts[:name])) | |
| 14 | + Parent.GenServer.start_link(__MODULE__, opts, name: via_tuple("gtfs" <> opts[:name])) | |
| 15 | 15 | end |
| 16 | 16 | |
| 17 | 17 | # Public |
@@ -33,29 +33,252 @@ defmodule RoomGtfs.Worker do
| 33 | 33 | |> GenServer.cast(:update_realtime) |
| 34 | 34 | end |
| 35 | 35 | |
| 36 | + def get_current_realtime(name, trips, stop) do | |
| 37 | + "gtfs#{name}" | |
| 38 | + |> via_tuple | |
| 39 | + |> GenServer.call({:query_realtime, trips, stop}) | |
| 40 | + end | |
| 41 | + | |
| 36 | 42 | def query_stop(id, query) do |
| 37 | − # Simple implementation for now, gtfs-rt bs later | |
| 38 | − Storage.get_upcoming_arrivals_for_stop(id, query.stop) | |
| 43 | + inst = Configuration.get_source!(id) | |
| 44 | + res = Storage.get_upcoming_arrivals_for_stop(id, query.stop) | |
| 45 | + case inst.config.url_rt_tu do | |
| 46 | + nil -> res | |
| 47 | + _val -> trips = res |> Enum.map(fn x -> x.trip_id end) | |
| 48 | + | |
| 49 | + case get_current_realtime(id, trips, query.stop) do | |
| 50 | + [] -> | |
| 51 | + res | |
| 52 | + | |
| 53 | + rtvals -> | |
| 54 | + res | |
| 55 | + |> Enum.map(fn x -> | |
| 56 | + case Enum.find(rtvals, fn v -> x.trip_id == v.trip_update.trip.trip_id end) do | |
| 57 | + nil -> | |
| 58 | + x | |
| 59 | + | |
| 60 | + val -> | |
| 61 | + case val.trip_update.stop_time_update.arrival do | |
| 62 | + nil -> | |
| 63 | + x | |
| 64 | + | |
| 65 | + _arrival -> | |
| 66 | + x | |
| 67 | + |> Map.put(:arrival_time_live_ts, val.trip_update.stop_time_update.arrival.time) | |
| 68 | + |> Map.put( | |
| 69 | + :arrival_time_live_delay, | |
| 70 | + val.trip_update.stop_time_update.arrival.delay | |
| 71 | + ) | |
| 72 | + |> Map.put( | |
| 73 | + :arrival_time_live_uncertianty, | |
| 74 | + val.trip_update.stop_time_update.arrival.uncertainty | |
| 75 | + ) | |
| 76 | + end | |
| 77 | + end | |
| 78 | + end) | |
| 79 | + end | |
| 80 | + end | |
| 81 | + | |
| 39 | 82 | end |
| 40 | 83 | |
| 41 | 84 | # etc |
| 42 | 85 | def init(opts) do |
| 43 | − {:ok, %{id: opts[:name]}} | |
| 86 | + Periodic.start_link( | |
| 87 | + every: :timer.seconds(4), | |
| 88 | + run: fn -> RoomGtfs.Worker.refresh_db_cfg(opts[:name]) end, | |
| 89 | + initial_delay: 10 | |
| 90 | + ) | |
| 91 | + | |
| 92 | + {:ok, child_rt} = Parent.start_child({RoomGtfs.Worker.RT, opts}) | |
| 93 | + {:ok, child_static} = Parent.start_child({RoomGtfs.Worker.Static, opts}) | |
| 94 | + | |
| 95 | + {:ok, | |
| 96 | + %{ | |
| 97 | + id: opts[:name], | |
| 98 | + inst: nil, | |
| 99 | + child_rt: child_rt, | |
| 100 | + child_static: child_static | |
| 101 | + }} | |
| 102 | + end | |
| 103 | + | |
| 104 | + def handle_cast(:refresh_db_cfg, state) do | |
| 105 | + inst = Configuration.get_source!(state.id) | |
| 106 | + {:noreply, state |> Map.put(:inst, inst)} | |
| 107 | + end | |
| 108 | + | |
| 109 | + def handle_cast(:update_static, state) do | |
| 110 | + GenServer.cast(state.child_static, :update_static) | |
| 111 | + {:noreply, state} | |
| 112 | + end | |
| 113 | + | |
| 114 | + def handle_cast(:update_realtime, state) do | |
| 115 | + GenServer.cast(state.child_rt, :update_realtime) | |
| 116 | + {:noreply, state} | |
| 117 | + end | |
| 118 | + | |
| 119 | + def handle_cast(_msg, state) do | |
| 120 | + {:noreply, state} | |
| 121 | + end | |
| 122 | + | |
| 123 | + def handle_call({:query_realtime, trips, stop}, _from, state) do | |
| 124 | + r = GenServer.call(state.child_rt, {:query_realtime, trips, stop}) | |
| 125 | + {:reply, r, state} | |
| 44 | 126 | end |
| 45 | 127 | |
| 46 | 128 | def handle_call(_msg, _from, state) do |
| 47 | 129 | {:reply, :ok, state} |
| 48 | 130 | end |
| 49 | 131 | |
| 132 | + defp via_tuple(name), do: {:via, Registry, {@registry, name}} | |
| 133 | +end | |
| 134 | + | |
| 135 | +defmodule RoomGtfs.Worker.RT do | |
| 136 | + use GenServer | |
| 137 | + @registry :zeus | |
| 138 | + | |
| 139 | + alias RoomSanctum.Configuration | |
| 140 | + alias RoomSanctum.Storage | |
| 141 | + alias RoomSanctum.Repo | |
| 142 | + | |
| 143 | + def start_link(opts) do | |
| 144 | + GenServer.start_link(__MODULE__, opts, name: via_tuple("gtfs-rt" <> opts[:name])) | |
| 145 | + end | |
| 146 | + | |
| 147 | + def update_realtime_data(name) do | |
| 148 | + "gtfs-rt#{name}" | |
| 149 | + |> via_tuple() | |
| 150 | + |> GenServer.cast(:update_realtime) | |
| 151 | + end | |
| 152 | + | |
| 153 | + def refresh_db_cfg(name) do | |
| 154 | + "gtfs-rt#{name}" | |
| 155 | + |> via_tuple() | |
| 156 | + |> GenServer.cast(:refresh_db_cfg) | |
| 157 | + end | |
| 158 | + | |
| 159 | + def init(opts) do | |
| 160 | + Periodic.start_link( | |
| 161 | + every: :timer.seconds(4), | |
| 162 | + run: fn -> RoomGtfs.Worker.RT.refresh_db_cfg(opts[:name]) end, | |
| 163 | + initial_delay: 10 | |
| 164 | + ) | |
| 165 | + | |
| 166 | + Periodic.start_link( | |
| 167 | + every: :timer.seconds(30), | |
| 168 | + run: fn -> RoomGtfs.Worker.RT.update_realtime_data(opts[:name]) end, | |
| 169 | + initial_delay: 100 | |
| 170 | + ) | |
| 171 | + | |
| 172 | + {:ok, | |
| 173 | + %{ | |
| 174 | + id: opts[:name], | |
| 175 | + inst: nil, | |
| 176 | + rt_sa: nil, | |
| 177 | + rt_tu: nil, | |
| 178 | + rt_vp: nil | |
| 179 | + }} | |
| 180 | + end | |
| 181 | + | |
| 182 | + defp via_tuple(name), do: {:via, Registry, {@registry, name}} | |
| 183 | + | |
| 184 | + def fetch_rt_url(url) do | |
| 185 | + case HTTPoison.get(url, [], follow_redirect: true) do | |
| 186 | + {:ok, result} -> {:ok, result.body |> TransitRealtime.FeedMessage.decode()} | |
| 187 | + {:error, error} -> {:error, error} | |
| 188 | + end | |
| 189 | + end | |
| 190 | + | |
| 50 | 191 | def handle_cast(:refresh_db_cfg, state) do |
| 51 | − IO.puts("rerere") | |
| 192 | + inst = Configuration.get_source!(state.id) | |
| 193 | + {:noreply, state |> Map.put(:inst, inst)} | |
| 194 | + end | |
| 195 | + | |
| 196 | + def handle_cast(:update_realtime, state) do | |
| 197 | + state = | |
| 198 | + case state.inst.config |> Map.get(:url_rt_sa) do | |
| 199 | + nil -> | |
| 200 | + state | |
| 201 | + | |
| 202 | + val -> | |
| 203 | + case fetch_rt_url(val) do | |
| 204 | + {:ok, data_sa} -> state |> Map.put(:rt_sa, data_sa) | |
| 205 | + {:error, _error} -> state | |
| 206 | + end | |
| 207 | + end | |
| 208 | + | |
| 209 | + state = | |
| 210 | + case state.inst.config |> Map.get(:url_rt_tu) do | |
| 211 | + nil -> | |
| 212 | + state | |
| 213 | + | |
| 214 | + val -> | |
| 215 | + case fetch_rt_url(val) do | |
| 216 | + {:ok, data_tu} -> state |> Map.put(:rt_tu, data_tu) | |
| 217 | + {:error, _error} -> state | |
| 218 | + end | |
| 219 | + end | |
| 220 | + | |
| 221 | + state = | |
| 222 | + case state.inst.config |> Map.get(:url_rt_vp) do | |
| 223 | + nil -> | |
| 224 | + state | |
| 225 | + | |
| 226 | + val -> | |
| 227 | + case fetch_rt_url(val) do | |
| 228 | + {:ok, data_vp} -> state |> Map.put(:rt_vp, data_vp) | |
| 229 | + {:error, _error} -> state | |
| 230 | + end | |
| 231 | + end | |
| 232 | + | |
| 52 | 233 | {:noreply, state} |
| 53 | 234 | end |
| 54 | 235 | |
| 236 | + def handle_call({:query_realtime, trips, stop}, _from, state) do | |
| 237 | +# IO.inspect(trips) | |
| 238 | + | |
| 239 | + # filter out the protobuf for all relevant trips and then the relevant stop on that trip, nice and small | |
| 240 | + relevant_trips = | |
| 241 | + state.rt_tu.entity | |
| 242 | + |> Enum.filter(fn x -> Enum.member?(trips, x.trip_update.trip.trip_id) end) | |
| 243 | + |> Enum.map(fn x -> | |
| 244 | + x | |
| 245 | + |> Kernel.put_in( | |
| 246 | + [Access.key(:trip_update, %{}), Access.key(:stop_time_update, %{})], | |
| 247 | + x.trip_update.stop_time_update | |
| 248 | + |> Enum.filter(fn x -> x.stop_id == stop end) | |
| 249 | + |> List.first() | |
| 250 | + ) | |
| 251 | + end) | |
| 252 | + {:reply, relevant_trips, state} | |
| 253 | + end | |
| 254 | +end | |
| 255 | + | |
| 256 | +defmodule RoomGtfs.Worker.Static do | |
| 257 | + use GenServer | |
| 258 | + require Logger | |
| 259 | + @registry :zeus | |
| 260 | + | |
| 261 | + alias RoomSanctum.Configuration | |
| 262 | + alias RoomSanctum.Storage | |
| 263 | + alias RoomSanctum.Repo | |
| 264 | + | |
| 265 | + def start_link(opts) do | |
| 266 | + GenServer.start_link(__MODULE__, opts, name: via_tuple("gtfs-st" <> opts[:name])) | |
| 267 | + end | |
| 268 | + | |
| 55 | 269 | defp bcast(id, file, complete, total) do |
| 56 | 270 | Phoenix.PubSub.broadcast(RoomSanctum.PubSub, "gtfs", {:gtfs, id, file, complete, total}) |
| 57 | 271 | end |
| 58 | 272 | |
| 273 | + def init(opts) do | |
| 274 | + {:ok, | |
| 275 | + %{ | |
| 276 | + id: opts[:name] | |
| 277 | + }} | |
| 278 | + end | |
| 279 | + | |
| 280 | + defp via_tuple(name), do: {:via, Registry, {@registry, name}} | |
| 281 | + | |
| 59 | 282 | defp write_file(contents, type, id) do |
| 60 | 283 | datetime = NaiveDateTime.local_now() |
| 61 | 284 | Logger.info("GTFS::#{id} writing #{type}") |
@@ -238,10 +461,4 @@ defmodule RoomGtfs.Worker do
| 238 | 461 | |
| 239 | 462 | {:noreply, state} |
| 240 | 463 | end |
| 241 | − | |
| 242 | − def handle_cast(_msg, state) do | |
| 243 | − {:noreply, state} | |
| 244 | − end | |
| 245 | − | |
| 246 | − defp via_tuple(name), do: {:via, Registry, {@registry, name}} | |
| 247 | 464 | end |
modified
apps/room_sanctum/lib/room_sanctum/condensers/basic_mqtt.ex
+22
−7
@@ -26,9 +26,17 @@ defmodule RoomSanctum.Condenser.BasicMQTT do
| 26 | 26 | datestr |> Timex.parse!("{ISO:Extended}") |> Timex.format!( "%H:%M", :strftime) |
| 27 | 27 | end |
| 28 | 28 | |
| 29 | + defp livetime(unix, _tz) when is_nil(unix) do | |
| 30 | + unix | |
| 31 | + end | |
| 32 | + | |
| 33 | + defp livetime(unix, tz) do | |
| 34 | + unix |> DateTime.from_unix! |> Timex.Timezone.convert(tz) |> DateTime.to_time | |
| 35 | + end | |
| 36 | + | |
| 29 | 37 | def condense({_id, type}, data) do |
| 30 | −# if type == :tidal do | |
| 31 | −# IO.inspect({id, type, data}) | |
| 38 | +# if type == :gtfs do | |
| 39 | +# IO.inspect({type, data}) | |
| 32 | 40 | # end |
| 33 | 41 | |
| 34 | 42 | case type do |
@@ -37,19 +45,26 @@ defmodule RoomSanctum.Condenser.BasicMQTT do
| 37 | 45 | |> Enum.map(fn f -> |
| 38 | 46 | %{ |
| 39 | 47 | time: f.arrival_time, |
| 48 | + time_live: f.arrival_time_live_ts, | |
| 40 | 49 | destination: f.trip.trip_headsign, |
| 41 | 50 | direction: f.trip.direction.direction, |
| 42 | 51 | route: f.trip.route_id, |
| 43 | − mode: f.trip.route.route_type |> gtfs_mode | |
| 52 | + mode: f.trip.route.route_type |> gtfs_mode, | |
| 53 | + tz: f.tz | |
| 44 | 54 | } |
| 45 | 55 | end) |
| 46 | − |> Enum.reduce(%{}, fn %{time: time, destination: dest, direction: dir, route: route, mode: mode}, acc -> | |
| 56 | + |> Enum.reduce(%{}, fn %{time: time, time_live: time_live, destination: dest, direction: dir, route: route, mode: mode, tz: tz}, acc -> | |
| 47 | 57 | update_in(acc, [{route, dest, dir}], fn |
| 48 | − nil -> %{route: route, dest: dest, dir: dir, mode: mode, times: [time]} | |
| 49 | − refs -> %{refs | times: [time | refs.times]} | |
| 58 | + nil -> %{route: route, dest: dest, dir: dir, mode: mode, times: [time], times_live: [livetime(time_live, tz)]} | |
| 59 | + refs -> %{refs | times: [time | refs.times], times_live: [livetime(time_live, tz) | refs.times_live]} | |
| 50 | 60 | end) |
| 51 | 61 | end) |
| 52 | − |> Enum.map(fn {_k,v} -> v |> Map.put(:times, v.times |> Enum.reverse) end) | |
| 62 | + |> Enum.map(fn {_k,v} -> | |
| 63 | + case Enum.any?(v.times_live, fn x -> x != nil end) do | |
| 64 | + true -> v |> Map.put(:times, v.times |> Enum.reverse) |> Map.put(:times_live, v.times_live |> Enum.reverse) | |
| 65 | + false -> v |> Map.put(:times, v.times |> Enum.reverse) |> Map.delete(:times_live) | |
| 66 | + end | |
| 67 | + end) | |
| 53 | 68 | |
| 54 | 69 | :gbfs -> |
| 55 | 70 | data |
modified
apps/room_sanctum/lib/room_sanctum/storage.ex
+162
−76
@@ -807,6 +807,13 @@ defmodule RoomSanctum.Storage do
| 807 | 807 | val |
| 808 | 808 | end |
| 809 | 809 | |
| 810 | + defp conditional_where(queryable, source_id, stop_id, timestamp_time_hour, timestamp_time) do | |
| 811 | + case timestamp_time < timestamp_time_hour do | |
| 812 | + true -> where(queryable, [st], st.source_id == ^source_id and st.arrival_time >= ^timestamp_time and st.arrival_time <= ^timestamp_time_hour and st.stop_id == ^stringify(stop_id)) | |
| 813 | + false -> where(queryable, [st], st.source_id == ^source_id and (st.arrival_time >= ^timestamp_time and st.arrival_time <= ^Time.new!(23, 59, 50) or ^Time.new!(0,0,0) <= st.arrival_time and st.arrival_time <= ^timestamp_time_hour) and st.stop_id == ^stringify(stop_id)) | |
| 814 | + end | |
| 815 | + end | |
| 816 | + | |
| 810 | 817 | def get_upcoming_arrivals_for_stop(source_id, stop_id, limit \\ 16, timestamp \\ :now) do |
| 811 | 818 | source = Cfg.get_source!(source_id) |
| 812 | 819 | tz = source.config.tz |
@@ -823,82 +830,161 @@ defmodule RoomSanctum.Storage do
| 823 | 830 | |
| 824 | 831 | timestamp_time_hour = timestamp |> DateTime.add(60*60) |> DateTime.to_time() |
| 825 | 832 | |
| 826 | − q = | |
| 827 | − from st in StopTime, | |
| 828 | − where: | |
| 829 | − st.source_id == ^source_id and st.arrival_time >= ^timestamp_time and st.arrival_time <= ^timestamp_time_hour and st.stop_id == ^stringify(stop_id), | |
| 830 | − order_by: [ | |
| 831 | − asc: st.arrival_time | |
| 832 | − ], | |
| 833 | − limit: ^limit, | |
| 834 | − left_join: s in Stop, | |
| 835 | − on: s.stop_id == st.stop_id, | |
| 836 | − left_join: t in Trip, | |
| 837 | − on: t.trip_id == st.trip_id, | |
| 838 | − left_join: r in Route, | |
| 839 | − on: t.route_id == r.route_id, | |
| 840 | − left_join: d in Direction, | |
| 841 | − on: t.direction_id == d.direction_id and t.route_id == d.route_id, | |
| 842 | − left_join: c in Calendar, | |
| 843 | − on: t.service_id == c.service_id, | |
| 844 | − select: %{ | |
| 845 | − arrival_time: st.arrival_time, | |
| 846 | − departure_time: st.departure_time, | |
| 847 | − stop_id: st.stop_id, | |
| 848 | − stop_sequence: st.stop_sequence, | |
| 849 | − stop: %{ | |
| 850 | − stop_address: s.stop_address, | |
| 851 | − stop_code: s.stop_code, | |
| 852 | − stop_desc: s.stop_desc, | |
| 853 | − stop_id: s.stop_id, | |
| 854 | − stop_lat: s.stop_lat, | |
| 855 | − stop_lon: s.stop_lon, | |
| 856 | − stop_name: s.stop_name, | |
| 857 | − stop_url: s.stop_url | |
| 858 | − }, | |
| 859 | − trip_id: st.trip_id, | |
| 860 | − trip: %{ | |
| 861 | − bikes_allowed: t.bikes_allowed, | |
| 862 | − direction_id: t.direction_id, | |
| 863 | − direction: %{ | |
| 864 | − direction: d.direction, | |
| 865 | − direction_id: d.direction_id | |
| 866 | − }, | |
| 867 | − route_id: t.route_id, | |
| 868 | − route: %{ | |
| 869 | − line_id: r.line_id, | |
| 870 | − route_color: r.route_color, | |
| 871 | − route_desc: r.route_desc, | |
| 872 | − route_fare_class: r.route_fare_class, | |
| 873 | − route_id: r.route_id, | |
| 874 | − route_long_name: r.route_long_name, | |
| 875 | − route_short_name: r.route_short_name, | |
| 876 | − route_sort_order: r.route_sort_order, | |
| 877 | − route_text_color: r.route_text_color, | |
| 878 | − route_type: r.route_type, | |
| 879 | − route_url: r.route_url | |
| 880 | − }, | |
| 881 | − service_id: t.service_id, | |
| 882 | − service: %{ | |
| 883 | − service_id: c.service_id, | |
| 884 | − service_name: c.service_name, | |
| 885 | − start_date: c.start_date, | |
| 886 | − end_date: c.end_date, | |
| 887 | − monday: c.monday, | |
| 888 | − tuesday: c.tuesday, | |
| 889 | − wednesday: c.wednesday, | |
| 890 | − thursday: c.thursday, | |
| 891 | − friday: c.friday, | |
| 892 | − saturday: c.saturday, | |
| 893 | − sunday: c.sunday | |
| 894 | − }, | |
| 895 | − trip_headsign: t.trip_headsign, | |
| 896 | − trip_id: t.trip_id, | |
| 897 | − trip_short_name: t.trip_short_name | |
| 898 | − } | |
| 899 | − } | |
| 900 | − | |
| 901 | − Repo.all(q) | |
| 833 | + StopTime | |
| 834 | + |> conditional_where(source_id, stop_id, timestamp_time_hour, timestamp_time) | |
| 835 | + |> order_by([st], asc: st.arrival_time) | |
| 836 | + |> limit(^limit) | |
| 837 | + |> join(:left, [st], s in Stop, as: :stop, on: s.stop_id == st.stop_id) | |
| 838 | + |> join(:left, [st], t in Trip, as: :trip, on: t.trip_id == st.trip_id) | |
| 839 | + |> join(:left, [_st, trip: t], r in Route, as: :route, on: t.route_id == r.route_id) | |
| 840 | + |> join(:left, [_st, trip: t], d in Direction, as: :direction, on: t.direction_id == d.direction_id and t.route_id == d.route_id ) | |
| 841 | + |> join(:left, [_st, trip: t], c in Calendar, as: :calendar, on: t.service_id == c.service_id) | |
| 842 | + |> select( | |
| 843 | + [st,s,t,r,d,c], | |
| 844 | +# [c,d,r,t,s,st], | |
| 845 | +# [st,:stop,:trip,:route,:direction,:calendar], | |
| 846 | + %{ | |
| 847 | + arrival_time: st.arrival_time, | |
| 848 | + arrival_time_live_ts: nil, | |
| 849 | + arrival_time_live_delay: nil, | |
| 850 | + arrival_time_live_uncertianty: nil, | |
| 851 | + departure_time: st.departure_time, | |
| 852 | + stop_id: st.stop_id, | |
| 853 | + stop_sequence: st.stop_sequence, | |
| 854 | + stop: %{ | |
| 855 | + stop_address: s.stop_address, | |
| 856 | + stop_code: s.stop_code, | |
| 857 | + stop_desc: s.stop_desc, | |
| 858 | + stop_id: s.stop_id, | |
| 859 | + stop_lat: s.stop_lat, | |
| 860 | + stop_lon: s.stop_lon, | |
| 861 | + stop_name: s.stop_name, | |
| 862 | + stop_url: s.stop_url | |
| 863 | + }, | |
| 864 | + trip_id: st.trip_id, | |
| 865 | + trip: %{ | |
| 866 | + bikes_allowed: t.bikes_allowed, | |
| 867 | + direction_id: t.direction_id, | |
| 868 | + direction: %{ | |
| 869 | + direction: d.direction, | |
| 870 | + direction_id: d.direction_id | |
| 871 | + }, | |
| 872 | + route_id: t.route_id, | |
| 873 | + route: %{ | |
| 874 | + line_id: r.line_id, | |
| 875 | + route_color: r.route_color, | |
| 876 | + route_desc: r.route_desc, | |
| 877 | + route_fare_class: r.route_fare_class, | |
| 878 | + route_id: r.route_id, | |
| 879 | + route_long_name: r.route_long_name, | |
| 880 | + route_short_name: r.route_short_name, | |
| 881 | + route_sort_order: r.route_sort_order, | |
| 882 | + route_text_color: r.route_text_color, | |
| 883 | + route_type: r.route_type, | |
| 884 | + route_url: r.route_url | |
| 885 | + }, | |
| 886 | + service_id: t.service_id, | |
| 887 | + service: %{ | |
| 888 | + service_id: c.service_id, | |
| 889 | + service_name: c.service_name, | |
| 890 | + start_date: c.start_date, | |
| 891 | + end_date: c.end_date, | |
| 892 | + monday: c.monday, | |
| 893 | + tuesday: c.tuesday, | |
| 894 | + wednesday: c.wednesday, | |
| 895 | + thursday: c.thursday, | |
| 896 | + friday: c.friday, | |
| 897 | + saturday: c.saturday, | |
| 898 | + sunday: c.sunday | |
| 899 | + }, | |
| 900 | + trip_headsign: t.trip_headsign, | |
| 901 | + trip_id: t.trip_id, | |
| 902 | + trip_short_name: t.trip_short_name | |
| 903 | + }, | |
| 904 | + tz: ^tz | |
| 905 | + } | |
| 906 | + ) | |
| 907 | + |> Repo.all | |
| 908 | + | |
| 909 | +# q = | |
| 910 | +# from st in StopTime, | |
| 911 | +# where: st.source_id == ^source_id and st.arrival_time >= ^timestamp_time and st.arrival_time <= ^timestamp_time_hour and st.stop_id == ^stringify(stop_id), | |
| 912 | +# order_by: [ | |
| 913 | +# asc: st.arrival_time | |
| 914 | +# ], | |
| 915 | +# limit: ^limit, | |
| 916 | +# left_join: s in Stop, | |
| 917 | +# on: s.stop_id == st.stop_id, | |
| 918 | +# left_join: t in Trip, | |
| 919 | +# on: t.trip_id == st.trip_id, | |
| 920 | +# left_join: r in Route, | |
| 921 | +# on: t.route_id == r.route_id, | |
| 922 | +# left_join: d in Direction, | |
| 923 | +# on: t.direction_id == d.direction_id and t.route_id == d.route_id, | |
| 924 | +# left_join: c in Calendar, | |
| 925 | +# on: t.service_id == c.service_id, | |
| 926 | +# select: %{ | |
| 927 | +# arrival_time: st.arrival_time, | |
| 928 | +# arrival_time_live_ts: nil, | |
| 929 | +# arrival_time_live_delay: nil, | |
| 930 | +# arrival_time_live_uncertianty: nil, | |
| 931 | +# departure_time: st.departure_time, | |
| 932 | +# stop_id: st.stop_id, | |
| 933 | +# stop_sequence: st.stop_sequence, | |
| 934 | +# stop: %{ | |
| 935 | +# stop_address: s.stop_address, | |
| 936 | +# stop_code: s.stop_code, | |
| 937 | +# stop_desc: s.stop_desc, | |
| 938 | +# stop_id: s.stop_id, | |
| 939 | +# stop_lat: s.stop_lat, | |
| 940 | +# stop_lon: s.stop_lon, | |
| 941 | +# stop_name: s.stop_name, | |
| 942 | +# stop_url: s.stop_url | |
| 943 | +# }, | |
| 944 | +# trip_id: st.trip_id, | |
| 945 | +# trip: %{ | |
| 946 | +# bikes_allowed: t.bikes_allowed, | |
| 947 | +# direction_id: t.direction_id, | |
| 948 | +# direction: %{ | |
| 949 | +# direction: d.direction, | |
| 950 | +# direction_id: d.direction_id | |
| 951 | +# }, | |
| 952 | +# route_id: t.route_id, | |
| 953 | +# route: %{ | |
| 954 | +# line_id: r.line_id, | |
| 955 | +# route_color: r.route_color, | |
| 956 | +# route_desc: r.route_desc, | |
| 957 | +# route_fare_class: r.route_fare_class, | |
| 958 | +# route_id: r.route_id, | |
| 959 | +# route_long_name: r.route_long_name, | |
| 960 | +# route_short_name: r.route_short_name, | |
| 961 | +# route_sort_order: r.route_sort_order, | |
| 962 | +# route_text_color: r.route_text_color, | |
| 963 | +# route_type: r.route_type, | |
| 964 | +# route_url: r.route_url | |
| 965 | +# }, | |
| 966 | +# service_id: t.service_id, | |
| 967 | +# service: %{ | |
| 968 | +# service_id: c.service_id, | |
| 969 | +# service_name: c.service_name, | |
| 970 | +# start_date: c.start_date, | |
| 971 | +# end_date: c.end_date, | |
| 972 | +# monday: c.monday, | |
| 973 | +# tuesday: c.tuesday, | |
| 974 | +# wednesday: c.wednesday, | |
| 975 | +# thursday: c.thursday, | |
| 976 | +# friday: c.friday, | |
| 977 | +# saturday: c.saturday, | |
| 978 | +# sunday: c.sunday | |
| 979 | +# }, | |
| 980 | +# trip_headsign: t.trip_headsign, | |
| 981 | +# trip_id: t.trip_id, | |
| 982 | +# trip_short_name: t.trip_short_name | |
| 983 | +# }, | |
| 984 | +# tz: ^tz | |
| 985 | +# } | |
| 986 | +# | |
| 987 | +# Repo.all(q) | |
| 902 | 988 | end |
| 903 | 989 | |
| 904 | 990 | alias RoomSanctum.Storage.GBFS.V1.SysInfo |
modified
apps/room_sanctum/lib/room_sanctum_web/live/cfg_source_live/form_component.html.heex
+29
−0
@@ -97,7 +97,36 @@
| 97 | 97 | </span> |
| 98 | 98 | </label> |
| 99 | 99 | </div> |
| 100 | + <div class="form-control"> | |
| 101 | + <label>Realtime URL Service Alerts</label> | |
| 102 | + <%= text_input gtfs_form, :url_rt_sa, class: "input w-full max-w-xs" %> | |
| 103 | + <label class="label"> | |
| 104 | + <span class="label-text-alt text-error"> | |
| 105 | + <%= error_tag gtfs_form, :url_rt_sa %> | |
| 106 | + </span> | |
| 107 | + </label> | |
| 108 | + </div> | |
| 109 | + <div class="form-control"> | |
| 110 | + <label>Realtime URL Trip Updates</label> | |
| 111 | + <%= text_input gtfs_form, :url_rt_tu, class: "input w-full max-w-xs" %> | |
| 112 | + <label class="label"> | |
| 113 | + <span class="label-text-alt text-error"> | |
| 114 | + <%= error_tag gtfs_form, :url_rt_tu %> | |
| 115 | + </span> | |
| 116 | + </label> | |
| 117 | + </div> | |
| 118 | + <div class="form-control"> | |
| 119 | + <label>Realtime URL Vehicle Positions</label> | |
| 120 | + <%= text_input gtfs_form, :url_rt_vp, class: "input w-full max-w-xs" %> | |
| 121 | + <label class="label"> | |
| 122 | + <span class="label-text-alt text-error"> | |
| 123 | + <%= error_tag gtfs_form, :url_rt_vp %> | |
| 124 | + </span> | |
| 125 | + </label> | |
| 126 | + </div> | |
| 127 | + | |
| 100 | 128 | <% end %> |
| 129 | + | |
| 101 | 130 | <% :gbfs -> %> |
| 102 | 131 | <%= polymorphic_embed_inputs_for f, :config, :gbfs, fn gbfs_form -> %> |
| 103 | 132 | <div class="form-control"> |
Parents: b5c06fa