Agenda.Track (Agenda v0.3.0)

Copy Markdown View Source

A family of sessions constrained against each other.

Every other constraint in this library relates a session to a resource. A track is the first that does not: it says these sessions share an audience, so no two of them may run at once, and — if asked — a delegate must be able to walk between consecutive ones in the gap between them.

Not overlapping is intrinsic, not an option. A set of sessions that may collide with each other is just a list; what makes a track a track is that it cannot clash with itself. reachable/2 is the optional extra.

The word is deliberately not "stream": Elixir's Stream owns that name and a conference stream would shadow it at every call site.

Example

iex> import Tempo.Sigils
iex> keynote = Agenda.session("Keynote", duration: ~o"PT1H")
iex> deep_dive = Agenda.session("OTP internals", duration: ~o"PT1H")
iex> {:ok, track} =
...>   Agenda.track("Elixir", of: [keynote, deep_dive])
...>   |> Agenda.Track.reachable(within: ~o"PT10M")
iex> {length(track.sessions), track.reachable_within}
{2, ~o"PT10M"}

"No two talks in the Elixir track may overlap, and a delegate must be able to walk between consecutive ones inside the ten-minute break."

In iCalendar

iCalendar can say which sessions make up a track, but not what makes them one. An export writes two RFC 9253 properties on each of the track's sessions:

  • REFID — the track's name, as text: the key that groups associated components, as an itinerary groups its legs.

  • CONCEPT — a URI for the track as a classification, such as https://example.com/tracks/elixir, which the adapter mints from the track's name.

Both name the grouping, which is why the word stays Track. The rule is lost: iCalendar has no way to say that a track's sessions must not overlap each other, nor that a delegate must be able to walk between them (reachable/2). A track read back from iCalendar is a group of sessions that may clash.

Summary

Types

t()

Sessions that cannot clash with each other.

Functions

Add a session to the track.

Build a track.

Require that a delegate can get between consecutive sessions.

The names of the sessions in track.

Types

t()

@type t() :: %Agenda.Track{
  name: String.t(),
  reachable_within: Agenda.Availability.pattern() | nil,
  sessions: [Agenda.Session.t()]
}

Sessions that cannot clash with each other.

Functions

add(track, session)

@spec add(t(), Agenda.Session.t()) :: t()

Add a session to the track.

Arguments

Returns

  • the track, with the session added.

Examples

iex> session = Agenda.session("Keynote")
iex> track = Agenda.Track.add(Agenda.Track.new("Elixir"), session)
iex> Enum.map(track.sessions, & &1.name)
["Keynote"]

new(name, options \\ [])

@spec new(String.t(), keyword()) :: t()

Build a track.

Arguments

  • name is the track's name.

  • options is a keyword list of options.

Options

Returns

Examples

iex> Agenda.Track.new("Elixir").name
"Elixir"

reachable(track, options)

@spec reachable(t(), keyword()) :: {:ok, t()} | {:error, {:missing_option, :within}}

Require that a delegate can get between consecutive sessions.

Two sessions running back to back in rooms twenty minutes apart, with a ten-minute break, cannot both be attended. This is what makes the place tree earn its keep — the journey is derived from where the rooms are, not configured per pair.

Arguments

  • track is a t/0.

  • options is a keyword list of options.

Options

  • :within is the longest journey a delegate is expected to make, a duration.

Returns

  • {:ok, track} with the reachability requirement set, or

  • {:error, {:missing_option, :within}}.

Examples

iex> import Tempo.Sigils
iex> track = Agenda.Track.new("Elixir")
iex> {:ok, track} = Agenda.Track.reachable(track, within: ~o"PT10M")
iex> track.reachable_within
~o"PT10M"

iex> Agenda.Track.reachable(Agenda.Track.new("Elixir"), [])
{:error, {:missing_option, :within}}

session_names(track)

@spec session_names(t()) :: [String.t()]

The names of the sessions in track.

Arguments

  • track is a t/0.

Returns

  • the session names, in track order.

Examples

iex> track = Agenda.track("Elixir", of: [Agenda.session("Keynote")])
iex> Agenda.Track.session_names(track)
["Keynote"]