My apologies, I really need to document the user metrics.
For the developers it is obvious because they use the same approach as the internal ones, but if you are a user its all greek !
relevant - is a function that returns non-zero if this metric is relevant for the activity - and should be declared only once.
it might need power, cadence etc and will check that. The idea is that when a metric is NOT relevant it saves compute time by just skipping the rest.
Assuming an activity is relevant then the user metric is computed by calling each function:
First "init" is called to setup any totals / counters etc you might use when computing the metric.
Secondly "sample" is called repeatedly for every sample, from the first to the last. In the code you can look at a variable "INDEX" to see where you are, and can use that to reference a sample directly i.e POWER[INDEX] is the power value for the current sample, POWER[INDEX-1] for prior etc.
During this iteration it is expected you will update some kind of aggregating values. You can also reference metrics too in this calculation as builtin metrics are also available. If you do not need to aggregate values you don't need a sample {} function.
Finally, a function called "value" is called to get the actual computed value; it may return the aggregated/computed value you updated during the sample {} function or it might just perform a computation using an existing metric; e.g. TSS/(Duration/3600) for TSS per hour (all time values are stored as seconds).
The "count" function is used when aggregating metrics to ensure the average is computed properly. Usually, count will just be the duration of the activity, so when averaging a metric from a 5hr ride with one from a 1hr ride you get the right result.
Hope this helps, but will update the wiki and record a video too.
Mark