mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-12-01 19:36:57 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
e15e45bd70
25 changed files with 2838 additions and 80 deletions
2680
app/assets/lib/ace/mode-markdown.js
Normal file
2680
app/assets/lib/ace/mode-markdown.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -56,8 +56,8 @@ module.exports = class Simulator extends CocoClass
|
|||
|
||||
simulateSingleGame: ->
|
||||
return if @destroyed
|
||||
@trigger 'statusUpdate', 'Simulating...'
|
||||
@assignWorldAndLevelFromLevelLoaderAndDestroyIt()
|
||||
@trigger 'statusUpdate', 'Simulating...'
|
||||
@setupGod()
|
||||
try
|
||||
@commenceSingleSimulation()
|
||||
|
@ -71,6 +71,7 @@ module.exports = class Simulator extends CocoClass
|
|||
|
||||
handleSingleSimulationError: (error) ->
|
||||
console.error 'There was an error simulating a single game!', error
|
||||
return if @destroyed
|
||||
if @options.headlessClient and @options.simulateOnlyOneGame
|
||||
console.log 'GAMERESULT:tie'
|
||||
process.exit(0)
|
||||
|
@ -78,6 +79,7 @@ module.exports = class Simulator extends CocoClass
|
|||
|
||||
handleSingleSimulationInfiniteLoop: ->
|
||||
console.log 'There was an infinite loop in the single game!'
|
||||
return if @destroyed
|
||||
if @options.headlessClient and @options.simulateOnlyOneGame
|
||||
console.log 'GAMERESULT:tie'
|
||||
process.exit(0)
|
||||
|
@ -174,8 +176,8 @@ module.exports = class Simulator extends CocoClass
|
|||
return if @destroyed
|
||||
info = 'All resources loaded, simulating!'
|
||||
console.log info
|
||||
@trigger 'statusUpdate', info, @task.getSessions()
|
||||
@assignWorldAndLevelFromLevelLoaderAndDestroyIt()
|
||||
@trigger 'statusUpdate', info, @task.getSessions()
|
||||
@setupGod()
|
||||
|
||||
try
|
||||
|
@ -227,6 +229,7 @@ module.exports = class Simulator extends CocoClass
|
|||
@hd = new @memwatch.HeapDiff()
|
||||
|
||||
onInfiniteLoop: ->
|
||||
return if @destroyed
|
||||
console.warn 'Skipping infinitely looping game.'
|
||||
@trigger 'statusUpdate', "Infinite loop detected; grabbing a new game in #{@retryDelayInSeconds} seconds."
|
||||
_.delay @cleanupAndSimulateAnotherTask, @retryDelayInSeconds * 1000
|
||||
|
@ -240,7 +243,11 @@ module.exports = class Simulator extends CocoClass
|
|||
@sendResultsBackToServer taskResults
|
||||
|
||||
sendResultsBackToServer: (results) ->
|
||||
@trigger 'statusUpdate', 'Simulation completed, sending results back to server!'
|
||||
status = 'Recording:'
|
||||
for session in results.sessions
|
||||
states = ['wins', if _.find(results.sessions, (s) -> s.metrics.rank is 0) then 'loses' else 'draws']
|
||||
status += " #{session.name} #{states[session.metrics.rank]}"
|
||||
@trigger 'statusUpdate', status
|
||||
console.log 'Sending result back to server:'
|
||||
console.log JSON.stringify results
|
||||
|
||||
|
|
|
@ -874,6 +874,7 @@
|
|||
tournament_ended: "Tournament ended"
|
||||
tournament_rules: "Tournament Rules"
|
||||
tournament_blurb: "Write code, collect gold, build armies, crush foes, win prizes, and upgrade your career in our $40,000 Greed tournament! Check out the details"
|
||||
tournament_blurb_criss_cross: "Win bids, construct paths, outwit opponents, grab gems, and upgrade your career in our Criss-Cross tournament! Check out the details"
|
||||
tournament_blurb_blog: "on our blog"
|
||||
rules: "Rules"
|
||||
winners: "Winners"
|
||||
|
|
|
@ -264,7 +264,10 @@ module.exports = class ThangType extends CocoModel
|
|||
@wizardType.fetch()
|
||||
@wizardType
|
||||
|
||||
getPortraitURL: -> "/file/db/thang.type/#{@get('original')}/portrait.png"
|
||||
getPortraitURL: ->
|
||||
if iconURL = @get('rasterIcon')
|
||||
return "/file/#{iconURL}"
|
||||
"/file/db/thang.type/#{@get('original')}/portrait.png"
|
||||
|
||||
# Item functions
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ _.extend AchievementSchema.properties,
|
|||
default: 'Probably the coolest you\'ll ever get.'
|
||||
userField: c.shortString()
|
||||
related: c.objectId(description: 'Related entity')
|
||||
icon: {type: 'string', format: 'image-file', title: 'Icon'}
|
||||
icon: {type: 'string', format: 'image-file', title: 'Icon', description: 'Image should be a 100x100 transparent png.'}
|
||||
category:
|
||||
enum: ['level', 'ladder', 'contributor']
|
||||
description: 'For categorizing and display purposes'
|
||||
|
|
|
@ -27,7 +27,7 @@ EventPrereqSchema = c.object {title: 'Event Prerequisite', format: 'event-prereq
|
|||
GoalSchema = c.object {title: 'Goal', description: 'A goal that the player can accomplish.', required: ['name', 'id']},
|
||||
name: c.shortString(title: 'Name', description: 'Name of the goal that the player will see, like \"Defeat eighteen dragons\".')
|
||||
i18n: {type: 'object', format: 'i18n', props: ['name'], description: 'Help translate this goal'}
|
||||
id: c.shortString(title: 'ID', description: 'Unique identifier for this goal, like \"defeat-dragons\".') # unique somehow?
|
||||
id: c.shortString(title: 'ID', description: 'Unique identifier for this goal, like \"defeat-dragons\".', pattern: '^[a-z0-9-]+$') # unique somehow?
|
||||
worldEndsAfter: {title: 'World Ends After', description: 'When included, ends the world this many seconds after this goal succeeds or fails.', type: 'number', minimum: 0, exclusiveMinimum: true, maximum: 300, default: 3}
|
||||
howMany: {title: 'How Many', description: 'When included, require only this many of the listed goal targets instead of all of them.', type: 'integer', minimum: 1}
|
||||
hiddenGoal: {title: 'Hidden', description: 'Hidden goals don\'t show up in the goals area for the player until they\'re failed. (Usually they\'re obvious, like "don\'t die".)', 'type': 'boolean', default: false}
|
||||
|
|
|
@ -124,6 +124,7 @@ _.extend ThangTypeSchema.properties,
|
|||
type: 'number'
|
||||
positions: PositionsSchema
|
||||
raster: {type: 'string', format: 'image-file', title: 'Raster Image'}
|
||||
rasterIcon: { type: 'string', format: 'image-file', title: 'Raster Image Icon' }
|
||||
colorGroups: c.object
|
||||
title: 'Color Groups'
|
||||
additionalProperties:
|
||||
|
|
|
@ -3,18 +3,24 @@
|
|||
background-color: #f5f5f5
|
||||
padding: 10px 20px 10px 0
|
||||
|
||||
.treema-markdown.treema-edit, .treema-coffee.treema-edit, .treema-javascript.treema-edit
|
||||
.treema-markdown
|
||||
border: 1px solid gray
|
||||
padding: 5px
|
||||
|
||||
&, & > div.ace_editor
|
||||
width: 100%
|
||||
|
||||
.treema-markdown.treema-display, .treema-coffee.treema-display, .treema-javascript.treema-display
|
||||
width: 100%
|
||||
border: 3px inset rgba(0, 100, 100, 0.2)
|
||||
box-sizing: border-box
|
||||
padding: 5px
|
||||
|
||||
.buttons button
|
||||
float: left
|
||||
margin-bottom: 5px
|
||||
margin-right: 5px
|
||||
|
||||
.preview
|
||||
clear: both
|
||||
width: 100%
|
||||
border: 3px inset rgba(0, 100, 100, 0.2)
|
||||
box-sizing: border-box
|
||||
padding: 5px
|
||||
|
||||
.treema-selection-map
|
||||
position: fixed
|
||||
|
|
|
@ -5,7 +5,6 @@ div.editor-nano-container.nano
|
|||
for group in groups
|
||||
h4= group.name
|
||||
for thangType in group.thangs
|
||||
div.add-thang-palette-icon(data-thang-type=thangType.name)
|
||||
- path = '/file/db/thang.type/'+thangType.original+'/portrait.png'
|
||||
img(title="Add " + thangType.name, src=path, alt="")
|
||||
div.add-thang-palette-icon(data-thang-type=thangType.get('name'))
|
||||
img(title="Add " + thangType.get('name'), src=thangType.getPortraitURL(), alt="")
|
||||
div.clearfix
|
|
@ -12,14 +12,13 @@ table.table
|
|||
th(data-i18n="general.description") Description
|
||||
th(data-i18n="general.version") Version
|
||||
|
||||
for data in documents
|
||||
- data = data.attributes;
|
||||
for thang in documents
|
||||
tr
|
||||
td
|
||||
- path = '/file/db/thang.type/'+data.original+'/portrait.png'
|
||||
img(title="Add " + data.name, src=path, alt="").portrait
|
||||
img(title="Add " + thang.get('name'), src=thang.getPortraitURL(), alt="").portrait
|
||||
td
|
||||
a(href="/editor/thang/#{data.slug || data._id}")
|
||||
| #{data.name}
|
||||
td.body-row #{data.description}
|
||||
td #{data.version.major}.#{data.version.minor}
|
||||
a(href="/editor/thang/#{thang.get('slug') || thang.id}")
|
||||
| #{thang.get('name')}
|
||||
td.body-row #{thang.get('description')}
|
||||
- var version = thang.get('version')
|
||||
td #{version.major}.#{version.minor}
|
|
@ -11,7 +11,6 @@ block content
|
|||
if level.get('name') == 'Greed'
|
||||
.tournament-blurb
|
||||
h2
|
||||
//span(data-i18n="ladder.tournament_ends") Tournament ends
|
||||
span(data-i18n="ladder.tournament_ended") Tournament ended
|
||||
| #{tournamentTimeLeft}
|
||||
p
|
||||
|
@ -46,6 +45,17 @@ block content
|
|||
a(href="http://aws.amazon.com/")
|
||||
img(src=base + "aws.png")
|
||||
|
||||
if level.get('name') == 'Criss-Cross'
|
||||
.tournament-blurb
|
||||
h2
|
||||
span(data-i18n="ladder.tournament_ends") Tournament ends
|
||||
| #{tournamentTimeLeft}
|
||||
p
|
||||
span(data-i18n="ladder.tournament_blurb_criss_cross") Win bids, construct paths, outwit opponents, grab gems, and upgrade your career in our Criss-Cross tournament! Check out the details
|
||||
|
|
||||
a(href="http://blog.codecombat.com/6-programming-languages-one-victor-codecombats-newest-tournament", data-i18n="ladder.tournament_blurb_blog") on our blog
|
||||
| .
|
||||
|
||||
div#columns.row
|
||||
div.column.col-md-2
|
||||
for team in teams
|
||||
|
@ -73,8 +83,10 @@ block content
|
|||
if level.get('name') == 'Greed'
|
||||
li
|
||||
a(href="#prizes", data-toggle="tab", data-i18n="ladder_prizes.prizes") Prizes
|
||||
if level.get('name') == 'Greed'
|
||||
li
|
||||
a(href="#rules", data-toggle="tab", data-i18n="ladder.rules") Rules
|
||||
if level.get('name') == 'Greed' || (level.get('name') == 'Criss-Cross!!!')
|
||||
li
|
||||
a(href="#winners", data-toggle="tab", data-i18n="ladder.winners") Winners
|
||||
|
||||
|
@ -651,6 +663,7 @@ block content
|
|||
| - $50
|
||||
td $50
|
||||
|
||||
if level.get('name') == 'Greed'
|
||||
.tab-pane.well#rules
|
||||
h1(data-i18n="ladder.tournament_rules") Tournament Rules
|
||||
h2 General
|
||||
|
@ -712,6 +725,7 @@ block content
|
|||
a(href="http://discourse.codecombat.com/") Discourse forum
|
||||
| .
|
||||
|
||||
if level.get('name') == 'Greed' || level.get('name') == 'Criss-Cross!!!'
|
||||
.tab-pane.well#winners
|
||||
h1(data-i18n="ladder.winners") Winners
|
||||
|
||||
|
|
|
@ -8,8 +8,7 @@ div#columns.row
|
|||
th(colspan=2)
|
||||
th(colspan=3, style="color: #{team.primaryColor}")
|
||||
span= team.name
|
||||
span
|
||||
span(data-i18n="ladder.leaderboard") Leaderboard
|
||||
span.spl(data-i18n="ladder.leaderboard") Leaderboard
|
||||
tr
|
||||
th(colspan=2)
|
||||
th(data-i18n="general.score") Score
|
||||
|
|
|
@ -4,7 +4,10 @@ h4.home
|
|||
i.icon-home.icon-white
|
||||
span(data-i18n="play_level.home") Home
|
||||
|
||||
h4.title #{worldName}
|
||||
h4.title
|
||||
| #{worldName}
|
||||
| -
|
||||
a(href=editorLink, data-i18n="nav.editor", title="Open " + worldName + " in the Level Editor") Editor
|
||||
|
||||
button.btn.btn-xs.btn-inverse.banner#game-menu-button(title="Show game menu", data-i18n="play_level.game_menu") Game Menu
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
strong.tip(data-i18n='play_level.tip_open_source') CodeCombat is 100% open source!
|
||||
strong.tip(data-i18n='play_level.tip_beta_launch') CodeCombat launched its beta in October, 2013.
|
||||
strong.tip(data-i18n='play_level.tip_js_beginning') JavaScript is just the beginning.
|
||||
strong.tip(data-i18n='play_level.tip_autocast_setting') Adjust autocast settings by clicking the gear on the cast button.
|
||||
strong.tip(data-i18n='play_level.tip_think_solution') Think of the solution, not the problem.
|
||||
strong.tip(data-i18n='play_level.tip_theory_practice') In theory there is no difference between theory and practice; in practice there is. - Yogi Berra
|
||||
strong.tip(data-i18n='play_level.tip_error_free') There are two ways to write error-free programs; only the third one works. - Alan Perlis
|
||||
|
|
|
@ -20,20 +20,30 @@ class LiveEditingMarkup extends TreemaNode.nodeMap.ace
|
|||
super(arguments...)
|
||||
@schema.aceMode = 'ace/mode/markdown'
|
||||
|
||||
buildValueForEditing: (valEl) ->
|
||||
initEditor: (valEl) ->
|
||||
buttonRow = $('<div class="buttons"></div>')
|
||||
valEl.append(buttonRow)
|
||||
@addPreviewToggle(buttonRow)
|
||||
@addImageUpload(buttonRow)
|
||||
super(valEl)
|
||||
@editor.on('change', @onEditorChange)
|
||||
@addImageUpload(valEl)
|
||||
valEl.append($('<div class="preview"></div>'))
|
||||
|
||||
addImageUpload: (valEl) ->
|
||||
return unless me.isAdmin()
|
||||
valEl.append(
|
||||
$('<div></div>').append(
|
||||
$('<div class="pick-image-button"></div>').append(
|
||||
$('<button>Pick Image</button>')
|
||||
.addClass('btn btn-sm btn-primary')
|
||||
.click(=> filepicker.pick @onFileChosen)
|
||||
)
|
||||
)
|
||||
|
||||
addPreviewToggle: (valEl) ->
|
||||
valEl.append($('<div class="toggle-preview-button"></div>').append(
|
||||
$('<button>Toggle Preview</button>')
|
||||
.addClass('btn btn-sm btn-primary')
|
||||
.click(@togglePreview)
|
||||
))
|
||||
|
||||
onFileChosen: (InkBlob) =>
|
||||
body =
|
||||
|
@ -49,14 +59,19 @@ class LiveEditingMarkup extends TreemaNode.nodeMap.ace
|
|||
onFileUploaded: (e) =>
|
||||
@editor.insert "![#{e.metadata.name}](/file/#{@uploadingPath})"
|
||||
|
||||
onEditorChange: =>
|
||||
@saveChanges()
|
||||
@flushChanges()
|
||||
@getRoot().broadcastChanges()
|
||||
showingPreview: false
|
||||
|
||||
buildValueForDisplay: (valEl) ->
|
||||
@editor?.destroy()
|
||||
valEl.html(marked(@data))
|
||||
togglePreview: =>
|
||||
valEl = @getValEl()
|
||||
if @showingPreview
|
||||
valEl.find('.preview').hide()
|
||||
valEl.find('.pick-image-button').show()
|
||||
valEl.find('.ace_editor').show()
|
||||
else
|
||||
valEl.find('.preview').html(marked(@data)).show()
|
||||
valEl.find('.pick-image-button').hide()
|
||||
valEl.find('.ace_editor').hide()
|
||||
@showingPreview = not @showingPreview
|
||||
|
||||
class SoundFileTreema extends TreemaNode.nodeMap.string
|
||||
valueClass: 'treema-sound-file'
|
||||
|
|
|
@ -4,7 +4,7 @@ ThangType = require 'models/ThangType'
|
|||
CocoCollection = require 'collections/CocoCollection'
|
||||
|
||||
class ThangTypeSearchCollection extends CocoCollection
|
||||
url: '/db/thang.type?project=true'
|
||||
url: '/db/thang.type?project=original,name,version,description,slug,kind,rasterIcon'
|
||||
model: ThangType
|
||||
|
||||
addTerm: (term) ->
|
||||
|
@ -33,18 +33,18 @@ module.exports = class AddThangsView extends CocoView
|
|||
else
|
||||
models = @supermodel.getModels(ThangType)
|
||||
|
||||
thangTypes = (thangType.attributes for thangType in models)
|
||||
thangTypes = _.uniq thangTypes, false, 'original'
|
||||
thangTypes = _.reject thangTypes, kind: 'Mark'
|
||||
thangTypes = _.uniq models, false, (thangType) -> thangType.get('original')
|
||||
thangTypes = _.reject thangTypes, (thangType) -> thangType.get('kind') is 'Mark'
|
||||
groupMap = {}
|
||||
for thangType in thangTypes
|
||||
groupMap[thangType.kind] ?= []
|
||||
groupMap[thangType.kind].push thangType
|
||||
kind = thangType.get('kind')
|
||||
groupMap[kind] ?= []
|
||||
groupMap[kind].push thangType
|
||||
|
||||
groups = []
|
||||
for groupName in Object.keys(groupMap).sort()
|
||||
someThangTypes = groupMap[groupName]
|
||||
someThangTypes = _.sortBy someThangTypes, 'name'
|
||||
someThangTypes = _.sortBy someThangTypes, (thangType) -> thangType.get('name')
|
||||
group =
|
||||
name: groupName
|
||||
thangs: someThangTypes
|
||||
|
|
|
@ -119,7 +119,7 @@ module.exports = class ThangsTabView extends CocoView
|
|||
$('#thangs-list').bind 'mousewheel', @preventBodyScrollingInThangList
|
||||
@$el.find('#extant-thangs-filter button:first').button('toggle')
|
||||
$(window).resize @onWindowResize
|
||||
@addThangsView = @insertSubView new AddThangsView world: @world, supermodel: @supermodel
|
||||
@addThangsView = @insertSubView new AddThangsView world: @world
|
||||
@buildInterface() # refactor to not have this trigger when this view re-renders?
|
||||
if @thangsTreema.data.length
|
||||
@$el.find('#canvas-overlay').css('display', 'none')
|
||||
|
|
|
@ -6,6 +6,7 @@ module.exports = class ThangTypeSearchView extends SearchView
|
|||
model: require 'models/ThangType'
|
||||
modelURL: '/db/thang.type'
|
||||
tableTemplate: require 'templates/editor/thang/table'
|
||||
projection: ['original', 'name', 'version', 'description', 'slug', 'kind', 'rasterIcon']
|
||||
|
||||
getRenderData: ->
|
||||
context = super()
|
||||
|
|
|
@ -143,14 +143,14 @@ module.exports = class MainPlayView extends RootView
|
|||
]
|
||||
|
||||
arenas = [
|
||||
#{
|
||||
# name: 'Criss-Cross'
|
||||
# difficulty: 4
|
||||
# id: 'criss-cross'
|
||||
# image: '/file/db/level/528aea2d7f37fc4e0700016b/its_a_trap_icon.png'
|
||||
# description: 'Participate in a bidding war with opponents to reach the other side!'
|
||||
# levelPath: 'ladder'
|
||||
#}
|
||||
{
|
||||
name: 'Criss-Cross'
|
||||
difficulty: 5
|
||||
id: 'criss-cross'
|
||||
image: '/file/db/level/528aea2d7f37fc4e0700016b/its_a_trap_icon.png'
|
||||
description: 'Participate in a bidding war with opponents to reach the other side!'
|
||||
levelPath: 'ladder'
|
||||
}
|
||||
{
|
||||
name: 'Greed'
|
||||
difficulty: 4
|
||||
|
@ -192,7 +192,7 @@ module.exports = class MainPlayView extends RootView
|
|||
levelPath: 'ladder'
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
classicAlgorithms = [
|
||||
{
|
||||
name: 'Bubble Sort Bootcamp Battle'
|
||||
|
|
|
@ -52,13 +52,13 @@ module.exports = class LadderView extends RootView
|
|||
ctx.levelID = @levelID
|
||||
ctx.levelDescription = marked(@level.get('description')) if @level.get('description')
|
||||
ctx._ = _
|
||||
ctx.tournamentTimeLeft = moment(new Date(1402444800000)).fromNow()
|
||||
if tournamentDate = {greed: 1402444800000, 'criss-cross': 1410912000000}[@levelID]
|
||||
ctx.tournamentTimeLeft = moment(new Date(tournamentDate)).fromNow()
|
||||
ctx.winners = require('views/play/ladder/tournament_results')[@levelID]
|
||||
ctx
|
||||
|
||||
afterRender: ->
|
||||
super()
|
||||
# console.debug 'gintau', 'ladder_view-afterRender', @supermodel.finished()
|
||||
return unless @supermodel.finished()
|
||||
@insertSubView(@ladderTab = new LadderTabView({}, @level, @sessions))
|
||||
@insertSubView(@myMatchesTab = new MyMatchesTabView({}, @level, @sessions))
|
||||
|
|
|
@ -30,6 +30,13 @@ module.exports = class LadderHomeView extends RootView
|
|||
getRenderData: (context={}) ->
|
||||
context = super(context)
|
||||
arenas = [
|
||||
{
|
||||
name: 'Criss-Cross'
|
||||
difficulty: 5
|
||||
id: 'criss-cross'
|
||||
image: '/file/db/level/5391f3d519dc22b8082159b2/banner2.png'
|
||||
description: 'Participate in a bidding war with opponents to reach the other side!'
|
||||
}
|
||||
{
|
||||
name: 'Greed'
|
||||
difficulty: 4
|
||||
|
@ -37,6 +44,13 @@ module.exports = class LadderHomeView extends RootView
|
|||
image: '/file/db/level/53558b5a9914f5a90d7ccddb/greed_banner.jpg'
|
||||
description: 'Liked Dungeon Arena and Gold Rush? Put them together in this economic arena!'
|
||||
}
|
||||
{
|
||||
name: 'Sky Span (Testing)'
|
||||
difficulty: 3
|
||||
id: 'sky-span'
|
||||
image: '/file/db/level/53c80fce0ddbef000084c667/sky-Span-banner.jpg'
|
||||
description: 'Preview version of an upgraded Dungeon Arena. Help us with hero balance before release!'
|
||||
}
|
||||
{
|
||||
name: 'Dungeon Arena'
|
||||
difficulty: 3
|
||||
|
|
|
@ -18,9 +18,6 @@ module.exports = class SimulateTabView extends CocoView
|
|||
@simulatorsLeaderboardDataRes = @supermodel.addModelResource(@simulatorsLeaderboardData, 'top_simulators')
|
||||
@simulatorsLeaderboardDataRes.load()
|
||||
|
||||
@simulator = new Simulator()
|
||||
@listenTo(@simulator, 'statusUpdate', @updateSimulationStatus)
|
||||
|
||||
onLoaded: ->
|
||||
super()
|
||||
@render()
|
||||
|
@ -42,7 +39,21 @@ module.exports = class SimulateTabView extends CocoView
|
|||
application.tracker?.trackEvent 'Simulate Button Click', {}
|
||||
$('#simulate-button').prop 'disabled', true
|
||||
$('#simulate-button').text 'Simulating...'
|
||||
@simulateNextGame()
|
||||
|
||||
simulateNextGame: ->
|
||||
unless @simulator
|
||||
@simulator = new Simulator()
|
||||
@listenTo @simulator, 'statusUpdate', @updateSimulationStatus
|
||||
# Work around simulator getting super slow on Chrome
|
||||
fetchAndSimulateTaskOriginal = @simulator.fetchAndSimulateTask
|
||||
@simulator.fetchAndSimulateTask = =>
|
||||
if @simulator.simulatedByYou >= 5
|
||||
@simulator.destroy()
|
||||
@simulator = null
|
||||
@simulateNextGame()
|
||||
else
|
||||
fetchAndSimulateTaskOriginal.apply @simulator
|
||||
@simulator.fetchAndSimulateTask()
|
||||
|
||||
refresh: ->
|
||||
|
@ -51,20 +62,23 @@ module.exports = class SimulateTabView extends CocoView
|
|||
$.ajax '/queue/messagesInQueueCount', {success}
|
||||
|
||||
updateSimulationStatus: (simulationStatus, sessions) ->
|
||||
if simulationStatus is 'Fetching simulation data!'
|
||||
@simulationMatchDescription = ''
|
||||
@simulationSpectateLink = ''
|
||||
@simulationStatus = simulationStatus
|
||||
try
|
||||
if sessions?
|
||||
#TODO: Fetch names from Redis, the creatorName is denormalized
|
||||
creatorNames = (session.creatorName for session in sessions)
|
||||
@simulationStatus = 'Simulating game between '
|
||||
for index in [0...creatorNames.length]
|
||||
unless creatorNames[index]
|
||||
creatorNames[index] = 'Anonymous'
|
||||
@simulationStatus += (if index != 0 then ' and ' else '') + creatorNames[index]
|
||||
@simulationStatus += '...'
|
||||
@simulationMatchDescription = ''
|
||||
@simulationSpectateLink = "/play/spectate/#{@simulator.level.get('slug')}?"
|
||||
for session, index in sessions
|
||||
# TODO: Fetch names from Redis, the creatorName is denormalized
|
||||
@simulationMatchDescription += "#{if index then ' vs ' else ''}#{session.creatorName or 'Anonymous'} (#{sessions[index].team})"
|
||||
@simulationSpectateLink += "session-#{if index then 'two' else 'one'}=#{session.sessionID}"
|
||||
@simulationMatchDescription += " on #{@simulator.level.get('name')}"
|
||||
catch e
|
||||
console.log "There was a problem with the named simulation status: #{e}"
|
||||
$('#simulation-status-text').text @simulationStatus
|
||||
link = if @simulationSpectateLink then "<a href=#{@simulationSpectateLink}>#{_.string.escapeHTML(@simulationMatchDescription)}</a>" else ''
|
||||
$('#simulation-status-text').html "<h3>#{@simulationStatus}</h3>#{link}"
|
||||
|
||||
resimulateAllSessions: ->
|
||||
postData =
|
||||
|
@ -81,7 +95,7 @@ module.exports = class SimulateTabView extends CocoView
|
|||
|
||||
destroy: ->
|
||||
clearInterval @refreshInterval
|
||||
@simulator.destroy()
|
||||
@simulator?.destroy()
|
||||
super()
|
||||
|
||||
class SimulatorsLeaderboardData extends CocoClass
|
||||
|
|
|
@ -54,6 +54,7 @@ module.exports = class ControlBarView extends CocoView
|
|||
c.homeLink = '/play/ladder/' + @level.get('slug').replace /\-tutorial$/, ''
|
||||
else
|
||||
c.homeLink = '/'
|
||||
c.editorLink = "/editor/level/#{@level.get('slug')}"
|
||||
c
|
||||
|
||||
afterRender: ->
|
||||
|
|
|
@ -61,15 +61,16 @@ module.exports = class TomeView extends CocoView
|
|||
super()
|
||||
@worker = @createWorker()
|
||||
programmableThangs = _.filter @options.thangs, 'isProgrammable'
|
||||
if programmableThangs.length
|
||||
@createSpells programmableThangs, programmableThangs[0].world # Do before spellList, thangList, and castButton
|
||||
@spellList = @insertSubView new SpellListView spells: @spells, supermodel: @supermodel
|
||||
@thangList = @insertSubView new ThangListView spells: @spells, thangs: @options.thangs, supermodel: @supermodel
|
||||
@castButton = @insertSubView new CastButtonView spells: @spells, levelID: @options.levelID
|
||||
@teamSpellMap = @generateTeamSpellMap(@spells)
|
||||
else
|
||||
@createSpells programmableThangs, programmableThangs[0]?.world # Do before spellList, thangList, and castButton
|
||||
@spellList = @insertSubView new SpellListView spells: @spells, supermodel: @supermodel
|
||||
@thangList = @insertSubView new ThangListView spells: @spells, thangs: @options.thangs, supermodel: @supermodel
|
||||
@castButton = @insertSubView new CastButtonView spells: @spells, levelID: @options.levelID
|
||||
@teamSpellMap = @generateTeamSpellMap(@spells)
|
||||
unless programmableThangs.length
|
||||
@cast()
|
||||
console.warn 'Warning: There are no Programmable Thangs in this level, which makes it unplayable.'
|
||||
warning = 'Warning: There are no Programmable Thangs in this level, which makes it unplayable.'
|
||||
noty text: warning, layout: 'topCenter', type: 'warning', killer: false, timeout: 15000, dismissQueue: true, maxVisible: 3
|
||||
console.warn warning
|
||||
delete @options.thangs
|
||||
|
||||
onNewWorld: (e) ->
|
||||
|
|
|
@ -21,6 +21,7 @@ ThangTypeHandler = class ThangTypeHandler extends Handler
|
|||
'colorGroups'
|
||||
'kind'
|
||||
'raster'
|
||||
'rasterIcon'
|
||||
]
|
||||
|
||||
hasAccess: (req) ->
|
||||
|
|
Loading…
Reference in a new issue