This commit is contained in:
Scott Erickson 2014-04-16 08:07:54 -07:00
commit 476d153717
16 changed files with 141 additions and 36 deletions

View file

@ -5,7 +5,7 @@ module.exports.load = (key) ->
value = JSON.parse(s) value = JSON.parse(s)
return value return value
catch SyntaxError catch SyntaxError
console.warning('error loading from storage', key) console.warn('error loading from storage', key)
return null return null
module.exports.save = (key, value) -> module.exports.save = (key, value) ->

View file

@ -668,3 +668,4 @@
user_schema: "User Schema" user_schema: "User Schema"
user_profile: "User Profile" user_profile: "User Profile"
patches: "Patches" patches: "Patches"
model: "Model"

View file

@ -175,29 +175,29 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
edit_settings: "Beállítások szerkesztése" edit_settings: "Beállítások szerkesztése"
# profile_for_prefix: "Profile for " # profile_for_prefix: "Profile for "
# profile_for_suffix: "" # profile_for_suffix: ""
# approved: "Approved" approved: "Jóváhagyva"
# not_approved: "Not Approved" not_approved: "Nincs jóváhagyva"
# looking_for: "Looking for:" looking_for: "Keres:"
# last_updated: "Last updated:" last_updated: "Legutóbb napra-készre hozva:"
# contact: "Contact" contact: "Kapcsolat"
# work_experience: "Work Experience" work_experience: "Munkatapasztalat"
# education: "Education" education: "Végzettség"
# our_notes: "Our Notes" # our_notes: "Our Notes"
# projects: "Projects" projects: "Projektek"
# employers: munkaadók:
# want_to_hire_our_players: "Want to hire expert CodeCombat players?" want_to_hire_our_players: "Akarsz szakértő CodeCombat játékosokat alkalmazni?"
# contact_george: "Contact George to see our candidates" contact_george: "Vedd fel a kapcsolatot George-dzsal, hogy megtekinthesd jelöltjeinket"
# candidates_count_prefix: "We currently have " candidates_count_prefix: "Pillanatnyilag van"
# candidates_count_many: "many" candidates_count_many: "sok"
# candidates_count_suffix: "highly skilled and vetted developers looking for work." candidates_count_suffix: "magasan képzett és ellenőrzött fejlesztő, aki munkát keres."
# candidate_name: "Name" candidate_name: "Név"
# candidate_location: "Location" # candidate_location: "Location"
# candidate_looking_for: "Looking For" candidate_looking_for: "Keres"
# candidate_role: "Role" candidate_role: "Szerep"
# candidate_top_skills: "Top Skills" # candidate_top_skills: "Top Skills"
# candidate_years_experience: "Yrs Exp" # candidate_years_experience: "Yrs Exp"
# candidate_last_updated: "Last Updated" candidate_last_updated: "Legutóbb napra-készre hozva"
play_level: play_level:
level_load_error: "A pályát nem sikerült betölteni: " level_load_error: "A pályát nem sikerült betölteni: "

View file

@ -8,7 +8,8 @@ module.exports = class Level extends CocoModel
urlRoot: "/db/level" urlRoot: "/db/level"
serialize: (supermodel) -> serialize: (supermodel) ->
o = _.cloneDeep @attributes # slow in level editor when there are hundreds of Thangs # o = _.cloneDeep @attributes # slow in level editor when there are hundreds of Thangs
o = $.extend true, {}, @attributes
# Figure out Components # Figure out Components
o.levelComponents = _.cloneDeep (lc.attributes for lc in supermodel.getModels LevelComponent) o.levelComponents = _.cloneDeep (lc.attributes for lc in supermodel.getModels LevelComponent)

View file

@ -101,9 +101,13 @@ _.extend LevelSessionSchema.properties,
source: source:
type: 'string' type: 'string'
# TODO: specify this more
code: code:
type: 'object' type: 'object'
additionalProperties:
type: 'object'
additionalProperties:
type: 'string'
format: 'javascript'
teamSpells: teamSpells:
type: 'object' type: 'object'
@ -134,6 +138,11 @@ _.extend LevelSessionSchema.properties,
submittedCode: submittedCode:
type: 'object' type: 'object'
additionalProperties:
type: 'object'
additionalProperties:
type: 'string'
format: 'javascript'
isRanking: isRanking:
type: 'boolean' type: 'boolean'

View file

@ -0,0 +1,9 @@
#model-modal
.treema-root
background-color: white
.modal-dialog
width: 1000px
.treema-ace .ace_editor
height: 600px

View file

