Merge branch 'master' into production

This commit is contained in:
Nick Winter 2014-02-08 10:21:34 -08:00
commit d417f0e693
50 changed files with 323 additions and 73 deletions

Binary file not shown.

Before

(image error) Size: 8.2 KiB

Binary file not shown.

After

(image error) Size: 10 KiB

Binary file not shown.

Before

(image error) Size: 3.4 KiB

Binary file not shown.

After

(image error) Size: 12 KiB

Binary file not shown.

Before

(image error) Size: 2.7 KiB

Binary file not shown.

After

(image error) Size: 9.2 KiB

Binary file not shown.

Before

(image error) Size: 7.8 KiB

Binary file not shown.

After

(image error) Size: 11 KiB

Binary file not shown.

Before

(image error) Size: 7.2 KiB

Binary file not shown.

After

(image error) Size: 12 KiB

Binary file not shown.

After

(image error) Size: 7.9 KiB

Binary file not shown.

After

(image error) Size: 7.7 KiB

Binary file not shown.

After

(image error) Size: 8.9 KiB

Binary file not shown.

After

(image error) Size: 9.6 KiB

Binary file not shown.

After

(image error) Size: 6.6 KiB

Binary file not shown.

After

(image error) Size: 8.6 KiB

Binary file not shown.

After

(image error) Size: 7.6 KiB

Binary file not shown.

After

(image error) Size: 12 KiB

Binary file not shown.

After

(image error) Size: 10 KiB

Binary file not shown.

After

(image error) Size: 8.3 KiB

Binary file not shown.

After

(image error) Size: 6.6 KiB

Binary file not shown.

After

(image error) Size: 8.4 KiB

Binary file not shown.

After

(image error) Size: 8.6 KiB

Binary file not shown.

After

(image error) Size: 9.2 KiB

Binary file not shown.

After

(image error) Size: 8.1 KiB

Binary file not shown.

After

(image error) Size: 8.7 KiB

Binary file not shown.

After

(image error) Size: 9.4 KiB

Binary file not shown.

After

(image error) Size: 8.6 KiB

Binary file not shown.

After

(image error) Size: 8.9 KiB

Binary file not shown.

After

(image error) Size: 9.7 KiB

Binary file not shown.

After

(image error) Size: 9.2 KiB

Binary file not shown.

After

(image error) Size: 7.1 KiB

View file

@ -120,6 +120,8 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
@actionQueue.push @currentRootAction.relatedActions.end if @currentRootAction?.relatedActions?.end
@actionQueue.push action.relatedActions.begin if action.relatedActions?.begin
@actionQueue.push action
if action.goesTo and nextAction = @actions[action.goesTo]
@actionQueue.push nextAction if nextAction
@currentRootAction = action
@playNextAction()

View file

@ -420,7 +420,7 @@ module.exports = class World
pos = camera.worldToSurface {x: pos.x, y: pos.y} if camera # without z
if not lastPos.x? or (Math.abs(lastPos.x - pos.x) + Math.abs(lastPos.y - pos.y)) > 1
lastPos = pos
allPoints.push lastPos.y, lastPos.x
allPoints.push lastPos.y, lastPos.x unless lastPos.y is 0 and lastPos.x is 0
allPoints.reverse()
@pointsForThangCache[cacheKey] = allPoints

View file

@ -1,31 +1,31 @@
module.exports = nativeDescription: "עברית", englishDescription: "Hebrew", translation:
common:
loading: "Loading..."
# saving: "Saving..."
# sending: "Sending..."
# cancel: "Cancel"
# save: "Save"
# delay_1_sec: "1 second"
# delay_3_sec: "3 seconds"
# delay_5_sec: "5 seconds"
# manual: "Manual"
loading: "...טוען"
saving: "...שומר"
sending: "...שולח"
cancel: "ביטול"
save: "שמור"
delay_1_sec: "שניה אחת"
delay_3_sec: "שלוש שניות"
delay_5_sec: "חמש שניות"
manual: "מדריך"
# fork: "Fork"
# play: "Play"
play: "שחק"
# modal:
# close: "Close"
# okay: "Okay"
modal:
close: "סגור"
okay: "אישור"
# not_found:
# page_not_found: "Page not found"
not_found:
page_not_found: "העמוד לא נמצא"
# nav:
# play: "Levels"
# editor: "Editor"
# blog: "Blog"
# forum: "Forum"
# admin: "Admin"
# home: "Home"
nav:
play: "שלבים"
editor: "עורך"
blog: "בלוג"
forum: "פורום"
admin: "אדמין"
home: "בית"
# contribute: "Contribute"
# legal: "Legal"
# about: "About"

