LoadProfile#

Per-bucket load and capacity for each requested resource over a date range. Project#loadProfile returns one for the solved baseline. Project#preview puts one in ScheduleResult.profile when its options carry a profile query.

Declaration#

package org.dhtmlx.plen;

public class LoadProfile extends ValueRecord implements DeepCloneable<LoadProfile> {
  public Basis basis = Basis.HOUR;
  public Vec<ResourceLoad> resources = new Vec<ResourceLoad>();

  public LoadProfile deepClone();
  public LoadProfile copy();
}

Each field has a fluent withX(value) setter, and resources also has a withResources(java.util.Collection<? extends ResourceLoad>) overload. ValueRecord gives the class structural equals / hashCode over all fields and a readable toString().

Fields#

Field Type Description
basis Basis Bucket size the profile was built with: the query's basis, or the one derived from the project's duration unit when the query leaves it null.
resources Vec<ResourceLoad> One entry per requested resource, in input order. All resources when ProfileQuery.resources is null.

Methods#

deepClone#

public LoadProfile deepClone()

Returns a copy with a new resources list and new ResourceLoad and LoadBucket objects.

copy#

public LoadProfile copy()

Returns a shallow copy: resources is shared with the original.

ResourceLoad#

The load of one resource over the profile's range.

public class ResourceLoad extends ValueRecord implements DeepCloneable<ResourceLoad> {
  public Id resource = null;
  public CapacityMode capacityMode = CapacityMode.CALENDAR;
  public Vec<LoadBucket> buckets = new Vec<LoadBucket>();

  public ResourceLoad deepClone();
  public ResourceLoad copy();
}
Field Type Description
resource Id Resource id.
capacityMode CapacityMode How capacity is spread over the buckets.
buckets Vec<LoadBucket> Every bucket whose start lies in [from, to) of the query, in time order, including buckets with no load.

CapacityMode#

How a resource's capacity is placed in the buckets of a ResourceLoad.

public enum CapacityMode {
  CALENDAR,
  FLAT
}
Value Description
CALENDAR The resource has a calendar in CalendarMode.RESOURCE and the project has useCalendars on. Buckets with working time of that calendar get the resource's capacity, all others get 0.
FLAT Every bucket gets the resource's capacity: the resource has no calendar, the calendar mode is task-based, or useCalendars is off.

LoadBucket#

Load and capacity of one resource in one bucket.

public class LoadBucket extends ValueRecord implements DeepCloneable<LoadBucket> {
  public Moment start = new Moment(0);
  public double load = 0.0;
  public double capacity = 0.0;
  public Vec<Id> tasks = null;

  public LoadBucket deepClone();
  public LoadBucket copy();
}
Field Type Description
start Moment Start of the bucket. The bucket is one basis long.
load double Booked load, in assignment value units (1.0 = 100 %).
capacity double Capacity in the same units. The bucket is overallocated when load > capacity.
tasks Vec<Id> Ids of the tasks booked in the bucket, in input order. Set by ProfileQuery.tasks: null with ProfileTasks.NONE; with OVER, the ids in overallocated buckets and an empty list elsewhere; with ALL, the ids in every bucket (empty where nothing is booked).

For how load is booked into buckets, see Resource load.

Example#

Read a daily profile with task lists for one resource that works on two tasks at once.

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

public class LoadProfileExample {
  public static void main(String[] args) throws Exception {
    ProjectData data = new ProjectData()
        .withTasks(List.of(
            new TaskData(Id.str("a")).withStartDate(Moment.fromYmdHm(2026, 1, 1, 0, 0)).withDuration(2.0),
            new TaskData(Id.str("b")).withStartDate(Moment.fromYmdHm(2026, 1, 2, 0, 0)).withDuration(2.0)))
        .withResources(List.of(new ResourceData().withId(Id.str("dev"))))
        .withAssignments(List.of(
            new AssignmentData().withTask(Id.str("a")).withResource(Id.str("dev")).withValue(1.0),
            new AssignmentData().withTask(Id.str("b")).withResource(Id.str("dev")).withValue(1.0)));
    data.config.useCalendars = false;

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

    ProfileQuery query = new ProfileQuery(Moment.fromYmdHm(2026, 1, 1, 0, 0), Moment.fromYmdHm(2026, 1, 5, 0, 0))
        .withBasis(Basis.DAY)
        .withTasks(ProfileTasks.ALL);
    LoadProfile profile = project.loadProfile(new LoadProfileOptions(query));

    System.out.println(profile.basis);                                    // DAY
    for (ResourceLoad resource : profile.resources) {
      System.out.println(resource.resource + " " + resource.capacityMode); // dev FLAT
      for (LoadBucket bucket : resource.buckets) {
        System.out.println(bucket.start + " " + bucket.load + "/" + bucket.capacity + " " + bucket.tasks);
      }
    }
    // 2026-01-01 00:00 1.0/1.0 [a]
    // 2026-01-02 00:00 2.0/1.0 [a, b]
    // 2026-01-03 00:00 1.0/1.0 [b]
    // 2026-01-04 00:00 0.0/1.0 []
  }
}