codecombat/scripts/mongodb/migrations/2015-11-28-add-concept-stats-to-users.js

53 lines
2.4 KiB
JavaScript

// Adds up all concept statistics for all non-anoymous users.
// Usage:
// mongo <address>:<port>/<database> <script file> -u <username> -p <password>
var alreadyCompleted = 0; // For simple skipping and restarting
addConceptStatsToUsers();
function addConceptStatsToUsers() {
print("Adding concept stats to all non-anonymous users...");
var levels = db.levels.find({slug: {$exists: true}}, {campaign: 1, slug: 1, original: 1, concepts: 1, 'state.complete': 1}).toArray();
levels = levels.filter(function(level) { return level.campaign && level.concepts && level.concepts.length; });
var conceptMap = {};
levels.forEach(function(level) { conceptMap[level.original + ''] = level.concepts || []; });
print("Got concept map for", levels.length, "levels.");
var users = db.users.find({emailLower: {$exists: true}});
var usersTotal = users.count();
var usersDone = 0;
var t0 = null;
users.forEach(function(user) {
if (usersDone < alreadyCompleted) return ++usersDone;
if (!t0) t0 = new Date(); // Started processing users, so start the timer.
user.stats = user.stats || {};
user.stats.concepts = {};
var sessions = db.level.sessions.find({creator: user._id + ''});
sessions.forEach(function(session) {
if (!session.state || !session.state.complete) return;
var concepts = conceptMap[session.level.original + ''];
if (!concepts) return;
concepts.forEach(function(concept) {
user.stats.concepts[concept] = (user.stats.concepts[concept] || 0) + 1;
});
});
//print("Would say", user.name, user.email, "learned concepts", JSON.stringify(user.stats.concepts));
db.users.save(user);
if (++usersDone % 100 == 0) {
var t1 = new Date();
var elapsedSeconds = Math.round((t1 - t0) / 1000);
var remainingSeconds = Math.round((usersTotal - usersDone) / ((usersDone - alreadyCompleted) / elapsedSeconds));
print(usersDone, "\t/", usersTotal, "\t-- ", (100 * usersDone / usersTotal).toFixed(4) + "%\tElapsed:", toHHMMSS(elapsedSeconds), "\tRemaining:", toHHMMSS(remainingSeconds));
}
});
}
function toHHMMSS(rawSeconds) {
var hours = Math.floor(rawSeconds / 3600);
var minutes = Math.floor((rawSeconds - (hours * 3600)) / 60);
var seconds = rawSeconds - (hours * 3600) - (minutes * 60);
if (hours < 10) hours = "0" + hours;
if (minutes < 10) minutes = "0" + minutes;
if (seconds < 10) seconds = "0" + seconds;
return hours + ':' + minutes + ':' + seconds;
}