Data Field: AppBuilder

By user request, this app lets you define your own data field, based on a simple math formula like cadence / 2.

If you want to get fancy, there's conditional expressions (like IF in Excel), functions for data analysis (like MIN and AVG), and the data field can also display the text of your choice. The resulting data can be (optionally) written to the activity FIT file.

With AppBuilder, you can implement almost any field that involves math, such as: calculating normalized power and saving the data to the FIT activity file, showing the average pace for even-numbered laps, or recording the amount of time you sprinted.

Full documentation and examples here:
http://ciq-appbuilder.blogspot.com/

AppBuilder 5:
Now with new features! AppBuilder 5 is a completely new app, so please check it out in the store if you are interested in any of the new features.
https://apps.garmin.com/en-US/apps/fd690281-9c22-4fee-a81e-3b7f39aa67c5

- Store up to four formulas per app. Switch between formulas directly on the watch, without using a phone or PC. With four clone apps, you can store up to 16 formulas total
- User variables. Allows for powerful formulas where information can be stored at one point, like the start of a lap, and used later. e.g. Lap elevation change
- Improved timeavg() options. Allows for simpler, more flexible normalized power function
- More functions and variables

4 clones of AppBuilder are available in the store, so you can have 2 formulas in the same activity
  • Update: 2.6.20
    Add semicolon operator:

    X ; Y = Y

    Useful for defining ALERTs while displaying other data.
    For example (modern/CIQ2 devices only):
    (Replace square brackets with parentheses)

    - Distance to next aid station at 5, 12.5, 17, [km or miles, depending on device distance units setting]
    IFS [distance LT 5, 5, distance LT 12.5, 12.5 , distance LT 17, 17] - distance

    - Alert at aid stations [5, 12.5, 17]
    ALERT[distance GTE 5]; ALERT[distance GTE 12.5]; ALERT[distance GTE 17]

    - Alert at aid stations and show distance to next aid station:
    ALERT[distance GTE 5]; ALERT[distance GTE 12.5]; ALERT[distance GTE 17]; IFS [distance LT 5, 5, distance LT 12.5, 12.5 , distance LT 17, 17] - distance
  • For anyone who need Yachting race timer 5min with signals and after that average speed 10s
    ifs[timer LTE 60 ,[when [timer GT 59,1,1,1,1]],timer LTE 120 ,[ when [Timer GT 119 , 1,1,1,1]] ,timer LTE 180 ,[when [timer GT 179,1,1,1,1]], timer LTE 240 ,[when [timer GT 239,1,1,1,1]] , timer LTE 293 ,[when [timer GT 290,1,2,1,1]] ,timer LTE 298 ,[when [timer GT 295,1,2,1,1]], timer LTE 300 ,[when [timer GT 298,1,1,1,1]] , Timer GTE 301, [TIMEAVG[Speed_raw, 10] * 1.94384]]

    it is work I LOVE IT
    Thank You


    Hey, glad it worked for you!

    Just want to clarify a couple of things:
    - Unlike if statements in imperative programming languages such as JavaScript, Java, Python, C, C#, etc. the expressions inside the IF and IFS functions are always evaluated, regardless of whether the corresponding condition is true or not. It is the condition inside ALERT that determines if/when the alert will go off. So all those IFS conditions are unnecessary. (I added a note to the documentation)

    IOW, AppBuilder is more like Excel than JavaScript.

    - In your app, while the timer is less than or equal to 300, it is displaying 0 [most of the time] or 1 when the alert goes off. Maybe it would be helpful to display a countdown.
    - I recently added a function ALERT[X] which is the same as WHEN[X, 1, 1, 1, 0]. It basically alerts you at the time X becomes true. WHEN[] is a bit more complicated, and ALERT[] might be a better choice in most cases.
    - I recently added the semicolon operator, which lets you have multiple ALERTs while displaying different data (for example)

    You might try this modification, which displays a countdown from 300s for the first five minutes, and the speed in knots afterwards. [Unfortunately it isn't possible to switch between display formats at the moment, so the time will be displayed in seconds, instead of minutes and seconds.]

    I split the formula up into different lines, for readability:
    (Replace square brackets with round brackets)
    ALERT[Timer GTE 60]; ALERT[Timer GTE 120];
    ALERT[Timer GTE 180]; ALERT[Timer GTE 240];
    ALERT[Timer GTE 290]; ALERT[Timer GTE 295];
    ALERT[Timer GTE 299];
    IF [Timer LTE 300, 300 - Timer, TIMEAVG[Speed_raw, 10] * 1.94384]



  • i tried it it works better then mine
    Thank you very mach for hard work !!!!!
  • No worries! I will probably continue to work on this app as long as there is interest and as long as it can be useful. (i.e. As long as it can do something that you can't get from another CIQ app.)

    Update 2.6.21:

    BREAKING CHANGE. AND() and OR() are now operators.
    Instead of AND(x, y), OR(x, y), use:
    x and y
    x or y


    This allows multiple and/or conditions to be easily chained together. Note that "and" has higher precedence than "or". [I will be adding operator precedence to the documentation]

    Example [modern/CIQ2 devices only]:

    Alert me every 5 km/mi milestone:
    ALERT[Distance GTE 5 and Distance mod 5 GTE 0 and Distance mod 5 LTE 0.1]


    Explanation:
    - Distance mod 5
    This is the remainder of dividing distance by 5. [It will always be between 0 and 4.9999...]
    When distance is zero, distance mod 5 will be zero
    When distance is 5, distance mod 5 will be zero
    When distance is 5.1, distance mod 5 will be 0.1
    When distance is 10, distance mod 10 will be 0
    When distance is 10.1, distance mod 10 will be 0.1
    etc.

    - Distance GTE 5
    We don't want an alert at the beginning of the activity [see above]
    - Distance mod 5 GTE 0
    We want an alert at 5, 10, 15, etc. [When distance mod 5 becomes greater or equal to 0]
    - Distance mod 5 LTE 0.1
    We want the alert "state" to reset itself at some point after 5, 10, 15, so we can get another notification at the next milestone.
    [This is because ALERT[] is purposely designed not to go off again unless the condition becomes false, then true again, to avoid continuous notifications].

    0.1 is chosen to give some leeway, since the GPS distance may never be exactly 5.0, 10.0, etc, and the formula is sampled once per second. But it will certainly be somewhere between 5.0 and 5.1, 10.0 and 10.1, etc, unless you're running really fast.

    In other words, alert me when:
    - I've run more than 5 km
    - distance mod 5 is between 0 and 0.1

    IOW, the big condition inside ALERT becomes:
    - True at 5 km [and you are alerted]
    - False at 5.1
    - True at 10 km [alert]
    - False at 10.1 km
    etc.

    We can simplify this by noticing that distance mod 5 is always greater than or equal to 0, so we can take that out of the formula.

    ALERT[Distance GTE 5 and Distance mod 5 LTE 0.1]

    Modified examples:
    Alert me every 5 km/mi milestone (simplified)
    ALERT[Distance GTE 5 and Distance mod 5 LTE 0.1]

    Alert me every 5 km/mi milestone and show distance to next milestone:
    ALERT[Distance GTE 5 and Distance mod 5 LTE 0.1]; 5 - distance mod 5

    Alert me every 1k, for the first 5k of my run:
    ALERT[Distance GTE 1 and Distance LTE 5.1 and Distance mod 1 LTE 0.1]

    Alert me every 1k, for the first 5k of my run, and show distance to next milestone:
    ALERT[Distance GTE 1 and Distance LTE 5.1 and Distance mod 1 LTE 0.1]; if [Distance lte 5, 1 - distance mod 1, null]

    (As explained above, the 0.1 "slack" for distance alerts accounts for the fact that the Distance variable may never be exactly equal to 1.0, 5.0, 10.0, etc., especially not when it's sampled once per second).

    If you're going faster (in a vehicle), you can pick a larger number for your slack as long as it's not too close to your alert distance. (e.g. 0.5)


    Alert me every 60 seconds:
    ALERT[Timer GTE 60 and Timer mod 60 LTE 2]
    [Similar to the distance alerts, the 2 seconds "slack" is just to give some leeway since the Timer value is never going to be exactly 60, 120, 180, etc.]

    Alert me every 60 seconds, and display time to next alert:
    ALERT[Timer GTE 60 and Timer mod 60 LTE 2]; 60 - timer mod 60


    Alert me every 60 seconds, for the first 5 minutes:
    ALERT[Timer GTE 60 and Timer LTE 302 and Timer mod 60 LTE 2]

    Alert me every 60 seconds, for the first 5 minutes, and display time to next alert:
    ALERT[Timer GTE 60 and Timer LTE 302 and Timer mod 60 LTE 2]; if [timer lte 300, 60 - timer mod 60, null]
  • A couple of people asked for this, so I have uploaded 2 more clones of AppBuilder to the store.

    They are available now:
    https://apps.garmin.com/en-US/apps/e...5-f436909377dd
    https://apps.garmin.com/en-US/apps/1...d-e1e81cb38e8a

    With the 735XT, you could have 3 AppBuilder fields in the same activity. For other watches, you could use the other 2 apps to store additional formulas and assign them to other activities.
  • Uh...good news and bad news.

    The bad news for anyone who's actually using all 4 AppBuilder fields is that AppBuilder4 is in a state right now where it can't be updated, otherwise it will conflict with AppBuilder3. Sorry about that! So please don't update via GCM or Garmin Express (PC/Mac). (You may have to turn off auto-updates in Garmin Express). I'll post again once that's sorted out.

    Pro tip: Never try to update 4 apps at the same time, without checking each step carefully! >_>

    The good news is the latest update has a function which makes "distance to next milestone" formulas much simpler, and also allows 3X as many milestones on older devices. (30 milestones, up from 10).

    2.6.22
    Added FINDLTE(), FINDEQ(), FINDGTE()

    FINDLTE(X, value1, value2, ...)
    - Finds the first value where X is less than or equal to value

    FINDGTE(X, value1, value2, ...)
    - Finds the first value where X is greater than or equal to value

    FINDEQ(X, value1, value2, ...)
    - Finds the first value where X is equal to value

    e.g.
    Distance to next milestone (5, 12.5, 15, 20, 25, 30 km or miles):

    FINDLTE(Distance, 5, 12.5, 15, 20, 25, 30) - Distance

    (Yes, the function names could be better. I didn't want to use MATCH() since Excel's MATCH is similar yet works differently, SELECT() would have its own issues, etc.)
  • I apologize to anyone who will be inconvenienced by this, but I bit the bullet and removed the broken version of AppBuilder4 from the store. I think that any action Garmin would take to help me fix the problem would have to be manually initiated by a real person, whereas the app approval process seems to be automatic (or at least very quick) once you've got one or two under your belt. So hopefully this will be a much quicker resolution.

    You should be able to continue using the field if you have it installed, but you won't be able to configure it. If you need to change the config before the fixed version is live, let me know and I can generate a settings file for you which can be copied to your watch via USB.

    The new incarnation of AppBuilder4 will be available here, when it's approved, which should be as early as tomorrow, if recent experience is any guide.
    https://apps.garmin.com/en-US/apps/f...e-9a39e44e1b9f

    Sorry for the inconvenience! But thanks for using the field! I would insert a smiley face here, but the forum won't let me.
  • Update 2.6.23:

    Fix DIV (integer division) for decimals.

    e.g. 10.5 div 2.5 = 4

    e.g. Display activity timer as mm:ss until 1 hour has passed, then display time as hh:mm:
    Display format: Time
    Formula: IF [Timer LT 3600, Timer, Timer div 60]

  • AppBuilder4 is back in the store. If you previously installed it, please uninstall the old one and use this instead:

    https://apps.garmin.com/en-US/apps/f...9a39e44e1b9f#0
  • Hello, I try to find a data field who can display the lap ascent for my 920XT, and I don't find it.
    Do you think AppBuilder can do it with a formula ?

    Is it possible to dislay the ascent minus the last lap ascent or another method ?

    Thanks for your help