diff --git a/lib/app/index.js b/lib/app/index.js index 44e5d6fa5f..9f3dfc97a1 100644 --- a/lib/app/index.js +++ b/lib/app/index.js @@ -197,8 +197,11 @@ ready(function(model) { }); } tour.start(); - model.on('set', '_user.tasks.*.completed', function(i, completed, previous, isLocal) { + model.on('set', '_user.tasks.*.completed', function(i, completed, previous, isLocal, passed) { var direction, from, ids, index, task, to, _ref3; + if (passed.cron != null) { + return; + } direction = function() { if (completed === true && previous === false) { return 'up'; @@ -206,7 +209,7 @@ ready(function(model) { if (completed === false && previous === true) { return 'down'; } - return console.error('Error: direction neither "up" nor "down" on checkbox set.'); + throw new Error("Direction neither 'up' nor 'down' on checkbox set."); }; task = model.at("_user.tasks." + i); Scoring.score({ diff --git a/lib/app/scoring.js b/lib/app/scoring.js new file mode 100644 index 0000000000..9451d75616 --- /dev/null +++ b/lib/app/scoring.js @@ -0,0 +1,157 @@ +// Generated by CoffeeScript 1.3.3 +var content, expModifier, hpModifier, score, tally, updateStats; + +content = require('./content'); + +expModifier = function(user, value) { + var dmg, modified; + dmg = user.get('items.weapon') * .03; + dmg += user.get('stats.lvl') * .03; + modified = value + (value * dmg); + return modified; +}; + +hpModifier = function(user, value) { + var ac, modified; + ac = user.get('items.armor') * .03; + ac += user.get('stats.lvl') * .03; + modified = value - (value * ac); + return modified; +}; + +updateStats = function(user, stats) { + var money, tnl; + if (stats.hp != null) { + if (stats.hp < 0) { + user.set('stats.lvl', 0); + } else { + user.set('stats.hp', stats.hp); + } + } + if (stats.exp != null) { + tnl = user.get('_tnl'); + if (stats.exp >= tnl) { + stats.exp -= tnl; + user.set('stats.lvl', user.get('stats.lvl') + 1); + } + if (!user.get('items.itemsEnabled') && stats.exp >= 50) { + user.set('items.itemsEnabled', true); + $('ul.items').popover({ + title: content.items.unlockedMessage.title, + placement: 'left', + trigger: 'manual', + html: true, + content: "
" + content.items.unlockedMessage.content + " [Close]
" + }); + $('ul.items').popover('show'); + } + user.set('stats.exp', stats.exp); + } + if (stats.money != null) { + if (!(typeof money !== "undefined" && money !== null) || money < 0) { + money = 0.0; + } + return user.set('stats.money', stats.money); + } +}; + +exports.score = score = function(spec) { + var adjustvalue, cron, delta, direction, exp, hp, lvl, money, sign, task, type, user, value, _ref, _ref1; + if (spec == null) { + spec = { + user: null, + task: null, + direction: null, + cron: null + }; + } + _ref = [spec.user, spec.task, spec.direction, spec.cron], user = _ref[0], task = _ref[1], direction = _ref[2], cron = _ref[3]; + sign = direction === "up" ? 1 : -1; + value = task.get('value'); + delta = value < 0 ? (-0.1 * value + 1) * sign : (Math.pow(0.9, value)) * sign; + type = task.get('type'); + adjustvalue = type !== 'reward'; + if ((type === 'habit') && (task.get("up") === false || task.get("down") === false)) { + adjustvalue = false; + } + if (adjustvalue) { + value += delta; + } + if (type === 'habit') { + if (task.get('value') !== value) { + task.push('history', { + date: new Date(), + value: value + }); + } + } + task.set('value', value); + _ref1 = [user.get('stats.money'), user.get('stats.hp'), user.get('stats.exp'), user.get('stats.lvl')], money = _ref1[0], hp = _ref1[1], exp = _ref1[2], lvl = _ref1[3]; + if (type === 'reward') { + money -= task.get('value'); + if (money < 0) { + hp += money; + money = 0; + } + } + if ((delta > 0 || (type === 'daily' || type === 'todo')) && !cron) { + exp += expModifier(user, delta); + money += delta; + } else if (type !== 'reward' && type !== 'todo') { + hp += hpModifier(user, delta); + } + updateStats(user, { + hp: hp, + exp: exp, + money: money + }); + return delta; +}; + +exports.tally = tally = function(model) { + var absVal, completed, expTally, key, lvl, task, todoTally, type, user, value, _ref; + user = model.at('_user'); + todoTally = 0; + for (key in model.get('_user.tasks')) { + task = model.at("_user.tasks." + key); + _ref = [task.get('type'), task.get('value'), task.get('completed')], type = _ref[0], value = _ref[1], completed = _ref[2]; + if (type === 'todo' || type === 'daily') { + if (!completed) { + score({ + user: user, + task: task, + direction: 'down', + cron: true + }); + } + if (type === 'daily') { + task.push("history", { + date: new Date(), + value: value + }); + } else { + absVal = completed ? Math.abs(value) : value; + todoTally += absVal; + } + if (type === 'daily') { + task.pass({ + cron: true + }).set('completed', false); + } + } + } + model.push('_user.history.todos', { + date: new Date(), + value: todoTally + }); + expTally = user.get('stats.exp'); + lvl = 0; + while (lvl < (user.get('stats.lvl') - 1)) { + lvl++; + expTally += 50 * Math.pow(lvl, 2) - 150 * lvl + 200; + } + return model.push('_user.history.exp', { + date: new Date(), + value: expTally + }); +}; diff --git a/src/app/index.coffee b/src/app/index.coffee index 0cf015e5a2..5c86304171 100644 --- a/src/app/index.coffee +++ b/src/app/index.coffee @@ -164,11 +164,12 @@ ready (model) -> # @render() # return false - model.on 'set', '_user.tasks.*.completed', (i, completed, previous, isLocal) -> + model.on 'set', '_user.tasks.*.completed', (i, completed, previous, isLocal, passed) -> + return if passed.cron? # Don't do this stuff on cron direction = () -> return 'up' if completed==true and previous == false return 'down' if completed==false and previous == true - console.error 'Error: direction neither "up" nor "down" on checkbox set.' + throw new Error("Direction neither 'up' nor 'down' on checkbox set.") # Score the user based on todo task task = model.at("_user.tasks.#{i}") diff --git a/src/app/scoring.coffee b/src/app/scoring.coffee index 0d07f17ac9..f818488e3e 100644 --- a/src/app/scoring.coffee +++ b/src/app/scoring.coffee @@ -49,6 +49,7 @@ updateStats = (user, stats) -> user.set 'stats.money', stats.money exports.score = score = (spec = {user:null, task:null, direction:null, cron:null}) -> + # console.log spec, "scoring.coffee: score( ->spec<- )" [user, task, direction, cron] = [spec.user, spec.task, spec.direction, spec.cron] # For negative values, use a line: something like y=-.1x+1 @@ -66,17 +67,10 @@ exports.score = score = (spec = {user:null, task:null, direction:null, cron:null adjustvalue = false value += delta if adjustvalue - # # up/down -voting as checkbox & assigning as completed, 2 birds one stone - # completed = task.get("completed") - # if type != 'habit' - # completed = true if direction=="up" - # completed = false if direction=="down" - # else if type == 'habit' # Add habit value to habit-history (if different) task.push 'history', { date: new Date(), value: value } if task.get('value') != value task.set('value', value) - # task.set('completed', completed) # Update the user's status [money, hp, exp, lvl] = [user.get('stats.money'), user.get('stats.hp'), user.get('stats.exp'), user.get('stats.lvl')] @@ -91,7 +85,7 @@ exports.score = score = (spec = {user:null, task:null, direction:null, cron:null # Add points to exp & money if positive delta # Only take away mony if it was a mistake (aka, a checkbox) - if delta > 0 or ( type in ['daily', 'todo'] and !cron ) + if (delta > 0 or ( type in ['daily', 'todo'])) and !cron exp += expModifier(user, delta) money += delta # Deduct from health (rewards case handled above) @@ -121,7 +115,7 @@ exports.tally = tally = (model) -> else absVal = if (completed) then Math.abs(value) else value todoTally += absVal - task.set('completed', false) if type == 'daily' + task.pass({cron:true}).set('completed', false) if type == 'daily' model.push '_user.history.todos', { date: new Date(), value: todoTally } # tally experience