[Canonical page](<https://docs.dhtmlx.com/planning-engine/rust/api/core/evaluate/overload/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# Overload

The resource overload of one evaluation stage: the total, the share of each resource, and the overload around each focus task. Each value comes with its difference from the baseline. You read it from [`Metrics::overload`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/evaluate/metrics.md>), which appears in [`EvaluateResult::baseline`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/evaluate/evaluate-result.md>) and in the `scheduled` and `leveled` stages of every [`CandidateResult`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/evaluate/candidate-result.md>).

## Declaration

```rust
#[derive(Clone, Debug, PartialEq)]
pub struct Overload {
    pub total: Amount,
    pub resources: Vec<ResourceOverload>,
    pub focus: Vec<FocusOverload>,
}
```

With the `serde` feature, `Overload` implements `Serialize` and `Deserialize` with camelCase field names.

## Fields

| Field | Type | Description |
|---|---|---|
| `total` | [`Amount`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/evaluate/amount.md>) | Overload summed over all resources. `delta` is the difference from the baseline total. |
| `resources` | `Vec<`[`ResourceOverload`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/evaluate/resource-overload.md>)`>` | One entry per resource with non-zero overload in this stage or in the baseline. Resources of this stage come first, then resources overloaded only in the baseline. |
| `focus` | `Vec<`[`FocusOverload`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/evaluate/focus-overload.md>)`>` | One entry per id in [`EvaluateOptions::focus`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/evaluate/evaluate-options.md>). Empty when `focus` is empty. |

### How overload is measured

For each resource, overload is the sum over time buckets of `max(0, load − capacity)`. The unit is capacity × buckets: one resource at capacity 1, double-booked for two day buckets, has an overload of 2.

The baseline and every stage of every candidate use the same bucket basis: [`LevelingOptions::basis`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/resources/leveling-options.md#basis>) when [`EvaluateOptions::level`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/evaluate/evaluate-options.md>) sets it, otherwise the basis derived from `config.duration_unit`. Values from one [`EvaluateResult`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/evaluate/evaluate-result.md>) are therefore comparable with each other.

## Example

Two tasks run on the same days and both use `dev1`. Score a candidate that moves task 2 to `dev2`, and print the overload of the baseline and of the candidate.

```rust
use plen_core::{
    AssignmentData, AssignmentUpdate, Candidate, DateTime, EvaluateOptions, Overload, Patch,
    Project, ProjectData, ProjectOptions, ResourceData, SchedulingChanges, SolveOptions, TaskData,
};

fn print(label: &str, overload: &Overload) {
    println!("{label}: total {} ({:+})", overload.total.value, overload.total.delta);
    for r in &overload.resources {
        println!("  {}: {} ({:+})", r.resource, r.overload.value, r.overload.delta);
    }
    for f in &overload.focus {
        match &f.resources {
            Some(resources) => println!("  around task {}: {} resource(s)", f.task, resources.len()),
            None => println!("  task {} removed", f.task),
        }
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let monday = DateTime::from_ymd_hm(2026, 8, 10, 8, 0).ok_or("invalid date")?;
    let task = |id: i32| TaskData {
        start_date: Some(monday),
        duration: Some(2.0),
        ..TaskData::new(id)
    };
    let resource = |id: &str| ResourceData {
        id: id.into(),
        capacity: None,
        calendar_id: None,
    };
    let assignment = |id: &str, task: i32| AssignmentData {
        id: Some(id.into()),
        task: task.into(),
        resource: "dev1".into(),
        value: 1.0,
        offset: None,
        duration: None,
    };
    let data = ProjectData {
        tasks: vec![task(1), task(2)],
        resources: vec![resource("dev1"), resource("dev2")],
        assignments: vec![assignment("a1", 1), assignment("a2", 2)],
        ..Default::default()
    };

    let mut project = Project::new(ProjectOptions::default());
    project.solve(Some(data), &SolveOptions::default())?;

    let mut changes = SchedulingChanges::default();
    let mut to_dev2 = AssignmentUpdate::new("a2");
    to_dev2.resource = Patch::Value("dev2".into());
    changes.assignments.update.push(to_dev2);
    let candidates = [Candidate { id: "dev2".into(), changes }];

    let options = EvaluateOptions {
        focus: vec![2.into()],
        ..Default::default()
    };
    let result = project.evaluate(&candidates, &options)?;

    print("baseline", &result.baseline.overload);
    for candidate in &result.candidates {
        if let Some(scheduled) = &candidate.scheduled {
            print(&candidate.id.to_string(), &scheduled.overload);
        }
    }
    Ok(())
}
```

## Related

- [`Metrics`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/evaluate/metrics.md>) - the stage measurements that contain it
- [`LoadProfile`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/resources/load-profile.md>) - per-bucket load and capacity, where the same excess can be inspected
- [`LevelingOptions`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/resources/leveling-options.md>) - its `basis` sets the bucket size
- [Evaluating Alternatives](<https://docs.dhtmlx.com/planning-engine/rust/resources-and-assignment/evaluating-alternatives.md#metrics-and-cost>) - how overload is compared across candidates