@ -5,6 +5,9 @@
overflow: hidden overflow: hidden
text-overflow: ellipsis text-overflow: ellipsis
.histogram-display
height: 130px
.bar rect .bar rect
fill: steelblue fill: steelblue
shape-rendering: crispEdges shape-rendering: crispEdges
@ -40,3 +43,7 @@
.ogres-rank-text .ogres-rank-text
fill: #3f44bf fill: #3f44bf
.load-more-ladder-entries
position: absolute
right: 15px
bottom: -5px

View file

@ -0,0 +1,9 @@
extends /templates/modal/modal_base
block modal-header
block modal-body-content
for model in models
h3= model.type() + ': ' + model.id
.model-treema(data-model-id=model.id)
hr

View file

@ -1,5 +1,5 @@
div#columns.row div#columns.row
for team in teams for team, teamIndex in teams
div.column.col-md-4 div.column.col-md-4
div(id="histogram-display-#{team.name}", class="histogram-display",data-team-name=team.name) div(id="histogram-display-#{team.name}", class="histogram-display",data-team-name=team.name)
table.table.table-bordered.table-condensed.table-hover table.table.table-bordered.table-condensed.table-hover
@ -17,10 +17,10 @@ div#columns.row
- var topSessions = team.leaderboard.topPlayers.models; - var topSessions = team.leaderboard.topPlayers.models;
- var showJustTop = team.leaderboard.inTopSessions() || me.get('anonymous'); - var showJustTop = team.leaderboard.inTopSessions() || me.get('anonymous');
- if(!showJustTop) topSessions = topSessions.slice(0, 10); - if(!showJustTop && topSessions.length == 20) topSessions = topSessions.slice(0, 10);
for session, rank in topSessions for session, rank in topSessions
- var myRow = session.get('creator') == me.id - var myRow = session.get('creator') == me.id
tr(class=myRow ? "success" : "") tr(class=myRow ? "success" : "", data-player-id=session.get('creator'), data-session-id=session.id)
td.rank-cell= rank + 1 td.rank-cell= rank + 1
td.score-cell= Math.round(session.get('totalScore') * 100) td.score-cell= Math.round(session.get('totalScore') * 100)
td.name-col-cell= session.get('creatorName') || "Anonymous" td.name-col-cell= session.get('creatorName') || "Anonymous"
@ -33,13 +33,15 @@ div#columns.row
td(colspan=4).ellipsis-row ... td(colspan=4).ellipsis-row ...
for session in team.leaderboard.nearbySessions() for session in team.leaderboard.nearbySessions()
- var myRow = session.get('creator') == me.id - var myRow = session.get('creator') == me.id
tr(class=myRow ? "success" : "") tr(class=myRow ? "success" : "", data-player-id=session.get('creator'), data-session-id=session.id)
td.rank-cell= session.rank td.rank-cell= session.rank
td.score-cell= Math.round(session.get('totalScore') * 100) td.score-cell= Math.round(session.get('totalScore') * 100)
td.name-col-cell= session.get('creatorName') || "Anonymous" td.name-col-cell= session.get('creatorName') || "Anonymous"
td.fight-cell td.fight-cell
a(href="/play/level/#{level.get('slug') || level.id}/?team=#{team.otherTeam}&opponent=#{session.id}") a(href="/play/level/#{level.get('slug') || level.id}/?team=#{team.otherTeam}&opponent=#{session.id}")
span(data-i18n="ladder.fight") Fight! span(data-i18n="ladder.fight") Fight!
if teamIndex == 1
.btn.btn-sm.load-more-ladder-entries moar
div.column.col-md-4 div.column.col-md-4
h4.friends-header Friends Playing h4.friends-header Friends Playing

View file

@ -78,7 +78,7 @@ module.exports = class SettingsView extends View
buildPictureTreema: -> buildPictureTreema: ->
data = photoURL: me.get('photoURL') data = photoURL: me.get('photoURL')
data.photoURL = null if data.photoURL?.search('gravatar') isnt -1 # Old style data.photoURL = null if data.photoURL?.search('gravatar') isnt -1 # Old style
schema = _.cloneDeep me.schema() schema = $.extend true, {}, me.schema()
schema.properties = _.pick me.schema().properties, 'photoURL' schema.properties = _.pick me.schema().properties, 'photoURL'
schema.required = ['photoURL'] schema.required = ['photoURL']
treemaOptions = treemaOptions =
@ -93,7 +93,6 @@ module.exports = class SettingsView extends View
@$el.find('.gravatar-fallback').toggle not me.get 'photoURL' @$el.find('.gravatar-fallback').toggle not me.get 'photoURL'
onPictureChanged: (e) => onPictureChanged: (e) =>
console.log "on Picture TChoinagaegd"
@trigger 'change' @trigger 'change'
@$el.find('.gravatar-fallback').toggle not me.get 'photoURL' @$el.find('.gravatar-fallback').toggle not me.get 'photoURL'

