info.trainingEffect returns a value before starting an activity. Shouldn't it be 0?

Definition from the api-docsThe Training Effect score of the current activity.

I am experimenting with this value as part of developing a Data Field. Although it worked as expected on my simulator, I got unexpected results running on my Fenix 6S. I did some further testing and found the following behavior:

  1. If you have selected an Activity type on a watch (Running, Walking, Cardio, whatever) but haven't started the activity, info.trainingEffect returns the final value of the most recent activity. Not even the last workout of the same Activity type, but the most recent activity, period. If you pull this data on a new Walking activity, and your last activity was Cardio, it will show you the Training Effect value from that Cardio activity.

  2. Once you Start your new activity, the value of info.trainingEffect drops to 0. It will then accurately reflect the current activity through all starts and stops up until the activity is saved.

I tested recording multiple activities in a row in case this would return the highest training impact (sort of like how Garmin Connect may show the highest for the day) but again, it's the most recent activity.

Prior to starting a new activity, I expected this to either be null, or to be 0. It means that if you look at data screens before you get started, any value based on Training Effect could be incorrect. I tested this with both Simple and Complex Data Fields and got the same result.

I tried detecting ActivityRecording.isRecording thinking that maybe I could use my own variable, set it to 0, and once we've started recording at least once to then load in info.trainingEffect, but ActivityRecording isn't available to Data Fields, so that's a no-go.

Am I doing something wrong? Is this a bug?

EDIT: While I'm asking... is there a way to extract Anaerobic Effect in addition to the Aerobic Effect that is provided? Or to pull the Primary Benefit at any given point during the workout (Base, Threshold, Sprint, etc.)

  • What device are you trying this on?  Real device or the sim?

  • What device are you trying this on?  Real device or the sim?
    Although it worked as expected on my simulator, I got unexpected results running on my Fenix 6S.

    I tried detecting ActivityRecording.isRecording thinking that maybe I could use my own variable, set it to 0, and once we've started recording at least once to then load in info.trainingEffect, but ActivityRecording isn't available to Data Fields, so that's a no-go.

    If you want to detect whether an activity has started, you could just check whether Activity.Info.TimerTime is non-null and non-0.

    Def sounds like a bug though, especially since the documentation for trainingEffect reads:

    "The Training Effect score of the current activity."

    You would also expect it to match whatever is displayed for the native (aerobic) Training Effect field. which would be "---" on my 945 LTE (*) before an activity is started. (* I assume "--" and "---" in native data fields are equivalent to null)

    You could file a bug in the CIQ bug reports section.

  • Yes, checking timerTime or elapsedTime can indiate of recording has started in a DF.  And yes, "--" or "---" would indicate the data isn't available or it's old data (recording hasn't started).

    I'm not sure it's a bug or just a matter of understanding what's available at a certain point.  Before recording is started, there is no "current activity" and on a real device, that could just be the value from the last activity.

  • I'm not sure it's a bug or just a matter of understanding what's available at a certain point.  Before recording is started, there is no "current activity" and on a real device, that could just be the value from the last activity.

    - Why would anyone (the dev or user) want to see any kind of value from the last activity (without explicitly asking for it), which could have happened minutes, hours, days, or weeks ago?

    - When data is "unavailable", I expect to see "no data" (e.g. "--", blank, or null), not "leftover data that isn't applicable to the current situation." This is sort of a general rule that transcends Garmin devices, I think.

    - I'm not aware of any other metric in Activity.Info that works this way. If there's no current heart rate, I doubt that the currentHeartRate field will contain the last known heart rate, for example

    - A common sense assumption would be that anything in the activity info class would refer to the current activity (and not the previous activity), even in the absence of an explicit statement to that effect. But as a matter of fact, there is an explicit statement:

    developer.garmin.com/.../Info.html

    The Activity.Info class contains information about the current activity.

    - The documentation for trainingEffect also literally says "current activity"

    - Again, the native training effect field does not behave this way (and if it did, a reasonable user would consider it a bug)

    - The only way this can be considered "correct" behavior is if we totally disregard the expectations of the average user or developer and just focus on either:

    - A completely literal reading of documentation. i.e. "The documentation doesn't specify what happens if the current activity hasn't started yet, therefore the field can contain any value we want, even if it doesn't make any sense!!!11!!"

    and/or

    - Some quirk which "makes sense" because "that's how it's implemented". (Nobody cares about implementation details, unless the desired behavior is literally impossible or impractical, which doesn't seem to be the case here.)

  • You'll find things in Activity.Info has things left over from the last activity.  A great example is currentLocation.  That's used by many watch faces to get a location for weather, sunrise/sunset, etc. and in that case, there is no "current activity".  Just the data from the last activity.

    If the timers haven't been started, there is no "current activity" and some thing may be inaccurate

    You also have things like Activity.Info.currentHeartRate that gets updated all the time on devices with OHR while they are being warn.  Another thing used in watch faces for "real time" heart rate.

    trainingEffect from the last activity could be displayed in watch faces and it will change when a new activity is started.

  • For now I will check timerTime and elapsedTime. That will probably get me by. I will also report this as a bug.

    I understand that it's possible that some properties could retain information from the previous activity, if it is an intended and documented behavior. I think that's what needs to be confirmed. I don't have other physical devices on me so I can't check if it's only my Fenix 6S.

    If it turns out this is intended, I will suggest that the docs are updated to indicate this scenario for trainingEffect and any other properties with that behavior.

    Since you're both here, do you have thoughts on getting the anaerobic value during the workout?

  • Fair enough. As soon as I posted my previous comment, I thought about the current location. In that case currentLocation matches native behavior more closely, as watches which support breadcrumb trails/courses/maps will show your last known location if you don't have a GPS fix. (And ofc there's the QUALITY_LAST_KNOWN enum value which implies this behavior)

    Overall I wish things were documented more clearly. The answer to most questions regarding CIQ seems to be "that's how it works, deal with it."

    I personally don't like this kind of undocumented behavior, because it seems that:

    - you have to test it on the real device, and the behavior could possibly change from device to device

    - since it's not documented, it's subject to change

    One example is the "half cadence" issues on some watches.

    You also have things like Activity.Info.currentHeartRate that gets updated all the time on devices with OHR while they are being warn.  Another thing used in watch faces for "real time" heart rate.
    trainingEffect from the last activity could be displayed in watch faces and it will change when a new activity is started.

    Sure, but it seems that its a different situation when you're in an actual activity (which hasn't started yet) and your app is a data field. For example, you wouldn't expect elapsedDistance to show the distance from the previous activity before the current activity has started, and it doesn't.

  • Since you're both here, do you have thoughts on getting the anaerobic value during the workout?

    I don't think you can, unless Garmin adds it in the future.