mirror of
https://github.com/sudoxnym/habitica.git
synced 2026-07-17 09:22:19 +00:00
add Spooky Skins; improve report to use node.js stream-based code
This commit is contained in:
parent
34e2f23361
commit
5b333a29ab
1 changed files with 121 additions and 91 deletions
|
|
@ -1,63 +1,59 @@
|
|||
var migrationName = '20140829_change_headAccessory_to_eyewear';
|
||||
var authorName = 'Alys'; // in case script author needs to know when their ...
|
||||
var authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; //... own data is done
|
||||
|
||||
/**
|
||||
* count_users_who_own_specified_gear.js
|
||||
* database_reports/count_users_who_own_specified_gear.js
|
||||
* https://github.com/HabitRPG/habitrpg/pull/3884
|
||||
*/
|
||||
|
||||
var thingsOfInterest = {
|
||||
'Unconventional Armor ownership': {
|
||||
'data_path': 'items.gear.owned',
|
||||
'identifyOwnershipWith': 'exists',
|
||||
'items': [
|
||||
'headAccessory_special_wondercon_red',
|
||||
'headAccessory_special_wondercon_black',
|
||||
'back_special_wondercon_black',
|
||||
'back_special_wondercon_red',
|
||||
'body_special_wondercon_red',
|
||||
'body_special_wondercon_black',
|
||||
'body_special_wondercon_gold'
|
||||
],
|
||||
},
|
||||
'Spooky Skins purchases': {
|
||||
'data_path': 'purchased.skin',
|
||||
'identifyOwnershipWith': 'true',
|
||||
'items': [
|
||||
'monster',
|
||||
'pumpkin',
|
||||
'skeleton',
|
||||
'zombie',
|
||||
'ghost',
|
||||
'shadow'
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
var mongo = require('mongoskin');
|
||||
var _ = require('lodash');
|
||||
|
||||
/////////////////// UNCOMMENT *ONE* OF THESE LINES: ///////////////////
|
||||
//////////////// UNCOMMENT ONE OF THESE mongo.db LINES: ////////////////
|
||||
// var dbUsers = mongo.db('lefnire:mAdn3s5s@charlotte.mongohq.com:10015/habitrpg_large?auto_reconnect').collection('users'); // @lefnire production?
|
||||
// var dbUsers = mongo.db('localhost:27017/habitrpg_old?auto_reconnect').collection('users'); // @lefnire habitrpg_old
|
||||
var dbUsers = mongo.db('localhost:27017/habitrpg?auto_reconnect').collection('users'); // for local testing by script author (e.g., vagrant install)
|
||||
// var dbUsers = mongo.db('localhost:27017/habitrpg?auto_reconnect').collection('users'); // for local testing by script author (e.g., vagrant install)
|
||||
if (typeof dbUsers == 'undefined') { exiting(1, 'Uncomment one of the "var dbUsers" lines!'); }
|
||||
|
||||
var thingsOfInterest = {
|
||||
'items.gear.owned': [
|
||||
'headAccessory_special_wondercon_red',
|
||||
'headAccessory_special_wondercon_black',
|
||||
'back_special_wondercon_black',
|
||||
'back_special_wondercon_red',
|
||||
'body_special_wondercon_red',
|
||||
'body_special_wondercon_black',
|
||||
'body_special_wondercon_gold'
|
||||
],
|
||||
'purchased.skin': [
|
||||
'monster',
|
||||
'pumpkin',
|
||||
'skeleton',
|
||||
'zombie',
|
||||
'ghost',
|
||||
'shadow'
|
||||
]
|
||||
};
|
||||
|
||||
var thingsOfInterest = [ // TST
|
||||
'headAccessory_special_wondercon_red',
|
||||
'headAccessory_special_wondercon_black',
|
||||
'back_special_wondercon_black',
|
||||
'back_special_wondercon_red',
|
||||
'body_special_wondercon_red',
|
||||
'body_special_wondercon_black',
|
||||
'body_special_wondercon_gold'
|
||||
];
|
||||
|
||||
var query = {}; // Not worth limiting search data with query and fields since
|
||||
var fields = {}; // this will be run over a local copy of the database?
|
||||
|
||||
var thingsFound = {}; // each key is one "thing" from thingsOfInterest,
|
||||
// and the value for that key is the number of users who own it
|
||||
// (for items, 'owned' values of both true and false are counted
|
||||
// to include items lost on death)
|
||||
|
||||
var query = {}; // Not worth limiting search data with query and fields since
|
||||
var fields = {}; // this will be run over a local copy of the database?
|
||||
|
||||
console.warn('Finding data...');
|
||||
var progressCount = 1000;
|
||||
var count = 0;
|
||||
// db.users.find().forEach(function(user) { ... });
|
||||
dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) {
|
||||
if (err) { return exiting(1, 'ERROR! ' + err); }
|
||||
if (!user) {
|
||||
|
|
@ -66,61 +62,75 @@ dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) {
|
|||
}
|
||||
count++;
|
||||
|
||||
_.each(thingsOfInterest,function(obj,label){
|
||||
var data_path = obj['data_path'];
|
||||
var items = obj['items'];
|
||||
var identifyOwnershipWith = obj['identifyOwnershipWith'];
|
||||
var userOwns = path(user, data_path);
|
||||
|
||||
/*
|
||||
_.each(['costume','equipped'],function(type){
|
||||
unset['items.gear.'+type+'.headAccessory'] = "";
|
||||
set['items.gear.'+type+'.eyewear'] = newName;
|
||||
});
|
||||
_.each(oldToNew,function(newName,oldName){
|
||||
unset['items.gear.owned.'+oldName] = "";
|
||||
});
|
||||
*/
|
||||
|
||||
var owned = user.items.gear.owned;
|
||||
for (var i=0, ic=thingsOfInterest.length; i<ic; i++) {
|
||||
var thingsKey = thingsOfInterest[i];
|
||||
if (thingsKey in owned) {
|
||||
thingsFound[thingsKey] = (thingsFound[thingsKey] || 0) + 1;
|
||||
// console.warn(user.auth.local.username + ": " + thingsKey); // good for testing, bad for privacy
|
||||
}
|
||||
}
|
||||
// console.warn(JSON.stringify(thingsFound, null, " "));
|
||||
_.each(items,function(item){
|
||||
if ( (identifyOwnershipWith == 'exists' && item in userOwns) ||
|
||||
(identifyOwnershipWith == 'true' && userOwns[item])
|
||||
) {
|
||||
if (! thingsFound[label]) { thingsFound[label] = {}; }
|
||||
thingsFound[label][item] = (thingsFound[label][item] || 0) + 1;
|
||||
// console.warn(user.auth.local.username + ": " + label + ": " + item); // good for testing, bad for privacy
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (count%progressCount == 0) console.warn(count + ' ' + user._id);
|
||||
if (user._id == '9') console.warn('lefnire processed');
|
||||
if (user._id == authorUuid) console.warn(authorName + ' processed');
|
||||
if (user._id == '9' ) console.warn('lefnire' + ' processed');
|
||||
});
|
||||
|
||||
|
||||
function displayData() {
|
||||
var today = yyyymmdd(new Date());
|
||||
var report = '';
|
||||
_.each(thingsFound,function(obj,label){
|
||||
report += '"' + label + '"' + '\n';
|
||||
var header = '"date"'; // heading row in CSV data
|
||||
var data = '"' + today + '"'; // data row in CSV data
|
||||
_.each(obj,function(value,key){
|
||||
header += ',"' + key + '"';
|
||||
data += ',"' + (value || 0) + '"';
|
||||
});
|
||||
report += header + '\n' + data + '\n\n';
|
||||
});
|
||||
|
||||
var header = '"date"'; // heading row in CSV data
|
||||
var data = '"' + today + '"'; // data row in CSV data
|
||||
for (var i=0, ic=thingsOfInterest.length; i<ic; i++) {
|
||||
var thingsKey = thingsOfInterest[i];
|
||||
header += ',"' + thingsKey + '"';
|
||||
data += ',"' + (thingsFound[thingsKey] || 0) + '"';
|
||||
}
|
||||
console.log('\nCSV DATA:\n\n' +
|
||||
report +
|
||||
'\nREADABLE DATA:\n\n' +
|
||||
today + '\n' +
|
||||
JSON.stringify(thingsFound, null, ' ') +
|
||||
'\n');
|
||||
|
||||
//_.each(userResults, function(text, uuid) {
|
||||
//console.log(text); // text contains uuid
|
||||
//});
|
||||
console.warn('\n' + count + ' users searched (should be >400k)\n');
|
||||
// NB: "should be" assumes that no query filter was applied to findEach
|
||||
|
||||
console.log("\nCSV DATA:\n");
|
||||
console.log(header);
|
||||
console.log(data);
|
||||
console.log("\nREADABLE DATA:\n");
|
||||
console.log(today);
|
||||
console.log(JSON.stringify(thingsFound, null, " "));
|
||||
console.log("\n");
|
||||
|
||||
console.warn('\n' + count + ' users searched\n');
|
||||
return exiting(0);
|
||||
}
|
||||
|
||||
|
||||
function path(obj, path, def) {
|
||||
/**
|
||||
* Retrieve nested item from object/array
|
||||
* @param {Object|Array} obj
|
||||
* @param {String} path dot separated
|
||||
* @param {*} def default value ( if result undefined )
|
||||
* @returns {*}
|
||||
* http://stackoverflow.com/a/16190716
|
||||
* Usage: console.log(path(someObject, pathname));
|
||||
*/
|
||||
for(var i = 0,path = path.split('.'),len = path.length; i < len; i++){
|
||||
if(!obj || typeof obj !== 'object') return def;
|
||||
obj = obj[path[i]];
|
||||
}
|
||||
if(obj === 'undefined') return def;
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
function yyyymmdd(date) {
|
||||
var yyyy = date.getFullYear().toString();
|
||||
|
|
@ -141,29 +151,49 @@ function exiting(code, msg) {
|
|||
}
|
||||
|
||||
|
||||
/* SAMPLE OUTPUT:
|
||||
> load("count_users_who_own_specified_gear.js")
|
||||
/* SAMPLE OUTPUT (STDOUT and STDERR):
|
||||
$ node database_reports/count_users_who_own_specified_gear.js
|
||||
|
||||
Finding data...
|
||||
Alys processed
|
||||
lefnire processed
|
||||
All users found.
|
||||
|
||||
CSV DATA:
|
||||
|
||||
"Unconventional Armor ownership"
|
||||
"date","headAccessory_special_wondercon_red","headAccessory_special_wondercon_black","back_special_wondercon_black","back_special_wondercon_red","body_special_wondercon_red","body_special_wondercon_black","body_special_wondercon_gold"
|
||||
"2014-08-17","5","4","3","3","3","3","3"
|
||||
"2014-09-01","9","7","7","7","7","7","7"
|
||||
|
||||
"Spooky Skins purchases"
|
||||
"date","monster","pumpkin","skeleton","zombie","ghost","shadow"
|
||||
"2014-09-01","3","3","4","3","2","6"
|
||||
|
||||
|
||||
READABLE DATA:
|
||||
|
||||
2014-08-17
|
||||
2014-09-01
|
||||
{
|
||||
"headAccessory_special_wondercon_red": 5,
|
||||
"headAccessory_special_wondercon_black": 4,
|
||||
"back_special_wondercon_black": 3,
|
||||
"back_special_wondercon_red": 3,
|
||||
"body_special_wondercon_red": 3,
|
||||
"body_special_wondercon_black": 3,
|
||||
"body_special_wondercon_gold": 3
|
||||
"Unconventional Armor ownership": {
|
||||
"headAccessory_special_wondercon_red": 9,
|
||||
"headAccessory_special_wondercon_black": 7,
|
||||
"back_special_wondercon_black": 7,
|
||||
"back_special_wondercon_red": 7,
|
||||
"body_special_wondercon_red": 7,
|
||||
"body_special_wondercon_black": 7,
|
||||
"body_special_wondercon_gold": 7
|
||||
},
|
||||
"Spooky Skins purchases": {
|
||||
"monster": 3,
|
||||
"pumpkin": 3,
|
||||
"skeleton": 4,
|
||||
"zombie": 3,
|
||||
"ghost": 2,
|
||||
"shadow": 6
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
true
|
||||
>
|
||||
*/
|
||||
400100 users searched (should be >400k)
|
||||
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue