Measure Advanced Configuration

The guide Managing Measures explains how to use the Measure Editor to create and manage measures. This reference gives more detail on the various options available when creating measures in advanced configuration. See Measure Settings for simple configuration. 

Who can use this feature?
 User Types
Admin users can create and edit measures.
 Pricing 
Available on paid plans (AnalystCLO, and Enterprise).
 Expertise
Only experts can use this feature.

Value types

The valueType property is used to tell Watershed what data value the value of an extension has. Valid value types are string, number, boolean, time, duration, percentage and array. This is especially important for durations. For example:

{ 
  "name": "Start", 
  "aggregation": { 
    "type": "LAST" 
  }, 
  "valueProducer": { 
    "type": "STATEMENT_PROPERTY", 
    "statementProperty": "context.extensions.[http://id.tincanapi.com/extension/starting-point]", 
    "valueType": "duration" 
  }
}

Format

The format property is used to tell Watershed how to format date values.

Please note: The format property only works in conjunction with the timestamp xAPI statement property.

For example:

{ 
  "name": "Last Timestamp With Time (am/pm)", 
  "aggregation": { 
    "type": "LAST" 
  }, 
  "valueProducer": { 
    "type": "STATEMENT_PROPERTY", 
    "statementProperty": "timestamp", 
    "format": "MMMM Do YYYY, h:mm:ss a" 
  }
},
{ 
  "name": "Last Timestamp With Time and Zone", 
  "aggregation": { 
    "type": "LAST" 
  }, 
  "valueProducer": { 
    "type": "STATEMENT_PROPERTY", 
    "statementProperty": "timestamp", 
    "format": "YYYY/MM/DD kk:mm:ss Z" 
  }
}

Other Aggregations

Some aggregations are not yet supported by the Measure Editor. 

Formula

The formula aggregation enables you to perform mathematical calculations with the results of other measures. In the formula, measures are identified by the letter m, followed by the index of that measure. For example, if your third measure was a formula measure and you wanted to multiply the first measure by the second measure, the syntax would be:

{
  "name": "Multiplication Example",
  "aggregation": {
    "type": "FORMULA",
    "formula": "m0 * m1"
  },
  "valueProducer": {}
}

More complex mathematical formula are also possible. For example:

{
  "name": "Pythagoras",
  "aggregation": {
    "type": "FORMULA",
    "formula": "sqrt(pow(m0, 2) + pow(m1, 2))"
  },
  "valueProducer": {}
}

The table below lists some of the possible operations.

Function

Description

Example Formula

Example Result

ceil

Rounds up to the next whole number.

ceil(4.4)

5

floor

Rounds down to the next whole number.

floor(4.4)

4

round

Rounds to the nearest whole number.

round(4.4)

4

max

Returns the highest value from a list.

max(5,3,7)

7

min

Returns the lowest value from a list.

min(5,3,7)

3

pow

Returns the number to the specified power.

pow(2,10)

1024

sqrt

Returns the square root of the number.

sqrt(9)

3

The Formula measure value producer can be used to set the data type of the resulting value. For example, the following measure will display the value in hours, minutes and seconds rather than a number. 

{
  "name": "Time Difference",
  "aggregation": {
    "type": "FORMULA",
    "formula": "m1 - m0"
  },
  "valueProducer": {
    "type": "STATEMENT_PROPERTY",
    "valueType": "duration"
  }
}

Formulas with null values

If any the measures you are using in a formula return a null value, then the default behavior of the formula is to also return null. If you would rather the formula treated null values as 0 values, then you can use the treatMissingAsZero flag.

The example below shows an overall score calculated based on points scored and points available for two different assessments of which the learner may have completed either one or both.

{
  "name": "Overall (%)",
  "aggregation": {
    "type": "FORMULA",
    "formula": "round((m3 + m4) / (m5 + m6) * 10000) /100",
    "treatMissingAsZero": true
  },
  "valueProducer": {}
}

Hidden Measures

Where measures used in calculations are not intended to be shown on the card, the hiddenMeasures property can be used to hide those measures. This property is currently only supported on the line and bar reports. The hiddenMeasures property is a direct property of the card configuration object and contains a list of the indexes of measures that should not be displayed. For example the following config would hide the first and third measures:

"hiddenMeasures": [0, 2]

Here is a complete card configuration using formula measures. It shows the number of interactions per person each week.

{
  "filter": {},
  "hiddenMeasures": [0, 1],
  "dimensions": [
    {
      "type": "TIME",
      "timePeriod": "WEEK"
    }
  ],
  "measures": [
    {
      "name": "Interaction Count",
      "aggregation": {
        "type": "COUNT"
      },
      "valueProducer": {
        "type": "STATEMENT_PROPERTY",
        "statementProperty": "id",
        "caseSensitive": true
      }
    },
    {
      "name": "Person Count",
      "aggregation": {
        "type": "DISTINCT_COUNT"
      },
      "valueProducer": {
        "type": "STATEMENT_PROPERTY",
        "statementProperty": "actor.person.id",
        "caseSensitive": true
      }
    },
    {
      "name": "Interactions per Person",
      "aggregation": {
        "type": "FORMULA",
        "formula": "m0 / m1"
      },
      "valueProducer": {}
    }
  ]
}

Group Count

The Group Count aggregation counts the number of people in a group, ignoring any filters. This aggregation only make sense for cards organized by group and uses a statement property value producer of actor.person.id. 

{ 
  "name": "Group Population", 
  "aggregation": { 
    "type": "GROUP_COUNT" 
  }, 
  "valueProducer": { 
    "type": "STATEMENT_PROPERTY", 
    "statementProperty": "actor.person.id"
  }
}

Group Percent

The Group Percent aggregation gives the total number of people matching a filter divided by the number of people in the group, displayed as a percentage. This aggregation only make sense for cards organized by group and uses a statement property value producer of actor.person.id or context.instructor.person.id. 

{ 
  "name": "Percent of People", 
  "aggregation": { 
    "type": "GROUP_PERCENT" 
  }, 
  "valueProducer": { 
    "type": "STATEMENT_PROPERTY", 
    "statementProperty": "actor.person.id"
  }
}

Last Between

The Last Between aggregation works in exactly the same way as the Last aggregation except that it only returns a value if the last value is with a particular date range. This is useful for identifying events that have happened most recently within a date range and not more recently, for example people who have completed a particular compliance course in the last year, but have not retaken it in the last 11 months. 

{
  "name": "Upcoming Expiration",
  "aggregation": {
    "type": "LAST_BETWEEN",
    "from": "P365D",
    "to": "P334D"
  },
  "valueProducer": {
    "type": "STATEMENT_PROPERTY",
    "statementProperty": "timestamp"
  },
  "filter": {
    "equals": [
      {
        "fieldName": "result.completion",
        "values": {
          "ids": [
            "true"
          ]
        }
      }
    ]
  }
}

Please note: you can use the LAST aggregation with a trailing date filter to get people who have taken the course in the last 11 months.

Expired

The Expired aggregation is used to identify people who have never completed something, or have completed it prior to a certain date. Again, this aggregation is useful for tracking compliance. The aggregation will return "never" if people have no statements matching the measure's filter. It will return the value of the most recent statement prior to the configured date if they do have matching statements only prior to that date. It will return nothing if they have matching statements after the configured date. 

Putting this into the context of compliance, this measure would return nothing for people who are compliant, the date when they last became compliant if they were compliant but aren't any longer, or 'never' if they have never been compliant. 

{
  "name": "Not Completed",
  "aggregation": {
    "type": "EXPIRED",
    "date": "P1Y"
  },
  "valueProducer": {
    "type": "STATEMENT_PROPERTY",
    "statementProperty": "timestamp"
  },
  "filter": {
    "equals": [
      {
        "fieldName": "result.completion",
        "values": {
          "ids": [
            "true"
          ]
        }
      }
    ]
  }
}

Last Value Count

The Last Value Count aggregation is used to count the number of distinct items for which the most recent value of a statement property matches a configured value. For example, this can be used to count the number of people who's most recently reported status for a course was 'registered' (i.e. only people who registered but have yet to complete the course). See the following example:

{
  "name": "Number of people registered for Some Course",
  "aggregation": {
    "type": "LAST_VALUE_COUNT",
    "lastValueProperty": "verb.id",
    "testValue": "http://adlnet.gov/expapi/verbs/registered",
    "regExp": false
  },
  "valueProducer": {
    "type": "STATEMENT_PROPERTY",
    "statementProperty": "actors.person.id",
    "caseSensitive": true
  },
  "filter":{
    "activityIds": {
      "ids": [
        "http:/example.com/courses/some-course"
      ]
    }
  }
}

