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


# Candidate

One alternative edit to score: an id and the [`SchedulingChanges`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/scheduling-changes.md>) to try. Create it with `new Candidate()` and the fluent setters, and pass a list of candidates to [`Project#evaluate`](<https://docs.dhtmlx.com/planning-engine/java/api/project-evaluate.md>) or [`Project#evaluateWith`](<https://docs.dhtmlx.com/planning-engine/java/api/project-evaluate.md#evaluatewith>).

## Declaration

```java
package org.dhtmlx.plen;

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

## Constructors

### Candidate()

```java
public Candidate()
```

Creates a candidate with `id` and `changes` set to `null`. Set both before passing it to `evaluate`.

## Fields

| Field | Type | Default | Description |
|---|---|---|---|
| `id` | [`Id`](<https://docs.dhtmlx.com/planning-engine/java/api/data/id.md>) | `null` | Label for the candidate. Copied unchanged into [`CandidateResult.id`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/candidate-result.md>). Uniqueness isn't checked. |
| `changes` | [`SchedulingChanges`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/scheduling-changes.md>) | `null` | Edits to apply to the copy before scheduling it. Required: `evaluate` throws `NullPointerException` when it's `null`. An empty `new SchedulingChanges()` scores the plan as it is. |

For how a stale `changes.baselineId` or a rejected operation in `changes` is reported, see [`Project#evaluate`](<https://docs.dhtmlx.com/planning-engine/java/api/project-evaluate.md#errors>) and [`CandidateResult.error`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/candidate-result.md>).

## Methods

### withId, withChanges

```java
public Candidate withId(Id value)
public Candidate withChanges(SchedulingChanges value)
```

Each setter assigns its field and returns this instance.

**Returns**: this `Candidate`.

### deepClone

```java
public Candidate deepClone()
```

Returns a new candidate with the same `id` and a deep copy of `changes`. Nothing in the change set is shared with the original.

**Returns**: a new `Candidate`.

**Errors**: `NullPointerException` when `changes` is `null`.

### copy

```java
public Candidate copy()
```

Returns a shallow copy: the new candidate holds the same `id` and `changes` objects.

**Returns**: a new `Candidate`.

### 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 candidates are equal when `id` and `changes` are equal. `toString()` prints both fields, for logging.

## Example

Score two ways to staff task `1`: assign `dev1` or assign `dev2`.

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

public class CandidateExample {
  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));
    }

    EvaluateResult result = project.evaluate(candidates, new EvaluateOptions());
    for (CandidateResult candidate : result.candidates) {
      System.out.println(candidate.id + ": cost " + candidate.cost);
    }
  }
}
```

## Related

- [`Project#evaluate`](<https://docs.dhtmlx.com/planning-engine/java/api/project-evaluate.md>) - the call that scores a list of candidates
- [`CandidateResult`](<https://docs.dhtmlx.com/planning-engine/java/api/evaluate/candidate-result.md>) - the score returned for each candidate
- [`SchedulingChanges`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/scheduling-changes.md>) - the change set a candidate carries
- [Evaluating alternatives](<https://docs.dhtmlx.com/planning-engine/java/resources-and-assignment/evaluating-alternatives.md#candidates>) - building candidates and committing the winner
