Added /play/ladder/levelID/clan/clanID clan-specific ladder pages.

This commit is contained in:
Nick Winter 2015-08-15 06:45:38 -07:00
parent bda2483738
commit 32ca453dec
7 changed files with 63 additions and 23 deletions

View file

@ -104,6 +104,7 @@ module.exports = class CocoRouter extends Backbone.Router
'multiplayer': go('MultiplayerView')
'play': go('play/CampaignView')
'play/ladder/:levelID/:leagueType/:leagueID': go('ladder/LadderView')
'play/ladder/:levelID': go('ladder/LadderView')
'play/ladder': go('ladder/MainLadderView')
'play/level/:levelID': go('play/level/PlayLevelView')

View file

@ -10,6 +10,9 @@ block content
else
h1= level.get('name')
if league
h1 #{league.get('name')} League
if level.get('name') == 'Greed'
.tournament-blurb
h2

View file

@ -154,7 +154,7 @@ module.exports = class LadderTabView extends CocoView
@supermodel.removeModelResource oldLeaderboard
oldLeaderboard.destroy()
teamSession = _.find @sessions.models, (session) -> session.get('team') is team.id
@leaderboards[team.id] = new LeaderboardData(@level, team.id, teamSession, @ladderLimit)
@leaderboards[team.id] = new LeaderboardData(@level, team.id, teamSession, @ladderLimit, @options.league)
@leaderboardRes = @supermodel.addModelResource(@leaderboards[team.id], 'leaderboard', {cache: false}, 3)
@leaderboardRes.load()
@ -166,7 +166,9 @@ module.exports = class LadderTabView extends CocoView
team = _.find @teams, name: histogramWrapper.data('team-name')
histogramData = null
$.when(
$.get "/db/level/#{@level.get('slug')}/histogram_data?team=#{team.name.toLowerCase()}", {cache: false}, (data) -> histogramData = data
url = "/db/level/#{@level.get('slug')}/histogram_data?team=#{team.name.toLowerCase()}"
url += '&leagues.leagueID=' + @options.league.id if @options.league
$.get url, {cache: false}, (data) -> histogramData = data
).then =>
@generateHistogram(histogramWrapper, histogramData, team.name.toLowerCase()) unless @destroyed
@ -301,24 +303,32 @@ module.exports.LeaderboardData = LeaderboardData = class LeaderboardData extends
Consolidates what you need to load for a leaderboard into a single Backbone Model-like object.
###
constructor: (@level, @team, @session, @limit) ->
constructor: (@level, @team, @session, @limit, @league) ->
super()
collectionParameters: (parameters) ->
parameters.team = @team
parameters['leagues.leagueID'] = @league.id if @league
parameters
fetch: ->
console.warn 'Already have top players on', @ if @topPlayers
@topPlayers = new LeaderboardCollection(@level, {order: -1, scoreOffset: HIGHEST_SCORE, team: @team, limit: @limit})
@topPlayers = new LeaderboardCollection(@level, @collectionParameters(order: -1, scoreOffset: HIGHEST_SCORE, limit: @limit))
promises = []
promises.push @topPlayers.fetch cache: false
if @session
score = @session.get('totalScore') or 10
@playersAbove = new LeaderboardCollection(@level, {order: 1, scoreOffset: score, limit: 4, team: @team})
@playersAbove = new LeaderboardCollection(@level, @collectionParameters(order: 1, scoreOffset: score, limit: 4))
promises.push @playersAbove.fetch cache: false
@playersBelow = new LeaderboardCollection(@level, {order: -1, scoreOffset: score, limit: 4, team: @team})
@playersBelow = new LeaderboardCollection(@level, @collectionParameters(order: -1, scoreOffset: score, limit: 4))
promises.push @playersBelow.fetch cache: false
level = "#{@level.get('original')}.#{@level.get('version').major}"
success = (@myRank) =>
promises.push $.ajax("/db/level/#{level}/leaderboard_rank?scoreOffset=#{@session.get('totalScore')}&team=#{@team}", cache: false, success: success)
loadURL = "/db/level/#{level}/leaderboard_rank?scoreOffset=#{@session.get('totalScore')}&team=#{@team}"
loadURL += '&leagues.leagueID=' + @league.id if @league
promises.push $.ajax(loadURL, cache: false, success: success)
@promise = $.when(promises...)
@promise.then @onLoad
@promise.fail @onFail

View file

@ -12,6 +12,9 @@ SimulateTabView = require './SimulateTabView'
LadderPlayModal = require './LadderPlayModal'
CocoClass = require 'core/CocoClass'
Clan = require 'models/Clan'
#CourseInstance = require 'models/CourseInstance'
HIGHEST_SCORE = 1000000
class LevelSessionsCollection extends CocoCollection
@ -35,12 +38,19 @@ module.exports = class LadderView extends RootView
'click a:not([data-toggle])': 'onClickedLink'
'click .spectate-button': 'onClickSpectateButton'
constructor: (options, @levelID) ->
constructor: (options, @levelID, @leagueType, @leagueID) ->
super(options)
@level = @supermodel.loadModel(new Level(_id: @levelID), 'level').model
@sessions = @supermodel.loadCollection(new LevelSessionsCollection(@levelID), 'your_sessions', {cache: false}).model
@teams = []
@loadLeague()
loadLeague: ->
@leagueID = @leagueType = null unless @leagueType in ['clan'] #, 'course']
return unless @leagueID
modelClass = if @leagueType is 'clan' then Clan else null# else CourseInstance
resourceString = if @leagueType is 'clan' then 'clans.clan' else null# else 'courses.course'
@league = @supermodel.loadModel(new modelClass(_id: @leagueID), resourceString).model
onLoaded: ->
@teams = teamDataFromLevel @level
@ -53,6 +63,8 @@ module.exports = class LadderView extends RootView
ctx.teams = @teams
ctx.levelID = @levelID
ctx.levelDescription = marked(@level.get('description')) if @level.get('description')
ctx.leagueType = @leagueType
ctx.league = @league
ctx._ = _
if tournamentEndDate = {greed: 1402444800000, 'criss-cross': 1410912000000, 'zero-sum': 1428364800000}[@levelID]
ctx.tournamentTimeLeft = moment(new Date(tournamentEndDate)).fromNow()
@ -64,9 +76,9 @@ module.exports = class LadderView extends RootView
afterRender: ->
super()
return unless @supermodel.finished()
@insertSubView(@ladderTab = new LadderTabView({}, @level, @sessions))
@insertSubView(@myMatchesTab = new MyMatchesTabView({}, @level, @sessions))
@insertSubView(@simulateTab = new SimulateTabView())
@insertSubView(@ladderTab = new LadderTabView({league: @league}, @level, @sessions))
@insertSubView(@myMatchesTab = new MyMatchesTabView({league: @league}, @level, @sessions))
@insertSubView(@simulateTab = new SimulateTabView(league: @league))
@refreshInterval = setInterval(@fetchSessionsAndRefreshViews.bind(@), 60 * 1000)
hash = document.location.hash[1..] if document.location.hash
if hash and not (hash in ['my-matches', 'simulate', 'ladder', 'prizes', 'rules', 'winners'])

View file

@ -24,7 +24,8 @@ module.exports = class MyMatchesTabView extends CocoView
# Only fetch the names for the userIDs we don't already have in @nameMap
ids = []
for session in @sessions.models
for match in (session.get('matches') or [])
matches = @statsFromSession(session).matches or []
for match in matches
id = match.opponents[0].userID
unless id
console.error 'Found bad opponent ID in malformed match:', match, 'from session', session
@ -37,7 +38,8 @@ module.exports = class MyMatchesTabView extends CocoView
success = (nameMap) =>
return if @destroyed
for session in @sessions.models
for match in session.get('matches') or []
matches = @statsFromSession(session).matches or []
for match in matches
opponent = match.opponents[0]
continue if @nameMap[opponent.userID]
opponentUser = nameMap[opponent.userID]
@ -88,15 +90,16 @@ module.exports = class MyMatchesTabView extends CocoView
for team in @teams
team.session = (s for s in @sessions.models when s.get('team') is team.id)[0]
stats = @statsFromSession team.session
team.readyToRank = team.session?.readyToRank()
team.isRanking = team.session?.get('isRanking')
team.matches = (convertMatch(match, team.session.get('submitDate')) for match in team.session?.get('matches') or [])
team.matches = (convertMatch(match, team.session.get('submitDate')) for match in (stats?.matches or []))
team.matches.reverse()
team.score = (team.session?.get('totalScore') or 10).toFixed(2)
team.score = (stats?.totalScore ? 10).toFixed(2)
team.wins = _.filter(team.matches, {state: 'win', stale: false}).length
team.ties = _.filter(team.matches, {state: 'tie', stale: false}).length
team.losses = _.filter(team.matches, {state: 'loss', stale: false}).length
scoreHistory = team.session?.get('scoreHistory')
scoreHistory = stats?.scoreHistory
if scoreHistory?.length > 1
team.scoreHistory = scoreHistory
@ -123,6 +126,12 @@ module.exports = class MyMatchesTabView extends CocoView
@$el.find('tr.fresh').removeClass('fresh', 5000)
statsFromSession: (session) ->
return null unless session
if @options.league
return _.find(session.get('leagues') or [], leagueID: @options.league.id)?.stats
session.attributes
generateScoreLineChart: (wrapperID, scoreHistory, teamName) =>
margin =
top: 20

