Files
habitica/lib/app/index.js
2012-07-28 16:26:06 -04:00

420 lines
12 KiB
JavaScript

// Generated by CoffeeScript 1.3.3
var Scoring, content, derby, get, getHabits, 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');
Scoring = require('./scoring');
view.fn('taskClasses', function(type, completed, value) {
var classes;
classes = type;
if (completed) {
classes += " completed";
}
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('/:uidParam?', function(page, model, _arg) {
var uidParam;
uidParam = _arg.uidParam;
return model.fetch('users', function(err, users) {
var guid, newUser, task, user, userId, _i, _len, _ref1;
if ((uidParam != null) && users.get(uidParam)) {
model.set('_userId', uidParam);
model.session.userId = uidParam;
}
userId = model.get('_userId');
user = users.get(userId);
if (user == null) {
newUser = require('./schema').userSchema;
_ref1 = content.defaultTasks;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
task = _ref1[_i];
guid = task.id = require('derby/node_modules/racer').uuid();
newUser.tasks[guid] = task;
switch (task.type) {
case 'habit':
newUser.habitIds.push(guid);
break;
case 'daily':
newUser.dailyIds.push(guid);
break;
case 'todo':
newUser.todoIds.push(guid);
break;
case 'reward':
newUser.rewardIds.push(guid);
}
}
users.set(userId, newUser);
}
return getHabits(page, model, userId);
});
});
getHabits = function(page, model, userId) {
return model.subscribe("users." + userId, function(err, user) {
console.log({
userId: userId,
err: err
}, "app/index.coffee: model.subscribe");
model.ref('_user', user);
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('_user._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("_completedList", "_user.tasks", "_user.completedIds");
model.refList("_rewardList", "_user.tasks", "_user.rewardIds");
return page.render();
});
};
ready(function(model) {
var 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() {
return $('[rel=popover]').popover();
});
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();
model.on('set', '_user.tasks.*.completed', function(i, completed, previous, isLocal, passed) {
var direction, from, fromIds, task, to, toIds, _ref3, _ref4;
if (passed.cron != null) {
return;
}
direction = function() {
if (completed === true && previous === false) {
return 'up';
}
if (completed === false && previous === true) {
return 'down';
}
throw new Error("Direction neither 'up' nor 'down' on checkbox set.");
};
task = model.at("_user.tasks." + i);
Scoring.score({
user: model.at('_user'),
task: task,
direction: direction()
});
if (task.get('type') === 'todo') {
_ref3 = direction() === 'up' ? ['todo', 'completed'] : ['completed', 'todo'], from = _ref3[0], to = _ref3[1];
_ref4 = ["_user." + from + "Ids", "_user." + to + "Ids"], from = _ref4[0], to = _ref4[1];
fromIds = model.get(from);
fromIds.splice(fromIds.indexOf(i), 1);
model.set(from, fromIds);
toIds = model.get(to);
toIds.push(i);
return model.set(to, toIds);
}
});
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.clearCompleted = function(e, el) {
return _.each(model.get('_completedList'), function(task) {
model.del('_user.tasks.' + task.id);
return model.set('_user.completedIds', []);
});
};
exports.toggleTaskEdit = function(e, el) {
var hideId, toggleId;
hideId = $(el).attr('data-hide-id');
toggleId = $(el).attr('data-toggle-id');
$(document.getElementById(hideId)).hide();
return $(document.getElementById(toggleId)).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-id');
chartSelector = $(el).attr('data-toggle-id');
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.vote = function(e, el, next) {
var direction, task, user;
direction = $(el).attr('data-direction');
if (direction === 'true/') {
direction = 'up';
}
if (direction === 'false/') {
direction = 'down';
}
user = model.at('_user');
task = model.at($(el).parents('li')[0]);
return Scoring.score({
user: user,
task: task,
direction: direction
});
};
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.poormanscron = poormanscron = function() {
var DAY, daysPassed, lastCron, n, today, _k, _results;
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) {
model.set('_user.lastCron', today);
_results = [];
for (n = _k = 1; 1 <= daysPassed ? _k <= daysPassed : _k >= daysPassed; n = 1 <= daysPassed ? ++_k : --_k) {
console.log({
today: today,
lastCron: lastCron,
daysPassed: daysPassed,
n: n
}, "[debug] Cron (" + today + ", " + n + ")");
_results.push(Scoring.tally(model));
}
return _results;
}
};
poormanscron();
setInterval((function() {
return poormanscron();
}), 3600000);
exports.endOfDayTally = function(e, el) {
return Scoring.tally(model);
};
exports.updateSchema = function(e, el) {
return require('./schema').updateSchema(model);
};
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);
});