Sync your own workout data from your "Strong" app
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

added a data transformer which returns a good object to work with

+79 -7
+70
src/data_transformer.rs
··· 1 + use crate::user_response::CellSetGroup; 2 + 3 + #[derive(Debug)] 4 + pub struct Set { 5 + id: String, 6 + // We assume each exercise set may have a weight, number of reps, and optional RPE. 7 + weight: Option<f32>, 8 + reps: u32, 9 + rpe: Option<f32>, 10 + } 11 + 12 + #[derive(Debug)] 13 + pub struct Workout { 14 + id: String, 15 + sets: Vec<Set>, 16 + } 17 + 18 + 19 + pub trait DataTransformer { 20 + fn transform(&self, json_data: &CellSetGroup) -> Result<Workout, serde_json::Error>; 21 + } 22 + 23 + pub(crate) struct DataTransformerImpl; 24 + 25 + impl DataTransformer for DataTransformerImpl { 26 + fn transform(&self, raw_workout: &CellSetGroup) -> Result<Workout, serde_json::Error> { 27 + let mut exercises = Vec::new(); 28 + 29 + // Process each cell set. 30 + for cell_set in &raw_workout.cell_sets { 31 + if !(cell_set.cells.iter().any(|cell| cell.cell_type == "REST_TIMER" || cell.cell_type == "NOTE")) { 32 + let weight = cell_set 33 + .cells 34 + .iter() 35 + .find(|cell| 36 + cell.cell_type == "OTHER_WEIGHT" || 37 + cell.cell_type == "DUMBBELL_WEIGHT" || 38 + cell.cell_type == "BARBELL_WEIGHT" || 39 + cell.cell_type == "WEIGHTED_BODYWEIGHT" 40 + ) 41 + .and_then(|cell| cell.value.as_ref()) 42 + .and_then(|s| s.parse::<f32>().ok()); 43 + 44 + let reps = cell_set 45 + .cells 46 + .iter() 47 + .find(|cell| cell.cell_type == "REPS") 48 + .and_then(|cell| cell.value.as_ref()) 49 + .and_then(|s| s.parse::<u32>().ok()) 50 + .unwrap_or(0); 51 + 52 + let rpe = cell_set 53 + .cells 54 + .iter() 55 + .find(|cell| cell.cell_type == "RPE") 56 + .and_then(|cell| cell.value.as_ref()) 57 + .and_then(|s| s.parse::<f32>().ok()); 58 + 59 + let id = cell_set.id.clone(); 60 + 61 + exercises.push(Set { id, weight, reps, rpe }); 62 + } 63 + } 64 + 65 + Ok(Workout { 66 + id: raw_workout.clone().id, 67 + sets: exercises, 68 + }) 69 + } 70 + }
+9 -7
src/main.rs
··· 4 4 use serde::Deserialize; 5 5 use serde_json::Value::String; 6 6 use crate::strong_api::{Includes, StrongApi}; 7 + use crate::data_transformer::{DataTransformer, DataTransformerImpl}; 7 8 8 9 mod strong_api; 9 10 mod user_response; 11 + mod data_transformer; 10 12 11 13 #[tokio::main] 12 14 async fn main() -> Result<(), Box<dyn std::error::Error>> { ··· 34 36 ] 35 37 ).await?; 36 38 39 + 40 + 37 41 for log in &user.embedded.log { 38 42 if let Some(start_date) = &log.start_date { 39 43 print!("{}: ", start_date); ··· 45 49 46 50 println!("{}", display_name); 47 51 for cell_set_group in &log.embedded.cell_set_group { 48 - 49 - for cell_set in &cell_set_group.cell_sets { 52 + /*for cell_set in &cell_set_group.cell_sets { 50 53 for cell in &cell_set.cells { 51 - if (cell.cell_type == "OTHER_WEIGHT" || cell.cell_type == "REPS") { 52 - println!(" {}", cell_set.id); 53 - print!("{} - {:?}", cell.cell_type, cell.value); 54 - } 54 + print!("{} - {:?} | ", cell.cell_type, cell.value); 55 55 } 56 - } 56 + }*/ 57 + println!(); 58 + dbg!(DataTransformerImpl.transform(cell_set_group).expect("TODO: panic message")); 57 59 } 58 60 println!(); 59 61 }