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


# Project.Level

Resolves resource overallocation in a [`Project`](<https://docs.dhtmlx.com/planning-engine/net/api/core/project/project.md>). It runs [`Solve(null, …)`](<https://docs.dhtmlx.com/planning-engine/net/api/project-solve.md>) with default options first, then writes persistent `LevelingDelay` and `Pauses` edits and accepts the leveled state as the baseline.

## Signature

```csharp
public LevelingResult Level(LevelingOptions options)
```

Synchronous and CPU-only. Changes the project's state.

## Parameters

| Name | Type | Description |
|---|---|---|
| `options` | [`LevelingOptions`](<https://docs.dhtmlx.com/planning-engine/net/api/core/resources/leveling-options.md>) | Scope, order, basis and how leveling may move tasks |

## Behavior

- Forward scheduling only.
- On a cyclic project, it returns the initial solve's result with [`Rounds`](<https://docs.dhtmlx.com/planning-engine/net/api/core/resources/leveling-result.md#rounds>) `= 0`.
- The leveled dates replace the baseline. To see leveling without committing it, call `Level` on a [`Clone()`](<https://docs.dhtmlx.com/planning-engine/net/api/core/project/project.md#clone>).

## Returns

A [`LevelingResult`](<https://docs.dhtmlx.com/planning-engine/net/api/core/resources/leveling-result.md>). The project keeps its `Schedule` as the baseline and shares it with clones. Treat `Schedule` as read-only, or call `DeepClone()` before modifying it.

## Errors

| Error | When |
|---|---|
| [`InputException`](<https://docs.dhtmlx.com/planning-engine/net/api/core/errors/input-exception.md>) | An unknown id in `options.Scope.Resources` or `options.Scope.Tasks` (`Path` is `scope.resources` / `scope.tasks`); the project has [`Config.ScheduleFromEnd`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/scheduling-config.md#schedulefromend>) `= true` (`Path` is `config.schedule_from_end`) |
| [`ProjectException`](<https://docs.dhtmlx.com/planning-engine/net/api/core/errors/project-exception.md>) `NeedsResync` | Thrown by the initial solve |
| `ArgumentNullException` | `options` is `null` |

## Example

Level two tasks that share one resource, first on a copy, then for real.

```csharp
using Plen;

var monday = Moment.FromYmdHm(2026, 8, 10, 8, 0) ?? throw new InvalidOperationException("invalid date");
TaskData Task(string id) => new(id) { StartDate = monday, Duration = 2.0 };
AssignmentData Assign(string task) => new() { Task = task, Resource = "dev", Value = 1.0 };

var data = new ProjectData
{
    Tasks = [Task("a"), Task("b")],
    Resources = [new ResourceData { Id = "dev" }],
    Assignments = [Assign("a"), Assign("b")],
};

var project = new Project();
project.Solve(data, new SolveOptions());

// A proposal: level a cheap copy, the project keeps its dates.
var draft = project.Clone();
var proposal = draft.Level(new LevelingOptions());
foreach (var update in proposal.Schedule.Updates)
    Console.WriteLine($"task {update.Id} delay {update.LevelingDelay}");

// Commit: level the project itself.
var leveled = project.Level(new LevelingOptions());
Console.WriteLine($"{leveled.Rounds} round(s)");
```

## Related

- [`LevelingOptions`](<https://docs.dhtmlx.com/planning-engine/net/api/core/resources/leveling-options.md>) - the options
- [`LevelingResult`](<https://docs.dhtmlx.com/planning-engine/net/api/core/resources/leveling-result.md>) - the returned result
- [Leveling resources](<https://docs.dhtmlx.com/planning-engine/net/resources-and-assignment/leveling-resources.md>) - resolving overallocation
- [Preview leveling](<https://docs.dhtmlx.com/planning-engine/net/how-to/preview-leveling.md>) - leveling a clone without committing
- [Clear leveling](<https://docs.dhtmlx.com/planning-engine/net/how-to/clear-leveling.md>) - removing leveling delays and pauses
