This commit is contained in:
Scott Erickson 2014-02-20 11:43:46 -08:00
commit 8184d0b9d3
9 changed files with 94 additions and 48 deletions

View file

@ -6,18 +6,33 @@
> .popover
// Only those popovers which are our direct children (spell documentation)
left: auto !important
top: auto !important
right: 100%
bottom: 151px
@include user-select(text)
// Wish I could set max-width and max-height (and override Bootstrap's stuff)
// but without explicitly setting height, child overflow-y: scroll doesn't work
min-width: 100%
height: 60%
max-width: 600px
&.pinned
@include box-shadow(0 0 500px white)
left: auto !important
top: auto !important
right: 100%
bottom: 151px
@include user-select(text)
// Wish I could set max-width and max-height (and override Bootstrap's stuff)
// but without explicitly setting height, child overflow-y: scroll doesn't work
min-width: 100%
height: 60%
.arrow
display: none
.close
position: absolute
top: 5%
right: 5%
font-size: 28px
font-weight: bold
@include opacity(0.6)
text-shadow: 0 1px 0 white
&:hover
@include opacity(1)
.popover
padding: 10px 10px 30px 10px

View file

@ -11,33 +11,36 @@ block content
for team in teams
div.column.col-md-6
a(href="/play/ladder/#{levelID}/team/#{team.id}", style="background-color: #{team.primaryColor}").play-button.btn.btn-danger.btn-block.btn-lg
span Play
span Play As
span= team.name
table.table.table-bordered.table-condensed
table.table.table-bordered.table-condensed.table-hover
tr
th(colspan=3, style="color: #{team.primaryColor}")
span= team.name
span Leaderboard
tr
th Score
th Name
for session in team.leaderboard.topPlayers.models
- var myRow = session.get('creator') == me.id
tr(class=myRow ? "success" : "")
td.score-cell= session.get('totalScore').toFixed(2)
td= session.get('creatorName')
td= session.get('creatorName') || "Anonymous"
td
if(!myRow)
a(href="/play/level/#{level.get('slug') || level.id}/?team=#{team.otherTeam}&opponent=#{session.id}") COMPETE
a(href="/play/level/#{level.get('slug') || level.id}/?team=#{team.otherTeam}&opponent=#{session.id}") Compete!
else
a(href="/play/ladder/#{levelID}/team/#{team.id}") View details
unless me.attributes.anonymous
hr
button.btn.btn-warning.btn-lg.highlight#simulate-button(style="margin-bottom:10px;") Simulate Games!
p(style="display:inline; margin-left:10px;")
p(id="simulationStatusText", style="display:inline; margin-left:10px;")
if simulationStatus
| #{simulationStatus}
else
| By simulating games you can get your game ranked faster!
if me.isAdmin()
button.btn.btn-warning.btn-lg.highlight#simulate-all-button(style="margin-bottom:10px; float: right;") RESET AND SIMULATE GAMES
button.btn.btn-danger.btn-lg.highlight#simulate-all-button(style="margin-bottom:10px; float: right;") RESET AND SIMULATE GAMES

View file

@ -39,7 +39,7 @@ block content
span.loss Loss
if match.state === 'tie'
span.tie Tie
td.name-cell= match.opponentName
td.name-cell= match.opponentName || "Anonymous"
td.time-cell= match.when
td.battle-cell
a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{match.sessionID}") Battle!

View file

@ -29,7 +29,8 @@
if me.get('anonymous')
p Sign in or create an account and get your solution on the leaderboard!
else
#submit-session-button.btn.btn-primary Update Ladder Score
a#go-to-leaderboard-button.btn.btn-primary(href="/play/ladder/#{levelSlug}/team/#{team}") Go to the leaderboard!
p You can submit your game to be ranked from the leaderboard page.
.modal-footer
a(href='#', data-dismiss="modal", aria-hidden="true", data-i18n="modal.close").btn.btn-primary Close

View file

