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


# LevelingOptions

Options for [`Project.Level`](<https://docs.dhtmlx.com/planning-engine/net/api/project-level.md>). `new LevelingOptions()` levels the whole project with the defaults below. [`EvaluateOptions.Level`](<https://docs.dhtmlx.com/planning-engine/net/api/core/evaluate/evaluate-options.md>) and [`SuggestOptions.Level`](<https://docs.dhtmlx.com/planning-engine/net/api/core/suggest/suggest-options.md>) take the same type.

## Declaration

```csharp
namespace Plen;

public sealed class LevelingOptions : IDeepCloneable<LevelingOptions>
{
    public LevelingScope? Scope { get; set; }
    public Basis? Basis { get; set; }
    public LevelingOrder Order { get; set; } = LevelingOrder.Standard;
    public bool WithinSlackOnly { get; set; } = false;
    public bool ClearFirst { get; set; } = true;
    public bool AllowSplits { get; set; } = true;
    public LevelingStep Step { get; set; } = LevelingStep.Minimal;

    public LevelingOptions DeepClone();
}
```

`LevelingOptions` doesn't implement `IEquatable<T>`, so two instances compare by reference.

## Properties

| Property | Type | Default | Description |
|---|---|---|---|
| `Scope` | [`LevelingScope`](<https://docs.dhtmlx.com/planning-engine/net/api/core/resources/leveling-options.md#levelingscope>)`?` | `null` | Which resources, tasks and dates leveling acts on. `null` levels the whole project. |
| `Basis` | [`Basis`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/basis.md>)`?` | `null` | Bucket size for detecting overallocation. `null` derives it from [`SchedulingConfig.DurationUnit`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/scheduling-config.md>). |
| `Order` | [`LevelingOrder`](<https://docs.dhtmlx.com/planning-engine/net/api/core/resources/leveling-options.md#levelingorder>) | `LevelingOrder.Standard` | Order in which contending tasks give way. |
| `WithinSlackOnly` | `bool` | `false` | `true` caps every delay or pause at the task's total slack, so leveling never pushes the plan past the end it had before leveling. |
| `ClearFirst` | `bool` | `true` | `true` resets `LevelingDelay` to `0` and clears `Pauses` on in-scope tasks before leveling starts. `false` keeps them and levels on top. |
| `AllowSplits` | `bool` | `true` | `true` lets leveling pause a task part-way through (`Pauses`) instead of delaying it whole. `false` keeps existing pauses but creates or extends none. |
| `Step` | [`LevelingStep`](<https://docs.dhtmlx.com/planning-engine/net/api/core/resources/leveling-options.md#levelingstep>) | `LevelingStep.Minimal` | How far one correction moves a task. |

Leveling writes its corrections to [`TaskData.LevelingDelay`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/task-data.md>) and [`TaskData.Pauses`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/task-data.md>). For how the leveler selects and moves tasks, see [Leveling resources](<https://docs.dhtmlx.com/planning-engine/net/resources-and-assignment/leveling-resources.md>).

### Validation

A call that reads these options throws an [`InputException`](<https://docs.dhtmlx.com/planning-engine/net/api/core/errors/input-exception.md>) for an unknown id in the scope:

| Path | When |
|---|---|
| `scope.resources` | `Scope.Resources` names a resource that isn't in the project |
| `scope.tasks` | `Scope.Tasks` names a task that isn't in the project |

## Methods

### DeepClone

```csharp
public LevelingOptions DeepClone()
```

Returns a copy whose `Scope` is a deep copy too, so the two instances share no list.

## LevelingScope

Limits what leveling acts on. Every property defaults to `null`, which means no limit.

```csharp
namespace Plen;

public sealed class LevelingScope : IDeepCloneable<LevelingScope>
{
    public List<Id>? Resources { get; set; }
    public List<Id>? Tasks { get; set; }
    public Moment? From { get; set; }
    public Moment? To { get; set; }

    public LevelingScope DeepClone();
}
```

| Property | Type | Default | Description |
|---|---|---|---|
| `Resources` | `List<`[`Id`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/id.md>)`>?` | `null` | Resources whose overallocation is resolved. `null` means every resource. |
| `Tasks` | `List<Id>?` | `null` | Tasks leveling may move. `null` means every task. Tasks outside the list are never delayed or paused. |
| `From` | [`Moment`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/moment.md>)`?` | `null` | Start of the range that triggers leveling. A bucket is in range when its start lies in `[From, To)`. `null` means no lower bound. |
| `To` | `Moment?` | `null` | End of the triggering range (exclusive). `null` means no upper bound. |

`From` and `To` limit which overallocated buckets get resolved, not where a task may land: a delayed task can end up after `To`.

`DeepClone()` returns a copy that shares no list with this one.

## LevelingOrder

Decides which contending task gives way in an overallocated bucket.

```csharp
namespace Plen;

public enum LevelingOrder
{
    Id = 1,
    Standard = 0,
    Priority = 2,
}
```

| Value | Description |
|---|---|
| `Standard` | Default. A task already running stays, then the standard chain decides: dependency (the successor moves), total slack (more slack moves), start date (later start moves), [`TaskData.Priority`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/task-data.md>) (lower priority moves), constraints (a task with a dated constraint stays), input order (the later task moves). |
| `Id` | A task already running stays, then the task later in input order moves. |
| `Priority` | `TaskData.Priority` decides first (lower priority moves), then the same rules as `Standard`. |

## LevelingStep

Sets how far one correction moves the selected task.

```csharp
namespace Plen;

public enum LevelingStep
{
    Minimal,
    Skip,
}
```

| Value | Description |
|---|---|
| `Minimal` | Default. Each correction moves the task past one bucket. The choice of which task moves runs again for the next bucket. |
| `Skip` | Each correction moves the task past the whole overallocated window in one step. Takes fewer rounds and can give a different result than `Minimal`. |

## Example

```csharp
using Plen;

static Moment Day(int day) =>
    Moment.FromYmdHm(2026, 1, day, 0, 0) ?? throw new InvalidOperationException("invalid date");

var data = new ProjectData
{
    Tasks =
    [
        new TaskData("a") { StartDate = Day(5), Duration = 3.0 },
        new TaskData("b") { StartDate = Day(5), 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());

var result = project.Level(new LevelingOptions
{
    Scope = new LevelingScope { Resources = ["dev"] },
    Order = LevelingOrder.Priority,
    AllowSplits = false,
});
```

## Related

- [`Project.Level`](<https://docs.dhtmlx.com/planning-engine/net/api/project-level.md>) - the call these options configure
- [`LevelingResult`](<https://docs.dhtmlx.com/planning-engine/net/api/core/resources/leveling-result.md>) - the result of a leveling run
- [`EvaluateOptions`](<https://docs.dhtmlx.com/planning-engine/net/api/core/evaluate/evaluate-options.md>) - scoring candidates with a leveling stage
- [Leveling resources](<https://docs.dhtmlx.com/planning-engine/net/resources-and-assignment/leveling-resources.md#leveling-options>) - what each option changes
- [Preview leveling](<https://docs.dhtmlx.com/planning-engine/net/how-to/preview-leveling.md>) - leveling a clone without committing
