Work on the job profile view, initial work on the code modal.

This commit is contained in:
Scott Erickson 2014-07-17 16:30:56 -07:00
parent 51e63ddbc3
commit 45a8278e7e
12 changed files with 422 additions and 339 deletions

View file

@ -230,6 +230,7 @@ _.extend LevelSchema.properties,
title: 'Next Level',
description: 'Reference to the next level players will play after beating this one.'
}
employerDescription: { type:'string' }
scripts: c.array {title: 'Scripts', description: 'An array of scripts that trigger based on what the player does and affect things outside of the core level simulation.', 'default': []}, ScriptSchema
thangs: c.array {title: 'Thangs', description: 'An array of Thangs that make up the level.', 'default': []}, LevelThangSchema
systems: c.array {title: 'Systems', description: 'Levels are configured by changing the Systems attached to them.', uniqueItems: true, default: []}, LevelSystemSchema # TODO: uniqueness should be based on 'original', not whole thing

View file

@ -13,7 +13,7 @@ LevelSessionPlayerSchema = c.object
changes:
type: 'Number'
LevelSessionLevelSchema = c.object {required: ['original', 'majorVersion']},
LevelSessionLevelSchema = c.object {required: ['original', 'majorVersion'], links: [{rel: 'db', href: '/db/level/{(original)}/version/{(majorVersion)}'}]},
original: c.objectId({})
majorVersion:
type: 'integer'

View file

@ -0,0 +1,19 @@
.level-session-code-view
#level-icon
width: 100px
margin-right: 10px
display: inline-block
float: left
#level-meta-data
margin-left: 120px
#session-code
clear: both
h3
font-family: Arial
.code
height: 600px
border: 2px solid black

View file

@ -0,0 +1,13 @@
extends /templates/modal/modal_base
block modal-header-content
.modal-header
h3 Applicant Code
block modal-body-content
.modal-body
.level-session-code-view
block modal-footer
.modal-footer
button(data-dismiss="modal", data-i18n="modal.close").btn Close

View file

@ -181,13 +181,14 @@ block content
ul.sessions
each session in sessions
li
- var sessionLink = "/play/level/" + session.levelID + "?team=" + (session.team || 'humans') + (myProfile ? '' : "&session=" + session._id);
a(href=sessionLink)
span= session.levelName
if session.team
span #{session.team}
if session.codeLanguage != 'javascript'
span - #{{coffeescript: 'CoffeeScript', python: 'Python', lua: 'Lua', io: 'Io', clojure: 'Clojure'}[session.codeLanguage]}
span.session-link(data-session-id=session._id)= session.levelName
//- var sessionLink = "/play/level/" + session.levelID + "?team=" + (session.team || 'humans') + (myProfile ? '' : "&session=" + session._id);
//a(href=sessionLink)
// span= session.levelName
// if session.team
// span #{session.team}
//if session.codeLanguage != 'javascript'
// span - #{{coffeescript: 'CoffeeScript', python: 'Python', lua: 'Lua', io: 'Io', clojure: 'Clojure'}[session.codeLanguage]}
.middle-column.full-height-column
.sub-column

View file

@ -0,0 +1,13 @@
div#session-info
img(src='/file/'+levelIcon alt='levelIcon')#level-icon
div#level-meta-data
strong= levelName
p!= levelDescription
div#session-code
for spell in levelSpells
.panel.panel-success
.panel-heading
h3= spell.name
.panel-body
.code= spell.code

View file

@ -0,0 +1,19 @@
ModalView = require 'views/kinds/ModalView'
template = require 'templates/account/job_profile_code_modal'
LevelSessionCodeView = require 'views/common/LevelSessionCodeView'
console.log 'template', template
module.exports = class JobProfileCodeModal extends ModalView
id: 'job_profile_code_modal'
template: template
constructor: (options) ->
super(arguments...)
@session = options.session
afterRender: ->
super()
return unless @session.loaded
codeView = new LevelSessionCodeView({session:@session})
@insertSubView(codeView)

View file

