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


# Slot

One requirement instance on one task: a position that one resource fills, plus the resources eligible for it. Create slots with `new Slot(id, task, allowed)` or get them from [`SkillLayer.slots`](<https://docs.dhtmlx.com/planning-engine/java/api/skill-layer-slots.md>), then pass the list to [`Project#suggestAssignments`](<https://docs.dhtmlx.com/planning-engine/java/api/project-suggest-assignments.md>). To build your own list from the project's tasks and resources, read [`Project#roster`](<https://docs.dhtmlx.com/planning-engine/java/api/project-roster.md>).

## Declaration

```java
package org.dhtmlx.plen;

public class Slot extends ValueRecord implements DeepCloneable<Slot>
```

## Constructors

### Slot(Id, Id, Vec<Id>)

```java
public Slot(Id id, Id task, Vec<Id> allowed)
public Slot(Id id, Id task, java.util.Collection<? extends Id> allowed)
```

Creates an empty slot with `value = 1.0` and `assignment = null`. The `Collection` overload copies `allowed` into a new `Vec`, so `List.of(...)` works. A `null` collection stays `null`.

**Parameters**

| Name | Type | Description |
|---|---|---|
| `id` | [`Id`](<https://docs.dhtmlx.com/planning-engine/java/api/data/id.md>) | Slot id. |
| `task` | [`Id`](<https://docs.dhtmlx.com/planning-engine/java/api/data/id.md>) | Task the slot belongs to. |
| `allowed` | [`Vec<Id>`](<https://docs.dhtmlx.com/planning-engine/java/api/support/vec.md>) or `Collection<? extends Id>` | Eligible resources. |

## Fields

| Field | Type | Default | Description |
|---|---|---|---|
| `id` | [`Id`](<https://docs.dhtmlx.com/planning-engine/java/api/data/id.md>) | set by the constructor | Unique within one call. Echoed in [`SuggestStep.slot`](<https://docs.dhtmlx.com/planning-engine/java/api/suggest/suggest-result.md#suggeststep>), `SuggestResult.unfilled` and `SuggestResult.invalid`. A new assignment that fills the slot takes this id. |
| `task` | [`Id`](<https://docs.dhtmlx.com/planning-engine/java/api/data/id.md>) | set by the constructor | A scheduled leaf task. |
| `allowed` | [`Vec<Id>`](<https://docs.dhtmlx.com/planning-engine/java/api/support/vec.md>) | set by the constructor | Resources eligible for the slot. List order is the tie-break preference: on equal scores, an earlier resource wins. |
| `value` | `double` | `1.0` | Units of the assignment created when the slot is filled. Finite and greater than `0`. |
| `assignment` | [`Id`](<https://docs.dhtmlx.com/planning-engine/java/api/data/id.md>) | `null` | The active assignment on `task` that fills the slot. `null` means the slot is empty. |

The slot's state follows from these fields: with `assignment` set, the slot is valid when that assignment's resource is in `allowed` and broken when it isn't. [`SuggestOptions.targets`](<https://docs.dhtmlx.com/planning-engine/java/api/suggest/suggest-options.md#targets>) picks which states a call works on.

The new assignment's id is the slot id, so after you commit a fill, pass `withAssignment(slotId)` on the next run to keep the slot bound. [`SkillLayer.slots`](<https://docs.dhtmlx.com/planning-engine/java/api/skill-layer-slots.md>) does this for you.

For the checks run on each field, see [`Project#suggestAssignments`](<https://docs.dhtmlx.com/planning-engine/java/api/project-suggest-assignments.md#errors>).

## Methods

### withId, withTask, withAllowed, withValue, withAssignment

```java
public Slot withId(Id value)
public Slot withTask(Id value)
public Slot withAllowed(Vec<Id> value)
public Slot withAllowed(java.util.Collection<? extends Id> value)
public Slot withValue(double value)
public Slot withAssignment(Id value)
```

Each setter assigns its field and returns this instance. The `Collection` overload of `withAllowed` copies the elements into a new `Vec`. A `null` collection sets the field to `null`.

**Returns**: this `Slot`.

### deepClone

```java
public Slot deepClone()
```

Returns a new slot with the same field values and its own copy of the `allowed` list.

**Returns**: a new `Slot`.

**Errors**: `NullPointerException` when `allowed` is `null`.

### copy

```java
public Slot copy()
```

Returns a shallow copy. The new slot shares the `allowed` list with the original.

**Returns**: a new `Slot`.

### equals, hashCode, toString

```java
public boolean equals(Object other)
public int hashCode()
public String toString()
```

Inherited from [`ValueRecord`](<https://docs.dhtmlx.com/planning-engine/java/api/support/value-record.md>). Two slots are equal when all five fields are equal. `toString()` prints every field, for logging.

## Example

Task `A` already has `dev1`. Task `B` needs a half-time person. Both slots accept `dev1` or `dev2`.

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

public class SlotExample {
  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("B")))
        .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());

    List<Id> devs = List.of(Id.str("dev1"), Id.str("dev2"));
    List<Slot> slots = List.of(
        // Filled slot: bound to the existing assignment on task A.
        new Slot(Id.str("sA"), Id.str("A"), devs).withAssignment(Id.str("aA")),
        // Empty slot: a half-time position on task B.
        new Slot(Id.str("sB"), Id.str("B"), devs).withValue(0.5));

    SuggestResult result = project.suggestAssignments(slots, new SuggestOptions());
    for (SuggestStep step : result.steps) {
      System.out.println(step.slot + " -> " + step.toResource); // sB -> dev2
    }
    System.out.println(result.changes.assignments.add);
    // [AssignmentData{id=sB, task=B, resource=dev2, value=0.5, offset=null, duration=null}]
  }
}
```

## Related

- [`Project#suggestAssignments`](<https://docs.dhtmlx.com/planning-engine/java/api/project-suggest-assignments.md>) - the call that fills the slots
- [`SkillLayer.slots`](<https://docs.dhtmlx.com/planning-engine/java/api/skill-layer-slots.md>) - builds slots from skills and requirements
- [`SuggestOptions`](<https://docs.dhtmlx.com/planning-engine/java/api/suggest/suggest-options.md>) - picks which slot states a call works on
- [`Roster`](<https://docs.dhtmlx.com/planning-engine/java/api/suggest/roster.md>) - the tasks and resources to build your own slots from
- [Suggesting assignments](<https://docs.dhtmlx.com/planning-engine/java/resources-and-assignment/suggesting-assignments.md#slots>) - how slots work in auto-assignment