@ -33,10 +33,13 @@ module.exports = class LadderView extends RootView
method: 'POST'
data:
session: ID
alert "Simulating all games!"
alert "(do not push more than once pls)"
$("#simulate-all-button").prop "disabled", true
$("#simulate-all-button").text "Submitted all!"
onSimulateButtonClick: (e) ->
$("#simulate-button").prop "disabled",true
$("#simulate-button").text "Simulating..."
@simulator.fetchAndSimulateTask()
updateSimulationStatus: (simulationStatus, sessions)->
@ -53,7 +56,7 @@ module.exports = class LadderView extends RootView
@simulationStatus += "..."
catch e
console.log "There was a problem with the named simulation status: #{e}"
@render()
$("#simulationStatusText").text @simulationStatus
constructor: (options, @levelID) ->

View file

@ -9,7 +9,7 @@ module.exports = class MultiplayerModal extends View
events:
'click textarea': 'onClickLink'
'change #multiplayer': 'updateLinkSection'
'click #submit-session-button': 'submitSession'
constructor: (options) ->
super(options)
@ -24,6 +24,8 @@ module.exports = class MultiplayerModal extends View
'?session=' +
@session.id)
c.multiplayer = @session.get('multiplayer')
c.team = @session.get 'team'
c.levelSlug = @level?.get('slug')
c.playableTeams = @playableTeams
c.ladderGame = @level?.get('name') is 'Project DotA' and not me.get('isAnonymous')
c
@ -41,13 +43,6 @@ module.exports = class MultiplayerModal extends View
la.toggle Boolean(multiplayer)
true
submitSession: ->
$.ajax('/queue/scoring', {
method: 'POST'
data:
session: @session.id
})
onHidden: ->
multiplayer = Boolean(@$el.find('#multiplayer').prop('checked'))
@session.set('multiplayer', multiplayer)

View file

