Invert the TraxRecord #182
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2023, Savanni D'Gerinel <savanni@luminescent-dreams.com>
|
Copyright 2023-2024, Savanni D'Gerinel <savanni@luminescent-dreams.com>
|
||||||
|
|
||||||
This file is part of FitnessTrax.
|
This file is part of FitnessTrax.
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with Fit
|
||||||
// use crate::components::{EditView, ParseError, TextEntry};
|
// use crate::components::{EditView, ParseError, TextEntry};
|
||||||
// use chrono::{Local, NaiveDate};
|
// use chrono::{Local, NaiveDate};
|
||||||
// use dimensioned::si;
|
// use dimensioned::si;
|
||||||
use ft_core::{RecordType, TimeDistance};
|
use ft_core::TimeDistance;
|
||||||
use glib::Object;
|
use glib::Object;
|
||||||
use gtk::{prelude::*, subclass::prelude::*};
|
use gtk::{prelude::*, subclass::prelude::*};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
@ -44,7 +44,7 @@ glib::wrapper! {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TimeDistanceView {
|
impl TimeDistanceView {
|
||||||
pub fn new(type_: RecordType, record: TimeDistance) -> Self {
|
pub fn new(record: TimeDistance) -> Self {
|
||||||
let s: Self = Object::builder().build();
|
let s: Self = Object::builder().build();
|
||||||
s.set_orientation(gtk::Orientation::Vertical);
|
s.set_orientation(gtk::Orientation::Vertical);
|
||||||
s.set_hexpand(true);
|
s.set_hexpand(true);
|
||||||
|
@ -58,12 +58,14 @@ impl TimeDistanceView {
|
||||||
.build(),
|
.build(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
first_row.append(
|
first_row.append(
|
||||||
>k::Label::builder()
|
>k::Label::builder()
|
||||||
.halign(gtk::Align::Start)
|
.halign(gtk::Align::Start)
|
||||||
.label(format!("{:?}", type_))
|
.label(format!("{:?}", type_))
|
||||||
.build(),
|
.build(),
|
||||||
);
|
);
|
||||||
|
*/
|
||||||
|
|
||||||
first_row.append(
|
first_row.append(
|
||||||
>k::Label::builder()
|
>k::Label::builder()
|
||||||
|
|
|
@ -20,7 +20,7 @@ use crate::app::{ReadError, RecordProvider, WriteError};
|
||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use dimensioned::si;
|
use dimensioned::si;
|
||||||
use emseries::{Record, RecordId, Recordable};
|
use emseries::{Record, RecordId, Recordable};
|
||||||
use ft_core::{TimeDistance, TimeDistanceWorkoutType, TraxRecord};
|
use ft_core::{TimeDistance, TimeDistanceActivity, TraxRecord};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
ops::Deref,
|
ops::Deref,
|
||||||
|
@ -48,20 +48,34 @@ impl<T: Clone + emseries::Recordable> RecordState<T> {
|
||||||
|
|
||||||
fn exists(&self) -> bool {
|
fn exists(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
RecordState::Original(ref _r) => true,
|
RecordState::Original(_) => true,
|
||||||
RecordState::New(ref _r) => true,
|
RecordState::New(_) => true,
|
||||||
RecordState::Updated(ref _r) => true,
|
RecordState::Updated(_) => true,
|
||||||
RecordState::Deleted(ref _r) => false,
|
RecordState::Deleted(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_value(self, value: T) -> RecordState<T> {
|
fn set_value(&mut self, value: T) {
|
||||||
match self {
|
*self = match self {
|
||||||
RecordState::Original(r) => RecordState::Updated(Record { data: value, ..r }),
|
RecordState::Original(r) => RecordState::Updated(Record {
|
||||||
|
id: r.id.clone(),
|
||||||
|
data: value,
|
||||||
|
}),
|
||||||
RecordState::New(_) => RecordState::New(value),
|
RecordState::New(_) => RecordState::New(value),
|
||||||
RecordState::Updated(r) => RecordState::Updated(Record { data: value, ..r }),
|
RecordState::Updated(r) => RecordState::Updated(Record {
|
||||||
RecordState::Deleted(r) => RecordState::Updated(Record { data: value, ..r }),
|
id: r.id.clone(),
|
||||||
|
data: value,
|
||||||
|
}),
|
||||||
|
RecordState::Deleted(r) => RecordState::Updated(Record {
|
||||||
|
id: r.id.clone(),
|
||||||
|
data: value,
|
||||||
|
}),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn with_value(mut self, value: T) -> RecordState<T> {
|
||||||
|
self.set_value(value);
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
@ -197,15 +211,16 @@ impl DayDetailViewModel {
|
||||||
*record = Some(new_record);
|
*record = Some(new_record);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_time_distance(&self, type_: TimeDistanceWorkoutType) -> Record<TimeDistance> {
|
pub fn new_time_distance(&self, activity: TimeDistanceActivity) -> Record<TimeDistance> {
|
||||||
let id = RecordId::default();
|
let id = RecordId::default();
|
||||||
let workout = TimeDistance {
|
let workout = TimeDistance {
|
||||||
datetime: chrono::Local::now().into(),
|
datetime: chrono::Local::now().into(),
|
||||||
|
activity,
|
||||||
distance: None,
|
distance: None,
|
||||||
duration: None,
|
duration: None,
|
||||||
comments: None,
|
comments: None,
|
||||||
};
|
};
|
||||||
let tr = TraxRecord::from_time_distance(type_, workout.clone());
|
let tr = TraxRecord::from(workout.clone());
|
||||||
self.records
|
self.records
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -222,44 +237,19 @@ impl DayDetailViewModel {
|
||||||
let data = workout.data.clone();
|
let data = workout.data.clone();
|
||||||
|
|
||||||
let mut record_set = self.records.write().unwrap();
|
let mut record_set = self.records.write().unwrap();
|
||||||
if let Some(record_state) = record_set.get(&id) {
|
record_set.entry(id).and_modify(|record_state| {
|
||||||
let updated_state = match **record_state {
|
record_state.set_value(TraxRecord::TimeDistance(data));
|
||||||
TraxRecord::BikeRide(_) => {
|
});
|
||||||
Some(record_state.clone().with_value(TraxRecord::BikeRide(data)))
|
|
||||||
}
|
|
||||||
TraxRecord::Row(_) => Some(record_state.clone().with_value(TraxRecord::Row(data))),
|
|
||||||
TraxRecord::Run(_) => Some(record_state.clone().with_value(TraxRecord::Run(data))),
|
|
||||||
TraxRecord::Swim(_) => {
|
|
||||||
Some(record_state.clone().with_value(TraxRecord::Swim(data)))
|
|
||||||
}
|
|
||||||
TraxRecord::Walk(_) => {
|
|
||||||
Some(record_state.clone().with_value(TraxRecord::Walk(data)))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(updated_state) = updated_state {
|
|
||||||
record_set.insert(id, updated_state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn time_distance_records(
|
pub fn time_distance_records(&self) -> Vec<Record<TimeDistance>> {
|
||||||
&self,
|
|
||||||
type_: TimeDistanceWorkoutType,
|
|
||||||
) -> Vec<Record<TimeDistance>> {
|
|
||||||
self.records
|
self.records
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, record)| record.exists())
|
.filter(|(_, record)| record.exists())
|
||||||
.filter(|(_, workout_state)| workout_state.is_time_distance_type(type_))
|
|
||||||
.filter_map(|(id, record_state)| match **record_state {
|
.filter_map(|(id, record_state)| match **record_state {
|
||||||
TraxRecord::BikeRide(ref workout)
|
TraxRecord::TimeDistance(ref workout) => Some(Record {
|
||||||
| TraxRecord::Row(ref workout)
|
|
||||||
| TraxRecord::Run(ref workout)
|
|
||||||
| TraxRecord::Swim(ref workout)
|
|
||||||
| TraxRecord::Walk(ref workout) => Some(Record {
|
|
||||||
id: id.clone(),
|
id: id.clone(),
|
||||||
data: workout.clone(),
|
data: workout.clone(),
|
||||||
}),
|
}),
|
||||||
|
@ -270,12 +260,18 @@ impl DayDetailViewModel {
|
||||||
|
|
||||||
pub fn time_distance_summary(
|
pub fn time_distance_summary(
|
||||||
&self,
|
&self,
|
||||||
type_: TimeDistanceWorkoutType,
|
activity: TimeDistanceActivity,
|
||||||
) -> (si::Meter<f64>, si::Second<f64>) {
|
) -> (si::Meter<f64>, si::Second<f64>) {
|
||||||
self.time_distance_records(type_).into_iter().fold(
|
self.time_distance_records()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|rec| rec.data.activity == activity)
|
||||||
|
.fold(
|
||||||
(0. * si::M, 0. * si::S),
|
(0. * si::M, 0. * si::S),
|
||||||
|(distance, duration), workout| match (workout.data.distance, workout.data.duration) {
|
|(distance, duration), workout| match (workout.data.distance, workout.data.duration)
|
||||||
(Some(distance_), Some(duration_)) => (distance + distance_, duration + duration_),
|
{
|
||||||
|
(Some(distance_), Some(duration_)) => {
|
||||||
|
(distance + distance_, duration + duration_)
|
||||||
|
}
|
||||||
(Some(distance_), None) => (distance + distance_, duration),
|
(Some(distance_), None) => (distance + distance_, duration),
|
||||||
(None, Some(duration_)) => (distance, duration + duration_),
|
(None, Some(duration_)) => (distance, duration + duration_),
|
||||||
(None, None) => (distance, duration),
|
(None, None) => (distance, duration),
|
||||||
|
@ -506,8 +502,9 @@ mod test {
|
||||||
},
|
},
|
||||||
Record {
|
Record {
|
||||||
id: RecordId::default(),
|
id: RecordId::default(),
|
||||||
data: TraxRecord::BikeRide(ft_core::TimeDistance {
|
data: TraxRecord::TimeDistance(ft_core::TimeDistance {
|
||||||
datetime: oct_13_am,
|
datetime: oct_13_am.clone(),
|
||||||
|
activity: TimeDistanceActivity::BikeRide,
|
||||||
distance: Some(15000. * si::M),
|
distance: Some(15000. * si::M),
|
||||||
duration: Some(3600. * si::S),
|
duration: Some(3600. * si::S),
|
||||||
comments: Some("somecomments present".to_owned()),
|
comments: Some("somecomments present".to_owned()),
|
||||||
|
@ -557,11 +554,11 @@ mod test {
|
||||||
async fn it_can_construct_new_records() {
|
async fn it_can_construct_new_records() {
|
||||||
let (view_model, provider) = create_empty_view_model().await;
|
let (view_model, provider) = create_empty_view_model().await;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
view_model.time_distance_summary(TimeDistanceWorkoutType::BikeRide),
|
view_model.time_distance_summary(TimeDistanceActivity::BikeRide),
|
||||||
(0. * si::M, 0. * si::S)
|
(0. * si::M, 0. * si::S)
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut record = view_model.new_time_distance(TimeDistanceWorkoutType::BikeRide);
|
let mut record = view_model.new_time_distance(TimeDistanceActivity::BikeRide);
|
||||||
record.data.duration = Some(60. * si::S);
|
record.data.duration = Some(60. * si::S);
|
||||||
view_model.async_save().await;
|
view_model.async_save().await;
|
||||||
|
|
||||||
|
@ -574,24 +571,24 @@ mod test {
|
||||||
async fn it_can_update_a_new_record_before_saving() {
|
async fn it_can_update_a_new_record_before_saving() {
|
||||||
let (view_model, provider) = create_empty_view_model().await;
|
let (view_model, provider) = create_empty_view_model().await;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
view_model.time_distance_summary(TimeDistanceWorkoutType::BikeRide),
|
view_model.time_distance_summary(TimeDistanceActivity::BikeRide),
|
||||||
(0. * si::M, 0. * si::S)
|
(0. * si::M, 0. * si::S)
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut record = view_model.new_time_distance(TimeDistanceWorkoutType::BikeRide);
|
let mut record = view_model.new_time_distance(TimeDistanceActivity::BikeRide);
|
||||||
record.data.duration = Some(60. * si::S);
|
record.data.duration = Some(60. * si::S);
|
||||||
view_model.update_time_distance(record.clone());
|
view_model.update_time_distance(record.clone());
|
||||||
let record = Record {
|
let record = Record {
|
||||||
id: record.id,
|
id: record.id,
|
||||||
data: TraxRecord::BikeRide(record.data),
|
data: TraxRecord::TimeDistance(record.data),
|
||||||
};
|
};
|
||||||
assert_eq!(view_model.get_record(&record.id), Some(record));
|
assert_eq!(view_model.get_record(&record.id), Some(record));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
view_model.time_distance_summary(TimeDistanceWorkoutType::BikeRide),
|
view_model.time_distance_summary(TimeDistanceActivity::BikeRide),
|
||||||
(0. * si::M, 60. * si::S)
|
(0. * si::M, 60. * si::S)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
view_model.time_distance_summary(TimeDistanceWorkoutType::Run),
|
view_model.time_distance_summary(TimeDistanceActivity::Running),
|
||||||
(0. * si::M, 0. * si::S)
|
(0. * si::M, 0. * si::S)
|
||||||
);
|
);
|
||||||
view_model.async_save().await;
|
view_model.async_save().await;
|
||||||
|
@ -604,11 +601,7 @@ mod test {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn it_can_update_an_existing_record() {
|
async fn it_can_update_an_existing_record() {
|
||||||
let (view_model, provider) = create_view_model().await;
|
let (view_model, provider) = create_view_model().await;
|
||||||
let mut workout = view_model
|
let mut workout = view_model.time_distance_records().first().cloned().unwrap();
|
||||||
.time_distance_records(TimeDistanceWorkoutType::BikeRide)
|
|
||||||
.first()
|
|
||||||
.cloned()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
println!("found record: {:?}", workout);
|
println!("found record: {:?}", workout);
|
||||||
|
|
||||||
|
@ -616,7 +609,7 @@ mod test {
|
||||||
view_model.update_time_distance(workout.clone());
|
view_model.update_time_distance(workout.clone());
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
view_model.time_distance_summary(TimeDistanceWorkoutType::BikeRide),
|
view_model.time_distance_summary(TimeDistanceActivity::BikeRide),
|
||||||
(15000. * si::M, 1800. * si::S)
|
(15000. * si::M, 1800. * si::S)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -631,11 +624,11 @@ mod test {
|
||||||
async fn it_can_remove_a_new_record() {
|
async fn it_can_remove_a_new_record() {
|
||||||
let (view_model, provider) = create_empty_view_model().await;
|
let (view_model, provider) = create_empty_view_model().await;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
view_model.time_distance_summary(TimeDistanceWorkoutType::BikeRide),
|
view_model.time_distance_summary(TimeDistanceActivity::BikeRide),
|
||||||
(0. * si::M, 0. * si::S)
|
(0. * si::M, 0. * si::S)
|
||||||
);
|
);
|
||||||
|
|
||||||
let record = view_model.new_time_distance(TimeDistanceWorkoutType::BikeRide);
|
let record = view_model.new_time_distance(TimeDistanceActivity::BikeRide);
|
||||||
view_model.remove_record(record.id);
|
view_model.remove_record(record.id);
|
||||||
view_model.save();
|
view_model.save();
|
||||||
|
|
||||||
|
@ -647,15 +640,11 @@ mod test {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn it_can_delete_an_existing_record() {
|
async fn it_can_delete_an_existing_record() {
|
||||||
let (view_model, provider) = create_view_model().await;
|
let (view_model, provider) = create_view_model().await;
|
||||||
let workout = view_model
|
let mut workout = view_model.time_distance_records().first().cloned().unwrap();
|
||||||
.time_distance_records(TimeDistanceWorkoutType::BikeRide)
|
|
||||||
.first()
|
|
||||||
.cloned()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
view_model.remove_record(workout.id);
|
view_model.remove_record(workout.id);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
view_model.time_distance_summary(TimeDistanceWorkoutType::BikeRide),
|
view_model.time_distance_summary(TimeDistanceActivity::BikeRide),
|
||||||
(0. * si::M, 0. * si::S)
|
(0. * si::M, 0. * si::S)
|
||||||
);
|
);
|
||||||
view_model.async_save().await;
|
view_model.async_save().await;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
mod legacy;
|
mod legacy;
|
||||||
|
|
||||||
mod types;
|
mod types;
|
||||||
pub use types::{RecordType, Steps, TimeDistance, TimeDistanceWorkoutType, TraxRecord, Weight};
|
pub use types::{Steps, TimeDistance, TimeDistanceActivity, TraxRecord, Weight};
|
||||||
|
|
|
@ -33,6 +33,15 @@ impl Recordable for Steps {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub enum TimeDistanceActivity {
|
||||||
|
BikeRide,
|
||||||
|
Running,
|
||||||
|
Rowing,
|
||||||
|
Swimming,
|
||||||
|
Walking,
|
||||||
|
}
|
||||||
|
|
||||||
/// TimeDistance represents workouts characterized by a duration and a distance travelled. These
|
/// TimeDistance represents workouts characterized by a duration and a distance travelled. These
|
||||||
/// sorts of workouts can occur many times a day, depending on how one records things. I might
|
/// sorts of workouts can occur many times a day, depending on how one records things. I might
|
||||||
/// record a single 30-km workout if I go on a long-distanec ride. Or I might record multiple 5km
|
/// record a single 30-km workout if I go on a long-distanec ride. Or I might record multiple 5km
|
||||||
|
@ -48,6 +57,8 @@ pub struct TimeDistance {
|
||||||
/// in the database, but we can still get a Naive Date from the DateTime, which will still read
|
/// in the database, but we can still get a Naive Date from the DateTime, which will still read
|
||||||
/// as the original day.
|
/// as the original day.
|
||||||
pub datetime: DateTime<FixedOffset>,
|
pub datetime: DateTime<FixedOffset>,
|
||||||
|
/// The activity
|
||||||
|
pub activity: TimeDistanceActivity,
|
||||||
/// The distance travelled. This is optional because such a workout makes sense even without
|
/// The distance travelled. This is optional because such a workout makes sense even without
|
||||||
/// the distance.
|
/// the distance.
|
||||||
pub distance: Option<si::Meter<f64>>,
|
pub distance: Option<si::Meter<f64>>,
|
||||||
|
@ -85,61 +96,15 @@ impl Recordable for Weight {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
|
||||||
pub enum RecordType {
|
|
||||||
BikeRide,
|
|
||||||
Row,
|
|
||||||
Run,
|
|
||||||
Steps,
|
|
||||||
Swim,
|
|
||||||
Walk,
|
|
||||||
Weight,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
||||||
pub enum TimeDistanceWorkoutType {
|
|
||||||
BikeRide,
|
|
||||||
Row,
|
|
||||||
Run,
|
|
||||||
Swim,
|
|
||||||
Walk,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The unified data structure for all records that are part of the app.
|
/// The unified data structure for all records that are part of the app.
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum TraxRecord {
|
pub enum TraxRecord {
|
||||||
BikeRide(TimeDistance),
|
TimeDistance(TimeDistance),
|
||||||
Row(TimeDistance),
|
|
||||||
Run(TimeDistance),
|
|
||||||
Steps(Steps),
|
Steps(Steps),
|
||||||
Swim(TimeDistance),
|
|
||||||
Walk(TimeDistance),
|
|
||||||
Weight(Weight),
|
Weight(Weight),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TraxRecord {
|
impl TraxRecord {
|
||||||
pub fn from_time_distance(type_: TimeDistanceWorkoutType, workout: TimeDistance) -> Self {
|
|
||||||
match type_ {
|
|
||||||
TimeDistanceWorkoutType::BikeRide => Self::BikeRide(workout),
|
|
||||||
TimeDistanceWorkoutType::Run => Self::Run(workout),
|
|
||||||
TimeDistanceWorkoutType::Row => Self::Row(workout),
|
|
||||||
TimeDistanceWorkoutType::Swim => Self::Swim(workout),
|
|
||||||
TimeDistanceWorkoutType::Walk => Self::Walk(workout),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn workout_type(&self) -> RecordType {
|
|
||||||
match self {
|
|
||||||
TraxRecord::BikeRide(_) => RecordType::BikeRide,
|
|
||||||
TraxRecord::Row(_) => RecordType::Row,
|
|
||||||
TraxRecord::Run(_) => RecordType::Run,
|
|
||||||
TraxRecord::Steps(_) => RecordType::Steps,
|
|
||||||
TraxRecord::Swim(_) => RecordType::Swim,
|
|
||||||
TraxRecord::Walk(_) => RecordType::Walk,
|
|
||||||
TraxRecord::Weight(_) => RecordType::Weight,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_weight(&self) -> bool {
|
pub fn is_weight(&self) -> bool {
|
||||||
matches!(self, TraxRecord::Weight(_))
|
matches!(self, TraxRecord::Weight(_))
|
||||||
}
|
}
|
||||||
|
@ -151,15 +116,27 @@ impl TraxRecord {
|
||||||
pub fn is_time_distance(&self) -> bool {
|
pub fn is_time_distance(&self) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
self,
|
self,
|
||||||
TraxRecord::BikeRide(_)
|
TraxRecord::TimeDistance(TimeDistance {
|
||||||
| TraxRecord::Row(_)
|
activity: TimeDistanceActivity::BikeRide,
|
||||||
| TraxRecord::Run(_)
|
..
|
||||||
| TraxRecord::Swim(_)
|
}) | TraxRecord::TimeDistance(TimeDistance {
|
||||||
| TraxRecord::Walk(_)
|
activity: TimeDistanceActivity::Running,
|
||||||
|
..
|
||||||
|
}) | TraxRecord::TimeDistance(TimeDistance {
|
||||||
|
activity: TimeDistanceActivity::Rowing,
|
||||||
|
..
|
||||||
|
}) | TraxRecord::TimeDistance(TimeDistance {
|
||||||
|
activity: TimeDistanceActivity::Swimming,
|
||||||
|
..
|
||||||
|
}) | TraxRecord::TimeDistance(TimeDistance {
|
||||||
|
activity: TimeDistanceActivity::Walking,
|
||||||
|
..
|
||||||
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_time_distance_type(&self, type_: TimeDistanceWorkoutType) -> bool {
|
/*
|
||||||
|
pub fn is_time_distance_type(&self, type_: TimeDistanceActivity) -> bool {
|
||||||
match type_ {
|
match type_ {
|
||||||
TimeDistanceWorkoutType::BikeRide => matches!(self, TraxRecord::BikeRide(_)),
|
TimeDistanceWorkoutType::BikeRide => matches!(self, TraxRecord::BikeRide(_)),
|
||||||
TimeDistanceWorkoutType::Row => matches!(self, TraxRecord::Row(_)),
|
TimeDistanceWorkoutType::Row => matches!(self, TraxRecord::Row(_)),
|
||||||
|
@ -168,17 +145,14 @@ impl TraxRecord {
|
||||||
TimeDistanceWorkoutType::Walk => matches!(self, TraxRecord::Walk(_)),
|
TimeDistanceWorkoutType::Walk => matches!(self, TraxRecord::Walk(_)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Recordable for TraxRecord {
|
impl Recordable for TraxRecord {
|
||||||
fn timestamp(&self) -> Timestamp {
|
fn timestamp(&self) -> Timestamp {
|
||||||
match self {
|
match self {
|
||||||
TraxRecord::BikeRide(rec) => Timestamp::DateTime(rec.datetime),
|
TraxRecord::TimeDistance(rec) => Timestamp::DateTime(rec.datetime),
|
||||||
TraxRecord::Row(rec) => Timestamp::DateTime(rec.datetime),
|
|
||||||
TraxRecord::Run(rec) => Timestamp::DateTime(rec.datetime),
|
|
||||||
TraxRecord::Steps(rec) => rec.timestamp(),
|
TraxRecord::Steps(rec) => rec.timestamp(),
|
||||||
TraxRecord::Swim(rec) => Timestamp::DateTime(rec.datetime),
|
|
||||||
TraxRecord::Walk(rec) => Timestamp::DateTime(rec.datetime),
|
|
||||||
TraxRecord::Weight(rec) => rec.timestamp(),
|
TraxRecord::Weight(rec) => rec.timestamp(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,6 +162,12 @@ impl Recordable for TraxRecord {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<TimeDistance> for TraxRecord {
|
||||||
|
fn from(td: TimeDistance) -> Self {
|
||||||
|
Self::TimeDistance(td)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
Loading…
Reference in New Issue