Files
habitica/lib/app/index.js
2012-07-16 17:06:44 -05:00

585 lines
17 KiB
JavaScript

// Generated by CoffeeScript 1.3.3
var Guid, content, derby, get, getRoom, ready, view, _ref;
derby = require('derby');
_ref = derby.createApp(module), get = _ref.get, view = _ref.view, ready = _ref.ready;
derby.use(require('derby-ui-boot'));
derby.use(require('../../ui'));
content = require('./content');
Guid = require('guid');
view.fn('taskClasses', function(type, completed, value, hideCompleted) {
var classes;
classes = type;
if (completed) {
classes += " completed";
}
if (type === 'todo') {
if ((hideCompleted && completed) || (!hideCompleted && !completed)) {
classes += " hide";
}
}
switch (false) {
case !(value < -8):
classes += ' color-worst';
break;
case !(value >= -8 && value < -5):
classes += ' color-worse';
break;
case !(value >= -5 && value < -1):
classes += ' color-bad';
break;
case !(value >= -1 && value < 1):
classes += ' color-neutral';
break;
case !(value >= 1 && value < 5):
classes += ' color-good';
break;
case !(value >= 5 && value < 10):
classes += ' color-better';
break;
case !(value >= 10):
classes += ' color-best';
}
return classes;
});
view.fn("percent", function(x, y) {
if (x === 0) {
x = 1;
}
return Math.round(x / y * 100);
});
view.fn("round", function(num) {
return Math.round(num);
});
view.fn("gold", function(num) {
if (num) {
return num.toFixed(1).split('.')[0];
} else {
return "0";
}
});
view.fn("silver", function(num) {
if (num) {
return num.toFixed(1).split('.')[1];
} else {
return "0";
}
});
get('/:userId?', function(page, model, _arg) {
var debuggingUsers, userId;
userId = _arg.userId;
debuggingUsers = parseInt(userId) < 40;
if ((userId != null) && (Guid.isGuid(userId) || debuggingUsers)) {
model.set('_session.userId', userId);
return getRoom(page, model, userId);
}
if (userId = model.get('_session.userId')) {
return getRoom(page, model, userId);
}
userId = Guid.raw();
model.set('_session.userId', userId);
model.set("users." + userId, {});
return getRoom(page, model, userId);
});
getRoom = function(page, model, userId) {
return model.subscribe("users." + userId, function(err, user) {
var task, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref1, _ref2, _ref3, _ref4;
model.ref('_user', user);
/* Set User Defaults
*/
user.setNull('stats', {
money: 0,
exp: 0,
lvl: 1,
hp: 50
});
user.setNull('items', {
itemsEnabled: false,
armor: 0,
weapon: 0
});
model.set('_items', {
armor: content.items.armor[parseInt(user.get('items.armor')) + 1],
weapon: content.items.weapon[parseInt(user.get('items.weapon')) + 1],
potion: content.items.potion,
reroll: content.items.reroll
});
model.fn('_tnl', '_user.stats.lvl', function(lvl) {
return 50 * Math.pow(lvl, 2) - 150 * lvl + 200;
});
model.refList("_habitList", "_user.tasks", "_user.habitIds");
model.refList("_dailyList", "_user.tasks", "_user.dailyIds");
model.refList("_todoList", "_user.tasks", "_user.todoIds");
model.refList("_rewardList", "_user.tasks", "_user.rewardIds");
if (!model.get('_user.tasks')) {
_ref1 = content.defaultTasks.habits;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
task = _ref1[_i];
model.push('_habitList', task);
}
_ref2 = content.defaultTasks.dailys;
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
task = _ref2[_j];
model.push('_dailyList', task);
}
_ref3 = content.defaultTasks.todos;
for (_k = 0, _len2 = _ref3.length; _k < _len2; _k++) {
task = _ref3[_k];
model.push('_todoList', task);
}
_ref4 = content.defaultTasks.rewards;
for (_l = 0, _len3 = _ref4.length; _l < _len3; _l++) {
task = _ref4[_l];
model.push('_rewardList', task);
}
}
return page.render();
});
};
ready(function(model) {
var endOfDayTally, expModifier, hpModifier, poormanscron, setupSortable, step, tour, type, updateStats, _i, _j, _len, _len1, _ref1, _ref2;
model.set('_purl', window.location.origin + '/' + model.get('_user.id'));
$('[rel=popover]').popover();
model.on('set', '*', function() {
return $('[rel=popover]').popover();
});
model.set('_hideCompleted', true);
$('a[data-toggle="tab"]').on('shown', function(e) {
var hideCompleted;
hideCompleted = $(e.target).attr('href') === '#tab1' ? true : false;
return model.set('_hideCompleted', hideCompleted);
});
setupSortable = function(type) {
return $("ul." + type + "s").sortable({
dropOnEmpty: false,
cursor: "move",
items: "li",
opacity: 0.4,
scroll: true,
axis: 'y',
update: function(e, ui) {
var domId, id, item, to;
item = ui.item[0];
domId = item.id;
id = item.getAttribute('data-id');
to = $("ul." + type + "s").children().index(item);
return model.at("_" + type + "List").pass({
ignore: domId
}).move({
id: id
}, to);
}
});
};
_ref1 = ['habit', 'daily', 'todo', 'reward'];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
type = _ref1[_i];
setupSortable(type);
}
tour = new Tour();
_ref2 = content.tourSteps;
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
step = _ref2[_j];
tour.addStep({
element: step.element,
title: step.title,
content: step.content,
placement: step.placement
});
}
tour.start();
exports.loadDebugDefaults = function(e, el) {
model.remove('_habitList', 0, 100, function() {
var task, _k, _len2, _ref3, _results;
_ref3 = content.tylerDefaultTasks.habits;
_results = [];
for (_k = 0, _len2 = _ref3.length; _k < _len2; _k++) {
task = _ref3[_k];
_results.push(model.push('_habitList', task));
}
return _results;
});
model.remove('_dailyList', 0, 100, function() {
var task, _k, _len2, _ref3, _results;
_ref3 = content.tylerDefaultTasks.dailys;
_results = [];
for (_k = 0, _len2 = _ref3.length; _k < _len2; _k++) {
task = _ref3[_k];
_results.push(model.push('_dailyList', task));
}
return _results;
});
model.remove('_todoList', 0, 100, function() {
var task, _k, _len2, _ref3, _results;
_ref3 = content.tylerDefaultTasks.todos;
_results = [];
for (_k = 0, _len2 = _ref3.length; _k < _len2; _k++) {
task = _ref3[_k];
_results.push(model.push('_todoList', task));
}
return _results;
});
return model.remove('_rewardList', 0, 100, function() {
var task, _k, _len2, _ref3, _results;
_ref3 = content.tylerDefaultTasks.rewards;
_results = [];
for (_k = 0, _len2 = _ref3.length; _k < _len2; _k++) {
task = _ref3[_k];
_results.push(model.push('_rewardList', task));
}
return _results;
});
};
exports.addTask = function(e, el, next) {
var list, newModel, text;
type = $(el).attr('data-task-type');
list = model.at("_" + type + "List");
newModel = model.at('_new' + type.charAt(0).toUpperCase() + type.slice(1));
if (!(text = view.escapeHtml(newModel.get()))) {
return;
}
newModel.set('');
switch (type) {
case 'habit':
return list.push({
type: type,
text: text,
notes: '',
value: 0,
up: true,
down: true
});
case 'reward':
return list.push({
type: type,
text: text,
notes: '',
value: 20
});
case 'daily':
case 'todo':
return list.push({
type: type,
text: text,
notes: '',
value: 0,
completed: false
});
}
};
exports.del = function(e, el) {
var task;
task = model.at(e.target);
model.del('_user.tasks.' + task.get('id'));
return task.remove();
};
exports.toggleTaskEdit = function(e, el) {
var task;
task = model.at($(el).parents('li')[0]);
$('#\\' + task.get('id') + '-chart').hide();
return $('#\\' + task.get('id') + '-edit').toggle();
};
exports.toggleChart = function(e, el) {
var chart, chartSelector, data, date, hideSelector, historyPath, matrix, obj, options, readableDate, _k, _len2, _ref3;
hideSelector = $(el).attr('data-hide-selector');
chartSelector = $(el).attr('data-chart-selector');
historyPath = $(el).attr('data-history-path');
$(document.getElementById(hideSelector)).hide();
$(document.getElementById(chartSelector)).toggle();
matrix = [['Date', 'Score']];
_ref3 = model.get(historyPath);
for (_k = 0, _len2 = _ref3.length; _k < _len2; _k++) {
obj = _ref3[_k];
date = new Date(obj.date);
readableDate = date.toISOString();
matrix.push([readableDate, obj.value]);
}
data = google.visualization.arrayToDataTable(matrix);
options = {
title: 'History',
backgroundColor: 'whiteSmoke'
};
chart = new google.visualization.LineChart(document.getElementById(chartSelector));
return chart.draw(data, options);
};
exports.buyItem = function(e, el, next) {
var hp, index, money, task, taskId, user, value, _ref3, _results;
user = model.at('_user');
money = user.get('stats.money');
_ref3 = [$(el).attr('data-type'), $(el).attr('data-value'), $(el).attr('data-index')], type = _ref3[0], value = _ref3[1], index = _ref3[2];
if (money < value) {
return;
}
user.set('stats.money', money - value);
if (type === 'armor') {
user.set('items.armor', index);
return model.set('_items.armor', content.items.armor[parseInt(index) + 1]);
} else if (type === 'weapon') {
user.set('items.weapon', index);
return model.set('_items.weapon', content.items.weapon[parseInt(index) + 1]);
} else if (type === 'potion') {
hp = user.get('stats.hp');
hp += 15;
if (hp > 50) {
hp = 50;
}
return user.set('stats.hp', hp);
} else if (type === 'reroll') {
_results = [];
for (taskId in user.get('tasks')) {
task = model.at('_user.tasks.' + taskId);
if (task.get('type') !== 'reward') {
_results.push(task.set('value', 0));
} else {
_results.push(void 0);
}
}
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;
direction = $(el).attr('data-direction');
if (direction === 'true/') {
direction = 'up';
}
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
});
};
exports.endOfDayTally = endOfDayTally = function(e, el) {
var absVal, completed, expTally, hp, key, lvl, task, todoTally, user, value, _ref3;
user = model.at('_user');
todoTally = 0;
for (key in model.get('_user.tasks')) {
task = model.at("_user.tasks." + key);
_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
});
}
}
if (type === 'daily') {
task.push("history", {
date: new Date(),
value: value
});
} else {
absVal = completed ? Math.abs(value) : value;
todoTally += absVal;
}
if (type === 'daily') {
task.set('completed', false);
}
}
}
model.push('_user.history.todos', {
date: new Date(),
value: todoTally
});
expTally = user.get('stats.exp');
lvl = 0;
_(user.get('stats.lvl') - 1).times(function() {
lvl++;
return expTally += 50 * Math.pow(lvl, 2) - 150 * lvl + 200;
});
return model.push('_user.history.exp', {
date: new Date(),
value: expTally
});
};
exports.poormanscron = poormanscron = function() {
var DAY, daysPassed, lastCron, today;
model.setNull('_user.lastCron', new Date());
lastCron = new Date((new Date(model.get('_user.lastCron'))).toDateString());
today = new Date((new Date).toDateString());
DAY = 1000 * 60 * 60 * 24;
daysPassed = Math.floor((today.getTime() - lastCron.getTime()) / DAY);
if (daysPassed > 0) {
_(daysPassed).times(function() {
return endOfDayTally();
});
model.set('_user.lastCron', today);
return console.log({
today: today,
lastCron: lastCron,
daysPassed: daysPassed
}, 'cron debugging');
}
};
poormanscron();
setInterval((function() {
return poormanscron();
}), 3600000);
exports.toggleDebug = function() {
return model.set('_debug', !model.get('_debug'));
};
exports.revive = function(e, el) {
var stats;
stats = model.at('_user.stats');
stats.set('hp', 50);
stats.set('lvl', 1);
stats.set('exp', 0);
stats.set('money', 0);
model.set('_user.items.armor', 0);
model.set('_user.items.weapon', 0);
model.set('_items.armor', content.items.armor[1]);
return model.set('_items.weapon', content.items.weapon[1]);
};
exports.shortcuts = function(e) {
var code, command;
if (!(e.metaKey || e.ctrlKey)) {
return;
}
code = e.which;
if (!(command = ((function() {
switch (code) {
case 66:
return 'bold';
case 73:
return 'italic';
case 32:
return 'removeFormat';
case 220:
return 'removeFormat';
default:
return null;
}
})()))) {
return;
}
document.execCommand(command, false, null);
if (e.preventDefault) {
e.preventDefault();
}
return false;
};
document.execCommand('useCSS', false, true);
return document.execCommand('styleWithCSS', false, false);
});