codecombat/server/analytics/analytics_log_event_handler.coffee

94 lines
3.6 KiB
CoffeeScript
Raw Normal View History

2014-12-15 14:45:12 -05:00
AnalyticsLogEvent = require './AnalyticsLogEvent'
Handler = require '../commons/Handler'
log = require 'winston'
2014-12-15 14:45:12 -05:00
class AnalyticsLogEventHandler extends Handler
modelClass: AnalyticsLogEvent
jsonSchema: require '../../app/schemas/models/analytics_log_event'
editableProperties: [
'event'
'properties'
]
hasAccess: (req) ->
2014-12-17 00:45:17 -05:00
req.method in ['POST'] or req.user?.isAdmin()
2014-12-15 14:45:12 -05:00
makeNewInstance: (req) ->
instance = super(req)
instance.set('user', req.user._id)
instance
getByRelationship: (req, res, args...) ->
return @getLevelCompletionsBySlugs(req, res) if args[1] is 'level_completions'
super(arguments...)
getLevelCompletionsBySlugs: (req, res) ->
# Returns an array of per-day level starts and finishes
# Parameters:
# slugs - array of level slugs
# startDay - Inclusive, optional, e.g. '2014-12-14'
# endDay - Exclusive, optional, e.g. '2014-12-16'
# TODO: An uncached call takes about 15s
levelSlugs = req.query.slugs or req.body.slugs
startDay = req.query.startDay or req.body.startDay
endDay = req.query.endDay or req.body.endDay
return @sendSuccess res, [] unless levelSlugs?
# Cache results for 1 day
@levelCompletionsCache ?= {}
@levelCompletionsCachedSince ?= new Date()
if (new Date()) - @levelCompletionsCachedSince > 86400 * 1000 # Dumb cache expiration
@levelCompletionsCache = {}
@levelCompletionsCacheSince = new Date()
cacheKey = levelSlugs.join(',')
cacheKey += 's' + startDay if startDay?
cacheKey += 'e' + endDay if endDay?
return @sendSuccess res, levelCompletions if levelCompletions = @levelCompletionsCache[cacheKey]
# Build query
match = {$match: {$and: [{$or: [{"event" : 'Started Level'}, {"event" : 'Saw Victory'}]}]}}
match["$match"]["$and"].push created: {$gte: new Date(startDay + "T00:00:00.000Z")} if startDay?
match["$match"]["$and"].push created: {$lt: new Date(endDay + "T00:00:00.000Z")} if endDay?
project = {"$project": {"_id": 0, "event": 1, "level": {$ifNull: ["$properties.level", "$properties.levelID"]}, "created": {"$concat": [{"$substr": ["$created", 0, 4]}, "-", {"$substr": ["$created", 5, 2]}, "-", {"$substr" : ["$created", 8, 2]}]}}}
group = {"$group": {"_id": {"event": "$event", "created": "$created", "level": "$level"}, "count": {"$sum": 1}}}
query = AnalyticsLogEvent.aggregate match, project, group
query.exec (err, data) =>
if err? then return @sendDatabaseError res, err
# Build per-level-day started and finished counts
levelDateMap = {}
for item in data
created = item._id.created
event = item._id.event
level = item._id.level
continue unless level?
# 'Started Level' event uses level slug, 'Saw Victory' event uses level name with caps and spaces.
level = level.toLowerCase().replace new RegExp(' ', 'g'), '-' if event is 'Saw Victory'
continue unless level in levelSlugs
levelDateMap[level] ?= {}
levelDateMap[level][created] ?= {}
levelDateMap[level][created] ?= {}
if event is 'Saw Victory'
levelDateMap[level][created]['finished'] = item.count
else
levelDateMap[level][created]['started'] = item.count
# Build list of level completions
completions = []
for level of levelDateMap
for created, item of levelDateMap[level]
completions.push
level: level
created: created
started: item.started
finished: item.finished
@levelCompletionsCache[cacheKey] = completions
@sendSuccess res, completions
2014-12-15 14:45:12 -05:00
module.exports = new AnalyticsLogEventHandler()