Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions source/Delegates/SimpleViewDelegate.mc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Toybox.Lang;
import Toybox.WatchUi;
import Toybox.System;

class SimpleViewDelegate extends WatchUi.BehaviorDelegate {

Expand All @@ -22,6 +23,17 @@ class SimpleViewDelegate extends WatchUi.BehaviorDelegate {
if (app.isActivityRecording()) {
app.stopRecording();
System.println("[UI] Cadence monitoring stopped");

// Auto-navigate to summary screen if we have valid data
if (app.hasValidSummaryData()) {
System.println("[UI] Showing activity summary");
var summaryView = new SummaryView();
WatchUi.pushView(
summaryView,
new SummaryViewDelegate(),
WatchUi.SLIDE_UP
);
}
} else {
app.startRecording();
System.println("[UI] Cadence monitoring started");
Expand Down
51 changes: 51 additions & 0 deletions source/Delegates/SummaryViewDelegate.mc
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import Toybox.Lang;
import Toybox.WatchUi;
import Toybox.System;

class SummaryViewDelegate extends WatchUi.BehaviorDelegate {

function initialize() {
BehaviorDelegate.initialize();
}

// SELECT or any key to dismiss and return to SimpleView
function onSelect() as Boolean {
System.println("[SUMMARY] Returning to main view");
WatchUi.popView(WatchUi.SLIDE_DOWN);
return true;
}

// BACK button to dismiss
function onBack() as Boolean {
System.println("[SUMMARY] Back pressed, returning to main view");
WatchUi.popView(WatchUi.SLIDE_DOWN);
return true;
}

// Swipe left to dismiss
function onSwipe(event as WatchUi.SwipeEvent) as Boolean {
var direction = event.getDirection();

if (direction == WatchUi.SWIPE_LEFT || direction == WatchUi.SWIPE_DOWN) {
System.println("[SUMMARY] Swiped to dismiss");
WatchUi.popView(WatchUi.SLIDE_DOWN);
return true;
}

return false;
}

// Any key press dismisses
function onKey(keyEvent as WatchUi.KeyEvent) as Boolean {
var key = keyEvent.getKey();

// Allow any key to dismiss
if (key == WatchUi.KEY_UP || key == WatchUi.KEY_DOWN ||
key == WatchUi.KEY_ENTER || key == WatchUi.KEY_MENU) {
WatchUi.popView(WatchUi.SLIDE_DOWN);
return true;
}

return false;
}
}
119 changes: 119 additions & 0 deletions source/GarminApp.mc
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ class GarminApp extends Application.AppBase {
private var _finalCQTrend = null;
private var _cqHistory as Array<Number> = [];

// Activity metrics captured when monitoring stops
private var _sessionDuration = null; // milliseconds
private var _sessionDistance = null; // centimeters
private var _avgHeartRate = null; // bpm
private var _peakHeartRate = null; // bpm

function initialize() {
AppBase.initialize();
Expand Down Expand Up @@ -110,6 +115,12 @@ class GarminApp extends Application.AppBase {
_cqHistory = [];
_cadenceCount = 0;
_missingCadenceCount = 0;

// Reset activity metrics
_sessionDuration = null;
_sessionDistance = null;
_avgHeartRate = null;
_peakHeartRate = null;

isRecording = true;
}
Expand All @@ -121,6 +132,9 @@ class GarminApp extends Application.AppBase {

System.println("[INFO] Stopping cadence monitoring");

// Capture activity metrics before stopping
captureActivityMetrics();

var cq = computeCadenceQualityScore();

if (cq >= 0) {
Expand All @@ -141,6 +155,29 @@ class GarminApp extends Application.AppBase {
isRecording = false;
}

function captureActivityMetrics() as Void {
var info = Activity.getActivityInfo();

if (info != null) {
if (info.timerTime != null) {
_sessionDuration = info.timerTime;
System.println("[ACTIVITY] Duration: " + (_sessionDuration / 1000).toString() + " seconds");
}

if (info.elapsedDistance != null) {
_sessionDistance = info.elapsedDistance;
System.println("[ACTIVITY] Distance: " + (_sessionDistance / 100000.0).format("%.2f") + " km");
}

if (info.currentHeartRate != null) {
// For now, use current heart rate as average (could be enhanced with history tracking)
_avgHeartRate = info.currentHeartRate;
_peakHeartRate = info.currentHeartRate;
System.println("[ACTIVITY] Heart Rate: " + _avgHeartRate.toString() + " bpm");
}
}
}

function updateCadenceBarAvg() as Void {
//if (!isRecording) { return;} // ignore samples when not actively monitoring

Expand Down Expand Up @@ -524,6 +561,88 @@ class GarminApp extends Application.AppBase {
function getInitialView() as [Views] or [Views, InputDelegates] {
return [ new SimpleView(), new SimpleViewDelegate() ];
}

// -----------------------
// Summary Statistics Methods
// -----------------------

function getAverageCadence() as Float {
if (_cadenceCount == 0) {
return 0.0;
}

var total = 0.0;
var validSamples = 0;

for (var i = 0; i < MAX_BARS; i++) {
var c = _cadenceHistory[i];
if (c != null) {
total += c;
validSamples++;
}
}

if (validSamples == 0) {
return 0.0;
}

return total / validSamples;
}

function getTimeInZonePercentage() as Number {
return computeTimeInZoneScore();
}

function getMinCadenceFromHistory() as Number {
var minCad = null;

for (var i = 0; i < MAX_BARS; i++) {
var c = _cadenceHistory[i];
if (c != null) {
if (minCad == null || c < minCad) {
minCad = c;
}
}
}

return (minCad != null) ? minCad.toNumber() : 0;
}

function getMaxCadenceFromHistory() as Number {
var maxCad = null;

for (var i = 0; i < MAX_BARS; i++) {
var c = _cadenceHistory[i];
if (c != null) {
if (maxCad == null || c > maxCad) {
maxCad = c;
}
}
}

return (maxCad != null) ? maxCad.toNumber() : 0;
}

function hasValidSummaryData() as Boolean {
return _cadenceCount >= MIN_CQ_SAMPLES && _finalCQ != null;
}

// Activity metrics getters
function getSessionDuration() {
return _sessionDuration;
}

function getSessionDistance() {
return _sessionDistance;
}

function getAvgHeartRate() {
return _avgHeartRate;
}

function getPeakHeartRate() {
return _peakHeartRate;
}
}

function getApp() as GarminApp {
Expand Down
Loading