View file

@ -38,4 +38,17 @@
.saved-notification
display: none
float: right
float: right
.thumbnail
background-color: transparent
height: 176px
&:hover
background-color: rgba(200, 244, 255, 0.2)
h4
text-align: center
img
max-width: 100px
max-height: 100px

View file

@ -0,0 +1,2 @@
#ladder-view
color: black

View file

@ -82,7 +82,7 @@ block content
li.row
img(src="/images/pages/about/george.jpg").img-thumbnail
img(src="/images/pages/about/george_small.png").img-thumbnail
.col-sm-8
@ -95,7 +95,7 @@ block content
li.row
img(src="/images/pages/about/scott.jpg").img-thumbnail
img(src="/images/pages/about/scott_small.png").img-thumbnail
.col-sm-8
@ -109,7 +109,7 @@ block content
li.row
img(src="/images/pages/about/nick.jpg").img-thumbnail
img(src="/images/pages/about/nick_small.png").img-thumbnail
.col-sm-8
@ -123,12 +123,11 @@ block content
li.row
img(src="/images/pages/about/jeremy.jpg").img-thumbnail
img(src="/images/pages/about/jeremy_small.png").img-thumbnail
.col-sm-8
h3
Jeremy Arns
h3 Jeremy Arns
p(data-i18n="about.jeremy_description")
| Customer support mage, usability tester,
@ -137,7 +136,7 @@ block content
li.row
img(src="/images/pages/about/michael.jpg").img-thumbnail
img(src="/images/pages/about/michael_small.png").img-thumbnail
.col-sm-8

View file

@ -79,25 +79,15 @@ block content
#Contributors
h3(data-i18n="contribute.powerful_archmages")
| Our Powerful Archmages:
ul.archmages
li Tom Steinbrecher
li Glen De Cauwsemaecker
li Sébastien Moratinos
li Ronnie Cheng
li phansch
li Zach Martin
li David Golds
li deepak1556
li Chloe Fan
li Rachel Xiang
li Dan Ristic
li gabceb
li Laura Watiker
li Shiying Zheng
li Mischa Lewis-Norelle
li Paul Buser
li Benjamin Stern
li Alex Cotsarelis
li MDP66
.row
for contributor in contributors
.col-xs-6.col-md-3
.thumbnail
if contributor.avatar
img.img-responsive(src="/images/pages/contribute/archmage/" + contributor.avatar + "_small.png", alt="")
else
img.img-responsive(src="/images/pages/contribute/archmage.png", alt="")
.caption
h4= contributor.name
div.clearfix
div.clearfix

View file

@ -77,17 +77,17 @@ block content
#Contributors
h3(data-i18n="contribute.creative_artisans")
| Our Creative Artisans:
ul.artisans
li Sootn
li Zach Martin
li Aftermath
li mcdavid1991
li dwhittaker
li Zacharias Fisches
li Tom Setliff
li Robert Moreton
li Andrew Witcher
li Axandre Oge
li Katharine Chan
.row
for contributor in contributors
.col-xs-6.col-md-3
.thumbnail
if contributor.avatar
img.img-responsive(src="/images/pages/contribute/artisan/" + contributor.avatar + "_small.png", alt="")
else
img.img-responsive(src="/images/pages/contribute/artisan.png", alt="")
.caption
h4= contributor.name
div.clearfix
div.clearfix

View file

