Skip to content

Trip replay

Rails
Status ✅
Code app/controllers/trip_replays_controller.rb, app/controllers/public_trips_controller.rb (replay, replay_points), app/services/trip_replay.rb, app/views/trip_replays/show.html.erb, app/views/tracks/_instruments.html.erb, app/helpers/sharing_helper.rb (replay_days), app/javascript/controllers/trip_replay_controller.js, app/javascript/track_view/ (squeezed_time.js and the modules shared with the track editor), config/locales/sharing.{en,de}.yml (sharing.replay.*)

Verified against code: 2026-10-27

Purpose

Sail the trip again: the whole trip on the map with the boat, the instruments where the boat is, and the speed over the whole trip underneath. For everyone who can see the trip: owner, skipper, crew, and anyone with a working public link. Nothing can be edited; owner and skipper get a link to the track editor for the track under the boat. Decision and data rules: ADR 016.

Opening

The map on the trip page and on the public page has one 66 px icon button in its top-right corner: Open the map (trip.md § Map). It opens the replay in its map view as its own page that fills the browser window, like the track editor (layout editor; no browser fullscreen mode). The day links of the Days table open it straight into the replay (?day=N&play=1):

Who Page Data
Owner, skipper, crew (roles, permission view) /my/trips/:id/replay /my/trips/:id/replay/points.json
Anyone with a working public link /t/<token>/replay /t/<token>/replay/points.json

Anyone else: 404. An ended public link: the expired page (410), as the public page. The public replay has no ids in its HTML, URLs or JSON, sends noindex, nofollow and shares the public page's rate limit (120 a minute per IP).

Layout

Part Content
Top bar Close (→ the trip page or the public page) · the trip's title · the boat's day: "Day 2 · Tue 6.10. · Hvar → Vis" (the route as in the Days table: "(at sea)" for a night at sea, "…" for a missing name) · ‹ "Previous day" / › "Next day" (disabled on the first / last day) · Edit track (primary, edit icon) to the editor of the track under the boat, only for owner and skipper
Map SailEver's map with depth and seamarks (maps.md), fitted to the whole trip on open, with Leaflet's + / − in its top-left corner, scroll and pinch zoom. Each track in the state colours (--sail, --engine, --motorsail; anchored or moored points muted), tracks not joined to each other. The boat's day: its start as a white circle, its end as a white square. The boat as in the editor (24 px arrow turned to its course, in its state's colour, white outline). The scale bottom left. The wind arrows of the track editor for the boat's moment, from the wind stored with the track the boat is on. A click on the track puts the boat at the nearest point.
Right The editor's instrument boxes (track-editor.md § Plotter boxes), without Kept: Date, Time, SOG, Log (NM from the start of the trip), COG, Wind (TWD, TWA, TWS, barb), Baro (only when the trip has pressure). Labels stay English, as on a chart plotter.
Tools For the histogram, as in the editor: "Zoom out of the time", "Zoom in on the time" (around the boat), "Whole trip"
Bottom The speed histogram of the editor (track-editor.md § Timeline): state band, SOG bars, speed grid, time axis, the boat as a line with a dot; no handles. Under it the editor's overview bar: the whole trip in state colours (squeezed gaps left empty), the histogram's window as a frame, the boat as a line. At the very bottom the editor's wind row, on the histogram's time scale.

Phone (899 px and narrower): as the editor's phone layout (65 px instrument column without Date); the day goes under the title.

Map view

The page opens in map view: only the top bar and the map, the map filling the rest of the window. Right, Tools and Bottom take no room. Everything on the map and in the top bar works as in the replay (boat, day start and end, wind arrows for the boat's moment, a click on the track puts the boat there, ‹ ›, Edit track).

Part Content
Play Top-right corner of the map: an orange 66 px icon button, the same as the trip page's (button_classes(:primary, size: :lg, icon_only: true), 30 px play icon, aria-label "Replay the trip" / "Törn abspielen"). Only in map view.
End the replay Right end of the Tools row, above the histogram: an orange 44 px icon button (button_classes(:primary, icon_only: true), close icon, aria-label "End the replay" / "Wiedergabe beenden"). Only in the replay.
  • Play slides the instrument column in from the right and the Tools row, histogram, overview bar and wind row in from the bottom (0.25 s; none with prefers-reduced-motion). They push the map smaller, they don't cover it; the map keeps its centre. The focus goes to the histogram. The boat does not move by itself.
  • End the replay (or Esc, unless a dialog is open) slides them out again; the focus goes to Play. Boat, day and the map's view stay as they are.
  • The URL carries the view: ?play=1 in the replay, none in map view (changed in place, no new history entry), so a reload opens the same view. With ?play=1 the page is rendered as the replay from the start.
  • In map view the hidden panels are inert (no focus, not read out); ← / → / Home / End work only in the replay, on the histogram.

Behaviour

  • Start: the whole trip on the map, the boat at the start of day 1, the top bar on day 1. With ?day=N (the day links of the Days table) it starts on day N instead: the map fitted to that day, the boat at its first point.
  • The boat: a click or drag on the histogram, a click on the track, ← / → (1 minute; with Shift 10), Home / End put the boat at the nearest point. Map, instruments, top bar and Edit track follow. With the keys the histogram scrolls along when the boat leaves it.
  • The day in the top bar is always the day the boat is on (the last day that started before the boat's moment). ‹ › put the boat at the first point of the day before / after and fit the map to that day.
  • Zooming the histogram (toolbar, + / − keys, scroll wheel; sideways scroll pans) and clicking or dragging the overview bar change only the histogram's window, never the map or the boat. At least 10 minutes are shown.
  • The histogram follows the map. Whenever the map stops moving (zoom, drag, Whole trip, a day), the histogram shows the time of the track on screen:
  • all of the trip on screen: the whole trip;
  • otherwise the continuous stretch of track on screen around the boat, or, with the boat off screen, around the point nearest the map's centre;
  • no track on screen: the whole trip.

A route that passes the same bay twice so shows only the pass the boat is on, not days in between. At least 10 minutes are shown. - Gaps: time without points longer than an hour (nights in harbour, a watch not recording) is squeezed to 20 minutes on the histogram, drawn as a dashed line with the date the next stretch starts on ("Sun, Sep 13"); tick labels near it are left out. Bars and wind barbs aren't drawn in a gap. - A trip still receiving tracks doesn't update itself; reloading shows the new points.

Data endpoint

GET …/replay/points.json (TripReplay):

{"points": [[epoch ms, lat, lon, sog kn, engine 0/1, state, cog, baro hPa, track index]], "tracks": [{"start", "end", "wind", "edit_url"}]}

  • Only the kept part of each track (its trim), all tracks of the trip in time order. The state is sail, engine or motorsail, anything else other.
  • At most 50 000 points per trip (one map's budget, the same as the track editor): when there are more, every n-th point of the tracks' files (ADR 017), cut to the kept parts on the server, so the browser never gets a trimmed-off part.
  • wind: the model wind stored with the track (track-editor.md § Wind endpoint), as it is. The replay never asks Open-Meteo: a track without stored wind shows "–". Crew and public viewers never cause an outside call.
  • edit_url: the track's editor, only for owner and skipper.
  • ETag over the trip, its tracks and their wind (signed in: per role; private). Public: public, max-age=300.
  • The days come with the page (data-trip-replay-days-value): label, route, start and end (epoch ms) and map bounds of each day.

States and edge cases

  • Loading fails: "The trip couldn't be loaded. Try again." on the map.
  • A trip with fewer than two points: an empty map and histogram.
  • The track under the boat decides the wind and Edit track; between tracks (in a gap) it is the nearest point's track.