Project#suggestAssignments#

Proposes resources for requirement slots of a Project. It fills empty slots, repairs broken ones and rebalances valid ones, and scores each step like evaluate. The project isn't modified: the proposal comes back as a change set. Needs a solved project.

Signature#

public SuggestResult suggestAssignments(Vec<Slot> slots, SuggestOptions options)

Synchronous and CPU-only. Not synchronized: serialize calls on one Project instance.

Parameters#

Name Type Description
slots Vec<Slot> The slots to fill or rebalance. To build them from skills and requirements, use SkillLayer.slots. To build your own, read the accepted state with roster. Not null
options SuggestOptions Targets, fixed assignments, new-resource penalty, passes and leveling stage. Not null; new SuggestOptions() for defaults

Behavior#

  • Greedy: it visits slots one at a time. 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.
  • Commit the proposal with apply(result.changes), then solve(null, ...), or level with the same leveling options when options.level was set.
  • With options.level set, the call doesn't return when an assignment asks for more units than its resource can ever supply, the same bug as level.

Returns#

A SuggestResult with the proposed changes and a step log.

Errors#

All engine exceptions are unchecked.

Error When
ProjectException NO_BASELINE The project is unsolved, including after apply
ProjectException STALE_BASELINE options.baselineId doesn't name the current baseline
InputException Invalid options (paths newResourcePenalty, passes, targets[i], fixed[i], or invalid level options); a cyclic accepted state (path is null); an invalid slot (paths under slots[i])
NullPointerException slots or options is null

Options are checked before slots. The accepted values are on the SuggestOptions and Slot pages.

Collection overload#

public SuggestResult suggestAssignments(java.util.Collection<Slot> slots, SuggestOptions options)

Copies slots into a Vec and calls the main form, so List.of(...) works. Same behavior and errors.

Example#

Fill an open position on task C, then commit the proposal.

import java.util.List;
import org.dhtmlx.plen.*;

public class SuggestFill {
  static TaskData task(String id) {
    return new TaskData(Id.str(id))
        .withStartDate(Moment.fromYmdHm(2026, 8, 10, 0, 0))
        .withDuration(2.0);
  }

  public static void main(String[] args) throws Exception {
    ProjectData data = new ProjectData()
        .withTasks(List.of(task("A"), task("C")))
        .withResources(List.of(
            new ResourceData().withId(Id.str("dev1")),
            new ResourceData().withId(Id.str("dev2"))))
        .withAssignments(List.of(new AssignmentData()
            .withId(Id.str("aA"))
            .withTask(Id.str("A"))
            .withResource(Id.str("dev1"))
            .withValue(1.0)));
    data.config.useCalendars = false;

    Project project = new Project();
    project.solve(data, new SolveOptions());

    // Task C needs one person: dev1 or dev2.
    List<Slot> slots = List.of(
        new Slot(Id.str("sC"), Id.str("C"), List.of(Id.str("dev1"), Id.str("dev2"))));
    SuggestResult result = project.suggestAssignments(slots, new SuggestOptions());
    for (SuggestStep step : result.steps) {
      System.out.println(step.slot + " -> " + step.toResource); // sC -> dev2
    }

    ApplyReport report = project.apply(result.changes);
    if (report.rejected.isEmpty()) {
      project.solve(null, new SolveOptions());
    }
  }
}