Merge branch 'master' into course-correction

Some package scripts got in the way of each other
This commit is contained in:
Scott Erickson 2015-11-09 18:18:02 -08:00
commit 0c5b39e029
93 changed files with 1032 additions and 3247 deletions

View file

@ -29,10 +29,12 @@ Whether you're novice or pro, the CodeCombat team is ready to help you implement
![Scott Erickson](http://codecombat.com/images/pages/about/scott_small.png) ![Scott Erickson](http://codecombat.com/images/pages/about/scott_small.png)
![Matt Lott](http://codecombat.com/images/pages/about/matt_small.png) ![Matt Lott](http://codecombat.com/images/pages/about/matt_small.png)
![Catherine Weresow](http://codecombat.com/images/pages/about/cat_small.png) ![Catherine Weresow](http://codecombat.com/images/pages/about/cat_small.png)
![Maka Gradin](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Maka%20Gradin/maka_gradin_100.png)
![Rob Blanckaert](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Rob%20Blanckaert/rob_blanckaert_100.png)
![Michael Schmatz](http://codecombat.com/images/pages/about/michael_small.png) ![Michael Schmatz](http://codecombat.com/images/pages/about/michael_small.png)
![Josh Lee](http://codecombat.com/images/pages/about/josh_small.png) ![Josh Lee](http://codecombat.com/images/pages/about/josh_small.png)
![Jeremy Arns](http://codecombat.com/images/pages/about/jeremy_small.png)
![Alex Cotsarelis](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Alex%20Cotsarelis/alex_100.png) ![Alex Cotsarelis](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Alex%20Cotsarelis/alex_100.png)
![Alex Crooks](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Alex%20Crooks/alex_100.png)
![Alexandru Caciulescu](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Alexandru%20Caciulescu/alexandru_100.png) ![Alexandru Caciulescu](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Alexandru%20Caciulescu/alexandru_100.png)
![Andreas Linn](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Andreas%20Linn/andreas_100.png) ![Andreas Linn](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Andreas%20Linn/andreas_100.png)
![Andrew Witcher](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Andrew%20Witcher/andrew_100.png) ![Andrew Witcher](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Andrew%20Witcher/andrew_100.png)
@ -40,22 +42,32 @@ Whether you're novice or pro, the CodeCombat team is ready to help you implement
![Bang Honam](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Bang%20Honam/bang_100.png) ![Bang Honam](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Bang%20Honam/bang_100.png)
![Benjamin Stern](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Benjamin%20Stern/benjamin_100.png) ![Benjamin Stern](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Benjamin%20Stern/benjamin_100.png)
![Brad Dickason](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Brad%20Dickason/brad_100.png) ![Brad Dickason](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Brad%20Dickason/brad_100.png)
![Carlos Maia](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Carlos%20Maia/carlos_maia_100.png)
![Chloe Fan](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Chloe%20Fan/chloe_100.png) ![Chloe Fan](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Chloe%20Fan/chloe_100.png)
![Dan Ristic](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Dan%20Ristic/dan_100.png) ![Dan Ristic](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Dan%20Ristic/dan_100.png)
![Danny Whittaker](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Danny%20Whittaker/danny_100.png)
![David Liu](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/David%20Liu/david_liu_100.png)
![David Pendray](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/David%20Pendray/david_100.png) ![David Pendray](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/David%20Pendray/david_100.png)
![Deepak1556](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Deepak1556/deepak_100.png) ![Deepak1556](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Deepak1556/deepak_100.png)
![Derek Wong](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Derek%20Wong/derek_100.png) ![Derek Wong](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Derek%20Wong/derek_100.png)
![Dominik Kundel](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Dominik%20Kundel/dominik_k_100.png) ![Dominik Kundel](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Dominik%20Kundel/dominik_k_100.png)
![Glen De Cauwsemaecker](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Glen%20de%20Cauwsemaecker/glen_100.png) ![Glen De Cauwsemaecker](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Glen%20de%20Cauwsemaecker/glen_100.png)
![Ian Li](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Ian%20Li/ian_100.png) ![Ian Li](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Ian%20Li/ian_100.png)
![Jeremy Arns](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Jeremy%20Arns/jeremy_100.png)
![Joachim Brehmer](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Joachim%20Brehmer/joachim_100.png)
![Jose Antonini](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Jose%20Antonini/jose_antonini_100.png)
![Katharine Chan](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Katharine%20Chan/katharine_100.png) ![Katharine Chan](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Katharine%20Chan/katharine_100.png)
![Ken Stanley](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Ken%20Stanley/ken_100.png) ![Ken Stanley](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Ken%20Stanley/ken_100.png)
![Kevin Holland](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Kevin%20Holland/kevin_100.png)
![Laura Watiker](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Laura%20Watiker/laura_100.png) ![Laura Watiker](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Laura%20Watiker/laura_100.png)
![Michael Heasell](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Michael%20Heasell/michael_100.png) ![Michael Heasell](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Michael%20Heasell/michael_100.png)
![Michael Polyak](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Michael%20Polyak/michael_100.png) ![Michael Polyak](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Michael%20Polyak/michael_100.png)
![Mischa Lewis-Norelle](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Mischa%20Lewis-Norelle/mischa_100.png) ![Mischa Lewis-Norelle](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Mischa%20Lewis-Norelle/mischa_100.png)
![Nathan Gosset](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Nathan%20Gosset/nathan_100.png) ![Nathan Gosset](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Nathan%20Gosset/nathan_100.png)
![Oleg Ulyanicky](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Oleg%20Ulyanickiy/oleg_100.png)
![Paul Buser](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Paul%20Buser/paul_100.png) ![Paul Buser](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Paul%20Buser/paul_100.png)
![Pavel Konstantynov](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Pavel%20Konstantinov/pavel_100.png)
![Popey Gilbert](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Popey%20Gilbert/popey_100.png)
![Prabhsimran Baweja](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Prabhsimran%20Baweja/prabhsimran_100.png) ![Prabhsimran Baweja](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Prabhsimran%20Baweja/prabhsimran_100.png)
![Rachel Xiang](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Rachel%20Xiang/rachel_100.png) ![Rachel Xiang](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Rachel%20Xiang/rachel_100.png)
![Rebecca Saines](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Rebecca%20Saines/rebecca_100.png) ![Rebecca Saines](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Rebecca%20Saines/rebecca_100.png)
@ -69,13 +81,3 @@ Whether you're novice or pro, the CodeCombat team is ready to help you implement
![Tom Steinbrecher](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Tom%20Steinbrecher/tom_100.png) ![Tom Steinbrecher](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Tom%20Steinbrecher/tom_100.png)
![Yang Shun Tay](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Yang%20Shun%20Tay/yang_shun_tay_100.png) ![Yang Shun Tay](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Yang%20Shun%20Tay/yang_shun_tay_100.png)
![Zach Martin](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Zach%20Martin/zack_100.png) ![Zach Martin](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Zach%20Martin/zack_100.png)
![Alex Crooks](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Alex%20Crooks/alex_100.png)
![Danny Whittaker](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Danny%20Whittaker/danny_100.png)
![Kevin Holland](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Kevin%20Holland/kevin_100.png)
![Joachim Brehmer](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Joachim%20Brehmer/joachim_100.png)
![Jose Antonini](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Jose%20Antonini/jose_antonini_100.png)
![Oleg Ulyanicky](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Oleg%20Ulyanickiy/oleg_100.png)
![Pavel Konstantynov](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Pavel%20Konstantinov/pavel_100.png)
![Popey Gilbert](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Popey%20Gilbert/popey_100.png)
![Rob Blanckaert](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Rob%20Blanckaert/rob_blanckaert_100.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
ace.define("ace/ext/beautify",["require","exports","module","ace/token_iterator","ace/ext/beautify/php_rules"],function(e,t,n){var r=e("ace/token_iterator").TokenIterator,i=e("./beautify/php_rules").transform;t.beautify=function(e){var t=new r(e,0,0),n=t.getCurrentToken(),s=e.$modeId.split("/").pop(),o=i(t,s);e.doc.setValue(o)},t.commands=[{name:"beautify",exec:function(e){t.beautify(e.session)},bindKey:"Ctrl-Shift-B"}]}),ace.define("ace/ext/beautify/php_rules",["require","exports","module","ace/token_iterator"],function(e,t,n){var r=e("ace/token_iterator").TokenIterator;t.newLines=[{type:"support.php_tag",value:"<?php"},{type:"support.php_tag",value:"<?"},{type:"support.php_tag",value:"?>"},{type:"paren.lparen",value:"{",indent:!0},{type:"paren.rparen",breakBefore:!0,value:"}",indent:!1},{type:"paren.rparen",breakBefore:!0,value:"})",indent:!1,dontBreak:!0},{type:"comment"},{type:"text",value:";"},{type:"text",value:":",context:"php"},{type:"keyword",value:"case",indent:!0,dontBreak:!0},{type:"keyword",value:"default",indent:!0,dontBreak:!0},{type:"keyword",value:"break",indent:!1,dontBreak:!0},{type:"punctuation.doctype.end",value:">"},{type:"meta.tag.punctuation.end",value:">"},{type:"meta.tag.punctuation.begin",value:"<",blockTag:!0,indent:!0,dontBreak:!0},{type:"meta.tag.punctuation.begin",value:"</",indent:!1,breakBefore:!0,dontBreak:!0},{type:"punctuation.operator",value:";"}],t.spaces=[{type:"xml-pe",prepend:!0},{type:"entity.other.attribute-name",prepend:!0},{type:"storage.type",value:"var",append:!0},{type:"storage.type",value:"function",append:!0},{type:"keyword.operator",value:"="},{type:"keyword",value:"as",prepend:!0,append:!0},{type:"keyword",value:"function",append:!0},{type:"support.function",next:/[^\(]/,append:!0},{type:"keyword",value:"or",append:!0,prepend:!0},{type:"keyword",value:"and",append:!0,prepend:!0},{type:"keyword",value:"case",append:!0},{type:"keyword.operator",value:"||",append:!0,prepend:!0},{type:"keyword.operator",value:"&&",append:!0,prepend:!0}],t.singleTags=["!doctype","area","base","br","hr","input","img","link","meta"],t.transform=function(e,n,r){var i=e.getCurrentToken(),s=t.newLines,o=t.spaces,u=t.singleTags,a="",f=0,l=!1,c,h,p={},d,v={},m=!1,g="";while(i!==null){console.log(i);if(!i){i=e.stepForward();continue}i.type=="support.php_tag"&&i.value!="?>"?r="php":i.type=="support.php_tag"&&i.value=="?>"?r="html":i.type=="meta.tag.name.style"&&r!="css"?r="css":i.type=="meta.tag.name.style"&&r=="css"?r="html":i.type=="meta.tag.name.script"&&r!="js"?r="js":i.type=="meta.tag.name.script"&&r=="js"&&(r="html"),v=e.stepForward(),v&&v.type.indexOf("meta.tag.name")==0&&(d=v.value),p.type=="support.php_tag"&&p.value=="<?="&&(l=!0),i.type=="meta.tag.name"&&(i.value=i.value.toLowerCase()),i.type=="text"&&(i.value=i.value.trim());if(!i.value){i=v;continue}g=i.value;for(var y in o)i.type==o[y].type&&(!o[y].value||i.value==o[y].value)&&v&&(!o[y].next||o[y].next.test(v.value))&&(o[y].prepend&&(g=" "+i.value),o[y].append&&(g+=" "));i.type.indexOf("meta.tag.name")==0&&(c=i.value),m=!1;for(y in s)if(i.type==s[y].type&&(!s[y].value||i.value==s[y].value)&&(!s[y].blockTag||u.indexOf(d)===-1)&&(!s[y].context||s[y].context===r)){s[y].indent===!1&&f--;if(s[y].breakBefore&&(!s[y].prev||s[y].prev.test(p.value))){a+="\n",m=!0;for(y=0;y<f;y++)a+=" "}break}if(l===!1)for(y in s)if(p.type==s[y].type&&(!s[y].value||p.value==s[y].value)&&(!s[y].blockTag||u.indexOf(c)===-1)&&(!s[y].context||s[y].context===r)){s[y].indent===!0&&f++;if(!s[y].dontBreak&&!m){a+="\n";for(y=0;y<f;y++)a+=" "}break}a+=g,p.type=="support.php_tag"&&p.value=="?>"&&(l=!1),h=c,p=i,i=v;if(i===null)break}return a}}),function(){ace.require(["ace/ext/beautify"],function(){})}()

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
ace.define("ace/ext/elastic_tabstops_lite",["require","exports","module","ace/editor","ace/config"],function(e,t,n){var r=function(e){this.$editor=e;var t=this,n=[],r=!1;this.onAfterExec=function(){r=!1,t.processRows(n),n=[]},this.onExec=function(){r=!0},this.onChange=function(e){var t=e.data.range;r&&(n.indexOf(t.start.row)==-1&&n.push(t.start.row),t.end.row!=t.start.row&&n.push(t.end.row))}};(function(){this.processRows=function(e){this.$inChange=!0;var t=[];for(var n=0,r=e.length;n<r;n++){var i=e[n];if(t.indexOf(i)>-1)continue;var s=this.$findCellWidthsForBlock(i),o=this.$setBlockCellWidthsToMax(s.cellWidths),u=s.firstRow;for(var a=0,f=o.length;a<f;a++){var l=o[a];t.push(u),this.$adjustRow(u,l),u++}}this.$inChange=!1},this.$findCellWidthsForBlock=function(e){var t=[],n,r=e;while(r>=0){n=this.$cellWidthsForRow(r);if(n.length==0)break;t.unshift(n),r--}var i=r+1;r=e;var s=this.$editor.session.getLength();while(r<s-1){r++,n=this.$cellWidthsForRow(r);if(n.length==0)break;t.push(n)}return{cellWidths:t,firstRow:i}},this.$cellWidthsForRow=function(e){var t=this.$selectionColumnsForRow(e),n=[-1].concat(this.$tabsForRow(e)),r=n.map(function(e){return 0}).slice(1),i=this.$editor.session.getLine(e);for(var s=0,o=n.length-1;s<o;s++){var u=n[s]+1,a=n[s+1],f=this.$rightmostSelectionInCell(t,a),l=i.substring(u,a);r[s]=Math.max(l.replace(/\s+$/g,"").length,f-u)}return r},this.$selectionColumnsForRow=function(e){var t=[],n=this.$editor.getCursorPosition();return this.$editor.session.getSelection().isEmpty()&&e==n.row&&t.push(n.column),t},this.$setBlockCellWidthsToMax=function(e){var t=!0,n,r,i,s=this.$izip_longest(e);for(var o=0,u=s.length;o<u;o++){var a=s[o];if(!a.push){console.error(a);continue}a.push(NaN);for(var f=0,l=a.length;f<l;f++){var c=a[f];t&&(n=f,i=0,t=!1);if(isNaN(c)){r=f;for(var h=n;h<r;h++)e[h][o]=i;t=!0}i=Math.max(i,c)}}return e},this.$rightmostSelectionInCell=function(e,t){var n=0;if(e.length){var r=[];for(var i=0,s=e.length;i<s;i++)e[i]<=t?r.push(i):r.push(0);n=Math.max.apply(Math,r)}return n},this.$tabsForRow=function(e){var t=[],n=this.$editor.session.getLine(e),r=/\t/g,i;while((i=r.exec(n))!=null)t.push(i.index);return t},this.$adjustRow=function(e,t){var n=this.$tabsForRow(e);if(n.length==0)return;var r=0,i=-1,s=this.$izip(t,n);for(var o=0,u=s.length;o<u;o++){var a=s[o][0],f=s[o][1];i+=1+a,f+=r;var l=i-f;if(l==0)continue;var c=this.$editor.session.getLine(e).substr(0,f),h=c.replace(/\s*$/g,""),p=c.length-h.length;l>0&&(this.$editor.session.getDocument().insertInLine({row:e,column:f+1},Array(l+1).join(" ")+" "),this.$editor.session.getDocument().removeInLine(e,f,f+1),r+=l),l<0&&p>=-l&&(this.$editor.session.getDocument().removeInLine(e,f+l,f),r+=l)}},this.$izip_longest=function(e){if(!e[0])return[];var t=e[0].length,n=e.length;for(var r=1;r<n;r++){var i=e[r].length;i>t&&(t=i)}var s=[];for(var o=0;o<t;o++){var u=[];for(var r=0;r<n;r++)e[r][o]===""?u.push(NaN):u.push(e[r][o]);s.push(u)}return s},this.$izip=function(e,t){var n=e.length>=t.length?t.length:e.length,r=[];for(var i=0;i<n;i++){var s=[e[i],t[i]];r.push(s)}return r}}).call(r.prototype),t.ElasticTabstopsLite=r;var i=e("../editor").Editor;e("../config").defineOptions(i.prototype,"editor",{useElasticTabstops:{set:function(e){e?(this.elasticTabstops||(this.elasticTabstops=new r(this)),this.commands.on("afterExec",this.elasticTabstops.onAfterExec),this.commands.on("exec",this.elasticTabstops.onExec),this.on("change",this.elasticTabstops.onChange)):this.elasticTabstops&&(this.commands.removeListener("afterExec",this.elasticTabstops.onAfterExec),this.commands.removeListener("exec",this.elasticTabstops.onExec),this.removeListener("change",this.elasticTabstops.onChange))}}})}),function(){ace.require(["ace/ext/elastic_tabstops_lite"],function(){})}()

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
(function(){ace.require(["ace/ext/error_marker"],function(){})})()

View file

@ -1 +0,0 @@
ace.define("ace/ext/keybinding_menu",["require","exports","module","ace/editor","ace/ext/menu_tools/overlay_page","ace/ext/menu_tools/get_editor_keyboard_shortcuts"],function(e,t,n){function i(t){if(!document.getElementById("kbshortcutmenu")){var n=e("./menu_tools/overlay_page").overlayPage,r=e("./menu_tools/get_editor_keyboard_shortcuts").getEditorKeybordShortcuts,i=r(t),s=document.createElement("div"),o=i.reduce(function(e,t){return e+'<div class="ace_optionsMenuEntry"><span class="ace_optionsMenuCommand">'+t.command+"</span> : "+'<span class="ace_optionsMenuKey">'+t.key+"</span></div>"},"");s.id="kbshortcutmenu",s.innerHTML="<h1>Keyboard Shortcuts</h1>"+o+"</div>",n(t,s,"0","0","0",null)}}var r=e("ace/editor").Editor;n.exports.init=function(e){r.prototype.showKeyboardShortcuts=function(){i(this)},e.commands.addCommands([{name:"showKeyboardShortcuts",bindKey:{win:"Ctrl-Alt-h",mac:"Command-Alt-h"},exec:function(e,t){e.showKeyboardShortcuts()}}])}}),ace.define("ace/ext/menu_tools/overlay_page",["require","exports","module","ace/lib/dom"],function(e,t,n){var r=e("../../lib/dom"),i="#ace_settingsmenu, #kbshortcutmenu {background-color: #F7F7F7;color: black;box-shadow: -5px 4px 5px rgba(126, 126, 126, 0.55);padding: 1em 0.5em 2em 1em;overflow: auto;position: absolute;margin: 0;bottom: 0;right: 0;top: 0;z-index: 9991;cursor: default;}.ace_dark #ace_settingsmenu, .ace_dark #kbshortcutmenu {box-shadow: -20px 10px 25px rgba(126, 126, 126, 0.25);background-color: rgba(255, 255, 255, 0.6);color: black;}.ace_optionsMenuEntry:hover {background-color: rgba(100, 100, 100, 0.1);-webkit-transition: all 0.5s;transition: all 0.3s}.ace_closeButton {background: rgba(245, 146, 146, 0.5);border: 1px solid #F48A8A;border-radius: 50%;padding: 7px;position: absolute;right: -8px;top: -8px;z-index: 1000;}.ace_closeButton{background: rgba(245, 146, 146, 0.9);}.ace_optionsMenuKey {color: darkslateblue;font-weight: bold;}.ace_optionsMenuCommand {color: darkcyan;font-weight: normal;}";r.importCssString(i),n.exports.overlayPage=function(t,n,i,s,o,u){function l(e){e.keyCode===27&&a.click()}i=i?"top: "+i+";":"",o=o?"bottom: "+o+";":"",s=s?"right: "+s+";":"",u=u?"left: "+u+";":"";var a=document.createElement("div"),f=document.createElement("div");a.style.cssText="margin: 0; padding: 0; position: fixed; top:0; bottom:0; left:0; right:0;z-index: 9990; background-color: rgba(0, 0, 0, 0.3);",a.addEventListener("click",function(){document.removeEventListener("keydown",l),a.parentNode.removeChild(a),t.focus(),a=null}),document.addEventListener("keydown",l),f.style.cssText=i+s+o+u,f.addEventListener("click",function(e){e.stopPropagation()});var c=r.createElement("div");c.style.position="relative";var h=r.createElement("div");h.className="ace_closeButton",h.addEventListener("click",function(){a.click()}),c.appendChild(h),f.appendChild(c),f.appendChild(n),a.appendChild(f),document.body.appendChild(a),t.blur()}}),ace.define("ace/ext/menu_tools/get_editor_keyboard_shortcuts",["require","exports","module","ace/lib/keys"],function(e,t,n){var r=e("../../lib/keys");n.exports.getEditorKeybordShortcuts=function(e){var t=r.KEY_MODS,n=[],i={};return e.keyBinding.$handlers.forEach(function(e){var r=e.commandKeyBinding;for(var s in r){var o=parseInt(s);o==-1?o="":isNaN(o)?o=s:o=""+(o&t.command?"Cmd-":"")+(o&t.ctrl?"Ctrl-":"")+(o&t.alt?"Alt-":"")+(o&t.shift?"Shift-":"");for(var u in r[s]){var a=r[s][u];typeof a!="string"&&(a=a.name),i[a]?i[a].key+="|"+o+u:(i[a]={key:o+u,command:a},n.push(i[a]))}}}),n}}),function(){ace.require(["ace/ext/keybinding_menu"],function(){})}()

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
ace.define("ace/ext/linking",["require","exports","module","ace/editor","ace/config"],function(e,t,n){function i(e){var t=e.editor,n=e.getAccelKey();if(n){var t=e.editor,r=e.getDocumentPosition(),i=t.session,s=i.getTokenAt(r.row,r.column);t._emit("linkHover",{position:r,token:s})}}function s(e){var t=e.getAccelKey(),n=e.getButton();if(n==0&&t){var r=e.editor,i=e.getDocumentPosition(),s=r.session,o=s.getTokenAt(i.row,i.column);r._emit("linkClick",{position:i,token:o})}}var r=e("ace/editor").Editor;e("../config").defineOptions(r.prototype,"editor",{enableLinking:{set:function(e){e?(this.on("click",s),this.on("mousemove",i)):(this.off("click",s),this.off("mousemove",i))},value:!1}})}),function(){ace.require(["ace/ext/linking"],function(){})}()

View file

@ -1 +0,0 @@
ace.define("ace/ext/modelist",["require","exports","module"],function(e,t,n){function i(e){var t=a.text,n=e.split(/[\/\\]/).pop();for(var i=0;i<r.length;i++)if(r[i].supportsFile(n)){t=r[i];break}return t}var r=[],s=function(e,t,n){this.name=e,this.caption=t,this.mode="ace/mode/"+e,this.extensions=n;if(/\^/.test(n))var r=n.replace(/\|(\^)?/g,function(e,t){return"$|"+(t?"^":"^.*\\.")})+"$";else var r="^.*\\.("+n+")$";this.extRe=new RegExp(r,"gi")};s.prototype.supportsFile=function(e){return e.match(this.extRe)};var o={ABAP:["abap"],ActionScript:["as"],ADA:["ada|adb"],Apache_Conf:["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"],AsciiDoc:["asciidoc"],Assembly_x86:["asm"],AutoHotKey:["ahk"],BatchFile:["bat|cmd"],C9Search:["c9search_results"],C_Cpp:["cpp|c|cc|cxx|h|hh|hpp"],Cirru:["cirru|cr"],Clojure:["clj"],Cobol:["CBL|COB"],coffee:["coffee|cf|cson|^Cakefile"],ColdFusion:["cfm"],CSharp:["cs"],CSS:["css"],Curly:["curly"],D:["d|di"],Dart:["dart"],Diff:["diff|patch"],Dockerfile:["^Dockerfile"],Dot:["dot"],Erlang:["erl|hrl"],EJS:["ejs"],Forth:["frt|fs|ldr"],FTL:["ftl"],Gherkin:["feature"],Glsl:["glsl|frag|vert"],golang:["go"],Groovy:["groovy"],HAML:["haml"],Handlebars:["hbs|handlebars|tpl|mustache"],Haskell:["hs"],haXe:["hx"],HTML:["html|htm|xhtml"],HTML_Ruby:["erb|rhtml|html.erb"],INI:["ini|conf|cfg|prefs"],Jack:["jack"],Jade:["jade"],Java:["java"],JavaScript:["js|jsm"],JSON:["json"],JSONiq:["jq"],JSP:["jsp"],JSX:["jsx"],Julia:["jl"],LaTeX:["tex|latex|ltx|bib"],LESS:["less"],Liquid:["liquid"],Lisp:["lisp"],LiveScript:["ls"],LogiQL:["logic|lql"],LSL:["lsl"],Lua:["lua"],LuaPage:["lp"],Lucene:["lucene"],Makefile:["^Makefile|^GNUmakefile|^makefile|^OCamlMakefile|make"],MATLAB:["matlab"],Markdown:["md|markdown"],MEL:["mel"],MySQL:["mysql"],MUSHCode:["mc|mush"],Nix:["nix"],ObjectiveC:["m|mm"],OCaml:["ml|mli"],Pascal:["pas|p"],Perl:["pl|pm"],pgSQL:["pgsql"],PHP:["php|phtml"],Powershell:["ps1"],Prolog:["plg|prolog"],Properties:["properties"],Protobuf:["proto"],Python:["py"],R:["r"],RDoc:["Rd"],RHTML:["Rhtml"],Ruby:["rb|ru|gemspec|rake|^Guardfile|^Rakefile|^Gemfile"],Rust:["rs"],SASS:["sass"],SCAD:["scad"],Scala:["scala"],Smarty:["smarty|tpl"],Scheme:["scm|rkt"],SCSS:["scss"],SH:["sh|bash|^.bashrc"],SJS:["sjs"],Space:["space"],snippets:["snippets"],Soy_Template:["soy"],SQL:["sql"],Stylus:["styl|stylus"],SVG:["svg"],Tcl:["tcl"],Tex:["tex"],Text:["txt"],Textile:["textile"],Toml:["toml"],Twig:["twig"],Typescript:["ts|typescript|str"],Vala:["vala"],VBScript:["vbs"],Velocity:["vm"],Verilog:["v|vh|sv|svh"],XML:["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl"],XQuery:["xq"],YAML:["yaml|yml"]},u={ObjectiveC:"Objective-C",CSharp:"C#",golang:"Go",C_Cpp:"C/C++",coffee:"CoffeeScript",HTML_Ruby:"HTML (Ruby)",FTL:"FreeMarker"},a={};for(var f in o){var l=o[f],c=(u[f]||f).replace(/_/g," "),h=f.toLowerCase(),p=new s(h,c,l[0]);a[h]=p,r.push(p)}n.exports={getModeForPath:i,modes:r,modesByName:a}}),function(){ace.require(["ace/ext/modelist"],function(){})}()

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
ace.define("ace/ext/prompt",["require","exports","module","ace/lib/lang","ace/lib/dom","ace/lib/event","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/editor","ace/multi_select"],function(e,t,n){function c(e,t){var n=this.pixelToScreenCoordinates(e,t);return this.session.screenToDocumentPosition(Math.min(this.session.getScreenLength()-1,Math.max(n.row,0)),Math.max(n.column,0))}var r=e("../lib/lang"),i=e("ace/lib/dom"),s=e("ace/lib/event"),o=e("ace/edit_session").EditSession,u=e("ace/undomanager").UndoManager,a=e("ace/virtual_renderer").VirtualRenderer,f=e("ace/editor").Editor,l=e("ace/multi_select").MultiSelect;t.singleLineEditor=function(e){var t=new a;t.container.style.overflow="hidden",t.screenToTextCoordinates=c,t.setStyle("ace_one-line");var n=new f(t);return n.session.setUndoManager(new u),n.setOptions({showPrintMargin:!1,showGutter:!1,highlightGutterLine:!1,focusWaitTimout:0,maxLines:4}),n}}),function(){ace.require(["ace/ext/prompt"],function(){})}()

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
ace.define("ace/ext/spellcheck",["require","exports","module","ace/lib/event","ace/editor","ace/config"],function(e,t,n){var r=e("../lib/event");t.contextMenuHandler=function(e){var t=e.target,n=t.textInput.getElement();if(!t.selection.isEmpty())return;var i=t.getCursorPosition(),s=t.session.getWordRange(i.row,i.column),o=t.session.getTextRange(s);t.session.tokenRe.lastIndex=0;if(!t.session.tokenRe.test(o))return;var u="\x01\x01",a=o+" "+u;n.value=a,n.setSelectionRange(o.length,o.length+1),n.setSelectionRange(0,0),n.setSelectionRange(0,o.length);var f=!1;r.addListener(n,"keydown",function l(){r.removeListener(n,"keydown",l),f=!0}),t.textInput.setInputHandler(function(e){console.log(e,a,n.selectionStart,n.selectionEnd);if(e==a)return"";if(e.lastIndexOf(a,0)===0)return e.slice(a.length);if(e.substr(n.selectionEnd)==a)return e.slice(0,-a.length);if(e.slice(-2)==u){var r=e.slice(0,-2);if(r.slice(-1)==" ")return f?r.substring(0,n.selectionEnd):(r=r.slice(0,-1),t.session.replace(s,r),"")}return e})};var i=e("../editor").Editor;e("../config").defineOptions(i.prototype,"editor",{spellcheck:{set:function(e){var n=this.textInput.getElement();n.spellcheck=!!e,e?this.on("nativecontextmenu",t.contextMenuHandler):this.removeListener("nativecontextmenu",t.contextMenuHandler)},value:!0}})}),function(){ace.require(["ace/ext/spellcheck"],function(){})}()

View file

@ -1 +0,0 @@
ace.define("ace/ext/split",["require","exports","module","ace/split"],function(e,t,n){n.exports=e("../split")}),ace.define("ace/split",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter","ace/editor","ace/virtual_renderer","ace/edit_session"],function(e,t,n){function l(e,t){this.$u=e,this.$doc=t}var r=e("./lib/oop"),i=e("./lib/lang"),s=e("./lib/event_emitter").EventEmitter,o=e("./editor").Editor,u=e("./virtual_renderer").VirtualRenderer,a=e("./edit_session").EditSession,f=function(e,t,n){this.BELOW=1,this.BESIDE=0,this.$container=e,this.$theme=t,this.$splits=0,this.$editorCSS="",this.$editors=[],this.$orientation=this.BESIDE,this.setSplits(n||1),this.$cEditor=this.$editors[0],this.on("focus",function(e){this.$cEditor=e}.bind(this))};(function(){r.implement(this,s),this.$createEditor=function(){var e=document.createElement("div");e.className=this.$editorCSS,e.style.cssText="position: absolute; top:0px; bottom:0px",this.$container.appendChild(e);var t=new o(new u(e,this.$theme));return t.on("focus",function(){this._emit("focus",t)}.bind(this)),this.$editors.push(t),t.setFontSize(this.$fontSize),t},this.setSplits=function(e){var t;if(e<1)throw"The number of splits have to be > 0!";if(e==this.$splits)return;if(e>this.$splits){while(this.$splits<this.$editors.length&&this.$splits<e)t=this.$editors[this.$splits],this.$container.appendChild(t.container),t.setFontSize(this.$fontSize),this.$splits++;while(this.$splits<e)this.$createEditor(),this.$splits++}else while(this.$splits>e)t=this.$editors[this.$splits-1],this.$container.removeChild(t.container),this.$splits--;this.resize()},this.getSplits=function(){return this.$splits},this.getEditor=function(e){return this.$editors[e]},this.getCurrentEditor=function(){return this.$cEditor},this.focus=function(){this.$cEditor.focus()},this.blur=function(){this.$cEditor.blur()},this.setTheme=function(e){this.$editors.forEach(function(t){t.setTheme(e)})},this.setKeyboardHandler=function(e){this.$editors.forEach(function(t){t.setKeyboardHandler(e)})},this.forEach=function(e,t){this.$editors.forEach(e,t)},this.$fontSize="",this.setFontSize=function(e){this.$fontSize=e,this.forEach(function(t){t.setFontSize(e)})},this.$cloneSession=function(e){var t=new a(e.getDocument(),e.getMode()),n=e.getUndoManager();if(n){var r=new l(n,t);t.setUndoManager(r)}return t.$informUndoManager=i.delayedCall(function(){t.$deltas=[]}),t.setTabSize(e.getTabSize()),t.setUseSoftTabs(e.getUseSoftTabs()),t.setOverwrite(e.getOverwrite()),t.setBreakpoints(e.getBreakpoints()),t.setUseWrapMode(e.getUseWrapMode()),t.setUseWorker(e.getUseWorker()),t.setWrapLimitRange(e.$wrapLimitRange.min,e.$wrapLimitRange.max),t.$foldData=e.$cloneFoldData(),t},this.setSession=function(e,t){var n;t==null?n=this.$cEditor:n=this.$editors[t];var r=this.$editors.some(function(t){return t.session===e});return r&&(e=this.$cloneSession(e)),n.setSession(e),e},this.getOrientation=function(){return this.$orientation},this.setOrientation=function(e){if(this.$orientation==e)return;this.$orientation=e,this.resize()},this.resize=function(){var e=this.$container.clientWidth,t=this.$container.clientHeight,n;if(this.$orientation==this.BESIDE){var r=e/this.$splits;for(var i=0;i<this.$splits;i++)n=this.$editors[i],n.container.style.width=r+"px",n.container.style.top="0px",n.container.style.left=i*r+"px",n.container.style.height=t+"px",n.resize()}else{var s=t/this.$splits;for(var i=0;i<this.$splits;i++)n=this.$editors[i],n.container.style.width=e+"px",n.container.style.top=i*s+"px",n.container.style.left="0px",n.container.style.height=s+"px",n.resize()}}}).call(f.prototype),function(){this.execute=function(e){this.$u.execute(e)},this.undo=function(){var e=this.$u.undo(!0);e&&this.$doc.selection.setSelectionRange(e)},this.redo=function(){var e=this.$u.redo(!0);e&&this.$doc.selection.setSelectionRange(e)},this.reset=function(){this.$u.reset()},this.hasUndo=function(){return this.$u.hasUndo()},this.hasRedo=function(){return this.$u.hasRedo()}}.call(l.prototype),t.Split=f}),function(){ace.require(["ace/ext/split"],function(){})}()

View file

@ -1 +0,0 @@
ace.define("ace/ext/static_highlight",["require","exports","module","ace/edit_session","ace/layer/text","ace/config","ace/lib/dom"],function(e,t,n){var r=e("../edit_session").EditSession,i=e("../layer/text").Text,s=".ace_static_highlight {font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', 'Droid Sans Mono', monospace;font-size: 12px;}.ace_static_highlight .ace_gutter {width: 25px !important;display: block;float: left;text-align: right;padding: 0 3px 0 0;margin-right: 3px;position: static !important;}.ace_static_highlight .ace_line { clear: both; }.ace_static_highlight .ace_gutter-cell {-moz-user-select: -moz-none;-khtml-user-select: none;-webkit-user-select: none;user-select: none;}.ace_static_highlight .ace_gutter-cell:before {content: counter(ace_line, decimal);counter-increment: ace_line;}.ace_static_highlight {counter-reset: ace_line;}",o=e("../config"),u=e("../lib/dom"),a=function(e,t,n){var r=e.className.match(/lang-(\w+)/),i=t.mode||r&&"ace/mode/"+r[1];if(!i)return!1;var s=t.theme||"ace/theme/textmate",o="",f=[];if(e.firstElementChild){var l=0;for(var c=0;c<e.childNodes.length;c++){var h=e.childNodes[c];h.nodeType==3?(l+=h.data.length,o+=h.data):f.push(l,h)}}else o=u.getInnerText(e),t.trim&&(o=o.trim());a.render(o,i,s,t.firstLineNumber,!t.showGutter,function(t){u.importCssString(t.css,"ace_highlight"),e.innerHTML=t.html;var r=e.firstChild.firstChild;for(var i=0;i<f.length;i+=2){var s=t.session.doc.indexToPosition(f[i]),o=f[i+1],a=r.children[s.row];a&&a.appendChild(o)}n&&n()})};a.render=function(e,t,n,i,s,u){function c(){var r=a.renderSync(e,t,n,i,s);return u?u(r):r}var f=1,l=r.prototype.$modes;return typeof n=="string"&&(f++,o.loadModule(["theme",n],function(e){n=e,--f||c()})),typeof t=="string"&&(f++,o.loadModule(["mode",t],function(e){l[t]||(l[t]=new e.Mode),t=l[t],--f||c()})),--f||c()},a.renderSync=function(e,t,n,o,u){o=parseInt(o||1,10);var a=new r("");a.setUseWorker(!1),a.setMode(t);var f=new i(document.createElement("div"));f.setSession(a),f.config={characterWidth:10,lineHeight:20},a.setValue(e);var l=[],c=a.getLength();for(var h=0;h<c;h++)l.push("<div class='ace_line'>"),u||l.push("<span class='ace_gutter ace_gutter-cell' unselectable='on'></span>"),f.$renderLine(l,h,!0,!1),l.push("\n</div>");var p="<div class='"+n.cssClass+"'>"+"<div class='ace_static_highlight' style='counter-reset:ace_line "+(o-1)+"'>"+l.join("")+"</div>"+"</div>";return f.destroy(),{css:s+n.cssText,html:p,session:a}},n.exports=a,n.exports.highlight=a}),function(){ace.require(["ace/ext/static_highlight"],function(){})}()

View file

@ -1 +0,0 @@
ace.define("ace/ext/statusbar",["require","exports","module","ace/lib/dom","ace/lib/lang"],function(e,t,n){var r=e("ace/lib/dom"),i=e("ace/lib/lang"),s=function(e,t){this.element=r.createElement("div"),this.element.className="ace_status-indicator",this.element.style.cssText="display: inline-block;",t.appendChild(this.element);var n=i.delayedCall(function(){this.updateStatus(e)}.bind(this));e.on("changeStatus",function(){n.schedule(100)}),e.on("changeSelection",function(){n.schedule(100)})};(function(){this.updateStatus=function(e){function n(e,n){e&&t.push(e,n||"|")}var t=[];e.$vimModeHandler?n(e.$vimModeHandler.getStatusText()):e.commands.recording&&n("REC");var r=e.selection.lead;n(r.row+":"+r.column," ");if(!e.selection.isEmpty()){var i=e.getSelectionRange();n("("+(i.end.row-i.start.row)+":"+(i.end.column-i.start.column)+")")}t.pop(),this.element.textContent=t.join("")}}).call(s.prototype),t.StatusBar=s}),function(){ace.require(["ace/ext/statusbar"],function(){})}()

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
ace.define("ace/ext/themelist",["require","exports","module","ace/lib/fixoldbrowsers"],function(e,t,n){e("ace/lib/fixoldbrowsers");var r=[["Chrome"],["Clouds"],["Crimson Editor"],["Dawn"],["Dreamweaver"],["Eclipse"],["GitHub"],["Solarized Light"],["TextMate"],["Tomorrow"],["XCode"],["Kuroir"],["KatzenMilch"],["Ambiance","ambiance","dark"],["Chaos","chaos","dark"],["Clouds Midnight","clouds_midnight","dark"],["Cobalt","cobalt","dark"],["idle Fingers","idle_fingers","dark"],["krTheme","kr_theme","dark"],["Merbivore","merbivore","dark"],["Merbivore Soft","merbivore_soft","dark"],["Mono Industrial","mono_industrial","dark"],["Monokai","monokai","dark"],["Pastel on dark","pastel_on_dark","dark"],["Solarized Dark","solarized_dark","dark"],["Terminal","terminal","dark"],["Tomorrow Night","tomorrow_night","dark"],["Tomorrow Night Blue","tomorrow_night_blue","dark"],["Tomorrow Night Bright","tomorrow_night_bright","dark"],["Tomorrow Night 80s","tomorrow_night_eighties","dark"],["Twilight","twilight","dark"],["Vibrant Ink","vibrant_ink","dark"]];t.themesByName={},t.themes=r.map(function(e){var n=e[1]||e[0].replace(/ /g,"_").toLowerCase(),r={caption:e[0],theme:"ace/theme/"+n,isDark:e[2]=="dark",name:n};return t.themesByName[n]=r,r})}),function(){ace.require(["ace/ext/themelist"],function(){})}()

View file

@ -1 +0,0 @@
ace.define("ace/ext/whitespace",["require","exports","module","ace/lib/lang"],function(e,t,n){var r=e("../lib/lang");t.$detectIndentation=function(e,t){function h(e){var t=0;for(var r=e;r<n.length;r+=e)t+=n[r]||0;return t}var n=[],r=[],i=0,s=0,o=Math.min(e.length,1e3);for(var u=0;u<o;u++){var a=e[u];if(!/^\s*[^*+\-\s]/.test(a))continue;var f=a.match(/^\t*/)[0].length;a[0]==" "&&i++;var l=a.match(/^ */)[0].length;if(l&&a[l]!=" "){var c=l-s;c>0&&!(s%c)&&!(l%c)&&(r[c]=(r[c]||0)+1),n[l]=(n[l]||0)+1}s=l;while(u<o&&a[a.length-1]=="\\")a=e[u++]}if(!n.length)return;var p=r.reduce(function(e,t){return e+t},0),d={score:0,length:0},v=0;for(var u=1;u<12;u++){if(u==1){v=h(u);var m=1}else var m=h(u)/v;r[u]&&(m+=r[u]/p),m>d.score&&(d={score:m,length:u})}if(d.score&&d.score>1.4)var g=d.length;if(i>v+1)return{ch:" ",length:g};if(v+1>i)return{ch:" ",length:g}},t.detectIndentation=function(e){var n=e.getLines(0,1e3),r=t.$detectIndentation(n)||{};return r.ch&&e.setUseSoftTabs(r.ch==" "),r.length&&e.setTabSize(r.length),r},t.trimTrailingSpace=function(e,t){var n=e.getDocument(),r=n.getAllLines(),i=t?-1:0;for(var s=0,o=r.length;s<o;s++){var u=r[s],a=u.search(/\s+$/);a>i&&n.removeInLine(s,a,u.length)}},t.convertIndentation=function(e,t,n){var i=e.getTabString()[0],s=e.getTabSize();n||(n=s),t||(t=i);var o=t==" "?t:r.stringRepeat(t,n),u=e.doc,a=u.getAllLines(),f={},l={};for(var c=0,h=a.length;c<h;c++){var p=a[c],d=p.match(/^\s*/)[0];if(d){var v=e.$getStringScreenWidth(d)[0],m=Math.floor(v/s),g=v%s,y=f[m]||(f[m]=r.stringRepeat(o,m));y+=l[g]||(l[g]=r.stringRepeat(" ",g)),y!=d&&(u.removeInLine(c,0,d.length),u.insertInLine({row:c,column:0},y))}}e.setTabSize(n),e.setUseSoftTabs(t==" ")},t.$parseStringArg=function(e){var t={};/t/.test(e)?t.ch=" ":/s/.test(e)&&(t.ch=" ");var n=e.match(/\d+/);return n&&(t.length=parseInt(n[0],10)),t},t.$parseArg=function(e){return e?typeof e=="string"?t.$parseStringArg(e):typeof e.text=="string"?t.$parseStringArg(e.text):e:{}},t.commands=[{name:"detectIndentation",exec:function(e){t.detectIndentation(e.session)}},{name:"trimTrailingSpace",exec:function(e){t.trimTrailingSpace(e.session)}},{name:"convertIndentation",exec:function(e,n){var r=t.$parseArg(n);t.convertIndentation(e.session,r.ch,r.length)}},{name:"setIndentation",exec:function(e,n){var r=t.$parseArg(n);r.length&&e.session.setTabSize(r.length),r.ch&&e.session.setUseSoftTabs(r.ch==" ")}}]}),function(){ace.require(["ace/ext/whitespace"],function(){})}()

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -1 +0,0 @@
ace.define("ace/mode/plain_text",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/text_highlight_rules","ace/mode/behaviour"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("./text_highlight_rules").TextHighlightRules,o=e("./behaviour").Behaviour,u=function(){this.HighlightRules=s,this.$behaviour=new o};r.inherits(u,i),function(){this.type="text",this.getNextLineIndent=function(e,t,n){return""},this.$id="ace/mode/plain_text"}.call(u.prototype),t.Mode=u})

View file

@ -1 +0,0 @@
ace.define("ace/mode/python",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/python_highlight_rules","ace/mode/folding/pythonic","ace/range"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("./python_highlight_rules").PythonHighlightRules,o=e("./folding/pythonic").FoldMode,u=e("../range").Range,a=function(){this.HighlightRules=s,this.foldingRules=new o("\\:")};r.inherits(a,i),function(){this.lineCommentStart="#",this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.getTokenizer().getLineTokens(t,e),s=i.tokens;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"){var o=t.match(/^.*[\{\(\[\:]\s*$/);o&&(r+=n)}return r};var e={pass:1,"return":1,raise:1,"break":1,"continue":1};this.checkOutdent=function(t,n,r){if(r!=="\r\n"&&r!=="\r"&&r!=="\n")return!1;var i=this.getTokenizer().getLineTokens(n.trim(),t).tokens;if(!i)return!1;do var s=i.pop();while(s&&(s.type=="comment"||s.type=="text"&&s.value.match(/^\s+$/)));return s?s.type=="keyword"&&e[s.value]:!1},this.autoOutdent=function(e,t,n){n+=1;var r=this.$getIndent(t.getLine(n)),i=t.getTabString();r.slice(-i.length)==i&&t.remove(new u(n,r.length-i.length,n,r.length))},this.$id="ace/mode/python"}.call(a.prototype),t.Mode=a}),ace.define("ace/mode/python_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="and|as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|loop|not|or|pass|print|raise|return|try|while|with|yield",t="True|False|None|NotImplemented|Ellipsis|__debug__",n="abs|divmod|input|open|staticmethod|all|enumerate|int|ord|str|any|eval|isinstance|pow|sum|basestring|execfile|issubclass|print|super|binfile|iter|property|tuple|bool|filter|len|range|type|bytearray|float|list|raw_input|unichr|callable|format|locals|reduce|unicode|chr|frozenset|long|reload|vars|classmethod|getattr|map|repr|xrange|cmp|globals|max|reversed|zip|compile|hasattr|memoryview|round|__import__|complex|hash|min|set|apply|delattr|help|next|setattr|buffer|dict|hex|object|slice|coerce|dir|id|oct|sorted|intern",r=this.createKeywordMapper({"invalid.deprecated":"debugger","support.function":n,"constant.language":t,keyword:e},"identifier"),i="(?:r|u|ur|R|U|UR|Ur|uR)?",s="(?:(?:[1-9]\\d*)|(?:0))",o="(?:0[oO]?[0-7]+)",u="(?:0[xX][\\dA-Fa-f]+)",a="(?:0[bB][01]+)",f="(?:"+s+"|"+o+"|"+u+"|"+a+")",l="(?:[eE][+-]?\\d+)",c="(?:\\.\\d+)",h="(?:\\d+)",p="(?:(?:"+h+"?"+c+")|(?:"+h+"\\.))",d="(?:(?:"+p+"|"+h+")"+l+")",v="(?:"+d+"|"+p+")",m="\\\\(x[0-9A-Fa-f]{2}|[0-7]{3}|[\\\\abfnrtv'\"]|U[0-9A-Fa-f]{8}|u[0-9A-Fa-f]{4})";this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string",regex:i+'"{3}',next:"qqstring3"},{token:"string",regex:i+'"(?=.)',next:"qqstring"},{token:"string",regex:i+"'{3}",next:"qstring3"},{token:"string",regex:i+"'(?=.)",next:"qstring"},{token:"constant.numeric",regex:"(?:"+v+"|\\d+)[jJ]\\b"},{token:"constant.numeric",regex:v},{token:"constant.numeric",regex:f+"[lL]\\b"},{token:"constant.numeric",regex:f+"\\b"},{token:r,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|="},{token:"paren.lparen",regex:"[\\[\\(\\{]"},{token:"paren.rparen",regex:"[\\]\\)\\}]"},{token:"text",regex:"\\s+"}],qqstring3:[{token:"constant.language.escape",regex:m},{token:"string",regex:'"{3}',next:"start"},{defaultToken:"string"}],qstring3:[{token:"constant.language.escape",regex:m},{token:"string",regex:"'{3}",next:"start"},{defaultToken:"string"}],qqstring:[{token:"constant.language.escape",regex:m},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"},{defaultToken:"string"}],qstring:[{token:"constant.language.escape",regex:m},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"},{defaultToken:"string"}]}};r.inherits(s,i),t.PythonHighlightRules=s}),ace.define("ace/mode/folding/pythonic",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=t.FoldMode=function(e){this.foldingStartMarker=new RegExp("([\\[{])(?:\\s*)$|("+e+")(?:\\s*)(?:#.*)?$")};r.inherits(s,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i)return i[1]?this.openingBracketBlock(e,i[1],n,i.index):i[2]?this.indentationBlock(e,n,i.index+i[2].length):this.indentationBlock(e,n)}}.call(s.prototype)})

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
ace.define("ace/snippets/clojure",["require","exports","module"],function(e,t,n){t.snippetText='snippet comm\n (comment\n ${1}\n )\nsnippet condp\n (condp ${1:pred} ${2:expr}\n ${3})\nsnippet def\n (def ${1})\nsnippet defm\n (defmethod ${1:multifn} "${2:doc-string}" ${3:dispatch-val} [${4:args}]\n ${5})\nsnippet defmm\n (defmulti ${1:name} "${2:doc-string}" ${3:dispatch-fn})\nsnippet defma\n (defmacro ${1:name} "${2:doc-string}" ${3:dispatch-fn})\nsnippet defn\n (defn ${1:name} "${2:doc-string}" [${3:arg-list}]\n ${4})\nsnippet defp\n (defprotocol ${1:name}\n ${2})\nsnippet defr\n (defrecord ${1:name} [${2:fields}]\n ${3:protocol}\n ${4})\nsnippet deft\n (deftest ${1:name}\n (is (= ${2:assertion})))\n ${3})\nsnippet is\n (is (= ${1} ${2}))\nsnippet defty\n (deftype ${1:Name} [${2:fields}]\n ${3:Protocol}\n ${4})\nsnippet doseq\n (doseq [${1:elem} ${2:coll}]\n ${3})\nsnippet fn\n (fn [${1:arg-list}] ${2})\nsnippet if\n (if ${1:test-expr}\n ${2:then-expr}\n ${3:else-expr})\nsnippet if-let \n (if-let [${1:result} ${2:test-expr}]\n (${3:then-expr} $1)\n (${4:else-expr}))\nsnippet imp\n (:import [${1:package}])\n & {:keys [${1:keys}] :or {${2:defaults}}}\nsnippet let\n (let [${1:name} ${2:expr}]\n ${3})\nsnippet letfn\n (letfn [(${1:name) [${2:args}]\n ${3})])\nsnippet map\n (map ${1:func} ${2:coll})\nsnippet mapl\n (map #(${1:lambda}) ${2:coll})\nsnippet met\n (${1:name} [${2:this} ${3:args}]\n ${4})\nsnippet ns\n (ns ${1:name}\n ${2})\nsnippet dotimes\n (dotimes [_ 10]\n (time\n (dotimes [_ ${1:times}]\n ${2})))\nsnippet pmethod\n (${1:name} [${2:this} ${3:args}])\nsnippet refer\n (:refer-clojure :exclude [${1}])\nsnippet require\n (:require [${1:namespace} :as [${2}]])\nsnippet use\n (:use [${1:namespace} :only [${2}]])\nsnippet print\n (println ${1})\nsnippet reduce\n (reduce ${1:(fn [p n] ${3})} ${2})\nsnippet when\n (when ${1:test} ${2:body})\nsnippet when-let\n (when-let [${1:result} ${2:test}]\n ${3:body})\n',t.scope="clojure"})

View file

@ -1 +0,0 @@
ace.define("ace/snippets/coffee",["require","exports","module"],function(e,t,n){t.snippetText="# Closure loop\nsnippet forindo\n for ${1:name} in ${2:array}\n do ($1) ->\n ${3:// body}\n# Array comprehension\nsnippet fora\n for ${1:name} in ${2:array}\n ${3:// body...}\n# Object comprehension\nsnippet foro\n for ${1:key}, ${2:value} of ${3:object}\n ${4:// body...}\n# Range comprehension (inclusive)\nsnippet forr\n for ${1:name} in [${2:start}..${3:finish}]\n ${4:// body...}\nsnippet forrb\n for ${1:name} in [${2:start}..${3:finish}] by ${4:step}\n ${5:// body...}\n# Range comprehension (exclusive)\nsnippet forrex\n for ${1:name} in [${2:start}...${3:finish}]\n ${4:// body...}\nsnippet forrexb\n for ${1:name} in [${2:start}...${3:finish}] by ${4:step}\n ${5:// body...}\n# Function\nsnippet fun\n (${1:args}) ->\n ${2:// body...}\n# Function (bound)\nsnippet bfun\n (${1:args}) =>\n ${2:// body...}\n# Class\nsnippet cla class ..\n class ${1:`substitute(Filename(), '\\(_\\|^\\)\\(.\\)', '\\u\\2', 'g')`}\n ${2}\nsnippet cla class .. constructor: ..\n class ${1:`substitute(Filename(), '\\(_\\|^\\)\\(.\\)', '\\u\\2', 'g')`}\n constructor: (${2:args}) ->\n ${3}\n\n ${4}\nsnippet cla class .. extends ..\n class ${1:`substitute(Filename(), '\\(_\\|^\\)\\(.\\)', '\\u\\2', 'g')`} extends ${2:ParentClass}\n ${3}\nsnippet cla class .. extends .. constructor: ..\n class ${1:`substitute(Filename(), '\\(_\\|^\\)\\(.\\)', '\\u\\2', 'g')`} extends ${2:ParentClass}\n constructor: (${3:args}) ->\n ${4}\n\n ${5}\n# If\nsnippet if\n if ${1:condition}\n ${2:// body...}\n# If __ Else\nsnippet ife\n if ${1:condition}\n ${2:// body...}\n else\n ${3:// body...}\n# Else if\nsnippet elif\n else if ${1:condition}\n ${2:// body...}\n# Ternary If\nsnippet ifte\n if ${1:condition} then ${2:value} else ${3:other}\n# Unless\nsnippet unl\n ${1:action} unless ${2:condition}\n# Switch\nsnippet swi\n switch ${1:object}\n when ${2:value}\n ${3:// body...}\n\n# Log\nsnippet log\n console.log ${1}\n# Try __ Catch\nsnippet try\n try\n ${1}\n catch ${2:error}\n ${3}\n# Require\nsnippet req\n ${2:$1} = require '${1:sys}'${3}\n# Export\nsnippet exp\n ${1:root} = exports ? this\n",t.scope="coffee"})

View file

@ -1 +0,0 @@
ace.define("ace/snippets/javascript",["require","exports","module"],function(e,t,n){t.snippetText='# Prototype\nsnippet proto\n ${1:class_name}.prototype.${2:method_name} = function(${3:first_argument}) {\n ${4:// body...}\n };\n# Function\nsnippet fun\n function ${1?:function_name}(${2:argument}) {\n ${3:// body...}\n }\n# Anonymous Function\nregex /((=)\\s*|(:)\\s*|(\\()|\\b)/f/(\\))?/\nsnippet f\n function${M1?: ${1:functionName}}($2) {\n ${0:$TM_SELECTED_TEXT}\n }${M2?;}${M3?,}${M4?)}\n# Immediate function\ntrigger \\(?f\\(\nendTrigger \\)?\nsnippet f(\n (function(${1}) {\n ${0:${TM_SELECTED_TEXT:/* code */}}\n }(${1}));\n# if\nsnippet if\n if (${1:true}) {\n ${0}\n }\n# if ... else\nsnippet ife\n if (${1:true}) {\n ${2}\n } else {\n ${0}\n }\n# tertiary conditional\nsnippet ter\n ${1:/* condition */} ? ${2:a} : ${3:b}\n# switch\nsnippet switch\n switch (${1:expression}) {\n case \'${3:case}\':\n ${4:// code}\n break;\n ${5}\n default:\n ${2:// code}\n }\n# case\nsnippet case\n case \'${1:case}\':\n ${2:// code}\n break;\n ${3}\n\n# while (...) {...}\nsnippet wh\n while (${1:/* condition */}) {\n ${0:/* code */}\n }\n# try\nsnippet try\n try {\n ${0:/* code */}\n } catch (e) {}\n# do...while\nsnippet do\n do {\n ${2:/* code */}\n } while (${1:/* condition */});\n# Object Method\nsnippet :f\nregex /([,{[])|^\\s*/:f/\n ${1:method_name}: function(${2:attribute}) {\n ${0}\n }${3:,}\n# setTimeout function\nsnippet setTimeout\nregex /\\b/st|timeout|setTimeo?u?t?/\n setTimeout(function() {${3:$TM_SELECTED_TEXT}}, ${1:10});\n# Get Elements\nsnippet gett\n getElementsBy${1:TagName}(\'${2}\')${3}\n# Get Element\nsnippet get\n getElementBy${1:Id}(\'${2}\')${3}\n# console.log (Firebug)\nsnippet cl\n console.log(${1});\n# return\nsnippet ret\n return ${1:result}\n# for (property in object ) { ... }\nsnippet fori\n for (var ${1:prop} in ${2:Things}) {\n ${0:$2[$1]}\n }\n# hasOwnProperty\nsnippet has\n hasOwnProperty(${1})\n# docstring\nsnippet /**\n /**\n * ${1:description}\n *\n */\nsnippet @par\nregex /^\\s*\\*\\s*/@(para?m?)?/\n @param {${1:type}} ${2:name} ${3:description}\nsnippet @ret\n @return {${1:type}} ${2:description}\n# JSON.parse\nsnippet jsonp\n JSON.parse(${1:jstr});\n# JSON.stringify\nsnippet jsons\n JSON.stringify(${1:object});\n# self-defining function\nsnippet sdf\n var ${1:function_name} = function(${2:argument}) {\n ${3:// initial code ...}\n\n $1 = function($2) {\n ${4:// main code}\n };\n }\n# singleton\nsnippet sing\n function ${1:Singleton} (${2:argument}) {\n // the cached instance\n var instance;\n\n // rewrite the constructor\n $1 = function $1($2) {\n return instance;\n };\n \n // carry over the prototype properties\n $1.prototype = this;\n\n // the instance\n instance = new $1();\n\n // reset the constructor pointer\n instance.constructor = $1;\n\n ${3:// code ...}\n\n return instance;\n }\n# class\nsnippet class\nregex /^\\s*/clas{0,2}/\n var ${1:class} = function(${20}) {\n $40$0\n };\n \n (function() {\n ${60:this.prop = ""}\n }).call(${1:class}.prototype);\n \n exports.${1:class} = ${1:class};\n# \nsnippet for-\n for (var ${1:i} = ${2:Things}.length; ${1:i}--; ) {\n ${0:${2:Things}[${1:i}];}\n }\n# for (...) {...}\nsnippet for\n for (var ${1:i} = 0; $1 < ${2:Things}.length; $1++) {\n ${3:$2[$1]}$0\n }\n# for (...) {...} (Improved Native For-Loop)\nsnippet forr\n for (var ${1:i} = ${2:Things}.length - 1; $1 >= 0; $1--) {\n ${3:$2[$1]}$0\n }\n\n\n#modules\nsnippet def\n ace.define(function(require, exports, module) {\n "use strict";\n var ${1/.*\\///} = require("${1}");\n \n $TM_SELECTED_TEXT\n });\nsnippet req\nguard ^\\s*\n var ${1/.*\\///} = require("${1}");\n $0\nsnippet requ\nguard ^\\s*\n var ${1/.*\\/(.)/\\u$1/} = require("${1}").${1/.*\\/(.)/\\u$1/};\n $0\n',t.scope="javascript"})

View file

@ -1 +0,0 @@
ace.define("ace/snippets/lua",["require","exports","module"],function(e,t,n){t.snippetText="snippet #!\n #!/usr/bin/env lua\n $1\nsnippet local\n local ${1:x} = ${2:1}\nsnippet fun\n function ${1:fname}(${2:...})\n ${3:-- body}\n end\nsnippet for\n for ${1:i}=${2:1},${3:10} do\n ${4:print(i)}\n end\nsnippet forp\n for ${1:i},${2:v} in pairs(${3:table_name}) do\n ${4:-- body}\n end\nsnippet fori\n for ${1:i},${2:v} in ipairs(${3:table_name}) do\n ${4:-- body}\n end\n",t.scope="lua"})

View file

@ -1 +0,0 @@
ace.define("ace/snippets/luapage",["require","exports","module"],function(e,t,n){t.snippetText="",t.scope="luapage"})

View file

@ -1 +0,0 @@
ace.define("ace/snippets/plain_text",["require","exports","module"],function(e,t,n){t.snippetText="",t.scope="plain_text"})

View file

@ -1 +0,0 @@
ace.define("ace/snippets/python",["require","exports","module"],function(e,t,n){t.snippetText='snippet #!\n #!/usr/bin/env python\nsnippet imp\n import ${1:module}\nsnippet from\n from ${1:package} import ${2:module}\n# Module Docstring\nsnippet docs\n \'\'\'\n File: ${1:FILENAME:file_name}\n Author: ${2:author}\n Description: ${3}\n \'\'\'\nsnippet wh\n while ${1:condition}:\n ${2:# TODO: write code...}\n# dowh - does the same as do...while in other languages\nsnippet dowh\n while True:\n ${1:# TODO: write code...}\n if ${2:condition}:\n break\nsnippet with\n with ${1:expr} as ${2:var}:\n ${3:# TODO: write code...}\n# New Class\nsnippet cl\n class ${1:ClassName}(${2:object}):\n """${3:docstring for $1}"""\n def __init__(self, ${4:arg}):\n ${5:super($1, self).__init__()}\n self.$4 = $4\n ${6}\n# New Function\nsnippet def\n def ${1:fname}(${2:`indent(\'.\') ? \'self\' : \'\'`}):\n """${3:docstring for $1}"""\n ${4:# TODO: write code...}\nsnippet deff\n def ${1:fname}(${2:`indent(\'.\') ? \'self\' : \'\'`}):\n ${3:# TODO: write code...}\n# New Method\nsnippet defs\n def ${1:mname}(self, ${2:arg}):\n ${3:# TODO: write code...}\n# New Property\nsnippet property\n def ${1:foo}():\n doc = "${2:The $1 property.}"\n def fget(self):\n ${3:return self._$1}\n def fset(self, value):\n ${4:self._$1 = value}\n# Ifs\nsnippet if\n if ${1:condition}:\n ${2:# TODO: write code...}\nsnippet el\n else:\n ${1:# TODO: write code...}\nsnippet ei\n elif ${1:condition}:\n ${2:# TODO: write code...}\n# For\nsnippet for\n for ${1:item} in ${2:items}:\n ${3:# TODO: write code...}\n# Encodes\nsnippet cutf8\n # -*- coding: utf-8 -*-\nsnippet clatin1\n # -*- coding: latin-1 -*-\nsnippet cascii\n # -*- coding: ascii -*-\n# Lambda\nsnippet ld\n ${1:var} = lambda ${2:vars} : ${3:action}\nsnippet .\n self.\nsnippet try Try/Except\n try:\n ${1:# TODO: write code...}\n except ${2:Exception}, ${3:e}:\n ${4:raise $3}\nsnippet try Try/Except/Else\n try:\n ${1:# TODO: write code...}\n except ${2:Exception}, ${3:e}:\n ${4:raise $3}\n else:\n ${5:# TODO: write code...}\nsnippet try Try/Except/Finally\n try:\n ${1:# TODO: write code...}\n except ${2:Exception}, ${3:e}:\n ${4:raise $3}\n finally:\n ${5:# TODO: write code...}\nsnippet try Try/Except/Else/Finally\n try:\n ${1:# TODO: write code...}\n except ${2:Exception}, ${3:e}:\n ${4:raise $3}\n else:\n ${5:# TODO: write code...}\n finally:\n ${6:# TODO: write code...}\n# if __name__ == \'__main__\':\nsnippet ifmain\n if __name__ == \'__main__\':\n ${1:main()}\n# __magic__\nsnippet _\n __${1:init}__${2}\n# python debugger (pdb)\nsnippet pdb\n import pdb; pdb.set_trace()\n# ipython debugger (ipdb)\nsnippet ipdb\n import ipdb; ipdb.set_trace()\n# ipython debugger (pdbbb)\nsnippet pdbbb\n import pdbpp; pdbpp.set_trace()\nsnippet pprint\n import pprint; pprint.pprint(${1})${2}\nsnippet "\n """\n ${1:doc}\n """\n# test function/method\nsnippet test\n def test_${1:description}(${2:self}):\n ${3:# TODO: write code...}\n# test case\nsnippet testcase\n class ${1:ExampleCase}(unittest.TestCase):\n \n def test_${2:description}(self):\n ${3:# TODO: write code...}\nsnippet fut\n from __future__ import ${1}\n#getopt\nsnippet getopt\n try:\n # Short option syntax: "hv:"\n # Long option syntax: "help" or "verbose="\n opts, args = getopt.getopt(sys.argv[1:], "${1:short_options}", [${2:long_options}])\n \n except getopt.GetoptError, err:\n # Print debug info\n print str(err)\n ${3:error_action}\n\n for option, argument in opts:\n if option in ("-h", "--help"):\n ${4}\n elif option in ("-v", "--verbose"):\n verbose = argument\n',t.scope="python"})

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
ace.define("ace/snippets/snippets",["require","exports","module"],function(e,t,n){t.snippetText="# snippets for making snippets :)\nsnippet snip\n snippet ${1:trigger}\n ${2}\nsnippet msnip\n snippet ${1:trigger} ${2:description}\n ${3}\nsnippet v\n {VISUAL}\n",t.scope="snippets"})

View file

@ -1 +0,0 @@
ace.define("ace/snippets/text",["require","exports","module"],function(e,t,n){t.snippetText="",t.scope="text"})

View file

@ -1 +0,0 @@
ace.define("ace/theme/textmate",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-tm",t.cssText='.ace-tm .ace_gutter {background: #f0f0f0;color: #333;}.ace-tm .ace_print-margin {width: 1px;background: #e8e8e8;}.ace-tm .ace_fold {background-color: #6B72E6;}.ace-tm {background-color: #FFFFFF;color: black;}.ace-tm .ace_cursor {color: black;}.ace-tm .ace_invisible {color: rgb(191, 191, 191);}.ace-tm .ace_storage,.ace-tm .ace_keyword {color: blue;}.ace-tm .ace_constant {color: rgb(197, 6, 11);}.ace-tm .ace_constant.ace_buildin {color: rgb(88, 72, 246);}.ace-tm .ace_constant.ace_language {color: rgb(88, 92, 246);}.ace-tm .ace_constant.ace_library {color: rgb(6, 150, 14);}.ace-tm .ace_invalid {background-color: rgba(255, 0, 0, 0.1);color: red;}.ace-tm .ace_support.ace_function {color: rgb(60, 76, 114);}.ace-tm .ace_support.ace_constant {color: rgb(6, 150, 14);}.ace-tm .ace_support.ace_type,.ace-tm .ace_support.ace_class {color: rgb(109, 121, 222);}.ace-tm .ace_keyword.ace_operator {color: rgb(104, 118, 135);}.ace-tm .ace_string {color: rgb(3, 106, 7);}.ace-tm .ace_comment {color: rgb(76, 136, 107);}.ace-tm .ace_comment.ace_doc {color: rgb(0, 102, 255);}.ace-tm .ace_comment.ace_doc.ace_tag {color: rgb(128, 159, 191);}.ace-tm .ace_constant.ace_numeric {color: rgb(0, 0, 205);}.ace-tm .ace_variable {color: rgb(49, 132, 149);}.ace-tm .ace_xml-pe {color: rgb(104, 104, 91);}.ace-tm .ace_entity.ace_name.ace_function {color: #0000A2;}.ace-tm .ace_heading {color: rgb(12, 7, 255);}.ace-tm .ace_list {color:rgb(185, 6, 144);}.ace-tm .ace_meta.ace_tag {color:rgb(0, 22, 142);}.ace-tm .ace_string.ace_regex {color: rgb(255, 0, 0)}.ace-tm .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-tm.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px white;border-radius: 2px;}.ace-tm .ace_marker-layer .ace_step {background: rgb(252, 255, 0);}.ace-tm .ace_marker-layer .ace_stack {background: rgb(164, 229, 101);}.ace-tm .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-tm .ace_marker-layer .ace_active-line {background: rgba(0, 0, 0, 0.07);}.ace-tm .ace_gutter-active-line {background-color : #dcdcdc;}.ace-tm .ace_marker-layer .ace_selected-word {background: rgb(250, 250, 255);border: 1px solid rgb(200, 200, 250);}.ace-tm .ace_indent-guide {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;}';var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)})

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -33,7 +33,7 @@ module.exports = class CocoRouter extends Backbone.Router
'admin/clas': go('admin/CLAsView') 'admin/clas': go('admin/CLAsView')
'admin/employers': go('admin/EmployersListView') 'admin/employers': go('admin/EmployersListView')
'admin/files': go('admin/FilesView') 'admin/files': go('admin/FilesView')
'admin/analytics/users': go('admin/AnalyticsUsersView') 'admin/analytics': go('admin/AnalyticsView')
'admin/analytics/subscriptions': go('admin/AnalyticsSubscriptionsView') 'admin/analytics/subscriptions': go('admin/AnalyticsSubscriptionsView')
'admin/level-sessions': go('admin/LevelSessionsView') 'admin/level-sessions': go('admin/LevelSessionsView')
'admin/users': go('admin/UsersView') 'admin/users': go('admin/UsersView')

View file

@ -31,7 +31,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
contact: "Kontakt" contact: "Kontakt"
twitter_follow: "Følg" twitter_follow: "Følg"
teachers: "Lærere" teachers: "Lærere"
# careers: "Careers" careers: "Karrierer"
modal: modal:
close: "Luk" close: "Luk"
@ -80,7 +80,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
adjust_volume: "Indstil lydstyrke" adjust_volume: "Indstil lydstyrke"
campaign_multiplayer: "Multiplayer Arenaer" campaign_multiplayer: "Multiplayer Arenaer"
campaign_multiplayer_description: "... hvor du koder ansigt-til-ansigt imod andre spillere." campaign_multiplayer_description: "... hvor du koder ansigt-til-ansigt imod andre spillere."
# campaign_old_multiplayer: "(Deprecated) Old Multiplayer Arenas" campaign_old_multiplayer: "(Forældet) Gammel version af Multiplayer Arenaer"
# campaign_old_multiplayer_description: "Relics of a more civilized age. No simulations are run for these older, hero-less multiplayer arenas." # campaign_old_multiplayer_description: "Relics of a more civilized age. No simulations are run for these older, hero-less multiplayer arenas."
share_progress_modal: share_progress_modal:
@ -159,7 +159,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
accepted: "Accepteret" accepted: "Accepteret"
rejected: "Afvist" rejected: "Afvist"
withdrawn: "Trukket tilbage" withdrawn: "Trukket tilbage"
# accept: "Accept" accept: "Accepter"
# reject: "Reject" # reject: "Reject"
# withdraw: "Withdraw" # withdraw: "Withdraw"
submitter: "Indsender" submitter: "Indsender"
@ -196,7 +196,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
player: "Spiller" player: "Spiller"
player_level: "Niveau" # Like player level 5, not like level: Dungeons of Kithgard player_level: "Niveau" # Like player level 5, not like level: Dungeons of Kithgard
warrior: "Krigsherre" warrior: "Krigsherre"
# ranger: "Ranger" ranger: "Bueskytte"
wizard: "Troldmand" wizard: "Troldmand"
units: units:
@ -217,8 +217,8 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
play_level: play_level:
done: "Færdig" done: "Færdig"
# next_game: "Next game" next_game: "Næste spil"
# show_menu: "Show game menu" show_menu: "Vis spil menu"
home: "Hjem" # Not used any more, will be removed soon. home: "Hjem" # Not used any more, will be removed soon.
level: "Bane" # Like "Level: Dungeons of Kithgard" level: "Bane" # Like "Level: Dungeons of Kithgard"
skip: "Spring over" skip: "Spring over"
@ -251,7 +251,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
victory_saving_progress: "Gemmer fremskridt" victory_saving_progress: "Gemmer fremskridt"
victory_go_home: "Gå hjem" victory_go_home: "Gå hjem"
victory_review: "Fortæl os mere!" victory_review: "Fortæl os mere!"
# victory_review_placeholder: "How was the level?" victory_review_placeholder: "Hvordan var levelet?"
victory_hour_of_code_done: "Er du færdig?" victory_hour_of_code_done: "Er du færdig?"
victory_hour_of_code_done_yes: "Ja, jeg er færdig med min Kodetime!" victory_hour_of_code_done_yes: "Ja, jeg er færdig med min Kodetime!"
victory_experience_gained: "XP tjent" victory_experience_gained: "XP tjent"
@ -260,7 +260,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
victory_viking_code_school: "For dælen det var en svær bane du lige slog! Hvis ikke du allerede er softwareudvikler, så burde du blive det. Du er lige kommet foran i køen til at blive accepteret hos Viking Code School, du kan tage dine evner til det næste niveau og blive en professionel webudvikler på 14 uger." victory_viking_code_school: "For dælen det var en svær bane du lige slog! Hvis ikke du allerede er softwareudvikler, så burde du blive det. Du er lige kommet foran i køen til at blive accepteret hos Viking Code School, du kan tage dine evner til det næste niveau og blive en professionel webudvikler på 14 uger."
victory_become_a_viking: "Bliv en Viking" victory_become_a_viking: "Bliv en Viking"
# victory_bloc: "Great work! Your skills are improving, and someone's taking notice. If you've considered becoming a software developer, this may be your lucky day. Bloc is an online bootcamp that pairs you 1-on-1 with an expert mentor who will help train you into a professional developer! By beating A Mayhem of Munchkins, you're now eligible for a $500 price reduction with the code: CCRULES" # victory_bloc: "Great work! Your skills are improving, and someone's taking notice. If you've considered becoming a software developer, this may be your lucky day. Bloc is an online bootcamp that pairs you 1-on-1 with an expert mentor who will help train you into a professional developer! By beating A Mayhem of Munchkins, you're now eligible for a $500 price reduction with the code: CCRULES"
# victory_bloc_cta: "Meet your mentor learn about Bloc" victory_bloc_cta: "Mød din mentor - Hør mere om Bloc"
guide_title: "Instruktioner" guide_title: "Instruktioner"
tome_minion_spells: "Dine Minions' besværgelser" # Only in old-style levels. tome_minion_spells: "Dine Minions' besværgelser" # Only in old-style levels.
tome_read_only_spells: "Læsebesværgelser" # Only in old-style levels. tome_read_only_spells: "Læsebesværgelser" # Only in old-style levels.
@ -298,7 +298,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
tip_scrub_shortcut: "Brug Ctrl+[ og Ctrl+] til at spole tilbage og frem." tip_scrub_shortcut: "Brug Ctrl+[ og Ctrl+] til at spole tilbage og frem."
tip_guide_exists: "Klik på guiden i spilmenuen (i toppen af siden) for brugbar info." tip_guide_exists: "Klik på guiden i spilmenuen (i toppen af siden) for brugbar info."
tip_open_source: "CodeCombat er 100% open source!" tip_open_source: "CodeCombat er 100% open source!"
# tip_tell_friends: "Enjoying CodeCombat? Tell your friends about us!" tip_tell_friends: "Kan du lide CodeCombat? Fortæl dine venner om os!"
tip_beta_launch: "CodeCombat søsatte sin beta i oktober, 2013." tip_beta_launch: "CodeCombat søsatte sin beta i oktober, 2013."
tip_think_solution: "Tænk på løsningen, ikke problemet." tip_think_solution: "Tænk på løsningen, ikke problemet."
tip_theory_practice: "I teorien er der ingen forskel på teori og praksis. Men i praksis er der. - Yogi Bjørn" tip_theory_practice: "I teorien er der ingen forskel på teori og praksis. Men i praksis er der. - Yogi Bjørn"
@ -327,23 +327,23 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..." # tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower." # tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds" # tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code." tip_no_code: "Ingen kode er hurtigerer end ingen kode."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries" tip_code_never_lies: "Kode lyver aldrig, kommentarer gør nogle gange. - Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable." tip_reusable_software: "Før software kan være genbrugeligt skal det først være brugbart."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //" # tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates" # tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# tip_source_code: "I want to change the world but they would not give me the source code." # tip_source_code: "I want to change the world but they would not give me the source code."
# tip_javascript_java: "Java is to JavaScript what Car is to Carpet. - Chris Heilmann" # tip_javascript_java: "Java is to JavaScript what Car is to Carpet. - Chris Heilmann"
# tip_move_forward: "Whatever you do, keep moving forward. - Martin Luther King Jr." tip_move_forward: "Hvad end du gør, så bliv ved med at rykke fremad. - Martin Luther King Jr."
tip_google: "Har du et problem du ikke kan løse? Google det!" tip_google: "Har du et problem du ikke kan løse? Google det!"
tip_adding_evil: "Tilføjer et strejf af ondskab.." tip_adding_evil: "Tilføjer et strejf af ondskab.."
# tip_hate_computers: "That's the thing about people who think they hate computers. What they really hate is lousy programmers. - Larry Niven" # tip_hate_computers: "That's the thing about people who think they hate computers. What they really hate is lousy programmers. - Larry Niven"
# tip_open_source_contribute: "You can help CodeCombat improve!" # tip_open_source_contribute: "You can help CodeCombat improve!"
# tip_recurse: "To iterate is human, to recurse divine. - L. Peter Deutsch" # tip_recurse: "To iterate is human, to recurse divine. - L. Peter Deutsch"
# tip_free_your_mind: "You have to let it all go, Neo. Fear, doubt, and disbelief. Free your mind. - Morpheus" # tip_free_your_mind: "You have to let it all go, Neo. Fear, doubt, and disbelief. Free your mind. - Morpheus"
# tip_strong_opponents: "Even the strongest of opponents always has a weakness. - Itachi Uchiha" tip_strong_opponents: "Selv de stærkeste modstandere har en svaghed. - Itachi Uchiha"
tip_paper_and_pen: "Før du starter med at programmere, kan du altid sætte dig ned med et stykke papir og blyant." tip_paper_and_pen: "Før du starter med at programmere, kan du altid sætte dig ned med et stykke papir og blyant."
# tip_solve_then_write: "First, solve the problem. Then, write the code. - John Johnson" tip_solve_then_write: "Først, løs problemet, derefter skriv koden. - John Johnson"
game_menu: game_menu:
inventory_tab: "Dine ting" inventory_tab: "Dine ting"
@ -367,14 +367,14 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
# view_other_solutions: "View Leaderboards" # view_other_solutions: "View Leaderboards"
# scores: "Scores" # scores: "Scores"
# top_players: "Top Players by" # top_players: "Top Players by"
# day: "Today" day: "Idag"
# week: "This Week" week: "Denne uge"
# all: "All-Time" # all: "All-Time"
# time: "Time" time: "Tid"
# damage_taken: "Damage Taken" # damage_taken: "Damage Taken"
# damage_dealt: "Damage Dealt" # damage_dealt: "Damage Dealt"
difficulty: "Sværhedsgrad" difficulty: "Sværhedsgrad"
# gold_collected: "Gold Collected" gold_collected: "Guld samlet"
# inventory: # inventory:
# choose_inventory: "Equip Items" # choose_inventory: "Equip Items"
@ -489,43 +489,43 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
# subscribe_prepaid: "Click Subscribe to use prepaid code" # subscribe_prepaid: "Click Subscribe to use prepaid code"
# using_prepaid: "Using prepaid code for monthly subscription" # using_prepaid: "Using prepaid code for monthly subscription"
# choose_hero: choose_hero:
# choose_hero: "Choose Your Hero" choose_hero: "Vælg din helt"
# programming_language: "Programming Language" programming_language: "Programmerings sprog"
# programming_language_description: "Which programming language do you want to use?" programming_language_description: "Hvilket programmerings sprog har du lyst til at bruge?"
# default: "Default" default: "Standard"
# experimental: "Experimental" experimental: "Experimental"
# python_blurb: "Simple yet powerful, great for beginners and experts." python_blurb: "Simplet, dog stærkt, godt for begyndere og eksperter."
# javascript_blurb: "The language of the web. (Not the same as Java.)" javascript_blurb: "Internettets sprog. (Ikke det samme som Java.)"
# coffeescript_blurb: "Nicer JavaScript syntax." coffeescript_blurb: "Pænere JavaScript syntax."
# clojure_blurb: "A modern Lisp." clojure_blurb: "En moderne version af Lisp."
# lua_blurb: "Game scripting language." lua_blurb: " Spil scripting sprog."
# io_blurb: "Simple but obscure." # io_blurb: "Simple but obscure."
# status: "Status" status: "Status"
# hero_type: "Type" hero_type: "Type"
# weapons: "Weapons" weapons: "Våben"
# weapons_warrior: "Swords - Short Range, No Magic" weapons_warrior: "Sværd - Kort afstand, Ingen Magi"
# weapons_ranger: "Crossbows, Guns - Long Range, No Magic" weapons_ranger: "Armbryst, Skydevåben - Lang afstand, Ingen Magi"
# weapons_wizard: "Wands, Staffs - Long Range, Magic" weapons_wizard: "Tryllestave, Stave - Lang afstand, Magi"
# attack: "Damage" # Can also translate as "Attack" # attack: "Damage" # Can also translate as "Attack"
# health: "Health" health: "Liv"
# speed: "Speed" speed: "Fart"
# regeneration: "Regeneration" regeneration: "Regeneration"
# range: "Range" # As in "attack or visual range" # range: "Range" # As in "attack or visual range"
# blocks: "Blocks" # As in "this shield blocks this much damage" # blocks: "Blocks" # As in "this shield blocks this much damage"
# backstab: "Backstab" # As in "this dagger does this much backstab damage" # backstab: "Backstab" # As in "this dagger does this much backstab damage"
# skills: "Skills" skills: "Færdigheder"
# attack_1: "Deals" # attack_1: "Deals"
# attack_2: "of listed" # attack_2: "of listed"
# attack_3: "weapon damage." # attack_3: "weapon damage."
# health_1: "Gains" # health_1: "Gains"
# health_2: "of listed" # health_2: "of listed"
# health_3: "armor health." # health_3: "armor health."
# speed_1: "Moves at" speed_1: "Rykker med"
# speed_2: "meters per second." speed_2: "meter i sekundet."
# available_for_purchase: "Available for Purchase" # Shows up when you have unlocked, but not purchased, a hero in the hero store available_for_purchase: "Kan nu blive købt" # Shows up when you have unlocked, but not purchased, a hero in the hero store
# level_to_unlock: "Level to unlock:" # Label for which level you have to beat to unlock a particular hero (click a locked hero in the store to see) level_to_unlock: "Level for at låse op:" # Label for which level you have to beat to unlock a particular hero (click a locked hero in the store to see)
# restricted_to_certain_heroes: "Only certain heroes can play this level." restricted_to_certain_heroes: "Kun visse helt kan spille dette level."
# skill_docs: # skill_docs:
# writable: "writable" # Hover over "attack" in Your Skills while playing a level to see most of this # writable: "writable" # Hover over "attack" in Your Skills while playing a level to see most of this

View file

@ -259,8 +259,6 @@
victory_new_item: "New Item" victory_new_item: "New Item"
victory_viking_code_school: "Holy smokes, that was a hard level you just beat! If you aren't already a software developer, you should be. You just got fast-tracked for acceptance with Viking Code School, where you can take your skills to the next level and become a professional web developer in 14 weeks." victory_viking_code_school: "Holy smokes, that was a hard level you just beat! If you aren't already a software developer, you should be. You just got fast-tracked for acceptance with Viking Code School, where you can take your skills to the next level and become a professional web developer in 14 weeks."
victory_become_a_viking: "Become a Viking" victory_become_a_viking: "Become a Viking"
victory_bloc: "Great work! Your skills are improving, and someone's taking notice. If you've considered becoming a software developer, this may be your lucky day. Bloc is an online bootcamp that pairs you 1-on-1 with an expert mentor who will help train you into a professional developer! By beating A Mayhem of Munchkins, you're now eligible for a $500 price reduction with the code: CCRULES"
victory_bloc_cta: "Meet your mentor learn about Bloc"
guide_title: "Guide" guide_title: "Guide"
tome_minion_spells: "Your Minions' Spells" # Only in old-style levels. tome_minion_spells: "Your Minions' Spells" # Only in old-style levels.
tome_read_only_spells: "Read-Only Spells" # Only in old-style levels. tome_read_only_spells: "Read-Only Spells" # Only in old-style levels.
@ -363,7 +361,6 @@
auth_caption: "Save your progress." auth_caption: "Save your progress."
leaderboard: leaderboard:
leaderboard: "Leaderboard"
view_other_solutions: "View Leaderboards" view_other_solutions: "View Leaderboards"
scores: "Scores" scores: "Scores"
top_players: "Top Players by" top_players: "Top Players by"
@ -604,6 +601,10 @@
retrostyle_blurb: "RetroStyle Games" retrostyle_blurb: "RetroStyle Games"
rob_title: "Compiler Engineer" rob_title: "Compiler Engineer"
rob_blurb: "Codes things and stuff" rob_blurb: "Codes things and stuff"
josh_c_title: "Game Designer"
josh_c_blurb: "Designs games"
carlos_title: "Region Manager"
carlos_blurb: "CodeCombat Brazil"
teachers: teachers:
more_info: "More Info for Teachers" more_info: "More Info for Teachers"
@ -895,9 +896,6 @@
send_invites: "Send Invites" send_invites: "Send Invites"
title: "Title" title: "Title"
description: "Description" description: "Description"
languages_available: "Select programming languages available to the class:"
all_lang: "All Languages"
show_progress: "Show student progress to everyone in the class"
creating_class: "Creating class..." creating_class: "Creating class..."
purchasing_course: "Purchasing course..." purchasing_course: "Purchasing course..."
buy_course: "Buy Course" buy_course: "Buy Course"
@ -1212,12 +1210,6 @@
last_earned: "Last Earned" last_earned: "Last Earned"
amount_achieved: "Amount" amount_achieved: "Amount"
achievement: "Achievement" achievement: "Achievement"
category_contributor: "Contributor"
category_ladder: "Ladder"
category_level: "Level"
category_miscellaneous: "Miscellaneous"
category_levels: "Levels"
category_undefined: "Uncategorized"
current_xp_prefix: "" current_xp_prefix: ""
current_xp_postfix: " in total" current_xp_postfix: " in total"
new_xp_prefix: "" new_xp_prefix: ""
@ -1227,8 +1219,6 @@
left_xp_postfix: "" left_xp_postfix: ""
account: account:
recently_played: "Recently Played"
no_recent_games: "No games played during the past two weeks."
payments: "Payments" payments: "Payments"
prepaid_codes: "Prepaid Codes" prepaid_codes: "Prepaid Codes"
purchased: "Purchased" purchased: "Purchased"

View file

@ -839,16 +839,16 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
playtime: "Tiempo de juego" playtime: "Tiempo de juego"
last_played: "Último jugado" last_played: "Último jugado"
leagues_explanation: "Juega en una liga contra otros miembros del clan en estas instancias de arena multijugador." leagues_explanation: "Juega en una liga contra otros miembros del clan en estas instancias de arena multijugador."
# track_concepts1: "Track concepts" track_concepts1: "Haga un seguimiento de los conceptos"
track_concepts2a: "aprendidos por cada estudiante" track_concepts2a: "aprendidos por cada estudiante"
track_concepts2b: "aprendidos por cada miembro" track_concepts2b: "aprendidos por cada miembro"
# track_concepts3a: "Track levels completados por cada estudiante" track_concepts3a: "Haga un seguimiento de los niveles completados por cada estudiante"
# track_concepts3b: "Track levels completados por cada miembro" track_concepts3b: "Haga un seguimiento de los niveles completados por cada miembro"
track_concepts4a: "Ve a tus estudiantes'" track_concepts4a: "Ve a tus estudiantes'"
track_concepts4b: "Ve a tus miembros'" track_concepts4b: "Ve a tus miembros'"
track_concepts5: "soluciones" track_concepts5: "soluciones"
# track_concepts6a: "Sort students by name or progress" track_concepts6a: "Ordene a sus estudiantes por nombre o progreso"
# track_concepts6b: "Sort members by name or progress" track_concepts6b: "Ordene a sus miembros por nombre o progreso"
track_concepts7: "Requiere invitación" track_concepts7: "Requiere invitación"
track_concepts8: "para unirse" track_concepts8: "para unirse"
private_require_sub: "Los clanes privados requieren una subscripción para crearlos o unírseles." private_require_sub: "Los clanes privados requieren una subscripción para crearlos o unírseles."
@ -886,7 +886,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
invite_students: "Invite a sus estudiantes a unirse a este grupo." invite_students: "Invite a sus estudiantes a unirse a este grupo."
invite_link_header: "Enlace para unirse al curso" invite_link_header: "Enlace para unirse al curso"
invite_link_p_1: "Proporciones este enalce a los estudiantes que desee que se unan al curso." invite_link_p_1: "Proporciones este enalce a los estudiantes que desee que se unan al curso."
# invite_link_p_2: "Or have us email them directly:" invite_link_p_2: "O envíenoslos directamente mediante el correo electrónico:"
capacity_used: "Espacios de curso usados:" capacity_used: "Espacios de curso usados:"
enter_emails: "Introducir los emails de los estudiantes a invitar, uno por línea" enter_emails: "Introducir los emails de los estudiantes a invitar, uno por línea"
send_invites: "¿Mandar Invitaciones?" send_invites: "¿Mandar Invitaciones?"
@ -1269,13 +1269,13 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
purchase_button: "Enviar Adquisición" purchase_button: "Enviar Adquisición"
your_codes: "Tus Códigos:" # {change} your_codes: "Tus Códigos:" # {change}
redeem_codes: "Reclamar un Código de Subscripción" redeem_codes: "Reclamar un Código de Subscripción"
# prepaid_code: "Prepaid Code" prepaid_code: "Código Prepagado"
# lookup_code: "Lookup prepaid code" # lookup_code: "Lookup prepaid code"
# apply_account: "Apply to your account" # apply_account: "Apply to your account"
# copy_link: "You can copy the code's link and send it to someone." # copy_link: "You can copy the code's link and send it to someone."
# quantity: "Quantity" quantity: "Cantidad"
# redeemed: "Redeemed" redeemed: "Reclamado"
# no_codes: "No codes yet!" no_codes: "¡Aún sin códigos!"
loading_error: loading_error:
could_not_load: "Error cargando del servidor" could_not_load: "Error cargando del servidor"

View file

@ -71,7 +71,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
choose_inventory: "Naudoti daiktus" choose_inventory: "Naudoti daiktus"
buy_gems: "Pirkti Deimantus" buy_gems: "Pirkti Deimantus"
# subscription_required: "Subscription Required" # subscription_required: "Subscription Required"
# anonymous: "Anonymous Player" anonymous: "Anoniminis Žaidėjas"
level_difficulty: "Sudėtingumas: " level_difficulty: "Sudėtingumas: "
campaign_beginner: "Naujoko kampanija" campaign_beginner: "Naujoko kampanija"
awaiting_levels_adventurer_prefix: "Kiekvieną savaitę sukuriame naujus lygius." awaiting_levels_adventurer_prefix: "Kiekvieną savaitę sukuriame naujus lygius."
@ -225,7 +225,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
game_menu: "Žaidimo meniu" game_menu: "Žaidimo meniu"
guide: "Vedlys" guide: "Vedlys"
restart: "Paleisti iš naujo" restart: "Paleisti iš naujo"
goals: "Tikslai" goals: "Pagalba"
goal: "Tikslas" goal: "Tikslas"
running: "Leidžiama..." running: "Leidžiama..."
success: "Sėkmingai!" success: "Sėkmingai!"
@ -233,7 +233,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
timed_out: "Laikas baigėsi" timed_out: "Laikas baigėsi"
failing: "Nesėkmingai" failing: "Nesėkmingai"
# action_timeline: "Action Timeline" # action_timeline: "Action Timeline"
# click_to_select: "Click on a unit to select it." click_to_select: "Spregtelkite ant veikėjo ar padaro, kad jį pažymėtumėte."
control_bar_multiplayer: "Žaidimas keliese" control_bar_multiplayer: "Žaidimas keliese"
control_bar_join_game: "Prisijungti prie žaidimo" control_bar_join_game: "Prisijungti prie žaidimo"
reload: "Perkrauti" reload: "Perkrauti"
@ -241,7 +241,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
reload_really: "Ar tikrai norite atsukti visą lygį į pradžią?" reload_really: "Ar tikrai norite atsukti visą lygį į pradžią?"
reload_confirm: "Perkrauti viską" reload_confirm: "Perkrauti viską"
victory: "Pergalė" victory: "Pergalė"
# victory_title_prefix: "" victory_title_prefix: ""
victory_title_suffix: " baigta" victory_title_suffix: " baigta"
victory_sign_up: "Užsiregistruokite, kad išsaugotumėte pažangą" victory_sign_up: "Užsiregistruokite, kad išsaugotumėte pažangą"
victory_sign_up_poke: "Norite išsaugoti savo kodą? Sukurkite paskyrą nemokamai!" victory_sign_up_poke: "Norite išsaugoti savo kodą? Sukurkite paskyrą nemokamai!"
@ -299,12 +299,12 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
tip_guide_exists: "Pasirinkite punktą Vedlys žaidimo meniu (puslapio viršuje), jame rasite naudingos informacijos." tip_guide_exists: "Pasirinkite punktą Vedlys žaidimo meniu (puslapio viršuje), jame rasite naudingos informacijos."
tip_open_source: "CodeCombat - 100% atviro kodo!" tip_open_source: "CodeCombat - 100% atviro kodo!"
tip_tell_friends: "Jums patinka CodeCombat? Papasakokite savo draugams!" tip_tell_friends: "Jums patinka CodeCombat? Papasakokite savo draugams!"
# tip_beta_launch: "CodeCombat launched its beta in October, 2013." tip_beta_launch: "CodeCombat Beta versija startavo 2013 m. spalio mėnesį."
tip_think_solution: "Galvok ne apie problemą, o apie sprendimą." tip_think_solution: "Galvok ne apie problemą, o apie sprendimą."
# tip_theory_practice: "In theory, there is no difference between theory and practice. But in practice, there is. - Yogi Berra" tip_theory_practice: "Teoriškai nėra skirtuma tarp teorijos ir praktikos. Praktiškai - yra. - Yogi Berra"
# tip_error_free: "There are two ways to write error-free programs; only the third one works. - Alan Perlis" # 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: "If debugging is the process of removing bugs, then programming must be the process of putting them in. - Edsger W. Dijkstra"
# tip_forums: "Head over to the forums and tell us what you think!" tip_forums: "Aplankykite forumą ir parašykite mums Jūsų nuomonę!"
# tip_baby_coders: "In the future, even babies will be Archmages." # tip_baby_coders: "In the future, even babies will be Archmages."
# tip_morale_improves: "Loading will continue until morale improves." # tip_morale_improves: "Loading will continue until morale improves."
# tip_all_species: "We believe in equal opportunities to learn programming for all species." # tip_all_species: "We believe in equal opportunities to learn programming for all species."
@ -314,13 +314,13 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
# tip_munchkin: "If you don't eat your vegetables, a munchkin will come after you while you're asleep." # tip_munchkin: "If you don't eat your vegetables, a munchkin will come after you while you're asleep."
# tip_binary: "There are only 10 types of people in the world: those who understand binary, and those who don't." # tip_binary: "There are only 10 types of people in the world: those who understand binary, and those who don't."
# tip_commitment_yoda: "A programmer must have the deepest commitment, the most serious mind. ~ Yoda" # tip_commitment_yoda: "A programmer must have the deepest commitment, the most serious mind. ~ Yoda"
# tip_no_try: "Do. Or do not. There is no try. - Yoda" tip_no_try: "Daryk. Arba ne. Jokių 'pabandysiu'. - Yoda"
# tip_patience: "Patience you must have, young Padawan. - Yoda" tip_patience: "Kantrybės turėti turi, jaunasis Padavane. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature." tip_documented_bug: "Dokumentuota klaida nėra klaida; tai programos ypatybė."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela" tip_impossible: "Tai visuomet atrodo neįmanoma tol, kol tai nėra padaryta. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds" # 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" # tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# tip_hardware_problem: "Q: How many programmers does it take to change a light bulb? A: None, it's a hardware problem." tip_hardware_problem: "K: Kiek programuotojų reikia tam, kad įsuktų lemputę? A: Nei vieno, tai 'geležies' problema."
# tip_hofstadters_law: "Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law." # tip_hofstadters_law: "Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law."
# tip_premature_optimization: "Premature optimization is the root of all evil. - Donald Knuth" # tip_premature_optimization: "Premature optimization is the root of all evil. - Donald Knuth"
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson" # tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
@ -335,12 +335,12 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
# tip_source_code: "I want to change the world but they would not give me the source code." # tip_source_code: "I want to change the world but they would not give me the source code."
# tip_javascript_java: "Java is to JavaScript what Car is to Carpet. - Chris Heilmann" # tip_javascript_java: "Java is to JavaScript what Car is to Carpet. - Chris Heilmann"
# tip_move_forward: "Whatever you do, keep moving forward. - Martin Luther King Jr." # tip_move_forward: "Whatever you do, keep moving forward. - Martin Luther King Jr."
# tip_google: "Have a problem you can't solve? Google it!" tip_google: "Turi problemą kurios negali išspręsti? Pagooglink!"
# tip_adding_evil: "Adding a pinch of evil." # tip_adding_evil: "Adding a pinch of evil."
# tip_hate_computers: "That's the thing about people who think they hate computers. What they really hate is lousy programmers. - Larry Niven" # tip_hate_computers: "That's the thing about people who think they hate computers. What they really hate is lousy programmers. - Larry Niven"
# tip_open_source_contribute: "You can help CodeCombat improve!" tip_open_source_contribute: "Gali padėti tobulinti CodeCombat!"
# tip_recurse: "To iterate is human, to recurse divine. - L. Peter Deutsch" # tip_recurse: "To iterate is human, to recurse divine. - L. Peter Deutsch"
# tip_free_your_mind: "You have to let it all go, Neo. Fear, doubt, and disbelief. Free your mind. - Morpheus" tip_free_your_mind: "Turi paleisti visą tai, Neo. Baimę, abejones ir netikėjimą. Išlaisvink savo mintis. - Morpheus"
# tip_strong_opponents: "Even the strongest of opponents always has a weakness. - Itachi Uchiha" # tip_strong_opponents: "Even the strongest of opponents always has a weakness. - Itachi Uchiha"
# tip_paper_and_pen: "Before you start coding, you can always plan with a sheet of paper and a pen." # tip_paper_and_pen: "Before you start coding, you can always plan with a sheet of paper and a pen."
# tip_solve_then_write: "First, solve the problem. Then, write the code. - John Johnson" # tip_solve_then_write: "First, solve the problem. Then, write the code. - John Johnson"
@ -349,7 +349,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
inventory_tab: "Inventorius" inventory_tab: "Inventorius"
save_load_tab: "Įrašyti / Atkurti" save_load_tab: "Įrašyti / Atkurti"
options_tab: "Pasirinkimai" options_tab: "Pasirinkimai"
guide_tab: "Vedlys" guide_tab: "Pagalba"
guide_video_tutorial: "Video vadovėlis" guide_video_tutorial: "Video vadovėlis"
guide_tips: "Patarimai" guide_tips: "Patarimai"
multiplayer_tab: "Žaidimas keliese" multiplayer_tab: "Žaidimas keliese"
@ -362,19 +362,19 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
multiplayer_caption: "Žaisk su draugais!" multiplayer_caption: "Žaisk su draugais!"
auth_caption: "Išsaugok savo pažangą." auth_caption: "Išsaugok savo pažangą."
# leaderboard: leaderboard:
# leaderboard: "Leaderboard" leaderboard: "Rezultatai"
# view_other_solutions: "View Leaderboards" view_other_solutions: "Peržiūrėti rezultatus"
# scores: "Scores" scores: "Taškai"
# top_players: "Top Players by" top_players: "Geriausi žaidėjai pagal"
# day: "Today" day: "Šiandien"
# week: "This Week" week: "Savaitė"
# all: "All-Time" all: "Visi laikotarpiai"
# time: "Time" time: "Laikas"
# damage_taken: "Damage Taken" damage_taken: "Gauta žalos"
# damage_dealt: "Damage Dealt" damage_dealt: "Padaryta žalos"
# difficulty: "Difficulty" difficulty: "Sudėtingumas"
# gold_collected: "Gold Collected" gold_collected: "Surinkta Aukso"
inventory: inventory:
choose_inventory: "Naudoti daiktus" choose_inventory: "Naudoti daiktus"
@ -389,18 +389,18 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
equip: "Naudoti" equip: "Naudoti"
unequip: "Nenaudoti" unequip: "Nenaudoti"
# buy_gems: buy_gems:
# few_gems: "A few gems" few_gems: "Sauja deimantų"
# pile_gems: "Pile of gems" pile_gems: "Krūvelė deimantų"
# chest_gems: "Chest of gems" chest_gems: "Skrynia deimantų"
# purchasing: "Purchasing..." purchasing: "Perkama..."
# declined: "Your card was declined" declined: "Jūsų kortelė atmesta"
# retrying: "Server error, retrying." retrying: "Serverio klaida, kartojame."
# prompt_title: "Not Enough Gems" prompt_title: "Deimantų nepakanka"
# prompt_body: "Do you want to get more?" prompt_body: "Ar norite gauti daugiau?"
# prompt_button: "Enter Shop" prompt_button: "Į Parduotuvę"
# recovered: "Previous gems purchase recovered. Please refresh the page." recovered: "Atstatyta deimantų pirkimo operacija. Prašome pakraukite puslapį iš naujo."
# price: "x3500 / mo" price: "x3500 / mėn"
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!" # comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
@ -500,8 +500,8 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
coffeescript_blurb: "JavaScript su malonesne sintakse." coffeescript_blurb: "JavaScript su malonesne sintakse."
clojure_blurb: "Šiolaikinis Lisp." clojure_blurb: "Šiolaikinis Lisp."
lua_blurb: "Žaidimų skriptų kalba." lua_blurb: "Žaidimų skriptų kalba."
# io_blurb: "Simple but obscure." io_blurb: "Paprasta bet paini."
# status: "Status" status: "Būsena"
hero_type: "Klasė" hero_type: "Klasė"
weapons: "Ginklai" weapons: "Ginklai"
weapons_warrior: "Kardai - artimas atstumas, be Kerų" weapons_warrior: "Kardai - artimas atstumas, be Kerų"
@ -551,23 +551,23 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
# granularity_saved_games: "Saved" # granularity_saved_games: "Saved"
# granularity_change_history: "History" # granularity_change_history: "History"
# options: options:
# general_options: "General Options" # Check out the Options tab in the Game Menu while playing a level general_options: "Bendri nustatymai" # Check out the Options tab in the Game Menu while playing a level
# volume_label: "Volume" volume_label: "Garsumas"
# music_label: "Music" music_label: "Muzika"
# music_description: "Turn background music on/off." music_description: "Įj./išj. fono muziką."
# editor_config_title: "Editor Configuration" editor_config_title: "Redaktoriaus konfigūravimas"
# editor_config_keybindings_label: "Key Bindings" editor_config_keybindings_label: "Mygtukų funkcijos"
# editor_config_keybindings_default: "Default (Ace)" editor_config_keybindings_default: "Pagal nutylėjimą (Ace)"
# editor_config_keybindings_description: "Adds additional shortcuts known from the common editors." editor_config_keybindings_description: "Prideda papildomas mygtukų kombinacijas iš žinomų redagavimo programų."
# editor_config_livecompletion_label: "Live Autocompletion" editor_config_livecompletion_label: "Automatinis žodžių užpildymas "
# editor_config_livecompletion_description: "Displays autocomplete suggestions while typing." editor_config_livecompletion_description: "Rodyti automatinio užpildymo siūlymus rašymo metu."
# editor_config_invisibles_label: "Show Invisibles" editor_config_invisibles_label: "Rodyti nematomus simbolius"
# editor_config_invisibles_description: "Displays invisibles such as spaces or tabs." editor_config_invisibles_description: "Rodyti nematomus simbolius, tokius kaip tarpai ar Tab."
# editor_config_indentguides_label: "Show Indent Guides" editor_config_indentguides_label: "Rodyti poslinkio rekomendacijas"
# editor_config_indentguides_description: "Displays vertical lines to see indentation better." editor_config_indentguides_description: "Rodomos vertikalios linijos patogesniam poslinkio matymui."
# editor_config_behaviors_label: "Smart Behaviors" editor_config_behaviors_label: "Išmanusis redagavimas"
# editor_config_behaviors_description: "Autocompletes brackets, braces, and quotes." editor_config_behaviors_description: "Automatiškai uždaro skliaustus, figurinius skliaustus ir kabutes."
# about: # about:
# why_codecombat: "Why CodeCombat?" # why_codecombat: "Why CodeCombat?"
@ -770,14 +770,14 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
# scrub_playback: "Scrub back and forward through time." # scrub_playback: "Scrub back and forward through time."
# single_scrub_playback: "Scrub back and forward through time by a single frame." # single_scrub_playback: "Scrub back and forward through time by a single frame."
# scrub_execution: "Scrub through current spell execution." # scrub_execution: "Scrub through current spell execution."
# toggle_debug: "Toggle debug display." toggle_debug: "Įj./išj. klaidų aptikimo (debug) displejų."
toggle_grid: "Įjungti tinklelį." toggle_grid: "Įjungti tinklelį."
# toggle_pathfinding: "Toggle pathfinding overlay." # toggle_pathfinding: "Toggle pathfinding overlay."
beautify: "Tvarkyti Jūsų kodą standartizuojant jo formatą." beautify: "Tvarkyti Jūsų kodą standartizuojant jo formatą."
# maximize_editor: "Maximize/minimize code editor." maximize_editor: "Išdidinti/sumažinti kodo redaktorių."
# community: community:
# main_title: "CodeCombat Community" main_title: "Bendruomenė CodeCombat"
# introduction: "Check out the ways you can get involved below and decide what sounds the most fun. We look forward to working with you!" # introduction: "Check out the ways you can get involved below and decide what sounds the most fun. We look forward to working with you!"
# level_editor_prefix: "Use the CodeCombat" # level_editor_prefix: "Use the CodeCombat"
# level_editor_suffix: "to create and edit levels. Users have created levels for their classes, friends, hackathons, students, and siblings. If create a new level sounds intimidating you can start by forking one of ours!" # level_editor_suffix: "to create and edit levels. Users have created levels for their classes, friends, hackathons, students, and siblings. If create a new level sounds intimidating you can start by forking one of ours!"
@ -941,24 +941,24 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
# hours_content: "Hours of content:" # hours_content: "Hours of content:"
# get_free: "Get FREE course" # get_free: "Get FREE course"
# classes: classes:
# archmage_title: "Archmage" archmage_title: "Arkimagas"
# archmage_title_description: "(Coder)" archmage_title_description: "(Koderis)"
# archmage_summary: "If you are a developer interested in coding educational games, become an archmage to help us build CodeCombat!" # archmage_summary: "If you are a developer interested in coding educational games, become an archmage to help us build CodeCombat!"
# artisan_title: "Artisan" artisan_title: "Menininkas"
# artisan_title_description: "(Level Builder)" artisan_title_description: "(Lygių architektas)"
# artisan_summary: "Build and share levels for you and your friends to play. Become an Artisan to learn the art of teaching others to program." # artisan_summary: "Build and share levels for you and your friends to play. Become an Artisan to learn the art of teaching others to program."
# adventurer_title: "Adventurer" adventurer_title: "Nuotykių ieškotojas"
# adventurer_title_description: "(Level Playtester)" adventurer_title_description: "(Lygių bandytojas)"
# adventurer_summary: "Get our new levels (even our subscriber content) for free one week early and help us work out bugs before our public release." # adventurer_summary: "Get our new levels (even our subscriber content) for free one week early and help us work out bugs before our public release."
# scribe_title: "Scribe" scribe_title: "Raštininkas"
# scribe_title_description: "(Article Editor)" scribe_title_description: "(Straipsnių redaktorius)"
# scribe_summary: "Good code needs good documentation. Write, edit, and improve the docs read by millions of players across the globe." # scribe_summary: "Good code needs good documentation. Write, edit, and improve the docs read by millions of players across the globe."
# diplomat_title: "Diplomat" diplomat_title: "Diplomatas"
# diplomat_title_description: "(Translator)" diplomat_title_description: "(Vertėjas)"
# diplomat_summary: "CodeCombat is localized in 45+ languages by our Diplomats. Help us out and contribute translations." # diplomat_summary: "CodeCombat is localized in 45+ languages by our Diplomats. Help us out and contribute translations."
# ambassador_title: "Ambassador" ambassador_title: "Ambasadorius"
# ambassador_title_description: "(Support)" ambassador_title_description: "(Palaikymas)"
# ambassador_summary: "Tame our forum users and provide direction for those with questions. Our ambassadors represent CodeCombat to the world." # ambassador_summary: "Tame our forum users and provide direction for those with questions. Our ambassadors represent CodeCombat to the world."
# editor: # editor:

View file

@ -6,12 +6,12 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
play: "Mula" # The big play button that opens up the campaign view. play: "Mula" # The big play button that opens up the campaign view.
old_browser: "Uh oh, browser anda terlalu lama untuk CodeCombat berfungsi. Maaf!" # Warning that shows up on really old Firefox/Chrome/Safari old_browser: "Uh oh, browser anda terlalu lama untuk CodeCombat berfungsi. Maaf!" # Warning that shows up on really old Firefox/Chrome/Safari
old_browser_suffix: "Anda boleh mencuba, tapi mungkin ia tidak akan berfungsi." old_browser_suffix: "Anda boleh mencuba, tapi mungkin ia tidak akan berfungsi."
# ipad_browser: "Bad news: CodeCombat doesn't run on iPad in the browser. Good news: our native iPad app is awaiting Apple approval." ipad_browser: "Berita buruk: CodeCombat tidak boleh berfungsi pada iPad di dalam pelayar web. Berita baik: Aplikasi native iPad kami sedang menunggu pengesahan Apple."
# campaign: "Campaign" campaign: "Kempen"
# for_beginners: "For Beginners" for_beginners: "Untuk Pemain Baru"
# multiplayer: "Multiplayer" # Not currently shown on home page multiplayer: "Ramai-Pemain" # Not currently shown on home page
# for_developers: "For Developers" # Not currently shown on home page. for_developers: "Untuk Pengaturcara" # Not currently shown on home page.
# or_ipad: "Or download for iPad" or_ipad: "Atau muat turun untuk iPad"
nav: nav:
play: "Mula" # The top nav bar entry where players choose which levels to play play: "Mula" # The top nav bar entry where players choose which levels to play

View file

@ -1,6 +1,6 @@
module.exports = nativeDescription: "Українська", englishDescription: "Ukrainian", translation: module.exports = nativeDescription: "Українська", englishDescription: "Ukrainian", translation:
home: home:
slogan: "Навчіться програмувати, граючи у гру" slogan: "Навчіться програмувати граючи"
no_ie: "На жаль, CodeCombat не працює в IE8 та старіших версіях!" # Warning that only shows up in IE8 and older no_ie: "На жаль, CodeCombat не працює в IE8 та старіших версіях!" # Warning that only shows up in IE8 and older
no_mobile: "CodeCombat не призначений для мобільних пристроїв і може не працювати!" # Warning that shows up on mobile devices no_mobile: "CodeCombat не призначений для мобільних пристроїв і може не працювати!" # Warning that shows up on mobile devices
play: "Грати" # The big play button that opens up the campaign view. play: "Грати" # The big play button that opens up the campaign view.
@ -31,7 +31,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
contact: "Контакти" contact: "Контакти"
twitter_follow: "Фоловити" twitter_follow: "Фоловити"
teachers: "Учителям" teachers: "Учителям"
# careers: "Careers" careers: "Робота"
modal: modal:
close: "Закрити" close: "Закрити"
@ -74,7 +74,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
anonymous: "Гравець-анонім" anonymous: "Гравець-анонім"
level_difficulty: "Складність: " level_difficulty: "Складність: "
campaign_beginner: "Кампанія для початківців" campaign_beginner: "Кампанія для початківців"
awaiting_levels_adventurer_prefix: "Ми випускаємо 5 рівнів на тиждень." # {change} awaiting_levels_adventurer_prefix: "Ми щотижня додаємо нові рівні."
awaiting_levels_adventurer: "Увійди як Шукач пригод" awaiting_levels_adventurer: "Увійди як Шукач пригод"
awaiting_levels_adventurer_suffix: "стань одним з перших, хто їх спробує." awaiting_levels_adventurer_suffix: "стань одним з перших, хто їх спробує."
adjust_volume: "Підлаштувати гучність" adjust_volume: "Підлаштувати гучність"
@ -84,12 +84,12 @@ module.exports = nativeDescription: "Українська", englishDescription:
# campaign_old_multiplayer_description: "Relics of a more civilized age. No simulations are run for these older, hero-less multiplayer arenas." # campaign_old_multiplayer_description: "Relics of a more civilized age. No simulations are run for these older, hero-less multiplayer arenas."
share_progress_modal: share_progress_modal:
blurb: "Ви робите великі успіхи! Розкажіть кому-небудь, як багато ви вивчили з CodeCombat." # {change} blurb: "У тебе гарно виходить! Розкажи своїм батькам як багато ти знаєш завдяки CodeCombat."
email_invalid: "Невірна електронна адреса." email_invalid: "Невірна електронна адреса."
form_blurb: "Введіть їхні електронні адреси, і ми покажемо ім!" form_blurb: "Введіть їхні електронні адреси, і ми покажемо ім!"
form_label: "Електронна адреса" form_label: "Електронна адреса"
placeholder: "електронна адреса" placeholder: "електронна адреса"
title: "Досконала робота, Учень" title: "Досконала робота, учню"
login: login:
sign_up: "створення акаунту" sign_up: "створення акаунту"
@ -161,7 +161,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
withdrawn: "Відкликано" withdrawn: "Відкликано"
accept: "Прийняти" accept: "Прийняти"
reject: "Відхилити" reject: "Відхилити"
# withdraw: "Withdraw" withdraw: "Відкликати"
submitter: "Відправник" submitter: "Відправник"
submitted: "Відправлено" submitted: "Відправлено"
commit_msg: "Доручити повідомлення" commit_msg: "Доручити повідомлення"
@ -343,7 +343,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
tip_free_your_mind: "Нео, ти повинен усе подолати. Страх... сумніви і невіра. Звільни від них свій розум. - Морфіус" tip_free_your_mind: "Нео, ти повинен усе подолати. Страх... сумніви і невіра. Звільни від них свій розум. - Морфіус"
tip_strong_opponents: "Навіть наймогутніший суперник має свою слабкість. - Ітачі Учіха" tip_strong_opponents: "Навіть наймогутніший суперник має свою слабкість. - Ітачі Учіха"
tip_paper_and_pen: "Перш ніж почати програмувати, ви завжди можете спробувати з аркушем паперу і ручкою." tip_paper_and_pen: "Перш ніж почати програмувати, ви завжди можете спробувати з аркушем паперу і ручкою."
# tip_solve_then_write: "First, solve the problem. Then, write the code. - John Johnson" tip_solve_then_write: "Спершу вирішуй проблему, а потім - пиши код. - Джон Джонсон"
game_menu: game_menu:
inventory_tab: "Інвентар" inventory_tab: "Інвентар"
@ -404,9 +404,9 @@ module.exports = nativeDescription: "Українська", englishDescription:
subscribe: subscribe:
comparison_blurb: "Відточіть свої навички завдяки підписці на CodeCombat!" comparison_blurb: "Відточіть свої навички завдяки підписці на CodeCombat!"
feature1: "Більше 60 основних рівней на просторах 4 світів" # {change} feature1: "Більше 110 основних рівней на просторах 4 світів"
feature2: "7 могутніх <strong>нових героїв</strong> з унікальними здібностями!" # {change} feature2: "10 могутніх <strong>нових героїв</strong> з унікальними здібностями!"
feature3: "Більше 30 бонусних рівнів" # {change} feature3: "Більше 80-ти бонусних рівнів"
feature4: "<strong>3500 бонусних самоцвітів</strong> кожного місяця!" feature4: "<strong>3500 бонусних самоцвітів</strong> кожного місяця!"
feature5: "Навчальні відеоролики" feature5: "Навчальні відеоролики"
feature6: "Екслюзивна підтримка по електронній пошті" feature6: "Екслюзивна підтримка по електронній пошті"
@ -432,8 +432,8 @@ module.exports = nativeDescription: "Українська", englishDescription:
parent_email_sent: "Лист відправлено!" parent_email_sent: "Лист відправлено!"
parent_email_title: "Яка в твоїх батьків електронна адреса?" parent_email_title: "Яка в твоїх батьків електронна адреса?"
parents: "Батькам" parents: "Батькам"
parents_title: "Ваша дитина вчитиметься програмувати." # {change} parents_title: "Дорога мамо/батьку, ваша дитина вчиться програмувати. Чи допоможите ви їй продовжити цю спрову?" # {change}
parents_blurb1: "Разом з CodeCombat Ваша дитина писатиме реальний код. Почне з простих команд та поступово буде розвиватись до складніших тем." parents_blurb1: "Разом з CodeCombat Ваша дитина писатиме реальний код. Почне з простих команд та поступово буде розвиватись до складніших тем." # {change}
parents_blurb1a: "Коп'ютерне програмування є необхідними вмінням, що ваша дитина беззаперечно використовуватиме у дорослому віці. До 2020 року 77% професій потребуватимуть базових навичок у програмному забезпечені, а програмісти надзвичайно потрібні у всьому світі. Чи знали ви, що Комп'ютерні Науки - це найбільш високооплачувана університетьська спеціальність?" parents_blurb1a: "Коп'ютерне програмування є необхідними вмінням, що ваша дитина беззаперечно використовуватиме у дорослому віці. До 2020 року 77% професій потребуватимуть базових навичок у програмному забезпечені, а програмісти надзвичайно потрібні у всьому світі. Чи знали ви, що Комп'ютерні Науки - це найбільш високооплачувана університетьська спеціальність?"
parents_blurb2: "За 9.99$ на місяць, вона отримуватиме нові завдання щотижня та персональні листи підтримки від професійних програмістів." # {change} parents_blurb2: "За 9.99$ на місяць, вона отримуватиме нові завдання щотижня та персональні листи підтримки від професійних програмістів." # {change}
parents_blurb3: "Жодного ризику: 100% гарантія повернення грошей, легке скасування абонементу одним кліком." parents_blurb3: "Жодного ризику: 100% гарантія повернення грошей, легке скасування абонементу одним кліком."
@ -455,7 +455,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
sale_continue: "Готовий продовжити пригоди?" sale_continue: "Готовий продовжити пригоди?"
sale_limited_time: "Обмежена пропозиція!" sale_limited_time: "Обмежена пропозиція!"
sale_new_heroes: "Нові герої!" sale_new_heroes: "Нові герої!"
# sale_title: "Back to School Sale" sale_title: "Дошкільні знижки"
sale_view_button: "Купити 1 рік підписки на" sale_view_button: "Купити 1 рік підписки на"
stripe_description: "Щомісячний абонемент" stripe_description: "Щомісячний абонемент"
stripe_description_year_sale: "1 рік підписки (35% знижка)" stripe_description_year_sale: "1 рік підписки (35% знижка)"
@ -473,7 +473,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
managed_subs_desc_2: "Одержувачі повинні мати обліковий запис CodeCombat, пов'язаний з вказаною Вами адресою електронної пошти." managed_subs_desc_2: "Одержувачі повинні мати обліковий запис CodeCombat, пов'язаний з вказаною Вами адресою електронної пошти."
group_discounts: "Групові знижки" group_discounts: "Групові знижки"
group_discounts_1: "Ми також пропонуємо знижки для пакетних передплат." group_discounts_1: "Ми також пропонуємо знижки для пакетних передплат."
group_discounts_1st: "1-ий абонемент (включає Ваш)" # {change} group_discounts_1st: "1-ий абонемент"
group_discounts_full: "Повна ціна" group_discounts_full: "Повна ціна"
group_discounts_2nd: "2-11 абонементи" group_discounts_2nd: "2-11 абонементи"
group_discounts_20: "Знижка 20%" group_discounts_20: "Знижка 20%"
@ -485,7 +485,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
users_subscribed: "Підписані користувачі:" users_subscribed: "Підписані користувачі:"
no_users_subscribed: "Користувачі не підписані, будь ласка, перевірте Ваші ел. адреси." no_users_subscribed: "Користувачі не підписані, будь ласка, перевірте Ваші ел. адреси."
current_recipients: "Поточні отримувачі" current_recipients: "Поточні отримувачі"
unsubscribing: "Скасування передплати..." # {change} unsubscribing: "Триває скасування підписки..."
subscribe_prepaid: "Натисніть Підписатися щоб використовувати передплачені коди" subscribe_prepaid: "Натисніть Підписатися щоб використовувати передплачені коди"
using_prepaid: "Використати передплачений код для щомісячної підписки" using_prepaid: "Використати передплачений код для щомісячної підписки"
@ -583,15 +583,15 @@ module.exports = nativeDescription: "Українська", englishDescription:
press_paragraph_1_link: "набору-для-преси" press_paragraph_1_link: "набору-для-преси"
press_paragraph_1_suffix: ". Всі логотипи та зображення можна використовувати, не зв'язуючись із нами напряму." press_paragraph_1_suffix: ". Всі логотипи та зображення можна використовувати, не зв'язуючись із нами напряму."
team: "Команда" team: "Команда"
george_title: "Виконавчий директор" # {change} george_title: "Співзасновник"
george_blurb: "Бізнесмен" george_blurb: "Бізнесмен"
scott_title: "Програміст" # {change} scott_title: "Співзасновник"
scott_blurb: "Розумник" scott_blurb: "Розумник"
nick_title: "Програміст" # {change} nick_title: "Співзасновник"
nick_blurb: "Ґуру мотивації" nick_blurb: "Ґуру мотивації"
michael_title: "Програміст" michael_title: "Програміст"
michael_blurb: "Сисадмін" michael_blurb: "Сисадмін"
matt_title: "Програміст" # {change} matt_title: "Співзасновник"
matt_blurb: "Велосипедист" matt_blurb: "Велосипедист"
cat_title: "Головний ремісник" cat_title: "Головний ремісник"
cat_blurb: "Маг повітря" cat_blurb: "Маг повітря"
@ -603,7 +603,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
retrostyle_blurb: "Ігри в стилі ретро" retrostyle_blurb: "Ігри в стилі ретро"
teachers: teachers:
# more_info: "More Info for Teachers" more_info: "Додаткова інформація для вчителів"
intro_1: "CodeCombat - це онлайн гра, що вчить програмуванню. Студенти пишуть код на реальних мовах програмування." intro_1: "CodeCombat - це онлайн гра, що вчить програмуванню. Студенти пишуть код на реальних мовах програмування."
intro_2: "Досвід не потрібен!" intro_2: "Досвід не потрібен!"
free_title: "Скільки це коштує?" free_title: "Скільки це коштує?"
@ -617,12 +617,12 @@ module.exports = nativeDescription: "Українська", englishDescription:
teacher_subs_3: "щоб налаштувати підписку." teacher_subs_3: "щоб налаштувати підписку."
sub_includes_title: "Що входить у підписку?" sub_includes_title: "Що входить у підписку?"
sub_includes_1: "На додаток до 110+ основних рівнів, студенти з щомісячною підпискою отримають доступ до цих додаткових функцій:" sub_includes_1: "На додаток до 110+ основних рівнів, студенти з щомісячною підпискою отримають доступ до цих додаткових функцій:"
sub_includes_2: "70 + рівнів практики" # {change} sub_includes_2: "80+ рівнів практики"
sub_includes_3: "Відео уроки" sub_includes_3: "Відео уроки"
sub_includes_4: "Преміум підтримка по електронній пошті" sub_includes_4: "Преміум підтримка по електронній пошті"
sub_includes_5: "10 нових героїв з унікальними навичками для оволодіння" sub_includes_5: "10 нових героїв з унікальними навичками для оволодіння"
sub_includes_6: "3500 бонусних дорогоцінних каменів кожен місяць" sub_includes_6: "3500 бонусних самоцвітів кожен місяць"
sub_includes_7: "Приватні Клани" sub_includes_7: "Приватні клани"
monitor_progress_title: "Як мені стежити за прогресом студентів?" monitor_progress_title: "Як мені стежити за прогресом студентів?"
monitor_progress_1: "Прогрес студентів може бути відстежити, створивши" monitor_progress_1: "Прогрес студентів може бути відстежити, створивши"
monitor_progress_2: "для вашого класу." monitor_progress_2: "для вашого класу."
@ -651,8 +651,8 @@ module.exports = nativeDescription: "Українська", englishDescription:
more_info_2: "вчительський форум" more_info_2: "вчительський форум"
more_info_3: "є гарним місцем для спілкування із колегами-педагогами, котрі використовують CodeCombat." more_info_3: "є гарним місцем для спілкування із колегами-педагогами, котрі використовують CodeCombat."
sys_requirements_title: "Системні вимоги" sys_requirements_title: "Системні вимоги"
sys_requirements_1: "Оскільки CodeCombat — це гра, для нормальної роботи він вимагає у комп'ютерів більше, ніж відео чи текстові посібники. Ми оптимізували його для швидкої роботи в усіх сучасних браузерах і на старіших машинах, щоб кожен міг грати. І ось наші підказки, як отримати від CodeCombat якнайбільше:" # {change} sys_requirements_1: "Сучасний веб-переглядач. Остання версія Chrome, Firefox або Safari. Internet Explorer 9 та вище."
sys_requirements_2: "Використовуйте новіші версії Chrome або Firefox." # {change} sys_requirements_2: "CodeCombat наразі не підтримується на iPad."
teachers_survey: teachers_survey:
title: "Анкета вчителя" title: "Анкета вчителя"
@ -727,8 +727,8 @@ module.exports = nativeDescription: "Українська", englishDescription:
admin: "Aдмін" admin: "Aдмін"
new_password: "Новий пароль" new_password: "Новий пароль"
new_password_verify: "Підтвердження паролю" new_password_verify: "Підтвердження паролю"
type_in_email: "Введіть свій email, щоб підтвердити вилучення" # {change} type_in_email: "Введіть свій email, аби підтвердити вилучення екаунту."
type_in_password: "Так само введіть ваш пароль." type_in_password: "Також, введіть свій пароль."
email_subscriptions: "Email-підписки" email_subscriptions: "Email-підписки"
email_subscriptions_none: "Жодних підписок." email_subscriptions_none: "Жодних підписок."
email_announcements: "Оголошення" email_announcements: "Оголошення"
@ -840,16 +840,16 @@ module.exports = nativeDescription: "Українська", englishDescription:
last_played: "Остання гра" last_played: "Остання гра"
leagues_explanation: "Грайте в лізі проти інших членів клану на мультіплєєрній арені." leagues_explanation: "Грайте в лізі проти інших членів клану на мультіплєєрній арені."
# track_concepts1: "Track concepts" # track_concepts1: "Track concepts"
# track_concepts2a: "learned by each student" track_concepts2a: "вивчено усіма студентами"
# track_concepts2b: "learned by each member" track_concepts2b: "вивчено усіма учасниками"
# track_concepts3a: "Track levels completed for each student" # track_concepts3a: "Track levels completed for each student"
# track_concepts3b: "Track levels completed for each member" # track_concepts3b: "Track levels completed for each member"
# track_concepts4a: "See your students'" # track_concepts4a: "See your students'"
# track_concepts4b: "See your members'" # track_concepts4b: "See your members'"
# track_concepts5: "solutions" track_concepts5: "рішення"
# track_concepts6a: "Sort students by name or progress" # track_concepts6a: "Sort students by name or progress"
# track_concepts6b: "Sort members by name or progress" # track_concepts6b: "Sort members by name or progress"
# track_concepts7: "Requires invitation" track_concepts7: "Потребує запрошення"
# track_concepts8: "to join" # track_concepts8: "to join"
# private_require_sub: "Private clans require a subscription to create or join." # private_require_sub: "Private clans require a subscription to create or join."
@ -1183,11 +1183,11 @@ module.exports = nativeDescription: "Українська", englishDescription:
rules: "Правила" rules: "Правила"
winners: "Переможці" winners: "Переможці"
league: "Ліга" league: "Ліга"
# red_ai: "Red AI" # "Red AI Wins", at end of multiplayer match playback red_ai: "Червоний ШІ" # "Red AI Wins", at end of multiplayer match playback
# blue_ai: "Blue AI" blue_ai: "Синій ШІ"
# wins: "Wins" # At end of multiplayer match playback wins: "переміг" # At end of multiplayer match playback
# humans: "Red" # Ladder page display team name humans: "Червоний" # Ladder page display team name
# ogres: "Blue" ogres: "Синій"
user: user:
stats: "Статистика" stats: "Статистика"
@ -1258,22 +1258,22 @@ module.exports = nativeDescription: "Українська", englishDescription:
retrying: "Помилка сервера, повторна спроба." retrying: "Помилка сервера, повторна спроба."
success: "Успішно оплачено. Дякуємо!" success: "Успішно оплачено. Дякуємо!"
# account_prepaid: account_prepaid:
# purchase_code: "Purchase a Subscription Code" # purchase_code: "Purchase a Subscription Code"
# purchase_code1: "Subscription Codes can be redeemed to add premium subscription time to one or more CodeCombat accounts." # purchase_code1: "Subscription Codes can be redeemed to add premium subscription time to one or more CodeCombat accounts."
# purchase_code2: "Each CodeCombat account can only redeem a particular Subscription Code once." # purchase_code2: "Each CodeCombat account can only redeem a particular Subscription Code once."
# purchase_code3: "Subscription Code months will be added to the end of any existing subscription on the account." # purchase_code3: "Subscription Code months will be added to the end of any existing subscription on the account."
# users: "Users" users: "Користувачі"
# months: "Months" months: "Місяці"
# purchase_total: "Total" purchase_total: "Загалом"
# purchase_button: "Submit Purchase" # purchase_button: "Submit Purchase"
# your_codes: "Your Codes" # your_codes: "Your Codes"
# redeem_codes: "Redeem a Subscription Code" # redeem_codes: "Redeem a Subscription Code"
# prepaid_code: "Prepaid Code" # prepaid_code: "Prepaid Code"
# lookup_code: "Lookup prepaid code" # lookup_code: "Lookup prepaid code"
# apply_account: "Apply to your account" apply_account: "Застосувати до свого екаунту"
# copy_link: "You can copy the code's link and send it to someone." # copy_link: "You can copy the code's link and send it to someone."
# quantity: "Quantity" quantity: "Кількіть"
# redeemed: "Redeemed" # redeemed: "Redeemed"
# no_codes: "No codes yet!" # no_codes: "No codes yet!"
@ -1350,12 +1350,12 @@ module.exports = nativeDescription: "Українська", englishDescription:
arrays: "Масиви" arrays: "Масиви"
basic_syntax: "Базовий синтаксис" basic_syntax: "Базовий синтаксис"
boolean_logic: "Булева логіка" boolean_logic: "Булева логіка"
# break_statements: "Break Statements" break_statements: "Оператори зупинки"
classes: "Класи" classes: "Класи"
# continue_statements: "Continue Statements" continue_statements: "Оператори продовження"
for_loops: "Цикл For" for_loops: "Цикл For"
functions: "Функції" functions: "Функції"
# graphics: "Graphics" graphics: "Графіка"
if_statements: "Умовні оператори" if_statements: "Умовні оператори"
input_handling: "Обробка введення" input_handling: "Обробка введення"
math_operations: "Математичні операції" math_operations: "Математичні операції"
@ -1490,7 +1490,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
next_photo: "додайте необов’язкове професійне фото." next_photo: "додайте необов’язкове професійне фото."
next_active: "відзначте що Ви у пошуках пропозицій, щобвідображатися у пошуку." next_active: "відзначте що Ви у пошуках пропозицій, щобвідображатися у пошуку."
example_blog: "Блог" example_blog: "Блог"
example_personal_site: "Особиста Сторінка" example_personal_site: "Персональний сайт"
links_header: "Особисті Посилання" links_header: "Особисті Посилання"
links_blurb: "Посилання на інші сторінки або профілі, які б ви хотіли вказати. Наприклад: аккаунт на GitHub'і, LinkedIn, або ваш блог. " links_blurb: "Посилання на інші сторінки або профілі, які б ви хотіли вказати. Наприклад: аккаунт на GitHub'і, LinkedIn, або ваш блог. "
links_name: "Назва посилання" links_name: "Назва посилання"

View file

@ -280,6 +280,7 @@ _.extend UserSchema.properties,
pollMiscPatches: c.int() pollMiscPatches: c.int()
campaignTranslationPatches: c.int() campaignTranslationPatches: c.int()
campaignMiscPatches: c.int() campaignMiscPatches: c.int()
concepts: {type: 'object', additionalProperties: c.int(), description: 'Number of levels completed using each programming concept.'}
earned: c.RewardSchema 'earned by achievements' earned: c.RewardSchema 'earned by achievements'
purchased: c.RewardSchema 'purchased with gems or money' purchased: c.RewardSchema 'purchased with gems or money'

View file

@ -1,4 +1,11 @@
#subscription-view #subscription-view
.invalid-email-message
color: red
font-size: 12px
.recipient-emails.invalid
border: 1px solid red
.logged-out-blurb .logged-out-blurb
font-size: 18px font-size: 18px

View file

@ -0,0 +1,16 @@
#admin-analytics-view
#site-content-area
width: 100%
.big-stat
width: auto
.active-classes
color: blue
.recurring-revenue
color: green
.active-users
color: red
.count
font-size: 70pt
.description
font-size: 8pt

View file

@ -183,4 +183,24 @@ block content
p(data-i18n="about.rob_title") p(data-i18n="about.rob_title")
| Compiler Engineer | Compiler Engineer
p(data-i18n="about.rob_blurb") p(data-i18n="about.rob_blurb")
| Codes things and stuff | Codes things and stuff.
img(src="/images/pages/about/placeholder.png").img-thumbnail
.team_bio
h4.team_name
| Josh Callebaut
p(data-i18n="about.josh_c_title")
| Game Designer
p(data-i18n="about.josh_c_blurb")
| Designs games.
li.row
img(src="/images/pages/about/carlos_small.png").img-thumbnail
.team_bio
h4.team_name
| Carlos Maia
p(data-i18n="about.carlos_title")
| Region Manager
p(data-i18n="about.carlos_blurb")
| CodeCombat Brazil

View file

@ -150,7 +150,9 @@ block content
if view.recipientSubs.state === 'subscribing' if view.recipientSubs.state === 'subscribing'
.alert.alert-info(data-i18n="subscribe.subscribing") .alert.alert-info(data-i18n="subscribe.subscribing")
else else
textarea.recipient-emails(rows=3, data-i18n="[placeholder]subscribe.recipient_emails_placeholder") if emailValidator.state === 'invalid'
div.invalid-email-message(aria-hidden="true") please make sure all entries are valid emails
textarea.recipient-emails(rows=3, data-i18n="[placeholder]subscribe.recipient_emails_placeholder")=emailValidator.lastEmails
div div
button.recipients-subscribe-button.btn.btn-lg.btn-success(data-i18n="subscribe.subscribe_users") button.recipients-subscribe-button.btn.btn-lg.btn-success(data-i18n="subscribe.subscribe_users")
if view.recipientSubs.state === 'declined' if view.recipientSubs.state === 'declined'

View file

@ -48,12 +48,11 @@ block content
li li
a(href="/admin/pending-patches", data-i18n="resources.patches") Patches a(href="/admin/pending-patches", data-i18n="resources.patches") Patches
if me.isAdmin() if me.isAdmin()
li Analytics li
a(href="/admin/analytics") Analytics
ul ul
li li
a(href="/admin/analytics/subscriptions") Subscriptions a(href="/admin/analytics/subscriptions") Subscriptions
li
a(href="/admin/analytics/users") Users (needs updating)
if me.isAdmin() if me.isAdmin()
hr hr

View file

@ -1,32 +0,0 @@
extends /templates/base
block content
h1(data-i18n="admin.growth_title") Users
if me.isAdmin()
if crunchingData
h4 Crunching Data..
else
h2 Registered Users
h3 Per-Day
h4 Totals
svg.perDayTotal
h4 Added
svg.perDayAdded
table.table.table-striped.table-bordered.table-condensed
-for (var i = 0; i < usersPerDay.length; i++)
tr
td= usersPerDay[i].date
td= usersPerDay[i].added
td= usersPerDay[i].total
h3 Per-Month
h4 Totals
svg.perMonthTotal
h4 Added
svg.perMonthAdded
table.table.table-striped.table-bordered.table-condensed
-for (var i = 0; i < usersPerMonth.length; i++)
tr
td= usersPerMonth[i].date
td= usersPerMonth[i].added
td= usersPerMonth[i].total

View file

@ -0,0 +1,61 @@
extends /templates/base
block content
if me.isAdmin()
.container-fluid
.row
.col-md-5.big-stat.active-classes
if activeClasses.length > 0
div.description 30-day Active Classes
div.count= activeClasses[0].groups[activeClasses[0].groups.length - 1]
.col-md-5.big-stat.recurring-revenue
if revenue.length > 0
div.description 30-day Monthly Recurring Revenue
div.count $#{Math.round((revenue[0].groups[revenue[0].groups.length - 1]) / 100)}
.col-md-5.big-stat.active-users
if activeUsers.length > 0
div.description 30-day Active Users
div.count= activeUsers[0].monthlyCount
h1 Active Classes
table.table.table-striped.table-condensed
tr
th Day
for group in activeClassGroups
th= group.replace('Active classes', '')
each activeClass in activeClasses
tr
td= activeClass.day
each val in activeClass.groups
td= val
h1 Recurring Revenue
table.table.table-striped.table-condensed
tr
th Day
for group in revenueGroups
th= group.replace('DRR ', '')
each entry in revenue
tr
td= entry.day
each val in entry.groups
td $#{(val / 100).toFixed(2)}
h1 Active Users
table.table.table-striped.table-condensed
tr
th Day
th Daily Actives
th Monthly Actives
th DAUs / MAUs
each activeUser in activeUsers
tr
td= activeUser.day
td= activeUser.dailyCount
if activeUser.monthlyCount
td= activeUser.monthlyCount
td #{(activeUser.dailyCount / activeUser.monthlyCount * 100).toFixed(2)}%
else
td
td

View file

@ -40,7 +40,7 @@ block content
a(href="/clans/#{clan.id}", style='font-weight:bold')= clan.get('name') a(href="/clans/#{clan.id}", style='font-weight:bold')= clan.get('name')
else else
a(href="/clans/#{clan.id}")= clan.get('name') a(href="/clans/#{clan.id}")= clan.get('name')
td= clan.get('members').length td= clan.get('memberCount')
td td
if idNameMap && idNameMap[clan.get('ownerID')] if idNameMap && idNameMap[clan.get('ownerID')]
a(href="/user/#{clan.get('ownerID')}")= idNameMap[clan.get('ownerID')] a(href="/user/#{clan.get('ownerID')}")= idNameMap[clan.get('ownerID')]
@ -70,7 +70,7 @@ block content
a(href="/clans/#{clan.id}", style='font-weight:bold')= clan.get('name') a(href="/clans/#{clan.id}", style='font-weight:bold')= clan.get('name')
else else
a(href="/clans/#{clan.id}")= clan.get('name') a(href="/clans/#{clan.id}")= clan.get('name')
td= clan.get('members').length td= clan.get('memberCount')
td td
if idNameMap && idNameMap[clan.get('ownerID')] if idNameMap && idNameMap[clan.get('ownerID')]
a(href="/user/#{clan.get('ownerID')}")= idNameMap[clan.get('ownerID')] a(href="/user/#{clan.get('ownerID')}")= idNameMap[clan.get('ownerID')]

View file

@ -120,10 +120,3 @@ block modal-footer-content
img.pull-right(src="/file/db/level/55144b509f0c4854051769c1/viking_2.png") img.pull-right(src="/file/db/level/55144b509f0c4854051769c1/viking_2.png")
span(data-i18n="play_level.victory_viking_code_school") span(data-i18n="play_level.victory_viking_code_school")
button.btn.btn-illustrated.btn-primary.btn-lg.world-map-button.continue-from-offer-button(data-i18n="play_level.victory_become_a_viking") Become a Viking button.btn.btn-illustrated.btn-primary.btn-lg.world-map-button.continue-from-offer-button(data-i18n="play_level.victory_become_a_viking") Become a Viking
.offer.a-mayhem-of-munchkins
p
img.pull-left(src="/file/db/level/55ca29439bc1892c835b0137/bloc_warrior.png")
img.pull-right(src="/file/db/level/55ca29439bc1892c835b0137/bloc_logo.png")
span(data-i18n="play_level.victory_bloc")
button.btn.btn-illustrated.btn-warning.btn-lg.world-map-button.skip-offer-button(data-i18n="play_level.victory_play_continue") Continue
button.btn.btn-illustrated.btn-primary.btn-lg.world-map-button.continue-from-offer-button(data-i18n="play_level.victory_bloc_cta")

View file

@ -3,7 +3,7 @@ extends /templates/base
block content block content
h2 Hour of Code(Combat) h2 Hour of Code(Combat)
p p
strong Hi Teachers! strong Hi Teachers!
p We're excited to participate in Hour of Code this year! p We're excited to participate in Hour of Code this year!
p We've set up an Introduction to Computer Science course, just for you. p We've set up an Introduction to Computer Science course, just for you.
@ -12,12 +12,12 @@ block content
ol ol
li li
span.spr Navigate to the span.spr Navigate to the
a.spr(href='/courses/teachers?hoc=true') Courses a(href='/courses/teachers?hoc=true') Courses
span page span.spl page
li Click the green 'Get FREE course' button under Introduction to Computer Science li Click the green 'Get FREE course' button under Introduction to Computer Science
li Follow the enrollment instructions li Follow the enrollment instructions
li Add students via the 'Add Students' tab li Add students via the 'Add Students' tab
p p
span.spr If you have any problems, please email span.spr If you have any problems, please email
a(href='mailto:team@codecombat.com') team@codecombat.com a(href='mailto:team@codecombat.com') team@codecombat.com
br br
@ -66,15 +66,15 @@ block content
p(data-i18n="teachers.monitor_progress_5") p(data-i18n="teachers.monitor_progress_5")
h4(data-i18n="teachers.sub_includes_7") h4(data-i18n="teachers.sub_includes_7")
ul ul
li li
strong(data-i18n="clans.track_concepts1") strong(data-i18n="clans.track_concepts1")
span.spl(data-i18n="clans.track_concepts2a") span.spl(data-i18n="clans.track_concepts2a")
li(data-i18n="clans.track_concepts3a") li(data-i18n="clans.track_concepts3a")
li li
span(data-i18n="clans.track_concepts4a") span(data-i18n="clans.track_concepts4a")
strong.spl(data-i18n="clans.track_concepts5") strong.spl(data-i18n="clans.track_concepts5")
li(data-i18n="clans.track_concepts6a") li(data-i18n="clans.track_concepts6a")
li li
strong(data-i18n="clans.track_concepts7") strong(data-i18n="clans.track_concepts7")
span.spl(data-i18n="clans.track_concepts8") span.spl(data-i18n="clans.track_concepts8")
p p
@ -144,7 +144,7 @@ block content
span.spr.spl span.spr.spl
a(href='/account/subscription', data-i18n="teachers.how_much_2") a(href='/account/subscription', data-i18n="teachers.how_much_2")
span.spr.spl(data-i18n="teachers.how_much_3") span.spr.spl(data-i18n="teachers.how_much_3")
p p
span.spr(data-i18n="teachers.how_much_5") span.spr(data-i18n="teachers.how_much_5")
a(href='mailto:team@codecombat.com') team@codecombat.com a(href='mailto:team@codecombat.com') team@codecombat.com
span.spl(data-i18n="teachers.how_much_6") span.spl(data-i18n="teachers.how_much_6")
@ -153,7 +153,7 @@ block content
a(href='/account/subscription', data-i18n="subscribe.group_discounts") a(href='/account/subscription', data-i18n="subscribe.group_discounts")
p(data-i18n="subscribe.group_discounts_1") p(data-i18n="subscribe.group_discounts_1")
table.table.table-condensed.discount-table table.table.table-condensed.discount-table
tr tr
td(data-i18n="subscribe.group_discounts_1st") td(data-i18n="subscribe.group_discounts_1st")
td(data-i18n="subscribe.group_discounts_full") td(data-i18n="subscribe.group_discounts_full")
tr tr

View file

@ -49,9 +49,15 @@ module.exports = class SubscriptionView extends RootView
prepaidCode = utils.getQueryVariable '_ppc' prepaidCode = utils.getQueryVariable '_ppc'
@personalSub = new PersonalSub(@supermodel, prepaidCode) @personalSub = new PersonalSub(@supermodel, prepaidCode)
@recipientSubs = new RecipientSubs(@supermodel) @recipientSubs = new RecipientSubs(@supermodel)
@emailValidator = new EmailValidator(@superModel)
@personalSub.update => @render?() @personalSub.update => @render?()
@recipientSubs.update => @render?() @recipientSubs.update => @render?()
getRenderData: ->
c = super()
c.emailValidator = @emailValidator
c
# Personal Subscriptions # Personal Subscriptions
onClickStartSubscription: (e) -> onClickStartSubscription: (e) ->
@ -82,7 +88,8 @@ module.exports = class SubscriptionView extends RootView
onClickRecipientsSubscribe: (e) -> onClickRecipientsSubscribe: (e) ->
emails = @$el.find('.recipient-emails').val().split('\n') emails = @$el.find('.recipient-emails').val().split('\n')
@recipientSubs.startSubscribe(emails) valid = @emailValidator.validateEmails(emails, =>@render?())
@recipientSubs.startSubscribe(emails) if valid
onClickRecipientUnsubscribe: (e) -> onClickRecipientUnsubscribe: (e) ->
$(e.target).addClass('hide') $(e.target).addClass('hide')
@ -97,6 +104,31 @@ module.exports = class SubscriptionView extends RootView
# Helper classes for managing subscription actions and updating UI state # Helper classes for managing subscription actions and updating UI state
class EmailValidator
validateEmails: (emails, render) ->
@lastEmails = emails.join('\n')
#taken from http://www.regular-expressions.info/email.html
emailRegex = /[A-z0-9._%+-]+@[A-z0-9.-]+\.[A-z]{2,4}/
@validEmails = (email for email in emails when emailRegex.test(email.trim().toLowerCase()))
return @emailsInvalid(render) if @validEmails.length < emails.length
return @emailsValid(render)
emailString: ->
return unless @validEmails
return @validEmails.join('\n')
emailsInvalid: (render) ->
@state = "invalid"
render()
return false
emailsValid: (render) ->
@state = "valid"
render()
return true
class PersonalSub class PersonalSub
constructor: (@supermodel, @prepaidCode) -> constructor: (@supermodel, @prepaidCode) ->

View file

@ -1,193 +0,0 @@
RootView = require 'views/core/RootView'
template = require 'templates/admin/analytics-users'
RealTimeCollection = require 'collections/RealTimeCollection'
require 'vendor/d3'
# Growth View ###################
#
# Display interesting growth data.
#
# Currently shows:
# Registered user totals and added, per-day and per-month
# 7-day moving average for registered users added per-day
#
# TODO: @padding isn't applied correctly
# TODO: aggregate recent data if missing?
#
module.exports = class AnalyticsUsersView extends RootView
id: 'admin-analytics-users-view'
template: template
height: 300
width: 1000
xAxisGuideHeight: 80
yAxisGuideWidth: 60
padding: 10
constructor: (options) ->
super options
@usersPerMonth = new RealTimeCollection 'growth/users/registered/per-month'
@usersPerMonth.on 'add', @refreshData
@usersPerDay = new RealTimeCollection 'growth/users/registered/per-day'
@usersPerDay.on 'add', @refreshData
destroy: ->
@usersPerMonth.off 'add', @refreshData
@usersPerDay.off 'add', @refreshData
refreshData: =>
@render()
getRenderData: ->
c = super()
c.crunchingData = @usersPerMonth.length is 0 and @usersPerDay.length is 0
c.usersPerDay = []
# @usersPerDay.each (item) ->
# c.usersPerDay.push date: item.get('id'), added: item.get('added'), total: item.get('total')
c.usersPerMonth = []
# @usersPerMonth.each (item) ->
# c.usersPerMonth.push date: item.get('id'), added: item.get('added'), total: item.get('total')
c
afterRender: ->
super()
if me.isAdmin()
@createPerDayChart()
@createPerMonthChart()
createPerDayChart: ->
addedData = []
totalData = []
@usersPerDay.each (item) ->
addedData.push id: item.get('id'), value: item.get('added')
totalData.push id: item.get('id'), value: item.get('total')
@createLineChart ".perDayTotal", totalData, 1000
@createLineChart ".perDayAdded", addedData, 10, true
createPerMonthChart: ->
addedData = []
totalData = []
@usersPerMonth.each (item) ->
addedData.push id: item.get('id'), value: item.get('added')
totalData.push id: item.get('id'), value: item.get('total')
@createLineChart ".perMonthTotal", totalData, 1000
@createLineChart ".perMonthAdded", addedData, 1000
createLineChart: (selector, data, guidelineSpacing, sevenDayAverage=false) ->
return unless data.length > 1
minVal = d3.min(data, (d) -> d.value)
maxVal = d3.max(data, (d) -> d.value)
widthSpacing = (@width - @yAxisGuideWidth - @padding) / (data.length - 1)
y = d3.scale.linear()
.domain([minVal, maxVal])
.range([@height - @xAxisGuideHeight - 2 * @padding, 0])
points = []
for i in [0...data.length]
points.push id: data[i].id, x: i * widthSpacing + @yAxisGuideWidth, y: y(data[i].value) + @padding
links = []
for i in [0...points.length - 1]
if points[i] and points[i + 1]
links.push start: points[i], end: points[i + 1]
guidelines = []
diff = maxVal - minVal
interval = Math.floor(diff / 5)
for i in [0..4]
yVal = i * interval + minVal
yVal = Math.floor(yVal / guidelineSpacing) * guidelineSpacing
guidelines.push start: {id: yVal, x: 0, y: y(yVal)}, end: {id: yVal, x: @width, y: y(yVal)}
sevenPoints = []
sevenLinks = []
if sevenDayAverage
sevenTotal = 0
for i in [0...data.length]
sevenTotal += data[i].value
if i > 5
sevenAvg = sevenTotal / 7
sevenPoints.push x: i * widthSpacing + @yAxisGuideWidth, y: y(sevenAvg) + @padding
if i > 6
sevenTotal -= data[i - 7].value
for i in [0...sevenPoints.length - 1]
if sevenPoints[i] and sevenPoints[i + 1]
sevenLinks.push start: sevenPoints[i], end: sevenPoints[i + 1]
chart = d3.select(selector)
.attr("width", @width)
.attr("height", @height)
chart.selectAll(".circle")
.data(points)
.enter()
.append("circle")
.attr("cx", (d) -> d.x )
.attr("cy", (d) -> d.y )
.attr("r", "2px")
.attr("fill", "black")
chart.selectAll(".text")
.data(points)
.enter()
.append("text")
.attr("dy", ".35em")
.attr("transform", (d, i) => "translate(" + d.x + "," + @height + ") rotate(270)")
.text((d) ->
if d.id.length is 8
return "#{parseInt(d.id[4..5])}/#{parseInt(d.id[6..7])}/#{d.id[0..3]}"
else
return "#{parseInt(d.id[4..5])}/#{d.id[0..3]}"
)
chart.selectAll('.line')
.data(links)
.enter()
.append("line")
.attr("x1", (d) -> d.start.x )
.attr("y1", (d) -> d.start.y )
.attr("x2", (d) -> d.end.x )
.attr("y2", (d) -> d.end.y )
.style("stroke", "rgb(6,120,155)")
chart.selectAll(".circle")
.data(sevenPoints)
.enter()
.append("circle")
.attr("cx", (d) -> d.x )
.attr("cy", (d) -> d.y )
.attr("r", "2px")
.attr("fill", "purple")
chart.selectAll('.line')
.data(sevenLinks)
.enter()
.append("line")
.attr("x1", (d) -> d.start.x )
.attr("y1", (d) -> d.start.y )
.attr("x2", (d) -> d.end.x )
.attr("y2", (d) -> d.end.y )
.style("stroke", "rgb(200,0,0)")
chart.selectAll('.line')
.data(guidelines)
.enter()
.append("line")
.attr("x1", (d) -> d.start.x )
.attr("y1", (d) -> d.start.y )
.attr("x2", (d) -> d.end.x )
.attr("y2", (d) -> d.end.y )
.style("stroke", "rgb(140,140,140)")
chart.selectAll(".text")
.data(guidelines)
.enter()
.append("text")
.attr("x", (d) -> d.start.x)
.attr("y", (d) -> d.start.y - 6)
.attr("dy", ".35em")
.text((d) -> d.start.id)

View file

@ -0,0 +1,96 @@
RootView = require 'views/core/RootView'
template = require 'templates/admin/analytics'
utils = require 'core/utils'
module.exports = class AnalyticsView extends RootView
id: 'admin-analytics-view'
template: template
constructor: (options) ->
super options
@supermodel.addRequestResource('active_classes', {
url: '/db/analytics_perday/-/active_classes'
method: 'POST'
success: (data) =>
@activeClassGroups = {}
dayEventsMap = {}
for activeClass in data
dayEventsMap[activeClass.day] ?= {}
dayEventsMap[activeClass.day]['Total'] = 0
for event, val of activeClass.classes
@activeClassGroups[event] = true
dayEventsMap[activeClass.day][event] = val
dayEventsMap[activeClass.day]['Total'] += val
@activeClassGroups = Object.keys(@activeClassGroups)
@activeClassGroups.push 'Total'
for day of dayEventsMap
for event in @activeClassGroups
dayEventsMap[day][event] ?= 0
@activeClasses = []
for day of dayEventsMap
data = day: day, groups: []
for group in @activeClassGroups
data.groups.push(dayEventsMap[day][group] ? 0)
@activeClasses.push data
@activeClasses.sort (a, b) -> b.day.localeCompare(a.day)
@render?()
}, 0).load()
@supermodel.addRequestResource('active_users', {
url: '/db/analytics_perday/-/active_users'
method: 'POST'
success: (data) =>
@activeUsers = data
@activeUsers.sort (a, b) -> b.day.localeCompare(a.day)
@render?()
}, 0).load()
@supermodel.addRequestResource('recurring_revenue', {
url: '/db/analytics_perday/-/recurring_revenue'
method: 'POST'
success: (data) =>
@revenueGroups = {}
dayGroupCountMap = {}
for dailyRevenue in data
dayGroupCountMap[dailyRevenue.day] ?= {}
dayGroupCountMap[dailyRevenue.day]['Daily'] = 0
for group, val of dailyRevenue.groups
@revenueGroups[group] = true
dayGroupCountMap[dailyRevenue.day][group] = val
dayGroupCountMap[dailyRevenue.day]['Daily'] += val
@revenueGroups = Object.keys(@revenueGroups)
@revenueGroups.push 'Daily'
@revenueGroups.push 'Monthly'
for day of dayGroupCountMap
for group in @revenueGroups
dayGroupCountMap[day][group] ?= 0
@revenue = []
for day of dayGroupCountMap
data = day: day, groups: []
for group in @revenueGroups
data.groups.push(dayGroupCountMap[day][group] ? 0)
@revenue.push data
@revenue.sort (a, b) -> b.day.localeCompare(a.day)
monthlyValues = []
return unless @revenue.length > 0
for i in [@revenue.length-1..0]
dailyTotal = @revenue[i].groups[@revenue[i].groups.length - 2]
monthlyValues.push(dailyTotal)
monthlyValues.shift() if monthlyValues.length > 30
if monthlyValues.length is 30
monthlyIndex = @revenue[i].groups.length - 1
@revenue[i].groups[monthlyIndex] = _.reduce(monthlyValues, (s, num) -> s + num)
@render?()
}, 0).load()
getRenderData: ->
context = super()
context.activeClasses = @activeClasses ? []
context.activeClassGroups = @activeClassGroups ? {}
context.activeUsers = @activeUsers ? []
context.revenue = @revenue ? []
context.revenueGroups = @revenueGroups ? {}
context

View file

@ -64,7 +64,6 @@ module.exports = class ClanDetailsView extends RootView
@supermodel.loadModel @clan, 'clan', cache: false @supermodel.loadModel @clan, 'clan', cache: false
@supermodel.loadCollection(@members, 'members', {cache: false}) @supermodel.loadCollection(@members, 'members', {cache: false})
@supermodel.loadCollection(@memberAchievements, 'member_achievements', {cache: false}) @supermodel.loadCollection(@memberAchievements, 'member_achievements', {cache: false})
@supermodel.loadCollection(@memberSessions, 'member_sessions', {cache: false})
getRenderData: -> getRenderData: ->
context = super() context = super()
@ -115,7 +114,7 @@ module.exports = class ClanDetailsView extends RootView
lastLevelIndex++ lastLevelIndex++
levelCount++ levelCount++
@sortMembers(highestUserLevelCountMap, userConceptsMap) if @clan.get('dashboardType') is 'premium' @sortMembers(highestUserLevelCountMap, userConceptsMap)# if @clan.get('dashboardType') is 'premium'
context.members = @members?.models ? [] context.members = @members?.models ? []
context.lastUserCampaignLevelMap = lastUserCampaignLevelMap context.lastUserCampaignLevelMap = lastUserCampaignLevelMap
context.showExpandedProgress = maxLastUserCampaignLevel <= 30 or @showExpandedProgress context.showExpandedProgress = maxLastUserCampaignLevel <= 30 or @showExpandedProgress
@ -207,6 +206,8 @@ module.exports = class ClanDetailsView extends RootView
@owner = new User _id: @clan.get('ownerID') @owner = new User _id: @clan.get('ownerID')
@listenTo @owner, 'sync', => @render?() @listenTo @owner, 'sync', => @render?()
@supermodel.loadModel @owner, 'owner', cache: false @supermodel.loadModel @owner, 'owner', cache: false
if @clan.get("dashboardType") is "premium"
@supermodel.loadCollection(@memberSessions, 'member_sessions', {cache: false})
@render?() @render?()
onMembersSync: -> onMembersSync: ->

View file

@ -43,8 +43,8 @@ module.exports = class ClansView extends RootView
@idNameMap = {} @idNameMap = {}
sortClanList = (a, b) -> sortClanList = (a, b) ->
if a.get('members').length isnt b.get('members').length if a.get('memberCount') isnt b.get('memberCount')
if a.get('members').length < b.get('members').length then 1 else -1 if a.get('memberCount') < b.get('memberCount') then 1 else -1
else else
b.id.localeCompare(a.id) b.id.localeCompare(a.id)
@publicClans = new CocoCollection([], { url: '/db/clan/-/public', model: Clan, comparator: sortClanList }) @publicClans = new CocoCollection([], { url: '/db/clan/-/public', model: Clan, comparator: sortClanList })

View file

@ -37,7 +37,7 @@ module.exports = class ThangAvatarView extends CocoView
context = super context context = super context
context.thang = @thang context.thang = @thang
options = @thang?.getLankOptions() or {} options = @thang?.getLankOptions() or {}
options.async = true #options.async = true # sync builds fail during async builds, and we build HUD version sync
context.avatarURL = @thangType.getPortraitSource(options) unless @thangType.loading context.avatarURL = @thangType.getPortraitSource(options) unless @thangType.loading
context.includeName = @includeName context.includeName = @includeName
context context

View file

@ -448,8 +448,6 @@ module.exports = class HeroVictoryModal extends ModalView
navigationEvent = route: nextLevelLink, viewClass: viewClass, viewArgs: viewArgs navigationEvent = route: nextLevelLink, viewClass: viewClass, viewArgs: viewArgs
if @level.get('slug') is 'lost-viking' and not (me.get('age') in ['0-13', '14-17']) if @level.get('slug') is 'lost-viking' and not (me.get('age') in ['0-13', '14-17'])
@showOffer navigationEvent @showOffer navigationEvent
else if @level.get('slug') is 'a-mayhem-of-munchkins' and not (me.get('age') in ['0-13']) and not options.showLeaderboard
@showOffer navigationEvent
else else
Backbone.Mediator.publish 'router:navigate', navigationEvent Backbone.Mediator.publish 'router:navigate', navigationEvent
@ -476,7 +474,6 @@ module.exports = class HeroVictoryModal extends ModalView
onClickContinueFromOffer: (e) -> onClickContinueFromOffer: (e) ->
url = { url = {
'lost-viking': 'http://www.vikingcodeschool.com/codecombat?utm_source=codecombat&utm_medium=viking_level&utm_campaign=affiliate&ref=Code+Combat+Elite' 'lost-viking': 'http://www.vikingcodeschool.com/codecombat?utm_source=codecombat&utm_medium=viking_level&utm_campaign=affiliate&ref=Code+Combat+Elite'
'a-mayhem-of-munchkins': 'https://www.bloc.io/web-developer-career-track?utm_campaign=affiliate&utm_source=codecombat&utm_medium=bloc_level'
}[@level.get('slug')] }[@level.get('slug')]
Backbone.Mediator.publish 'router:navigate', @navigationEventUponCompletion Backbone.Mediator.publish 'router:navigate', @navigationEventUponCompletion
window.open url, '_blank' if url window.open url, '_blank' if url

View file

@ -106,6 +106,7 @@ module.exports = class SpellView extends CocoView
@ace.setAnimatedScroll true @ace.setAnimatedScroll true
@ace.setShowFoldWidgets false @ace.setShowFoldWidgets false
@ace.setKeyboardHandler @keyBindings[aceConfig.keyBindings ? 'default'] @ace.setKeyboardHandler @keyBindings[aceConfig.keyBindings ? 'default']
@ace.$blockScrolling = Infinity
@toggleControls null, @writable @toggleControls null, @writable
@aceSession.selection.on 'changeCursor', @onCursorActivity @aceSession.selection.on 'changeCursor', @onCursorActivity
$(@ace.container).find('.ace_gutter').on 'click mouseenter', '.ace_error, .ace_warning, .ace_info', @onAnnotationClick $(@ace.container).find('.ace_gutter').on 'click mouseenter', '.ace_error, .ace_warning, .ace_info', @onAnnotationClick
@ -262,8 +263,10 @@ module.exports = class SpellView extends CocoView
@ace.commands.on 'exec', (e) => @ace.commands.on 'exec', (e) =>
# When pressing enter with an active selection, just make a new line under it. # When pressing enter with an active selection, just make a new line under it.
if e.command.name is 'enter-skip-delimiters' if e.command.name is 'enter-skip-delimiters'
e.editor.execCommand 'gotolineend' selection = @ace.selection.getRange()
return true unless selection.start.column is selection.end.column and selection.start.row is selection.end.row
e.editor.execCommand 'gotolineend'
return true
fillACE: -> fillACE: ->
@ace.setValue @spell.source @ace.setValue @spell.source
@ -459,7 +462,7 @@ module.exports = class SpellView extends CocoView
entry.captureReturn = switch e.language entry.captureReturn = switch e.language
when 'io' then varName + ' := ' when 'io' then varName + ' := '
when 'javascript' then 'var ' + varName + ' = ' when 'javascript' then 'var ' + varName + ' = '
when 'clojure' then '(let [' + varName + ' ' when 'clojure' then '(let [' + varName + ' '
else varName + ' = ' else varName + ' = '
# TODO: Generalize this snippet replacement # TODO: Generalize this snippet replacement

View file

@ -41,7 +41,7 @@ module.exports = class LevelGuideView extends CocoView
@docs = specific.concat(general) @docs = specific.concat(general)
@docs = $.extend(true, [], @docs) @docs = $.extend(true, [], @docs)
@docs = [@docs[0]] if @firstOnly and @docs[0] @docs = [@docs[0]] if @firstOnly and @docs[0]
doc.html = marked(utils.i18n doc, 'body') for doc in @docs doc.html = marked(@filterCodeLanguages(utils.i18n(doc, 'body'))) for doc in @docs
doc.name = (utils.i18n doc, 'name') for doc in @docs doc.name = (utils.i18n doc, 'name') for doc in @docs
doc.slug = _.string.slugify(doc.name) for doc in @docs doc.slug = _.string.slugify(doc.name) for doc in @docs
super() super()
@ -72,6 +72,12 @@ module.exports = class LevelGuideView extends CocoView
@$el.find('.nav-tabs a').click(@clickTab) @$el.find('.nav-tabs a').click(@clickTab)
@playSound 'guide-open' @playSound 'guide-open'
filterCodeLanguages: (text) ->
currentLanguage = me.get('aceConfig')?.language or 'python'
excludedLanguages = _.without ['javascript', 'python', 'coffeescript', 'clojure', 'lua', 'io'], currentLanguage
exclusionRegex = new RegExp "```(#{excludedLanguages.join('|')})\n[^`]+```\n?", 'gm'
text.replace exclusionRegex, ''
clickSubscribe: (e) -> clickSubscribe: (e) ->
level = @levelSlug # Save ref to level slug level = @levelSlug # Save ref to level slug
@openModalView new SubscribeModal() @openModalView new SubscribeModal()

View file

@ -32,13 +32,17 @@ exports.config =
overrides: overrides:
production: production:
sourceMaps: 'absoluteUrl' sourceMaps: 'absoluteUrl'
onCompile: (files) -> plugins:
# For some reason, production brunch produces two entries, the first of which is wrong: coffeelint:
# //# sourceMappingURL=public/javascripts/app.js.map pattern: /\A\Z/
# //# sourceMappingURL=/javascripts/app.js.map afterBrunch: [
# So we remove the ones that have public in them. "coffee scripts/minify.coffee",
exec = require('child_process').exec ]
exec "perl -pi -e 's/\\/\\/# sourceMappingURL=public.*//g' public/javascripts/*.js" fast:
onCompile: (files) -> console.log "I feel the need, the need... for speed."
plugins:
coffeelint:
pattern: /\A\Z/
vagrant: vagrant:
watcher: watcher:
usePolling: true usePolling: true
@ -181,7 +185,6 @@ exports.config =
plugins: plugins:
coffeelint: coffeelint:
pattern: /^app\/.*\.coffee$/ pattern: /^app\/.*\.coffee$/
# pattern: /^dne/ # use this pattern instead if you want to speed compilation
options: options:
line_endings: line_endings:
value: 'unix' value: 'unix'
@ -192,16 +195,14 @@ exports.config =
level: 'ignore' # PyCharm can't just autostrip for .coffee, needed for .jade level: 'ignore' # PyCharm can't just autostrip for .coffee, needed for .jade
no_unnecessary_fat_arrows: no_unnecessary_fat_arrows:
level: 'ignore' level: 'ignore'
uglify:
mangle:
except: ['require']
output:
semicolons: false
sass: sass:
mode: 'native' mode: 'native'
allowCache: true allowCache: true
bless: bless:
cacheBuster: false cacheBuster: false
assetsmanager:
copyTo:
'lib/ace': ['node_modules/ace-builds/src-min-noconflict/*']
modules: modules:
definition: (path, data) -> definition: (path, data) ->

View file

@ -45,7 +45,17 @@ disable = [
GLOBAL.window = GLOBAL GLOBAL.window = GLOBAL
GLOBAL.document = location: pathname: 'headless_client' GLOBAL.document = location: pathname: 'headless_client'
GLOBAL.console.debug = console.log GLOBAL.console.debug = console.log
GLOBAL.Worker = require('webworker-threads').Worker try
GLOBAL.Worker = require('webworker-threads').Worker
catch
console.log ""
console.log "Headless client needs the webworker-threads package from NPM to function."
console.log "Try installing it with the command:"
console.log ""
console.log " npm install webworker-threads"
console.log ""
process.exit(1)
Worker::removeEventListener = (what) -> Worker::removeEventListener = (what) ->
if what is 'message' if what is 'message'
@onmessage = -> #This webworker api has only one event listener at a time. @onmessage = -> #This webworker api has only one event listener at a time.

View file

@ -33,12 +33,14 @@
"test": "./node_modules/.bin/karma start", "test": "./node_modules/.bin/karma start",
"predeploy": "echo Starting deployment--hold onto your butts.; echo Skipping brunch build --production", "predeploy": "echo Starting deployment--hold onto your butts.; echo Skipping brunch build --production",
"postdeploy": "echo Deployed. Unclench.", "postdeploy": "echo Deployed. Unclench.",
"postinstall": "bower install && brunch build", "postinstall": "bower install && brunch build --env fast",
"brunch": "brunch", "brunch": "brunch",
"bower": "bower", "bower": "bower",
"dev": "brunch watch --server", "dev": "brunch watch --server",
"nodemon": "nodemon", "nodemon": "nodemon",
"jasmine-node": "jasmine-node" "jasmine-node": "jasmine-node",
"multicore": "coffee multicore.coffee",
"nodemon": "nodemon"
}, },
"main": "index.js", "main": "index.js",
"keywords": [ "keywords": [
@ -49,6 +51,7 @@
], ],
"dependencies": { "dependencies": {
"JQDeferred": "~2.1.0", "JQDeferred": "~2.1.0",
"ace-builds": "https://github.com/ajaxorg/ace-builds/archive/3fb55e8e374ab02ce47c1ae55ffb60a1835f3055.tar.gz",
"aether": "~0.3.0", "aether": "~0.3.0",
"async": "0.2.x", "async": "0.2.x",
"aws-sdk": "~2.0.0", "aws-sdk": "~2.0.0",
@ -78,19 +81,21 @@
"stripe": "~2.9.0", "stripe": "~2.9.0",
"tv4": "~1.0.16", "tv4": "~1.0.16",
"underscore.string": "2.3.x", "underscore.string": "2.3.x",
"webworker-threads": "~0.5.5",
"winston": "0.6.x" "winston": "0.6.x"
}, },
"devDependencies": { "devDependencies": {
"after-brunch": "0.0.5",
"assetsmanager-brunch": "^1.8.1",
"auto-reload-brunch": "> 1.0 < 1.8", "auto-reload-brunch": "> 1.0 < 1.8",
"bless-brunch": "https://github.com/ThomasConner/bless-brunch/tarball/master", "bless-brunch": "https://github.com/ThomasConner/bless-brunch/tarball/master",
"bower": "~1.6.4", "bower": "~1.6.4",
"brunch": "^1.8.5", "brunch": "^1.8.5",
"coffee-script-brunch": "^1.8.3", "coffee-script-brunch": "^1.8.3",
"coffeelint-brunch": "^1.7.1", "coffeelint-brunch": "^1.7.1",
"compressible": "~1.0.1",
"commonjs-require-definition": "0.2.0", "commonjs-require-definition": "0.2.0",
"compressible": "~1.0.1",
"css-brunch": "^1.7.0", "css-brunch": "^1.7.0",
"fs-extra": "^0.26.2",
"jade-brunch": "1.7.5", "jade-brunch": "1.7.5",
"jasmine-node": "1.13.x", "jasmine-node": "1.13.x",
"jasmine-spec-reporter": "~0.3.0", "jasmine-spec-reporter": "~0.3.0",
@ -110,7 +115,10 @@
"requirejs": "~2.1.10", "requirejs": "~2.1.10",
"sass-brunch": "https://github.com/basicer/sass-brunch-bleeding/archive/1.9.1-bleeding.tar.gz", "sass-brunch": "https://github.com/basicer/sass-brunch-bleeding/archive/1.9.1-bleeding.tar.gz",
"telepath-brunch": "https://github.com/nwinter/telepath-brunch/tarball/master", "telepath-brunch": "https://github.com/nwinter/telepath-brunch/tarball/master",
"uglify-js-brunch": "^1.7.8" "uglify-js": "^2.5.0"
},
"optionalDependencies": {
"webworker-threads": "~0.5.5"
}, },
"license": "MIT for the code, and CC-BY for the art and music", "license": "MIT for the code, and CC-BY for the art and music",
"private": true, "private": true,

View file

@ -17,8 +17,8 @@ try {
var scriptStartTime = new Date(); var scriptStartTime = new Date();
var analyticsStringCache = {}; var analyticsStringCache = {};
// Look at last 30 days, same as Mixpanel var numDays = 40;
var numDays = 30; var daysInMonth = 30;
var startDay = new Date(); var startDay = new Date();
today = startDay.toISOString().substr(0, 10); today = startDay.toISOString().substr(0, 10);
@ -27,6 +27,7 @@ try {
var levelCompletionFunnel = ['Started Level', 'Saw Victory']; var levelCompletionFunnel = ['Started Level', 'Saw Victory'];
var levelHelpEvents = ['Problem alert help clicked', 'Spell palette help clicked', 'Start help video']; var levelHelpEvents = ['Problem alert help clicked', 'Spell palette help clicked', 'Start help video'];
var activeUserEvents = ['Finished Signup', 'Started Level'];
log("Today is " + today); log("Today is " + today);
log("Start day is " + startDay); log("Start day is " + startDay);
@ -39,7 +40,7 @@ try {
for (day in levelCompletionData[level]) { for (day in levelCompletionData[level]) {
if (today === day) continue; // Never save data for today because it's incomplete if (today === day) continue; // Never save data for today because it's incomplete
for (event in levelCompletionData[level][day]) { for (event in levelCompletionData[level][day]) {
insertEventCount(event, level, day, levelCompletionData[level][day][event]); insertLevelEventCount(event, level, day, levelCompletionData[level][day][event]);
} }
} }
} }
@ -50,7 +51,7 @@ try {
for (level in levelDropCounts) { for (level in levelDropCounts) {
for (day in levelDropCounts[level]) { for (day in levelDropCounts[level]) {
if (today === day) continue; // Never save data for today because it's incomplete if (today === day) continue; // Never save data for today because it's incomplete
insertEventCount('User Dropped', level, day, levelDropCounts[level][day]); insertLevelEventCount('User Dropped', level, day, levelDropCounts[level][day]);
} }
} }
@ -61,7 +62,7 @@ try {
for (day in levelHelpCounts[level]) { for (day in levelHelpCounts[level]) {
if (today === day) continue; // Never save data for today because it's incomplete if (today === day) continue; // Never save data for today because it's incomplete
for (event in levelHelpCounts[level][day]) { for (event in levelHelpCounts[level][day]) {
insertEventCount(event, level, day, levelHelpCounts[level][day][event]); insertLevelEventCount(event, level, day, levelHelpCounts[level][day][event]);
} }
} }
} }
@ -73,11 +74,44 @@ try {
for (day in levelSubscriptionCounts[level]) { for (day in levelSubscriptionCounts[level]) {
if (today === day) continue; // Never save data for today because it's incomplete if (today === day) continue; // Never save data for today because it's incomplete
for (event in levelSubscriptionCounts[level][day]) { for (event in levelSubscriptionCounts[level][day]) {
insertEventCount(event, level, day, levelSubscriptionCounts[level][day][event]); insertLevelEventCount(event, level, day, levelSubscriptionCounts[level][day][event]);
} }
} }
} }
log("Getting active user counts...");
var activeUserCounts = getActiveUserCounts(startDay, activeUserEvents);
// printjson(activeUserCounts);
log("Inserting active user counts...");
for (day in activeUserCounts) {
if (today === day) continue; // Never save data for today because it's incomplete
for (event in activeUserCounts[day]) {
insertEventCount(event, day, activeUserCounts[day][event]);
}
}
log("Getting active class counts...");
var activeClassCounts = getActiveClassCounts(startDay);
// printjson(activeClassCounts);
log("Inserting active class counts...");
for (var event in activeClassCounts) {
for (var day in activeClassCounts[event]) {
if (today === day) continue; // Never save data for today because it's incomplete
insertEventCount(event, day, activeClassCounts[event][day]);
}
}
log("Getting monthly recurring revenue counts...");
var recurringRevenueCounts = getRecurringRevenueCounts(startDay);
// printjson(recurringRevenueCounts);
log("Inserting monthly recurring revenue counts...");
for (var event in recurringRevenueCounts) {
for (var day in recurringRevenueCounts[event]) {
if (today === day) continue; // Never save data for today because it's incomplete
insertEventCount(event, day, recurringRevenueCounts[event][day]);
}
}
log("Script runtime: " + (new Date() - scriptStartTime)); log("Script runtime: " + (new Date() - scriptStartTime));
} }
catch(err) { catch(err) {
@ -383,7 +417,306 @@ function getLevelSubscriptionCounts(startDay) {
return levelFunnelData; return levelFunnelData;
} }
function insertEventCount(event, level, day, count) { function getActiveUserCounts(startDay, activeUserEvents) {
// Counts active users per day
if (!startDay) return {};
var startObj = objectIdWithTimestamp(ISODate(startDay + "T00:00:00.000Z"));
var queryParams = {$and: [
{_id: {$gte: startObj}},
{'event': {$in: activeUserEvents}}
]};
var cursor = logDB['log'].find(queryParams);
var dayUserMap = {};
while (cursor.hasNext()) {
var doc = cursor.next();
var created = doc._id.getTimestamp().toISOString();
var day = created.substring(0, 10);
var user = doc.user;
if (!dayUserMap[day]) dayUserMap[day] = {};
dayUserMap[day][user] = true;
}
// printjson(dayUserMap['2015-11-01']);
var activeUsersCounts = {};
var monthlyActives = [];
for (day in dayUserMap) {
activeUsersCounts[day] = {'Daily Active Users': Object.keys(dayUserMap[day]).length};
monthlyActives.push({day: day, users: dayUserMap[day]});
}
monthlyActives.sort(function (a, b) {return a.day.localeCompare(b.day);});
// Calculate monthly actives for each day, starting when we have enough data
for (var i = daysInMonth - 1; i < monthlyActives.length; i++) {
var monthUserMap = {};
for (var j = i - daysInMonth + 1; j <= i; j++) {
for (var user in monthlyActives[j].users) {
monthUserMap[user] = true;
}
}
activeUsersCounts[monthlyActives[i].day]['Monthly Active Users'] = Object.keys(monthUserMap).length;
}
return activeUsersCounts;
}
function getActiveClassCounts(startDay) {
// Tally active classes per day
// TODO: does not handle class membership changes
if (!startDay) return {};
var minGroupSize = 12;
var classes = {
'Active classes private clan': [],
'Active classes managed subscription': [],
'Active classes bulk subscription': [],
'Active classes prepaid': [],
'Active classes course': [],
};
var userPlayedMap = {};
// Private clans
// TODO: does not handle clan membership changes over time
var cursor = db.clans.find({$and: [{type: 'private'}, {$where: 'this.members.length >= ' + minGroupSize}]});
while (cursor.hasNext()) {
var doc = cursor.next();
var members = doc.members.map(function(a) {
userPlayedMap[a.valueOf()] = [];
return a.valueOf();
});
classes['Active classes private clan'].push({
owner: doc.ownerID.valueOf(),
members: members,
activeDayMap: {}
});
}
// Managed subscriptions
// TODO: does not handle former recipients playing after sponsorship ends
var bulkSubGroups = {};
cursor = db.payments.find({$and: [{service: 'stripe'}, {$where: '!this.purchaser.equals(this.recipient)'}]});
while (cursor.hasNext()) {
var doc = cursor.next();
var purchaser = doc.purchaser.valueOf();
if (!bulkSubGroups[purchaser]) bulkSubGroups[purchaser] = {};
bulkSubGroups[purchaser][doc.recipient.valueOf()] = true;
}
for (var purchaser in bulkSubGroups) {
if (Object.keys(bulkSubGroups[purchaser]).length >= minGroupSize) {
for (var member in bulkSubGroups[purchaser]) {
userPlayedMap[member] = [];
}
classes['Active classes managed subscription'].push({
owner: purchaser,
members: Object.keys(bulkSubGroups[purchaser]),
activeDayMap: {}
});
}
}
// Bulk subscriptions
bulkSubGroups = {};
cursor = db.payments.find({$and: [{service: 'external'}, {$where: '!this.purchaser.equals(this.recipient)'}]});
while (cursor.hasNext()) {
var doc = cursor.next();
var purchaser = doc.purchaser.valueOf();
if (!bulkSubGroups[purchaser]) bulkSubGroups[purchaser] = {};
bulkSubGroups[purchaser][doc.recipient.valueOf()] = true;
}
for (var purchaser in bulkSubGroups) {
if (Object.keys(bulkSubGroups[purchaser]).length >= minGroupSize) {
for (var member in bulkSubGroups[purchaser]) {
userPlayedMap[member] = [];
}
classes['Active classes bulk subscription'].push({
owner: purchaser,
members: Object.keys(bulkSubGroups[purchaser]),
activeDayMap: {}
});
}
}
// Prepaids terminal_subscription & course
bulkSubGroups = {};
cursor = db.prepaids.find(
{$and: [{type: {$in: ['terminal_subscription', 'course']}}, {$where: 'this.redeemers && this.redeemers.length >= ' + minGroupSize}]},
{creator: 1, type: 1, redeemers: 1}
);
while (cursor.hasNext()) {
var doc = cursor.next();
var owner = doc.creator.valueOf();
var members = [];
for (var i = 0 ; i < doc.redeemers.length; i++) {
userPlayedMap[doc.redeemers[i].userID.valueOf()] = [];
members.push(doc.redeemers[i].userID.valueOf());
}
var event = doc.type == 'terminal_subscription' ? 'Active classes prepaid' : 'Active classes course';
classes[event].push({
owner: owner,
members: members,
activeDayMap: {}
});
}
// printjson(classes);
// TODO: classrooms
// Find all the started level events for our class members, for startDay - daysInMonth
var startDate = ISODate(startDay + "T00:00:00.000Z");
startDate.setUTCDate(startDate.getUTCDate() - daysInMonth);
var endDate = ISODate(startDay + "T00:00:00.000Z");
var todayDate = new Date(new Date().toISOString().substring(0, 10));
var startObj = objectIdWithTimestamp(startDate);
var queryParams = {$and: [
{_id: {$gte: startObj}},
{event: 'Started Level'},
{user: {$in: Object.keys(userPlayedMap)}}
]};
cursor = logDB['log'].find(queryParams, {user: 1});
// cursor = db['level.sessions'].find({$and: [{creator: {$in: Object.keys(userPlayedMap)}}, {changed: {$gte: startDate}}]}, {creator: 1, changed: 1});
while (cursor.hasNext()) {
var doc = cursor.next();
userPlayedMap[doc.user].push(doc._id.getTimestamp());
}
// printjson(userPlayedMap);
// print(startDate, endDate, todayDate);
// Now we have a set of classes, and when users played
// For a given day, walk classes and find out how many members were active during the previous daysInMonth
while (endDate < todayDate) {
var endDay = endDate.toISOString().substring(0, 10);
// For each class
for (var event in classes) {
for (var i = 0; i < classes[event].length; i++) {
// For each member of current class
var activeMemberCount = 0;
for (var j = 0; j < classes[event][i].members.length; j++) {
var member = classes[event][i].members[j];
// Was member active during current timeframe?
if (userPlayedMap[member]) {
for (var k = 0; k < userPlayedMap[member].length; k++) {
if (userPlayedMap[member][k] > startDate && userPlayedMap[member][k] <= endDate) {
activeMemberCount++;
break;
}
}
}
}
// Classes active for a given day if has minGroupSize members, and at least 1/2 played in last daysInMonth days
if (activeMemberCount >= Math.round(classes[event][i].members.length / 2)) {
classes[event][i].activeDayMap[endDay] = true;
}
}
}
startDate.setUTCDate(startDate.getUTCDate() + 1);
endDate.setUTCDate(endDate.getUTCDate() + 1);
}
var activeClassCounts = {};
for (var event in classes) {
if (!activeClassCounts[event]) activeClassCounts[event] = {};
for (var i = 0; i < classes[event].length; i++) {
for (var endDay in classes[event][i].activeDayMap) {
if (!activeClassCounts[event][endDay]) activeClassCounts[event][endDay] = 0;
activeClassCounts[event][endDay]++;
}
}
}
return activeClassCounts;
}
function getRecurringRevenueCounts(startDay) {
if (!startDay) return {};
var dailyRevenueCounts = {};
var startObj = objectIdWithTimestamp(ISODate(startDay + "T00:00:00.000Z"));
var cursor = db.payments.find({_id: {$gte: startObj}});
while (cursor.hasNext()) {
var doc = cursor.next();
var day = doc._id.getTimestamp().toISOString().substring(0, 10);
if (doc.service === 'ios' || doc.service === 'bitcoin') continue;
if (doc.productID && doc.productID.indexOf('gems_') === 0) {
if (!dailyRevenueCounts['DRR gems']) dailyRevenueCounts['DRR gems'] = {};
if (!dailyRevenueCounts['DRR gems'][day]) dailyRevenueCounts['DRR gems'][day] = 0;
dailyRevenueCounts['DRR gems'][day] += doc.amount
}
else if (doc.productID === 'custom' || doc.service === 'external' || doc.service === 'invoice') {
if (!dailyRevenueCounts['DRR school sales']) dailyRevenueCounts['DRR school sales'] = {};
if (!dailyRevenueCounts['DRR school sales'][day]) dailyRevenueCounts['DRR school sales'][day] = 0;
dailyRevenueCounts['DRR school sales'][day] += doc.amount
}
else if (doc.service === 'stripe' && doc.gems === 42000) {
if (!dailyRevenueCounts['DRR yearly subs']) dailyRevenueCounts['DRR yearly subs'] = {};
if (!dailyRevenueCounts['DRR yearly subs'][day]) dailyRevenueCounts['DRR yearly subs'][day] = 0;
dailyRevenueCounts['DRR yearly subs'][day] += doc.amount
}
else if (doc.service === 'stripe') {
// Catches prepaids, and assumes all are type terminal_subscription
if (!dailyRevenueCounts['DRR monthly subs']) dailyRevenueCounts['DRR monthly subs'] = {};
if (!dailyRevenueCounts['DRR monthly subs'][day]) dailyRevenueCounts['DRR monthly subs'][day] = 0;
dailyRevenueCounts['DRR monthly subs'][day] += doc.amount
}
else if (doc.service === 'paypal') {
if (!dailyRevenueCounts['DRR paypal']) dailyRevenueCounts['DRR paypal'] = {};
if (!dailyRevenueCounts['DRR paypal'][day]) dailyRevenueCounts['DRR paypal'][day] = 0;
dailyRevenueCounts['DRR paypal'][day] += doc.amount
}
// else {
// // printjson(doc);
// // print(doc.service, doc.amount, doc.description, JSON.stringify(doc.stripe));
// }
}
return dailyRevenueCounts;
}
function insertEventCount(event, day, count) {
// analytics.perdays schema in server/analytics/AnalyticsPeryDay.coffee
day = day.replace(/-/g, '');
var eventID = getAnalyticsString(event);
var filterID = getAnalyticsString('all');
var startObj = objectIdWithTimestamp(ISODate(startDay + "T00:00:00.000Z"));
var queryParams = {$and: [{d: day}, {e: eventID}, {f: filterID}]};
var doc = db['analytics.perdays'].findOne(queryParams);
if (doc && doc.c === count) return;
if (doc && doc.c !== count) {
// Update existing count, assume new one is more accurate
// log("Updating count in db for " + day + " " + event + " " + doc.c + " => " + count);
var results = db['analytics.perdays'].update(queryParams, {$set: {c: count}});
if (results.nMatched !== 1 && results.nModified !== 1) {
log("ERROR: update event count failed");
printjson(results);
}
}
else {
var insertDoc = {d: day, e: eventID, f: filterID, c: count};
var results = db['analytics.perdays'].insert(insertDoc);
if (results.nInserted !== 1) {
log("ERROR: insert event failed");
printjson(results);
printjson(insertDoc);
}
// else {
// log("Added " + day + " " + event + " " + count);
// }
}
}
function insertLevelEventCount(event, level, day, count) {
// analytics.perdays schema in server/analytics/AnalyticsPeryDay.coffee // analytics.perdays schema in server/analytics/AnalyticsPeryDay.coffee
day = day.replace(/-/g, ''); day = day.replace(/-/g, '');

61
scripts/minify.coffee Normal file
View file

@ -0,0 +1,61 @@
path = require 'path'
fs = require 'fs-extra'
_ = require 'lodash'
async = require 'async'
cores = require('os').cpus().length
child_process = require 'child_process'
root = path.join(__dirname, '..', 'public','javascripts');
dest = path.join(__dirname, '..', 'public','javascripts-min');
console.log root
dirStack = [path.join(root)]
files = []
while dirStack.length
dir = dirStack.pop()
contents = fs.readdirSync(dir)
for file in contents
fullPath = "#{dir}/#{file}"
stat = fs.statSync(fullPath)
if stat.isDirectory()
dirStack.push(fullPath)
else if /\.js$/.test(file)
files.push fullPath.replace root + '/', ''
jobs = _.map files, (file) ->
(cb2) ->
fpath = path.join(root, file)
dpath = path.join(dest, file)
smArgs = []
if fs.existsSync fpath + '.map'
smArgs = [
'--in-source-map', fpath + '.map',
'--source-map', dpath + '.map',
'--source-map-include-sources',
'--source-map-url', '/javascripts/' + file.replace('/\\/g', '/') + '.map'
]
args = [fpath, '-m', '-r', 'require' , '-b', 'beautify=false,semicolons=false'].concat smArgs, ['-o', dpath]
async.waterfall [
_.bind(fs.mkdirs, fs, path.dirname dpath),
(last, cb) ->
child = child_process.spawn 'uglifyjs', args, stdio:'inherit'
child.on 'close', (code) ->
if code == 0 then cb null
else cb code
child.on 'error', (err) ->
cb err
], cb2
async.parallelLimit jobs, cores, (err, res)->
if err
console.log "ERROR:", err
else
console.log "Done, minified " + jobs.length + " files."
fs.renameSync(root, root + "-old")
fs.renameSync(dest, root)
fs.removeSync(root + "-old")

View file

@ -14,13 +14,67 @@ class AnalyticsPerDayHandler extends Handler
getByRelationship: (req, res, args...) -> getByRelationship: (req, res, args...) ->
return @sendForbiddenError res unless @hasAccess req return @sendForbiddenError res unless @hasAccess req
return @getActiveClasses(req, res) if args[1] is 'active_classes'
return @getActiveUsers(req, res) if args[1] is 'active_users'
return @getCampaignCompletionsBySlug(req, res) if args[1] is 'campaign_completions' return @getCampaignCompletionsBySlug(req, res) if args[1] is 'campaign_completions'
return @getLevelCompletionsBySlug(req, res) if args[1] is 'level_completions' return @getLevelCompletionsBySlug(req, res) if args[1] is 'level_completions'
return @getLevelDropsBySlugs(req, res) if args[1] is 'level_drops' return @getLevelDropsBySlugs(req, res) if args[1] is 'level_drops'
return @getLevelHelpsBySlugs(req, res) if args[1] is 'level_helps' return @getLevelHelpsBySlugs(req, res) if args[1] is 'level_helps'
return @getLevelSubscriptionsBySlugs(req, res) if args[1] is 'level_subscriptions' return @getLevelSubscriptionsBySlugs(req, res) if args[1] is 'level_subscriptions'
return @getRecurringRevenue(req, res) if args[1] is 'recurring_revenue'
super(arguments...) super(arguments...)
getActiveClasses: (req, res) ->
events = [
'Active classes private clan',
'Active classes managed subscription',
'Active classes bulk subscription',
'Active classes prepaid',
'Active classes course']
AnalyticsString.find({v: {$in: events}}).exec (err, documents) =>
return @sendDatabaseError(res, err) if err
eventIDs = []
eventStringMap = {}
for doc in documents
eventStringMap[doc._id.valueOf()] = doc.v
eventIDs.push doc._id
return @sendSuccess res, [] unless eventIDs.length is events.length
AnalyticsPerDay.find({e: {$in: eventIDs}}).exec (err, documents) =>
return @sendDatabaseError(res, err) if err
dayCountsMap = {}
for doc in documents
dayCountsMap[doc.d] ?= {}
dayCountsMap[doc.d][eventStringMap[doc.e.valueOf()]] = doc.c
activeClasses = []
for key, val of dayCountsMap
activeClasses.push day: key, classes: dayCountsMap[key]
@sendSuccess(res, activeClasses)
getActiveUsers: (req, res) ->
AnalyticsString.find({v: {$in: ['Daily Active Users', 'Monthly Active Users']}}).exec (err, documents) =>
return @sendDatabaseError(res, err) if err
for doc in documents
dailyID = doc._id if doc.v is 'Daily Active Users'
monthlyID = doc._id if doc.v is 'Monthly Active Users'
return @sendSuccess res, [] unless dailyID? and monthlyID?
AnalyticsPerDay.find({e: {$in: [dailyID, monthlyID]}}).exec (err, documents) =>
return @sendDatabaseError(res, err) if err
dayCountsMap = {}
for doc in documents
dayCountsMap[doc.d] ?= {}
dayCountsMap[doc.d]['dailyCount'] = doc.c if doc.e is dailyID
dayCountsMap[doc.d]['monthlyCount'] = doc.c if doc.e is monthlyID
activeUsers = []
for key, val of dayCountsMap
data = day: key
data.dailyCount = val.dailyCount if val.dailyCount
data.monthlyCount = val.monthlyCount if val.monthlyCount
activeUsers.push data
@sendSuccess(res, activeUsers)
getCampaignCompletionsBySlug: (req, res) -> getCampaignCompletionsBySlug: (req, res) ->
# Send back an ordered array of level per-day starts and finishes # Send back an ordered array of level per-day starts and finishes
# Parameters: # Parameters:
@ -412,4 +466,33 @@ class AnalyticsPerDayHandler extends Handler
@levelSubscriptionsCache[cacheKey] = subscriptions @levelSubscriptionsCache[cacheKey] = subscriptions
@sendSuccess res, subscriptions @sendSuccess res, subscriptions
getRecurringRevenue: (req, res) ->
events = [
'DRR gems',
'DRR school sales',
'DRR yearly subs',
'DRR monthly subs',
'DRR paypal']
AnalyticsString.find({v: {$in: events}}).exec (err, documents) =>
return @sendDatabaseError(res, err) if err
eventIDs = []
eventStringMap = {}
for doc in documents
eventStringMap[doc._id.valueOf()] = doc.v
eventIDs.push doc._id
return @sendSuccess res, [] unless eventIDs.length is events.length
AnalyticsPerDay.find({e: {$in: eventIDs}}).exec (err, documents) =>
return @sendDatabaseError(res, err) if err
dayCountsMap = {}
for doc in documents
dayCountsMap[doc.d] ?= {}
dayCountsMap[doc.d][eventStringMap[doc.e.valueOf()]] = doc.c
recurringRevenue = []
for key, val of dayCountsMap
recurringRevenue.push day: key, groups: dayCountsMap[key] ? {}
@sendSuccess(res, recurringRevenue)
module.exports = new AnalyticsPerDayHandler() module.exports = new AnalyticsPerDayHandler()

View file

@ -10,6 +10,8 @@ LevelSessionHandler = require '../levels/sessions/level_session_handler'
User = require '../users/User' User = require '../users/User'
UserHandler = require '../users/user_handler' UserHandler = require '../users/user_handler'
memberLimit = 200
ClanHandler = class ClanHandler extends Handler ClanHandler = class ClanHandler extends Handler
modelClass: Clan modelClass: Clan
jsonSchema: require '../../app/schemas/models/clan.schema' jsonSchema: require '../../app/schemas/models/clan.schema'
@ -94,17 +96,15 @@ ClanHandler = class ClanHandler extends Handler
getMemberAchievements: (req, res, clanID) -> getMemberAchievements: (req, res, clanID) ->
# TODO: add tests # TODO: add tests
memberLimit = 200
Clan.findById clanID, (err, clan) => Clan.findById clanID, (err, clan) =>
return @sendDatabaseError(res, err) if err return @sendDatabaseError(res, err) if err
return @sendNotFoundError(res) unless clan return @sendNotFoundError(res) unless clan
memberIDs = _.map clan.get('members') ? [], (memberID) -> memberID.toHexString?() or memberID memberIDs = _.map clan.get('members') ? [], (memberID) -> memberID.toHexString?() or memberID
User.find {_id: {$in: memberIDs}}, 'nameLower', {sort: {nameLower: 1}}, (err, users) => User.find {_id: {$in: memberIDs}}, 'nameLower', {limit: memberLimit}, (err, users) =>
return @sendDatabaseError(res, err) if err return @sendDatabaseError(res, err) if err
memberIDs = [] memberIDs = []
for user in users for user in users
memberIDs.push user.id memberIDs.push user.id
break unless memberIDs.length < memberLimit
EarnedAchievement.find {user: {$in: memberIDs}}, 'achievementName user', (err, documents) => EarnedAchievement.find {user: {$in: memberIDs}}, 'achievementName user', (err, documents) =>
return @sendDatabaseError(res, err) if err? return @sendDatabaseError(res, err) if err?
cleandocs = (EarnedAchievementHandler.formatEntity(req, doc) for doc in documents) cleandocs = (EarnedAchievementHandler.formatEntity(req, doc) for doc in documents)
@ -115,8 +115,8 @@ ClanHandler = class ClanHandler extends Handler
Clan.findById clanID, (err, clan) => Clan.findById clanID, (err, clan) =>
return @sendDatabaseError(res, err) if err return @sendDatabaseError(res, err) if err
return @sendNotFoundError(res) unless clan return @sendNotFoundError(res) unless clan
memberIDs = clan.get('members') ? [] memberIDs = _.map clan.get('members') ? [], (memberID) -> memberID.toHexString?() or memberID
User.find {_id: {$in: memberIDs}}, 'name nameLower points heroConfig.thangType', {sort: {nameLower: 1}}, (err, users) => User.find {_id: {$in: memberIDs}}, 'name nameLower points heroConfig.thangType', {}, (err, users) =>
return @sendDatabaseError(res, err) if err return @sendDatabaseError(res, err) if err
cleandocs = (UserHandler.formatEntity(req, doc) for doc in users) cleandocs = (UserHandler.formatEntity(req, doc) for doc in users)
@sendSuccess(res, cleandocs) @sendSuccess(res, cleandocs)
@ -124,12 +124,12 @@ ClanHandler = class ClanHandler extends Handler
getMemberSessions: (req, res, clanID) -> getMemberSessions: (req, res, clanID) ->
# TODO: add tests # TODO: add tests
# TODO: restrict information returned based on clan type # TODO: restrict information returned based on clan type
memberLimit = 200
Clan.findById clanID, (err, clan) => Clan.findById clanID, (err, clan) =>
return @sendDatabaseError(res, err) if err return @sendDatabaseError(res, err) if err
return @sendNotFoundError(res) unless clan return @sendNotFoundError(res) unless clan
return @sendForbiddenError(res) unless clan.get('dashboardType') is 'premium'
memberIDs = _.map clan.get('members') ? [], (memberID) -> memberID.toHexString?() or memberID memberIDs = _.map clan.get('members') ? [], (memberID) -> memberID.toHexString?() or memberID
User.find {_id: {$in: memberIDs}}, 'name', {sort: {name: 1}}, (err, users) => User.find {_id: {$in: memberIDs}}, 'name', {limit: memberLimit}, (err, users) =>
return @sendDatabaseError(res, err) if err return @sendDatabaseError(res, err) if err
memberIDs = [] memberIDs = []
for user in users for user in users
@ -143,7 +143,7 @@ ClanHandler = class ClanHandler extends Handler
getPublicClans: (req, res) -> getPublicClans: (req, res) ->
# Return 100 public clans, sorted by member count, created date # Return 100 public clans, sorted by member count, created date
query = [{ $match : {type : 'public'} }] query = [{ $match : {type : 'public'} }]
query.push {$project : {_id: 1, name: 1, slug: 1, type: 1, description: 1, members: 1, memberCount: {$size: "$members"}, ownerID: 1}} query.push {$project : {_id: 1, name: 1, slug: 1, type: 1, description: 1, memberCount: {$size: "$members"}, ownerID: 1}}
query.push {$sort: { memberCount: -1, _id: -1 }} query.push {$sort: { memberCount: -1, _id: -1 }}
query.push {$limit: 100} query.push {$limit: 100}
Clan.aggregate(query).exec (err, documents) => Clan.aggregate(query).exec (err, documents) =>

View file

@ -166,6 +166,9 @@ module.exports = class Handler
res.end() res.end()
if term if term
filter.filter.$text = $search: term filter.filter.$text = $search: term
else if filters.length is 1 and filters[0].filter?.index is true
# All we are doing is an empty text search, but that doesn't hit the index, so we'll just look for the slug.
filter.filter = slug: {$exists: true}
args = [filter.filter] args = [filter.filter]
args.push projection if projection args.push projection if projection
q = @modelClass.find(args...) q = @modelClass.find(args...)

View file

@ -21,6 +21,7 @@ LevelSchema.index(
'language_override': 'searchLanguage' 'language_override': 'searchLanguage'
'textIndexVersion': 2 'textIndexVersion': 2
}) })
LevelSchema.index( LevelSchema.index(
{ {
original: 1 original: 1
@ -32,6 +33,7 @@ LevelSchema.index(
unique: true unique: true
}) })
LevelSchema.index({slug: 1}, {name: 'slug index', sparse: true, unique: true}) LevelSchema.index({slug: 1}, {name: 'slug index', sparse: true, unique: true})
LevelSchema.index({index: 1}, {name: 'index index', sparse: true}) # because we can't use the text search index with no term
LevelSchema.plugin(plugins.NamedPlugin) LevelSchema.plugin(plugins.NamedPlugin)
LevelSchema.plugin(plugins.PermissionsPlugin) LevelSchema.plugin(plugins.PermissionsPlugin)

View file

@ -44,6 +44,7 @@ LevelSessionSchema.post 'init', (doc) ->
LevelSessionSchema.pre 'save', (next) -> LevelSessionSchema.pre 'save', (next) ->
User = require '../../users/User' # Avoid mutual inclusion cycles User = require '../../users/User' # Avoid mutual inclusion cycles
Level = require '../Level'
@set('changed', new Date()) @set('changed', new Date())
id = @get('id') id = @get('id')
@ -54,12 +55,20 @@ LevelSessionSchema.pre 'save', (next) ->
# Newly completed level # Newly completed level
if not (initd and @previousStateInfo['state.complete']) and @get('state.complete') if not (initd and @previousStateInfo['state.complete']) and @get('state.complete')
User.findByIdAndUpdate userID, {$inc: 'stats.gamesCompleted': 1}, {}, (err, doc) -> Level.findOne({slug: levelID}).select('concepts -_id').lean().exec (err, level) ->
log.error err if err? log.error err if err?
oldCopy = doc.toObject() update = $inc: {'stats.gamesCompleted': 1}
oldCopy.stats = _.clone oldCopy.stats for concept in level?.concepts ? []
oldCopy.stats.gamesCompleted = oldCopy.stats.gamesCompleted - 1 update.$inc["stats.concepts.#{concept}"] = 1
User.schema.statics.createNewEarnedAchievements doc, oldCopy User.findByIdAndUpdate userID, update, {}, (err, user) ->
log.error err if err?
oldCopy = user.toObject()
oldCopy.stats = _.clone oldCopy.stats
--oldCopy.stats.gamesCompleted
oldCopy.stats.concepts ?= {}
for concept in level?.concepts ? []
--oldCopy.stats.concepts[concept]
User.schema.statics.createNewEarnedAchievements user, oldCopy
activeUserEvent = "level-completed/#{levelID}" activeUserEvent = "level-completed/#{levelID}"
# Spent at least 30s playing this level # Spent at least 30s playing this level

View file

@ -192,7 +192,14 @@ UserSchema.statics.incrementStat = (id, statName, done, inc=1) ->
user.incrementStat statName, done, inc user.incrementStat statName, done, inc
UserSchema.methods.incrementStat = (statName, done, inc=1) -> UserSchema.methods.incrementStat = (statName, done, inc=1) ->
@set statName, (@get(statName) or 0) + inc if /^concepts\./.test statName
# Concept stats are nested a level deeper.
concepts = @get('concepts') or {}
concept = statName.split('.')[1]
concepts[concept] = (concepts[concept] or 0) + inc
@set 'concepts', concepts
else
@set statName, (@get(statName) or 0) + inc
@save (err) -> done?(err) @save (err) -> done?(err)
UserSchema.statics.unconflictName = unconflictName = (name, done) -> UserSchema.statics.unconflictName = unconflictName = (name, done) ->

View file

@ -80,14 +80,13 @@ setupPassportMiddleware = (app) ->
setupCountryRedirectMiddleware = (app, country="china", countryCode="CN", languageCode="zh", serverID="tokyo") -> setupCountryRedirectMiddleware = (app, country="china", countryCode="CN", languageCode="zh", serverID="tokyo") ->
shouldRedirectToCountryServer = (req) -> shouldRedirectToCountryServer = (req) ->
firstLanguage = req.acceptedLanguages[0] speaksLanguage = _.any req.acceptedLanguages, (language) -> language.indexOf languageCode isnt -1
speaksLanguage = firstLanguage and firstLanguage.indexOf(languageCode) isnt -1
unless config[serverID] unless config[serverID]
ip = req.headers['x-forwarded-for'] or req.connection.remoteAddress ip = req.headers['x-forwarded-for'] or req.connection.remoteAddress
ip = ip?.split(/,? /)[0] # If there are two IP addresses, say because of CloudFlare, we just take the first. ip = ip?.split(/,? /)[0] # If there are two IP addresses, say because of CloudFlare, we just take the first.
geo = geoip.lookup(ip) geo = geoip.lookup(ip)
#if speaksLanguage or geo?.country is countryCode #if speaksLanguage or geo?.country is countryCode
# log.info("Should we redirect to #{serverID} server? speaksLanguage: #{speaksLanguage}, firstLanguage: #{firstLanguage}, ip: #{ip}, geo: #{geo} -- so redirecting? #{geo?.country is 'CN' and speaksLanguage}") # log.info("Should we redirect to #{serverID} server? speaksLanguage: #{speaksLanguage}, acceptedLanguages: #{req.acceptedLanguages}, ip: #{ip}, geo: #{geo} -- so redirecting? #{geo?.country is 'CN' and speaksLanguage}")
return geo?.country is countryCode and speaksLanguage return geo?.country is countryCode and speaksLanguage
else else
#log.info("We are on #{serverID} server. speaksLanguage: #{speaksLanguage}, acceptedLanguages: #{req.acceptedLanguages[0]}") #log.info("We are on #{serverID} server. speaksLanguage: #{speaksLanguage}, acceptedLanguages: #{req.acceptedLanguages[0]}")

View file

@ -1,4 +0,0 @@
require('coffee-script')
require('coffee-script/register')
server = require('./server')
server.startServer()