# `PhxDemo.Plan`
[🔗](https://github.com/thenatespack/phoenix_demo/blob/main/lib/phx_demo/plan.ex#L1)

Maps a demo timeline onto its raw video, then decides what to keep.

Timeline times start at the sync flash. `sync_ms` is where that flash
appears in the raw video (found by `PhxDemo.Render`), so an event's
position in the raw video is `sync_ms + at_ms`.

Trimming keeps from the intro card (or shortly before the first real step)
to shortly after the last event (or the end of the outro). The sync flash
is always cut: `clear_ms`, when given, is the raw video's first frame after
the flash, and the output never starts before it (the next step can be
recorded a frame or two before the browser paints it). Events are returned
re-based to the trimmed output.

# `t`

```elixir
@type t() :: %PhxDemo.Plan{
  duration_ms: term(),
  events: term(),
  timeline: term(),
  trim_end: term(),
  trim_start: term()
}
```

# `build`

Builds the plan.

    iex> timeline = %{"settings" => %{"trim" => true}, "events" => [
    ...>   %{"type" => "sync_end", "at_ms" => 200},
    ...>   %{"type" => "scene", "at_ms" => 210, "title" => "A"},
    ...>   %{"type" => "say", "at_ms" => 1000, "duration_ms" => 1000, "text" => "Hi"}]}
    iex> plan = PhxDemo.Plan.build(timeline, sync_ms: 100, video_ms: 10_000)
    iex> {plan.trim_start, plan.trim_end, plan.duration_ms}
    {700, 2700, 2000}
    iex> Enum.map(plan.events, &{&1["type"], &1["at_ms"]})
    [{"scene", 0}, {"say", 400}]

---

*Consult [api-reference.md](api-reference.md) for complete listing*
