From bfb67fecfcab874dfbedce7001bbf991fadd7d73 Mon Sep 17 00:00:00 2001
From: Tilman Sauerbeck <tilman@code-monkey.de>
Date: Sun, 5 Jul 2020 18:37:42 +0200
Subject: [PATCH] application: Store pace in the model and show it in its own
 view.

---
 src/application/main.rs  | 15 +++++++++++++--
 src/application/model.rs | 16 ++++++++++++++++
 src/application/views.rs | 39 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 68 insertions(+), 2 deletions(-)

diff --git a/src/application/main.rs b/src/application/main.rs
index 95a60da..bdd1e4d 100644
--- a/src/application/main.rs
+++ b/src/application/main.rs
@@ -60,6 +60,7 @@ extern {
 enum View {
     Time,
     Distance,
+    Pace,
 }
 
 struct Timer {
@@ -91,14 +92,16 @@ impl Timer {
 fn next_view(view: View) -> View {
     match view {
         View::Time => View::Distance,
-        View::Distance => View::Time,
+        View::Distance => View::Pace,
+        View::Pace => View::Time,
     }
 }
 
 fn previous_view(view: View) -> View {
     match view {
-        View::Time => View::Distance,
+        View::Time => View::Pace,
         View::Distance => View::Time,
+        View::Pace => View::Distance,
     }
 }
 
@@ -252,6 +255,7 @@ pub unsafe extern "C" fn _start() -> ! {
 
     let mut time_view = views::TimeView::new();
     let mut distance_view = views::DistanceView::new();
+    let mut pace_view = views::PaceView::new();
 
     let mut model = model::Model::new();
 
@@ -264,6 +268,7 @@ pub unsafe extern "C" fn _start() -> ! {
                 logger.log(&prev_tap, &tap);
 
                 model.update(model::Field::Distance(logger.total_distance_cm));
+                model.update(model::Field::Pace(logger.pace_s));
             }
 
             model.update(model::Field::UnixTime(tap.unix_time));
@@ -314,6 +319,11 @@ pub unsafe extern "C" fn _start() -> ! {
                     display.draw(&screen);
                 }
             },
+            View::Pace => {
+                if pace_view.draw(&mut screen, &mut model) {
+                    display.draw(&screen);
+                }
+            },
         }
 
         heart_icon_timer.update(|state| {
@@ -358,6 +368,7 @@ pub unsafe extern "C" fn _start() -> ! {
             match view {
                 View::Time => time_view.invalidate(),
                 View::Distance => distance_view.invalidate(),
+                View::Pace => pace_view.invalidate(),
             }
         }
 
diff --git a/src/application/model.rs b/src/application/model.rs
index a056af5..4dc30c0 100644
--- a/src/application/model.rs
+++ b/src/application/model.rs
@@ -24,11 +24,13 @@
 pub enum Field {
     UnixTime(u32),
     Distance(u32),
+    Pace(u32)
 }
 
 pub struct Model {
     pub unix_time: u32,
     pub distance_cm: u32,
+    pub pace_s: u32,
 
     is_dirty: u32,
 }
@@ -38,6 +40,7 @@ impl Model {
         Model {
             unix_time: 0,
             distance_cm: 0,
+            pace_s: 0,
             is_dirty: 0,
         }
     }
@@ -47,6 +50,12 @@ impl Model {
             self.distance_cm = 0;
             self.is_dirty |= Model::dirty_mask(Field::Distance(0));
         }
+
+        if self.pace_s != 0 {
+            self.pace_s = 0;
+
+            self.is_dirty |= Model::dirty_mask(Field::Pace(0));
+        }
     }
 
     pub fn update(&mut self, data: Field) {
@@ -63,6 +72,12 @@ impl Model {
                     self.is_dirty |= Model::dirty_mask(data);
                 }
             },
+            Field::Pace(pace_s) => {
+                if self.pace_s != pace_s {
+                    self.pace_s = pace_s;
+                    self.is_dirty |= Model::dirty_mask(data);
+                }
+            },
         }
     }
 
@@ -82,6 +97,7 @@ impl Model {
         match data {
             Field::UnixTime(_) => 1,
             Field::Distance(_) => 2,
+            Field::Pace(_) => 4,
         }
     }
 }
diff --git a/src/application/views.rs b/src/application/views.rs
index 1218532..f29726f 100644
--- a/src/application/views.rs
+++ b/src/application/views.rs
@@ -95,3 +95,42 @@ impl DistanceView {
         true
     }
 }
+
+pub struct PaceView {
+    is_valid: bool,
+}
+
+impl PaceView {
+    pub fn new() -> PaceView {
+        PaceView {
+            is_valid: false,
+        }
+    }
+
+    pub fn invalidate(&mut self) {
+        self.is_valid = false;
+    }
+
+    pub fn draw(&mut self, screen: &mut screen::Screen,
+                model: &mut model::Model) -> bool {
+        if self.is_valid &&
+           !model.check_and_reset_is_dirty(model::Field::Pace(0)) {
+            return false;
+        }
+
+        let mut min_and_s = [b':'; 6];
+
+        common::fmt::fmt_u32_pad(&mut min_and_s[0..3], model.pace_s / 60,
+                                 3, b' ');
+
+        common::fmt::fmt_u32_pad(&mut min_and_s[4..6], model.pace_s % 60,
+                                 2, b'0');
+
+        screen.clear();
+        screen.draw_text(&min_and_s);
+
+        self.is_valid = true;
+
+        true
+    }
+}
-- 
2.30.2