Skip to content

Commit 30aa7a3

Browse files
committed
fix: metadata servings scale
1 parent dd9a84c commit 30aa7a3

2 files changed

Lines changed: 113 additions & 3 deletions

File tree

src/scale.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ impl ScaleTarget {
2323
/// Creates a new [`ScaleTarget`].
2424
///
2525
/// - `factor` is the multiplier to scale the recipe by.
26-
/// Invalid parameters don't error here, but may do so in the
27-
/// scaling process.
26+
/// Invalid parameters don't error here, but may do so in the
27+
/// scaling process.
2828
fn new(factor: f64) -> Self {
2929
ScaleTarget { factor }
3030
}
@@ -150,8 +150,25 @@ impl ScalableRecipe {
150150
timers: timer_outcomes,
151151
};
152152

153+
// Update metadata with new servings
154+
let mut metadata = self.metadata;
155+
if let Servings(Some(servings)) = &self.data {
156+
if let Some(base_servings) = servings.first() {
157+
let new_servings = (*base_servings as f64 * factor).round() as u32;
158+
if metadata.get(crate::metadata::StdKey::Servings).is_some() {
159+
// Update existing servings value
160+
if let Some(servings_value) =
161+
metadata.get_mut(crate::metadata::StdKey::Servings)
162+
{
163+
*servings_value =
164+
serde_yaml::Value::Number(serde_yaml::Number::from(new_servings));
165+
}
166+
}
167+
}
168+
}
169+
153170
ScaledRecipe {
154-
metadata: self.metadata,
171+
metadata,
155172
sections: self.sections,
156173
ingredients,
157174
cookware,

tests/scale.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
use cooklang::{Converter, CooklangParser, Extensions};
2+
3+
#[test]
4+
fn test_scale_updates_servings_metadata() {
5+
let input = r#">> servings: 4
6+
7+
@flour{200%g}
8+
@eggs{2}
9+
Mix and bake."#;
10+
11+
let parser = CooklangParser::new(Extensions::all(), Converter::default());
12+
let recipe = parser.parse(input).unwrap_output();
13+
14+
// Check original servings
15+
assert_eq!(recipe.servings(), Some(&[4][..]));
16+
let orig_servings_value = recipe
17+
.metadata
18+
.get(cooklang::metadata::StdKey::Servings)
19+
.unwrap();
20+
assert_eq!(orig_servings_value.as_str(), Some("4"));
21+
22+
// Scale to 8 servings (2x)
23+
let scaled = recipe.scale_to_servings(8, &Converter::default());
24+
25+
// Check that servings in metadata were updated
26+
let scaled_servings_value = scaled
27+
.metadata
28+
.get(cooklang::metadata::StdKey::Servings)
29+
.unwrap();
30+
assert_eq!(scaled_servings_value.as_u64(), Some(8));
31+
}
32+
33+
#[test]
34+
fn test_scale_by_factor_updates_servings_metadata() {
35+
let input = r#">> servings: 2
36+
37+
@butter{100%g}
38+
@sugar{50%g}"#;
39+
40+
let parser = CooklangParser::new(Extensions::all(), Converter::default());
41+
let recipe = parser.parse(input).unwrap_output();
42+
43+
// Scale by factor of 3
44+
let scaled = recipe.scale(3.0, &Converter::default());
45+
46+
// Check that servings in metadata were updated (2 * 3 = 6)
47+
let scaled_servings_value = scaled
48+
.metadata
49+
.get(cooklang::metadata::StdKey::Servings)
50+
.unwrap();
51+
assert_eq!(scaled_servings_value.as_u64(), Some(6));
52+
}
53+
54+
#[test]
55+
fn test_scale_without_servings_metadata() {
56+
// Recipe without servings metadata
57+
let input = r#"@flour{200%g}
58+
@eggs{2}"#;
59+
60+
let parser = CooklangParser::new(Extensions::all(), Converter::default());
61+
let recipe = parser.parse(input).unwrap_output();
62+
63+
// Should not have servings
64+
assert_eq!(recipe.servings(), None);
65+
66+
// Scale by factor of 2
67+
let scaled = recipe.scale(2.0, &Converter::default());
68+
69+
// Should still not have servings in metadata
70+
assert!(scaled
71+
.metadata
72+
.get(cooklang::metadata::StdKey::Servings)
73+
.is_none());
74+
}
75+
76+
#[test]
77+
fn test_scale_with_fractional_servings() {
78+
let input = r#">> servings: 3
79+
80+
@milk{300%ml}"#;
81+
82+
let parser = CooklangParser::new(Extensions::all(), Converter::default());
83+
let recipe = parser.parse(input).unwrap_output();
84+
85+
// Scale by factor that results in fractional servings (3 * 1.5 = 4.5, should round to 5)
86+
let scaled = recipe.scale(1.5, &Converter::default());
87+
88+
let scaled_servings_value = scaled
89+
.metadata
90+
.get(cooklang::metadata::StdKey::Servings)
91+
.unwrap();
92+
assert_eq!(scaled_servings_value.as_u64(), Some(5));
93+
}

0 commit comments

Comments
 (0)