@ -9,6 +9,7 @@ JobProfileView = require 'views/account/job_profile_view'
UserRemark = require 'models/UserRemark'
forms = require 'lib/forms'
ModelModal = require 'views/modal/model_modal'
JobProfileCodeModal = require './JobProfileCodeModal'
class LevelSessionsCollection extends CocoCollection
url: -> "/db/user/#{@userID}/level.sessions/employer"
@ -51,6 +52,7 @@ module.exports = class ProfileView extends RootView
'keyup .editable-profile .editable-array input': 'onEditArray'
'click .editable-profile a': 'onClickLinkWhileEditing'
'change #admin-contact': 'onAdminContactChanged'
'click .session-link': 'onSessionLinkPressed'
constructor: (options, @userID) ->
@userID ?= me.id
@ -586,3 +588,9 @@ module.exports = class ProfileView extends RootView
{name: t('account_profile.next_photo'), weight: 2, container: '#profile-photo-container', fn: modified 'photoURL'}
{name: t('account_profile.next_active'), weight: 1, fn: modified 'active'}
]
onSessionLinkPressed: (e) ->
sessionID = $(e.target).data('session-id')
session = _.find @sessions.models, (session) -> session.id is sessionID
modal = new JobProfileCodeModal({session:session})
@openModalView modal

View file

@ -0,0 +1,46 @@
CocoView = require 'views/kinds/CocoView'
template = require 'templates/common/level_session_code'
Level = require 'models/Level'
LevelSession = require 'models/LevelSession'
module.exports = class LevelSessionCodeView extends CocoView
className: 'level-session-code-view'
template: template
modalWidthPercent: 80
plain: true
constructor: (options) ->
super(options)
@session = options.session
@level = LevelSession.getReferencedModel(@session.get('level'), LevelSession.schema.properties.level)
@level.setProjection ['employerDescription', 'name', 'icon']
@supermodel.loadModel @level, 'level'
getRenderData: ->
c = super()
c.levelIcon = @level.get('icon')
c.levelName = @level.get('name')
c.levelDescription = marked(@level.get('employerDescription') or '')
c.levelSpells = @organizeCode()
c
afterRender: ->
super()
@$el.find('.code').each (index, codeEl) ->
editor = ace.edit codeEl
editor.setReadOnly true
aceSession = editor.getSession()
aceSession.setMode 'ace/mode/javascript'
organizeCode: ->
team = @session.get('team') or 'humans'
teamSpells = @session.get('teamSpells')[team] or []
filteredSpells = []
for spell in teamSpells
code = @session.getSourceFor(spell)
filteredSpells.push {
code: code
name: spell.split('/')[1]
}
filteredSpells

View file

@ -233,7 +233,7 @@ UserHandler = class UserHandler extends Handler
getLevelSessionsForEmployer: (req, res, userID) ->
return @sendUnauthorizedError(res) unless req.user._id+'' is userID or req.user.isAdmin() or ('employer' in req.user.get('permissions'))
query = creator: userID, levelID: {$in: ['gridmancer', 'greed', 'dungeon-arena', 'brawlwood', 'gold-rush']}
projection = 'levelName levelID team playtime codeLanguage submitted code totalScore'
projection = 'levelName levelID team playtime codeLanguage submitted code totalScore teamSpells level'
LevelSession.find(query).select(projection).exec (err, documents) =>
return @sendDatabaseError(res, err) if err
documents = (LevelSessionHandler.formatEntity(req, doc) for doc in documents)

View file

