use super::funejson::Value; use super::math_rational::{rational, rational_to_integer, rational_to_value}; const MAX_SAFE: i64 = (1i64 << 53) - 1; /// Takt time, available time / demand, as an exact fraction and in whole /// seconds. The whole seconds are rounded once from the exact fraction, so a /// caller balancing a line on `exact` never inherits a rounding step. /// /// # Panics /// Panics on negative available time, demand that is not positive, or an /// unknown rounding mode. pub fn takt_time(available_seconds: i64, demand: i64, mode: &str) -> TaktTime { if !(0..=MAX_SAFE).contains(&available_seconds) { panic!( "availableSeconds must be a whole number of seconds, not negative, received {}", available_seconds ); } if !(1..=MAX_SAFE).contains(&demand) { panic!("demand must be a whole number of units greater than zero, received {}", demand); } let exact = rational(available_seconds, demand); let seconds = rational_to_integer(&exact, mode); TaktTime { exact, seconds } } pub fn takt_time_to_value(result: &TaktTime) -> Value { Value::obj(vec![ ("exact", rational_to_value(&result.exact)), ("seconds", Value::Int(result.seconds)), ]) } pub fn fune_vector(args: &[Value]) -> Value { if let Value::Float(f) = &args[0] { panic!("availableSeconds must be a whole number of seconds, not negative, received {}", f); } if let Value::Float(f) = &args[1] { panic!("demand must be a whole number of units greater than zero, received {}", f); } takt_time_to_value(&takt_time(args[0].as_i64(), args[1].as_i64(), args[2].as_str())) }