mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-28 10:06:08 -05:00
217 lines
7.7 KiB
CoffeeScript
217 lines
7.7 KiB
CoffeeScript
ModalView = require 'views/core/ModalView'
|
|
template = require 'templates/play/ladder/play_modal'
|
|
ThangType = require 'models/ThangType'
|
|
{me} = require 'core/auth'
|
|
LeaderboardCollection = require 'collections/LeaderboardCollection'
|
|
{teamDataFromLevel} = require './utils'
|
|
|
|
module.exports = class LadderPlayModal extends ModalView
|
|
id: 'ladder-play-modal'
|
|
template: template
|
|
closeButton: true
|
|
@shownTutorialButton: false
|
|
tutorialLevelExists: null
|
|
|
|
events:
|
|
'click #skip-tutorial-button': 'hideTutorialButtons'
|
|
'change #tome-language': 'updateLanguage'
|
|
|
|
defaultAceConfig:
|
|
language: 'javascript'
|
|
keyBindings: 'default'
|
|
invisibles: false
|
|
indentGuides: false
|
|
behaviors: false
|
|
liveCompletion: true
|
|
|
|
constructor: (options, @level, @session, @team) ->
|
|
super(options)
|
|
@nameMap = {}
|
|
@otherTeam = if @team is 'ogres' then 'humans' else 'ogres'
|
|
@startLoadingChallengersMaybe()
|
|
@wizardType = ThangType.loadUniversalWizard()
|
|
|
|
updateLanguage: ->
|
|
aceConfig = _.cloneDeep me.get('aceConfig') ? {}
|
|
aceConfig = _.defaults aceConfig, @defaultAceConfig
|
|
aceConfig.language = @$el.find('#tome-language').val()
|
|
me.set 'aceConfig', aceConfig
|
|
me.patch()
|
|
|
|
# PART 1: Load challengers from the db unless some are in the matches
|
|
startLoadingChallengersMaybe: ->
|
|
matches = @session?.get('matches')
|
|
if matches?.length then @loadNames() else @loadChallengers()
|
|
|
|
loadChallengers: ->
|
|
@challengersCollection = new ChallengersData(@level, @team, @otherTeam, @session)
|
|
@listenTo(@challengersCollection, 'sync', @loadNames)
|
|
|
|
# PART 2: Loading the names of the other users
|
|
|
|
loadNames: ->
|
|
@challengers = @getChallengers()
|
|
ids = (challenger.opponentID for challenger in _.values @challengers)
|
|
|
|
success = (@nameMap) =>
|
|
for challenger in _.values(@challengers)
|
|
challenger.opponentName = @nameMap[challenger.opponentID]?.name or 'Anoner'
|
|
challenger.opponentWizard = @nameMap[challenger.opponentID]?.wizard or {}
|
|
@checkWizardLoaded()
|
|
|
|
userNamesRequest = @supermodel.addRequestResource 'user_names', {
|
|
url: '/db/user/-/names'
|
|
data: {ids: ids, wizard: true}
|
|
method: 'POST'
|
|
success: success
|
|
}, 0
|
|
userNamesRequest.load()
|
|
|
|
# PART 3: Make sure wizard is loaded
|
|
|
|
checkWizardLoaded: ->
|
|
if @wizardType.loaded then @finishRendering() else @listenToOnce(@wizardType, 'sync', @finishRendering)
|
|
|
|
# PART 4: Render
|
|
|
|
finishRendering: ->
|
|
@checkTutorialLevelExists (exists) =>
|
|
@tutorialLevelExists = exists
|
|
@render()
|
|
@maybeShowTutorialButtons()
|
|
|
|
getRenderData: ->
|
|
ctx = super()
|
|
ctx.level = @level
|
|
ctx.levelID = @level.get('slug') or @level.id
|
|
ctx.teamName = _.string.titleize @team
|
|
ctx.teamID = @team
|
|
ctx.otherTeamID = @otherTeam
|
|
ctx.tutorialLevelExists = @tutorialLevelExists
|
|
ctx.languages = [
|
|
{id: 'python', name: 'Python'}
|
|
{id: 'javascript', name: 'JavaScript'}
|
|
{id: 'coffeescript', name: 'CoffeeScript'}
|
|
{id: 'clojure', name: 'Clojure (Experimental)'}
|
|
{id: 'lua', name: 'Lua (Experimental)'}
|
|
{id: 'io', name: 'Io (Experimental)'}
|
|
]
|
|
teamsList = teamDataFromLevel @level
|
|
teams = {}
|
|
teams[team.id] = team for team in teamsList
|
|
ctx.teamColor = teams[@team].primaryColor
|
|
ctx.teamBackgroundColor = teams[@team].bgColor
|
|
ctx.opponentTeamColor = teams[@otherTeam].primaryColor
|
|
ctx.opponentTeamBackgroundColor = teams[@otherTeam].bgColor
|
|
|
|
ctx.challengers = @challengers or {}
|
|
for challenger in _.values ctx.challengers
|
|
continue unless challenger and @wizardType.loaded
|
|
if (not challenger.opponentImageSource) and challenger.opponentWizard?.colorConfig
|
|
challenger.opponentImageSource = @wizardType.getPortraitSource(
|
|
{colorConfig: challenger.opponentWizard.colorConfig})
|
|
|
|
if @wizardType.loaded
|
|
ctx.genericPortrait = @wizardType.getPortraitSource()
|
|
myColorConfig = me.get('wizard')?.colorConfig
|
|
ctx.myPortrait = if myColorConfig then @wizardType.getPortraitSource({colorConfig: myColorConfig}) else ctx.genericPortrait
|
|
|
|
ctx.myName = me.get('name') || 'Newcomer'
|
|
ctx
|
|
|
|
maybeShowTutorialButtons: ->
|
|
return if @session or LadderPlayModal.shownTutorialButton or not @tutorialLevelExists
|
|
@$el.find('#normal-view').addClass('secret')
|
|
@$el.find('.modal-header').addClass('secret')
|
|
@$el.find('#noob-view').removeClass('secret')
|
|
LadderPlayModal.shownTutorialButton = true
|
|
|
|
hideTutorialButtons: ->
|
|
@$el.find('#normal-view').removeClass('secret')
|
|
@$el.find('.modal-header').removeClass('secret')
|
|
@$el.find('#noob-view').addClass('secret')
|
|
|
|
checkTutorialLevelExists: (cb) ->
|
|
levelID = @level.get('slug') or @level.id
|
|
tutorialLevelID = "#{levelID}-tutorial"
|
|
success = => cb true
|
|
failure = => cb false
|
|
$.ajax
|
|
type: 'GET'
|
|
url: "/db/level/#{tutorialLevelID}/exists"
|
|
success: success
|
|
error: failure
|
|
|
|
# Choosing challengers
|
|
|
|
getChallengers: ->
|
|
# make an object of challengers to everything needed to link to them
|
|
challengers = {}
|
|
if @challengersCollection
|
|
easyInfo = @challengeInfoFromSession(@challengersCollection.easyPlayer.models[0])
|
|
mediumInfo = @challengeInfoFromSession(@challengersCollection.mediumPlayer.models[0])
|
|
hardInfo = @challengeInfoFromSession(@challengersCollection.hardPlayer.models[0])
|
|
else
|
|
matches = @session.get('matches')
|
|
won = (m for m in matches when m.metrics.rank < m.opponents[0].metrics.rank)
|
|
lost = (m for m in matches when m.metrics.rank > m.opponents[0].metrics.rank)
|
|
tied = (m for m in matches when m.metrics.rank is m.opponents[0].metrics.rank)
|
|
easyInfo = @challengeInfoFromMatches(won)
|
|
mediumInfo = @challengeInfoFromMatches(tied)
|
|
hardInfo = @challengeInfoFromMatches(lost)
|
|
@addChallenger easyInfo, challengers, 'easy'
|
|
@addChallenger mediumInfo, challengers, 'medium'
|
|
@addChallenger hardInfo, challengers, 'hard'
|
|
challengers
|
|
|
|
addChallenger: (info, challengers, title) ->
|
|
# check for duplicates first
|
|
return unless info
|
|
for key, value of challengers
|
|
return if value.sessionID is info.sessionID
|
|
challengers[title] = info
|
|
|
|
challengeInfoFromSession: (session) ->
|
|
# given a model from the db, return info needed for a link to the match
|
|
return unless session
|
|
return {
|
|
sessionID: session.id
|
|
opponentID: session.get 'creator'
|
|
codeLanguage: session.get 'submittedCodeLanguage'
|
|
}
|
|
|
|
challengeInfoFromMatches: (matches) ->
|
|
return unless matches?.length
|
|
match = _.sample matches
|
|
opponent = match.opponents[0]
|
|
return {
|
|
sessionID: opponent.sessionID
|
|
opponentID: opponent.userID
|
|
codeLanguage: opponent.codeLanguage
|
|
}
|
|
|
|
class ChallengersData
|
|
constructor: (@level, @team, @otherTeam, @session) ->
|
|
_.extend @, Backbone.Events
|
|
score = @session?.get('totalScore') or 25
|
|
@easyPlayer = new LeaderboardCollection(@level, {order: 1, scoreOffset: score - 5, limit: 1, team: @otherTeam})
|
|
@easyPlayer.fetch()
|
|
@listenToOnce(@easyPlayer, 'sync', @challengerLoaded)
|
|
@mediumPlayer = new LeaderboardCollection(@level, {order: 1, scoreOffset: score, limit: 1, team: @otherTeam})
|
|
@mediumPlayer.fetch()
|
|
@listenToOnce(@mediumPlayer, 'sync', @challengerLoaded)
|
|
@hardPlayer = new LeaderboardCollection(@level, {order: -1, scoreOffset: score + 5, limit: 1, team: @otherTeam})
|
|
@hardPlayer.fetch()
|
|
@listenToOnce(@hardPlayer, 'sync', @challengerLoaded)
|
|
|
|
challengerLoaded: ->
|
|
if @allLoaded()
|
|
@loaded = true
|
|
@trigger 'sync'
|
|
|
|
playerIDs: ->
|
|
collections = [@easyPlayer, @mediumPlayer, @hardPlayer]
|
|
(c.models[0].get('creator') for c in collections when c?.models[0])
|
|
|
|
allLoaded: ->
|
|
_.all [@easyPlayer.loaded, @mediumPlayer.loaded, @hardPlayer.loaded]
|