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


# LevelingOptions

Options for a leveling run. Pass them to [`Project::level`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#level>), or set them as `level` in [`EvaluateOptions`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/evaluate/evaluate-options.md>) and [`SuggestOptions`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/suggest/suggest-options.md>) to score candidates at the leveled stage. `LevelingOptions::default()` levels the whole project with the standard order. Override single fields with struct update syntax.

## Declaration

```rust
#[derive(Clone, Debug)]
pub struct LevelingOptions {
    pub scope: Option<LevelingScope>,
    pub basis: Option<Basis>,
    pub order: LevelingOrder,
    pub within_slack_only: bool,
    pub clear_first: bool,
    pub allow_splits: bool,
    pub step: LevelingStep,
}

impl Default for LevelingOptions
```

## Fields

### scope

```rust
pub scope: Option<LevelingScope>
```

Resources whose contention is resolved, tasks that may move, and the date range that triggers leveling. `None` covers the whole project.

Default: `None`.

### basis

```rust
pub basis: Option<Basis>
```

Bucket size for detecting overallocation. `None` derives it from [`SchedulingConfig::duration_unit`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/scheduling-config.md#duration_unit>): `Day` for a `day` unit, `Hour` for `hour` and `minute`.

Default: `None`.

### order

```rust
pub order: LevelingOrder
```

Order in which contenders are picked to move.

Default: `LevelingOrder::Standard`.

### within_slack_only

```rust
pub within_slack_only: bool
```

`true` never moves a task past its total slack, so the project end of the base plan doesn't move. A window that can't be cleared this way stays with reason `slack-exhausted`.

Default: `false`.

### clear_first

```rust
pub clear_first: bool
```

`true` resets `leveling_delay` and `pauses` on in-scope tasks before leveling. `false` keeps them, and leveling adds to them.

Default: `true`.

### allow_splits

```rust
pub allow_splits: bool
```

`true` lets leveling split a task by adding or extending [`pauses`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/pause.md>). `false` makes every correction a whole-task `leveling_delay`; existing pauses are kept unless `clear_first` clears them.

Default: `true`.

### step

```rust
pub step: LevelingStep
```

How far one correction moves a task.

Default: `LevelingStep::Minimal`.

See [`Project::level`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#level>) for the errors.

## Example

```rust
use plen_core::{
    AssignmentData, DateTime, LevelingOptions, LevelingOrder, LevelingScope, Project,
    ProjectData, ResourceData, SolveOptions, TaskData,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let start = DateTime::from_ymd_hm(2026, 1, 5, 0, 0).ok_or("invalid date")?;

    // Two tasks on the same resource at the same time.
    let mut tasks = Vec::new();
    let mut assignments = Vec::new();
    for id in ["a", "b"] {
        let mut task = TaskData::new(id);
        task.start_date = Some(start);
        task.duration = Some(2.0);
        tasks.push(task);
        assignments.push(AssignmentData {
            id: None,
            task: id.into(),
            resource: "r1".into(),
            value: 1.0,
            offset: None,
            duration: None,
        });
    }

    let data = ProjectData {
        tasks,
        resources: vec![ResourceData { id: "r1".into(), capacity: None, calendar_id: None }],
        assignments,
        ..Default::default()
    };

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

    // Only task "b" may move, picked by priority, without splits.
    let options = LevelingOptions {
        scope: Some(LevelingScope {
            tasks: Some(vec!["b".into()]),
            ..Default::default()
        }),
        order: LevelingOrder::Priority,
        allow_splits: false,
        ..Default::default()
    };

    let result = project.level(&options)?;
    for update in &result.schedule.updates {
        println!("{:?}: delay {:?}", update.id, update.leveling_delay);
    }
    Ok(())
}
```

## Related

- [`LevelingResult`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/resources/leveling-result.md>) - what a leveling run with these options returns
- [`LevelingScope`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/resources/leveling-scope.md>) - the type of `scope`
- [`EvaluateOptions`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/evaluate/evaluate-options.md>) - takes these options to score candidates at the leveled stage
- [Leveling Resources](<https://docs.dhtmlx.com/planning-engine/rust/resources-and-assignment/leveling-resources.md#leveling-options>) - walks through each option on a sample plan
- [Evaluating Alternatives](<https://docs.dhtmlx.com/planning-engine/rust/resources-and-assignment/evaluating-alternatives.md>) - compares candidates after leveling
