Project.Roster#
Reads the accepted state of a Project without skills: scheduled leaf tasks, resources and active assignments, in model order. Use it to build a custom Slot list for SuggestAssignments. Needs a solved project with no unsolved edits.
Signature#
public Roster Roster()
Synchronous and CPU-only. Doesn't change the project's state.
Returns#
A new Roster on each call.
Errors#
| Error | When |
|---|---|
ProjectException NoBaseline |
The project is unsolved, or has unsolved edits after Apply |
Example#
Build one slot per scheduled task that has no assignment yet, open to every resource.
using Plen;
var monday = Moment.FromYmdHm(2026, 8, 10, 8, 0) ?? throw new InvalidOperationException("invalid date");
var data = new ProjectData
{
Tasks =
[
new TaskData("a") { StartDate = monday, Duration = 2.0 },
new TaskData("b") { StartDate = monday, Duration = 2.0 },
],
Resources = [new ResourceData { Id = "dev1" }, new ResourceData { Id = "dev2" }],
Assignments = [new AssignmentData { Id = "x", Task = "a", Resource = "dev1", Value = 1.0 }],
};
var project = new Project();
project.Solve(data, new SolveOptions());
var roster = project.Roster();
var slots = roster.Tasks
.Where(task => !roster.Assignments.Any(a => a.Task == task))
.Select(task => new Slot($"slot-{task}", task, [.. roster.Resources]))
.ToList();
var result = project.SuggestAssignments(slots, new SuggestOptions());
Console.WriteLine($"{slots.Count} slot(s), {result.Steps.Count} step(s)");
Related#
Roster- the returned snapshotSlot- slots built from the rosterProject.SuggestAssignments- the call that takes the slotsSkillLayer.Slots- builds slots from skills instead- Skills and requirements - slots from workers and requirements