~ihabunek/triglav

f66c43139d76b7a26925de4e29498ff1473c0950 — Ivan Habunek 3 months ago d1b5915
Store sample trip ID in derived data, simplify schemas
M lib/mix/tasks/triglav/validate_routes.ex => lib/mix/tasks/triglav/validate_routes.ex +1 -1
@@ 48,7 48,7 @@ defmodule Mix.Tasks.Triglav.ValidateRoutes do
  end

  @spec validate_routes(Keyword.t()) :: :ok | :error
  def validate_routes(opts) do
  def validate_routes(opts \\ []) do
    dry_run = Keyword.get(opts, :dry_run, false)

    osm_state = Geofabrik.get_local_state()

M lib/triglav/derived/public_transport.ex => lib/triglav/derived/public_transport.ex +15 -3
@@ 9,6 9,7 @@ defmodule Triglav.Derived.PublicTransport do
  alias Triglav.Repo
  alias Triglav.Schemas.Osmosis.Relation
  alias Triglav.Schemas.PublicTransport.{Trip, Platform}
  alias Triglav.Schemas.Zet.{DistinctTrip, Route}
  alias Triglav.Zet.Gtfs
  alias Triglav.Zet.Osmosis



@@ 33,10 34,14 @@ defmodule Triglav.Derived.PublicTransport do
    relations_map = Map.new(relations, &{&1.id, &1})
    ways_map = Osmosis.list_ways(relations) |> Map.new(&{&1.id, &1})
    routes_map = Gtfs.list_routes() |> Map.new(&{&1.id, &1})
    distinct_trip_map = Gtfs.list_distinct_trips() |> Map.new(&{{&1.route_id, &1.stops}, &1})
    platform_members = relations |> Enum.map(& &1.id) |> Osmosis.list_platform_members()
    platform_member_map = Map.new(platform_members, &{{&1.relation_id, &1.sequence_id}, &1})

    trips = Enum.map(relations, &generate_trip(&1, ways_map, routes_map, platform_member_map))
    trips =
      Enum.map(relations, fn relation ->
        generate_trip(relation, ways_map, routes_map, platform_member_map, distinct_trip_map)
      end)

    stops_map =
      trips


@@ 74,17 79,24 @@ defmodule Triglav.Derived.PublicTransport do
    end)
  end

  defp generate_trip(relation, ways_map, routes_map, platform_member_map) do
  defp generate_trip(relation, ways_map, routes_map, platform_member_map, distinct_trip_map) do
    {geometry, exact} = trip_geometry(relation, ways_map)
    stop_ids = trip_stop_ids(relation, platform_member_map)
    route = Map.get(routes_map, Relation.ref(relation))

    sample_trip_id =
      with %Route{} <- route,
           %DistinctTrip{} = distinct_trip <- Map.get(distinct_trip_map, {route.id, stop_ids}) do
        distinct_trip.sample_trip_id
      end

    %Trip{
      relation: relation,
      route: route,
      geometry: geometry,
      exact: exact,
      stop_ids: stop_ids
      stop_ids: stop_ids,
      sample_trip_id: sample_trip_id
    }
  end


M lib/triglav/schemas/public_transport/platform.ex => lib/triglav/schemas/public_transport/platform.ex +10 -5
@@ 10,18 10,23 @@ defmodule Triglav.Schemas.PublicTransport.Platform do

  @type t :: %__MODULE__{}

  @primary_key false

  schema "public_transport_platforms" do
    belongs_to :relation, Osmosis.Relation, primary_key: true
    belongs_to :trip, Trip
    belongs_to :relation, Osmosis.Relation

    # These are optional, populated if relation is matched to route
    belongs_to :stop, Zet.Stop, type: :binary
    belongs_to :route, Zet.Route, type: :binary

    # Platform can be either a way or node
    belongs_to :node, Osmosis.Node
    belongs_to :way, Osmosis.Way
    field :sequence_id, :integer, primary_key: true

    field :sequence_id, :integer
    field :geometry, Geo.PostGIS.Geometry

    has_one :trip, Trip, foreign_key: :relation_id, references: :relation_id
    # TODO: maybe make this a real field, we'd need to import data first, to get
    # it indexed, and then populate this field
    field :distance_from_route, :float, virtual: true
  end
end

M lib/triglav/schemas/public_transport/trip.ex => lib/triglav/schemas/public_transport/trip.ex +4 -3
@@ 8,15 8,16 @@ defmodule Triglav.Schemas.PublicTransport.Trip do
  alias Triglav.Schemas.Osmosis
  alias Triglav.Schemas.Zet

  @type t :: %__MODULE__{}
  @derive {Inspect, only: [:id, :relation_id, :sample_trip_id]}

  @primary_key false
  @type t :: %__MODULE__{}

  schema "public_transport_trips" do
    belongs_to :relation, Osmosis.Relation, primary_key: true
    belongs_to :relation, Osmosis.Relation
    belongs_to :route, Zet.Route, type: :binary
    field :geometry, Geo.PostGIS.Geometry
    field :exact, :boolean
    field :stop_ids, {:array, :string}
    field :sample_trip_id, :string
  end
end

M lib/triglav/schemas/zet/distinct_trip.ex => lib/triglav/schemas/zet/distinct_trip.ex +1 -0
@@ 9,5 9,6 @@ defmodule Triglav.Schemas.Zet.DistinctTrip do
    field :direction_id, :integer
    field :stops, {:array, :string}
    field :trip_count, :integer
    field :sample_trip_id, :binary
  end
end

M priv/gtfs/transform.sql => priv/gtfs/transform.sql +6 -2
@@ 15,7 15,11 @@ WITH trips AS (
  JOIN zet.stops s ON s.stop_id = st.stop_id
  GROUP BY 1, 2, 3
)
SELECT route_id, direction_id, stops, count(*) AS trip_count
FROM trips
  SELECT route_id,
         direction_id,
         stops,
         count(*) AS trip_count,
         min(trip_id) AS sample_trip_id
    FROM trips
GROUP BY route_id, direction_id, stops
ORDER BY route_id::integer, direction_id, trip_count DESC;

M priv/repo/migrations/20210227082725_create_public_transport_tables.exs => priv/repo/migrations/20210227082725_create_public_transport_tables.exs +10 -5
@@ 2,25 2,30 @@ defmodule Triglav.Repo.Migrations.CreatePublicTransportTables do
  use Ecto.Migration

  def up do
    create table("public_transport_trips", primary_key: false) do
      add :relation_id, :bigint, null: false, primary_key: true
    create table("public_transport_trips") do
      add :relation_id, :bigint, null: false
      add :route_id, :string
      add :geometry, :geometry, null: false
      add :exact, :boolean, null: false
      add :stop_ids, {:array, :string}
      add :sample_trip_id, :string
    end

    create table("public_transport_platforms", primary_key: false) do
      add :relation_id, :bigint, null: false, primary_key: true
    create table("public_transport_platforms") do
      add :trip_id, references("public_transport_trips")
      add :relation_id, :bigint, null: false
      add :route_id, :string
      add :stop_id, :string
      add :node_id, :bigint
      add :way_id, :bigint
      add :sequence_id, :integer, null: false, primary_key: true
      add :sequence_id, :integer, null: false
      add :geometry, :geometry, null: false
    end

    create index("public_transport_trips", [:sample_trip_id], unique: true)
    create index("public_transport_trips", [:geometry], using: :gist)

    create index("public_transport_platforms", [:relation_id, :sequence_id], unique: true)
    create index("public_transport_platforms", [:geometry], using: :gist)
  end