@ -0,0 +1,31 @@
extends /templates/base
block content
div#level-column
h3= level.get('name')
div#level-description
!{description}
div#leaderboard-column
ul.nav.nav-pills
for team in teams
li
a(href="#team-#{team.id}", data-toggle="tab")= team.name
.tab-content
for team in teams
.tab-pane(id="team-#{team.id}")
.leaderboard
h4 Leaderboard
table.table
for session in team.leaderboard.topPlayers.models
tr= session.get('creatorName')
.challengers
h4 Challengers
if team.easyChallenger
div.challenger-select
| Easy challenger:
button
a(href=link+'?team='+team.id+'&opponent='+team.easyChallenger.id)
//TODO: finish once the scoring system is finished

View file

@ -28,8 +28,11 @@
if playableTeams.length > 1
#multiplayer-team-selection
for team in playableTeams
label(for="multiplayer_team_"+team)= team
input(id="multiplayer_team_"+team, type="radio", name="multiplayer", value=team)
h4
if team == me.team
em= "Playing as " + team
else
a(href=joinLink + "&skip_protect_api=true&team=" + team)= "Play as " + team
.modal-footer
a(href='#', data-dismiss="modal", aria-hidden="true", data-i18n="modal.close").btn.btn-primary Close

View file

@ -3,4 +3,30 @@ template = require 'templates/contribute/archmage'
module.exports = class ArchmageView extends ContributeClassView
id: "archmage-view"
template: template
template: template
contributors: [
{name: "Tom Steinbrecher", avatar: "tom"}
{name: "Glen De Cauwsemaecker", avatar: "glen"}
{name: "Sébastien Moratinos", avatar: "sebastien"}
{name: "deepak1556", avatar: "deepak"}
{name: "Ronnie Cheng", avatar: "ronald"}
{name: "Chloe Fan", avatar: "chloe"}
{name: "Rachel Xiang", avatar: "rachel"}
{name: "Dan Ristic", avatar: "dan"}
{name: "Brad Dickason", avatar: "brad"}
{name: "Rebecca Saines", avatar: "becca"}
{name: "Laura Watiker", avatar: "laura"}
{name: "Shiying Zheng", avatar: "shiying"}
{name: "Mischa Lewis-Norelle", avatar: "mischa"}
{name: "Paul Buser", avatar: "paul"}
{name: "Benjamin Stern", avatar: "ben"}
{name: "Alex Cotsarelis", avatar: "alex"}
{name: "Ken Stanley", avatar: "ken"}
{name: "devast8a", avatar: ""}
{name: "phansch", avatar: ""}
{name: "Zach Martin", avatar: ""}
{name: "David Golds", avatar: ""}
{name: "gabceb", avatar: ""}
{name: "MDP66", avatar: ""}
]

View file

@ -4,4 +4,19 @@ template = require 'templates/contribute/artisan'
module.exports = class ArtisanView extends ContributeClassView
id: "artisan-view"
template: template
template: template
contributors: [
{name: "Sootn", avatar: ""}
{name: "Zach Martin", avatar: ""}
{name: "Aftermath", avatar: ""}
{name: "mcdavid1991", avatar: ""}
{name: "dwhittaker", avatar: ""}
{name: "Zacharias Fisches", avatar: ""}
{name: "Tom Setliff", avatar: ""}
{name: "Robert Moreton", avatar: "rob"}
{name: "Andrew Witcher", avatar: "andrew"}
{name: "Axandre Oge", avatar: "axandre"}
{name: "Katharine Chan", avatar: "katharine"}
{name: "Derek Wong", avatar: "derek"}
]

View file

@ -11,6 +11,7 @@ module.exports = class ContributeClassView extends View
getRenderData: ->
c = super()
c.navPrefix = @navPrefix
c.contributors = @contributors
c
afterRender: ->
@ -36,3 +37,5 @@ module.exports = class ContributeClassView extends View
me.set('emailSubscriptions', subscriptions)
me.save()
contributors: []

View file

