Skip to content

Achievements discussion

Simon Bear edited this page Mar 3, 2015 · 12 revisions

#Achievements

##Creating an achievement:

  • Achievements are created in the Admin section:
  • Achievements have a:
    • name: Used under the image
    • description: Hover text for the image
    • badge: Image for the achievement, this image should have a transparent background and will be sized to 140px x 140px when displayed on the UI.
    • on/off toggle: Enables/disables the evaluation and granting of this achievement to users. Users to whom this achievement is already granted are unaffected.
    • type: Determines what kind of achievements this is, options are:
      • ElasticSearch query and aggregation
      • ElasticSearch query
      • Groovy script
  • Creating an achievement will generally require some developer time to write and test the queries/code behind it.

###ElasticSearch queries, aggregations

Are input using ElasticSearch JSON formats, eg:

{
    "term" : { "fullyTranscribedBy" : "8737" }
}

String substitution is performed on the queries, insert a substitution using ${varName}.

The following variables are available for string subsitution:

  • userId: the id of the user being evaluated for the achievement

eg, to genericise the above, replace the 8737 with ${userId} like so:

{
    "term" : { "fullyTranscribedBy" : "${userId}" }
}

Aggregations are similarly added:

{
    "projectids" : {
      "terms" : { "field" : "projectid", "size": 7 }
    }
}

This aggregation query will:

  • Create an aggregations called projectids
  • bundle up all documents into buckets based on a terms match
  • the terms in question is the field projectid
  • the size: 7 parameter limits the query to returning 7 buckets at most

###Evaluating ES queries:

A non-aggregation query is evaluated against the count field on the achievement.

If the number of documents returned by the query is greater than or equal to the number given in the count field then the achievement will be granted to the user being evaluated.

EG, simple "You have transcribed 100 tasks" type achievements can be done this way. Additional filters can be added such as a "Holiday Hero" badge for someone who transcribed 50 tasks in December, for example.

###Evaluating ES Aggregation queries:

Aggregation queries, the equivalent of an SQL GROUP BY clause, don't have a corresponding SQL HAVING clause. So ensuring that the required number of buckets or number of documents in a bucket is above a threshold can't be done by a query alone.

At the moment, the means of evaluating an aggregation is via a groovy script.

The script is granted access to a org.elasticsearch.action.search.SearchResponse typed variable with the name 'searchResponse', the id of the task that triggered this evaluation under taskId (may be null and probably to be removed) and the user being evaluated under user. The script should return a boolean, with true indicating the aggregation matches the conditions for the achievement, false otherwise.

For example, to ensure that at least 7 buckets exist with 7 tasks (ie for an x tasks in y projects type achievement) you would use:

def projectIds = searchResponse.aggregations.get('projectids')
projectIds.buckets().size() > 7 && projectIds.buckets*.docCount.min() >= 7

NOTE The count field is ignored in the Aggregation at the moment, probably needs to be hidden on the edit UI.

TODO Can the groovy be removed?

###Groovy type queries:

Use a groovy script, which is granted access to:

  • applicationContext, the Spring applicationContext for the digivol application
  • user, the user the achievement is being evaluated for
  • taskId, the task id that caused the achievement to be evaluated (may be null)

###ElasticSearch index fields:

Documents in the ElasticSearch index have the following fields:

TODO

###Achievement types:

Discussion of how each achievement type works:

####ElasticSearch query and aggregation

  • Uses an initial ES query to filter the documents being considered, eg to the user being evaluated:

####ElasticSearch queries should be changed to filters?

Currently ES Queries are being used. Perhaps it should be filters only:

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html

"Filters are very handy since they perform an order of magnitude better than plain queries since no scoring is performed and they are automatically cached."

Investigate whether filters can be used directly in the setQuery call or whether they require their own call to the ES client.

May be some issues as filter syntax looks weirder and may present issues with extracting results:

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-term-filter.html

vs

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-term-query.html

Clone this wiki locally