diff --git a/lib/app/index.js b/lib/app/index.js index 619bf96704..b3c1b4a580 100644 --- a/lib/app/index.js +++ b/lib/app/index.js @@ -1,5 +1,5 @@ // Generated by CoffeeScript 1.3.3 -var Guid, content, derby, get, getHabits, ready, view, _ref; +var Guid, content, derby, get, getHabits, ready, score, view, _ref; derby = require('derby'); @@ -13,6 +13,8 @@ content = require('./content'); Guid = require('guid'); +score = require('./score'); + view.fn('taskClasses', function(type, completed, value, hideCompleted) { var classes; classes = type; @@ -128,15 +130,6 @@ get('/:uidParam?', function(page, model, _arg) { } users.set(userId, newUser); } - model.store.accessControl = true; - model.store.readPathAccess('users.*', function(id, accept) { - console.log("model.writeAccess called with id:" + id); - return accept(id === userId); - }); - model.store.writeAccess('*', 'users.*', function(id, accept) { - console.log("model.writeAccess called with id:" + id); - return accept(id === userId); - }); return getHabits(page, model, userId); }); }); @@ -152,7 +145,7 @@ getHabits = function(page, model, userId) { potion: content.items.potion, reroll: content.items.reroll }); - model.fn('_tnl', '_user.stats.lvl', function(lvl) { + model.fn('_user._tnl', '_user.stats.lvl', function(lvl) { return 50 * Math.pow(lvl, 2) - 150 * lvl + 200; }); model.refList("_habitList", "_user.tasks", "_user.habitIds"); @@ -164,7 +157,7 @@ getHabits = function(page, model, userId) { }; ready(function(model) { - var endOfDayTally, expModifier, hpModifier, poormanscron, setupSortable, step, tour, type, updateStats, _i, _j, _len, _len1, _ref1, _ref2; + var endOfDayTally, poormanscron, setupSortable, step, tour, type, _i, _j, _len, _len1, _ref1, _ref2; model.set('_purl', window.location.origin + '/' + model.get('_userId')); $('[rel=popover]').popover(); model.on('set', '*', function() { @@ -323,59 +316,8 @@ ready(function(model) { return _results; } }; - exports.updateStats = 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 = model.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); - } - }; - expModifier = function(value) { - var dmg, modified, user; - user = model.at('_user'); - dmg = user.get('items.weapon') * .03; - dmg += user.get('stats.lvl') * .03; - modified = value + (value * dmg); - return modified; - }; - hpModifier = function(value) { - var ac, modified, user; - user = model.at('_user'); - ac = user.get('items.armor') * .03; - ac += user.get('stats.lvl') * .03; - modified = value - (value * ac); - return modified; - }; exports.vote = function(e, el, next) { - var adjustvalue, completed, delta, direction, exp, hp, lvl, money, sign, task, user, value, _ref3; + var direction, task, user; direction = $(el).attr('data-direction'); if (direction === 'true/') { direction = 'up'; @@ -383,63 +325,12 @@ ready(function(model) { if (direction === 'false/') { direction = 'down'; } - task = model.at($(el).parents('li')[0]); user = model.at('_user'); - sign = direction === "up" ? 1 : -1; - value = task.get('value'); - delta = 0; - if (value < 0) { - delta = (-0.1 * value + 1) * sign; - } else { - delta = (Math.pow(0.9, value)) * sign; - } - adjustvalue = task.get('type') !== 'reward'; - if ((task.get('type') === 'habit') && (task.get("up") === false || task.get("down") === false)) { - adjustvalue = false; - } - if (adjustvalue) { - value += delta; - } - completed = task.get("completed"); - if (task.get('type') !== 'habit') { - if (direction === "up") { - completed = true; - } - if (direction === "down") { - completed = false; - } - } else { - if (task.get('value') !== value) { - task.push('history', { - date: new Date(), - value: value - }); - } - } - task.set('value', value); - task.set('completed', completed); - _ref3 = [user.get('stats.money'), user.get('stats.hp'), user.get('stats.exp'), user.get('stats.lvl')], money = _ref3[0], hp = _ref3[1], exp = _ref3[2], lvl = _ref3[3]; - if (task.get('type') === 'reward') { - money -= task.get('value'); - if (money < 0) { - hp += money; - money = 0; - } - } - if (delta > 0 || (task.get('type') === 'daily' || task.get('type') === 'todo')) { - exp += expModifier(delta); - money += delta; - } else if (task.get('type') !== 'reward') { - hp += hpModifier(delta); - } - return updateStats(user, { - hp: hp, - exp: exp, - money: money - }); + task = model.at($(el).parents('li')[0]); + return score(user, task, direction); }; exports.endOfDayTally = endOfDayTally = function(e, el) { - var absVal, completed, expTally, hp, key, lvl, task, todoTally, user, value, _ref3; + var absVal, completed, expTally, key, lvl, task, todoTally, user, value, _ref3; user = model.at('_user'); todoTally = 0; for (key in model.get('_user.tasks')) { @@ -447,14 +338,7 @@ ready(function(model) { _ref3 = [task.get('type'), task.get('value'), task.get('completed')], type = _ref3[0], value = _ref3[1], completed = _ref3[2]; if (type === 'todo' || type === 'daily') { if (!completed) { - value += value < 0 ? (-0.1 * value + 1) * -1 : (Math.pow(0.9, value)) * -1; - task.set('value', value); - if (type === 'daily') { - hp = user.get('stats.hp') + hpModifier(value); - updateStats(user, { - hp: hp - }); - } + score(user, task, 'down', true); } if (type === 'daily') { task.push("history", { diff --git a/lib/app/score.js b/lib/app/score.js new file mode 100644 index 0000000000..fb0c024ac3 --- /dev/null +++ b/lib/app/score.js @@ -0,0 +1,109 @@ +// Generated by CoffeeScript 1.3.3 +var content, expModifier, hpModifier, 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); + } +}; + +module.exports = function(user, task, direction, cron) { + var adjustvalue, completed, delta, exp, hp, lvl, money, sign, type, value, _ref; + 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; + } + completed = task.get("completed"); + if (type !== 'habit') { + if (direction === "up") { + completed = true; + } + if (direction === "down") { + completed = false; + } + } else { + if (task.get('value') !== value) { + task.push('history', { + date: new Date(), + value: value + }); + } + } + task.set('value', value); + task.set('completed', completed); + _ref = [user.get('stats.money'), user.get('stats.hp'), user.get('stats.exp'), user.get('stats.lvl')], money = _ref[0], hp = _ref[1], exp = _ref[2], lvl = _ref[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' && cron)) { + hp += hpModifier(user, delta); + } + updateStats(user, { + hp: hp, + exp: exp, + money: money + }); + return delta; +}; diff --git a/src/app/index.coffee b/src/app/index.coffee index 8332dc28a6..bc35c3045d 100644 --- a/src/app/index.coffee +++ b/src/app/index.coffee @@ -4,6 +4,7 @@ derby.use require('derby-ui-boot') derby.use(require('../../ui')) content = require('./content') Guid = require('guid') +score = require('./score') ## VIEW HELPERS ## view.fn 'taskClasses', (type, completed, value, hideCompleted) -> @@ -76,14 +77,14 @@ get '/:uidParam?', (page, model, {uidParam}) -> when 'reward' then newUser.rewardIds.push guid users.set userId, newUser - #TODO these *Access functions aren't being called, why? - model.store.accessControl = true - model.store.readPathAccess 'users.*', (id, accept) -> - console.log "model.writeAccess called with id:#{id}" # never called - accept(id == userId) - model.store.writeAccess '*', 'users.*', (id, accept) -> - console.log "model.writeAccess called with id:#{id}" # never called - accept(id == userId) + # #TODO these *Access functions aren't being called, why? + # model.store.accessControl = true + # model.store.readPathAccess 'users.*', (id, accept) -> + # console.log "model.writeAccess called with id:#{id}" # never called + # accept(id == userId) + # model.store.writeAccess '*', 'users.*', (id, accept) -> + # console.log "model.writeAccess called with id:#{id}" # never called + # accept(id == userId) getHabits(page, model, userId) @@ -104,7 +105,7 @@ getHabits = (page, model, userId) -> reroll: content.items.reroll # http://tibia.wikia.com/wiki/Formula - model.fn '_tnl', '_user.stats.lvl', (lvl) -> 50 * Math.pow(lvl, 2) - 150 * lvl + 200 + model.fn '_user._tnl', '_user.stats.lvl', (lvl) -> 50 * Math.pow(lvl, 2) - 150 * lvl + 200 # Default Tasks model.refList "_habitList", "_user.tasks", "_user.habitIds" @@ -255,113 +256,15 @@ ready (model) -> task = model.at('_user.tasks.'+taskId) task.set('value', 0) unless task.get('type')=='reward' - # Setter for user.stats: handles death, leveling up, etc - exports.updateStats = updateStats = (user, stats) -> - if stats.hp? - # game over - if stats.hp < 0 - user.set 'stats.lvl', 0 # this signifies dead - else - user.set 'stats.hp', stats.hp - - if stats.exp? - # level up & carry-over exp - tnl = model.get '_tnl' - if stats.exp >= tnl - stats.exp -= tnl - user.set 'stats.lvl', user.get('stats.lvl') + 1 - if !user.get('items.itemsEnabled') and 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? - money = 0.0 if (!money? or money<0) - user.set 'stats.money', stats.money - - # Calculates Exp modification based on weapon & lvl - expModifier = (value) -> - user = model.at '_user' - dmg = user.get('items.weapon') * .03 # each new weapon adds an additional 3% experience - dmg += user.get('stats.lvl') * .03 # same for lvls - modified = value + (value * dmg) - return modified - - # Calculates HP-loss modification based on armor & lvl - hpModifier = (value) -> - user = model.at '_user' - ac = user.get('items.armor') * .03 # each new armor blocks an additional 3% damage - ac += user.get('stats.lvl') * .03 # same for lvls - modified = value - (value * ac) - return modified exports.vote = (e, el, next) -> direction = $(el).attr('data-direction') direction = 'up' if direction == 'true/' direction = 'down' if direction == 'false/' - - #TODO this should be model.at(el), shouldn't have to find parent + user = model.at('_user') task = model.at $(el).parents('li')[0] - user = model.at '_user' - # For negative values, use a line: something like y=-.1x+1 - # For positibe values, taper off with inverse log: y=.9^x - # Would love to use inverse log for the whole thing, but after 13 fails it hits infinity - sign = if (direction == "up") then 1 else -1 - value = task.get('value') - delta = 0 - if value < 0 - delta = (( -0.1 * value + 1 ) * sign) - else - delta = (( Math.pow(0.9, value) ) * sign) - - # Don't adjust values for rewards, or for habits that don't have both + and - - adjustvalue = (task.get('type') != 'reward') - if (task.get('type') == 'habit') and (task.get("up")==false or task.get("down")==false) - adjustvalue = false - value += delta if adjustvalue - - # up/down -voting as checkbox & assigning as completed, 2 birds one stone - completed = task.get("completed") - if task.get('type') != 'habit' - completed = true if direction=="up" - completed = false if direction=="down" - else - # 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')] - - if task.get('type') == 'reward' - # purchase item - money -= task.get('value') - # if too expensive, reduce health & zero money - if money < 0 - hp += money # hp - money difference - money = 0 - - # If positive delta, add points to exp & money - # Only take away mony if it was a mistake (aka, a checkbox) - if delta > 0 or (task.get('type') == 'daily' or task.get('type') == 'todo') - exp += expModifier(delta) - money += delta - # Deduct from health (rewards case handled above) - else if task.get('type') != 'reward' - hp += hpModifier(delta) - - updateStats(user, {hp: hp, exp: exp, money: money}) + + score(user, task, direction) # Note: Set 12am daily cron for this # At end of day, add value to all incomplete Daily & Todo tasks (further incentive) @@ -375,15 +278,10 @@ ready (model) -> for key of model.get '_user.tasks' task = model.at "_user.tasks.#{key}" [type, value, completed] = [task.get('type'), task.get('value'), task.get('completed')] - if type == 'todo' or type == 'daily' - unless completed - value += if (value < 0) then (( -0.1 * value + 1 ) * -1) else (( Math.pow(0.9,value) ) * -1) - task.set('value', value) - # Deduct experience for missed Daily tasks, - # but not for Todos (just increase todo's value) - if (type == 'daily') - hp = user.get('stats.hp') + hpModifier(value) - updateStats user, { hp: hp } + if type in ['todo', 'daily'] + # Deduct experience for missed Daily tasks, + # but not for Todos (just increase todo's value) + score(user, task, 'down', true) unless completed if type == 'daily' task.push "history", { date: new Date(), value: value } else diff --git a/src/app/score.coffee b/src/app/score.coffee new file mode 100644 index 0000000000..eaf4aa5d56 --- /dev/null +++ b/src/app/score.coffee @@ -0,0 +1,101 @@ +content = require('./content') + +# Calculates Exp modification based on weapon & lvl +expModifier = (user, value) -> + dmg = user.get('items.weapon') * .03 # each new weapon adds an additional 3% experience + dmg += user.get('stats.lvl') * .03 # same for lvls + modified = value + (value * dmg) + return modified + +# Calculates HP-loss modification based on armor & lvl +hpModifier = (user, value) -> + ac = user.get('items.armor') * .03 # each new armor blocks an additional 3% damage + ac += user.get('stats.lvl') * .03 # same for lvls + modified = value - (value * ac) + return modified + +# Setter for user.stats: handles death, leveling up, etc +updateStats = (user, stats) -> + if stats.hp? + # game over + if stats.hp < 0 + user.set 'stats.lvl', 0 # this signifies dead + else + user.set 'stats.hp', stats.hp + + if stats.exp? + # level up & carry-over exp + 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') and 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? + money = 0.0 if (!money? or money<0) + user.set 'stats.money', stats.money + +module.exports = (user, task, direction, cron) -> + + # For negative values, use a line: something like y=-.1x+1 + # For positibe values, taper off with inverse log: y=.9^x + # Would love to use inverse log for the whole thing, but after 13 fails it hits infinity + sign = if (direction == "up") then 1 else -1 + value = task.get('value') + delta = if (value < 0) then (( -0.1 * value + 1 ) * sign) else (( Math.pow(0.9,value) ) * sign) + + type = task.get('type') + + # Don't adjust values for rewards, or for habits that don't have both + and - + adjustvalue = (type != 'reward') + if (type == 'habit') and (task.get("up")==false or task.get("down")==false) + 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 + # 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')] + + if type == 'reward' + # purchase item + money -= task.get('value') + # if too expensive, reduce health & zero money + if money < 0 + hp += money # hp - money difference + money = 0 + + # 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 ) + exp += expModifier(user, delta) + money += delta + # Deduct from health (rewards case handled above) + else if type != 'reward' and ( type!='todo' and cron ) + hp += hpModifier(user, delta) + + updateStats(user, {hp: hp, exp: exp, money: money}) + + return delta \ No newline at end of file diff --git a/views/app/index.html b/views/app/index.html index 3bd9c69ada..6dd764d54b 100644 --- a/views/app/index.html +++ b/views/app/index.html @@ -38,9 +38,9 @@ {#if _user.history.exp}   {/} - Exp: {round(_user.stats.exp)} / {_tnl} + Exp: {round(_user.stats.exp)} / {_user._tnl} -
+