@ -0,0 +1,138 @@
RootView = require 'views/kinds/RootView'
Level = require 'models/Level'
LevelSession = require 'models/LevelSession'
CocoCollection = require 'models/CocoCollection'
HIGHEST_SCORE = 1000000
class LevelSessionsCollection extends CocoCollection
url: ''
model: LevelSession
constructor: (levelID) ->
super()
@url = "/db/level/#{levelID}/all_sessions"
class LeaderboardCollection extends CocoCollection
url: ''
model: LevelSession
constructor: (level, options) ->
super()
options ?= {}
@url = "/db/level/#{level.get('original')}.#{level.get('version').major}/leaderboard?#{$.param(options)}"
module.exports = class LadderView extends RootView
id: 'ladder-view'
template: require 'templates/play/ladder'
startsLoading: true
constructor: (options, levelID) ->
super(options)
@level = new Level(_id:levelID)
@level.fetch()
@level.once 'sync', @onLevelLoaded, @
@sessions = new LevelSessionsCollection(levelID)
@sessions.fetch({})
@sessions.once 'sync', @onMySessionsLoaded, @
onLevelLoaded: -> @startLoadingPhaseTwoMaybe()
onMySessionsLoaded: -> @startLoadingPhaseTwoMaybe()
startLoadingPhaseTwoMaybe: ->
return unless @level.loaded and @sessions.loaded
@loadPhaseTwo()
loadPhaseTwo: ->
alliedSystem = _.find @level.get('systems'), (value) -> value.config?.teams?
teams = []
for teamName, teamConfig of alliedSystem.config.teams
continue unless teamConfig.playable
teams.push teamName
@teams = teams
@leaderboards = {}
@challengers = {}
for team in teams
teamSession = _.find @sessions.models, (session) -> session.get('team') is team
@leaderboards[team] = new LeaderboardData(@level, team, teamSession)
@leaderboards[team].once 'sync', @onLeaderboardLoaded, @
@challengers[team] = new ChallengersData(@level, team, teamSession)
@challengers[team].once 'sync', @onChallengersLoaded, @
onChallengersLoaded: -> @renderMaybe()
onLeaderboardLoaded: -> @renderMaybe()
renderMaybe: ->
loaders = _.values(@leaderboards).concat(_.values(@challengers))
return unless _.every loaders, (loader) -> loader.loaded
@startsLoading = false
@render()
getRenderData: ->
ctx = super()
ctx.level = @level
description = @level.get('description')
ctx.description = if description then marked(description) else ''
ctx.link = "/play/level/#{@level.get('name')}"
ctx.teams = []
for team in @teams or []
ctx.teams.push({
id: team
name: _.string.titleize(team)
leaderboard: @leaderboards[team]
easyChallenger: @challengers[team].easyPlayer.models[0]
mediumChallenger: @challengers[team].mediumPlayer.models[0]
hardChallenger: @challengers[team].hardPlayer.models[0]
})
ctx
afterRender: ->
super()
@$el.find('#leaderboard-column .nav a:first').tab('show')
class LeaderboardData
constructor: (@level, @team, @session) ->
_.extend @, Backbone.Events
@topPlayers = new LeaderboardCollection(@level, {order:-1, scoreOffset: HIGHEST_SCORE, team: @team, limit: if @session then 10 else 20})
@topPlayers.fetch()
@topPlayers.once 'sync', @leaderboardPartLoaded, @
if @session
score = @session.get('score') or 25
@playersAbove = new LeaderboardCollection(@level, {order:1, scoreOffset: score, limit: 4, team: @team})
@playersAbove.fetch()
@playersAbove.once 'sync', @leaderboardPartLoaded, @
@playersBelow = new LeaderboardCollection(@level, {order:-1, scoreOffset: score, limit: 4, team: @team})
@playersBelow.fetch()
@playersBelow.once 'sync', @leaderboardPartLoaded, @
leaderboardPartLoaded: ->
if @session
if @topPlayers.loaded and @playersAbove.loaded and @playersBelow.loaded
@loaded = true
@trigger 'sync'
else
@loaded = true
@trigger 'sync'
class ChallengersData
constructor: (@level, @team, @session) ->
_.extend @, Backbone.Events
score = @session?.get('score') or 25
@easyPlayer = new LeaderboardCollection(@level, {order:1, scoreOffset: score - 5, limit: 1, team: @team})
@easyPlayer.fetch()
@easyPlayer.once 'sync', @challengerLoaded, @
@mediumPlayer = new LeaderboardCollection(@level, {order:1, scoreOffset: score, limit: 1, team: @team})
@mediumPlayer.fetch()
@mediumPlayer.once 'sync', @challengerLoaded, @
@hardPlayer = new LeaderboardCollection(@level, {order:-1, scoreOffset: score + 5, limit: 1, team: @team})
@hardPlayer.fetch()
@hardPlayer.once 'sync', @challengerLoaded, @
challengerLoaded: ->
if @easyPlayer.loaded and @mediumPlayer.loaded and @hardPlayer.loaded
@loaded = true
@trigger 'sync'

