LoadProfile#
Per-bucket load and capacity of a set of resources over a date range. Project.LoadProfile returns one for the solved baseline. ScheduleResult.Profile holds one after Project.Preview with PreviewOptions.Profile set. The ProfileQuery of the call decides the range, the resources, the bucket size and which buckets list their tasks.
Declaration#
namespace Plen;
public sealed class LoadProfile : IDeepCloneable<LoadProfile>, IEquatable<LoadProfile>
{
public Basis Basis { get; set; }
public List<ResourceLoad> Resources { get; set; } = [];
public LoadProfile DeepClone();
public bool Equals(LoadProfile? other);
}
Treat a returned profile as read-only. Call DeepClone() before changing one.
Properties#
| Property | Type | Description |
|---|---|---|
Basis |
Basis |
Bucket size of every bucket in the profile: Hour or Day. It's ProfileQuery.Basis when the query set it, otherwise the basis derived from SchedulingConfig.DurationUnit. |
Resources |
List<ResourceLoad> |
One entry per requested resource, in input order. All resources of the project when ProfileQuery.Resources is null. |
Methods#
DeepClone#
public LoadProfile DeepClone()
Returns a copy that shares no list or nested object with this one.
Equals#
public bool Equals(LoadProfile? other)
public override bool Equals(object? obj)
Value equality: Basis is equal and Resources is equal element by element. GetHashCode is consistent with it.
ToString#
public override string ToString()
Returns a readable dump of all properties, for logging.
ResourceLoad#
The buckets of one resource.
public sealed class ResourceLoad : IDeepCloneable<ResourceLoad>, IEquatable<ResourceLoad>
{
public required Id Resource { get; set; }
public CapacityMode CapacityMode { get; set; }
public List<LoadBucket> Buckets { get; set; } = [];
}
| Property | Type | Description |
|---|---|---|
Resource |
Id |
Id of the resource. Required. |
CapacityMode |
CapacityMode |
Where each bucket's Capacity comes from. |
Buckets |
List<LoadBucket> |
Dense over the range: one bucket for every bucket start in [From, To) of the query, in time order, including buckets with no load. |
ResourceLoad has value equality (Buckets compared element by element), DeepClone() and ToString(), like LoadProfile.
CapacityMode#
Where the Capacity of a resource's buckets comes from.
public enum CapacityMode
{
Calendar,
Flat,
}
| Value | Description |
|---|---|
Calendar |
The resource has a calendar, SchedulingConfig.CalendarMode is Resource and UseCalendars is true. Buckets with working time in that calendar get the resource's capacity; all other buckets get 0. |
Flat |
Every bucket gets the resource's capacity. Applies when the resource has no calendar, CalendarMode is Task or TaskInherited, or UseCalendars is false. |
The resource's capacity is ResourceData.Capacity, or SchedulingConfig.DefaultResourceCapacity when that is null. CapacityMode is a plain enum with no parse or spelling helpers. The Plen.Wire package handles the JSON spellings "calendar" and "flat".
LoadBucket#
Load and capacity of one resource in one bucket.
public sealed class LoadBucket : IDeepCloneable<LoadBucket>, IEquatable<LoadBucket>
{
public Moment Start { get; set; }
public double Load { get; set; }
public double Capacity { get; set; }
public List<Id>? Tasks { get; set; }
}
| Property | Type | Description |
|---|---|---|
Start |
Moment |
Start of the bucket. It lies in [From, To) of the query. |
Load |
double |
Load booked in the bucket, in assignment Value units (1.0 = 100 %). |
Capacity |
double |
Capacity of the resource in the bucket, in the same units. See CapacityMode. |
Tasks |
List<Id>? |
Ids of the tasks booked in the bucket, in input order. null with ProfileTasks.None. With ProfileTasks.Over, set in buckets where Load > Capacity and empty elsewhere. With ProfileTasks.All, set in every bucket. See ProfileTasks. |
The bucket is overallocated when Load > Capacity. LoadBucket has value equality (Load and Capacity compared with ==, Tasks equal element by element or both null), DeepClone() and ToString(), like LoadProfile.
Example#
Reads the day buckets of one resource and prints the overallocated ones with their tasks:
using Plen;
static Moment Day(int day) =>
Moment.FromYmdHm(2026, 8, day, 0, 0) ?? throw new InvalidOperationException("invalid date");
var data = new ProjectData
{
Tasks =
[
new TaskData("a") { StartDate = Day(10), Duration = 2.0 },
new TaskData("b") { StartDate = Day(11), Duration = 2.0 },
],
Resources = [new ResourceData { Id = "dev" }],
Assignments =
[
new AssignmentData { Task = "a", Resource = "dev", Value = 1.0 },
new AssignmentData { Task = "b", Resource = "dev", Value = 1.0 },
],
};
var project = new Project();
project.Solve(data, new SolveOptions());
LoadProfile profile = project.LoadProfile(
new ProfileQuery(Day(10), Day(15)) { Basis = Basis.Day, Tasks = ProfileTasks.Over });
foreach (var row in profile.Resources)
{
Console.WriteLine($"{row.Resource} ({row.CapacityMode})");
foreach (var bucket in row.Buckets)
{
if (bucket.Load > bucket.Capacity)
Console.WriteLine($" {bucket.Start}: {bucket.Load} / {bucket.Capacity}, tasks {string.Join(", ", bucket.Tasks ?? [])}");
}
}
Related#
Project.LoadProfile- the call that returns a profile of the baselineProfileQuery- the range, resources, basis and task lists of the profileResourceOverallocation- overallocated windows reported in a schedule result- Resource load - how load is booked and how to read a profile
- Previewing changes - the profile of previewed dates