Functional Weave
Code in Rust

energy.degree-days@1.0.0

impl/rust.rs

1,819 bytes · the Rust implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

use super::funejson::Value;  ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one

const LIMIT: i64 = 1000; // 100.0 °C in tenths

fn check_temperature(what: &str, value: i64) {
    if value < -LIMIT || value > LIMIT {
        panic!("{} must be whole tenths of a degree from -1000 to 1000, received {}", what, value);
    }
}

/// Heating and cooling degree days in tenths: each day adds how far its mean
/// fell below (heating) or rose above (cooling) the base.
///
/// # Panics
/// Panics if a temperature is outside -100.0 to 100.0 °C.
pub fn degree_days(daily_mean_temperatures: &[i64], base_temperature: i64) -> DegreeDays {
    check_temperature("base temperature", base_temperature);
    let mut heating = 0;
    let mut cooling = 0;
    for &mean in daily_mean_temperatures {
        check_temperature("daily mean temperature", mean);
        if mean < base_temperature {
            heating += base_temperature - mean;
        } else if mean > base_temperature {
            cooling += mean - base_temperature;
        }
    }
    DegreeDays {
        heating,
        cooling,
        days: daily_mean_temperatures.len() as i64,
    }
}

pub fn degree_days_to_value(d: &DegreeDays) -> Value {
    Value::obj(vec![
        ("heating", Value::Int(d.heating)),
        ("cooling", Value::Int(d.cooling)),
        ("days", Value::Int(d.days)),
    ])
}

fn whole_tenths(what: &str, v: &Value) -> i64 {
    if let Value::Float(f) = v {
        panic!("{} must be whole tenths of a degree from -1000 to 1000, received {}", what, f);
    }
    v.as_i64()
}

pub fn fune_vector(args: &[Value]) -> Value {
    let temps: Vec<i64> = args[0]
        .as_arr()
        .iter()
        .map(|v| whole_tenths("daily mean temperature", v))
        .collect();
    let base = whole_tenths("base temperature", &args[1]);
    degree_days_to_value(&degree_days(&temps, base))
}