mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-25 16:47:58 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
c85c39fd92
17 changed files with 100 additions and 136 deletions
BIN
app/assets/images/pages/about/coco_comic.jpg
Normal file
BIN
app/assets/images/pages/about/coco_comic.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 9.5 KiB |
BIN
app/assets/images/pages/about/placeholder.png
Normal file
BIN
app/assets/images/pages/about/placeholder.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
|
@ -334,7 +334,7 @@ module.exports = class SpriteBoss extends CocoClass
|
|||
|
||||
onFlagUpdated: (e) ->
|
||||
return unless e.active
|
||||
pendingFlag = new FlagSprite @thangTypeFor('Flag'), @createSpriteOptions(thangID: 'Pending Flag ' + Math.random(), color: e.color, team: me.team, isCursor: false, pos: e.pos)
|
||||
pendingFlag = new FlagSprite @thangTypeFor('Flag'), @createSpriteOptions(thangID: 'Pending Flag ' + Math.random(), color: e.color, team: e.team, isCursor: false, pos: e.pos)
|
||||
@addSprite pendingFlag, pendingFlag.thang.id, @spriteLayers['Floating']
|
||||
@pendingFlags.push pendingFlag
|
||||
|
||||
|
|
|
@ -657,12 +657,16 @@
|
|||
why_paragraph_4: "If you're going to get addicted to some game, get addicted to this one and become one of the wizards of the tech age."
|
||||
why_ending: "And hey, it's free. "
|
||||
why_ending_url: "Start wizarding now!"
|
||||
george_description: "CEO, business guy, web designer, game designer, and champion of beginning programmers everywhere."
|
||||
scott_description: "Programmer extraordinaire, software architect, kitchen wizard, and master of finances. Scott is the reasonable one."
|
||||
nick_description: "Programming wizard, eccentric motivation mage, and upside-down experimenter. Nick can do anything and chooses to build CodeCombat."
|
||||
jeremy_description: "Customer support mage, usability tester, and community organizer; you've probably already spoken with Jeremy."
|
||||
michael_description: "Programmer, sys-admin, and undergrad technical wunderkind, Michael is the person keeping our servers online."
|
||||
matt_description: "Bicyclist, Software Engineer, reader of heroic fantasy, connoisseur of peanut butter, sipper of coffee."
|
||||
george_title: "CEO"
|
||||
george_description: "Businesser"
|
||||
scott_title: "Programmer"
|
||||
scott_description: "Reasonable One"
|
||||
nick_title: "Programmer"
|
||||
nick_description: "Motivation Guru"
|
||||
michael_title: "Programmer"
|
||||
michael_description: "Sys Admin"
|
||||
matt_title: "Programmer"
|
||||
matt_description: "Bicyclist"
|
||||
|
||||
legal:
|
||||
page_title: "Legal"
|
||||
|
|
|
@ -2,8 +2,7 @@ c = require './../schemas'
|
|||
|
||||
# TODO add these: http://docs.mongodb.org/manual/reference/operator/query/
|
||||
MongoQueryOperatorSchema =
|
||||
title: 'MongoDB Query operator'
|
||||
id: 'mongoQueryOperator'
|
||||
title: 'Query Operator'
|
||||
type: 'object'
|
||||
properties:
|
||||
'$gt': type: 'number'
|
||||
|
@ -13,26 +12,23 @@ MongoQueryOperatorSchema =
|
|||
'$lte': type: 'number'
|
||||
'$ne': type: ['number', 'string']
|
||||
'$nin': type: 'array'
|
||||
additionalProperties: true # TODO set to false when the schema's done
|
||||
'$exists': type: 'boolean'
|
||||
additionalProperties: false
|
||||
|
||||
MongoFindQuerySchema =
|
||||
title: 'MongoDB Query'
|
||||
id: 'mongoFindQuery'
|
||||
title: 'Query'
|
||||
type: 'object'
|
||||
patternProperties:
|
||||
#'^[-a-zA-Z0-9_]*$':
|
||||
'^[-a-zA-Z0-9\.]*$':
|
||||
oneOf: [
|
||||
#{$ref: '#/definitions/' + MongoQueryOperatorSchema.id},
|
||||
'^[-a-zA-Z0-9.]*$':
|
||||
anyOf: [
|
||||
{$ref: '#/definitions/mongoQueryOperator'},
|
||||
{type: 'string'}
|
||||
{type: 'object'}
|
||||
{type: 'boolean'}
|
||||
]
|
||||
additionalProperties: true # TODO make Treema accept new pattern matched keys
|
||||
additionalProperties: false
|
||||
definitions: {}
|
||||
|
||||
MongoFindQuerySchema.definitions[MongoQueryOperatorSchema.id] = MongoQueryOperatorSchema
|
||||
|
||||
AchievementSchema = c.object()
|
||||
c.extendNamedProperties AchievementSchema
|
||||
c.extendBasicProperties AchievementSchema, 'achievement'
|
||||
|
@ -48,7 +44,7 @@ AchievementSchema.default =
|
|||
_.extend AchievementSchema.properties,
|
||||
query:
|
||||
#type:'object'
|
||||
$ref: '#/definitions/' + MongoFindQuerySchema.id
|
||||
$ref: '#/definitions/mongoFindQuery'
|
||||
worth: c.float
|
||||
collection: {type: 'string'}
|
||||
description: c.shortString()
|
||||
|
@ -93,6 +89,7 @@ _.extend AchievementSchema, # Let's have these on the bottom
|
|||
additionalProperties: false
|
||||
|
||||
AchievementSchema.definitions = {}
|
||||
AchievementSchema.definitions[MongoFindQuerySchema.id] = MongoFindQuerySchema
|
||||
AchievementSchema.definitions['mongoQueryOperator'] = MongoQueryOperatorSchema
|
||||
AchievementSchema.definitions['mongoFindQuery'] = MongoFindQuerySchema
|
||||
|
||||
module.exports = AchievementSchema
|
||||
|
|
|
@ -148,10 +148,7 @@ _.extend LevelComponentSchema.properties,
|
|||
type: 'boolean'
|
||||
title: 'Official'
|
||||
description: 'Whether this is an official CodeCombat Component.'
|
||||
searchStrings: {
|
||||
type: 'array'
|
||||
items: { type: 'string' }
|
||||
}
|
||||
searchStrings: {type: 'string'}
|
||||
|
||||
c.extendBasicProperties LevelComponentSchema, 'level.component'
|
||||
c.extendSearchableProperties LevelComponentSchema
|
||||
|
|
|
@ -11,4 +11,4 @@ module.exports =
|
|||
'real-time-multiplayer:new-opponent-code': c.object {title: 'Multiplayer new opponent code', required: ['code', 'codeLanguage']},
|
||||
code: {type: 'object'}
|
||||
codeLanguage: {type: 'string'}
|
||||
|
||||
team: {type: 'string'}
|
||||
|
|
|
@ -180,5 +180,5 @@ module.exports = # /app/lib/surface
|
|||
|
||||
'surface:remove-selected-flag': c.object {}
|
||||
|
||||
'surface:remove-flag': c.object {required: 'color'},
|
||||
'surface:remove-flag': c.object {required: ['color']},
|
||||
color: {type: 'string'}
|
||||
|
|
|
@ -18,6 +18,13 @@
|
|||
&:hover
|
||||
background-color: rgba(200, 244, 255, 0.2)
|
||||
float: left
|
||||
width: 100px
|
||||
height: 100px
|
||||
margin-top: 22px
|
||||
width: 80px
|
||||
height: 80px
|
||||
margin: 0px 10px 22px 0px
|
||||
|
||||
.team_name
|
||||
margin-top: 0
|
||||
|
||||
.team_bio
|
||||
width: 150px
|
||||
float: left
|
|
@ -121,7 +121,7 @@
|
|||
background-position-x: -4 * $iconSize
|
||||
&.prop-label-icon-attackDamage
|
||||
background-position-x: -5 * $iconSize
|
||||
&.prop-label-icon-attackRange
|
||||
&.prop-label-icon-attackRange, &.prop-label-icon-attackNearbyEnemyRange
|
||||
background-position-x: -6 * $iconSize
|
||||
&.prop-label-icon-maxSpeed
|
||||
background-position-x: -7 * $iconSize
|
||||
|
|
|
@ -2,48 +2,17 @@ extends /templates/base
|
|||
|
||||
block content
|
||||
|
||||
img(src="/images/pages/about/coco_comic.jpg")
|
||||
|
||||
.row
|
||||
|
||||
.col-sm-6
|
||||
|
||||
h2(data-i18n="about.who_is_codecombat")
|
||||
| Who is CodeCombat?
|
||||
|
||||
p
|
||||
a(href="http://georgesaines.com/") George
|
||||
span ,
|
||||
a(href="http://scotterickson.info/") Scott
|
||||
span ,
|
||||
span(data-i18n="general.and") and
|
||||
span
|
||||
a(href="http://www.nickwinter.net") Nick
|
||||
span
|
||||
span(data-i18n="about.who_description_prefix")
|
||||
| together started CodeCombat in 2013. We also created
|
||||
a(href="http://www.skritter.com/") Skritter
|
||||
span
|
||||
span(data-i18n="about.who_description_suffix")
|
||||
| in 2008, growing it to the #1 web and iOS application
|
||||
| for learning to write Chinese and Japanese characters.
|
||||
|
||||
p(data-i18n="about.who_description_ending")
|
||||
| Now it's time to teach people to write code.
|
||||
|
||||
h2(data-i18n="about.why_codecombat")
|
||||
| Why CodeCombat?
|
||||
|
||||
p(data-i18n="about.why_paragraph_1")
|
||||
| When making Skritter, George didn't know how to program and was constantly
|
||||
| frustrated by his inability to implement his ideas. Afterwards,
|
||||
| he tried learning, but the lessons were too slow. His housemate,
|
||||
| wanting to reskill and stop teaching, tried Codecademy, but "got bored."
|
||||
| Each week another friend started Codecademy, then dropped off.
|
||||
| We realized it was the same problem we'd solved with Skritter:
|
||||
| people learning a skill via slow, intensive lessons when what they need is fast,
|
||||
| extensive practice. We know how to fix that.
|
||||
|
||||
p(data-i18n="about.why_paragraph_2")
|
||||
| Need to learn to code? You don't need lessons.
|
||||
| If you want to learn to program, you don't need lessons.
|
||||
| You need to write a lot of code and have a great time doing it.
|
||||
|
||||
p
|
||||
|
@ -69,11 +38,13 @@ block content
|
|||
| If you're going to get addicted to some game,
|
||||
| get addicted to this one and become one of the wizards of the tech age.
|
||||
|
||||
p.lead
|
||||
span(data-i18n="about.why_ending")
|
||||
| And hey, it's free.
|
||||
a(href="/", data-i18n="about.why_ending_url")
|
||||
| Start wizarding now!
|
||||
h2
|
||||
| Bloggers/Press
|
||||
|
||||
p
|
||||
| Want to write about us? Feel free to download and use all of the resources included in our
|
||||
a(href="https://s3.amazonaws.com/CodeCombatMisc/press_packet.zip") press packet.
|
||||
| All logos and images may be used without contacting us directly.
|
||||
|
||||
|
||||
ul.col-sm-6.team-column
|
||||
|
@ -82,86 +53,73 @@ block content
|
|||
|
||||
li.row
|
||||
|
||||
a(href="http://georgesaines.com")
|
||||
h2 Team
|
||||
|
||||
img(src="/images/pages/about/george_small.png").img-thumbnail
|
||||
|
||||
.col-sm-8
|
||||
.team_bio
|
||||
|
||||
h3
|
||||
h4.team_name
|
||||
a(href="http://georgesaines.com") George Saines
|
||||
|
||||
p(data-i18n="about.george_title")
|
||||
| CEO
|
||||
p(data-i18n="about.george_description")
|
||||
| CEO, business guy, web designer, game designer,
|
||||
| and champion of beginning programmers everywhere.
|
||||
|
||||
li.row
|
||||
| Businesser
|
||||
|
||||
a(href="http://scotterickson.info")
|
||||
img(src="/images/pages/about/scott_small.png").img-thumbnail
|
||||
|
||||
.col-sm-8
|
||||
.team_bio
|
||||
|
||||
h3
|
||||
h4.team_name
|
||||
a(href="http://scotterickson.info") Scott Erickson
|
||||
|
||||
p(data-i18n="about.scott_title")
|
||||
| Programmer
|
||||
p(data-i18n="about.scott_description")
|
||||
| Programmer extraordinaire, software architect,
|
||||
| kitchen wizard, and master of finances.
|
||||
| Scott is the reasonable one.
|
||||
| Reasonable one
|
||||
|
||||
li.row
|
||||
|
||||
a(href="http://www.nickwinter.net")
|
||||
img(src="/images/pages/about/nick_small.png").img-thumbnail
|
||||
|
||||
.col-sm-8
|
||||
.team_bio
|
||||
|
||||
h3
|
||||
h4.team_name
|
||||
a(href="http://www.nickwinter.net") Nick Winter
|
||||
|
||||
p(data-i18n="about.nick_title")
|
||||
| Programmer
|
||||
p(data-i18n="about.nick_description")
|
||||
| Programming wizard, eccentric motivation mage,
|
||||
| and upside-down experimenter.
|
||||
| Nick can do anything and chooses to build CodeCombat.
|
||||
|
||||
li.row
|
||||
| Motivation Guru
|
||||
|
||||
a(href="http://michaelschmatz.com")
|
||||
img(src="/images/pages/about/michael_small.png").img-thumbnail
|
||||
|
||||
.col-sm-8
|
||||
.team_bio
|
||||
|
||||
h3
|
||||
h4.team_name
|
||||
a(href="http://michaelschmatz.com/") Michael Schmatz
|
||||
|
||||
p(data-i18n="about.michael_title")
|
||||
| Programmer
|
||||
p(data-i18n="about.michael_description")
|
||||
| Programmer, sys-admin, and undergrad technical wunderkind,
|
||||
| Michael is the person keeping our servers online.
|
||||
| Sys Admin
|
||||
|
||||
li.row
|
||||
|
||||
img(src="/images/pages/about/jeremy_small.png").img-thumbnail
|
||||
img(src="/images/pages/about/placeholder.png").img-thumbnail
|
||||
|
||||
.col-sm-8
|
||||
.team_bio
|
||||
|
||||
h3 Jeremy Arns
|
||||
|
||||
p(data-i18n="about.jeremy_description")
|
||||
| Customer support mage, usability tester,
|
||||
| and community organizer; you've probably
|
||||
| already spoken with Jeremy.
|
||||
|
||||
li.row
|
||||
|
||||
img(src="/images/pages/contribute/archmage.png").img-thumbnail
|
||||
|
||||
.col-sm-8
|
||||
|
||||
h3
|
||||
h4.team_name
|
||||
a(href="http://www.mattlott.com/") Matt Lott
|
||||
|
||||
p(data-i18n="about.matt_title")
|
||||
| Programmer
|
||||
p(data-i18n="about.matt_description")
|
||||
| Bicyclist, Software Engineer, reader of heroic fantasy, connoisseur
|
||||
| of peanut butter, sipper of coffee.
|
||||
| Bicyclist
|
||||
|
||||
|
||||
|
|
|
@ -28,22 +28,13 @@ module.exports = class NewAchievementModal extends NewModelModal
|
|||
createQuery: ->
|
||||
checked = @$el.find('[name=queryOptions]:checked')
|
||||
checkedValues = ($(check).val() for check in checked)
|
||||
subQueries = []
|
||||
query = {}
|
||||
for id in checkedValues
|
||||
switch id
|
||||
when 'misc-level-completion'
|
||||
subQueries.push state: complete: true
|
||||
else # It's a goal
|
||||
q = state: goalStates: {}
|
||||
q.state.goalStates[id] = {}
|
||||
q.state.goalStates[id].status = 'success'
|
||||
subQueries.push q
|
||||
unless subQueries.length
|
||||
query = {}
|
||||
else if subQueries.length is 1
|
||||
query = subQueries[0]
|
||||
query['state.complete'] = true
|
||||
else
|
||||
query = $or: subQueries
|
||||
query["state.goalStates.#{id}.status"] = 'success'
|
||||
query['level.original'] = @level.get 'original'
|
||||
query
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@ template = require 'templates/play/level/level-flags-view'
|
|||
{me} = require 'lib/auth'
|
||||
RealTimeCollection = require 'collections/RealTimeCollection'
|
||||
|
||||
multiplayerFlagDelay = 0.5 # Long, static second delay for now; should be more than enough.
|
||||
|
||||
module.exports = class LevelFlagsView extends CocoView
|
||||
id: 'level-flags-view'
|
||||
template: template
|
||||
|
@ -54,7 +56,9 @@ module.exports = class LevelFlagsView extends CocoView
|
|||
onStageMouseDown: (e) ->
|
||||
return unless @flagColor and @realTime
|
||||
pos = x: e.worldPos.x, y: e.worldPos.y
|
||||
flag = player: me.id, team: me.team, color: @flagColor, pos: pos, time: @world.dt * @world.frames.length, active: true
|
||||
delay = if @realTimeFlags then multiplayerFlagDelay else 0
|
||||
now = @world.dt * @world.frames.length
|
||||
flag = player: me.id, team: me.team, color: @flagColor, pos: pos, time: now + delay, active: true
|
||||
@flags[@flagColor] = flag
|
||||
@flagHistory.push flag
|
||||
@realTimeFlags?.create flag
|
||||
|
@ -67,7 +71,9 @@ module.exports = class LevelFlagsView extends CocoView
|
|||
|
||||
onRemoveFlag: (e) ->
|
||||
delete @flags[e.color]
|
||||
flag = player: me.id, team: me.team, color: e.color, time: @world.dt * @world.frames.length, active: false
|
||||
delay = if @realTimeFlags then multiplayerFlagDelay else 0
|
||||
now = @world.dt * @world.frames.length
|
||||
flag = player: me.id, team: me.team, color: e.color, time: now + delay, active: false
|
||||
@flagHistory.push flag
|
||||
Backbone.Mediator.publish 'level:flag-updated', flag
|
||||
#console.log e.color, 'deleted at time', flag.time
|
||||
|
@ -79,6 +85,7 @@ module.exports = class LevelFlagsView extends CocoView
|
|||
onJoinedMultiplayerGame: (e) ->
|
||||
@realTimeFlags = new RealTimeCollection('multiplayer_level_sessions/' + e.session.id + '/flagHistory')
|
||||
@realTimeFlags.on 'add', @onRealTimeMultiplayerFlagAdded
|
||||
@realTimeFlags.on 'remove', @onRealTimeMultiplayerFlagRemoved
|
||||
|
||||
onLeftMultiplayerGame: (e) ->
|
||||
if @realTimeFlags
|
||||
|
@ -98,3 +105,5 @@ module.exports = class LevelFlagsView extends CocoView
|
|||
active: e.get('active')
|
||||
@flagHistory.push flag
|
||||
Backbone.Mediator.publish 'level:flag-updated', flag
|
||||
|
||||
onRealTimeMultiplayerFlagRemoved: (e) =>
|
||||
|
|
|
@ -265,7 +265,7 @@ module.exports = class LevelHUDView extends CocoView
|
|||
return null # included in the bar
|
||||
context =
|
||||
prop: prop
|
||||
hasIcon: prop in ['health', 'pos', 'target', 'collectedThangIDs', 'gold', 'bountyGold', 'visualRange', 'attackDamage', 'attackRange', 'maxSpeed']
|
||||
hasIcon: prop in ['health', 'pos', 'target', 'collectedThangIDs', 'gold', 'bountyGold', 'visualRange', 'attackDamage', 'attackRange', 'maxSpeed', 'attackNearbyEnemyRange']
|
||||
hasBar: prop in ['health']
|
||||
$(prop_template(context))
|
||||
|
||||
|
|
|
@ -619,6 +619,7 @@ module.exports = class PlayLevelView extends RootView
|
|||
myPlayer.set 'code', @session.get('code')
|
||||
myPlayer.set 'codeLanguage', @session.get('codeLanguage')
|
||||
myPlayer.set 'state', 'submitted'
|
||||
myPlayer.set 'team', me.team
|
||||
else
|
||||
console.error 'Did not find my player in onRealTimeMultiplayerCast'
|
||||
if opponentPlayer
|
||||
|
@ -636,7 +637,7 @@ module.exports = class PlayLevelView extends RootView
|
|||
|
||||
onOpponentSubmitted: (opponentPlayer, myPlayer) =>
|
||||
# Save opponent's code
|
||||
Backbone.Mediator.publish 'real-time-multiplayer:new-opponent-code', {codeLanguage: opponentPlayer.get('codeLanguage'), code: opponentPlayer.get('code')}
|
||||
Backbone.Mediator.publish 'real-time-multiplayer:new-opponent-code', {codeLanguage: opponentPlayer.get('codeLanguage'), code: opponentPlayer.get('code'), team: opponentPlayer.get('team')}
|
||||
# I'm ready to rumble
|
||||
myPlayer.set 'state', 'ready'
|
||||
if opponentPlayer.get('state') is 'ready'
|
||||
|
|
|
@ -164,11 +164,11 @@ module.exports = class Spell
|
|||
false
|
||||
|
||||
onNewOpponentCode: (e) =>
|
||||
return unless @spellKey
|
||||
return unless @spellKey and @canWrite e.team
|
||||
if e.codeLanguage and e.code
|
||||
spellkeyComponents = @spellKey.split '/'
|
||||
if e.code[spellkeyComponents[0]]?[spellkeyComponents[1]]
|
||||
@source = e.code[spellkeyComponents[0]][spellkeyComponents[1]]
|
||||
[thangSlug, methodSlug] = @spellKey.split '/'
|
||||
if opponentCode = e.code[thangSlug]?[methodSlug]
|
||||
@source = opponentCode
|
||||
@updateLanguageAether e.codeLanguage
|
||||
else
|
||||
console.error 'Spell onNewOpponentCode did not receive code', e
|
||||
|
|
Loading…
Reference in a new issue