$performances scoped to one * (stage_id, event_id) * group * @return array perf-id → resolved lane */ public function resolve(iterable $performances): array { $list = Collection::make($performances) ->sortBy([ fn (Performance $p): string => (string) $p->start_at, fn (Performance $p): int => (int) $p->lane, ]) ->values(); /** @var array $laneEnds */ $laneEnds = []; $resolved = []; foreach ($list as $perf) { $start = CarbonImmutable::instance($perf->start_at); $end = CarbonImmutable::instance($perf->end_at); $assigned = null; foreach ($laneEnds as $idx => $occupiedUntil) { if ($start >= $occupiedUntil) { $assigned = $idx; $laneEnds[$idx] = $end; break; } } if ($assigned === null) { $assigned = count($laneEnds); $laneEnds[$assigned] = $end; } $resolved[(string) $perf->id] = $assigned; } return $resolved; } }