use super::funejson::Value; use super::math_round_div::round_div; const MAX_OUTPUT: i64 = ((1i64 << 53) - 1) / 10000; /// Starts needed for a good output at a yield, rounded up in integers so an /// exact answer (95 at 95% is 100) never becomes 101 through a float. /// /// # Panics /// Panics on a negative or oversized output, or a yield outside 1-10000. pub fn input_for_yield(required_output: i64, yield_basis_points: i64) -> YieldPlan { if !(0..=MAX_OUTPUT).contains(&required_output) { panic!( "requiredOutput must be a whole number of units from 0 to {}, received {}", MAX_OUTPUT, required_output ); } if !(1..=10000).contains(&yield_basis_points) { panic!("yieldBasisPoints must be a whole number from 1 to 10000, received {}", yield_basis_points); } let input = round_div(required_output * 10000, yield_basis_points, "up"); YieldPlan { input, scrap: input - required_output, } } pub fn yield_plan_to_value(plan: &YieldPlan) -> Value { Value::obj(vec![("input", Value::Int(plan.input)), ("scrap", Value::Int(plan.scrap))]) } pub fn fune_vector(args: &[Value]) -> Value { if let Value::Float(f) = &args[0] { panic!("requiredOutput must be a whole number of units from 0 to {}, received {}", MAX_OUTPUT, f); } if let Value::Float(f) = &args[1] { panic!("yieldBasisPoints must be a whole number from 1 to 10000, received {}", f); } yield_plan_to_value(&input_for_yield(args[0].as_i64(), args[1].as_i64())) }