Rearranging the ladder view.

This commit is contained in:
Scott Erickson 2014-03-02 12:43:21 -08:00
parent 6c48660922
commit d0f416f668
8 changed files with 372 additions and 188 deletions

View file

@ -1,4 +1,10 @@
#ladder-view
h1
text-align: center
.tab-pane
margin-top: 10px
.score-cell
width: 50px
@ -10,10 +16,6 @@
width: 45%
margin: 0 2.5%
#simulation-status-text
display: inline
margin-left: 10px
.name-col-cell
max-width: 300px
text-overflow: ellipsis

View file

@ -2,17 +2,11 @@ extends /templates/base
block content
div#level-column
h3= level.get('name')
div#level-description
!{description}
if !me.get('anonymous')
//a(href="http://www.youtube.com/watch?v=IFvfZiJGDsw&list=HL1392928835&feature=mh_lolz").intro-button.btn.btn-primary.btn-lg Watch the Video
a(href="/play/level/brawlwood-tutorial").intro-button.btn.btn-primary.btn-lg Play the Tutorial
h1= level.get('name')
//if !me.get('anonymous')
// a(href="/play/level/brawlwood-tutorial").intro-button.btn.btn-primary.btn-lg Play the Tutorial
hr
if me.get('anonymous')
div#must-log-in
p
@ -23,41 +17,37 @@ block content
else
div#columns.row
div.column.col-md-2
for team in teams
div.column.col-md-6
div.column.col-md-4
a(href="/play/ladder/#{levelID}/team/#{team.id}", style="background-color: #{team.primaryColor}").play-button.btn.btn-danger.btn-block.btn-lg
span Play As
span= team.name
table.table.table-bordered.table-condensed.table-hover
//(style="background-color: #{team.bgColor}")
tr
th(colspan=3, style="color: #{team.primaryColor}")
span= team.name
span Leaderboard
tr
th Score
th.name-col-cell Name
th
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.name-col-cell= session.get('creatorName') || "Anonymous"
td
if(!myRow)
a(href="/play/level/#{level.get('slug') || level.id}/?team=#{team.otherTeam}&opponent=#{session.id}") Battle as #{team.otherTeam}!
else
a(href="/play/ladder/#{levelID}/team/#{team.id}") View your #{team.id} matches.
unless me.attributes.anonymous
hr
button.btn.btn-warning.btn-lg.highlight#simulate-button(style="margin-bottom:10px;") Simulate Games!
p(id="simulation-status-text", 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-danger.btn-lg.highlight#simulate-all-button(style="margin-bottom:10px; float: right;") RESET AND SIMULATE GAMES
div.column.col-md-2
hr
ul.nav.nav-pills
li.active
a(href="#ladder", data-toggle="tab") Ladder
li
a(href="#my-matches", data-toggle="tab") My Matches
li
a(href="#simulate", data-toggle="tab") Simulate
div.tab-content
.tab-pane.active.well#ladder
#ladder-tab-view
.tab-pane.well#my-matches
| My Matches Pane
.tab-pane.well#simulate
p(id="simulation-status-text")
if simulationStatus
| #{simulationStatus}
else
| By simulating games you can get your game ranked faster!
p
button.btn.btn-warning.btn-lg.highlight#simulate-button() Simulate Games!
if me.isAdmin()
p
button.btn.btn-danger.btn-lg.highlight#simulate-all-button() RESET AND SIMULATE GAMES

View file

@ -0,0 +1,23 @@
div#columns.row
for team in teams
div.column.col-md-6
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-col-cell Name
th
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.name-col-cell= session.get('creatorName') || "Anonymous"
td
if(!myRow)
a(href="/play/level/#{level.get('slug') || level.id}/?team=#{team.otherTeam}&opponent=#{session.id}") Battle as #{team.otherTeam}!
else
a(href="/play/ladder/#{levelID}/team/#{team.id}") View your #{team.id} matches.

View file

@ -0,0 +1,45 @@
//if matches.length
// p#your-score
// span Your Current Score:
// span
// strong= score
h3.pull-left Ranked Games
div#columns.row
for team in teams
div#matches-column.col-md-6
button.btn.btn-warning.pull-right.rank-button(data-session-id=team.session.id)
span.unavailable.hidden No New Code to Rank
span.rank.hidden Rank My Game!
span.ranking.hidden Submitting...
span.ranked.hidden Submitted for Ranking
span.failed.hidden Failed to Rank
hr.clearfix(style="clear: both")
if matches.length
table.table.table-bordered.table-condensed
tr
th Result
th Opponent
th When
for match in matches
tr
td.state-cell
if match.state === 'win'
span.win Win
if match.state === 'loss'
span.loss Loss
if match.state === 'tie'
span.tie Tie
td.name-cell= match.opponentName || "Anonymous"
td.time-cell= match.when
td.battle-cell
- var text = match.state === 'win' ? 'Watch your victory' : 'Defeat the ' + otherTeamID
a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{match.sessionID}")= text
else
div.alert.alert-warning
| No ranked matches played yet!
| Play some competitors on the right and then come back to get your game ranked.

View file

@ -0,0 +1,97 @@
CocoView = require 'views/kinds/CocoView'
Level = require 'models/Level'
LevelSession = require 'models/LevelSession'
CocoCollection = require 'models/CocoCollection'
LeaderboardCollection = require 'collections/LeaderboardCollection'
{teamDataFromLevel} = require './utils'
HIGHEST_SCORE = 1000000
class LevelSessionsCollection extends CocoCollection
url: ''
model: LevelSession
constructor: (levelID) ->
super()
@url = "/db/level/#{levelID}/all_sessions"
module.exports = class LadderView extends CocoView
id: 'ladder-tab-view'
template: require 'templates/play/ladder/ladder_tab'
startsLoading: true
constructor: (options, @level, @sessions) ->
super(options)
@teams = teamDataFromLevel @level
@leaderboards = {}
for team in @teams
# teamSession = _.find @sessions.models, (session) -> session.get('team') is team.id
teamSession = null
console.log "Team session: #{JSON.stringify teamSession}"
@leaderboards[team.id] = new LeaderboardData(@level, team.id, teamSession)
@leaderboards[team.id].once 'sync', @onLeaderboardLoaded, @
onChallengersLoaded: -> @renderMaybe()
onLeaderboardLoaded: -> @renderMaybe()
renderMaybe: ->
leaderboardModels = _.values(@leaderboards)
return unless _.every leaderboardModels, (loader) -> loader.loaded
@startsLoading = false
@render()
getRenderData: ->
ctx = super()
ctx.level = @level
ctx.link = "/play/level/#{@level.get('name')}"
ctx.teams = @teams
team.leaderboard = @leaderboards[team.id] for team in @teams
ctx.levelID = @levelID
ctx
class LeaderboardData
constructor: (@level, @team, @session) ->
_.extend @, Backbone.Events
@topPlayers = new LeaderboardCollection(@level, {order:-1, scoreOffset: HIGHEST_SCORE, team: @team, limit: if @session then 10 else 20})
@topPlayers.fetch()
@topPlayers.comparator = (model) ->
return -model.get('totalScore')
@topPlayers.sort()
@topPlayers.once 'sync', @leaderboardPartLoaded, @
# if @session
# score = @session.get('totalScore') or 25
# @playersAbove = new LeaderboardCollection(@level, {order:1, scoreOffset: score, limit: 4, team: @team})
# @playersAbove.fetch()
# @playersAbove.once 'sync', @leaderboardPartLoaded, @
# @playersBelow = new LeaderboardCollection(@level, {order:-1, scoreOffset: score, limit: 4, team: @team})
# @playersBelow.fetch()
# @playersBelow.once 'sync', @leaderboardPartLoaded, @
leaderboardPartLoaded: ->
if @session
if @topPlayers.loaded # and @playersAbove.loaded and @playersBelow.loaded
@loaded = true
@fetchNames()
else
@loaded = true
@fetchNames()
fetchNames: ->
sessionCollections = [@topPlayers, @playersAbove, @playersBelow]
sessionCollections = (s for s in sessionCollections when s)
ids = []
for collection in sessionCollections
ids.push model.get('creator') for model in collection.models
success = (nameMap) =>
for collection in sessionCollections
session.set('creatorName', nameMap[session.get('creator')]) for session in collection.models
@trigger 'sync'
$.ajax('/db/user/-/names', {
data: {ids: ids}
type: 'POST'
success: success
})

View file

@ -0,0 +1,101 @@
CocoView = require 'views/kinds/CocoView'
Level = require 'models/Level'
LevelSession = require 'models/LevelSession'
LeaderboardCollection = require 'collections/LeaderboardCollection'
{teamDataFromLevel} = require './utils'
module.exports = class LadderTeamView extends CocoView
id: 'ladder-team-view'
template: require 'templates/play/ladder/team'
startsLoading: true
events:
'click #rank-button': 'rankSession'
constructor: (options, @level, @sessions) ->
super(options)
@teams = teamDataFromLevel @level
@loadNames()
loadNames: ->
ids = []
for session in @sessions.models
ids.push match.opponents[0].userID for match in session.get('matches') or []
success = (@nameMap) =>
for match in @session.get('matches') or []
opponent = match.opponents[0]
opponent.userName = @nameMap[opponent.userID]
@finishRendering()
$.ajax('/db/user/-/names', {
data: {ids: ids}
type: 'POST'
success: success
})
finishRendering: ->
@startsLoading = false
@render()
getRenderData: ->
ctx = super()
ctx.level = @level
ctx.levelID = @level.get('slug') or @level.id
ctx.teams = @teams
convertMatch = (match) =>
opponent = match.opponents[0]
state = 'win'
state = 'loss' if match.metrics.rank > opponent.metrics.rank
state = 'tie' if match.metrics.rank is opponent.metrics.rank
{
state: state
opponentName: @nameMap[opponent.userID]
opponentID: opponent.userID
when: moment(match.date).fromNow()
sessionID: opponent.sessionID
}
for team in @teams
team.session = (s for s in @sessions.models when s.get('team') is team.id)[0]
team.readyToRank = @readyToRank(team.session)
team.matches = (convertMatch(match) for match in team.session.get('matches') or [])
team.matches.reverse()
team.score = (team.session.get('totalScore') or 10).toFixed(2)
ctx
afterRender: ->
super()
@$el.find('.rank-button').each (i, el) =>
sessionID = button.data('session-id')
session = _.find @sessions.models, { id: sessionID }
@setRankingButtonText $(el), if @readyToRank(session) then 'rank' else 'unavailable'
readyToRank: (session) ->
c1 = session.get('code')
c2 = session.get('submittedCode')
c1 and not _.isEqual(c1, c2)
rankSession: (e) ->
button = $(e.target).closest('.rank-button')
sessionID = button.data('session-id')
session = _.find @sessions.models, { id: sessionID }
return unless @readyToRank(session)
@setRankingButtonText(button, 'ranking')
success = => @setRankingButtonText(button, 'ranked')
failure = => @setRankingButtonText(button, 'failed')
$.ajax '/queue/scoring', {
type: 'POST'
data: { session: sessionID }
success: success
failure: failure
}
setRankingButtonText: (rankButton, spanClass) ->
rankButton.find('span').addClass('hidden')
rankButton.find(".#{spanClass}").removeClass('hidden')
rankButton.toggleClass 'disabled', spanClass isnt 'rank'

View file

@ -0,0 +1,23 @@
{hslToHex} = require 'lib/utils'
module.exports.teamDataFromLevel = (level) ->
alliedSystem = _.find level.get('systems'), (value) -> value.config?.teams?
teamNames = (teamName for teamName, teamConfig of alliedSystem.config.teams when teamConfig.playable)
teamConfigs = alliedSystem.config.teams
teams = []
for team in teamNames or []
otherTeam = if team is 'ogres' then 'humans' else 'ogres'
color = teamConfigs[team].color
bgColor = hslToHex([color.hue, color.saturation, color.lightness + (1 - color.lightness) * 0.5])
primaryColor = hslToHex([color.hue, 0.5, 0.5])
teams.push({
id: team
name: _.string.titleize(team)
otherTeam: otherTeam
bgColor: bgColor
primaryColor: primaryColor
})
console.log 'created teams', teams
teams

View file

@ -4,7 +4,8 @@ Simulator = require 'lib/simulator/Simulator'
LevelSession = require 'models/LevelSession'
CocoCollection = require 'models/CocoCollection'
LeaderboardCollection = require 'collections/LeaderboardCollection'
{hslToHex} = require 'lib/utils'
{teamDataFromLevel} = require './ladder/utils'
LadderTabView = require './ladder/ladder_tab'
HIGHEST_SCORE = 1000000
@ -25,8 +26,48 @@ module.exports = class LadderView extends RootView
'click #simulate-button': 'onSimulateButtonClick'
'click #simulate-all-button': 'onSimulateAllButtonClick'
constructor: (options, @levelID) ->
super(options)
@level = new Level(_id:@levelID)
@level.fetch()
@level.once 'sync', @onLevelLoaded, @
# @sessions = new LevelSessionsCollection(levelID)
# @sessions.fetch({})
# @sessions.once 'sync', @onMySessionsLoaded, @
@simulator = new Simulator()
@simulator.on 'statusUpdate', @updateSimulationStatus, @
@teams = []
onLevelLoaded: -> @renderMaybe()
onMySessionsLoaded: -> @renderMaybe()
renderMaybe: ->
return unless @level.loaded # and @sessions.loaded
@teams = teamDataFromLevel @level
console.log 'made teams', @teams
@startsLoading = false
@render()
getRenderData: ->
ctx = super()
ctx.level = @level
ctx.link = "/play/level/#{@level.get('name')}"
ctx.simulationStatus = @simulationStatus
ctx.teams = @teams
console.log 'ctx teams', ctx.teams
ctx.levelID = @levelID
ctx
afterRender: ->
super()
return if @startsLoading
@ladderTab = new LadderTabView({}, @level, @sessions)
@insertSubView(@ladderTab)
# Simulations
onSimulateAllButtonClick: (e) ->
submitIDs = _.pluck @leaderboards[@teams[0]].topPlayers.models, "id"
submitIDs = _.pluck @leaderboards[@teams[0].id].topPlayers.models, "id"
for ID in submitIDs
$.ajax
url: '/queue/scoring'
@ -57,141 +98,3 @@ module.exports = class LadderView extends RootView
catch e
console.log "There was a problem with the named simulation status: #{e}"
$("#simulation-status-text").text @simulationStatus
constructor: (options, @levelID) ->
super(options)
@level = new Level(_id:@levelID)
@level.fetch()
@level.once 'sync', @onLevelLoaded, @
@simulator = new Simulator()
@simulator.on 'statusUpdate', @updateSimulationStatus, @
# @sessions = new LevelSessionsCollection(levelID)
# @sessions.fetch({})
# @sessions.once 'sync', @onMySessionsLoaded, @
onLevelLoaded: -> @startLoadingPhaseTwoMaybe()
onMySessionsLoaded: ->
@startLoadingPhaseTwoMaybe()
startLoadingPhaseTwoMaybe: ->
return unless @level.loaded # and @sessions.loaded
@loadPhaseTwo()
loadPhaseTwo: ->
alliedSystem = _.find @level.get('systems'), (value) -> value.config?.teams?
teams = []
for teamName, teamConfig of alliedSystem.config.teams
continue unless teamConfig.playable
teams.push teamName
@teams = teams
@teamConfigs = alliedSystem.config.teams
@leaderboards = {}
@challengers = {}
for team in teams
# teamSession = _.find @sessions.models, (session) -> session.get('team') is team
teamSession = null
console.log "Team session: #{JSON.stringify teamSession}"
@leaderboards[team] = new LeaderboardData(@level, team, teamSession)
@leaderboards[team].once 'sync', @onLeaderboardLoaded, @
onChallengersLoaded: -> @renderMaybe()
onLeaderboardLoaded: -> @renderMaybe()
renderMaybe: ->
loaders = _.values(@leaderboards) # .concat(_.values(@challengers))
return unless _.every loaders, (loader) -> loader.loaded
@startsLoading = false
@render()
getRenderData: ->
ctx = super()
ctx.level = @level
description = @level.get('description')
ctx.description = if description then marked(description) else ''
ctx.link = "/play/level/#{@level.get('name')}"
ctx.simulationStatus = @simulationStatus
ctx.teams = []
ctx.levelID = @levelID
for team in @teams or []
otherTeam = if team is 'ogres' then 'humans' else 'ogres'
color = @teamConfigs[team].color
bgColor = hslToHex([color.hue, color.saturation, color.lightness + (1 - color.lightness) * 0.5])
primaryColor = hslToHex([color.hue, 0.5, 0.5])
ctx.teams.push({
id: team
name: _.string.titleize(team)
leaderboard: @leaderboards[team]
otherTeam: otherTeam
bgColor: bgColor
primaryColor: primaryColor
})
ctx
class LeaderboardData
constructor: (@level, @team, @session) ->
_.extend @, Backbone.Events
@topPlayers = new LeaderboardCollection(@level, {order:-1, scoreOffset: HIGHEST_SCORE, team: @team, limit: if @session then 10 else 20})
@topPlayers.fetch()
@topPlayers.comparator = (model) ->
return -model.get('totalScore')
@topPlayers.sort()
@topPlayers.once 'sync', @leaderboardPartLoaded, @
# if @session
# score = @session.get('totalScore') or 25
# @playersAbove = new LeaderboardCollection(@level, {order:1, scoreOffset: score, limit: 4, team: @team})
# @playersAbove.fetch()
# @playersAbove.once 'sync', @leaderboardPartLoaded, @
# @playersBelow = new LeaderboardCollection(@level, {order:-1, scoreOffset: score, limit: 4, team: @team})
# @playersBelow.fetch()
# @playersBelow.once 'sync', @leaderboardPartLoaded, @
leaderboardPartLoaded: ->
if @session
if @topPlayers.loaded # and @playersAbove.loaded and @playersBelow.loaded
@loaded = true
@fetchNames()
else
@loaded = true
@fetchNames()
fetchNames: ->
sessionCollections = [@topPlayers, @playersAbove, @playersBelow]
sessionCollections = (s for s in sessionCollections when s)
ids = []
for collection in sessionCollections
ids.push model.get('creator') for model in collection.models
success = (nameMap) =>
for collection in sessionCollections
session.set('creatorName', nameMap[session.get('creator')]) for session in collection.models
@trigger 'sync'
$.ajax('/db/user/-/names', {
data: {ids: ids}
type: 'POST'
success: success
})
class ChallengersData
constructor: (@level, @team, @session) ->
_.extend @, Backbone.Events
score = @session?.get('totalScore') or 25
@easyPlayer = new LeaderboardCollection(@level, {order:1, scoreOffset: score - 5, limit: 1, team: @team})
@easyPlayer.fetch()
@easyPlayer.once 'sync', @challengerLoaded, @
@mediumPlayer = new LeaderboardCollection(@level, {order:1, scoreOffset: score, limit: 1, team: @team})
@mediumPlayer.fetch()
@mediumPlayer.once 'sync', @challengerLoaded, @
@hardPlayer = new LeaderboardCollection(@level, {order:-1, scoreOffset: score + 5, limit: 1, team: @team})
@hardPlayer.fetch()
@hardPlayer.once 'sync', @challengerLoaded, @
challengerLoaded: ->
if @easyPlayer.loaded and @mediumPlayer.loaded and @hardPlayer.loaded
@loaded = true
@trigger 'sync'