Merge conflicts master

This commit is contained in:
Glen De Cauwsemaecker 2014-04-03 17:42:08 +02:00
commit 12cf298467
69 changed files with 472 additions and 285 deletions

View file

@ -5,10 +5,12 @@ locale = require 'locale/locale'
Tracker = require 'lib/Tracker'
CocoView = require 'views/kinds/CocoView'
# Prevent Ctrl/Cmd + [ / ], P, S
ctrlDefaultPrevented = [219, 221, 80, 83]
preventBackspace = (event) ->
if event.keyCode is 8 and not elementAcceptsKeystrokes(event.srcElement or event.target)
event.preventDefault()
else if (key.ctrl or key.command) and not key.alt and event.keyCode in [219, 221] # prevent Ctrl/Cmd + [ / ]
else if (key.ctrl or key.command) and not key.alt and event.keyCode in ctrlDefaultPrevented
event.preventDefault()
elementAcceptsKeystrokes = (el) ->

View file

@ -35,6 +35,11 @@
<!--[if IE 9]> <script src="/javascripts/vendor_with_box2d.js"></script> <![endif]-->
<!--[if !IE]><!--> <script src="/javascripts/vendor.js"></script> <!--<![endif]-->
<script src="/javascripts/app.js"></script> <!-- it's all Backbone! -->
<script>
window.userObject = "userObjectTag";
</script>
<script>require('initialize');</script>

View file

@ -1,5 +1,4 @@
app = require 'application'
auth = require 'lib/auth'
init = ->
app.initialize()
@ -10,15 +9,8 @@ init = ->
treemaExt.setup()
filepicker.setKey('AvlkNoldcTOU4PvKi2Xm7z')
$ ->
# Make sure we're "logged in" first.
if auth.me.id
init()
else
Backbone.Mediator.subscribeOnce 'me:synced', init
$ -> init()
window.init = init
handleNormalUrls = ->
# http://artsy.github.com/blog/2012/06/25/replacing-hashbang-routes-with-pushstate/
$(document).on "click", "a[href^='/']", (event) ->

View file

@ -1,5 +1,5 @@
CocoClass = require 'lib/CocoClass'
{me, CURRENT_USER_KEY} = require 'lib/auth'
{me} = require 'lib/auth'
{backboneFailure} = require 'lib/errors'
storage = require 'lib/storage'
@ -59,7 +59,6 @@ module.exports = FacebookHandler = class FacebookHandler extends CocoClass
error: backboneFailure,
url: "/db/user?facebookID=#{r.id}&facebookAccessToken=#{@authResponse.accessToken}"
success: (model) ->
storage.save(CURRENT_USER_KEY, model.attributes)
window.location.reload() if model.get('email') isnt oldEmail
})

View file

@ -1,5 +1,5 @@
CocoClass = require 'lib/CocoClass'
{me, CURRENT_USER_KEY} = require 'lib/auth'
{me} = require 'lib/auth'
{backboneFailure} = require 'lib/errors'
storage = require 'lib/storage'
GPLUS_TOKEN_KEY = 'gplusToken'
@ -102,7 +102,6 @@ module.exports = GPlusHandler = class GPlusHandler extends CocoClass
error: backboneFailure,
url: "/db/user?gplusID=#{gplusID}&gplusAccessToken=#{@accessToken.access_token}"
success: (model) ->
storage.save(CURRENT_USER_KEY, model.attributes)
window.location.reload() if wasAnonymous and not model.get('anonymous')
})

View file

@ -1,5 +1,3 @@
{me} = require 'lib/auth'
gplusClientID = "800329290710-j9sivplv2gpcdgkrsis9rff3o417mlfa.apps.googleusercontent.com"
go = (path) -> -> @routeDirectly path, arguments

View file