@ -0,0 +1,65 @@
LevelSessionCodeView = require 'views/common/LevelSessionCodeView'
LevelSession = require 'models/LevelSession'
levelSessionData = {
"_id": "5334901f0a0f9b286f57382c",
"level": {
"original": "533353722a61b7ca6832840c",
"majorVersion": 0
},
"team": "humans",
"code": {
"coin-generator-9000": {
"chooseAction": "var buildOrder = ['coin2', 'coin3', 'coin4'];\n//if (Math.random() < 0.25)\n// this.build(buildOrder[this.built.length % buildOrder.length]);\nif (Math.random() < 0.05)\n this.build('gem');\nelse if (Math.random() < 0.25)\n this.build(buildOrder[this.built.length % buildOrder.length])\nelse if (Math.random() < 0.5)\n this.build('coin');\n\n\n\nvar human = this.getThangByID(\"Tharin\");\nvar ogre = this.getThangByID(\"Mak Fod\");\n\n//this.say(human.gold);\n\n//this.say(\"Humans: \" + human.gold + \", \" + \"Ogres: \" + ogre.gold);\n\nif(ogre.gold >= 150) {\n this.say(\"Ogres win!\");\n this.setGoalState(\"goldOgres\", \"success\");\n}\n\nelse if(human.gold >= 150) {\n this.say(\"Humans win!\");\n this.setGoalState(\"goldHumans\", \"success\");\n}"
},
"programmable-coin": {
"chooseAction": "//this.say(\"Say, who's in charge around here?\"); // Should fill in some default source\n\n//var time = this.now();\n//if(Math.round(time) % 20 === 0) {\nif (typeof this.teleportOnce === 'undefined') {\n this.teleportRandom();\n this.teleportOnce = true;\n}\n//}"
},
"tharin": {
"chooseAction": "var t = this;\nvar e = t.getNearestEnemy();\nvar vec = new Vector(0, 0);\n\nfunction item_worth(item) {\n return item.bountyGold/Math.pow(item.distance(e) - t.distance(item), 1.5);\n}\n\nvar items = this.getItems();\nfor (var i = 0; i < items.length; i++) {\n var item = items[i];\n var direction = Vector.normalize(Vector.subtract(item.pos, this.pos));\n var weighted_dir = Vector.multiply(direction, 1000 * item_worth(item));\n vec = Vector.add(vec, weighted_dir);\n}\n\nvar action = \"move\";\nif (typeof this.used_terrify == \"undefined\") {\n var enemy = this.getNearestEnemy();\n \n if (enemy.gold >= 140 || this.distance(enemy) <= 15) {\n action = \"terrify\";\n }\n}\n\nif (action == \"move\") {\n var best_item = null;\n var best_item_value = 0;\n for (var i = 0; i < items.length; i++) {\n var item = items[i];\n var direction = Vector.subtract(item.pos, this.pos);\n \n var angle = Math.acos(vec.dot(direction) / (vec.magnitude() * direction.magnitude()))\n if (angle < Math.PI / 16 || angle > Math.PI * (31/16)) {\n if (item_worth(item) > best_item_value) {\n best_item_value = item_worth(item);\n best_item = item;\n }\n }\n }\n \n if (best_item_value > 0.05) {\n this.move(best_item.pos);\n } else {\n this.say(\"Move to \" + Vector.add(this.pos, vec).x + \" \" + Vector.add(this.pos, vec).y);\n this.move(Vector.add(this.pos, vec));\n }\n} else if (action == \"terrify\") {\n //this.terrify();\n this.used_terrify = true;\n}\n/*\n\n// This code runs once per frame. Choose where to move to grab gold!\n// First player to 150 gold wins.\n\n// This is an example of grabbing the 0th coin from the items array.\nvar items = this.getItems();\nif (items[0]) {\n this.move(items[0].pos);\n} else {\n this.moveXY(18, 36);\n}\n\n\n// You can surely pick a better coin using the methods below.\n// Click on a coin to see its API.\n*/\n"
},
"wizard-purple": {
"chooseAction": "//this.say(\"Say, who's in charge around here?\"); // Should fill in some default source\n\n//var time = this.now();\n\n//if(Math.round(time) % 20 == 0) {\n this.build('coin');\n// console.log(\"build coin\");\n//}"
}
},
"teamSpells": {
"common": [
"coin-generator-9000/chooseAction"
],
"humans": [
"tharin/chooseAction"
],
"ogres": [
"mak-fod/chooseAction"
]
},
"levelID": "gold-rush",
"levelName": "Gold Rush",
"totalScore": 39.23691444835561,
"submitted": true,
"submittedCodeLanguage": "javascript",
"playtime": 1158,
"codeLanguage": "javascript"
}
levelData = {
"_id": "53c71962587cd615bf404919",
"name": "Dungeon Arena",
"icon": "db/level/53173f76c269d400000543c2/11_dungeon.png",
"description": "This level is indescribably flarmy!",
"employerDescription": "A DotA-like level where players:\n* Take control of a hero with special abilities\n* Choose which sorts of troops to build.\n* Have limited control over their troops."
"version": {
"minor": 0,
"major": 0,
"isLatestMajor": true,
"isLatestMinor": true
}
}
module.exports = ->
session = new LevelSession(levelSessionData)
v = new LevelSessionCodeView({session:session})
request = jasmine.Ajax.requests.mostRecent()
request.response({status: 200, responseText: JSON.stringify(levelData)})
console.log 'okay should be fine'
v

File diff suppressed because one or more lines are too long