syntax-workout-core 0.2.0

Workout tree algebra — represent any physical workout as a recursive tree
Documentation
use serde::{Deserialize, Serialize};
use ts_rs::TS;

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)]
#[ts(export, export_to = "../../../bindings/napi/generated/")]
pub enum WeightUnit {
    Kg,
    Lbs,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)]
#[ts(export, export_to = "../../../bindings/napi/generated/")]
pub enum DistanceUnit {
    Meters,
    Kilometers,
    Miles,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)]
#[ts(export, export_to = "../../../bindings/napi/generated/")]
#[serde(tag = "type", content = "value")]
pub enum Measure {
    Reps(u32),
    Weight { amount: f64, unit: WeightUnit },
    Distance { amount: f64, unit: DistanceUnit },
    Duration { seconds: f64 },
    Pace { per: DistanceUnit, seconds: f64 },
    HeartRate { bpm: u32 },
    Calories(u32),
    Custom { name: String, value: serde_json::Value },
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn reps_round_trip() {
        let m = Measure::Reps(10);
        let json = serde_json::to_string(&m).unwrap();
        assert_eq!(json, r#"{"type":"Reps","value":10}"#);
        let back: Measure = serde_json::from_str(&json).unwrap();
        assert_eq!(back, m);
    }

    #[test]
    fn weight_round_trip() {
        let m = Measure::Weight { amount: 80.0, unit: WeightUnit::Kg };
        let json = serde_json::to_string(&m).unwrap();
        let back: Measure = serde_json::from_str(&json).unwrap();
        assert_eq!(back, m);
        assert!(json.contains(r#""type":"Weight""#));
        assert!(json.contains(r#""unit":"Kg""#));
    }

    #[test]
    fn distance_round_trip() {
        let m = Measure::Distance { amount: 5.0, unit: DistanceUnit::Kilometers };
        let json = serde_json::to_string(&m).unwrap();
        let back: Measure = serde_json::from_str(&json).unwrap();
        assert_eq!(back, m);
    }

    #[test]
    fn duration_round_trip() {
        let m = Measure::Duration { seconds: 180.0 };
        let json = serde_json::to_string(&m).unwrap();
        let back: Measure = serde_json::from_str(&json).unwrap();
        assert_eq!(back, m);
    }

    #[test]
    fn pace_round_trip() {
        let m = Measure::Pace { per: DistanceUnit::Kilometers, seconds: 330.0 };
        let json = serde_json::to_string(&m).unwrap();
        let back: Measure = serde_json::from_str(&json).unwrap();
        assert_eq!(back, m);
    }

    #[test]
    fn custom_measure_round_trip() {
        let m = Measure::Custom {
            name: "elevation".into(),
            value: serde_json::json!(150),
        };
        let json = serde_json::to_string(&m).unwrap();
        let back: Measure = serde_json::from_str(&json).unwrap();
        assert_eq!(back, m);
    }
}