View file

@ -113,15 +113,18 @@ class CocoView extends Backbone.View
@listenToOnce modelOrCollection, 'sync', @updateProgress @listenToOnce modelOrCollection, 'sync', @updateProgress
@listenTo modelOrCollection, 'error', @onResourceLoadFailed @listenTo modelOrCollection, 'error', @onResourceLoadFailed
@updateProgress() @updateProgress()
@loaded = false
addRequestToLoad: (jqxhr, name, retryFunc, value=1) -> addRequestToLoad: (jqxhr, name, retryFunc, value=1) ->
@loadProgress.requests.push {request:jqxhr, value:value, name: name, retryFunc: retryFunc} @loadProgress.requests.push {request:jqxhr, value:value, name: name, retryFunc: retryFunc}
jqxhr.done @updateProgress jqxhr.done @updateProgress
jqxhr.fail @onRequestLoadFailed jqxhr.fail @onRequestLoadFailed
@loaded = false
addSomethingToLoad: (name, value=1) -> addSomethingToLoad: (name, value=1) ->
@loadProgress.somethings.push {loaded: false, name: name, value: value} @loadProgress.somethings.push {loaded: false, name: name, value: value}
@updateProgress() @updateProgress()
@loaded = false
somethingLoaded: (name) -> somethingLoaded: (name) ->
r = _.find @loadProgress.somethings, {name: name} r = _.find @loadProgress.somethings, {name: name}
@ -145,9 +148,9 @@ class CocoView extends Backbone.View
console.debug 'Loaded', r.name if arguments[0] and r = _.find @loadProgress.somethings, {name:arguments[0]} console.debug 'Loaded', r.name if arguments[0] and r = _.find @loadProgress.somethings, {name:arguments[0]}
denom = 0 denom = 0
denom += r.value for r in @loadProgress.resources denom += r.value for r in @loadProgress.resources when not r.resource.destroyed
denom += r.value for r in @loadProgress.requests denom += r.value for r in @loadProgress.requests
denom += r.value for r in @loadProgress.somethings denom += r.value for r in @loadProgress.somethings when not r.destroyed
num = @loadProgress.num num = @loadProgress.num
num += r.value for r in @loadProgress.resources when r.resource.loaded num += r.value for r in @loadProgress.resources when r.resource.loaded
num += r.value for r in @loadProgress.requests when r.request.status num += r.value for r in @loadProgress.requests when r.request.status

View file

@ -0,0 +1,47 @@
View = require 'views/kinds/ModalView'
template = require 'templates/modal/model'
module.exports = class ModelModal extends View
id: 'model-modal'
template: template
constructor: (options) ->
super options
@models = options.models
for model in @models when not model.loaded
@addResourceToLoad model, 'model'
model.fetch()
getRenderData: ->
c = super()
c.models = @models
c
afterRender: ->
super()
return if @loading()
for model in @models
data = $.extend true, {}, model.attributes
schema = $.extend true, {}, model.schema()
treemaOptions =
schema: schema
data: data
readOnly: true
modelTreema = @$el.find(".model-treema[data-model-id='#{model.id}']").treema treemaOptions
modelTreema?.build()
modelTreema?.open()
@openTastyTreemas modelTreema, model
openTastyTreemas: (modelTreema, model) ->
# To save on quick inspection, let's auto-open the properties we're most likely to want to see.
delicacies = ['code']
for dish in delicacies
child = modelTreema.childrenTreemas[dish]
child?.open()
if child and dish is 'code' and model.type() is 'LevelSession' and team = modelTreema.get('team')
desserts = {
humans: ['programmable-tharin', 'programmable-librarian']
ogres: ['programmable-brawler', 'programmable-shaman']
}[team]
for dessert in desserts
child.childrenTreemas[dessert]?.open()

View file

@ -18,7 +18,6 @@ module.exports = class SaveVersionModal extends ModalView
constructor: (options) -> constructor: (options) ->
super options super options
@model = options.model or options.level @model = options.model or options.level
new Patch() # hack to get the schema to load, delete this later
@isPatch = not @model.hasWriteAccess() @isPatch = not @model.hasWriteAccess()
getRenderData: -> getRenderData: ->

View file

@ -3,8 +3,10 @@ CocoClass = require 'lib/CocoClass'
Level = require 'models/Level' Level = require 'models/Level'
LevelSession = require 'models/LevelSession' LevelSession = require 'models/LevelSession'
CocoCollection = require 'models/CocoCollection' CocoCollection = require 'models/CocoCollection'
User = require 'models/User'
LeaderboardCollection = require 'collections/LeaderboardCollection' LeaderboardCollection = require 'collections/LeaderboardCollection'
{teamDataFromLevel} = require './utils' {teamDataFromLevel} = require './utils'
ModelModal = require 'views/modal/model_modal'
HIGHEST_SCORE = 1000000 HIGHEST_SCORE = 1000000
@ -23,6 +25,8 @@ module.exports = class LadderTabView extends CocoView
events: events:
'click .connect-facebook': 'onConnectFacebook' 'click .connect-facebook': 'onConnectFacebook'
'click .connect-google-plus': 'onConnectGPlus' 'click .connect-google-plus': 'onConnectGPlus'
'click .name-col-cell': 'onClickPlayerName'
'click .load-more-ladder-entries': 'onLoadMoreLadderEntries'
subscriptions: subscriptions:
'fbapi-loaded': 'checkFriends' 'fbapi-loaded': 'checkFriends'
@ -134,7 +138,8 @@ module.exports = class LadderTabView extends CocoView
for team in @teams for team in @teams
@leaderboards[team.id]?.destroy() @leaderboards[team.id]?.destroy()
teamSession = _.find @sessions.models, (session) -> session.get('team') is team.id teamSession = _.find @sessions.models, (session) -> session.get('team') is team.id
@leaderboards[team.id] = new LeaderboardData(@level, team.id, teamSession) @ladderLimit ?= parseInt @getQueryVariable('top_players', 20)
@leaderboards[team.id] = new LeaderboardData(@level, team.id, teamSession, @ladderLimit)
@addResourceToLoad @leaderboards[team.id], 'leaderboard', 3 @addResourceToLoad @leaderboards[team.id], 'leaderboard', 3
@ -245,17 +250,30 @@ module.exports = class LadderTabView extends CocoView
sessions.reverse() sessions.reverse()
sessions sessions
# Admin view of players' code
onClickPlayerName: (e) ->
return unless me.isAdmin()
row = $(e.target).parent()
player = new User _id: row.data 'player-id'
session = new LevelSession _id: row.data 'session-id'
@openModalView new ModelModal models: [session, player]
onLoadMoreLadderEntries: (e) ->
@ladderLimit ?= 100
@ladderLimit += 100
@refreshLadder()
class LeaderboardData extends CocoClass class LeaderboardData extends CocoClass
### ###
Consolidates what you need to load for a leaderboard into a single Backbone Model-like object. Consolidates what you need to load for a leaderboard into a single Backbone Model-like object.
### ###
constructor: (@level, @team, @session) -> constructor: (@level, @team, @session, @limit) ->
super() super()
@fetch() @fetch()
fetch: -> fetch: ->
@topPlayers = new LeaderboardCollection(@level, {order:-1, scoreOffset: HIGHEST_SCORE, team: @team, limit: 20}) @topPlayers = new LeaderboardCollection(@level, {order:-1, scoreOffset: HIGHEST_SCORE, team: @team, limit: @limit})
promises = [] promises = []
promises.push @topPlayers.fetch() promises.push @topPlayers.fetch()

View file

@ -71,7 +71,7 @@ module.exports = class LadderView extends RootView
return if @loading() return if @loading()
@insertSubView(@ladderTab = new LadderTabView({}, @level, @sessions)) @insertSubView(@ladderTab = new LadderTabView({}, @level, @sessions))
@insertSubView(@myMatchesTab = new MyMatchesTabView({}, @level, @sessions)) @insertSubView(@myMatchesTab = new MyMatchesTabView({}, @level, @sessions))
@refreshInterval = setInterval(@fetchSessionsAndRefreshViews.bind(@), 10 * 1000) @refreshInterval = setInterval(@fetchSessionsAndRefreshViews.bind(@), 20 * 1000)
hash = document.location.hash[1..] if document.location.hash hash = document.location.hash[1..] if document.location.hash
if hash and not (hash in ['my-matches', 'simulate', 'ladder']) if hash and not (hash in ['my-matches', 'simulate', 'ladder'])
@showPlayModal(hash) if @sessions.loaded @showPlayModal(hash) if @sessions.loaded

View file

@ -17,6 +17,7 @@ module.exports = class LevelLoadingView extends View
@$el.find('.to-remove').remove() @$el.find('.to-remove').remove()
onLevelLoaderProgressChanged: (e) -> onLevelLoaderProgressChanged: (e) ->
return if @destroyed
@progress = e.progress @progress = e.progress
@progress = 0.01 if @progress < 0.01 @progress = 0.01 if @progress < 0.01
@updateProgressBar() @updateProgressBar()