Compare commits
No commits in common. "b9aa434278c7e94484dbace3de9c43b180d255ba" and "7abb33c4feaf9b8c05c8dec08bbac648df891404" have entirely different histories.
b9aa434278
...
7abb33c4fe
|
@ -756,18 +756,6 @@ dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "dimensioned"
|
|
||||||
version = "0.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a0b0a86c5d31c93238ff4b694fa31f3acdf67440770dc314c57d90e433914397"
|
|
||||||
dependencies = [
|
|
||||||
"generic-array 0.14.7",
|
|
||||||
"num-traits",
|
|
||||||
"serde 1.0.188",
|
|
||||||
"typenum",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "displaydoc"
|
name = "displaydoc"
|
||||||
version = "0.2.4"
|
version = "0.2.4"
|
||||||
|
@ -819,7 +807,7 @@ version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"chrono-tz",
|
"chrono-tz",
|
||||||
"dimensioned 0.7.0",
|
"dimensioned",
|
||||||
"serde 1.0.188",
|
"serde 1.0.188",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -972,18 +960,6 @@ version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6"
|
checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fitnesstrax"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"gio",
|
|
||||||
"glib",
|
|
||||||
"glib-build-tools 0.18.0",
|
|
||||||
"gtk4",
|
|
||||||
"libadwaita",
|
|
||||||
"tokio",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.0.27"
|
version = "1.0.27"
|
||||||
|
@ -1128,18 +1104,6 @@ dependencies = [
|
||||||
"syn 2.0.37",
|
"syn 2.0.37",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ft-core"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"chrono",
|
|
||||||
"chrono-tz",
|
|
||||||
"dimensioned 0.8.0",
|
|
||||||
"emseries",
|
|
||||||
"serde 1.0.188",
|
|
||||||
"tempfile",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fuchsia-cprng"
|
name = "fuchsia-cprng"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
|
|
@ -10,8 +10,6 @@ members = [
|
||||||
"dashboard",
|
"dashboard",
|
||||||
"emseries",
|
"emseries",
|
||||||
"file-service",
|
"file-service",
|
||||||
"fitnesstrax/core",
|
|
||||||
"fitnesstrax/app",
|
|
||||||
"fluent-ergonomics",
|
"fluent-ergonomics",
|
||||||
"geo-types",
|
"geo-types",
|
||||||
"gm-control-panel",
|
"gm-control-panel",
|
||||||
|
|
1
build.sh
1
build.sh
|
@ -11,7 +11,6 @@ RUST_ALL_TARGETS=(
|
||||||
"dashboard"
|
"dashboard"
|
||||||
"emseries"
|
"emseries"
|
||||||
"file-service"
|
"file-service"
|
||||||
"fitnesstrax"
|
|
||||||
"fluent-ergonomics"
|
"fluent-ergonomics"
|
||||||
"geo-types"
|
"geo-types"
|
||||||
"gm-control-panel"
|
"gm-control-panel"
|
||||||
|
|
|
@ -42,7 +42,7 @@ where
|
||||||
{
|
{
|
||||||
/// Open a time series database at the specified path. `path` is the full path and filename for
|
/// Open a time series database at the specified path. `path` is the full path and filename for
|
||||||
/// the database.
|
/// the database.
|
||||||
pub fn open<P: AsRef<std::path::Path>>(path: P) -> Result<Series<T>, EmseriesReadError> {
|
pub fn open(path: &str) -> Result<Series<T>, EmseriesReadError> {
|
||||||
let f = OpenOptions::new()
|
let f = OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
.append(true)
|
.append(true)
|
||||||
|
|
|
@ -99,8 +99,8 @@ mod test {
|
||||||
{
|
{
|
||||||
let tmp_file = tempfile::NamedTempFile::new().expect("temporary path created");
|
let tmp_file = tempfile::NamedTempFile::new().expect("temporary path created");
|
||||||
let tmp_path = tmp_file.into_temp_path();
|
let tmp_path = tmp_file.into_temp_path();
|
||||||
let ts: Series<BikeTrip> =
|
let ts: Series<BikeTrip> = Series::open(&tmp_path.to_string_lossy())
|
||||||
Series::open(&tmp_path).expect("the time series should open correctly");
|
.expect("the time series should open correctly");
|
||||||
test(ts);
|
test(ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,8 +136,8 @@ mod test {
|
||||||
pub fn can_search_for_an_entry_with_exact_time() {
|
pub fn can_search_for_an_entry_with_exact_time() {
|
||||||
run_test(|path| {
|
run_test(|path| {
|
||||||
let trips = mk_trips();
|
let trips = mk_trips();
|
||||||
let mut ts: Series<BikeTrip> =
|
let mut ts: Series<BikeTrip> = Series::open(&path.to_string_lossy())
|
||||||
Series::open(&path).expect("expect the time series to open correctly");
|
.expect("expect the time series to open correctly");
|
||||||
|
|
||||||
for trip in &trips[0..=4] {
|
for trip in &trips[0..=4] {
|
||||||
ts.put(trip.clone()).expect("expect a successful put");
|
ts.put(trip.clone()).expect("expect a successful put");
|
||||||
|
@ -157,8 +157,8 @@ mod test {
|
||||||
pub fn can_get_entries_in_time_range() {
|
pub fn can_get_entries_in_time_range() {
|
||||||
run_test(|path| {
|
run_test(|path| {
|
||||||
let trips = mk_trips();
|
let trips = mk_trips();
|
||||||
let mut ts: Series<BikeTrip> =
|
let mut ts: Series<BikeTrip> = Series::open(&path.to_string_lossy())
|
||||||
Series::open(&path).expect("expect the time series to open correctly");
|
.expect("expect the time series to open correctly");
|
||||||
|
|
||||||
for trip in &trips[0..=4] {
|
for trip in &trips[0..=4] {
|
||||||
ts.put(trip.clone()).expect("expect a successful put");
|
ts.put(trip.clone()).expect("expect a successful put");
|
||||||
|
@ -186,8 +186,8 @@ mod test {
|
||||||
let trips = mk_trips();
|
let trips = mk_trips();
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut ts: Series<BikeTrip> =
|
let mut ts: Series<BikeTrip> = Series::open(&path.to_string_lossy())
|
||||||
Series::open(&path).expect("expect the time series to open correctly");
|
.expect("expect the time series to open correctly");
|
||||||
|
|
||||||
for trip in &trips[0..=4] {
|
for trip in &trips[0..=4] {
|
||||||
ts.put(trip.clone()).expect("expect a successful put");
|
ts.put(trip.clone()).expect("expect a successful put");
|
||||||
|
@ -195,8 +195,8 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let ts: Series<BikeTrip> =
|
let ts: Series<BikeTrip> = Series::open(&path.to_string_lossy())
|
||||||
Series::open(&path).expect("expect the time series to open correctly");
|
.expect("expect the time series to open correctly");
|
||||||
let v: Vec<(&UniqueId, &BikeTrip)> = ts.search_sorted(
|
let v: Vec<(&UniqueId, &BikeTrip)> = ts.search_sorted(
|
||||||
time_range(
|
time_range(
|
||||||
DateTimeTz(UTC.with_ymd_and_hms(2011, 10, 31, 0, 0, 0).unwrap()).into(),
|
DateTimeTz(UTC.with_ymd_and_hms(2011, 10, 31, 0, 0, 0).unwrap()).into(),
|
||||||
|
@ -220,8 +220,8 @@ mod test {
|
||||||
let trips = mk_trips();
|
let trips = mk_trips();
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut ts: Series<BikeTrip> =
|
let mut ts: Series<BikeTrip> = Series::open(&path.to_string_lossy())
|
||||||
Series::open(&path).expect("expect the time series to open correctly");
|
.expect("expect the time series to open correctly");
|
||||||
|
|
||||||
for trip in &trips[0..=2] {
|
for trip in &trips[0..=2] {
|
||||||
ts.put(trip.clone()).expect("expect a successful put");
|
ts.put(trip.clone()).expect("expect a successful put");
|
||||||
|
@ -229,8 +229,8 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut ts: Series<BikeTrip> =
|
let mut ts: Series<BikeTrip> = Series::open(&path.to_string_lossy())
|
||||||
Series::open(&path).expect("expect the time series to open correctly");
|
.expect("expect the time series to open correctly");
|
||||||
let v: Vec<(&UniqueId, &BikeTrip)> = ts.search_sorted(
|
let v: Vec<(&UniqueId, &BikeTrip)> = ts.search_sorted(
|
||||||
time_range(
|
time_range(
|
||||||
DateTimeTz(UTC.with_ymd_and_hms(2011, 10, 31, 0, 0, 0).unwrap()).into(),
|
DateTimeTz(UTC.with_ymd_and_hms(2011, 10, 31, 0, 0, 0).unwrap()).into(),
|
||||||
|
@ -248,8 +248,8 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let ts: Series<BikeTrip> =
|
let ts: Series<BikeTrip> = Series::open(&path.to_string_lossy())
|
||||||
Series::open(&path).expect("expect the time series to open correctly");
|
.expect("expect the time series to open correctly");
|
||||||
let v: Vec<(&UniqueId, &BikeTrip)> = ts.search_sorted(
|
let v: Vec<(&UniqueId, &BikeTrip)> = ts.search_sorted(
|
||||||
time_range(
|
time_range(
|
||||||
DateTimeTz(UTC.with_ymd_and_hms(2011, 10, 31, 0, 0, 0).unwrap()).into(),
|
DateTimeTz(UTC.with_ymd_and_hms(2011, 10, 31, 0, 0, 0).unwrap()).into(),
|
||||||
|
@ -273,8 +273,8 @@ mod test {
|
||||||
run_test(|path| {
|
run_test(|path| {
|
||||||
let trips = mk_trips();
|
let trips = mk_trips();
|
||||||
|
|
||||||
let mut ts: Series<BikeTrip> =
|
let mut ts: Series<BikeTrip> = Series::open(&path.to_string_lossy())
|
||||||
Series::open(&path).expect("expect the time series to open correctly");
|
.expect("expect the time series to open correctly");
|
||||||
|
|
||||||
ts.put(trips[0].clone()).expect("expect a successful put");
|
ts.put(trips[0].clone()).expect("expect a successful put");
|
||||||
ts.put(trips[1].clone()).expect("expect a successful put");
|
ts.put(trips[1].clone()).expect("expect a successful put");
|
||||||
|
@ -310,8 +310,8 @@ mod test {
|
||||||
let trips = mk_trips();
|
let trips = mk_trips();
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut ts: Series<BikeTrip> =
|
let mut ts: Series<BikeTrip> = Series::open(&path.to_string_lossy())
|
||||||
Series::open(&path).expect("expect the time series to open correctly");
|
.expect("expect the time series to open correctly");
|
||||||
|
|
||||||
ts.put(trips[0].clone()).expect("expect a successful put");
|
ts.put(trips[0].clone()).expect("expect a successful put");
|
||||||
ts.put(trips[1].clone()).expect("expect a successful put");
|
ts.put(trips[1].clone()).expect("expect a successful put");
|
||||||
|
@ -327,8 +327,8 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let ts: Series<BikeTrip> =
|
let ts: Series<BikeTrip> = Series::open(&path.to_string_lossy())
|
||||||
Series::open(&path).expect("expect the time series to open correctly");
|
.expect("expect the time series to open correctly");
|
||||||
|
|
||||||
let trips: Vec<(&UniqueId, &BikeTrip)> = ts.records().collect();
|
let trips: Vec<(&UniqueId, &BikeTrip)> = ts.records().collect();
|
||||||
assert_eq!(trips.len(), 3);
|
assert_eq!(trips.len(), 3);
|
||||||
|
@ -356,8 +356,8 @@ mod test {
|
||||||
let trips = mk_trips();
|
let trips = mk_trips();
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut ts: Series<BikeTrip> =
|
let mut ts: Series<BikeTrip> = Series::open(&path.to_string_lossy())
|
||||||
Series::open(&path).expect("expect the time series to open correctly");
|
.expect("expect the time series to open correctly");
|
||||||
let trip_id = ts.put(trips[0].clone()).expect("expect a successful put");
|
let trip_id = ts.put(trips[0].clone()).expect("expect a successful put");
|
||||||
ts.put(trips[1].clone()).expect("expect a successful put");
|
ts.put(trips[1].clone()).expect("expect a successful put");
|
||||||
ts.put(trips[2].clone()).expect("expect a successful put");
|
ts.put(trips[2].clone()).expect("expect a successful put");
|
||||||
|
@ -368,8 +368,8 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let ts: Series<BikeTrip> =
|
let ts: Series<BikeTrip> = Series::open(&path.to_string_lossy())
|
||||||
Series::open(&path).expect("expect the time series to open correctly");
|
.expect("expect the time series to open correctly");
|
||||||
let recs: Vec<(&UniqueId, &BikeTrip)> = ts.records().collect();
|
let recs: Vec<(&UniqueId, &BikeTrip)> = ts.records().collect();
|
||||||
assert_eq!(recs.len(), 2);
|
assert_eq!(recs.len(), 2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "fitnesstrax"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
adw = { version = "0.5", package = "libadwaita", features = [ "v1_2" ] }
|
|
||||||
gio = { version = "0.18" }
|
|
||||||
glib = { version = "0.18" }
|
|
||||||
gtk = { version = "0.7", package = "gtk4", features = [ "v4_8" ] }
|
|
||||||
tokio = { version = "1.34", features = [ "full" ] }
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
glib-build-tools = "0.18"
|
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
use fitnesstrax;
|
|
||||||
use gtk::prelude::*;
|
|
||||||
use std::env;
|
|
||||||
|
|
||||||
struct AppState {}
|
|
||||||
|
|
||||||
struct AppWindow {
|
|
||||||
window: adw::ApplicationWindow,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
println!("Hello, world!");
|
|
||||||
|
|
||||||
let app = adw::Application::builder()
|
|
||||||
.application_id("com.luminescent-dreams.fitnesstrax")
|
|
||||||
.resource_base_path("/com/luminescent-dreams/fitnesstrax")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
/*
|
|
||||||
let runtime = tokio::runtime::Builder::new_multi_thread()
|
|
||||||
.enable_all()
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
*/
|
|
||||||
|
|
||||||
let app = adw::Application::builder()
|
|
||||||
.application_id("com.luminescent-dreams.fitnesstrax")
|
|
||||||
.resource_base_path("/com/luminescent-dreams/fitnesstrax")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
app.connect_activate(move |app| {
|
|
||||||
let window = adw::ApplicationWindow::new(app);
|
|
||||||
window.present();
|
|
||||||
});
|
|
||||||
|
|
||||||
let args: Vec<String> = env::args().collect();
|
|
||||||
ApplicationExtManual::run_with_args(&app, &args);
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "ft-core"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
chrono = { version = "0.4" }
|
|
||||||
chrono-tz = { version = "0.8" }
|
|
||||||
dimensioned = { version = "0.8", features = [ "serde" ] }
|
|
||||||
emseries = { path = "../../emseries" }
|
|
||||||
serde = { version = "1", features = [ "derive" ] }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
tempfile = "*"
|
|
||||||
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
use crate::types;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
#[test]
|
|
||||||
fn read_a_legacy_set_rep_record() {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn read_a_legacy_steps_record() {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn read_a_legacy_time_distance_record() {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn read_a_legacy_weight_record() {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
use chrono::NaiveDate;
|
|
||||||
use dimensioned::si;
|
|
||||||
use emseries::DateTimeTz;
|
|
||||||
|
|
||||||
mod legacy;
|
|
||||||
mod types;
|
|
|
@ -1,106 +0,0 @@
|
||||||
use chrono::NaiveDate;
|
|
||||||
use dimensioned::si;
|
|
||||||
use emseries::{DateTimeTz, Recordable, Timestamp};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
/// SetRep represents workouts like pushups or situps, which involve doing a "set" of a number of
|
|
||||||
/// actions, resting, and then doing another set.
|
|
||||||
pub struct SetRep {
|
|
||||||
/// I assume that a set/rep workout is only done once in a day.
|
|
||||||
date: NaiveDate,
|
|
||||||
/// Each set entry represents the number of times that the action was performed in a set. So, a
|
|
||||||
/// pushup workout that involved five sets would have five entries. Each entry would be x
|
|
||||||
/// number of pushups. A viable workout would be something like [6, 6, 4, 4, 5].
|
|
||||||
sets: Vec<u32>,
|
|
||||||
comments: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The number of steps one takes in a single day.
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
pub struct Steps {
|
|
||||||
date: NaiveDate,
|
|
||||||
count: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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
|
|
||||||
/// record a single 30-km workout if I go on a long-distanec ride. Or I might record multiple 5km
|
|
||||||
/// workouts if I am out running errands. Distance and Duration are both optional because different
|
|
||||||
/// people have different priorities and may choose to measure different things.
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
pub struct TimeDistance {
|
|
||||||
/// The precise time (and the relevant timezone) of the workout. One of the edge cases that I
|
|
||||||
/// account for is that a ride which occurred at 11pm in one timezone would then count as 1am
|
|
||||||
/// if one moved two timezones to the east. This is kind of nonsensical from a human
|
|
||||||
/// perspective, so the DateTimeTz keeps track of the precise time in UTC, but also the
|
|
||||||
/// timezone in which the event was recorded.
|
|
||||||
datetime: DateTimeTz,
|
|
||||||
/// The distance travelled. This is optional because such a workout makes sense even without
|
|
||||||
/// the distance.
|
|
||||||
distance: Option<si::Meter<f64>>,
|
|
||||||
/// The duration of the workout, which is also optional. Some people may keep track of the
|
|
||||||
/// amount of distance travelled without tracking the duration.
|
|
||||||
duration: Option<si::Second<f64>>,
|
|
||||||
comments: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A singular daily weight measurement. Weight changes slowly enough that it seems unlikely to
|
|
||||||
/// need to track more than a single weight in a day.
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
pub struct Weight {
|
|
||||||
date: NaiveDate,
|
|
||||||
weight: si::Kilogram<f64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The unified data structure for all records that are part of the app.
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
pub enum TraxRecord {
|
|
||||||
BikeRide(TimeDistance),
|
|
||||||
Row(TimeDistance),
|
|
||||||
Run(TimeDistance),
|
|
||||||
Steps(Steps),
|
|
||||||
Swim(TimeDistance),
|
|
||||||
Walk(TimeDistance),
|
|
||||||
Weight(Weight),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Recordable for TraxRecord {
|
|
||||||
fn timestamp(&self) -> Timestamp {
|
|
||||||
match self {
|
|
||||||
TraxRecord::BikeRide(rec) => Timestamp::DateTime(rec.datetime.clone()),
|
|
||||||
TraxRecord::Row(rec) => Timestamp::DateTime(rec.datetime.clone()),
|
|
||||||
TraxRecord::Run(rec) => Timestamp::DateTime(rec.datetime.clone()),
|
|
||||||
TraxRecord::Steps(rec) => Timestamp::Date(rec.date),
|
|
||||||
TraxRecord::Swim(rec) => Timestamp::DateTime(rec.datetime.clone()),
|
|
||||||
TraxRecord::Walk(rec) => Timestamp::DateTime(rec.datetime.clone()),
|
|
||||||
TraxRecord::Weight(rec) => Timestamp::Date(rec.date),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tags(&self) -> Vec<String> {
|
|
||||||
vec![]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::*;
|
|
||||||
use emseries::Series;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn can_record_records() {
|
|
||||||
let file = tempfile::NamedTempFile::new().expect("a temporary file");
|
|
||||||
let path = file.into_temp_path();
|
|
||||||
let mut series: Series<TraxRecord> = Series::open(&path).unwrap();
|
|
||||||
|
|
||||||
let record = TraxRecord::Steps(Steps {
|
|
||||||
date: NaiveDate::from_ymd_opt(2023, 1, 1).unwrap(),
|
|
||||||
count: 1000,
|
|
||||||
});
|
|
||||||
|
|
||||||
let id = series.put(record.clone()).unwrap();
|
|
||||||
|
|
||||||
let record_ = series.get(&id).unwrap();
|
|
||||||
assert_eq!(record_, record);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue