League now preserved throughout ladder navigation flow. Mirror match support for submitting to both sides at once.

This commit is contained in:
Nick Winter 2015-09-04 16:21:35 -07:00
parent 765627a627
commit 73f3e7cdd9
17 changed files with 106 additions and 33 deletions

View file

@ -54,12 +54,23 @@
border-image: url(/images/level/code_toolbar_run_button_active_pressed.png) 14 20 20 20 fill round
padding: 2px 0 0 2px
&.submit-button, &.done-button
&.submit-button, &.done-button, &.rank-button
margin-left: 10px
border-image: url(/images/level/code_toolbar_submit_button_active.png) 14 20 20 20 fill round
&:active
border-image: url(/images/level/code_toolbar_submit_button_active_pressed.png) 14 20 20 20 fill round
.ladder-submission-view
width: 45%
width: -webkit-calc(50% - 10px)
width: calc(50% - 10px)
display: inline-block
.btn.btn-illustrated
width: 100%
font-size: 18px
.cast-button
@include opacity(0.77)

View file

@ -32,7 +32,7 @@ div#columns.row
td.score-cell= Math.round(sessionStats.totalScore * 100)
td.name-col-cell= session.get('creatorName') || "Anonymous"
td.fight-cell
a(href="/play/level/#{level.get('slug') || level.id}?team=#{team.otherTeam}&opponent=#{session.id}")
a(href="/play/level/#{level.get('slug') || level.id}?team=#{team.otherTeam}&opponent=#{session.id}" + (league ? "&league=" + league.id : ""))
span(data-i18n="ladder.fight") Fight!
td.spectate-cell.iconic-cell
.glyphicon.glyphicon-eye-open
@ -51,7 +51,7 @@ div#columns.row
td.score-cell= Math.round(sessionStats.totalScore * 100)
td.name-col-cell= session.get('creatorName') || "Anonymous"
td.fight-cell
a(href="/play/level/#{level.get('slug') || level.id}?team=#{team.otherTeam}&opponent=#{session.id}")
a(href="/play/level/#{level.get('slug') || level.id}?team=#{team.otherTeam}&opponent=#{session.id}" + (league ? "&league=" + league.id : ""))
span(data-i18n="ladder.fight") Fight!
td.spectate-cell.iconic-cell
.glyphicon.glyphicon-eye-open
@ -84,7 +84,7 @@ div#columns.row
span :
span= friend.team
br
a(href="/play/level/#{level.get('slug') || level.id}/?team=#{friend.otherTeam}&opponent=#{friend._id}")
a(href="/play/level/#{level.get('slug') || level.id}/?team=#{friend.otherTeam}&opponent=#{friend._id}" + (league ? "&league=" + league.id : ""))
span(data-i18n="ladder.fight") Fight!
else if onFacebook || onGPlus

View file

@ -109,7 +109,7 @@ block content
div.column.col-md-2
.spectate-button-container
a(href="/play/spectate/#{level.get('slug')}").spectate-button.btn.btn-illustrated.btn-info.center
a(href="/play/spectate/#{level.get('slug')}" + (league ? "?league=" + league.id : "")).spectate-button.btn.btn-illustrated.btn-info.center
span(data-i18n="play.spectate") Spectate
ul.nav.nav-pills

View file

@ -43,7 +43,7 @@ div#columns.row
td.name-cell= match.opponentName || "Anonymous"
td.time-cell= match.when
td.battle-cell
a(href="/play/level/#{levelID}?team=#{team.id}&opponent=#{match.sessionID}")
a(href="/play/level/#{levelID}?team=#{team.id}&opponent=#{match.sessionID}" + (league ? "&league=" + league.id : ""))
if (match.state === 'win')
span(data-i18n="ladder.watch_victory") Watch your victory
else

View file

@ -12,7 +12,7 @@ block modal-body-content
option(value=option.id selected=(language === option.id))= option.name
div#noob-view.secret
a(href="/play/level/#{levelID}-tutorial").btn.btn-success.btn-block.btn-lg
a(href="/play/level/#{levelID}-tutorial" + (league ? "?league=" + league.id : "")).btn.btn-success.btn-block.btn-lg
p
strong(data-i18n="ladder.tutorial_play") Play Tutorial
span(data-i18n="ladder.tutorial_recommended") Recommended if you've never played before
@ -23,8 +23,8 @@ block modal-body-content
p.tutorial-suggestion
strong(data-i18n="ladder.tutorial_not_sure") Not sure what's going on?
|
a(href="/play/level/#{levelID}-tutorial", data-i18n="ladder.tutorial_play_first") Play the tutorial first.
a(href="/play/level/#{levelID}?team=#{teamID}")
a(href="/play/level/#{levelID}-tutorial" + (league ? "?league=" + league.id : ""), data-i18n="ladder.tutorial_play_first") Play the tutorial first.
a(href="/play/level/#{levelID}?team=#{teamID}" + (league ? "&league=" + league.id : ""))
div.play-option
img(src=myPortrait).my-icon.only-one
img(src="/images/pages/play/ladder/"+teamID+"_ladder_tutorial.png", style="border: 1px solid #{teamColor}; background: #{teamBackgroundColor}").my-team-icon.img-circle.only-one
@ -39,7 +39,7 @@ block modal-body-content
span(data-i18n="ladder.warmup") Warmup
if challengers.easy
a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.easy.sessionID}")
a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.easy.sessionID}" + (league ? "&league=" + league.id : ""))
div.play-option.easy-option
img(src=myPortrait).my-icon.only-one
img(src="/images/pages/play/ladder/"+teamID+"_ladder_easy.png", style="border: 1px solid #{teamColor}; background: #{teamBackgroundColor}").my-team-icon.img-circle.only-one
@ -55,7 +55,7 @@ block modal-body-content
span(data-i18n="general.easy") Easy
if challengers.medium
a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.medium.sessionID}")
a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.medium.sessionID}" + (league ? "&league=" + league.id : ""))
div.play-option.medium-option
img(src=myPortrait).my-icon.only-one
img(src="/images/pages/play/ladder/"+teamID+"_ladder_medium.png", style="border: 1px solid #{teamColor}; background: #{teamBackgroundColor}").my-team-icon.img-circle.only-one
@ -71,7 +71,7 @@ block modal-body-content
span(data-i18n="general.medium") Medium
if challengers.hard
a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.hard.sessionID}")
a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.hard.sessionID}" + (league ? "&league=" + league.id : ""))
div.play-option.hard-option
img(src=myPortrait).my-icon.only-one
img(src="/images/pages/play/ladder/"+teamID+"_ladder_hard.png", style="border: 1px solid #{teamColor}; background: #{teamBackgroundColor}").my-team-icon.img-circle.only-one

View file

@ -7,7 +7,7 @@
.levels-link-area
a.levels-link(href=homeLink || "/")
.glyphicon.glyphicon-play
span(data-i18n="nav.play").home-text Levels
span(data-i18n=ladderGame ? "general.ladder" : "nav.play").home-text Levels
if isMultiplayerLevel && !observing
.multiplayer-area-container

View file

@ -2,9 +2,12 @@ button.btn.btn-lg.btn-illustrated.cast-button(title=castVerbose)
span(data-i18n="play_level.tome_run_button_ran") Ran
if !observing
button.btn.btn-lg.btn-illustrated.submit-button(title=castRealTimeVerbose)
span(data-i18n="play_level.tome_submit_button") Submit
span.spl.secret.submit-again-time
button.btn.btn-lg.btn-illustrated.done-button.secret
span(data-i18n="play_level.done") Done
if mirror
.ladder-submission-view
else
button.btn.btn-lg.btn-illustrated.submit-button(title=castRealTimeVerbose)
span(data-i18n="play_level.tome_submit_button") Submit
span.spl.secret.submit-again-time
button.btn.btn-lg.btn-illustrated.done-button.secret
span(data-i18n="play_level.done") Done

View file

@ -103,6 +103,7 @@ module.exports = class LadderPlayModal extends ModalView
{id: 'lua', name: 'Lua'}
{id: 'io', name: 'Io (Experimental)'}
]
ctx.league = @options.league
teamsList = teamDataFromLevel @level
teams = {}
teams[team.id] = team for team in teamsList

View file

@ -108,6 +108,8 @@ module.exports = class LadderView extends RootView
e.preventDefault()
e.stopImmediatePropagation()
url = "/play/spectate/#{@level.get('slug')}?session-one=#{humanSession}&session-two=#{ogreSession}"
url += '&league=' + @league.id if @league
url += '&autoplay=false' if key.command
window.open url, if key.command then '_blank' else 'spectate' # New tab for spectating specific matches
#Backbone.Mediator.publish 'router:navigate', route: url

View file

@ -67,6 +67,7 @@ module.exports = class MyMatchesTabView extends CocoView
ctx.level = @level
ctx.levelID = @level.get('slug') or @level.id
ctx.teams = @teams
ctx.league = @options.league
convertMatch = (match, submitDate) =>
opponent = match.opponents[0]
@ -116,7 +117,9 @@ module.exports = class MyMatchesTabView extends CocoView
placeholder = $(el)
sessionID = placeholder.data('session-id')
session = _.find @sessions.models, {id: sessionID}
ladderSubmissionView = new LadderSubmissionView session: session, level: @level
if @level.get('slug') in ['ace-of-coders']
mirrorSession = (s for s in @sessions.models when s.get('team') isnt session.get('team'))[0]
ladderSubmissionView = new LadderSubmissionView session: session, level: @level, mirrorSession: mirrorSession
@insertSubView ladderSubmissionView, placeholder
@$el.find('.score-chart-wrapper').each (i, el) =>

View file

