mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-26 22:13:32 -04:00
Campaign drop off rates script
Shows where players stop playing.
This commit is contained in:
parent
1df017b271
commit
de334b8ced
2 changed files with 244 additions and 4 deletions
scripts/analytics/mongodb/queries
244
scripts/analytics/mongodb/queries/campaignRates.js
Normal file
244
scripts/analytics/mongodb/queries/campaignRates.js
Normal file
|
@ -0,0 +1,244 @@
|
|||
// Print out campaign drop-off rates
|
||||
// Drop off: last started or finished level event
|
||||
// Adjust startDate below for different timeframe than last 7 days.
|
||||
|
||||
// Usage:
|
||||
// mongo <address>:<port>/<database> <script file> -u <username> -p <password>
|
||||
|
||||
// Ignores the order at which levels are completed
|
||||
// Ignores level skipping
|
||||
|
||||
// TODO: Is our overall drop-off rate correct?
|
||||
// TODO: What's the right time frame for this data?
|
||||
|
||||
// TODO: Calculate completion rates per-level, and campaign overall
|
||||
|
||||
var today = new Date();
|
||||
today = today.toISOString().substr(0, 10);
|
||||
print("Today is " + today);
|
||||
|
||||
var todayMinus6 = new Date();
|
||||
todayMinus6.setDate(todayMinus6.getUTCDate() - 6);
|
||||
var startDate = todayMinus6.toISOString().substr(0, 10) + "T00:00:00.000Z";
|
||||
// startDate = "2014-12-01T00:00:00.000Z";
|
||||
print("Start date is " + startDate)
|
||||
|
||||
var cursor = db['analytics.log.events'].find({
|
||||
$and: [
|
||||
{"created": { $gte: ISODate(startDate)}},
|
||||
{$or: [ {"event" : 'Started Level'}, {"event" : 'Saw Victory'}]}
|
||||
]
|
||||
});
|
||||
|
||||
var longestLevelName = -1;
|
||||
|
||||
|
||||
// Copied from WorldMapView
|
||||
var dungeonLevels = [
|
||||
'dungeons-of-kithgard',
|
||||
'gems-in-the-deep',
|
||||
'shadow-guard',
|
||||
'kounter-kithwise',
|
||||
'crawlways-of-kithgard',
|
||||
'forgetful-gemsmith',
|
||||
'true-names',
|
||||
'favorable-odds',
|
||||
'the-raised-sword',
|
||||
'haunted-kithmaze',
|
||||
'riddling-kithmaze',
|
||||
'descending-further',
|
||||
'the-second-kithmaze',
|
||||
'dread-door',
|
||||
'known-enemy',
|
||||
'master-of-names',
|
||||
'lowly-kithmen',
|
||||
'closing-the-distance',
|
||||
'tactical-strike',
|
||||
'the-final-kithmaze',
|
||||
'the-gauntlet',
|
||||
'kithgard-gates',
|
||||
'cavern-survival'
|
||||
];
|
||||
|
||||
var forestLevels = [
|
||||
'defense-of-plainswood',
|
||||
'winding-trail',
|
||||
'patrol-buster',
|
||||
'endangered-burl',
|
||||
'village-guard',
|
||||
'thornbush-farm',
|
||||
'back-to-back',
|
||||
'ogre-encampment',
|
||||
'woodland-cleaver',
|
||||
'shield-rush',
|
||||
'peasant-protection',
|
||||
'munchkin-swarm',
|
||||
'munchkin-harvest',
|
||||
'swift-dagger',
|
||||
'shrapnel',
|
||||
'arcane-ally',
|
||||
'touch-of-death',
|
||||
'bonemender',
|
||||
'coinucopia',
|
||||
'copper-meadows',
|
||||
'drop-the-flag',
|
||||
'deadly-pursuit',
|
||||
'rich-forager',
|
||||
'siege-of-stonehold',
|
||||
'multiplayer-treasure-grove',
|
||||
'dueling-grounds'
|
||||
];
|
||||
|
||||
var desertLevels = [
|
||||
'the-dunes',
|
||||
'the-mighty-sand-yak',
|
||||
'oasis',
|
||||
'sarven-road',
|
||||
'sarven-gaps',
|
||||
'thunderhooves',
|
||||
'medical-attention',
|
||||
'minesweeper',
|
||||
'sarven-sentry',
|
||||
'keeping-time',
|
||||
'hoarding-gold',
|
||||
'decoy-drill',
|
||||
'yakstraction',
|
||||
'sarven-brawl'
|
||||
];
|
||||
|
||||
var campaigns = {
|
||||
'dungeon': dungeonLevels,
|
||||
'forest': forestLevels,
|
||||
'desert': desertLevels
|
||||
};
|
||||
|
||||
// Bucketize events by user
|
||||
print("Getting event data...");
|
||||
var userProgression = {};
|
||||
while (cursor.hasNext()) {
|
||||
var doc = cursor.next();
|
||||
var created = doc.created;
|
||||
var event = doc.event;
|
||||
if (event === 'Saw Victory') var level = doc.properties.level.toLowerCase().replace(/ /g, '-');
|
||||
else var level = doc.properties.levelID
|
||||
if (level) {
|
||||
if (level.length > longestLevelName) longestLevelName = level.length;
|
||||
var user = doc.user.valueOf();
|
||||
if (!userProgression[user]) userProgression[user] = [];
|
||||
userProgression[user].push({
|
||||
created: created,
|
||||
event: event,
|
||||
level: level
|
||||
});
|
||||
}
|
||||
}
|
||||
longestLevelName += 2;
|
||||
|
||||
print("Processing data...");
|
||||
|
||||
// Order user progression by created
|
||||
for (user in userProgression) userProgression[user].sort(function (a,b) {return a.created < b.created ? -1 : 1});
|
||||
|
||||
// Per-level start/drop/finish/drop
|
||||
var levelProgression = {};
|
||||
for (user in userProgression) {
|
||||
for (var i = 0; i < userProgression[user].length; i++) {
|
||||
var event = userProgression[user][i].event;
|
||||
var level = userProgression[user][i].level;
|
||||
if (!levelProgression[level]) {
|
||||
levelProgression[level] = {
|
||||
started: 0,
|
||||
startDropped: 0,
|
||||
finished: 0,
|
||||
finishDropped: 0
|
||||
};
|
||||
}
|
||||
if (event === 'Started Level') {
|
||||
levelProgression[level].started++;
|
||||
if (i === userProgression[user].length - 1) levelProgression[level].startDropped++;
|
||||
}
|
||||
else if (event === 'Saw Victory') {
|
||||
levelProgression[level].finished++;
|
||||
if (i === userProgression[user].length - 1) levelProgression[level].finishDropped++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Put in campaign order
|
||||
// Calculate overall campaign stats
|
||||
var campaignRates = {};
|
||||
for (level in levelProgression) {
|
||||
for (campaign in campaigns) {
|
||||
if (campaigns[campaign].indexOf(level) >= 0) {
|
||||
var started = levelProgression[level].started;
|
||||
var startDropped = levelProgression[level].startDropped;
|
||||
var finished = levelProgression[level].finished;
|
||||
var finishDropped = levelProgression[level].finishDropped;
|
||||
if (!campaignRates[campaign]) {
|
||||
campaignRates[campaign] = { levels: [], overall: {
|
||||
started: 0,
|
||||
startDropped: 0,
|
||||
finished: 0,
|
||||
finishDropped: 0
|
||||
}};
|
||||
}
|
||||
campaignRates[campaign].levels.push({
|
||||
level: level,
|
||||
started: started,
|
||||
startDropped: startDropped,
|
||||
finished: finished,
|
||||
finishDropped: finishDropped
|
||||
});
|
||||
campaignRates[campaign].overall.started += started;
|
||||
campaignRates[campaign].overall.finished += finished;
|
||||
campaignRates[campaign].overall.startDropped += startDropped;
|
||||
|
||||
// Only finishDropped if on last level in campaign
|
||||
if (campaigns[campaign].indexOf(level) === campaigns[campaign].length - 1) {
|
||||
campaignRates[campaign].overall.finishDropped += finishDropped;
|
||||
}
|
||||
else {
|
||||
campaignRates[campaign].overall.startDropped += finishDropped;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort level data by campaign order
|
||||
for (campaign in campaignRates) {
|
||||
campaignRates[campaign].levels.sort(function(a, b) {
|
||||
if (campaigns[campaign].indexOf(a.level) < campaigns[campaign].indexOf(b.level)) return -1;
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
print("\nCampaign drop off rates");
|
||||
print("Where do players stop playing?");
|
||||
print("Drop-off point: last start or finish level event.");
|
||||
print("Columns: level, started the level, left after starting, finished level, left after finishing level");
|
||||
|
||||
for (campaign in campaigns) {
|
||||
print("\n" + campaign);
|
||||
var level = "level";
|
||||
var levelSpacer = new Array(longestLevelName - level.length).join(' ');
|
||||
print(level + levelSpacer + "started\tdropped\t\tfinished dropped");
|
||||
for (var i = 0; i < campaignRates[campaign].levels.length; i++) {
|
||||
var level = campaignRates[campaign].levels[i].level;
|
||||
var started = campaignRates[campaign].levels[i].started;
|
||||
var startDropped = campaignRates[campaign].levels[i].startDropped;
|
||||
var finished = campaignRates[campaign].levels[i].finished;
|
||||
var finishDropped = campaignRates[campaign].levels[i].finishDropped;
|
||||
var levelSpacer = new Array(longestLevelName - level.length).join(' ');
|
||||
print(level + levelSpacer + started + "\t" + (started < 100 ? "\t" : "") + startDropped + "\t" + (startDropped / started * 100).toFixed(2) + "%\t" + finished + "\t" + finishDropped + "\t" + (finishDropped / finished * 100).toFixed(2) + "%");
|
||||
}
|
||||
var level = 'Overall';
|
||||
var started = campaignRates[campaign].overall.started;
|
||||
var startDropped = campaignRates[campaign].overall.startDropped;
|
||||
var finished = campaignRates[campaign].overall.finished;
|
||||
var finishDropped = campaignRates[campaign].overall.finishDropped;
|
||||
var levelSpacer = new Array(longestLevelName - level.length).join(' ');
|
||||
print(level + levelSpacer + started + "\t" + (started < 100 ? "\t" : "") + startDropped + "\t" + (startDropped / started * 100).toFixed(2) + "%\t" + finished + "\t" + finishDropped + "\t" + (finishDropped / finished * 100).toFixed(2) + "%");
|
||||
}
|
|
@ -53,10 +53,6 @@ function getCompletionRates() {
|
|||
}
|
||||
}};
|
||||
|
||||
// TODO: sort by level, date,
|
||||
// var sort = {$sort: { "_id.level" : 1, "_id.created" : -1}};
|
||||
//var cursor = db['analytics.log.events'].aggregate(match, proj0, proj1, proj2, group, sort);
|
||||
// var cursor = db['analytics.log.events'].aggregate(match, proj0, group, sort);
|
||||
var cursor = db['analytics.log.events'].aggregate(match, proj0, group);
|
||||
|
||||
// <level><date><data>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue