precedence-net 1.1.0

Create and analyse precedence networks
Documentation
use crate::activity_builder::ActivityBuilder;
use crate::{DurationType, StartType};
use std::hash::{Hash, Hasher};

#[derive(Clone, Debug)]
pub struct Activity {
    pub reference: String,
    pub description: String,
    pub minimum_duration: f64,
    pub expected_duration: f64,
    pub maximum_duration: f64,
    pub start_type: StartType,
    pub duration_type: DurationType,
    pub depth: usize,

    pub earliest_start: f64,
    pub earliest_finish: f64,
    pub latest_start: f64,
    pub latest_finish: f64,
}

pub(crate) const START_REFERENCE: &str = "precedence_net_crate_start";
pub(crate) const FINISH_REFERENCE: &str = "precedence_net_crate_finish";

impl Activity {
    pub(crate) fn mean_duration(&self) -> f64 {
        ((4.0 * self.expected_duration) + self.minimum_duration + self.maximum_duration) / 6.0
    }

    pub(crate) fn standard_deviation(&self) -> f64 {
        (self.maximum_duration - self.minimum_duration) / 6.0
    }

    pub(crate) fn variance(&self) -> f64 {
        self.standard_deviation().powi(2)
    }

    pub(crate) fn duration(&self) -> f64 {
        match self.duration_type {
            DurationType::Expected => self.expected_duration,
            DurationType::Maximum => self.maximum_duration,
            DurationType::Minimum => self.minimum_duration,
            DurationType::Mean => self.mean_duration(),
        }
    }

    pub(crate) fn on_critical_path(&self) -> bool {
        self.latest_start == self.earliest_start
    }

    pub(crate) fn total_float(&self) -> f64 {
        self.latest_finish - self.earliest_finish
    }

    pub(crate) fn start(&self) -> f64 {
        match self.start_type {
            StartType::Earliest => self.earliest_start,
            StartType::Latest => self.latest_start,
        }
    }

    pub(crate) fn finish(&self) -> f64 {
        match self.start_type {
            StartType::Earliest => self.earliest_finish,
            StartType::Latest => self.latest_finish,
        }
    }

    pub(crate) fn active_on(&self, time: f64) -> bool {
        (self.start()..self.finish()).contains(&time)
    }

    pub(crate) fn active_during(&self, range: std::ops::Range<f64>) -> bool {
        !(self.finish() <= range.start || self.start() >= range.end)
    }

    pub(crate) fn to_builder(&self) -> ActivityBuilder {
        ActivityBuilder {
            reference: self.reference.clone(),
            description: self.description.clone(),
            minimum_duration: self.minimum_duration,
            expected_duration: self.expected_duration,
            maximum_duration: self.maximum_duration,
            depth: self.depth,
            start_type: self.start_type,
            duration_type: self.duration_type,

            earliest_start: None,
            earliest_finish: None,
            latest_start: None,
            latest_finish: None,
        }
    }
}

impl Hash for Activity {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.reference.hash(state);
    }
}

impl TryFrom<&ActivityBuilder> for Activity {
    type Error = crate::Error;

    fn try_from(activity_builder: &ActivityBuilder) -> std::result::Result<Activity, Self::Error> {
        activity_builder.build()
    }
}

impl TryFrom<ActivityBuilder> for Activity {
    type Error = crate::Error;

    fn try_from(activity_builder: ActivityBuilder) -> std::result::Result<Activity, Self::Error> {
        activity_builder.build()
    }
}