View file

@ -28,9 +28,6 @@ module.exports = class MultiplayerModal extends View
afterRender: ->
super()
@updateLinkSection()
@$el.find('#multiplayer-team-selection input')
.prop('checked', -> $(@).val() is me.team)
.bind('change', -> Backbone.Mediator.publish 'level:set-team', team: $(@).val())
onClickLink: (e) ->
e.target.select()

View file

@ -123,7 +123,8 @@ module.exports = class PlayLevelView extends View
@levelLoader.destroy()
@levelLoader = null
@loadingScreen.destroy()
@setTeam @world.teamForPlayer _.size @session.get 'players' # TODO: players aren't initialized yet?
#@setTeam @world.teamForPlayer _.size @session.get 'players' # TODO: players aren't initialized yet?
@setTeam @getQueryVariable("team") ? @world.teamForPlayer(0)
@initSurface()
@initGod()
@initGoalManager()

View file

@ -23,6 +23,8 @@ LevelHandler = class LevelHandler extends Handler
getByRelationship: (req, res, args...) ->
return @getSession(req, res, args[0]) if args[1] is 'session'
return @getLeaderboard(req, res, args[0]) if args[1] is 'leaderboard'
return @getAllSessions(req, res, args[0]) if args[1] is 'all_sessions'
return @getFeedback(req, res, args[0]) if args[1] is 'feedback'
return @sendNotFoundError(res)
@ -36,6 +38,9 @@ LevelHandler = class LevelHandler extends Handler
level: {original: level.original.toString(), majorVersion: level.version.major}
creator: req.user.id
}
sessionQuery.team = req.query.team if req.query.team
Session.findOne(sessionQuery).exec (err, doc) =>
return @sendDatabaseError(res, err) if err
if doc
@ -45,6 +50,7 @@ LevelHandler = class LevelHandler extends Handler
initVals = sessionQuery
initVals.state = {complete:false, scripts:{currentScript:null}} # will not save empty objects
initVals.permissions = [{target:req.user.id, access:'owner'}, {target:'public', access:'write'}]
initVals.team = req.query.team if req.query.team
session = new Session(initVals)
session.save (err) =>
return @sendDatabaseError(res, err) if err
@ -53,6 +59,29 @@ LevelHandler = class LevelHandler extends Handler
# associated with the handler, because the handler might return a different type
# of model, like in this case. Refactor to move that logic to the model instead.
getAllSessions: (req, res, id) ->
@getDocumentForIdOrSlug id, (err, level) =>
return @sendDatabaseError(res, err) if err
return @sendNotFoundError(res) unless level?
return @sendUnauthorizedError(res) unless @hasAccessToDocument(req, level)
sessionQuery = {
level: {original: level.original.toString(), majorVersion: level.version.major}
creator: req.user.id
}
Session.find(sessionQuery).exec (err, results) =>
return @sendDatabaseError(res, err) if err
res.send(results)
res.end()
getLeaderboard: (req, res, id) ->
# stub handler
# [original, version] = id.split('.')
# version = parseInt version
# console.log 'get leaderboard for', original, version, req.query
return res.send([])
getFeedback: (req, res, id) ->
@getDocumentForIdOrSlug id, (err, level) =>
return @sendDatabaseError(res, err) if err

View file

@ -25,6 +25,7 @@ _.extend LevelSessionSchema.properties,
creator: c.objectId(links: [{rel: 'extra', href: "/db/user/{($)}"}])
created: c.date( { title: 'Created', readOnly: true })
changed: c.date( { title: 'Changed', readOnly: true })
team: c.shortString()
level: LevelSessionLevelSchema
screenshot: { type: 'string' }
state: c.object {}, {