ResourceOverallocation#

The periods in which one resource is booked above its capacity. Read it from ScheduleResult.overallocations, which holds one entry per resource with at least one overallocated window. In a result from Project#level, each window also says why leveling left it in place.

Declaration#

package org.dhtmlx.plen;

public class ResourceOverallocation extends ValueRecord
    implements DeepCloneable<ResourceOverallocation>

The entry belongs to a result that's read-only by contract. Call deepClone() before changing it.

Fields#

Each field has a fluent setter of the same name, withX(value), that returns this entry. withWindows also takes any Collection<? extends OverallocationWindow>, such as List.of(...).

Field Type Default Description
resource Id null The overallocated resource. Always set in a reported entry.
windows Vec<OverallocationWindow> empty Its overallocated windows. Never empty in a reported entry.

Methods#

deepClone#

public ResourceOverallocation deepClone()

Returns a copy with its own windows list and cloned OverallocationWindow entries.

Returns - a new ResourceOverallocation equal to this one.

copy#

public ResourceOverallocation copy()

Returns a shallow copy. The copy shares the windows list with this entry.

Returns - a new ResourceOverallocation with the same field values.

equals, hashCode, toString#

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

Inherited from ValueRecord. equals and hashCode compare resource and windows, the windows element by element. toString() lists the fields, e.g. ResourceOverallocation{resource=dev1, windows=[…]}.

OverallocationWindow#

A maximal run of consecutive buckets in which the resource's load exceeds its capacity. The bucket size is the result's basis: derived from SchedulingConfig.durationUnit, or LevelingOptions.basis in a result from level.

package org.dhtmlx.plen;

public class OverallocationWindow extends ValueRecord
    implements DeepCloneable<OverallocationWindow>
Field Type Default Description
from Moment new Moment(0) Window start: the earliest working moment of the contending tasks in the first bucket.
to Moment new Moment(0) Window end: the latest working moment of the contending tasks in the last bucket. Both edges are clipped to the booked assignment slices, not to the whole task.
capacity double 0.0 The resource's capacity, in assignment value units (1.0 = 100 %). See ResourceData.capacity.
peak double 0.0 The highest bucket load in the window.
overload double 0.0 Σ (load − capacity) over the window's buckets, in capacity × buckets. Per resource, the windows' overload adds up to the overload metric at the same basis.
tasks Vec<Id> empty The contending tasks, in input order.
reason String null Why leveling left the window. Set only in results from level, null otherwise. One of pinned-constraint, fixed-task, completed, priority-1000, slack-exhausted, out-of-scope. When several apply, the first in this list wins.

Each field has a withX(value) setter that returns this window. withTasks also takes any Collection<? extends Id>.

deepClone() returns a copy with its own tasks list. copy() returns a shallow copy that shares the tasks list. equals, hashCode and toString are inherited from ValueRecord and compare or list all seven fields, with tasks compared element by element.

The reasons are explained in Leveling resources.

Example#

Two fixed tasks overlap on dev1 on Tuesday. level can't move either of them, so the window stays and carries a reason.

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

public class OverallocationExample {
  public static void main(String[] args) throws Exception {
    Id dev1 = Id.str("dev1");

    ProjectData data = new ProjectData()
        .withTasks(List.of(
            new TaskData(Id.str("A"))
                .withStartDate(Moment.fromYmdHm(2026, 8, 10, 8, 0))
                .withDuration(2.0)
                .withAutoScheduling(false),
            new TaskData(Id.str("B"))
                .withStartDate(Moment.fromYmdHm(2026, 8, 11, 8, 0))
                .withDuration(2.0)
                .withAutoScheduling(false)))
        .withResources(List.of(new ResourceData().withId(dev1)))
        .withAssignments(List.of(
            new AssignmentData().withTask(Id.str("A")).withResource(dev1).withValue(1.0),
            new AssignmentData().withTask(Id.str("B")).withResource(dev1).withValue(1.0)));

    Project project = new Project();
    project.solve(data, new SolveOptions());
    LevelingResult leveled = project.level(new LevelingOptions());

    for (ResourceOverallocation over : leveled.schedule.overallocations) {
      for (OverallocationWindow window : over.windows) {
        // dev1: 2026-08-11 08:00 .. 2026-08-11 17:00, peak 2.0 of 1.0, overload 1.0, tasks [A, B], reason fixed-task
        System.out.println(over.resource + ": " + window.from + " .. " + window.to
            + ", peak " + window.peak + " of " + window.capacity
            + ", overload " + window.overload
            + ", tasks " + window.tasks
            + ", reason " + window.reason);
      }
    }
  }
}

The same window in the result of solve has reason set to null.