@ -1,20 +1,24 @@
{backboneFailure, genericFailure} = require 'lib/errors'
User = require 'models/User'
storage = require 'lib/storage'
module.exports.CURRENT_USER_KEY = CURRENT_USER_KEY = 'whoami'
BEEN_HERE_BEFORE_KEY = 'beenHereBefore'
init = ->
module.exports.me = window.me = new User(window.userObject) # inserted into main.html
trackFirstArrival()
if me and not me.get('testGroupNumber')?
# Assign testGroupNumber to returning visitors; new ones in server/routes/auth
me.set 'testGroupNumber', Math.floor(Math.random() * 256)
me.save()
me.loadGravatarProfile() if me.get('email')
Backbone.listenTo(me, 'sync', Backbone.Mediator.publish('me:synced', {me:me}))
module.exports.createUser = (userObject, failure=backboneFailure, nextURL=null) ->
user = new User(userObject)
user.save({}, {
error: failure,
success: (model) ->
storage.save(CURRENT_USER_KEY, model)
if nextURL
window.location.href = nextURL
else
window.location.reload()
error: failure,
success: -> if nextURL then window.location.href = nextURL else window.location.reload()
})
module.exports.loginUser = (userObject, failure=genericFailure) ->
@ -23,52 +27,15 @@ module.exports.loginUser = (userObject, failure=genericFailure) ->
username:userObject.email,
password:userObject.password
},
(model) ->
storage.save(CURRENT_USER_KEY, model)
window.location.reload()
(model) -> window.location.reload()
)
jqxhr.fail(failure)
module.exports.logoutUser = ->
FB?.logout?()
res = $.post('/auth/logout', {}, ->
storage.save(CURRENT_USER_KEY, null)
window.location.reload()
)
res = $.post('/auth/logout', {}, -> window.location.reload())
res.fail(genericFailure)
init = ->
# Load the user from local storage, and refresh it from the server.
# Also refresh and cache the gravatar info.
storedUser = storage.load(CURRENT_USER_KEY)
firstTime = not storedUser
module.exports.me = window.me = new User(storedUser)
me.url = -> '/auth/whoami'
me.fetch()
retry = -> me.fetch() # blindly try again
error = -> setTimeout(retry, 1000) # blindly try again
me.on 'error', error, @
me.on 'sync', ->
me.off 'error', error, @ if firstTime
me.url = -> "/db/user/#{me.id}"
trackFirstArrival() if firstTime
if me and not me.get('testGroupNumber')?
# Assign testGroupNumber to returning visitors; new ones in server/handlers/user
me.set 'testGroupNumber', Math.floor(Math.random() * 256)
me.save()
storage.save(CURRENT_USER_KEY, me.attributes)
me.loadGravatarProfile() if me.get('email')
Backbone.listenTo(me, 'sync', userSynced)
userSynced = (user) ->
Backbone.Mediator.publish('me:synced', {me:user})
storage.save(CURRENT_USER_KEY, user)
init()
onSetVolume = (e) ->
return if e.volume is me.get('volume')
me.set('volume', e.volume)
@ -83,3 +50,6 @@ trackFirstArrival = ->
return if beenHereBefore
window.tracker?.trackEvent 'First Arrived'
storage.save(BEEN_HERE_BEFORE_KEY, true)
init()

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "български език", englishDescri
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "Deutsch", englishDescription: "German", tra
tip_patience: "Geduld du musst haben, junger Padawan. - Yoda"
tip_documented_bug: "Ein dokumentierter Fehler ist kein Fehler; er ist ein Merkmal."
tip_impossible: "Es wirkt immer unmöglich bis es vollbracht ist. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
time_current: "Aktuell"
time_total: "Total"
time_goto: "Gehe zu"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "ελληνικά", englishDescription: "Gre
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "English", englishDescription: "English", tr
tip_patience: "Patience you must have, young Padawan. - Yoda"
tip_documented_bug: "A documented bug is not a bug; it is a feature."
tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
time_current: "Now:"
time_total: "Max:"
time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "español (América Latina)", englishDescrip
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription:
tip_patience: "Geduld moet je hebben, jonge Padawan. - Yoda"
tip_documented_bug: "Een gedocumenteerde fout is geen fout; het is deel van het programma."
tip_impossible: "Het lijkt altijd onmogelijk tot het gedaan wordt. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
time_current: "Nu:"
time_total: "Maximum:"
time_goto: "Ga naar:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
tip_patience: "Geduld moet je hebben, jonge Padawan. - Yoda"
tip_documented_bug: "Een gedocumenteerde fout is geen fout; het is deel van het programma."
tip_impossible: "Het lijkt altijd onmogelijk tot het gedaan wordt. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
time_current: "Nu:"
time_total: "Maximum:"
time_goto: "Ga naar:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
tip_patience: "Geduld moet je hebben, jonge Padawan. - Yoda"
tip_documented_bug: "Een gedocumenteerde fout is geen fout; het is deel van het programma."
tip_impossible: "Het lijkt altijd onmogelijk tot het gedaan wordt. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
time_current: "Nu:"
time_total: "Maximum:"
time_goto: "Ga naar:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "português do Brasil", englishDescription:
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "português", englishDescription: "Portugues
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
tip_patience: "Терпением ты обладать должен, юный падаван. - Yoda"
tip_documented_bug: "Документированный баг не является багом; это фича."
tip_impossible: "Это всегда кажется невозможным, пока не сделано. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
time_current: "Текущее:"
time_total: "Максимальное:"
time_goto: "Перейти на:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "українська мова", englishDesc
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu",
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -264,6 +264,8 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# time_current: "Now:"
# time_total: "Max:"
# time_goto: "Go to:"

View file

@ -0,0 +1,13 @@
#my-matches-tab-view
.axis path, .axis line
fill: none
stroke: #000
shape-rendering: crispEdges
.x.axis.path
display: none
.line
fill: none
stroke: steelblue
stroke-width: 1.5px

View file

@ -11,14 +11,14 @@ div#columns.row
tr
th(colspan=4, style="color: #{team.primaryColor}")
span(data-i18n="ladder.summary_your") Your
span(data-i18n="ladder.summary_your") Your
|#{team.name}
|
span(data-i18n="ladder.summary_matches") Matches -
span(data-i18n="ladder.summary_matches") Matches -
|#{team.wins}
span(data-i18n="ladder.summary_wins") Wins,
span(data-i18n="ladder.summary_wins") Wins,
|#{team.losses}
span(data-i18n="ladder.summary_losses") Losses
span(data-i18n="ladder.summary_losses") Losses
if team.session
tr
@ -34,7 +34,9 @@ div#columns.row
if team.chartData
tr
th(colspan=4, style="color: #{team.primaryColor}")
img(src="https://chart.googleapis.com/chart?chs=450x125&cht=lxy&chco=#{team.chartColor}&chtt=Score%3A+#{team.currentScore}&chts=#{team.chartColor},16,r&chf=a,s,000000FF&chls=2&chm=o,#{team.chartColor},0,4&chd=t:#{team.chartData}&chxt=y&chxr=0,#{team.minScore},#{team.maxScore}")
div(class="score-chart-wrapper", data-team-name=team.name, id="score-chart-#{team.name}")
tr
th(data-i18n="general.result") Result