@ -64,7 +64,7 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView
@$el.find('code').popover(
animation: true
html: true
placement: 'left'
placement: 'bottom'
trigger: 'hover'
content: @formatPopover doc
container: @$el.parent()

View file

@ -64,6 +64,8 @@ module.exports = class SpellPaletteEntryView extends View
subscriptions:
'surface:frame-changed': "onFrameChanged"
'tome:palette-hovered': "onPaletteHovered"
'tome:palette-pin-toggled': "onPalettePinToggled"
events:
'mouseenter': 'onMouseEnter'
@ -100,13 +102,13 @@ module.exports = class SpellPaletteEntryView extends View
@$el.popover(
animation: false
html: true
placement: 'left'
placement: 'top'
trigger: 'manual' # Hover, until they click, which will then pin it until unclick.
content: @formatPopover()
container: '#tome-view'
)
@$el.on 'show.bs.popover', =>
Backbone.Mediator.publish 'tome:palette-hovered', thang: @thang, prop: @doc.name
Backbone.Mediator.publish 'tome:palette-hovered', thang: @thang, prop: @doc.name, entry: @
formatPopover: ->
content = popoverTemplate doc: @doc, value: @formatValue(), marked: marked, argumentExamples: (arg.example or arg.default or arg.name for arg in @doc.args ? [])
@ -143,31 +145,45 @@ module.exports = class SpellPaletteEntryView extends View
# Make sure the doc has the updated Thang so it can regenerate its prop value
@$el.data('bs.popover').options.content = @formatPopover()
@$el.popover('setContent')
@$el.popover 'show' unless @popoverPinned
@$el.popover 'show' unless @popoverPinned or @otherPopoverPinned
onMouseLeave: (e) ->
@$el.popover 'hide' unless @popoverPinned
@$el.popover 'hide' unless @popoverPinned or @otherPopoverPinned
togglePinned: ->
if @popoverPinned
@popoverPinned = false
@$el.add('#tome-view .popover').removeClass 'pinned'
$('#tome-view .popover .close').remove()
@$el.popover 'hide'
else
@popoverPinned = true
@$el.popover 'show'
@$el.add('#tome-view .popover').addClass 'pinned'
x = $('<button type="button" data-dismiss="modal" aria-hidden="true" class="close">×</button>')
$('#tome-view .popover').append x
x.on 'click', @onClick
Backbone.Mediator.publish 'tome:palette-pin-toggled', entry: @, pinned: @popoverPinned
onClick: (e) ->
onClick: (e) =>
unless @popoverPinned
$(e.target).selectText()
e.stopPropagation() # don't re-focus editor since we might want to select text
@togglePinned()
Backbone.Mediator.publish 'tome:palette-clicked', thang: @thang, prop: @doc.name
Backbone.Mediator.publish 'tome:palette-clicked', thang: @thang, prop: @doc.name, entry: @
onFrameChanged: (e) ->
return unless e.selectedThang?.id is @thang.id
@options.thang = @thang = e.selectedThang # Update our thang to the current version
onPaletteHovered: (e) ->
return if e.entry is @
@togglePinned() if @popoverPinned
onPalettePinToggled: (e) ->
return if e.entry is @
@otherPopoverPinned = e.pinned
destroy: ->
$('.popover.pinned').remove() if @popoverPinned # @$el.popover('destroy') doesn't work
@togglePinned() if @popoverPinned

View file

@ -26,23 +26,26 @@ connectToScoringQueue = ->
module.exports.createNewTask = (req, res) ->
requestSessionID = req.body.session
if isUserAnonymous req then return errors.forbidden res, "You need to be logged in to be added to the leaderboard"
return errors.badInput res, "The session ID is invalid" unless typeof requestSessionID is "string"
validatePermissions req, requestSessionID, (error, permissionsAreValid) ->
if err? then return errors.serverError res, "There was an error validating permissions"
unless permissionsAreValid then return errors.forbidden res, "You do not have the permissions to submit that game to the leaderboard"
fetchSessionToSubmit requestSessionID, (err, sessionToSubmit) ->
if err? then return errors.serverError res, "There was an error finding the given session."
return errors.badInput res, "The session ID is invalid" unless typeof requestSessionID is "string"
updateSessionToSubmit sessionToSubmit, (err, data) ->
if err? then return errors.serverError res, "There was an error updating the session"
fetchSessionToSubmit requestSessionID, (err, sessionToSubmit) ->
if err? then return errors.serverError res, "There was an error finding the given session."
fetchSessionsToRankAgainst (err, sessionsToRankAgainst) ->
if err? then return errors.serverError res, "There was an error fetching the sessions to rank against"
updateSessionToSubmit sessionToSubmit, (err, data) ->
if err? then return errors.serverError res, "There was an error updating the session"
taskPairs = generateTaskPairs(sessionsToRankAgainst, sessionToSubmit)
sendEachTaskPairToTheQueue taskPairs, (taskPairError) ->
if taskPairError? then return errors.serverError res, "There was an error sending the task pairs to the queue"
fetchSessionsToRankAgainst (err, sessionsToRankAgainst) ->
if err? then return errors.serverError res, "There was an error fetching the sessions to rank against"
sendResponseObject req, res, {"message":"All task pairs were succesfully sent to the queue"}
taskPairs = generateTaskPairs(sessionsToRankAgainst, sessionToSubmit)
sendEachTaskPairToTheQueue taskPairs, (taskPairError) ->
if taskPairError? then return errors.serverError res, "There was an error sending the task pairs to the queue"
sendResponseObject req, res, {"message":"All task pairs were succesfully sent to the queue"}
module.exports.dispatchTaskToConsumer = (req, res) ->
if isUserAnonymous(req) then return errors.forbidden res, "You need to be logged in to simulate games"
@ -95,6 +98,14 @@ module.exports.processTaskResult = (req, res) ->
console.log "Sending response object"
sendResponseObject req, res, {"message":"The scores were updated successfully!"}
validatePermissions = (req, sessionID, callback) ->
if isUserAnonymous req then return callback null, false
if isUserAdmin req then return callback null, true
LevelSession.findOne(_id:sessionID).select('creator submittedCode code').lean().exec (err, retrievedSession) ->
if err? then return callback err, retrievedSession
code = retrievedSession.code
submittedCode = retrievedSession.submittedCode
callback null, (retrievedSession.creator is req.user?.id and not _.isEqual(code, submittedCode))
addMatchToSessions = (clientResponseObject, newScoreObject, callback) ->
matchObject = {}
@ -175,6 +186,8 @@ getUserIDFromRequest = (req) -> if req.user? then return req.user._id else retur
isUserAnonymous = (req) -> if req.user? then return req.user.get('anonymous') else return true
isUserAdmin = (req) -> return Boolean(req.user?.isAdmin())
parseTaskQueueMessage = (req, res, message) ->
try
if typeof message.getBody() is "object" then return message.getBody()