mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-24 08:08:15 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
f2f008e01a
12 changed files with 83 additions and 30 deletions
|
@ -72,10 +72,12 @@ module.exports = class LevelLoader extends CocoClass
|
||||||
url += "?team=#{@team}" if @team
|
url += "?team=#{@team}" if @team
|
||||||
|
|
||||||
session = new LevelSession().setURL url
|
session = new LevelSession().setURL url
|
||||||
|
session.project = ['creator', 'team', 'heroConfig', 'codeLanguage', 'submittedCodeLanguage', 'state'] if @headless
|
||||||
@sessionResource = @supermodel.loadModel(session, 'level_session', {cache: false})
|
@sessionResource = @supermodel.loadModel(session, 'level_session', {cache: false})
|
||||||
@session = @sessionResource.model
|
@session = @sessionResource.model
|
||||||
if @opponentSessionID
|
if @opponentSessionID
|
||||||
opponentSession = new LevelSession().setURL "/db/level.session/#{@opponentSessionID}"
|
opponentSession = new LevelSession().setURL "/db/level.session/#{@opponentSessionID}"
|
||||||
|
opponentSession.project = session.project if @headless
|
||||||
@opponentSessionResource = @supermodel.loadModel(opponentSession, 'opponent_session', {cache: false})
|
@opponentSessionResource = @supermodel.loadModel(opponentSession, 'opponent_session', {cache: false})
|
||||||
@opponentSession = @opponentSessionResource.model
|
@opponentSession = @opponentSessionResource.model
|
||||||
|
|
||||||
|
|
|
@ -447,6 +447,7 @@
|
||||||
managed_subs: "Managed Subscriptions"
|
managed_subs: "Managed Subscriptions"
|
||||||
managed_subs_desc: "Add subscriptions for other players (students, children, etc.)"
|
managed_subs_desc: "Add subscriptions for other players (students, children, etc.)"
|
||||||
group_discounts: "Group discounts"
|
group_discounts: "Group discounts"
|
||||||
|
group_discounts_1: "We also offer group discounts for bulk subscriptions."
|
||||||
group_discounts_1st: "1st subscription"
|
group_discounts_1st: "1st subscription"
|
||||||
group_discounts_full: "Full price"
|
group_discounts_full: "Full price"
|
||||||
group_discounts_2nd: "Subscriptions 2-11"
|
group_discounts_2nd: "Subscriptions 2-11"
|
||||||
|
@ -611,7 +612,6 @@
|
||||||
how_much_2: "monthly subscription"
|
how_much_2: "monthly subscription"
|
||||||
how_much_3: "costs $9.99, and can be cancelled anytime."
|
how_much_3: "costs $9.99, and can be cancelled anytime."
|
||||||
how_much_4: "Additionally, we provide discounts for larger groups:"
|
how_much_4: "Additionally, we provide discounts for larger groups:"
|
||||||
group_discounts_1: "We also offer group discounts for bulk subscriptions."
|
|
||||||
sys_requirements_title: "System Requirements"
|
sys_requirements_title: "System Requirements"
|
||||||
sys_requirements_1: "A modern web browser. Newer versions of Chrome, Firefox, or Safari. Internet Explorer 9 or later."
|
sys_requirements_1: "A modern web browser. Newer versions of Chrome, Firefox, or Safari. Internet Explorer 9 or later."
|
||||||
sys_requirements_2: "CodeCombat is not supported on iPad yet."
|
sys_requirements_2: "CodeCombat is not supported on iPad yet."
|
||||||
|
|
|
@ -27,6 +27,7 @@ class CocoModel extends Backbone.Model
|
||||||
# if fixed, RevertModal will also need the fix
|
# if fixed, RevertModal will also need the fix
|
||||||
|
|
||||||
setProjection: (project) ->
|
setProjection: (project) ->
|
||||||
|
# TODO: ends up getting done twice, since the URL is modified and the @project is modified. So don't do this, just set project directly... (?)
|
||||||
return if project is @project
|
return if project is @project
|
||||||
url = @getURL()
|
url = @getURL()
|
||||||
url += '&project=' unless /project=/.test url
|
url += '&project=' unless /project=/.test url
|
||||||
|
|
|
@ -88,7 +88,7 @@ _.extend LevelSessionSchema.properties,
|
||||||
type: 'boolean' # Not tracked any more
|
type: 'boolean' # Not tracked any more
|
||||||
frame:
|
frame:
|
||||||
type: 'number' # Not tracked any more
|
type: 'number' # Not tracked any more
|
||||||
thangs:
|
thangs: # ... what is this? Is this used?
|
||||||
type: 'object'
|
type: 'object'
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
title: 'Thang'
|
title: 'Thang'
|
||||||
|
@ -241,7 +241,7 @@ _.extend LevelSessionSchema.properties,
|
||||||
description: 'The date a match was computed.'
|
description: 'The date a match was computed.'
|
||||||
playtime:
|
playtime:
|
||||||
title: 'Playtime so far'
|
title: 'Playtime so far'
|
||||||
description: 'The total seconds of playtime on this session when the match was computed.'
|
description: 'The total seconds of playtime on this session when the match was computed. Not currently tracked.'
|
||||||
type: 'number'
|
type: 'number'
|
||||||
metrics:
|
metrics:
|
||||||
type: 'object'
|
type: 'object'
|
||||||
|
|
|
@ -47,6 +47,9 @@ block content
|
||||||
tr
|
tr
|
||||||
th User Start
|
th User Start
|
||||||
th Sub Start
|
th Sub Start
|
||||||
|
if subscriberCancelled
|
||||||
|
th Cancelled
|
||||||
|
else
|
||||||
th
|
th
|
||||||
th
|
th
|
||||||
//- th Name
|
//- th Name
|
||||||
|
|
|
@ -16,9 +16,9 @@ block modal-body-content
|
||||||
p(data-i18n="contact.subscriber_support") Since you're a CodeCombat subscriber, your email will get our priority support.
|
p(data-i18n="contact.subscriber_support") Since you're a CodeCombat subscriber, your email will get our priority support.
|
||||||
else
|
else
|
||||||
p
|
p
|
||||||
span(data-i18n="contact.subscribe_prefix") If you need help figuring out a level, please
|
span.spr(data-i18n="contact.subscribe_prefix") If you need help figuring out a level, please
|
||||||
a.spl.spr(data-toggle="coco-modal", data-target="core/SubscribeModal", data-i18n="contact.subscribe") buy a CodeCombat subscription
|
a(data-toggle="coco-modal", data-target="core/SubscribeModal", data-i18n="contact.subscribe") buy a CodeCombat subscription
|
||||||
span(data-i18n="contact.subscribe_suffix") and we'll be happy to help you with your code.
|
span.spl(data-i18n="contact.subscribe_suffix") and we'll be happy to help you with your code.
|
||||||
.form
|
.form
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(for="contact-email", data-i18n="general.email") Email
|
label.control-label(for="contact-email", data-i18n="general.email") Email
|
||||||
|
|
|
@ -3,8 +3,6 @@ template = require 'templates/admin/analytics-subscriptions'
|
||||||
ThangType = require 'models/ThangType'
|
ThangType = require 'models/ThangType'
|
||||||
User = require 'models/User'
|
User = require 'models/User'
|
||||||
|
|
||||||
# TODO: Add last N subscribers table
|
|
||||||
# TODO: Add revenue line
|
|
||||||
# TODO: Graphing code copied/mangled from campaign editor level view. OMG, DRY.
|
# TODO: Graphing code copied/mangled from campaign editor level view. OMG, DRY.
|
||||||
|
|
||||||
require 'vendor/d3'
|
require 'vendor/d3'
|
||||||
|
@ -12,10 +10,11 @@ require 'vendor/d3'
|
||||||
module.exports = class AnalyticsSubscriptionsView extends RootView
|
module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
id: 'admin-analytics-subscriptions-view'
|
id: 'admin-analytics-subscriptions-view'
|
||||||
template: template
|
template: template
|
||||||
|
targetSubCount: 2000
|
||||||
|
|
||||||
constructor: (options) ->
|
constructor: (options) ->
|
||||||
super options
|
super options
|
||||||
@resetData()
|
@resetSubscriptionsData()
|
||||||
if me.isAdmin()
|
if me.isAdmin()
|
||||||
@refreshData()
|
@refreshData()
|
||||||
_.delay (=> @refreshData()), 30 * 60 * 1000
|
_.delay (=> @refreshData()), 30 * 60 * 1000
|
||||||
|
@ -25,6 +24,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
context.analytics = @analytics ? graphs: []
|
context.analytics = @analytics ? graphs: []
|
||||||
context.subs = _.cloneDeep(@subs ? []).reverse()
|
context.subs = _.cloneDeep(@subs ? []).reverse()
|
||||||
context.subscribers = @subscribers ? []
|
context.subscribers = @subscribers ? []
|
||||||
|
context.subscriberCancelled = _.find context.subscribers, (subscriber) -> subscriber.cancel
|
||||||
context.total = @total ? 0
|
context.total = @total ? 0
|
||||||
context.cancelled = @cancelled ? 0
|
context.cancelled = @cancelled ? 0
|
||||||
context.monthlyChurn = @monthlyChurn ? 0.0
|
context.monthlyChurn = @monthlyChurn ? 0.0
|
||||||
|
@ -35,16 +35,17 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
super()
|
super()
|
||||||
@updateAnalyticsGraphs()
|
@updateAnalyticsGraphs()
|
||||||
|
|
||||||
resetData: ->
|
resetSubscriptionsData: ->
|
||||||
@analytics = graphs: []
|
@analytics = graphs: []
|
||||||
@subs = []
|
@subs = []
|
||||||
@total = 0
|
@total = 0
|
||||||
@cancelled = 0
|
@cancelled = 0
|
||||||
@monthlyChurn = 0.0
|
@monthlyChurn = 0.0
|
||||||
|
@monthlyGrowth = 0.0
|
||||||
|
|
||||||
refreshData: ->
|
refreshData: ->
|
||||||
return unless me.isAdmin()
|
return unless me.isAdmin()
|
||||||
@resetData()
|
@resetSubscriptionsData()
|
||||||
@getSubscribers()
|
@getSubscribers()
|
||||||
@getSubscriptions()
|
@getSubscriptions()
|
||||||
|
|
||||||
|
@ -75,7 +76,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
console.error 'Failed to get subscriptions', response
|
console.error 'Failed to get subscriptions', response
|
||||||
options.success = (subs, response, options) =>
|
options.success = (subs, response, options) =>
|
||||||
return if @destroyed
|
return if @destroyed
|
||||||
@resetData()
|
@resetSubscriptionsData()
|
||||||
subDayMap = {}
|
subDayMap = {}
|
||||||
for sub in subs
|
for sub in subs
|
||||||
startDay = sub.start.substring(0, 10)
|
startDay = sub.start.substring(0, 10)
|
||||||
|
@ -121,6 +122,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
# TODO: Where should this metadata live?
|
# TODO: Where should this metadata live?
|
||||||
# TODO: lineIDs assumed to be unique across graphs
|
# TODO: lineIDs assumed to be unique across graphs
|
||||||
totalSubsID = 'total-subs'
|
totalSubsID = 'total-subs'
|
||||||
|
targetSubsID = 'target-subs'
|
||||||
startedSubsID = 'started-subs'
|
startedSubsID = 'started-subs'
|
||||||
cancelledSubsID = 'cancelled-subs'
|
cancelledSubsID = 'cancelled-subs'
|
||||||
netSubsID = 'net-subs'
|
netSubsID = 'net-subs'
|
||||||
|
@ -129,6 +131,11 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
description: 'Total Active Subscriptions'
|
description: 'Total Active Subscriptions'
|
||||||
color: 'green'
|
color: 'green'
|
||||||
strokeWidth: 1
|
strokeWidth: 1
|
||||||
|
lineMetadata[targetSubsID] =
|
||||||
|
description: 'Target Total Subscriptions'
|
||||||
|
color: 'gold'
|
||||||
|
strokeWidth: 4
|
||||||
|
opacity: 1.0
|
||||||
lineMetadata[startedSubsID] =
|
lineMetadata[startedSubsID] =
|
||||||
description: 'New Subscriptions'
|
description: 'New Subscriptions'
|
||||||
color: 'blue'
|
color: 'blue'
|
||||||
|
@ -185,8 +192,9 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
points: levelPoints
|
points: levelPoints
|
||||||
description: lineMetadata[totalSubsID].description
|
description: lineMetadata[totalSubsID].description
|
||||||
lineColor: lineMetadata[totalSubsID].color
|
lineColor: lineMetadata[totalSubsID].color
|
||||||
|
strokeWidth: lineMetadata[totalSubsID].strokeWidth
|
||||||
min: 0
|
min: 0
|
||||||
max: d3.max(@subs, (d) -> d.total)
|
max: Math.max(@targetSubCount, d3.max(@subs, (d) -> d.total))
|
||||||
|
|
||||||
## Started
|
## Started
|
||||||
|
|
||||||
|
@ -219,9 +227,34 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
points: levelPoints
|
points: levelPoints
|
||||||
description: lineMetadata[startedSubsID].description
|
description: lineMetadata[startedSubsID].description
|
||||||
lineColor: lineMetadata[startedSubsID].color
|
lineColor: lineMetadata[startedSubsID].color
|
||||||
|
strokeWidth: lineMetadata[startedSubsID].strokeWidth
|
||||||
min: 0
|
min: 0
|
||||||
max: d3.max(@subs, (d) -> d.started)
|
max: d3.max(@subs, (d) -> d.started)
|
||||||
|
|
||||||
|
## Total subs target
|
||||||
|
|
||||||
|
# Build line data
|
||||||
|
levelPoints = []
|
||||||
|
for sub, i in @subs
|
||||||
|
levelPoints.push
|
||||||
|
x: i
|
||||||
|
y: @targetSubCount
|
||||||
|
day: sub.day
|
||||||
|
pointID: "#{targetSubsID}#{i}"
|
||||||
|
values: []
|
||||||
|
|
||||||
|
levelPoints.splice(0, levelPoints.length - timeframeDays) if levelPoints.length > timeframeDays
|
||||||
|
|
||||||
|
@analytics.graphs[0].lines.push
|
||||||
|
lineID: targetSubsID
|
||||||
|
enabled: true
|
||||||
|
points: levelPoints
|
||||||
|
description: lineMetadata[targetSubsID].description
|
||||||
|
lineColor: lineMetadata[targetSubsID].color
|
||||||
|
strokeWidth: lineMetadata[targetSubsID].strokeWidth
|
||||||
|
min: 0
|
||||||
|
max: @targetSubCount
|
||||||
|
|
||||||
## Cancelled
|
## Cancelled
|
||||||
averageCancelled = 0
|
averageCancelled = 0
|
||||||
|
|
||||||
|
@ -258,6 +291,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
points: levelPoints
|
points: levelPoints
|
||||||
description: lineMetadata[cancelledSubsID].description
|
description: lineMetadata[cancelledSubsID].description
|
||||||
lineColor: lineMetadata[cancelledSubsID].color
|
lineColor: lineMetadata[cancelledSubsID].color
|
||||||
|
strokeWidth: lineMetadata[cancelledSubsID].strokeWidth
|
||||||
min: 0
|
min: 0
|
||||||
max: d3.max(@subs, (d) -> d.started)
|
max: d3.max(@subs, (d) -> d.started)
|
||||||
|
|
||||||
|
@ -333,7 +367,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
xRange = d3.scale.linear().range([0, width]).domain([d3.min(line.points, (d) -> d.x), d3.max(line.points, (d) -> d.x)])
|
xRange = d3.scale.linear().range([0, width]).domain([d3.min(line.points, (d) -> d.x), d3.max(line.points, (d) -> d.x)])
|
||||||
yRange = d3.scale.linear().range([height, 0]).domain([line.min, line.max])
|
yRange = d3.scale.linear().range([height, 0]).domain([line.min, line.max])
|
||||||
|
|
||||||
# x-Axis and guideline once
|
# x-Axis
|
||||||
if currentLine is 0
|
if currentLine is 0
|
||||||
startDay = new Date(line.points[0].day)
|
startDay = new Date(line.points[0].day)
|
||||||
endDay = new Date(line.points[line.points.length - 1].day)
|
endDay = new Date(line.points[line.points.length - 1].day)
|
||||||
|
@ -392,7 +426,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
svg.append("text")
|
svg.append("text")
|
||||||
.attr("x", margin + 40 + 10)
|
.attr("x", margin + 40 + 10)
|
||||||
.attr("y", margin + height + xAxisHeight + keyHeight * currentLine + (keyHeight + 10) / 2)
|
.attr("y", margin + height + xAxisHeight + keyHeight * currentLine + (keyHeight + 10) / 2)
|
||||||
.attr("fill", line.lineColor)
|
.attr("fill", if line.lineColor is 'gold' then 'orange' else line.lineColor)
|
||||||
.attr("class", "key-text")
|
.attr("class", "key-text")
|
||||||
.text(line.description)
|
.text(line.description)
|
||||||
|
|
||||||
|
|
|
@ -299,7 +299,12 @@ module.exports = class CampaignView extends RootView
|
||||||
unless foundNext
|
unless foundNext
|
||||||
for nextLevelOriginal in level.nextLevels
|
for nextLevelOriginal in level.nextLevels
|
||||||
nextLevel = _.find levels, original: nextLevelOriginal
|
nextLevel = _.find levels, original: nextLevelOriginal
|
||||||
if nextLevel and not nextLevel.locked and @levelStatusMap[nextLevel.slug] isnt 'complete' and (me.isPremium() or not nextLevel.requiresSubscription or nextLevel.slug is 'apocalypse')
|
if nextLevel and not nextLevel.locked and @levelStatusMap[nextLevel.slug] isnt 'complete' and (
|
||||||
|
me.isPremium() or
|
||||||
|
not nextLevel.requiresSubscription or
|
||||||
|
nextLevel.slug is 'apocalypse' or
|
||||||
|
(nextLevel.slug is 'favorable-odds' and not @levelStatusMap['the-raised-sword'])
|
||||||
|
)
|
||||||
nextLevel.next = true
|
nextLevel.next = true
|
||||||
foundNext = true
|
foundNext = true
|
||||||
break
|
break
|
||||||
|
|
|
@ -19,7 +19,9 @@ module.exports = class LeaderboardModal extends ModalView
|
||||||
constructor: (options) ->
|
constructor: (options) ->
|
||||||
super options
|
super options
|
||||||
@levelSlug = @options.levelSlug
|
@levelSlug = @options.levelSlug
|
||||||
@level = @supermodel.loadModel(new Level({_id: @levelSlug}, {project: ['name', 'i18n', 'scoreType', 'original']}), 'level').model
|
level = new Level({_id: @levelSlug})
|
||||||
|
level.project = ['name', 'i18n', 'scoreType', 'original']
|
||||||
|
@level = @supermodel.loadModel(level, 'level').model
|
||||||
|
|
||||||
getRenderData: (c) ->
|
getRenderData: (c) ->
|
||||||
c = super c
|
c = super c
|
||||||
|
|
|
@ -206,10 +206,11 @@ module.exports = class Handler
|
||||||
return @sendForbiddenError(res)
|
return @sendForbiddenError(res)
|
||||||
|
|
||||||
getById: (req, res, id) ->
|
getById: (req, res, id) ->
|
||||||
# return @sendNotFoundError(res) # for testing
|
|
||||||
return @sendForbiddenError(res) unless @hasAccess(req)
|
return @sendForbiddenError(res) unless @hasAccess(req)
|
||||||
|
if req.query.project
|
||||||
@getDocumentForIdOrSlug id, (err, document) =>
|
projection = {}
|
||||||
|
projection[field] = 1 for field in req.query.project.split(',')
|
||||||
|
@getDocumentForIdOrSlug id, projection, (err, document) =>
|
||||||
return @sendDatabaseError(res, err) if err
|
return @sendDatabaseError(res, err) if err
|
||||||
return @sendNotFoundError(res) unless document?
|
return @sendNotFoundError(res) unless document?
|
||||||
return @sendForbiddenError(res) unless @hasAccessToDocument(req, document)
|
return @sendForbiddenError(res) unless @hasAccessToDocument(req, document)
|
||||||
|
@ -491,13 +492,17 @@ module.exports = class Handler
|
||||||
|
|
||||||
@isID: (id) -> _.isString(id) and id.length is 24 and id.match(/[a-f0-9]/gi)?.length is 24
|
@isID: (id) -> _.isString(id) and id.length is 24 and id.match(/[a-f0-9]/gi)?.length is 24
|
||||||
|
|
||||||
getDocumentForIdOrSlug: (idOrSlug, done) ->
|
getDocumentForIdOrSlug: (idOrSlug, projection, done) ->
|
||||||
|
unless done
|
||||||
|
done = projection # projection is optional argument
|
||||||
|
projection = null
|
||||||
idOrSlug = idOrSlug+''
|
idOrSlug = idOrSlug+''
|
||||||
if Handler.isID(idOrSlug)
|
if Handler.isID(idOrSlug)
|
||||||
@modelClass.findById(idOrSlug).exec (err, document) ->
|
query = @modelClass.findById(idOrSlug)
|
||||||
done(err, document)
|
|
||||||
else
|
else
|
||||||
@modelClass.findOne {slug: idOrSlug}, (err, document) ->
|
query = @modelClass.findOne {slug: idOrSlug}
|
||||||
|
query.select projection if projection
|
||||||
|
query.exec (err, document) ->
|
||||||
done(err, document)
|
done(err, document)
|
||||||
|
|
||||||
doWaterfallChecks: (req, document, done) ->
|
doWaterfallChecks: (req, document, done) ->
|
||||||
|
|
|
@ -158,7 +158,8 @@ LevelHandler = class LevelHandler extends Handler
|
||||||
majorVersion: level.version.major
|
majorVersion: level.version.major
|
||||||
creator: req.user._id+''
|
creator: req.user._id+''
|
||||||
|
|
||||||
query = Session.find(sessionQuery).select('-screenshot')
|
query = Session.find(sessionQuery).select('-screenshot -transpiledCode')
|
||||||
|
# TODO: take out "code" as well, since that can get huge containing the transpiled code for the lat hero, and find another way of having the LadderSubmissionViews in the MyMatchesTab determine rankin readiness
|
||||||
query.exec (err, results) =>
|
query.exec (err, results) =>
|
||||||
if err then @sendDatabaseError(res, err) else @sendSuccess res, results
|
if err then @sendDatabaseError(res, err) else @sendSuccess res, results
|
||||||
|
|
||||||
|
|
|
@ -527,11 +527,11 @@ updateMatchesInSession = (matchObject, sessionID, callback) ->
|
||||||
opponentsArray = _.toArray opponentsClone
|
opponentsArray = _.toArray opponentsClone
|
||||||
currentMatchObject.opponents = opponentsArray
|
currentMatchObject.opponents = opponentsArray
|
||||||
currentMatchObject.codeLanguage = matchObject.opponents[opponentsArray[0].sessionID].codeLanguage
|
currentMatchObject.codeLanguage = matchObject.opponents[opponentsArray[0].sessionID].codeLanguage
|
||||||
currentMatchObject.simulator = @clientResponseObject.simulator
|
#currentMatchObject.simulator = @clientResponseObject.simulator # Uncomment when actively debugging simulation mismatches
|
||||||
currentMatchObject.randomSeed = parseInt(@clientResponseObject.randomSeed or 0, 10)
|
#currentMatchObject.randomSeed = parseInt(@clientResponseObject.randomSeed or 0, 10) # Uncomment when actively debugging simulation mismatches
|
||||||
LevelSession.findOne {'_id': sessionID}, (err, session) ->
|
LevelSession.findOne {'_id': sessionID}, (err, session) ->
|
||||||
session = session.toObject()
|
session = session.toObject()
|
||||||
currentMatchObject.playtime = session.playtime ? 0
|
#currentMatchObject.playtime = session.playtime ? 0 # Not useful if we can only see last 200
|
||||||
sessionUpdateObject =
|
sessionUpdateObject =
|
||||||
$push: {matches: {$each: [currentMatchObject], $slice: -200}}
|
$push: {matches: {$each: [currentMatchObject], $slice: -200}}
|
||||||
#log.info "Updating session #{sessionID}"
|
#log.info "Updating session #{sessionID}"
|
||||||
|
|
Loading…
Reference in a new issue