The aggregation also supports a testValues property instead of testValue so that you can specify an array of values to match instead of a single value.

Accumulation

The Accumulation aggregation is used to look at data for a filtered set of statements before and after an xAPI statement matching a filter. For example, it might be used to get the average or total sales made by a salesperson in the 6 months before or 6 months after completing a training course. This measure works especially well in pairs of measures, one for before and one for after an event displayed in a Range report. The aggregation works by defining an event filter and before or after period in which to filter statements, and an aggregation and value producer to aggegrate those statements.

Where there are multiple statements matching the event filter, the set of statements before or after that each matching statement are each aggregated separately based on the aggegration property, then resulting values are averaged to give the final value returned by the aggregation.

The event filter currently only supports activity id and verb id filters. The aggregation property supports SUM, AVG, COUNT and DISTINCT_COUNT aggregations.

The following example shows two measures

{
  "name": "Score Before Training", 
  "aggregation": { 
    "type": "ACCUMULATION",
    "eventFilter": {
      "activityIds": {
        "ids": [
          "http:/example.com/courses/some-course"
        ]
      },
      "verbIds": {
        "ids": [
          "http://adlnet.gov/expapi/verbs/completed"
        ]
      }
    },
    "aggregation": "SUM",
    "before": "P6M"
  },
  "valueProducer": {
    "type": "STATEMENT_PROPERTY",
    "statementProperty": "result.score.raw",
    "caseSensitive": true
  }
},{
  "name": "Score After Training", 
  "aggregation": { 
    "type": "ACCUMULATION",
    "eventFilter": {
      "activityIds": {
        "ids": [
          "http:/example.com/courses/some-course"
        ]
      },
      "verbIds": {
        "ids": [
          "http://adlnet.gov/expapi/verbs/completed"
        ]
      }
    },
    "aggregation": "SUM",
    "after": "P6M"
  },
  "valueProducer": {
    "type": "STATEMENT_PROPERTY",
    "statementProperty": "result.score.raw",
    "caseSensitive": true
  }
}

Other Types of Value Producer

Simple configuration supports the Statement property and Time period. Other types of value producer and their functionality are outlined below.

Groups of Type

The Groups of Type value producer displays the Watershed group that a person (or parent group) belongs to, based on a configured group type. This works best with leaderboard cards organized by person to display additional metadata about the person and enable the user to sort the leaderboard by group. It can also work with cards organized by group to show the parent group(s) of the group type used to organize the card.

The configuration below shows a measure that will display the name of the first 'division' group that a person belongs to. Note that if people belong to multiple groups of the configured type, only one of those groups will be displayed. 

{ 
"name": "Division",
"aggregation": {
"type": "FIRST"
},
"valueProducer": {
"type": "GROUPS_OF_TYPE",
"groupType": "Division"
}
}

Please note: the Groups of Type value producer only works for items that have statements. For cards organized by person that have includedPeopleWithStatements set to true, people without statements will not show any value for Groups of Type measures (or, in fact, any measure using a FIRST aggregation).

Time Between

The time between value producer looks at the time between two events, for example the time between starting one task and getting to another one. It uses a start filter and an end filter to find pairs of statements, then calculates the time difference between the two. Where multiple pairs of statements matching the start and end filter are found, the measure will return the average time between.

The measure will match the closest pairs and not include overlapping matches. So in the sequence of statement start1 start2 end1 end2 start3 end3, it will average the time between start2 and end1, and between start3 and end3. start1 will be ignored because there is no matching end statement before the next matching start statement. end2 will be ignored because there is no matching start statement after the last matching end statement. 

Here's the syntax:

{
  "name": "Most Recent Time Between Activity 1 and Activity 2",
  "aggregation": {
    "type": "TIME_BETWEEN"
  },
  "valueProducer": {
    "type": "TIME_BETWEEN",
    "startFilter": {
      "activityIds": {
        "ids": [
          "http://example.com/expapi/activities/example-1"
        ]
      }
    },
    "endFilter": {
      "activityIds": {
        "ids": [
          "http:/example.com/expapi/activities/example-2"
        ]
      }
    }
  }
}

Measure Filters

You can configure simple measure filters in simple measure configuration. See the filters section of the advanced configuration help guide for details of how to customize these simple filters for more complex requirements.

Was this article helpful?
0 out of 0 found this helpful

Comments

0 comments

Please sign in to leave a comment.

If you can't find what you need or you want to ask a real person a question, please contact customer support.