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


# CandidateResult

The score of one [`Candidate`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/candidate.md>). [`Project#evaluate`](<https://docs.dhtmlx.com/planning-engine/java/api/project-evaluate.md>) and [`Project#evaluateWith`](<https://docs.dhtmlx.com/planning-engine/java/api/project-evaluate.md#evaluatewith>) return one per candidate in [`EvaluateResult.candidates`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/evaluate-result.md#candidates>), in input order.

## Declaration

```java
package org.dhtmlx.plen;

public class CandidateResult extends ValueRecord implements DeepCloneable<CandidateResult>
```

A result holds either an error or metrics, never both. Check `error` first.

## Constructors

### CandidateResult()

```java
public CandidateResult()
```

Creates an instance with every field set to `null`. The library fills the fields on every instance it returns.

## Fields

| Field | Type | Description |
|---|---|---|
| `id` | [`Id`](<https://docs.dhtmlx.com/planning-engine/java/api/data/id.md>) | The candidate's `id`, copied unchanged. |
| `error` | [`RejectedOperation`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/rejected-operation.md>) | Set when the candidate failed: the first rejected operation of its change set, or an input error from its solve or level run. `path` is `""` when the error has no input path. When set, `scheduled`, `leveled` and `cost` are `null`. `null` otherwise. |
| `scheduled` | [`Metrics`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/metrics.md>) | Metrics of the scheduled stage. Set on every candidate without `error`. |
| `leveled` | [`LeveledMetrics`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/leveled-metrics.md>) | Metrics of the leveled stage. Set only when [`EvaluateOptions.level`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/evaluate-options.md#level>) is set and the scheduled stage has no cycles; `null` otherwise. |
| `cost` | `Double` | The cost of the last stage present: `leveled.metrics.cost` when `leveled` is set, else `scheduled.cost`. Lower is better. `null` when `error` is set. |

For how cost is computed, see [`Metrics.cost`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/metrics.md>).

## Methods

### withId, withError, withScheduled, withLeveled, withCost

```java
public CandidateResult withId(Id value)
public CandidateResult withError(RejectedOperation value)
public CandidateResult withScheduled(Metrics value)
public CandidateResult withLeveled(LeveledMetrics value)
public CandidateResult withCost(Double value)
```

Each setter assigns its field and returns this instance.

**Returns**: this `CandidateResult`.

### deepClone

```java
public CandidateResult deepClone()
```

Returns a deep copy: `error`, `scheduled` and `leveled` are copied recursively, so no list or nested object is shared with the original. `null` fields stay `null`.

**Returns**: a new `CandidateResult`.

### copy

```java
public CandidateResult copy()
```

Returns a shallow copy: the new result holds the same `id`, `error`, `scheduled` and `leveled` objects.

**Returns**: a new `CandidateResult`.

### equals, hashCode, toString

```java
public boolean equals(Object other)
public int hashCode()
public String toString()
```

Inherited from [`ValueRecord`](<https://docs.dhtmlx.com/planning-engine/java/api/support/value-record.md>). Two results are equal when every field is equal, nested metrics and lists included. `cost` compares with `Double.equals`. `toString()` prints all fields, for logging.

## Example

Rank the scored candidates by cost and list the rejected ones separately.

```java
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import org.dhtmlx.plen.*;

public class CandidateResultExample {
  public static void main(String[] args) throws Exception {
    Moment monday = Moment.fromYmdHm(2026, 8, 10, 8, 0);
    ProjectData data = new ProjectData()
        .withTasks(List.of(
            new TaskData(Id.num(1)).withStartDate(monday).withDuration(2.0)))
        .withResources(List.of(
            new ResourceData().withId(Id.str("dev1")),
            new ResourceData().withId(Id.str("dev2"))));

    Project project = new Project();
    project.solve(data, new SolveOptions());

    List<Candidate> candidates = new ArrayList<>();
    for (String dev : List.of("dev1", "dev2")) {
      SchedulingChanges changes = new SchedulingChanges();
      changes.assignments.add.add(new AssignmentData()
          .withId(Id.str("a-" + dev))
          .withTask(Id.num(1))
          .withResource(Id.str(dev))
          .withValue(1.0));
      candidates.add(new Candidate().withId(Id.str(dev)).withChanges(changes));
    }

    // Rejected: "dev9" isn't in the project.
    SchedulingChanges bad = new SchedulingChanges();
    bad.resources.remove.add(Id.str("dev9"));
    candidates.add(new Candidate().withId(Id.str("drop-dev9")).withChanges(bad));

    EvaluateResult result = project.evaluate(candidates, new EvaluateOptions());

    result.candidates.stream()
        .filter(c -> c.error == null)
        .sorted(Comparator.comparing((CandidateResult c) -> c.cost))
        .forEach(c -> System.out.println(
            c.id + ": cost " + c.cost + ", conflicts " + c.scheduled.conflicts.value));

    result.candidates.stream()
        .filter(c -> c.error != null)
        .forEach(c -> System.out.println(
            c.id + " rejected at " + c.error.path + ": " + c.error.message));
  }
}
```

## Related

- [`EvaluateResult`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/evaluate-result.md>) - the call result that holds every candidate result
- [`Metrics`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/metrics.md>) - the stage metrics and how cost is computed
- [`LeveledMetrics`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/leveled-metrics.md>) - the leveled stage, when leveling is requested
- [`RejectedOperation`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/rejected-operation.md>) - the type of `error`
- [Evaluating alternatives](<https://docs.dhtmlx.com/planning-engine/java/resources-and-assignment/evaluating-alternatives.md#failed-and-cyclic-candidates>) - reading failed and cyclic candidates
