// 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;
}