Project.SuggestAssignments#
Proposes resources for the requirement slots of a Project. It fills empty slots, repairs broken ones and rebalances valid ones, and scores each step the way Evaluate does. The project isn't modified; the proposal comes back as a change set. Needs a solved project with no unsolved edits.
Signature#
public SuggestResult SuggestAssignments(IReadOnlyList<Slot> slots, SuggestOptions options)
Synchronous and CPU-only. Doesn't change the project's state.
Parameters#
| Name | Type | Description |
|---|---|---|
slots |
IReadOnlyList<Slot> |
The slots to fill or rebalance. To build them from skills and requirements, use SkillLayer.Slots. To build your own, read the current state with Roster. |
options |
SuggestOptions |
Expected baseline, targets, fixed assignments, penalty, passes, leveling stage and ClearFirst |
Behavior#
- Greedy: it visits slots one at a time, and later slots build on earlier picks.
- It never removes an assignment. It adds one per filled slot and changes the resource of a repaired or rebalanced one.
- With
options.ClearFirst, the proposal also carries the leveling clears it measured against. SeeSuggestOptions. - Commit the proposal with
Apply(result.Changes), thenSolve(null, …). Whenoptions.Levelwas set, callLevelwith the same leveling options instead.
Returns#
A SuggestResult with the proposed changes and a step log.
Errors#
| Error | When |
|---|---|
ProjectException NoBaseline |
The project is unsolved, including after Apply |
ProjectException StaleBaseline |
options.BaselineId doesn't name the current baseline |
InputException |
Invalid options (newResourcePenalty, passes, targets[i], fixed[i], Level); a cyclic accepted state (Path is null); an invalid slot (paths under slots[i]) |
ArgumentNullException |
slots or options is null |
It checks options before slots. The accepted values are on the SuggestOptions and Slot pages.
Example#
Fill an open position on task C, then commit the proposal.
using Plen;
var start = Moment.FromYmdHm(2026, 8, 10, 0, 0) ?? throw new InvalidOperationException("invalid date");
var data = new ProjectData
{
Tasks =
[
new TaskData("A") { StartDate = start, Duration = 2.0 },
new TaskData("C") { StartDate = start, Duration = 2.0 },
],
Resources = [new ResourceData { Id = "dev1" }, new ResourceData { Id = "dev2" }],
Assignments = [new AssignmentData { Id = "aA", Task = "A", Resource = "dev1", Value = 1.0 }],
};
data.Config.UseCalendars = false;
var project = new Project();
project.Solve(data, new SolveOptions());
// Task C needs one person: dev1 or dev2.
List<Slot> slots = [new Slot("sC", "C", ["dev1", "dev2"])];
var result = project.SuggestAssignments(slots, new SuggestOptions());
foreach (var step in result.Steps)
Console.WriteLine($"{step.Slot} -> {step.ToResource}"); // sC -> dev2
var report = project.Apply(result.Changes);
if (report.Rejected.Count == 0)
project.Solve(null, new SolveOptions());
Related#
Slot- the slots to fillSuggestOptions- the optionsSuggestResult- the returned proposal- Suggesting assignments - how picks are made and how to read the proposal
- Skills and requirements - slots from workers and requirements