mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-27 09:35:39 -05:00
Add common user code problems to campaign editor
In level view, showing data from last 30 days, with top 20 issues by count.
This commit is contained in:
parent
0df9de551c
commit
b4a0fe146e
3 changed files with 106 additions and 3 deletions
|
@ -38,9 +38,31 @@
|
|||
td= levelPlaytimes[i].average.toFixed(2)
|
||||
else
|
||||
div Loading...
|
||||
|
||||
|
||||
|
||||
|
||||
h4 Common Problems
|
||||
if commonProblems
|
||||
if commonProblems.startDay
|
||||
if commonProblems.endDay
|
||||
div(style='font-size:10pt') #{commonProblems.startDay} to #{commonProblems.endDay}
|
||||
else
|
||||
div(style='font-size:10pt') #{commonProblems.startDay} to today
|
||||
table.table.table-bordered.table-condensed.table-hover(style='font-size:10pt')
|
||||
thead
|
||||
tr
|
||||
td Language
|
||||
td Error Message
|
||||
td Error Hint
|
||||
td Count
|
||||
tbody
|
||||
- for (var i = 0; i < commonProblems.length && i < 20; i++)
|
||||
tr
|
||||
td= commonProblems[i].language
|
||||
td= commonProblems[i].message
|
||||
td= commonProblems[i].hint
|
||||
td= commonProblems[i].count
|
||||
else
|
||||
div Loading...
|
||||
|
||||
if level.get('tasks')
|
||||
.tasks
|
||||
h3 Tasks (read only)
|
||||
|
|
|
@ -15,12 +15,14 @@ module.exports = class CampaignLevelView extends CocoView
|
|||
@listenToOnce @fullLevel, 'sync', => @render?()
|
||||
|
||||
@levelSlug = @level.get('slug')
|
||||
@getCommonLevelProblems()
|
||||
@getLevelCompletions()
|
||||
@getLevelPlaytimes()
|
||||
|
||||
getRenderData: ->
|
||||
c = super()
|
||||
c.level = if @fullLevel.loaded then @fullLevel else @level
|
||||
c.commonProblems = @commonProblems
|
||||
c.levelCompletions = @levelCompletions
|
||||
c.levelPlaytimes = @levelPlaytimes
|
||||
c
|
||||
|
@ -29,6 +31,27 @@ module.exports = class CampaignLevelView extends CocoView
|
|||
@$el.addClass('hidden')
|
||||
@trigger 'hidden'
|
||||
|
||||
getCommonLevelProblems: ->
|
||||
# Fetch last 30 days of common level problems
|
||||
startDay = new Date()
|
||||
startDay.setDate(startDay.getUTCDate() - 29)
|
||||
startDay = startDay.getUTCFullYear() + '-' + (startDay.getUTCMonth() + 1) + '-' + startDay.getUTCDate()
|
||||
|
||||
success = (data) =>
|
||||
return if @destroyed
|
||||
@commonProblems = data
|
||||
@commonProblems.startDay = startDay
|
||||
@render()
|
||||
|
||||
# TODO: Why do we need this url dash?
|
||||
request = @supermodel.addRequestResource 'common_problems', {
|
||||
url: '/db/user_code_problem/-/common_problems'
|
||||
data: {startDay: startDay, slug: @levelSlug}
|
||||
method: 'POST'
|
||||
success: success
|
||||
}, 0
|
||||
request.load()
|
||||
|
||||
getLevelCompletions: ->
|
||||
# Fetch last 7 days of level completion counts
|
||||
success = (data) =>
|
||||
|
|
|
@ -23,4 +23,62 @@ class UserCodeProblemHandler extends Handler
|
|||
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 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?
|
||||
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()
|
||||
|
|
Loading…
Reference in a new issue