This commit is contained in:
Scott Erickson 2014-01-05 16:03:06 -08:00
commit 9019368d1d
30 changed files with 154 additions and 253 deletions

View file

@ -1,8 +1,20 @@
CodeCombat
==========
CodeCombat is a multiplayer programming game for learning how to code. See the [Archmage developer wiki](https://github.com/codecombat/codecombat/wiki) for all information.
![](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/readme_00.png)
We just open-sourced everything on 2014-01-03 as a preview release for our [Archmages](http://codecombat.com/contribute#archmage) who have been waiting to contribute. We will announce it fully on Monday. Please poke around, add issues, work on issues, and have fun! We'd love to see as many contributors as possible this weekend, so no contribution is too small.
CodeCombat is a multiplayer programming game for learning how to code. **See the [Archmage developer wiki](https://github.com/codecombat/codecombat/wiki) for a dev setup guide, extensive documentation, and much more.**
It's both a startup and a community project, completely open source under the [MIT and Creative Commons licenses](http://codecombat.com/legal). It's the largest open source [CoffeeScript](http://coffeescript.org/) project by lines of code, and since it's a game (with [really cool tech](https://github.com/codecombat/codecombat/wiki/Third-party-software-and-services)), it's really fun to hack on. Join us in teaching the world to code! Your contribution will go on to show millions of players how cool programming can be.
### [Getting Started](https://github.com/codecombat/codecombat/wiki/Developer-environment)
We've made it easy to fork the project, run a simple script that'll install all the dependencies, and get a local copy of CodeCombat running right away on Mac, Linux, or Windows. See [the docs for details](https://github.com/codecombat/codecombat/wiki/Developer-environment).
### [Getting In Touch](https://github.com/codecombat/codecombat/wiki/Developer-organization)
Whether you're novice or pro, the CodeCombat team is ready to help you implement your ideas. Reach out on our forum, our issue tracker, or our developer chat room, or see the docs for [more on how to contribute](https://github.com/codecombat/codecombat/wiki/Developer-organization).
### [License](https://github.com/codecombat/codecombat/blob/master/LICENSE)
[MIT](https://github.com/codecombat/codecombat/blob/master/LICENSE) for the code, and [CC-BY](http://codecombat.com/legal) for the art and music. Please also [sign the CodeCombat contributor license agreement](http://codecombat.com/cla) so we can accept your pull requests. It is easy.

View file

@ -52,9 +52,10 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
'level-sprite-dialogue': 'onDialogue'
'level-sprite-clear-dialogue': 'onClearDialogue'
'level-set-letterbox': 'onSetLetterbox'
'surface:ticked': 'onSurfaceTicked'
constructor: (@thangType, options) ->
super()
super()
@options = _.extend(_.cloneDeep(@options), options)
@setThang @options.thang
console.error @toString(), "has no ThangType!" unless @thangType
@ -63,6 +64,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
@labels = {}
@actions = @thangType.getActions()
@buildFromSpriteSheet @buildSpriteSheet()
@ticker = 0
destroy: ->
super()
@ -112,6 +114,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
@playNextAction()
onActionEnd: (e) => @playNextAction()
onSurfaceTicked: -> @ticker += 1
playNextAction: ->
@playAction(@actionQueue.splice(0,1)[0]) if @actionQueue.length
@ -147,6 +150,8 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
updatePosition: ->
return unless @thang?.pos and @options.camera?
if @thang.bobHeight
@thang.pos.z = @thang.pos.z + (Math.sin @ticker / @thang.bobTime) * 0.1 * @thang.bobHeight
[p0, p1] = [@lastPos, @thang.pos]
return if p0 and p0.x is p1.x and p0.y is p1.y and p0.z is p1.z and not @options.camera.tweeningZoomTo
wop = x: p1.x, y: p1.y, z: if @thang.isLand then 0 else p1.z - @thang.depth / 2
@ -422,4 +427,4 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
name = AudioPlayer.nameForSoundReference sound
instance = createjs.Sound.play name, "none", delay, 0, 0, volume
#console.log @thang?.id, "played sound", name, "with delay", delay, "volume", volume, "and got sound instance", instance
instance
instance

View file

@ -21,8 +21,7 @@ module.exports = class WizardSprite extends IndieSprite
subscriptions:
'bus:player-states-changed': 'onPlayerStatesChanged'
'me:synced': 'onMeSynced'
'surface:sprite-selected': 'onSpriteSelected'
'surface:ticked': 'onSurfaceTicked'
'surface:sprite-selected': 'onSpriteSelected'
'echo-self-wizard-sprite': 'onEchoSelfWizardSprite'
'echo-all-wizard-sprites': 'onEchoAllWizardSprites'
@ -102,8 +101,7 @@ module.exports = class WizardSprite extends IndieSprite
onEchoSelfWizardSprite: (e) -> e.payload = @ if @isSelf
onEchoAllWizardSprites: (e) -> e.payload.push @
defaultPos: -> x: 35, y: 24, z: @thang.depth / 2 + @spriteZOffset
getZOffset: -> @thang.depth / 2 + @spriteZOffset + Math.sin @ticker / 20 # Cloud bobbing.
onSurfaceTicked: -> @ticker += 1
getZOffset: -> @thang.depth / 2 + @spriteZOffset + Math.sin @ticker / 20 # Cloud bobbing.
move: (pos, duration) -> @setTarget(pos, duration)
setTarget: (newTarget, duration) ->

View file

@ -72,7 +72,7 @@ module.exports = nativeDescription: "English", englishDescription: "English", tr
contact:
contact_us: "Contact CodeCombat"
welcome: "Good to hear from you! Use this form to send us email."
welcome: "Good to hear from you! Use this form to send us email. "
contribute_prefix: "If you're interested in contributing, check out our "
contribute_page: "contribute page"
contribute_suffix: "!"

View file

@ -1,13 +1,10 @@
#contribute-view
#intro
margin-right: 20%
#homepage_screenshot
margin: 20px 0px
.signature
text-align: right
a
cursor: pointer
@ -15,8 +12,8 @@
float: left
width: 150px
margin: 10px 10px 20px 20px
padding-top: 30px
padding-top: 65px
#contribute-nav
float: left
max-width: 20%
@ -27,14 +24,18 @@
li
float: none
width: 100%
#contribute-main
margin-left: 25%
padding: 40px
box-sizing: border-box
h3
padding-top: 30px
padding-top: 70px
.well
padding: 5px 5px 5px 30px
.saved-notification
display: none
float: right

View file

@ -82,7 +82,7 @@
hr
if me.get('anonymous')
p
h1
| Either
a(data-toggle="coco-modal", data-target="modal/signup", data-i18n="nav.sign_up") create an account
| or

View file

@ -40,8 +40,7 @@ block content
li Artisans - Sootn, Aftermath, mcdavid1991
li Scribes - Ryan Faidley
li Adventurers - Kieizroe, (...)
li Archmages - David Golds, Zach Martin
li Archmages - David Golds, Zach Martin, Tom Steinbrecher, Mischa Lewis-Norelle, Sébastien Moratinos
div#contribute-main
div#intro
@ -59,10 +58,12 @@ block content
| We can't and don't want to do that alone;
| what makes projects like GitHub, Stack Overflow and Linux great are the people who
| use them and build on them.
| To that end, we aim to provide as many ways as possible for you to take part and
| To that end,
a(href="https://github.com/codecombat/codecombat") CodeCombat is totally open source
| , and we aim to provide as many ways as possible for you to take part and
| make this project as much yours as ours.
p We hope you'll join our party!
p.signature - Nick, George and Scott
p.signature - Nick, George, Scott, Michael, and Jeremy
hr
if me.attributes.anonymous
@ -72,8 +73,6 @@ block content
a(data-toggle="coco-modal", data-target="modal/signup") create an account
| first .
h3 Changes are saved automatically when you toggle checkboxes.
#archmage
.class_image
img(src="/images/pages/contribute/archmage.png", alt="")
@ -85,13 +84,7 @@ block content
| and server administration to user facing design and interface building.
| There's a lot to do, and if you're an experienced programmer with a hankering
| to really dive into the nitty-gritty of CodeCombat, this class might be for you.
p Right now we have open-sourced two of our tools on the project:
a(href="https://github.com/codecombat/aether") Aether
| and
a(href="https://github.com/codecombat/treema") Treema
| . We are also open sourcing everything momentarily, so stay tuned for access to the main repo!
| We would love to have your help building out the best programming game ever.
| We would love to have your help building the best programming game ever.
h4 Class Attributes
ul
@ -107,17 +100,17 @@ block content
p
| Anyone can help out! Just check out our
a(title='GitHub', tabindex=-1) GitHub
a(title='GitHub', href="https://github.com/codecombat/codecombat", tabindex=-1) GitHub
| to get started, and check the box below to mark yourself as a brave Archmage.
| Want to chat about what to do or how to get more deeply involved?
a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact") Contact us
| , tell us a little about yourself, what you've done and what you'd
| be interested in working on. We'll go from there!
if !me.attributes.anonymous
label.checkbox(for="developer").well
input(type='checkbox', name="developer", id="developer")
| Get emails on new coding opportunities and announcements.
label.checkbox(for="developer").well
input(type='checkbox', name="developer", id="developer")
| Get emails on new coding opportunities and announcements.
.saved-notification ✓ Saved
#artisan
@ -152,10 +145,10 @@ block content
a(href="https://docs.google.com/document/d/117tMcL95T1KY8BDisr0iGi5Frb2ZvBJTC0us5hyQkJY/edit?usp=sharing") preliminary documentation
| for more info, and please comment on it so we can make the whole system better.
if !me.attributes.anonymous
label.checkbox(for="level_creator").well
input(type='checkbox', name="level_creator", id="level_creator")
| Get emails on level editor updates and announcements.
label.checkbox(for="level_creator").well
input(type='checkbox', name="level_creator", id="level_creator")
| Get emails on level editor updates and announcements.
.saved-notification ✓ Saved
#adventurer
@ -192,10 +185,10 @@ block content
a(href="https://plus.google.com/115285980638641924488/posts") Google+
| , so if you prefer to be notified those ways, sign up there!
if !me.attributes.anonymous
label.checkbox(for="tester").well
input(type='checkbox', name="tester", id="tester")
| Get emails when there are new levels to test.
label.checkbox(for="tester").well
input(type='checkbox', name="tester", id="tester")
| Get emails when there are new levels to test.
.saved-notification ✓ Saved
#scribe
@ -224,10 +217,10 @@ block content
| , tell us a little about yourself, your experience with programming and
| what sort of things you'd like to write about. We'll go from there!
if !me.attributes.anonymous
label.checkbox(for="article_editor").well
input(type='checkbox', name="article_editor", id="article_editor")
| Get emails about article writing announcements.
label.checkbox(for="article_editor").well
input(type='checkbox', name="article_editor", id="article_editor")
| Get emails about article writing announcements.
.saved-notification ✓ Saved
@ -257,10 +250,10 @@ block content
| , so check it out and add things for your language. Also, check this box below to
| keep up-to-date on new internationalization developments!
if !me.attributes.anonymous
label.checkbox(for="translator").well
input(type='checkbox', name="translator", id="translator")
| Get emails about i18n developments and levels to translate.
label.checkbox(for="translator").well
input(type='checkbox', name="translator", id="translator")
| Get emails about i18n developments and levels to translate.
.saved-notification ✓ Saved
#ambassador
@ -293,10 +286,10 @@ block content
| solving levels can summon higher level wizards to help them.
| This will be a great way for ambassadors to do their thing. We'll keep you posted!
if !me.attributes.anonymous
label.checkbox(for="support").well
input(type='checkbox', name="support", id="support")
| Get emails on support updates and multiplayer developments.
label.checkbox(for="support").well
input(type='checkbox', name="support", id="support")
| Get emails on support updates and multiplayer developments.
.saved-notification ✓ Saved
#counselor

View file

@ -77,13 +77,13 @@ module.exports = class SettingsView extends View
getSubscriptions: ->
inputs = $('#email-pane input[type="checkbox"]', @$el)
inputs = ($(i) for i in inputs)
subs = (i.attr('name') for i in inputs when i.attr('checked'))
subs = (i.attr('name') for i in inputs when i.prop('checked'))
subs = (s.replace('email_', '') for s in subs)
subs
toggleEmailSubscriptions: =>
subs = @getSubscriptions()
$('#email-pane input[type="checkbox"]', @$el).attr('checked', not Boolean(subs.length))
$('#email-pane input[type="checkbox"]', @$el).prop('checked', not Boolean(subs.length))
@save()
save: =>

View file

@ -5,17 +5,17 @@ template = require 'templates/cla'
module.exports = class CLAView extends View
id: "cla-view"
template: template
events:
'click #agreement-button': 'onAgree'
getRenderData: ->
c = super()
c.signedOn = moment(me.get('signedCLA')).format('LLLL') if me.get('signedCLA')
c
onAgree: ->
@$el.find('#agreement-button').attr('disabled', true).text('Saving')
@$el.find('#agreement-button').prop('disabled', true).text('Saving')
$.ajax({
url: "/db/user/me/agreeToCLA"
data: { 'githubUsername': @$el.find('#github-username').val() }
@ -23,9 +23,9 @@ module.exports = class CLAView extends View
success: @onAgreeSucceeded
error: @onAgreeFailed
})
onAgreeSucceeded: =>
@$el.find('#agreement-button').text('Success')
onAgreeFailed: =>
@$el.find('#agreement-button').text('Failed')
@$el.find('#agreement-button').text('Failed')

View file

@ -1,6 +1,7 @@
View = require 'views/kinds/RootView'
template = require 'templates/contribute'
{me} = require('lib/auth')
{me} = require 'lib/auth'
SignupModalView = require 'views/modal/signup_modal'
module.exports = class ContributeView extends View
id: "contribute-view"
@ -15,17 +16,20 @@ module.exports = class ContributeView extends View
_.forEach checkboxes, (el) ->
el = $(el)
if el.attr('name') in me.get('emailSubscriptions')
el.attr('checked', true)
el.prop('checked', true)
onCheckboxChanged: (e) ->
el = $(e.target)
checked = el.attr('checked')
checked = el.prop('checked')
subscription = el.attr('name')
subscriptions = me.get('emailSubscriptions')
subscriptions = me.get('emailSubscriptions') ? []
if checked and not (subscription in subscriptions)
subscriptions.push(subscription)
if me.get 'anonymous'
@openModalView new SignupModalView()
if not checked
subscriptions = _.without subscriptions, subscription
el.parent().find('.saved-notification').finish().show('fast').delay(3000).fadeOut(2000)
me.set('emailSubscriptions', subscriptions)
me.save()

View file

@ -27,10 +27,10 @@ module.exports = class ThangTypeEditView extends View
'click #upload-button': -> @$el.find('input#real-upload-button').click()
'change #real-upload-button': 'animationFileChosen'
'change #animations-select': 'showAnimation'
subscriptions:
'save-new-version': 'saveNewThangType'
# init / render
constructor: (options, @thangTypeID) ->
@ -160,7 +160,7 @@ module.exports = class ThangTypeEditView extends View
@file = e.target.files[0]
return unless @file
return unless @file.type is 'text/javascript'
@$el.find('#upload-button').val('disabled', true)
@$el.find('#upload-button').prop('disabled', true)
@reader = new FileReader()
@reader.onload = @onFileLoad
@reader.readAsText(@file)
@ -205,7 +205,7 @@ module.exports = class ThangTypeEditView extends View
movieClip.regX = -reg.x
movieClip.regY = -reg.y
@showDisplayObject(movieClip)
getSpriteOptions: -> { resolutionFactor: @resolution, thang: @mockThang}
showSprite: (actionName) ->
@ -215,14 +215,14 @@ module.exports = class ThangTypeEditView extends View
@currentSprite?.destroy()
@currentSprite = sprite
@showDisplayObject(sprite.displayObject)
updatePortrait: ->
options = @getSpriteOptions()
portrait = @thangType.getPortrait(options)
return unless portrait
portrait?.attr('id', 'portrait').addClass('img-polaroid')
$('#portrait').replaceWith(portrait)
showDisplayObject: (displayObject) ->
@clearDisplayObject()
displayObject.x = CENTER.x

View file

@ -57,7 +57,7 @@ module.exports = class CocoView extends Backbone.View
@hidden = false
@listenToShortcuts()
view.didReappear() for id, view of @subviews
# View Rendering
render: =>
@ -86,7 +86,7 @@ module.exports = class CocoView extends Backbone.View
# Modals
toggleModal: (e) ->
if $(event.currentTarget).prop('target') is '_blank'
if $(e.currentTarget).prop('target') is '_blank'
return true
# special handler for opening modals that are dynamically loaded, rather than static in the page. It works (or should work) like Bootstrap's modals, except use coco-modal for the data-toggle value.
elem = $(e.target)
@ -133,7 +133,7 @@ module.exports = class CocoView extends Backbone.View
visibleModal.$el.addClass('hide')
waitingModal = null
@modalClosed()
# Loading RootViews
showLoading: ($el=@$el) ->
@ -148,7 +148,7 @@ module.exports = class CocoView extends Backbone.View
@_lastLoading.find('.loading-screen').remove()
@_lastLoading.find('>').removeClass('hide')
@_lastLoading = null
# Loading ModalViews
enableModalInProgress: (modal) ->
@ -194,7 +194,7 @@ module.exports = class CocoView extends Backbone.View
return (tag is 'textarea' or (tag is 'input' and type in textInputTypes) or el.contentEditable in ["", "true"]) and not (el.readOnly or el.disabled)
# Subviews
insertSubView: (view) ->
@subviews[view.id].destroy() if view.id of @subviews
@$el.find('#'+view.id).after(view.el).remove()

View file

@ -16,7 +16,7 @@ module.exports = class RootView extends CocoView
events:
"click #logout-button": "logoutAccount"
'change .language-dropdown': 'showDiplomatSuggestionModal'
shortcuts:
'backspace, delete': 'preventBackspace'
# 'backspace': 'preventBackspace'
@ -56,7 +56,7 @@ module.exports = class RootView extends CocoView
code2 isnt code and code2.split('-')[0] is code)
for code, localeInfo of locale when not (code in genericCodes) or code is preferred
$select.append(
$("<option></option>").attr("value", code).text(localeInfo.nativeDescription))
$("<option></option>").val(code).text(localeInfo.nativeDescription))
$select.val(preferred).fancySelect()
showDiplomatSuggestionModal: ->

View file

@ -14,6 +14,6 @@ module.exports = class DiplomatSuggestionView extends View
currentSubscriptions = me.get("emailSubscriptions")
me.set("emailSubscriptions", currentSubscriptions.concat ["translator"]) if "translator" not in currentSubscriptions
me.save()
$("#email_translator").attr("checked", 1)
$("#email_translator").prop("checked", 1)
@hide()
return

View file

@ -37,17 +37,20 @@ module.exports = class SignupModalView extends View
@enableModalInProgress(modal) # TODO: part of forms
checkAge: (e) ->
$("#signup-button", @$el).attr 'disabled', not $(e.target).attr('checked')
$("#signup-button", @$el).prop 'disabled', not $(e.target).prop('checked')
createAccount: (e) =>
forms.clearFormAlerts(@$el)
userObject = forms.formToObject @$el
delete userObject.subscribe
delete userObject["confirm-age"]
for key, val of me.attributes when key in ["preferredLanguage", "testGroupNumber", "dateCreated", "wizardColor1", "name", "music", "volume"]
for key, val of me.attributes when key in ["preferredLanguage", "testGroupNumber", "dateCreated", "wizardColor1", "name", "music", "volume", "emailSubscriptions"]
userObject[key] ?= val
subscribe = @$el.find('#signup-subscribe').attr('checked')
userObject.emailSubscriptions = if subscribe then ['announcement'] else []
subscribe = @$el.find('#signup-subscribe').prop('checked')
if subscribe
(userObject.emailSubscriptions ?= []).push 'announcement'
else
userObject.emailSubscriptions = _.without (userObject.emailSubscriptions ? []), 'announcement'
res = tv4.validateMultiple userObject, User.schema.attributes
return forms.applyErrorsToForm(@$el, res.errors) unless res.valid
window.tracker?.trackEvent 'Finished Signup'

View file

@ -8,7 +8,7 @@ module.exports = class MultiplayerModal extends View
events:
'click textarea': 'onClickLink'
'change #multiplayer': 'updateLinkSection'
constructor: (options) ->
super(options)
@session = options.session
@ -21,19 +21,20 @@ module.exports = class MultiplayerModal extends View
@session.id)
c.multiplayer = @session.get('multiplayer')
c
afterRender: ->
super()
@updateLinkSection()
onClickLink: (e) =>
e.target.select()
updateLinkSection: =>
multiplayer = @$el.find('#multiplayer').attr('checked')
multiplayer = @$el.find('#multiplayer').prop('checked')
la = @$el.find('#link-area')
if multiplayer then la.show() else la.hide()
true
onHidden: ->
multiplayer = Boolean(@$el.find('#multiplayer').attr('checked'))
@session.set('multiplayer', multiplayer)
multiplayer = Boolean(@$el.find('#multiplayer').prop('checked'))
@session.set('multiplayer', multiplayer)

View file

@ -73,7 +73,7 @@ module.exports = class CastButtonView extends View
else
s = $.i18n.t("play_level.tome_cast_button_cast", defaultValue: "Spell Cast")
@castButton.text s
@castButton.attr 'disabled', not castable
@castButton.prop 'disabled', not castable
setAutocastDelay: (delay) ->
#console.log "Set autocast delay to", delay

View file

@ -95,4 +95,4 @@ module.exports = class SpellListEntryView extends View
disabled = not enabled
# Should refactor the disabling list so we can target the spell list separately?
# Should not call it 'editor' any more?
@$el.toggleClass('disabled', disabled).find('*').attr('disabled', disabled)
@$el.toggleClass('disabled', disabled).find('*').prop('disabled', disabled)

View file

@ -53,6 +53,8 @@ module.exports = class SpellView extends View
@aceSession.setMode 'ace/mode/javascript'
@aceSession.setWrapLimitRange null
@aceSession.setUseWrapMode true
@aceSession.setNewLineMode "unix"
@aceSession.setUseSoftTabs true
@ace.setTheme 'ace/theme/textmate'
@ace.setDisplayIndentGuides false
@ace.setShowPrintMargin false
@ -79,7 +81,7 @@ module.exports = class SpellView extends View
name: 'end-all-scripts'
bindKey: {win: 'Escape', mac: 'Escape'}
exec: -> Backbone.Mediator.publish 'level:escape-pressed'
# TODO: These don't work on, for example, Danish keyboards. Figure out a more universal solution.
# @ace.commands.addCommand
# name: 'toggle-grid'

View file

@ -353,7 +353,7 @@ module.exports = class PlayLevelView extends View
# Need to set this team stuff before the Tome loads... let's think about this with Scott.
#@setTeam @world.teamForPlayer(@bus.countPlayers()) unless me.team
#$('#multiplayer-team-selection').toggle(@world.playableTeams.length > 1)
# .find('input').attr('checked', -> $(@).val() is me.team)
# .find('input').prop('checked', -> $(@).val() is me.team)
# .bind('change', @setTeam)
onSessionWillSave: (e) ->

View file

@ -1,7 +1,11 @@
#!/bin/bash
# full script path
_scriptDir="$(cd "$(dirname "$0")" && pwd -P)"
sleep 5
cd ~/Desktop/coco
cd $_scriptDir
cd ../
until node_modules/karma/bin/karma start; do
echo "Karma crashed with exit code $?. Respawning.." >&2
sleep 1

View file

@ -1,5 +1,8 @@
#!/bin/bash
#sleep 5
cd ~/Desktop/coco
# full script path
_scriptDir="$(cd "$(dirname "$0")" && pwd -P)"
cd $_scriptDir
cd ../
node_modules/jasmine-node/bin/jasmine-node test/server/ --coffee --autotest --captureExceptions

View file

@ -1,4 +1,8 @@
#!/bin/bash
cd ~/Desktop/coco
# full script path
_scriptDir="$(cd "$(dirname "$0")" && pwd -P)"
cd $_scriptDir
cd ../
node_modules/.bin/nodemon . --ext ".coffee|.js" --watch server --watch server.coffee --unittest

View file

@ -1,12 +0,0 @@
__author__ = u'schmatz'
from subprocess import call
import os
import sys
#TODO: Upgrade this so it works on windows
#These scripts will be placed in coco/bin
current_directory = os.path.dirname(os.path.realpath(sys.argv[0]))
coco_path = os.getenv("COCO_DIR",os.path.join(current_directory,os.pardir))
nodemon_path = coco_path + os.sep + "node_modules" + os.sep + ".bin" + os.sep + "nodemon"
call(nodemon_path + " . --ext \".coffee|.js\" --watch server --watch app.js --watch server_config.js",shell=True,cwd=coco_path)

View file

@ -1,16 +0,0 @@
__author__ = u'schmatz'
from subprocess import call
import subprocess
import os
import time
import sys
#TODO: Upgrade this so it works on windows
#These scripts will be placed in coco/bin
current_directory = os.path.dirname(os.path.realpath(sys.argv[0]))
coco_path = os.getenv("COCO_DIR",os.path.join(current_directory,os.pardir))
brunch_path = coco_path + os.sep + "node_modules" + os.sep + ".bin" + os.sep + "brunch"
subprocess.Popen("ulimit -n 10000",shell=True)
while True:
call(brunch_path + " w --config " + coco_path + os.sep + "brunch.coffee",shell=True,cwd=coco_path)
print("Brunch crashed. Press control+C within 1 second to quit.")
time.sleep(1)

View file

@ -1,90 +0,0 @@
__author__ = u'schmatz'
from subprocess import call
import os
import sys
import subprocess
#copied straight from the python 3 standard library
def which(cmd, mode=os.F_OK | os.X_OK, path=None):
"""Given a command, mode, and a PATH string, return the path which
conforms to the given mode on the PATH, or None if there is no such
file.
`mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
of os.environ.get("PATH"), or can be overridden with a custom search
path.
"""
# Check that a given file can be accessed with the correct mode.
# Additionally check that `file` is not a directory, as on Windows
# directories pass the os.access check.
def _access_check(fn, mode):
return (os.path.exists(fn) and os.access(fn, mode)
and not os.path.isdir(fn))
# If we're given a path with a directory part, look it up directly rather
# than referring to PATH directories. This includes checking relative to the
# current directory, e.g. ./script
if os.path.dirname(cmd):
if _access_check(cmd, mode):
return cmd
return None
if path is None:
path = os.environ.get("PATH", os.defpath)
if not path:
return None
path = path.split(os.pathsep)
if sys.platform == "win32":
# The current directory takes precedence on Windows.
if not os.curdir in path:
path.insert(0, os.curdir)
# PATHEXT is necessary to check on Windows.
pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
# See if the given file matches any of the expected path extensions.
# This will allow us to short circuit when given "python.exe".
# If it does match, only test that one, otherwise we have to try
# others.
if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
files = [cmd]
else:
files = [cmd + ext for ext in pathext]
else:
# On other platforms you don't have things like PATHEXT to tell you
# what file suffixes are executable, so just pass on cmd as-is.
files = [cmd]
seen = set()
for dir in path:
normdir = os.path.normcase(dir)
if not normdir in seen:
seen.add(normdir)
for thefile in files:
name = os.path.join(dir, thefile)
if _access_check(name, mode):
return name
return None
#TODO: Upgrade this so it works on windows
#These scripts will be placed in coco/bin
current_directory = os.path.dirname(os.path.realpath(sys.argv[0]))
if which("mongod") and "v2.5.4" in subprocess.check_output("mongod --version",shell=True):
mongo_executable = "mongod"
else:
mongo_executable = None
print("Mongod 2.5.4 wasn't found. Searching in bin directory...")
mongo_directory = current_directory + os.sep + u"mongo"
if not mongo_executable:
mongo_executable = os.environ.get("COCO_MONGOD_PATH",mongo_directory + os.sep + u"mongod")
if not os.path.exists(mongo_executable):
raise FileNotFoundError("Mongo executable not found.")
print("Using mongo executable: " + str(mongo_executable))
mongo_db_path = os.path.abspath(os.path.join(current_directory,os.pardir)) + os.sep + u"mongo"
if not os.path.exists(mongo_db_path):
os.mkdir(mongo_db_path)
mongo_arguments = [mongo_executable + u" --setParameter textSearchEnabled=true --dbpath=" + mongo_db_path]
call(mongo_arguments,shell=True)

View file

@ -12,7 +12,6 @@ class DirectoryController(object):
@property
def root_install_directory(self):
#return self.root_dir + os.sep + u"codecombat"
return self.root_dir + os.sep + "coco" + os.sep + "bin"
@property
def tmp_directory(self):
@ -31,20 +30,19 @@ class DirectoryController(object):
os.mkdir(full_path)
def create_base_directories(self):
#first create the directory for the development environment to be installed in
shutil.rmtree(self.root_dir + os.sep + "coco" + os.sep + "node_modules",ignore_errors=True) #just in case
try:
#os.mkdir(self.root_install_directory)
#then the tmp directory for file downloads and the like
os.mkdir(self.tmp_directory)
#then the bin directory for binaries(also includes binaries for dependencies?
#os.mkdir(self.bin_directory)
if os.path.exists(self.tmp_directory):
self.remove_directories()
os.mkdir(self.tmp_directory)
except:
#cleanup whatever we created
#self.remove_directories()
raise errors.CoCoError(u"There was an error creating the directory structure, do you have correct permissions? Please remove all and start over.")
raise errors.CoCoError(u"There was an error creating the directory structure, do you have correct permissions? Please remove all and start over.")
def remove_directories(self):
print u"Removed directories created!"
shutil.rmtree(self.bin_directory + os.sep + "node",ignore_errors=True)
shutil.rmtree(self.bin_directory + os.sep + "mongo",ignore_errors=True)
def remove_tmp_directory(self):
shutil.rmtree(self.tmp_directory)
#shutil.rmtree(self.root_install_directory)

View file

@ -10,17 +10,19 @@ import shutil
import os
import glob
import subprocess
def print_computer_information(os_name,address_width):
print(os_name + " detected, architecture: " + str(address_width) + " bit")
def constructSetup():
config = configuration.Configuration()
address_width = config.system.get_virtual_memory_address_width()
if config.system.operating_system == u"mac":
print("Mac detected, architecture: " + str(config.system.get_virtual_memory_address_width()) + " bit")
print_computer_information("Mac",address_width)
return MacSetup(config)
elif config.system.operating_system == u"win":
print("Windows detected, architecture: " + str(config.system.get_virtual_memory_address_width())+ " bit")
print_computer_information("Windows",address_width)
raise NotImplementedError("Windows is not supported at this time.")
#return WinSetup(config)
elif config.system.operating_system == u"linux":
print("Linux detected, architecture: " + str(config.system.get_virtual_memory_address_width())+ " bit")
print_computer_information("Linux",address_width)
return LinuxSetup(config)
class SetupFactory(object):
@ -49,13 +51,6 @@ class SetupFactory(object):
print ("Doing initial bower install...")
bower_path = self.config.directory.root_dir + os.sep + "coco" + os.sep + "node_modules" + os.sep + ".bin" + os.sep + "bower"
subprocess.call(bower_path + " --allow-root install",shell=True,cwd=self.config.directory.root_dir + os.sep + "coco")
print("Copying bin scripts...")
script_location =self.config.directory.root_dir + os.sep + "coco" + os.sep + "scripts" + os.sep + "devSetup" + os.sep + "bin"
#print("Script location: " + script_location)
#print("Destination: "+ self.config.directory.root_install_directory)
#for filename in glob.glob(os.path.join(script_location, '*.*')):
# shutil.copy(filename, self.config.directory.root_install_directory)
print("Removing temporary directories")
self.config.directory.remove_directories()
print("Changing permissions of files...")
@ -67,12 +62,8 @@ class SetupFactory(object):
print("2. ./coco-brunch")
print("3. ./coco-dev-server")
print("Once brunch is done, visit http://localhost:3000!")
#print self.mongo.bashrc_string()
#print self.node.bashrc_string()
#print "COCO_DIR="+ self.config.directory.root_dir + os.sep + "coco"
def cleanup(self):
self.config.directory.remove_directories()
self.config.directory.remove_tmp_directory()
class MacSetup(SetupFactory):
def setup(self):

View file

@ -12,7 +12,7 @@ class MongoDB(Dependency):
super(self.__class__, self).__init__(configuration)
operating_system = configuration.system.operating_system
self.config.directory.create_directory_in_tmp(u"mongo")
#self.config.directory.create_directory_in_bin("mongo")
if operating_system == u"mac":
self.downloader = MacMongoDBDownloader(self)
elif operating_system == u"win":

View file

@ -29,7 +29,7 @@ class SystemConfiguration(object):
if is64Bit:
return 64
else:
if self.operating_system != u"linux" or self.operating_system !=u"windows":
if self.operating_system == u"mac":
raise NotSupportedError(u"Your processor is determined to have a maxSize of" + sys.maxsize +
u",\n which doesn't correspond with a 64-bit architecture.")
return 32