mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-26 14:03:28 -04:00
Update campaign analytics scripts
This commit is contained in:
parent
31eb6e6045
commit
e0c88cf146
2 changed files with 173 additions and 63 deletions
scripts/analytics/mongodb/queries
|
@ -1,65 +1,41 @@
|
|||
// Average level playtimes by campaign
|
||||
// Average level playtimes in seconds by campaign, broken up by course and campaign levels
|
||||
|
||||
// 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
|
||||
// NOTE: faster to ask for one level at a time.
|
||||
|
||||
// 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 courseCampaigns = ['intro', 'course-2', 'course-3', 'course-4'];
|
||||
var individualCampaigns = ['dungeon', 'forest', 'desert', 'mountain'];
|
||||
|
||||
var scriptStartTime = new Date();
|
||||
var startDay = '2015-07-01';
|
||||
var endDay = '2015-08-06';
|
||||
var startDay = '2015-12-06';
|
||||
var endDay = '2015-12-13';
|
||||
|
||||
log("Dates: " + startDay + " to " + endDay);
|
||||
print("Dates: " + startDay + " to " + endDay);
|
||||
|
||||
// Print out playtimes for each campaign
|
||||
var campaigns = getCampaigns();
|
||||
var campaigns = getCampaigns(courseCampaigns);
|
||||
|
||||
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];
|
||||
print(campaign.slug);
|
||||
print("Sessions\tAverage\tSessions\tAverage\tLevel");
|
||||
for (var j = 0; j < campaign.levelSlugs.length; j++) {
|
||||
var levelSlug = campaign.levelSlugs[j];
|
||||
var levelPlaytimes = getPlaytimes([levelSlug]);
|
||||
if (levelPlaytimes[levelSlug]) {
|
||||
print(levelPlaytimes[levelSlug].campaign.count,
|
||||
'\t', levelPlaytimes[levelSlug].campaign.average,
|
||||
'\t', levelPlaytimes[levelSlug].course.count,
|
||||
'\t', levelPlaytimes[levelSlug].course.average,
|
||||
'\t', levelSlug);
|
||||
}
|
||||
else {
|
||||
print("0\t0\t" + levelSlug);
|
||||
print(0, '\t', 0, '\t', 0, '\t', 0, '\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;
|
||||
}
|
||||
|
||||
|
@ -79,32 +55,32 @@ function objectIdWithTimestamp(timestamp) {
|
|||
return constructedObjectId
|
||||
}
|
||||
|
||||
function getCampaigns() {
|
||||
function getCampaigns(campaignSlugs) {
|
||||
var campaigns = [];
|
||||
var cursor = db.campaigns.find({}, {slug: 1, levels: 1});
|
||||
var cursor = db.campaigns.find({slug: {$in: campaignSlugs}}, {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: []};
|
||||
var campaign = {slug: doc.slug, levelSlugs: []};
|
||||
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);
|
||||
}
|
||||
campaign.levelSlugs.push(doc.levels[levelID].slug);
|
||||
}
|
||||
campaigns.push(campaign);
|
||||
}
|
||||
|
||||
campaigns.sort(function (a, b) {
|
||||
if (campaignSlugs.indexOf(a.slug) < campaignSlugs.indexOf(b.slug)){
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
return campaigns;
|
||||
}
|
||||
|
||||
function getPlaytimes(levelSlugs) {
|
||||
// printjson(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({
|
||||
|
@ -116,21 +92,49 @@ function getPlaytimes(levelSlugs) {
|
|||
{_id: {$gte: startObj}},
|
||||
{_id: {$lt: endObj}}
|
||||
]
|
||||
});
|
||||
}, {heroConfig: 1, levelID: 1, playtime: 1});
|
||||
|
||||
var playtimes = {};
|
||||
while (cursor.hasNext()) {
|
||||
var myDoc = cursor.next();
|
||||
var levelID = myDoc.levelID;
|
||||
if (!playtimes[levelID]) playtimes[levelID] = [];
|
||||
playtimes[levelID].push(myDoc.playtime);
|
||||
|
||||
if (!playtimes[levelID]) playtimes[levelID] = {campaign: [], course: []};
|
||||
if (myDoc.heroConfig) {
|
||||
playtimes[levelID].campaign.push(myDoc.playtime);
|
||||
}
|
||||
else {
|
||||
playtimes[levelID].course.push(myDoc.playtime);
|
||||
}
|
||||
}
|
||||
// printjson(playtimes);
|
||||
|
||||
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);
|
||||
var campaignTotal = 0;
|
||||
var courseTotal = 0;
|
||||
if (playtimes[levelID].campaign.length > 0) {
|
||||
campaignTotal = playtimes[levelID].campaign.reduce(function(a, b) {return a + b;});
|
||||
}
|
||||
if (playtimes[levelID].course.length > 0) {
|
||||
courseTotal = playtimes[levelID].course.reduce(function(a, b) {return a + b;});
|
||||
}
|
||||
|
||||
var campaignAverage = parseInt(playtimes[levelID].campaign.length > 0 ? parseInt(campaignTotal / playtimes[levelID].campaign.length): 0);
|
||||
var courseAverage = parseInt(playtimes[levelID].course.length > 0 ? parseInt(courseTotal / playtimes[levelID].course.length): 0);
|
||||
|
||||
data[levelID] = {
|
||||
campaign: {
|
||||
count: playtimes[levelID].campaign.length,
|
||||
total: campaignTotal,
|
||||
average: campaignAverage
|
||||
},
|
||||
course: {
|
||||
count: playtimes[levelID].course.length,
|
||||
total: courseTotal,
|
||||
average: courseAverage
|
||||
}
|
||||
};
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
|
106
scripts/analytics/mongodb/queries/campaignCompletionCounts.js
Normal file
106
scripts/analytics/mongodb/queries/campaignCompletionCounts.js
Normal file
|
@ -0,0 +1,106 @@
|
|||
// Campaign completion counts
|
||||
|
||||
// Usage:
|
||||
// mongo <address>:<port>/<database> <script file> -u <username> -p <password>
|
||||
|
||||
var courseCampaigns = ['intro', 'course-2', 'course-3', 'course-4'];
|
||||
var individualCampaigns = ['dungeon', 'forest', 'desert', 'mountain'];
|
||||
|
||||
var scriptStartTime = new Date();
|
||||
var startDay = '2015-11-08';
|
||||
var endDay = '2015-11-15'; // Not inclusive
|
||||
|
||||
log("Dates: " + startDay + " to " + endDay);
|
||||
|
||||
var campaigns = getCampaigns(courseCampaigns);
|
||||
// var campaigns = getCampaigns(individualCampaigns);
|
||||
// printjson(campaigns);
|
||||
|
||||
for (var i = 0; i < campaigns.length; i++) {
|
||||
var campaign = campaigns[i];
|
||||
print(campaign.slug);
|
||||
print("Total\tCampaign\tCourse\tLevel");
|
||||
var completionCounts = getCompletionCounts(campaign.levelSlugs);
|
||||
for (var j = 0; j < campaign.levelSlugs.length; j++) {
|
||||
var levelSlug = campaign.levelSlugs[j];
|
||||
if (completionCounts[levelSlug]) {
|
||||
print(completionCounts[levelSlug].campaign + completionCounts[levelSlug].course,
|
||||
'\t', completionCounts[levelSlug].campaign,
|
||||
'\t', completionCounts[levelSlug].course,
|
||||
'\t', levelSlug);
|
||||
}
|
||||
else {
|
||||
print(0, '\t', 0, '\t', 0, '\t', levelSlug);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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(campaignSlugs) {
|
||||
var campaigns = [];
|
||||
var cursor = db.campaigns.find({slug: {$in: campaignSlugs}}, {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, levelSlugs: []};
|
||||
for (var levelID in doc.levels) {
|
||||
campaign.levelSlugs.push(doc.levels[levelID].slug);
|
||||
}
|
||||
campaigns.push(campaign);
|
||||
}
|
||||
|
||||
campaigns.sort(function (a, b) {
|
||||
if (campaignSlugs.indexOf(a.slug) < campaignSlugs.indexOf(b.slug)){
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
return campaigns;
|
||||
}
|
||||
|
||||
function getCompletionCounts(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},
|
||||
{levelID: {$in: levelSlugs}},
|
||||
{_id: {$gte: startObj}},
|
||||
{_id: {$lt: endObj}}
|
||||
]
|
||||
}, {heroConfig: 1, levelID: 1});
|
||||
|
||||
var completionCounts = {};
|
||||
while (cursor.hasNext()) {
|
||||
var myDoc = cursor.next();
|
||||
var levelID = myDoc.levelID;
|
||||
|
||||
if (!completionCounts[levelID]) completionCounts[levelID] = {campaign: 0, course: 0};
|
||||
if (myDoc.heroConfig) {
|
||||
completionCounts[levelID].campaign++;
|
||||
}
|
||||
else {
|
||||
completionCounts[levelID].course++;
|
||||
}
|
||||
}
|
||||
|
||||
return completionCounts;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue