mirror of
https://github.com/sudoxnym/habitica.git
synced 2026-07-14 07:52:15 +00:00
Moved scoring functionality into score.coffee, separate it out so i
can start implementing services
This commit is contained in:
parent
2f008533bc
commit
0b58c24e58
5 changed files with 239 additions and 247 deletions
136
lib/app/index.js
136
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: "<div class='item-store-popover'> <img src='/img/BrowserQuest/chest.png' /> " + content.items.unlockedMessage.content + " <a href='#' onClick=\"$('ul.items').popover('hide');return false;\">[Close]</a> </div>"
|
||||
});
|
||||
$('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", {
|
||||
|
|
|
|||
109
lib/app/score.js
Normal file
109
lib/app/score.js
Normal file
|
|
@ -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: "<div class='item-store-popover'> <img src='/img/BrowserQuest/chest.png' /> " + content.items.unlockedMessage.content + " <a href='#' onClick=\"$('ul.items').popover('hide');return false;\">[Close]</a> </div>"
|
||||
});
|
||||
$('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;
|
||||
};
|
||||
|
|
@ -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: "<div class='item-store-popover'>\
|
||||
<img src='/img/BrowserQuest/chest.png' />\
|
||||
#{content.items.unlockedMessage.content} <a href='#' onClick=\"$('ul.items').popover('hide');return false;\">[Close]</a>\
|
||||
</div>"
|
||||
$('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
|
||||
|
|
|
|||
101
src/app/score.coffee
Normal file
101
src/app/score.coffee
Normal file
|
|
@ -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: "<div class='item-store-popover'>\
|
||||
<img src='/img/BrowserQuest/chest.png' />\
|
||||
#{content.items.unlockedMessage.content} <a href='#' onClick=\"$('ul.items').popover('hide');return false;\">[Close]</a>\
|
||||
</div>"
|
||||
$('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
|
||||
|
|
@ -38,9 +38,9 @@
|
|||
{#if _user.history.exp}
|
||||
<a x-bind=click:toggleChart data-toggle-id="exp-chart" data-history-path="_user.history.exp"><i class=icon-signal></i></a>
|
||||
{/}
|
||||
Exp: {round(_user.stats.exp)} / {_tnl}
|
||||
Exp: {round(_user.stats.exp)} / {_user._tnl}
|
||||
</span>
|
||||
<div class="bar" style="width: {percent(_user.stats.exp,_tnl)}%;"></div>
|
||||
<div class="bar" style="width: {percent(_user.stats.exp,_user._tnl)}%;"></div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
Loading…
Reference in a new issue