App: PaceMate

I'm very new to Monkey C programming and wanted to show off my latest app, PaceMate.

https://apps.garmin.com/apps/10f0ba71-cc76-4cfe-88b3-3f39825ff89f

My friends and I are used to speaking in km / h, but when we got into running it slowly changed into using pace (min / km) as a metric instead. We struggled to convert pace to km and had to take our phone out to find a website to convert it. Instead, I decided to create a Garmin app for it.

Features:

  1. Input pace, speed or goal time for a specific distance. The app will show the calculated values for the rest of the fields, based on the input.
  2. Define up to 4 custom distance fields in Connect IQ settings (apart from the default 5k, 10k, half marathon and marathon distances), and display these custom distance fields instead of the default distances.

My challenges in building this app:

  1. Finding a way to handle input (realising that Garmin API does not have a uniform way to capture pace, speed or time input).
    I ended up creating my own input views / delegate pairs to handle inputs for three different data types (pace, speed and time). They can now handle both touch (tap and flick) and button (press and hold) input.
  2. Supporting non-touch enabled devices.
    Still need to add a way for non-touch enabled devices to select fields and push a menu to allow users to select a different distance to display in that field.
  3. Clash with Hold DOWN hot key.
    In my app, when you want to use buttons for example to input pace, I made it so that if you HOLD the Up button, instead of just going up by 1 sec, the pace will go up by 5 (and increment significantly upon holding longer). The Down button works in the same way. However, if you have a hot key set for Hold DOWN, the hot key will take over and the onKeyReleased event will not be fired. Therefore, the input value will keep going down, until you press Down again and release it.

I still need to add support for the Imperial system, but I wanted to publish the app already.

What do you think?

