recipe_ratio/lib.rs
1//! # recipe-ratio
2//!
3//! Baker's percentages, dough hydration, and recipe scaling by flour weight. Pure math,
4//! no deps. The same ratios behind the [IngredientCalculator](https://ingredientcalculator.com/)
5//! [the cups-to-grams page](https://ingredientcalculator.com/cups-to-grams/).
6//!
7//! ```
8//! use recipe_ratio::{baker_percent, hydration, scale};
9//! assert!((baker_percent(300.0, 500.0) - 60.0).abs() < 1e-9); // 300 g water / 500 g flour
10//! assert!((hydration(300.0, 500.0) - 60.0).abs() < 1e-9);
11//! assert!((scale(300.0, 500.0, 1000.0) - 600.0).abs() < 1e-9); // scale water to 1 kg flour
12//! ```
13
14/// Baker's percentage for an ingredient relative to flour weight (flour = 100%).
15pub fn baker_percent(ingredient_grams: f64, flour_grams: f64) -> f64 {
16 if flour_grams <= 0.0 { 0.0 } else { ingredient_grams / flour_grams * 100.0 }
17}
18
19/// Dough hydration = water weight / flour weight * 100 (baker's % of water).
20pub fn hydration(water_grams: f64, flour_grams: f64) -> f64 {
21 baker_percent(water_grams, flour_grams)
22}
23
24/// Scale an ingredient weight when flour changes from `from_flour` to `to_flour`.
25pub fn scale(ingredient_grams: f64, from_flour: f64, to_flour: f64) -> f64 {
26 if from_flour <= 0.0 { 0.0 } else { ingredient_grams * (to_flour / from_flour) }
27}
28
29/// Total dough weight = sum of ingredient weights (flour + water + salt + ...).
30pub fn dough_weight(ingredient_grams: &[f64]) -> f64 {
31 ingredient_grams.iter().sum()
32}
33
34#[cfg(test)]
35mod tests {
36 use super::*;
37 #[test]
38 fn baker_percent_basic() { assert!((baker_percent(300.0, 500.0) - 60.0).abs() < 1e-9); }
39 #[test]
40 fn flour_is_100() { assert!((baker_percent(500.0, 500.0) - 100.0).abs() < 1e-9); }
41 #[test]
42 fn salt_typical() {
43 // 10 g salt to 500 g flour = 2%
44 assert!((baker_percent(10.0, 500.0) - 2.0).abs() < 1e-9);
45 }
46 #[test]
47 fn scale_doubles() { assert!((scale(300.0, 500.0, 1000.0) - 600.0).abs() < 1e-9); }
48 #[test]
49 fn dough_weight_sums() { assert!((dough_weight(&[500.0, 300.0, 10.0]) - 810.0).abs() < 1e-9); }
50}