One session must finish before another starts.
Every other constraint in this library asks whether two things can coexist. This one asks about order, and it is what separates a bag of tasks from a task graph: preparation before delivery, the survey before the quote, the first interview before the second.
The gap is part of the constraint
A precedence with no gap means the successor may begin the instant
its predecessor ends. :gap widens that — thirty minutes to write
up the survey — and :within caps it, which is what makes an
interview loop a loop rather than two appointments a fortnight
apart:
Programme.precede(programme, "Screening", "Panel", gap: "PT15M", within: "PT2H")"The panel follows screening, no sooner than fifteen minutes after and no later than two hours."
:within is measured from the end of the predecessor, not its
start, so it does not shorten as the predecessor runs long.
Why it is a pairwise constraint
Precedence relates exactly two sessions, which is why it lives alongside the track and resource checks rather than needing new machinery. A chain of three is two precedences, and the search enforces them independently — it never has to reason about the chain as a whole.
That is also why Agenda.Arranger.conflict?/4 covers it, and so
the fixpoint bridge gets precedence for free: both solvers ask the
same question about the same pair.
Summary
Functions
The precedence relating two sessions, whichever way round they are
given, or nil when they are unordered.
Build a precedence.
Types
@type t() :: %Agenda.Precedence{ first: String.t(), gap: Agenda.Availability.pattern() | nil, then: String.t(), within: Agenda.Availability.pattern() | nil }
An ordering between two sessions.
Functions
The precedence relating two sessions, whichever way round they are
given, or nil when they are unordered.
Arguments
precedencesis a list oft/0.aandbare session names.
Returns
{precedence, :in_order}whenaprecedesb,{precedence, :reversed}whenbprecedesa, ornil.
Examples
iex> precedences = [Agenda.Precedence.new("Survey", "Quote")]
iex> {_precedence, order} = Agenda.Precedence.between(precedences, "Quote", "Survey")
iex> order
:reversed
iex> Agenda.Precedence.between([], "A", "B")
nil
Build a precedence.
Arguments
firstis the name of the session that must finish first.thenis the name of the session that follows it.
Options
:gapis the least time that must pass between them, a duration. The default is none, meaning the successor may start immediately.:withinis the most time that may pass, measured from the end offirst. The default is none, meaning no upper bound.
Returns
- a
t/0.
Examples
iex> precedence = Agenda.Precedence.new("Survey", "Quote", gap: "PT30M")
iex> {precedence.first, precedence.then}
{"Survey", "Quote"}