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
use super::math_round_div::round_div; ← from math.round-div ^1.0.0 · built alongside by fune
use super::money_amount::{money_from_value, money_to_value, Money}; ← from money.amount ^1.0.0 · built alongside by fune
use super::money_sum::sum_money; ← from money.sum ^1.0.0 · built alongside by fune
fn tenths(amount: &Money, miles: i64) -> i64 {
round_div(amount.minor * 10, miles, "half-up")
}
fn display(value: i64) -> String {
let sign = if value < 0 { "-" } else { "" };
let magnitude = value.unsigned_abs();
format!("{}{}.{}", sign, magnitude / 10, magnitude % 10)
}
/// Whole-life cost per mile, in tenths of a penny, the unit fleet reports use.
///
/// Each part is rounded on its own for the breakdown, and the total is rounded
/// from the total cost: adding up the rounded parts drifts by a tenth or two,
/// which is why the total is not their sum.
///
/// # Panics
/// Panics if miles is not above zero or the costs mix currencies.
pub fn cost_per_mile(costs: &WholeLifeCosts, miles: i64) -> CostPerMile {
if miles <= 0 {
panic!("miles must be a whole number above zero, received {}", miles);
}
let total_cost = sum_money(
&[
costs.depreciation.clone(),
costs.fuel.clone(),
costs.maintenance.clone(),
costs.insurance.clone(),
costs.tax.clone(),
],
&costs.depreciation.currency,
);
let total_tenths = tenths(&total_cost, miles);
CostPerMile {
depreciation_tenths: tenths(&costs.depreciation, miles),
fuel_tenths: tenths(&costs.fuel, miles),
maintenance_tenths: tenths(&costs.maintenance, miles),
insurance_tenths: tenths(&costs.insurance, miles),
tax_tenths: tenths(&costs.tax, miles),
total_tenths,
per_mile: display(total_tenths),
total_cost,
}
}
pub fn cost_per_mile_to_value(c: &CostPerMile) -> Value {
Value::obj(vec![
("totalCost", money_to_value(&c.total_cost)),
("depreciationTenths", Value::Int(c.depreciation_tenths)),
("fuelTenths", Value::Int(c.fuel_tenths)),
("maintenanceTenths", Value::Int(c.maintenance_tenths)),
("insuranceTenths", Value::Int(c.insurance_tenths)),
("taxTenths", Value::Int(c.tax_tenths)),
("totalTenths", Value::Int(c.total_tenths)),
("perMile", Value::str(&c.per_mile)),
])
}
pub fn fune_vector(args: &[Value]) -> Value {
if let Value::Float(f) = &args[1] {
panic!("miles must be a whole number above zero, received {}", f);
}
let c = &args[0];
let costs = WholeLifeCosts {
depreciation: money_from_value(c.get("depreciation")),
fuel: money_from_value(c.get("fuel")),
maintenance: money_from_value(c.get("maintenance")),
insurance: money_from_value(c.get("insurance")),
tax: money_from_value(c.get("tax")),
};
cost_per_mile_to_value(&cost_per_mile(&costs, args[1].as_i64()))
}