diff --git a/app/lib/simulator/Simulator.coffee b/app/lib/simulator/Simulator.coffee index 96e730b78..f38fd23b2 100644 --- a/app/lib/simulator/Simulator.coffee +++ b/app/lib/simulator/Simulator.coffee @@ -32,7 +32,7 @@ module.exports = class Simulator extends CocoClass @simulateAnotherTaskAfterDelay() handleNoGamesResponse: -> - @trigger 'statusUpdate', 'There were no games to simulate--nice. Retrying in 10 seconds.' + @trigger 'statusUpdate', 'There were no games to simulate--all simulations are done or in process. Retrying in 10 seconds.' @simulateAnotherTaskAfterDelay() simulateAnotherTaskAfterDelay: => @@ -102,7 +102,7 @@ module.exports = class Simulator extends CocoClass sendResultsBackToServer: (results) => @trigger 'statusUpdate', 'Simulation completed, sending results back to server!' console.log "Sending result back to server!" - + $.ajax url: "/queue/scoring" data: results @@ -257,7 +257,7 @@ class SimulationTask @spellKeyToTeamMap = {} getLevelName: -> - levelName = @rawData.sessions?[0]?.levelID + levelName = @rawData.sessions?[0]?.levelID return levelName if levelName? @throwMalformedTaskError "The level name couldn't be deduced from the task." @@ -279,9 +279,9 @@ class SimulationTask getReceiptHandle: -> @rawData.receiptHandle getSessions: -> @rawData.sessions - + getSpellKeyToTeamMap: -> @spellKeyToTeamMap - + getPlayerTeams: -> _.pluck @rawData.sessions, 'team' generateSpellKeyToSourceMap: -> @@ -303,7 +303,7 @@ class SimulationTask fullSpellName = [thangName,spellName].join '/' if _.contains(teamSpells, fullSpellName) teamCode[fullSpellName]=spell - + _.merge spellKeyToSourceMap, teamCode spellKeyToSourceMap diff --git a/app/locale/fr.coffee b/app/locale/fr.coffee index c8a756cb4..351ba7122 100644 --- a/app/locale/fr.coffee +++ b/app/locale/fr.coffee @@ -3,29 +3,29 @@ module.exports = nativeDescription: "français", englishDescription: "French", t loading: "Chargement..." saving: "Sauvegarde..." sending: "Envoi..." -# send: "Send" + send: "Envoyer" cancel: "Annuler" save: "Sauvegarder" -# publish: "Publish" -# create: "Create" + publish: "Publier" + create: "Creer" delay_1_sec: "1 seconde" delay_3_sec: "3 secondes" delay_5_sec: "5 secondes" manual: "Manuel" fork: "Fork" play: "Jouer" -# retry: "Retry" -# watch: "Watch" + retry: "Reessayer" + watch: "Regarder" # unwatch: "Unwatch" # submit_patch: "Submit Patch" -# units: -# second: "second" -# seconds: "seconds" -# minute: "minute" -# minutes: "minutes" -# hour: "hour" -# hours: "hours" + units: + second: "seconde" + seconds: "secondes" + minute: "minute" + minutes: "minutes" + hour: "heure" + hours: "heures" modal: close: "Fermer" @@ -39,7 +39,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t editor: "Éditeur" blog: "Blog" forum: "Forum" -# account: "Account" + account: "Compte" admin: "Admin" home: "Accueil" contribute: "Contribuer" @@ -60,7 +60,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t login: sign_up: "Créer un compte" log_in: "Connexion" -# logging_in: "Logging In" + logging_in: "Connecter" log_out: "Déconnexion" recover: "récupérer son compte" @@ -77,7 +77,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t creating: "Création du compte en cours..." sign_up: "S'abonner" log_in: "se connecter avec votre mot de passe" -# social_signup: "Or, you can sign up through Facebook or G+:" + social_signup: "Ou, vous pouvez vous identifier avec Facecook ou G+:" home: slogan: "Apprenez à coder en JavaScript tout en jouant" @@ -133,12 +133,12 @@ module.exports = nativeDescription: "français", englishDescription: "French", t title: "Paramètres du Magicien" customize_avatar: "Personnaliser votre avatar" # active: "Active" -# color: "Color" -# group: "Group" + color: "Couleur" + group: "Groupe" clothes: "Vêtements" trim: "Tailleur" cloud: "Nuage" -# team: "Team" + team: "Equipe" spell: "Sort" boots: "Bottes" hue: "Teinte" @@ -175,7 +175,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t # job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks." # job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." # sample_profile: "See a sample profile" -# view_profile: "View Your Profile" + view_profile: "Voir votre profile" account_profile: edit_settings: "Éditer les préférences" @@ -183,10 +183,10 @@ module.exports = nativeDescription: "français", englishDescription: "French", t profile_for_suffix: "" # approved: "Approved" # not_approved: "Not Approved" -# looking_for: "Looking for:" -# last_updated: "Last updated:" + looking_for: "à la recherche de:" + last_updated: "Last Mise à jour:" # contact: "Contact" -# work_experience: "Work Experience" + work_experience: "Experience de travail" # education: "Education" # our_notes: "Our Notes" # projects: "Projects" @@ -256,8 +256,8 @@ module.exports = nativeDescription: "français", englishDescription: "French", t skip_tutorial: "Passer (esc)" editor_config: "Config de l'éditeur" editor_config_title: "Configuration de l'éditeur" -# editor_config_language_label: "Programming Language" -# editor_config_language_description: "Define the programming language you want to code in." + editor_config_language_label: "Langage de programmation" + editor_config_language_description: "Définissez le langage de programmation avec lequel vous voulez coder." editor_config_keybindings_label: "Raccourcis clavier" editor_config_keybindings_default: "Par défault (Ace)" editor_config_keybindings_description: "Ajouter de nouveaux raccourcis connus depuis l'éditeur commun." @@ -267,21 +267,21 @@ module.exports = nativeDescription: "français", englishDescription: "French", t editor_config_indentguides_description: "Affiche des guides verticaux qui permettent de visualiser l'indentation." editor_config_behaviors_label: "Auto-complétion" editor_config_behaviors_description: "Ferme automatiquement les accolades, parenthèses, et chaînes de caractères." -# loading_ready: "Ready!" + loading_ready: "Pret!" # tip_insert_positions: "Shift+Click a point on the map to insert it into the spell editor." -# tip_toggle_play: "Toggle play/paused with Ctrl+P." + tip_toggle_play: "Jouer/Pause avec Ctrl+P." # tip_scrub_shortcut: "Ctrl+[ and Ctrl+] rewind and fast-forward." # tip_guide_exists: "Click the guide at the top of the page for useful info." -# tip_open_source: "CodeCombat is 100% open source!" + tip_open_source: "CodeCombat est 100% open source!" # tip_beta_launch: "CodeCombat launched its beta in October, 2013." -# tip_js_beginning: "JavaScript is just the beginning." + tip_js_beginning: "JavaScript n'est que le commencement." # tip_autocast_setting: "Adjust autocast settings by clicking the gear on the cast button." -# think_solution: "Think of the solution, not the problem." -# tip_theory_practice: "In theory, there is no difference between theory and practice. But in practice, there is. - Yogi Berra" + think_solution: "Reflechissez a propos de la solution et non du problème." + tip_theory_practice: "En théorie, il n'y a pas de différence entre la théorie et la pratique. Mais en pratique il y en a. - Yogi Berra" # tip_error_free: "There are two ways to write error-free programs; only the third one works. - Alan Perlis" -# tip_debugging_program: "If debugging is the process of removing bugs, then programming must be the process of putting them in. - Edsger W. Dijkstra" + tip_debugging_program: "Si débugger est l'art de corriger les bugs, alors programmer est l'art d'en créer. . - Edsger W. Dijkstra" # tip_forums: "Head over to the forums and tell us what you think!" -# tip_baby_coders: "In the future, even babies will be Archmages." + tip_baby_coders: "Dans le futur, même les bébés seront des archimages." # tip_morale_improves: "Loading will continue until morale improves." # tip_all_species: "We believe in equal opportunities to learn programming for all species." # tip_reticulating: "Reticulating spines." @@ -296,12 +296,12 @@ module.exports = nativeDescription: "français", englishDescription: "French", t # tip_impossible: "It always seems impossible until it's done. - Nelson Mandela" # tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds" # tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay" -# time_current: "Now:" + time_current: "Maintenant:" # time_total: "Max:" # time_goto: "Go to:" -# infinite_loop_try_again: "Try Again" -# infinite_loop_reset_level: "Reset Level" -# infinite_loop_comment_out: "Comment Out My Code" + infinite_loop_try_again: "Reessayer" + infinite_loop_reset_level: "Redemarrer le niveau" + infinite_loop_comment_out: "Supprimez les commentaire de mon code" admin: av_title: "Vues d'administrateurs" @@ -339,7 +339,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t revert_models: "Annuler les modèles" # fork_title: "Fork New Version" # fork_creating: "Creating Fork..." -# more: "More" + more: "Plus" # wiki: "Wiki" # live_chat: "Live Chat" level_some_options: "Quelques options?" @@ -349,11 +349,11 @@ module.exports = nativeDescription: "français", englishDescription: "French", t level_tab_components: "Composants" level_tab_systems: "Systèmes" level_tab_thangs_title: "Thangs actuels" -# level_tab_thangs_all: "All" + level_tab_thangs_all: "Tout" level_tab_thangs_conditions: "Conditions de départ" level_tab_thangs_add: "ajouter des Thangs" -# delete: "Delete" -# duplicate: "Duplicate" + delete: "Supprimer" + duplicate: "Dupliquer" level_settings_title: "Paramètres" level_component_tab_title: "Composants actuels" level_component_btn_new: "Créer un nouveau composant" @@ -372,13 +372,13 @@ module.exports = nativeDescription: "français", englishDescription: "French", t new_article_title: "Créer un nouvel article" new_thang_title: "Créer un nouveau Type Thang" new_level_title: "Créer un nouveau niveau" -# new_article_title_signup: "Sign Up to Create a New Article" + new_article_title_signup: "Identifiez vous pour creer un nouvel article" # new_thang_title_signup: "Sign Up to Create a New Thang Type" -# new_level_title_signup: "Sign Up to Create a New Level" + new_level_title_signup: "Identifiez vous pour créer un Nouveau niveau" article_search_title: "Rechercher dans les articles" thang_search_title: "Rechercher dans les types Thang" level_search_title: "Rechercher dans les niveaux" -# read_only_warning2: "Note: you can't save any edits here, because you're not logged in." + read_only_warning2: "Note: vous ne pouvez sauvegarder aucune édition, car vous n'êtes pas identifié." article: edit_btn_preview: "Prévisualiser" @@ -500,7 +500,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t contribute: page_title: "Contribution" -# character_classes_title: "Character Classes" + character_classes_title: "Classes du personnage" introduction_desc_intro: "Nous avons beaucoup d'espoir pour CodeCombat." introduction_desc_pref: "Nous voulons être l'endroit où les développeurs de tous horizons viennent pour apprendre et jouer ensemble, présenter les autres au monde du développement, et refléter le meilleur de la communauté. Nous ne pouvons et ne voulons pas faire ça seuls ; ce qui rend super les projets comme GitHub, Stack Overflow et Linux, est que les gens qui l'utilisent le construisent. Dans ce but, " introduction_desc_github_url: "CodeCombat est totalement open source" diff --git a/app/templates/account/profile.jade b/app/templates/account/profile.jade index 3b72a5ead..3f9c57524 100644 --- a/app/templates/account/profile.jade +++ b/app/templates/account/profile.jade @@ -14,6 +14,8 @@ block content i.icon-cog span(data-i18n='account_profile.approved').approved Approved span(data-i18n='account_profile.not_approved').not-approved Not Approved + if user.id != me.id + button.btn.edit-settings-button#enter-espionage-mode 007 if user.get('jobProfile') - var profile = user.get('jobProfile'); diff --git a/app/views/account/profile_view.coffee b/app/views/account/profile_view.coffee index 3c269657e..7a7b36172 100644 --- a/app/views/account/profile_view.coffee +++ b/app/views/account/profile_view.coffee @@ -11,6 +11,7 @@ module.exports = class ProfileView extends View 'click #toggle-job-profile-approved': 'toggleJobProfileApproved' 'keyup #job-profile-notes': 'onJobProfileNotesChanged' 'click #contact-candidate': 'onContactCandidate' + 'click #enter-espionage-mode': 'enterEspionageMode' constructor: (options, @userID) -> @onJobProfileNotesChanged = _.debounce @onJobProfileNotesChanged, 1000 @@ -52,6 +53,17 @@ module.exports = class ProfileView extends View @user.save() @updateProfileApproval() + enterEspionageMode: -> + postData = emailLower: @user.get('email').toLowerCase(), usernameLower: @user.get('name').toLowerCase() + $.ajax + type: "POST", + url: "/auth/spy" + data: postData + success: @espionageSuccess + + espionageSuccess: (model) -> + window.location.reload() + onJobProfileNotesChanged: (e) => notes = @$el.find("#job-profile-notes").val() @user.set 'jobProfileNotes', notes diff --git a/app/views/admin_view.coffee b/app/views/admin_view.coffee index cd06c0999..8c93ff616 100644 --- a/app/views/admin_view.coffee +++ b/app/views/admin_view.coffee @@ -1,36 +1,31 @@ {backboneFailure, genericFailure} = require 'lib/errors' View = require 'views/kinds/RootView' template = require 'templates/admin' -storage = require 'lib/storage' module.exports = class AdminView extends View id: "admin-view" template: template - + events: 'click #enter-espionage-mode': 'enterEspionageMode' - + enterEspionageMode: -> userEmail = $("#user-email").val().toLowerCase() username = $("#user-username").val().toLowerCase() - - userIdentifier = userEmail || username + postData = usernameLower: username emailLower: userEmail - + $.ajax type: "POST", url: "/auth/spy" data: postData success: @espionageSuccess error: @espionageFailure - + espionageSuccess: (model) -> - storage.save('whoami',model) window.location.reload() - + espionageFailure: (jqxhr, status,error)-> console.log "There was an error entering espionage mode: #{error}" - - diff --git a/app/views/play/level/tome/spell.coffee b/app/views/play/level/tome/spell.coffee index 719f8488e..acf2b0e3e 100644 --- a/app/views/play/level/tome/spell.coffee +++ b/app/views/play/level/tome/spell.coffee @@ -18,10 +18,11 @@ module.exports = class Spell p = options.programmableMethod @name = p.name - @source = @session.getSourceFor(@spellKey) ? p.source - @originalSource = p.source - @parameters = p.parameters @permissions = read: p.permissions?.read ? [], readwrite: p.permissions?.readwrite ? [] # teams + @source = @originalSource = p.source + @parameters = p.parameters + if @permissions.readwrite.length and sessionSource = @session.getSourceFor(@spellKey) + @source = sessionSource @thangs = {} @view = new SpellView {spell: @, session: @session, worker: @worker} @view.render() # Get it ready and code loaded in advance @@ -30,7 +31,6 @@ module.exports = class Spell @team = @permissions.readwrite[0] ? "common" Backbone.Mediator.publish 'tome:spell-created', spell: @ - destroy: -> @view.destroy() @tabView.destroy() @@ -95,7 +95,7 @@ module.exports = class Spell @worker.removeEventListener("message",arguments.callee, false) cb(workerData.hasChanged) @worker.postMessage JSON.stringify(workerMessage) - + createAether: (thang) -> aceConfig = me.get('aceConfig') ? {} aetherOptions = @@ -136,7 +136,7 @@ module.exports = class Spell for thangId, spellThang of @thangs spellThang.aether?.setLanguage newLanguage spellThang.castAether = null - workerMessage = + workerMessage = function: "updateLanguageAether" newLanguage: newLanguage @worker.postMessage JSON.stringify workerMessage diff --git a/app/views/play/level/tome/spell_palette_view.coffee b/app/views/play/level/tome/spell_palette_view.coffee index 776c28f53..e14ff1507 100644 --- a/app/views/play/level/tome/spell_palette_view.coffee +++ b/app/views/play/level/tome/spell_palette_view.coffee @@ -51,19 +51,24 @@ module.exports = class SpellPaletteView extends View allDocs['__' + doc.name].push doc if doc.type is 'snippet' then doc.owner = 'snippets' - propStorage = - 'this': 'programmableProperties' - more: 'moreProgrammableProperties' - Math: 'programmableMathProperties' - Array: 'programmableArrayProperties' - Object: 'programmableObjectProperties' - String: 'programmableStringProperties' - Vector: 'programmableVectorProperties' - snippets: 'programmableSnippets' + if @options.programmable + propStorage = + 'this': 'programmableProperties' + more: 'moreProgrammableProperties' + Math: 'programmableMathProperties' + Array: 'programmableArrayProperties' + Object: 'programmableObjectProperties' + String: 'programmableStringProperties' + Vector: 'programmableVectorProperties' + snippets: 'programmableSnippets' + else + propStorage = + 'this': 'apiProperties' count = 0 propGroups = {} for owner, storage of propStorage - added = propGroups[owner] = _.sortBy(@thang[storage] ? []).slice() + props = _.reject @thang[storage] ? [], (prop) -> prop[0] is '_' # no private properties + added = propGroups[owner] = _.sortBy(props).slice() count += added.length shortenize = count > 6 @@ -78,7 +83,7 @@ module.exports = class SpellPaletteView extends View doc ?= prop @entries.push @addEntry(doc, shortenize, tabbify, owner is 'snippets') groupForEntry = (entry) -> - return 'more' if entry.doc.owner is 'this' and entry.doc.name in propGroups.more + return 'more' if entry.doc.owner is 'this' and entry.doc.name in (propGroups.more ? []) entry.doc.owner @entries = _.sortBy @entries, (entry) -> order = ['this', 'more', 'Math', 'Vector', 'snippets'] diff --git a/app/views/play/level/tome/tome_view.coffee b/app/views/play/level/tome/tome_view.coffee index f3486df49..3abf08f8c 100644 --- a/app/views/play/level/tome/tome_view.coffee +++ b/app/views/play/level/tome/tome_view.coffee @@ -178,14 +178,12 @@ module.exports = class TomeView extends View thang = e.thang spellName = e.spellName @spellList?.$el.hide() - return @clearSpellView() unless thang?.isProgrammable - selectedThangSpells = (@spells[spellKey] for spellKey in @thangSpells[thang.id]) - if spellName - spell = _.find selectedThangSpells, {name: spellName} - else - spell = @thangList.topSpellForThang thang - #spell = selectedThangSpells[0] # TODO: remember last selected spell for this thang - return @clearSpellView() unless spell?.canRead() + return @clearSpellView() unless thang + spell = @spellFor thang, spellName + unless spell?.canRead() + @clearSpellView() + @updateSpellPalette thang, spell + return unless spell.view is @spellView @clearSpellView() @spellView = spell.view @@ -198,9 +196,22 @@ module.exports = class TomeView extends View @spellList.setThangAndSpell thang, spell @spellView?.setThang thang @spellTabView?.setThang thang - if @spellPaletteView?.thang isnt thang - @spellPaletteView = @insertSubView new SpellPaletteView thang: thang, supermodel: @supermodel - @spellPaletteView.toggleControls {}, spell.view.controlsEnabled # TODO: know when palette should have been disabled but didn't exist + @updateSpellPalette thang, spell + + updateSpellPalette: (thang, spell) -> + return unless thang and @spellPaletteView?.thang isnt thang and thang.programmableProperties or thang.apiProperties + @spellPaletteView = @insertSubView new SpellPaletteView thang: thang, supermodel: @supermodel, programmable: spell?.canRead() + @spellPaletteView.toggleControls {}, spell.view.controlsEnabled if spell # TODO: know when palette should have been disabled but didn't exist + + spellFor: (thang, spellName) -> + return null unless thang?.isProgrammable + selectedThangSpells = (@spells[spellKey] for spellKey in @thangSpells[thang.id]) + if spellName + spell = _.find selectedThangSpells, {name: spellName} + else + spell = @thangList.topSpellForThang thang + #spell = selectedThangSpells[0] # TODO: remember last selected spell for this thang + spell reloadAllCode: -> spell.view.reloadCode false for spellKey, spell of @spells when spell.team is me.team or (spell.team in ["common", "neutral", null])