@ -257,7 +257,8 @@ module.exports = class SpectateLevelView extends RootView
startFrame = @lastWorldFramesLoaded ? 0
if @world.frames.length is @world.totalFrames # Finished loading
@lastWorldFramesLoaded = 0
Backbone.Mediator.publish 'level:set-playing', playing: true # Since we paused at first, now we autostart playback.
unless @getQueryVariable('autoplay') is false
Backbone.Mediator.publish 'level:set-playing', playing: true # Since we paused at first, now we autostart playback.
else
@lastWorldFramesLoaded = @world.frames.length
for [spriteName, message] in @world.thangDialogueSounds startFrame
@ -271,6 +272,8 @@ module.exports = class SpectateLevelView extends RootView
@sessionOne = data[0]._id
@sessionTwo = data[1]._id
url = "/play/spectate/#{@levelID}?session-one=#{@sessionOne}&session-two=#{@sessionTwo}"
if leagueID = @getQueryVariable 'league'
url += "&league=" + leagueID
Backbone.Mediator.publish 'router:navigate', {
route: url,
viewClass: SpectateLevelView,

View file

@ -13,6 +13,7 @@ module.exports = class LadderSubmissionView extends CocoView
constructor: (options) ->
super options
@session = options.session
@mirrorSession = options.mirrorSession
@level = options.level
getRenderData: ->
@ -62,20 +63,31 @@ module.exports = class LadderSubmissionView extends CocoView
console.log jqxhr.responseText
@setRankingButtonText 'failed' unless @destroyed
@transpileSession (transpiledCode) =>
ajaxData =
session: @session.id
levelID: @level.id
originalLevelID: @level.get('original')
levelMajorVersion: @level.get('version').major
transpiledCode: transpiledCode
$.ajax '/queue/scoring', {
ajaxOptions =
type: 'POST'
data: ajaxData
success: success
error: failure
}
if @mirrorSession
# Also submit the mirrorSession after the main session submits successfully.
mirrorAjaxData = _.clone ajaxData
mirrorAjaxData.session = @mirrorSession.id
if @session.get('team') is 'humans'
mirrorAjaxData.transpiledCode = 'hero-placeholder-1': transpiledCode['hero-placeholder']
else
mirrorAjaxData.transpiledCode = 'hero-placeholder': transpiledCode['hero-placeholder-1']
mirrorAjaxOptions = _.clone ajaxOptions
mirrorAjaxOptions.data = mirrorAjaxData
ajaxOptions.success = ->
$.ajax '/queue/scoring', mirrorAjaxOptions
$.ajax '/queue/scoring', ajaxOptions
transpileSession: (callback) ->
submittedCode = @session.get('code')

View file

@ -76,13 +76,18 @@ module.exports = class ControlBarView extends CocoView
@homeLink = '/play/ladder/' + levelID
@homeViewClass = 'views/ladder/LadderView'
@homeViewArgs.push levelID
if leagueID = @getQueryVariable 'league'
leagueType = if @level.get('type') is 'course-ladder' then 'course' else 'clan'
@homeViewArgs.push leagueType
@homeViewArgs.push leagueID
@homeLink += "/#{leagueType}/#{leagueID}"
else if @level.get('type', true) in ['hero', 'hero-coop']
@homeLink = '/play'
@homeViewClass = 'views/play/CampaignView'
campaign = @level.get 'campaign'
@homeLink += '/' + campaign
@homeViewArgs.push campaign
else if @level.get('type', true) in ['course', 'course-ladder']
else if @level.get('type', true) in ['course']
@homeLink = '/courses/mock1'
@homeViewClass = 'views/courses/mock1/CourseDetailsView'
#campaign = @level.get 'campaign'

View file

@ -369,9 +369,18 @@ module.exports = class HeroVictoryModal extends ModalView
@$el.find('.sign-up-poke').toggleClass('hide', not @readyToContinue)
onGameSubmitted: (e) ->
ladderURL = "/play/ladder/#{@level.get('slug')}#my-matches"
@returnToLadder()
returnToLadder: ->
# Preserve the supermodel as we navigate back to the ladder.
Backbone.Mediator.publish 'router:navigate', route: ladderURL, viewClass: 'views/ladder/LadderView', viewArgs: [{supermodel: @supermodel}, @level.get('slug')]
viewArgs = [{supermodel: if @options.hasReceivedMemoryWarning then null else @supermodel}, @level.get('slug')]
ladderURL = "/play/ladder/#{@level.get('slug') || @level.id}#my-matches"
if leagueID = @getQueryVariable 'league'
leagueType = if @level.get('type') is 'course-ladder' then 'course' else 'clan'
viewArgs.push leagueType
viewArgs.push leagueID
ladderURL += "/#{leagueType}/#{leagueID}"
Backbone.Mediator.publish 'router:navigate', route: ladderURL, viewClass: 'views/ladder/LadderView', viewArgs: viewArgs
playSelectionSound: (hero, preload=false) ->
return unless sounds = hero.get('soundTriggers')?.selected
@ -433,9 +442,7 @@ module.exports = class HeroVictoryModal extends ModalView
onClickReturnToLadder: (e) ->
@playSound 'menu-button-click'
e.preventDefault()
route = $(e.target).data('href')
# Preserve the supermodel as we navigate back to the ladder.
Backbone.Mediator.publish 'router:navigate', route: route, viewClass: 'views/ladder/LadderView', viewArgs: [{supermodel: if @options.hasReceivedMemoryWarning then null else @supermodel}, @level.get('slug')]
@returnToLadder()
onClickSignupButton: (e) ->
e.preventDefault()

View file

@ -1,6 +1,8 @@
CocoView = require 'views/core/CocoView'
template = require 'templates/play/level/tome/cast_button'
{me} = require 'core/auth'
LadderSubmissionView = require 'views/play/common/LadderSubmissionView'
LevelSession = require 'models/LevelSession'
module.exports = class CastButtonView extends CocoView
id: 'cast-button-view'
@ -28,6 +30,7 @@ module.exports = class CastButtonView extends CocoView
@castShortcut = '⇧↵'
@updateReplayabilityInterval = setInterval @updateReplayability, 1000
@observing = options.session.get('creator') isnt me.id
@loadMirrorSession() if @options.level.get('slug') in ['ace-of-coders']
destroy: ->
clearInterval @updateReplayabilityInterval
@ -42,6 +45,7 @@ module.exports = class CastButtonView extends CocoView
context.castVerbose = castShortcutVerbose + ': ' + $.i18n.t('keyboard_shortcuts.run_code')
context.castRealTimeVerbose = castRealTimeShortcutVerbose + ': ' + $.i18n.t('keyboard_shortcuts.run_real_time')
context.observing = @observing
context.mirror = @mirrorSession?
context
afterRender: ->
@ -55,6 +59,7 @@ module.exports = class CastButtonView extends CocoView
if @options.level.get('slug') is 'thornbush-farm'# and not @options.session.get('state')?.complete
@$el.find('.submit-button').hide() # Hide submit until first win so that script can explain it.
@updateReplayability()
@updateLadderSubmissionViews()
attachTo: (spellView) ->
@$el.detach().prependTo(spellView.toolbarView.$el).show()
@ -96,6 +101,7 @@ module.exports = class CastButtonView extends CocoView
@casting = false
if @hasCastOnce # Don't play this sound the first time
@playSound 'cast-end', 0.5
_.delay (=> @ladderSubmissionView?.rankSession()), 1000 if @ladderSubmissionView
@hasCastOnce = true
@updateCastButton()
@world = e.world
@ -136,6 +142,7 @@ module.exports = class CastButtonView extends CocoView
castText = $.i18n.t('play_level.tome_cast_button_ran')
@castButton.text castText
#@castButton.prop 'disabled', not castable
@ladderSubmissionView?.updateButton()
updateReplayability: =>
return if @destroyed
@ -148,6 +155,18 @@ module.exports = class CastButtonView extends CocoView
waitTime = moment().add(timeUntilResubmit, 'ms').fromNow()
submitAgainLabel.text waitTime
loadMirrorSession: ->
url = "/db/level/#{@options.level.get('slug') or @options.level.id}/session"
url += "?team=#{if me.team is 'humans' then 'ogres' else 'humans'}"
mirrorSession = new LevelSession().setURL url
@mirrorSession = @supermodel.loadModel(mirrorSession, 'level_session', {cache: false}).model
updateLadderSubmissionViews: ->
@removeSubView subview for key, subview of @subviews when subview instanceof LadderSubmissionView
placeholder = @$el.find('.ladder-submission-view')
@ladderSubmissionView = new LadderSubmissionView session: @options.session, level: @options.level, mirrorSession: @mirrorSession
@insertSubView @ladderSubmissionView, placeholder
onJoinedRealTimeMultiplayerGame: (e) ->
@inRealTimeMultiplayerSession = true

View file

@ -33,7 +33,7 @@ module.exports = class GameMenuModal extends ModalView
submenus = ['guide', 'options', 'save-load', 'multiplayer']
submenus = _.without submenus, 'guide' unless docs.specificArticles?.length or docs.generalArticles?.length
submenus = _.without submenus, 'save-load' unless me.isAdmin() or /https?:\/\/localhost/.test(window.location.href)
submenus = _.without submenus, 'multiplayer' unless me.isAdmin() or @level?.get('type') in ['ladder', 'hero-ladder', 'course-ladder']
submenus = _.without submenus, 'multiplayer' unless me.isAdmin() or (@level?.get('type') in ['ladder', 'hero-ladder', 'course-ladder'] and @level.get('slug') not in ['ace-of-coders'])
@includedSubmenus = submenus
context.showTab = @options.showTab ? submenus[0]
context.submenus = submenus

View file

@ -72,8 +72,15 @@ module.exports = class MultiplayerView extends CocoView
e.target.select()
onGameSubmitted: (e) ->
# Preserve the supermodel as we navigate back to the ladder.
viewArgs = [{supermodel: if @options.hasReceivedMemoryWarning then null else @supermodel}, @levelID]
ladderURL = "/play/ladder/#{@levelID}#my-matches"
Backbone.Mediator.publish 'router:navigate', route: ladderURL
if leagueID = @getQueryVariable 'league'
leagueType = if @level?.get('type') is 'course-ladder' then 'course' else 'clan'
viewArgs.push leagueType
viewArgs.push leagueID
ladderURL += "/#{leagueType}/#{leagueID}"
Backbone.Mediator.publish 'router:navigate', route: ladderURL, viewClass: 'views/ladder/LadderView', viewArgs: viewArgs
updateLinkSection: ->
multiplayer = @$el.find('#multiplayer').prop('checked')