Project::analyze#

Computes analytics over dates without scheduling them. It reads either supplied ProjectData or the current dates of a Project, including unsolved edits. It never installs data and never changes the solved status.

Signature#

pub fn analyze(
    &self,
    data: Option<&ProjectData>,
    options: &AnalyzeOptions,
) -> Result<ScheduleResult, Error>

Takes &self. Synchronous and CPU-only. Works on an unsolved project.

Parameters#

Name Type Description
data Option<&ProjectData> Dates to analyze, or None for the project's current dates
options &AnalyzeOptions Which analytics to compute

Returns#

A ScheduleResult with cycles, notes, analytics and overallocations. It has no updates and no conflicts. Its baseline_id is set only for None on a solved project with no unsolved edits.

Errors#

Error When
Error::Input Supplied data fails validation

Example#

Get the critical path of dates stored elsewhere, without scheduling them.

use plen_core::{
    AnalyticsOptions, AnalyzeOptions, DateTime, LinkData, LinkType, Project, ProjectData, TaskData,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let day = |d| DateTime::from_ymd_hm(2026, 1, d, 0, 0).ok_or("invalid date");

    let mut design = TaskData::new("design");
    design.start_date = Some(day(5)?);
    design.duration = Some(2.0);
    let mut build = TaskData::new("build");
    build.start_date = Some(day(7)?);
    build.duration = Some(3.0);
    let data = ProjectData {
        tasks: vec![design, build],
        links: vec![LinkData {
            id: "l1".into(),
            source: "design".into(),
            target: "build".into(),
            link_type: LinkType::Fs,
            lag: 0.0,
            lag_unit: None,
        }],
        ..Default::default()
    };

    let project = Project::default();
    let options = AnalyzeOptions {
        analytics: AnalyticsOptions {
            critical_path: true,
            slack: false,
        },
    };
    let result = project.analyze(Some(&data), &options)?;

    if let Some(critical) = result.analytics.as_ref().and_then(|a| a.critical_path.as_ref()) {
        println!("critical tasks: {:?}", critical.tasks);
    }
    Ok(())
}