// Generated by CoffeeScript 1.3.3 var MODIFIER, async, content, cron, expModifier, helpers, hpModifier, model, moment, score, setModel, setupNotifications, taskDeltaFormula, updateStats, user, _; async = require('async'); moment = require('moment'); _ = require('lodash'); content = require('./content'); helpers = require('./helpers'); MODIFIER = .03; user = void 0; model = void 0; setModel = function(m) { model = m; user = model.at('_user'); return setupNotifications(); }; setupNotifications = function() { var statsNotification; if (typeof jQuery === "undefined" || jQuery === null) { return; } statsNotification = function(html, type) { if (user.get('stats.lvl') === 0) { return; } return $.bootstrapGrowl(html, { type: type, top_offset: 20, align: 'right', width: 250, delay: 3000, allow_dismiss: true, stackup_spacing: 10 }); }; user.on('set', 'stats.hp', function(captures, args) { var num, rounded; num = captures - args; rounded = Math.abs(num.toFixed(1)); if (num < 0) { return statsNotification("HP -" + rounded, 'error'); } }); user.on('set', 'stats.money', function(captures, args) { var num, rounded; num = captures - args; rounded = Math.abs(num.toFixed(1)); if (num < 0) { return statsNotification("GP -" + rounded, 'success'); } else if (num > 0) { num = Math.abs(num); return statsNotification("Exp,GP +" + rounded, 'success'); } }); return user.on('set', 'stats.lvl', function(captures, args) { if (captures > args) { return statsNotification(' Level Up!', 'info'); } }); }; /* Calculates Exp & GP modification based on weapon & lvl {value} task.value for gain {modifiers} may manually pass in stats as {weapon, exp}. This is used for testing */ expModifier = function(value, modifiers) { var dmg, lvl, modified, weapon; if (modifiers == null) { modifiers = {}; } weapon = modifiers.weapon || user.get('items.weapon'); lvl = modifiers.lvl || user.get('stats.lvl'); dmg = weapon * MODIFIER; dmg += (lvl - 1) * MODIFIER; modified = value + (value * dmg); return modified; }; /* Calculates HP-loss modification based on armor & lvl {value} task.value which is hurting us {modifiers} may manually pass in modifier as {armor, lvl}. This is used for testing */ hpModifier = function(value, modifiers) { var ac, armor, lvl, modified; if (modifiers == null) { modifiers = {}; } armor = modifiers.armor || user.get('items.armor'); lvl = modifiers.lvl || user.get('stats.lvl'); ac = armor * MODIFIER; ac += (lvl - 1) * MODIFIER; modified = value - (value * ac); return modified; }; /* Calculates the next task.value based on direction 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. Revisit this formula later {currentValue} the current value of the task, determines it's next value {direction} 'up' or 'down' */ taskDeltaFormula = function(currentValue, direction) { var delta, sign; sign = direction === "up" ? 1 : -1; delta = currentValue < 0 ? (-0.1 * currentValue + 1) * sign : (Math.pow(0.9, currentValue)) * sign; return delta; }; updateStats = function(stats) { var money, tnl; if (user.get('stats.lvl') === 0) { return; } if (stats.hp != null) { if (stats.hp <= 0) { user.set('stats.lvl', 0); user.set('stast.hp', 0); return; } 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); user.set('stats.hp', 50); } if (!user.get('items.itemsEnabled') && stats.exp >= 15) { 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); } }; score = function(taskId, direction, options) { var adjustvalue, delta, exp, hp, lvl, modified, money, num, task, taskObj, taskPath, type, userObj, value, _ref, _ref1, _ref2; if (options == null) { options = { cron: false, times: 1 }; } taskPath = "_user.tasks." + taskId; _ref = [model.at(taskPath), model.get(taskPath)], task = _ref[0], taskObj = _ref[1]; type = taskObj.type, value = taskObj.value; userObj = user.get(); if (!task) { _ref1 = userObj.stats, money = _ref1.money, hp = _ref1.hp, exp = _ref1.exp; if (direction === "up") { modified = expModifier(1); money += modified; exp += modified; } else { modified = hpModifier(1); hp -= modified; } updateStats({ hp: hp, exp: exp, money: money }); return; } adjustvalue = type !== 'reward'; if ((type === 'habit') && (taskObj.up === false || taskObj.down === false)) { adjustvalue = false; } delta = 0; _.times(options.times, function(n) { var nextDelta; nextDelta = taskDeltaFormula(value, direction); if (adjustvalue) { value += nextDelta; } return delta += nextDelta; }); if (type === 'habit') { if (taskObj.value !== value) { task.push('history', { date: new Date(), value: value }); } } task.set('value', value); if (options.cron) { if (type === 'daily') { return delta; } else { return 0; } } _ref2 = userObj.stats, money = _ref2.money, hp = _ref2.hp, exp = _ref2.exp, lvl = _ref2.lvl; if (type === 'reward') { money -= task.get('value'); num = parseFloat(task.get('value')).toFixed(2); if (money < 0) { hp += money; money = 0; } } if ((delta > 0 || (type === 'daily' || type === 'todo')) && !options.cron) { modified = expModifier(delta); exp += modified; money += modified; } else if (type !== 'reward' && type !== 'todo') { modified = hpModifier(delta); hp += modified; } updateStats({ hp: hp, exp: exp, money: money }); return delta; }; cron = function() { var daysPassed, hpTally, lastCron, tallyTask, tasks, today, todoTally; today = new Date(); user.setNull('lastCron', today); lastCron = user.get('lastCron'); daysPassed = helpers.daysBetween(today, lastCron); if (daysPassed > 0) { todoTally = 0; hpTally = 0; tallyTask = function(taskObj, callback) { var absVal, completed, daysFailed, id, repeat, task, type, value; id = taskObj.id, type = taskObj.type, completed = taskObj.completed, repeat = taskObj.repeat; if (id == null) { return callback('a task had a null id during cron, this should not be happening'); } task = user.at("tasks." + id); if (type === 'todo' || type === 'daily') { if (!completed) { daysFailed = daysPassed; if (type === 'daily' && repeat) { daysFailed = 0; _.times(daysPassed, function(n) { var thatDay; thatDay = moment().subtract('days', n + 1); if (repeat[helpers.dayMapping[thatDay.day()]] === true) { return daysFailed++; } }); } hpTally += score(id, 'down', { cron: true, times: daysFailed }); } value = task.get('value'); if (type === 'daily') { task.push("history", { date: today, value: value }); } else { absVal = completed ? Math.abs(value) : value; todoTally += absVal; } if (type === 'daily') { task.pass({ cron: true }).set('completed', false); } } return callback(); }; tasks = _.toArray(user.get('tasks')); return async.forEach(tasks, tallyTask, function(err) { var expTally, lvl; user.push('history.todos', { date: today, value: todoTally }); expTally = user.get('stats.exp'); lvl = 0; while (lvl < (user.get('stats.lvl') - 1)) { lvl++; expTally += (lvl * 100) / 5; } user.push('history.exp', { date: today, value: expTally }); updateStats({ hp: user.get('stats.hp') + hpTally }); return user.set('lastCron', today); }); } }; module.exports = { setModel: setModel, MODIFIER: MODIFIER, score: score, cron: cron, expModifier: expModifier, hpModifier: hpModifier, taskDeltaFormula: taskDeltaFormula };