[Canonical page](<https://docs.dhtmlx.com/planning-engine/java/api/project-suggest-assignments/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# Project#suggestAssignments

Proposes resources for requirement slots of a [`Project`](<https://docs.dhtmlx.com/planning-engine/java/api/project/project.md>). It fills empty slots, repairs broken ones and rebalances valid ones, and scores each step like [`evaluate`](<https://docs.dhtmlx.com/planning-engine/java/api/project-evaluate.md>). The project isn't modified: the proposal comes back as a change set. Needs a solved project.

## Signature

```java
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`](<https://docs.dhtmlx.com/planning-engine/java/api/suggest/slot.md>)`>` | The slots to fill or rebalance. To build them from skills and requirements, use [`SkillLayer.slots`](<https://docs.dhtmlx.com/planning-engine/java/api/skill-layer-slots.md>). To build your own, read the accepted state with [`roster`](<https://docs.dhtmlx.com/planning-engine/java/api/project-roster.md>). Not `null` |
| `options` | [`SuggestOptions`](<https://docs.dhtmlx.com/planning-engine/java/api/suggest/suggest-options.md>) | 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`](<https://docs.dhtmlx.com/planning-engine/java/api/project-level.md>).

## Returns

A [`SuggestResult`](<https://docs.dhtmlx.com/planning-engine/java/api/suggest/suggest-result.md>) with the proposed changes and a step log.

## Errors

All engine exceptions are unchecked.

| Error | When |
|---|---|
| [`ProjectException`](<https://docs.dhtmlx.com/planning-engine/java/api/errors/project-exception.md>) `NO_BASELINE` | The project is unsolved, including after `apply` |
| `ProjectException` `STALE_BASELINE` | `options.baselineId` doesn't name the current baseline |
| [`InputException`](<https://docs.dhtmlx.com/planning-engine/java/api/errors/input-exception.md>) | 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`](<https://docs.dhtmlx.com/planning-engine/java/api/suggest/suggest-options.md>) and [`Slot`](<https://docs.dhtmlx.com/planning-engine/java/api/suggest/slot.md>) pages.

## Collection overload

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

Copies `slots` into a [`Vec`](<https://docs.dhtmlx.com/planning-engine/java/api/support/vec.md>) 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.

```java
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());
    }
  }
}
```

## Related

- [`Slot`](<https://docs.dhtmlx.com/planning-engine/java/api/suggest/slot.md>) - a requirement slot to fill
- [`SuggestOptions`](<https://docs.dhtmlx.com/planning-engine/java/api/suggest/suggest-options.md>) - targets, fixed assignments and passes
- [`SuggestResult`](<https://docs.dhtmlx.com/planning-engine/java/api/suggest/suggest-result.md>) - the proposed change set and step log
- [`SkillLayer.slots`](<https://docs.dhtmlx.com/planning-engine/java/api/skill-layer-slots.md>) - builds slots from skills and requirements
- [Suggesting assignments](<https://docs.dhtmlx.com/planning-engine/java/resources-and-assignment/suggesting-assignments.md>) - how picks are made and committing the proposal