View file

@ -160,16 +160,18 @@ LevelHandler = class LevelHandler extends Handler
creator: req.user._id+''
query = Session.find(sessionQuery).select('-screenshot -transpiledCode')
# TODO: take out "code" as well, since that can get huge containing the transpiled code for the lat hero, and find another way of having the LadderSubmissionViews in the MyMatchesTab determine rankin readiness
# TODO: take out "code" as well, since that can get huge containing the transpiled code for the lat hero, and find another way of having the LadderSubmissionViews in the MyMatchesTab determine ranking readiness
query.exec (err, results) =>
if err then @sendDatabaseError(res, err) else @sendSuccess res, results
getHistogramData: (req, res, slug) ->
match = levelID: slug, submitted: true, team: req.query.team
match['leagues.leagueID'] = league if league = req.query['leagues.leagueID']
aggregate = Session.aggregate [
{$match: {'levelID': slug, 'submitted': true, 'team': req.query.team}}
{$match: match}
{$project: {totalScore: 1, _id: 0}}
]
aggregate.cache()
aggregate.cache() unless league
aggregate.exec (err, data) =>
if err? then return @sendDatabaseError res, err
@ -198,7 +200,7 @@ LevelHandler = class LevelHandler extends Handler
sortParameters =
'totalScore': req.query.order
selectProperties = ['totalScore', 'creatorName', 'creator', 'submittedCodeLanguage', 'heroConfig']
selectProperties = ['totalScore', 'creatorName', 'creator', 'submittedCodeLanguage', 'heroConfig', 'leagues.leagueID']
query = Session
.find(sessionsQueryParameters)
@ -232,6 +234,7 @@ LevelHandler = class LevelHandler extends Handler
team: req.query.team
totalScore: scoreQuery
submitted: true
query['leagues.leagueID'] = league if league = req.query['leagues.leagueID']
query
validateLeaderboardRequestParameters: (req) ->

View file

@ -24,8 +24,10 @@ LevelSessionSchema.index({team: 1}, {sparse: true})
LevelSessionSchema.index({totalScore: 1}, {sparse: true})
LevelSessionSchema.index({user: 1, changed: -1}, {name: 'last played index', sparse: true})
LevelSessionSchema.index({'level.original': 1, 'state.topScores.type': 1, 'state.topScores.date': -1, 'state.topScores.score': -1}, {name: 'top scores index', sparse: true})
LevelSessionSchema.index({submitted: 1, team: 1, level:1, totalScore: -1}, {name: 'rank counting index', sparse: true})
LevelSessionSchema.index({levelID: 1, submitted:1, team: 1}, {name: 'get all scores index', sparse: true})
LevelSessionSchema.index({submitted: 1, team: 1, level: 1, totalScore: -1}, {name: 'rank counting index', sparse: true})
#LevelSessionSchema.index({level: 1, 'leagues.leagueID': 1, submitted: 1, team: 1, totalScore: -1}, {name: 'league rank counting index', sparse: true}) # needed for league leaderboards?
LevelSessionSchema.index({levelID: 1, submitted: 1, team: 1}, {name: 'get all scores index', sparse: true})
#LevelSessionSchema.index({levelID: 1, 'leagues.leagueID': 1, submitted: 1, team: 1}, {name: 'league get all scores index', sparse: true}) # needed for league histograms?
LevelSessionSchema.index({submitted: 1, team: 1, levelID: 1, submitDate: -1}, {name: 'matchmaking index', sparse: true})
LevelSessionSchema.index({submitted: 1, team: 1, levelID: 1, randomSimulationIndex: -1}, {name: 'matchmaking random index', sparse: true})
LevelSessionSchema.index({'leagues.leagueID': 1, submitted: 1, levelID: 1, team: 1, randomSimulationIndex: -1}, {name: 'league-based matchmaking random index', sparse: true}) # Really need MongoDB 3.2 for partial indexes for this and several others: https://jira.mongodb.org/browse/SERVER-785