Also if someone has a suggested solution for the "Clash with Hold DOWN hot key" issue, please let me know.

  • Hi

    I have just uploaded version 0.2.1 based on your feedback! (will take some time to be visible to you)

    Again, thank you for your engagement.

    For now my focus will be to implement the Imperial system, which will finally be version 1.0.0.

  • Hey I tried the latest version and it's a great improvement! Thank you for incorporating so many of the changes I suggested. Overall I could see myself using this app on a regular basis.

    Here's a few observations about the latest version:

    - I really like the selection cursor for navigating the main fields

    - The size and appearance of the new spinners is perfect

    - For screens which select time, the seconds spinner is a bit too close to the checkmark

    - If I use the buttons to a select a field to change, and return to the main screen, the selection cursor disappears. I have to press UP or DOWN to bring it back. Ideally the selection cursor would be restored to the current field

    - I like the fact that the spinners are separated now, but if use the buttons there's no way to return to the previous spinner. START does advance to the next spinner as expected. Suggestion: use the BACK button to return to the previous spinner. BACK should only return the main screen if you are on the first spinner. (Analogous to how START only accepts the changes if you are on the last spinner.) One advantage of this change is it would make your app even more similar to native fields. 

    - For custom fields, instead of displaying text like "Custom 1" on the main page, it would be nice if the app just displayed the distance itself

    - scrolling the spinner via swipes seems a bit slow/unresponsive, although the usability issues with crazy scrolling have been fixed. Maybe just make the spinners a tiny bit more responsive? Or maybe there needs to be some sort of "acceleration" built in when multiple swipes are detected in a short period of time (almost like a real spinner). I will note that the built-in garmin spinners don't have acceleration, but they do seem to respond acceptably to multiple quick swipes. iOS spinners are even better - the user can spin them pretty fast with one very "forceful" swipe (not sure if the garmin touchscreen is sensitive enough for this, otherwise you'd think Garmin would've implemented this too).

    - swiping a spinner that isn't currently "selected" doesn't work. I have to first tap the spinner, then swipe it. As an end user, I expect that if I swipe a spinner that's not currently selected, it will "just work" (i.e. it should be automatically selected and start scrolling). Upon further investigation it seems that an unselected spinner doesn't respond to swipes because the blank areas above and below the number don't respond to swipes. What I am trying to do actually would work if I'm careful to swipe *directly* on the number, as opposed to the blank space above/below the number, but I don't think most users are gonna be that careful.

    So the simple fix here is to allow blank space above and below an unselected spinner to respond to swipes.

    - instead of having custom distance presets in the "off-device" app settings, in the app itself I would just let the user select from a set of standard distances (e.g. 200m, 400m, ..., 5k, ..., marathon, 50k, 100m), and also let them enter a custom distance. The app could automatically remember the last few custom distances that were entered

    - it would be nice if there were a way to reset the fields to default on the app itself

    - it seems that you are planning to have imperial/metric as a global "off-device" setting. In a perfect world, the user would be able to independently toggle between metric and imperial for any field (pace, speed, any of the distance fields). e.g. maybe I want to see pace in min/km but speed in miles per hour. Or maybe I want to quickly toggle pace from min/km to min/mi, so I can see that 5:00/km (for example) is equal to 8:00/mile.

    For distance and pace, the units are already at the bottom of the screen, so it would be very intuitive if tapping on the units toggles them between imperial and metric.

    For the other fields, the distance is at the bottom of the screen, and I think it would still make sense that tapping on the units would toggle between imperial and metric.

    Or to make things easier for button-based users, the units could just be an additional "spinner". 

    (Either way, I would expect that toggling between metric/imperial would also instantly convert the metric that's being displayed)

    - although the hours spinner maxes out at 99 (and I don't have a problem with that), it doesn't wrap around at 0/99, unlike the minutes and seconds spinners, which wrap around at 0/59, as expected.

    - the "Pace" and "Speed" labels on the main screen could be replaced with the actual units ("min/km", "min/mi", "mph", "kph"), which would be especially useful if you implement the suggested feature to mix and match imperial/metric

  • Also, if I change the distance of a field (like say, 42.2 km to 5 km), the app keeps the time constant and changes the pace/speed, which may produce unwanted results. One way around this could be to assume that the user really wanted to keep the pace/speed constant, and to change the time instead. I feel like this assumption would fit better with the current design of the app.

    This goes back to the general issue that there's 3 variables (time, speed and distance), and when you change any one of them, the app has to guess which of the other 2 you want to calculate (while holding the 3rd one fixed). It's less of an issue with this app because changing the distance is an uncommon thing to do, and if you change the pace/speed, it's obvious that the times for all the distances are supposed to be recalculated, as opposed recalculating all the distances while holding the times fixed.

    Ways I've seen this handled in other (phone-based) apps:

    - Pacey forces you to "lock" one of the metrics (pace/speed, distance, and time) so it's always clear which metric will be calculated when you select one of the other two

    - another pace calculator just guesses which metric you want to calculate (based on which ones you've changed recently)

    - most pace calculators just have a separate page for every single "output" metric you want to calculate (like I said, this is my least favourite solution because it's inefficient when it comes to multiple calculations)

    Obviously this approach wouldn't work for your app (nor is it really necessary).

    This does mean that there's no way to ask the app a question like "how far would I run if I ran 4:30/km for 90 minutes"? 

     In your app, maybe the way to handle this use case is to have a 2nd type of field which has a fixed time, and it's the distance that you edit on the main page. This way, when you edit distance/speed, the app recalculates the time for all the other fixed-distance fields, but recalculates the distance for the fixed-time fields.

    e.g.

    Pace        Speed
    4:30        13.33

    5k          10k
    22:30       45:00

    HM          90:00
    1:34:57     19.99 km

    Only problem is that this may be difficult to present to the user in an intuitive way. (Basically every field has a fixed distance/time, and it's the other metric - time/distance - which is calculated when you change pace/speed).

  • Also, it's confusing that after you select a field to edit, the menu for choosing a distance is entitled "Select field". I would expect this menu to have a title like "Set Field Distance" or something. (I already selected a field in the previous step.)