EvaluateOptions#

Options for Project#evaluate and Project#evaluateWith. They set the baseline the call expects, whether each candidate also gets a leveled stage, which tasks get per-task finish and overload figures, and whether candidates are scored against a cleared copy of the baseline. new EvaluateOptions() scores the scheduled stage only, with no focus tasks.

Declaration#

public class EvaluateOptions extends ValueRecord implements DeepCloneable<EvaluateOptions>

Set fields with the fluent withX setters: new EvaluateOptions().withLevel(new LevelingOptions()).

Constructors#

EvaluateOptions()#

public EvaluateOptions()

Creates options with every field at its default.

Fields#

Field Type Default Description
baselineId String null The baseline the call expects. null skips the check.
level LevelingOptions null Adds a leveled stage to each candidate. null scores the scheduled stage only.
focus Vec<Id> empty Tasks to report finish and overload for. Must not be null.
clearFirst boolean false Scores against a copy of the baseline with leveling delays and pauses cleared.

baselineId#

public String baselineId = null;

A baseline token taken from the latest ScheduleResult.baselineId. When it isn't null and doesn't name the project's current baseline, Project#evaluate throws a ProjectException with code STALE_BASELINE.

Each candidate's SchedulingChanges.baselineId is checked the same way, independently of this field.

level#

public LevelingOptions level = null;

When set, every candidate is leveled with these options after it's solved, and CandidateResult.leveled holds the LeveledMetrics of that stage. The options are used unchanged, so level.clearFirst (default true) applies. When null, CandidateResult.leveled is always null.

level.basis, when given, is the bucket basis for every overload figure in the result, baseline included. Without it, the basis is derived from the project.

Options that are invalid for the baseline make Project#evaluate throw an InputException. To commit a scored candidate with Project#level, pass the same LevelingOptions, step included, so the committed plan matches the scored one.

focus#

public Vec<Id> focus = new Vec<Id>();

Task ids that get per-task figures in every Metrics value of the result: one TaskFinish entry in finish.tasks and one FocusOverload entry in overload.focus per id, in this order. An empty list adds no per-task figures.

Every id must name a task in the baseline. An unknown id makes Project#evaluate throw an InputException with path focus[i]. A focus task that a candidate removes reports null for its finish and focus overload in that candidate's metrics.

clearFirst#

public boolean clearFirst = false;

When true, the reference state is a copy of the baseline with levelingDelay and pauses cleared on the tasks in scope, then solved. The scope is level.scope.tasks when level gives it, otherwise every task, also when level is null. EvaluateResult.baseline and every candidate are measured on that copy.

  • clearFirst is independent of level.clearFirst, so it also applies when only the scheduled stage is scored.
  • baselineId, candidate tokens, level and focus are checked against the accepted baseline before anything is cleared. A valid candidate baselineId is dropped before that candidate's changes are applied to the copy.
  • EvaluateResult.baselineId stays the accepted baseline's id.
  • When nothing in scope has a delay or pause to clear, the result is identical to clearFirst = false.

Methods#

withBaselineId, withLevel, withFocus, withClearFirst#

public EvaluateOptions withBaselineId(String value)
public EvaluateOptions withLevel(LevelingOptions value)
public EvaluateOptions withFocus(Vec<Id> value)
public EvaluateOptions withFocus(Collection<? extends Id> value)
public EvaluateOptions withClearFirst(boolean value)

Each setter assigns its field and returns this instance for chaining. The Collection overload of withFocus copies the ids into a new Vec, so List.of(...) works. Passing null to either withFocus overload sets focus to null, which Project#evaluate rejects with a NullPointerException.

Returns - this EvaluateOptions.

deepClone#

public EvaluateOptions deepClone()

Returns a copy that shares no nested object (level, the focus list) with this instance.

Returns - a new EvaluateOptions with the same values.

copy#

public EvaluateOptions copy()

Returns a shallow copy. The copy shares the level object and the focus list with this instance.

Returns - a new EvaluateOptions with the same field values.

equals, hashCode, toString#

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

Inherited from ValueRecord. Two EvaluateOptions are equal when their public fields are equal, nested records compared by value. toString() lists the fields.

Example#

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

public class EvaluateOptionsExample {
  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.str("A")).withStartDate(monday).withDuration(2.0),
            new TaskData(Id.str("B")).withStartDate(monday).withDuration(2.0)))
        .withResources(List.of(
            new ResourceData().withId(Id.str("dev1")),
            new ResourceData().withId(Id.str("dev2"))))
        .withAssignments(List.of(
            new AssignmentData().withId(Id.str("aA")).withTask(Id.str("A"))
                .withResource(Id.str("dev1")).withValue(1.0),
            new AssignmentData().withId(Id.str("aB")).withTask(Id.str("B"))
                .withResource(Id.str("dev1")).withValue(1.0)));

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

    SchedulingChanges toDev2 = new SchedulingChanges();
    toDev2.assignments.update.add(
        new AssignmentUpdate(Id.str("aB")).withResource(Patch.of(Id.str("dev2"))));

    EvaluateOptions options = new EvaluateOptions()
        .withBaselineId(solved.baselineId)
        .withLevel(new LevelingOptions())
        .withFocus(List.of(Id.str("B")));

    EvaluateResult result = project.evaluate(
        List.of(
            new Candidate().withId(Id.str("stay")).withChanges(new SchedulingChanges()),
            new Candidate().withId(Id.str("dev2")).withChanges(toDev2)),
        options);

    for (CandidateResult candidate : result.candidates) {
      if (candidate.leveled == null) continue;
      TaskFinish finishB = candidate.leveled.metrics.finish.tasks.get(0);
      System.out.println(candidate.id + ": B finishes " + finishB.finish.date
          + ", leveled cost " + candidate.cost);
    }
  }
}