View file

@ -35,6 +35,8 @@
strong.tip.rare(data-i18n='play_level.tip_no_try') Do. Or do not. There is no try. - Yoda
strong.tip.rare(data-i18n='play_level.tip_patience') Patience you must have, young Padawan. - Yoda
strong.tip.rare(data-i18n='play_level.tip_documented_bug') A documented bug is not a bug; it is a feature.
strong.tip.rare(data-i18n='play_level.tip_talk_is_cheap') Talk is cheap. Show me the code. - Linus Torvalds
strong.tip.rare(data-i18n='play_level.tip_first_language') The most disastrous thing that you can ever learn is your first programming language. - Alan Kay
strong.tip.rare
span(data-i18n='play_level.tip_harry') Yer a Wizard,
span= me.get('name') || 'Anoner'

View file

@ -21,6 +21,10 @@ module.exports = class ColorsTabView extends CocoView
@interval = setInterval f, 1000
super options
destroy: ->
clearInterval @interval
super()
afterRender: ->
super()
@createShapeButtons()

View file

@ -48,6 +48,8 @@ module.exports = class MyMatchesTabView extends CocoView
@startsLoading = false
@render()
getRenderData: ->
ctx = super()
ctx.level = @level
@ -80,7 +82,9 @@ module.exports = class MyMatchesTabView extends CocoView
team.losses = _.filter(team.matches, {state: 'loss'}).length
scoreHistory = team.session?.get('scoreHistory')
if scoreHistory?.length > 1
team.scoreHistory = scoreHistory
scoreHistory = _.last scoreHistory, 100 # Chart URL needs to be under 2048 characters for GET
team.currentScore = Math.round scoreHistory[scoreHistory.length - 1][1] * 100
team.chartColor = team.primaryColor.replace '#', ''
#times = (s[0] for s in scoreHistory)
@ -109,7 +113,69 @@ module.exports = class MyMatchesTabView extends CocoView
else if session.get 'isRanking'
rankingState = 'ranking'
@setRankingButtonText button, rankingState
@$el.find('.score-chart-wrapper').each (i, el) =>
scoreWrapper = $(el)
team = _.find @teams, name: scoreWrapper.data('team-name')
@generateScoreLineChart(scoreWrapper.attr('id'), team.scoreHistory)
generateScoreLineChart: (wrapperID, scoreHistory) =>
margin =
top: 20
right: 20
bottom: 30
left: 50
width = 450 - margin.left - margin.right
height = 125
x = d3.time.scale().range([0,width])
y = d3.scale.linear().range([height,0])
xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(4).outerTickSize(0)
yAxis = d3.svg.axis().scale(y).orient("left").ticks(4).outerTickSize(0)
line = d3.svg.line().x(((d) -> x(d.date))).y((d) -> y(d.close))
selector = "#" + wrapperID
svg = d3.select(selector).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform","translate(#{margin.left},#{margin.top})")
time = 0
data = scoreHistory.map (d) ->
time +=1
return {
date: time
close: d[1] * 100
}
x.domain(d3.extent(data, (d) -> d.date))
y.domain(d3.extent(data, (d) -> d.close))
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y",4)
.attr("dy", ".75em")
.style("text-anchor","end")
.text("Score")
svg.append("path")
.datum(data)
.attr("class","line")
.attr("d",line)
readyToRank: (session) ->
return false unless session?.get('levelID') # If it hasn't been denormalized, then it's not ready.
return false unless c1 = session.get('code')

View file

@ -44,7 +44,6 @@ module.exports = class PlaybackView extends View
'⌘+[, ctrl+[': 'onScrubBack'
'⌘+], ctrl+]': 'onScrubForward'
# popover that shows at the current mouse position on the progressbar, using the bootstrap popover.
# Could make this into a jQuery plugins itself theoretically.
class HoverPopup extends $.fn.popover.Constructor

View file

@ -35,7 +35,8 @@
"aether": "~0.1.18",
"underscore.string": "~2.3.3",
"firebase": "~1.0.2",
"catiline": "~2.9.3"
"catiline": "~2.9.3",
"d3": "~3.4.4"
},
"overrides": {
"backbone": {

View file

@ -65,6 +65,7 @@ exports.config =
# Aether before box2d for some strange Object.defineProperty thing
'bower_components/aether/build/aether.js'
'bower_components/d3/d3.min.js'
]
stylesheets:
defaultExtension: 'sass'

View file

@ -311,8 +311,9 @@ module.exports = class Handler
for prop in @getEditableProperties req, document
if (val = req.body[prop])?
document.set prop, val
else if document.get(prop)? and req.method isnt 'PATCH'
document.set prop, 'undefined'
# Hold on, gotta think about that one
#else if document.get(prop)? and req.method isnt 'PATCH'
# document.set prop, 'undefined'
obj = document.toObject()
# Hack to get saving of Users to work. Probably should replace these props with strings

View file

@ -43,17 +43,17 @@ module.exports.addPairwiseTaskToQueueFromRequest = (req, res) ->
addPairwiseTaskToQueue = (taskPair, cb) ->
LevelSession.findOne(_id:taskPair[0]).lean().exec (err, firstSession) =>
if err? then return cb err, false
if err? then return cb err
LevelSession.find(_id:taskPair[1]).exec (err, secondSession) =>
if err? then return cb err, false
if err? then return cb err
try
taskPairs = generateTaskPairs(secondSession, firstSession)
catch e
if e then return cb e, false
if e then return cb e
sendEachTaskPairToTheQueue taskPairs, (taskPairError) ->
if taskPairError? then return cb taskPairError,false
cb null, true
if taskPairError? then return cb taskPairError
cb null
module.exports.resimulateAllSessions = (req, res) ->
unless isUserAdmin req then return errors.unauthorized res, "Unauthorized. Even if you are authorized, you shouldn't do this"
@ -68,8 +68,8 @@ module.exports.resimulateAllSessions = (req, res) ->
majorVersion: levelMajorVersion
query = LevelSession
.find(findParameters)
.lean()
.find(findParameters)
.lean()
query.exec (err, result) ->
if err? then return errors.serverError res, err
@ -100,14 +100,12 @@ resimulateSession = (originalLevelID, levelMajorVersion, session, cb) =>
cb null
module.exports.createNewTask = (req, res) ->
requestSessionID = req.body.session
originalLevelID = req.body.originalLevelID
currentLevelID = req.body.levelID
requestLevelMajorVersion = parseInt(req.body.levelMajorVersion)
async.waterfall [
validatePermissions.bind(@,req,requestSessionID)
fetchAndVerifyLevelType.bind(@,currentLevelID)
@ -115,12 +113,12 @@ module.exports.createNewTask = (req, res) ->
updateSessionToSubmit
fetchInitialSessionsToRankAgainst.bind(@, requestLevelMajorVersion, originalLevelID)
generateAndSendTaskPairsToTheQueue
], (err, successMessageObject) ->
if err? then return errors.serverError res, "There was an error submitting the game to the queue:#{err}"
sendResponseObject req, res, successMessageObject
validatePermissions = (req,sessionID, callback) ->
if isUserAnonymous req then return callback "You are unauthorized to submit that game to the simulator"
if isUserAdmin req then return callback null
@ -136,7 +134,7 @@ validatePermissions = (req,sessionID, callback) ->
query.exec (err, retrievedSession) ->
if err? then return callback err
userHasPermissionToSubmitCode = retrievedSession.creator is req.user?.id and
not _.isEqual(retrievedSession.code, retrievedSession.submittedCode)
not _.isEqual(retrievedSession.code, retrievedSession.submittedCode)
unless userHasPermissionToSubmitCode then return callback "You are unauthorized to submit that game to the simulator"
callback null
@ -209,7 +207,7 @@ generateAndSendTaskPairsToTheQueue = (sessionToRankAgainst,submittedSession, cal
sendEachTaskPairToTheQueue taskPairs, (taskPairError) ->
if taskPairError? then return callback taskPairError
callback null, {"message": "All task pairs were succesfully sent to the queue"}
module.exports.dispatchTaskToConsumer = (req, res) ->
async.waterfall [
@ -221,7 +219,7 @@ module.exports.dispatchTaskToConsumer = (req, res) ->
constructTaskLogObject.bind(@, getUserIDFromRequest(req))
processTaskObject
], (err, taskObjectToSend) ->
if err?
if err?
if typeof err is "string" and err.indexOf "No more games in the queue" isnt -1
res.send(204, "No games to score.")
return res.end()
@ -229,16 +227,16 @@ module.exports.dispatchTaskToConsumer = (req, res) ->
return errors.serverError res, "There was an error dispatching the task: #{err}"
sendResponseObject req, res, taskObjectToSend
checkSimulationPermissions = (req, cb) ->
if isUserAnonymous req
if isUserAnonymous req
cb "You need to be logged in to simulate games"
else
cb null
receiveMessageFromSimulationQueue = (cb) ->
scoringTaskQueue.receiveMessage (err, message) ->
scoringTaskQueue.receiveMessage (err, message) ->
if err? then return cb "No more games in the queue, error:#{err}"
if messageIsInvalid(message) then return cb "Message received from queue is invalid"
cb null, message
@ -292,90 +290,190 @@ processTaskObject = (taskObject,taskLogObject, message, cb) ->
cb null, taskObject
getSessionInformation = (sessionIDString, callback) ->
findParameters =
findParameters =
_id: sessionIDString
selectString = 'submitDate team submittedCode teamSpells levelID creator creatorName'
query = LevelSession
.findOne(findParameters)
.select(selectString)
.lean()
.findOne(findParameters)
.select(selectString)
.lean()
query.exec (err, session) ->
if err? then return callback err, {"error":"There was an error retrieving the session."}
callback null, session
module.exports.processTaskResult = (req, res) ->
clientResponseObject = verifyClientResponse req.body, res
async.waterfall [
verifyClientResponse.bind(@,req.body)
fetchTaskLog.bind(@)
checkTaskLog.bind(@)
deleteQueueMessage.bind(@)
fetchLevelSession.bind(@)
checkSubmissionDate.bind(@)
logTaskComputation.bind(@)
updateSessions.bind(@)
indexNewScoreArray.bind(@)
addMatchToSessions.bind(@)
updateUserSimulationCounts.bind(@, req.user._id)
determineIfSessionShouldContinueAndUpdateLog.bind(@)
findNearestBetterSessionID.bind(@)
addNewSessionsToQueue.bind(@)
], (err, results) ->
if err is "shouldn't continue"
sendResponseObject req, res, {"message":"The scores were updated successfully, person lost so no more games are being inserted!"}
else if err is "no session was found"
sendResponseObject req, res, {"message":"There were no more games to rank (game is at top)!"}
else if err?
errors.serverError res, "There was an error:#{err}"
else
sendResponseObject req, res, {"message":"The scores were updated successfully and more games were sent to the queue!"}
return unless clientResponseObject?
TaskLog.findOne {_id: clientResponseObject.taskID}, (err, taskLog) ->
return errors.serverError res, "There was an error retrieiving the task log object" if err?
verifyClientResponse = (responseObject, callback) ->
#TODO: better verification
unless typeof responseObject is "object"
callback "The response to that query is required to be a JSON object."
else
@clientResponseObject = responseObject
log.info "Verified client response!"
callback null, responseObject
taskLogJSON = taskLog.toObject()
fetchTaskLog = (responseObject, callback) ->
findParameters =
_id: responseObject.taskID
query = TaskLog
.findOne(findParameters)
query.exec (err, taskLog) =>
@taskLog = taskLog
log.info "Fetched task log!"
callback err, taskLog.toObject()
return errors.badInput res, "That computational task has already been performed" if taskLogJSON.calculationTimeMS
return handleTimedOutTask req, res, clientResponseObject if hasTaskTimedOut taskLogJSON.sentDate
checkTaskLog = (taskLog, callback) ->
if taskLog.calculationTimeMS then return callback "That computational task has already been performed"
if hasTaskTimedOut taskLog.sentDate then return callback "The task has timed out"
log.info "Checked task log"
callback null
scoringTaskQueue.deleteMessage clientResponseObject.receiptHandle, (err) ->
console.log "Deleted message."
if err? then return errors.badInput res, "The queue message is already back in the queue, rejecting results."
deleteQueueMessage = (callback) ->
scoringTaskQueue.deleteMessage @clientResponseObject.receiptHandle, (err) ->
log.info "Deleted queue message"
callback err
LevelSession.findOne(_id: clientResponseObject.originalSessionID).lean().exec (err, levelSession) ->
if err? then return errors.serverError res, "There was a problem finding the level session:#{err}"
supposedSubmissionDate = new Date(clientResponseObject.sessions[0].submitDate)
if Number(supposedSubmissionDate) isnt Number(levelSession.submitDate)
return sendResponseObject req, res, {"message":"The game has been resubmitted. Removing from queue..."}
logTaskComputation clientResponseObject, taskLog, (logErr) ->
if logErr? then return errors.serverError res, "There as a problem logging the task computation: #{logErr}"
updateSessions clientResponseObject, (updateError, newScoreArray) ->
if updateError? then return errors.serverError res, "There was an error updating the scores.#{updateError}"
newScoresObject = _.indexBy newScoreArray, 'id'
addMatchToSessions clientResponseObject, newScoresObject, (err, data) ->
if err? then return errors.serverError res, "There was an error updating the sessions with the match! #{JSON.stringify err}"
incrementUserSimulationCount req.user._id, 'simulatedBy'
incrementUserSimulationCount levelSession.creator, 'simulatedFor'
originalSessionID = clientResponseObject.originalSessionID
originalSessionTeam = clientResponseObject.originalSessionTeam
originalSessionRank = parseInt clientResponseObject.originalSessionRank
determineIfSessionShouldContinueAndUpdateLog originalSessionID, originalSessionRank, (err, sessionShouldContinue) ->
if err? then return errors.serverError res, "There was an error determining if the session should continue, #{err}"
if sessionShouldContinue
opposingTeam = calculateOpposingTeam(originalSessionTeam)
opponentID = _.pull(_.keys(newScoresObject), originalSessionID)
sessionNewScore = newScoresObject[originalSessionID].totalScore
opponentNewScore = newScoresObject[opponentID].totalScore
levelOriginalID = levelSession.level.original
levelOriginalMajorVersion = levelSession.level.majorVersion
findNearestBetterSessionID levelOriginalID, levelOriginalMajorVersion, originalSessionID, sessionNewScore, opponentNewScore, opponentID, opposingTeam, (err, opponentSessionID) ->
if err? then return errors.serverError res, "There was an error finding the nearest sessionID!"
if opponentSessionID
addPairwiseTaskToQueue [originalSessionID, opponentSessionID], (err, success) ->
if err? then return errors.serverError res, "There was an error sending the pairwise tasks to the queue!"
sendResponseObject req, res, {"message":"The scores were updated successfully and more games were sent to the queue!"}
else
LevelSession.update {_id: originalSessionID}, {isRanking: false}, {multi: false}, (err, affected) ->
if err? then return errors.serverError res, "There was an error marking the victorious session as not being ranked."
return sendResponseObject req, res, {"message":"There were no more games to rank (game is at top)!"}
else
console.log "Player lost, achieved rank #{originalSessionRank}"
LevelSession.update {_id: originalSessionID}, {isRanking: false}, {multi: false}, (err, affected) ->
if err? then return errors.serverError res, "There was an error marking the completed session as not being ranked."
sendResponseObject req, res, {"message":"The scores were updated successfully, person lost so no more games are being inserted!"}
fetchLevelSession = (callback) ->
findParameters =
_id: @clientResponseObject.originalSessionID
query = LevelSession
.findOne(findParameters)
.lean()
query.exec (err, session) =>
@levelSession = session
log.info "Fetched level session"
callback err
determineIfSessionShouldContinueAndUpdateLog = (sessionID, sessionRank, cb) ->
checkSubmissionDate = (callback) ->
supposedSubmissionDate = new Date(@clientResponseObject.sessions[0].submitDate)
if Number(supposedSubmissionDate) isnt Number(@levelSession.submitDate)
callback "The game has been resubmitted. Removing from queue..."
else
log.info "Checked submission date"
callback null
logTaskComputation = (callback) ->
@taskLog.set('calculationTimeMS',@clientResponseObject.calculationTimeMS)
@taskLog.set('sessions')
@taskLog.calculationTimeMS = @clientResponseObject.calculationTimeMS
@taskLog.sessions = @clientResponseObject.sessions
@taskLog.save (err, saved) ->
log.info "Logged task computation"
callback err
updateSessions = (callback) ->
sessionIDs = _.pluck @clientResponseObject.sessions, 'sessionID'
async.map sessionIDs, retrieveOldSessionData, (err, oldScores) =>
if err? then callback err, {"error": "There was an error retrieving the old scores"}
oldScoreArray = _.toArray putRankingFromMetricsIntoScoreObject @clientResponseObject, oldScores
newScoreArray = bayes.updatePlayerSkills oldScoreArray
saveNewScoresToDatabase newScoreArray, callback
saveNewScoresToDatabase = (newScoreArray, callback) ->
async.eachSeries newScoreArray, updateScoreInSession, (err) ->
log.info "Saved new scores to database"
callback err,newScoreArray
updateScoreInSession = (scoreObject,callback) ->
LevelSession.findOne {"_id": scoreObject.id}, (err, session) ->
if err? then return callback err, null
session = session.toObject()
newTotalScore = scoreObject.meanStrength - 1.8 * scoreObject.standardDeviation
scoreHistoryAddition = [Date.now(), newTotalScore]
updateObject =
meanStrength: scoreObject.meanStrength
standardDeviation: scoreObject.standardDeviation
totalScore: newTotalScore
$push: {scoreHistory: {$each: [scoreHistoryAddition], $slice: -1000}}
LevelSession.update {"_id": scoreObject.id}, updateObject, callback
log.info "New total score for session #{scoreObject.id} is #{updateObject.totalScore}"
indexNewScoreArray = (newScoreArray, callback) ->
newScoresObject = _.indexBy newScoreArray, 'id'
@newScoresObject = newScoresObject
callback null, newScoresObject
addMatchToSessions = (newScoreObject, callback) ->
matchObject = {}
matchObject.date = new Date()
matchObject.opponents = {}
for session in @clientResponseObject.sessions
sessionID = session.sessionID
matchObject.opponents[sessionID] = {}
matchObject.opponents[sessionID].sessionID = sessionID
matchObject.opponents[sessionID].userID = session.creator
matchObject.opponents[sessionID].metrics = {}
matchObject.opponents[sessionID].metrics.rank = Number(newScoreObject[sessionID].gameRanking)
log.info "Match object computed, result: #{matchObject}"
log.info "Writing match object to database..."
#use bind with async to do the writes
sessionIDs = _.pluck @clientResponseObject.sessions, 'sessionID'
async.each sessionIDs, updateMatchesInSession.bind(@,matchObject), (err) -> callback err
updateMatchesInSession = (matchObject, sessionID, callback) ->
currentMatchObject = {}
currentMatchObject.date = matchObject.date
currentMatchObject.metrics = matchObject.opponents[sessionID].metrics
opponentsClone = _.cloneDeep matchObject.opponents
opponentsClone = _.omit opponentsClone, sessionID
opponentsArray = _.toArray opponentsClone
currentMatchObject.opponents = opponentsArray
sessionUpdateObject =
$push: {matches: {$each: [currentMatchObject], $slice: -200}}
log.info "Updating session #{sessionID}"
LevelSession.update {"_id":sessionID}, sessionUpdateObject, callback
updateUserSimulationCounts = (reqUserID,callback) ->
incrementUserSimulationCount reqUserID, 'simulatedBy', (err) =>
if err? then return callback err
incrementUserSimulationCount @levelSession.creator, 'simulatedFor', callback
incrementUserSimulationCount = (userID, type, callback) =>
inc = {}
inc[type] = 1
User.update {_id: userID}, {$inc: inc}, (err, affected) ->
log.error "Error incrementing #{type} for #{userID}: #{err}" if err
callback err
determineIfSessionShouldContinueAndUpdateLog = (cb) ->
sessionID = @clientResponseObject.originalSessionID
sessionRank = parseInt @clientResponseObject.originalSessionRank
queryParameters =
_id: sessionID
@ -394,18 +492,26 @@ determineIfSessionShouldContinueAndUpdateLog = (sessionID, sessionRank, cb) ->
totalNumberOfGamesPlayed = updatedSession.numberOfWinsAndTies + updatedSession.numberOfLosses
if totalNumberOfGamesPlayed < 10
console.log "Number of games played is less than 10, continuing..."
cb null, true
cb null
else
ratio = (updatedSession.numberOfLosses) / (totalNumberOfGamesPlayed)
if ratio > 0.33
cb null, false
cb "shouldn't continue"
console.log "Ratio(#{ratio}) is bad, ending simulation"
else
console.log "Ratio(#{ratio}) is good, so continuing simulations"
cb null, true
cb null
findNearestBetterSessionID = (levelOriginalID, levelMajorVersion, sessionID, sessionTotalScore, opponentSessionTotalScore, opponentSessionID, opposingTeam, cb) ->
findNearestBetterSessionID = (cb) ->
levelOriginalID = @levelSession.level.original
levelMajorVersion = @levelSession.level.majorVersion
sessionID = @clientResponseObject.originalSessionID
sessionTotalScore = @newScoresObject[sessionID].totalScore
opponentSessionID = _.pull(_.keys(@newScoresObject), sessionID)
opponentSessionTotalScore = @newScoresObject[opponentSessionID].totalScore
opposingTeam = calculateOpposingTeam(@clientResponseObject.originalSessionTeam)
retrieveAllOpponentSessionIDs sessionID, (err, opponentSessionIDs) ->
if err? then return cb err, null
@ -434,23 +540,23 @@ findNearestBetterSessionID = (levelOriginalID, levelMajorVersion, sessionID, ses
selectString = '_id totalScore'
query = LevelSession.findOne(queryParameters)
.sort(sortParameters)
.limit(limitNumber)
.select(selectString)
.lean()
.sort(sortParameters)
.limit(limitNumber)
.select(selectString)
.lean()
console.log "Finding session with score near #{opponentSessionTotalScore}"
query.exec (err, session) ->
if err? then return cb err, session
unless session then return cb err, null
unless session then return cb "no session was found"
console.log "Found session with score #{session.totalScore}"
cb err, session._id
retrieveAllOpponentSessionIDs = (sessionID, cb) ->
query = LevelSession.findOne({"_id":sessionID})
.select('matches.opponents.sessionID matches.date submitDate')
.lean()
.select('matches.opponents.sessionID matches.date submitDate')
.lean()
query.exec (err, session) ->
if err? then return cb err, null
opponentSessionIDs = (match.opponents[0].sessionID for match in session.matches when match.date > session.submitDate)
@ -462,56 +568,15 @@ calculateOpposingTeam = (sessionTeam) ->
opposingTeams = _.pull teams, sessionTeam
return opposingTeams[0]
incrementUserSimulationCount = (userID, type) ->
inc = {}
inc[type] = 1
User.update {_id: userID}, {$inc: inc}, (err, affected) ->
log.error "Error incrementing #{type} for #{userID}: #{err}" if err
addMatchToSessions = (clientResponseObject, newScoreObject, callback) ->
matchObject = {}
matchObject.date = new Date()
matchObject.opponents = {}
for session in clientResponseObject.sessions
sessionID = session.sessionID
matchObject.opponents[sessionID] = {}
matchObject.opponents[sessionID].sessionID = sessionID
matchObject.opponents[sessionID].userID = session.creator
matchObject.opponents[sessionID].metrics = {}
matchObject.opponents[sessionID].metrics.rank = Number(newScoreObject[sessionID].gameRanking)
log.info "Match object computed, result: #{matchObject}"
log.info "Writing match object to database..."
#use bind with async to do the writes
sessionIDs = _.pluck clientResponseObject.sessions, 'sessionID'
async.each sessionIDs, updateMatchesInSession.bind(@,matchObject), (err) -> callback err, null
updateMatchesInSession = (matchObject, sessionID, callback) ->
currentMatchObject = {}
currentMatchObject.date = matchObject.date
currentMatchObject.metrics = matchObject.opponents[sessionID].metrics
opponentsClone = _.cloneDeep matchObject.opponents
opponentsClone = _.omit opponentsClone, sessionID
opponentsArray = _.toArray opponentsClone
currentMatchObject.opponents = opponentsArray
sessionUpdateObject =
$push: {matches: {$each: [currentMatchObject], $slice: -200}}
log.info "Updating session #{sessionID}"
LevelSession.update {"_id":sessionID}, sessionUpdateObject, callback
addNewSessionsToQueue = (sessionID, callback) ->
sessions = [@clientResponseObject.originalSessionID, sessionID]
addPairwiseTaskToQueue sessions, callback
messageIsInvalid = (message) -> (not message?) or message.isEmpty()
sendEachTaskPairToTheQueue = (taskPairs, callback) -> async.each taskPairs, sendTaskPairToQueue, callback
generateTaskPairs = (submittedSessions, sessionToScore) ->
taskPairs = []
for session in submittedSessions
@ -532,10 +597,6 @@ isUserAnonymous = (req) -> if req.user? then return req.user.get('anonymous') el
isUserAdmin = (req) -> return Boolean(req.user?.isAdmin())
sendResponseObject = (req,res,object) ->
res.setHeader('Content-Type', 'application/json')
res.send(object)
@ -545,51 +606,6 @@ hasTaskTimedOut = (taskSentTimestamp) -> taskSentTimestamp + scoringTaskTimeoutI
handleTimedOutTask = (req, res, taskBody) -> errors.clientTimeout res, "The results weren't provided within the timeout"
verifyClientResponse = (responseObject, res) ->
unless typeof responseObject is "object"
errors.badInput res, "The response to that query is required to be a JSON object."
null
else
responseObject
logTaskComputation = (taskObject,taskLogObject, callback) ->
taskLogObject.calculationTimeMS = taskObject.calculationTimeMS
taskLogObject.sessions = taskObject.sessions
taskLogObject.save callback
updateSessions = (taskObject,callback) ->
sessionIDs = _.pluck taskObject.sessions, 'sessionID'
async.map sessionIDs, retrieveOldSessionData, (err, oldScores) ->
if err? then callback err, {"error": "There was an error retrieving the old scores"}
oldScoreArray = _.toArray putRankingFromMetricsIntoScoreObject taskObject, oldScores
newScoreArray = bayes.updatePlayerSkills oldScoreArray
saveNewScoresToDatabase newScoreArray, callback
saveNewScoresToDatabase = (newScoreArray, callback) ->
async.eachSeries newScoreArray, updateScoreInSession, (err) -> callback err,newScoreArray
updateScoreInSession = (scoreObject,callback) ->
LevelSession.findOne {"_id": scoreObject.id}, (err, session) ->
if err? then return callback err, null
session = session.toObject()
newTotalScore = scoreObject.meanStrength - 1.8 * scoreObject.standardDeviation
scoreHistoryAddition = [Date.now(), newTotalScore]
updateObject =
meanStrength: scoreObject.meanStrength
standardDeviation: scoreObject.standardDeviation
totalScore: newTotalScore
$push: {scoreHistory: {$each: [scoreHistoryAddition], $slice: -1000}}
LevelSession.update {"_id": scoreObject.id}, updateObject, callback
log.info "New total score for session #{scoreObject.id} is #{updateObject.totalScore}"
putRankingFromMetricsIntoScoreObject = (taskObject,scoreObject) ->
scoreObject = _.indexBy scoreObject, 'id'
scoreObject[session.sessionID].gameRanking = session.metrics.rank for session in taskObject.sessions

View file

@ -71,9 +71,7 @@ module.exports.setup = (app) ->
if req.user
sendSelf(req, res)
else
user = new User({anonymous:true})
user.set 'testGroupNumber', Math.floor(Math.random() * 256) # also in app/lib/auth
user.set 'preferredLanguage', languages.languageCodeFromAcceptedLanguages req.acceptedLanguages
user = makeNewUser(req)
makeNext = (req, res) -> -> sendSelf(req, res)
next = makeNext(req, res)
loginUser(req, res, user, false, next)
@ -84,21 +82,6 @@ module.exports.setup = (app) ->
res.send(UserHandler.formatEntity(req, req.user))
res.end()
loginUser = (req, res, user, send=true, next=null) ->
user.save((err) ->
if err
return @sendDatabaseError(res, err)
req.logIn(user, (err) ->
if err
return @sendDatabaseError(res, err)
if send
return @sendSuccess(res, user)
next() if next
)
)
app.post('/auth/logout', (req, res) ->
req.logout()
res.end()
@ -155,6 +138,26 @@ module.exports.setup = (app) ->
res.send "Unsubscribed #{req.query.email} from all CodeCombat emails. Sorry to see you go! <p><a href='/account/settings'>Account settings</a></p>"
res.end()
module.exports.loginUser = loginUser = (req, res, user, send=true, next=null) ->
user.save((err) ->
if err
return @sendDatabaseError(res, err)
req.logIn(user, (err) ->
if err
return @sendDatabaseError(res, err)
if send
return @sendSuccess(res, user)
next() if next
)
)
module.exports.makeNewUser = makeNewUser = (req) ->
user = new User({anonymous:true})
user.set 'testGroupNumber', Math.floor(Math.random() * 256) # also in app/lib/auth
user.set 'preferredLanguage', languages.languageCodeFromAcceptedLanguages req.acceptedLanguages
createMailOptions = (receiver, password) ->
# TODO: use email templates here
options =
@ -163,4 +166,4 @@ createMailOptions = (receiver, password) ->
replyTo: config.mail.username
subject: "[CodeCombat] Password Reset"
text: "You can log into your account with: #{password}"
#

View file

@ -9,6 +9,8 @@ baseRoute = require './server/routes/base'
user = require './server/users/user_handler'
logging = require './server/commons/logging'
config = require './server_config'
auth = require './server/routes/auth'
UserHandler = require('./server/users/user_handler')
###Middleware setup functions implementation###
# 2014-03-03: Try not using this and see if it's still a problem
@ -85,7 +87,19 @@ exports.setupMiddleware = (app) ->
setupFallbackRouteToIndex = (app) ->
app.all '*', (req, res) ->
res.sendfile path.join(__dirname, 'public', 'index.html')
if req.user
sendMain(req, res)
else
user = auth.makeNewUser(req)
makeNext = (req, res) -> -> sendMain(req, res)
next = makeNext(req, res)
auth.loginUser(req, res, user, false, next)
sendMain = (req, res) ->
fs.readFile path.join(__dirname, 'public', 'main.html'), 'utf8', (err,data) ->
# insert the user object directly into the html so the application can have it immediately
data = data.replace('"userObjectTag"', JSON.stringify(UserHandler.formatEntity(req, req.user)))
res.send data
setupFacebookCrossDomainCommunicationRoute = (app) ->
app.get '/channel.html', (req, res) ->