2012-06-20 22:15:38 +00:00
derby = require ( ' derby ' )
{ get , view , ready } = derby . createApp module
derby . use require ( ' derby-ui-boot ' )
2012-06-21 00:47:08 +00:00
derby . use ( require ( ' ../../ui ' ) )
2012-04-27 02:19:31 +00:00
## ROUTES ##
2012-07-06 05:12:35 +00:00
get ' / ' , (page, model) ->
# Render page if a userId is already stored in session data
if userId = model . get ' _session.userId '
return getRoom page , model , userId
# Otherwise, select a new userId and initialize user
model . async . incr ' configs.1.nextUserId ' , (err, userId) ->
2012-05-02 19:50:43 +00:00
model . set ' _session.userId ' , userId
model . set " users. #{ userId } " ,
name: ' User ' + userId
money: 0
exp: 0
lvl: 1
2012-06-20 20:45:39 +00:00
hp: 50
2012-07-06 05:12:35 +00:00
getRoom page , model , userId
2012-06-20 20:45:39 +00:00
2012-07-06 05:12:35 +00:00
getRoom = (page, model, userId) ->
2012-07-07 02:09:51 +00:00
2012-06-28 18:46:59 +00:00
model . subscribe " users. #{ userId } " , (err, user) ->
2012-05-02 19:50:43 +00:00
model . ref ' _user ' , user
2012-06-28 18:46:59 +00:00
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 "
2012-06-28 21:47:48 +00:00
unless model . get ( ' _user.tasks ' )
2012-07-06 19:44:14 +00:00
model . push ' _habitList ' , task for task in [
{ type: ' habit ' , text: ' Take the stairs ' , notes: ' ' , value: 0 , up: true , down: true }
{ type: ' habit ' , text: ' Nail-biting ' , notes: ' ' , value: 0 , up: true , down: true }
2012-06-28 19:07:39 +00:00
]
2012-07-06 19:44:14 +00:00
model . push ' _dailyList ' , task for task in [
2012-06-28 19:07:39 +00:00
{ type: ' daily ' , text: ' Exercise ' , notes: ' ' , value: 0 , completed: false }
2012-07-06 19:44:14 +00:00
{ type: ' daily ' , text: ' 1 hour personal project ' , notes: ' ' , value: 0 , completed: false }
2012-06-28 19:07:39 +00:00
]
2012-07-06 19:44:14 +00:00
model . push ' _todoList ' , task for task in [
{ type: ' todo ' , text: ' Call Frank ' , notes: ' ' , value: 0 , completed: false }
{ type: ' todo ' , text: ' Buy a bike ' , notes: ' ' , value: 0 , completed: false }
2012-06-28 19:07:39 +00:00
]
2012-07-06 19:44:14 +00:00
model . push ' _rewardList ' , task for task in [
{ type: ' reward ' , text: ' 1 Episode of Game of Thrones ' , notes: ' ' , value: 20 }
{ type: ' reward ' , text: ' Cake ' , notes: ' ' , value: 10 }
2012-06-28 19:07:39 +00:00
]
2012-06-20 21:13:47 +00:00
# http://tibia.wikia.com/wiki/Formula
model . fn ' _tnl ' , ' _user.lvl ' , (lvl) -> 50 * Math . pow ( lvl , 2 ) - 150 * lvl + 200
2012-06-28 23:15:46 +00:00
2012-04-27 17:04:44 +00:00
page . render ( )
2012-06-28 23:15:46 +00:00
2012-06-10 00:15:33 +00:00
## VIEW HELPERS ##
2012-06-27 13:37:36 +00:00
view . fn ' taskClasses ' , (type, completed, value, hideCompleted) ->
#TODO figure out how to just pass in the task model, so i can access all these properties from one object
2012-06-20 21:13:47 +00:00
classes = type
2012-06-26 12:45:35 +00:00
classes += " completed " if completed
2012-06-27 13:37:36 +00:00
if type == ' todo '
classes += " hide " if ( hideCompleted and completed ) or ( ! hideCompleted and ! completed )
2012-06-26 12:02:16 +00:00
switch
2012-06-26 15:02:29 +00:00
when value < - 8 then classes += ' color-worst '
when value >= - 8 and value < - 5 then classes += ' color-worse '
when value >= - 5 and value < - 1 then classes += ' color-bad '
when value >= - 1 and value < 1 then classes += ' color-neutral '
when value >= 1 and value < 5 then classes += ' color-good '
when value >= 5 and value < 10 then classes += ' color-better '
when value >= 10 then classes += ' color-best '
2012-06-10 00:15:33 +00:00
return classes
2012-06-20 21:30:10 +00:00
2012-06-20 22:34:15 +00:00
view . fn " percent " , (x, y) ->
x = 1 if x == 0
Math . round ( x / y * 100 )
2012-06-20 21:30:10 +00:00
view . fn " round " , (num) ->
Math . round num
view . fn " gold " , (num) ->
2012-06-20 22:34:15 +00:00
num . toFixed ( 1 ) . split ( ' . ' ) [ 0 ] if num
2012-06-20 21:30:10 +00:00
view . fn " silver " , (num) ->
2012-06-20 22:34:15 +00:00
num . toFixed ( 1 ) . split ( ' . ' ) [ 1 ] if num
2012-04-27 02:19:31 +00:00
## CONTROLLER FUNCTIONS ##
ready (model) ->
2012-07-06 19:16:26 +00:00
# Note: Set 12am daily cron for this
# At end of day, add value to all incomplete Daily & Todo tasks (further incentive)
# For incomplete Dailys, deduct experience
#TODO: remove from exports when cron implemented
exports.endOfDayTally = endOfDayTally = (e, el) ->
# users = model.at('users') #TODO this isn't working, iterate over all users
# for user in users
user = model . at ' _user '
todoTally = 0
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 ' )
user . set ( ' hp ' , user . get ( ' hp ' ) + value )
if user . get ( ' hp ' ) < 0
#TODO this is implemented in exports.vote also, make it a user.on or something
user . set ( ' hp ' , 50 ) ; user . set ( ' lvl ' , 1 ) ; user . set ( ' exp ' , 0 )
if type == ' daily '
task . push " history " , { date: new Date ( ) , value: value }
else
absVal = if ( completed ) then Math . abs ( value ) else value
todoTally += absVal
task . set ( ' completed ' , false ) if type == ' daily '
model . push ' _user.history.todos ' , { date: new Date ( ) , value: todoTally }
2012-07-06 20:54:57 +00:00
# tally experience
expTally = user . get ' exp '
2012-07-06 21:21:36 +00:00
lvl = 0 #iterator
2012-07-06 20:54:57 +00:00
_ ( user . get ( ' lvl ' ) - 1 ) . times ->
2012-07-06 21:21:36 +00:00
lvl ++
2012-07-06 20:54:57 +00:00
expTally += 50 * Math . pow ( lvl , 2 ) - 150 * lvl + 200
model . push ' _user.history.exp ' , { date: new Date ( ) , value: expTally }
2012-07-06 19:16:26 +00:00
#TODO: remove when cron implemented
poormanscron = ->
lastCron = model . get ( ' _user.lastCron ' )
lastCron = if lastCron then ( new Date ( lastCron ) ) else new Date ( )
DAY = 1000 * 60 * 60 * 24
today = new Date ( )
2012-07-06 20:57:17 +00:00
daysPassed = Math . round ( ( today . getTime ( ) - lastCron . getTime ( ) ) / DAY )
if daysPassed > 0
_ ( daysPassed ) . times ->
endOfDayTally ( )
2012-07-06 19:16:26 +00:00
lastCron = new Date ( )
model . set ( ' _user.lastCron ' , lastCron )
poormanscron ( )
exports.toggleDebug = ->
model . set ( ' _debug ' , ! model . get ( ' _debug ' ) )
2012-07-07 16:58:34 +00:00
$ ( ' .task-notes, [rel=popover] ' ) . popover ( )
2012-06-27 13:37:36 +00:00
model . set ( ' _hideCompleted ' , true )
$ ( ' a[data-toggle= " tab " ] ' ) . on ' shown ' , (e) ->
#see http://twitter.github.com/bootstrap/javascript.html#tabs
hideCompleted = if $ ( e . target ) . attr ( ' href ' ) == ' # tab1 ' then true else false
model . set ( ' _hideCompleted ' , hideCompleted )
2012-06-25 02:35:04 +00:00
2012-07-07 04:07:30 +00:00
# Make the lists draggable using jQuery UI
# Note, have to setup helper function here and call it for each type later
# due to variable binding of "type"
setupSortable = (type) ->
$ ( " ul. #{ type } s " ) . sortable
2012-06-26 15:44:37 +00:00
dropOnEmpty: false
cursor: " move "
items: " li "
opacity: 0.4
scroll: true
2012-05-03 01:07:36 +00:00
axis: ' y '
update: (e, ui) ->
item = ui . item [ 0 ]
domId = item . id
id = item . getAttribute ' data-id '
2012-07-07 04:07:30 +00:00
to = $ ( " ul. #{ type } s " ) . children ( ) . index ( item )
2012-05-03 01:07:36 +00:00
# Use the Derby ignore option to suppress the normal move event
# binding, since jQuery UI will move the element in the DOM.
# Also, note that refList index arguments can either be an index
# or the item's id property
2012-07-07 04:07:30 +00:00
model . at ( " _ #{ type } List " ) . pass ( ignore: domId ) . move { id } , to
setupSortable ( type ) for type in [ ' habit ' , ' daily ' , ' todo ' , ' reward ' ]
2012-07-07 16:31:51 +00:00
tour = new Tour ( )
tour . addStep
element: " # avatar "
title: " Welcome to HabitRPG "
content: " A habit-tracker which treats your goals like a Role Playing Game. "
tour . addStep
element: " # bars "
title: " Acheive goals and level up "
content: " As you accomplish goals, you level up and earn gold to spend on rewards. If you fail your goals, you lose hit points. Lose all your HP and you die. "
tour . addStep
element: " ul.habits "
title: " Habits "
content: " Habits are goals that you constantly monitor. "
placement: " bottom "
tour . addStep
element: " ul.dailys "
title: " Dailies "
content: " Dailies are goals that you want to complete once a day. "
placement: " bottom "
tour . addStep
element: " ul.todos "
title: " Todos "
content: " Todos are one-off goals which need to be completed eventually. "
placement: " bottom "
tour . addStep
element: " ul.rewards "
title: " Rewards "
2012-07-07 16:58:34 +00:00
content: " As you complete goals, you earn gold to buy rewards. Buy them liberally - rewards are integral in forming good habits. "
2012-07-07 16:31:51 +00:00
placement: " bottom "
tour . start ( )
2012-06-26 15:34:45 +00:00
#TODO: implement this for completed tab
# clearCompleted: ->
# _.each @options.habits.doneTodos(), (todo) ->
# todo.destroy()
# @render()
# return false
2012-06-26 15:31:58 +00:00
2012-07-06 19:44:14 +00:00
exports.loadDebugDefaults = (e, el) ->
model . remove ' _habitList ' , 0 , 100 , ->
model . push ' _habitList ' , task for task in [
{ type: ' habit ' , text: ' Stairs ' , notes: ' ' , value: 0 , up: true , down: true }
{ type: ' habit ' , text: ' Diet ' , notes: ' ' , value: 0 , up: true , down: true }
{ type: ' habit ' , text: ' Ticket (Workflowy, Pivotal) ' , notes: ' ' , value: 0 , up: true , down: false }
{ type: ' habit ' , text: ' Temptation Control ' , notes: ' * meditate for 1 minute, visualize<br/>* positive, specific, present self-talk<br/>* do first task ' , value: 0 , up: true , down: false }
{ type: ' habit ' , text: ' Propose, not ask ' , notes: ' ' , value: 0 , up: true , down: false }
{ type: ' habit ' , text: ' Focus ' , notes: ' ' , value: 0 , up: false , down: true }
{ type: ' habit ' , text: ' Facebook/RSS out of turn ' , notes: ' ' , value: 0 , up: false , down: true }
{ type: ' habit ' , text: ' Negative Talk ' , notes: ' ' , value: 0 , up: false , down: true }
{ type: ' habit ' , text: ' Exaggeration ' , notes: ' ' , value: 0 , up: false , down: true }
{ type: ' habit ' , text: ' Insult Self ' , notes: ' ' , value: 0 , up: false , down: true }
{ type: ' habit ' , text: ' Other ' , notes: ' * Nail-biting<br/>* Posture<br/>* Visualize / Meditate to sleep<br/>* Smile/eye-gaze ' , value: 0 , up: false , down: false }
]
model . remove ' _dailyList ' , 0 , 100 , ->
model . push ' _dailyList ' , task for task in [
{ type: ' daily ' , text: ' Review Pivotal, Asana, Workflowy ' , notes: ' ' , value: 0 , completed: false }
{ type: ' daily ' , text: ' TMJ Exercise ' , notes: ' ' , value: 0 , completed: false }
{ type: ' daily ' , text: ' Anki (20m) ' , notes: ' ' , value: 0 , completed: false }
{ type: ' daily ' , text: ' 30m Code Reading ' , notes: ' ' , value: 0 , completed: false }
{ type: ' daily ' , text: ' Google News ' , notes: ' ' , value: 0 , completed: false }
{ type: ' daily ' , text: ' Mint ' , notes: ' ' , value: 0 , completed: false }
{ type: ' daily ' , text: ' Anki (new / review) ' , notes: ' ' , value: 0 , completed: false }
{ type: ' daily ' , text: ' Check Meetup ' , notes: ' ' , value: 0 , completed: false }
{ type: ' daily ' , text: ' Read it later ' , notes: ' ' , value: 0 , completed: false }
{ type: ' daily ' , text: ' RSS (Drupal) ' , notes: ' ' , value: 0 , completed: false }
{ type: ' daily ' , text: ' RSS (Other) ' , notes: ' ' , value: 0 , completed: false }
{ type: ' daily ' , text: ' Lunch TODO ' , notes: ' ' , value: 0 , completed: false }
{ type: ' daily ' , text: ' Exercise ' , notes: ' ' , value: 0 , completed: false }
{ type: ' daily ' , text: ' Read (45m) ' , notes: ' ' , value: 0 , completed: false }
{ type: ' daily ' , text: ' Night TODO ' , notes: ' ' , value: 0 , completed: false }
{ type: ' daily ' , text: ' Brain Game ' , notes: ' ' , value: 0 , completed: false }
{ type: ' daily ' , text: ' 1h Personal Project ' , notes: ' ' , value: 0 , completed: false }
]
model . remove ' _todoList ' , 0 , 100 , ->
model . push ' _todoList ' , task for task in [
{ type: ' todo ' , text: ' Print insurance request card ' , notes: ' " travel " tag ' , value: 0 , completed: false }
{ type: ' todo ' , text: ' VPM ' , notes: ' ' , value: 0 , completed: false }
{ type: ' todo ' , text: ' set STO as PTO or makup time with joshua (email) ' , notes: ' ' , value: 0 , completed: false }
{ type: ' todo ' , text: ' ocdevel ads ' , notes: ' ' , value: 0 , completed: false }
{ type: ' todo ' , text: ' mail ' , notes: ' ' , value: 0 , completed: false }
{ type: ' todo ' , text: ' krav ' , notes: ' ' , value: 0 , completed: false }
{ type: ' todo ' , text: ' rubber cement ' , notes: ' ' , value: 0 , completed: false }
{ type: ' todo ' , text: ' bike ' , notes: ' ' , value: 0 , completed: false }
{ type: ' todo ' , text: ' clean ~/.ievms ' , notes: ' ' , value: 0 , completed: false }
{ type: ' todo ' , text: ' http://www.php-debug.com/www/ ' , notes: ' ' , value: 0 , completed: false }
{ type: ' todo ' , text: ' make sure IRA is setup for auto distribution ' , notes: ' ' , value: 0 , completed: false }
]
model . remove ' _rewardList ' , 0 , 100 , ->
model . push ' _rewardList ' , task for task in [
{ type: ' reward ' , text: ' TV Show ' , notes: ' ' , value: 20 }
{ type: ' reward ' , text: ' 1h Novel ' , notes: ' ' , value: 10 }
{ type: ' reward ' , text: ' Shop ' , notes: ' ' , value: 10 }
{ type: ' reward ' , text: ' Junk Food ' , notes: ' ' , value: 10 }
{ type: ' reward ' , text: ' 9gag ' , notes: ' ' , value: 5 }
{ type: ' reward ' , text: ' Coffee ' , notes: ' ' , value: 5 }
]
2012-06-09 18:25:10 +00:00
exports.addTask = (e, el, next) ->
type = $ ( el ) . attr ( ' data-task-type ' )
list = model . at " _ #{ type } List "
newModel = model . at ( ' _new ' + type . charAt ( 0 ) . toUpperCase ( ) + type . slice ( 1 ) )
2012-04-27 17:04:44 +00:00
# Don't add a blank todo
2012-06-09 18:25:10 +00:00
return unless text = view . escapeHtml newModel . get ( )
newModel . set ' '
switch type
2012-06-20 21:43:23 +00:00
2012-06-09 18:25:10 +00:00
when ' habit '
2012-06-26 15:02:29 +00:00
list . push { type: type , text: text , notes: ' ' , value: 0 , up: true , down: true }
2012-06-20 21:43:23 +00:00
2012-06-09 18:25:10 +00:00
when ' reward '
2012-06-26 15:02:29 +00:00
list . push { type: type , text: text , notes: ' ' , value: 20 }
2012-06-20 21:43:23 +00:00
2012-06-09 18:25:10 +00:00
when ' daily ' , ' todo '
2012-06-26 15:02:29 +00:00
list . push { type: type , text: text , notes: ' ' , value: 0 , completed: false }
2012-06-25 22:26:12 +00:00
# list.on 'set', '*.completed', (i, completed, previous, isLocal) ->
# # Move the item to the bottom if it was checked off
# list.move i, -1 if completed && isLocal
2012-04-27 17:04:44 +00:00
2012-07-07 02:09:51 +00:00
exports.del = (e, el) ->
2012-04-27 17:04:44 +00:00
# Derby extends model.at to support creation from DOM nodes
2012-07-07 02:09:51 +00:00
task = model . at ( e . target )
#TODO bug where I have to delete from _users.tasks AND _{type}List,
# fix when query subscriptions implemented properly
console . log model . del ( ' _user.tasks. ' + task . get ( ' id ' ) )
console . log task . remove ( )
2012-06-25 01:51:13 +00:00
2012-06-29 13:45:50 +00:00
exports.toggleTaskEdit = (e, el) ->
2012-06-29 08:33:09 +00:00
task = model . at $ ( el ) . parents ( ' li ' ) [ 0 ]
$ ( ' # \\ ' + task . get ( ' id ' ) + ' -chart ' ) . hide ( )
$ ( ' # \\ ' + task . get ( ' id ' ) + ' -edit ' ) . toggle ( )
2012-07-07 02:46:22 +00:00
exports.toggleChart = (e, el) ->
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 ( )
2012-06-29 08:33:09 +00:00
matrix = [ [ ' Date ' , ' Score ' ] ]
2012-07-07 02:46:22 +00:00
for obj in model . get ( historyPath )
2012-06-29 08:51:50 +00:00
date = new Date ( obj . date )
readableDate = " #{ date . getMonth ( ) } / #{ date . getDate ( ) } / #{ date . getFullYear ( ) } "
matrix . push [ readableDate , obj . value ]
2012-06-29 08:33:09 +00:00
data = google . visualization . arrayToDataTable matrix
2012-06-29 08:44:52 +00:00
2012-06-29 08:33:09 +00:00
options = {
title: ' History '
2012-06-29 08:44:52 +00:00
#TODO use current background color: $(el).css('background-color), but convert to hex (see http://goo.gl/ql5pR)
backgroundColor: ' whiteSmoke '
2012-06-29 08:33:09 +00:00
}
2012-07-07 02:46:22 +00:00
chart = new google . visualization . LineChart ( document . getElementById ( chartSelector ) )
2012-06-29 08:33:09 +00:00
chart . draw ( data , options )
2012-06-29 13:45:50 +00:00
2012-06-20 20:40:59 +00:00
exports.vote = (e, el, next) ->
2012-06-10 00:41:21 +00:00
direction = $ ( el ) . attr ( ' data-direction ' )
2012-06-26 14:55:24 +00:00
direction = ' up ' if direction == ' true/ '
direction = ' down ' if direction == ' false/ '
2012-06-20 20:40:59 +00:00
#TODO this should be model.at(el), shouldn't have to find parent
task = model . at $ ( el ) . parents ( ' li ' ) [ 0 ]
user = model . at ' _user '
2012-06-10 00:41:21 +00:00
# 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
2012-06-26 15:02:29 +00:00
value = task . get ( ' value ' )
2012-06-10 00:41:21 +00:00
delta = 0
2012-06-26 15:02:29 +00:00
if value < 0
delta = ( ( - 0.1 * value + 1 ) * sign )
2012-06-10 00:41:21 +00:00
else
2012-06-26 15:02:29 +00:00
delta = ( ( Math . pow ( 0.9 , value ) ) * sign )
2012-06-20 21:43:23 +00:00
2012-06-26 15:02:29 +00:00
# Don't adjust values for rewards, or for habits that don't have both + and -
adjustvalue = ( task . get ( ' type ' ) != ' reward ' )
2012-06-10 00:41:21 +00:00
if ( task . get ( ' type ' ) == ' habit ' ) and ( task . get ( " up " ) == false or task . get ( " down " ) == false )
2012-06-26 15:02:29 +00:00
adjustvalue = false
value += delta if adjustvalue
2012-06-20 21:43:23 +00:00
2012-06-26 14:55:24 +00:00
# up/down -voting as checkbox & assigning as completed, 2 birds one stone
completed = task . get ( " completed " )
2012-06-10 01:16:11 +00:00
if task . get ( ' type ' ) != ' habit '
2012-06-26 14:55:24 +00:00
completed = true if direction == " up "
completed = false if direction == " down "
2012-07-06 20:30:18 +00:00
else
# Add habit value to habit-history (if different)
task . push ' history ' , { date: new Date ( ) , value: value } if task . get ( ' value ' ) != value
2012-06-26 15:02:29 +00:00
task . set ( ' value ' , value )
2012-06-26 14:55:24 +00:00
task . set ( ' completed ' , completed )
2012-06-20 21:43:23 +00:00
2012-06-10 00:41:21 +00:00
# Update the user's status
[ money , hp , exp , lvl ] = [ user . get ( ' money ' ) , user . get ( ' hp ' ) , user . get ( ' exp ' ) , user . get ( ' lvl ' ) ]
if task . get ( ' type ' ) == ' reward '
# purchase item
2012-06-26 15:02:29 +00:00
money -= task . get ( ' value ' )
2012-06-10 00:41:21 +00:00
# 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 += delta
money += delta
# Deduct from health (rewards case handled above)
else if task . get ( ' type ' ) != ' reward '
hp += delta
2012-06-28 22:11:13 +00:00
tnl = model . get ' _tnl '
2012-06-10 00:41:21 +00:00
# level up & carry-over exp
2012-06-26 15:07:20 +00:00
if exp >= tnl
2012-06-10 01:16:11 +00:00
exp -= tnl
2012-06-10 00:41:21 +00:00
lvl += 1
# game over
if hp < 0
[ hp , lvl , exp ] = [ 50 , 1 , 0 ]
2012-06-20 20:40:59 +00:00
user . set ( ' money ' , money )
user . set ( ' hp ' , hp )
user . set ( ' exp ' , exp )
user . set ( ' lvl ' , lvl )
#[user.money, user.hp, user.exp, user.lvl] = [money, hp, exp, lvl]
2012-06-28 22:11:13 +00:00
2012-06-26 15:44:10 +00:00
## SHORTCUTS ##
2012-04-27 17:04:44 +00:00
exports.shortcuts = (e) ->
return unless e . metaKey || e . ctrlKey
code = e . which
return unless command = ( switch code
when 66 then ' bold ' # Bold: Ctrl/Cmd + B
when 73 then ' italic ' # Italic: Ctrl/Cmd + I
when 32 then ' removeFormat ' # Clear formatting: Ctrl/Cmd + Space
when 220 then ' removeFormat ' # Clear formatting: Ctrl/Cmd + \
else null
)
document . execCommand command , false , null
e . preventDefault ( ) if e . preventDefault
return false
# Tell Firefox to use elements for styles instead of CSS
# See: https://developer.mozilla.org/en/Rich-Text_Editing_in_Mozilla
document . execCommand ' useCSS ' , false , true
document . execCommand ' styleWithCSS ' , false , false