Candidate#

One alternative edit to score: an id and the SchedulingChanges to try. Build a slice of candidates and pass it to Project::evaluate or Project::evaluate_with.

Declaration#

#[derive(Clone, Debug)]
pub struct Candidate {
    pub id: Id,
    pub changes: SchedulingChanges,
}

Candidate doesn't implement Default. Build it with a struct literal.

Fields#

Field Type Description
id Id Label for the candidate. Copied unchanged into CandidateResult::id. Uniqueness isn't checked.
changes SchedulingChanges Edits to apply to the copy before scheduling it.

For how a stale changes.baseline_id or a rejected operation in changes is reported, see Project::evaluate and CandidateResult::error.

Example#

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

use plen_core::{
    AssignmentData, Candidate, DateTime, EvaluateOptions, Project, ProjectData,
    ProjectOptions, ResourceData, SchedulingChanges, SolveOptions, TaskData,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let monday = DateTime::from_ymd_hm(2026, 8, 10, 8, 0).ok_or("invalid date")?;

    let data = ProjectData {
        tasks: vec![TaskData {
            start_date: Some(monday),
            duration: Some(2.0),
            ..TaskData::new(1)
        }],
        resources: ["dev1", "dev2"]
            .iter()
            .map(|id| ResourceData { id: (*id).into(), capacity: None, calendar_id: None })
            .collect(),
        ..Default::default()
    };

    let mut project = Project::new(ProjectOptions::default());
    project.solve(Some(data), &SolveOptions::default())?;

    let candidates: Vec<Candidate> = ["dev1", "dev2"]
        .iter()
        .map(|dev| {
            let mut changes = SchedulingChanges::default();
            changes.assignments.add.push(AssignmentData {
                id: None,
                task: 1.into(),
                resource: (*dev).into(),
                value: 1.0,
                offset: None,
                duration: None,
            });
            Candidate { id: (*dev).into(), changes }
        })
        .collect();

    let result = project.evaluate(&candidates, &EvaluateOptions::default())?;
    for c in &result.candidates {
        println!("{:?}: cost {:?}", c.id, c.cost);
    }
    Ok(())
}