mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-25 00:28:31 -05:00
3fd5f49220
Add analytics per-day aggregation collection. Add analytics strings collection. Add per-day aggregation mongo insertion script. Update campaign editor to use aggregation collection. Update queries to use _id instead of created field.
85 lines
3 KiB
CoffeeScript
85 lines
3 KiB
CoffeeScript
UserCodeProblem = require './UserCodeProblem'
|
|
Handler = require '../commons/Handler'
|
|
utils = require '../lib/utils'
|
|
|
|
class UserCodeProblemHandler extends Handler
|
|
modelClass: UserCodeProblem
|
|
jsonSchema: require '../../app/schemas/models/user_code_problem'
|
|
editableProperties: [
|
|
'code'
|
|
'codeSnippet'
|
|
'errHint'
|
|
'errId'
|
|
'errLevel'
|
|
'errMessage'
|
|
'errMessageNoLineInfo'
|
|
'errRange'
|
|
'errType'
|
|
'language'
|
|
'levelID'
|
|
]
|
|
|
|
makeNewInstance: (req) ->
|
|
ucp = super(req)
|
|
ucp.set('creator', req.user._id)
|
|
ucp
|
|
|
|
getByRelationship: (req, res, args...) ->
|
|
return @getCommonLevelProblemsBySlug(req, res) if args[1] is 'common_problems'
|
|
super(arguments...)
|
|
|
|
getCommonLevelProblemsBySlug: (req, res) ->
|
|
# Returns an ordered array of common user code problems with: language, message, hint, count
|
|
# Parameters:
|
|
# slug - level slug
|
|
# startDay - Inclusive, optional, e.g. '2014-12-14'
|
|
# endDay - Exclusive, optional, e.g. '2014-12-16'
|
|
|
|
levelSlug = req.query.slug or req.body.slug
|
|
startDay = req.query.startDay or req.body.startDay
|
|
endDay = req.query.endDay or req.body.endDay
|
|
|
|
return @sendSuccess res, [] unless levelSlug?
|
|
|
|
# Cache results for 1 day
|
|
@commonLevelProblemsCache ?= {}
|
|
@commonLevelProblemsCachedSince ?= new Date()
|
|
if (new Date()) - @commonLevelProblemsCachedSince > 86400 * 1000 # Dumb cache expiration
|
|
@commonLevelProblemsCache = {}
|
|
@commonLevelProblemsCachedSince = new Date()
|
|
cacheKey = levelSlug
|
|
cacheKey += 's' + startDay if startDay?
|
|
cacheKey += 'e' + endDay if endDay?
|
|
return @sendSuccess res, commonProblems if commonProblems = @commonLevelProblemsCache[cacheKey]
|
|
|
|
# Build query
|
|
match = if startDay? or endDay? then {$match: {$and: []}} else {$match: {}}
|
|
match["$match"]["$and"].push _id: {$gte: utils.objectIdFromTimestamp(startDay + "T00:00:00.000Z")} if startDay?
|
|
match["$match"]["$and"].push _id: {$lt: utils.objectIdFromTimestamp(endDay + "T00:00:00.000Z")} if endDay?
|
|
group = {"$group": {"_id": {"errMessage": "$errMessageNoLineInfo", "errHint": "$errHint", "language": "$language", "levelID": "$levelID"}, "count": {"$sum": 1}}}
|
|
sort = { $sort : { "_id.levelID": 1, count : -1, "_id.language": 1 } }
|
|
query = UserCodeProblem.aggregate match, group, sort
|
|
|
|
query.exec (err, data) =>
|
|
if err? then return @sendDatabaseError res, err
|
|
|
|
# Build per-level common problem lists
|
|
commonProblems = {}
|
|
for item in data
|
|
levelID = item._id.levelID
|
|
commonProblems[levelID] ?= []
|
|
commonProblems[levelID].push
|
|
language: item._id.language
|
|
message: item._id.errMessage
|
|
hint: item._id.errHint
|
|
count: item.count
|
|
|
|
# Cache all the levels
|
|
for levelID of commonProblems
|
|
cacheKey = levelID
|
|
cacheKey += 's' + startDay if startDay?
|
|
cacheKey += 'e' + endDay if endDay?
|
|
@commonLevelProblemsCache[cacheKey] = commonProblems[levelID]
|
|
@sendSuccess res, commonProblems[levelSlug]
|
|
|
|
module.exports = new UserCodeProblemHandler()
|