mathhook_core/educational/
enhanced_steps.rs

1//! Enhanced steps with human messages and structured API data
2//!
3//! Provides both human-readable educational content and machine-consumable
4//! structured data for external applications.
5
6mod formatting;
7mod generation;
8
9pub use formatting::{
10    EnhancedStepExplanation, ExplanationMetadata, ExplanationSummary, FormatContext,
11    PresentationHints,
12};
13
14pub use generation::{
15    DifficultyLevel, EducationalResult, EnhancedStep, EnhancedStepBuilder, EnhancedStepFactory,
16    MathContext, MessageKey, SmartStep, SmartStepBuilder, SmartStepFactory, StepApiData,
17    StepFactory,
18};
19
20pub type SmartStepExplanation = EnhancedStepExplanation;
21
22#[cfg(test)]
23mod tests {
24    use super::*;
25    use crate::{symbol, Expression};
26
27    #[test]
28    fn test_smart_step_creation() {
29        let x = symbol!(x);
30        let equation = Expression::add(vec![Expression::symbol(x.clone()), Expression::integer(2)]);
31
32        let step = SmartStepFactory::linear_introduction(&equation, &x);
33
34        assert!(step.human_message.contains("2 + x"));
35        assert!(step.human_message.contains("linear equation"));
36
37        assert_eq!(step.api_data.category, "linear_equation");
38        assert_eq!(step.api_data.step_type, "introduction");
39        assert!(step.api_data.inputs.contains_key("variable"));
40
41        assert_eq!(step.message_key.category, "linear");
42        assert_eq!(step.message_key.message_type, "introduction");
43    }
44
45    #[test]
46    fn test_json_export() {
47        let x = symbol!(x);
48        let equation = Expression::add(vec![Expression::symbol(x.clone()), Expression::integer(2)]);
49
50        let steps = vec![
51            SmartStepFactory::linear_introduction(&equation, &x),
52            SmartStepFactory::linear_strategy(&x),
53        ];
54
55        let explanation = SmartStepExplanation::new(steps);
56        let json = explanation.to_json().unwrap();
57
58        assert!(json.contains("human_message"));
59        assert!(json.contains("api_data"));
60        assert!(json.contains("message_key"));
61        assert!(json.contains("math_context"));
62    }
63
64    #[test]
65    fn test_api_data_extraction() {
66        let x = symbol!(x);
67        let steps = vec![SmartStepFactory::linear_strategy(&x)];
68        let explanation = SmartStepExplanation::new(steps);
69
70        let api_data = explanation.to_api_data();
71
72        assert!(api_data.contains_key("metadata"));
73        assert!(api_data.contains_key("summary"));
74        assert!(api_data.contains_key("steps"));
75    }
76
77    #[test]
78    fn test_legacy_compatibility() {
79        let x = symbol!(x);
80        let equation = Expression::integer(0);
81        let smart_step = EnhancedStepFactory::linear_introduction(&equation, &x);
82
83        let legacy_step: crate::educational::step_by_step::Step = smart_step.into();
84        assert!(!legacy_step.title.is_empty());
85        assert!(!legacy_step.description.is_empty());
86    }
87}