Merge branch 'master' into production

This commit is contained in:
Nick Winter 2014-03-27 13:40:27 -07:00
commit e57a1655c6
13 changed files with 84 additions and 67 deletions

View file

@ -74,7 +74,7 @@
<script> <script>
// Additional JS functions here // Additional JS functions here
window.fbAsyncInit = function() { window.fbAsyncInit = function() {
Backbone.Mediator.publish('fbapi-loaded') Backbone.Mediator.publish('fbapi-loaded');
FB.init({ FB.init({
appId : document.location.origin === 'http://localhost:3000' ? '607435142676437' : '148832601965463', // App ID appId : document.location.origin === 'http://localhost:3000' ? '607435142676437' : '148832601965463', // App ID
channelUrl : document.location.origin +'/channel.html', // Channel File channelUrl : document.location.origin +'/channel.html', // Channel File

View file

@ -49,6 +49,7 @@ module.exports = ScriptManager = class ScriptManager extends CocoClass
@originalScripts = options.scripts @originalScripts = options.scripts
@view = options.view @view = options.view
@session = options.session @session = options.session
@debugScripts = @view.getQueryVariable 'dev'
@initProperties() @initProperties()
@addScriptSubscriptions() @addScriptSubscriptions()
@ -146,7 +147,7 @@ module.exports = ScriptManager = class ScriptManager extends CocoClass
continue unless @scriptPrereqsSatisfied(script) continue unless @scriptPrereqsSatisfied(script)
continue unless scriptMatchesEventPrereqs(script, event) continue unless scriptMatchesEventPrereqs(script, event)
# everything passed! # everything passed!
console.log "SCRIPT: Running script '#{script.id}'" console.log "SCRIPT: Running script '#{script.id}'" if @debugScripts
script.lastTriggered = new Date().getTime() script.lastTriggered = new Date().getTime()
@triggered.push(script.id) unless alreadyTriggered @triggered.push(script.id) unless alreadyTriggered
noteChain = @processScript(script) noteChain = @processScript(script)
@ -206,7 +207,7 @@ module.exports = ScriptManager = class ScriptManager extends CocoClass
@notifyScriptStateChanged() @notifyScriptStateChanged()
@scriptInProgress = true @scriptInProgress = true
@currentTimeouts = [] @currentTimeouts = []
console.log "SCRIPT: Starting note group '#{nextNoteGroup.name}'" console.log "SCRIPT: Starting note group '#{nextNoteGroup.name}'" if @debugScripts
for module in nextNoteGroup.modules for module in nextNoteGroup.modules
@processNote(note, nextNoteGroup) for note in module.startNotes() @processNote(note, nextNoteGroup) for note in module.startNotes()
if nextNoteGroup.script.duration if nextNoteGroup.script.duration
@ -220,7 +221,7 @@ module.exports = ScriptManager = class ScriptManager extends CocoClass
@ignoreEvents = true @ignoreEvents = true
for noteGroup, i in @noteGroupQueue for noteGroup, i in @noteGroupQueue
break unless noteGroup.skipMe break unless noteGroup.skipMe
console.log "SCRIPT: Skipping note group '#{noteGroup.name}'" console.log "SCRIPT: Skipping note group '#{noteGroup.name}'" if @debugScripts
@processNoteGroup(noteGroup) @processNoteGroup(noteGroup)
for module in noteGroup.modules for module in noteGroup.modules
notes = module.skipNotes() notes = module.skipNotes()
@ -267,7 +268,7 @@ module.exports = ScriptManager = class ScriptManager extends CocoClass
return if @ending # kill infinite loops right here return if @ending # kill infinite loops right here
@ending = true @ending = true
return unless @currentNoteGroup? return unless @currentNoteGroup?
console.log "SCRIPT: Ending note group '#{@currentNoteGroup.name}'" console.log "SCRIPT: Ending note group '#{@currentNoteGroup.name}'" if @debugScripts
clearTimeout(timeout) for timeout in @currentTimeouts clearTimeout(timeout) for timeout in @currentTimeouts
for module in @currentNoteGroup.modules for module in @currentNoteGroup.modules
@processNote(note, @currentNoteGroup) for note in module.endNotes() @processNote(note, @currentNoteGroup) for note in module.endNotes()

View file

@ -360,7 +360,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
opensource_description_center: "и посодействуйте, если вам понравилось! CodeCombat построен на десятках проектов с открытым кодом, и мы любим их. Загляните в " opensource_description_center: "и посодействуйте, если вам понравилось! CodeCombat построен на десятках проектов с открытым кодом, и мы любим их. Загляните в "
archmage_wiki_url: "наш вики-портал для Архимагов" archmage_wiki_url: "наш вики-портал для Архимагов"
opensource_description_suffix: ", чтобы увидеть список программного обеспечения, делающего игру возможной." opensource_description_suffix: ", чтобы увидеть список программного обеспечения, делающего игру возможной."
practices_title: "Почтительные лучшие практики" practices_title: "Уважаемые лучшие практики"
practices_description: "Это наши обещания тебе, игроку, менее юридическим языком." practices_description: "Это наши обещания тебе, игроку, менее юридическим языком."
privacy_title: "Конфиденциальность" privacy_title: "Конфиденциальность"
privacy_description: "Мы не будем продавать какой-либо личной информации. Мы намерены заработать деньги с помощью рекрутинга в конечном счёте, но будьте уверены, мы не будем распространять вашу личную информацию заинтересованным компаниям без вашего явного согласия." privacy_description: "Мы не будем продавать какой-либо личной информации. Мы намерены заработать деньги с помощью рекрутинга в конечном счёте, но будьте уверены, мы не будем распространять вашу личную информацию заинтересованным компаниям без вашего явного согласия."
@ -421,7 +421,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
introduction_desc_github_url: "исходный код CodeCombat полностью открыт" introduction_desc_github_url: "исходный код CodeCombat полностью открыт"
introduction_desc_suf: ", и мы стремимся предоставить как можно больше способов, чтобы вы могли принять участие и сделать этот проект настолько же вашим, как и нашим." introduction_desc_suf: ", и мы стремимся предоставить как можно больше способов, чтобы вы могли принять участие и сделать этот проект настолько же вашим, как и нашим."
introduction_desc_ending: "Мы надеемся, что вы присоединитесь к нашей команде!" introduction_desc_ending: "Мы надеемся, что вы присоединитесь к нашей команде!"
introduction_desc_signature: "- Ник, Джордж, Скотт, Михаэль, Джереми и лощина" introduction_desc_signature: "- Ник, Джордж, Скотт, Михаэль, Джереми и Глен"
alert_account_message_intro: "Привет!" alert_account_message_intro: "Привет!"
alert_account_message_pref: "Чтобы подписаться на email-ы для классов, вам необходимо сначала " alert_account_message_pref: "Чтобы подписаться на email-ы для классов, вам необходимо сначала "
alert_account_message_suf: "." alert_account_message_suf: "."

View file

@ -36,9 +36,9 @@
margin-bottom: 5px margin-bottom: 5px
.connect-buttons .connect-buttons
margin-bottom: 10px margin-bottom: 15px
.btn .btn
margin-left: 5px margin-right: 5px
.friend-entry img .friend-entry img
float: left float: left

View file

@ -73,7 +73,8 @@
.executing, .executed, .problem-marker-info, .problem-marker-warning, .problem-marker-error .executing, .executed, .problem-marker-info, .problem-marker-warning, .problem-marker-error
position: absolute position: absolute
.executing .executing
background-color: rgba(50, 255, 80, 0.35) // https://github.com/codecombat/codecombat/issues/6
background-color: rgba(50, 255, 80, 0.65)
@include gradient-striped() @include gradient-striped()
.executed .executed
background-color: rgba(110, 110, 110, 0.12) background-color: rgba(110, 110, 110, 0.12)
@ -113,3 +114,8 @@
.ace_text-layer .ace_comment .ace_text-layer .ace_comment
color: darken(rgb(103, 164, 200), 5%) color: darken(rgb(103, 164, 200), 5%)
.ace_text-layer .ace_variable
// https://github.com/codecombat/codecombat/issues/6
color: rgb(145, 48, 50)

View file

@ -47,31 +47,27 @@ div#columns.row
a(data-toggle="coco-modal", data-target="modal/signup") Sign up to play with your friends! a(data-toggle="coco-modal", data-target="modal/signup") Sign up to play with your friends!
else else
if !onFacebook if !onFacebook || !onGPlus
div.connect-buttons div.connect-buttons
| Connect: | Connect and play against your friends!
br
if !onFacebook if !onFacebook
button.btn.btn-sm.connect-facebook Facebook button.btn.btn-sm.connect-facebook Facebook
//button.btn.btn-sm.connect-google-plus Google+ if !onGPlus
button.btn.btn-sm.connect-google-plus Google+
if !!friends if friends.length
for friend in friends
if friends.length p.friend-entry
for friend in friends img(src=friend.imageSource).img-thumbnail
p.friend-entry span= friend.creatorName + ' (' + friend.name + ')'
img(src="http://graph.facebook.com/#{friend.facebookID}/picture").img-thumbnail br
span= friend.creatorName + ' (' + friend.facebookName + ')' span= Math.round(friend.totalScore * 100)
br span :
span= Math.round(friend.totalScore * 100) span= friend.team
span : br
span= friend.team a(href="/play/level/#{level.get('slug') || level.id}/?team=#{friend.otherTeam}&opponent=#{friend._id}")
br span(data-i18n="ladder.fight") Fight!
a(href="/play/level/#{level.get('slug') || level.id}/?team=#{friend.otherTeam}&opponent=#{friend._id}")
span(data-i18n="ladder.fight") Fight!
else
p Invite your friends to join you in battle!
else else
p Connect to social networks to play with your friends! p Invite your friends to join you in battle!

View file

@ -24,7 +24,7 @@ module.exports = class WizardSettingsView extends CocoView
@wizardThangType = new ThangType() @wizardThangType = new ThangType()
@wizardThangType.url = -> '/db/thang.type/wizard' @wizardThangType.url = -> '/db/thang.type/wizard'
@wizardThangType.fetch() @wizardThangType.fetch()
@wizardThangType.once 'sync', @initCanvas, @ @listenToOnce(@wizardThangType, 'sync', @initCanvas)
initCanvas: -> initCanvas: ->
@startsLoading = false @startsLoading = false

View file

@ -11,8 +11,8 @@ module.exports = class ColorsTabView extends CocoView
offset: 0 offset: 0
constructor: (@thangType, options) -> constructor: (@thangType, options) ->
@thangType.once 'sync', @tryToBuild, @ @listenToOnce(@thangType, 'sync', @tryToBuild)
@thangType.schema().once 'sync', @tryToBuild, @ @listenToOnce(@thangType.schema(), 'sync', @tryToBuild)
@colorConfig = { hue: 0, saturation: 0.5, lightness: 0.5 } @colorConfig = { hue: 0, saturation: 0.5, lightness: 0.5 }
@spriteBuilder = new SpriteBuilder(@thangType) @spriteBuilder = new SpriteBuilder(@thangType)
f = => f = =>

View file

@ -196,12 +196,12 @@ module.exports = class CocoView extends Backbone.View
# Utilities # Utilities
getQueryVariable: (param) -> getQueryVariable: (param, defaultValue) ->
query = document.location.search.substring 1 query = document.location.search.substring 1
pairs = (pair.split("=") for pair in query.split "&") pairs = (pair.split("=") for pair in query.split "&")
for pair in pairs for pair in pairs when pair[0] is param
return decodeURIComponent(pair[1]) if pair[0] is param return {"true": true, "false": false}[pair[1]] ? decodeURIComponent(pair[1])
null defaultValue
getRootView: -> getRootView: ->
view = @ view = @

View file

@ -22,19 +22,25 @@ module.exports = class LadderTabView extends CocoView
events: events:
'click .connect-facebook': 'onConnectFacebook' 'click .connect-facebook': 'onConnectFacebook'
'click .connect-google-plus': 'onConnectGPlus'
subscriptions: subscriptions:
'fbapi-loaded': 'onFacebookAPILoaded' 'fbapi-loaded': 'checkFriends'
'gapi-loaded': 'onGPlusAPILoaded' 'gapi-loaded': 'checkFriends'
'facebook-logged-in': 'onConnectedWithFacebook' 'facebook-logged-in': 'onConnectedWithFacebook'
'gplus-logged-in': 'onConnectedWithGPlus'
constructor: (options, @level, @sessions) -> constructor: (options, @level, @sessions) ->
super(options) super(options)
@teams = teamDataFromLevel @level @teams = teamDataFromLevel @level
@leaderboards = {} @leaderboards = {}
@refreshLadder() @refreshLadder()
@checkFriends()
checkFriends: -> checkFriends: ->
return if @checked or (not window.FB) or (not window.gapi)
@checked = true
@loadingFacebookFriends = true @loadingFacebookFriends = true
FB.getLoginStatus (response) => FB.getLoginStatus (response) =>
@facebookStatus = response.status @facebookStatus = response.status
@ -46,24 +52,14 @@ module.exports = class LadderTabView extends CocoView
else else
@gplusSessionStateLoaded() @gplusSessionStateLoaded()
apiLoaded: ->
return unless @fbAPILoaded and @gplusAPILoaded
@checkFriends()
# FACEBOOK # FACEBOOK
onFacebookAPILoaded: ->
@fbAPILoaded = true
@apiLoaded()
# Connect button pressed
onConnectFacebook: -> onConnectFacebook: ->
@connecting = true @connecting = true
FB.login() FB.login()
onConnectedWithFacebook: -> location.reload() if @connecting onConnectedWithFacebook: -> location.reload() if @connecting
# Load friends
loadFacebookFriendSessions: -> loadFacebookFriendSessions: ->
FB.api '/me/friends', (response) => FB.api '/me/friends', (response) =>
@facebookData = response.data @facebookData = response.data
@ -79,17 +75,21 @@ module.exports = class LadderTabView extends CocoView
friendsMap = {} friendsMap = {}
friendsMap[friend.id] = friend.name for friend in @facebookData friendsMap[friend.id] = friend.name for friend in @facebookData
for friend in result for friend in result
friend.facebookName = friendsMap[friend.facebookID] friend.name = friendsMap[friend.facebookID]
friend.otherTeam = if friend.team is 'humans' then 'ogres' else 'humans' friend.otherTeam = if friend.team is 'humans' then 'ogres' else 'humans'
@facebookFriends = result friend.imageSource = "http://graph.facebook.com/#{friend.facebookID}/picture"
@facebookFriendSessions = result
@loadingFacebookFriends = false @loadingFacebookFriends = false
@renderMaybe() @renderMaybe()
# GOOGLE PLUS # GOOGLE PLUS
onGPlusAPILoaded: -> onConnectGPlus: ->
@gplusAPILoaded = true @connecting = true
@apiLoaded() @listenToOnce application.gplusHandler, 'logged-in', @onConnectedWithGPlus
application.gplusHandler.reauthorize()
onConnectedWithGPlus: -> location.reload() if @connecting
gplusSessionStateLoaded: -> gplusSessionStateLoaded: ->
if application.gplusHandler.loggedIn if application.gplusHandler.loggedIn
@ -110,6 +110,13 @@ module.exports = class LadderTabView extends CocoView
} }
onGPlusFriendSessionsLoaded: (result) => onGPlusFriendSessionsLoaded: (result) =>
friendsMap = {}
friendsMap[friend.id] = friend for friend in @gplusData
for friend in result
friend.name = friendsMap[friend.gplusID].displayName
friend.otherTeam = if friend.team is 'humans' then 'ogres' else 'humans'
friend.imageSource = friendsMap[friend.gplusID].image.url
@gplusFriendSessions = result
@loadingGPlusFriends = false @loadingGPlusFriends = false
@renderMaybe() @renderMaybe()
@ -130,7 +137,7 @@ module.exports = class LadderTabView extends CocoView
@renderMaybe() @renderMaybe()
renderMaybe: -> renderMaybe: ->
return if @loadingFacebookFriends or @loadingLeaderboards return if @loadingFacebookFriends or @loadingLeaderboards or @loadingGPlusFriends
@startsLoading = false @startsLoading = false
@render() @render()
@ -141,11 +148,18 @@ module.exports = class LadderTabView extends CocoView
ctx.teams = @teams ctx.teams = @teams
team.leaderboard = @leaderboards[team.id] for team in @teams team.leaderboard = @leaderboards[team.id] for team in @teams
ctx.levelID = @levelID ctx.levelID = @levelID
ctx.friends = @facebookFriends ctx.friends = @consolidateFriends()
ctx.onFacebook = @facebookStatus is 'connected' ctx.onFacebook = @facebookStatus is 'connected'
ctx.onGPlus = application.gplusHandler.loggedIn ctx.onGPlus = application.gplusHandler.loggedIn
ctx ctx
consolidateFriends: ->
allFriendSessions = (@facebookFriendSessions or []).concat(@gplusFriendSessions or [])
sessions = _.uniq allFriendSessions, false, (session) -> session._id
sessions = _.sortBy sessions, 'totalScore'
sessions.reverse()
sessions
class LeaderboardData class LeaderboardData
constructor: (@level, @team, @session) -> constructor: (@level, @team, @session) ->
_.extend @, Backbone.Events _.extend @, Backbone.Events

View file

@ -38,8 +38,8 @@ module.exports = class VictoryModal extends View
@feedback = new LevelFeedback() @feedback = new LevelFeedback()
@feedback.url = -> url @feedback.url = -> url
@feedback.fetch() @feedback.fetch()
@feedback.once 'sync', => @onFeedbackLoaded() @listenToOnce(@feedback, 'sync', -> @onFeedbackLoaded())
@feedback.once 'error', => @onFeedbackNotFound() @listenToOnce(@feedback, 'error', -> @onFeedbackNotFound())
onFeedbackLoaded: -> onFeedbackLoaded: ->
@feedback.url = -> '/db/level.feedback/' + @id @feedback.url = -> '/db/level.feedback/' + @id

View file

@ -128,9 +128,9 @@ module.exports = class TomeView extends View
spellKey = pathComponents.join '/' spellKey = pathComponents.join '/'
@thangSpells[thang.id].push spellKey @thangSpells[thang.id].push spellKey
unless method.cloneOf unless method.cloneOf
skipProtectAPI = @getQueryVariable("skip_protect_api") is "true" or @options.levelID isnt 'brawlwood' skipProtectAPI = @getQueryVariable "skip_protect_api", not @options.ladderGame
skipProtectAPI = false if @options.levelID is 'dungeon-arena' skipFlow = @getQueryVariable "skip_flow", @options.levelID is 'brawlwood'
skipFlow = @getQueryVariable("skip_flow") is "true" or @options.levelID is 'brawlwood' console.log 'skip protect api', skipProtectAPI, 'skip flow', skipFlow
spell = @spells[spellKey] = new Spell programmableMethod: method, spellKey: spellKey, pathComponents: pathPrefixComponents.concat(pathComponents), session: @options.session, supermodel: @supermodel, skipFlow: skipFlow, skipProtectAPI: skipProtectAPI, worker: @worker spell = @spells[spellKey] = new Spell programmableMethod: method, spellKey: spellKey, pathComponents: pathPrefixComponents.concat(pathComponents), session: @options.session, supermodel: @supermodel, skipFlow: skipFlow, skipProtectAPI: skipProtectAPI, worker: @worker
for thangID, spellKeys of @thangSpells for thangID, spellKeys of @thangSpells
thang = world.getThangByID thangID thang = world.getThangByID thangID