// Average level playtimes by campaign // Usage: // mongo <address>:<port>/<database> <script file> -u <username> -p <password> // NOTE: faster to use find() instead of aggregate() // NOTE: faster to ask for one level at a time. also keeps levels in campaign order // Excluded for one reason or another // Some relevant code: https://github.com/codecombat/codecombat/blob/master/app/views/play/CampaignView.coffee#L281-L292 var excludedLevels = ['deadly-dungeon-rescue', 'kithgard-brawl', 'cavern-survival', 'kithgard-mastery', 'destroying-angel', 'kithgard-apprentice', 'wild-horses', 'lost-viking', 'forest-flower-grove', 'boulder-woods', 'the-trials']; var scriptStartTime = new Date(); var startDay = '2015-05-10'; var endDay = '2015-06-11'; log("Dates: " + startDay + " to " + endDay); // Print out playtimes for each campaign var campaigns = getCampaigns(); for (var i = 0; i < campaigns.length; i++) { var campaign = campaigns[i]; // if (campaign.slug !== 'dungeon') continue; print(campaign.slug + " (free)"); var total = 0; for (var j = 0; j < campaign.free.length; j++) { var levelSlug = campaign.free[j]; if (excludedLevels.indexOf(levelSlug) >= 0) continue; var data = getPlaytimes([levelSlug]); print(data[levelSlug].average + "\t" + data[levelSlug].count + "\t" + levelSlug); total += data[levelSlug]; } // print(parseInt(total/60/60) + "\t\t total hours"); total = 0; print(campaign.slug + " (paid)"); for (var j = 0; j < campaign.paid.length; j++) { var levelSlug = campaign.paid[j]; if (excludedLevels.indexOf(levelSlug) >= 0) continue; var data = getPlaytimes([levelSlug]); if (data[levelSlug]) { print(data[levelSlug].average + "\t" + data[levelSlug].count + "\t" + levelSlug); total += data[levelSlug]; } else { print("0\t0\t" + levelSlug); } } // print(parseInt(total/60/60) + "\t\t total hours"); total = 0; print(campaign.slug + " (replayable)"); for (var j = 0; j < campaign.replayable.length; j++) { var levelSlug = campaign.replayable[j]; if (excludedLevels.indexOf(levelSlug) >= 0) continue; var data = getPlaytimes([levelSlug]); print(data[levelSlug].average + "\t" + data[levelSlug].count + "\t" + levelSlug); total += data[levelSlug]; } // print(parseInt(total/60/60) + "\t\t total hours"); // break; } log("Script runtime: " + (new Date() - scriptStartTime)); function log(str) { print(new Date().toISOString() + " " + str); } function objectIdWithTimestamp(timestamp) { // Convert string date to Date object (otherwise assume timestamp is a date) if (typeof(timestamp) == 'string') timestamp = new Date(timestamp); // Convert date object to hex seconds since Unix epoch var hexSeconds = Math.floor(timestamp/1000).toString(16); // Create an ObjectId with that hex timestamp var constructedObjectId = ObjectId(hexSeconds + "0000000000000000"); return constructedObjectId } function getCampaigns() { var campaigns = []; var cursor = db.campaigns.find({}, {slug: 1, levels: 1}); var allFree = 0; var allpaid = 0; while (cursor.hasNext()) { var doc = cursor.next(); if (doc.slug === 'auditions') continue; var campaign = {slug: doc.slug, free: [], paid: [], replayable: []}; for (var levelID in doc.levels) { if (doc.levels[levelID].replayable) { campaign.replayable.push(doc.levels[levelID].slug); } else if (doc.levels[levelID].requiresSubscription) { campaign.paid.push(doc.levels[levelID].slug); } else { campaign.free.push(doc.levels[levelID].slug); } } campaigns.push(campaign); } return campaigns; } function getPlaytimes(levelSlugs) { var startObj = objectIdWithTimestamp(ISODate(startDay + "T00:00:00.000Z")); var endObj = objectIdWithTimestamp(ISODate(endDay + "T00:00:00.000Z")) var cursor = db['level.sessions'].find({ $and: [ {"state.complete": true}, {"playtime": {$gt: 0}}, {levelID: {$in: levelSlugs}}, {_id: {$gte: startObj}}, {_id: {$lt: endObj}} ] }); var playtimes = {}; while (cursor.hasNext()) { var myDoc = cursor.next(); var levelID = myDoc.levelID; if (!playtimes[levelID]) playtimes[levelID] = []; playtimes[levelID].push(myDoc.playtime); } var data = {}; for (levelID in playtimes) { var total = playtimes[levelID].reduce(function(a, b) {return a + b;}); data[levelID] = {count: playtimes[levelID].length, total: total}; data[levelID]['average'] = parseInt(total / playtimes[levelID].length); } return data; }