mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-23 15:48:11 -05:00
Merge branch 'master' into course-correction
Some package scripts got in the way of each other
This commit is contained in:
commit
0c5b39e029
93 changed files with 1032 additions and 3247 deletions
24
README.md
24
README.md
|
@ -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)
|
||||
![Matt Lott](http://codecombat.com/images/pages/about/matt_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)
|
||||
![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 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)
|
||||
![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)
|
||||
|
@ -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)
|
||||
![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)
|
||||
![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)
|
||||
![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)
|
||||
![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)
|
||||
![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)
|
||||
![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)
|
||||
![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)
|
||||
![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)
|
||||
![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)
|
||||
![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)
|
||||
![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)
|
||||
![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)
|
||||
|
@ -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)
|
||||
![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)
|
||||
![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)
|
||||
|
||||
|
|
BIN
app/assets/images/pages/about/carlos_small.png
Normal file
BIN
app/assets/images/pages/about/carlos_small.png
Normal file
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
|
@ -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
|
@ -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
|
@ -1 +0,0 @@
|
|||
(function(){ace.require(["ace/ext/error_marker"],function(){})})()
|
|
@ -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
|
@ -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(){})}()
|
|
@ -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
|
@ -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
|
@ -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(){})}()
|
|
@ -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(){})}()
|
|
@ -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(){})}()
|
|
@ -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
|
@ -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(){})}()
|
|
@ -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
|
@ -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})
|
|
@ -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
|
@ -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"})
|
|
@ -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"})
|
|
@ -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"})
|
|
@ -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"})
|
|
@ -1 +0,0 @@
|
|||
ace.define("ace/snippets/luapage",["require","exports","module"],function(e,t,n){t.snippetText="",t.scope="luapage"})
|
|
@ -1 +0,0 @@
|
|||
ace.define("ace/snippets/plain_text",["require","exports","module"],function(e,t,n){t.snippetText="",t.scope="plain_text"})
|
|
@ -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
|
@ -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"})
|
|
@ -1 +0,0 @@
|
|||
ace.define("ace/snippets/text",["require","exports","module"],function(e,t,n){t.snippetText="",t.scope="text"})
|
|
@ -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
|
@ -33,7 +33,7 @@ module.exports = class CocoRouter extends Backbone.Router
|
|||
'admin/clas': go('admin/CLAsView')
|
||||
'admin/employers': go('admin/EmployersListView')
|
||||
'admin/files': go('admin/FilesView')
|
||||
'admin/analytics/users': go('admin/AnalyticsUsersView')
|
||||
'admin/analytics': go('admin/AnalyticsView')
|
||||
'admin/analytics/subscriptions': go('admin/AnalyticsSubscriptionsView')
|
||||
'admin/level-sessions': go('admin/LevelSessionsView')
|
||||
'admin/users': go('admin/UsersView')
|
||||
|
|
|
@ -31,7 +31,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
|
|||
contact: "Kontakt"
|
||||
twitter_follow: "Følg"
|
||||
teachers: "Lærere"
|
||||
# careers: "Careers"
|
||||
careers: "Karrierer"
|
||||
|
||||
modal:
|
||||
close: "Luk"
|
||||
|
@ -80,7 +80,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
|
|||
adjust_volume: "Indstil lydstyrke"
|
||||
campaign_multiplayer: "Multiplayer Arenaer"
|
||||
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."
|
||||
|
||||
share_progress_modal:
|
||||
|
@ -159,7 +159,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
|
|||
accepted: "Accepteret"
|
||||
rejected: "Afvist"
|
||||
withdrawn: "Trukket tilbage"
|
||||
# accept: "Accept"
|
||||
accept: "Accepter"
|
||||
# reject: "Reject"
|
||||
# withdraw: "Withdraw"
|
||||
submitter: "Indsender"
|
||||
|
@ -196,7 +196,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
|
|||
player: "Spiller"
|
||||
player_level: "Niveau" # Like player level 5, not like level: Dungeons of Kithgard
|
||||
warrior: "Krigsherre"
|
||||
# ranger: "Ranger"
|
||||
ranger: "Bueskytte"
|
||||
wizard: "Troldmand"
|
||||
|
||||
units:
|
||||
|
@ -217,8 +217,8 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
|
|||
|
||||
play_level:
|
||||
done: "Færdig"
|
||||
# next_game: "Next game"
|
||||
# show_menu: "Show game menu"
|
||||
next_game: "Næste spil"
|
||||
show_menu: "Vis spil menu"
|
||||
home: "Hjem" # Not used any more, will be removed soon.
|
||||
level: "Bane" # Like "Level: Dungeons of Kithgard"
|
||||
skip: "Spring over"
|
||||
|
@ -251,7 +251,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
|
|||
victory_saving_progress: "Gemmer fremskridt"
|
||||
victory_go_home: "Gå hjem"
|
||||
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_yes: "Ja, jeg er færdig med min Kodetime!"
|
||||
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_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_cta: "Meet your mentor – learn about Bloc"
|
||||
victory_bloc_cta: "Mød din mentor - Hør mere om Bloc"
|
||||
guide_title: "Instruktioner"
|
||||
tome_minion_spells: "Dine Minions' besvæ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_guide_exists: "Klik på guiden i spilmenuen (i toppen af siden) for brugbar info."
|
||||
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_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"
|
||||
|
@ -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_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_no_code: "No code is faster than no code."
|
||||
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
|
||||
# tip_reusable_software: "Before software can be reusable it first has to be usable."
|
||||
tip_no_code: "Ingen kode er hurtigerer end ingen kode."
|
||||
tip_code_never_lies: "Kode lyver aldrig, kommentarer gør nogle gange. - Ron Jeffries"
|
||||
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_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_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_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_open_source_contribute: "You can help CodeCombat improve!"
|
||||
# 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_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_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:
|
||||
inventory_tab: "Dine ting"
|
||||
|
@ -367,14 +367,14 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
|
|||
# view_other_solutions: "View Leaderboards"
|
||||
# scores: "Scores"
|
||||
# top_players: "Top Players by"
|
||||
# day: "Today"
|
||||
# week: "This Week"
|
||||
day: "Idag"
|
||||
week: "Denne uge"
|
||||
# all: "All-Time"
|
||||
# time: "Time"
|
||||
time: "Tid"
|
||||
# damage_taken: "Damage Taken"
|
||||
# damage_dealt: "Damage Dealt"
|
||||
difficulty: "Sværhedsgrad"
|
||||
# gold_collected: "Gold Collected"
|
||||
gold_collected: "Guld samlet"
|
||||
|
||||
# inventory:
|
||||
# choose_inventory: "Equip Items"
|
||||
|
@ -489,43 +489,43 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
|
|||
# subscribe_prepaid: "Click Subscribe to use prepaid code"
|
||||
# using_prepaid: "Using prepaid code for monthly subscription"
|
||||
|
||||
# choose_hero:
|
||||
# choose_hero: "Choose Your Hero"
|
||||
# programming_language: "Programming Language"
|
||||
# programming_language_description: "Which programming language do you want to use?"
|
||||
# default: "Default"
|
||||
# experimental: "Experimental"
|
||||
# python_blurb: "Simple yet powerful, great for beginners and experts."
|
||||
# javascript_blurb: "The language of the web. (Not the same as Java.)"
|
||||
# coffeescript_blurb: "Nicer JavaScript syntax."
|
||||
# clojure_blurb: "A modern Lisp."
|
||||
# lua_blurb: "Game scripting language."
|
||||
# io_blurb: "Simple but obscure."
|
||||
# status: "Status"
|
||||
# hero_type: "Type"
|
||||
# weapons: "Weapons"
|
||||
# weapons_warrior: "Swords - Short Range, No Magic"
|
||||
# weapons_ranger: "Crossbows, Guns - Long Range, No Magic"
|
||||
# weapons_wizard: "Wands, Staffs - Long Range, Magic"
|
||||
choose_hero:
|
||||
choose_hero: "Vælg din helt"
|
||||
programming_language: "Programmerings sprog"
|
||||
programming_language_description: "Hvilket programmerings sprog har du lyst til at bruge?"
|
||||
default: "Standard"
|
||||
experimental: "Experimental"
|
||||
python_blurb: "Simplet, dog stærkt, godt for begyndere og eksperter."
|
||||
javascript_blurb: "Internettets sprog. (Ikke det samme som Java.)"
|
||||
coffeescript_blurb: "Pænere JavaScript syntax."
|
||||
clojure_blurb: "En moderne version af Lisp."
|
||||
lua_blurb: " Spil scripting sprog."
|
||||
# io_blurb: "Simple but obscure."
|
||||
status: "Status"
|
||||
hero_type: "Type"
|
||||
weapons: "Våben"
|
||||
weapons_warrior: "Sværd - Kort afstand, Ingen Magi"
|
||||
weapons_ranger: "Armbryst, Skydevåben - Lang afstand, Ingen Magi"
|
||||
weapons_wizard: "Tryllestave, Stave - Lang afstand, Magi"
|
||||
# attack: "Damage" # Can also translate as "Attack"
|
||||
# health: "Health"
|
||||
# speed: "Speed"
|
||||
# regeneration: "Regeneration"
|
||||
health: "Liv"
|
||||
speed: "Fart"
|
||||
regeneration: "Regeneration"
|
||||
# range: "Range" # As in "attack or visual range"
|
||||
# blocks: "Blocks" # As in "this shield blocks this much damage"
|
||||
# backstab: "Backstab" # As in "this dagger does this much backstab damage"
|
||||
# skills: "Skills"
|
||||
skills: "Færdigheder"
|
||||
# attack_1: "Deals"
|
||||
# attack_2: "of listed"
|
||||
# attack_3: "weapon damage."
|
||||
# health_1: "Gains"
|
||||
# health_2: "of listed"
|
||||
# health_3: "armor health."
|
||||
# speed_1: "Moves at"
|
||||
# speed_2: "meters per second."
|
||||
# available_for_purchase: "Available for Purchase" # 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)
|
||||
# restricted_to_certain_heroes: "Only certain heroes can play this level."
|
||||
speed_1: "Rykker med"
|
||||
speed_2: "meter i sekundet."
|
||||
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 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: "Kun visse helt kan spille dette level."
|
||||
|
||||
# skill_docs:
|
||||
# writable: "writable" # Hover over "attack" in Your Skills while playing a level to see most of this
|
||||
|
|
|
@ -259,8 +259,6 @@
|
|||
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_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"
|
||||
tome_minion_spells: "Your Minions' 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."
|
||||
|
||||
leaderboard:
|
||||
leaderboard: "Leaderboard"
|
||||
view_other_solutions: "View Leaderboards"
|
||||
scores: "Scores"
|
||||
top_players: "Top Players by"
|
||||
|
@ -604,6 +601,10 @@
|
|||
retrostyle_blurb: "RetroStyle Games"
|
||||
rob_title: "Compiler Engineer"
|
||||
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:
|
||||
more_info: "More Info for Teachers"
|
||||
|
@ -895,9 +896,6 @@
|
|||
send_invites: "Send Invites"
|
||||
title: "Title"
|
||||
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..."
|
||||
purchasing_course: "Purchasing course..."
|
||||
buy_course: "Buy Course"
|
||||
|
@ -1212,12 +1210,6 @@
|
|||
last_earned: "Last Earned"
|
||||
amount_achieved: "Amount"
|
||||
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_postfix: " in total"
|
||||
new_xp_prefix: ""
|
||||
|
@ -1227,8 +1219,6 @@
|
|||
left_xp_postfix: ""
|
||||
|
||||
account:
|
||||
recently_played: "Recently Played"
|
||||
no_recent_games: "No games played during the past two weeks."
|
||||
payments: "Payments"
|
||||
prepaid_codes: "Prepaid Codes"
|
||||
purchased: "Purchased"
|
||||
|
|
|
@ -839,16 +839,16 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
playtime: "Tiempo de juego"
|
||||
last_played: "Último jugado"
|
||||
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_concepts2b: "aprendidos por cada miembro"
|
||||
# track_concepts3a: "Track levels completados por cada estudiante"
|
||||
# track_concepts3b: "Track levels completados por cada miembro"
|
||||
track_concepts3a: "Haga un seguimiento de los niveles completados por cada estudiante"
|
||||
track_concepts3b: "Haga un seguimiento de los niveles completados por cada miembro"
|
||||
track_concepts4a: "Ve a tus estudiantes'"
|
||||
track_concepts4b: "Ve a tus miembros'"
|
||||
track_concepts5: "soluciones"
|
||||
# track_concepts6a: "Sort students by name or progress"
|
||||
# track_concepts6b: "Sort members by name or progress"
|
||||
track_concepts6a: "Ordene a sus estudiantes por nombre o progreso"
|
||||
track_concepts6b: "Ordene a sus miembros por nombre o progreso"
|
||||
track_concepts7: "Requiere invitación"
|
||||
track_concepts8: "para unirse"
|
||||
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_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_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:"
|
||||
enter_emails: "Introducir los emails de los estudiantes a invitar, uno por línea"
|
||||
send_invites: "¿Mandar Invitaciones?"
|
||||
|
@ -1269,13 +1269,13 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
purchase_button: "Enviar Adquisición"
|
||||
your_codes: "Tus Códigos:" # {change}
|
||||
redeem_codes: "Reclamar un Código de Subscripción"
|
||||
# prepaid_code: "Prepaid Code"
|
||||
prepaid_code: "Código Prepagado"
|
||||
# lookup_code: "Lookup prepaid code"
|
||||
# apply_account: "Apply to your account"
|
||||
# copy_link: "You can copy the code's link and send it to someone."
|
||||
# quantity: "Quantity"
|
||||
# redeemed: "Redeemed"
|
||||
# no_codes: "No codes yet!"
|
||||
quantity: "Cantidad"
|
||||
redeemed: "Reclamado"
|
||||
no_codes: "¡Aún sin códigos!"
|
||||
|
||||
loading_error:
|
||||
could_not_load: "Error cargando del servidor"
|
||||
|
|
|
@ -71,7 +71,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
|
|||
choose_inventory: "Naudoti daiktus"
|
||||
buy_gems: "Pirkti Deimantus"
|
||||
# subscription_required: "Subscription Required"
|
||||
# anonymous: "Anonymous Player"
|
||||
anonymous: "Anoniminis Žaidėjas"
|
||||
level_difficulty: "Sudėtingumas: "
|
||||
campaign_beginner: "Naujoko kampanija"
|
||||
awaiting_levels_adventurer_prefix: "Kiekvieną savaitę sukuriame naujus lygius."
|
||||
|
@ -225,7 +225,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
|
|||
game_menu: "Žaidimo meniu"
|
||||
guide: "Vedlys"
|
||||
restart: "Paleisti iš naujo"
|
||||
goals: "Tikslai"
|
||||
goals: "Pagalba"
|
||||
goal: "Tikslas"
|
||||
running: "Leidžiama..."
|
||||
success: "Sėkmingai!"
|
||||
|
@ -233,7 +233,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
|
|||
timed_out: "Laikas baigėsi"
|
||||
failing: "Nesėkmingai"
|
||||
# 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_join_game: "Prisijungti prie žaidimo"
|
||||
reload: "Perkrauti"
|
||||
|
@ -241,7 +241,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
|
|||
reload_really: "Ar tikrai norite atsukti visą lygį į pradžią?"
|
||||
reload_confirm: "Perkrauti viską"
|
||||
victory: "Pergalė"
|
||||
# victory_title_prefix: ""
|
||||
victory_title_prefix: ""
|
||||
victory_title_suffix: " baigta"
|
||||
victory_sign_up: "Užsiregistruokite, kad išsaugotumėte pažangą"
|
||||
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_open_source: "CodeCombat - 100% atviro kodo!"
|
||||
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_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_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_morale_improves: "Loading will continue until morale improves."
|
||||
# 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_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_no_try: "Do. Or do not. There is no try. - Yoda"
|
||||
# tip_patience: "Patience you must have, young Padawan. - Yoda"
|
||||
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
|
||||
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
|
||||
tip_no_try: "Daryk. Arba ne. Jokių 'pabandysiu'. - Yoda"
|
||||
tip_patience: "Kantrybės turėti turi, jaunasis Padavane. - Yoda"
|
||||
tip_documented_bug: "Dokumentuota klaida nėra klaida; tai programos ypatybė."
|
||||
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_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_premature_optimization: "Premature optimization is the root of all evil. - Donald Knuth"
|
||||
# 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_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_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_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_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_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"
|
||||
|
@ -349,7 +349,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
|
|||
inventory_tab: "Inventorius"
|
||||
save_load_tab: "Įrašyti / Atkurti"
|
||||
options_tab: "Pasirinkimai"
|
||||
guide_tab: "Vedlys"
|
||||
guide_tab: "Pagalba"
|
||||
guide_video_tutorial: "Video vadovėlis"
|
||||
guide_tips: "Patarimai"
|
||||
multiplayer_tab: "Žaidimas keliese"
|
||||
|
@ -362,19 +362,19 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
|
|||
multiplayer_caption: "Žaisk su draugais!"
|
||||
auth_caption: "Išsaugok savo pažangą."
|
||||
|
||||
# leaderboard:
|
||||
# leaderboard: "Leaderboard"
|
||||
# view_other_solutions: "View Leaderboards"
|
||||
# scores: "Scores"
|
||||
# top_players: "Top Players by"
|
||||
# day: "Today"
|
||||
# week: "This Week"
|
||||
# all: "All-Time"
|
||||
# time: "Time"
|
||||
# damage_taken: "Damage Taken"
|
||||
# damage_dealt: "Damage Dealt"
|
||||
# difficulty: "Difficulty"
|
||||
# gold_collected: "Gold Collected"
|
||||
leaderboard:
|
||||
leaderboard: "Rezultatai"
|
||||
view_other_solutions: "Peržiūrėti rezultatus"
|
||||
scores: "Taškai"
|
||||
top_players: "Geriausi žaidėjai pagal"
|
||||
day: "Šiandien"
|
||||
week: "Savaitė"
|
||||
all: "Visi laikotarpiai"
|
||||
time: "Laikas"
|
||||
damage_taken: "Gauta žalos"
|
||||
damage_dealt: "Padaryta žalos"
|
||||
difficulty: "Sudėtingumas"
|
||||
gold_collected: "Surinkta Aukso"
|
||||
|
||||
inventory:
|
||||
choose_inventory: "Naudoti daiktus"
|
||||
|
@ -389,18 +389,18 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
|
|||
equip: "Naudoti"
|
||||
unequip: "Nenaudoti"
|
||||
|
||||
# buy_gems:
|
||||
# few_gems: "A few gems"
|
||||
# pile_gems: "Pile of gems"
|
||||
# chest_gems: "Chest of gems"
|
||||
# purchasing: "Purchasing..."
|
||||
# declined: "Your card was declined"
|
||||
# retrying: "Server error, retrying."
|
||||
# prompt_title: "Not Enough Gems"
|
||||
# prompt_body: "Do you want to get more?"
|
||||
# prompt_button: "Enter Shop"
|
||||
# recovered: "Previous gems purchase recovered. Please refresh the page."
|
||||
# price: "x3500 / mo"
|
||||
buy_gems:
|
||||
few_gems: "Sauja deimantų"
|
||||
pile_gems: "Krūvelė deimantų"
|
||||
chest_gems: "Skrynia deimantų"
|
||||
purchasing: "Perkama..."
|
||||
declined: "Jūsų kortelė atmesta"
|
||||
retrying: "Serverio klaida, kartojame."
|
||||
prompt_title: "Deimantų nepakanka"
|
||||
prompt_body: "Ar norite gauti daugiau?"
|
||||
prompt_button: "Į Parduotuvę"
|
||||
recovered: "Atstatyta deimantų pirkimo operacija. Prašome pakraukite puslapį iš naujo."
|
||||
price: "x3500 / mėn"
|
||||
|
||||
# subscribe:
|
||||
# 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."
|
||||
clojure_blurb: "Šiolaikinis Lisp."
|
||||
lua_blurb: "Žaidimų skriptų kalba."
|
||||
# io_blurb: "Simple but obscure."
|
||||
# status: "Status"
|
||||
io_blurb: "Paprasta bet paini."
|
||||
status: "Būsena"
|
||||
hero_type: "Klasė"
|
||||
weapons: "Ginklai"
|
||||
weapons_warrior: "Kardai - artimas atstumas, be Kerų"
|
||||
|
@ -551,23 +551,23 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
|
|||
# granularity_saved_games: "Saved"
|
||||
# granularity_change_history: "History"
|
||||
|
||||
# options:
|
||||
# general_options: "General Options" # Check out the Options tab in the Game Menu while playing a level
|
||||
# volume_label: "Volume"
|
||||
# music_label: "Music"
|
||||
# music_description: "Turn background music on/off."
|
||||
# editor_config_title: "Editor Configuration"
|
||||
# editor_config_keybindings_label: "Key Bindings"
|
||||
# editor_config_keybindings_default: "Default (Ace)"
|
||||
# editor_config_keybindings_description: "Adds additional shortcuts known from the common editors."
|
||||
# editor_config_livecompletion_label: "Live Autocompletion"
|
||||
# editor_config_livecompletion_description: "Displays autocomplete suggestions while typing."
|
||||
# editor_config_invisibles_label: "Show Invisibles"
|
||||
# editor_config_invisibles_description: "Displays invisibles such as spaces or tabs."
|
||||
# editor_config_indentguides_label: "Show Indent Guides"
|
||||
# editor_config_indentguides_description: "Displays vertical lines to see indentation better."
|
||||
# editor_config_behaviors_label: "Smart Behaviors"
|
||||
# editor_config_behaviors_description: "Autocompletes brackets, braces, and quotes."
|
||||
options:
|
||||
general_options: "Bendri nustatymai" # Check out the Options tab in the Game Menu while playing a level
|
||||
volume_label: "Garsumas"
|
||||
music_label: "Muzika"
|
||||
music_description: "Įj./išj. fono muziką."
|
||||
editor_config_title: "Redaktoriaus konfigūravimas"
|
||||
editor_config_keybindings_label: "Mygtukų funkcijos"
|
||||
editor_config_keybindings_default: "Pagal nutylėjimą (Ace)"
|
||||
editor_config_keybindings_description: "Prideda papildomas mygtukų kombinacijas iš žinomų redagavimo programų."
|
||||
editor_config_livecompletion_label: "Automatinis žodžių užpildymas "
|
||||
editor_config_livecompletion_description: "Rodyti automatinio užpildymo siūlymus rašymo metu."
|
||||
editor_config_invisibles_label: "Rodyti nematomus simbolius"
|
||||
editor_config_invisibles_description: "Rodyti nematomus simbolius, tokius kaip tarpai ar Tab."
|
||||
editor_config_indentguides_label: "Rodyti poslinkio rekomendacijas"
|
||||
editor_config_indentguides_description: "Rodomos vertikalios linijos patogesniam poslinkio matymui."
|
||||
editor_config_behaviors_label: "Išmanusis redagavimas"
|
||||
editor_config_behaviors_description: "Automatiškai uždaro skliaustus, figurinius skliaustus ir kabutes."
|
||||
|
||||
# about:
|
||||
# why_codecombat: "Why CodeCombat?"
|
||||
|
@ -770,14 +770,14 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
|
|||
# scrub_playback: "Scrub back and forward through time."
|
||||
# single_scrub_playback: "Scrub back and forward through time by a single frame."
|
||||
# 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_pathfinding: "Toggle pathfinding overlay."
|
||||
beautify: "Tvarkyti Jūsų kodą standartizuojant jo formatą."
|
||||
# maximize_editor: "Maximize/minimize code editor."
|
||||
maximize_editor: "Išdidinti/sumažinti kodo redaktorių."
|
||||
|
||||
# community:
|
||||
# main_title: "CodeCombat Community"
|
||||
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!"
|
||||
# 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!"
|
||||
|
@ -941,24 +941,24 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
|
|||
# hours_content: "Hours of content:"
|
||||
# get_free: "Get FREE course"
|
||||
|
||||
# classes:
|
||||
# archmage_title: "Archmage"
|
||||
# archmage_title_description: "(Coder)"
|
||||
classes:
|
||||
archmage_title: "Arkimagas"
|
||||
archmage_title_description: "(Koderis)"
|
||||
# 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_description: "(Level Builder)"
|
||||
artisan_title: "Menininkas"
|
||||
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."
|
||||
# adventurer_title: "Adventurer"
|
||||
# adventurer_title_description: "(Level Playtester)"
|
||||
adventurer_title: "Nuotykių ieškotojas"
|
||||
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."
|
||||
# scribe_title: "Scribe"
|
||||
# scribe_title_description: "(Article Editor)"
|
||||
scribe_title: "Raštininkas"
|
||||
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."
|
||||
# diplomat_title: "Diplomat"
|
||||
# diplomat_title_description: "(Translator)"
|
||||
diplomat_title: "Diplomatas"
|
||||
diplomat_title_description: "(Vertėjas)"
|
||||
# diplomat_summary: "CodeCombat is localized in 45+ languages by our Diplomats. Help us out and contribute translations."
|
||||
# ambassador_title: "Ambassador"
|
||||
# ambassador_title_description: "(Support)"
|
||||
ambassador_title: "Ambasadorius"
|
||||
ambassador_title_description: "(Palaikymas)"
|
||||
# ambassador_summary: "Tame our forum users and provide direction for those with questions. Our ambassadors represent CodeCombat to the world."
|
||||
|
||||
# editor:
|
||||
|
|
|
@ -6,12 +6,12 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
|
|||
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_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."
|
||||
# campaign: "Campaign"
|
||||
# for_beginners: "For Beginners"
|
||||
# multiplayer: "Multiplayer" # Not currently shown on home page
|
||||
# for_developers: "For Developers" # Not currently shown on home page.
|
||||
# or_ipad: "Or download for iPad"
|
||||
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: "Kempen"
|
||||
for_beginners: "Untuk Pemain Baru"
|
||||
multiplayer: "Ramai-Pemain" # Not currently shown on home page
|
||||
for_developers: "Untuk Pengaturcara" # Not currently shown on home page.
|
||||
or_ipad: "Atau muat turun untuk iPad"
|
||||
|
||||
nav:
|
||||
play: "Mula" # The top nav bar entry where players choose which levels to play
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module.exports = nativeDescription: "Українська", englishDescription: "Ukrainian", translation:
|
||||
home:
|
||||
slogan: "Навчіться програмувати, граючи у гру"
|
||||
slogan: "Навчіться програмувати граючи"
|
||||
no_ie: "На жаль, CodeCombat не працює в IE8 та старіших версіях!" # Warning that only shows up in IE8 and older
|
||||
no_mobile: "CodeCombat не призначений для мобільних пристроїв і може не працювати!" # Warning that shows up on mobile devices
|
||||
play: "Грати" # The big play button that opens up the campaign view.
|
||||
|
@ -31,7 +31,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
contact: "Контакти"
|
||||
twitter_follow: "Фоловити"
|
||||
teachers: "Учителям"
|
||||
# careers: "Careers"
|
||||
careers: "Робота"
|
||||
|
||||
modal:
|
||||
close: "Закрити"
|
||||
|
@ -74,7 +74,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
anonymous: "Гравець-анонім"
|
||||
level_difficulty: "Складність: "
|
||||
campaign_beginner: "Кампанія для початківців"
|
||||
awaiting_levels_adventurer_prefix: "Ми випускаємо 5 рівнів на тиждень." # {change}
|
||||
awaiting_levels_adventurer_prefix: "Ми щотижня додаємо нові рівні."
|
||||
awaiting_levels_adventurer: "Увійди як Шукач пригод"
|
||||
awaiting_levels_adventurer_suffix: "стань одним з перших, хто їх спробує."
|
||||
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."
|
||||
|
||||
share_progress_modal:
|
||||
blurb: "Ви робите великі успіхи! Розкажіть кому-небудь, як багато ви вивчили з CodeCombat." # {change}
|
||||
blurb: "У тебе гарно виходить! Розкажи своїм батькам як багато ти знаєш завдяки CodeCombat."
|
||||
email_invalid: "Невірна електронна адреса."
|
||||
form_blurb: "Введіть їхні електронні адреси, і ми покажемо ім!"
|
||||
form_label: "Електронна адреса"
|
||||
placeholder: "електронна адреса"
|
||||
title: "Досконала робота, Учень"
|
||||
title: "Досконала робота, учню"
|
||||
|
||||
login:
|
||||
sign_up: "створення акаунту"
|
||||
|
@ -161,7 +161,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
withdrawn: "Відкликано"
|
||||
accept: "Прийняти"
|
||||
reject: "Відхилити"
|
||||
# withdraw: "Withdraw"
|
||||
withdraw: "Відкликати"
|
||||
submitter: "Відправник"
|
||||
submitted: "Відправлено"
|
||||
commit_msg: "Доручити повідомлення"
|
||||
|
@ -343,7 +343,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
tip_free_your_mind: "Нео, ти повинен усе подолати. Страх... сумніви і невіра. Звільни від них свій розум. - Морфіус"
|
||||
tip_strong_opponents: "Навіть наймогутніший суперник має свою слабкість. - Ітачі Учіха"
|
||||
tip_paper_and_pen: "Перш ніж почати програмувати, ви завжди можете спробувати з аркушем паперу і ручкою."
|
||||
# tip_solve_then_write: "First, solve the problem. Then, write the code. - John Johnson"
|
||||
tip_solve_then_write: "Спершу вирішуй проблему, а потім - пиши код. - Джон Джонсон"
|
||||
|
||||
game_menu:
|
||||
inventory_tab: "Інвентар"
|
||||
|
@ -404,9 +404,9 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
|
||||
subscribe:
|
||||
comparison_blurb: "Відточіть свої навички завдяки підписці на CodeCombat!"
|
||||
feature1: "Більше 60 основних рівней на просторах 4 світів" # {change}
|
||||
feature2: "7 могутніх <strong>нових героїв</strong> з унікальними здібностями!" # {change}
|
||||
feature3: "Більше 30 бонусних рівнів" # {change}
|
||||
feature1: "Більше 110 основних рівней на просторах 4 світів"
|
||||
feature2: "10 могутніх <strong>нових героїв</strong> з унікальними здібностями!"
|
||||
feature3: "Більше 80-ти бонусних рівнів"
|
||||
feature4: "<strong>3500 бонусних самоцвітів</strong> кожного місяця!"
|
||||
feature5: "Навчальні відеоролики"
|
||||
feature6: "Екслюзивна підтримка по електронній пошті"
|
||||
|
@ -432,8 +432,8 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
parent_email_sent: "Лист відправлено!"
|
||||
parent_email_title: "Яка в твоїх батьків електронна адреса?"
|
||||
parents: "Батькам"
|
||||
parents_title: "Ваша дитина вчитиметься програмувати." # {change}
|
||||
parents_blurb1: "Разом з CodeCombat Ваша дитина писатиме реальний код. Почне з простих команд та поступово буде розвиватись до складніших тем."
|
||||
parents_title: "Дорога мамо/батьку, ваша дитина вчиться програмувати. Чи допоможите ви їй продовжити цю спрову?" # {change}
|
||||
parents_blurb1: "Разом з CodeCombat Ваша дитина писатиме реальний код. Почне з простих команд та поступово буде розвиватись до складніших тем." # {change}
|
||||
parents_blurb1a: "Коп'ютерне програмування є необхідними вмінням, що ваша дитина беззаперечно використовуватиме у дорослому віці. До 2020 року 77% професій потребуватимуть базових навичок у програмному забезпечені, а програмісти надзвичайно потрібні у всьому світі. Чи знали ви, що Комп'ютерні Науки - це найбільш високооплачувана університетьська спеціальність?"
|
||||
parents_blurb2: "За 9.99$ на місяць, вона отримуватиме нові завдання щотижня та персональні листи підтримки від професійних програмістів." # {change}
|
||||
parents_blurb3: "Жодного ризику: 100% гарантія повернення грошей, легке скасування абонементу одним кліком."
|
||||
|
@ -455,7 +455,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
sale_continue: "Готовий продовжити пригоди?"
|
||||
sale_limited_time: "Обмежена пропозиція!"
|
||||
sale_new_heroes: "Нові герої!"
|
||||
# sale_title: "Back to School Sale"
|
||||
sale_title: "Дошкільні знижки"
|
||||
sale_view_button: "Купити 1 рік підписки на"
|
||||
stripe_description: "Щомісячний абонемент"
|
||||
stripe_description_year_sale: "1 рік підписки (35% знижка)"
|
||||
|
@ -473,7 +473,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
managed_subs_desc_2: "Одержувачі повинні мати обліковий запис CodeCombat, пов'язаний з вказаною Вами адресою електронної пошти."
|
||||
group_discounts: "Групові знижки"
|
||||
group_discounts_1: "Ми також пропонуємо знижки для пакетних передплат."
|
||||
group_discounts_1st: "1-ий абонемент (включає Ваш)" # {change}
|
||||
group_discounts_1st: "1-ий абонемент"
|
||||
group_discounts_full: "Повна ціна"
|
||||
group_discounts_2nd: "2-11 абонементи"
|
||||
group_discounts_20: "Знижка 20%"
|
||||
|
@ -485,7 +485,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
users_subscribed: "Підписані користувачі:"
|
||||
no_users_subscribed: "Користувачі не підписані, будь ласка, перевірте Ваші ел. адреси."
|
||||
current_recipients: "Поточні отримувачі"
|
||||
unsubscribing: "Скасування передплати..." # {change}
|
||||
unsubscribing: "Триває скасування підписки..."
|
||||
subscribe_prepaid: "Натисніть Підписатися щоб використовувати передплачені коди"
|
||||
using_prepaid: "Використати передплачений код для щомісячної підписки"
|
||||
|
||||
|
@ -583,15 +583,15 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
press_paragraph_1_link: "набору-для-преси"
|
||||
press_paragraph_1_suffix: ". Всі логотипи та зображення можна використовувати, не зв'язуючись із нами напряму."
|
||||
team: "Команда"
|
||||
george_title: "Виконавчий директор" # {change}
|
||||
george_title: "Співзасновник"
|
||||
george_blurb: "Бізнесмен"
|
||||
scott_title: "Програміст" # {change}
|
||||
scott_title: "Співзасновник"
|
||||
scott_blurb: "Розумник"
|
||||
nick_title: "Програміст" # {change}
|
||||
nick_title: "Співзасновник"
|
||||
nick_blurb: "Ґуру мотивації"
|
||||
michael_title: "Програміст"
|
||||
michael_blurb: "Сисадмін"
|
||||
matt_title: "Програміст" # {change}
|
||||
matt_title: "Співзасновник"
|
||||
matt_blurb: "Велосипедист"
|
||||
cat_title: "Головний ремісник"
|
||||
cat_blurb: "Маг повітря"
|
||||
|
@ -603,7 +603,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
retrostyle_blurb: "Ігри в стилі ретро"
|
||||
|
||||
teachers:
|
||||
# more_info: "More Info for Teachers"
|
||||
more_info: "Додаткова інформація для вчителів"
|
||||
intro_1: "CodeCombat - це онлайн гра, що вчить програмуванню. Студенти пишуть код на реальних мовах програмування."
|
||||
intro_2: "Досвід не потрібен!"
|
||||
free_title: "Скільки це коштує?"
|
||||
|
@ -617,12 +617,12 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
teacher_subs_3: "щоб налаштувати підписку."
|
||||
sub_includes_title: "Що входить у підписку?"
|
||||
sub_includes_1: "На додаток до 110+ основних рівнів, студенти з щомісячною підпискою отримають доступ до цих додаткових функцій:"
|
||||
sub_includes_2: "70 + рівнів практики" # {change}
|
||||
sub_includes_2: "80+ рівнів практики"
|
||||
sub_includes_3: "Відео уроки"
|
||||
sub_includes_4: "Преміум підтримка по електронній пошті"
|
||||
sub_includes_5: "10 нових героїв з унікальними навичками для оволодіння"
|
||||
sub_includes_6: "3500 бонусних дорогоцінних каменів кожен місяць"
|
||||
sub_includes_7: "Приватні Клани"
|
||||
sub_includes_6: "3500 бонусних самоцвітів кожен місяць"
|
||||
sub_includes_7: "Приватні клани"
|
||||
monitor_progress_title: "Як мені стежити за прогресом студентів?"
|
||||
monitor_progress_1: "Прогрес студентів може бути відстежити, створивши"
|
||||
monitor_progress_2: "для вашого класу."
|
||||
|
@ -651,8 +651,8 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
more_info_2: "вчительський форум"
|
||||
more_info_3: "є гарним місцем для спілкування із колегами-педагогами, котрі використовують CodeCombat."
|
||||
sys_requirements_title: "Системні вимоги"
|
||||
sys_requirements_1: "Оскільки CodeCombat — це гра, для нормальної роботи він вимагає у комп'ютерів більше, ніж відео чи текстові посібники. Ми оптимізували його для швидкої роботи в усіх сучасних браузерах і на старіших машинах, щоб кожен міг грати. І ось наші підказки, як отримати від CodeCombat якнайбільше:" # {change}
|
||||
sys_requirements_2: "Використовуйте новіші версії Chrome або Firefox." # {change}
|
||||
sys_requirements_1: "Сучасний веб-переглядач. Остання версія Chrome, Firefox або Safari. Internet Explorer 9 та вище."
|
||||
sys_requirements_2: "CodeCombat наразі не підтримується на iPad."
|
||||
|
||||
teachers_survey:
|
||||
title: "Анкета вчителя"
|
||||
|
@ -727,8 +727,8 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
admin: "Aдмін"
|
||||
new_password: "Новий пароль"
|
||||
new_password_verify: "Підтвердження паролю"
|
||||
type_in_email: "Введіть свій email, щоб підтвердити вилучення" # {change}
|
||||
type_in_password: "Так само введіть ваш пароль."
|
||||
type_in_email: "Введіть свій email, аби підтвердити вилучення екаунту."
|
||||
type_in_password: "Також, введіть свій пароль."
|
||||
email_subscriptions: "Email-підписки"
|
||||
email_subscriptions_none: "Жодних підписок."
|
||||
email_announcements: "Оголошення"
|
||||
|
@ -840,16 +840,16 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
last_played: "Остання гра"
|
||||
leagues_explanation: "Грайте в лізі проти інших членів клану на мультіплєєрній арені."
|
||||
# track_concepts1: "Track concepts"
|
||||
# track_concepts2a: "learned by each student"
|
||||
# track_concepts2b: "learned by each member"
|
||||
track_concepts2a: "вивчено усіма студентами"
|
||||
track_concepts2b: "вивчено усіма учасниками"
|
||||
# track_concepts3a: "Track levels completed for each student"
|
||||
# track_concepts3b: "Track levels completed for each member"
|
||||
# track_concepts4a: "See your students'"
|
||||
# track_concepts4b: "See your members'"
|
||||
# track_concepts5: "solutions"
|
||||
track_concepts5: "рішення"
|
||||
# track_concepts6a: "Sort students by name or progress"
|
||||
# track_concepts6b: "Sort members by name or progress"
|
||||
# track_concepts7: "Requires invitation"
|
||||
track_concepts7: "Потребує запрошення"
|
||||
# track_concepts8: "to join"
|
||||
# private_require_sub: "Private clans require a subscription to create or join."
|
||||
|
||||
|
@ -1183,11 +1183,11 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
rules: "Правила"
|
||||
winners: "Переможці"
|
||||
league: "Ліга"
|
||||
# red_ai: "Red AI" # "Red AI Wins", at end of multiplayer match playback
|
||||
# blue_ai: "Blue AI"
|
||||
# wins: "Wins" # At end of multiplayer match playback
|
||||
# humans: "Red" # Ladder page display team name
|
||||
# ogres: "Blue"
|
||||
red_ai: "Червоний ШІ" # "Red AI Wins", at end of multiplayer match playback
|
||||
blue_ai: "Синій ШІ"
|
||||
wins: "переміг" # At end of multiplayer match playback
|
||||
humans: "Червоний" # Ladder page display team name
|
||||
ogres: "Синій"
|
||||
|
||||
user:
|
||||
stats: "Статистика"
|
||||
|
@ -1258,22 +1258,22 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
retrying: "Помилка сервера, повторна спроба."
|
||||
success: "Успішно оплачено. Дякуємо!"
|
||||
|
||||
# account_prepaid:
|
||||
account_prepaid:
|
||||
# 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_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."
|
||||
# users: "Users"
|
||||
# months: "Months"
|
||||
# purchase_total: "Total"
|
||||
users: "Користувачі"
|
||||
months: "Місяці"
|
||||
purchase_total: "Загалом"
|
||||
# purchase_button: "Submit Purchase"
|
||||
# your_codes: "Your Codes"
|
||||
# redeem_codes: "Redeem a Subscription Code"
|
||||
# prepaid_code: "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."
|
||||
# quantity: "Quantity"
|
||||
quantity: "Кількіть"
|
||||
# redeemed: "Redeemed"
|
||||
# no_codes: "No codes yet!"
|
||||
|
||||
|
@ -1350,12 +1350,12 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
arrays: "Масиви"
|
||||
basic_syntax: "Базовий синтаксис"
|
||||
boolean_logic: "Булева логіка"
|
||||
# break_statements: "Break Statements"
|
||||
break_statements: "Оператори зупинки"
|
||||
classes: "Класи"
|
||||
# continue_statements: "Continue Statements"
|
||||
continue_statements: "Оператори продовження"
|
||||
for_loops: "Цикл For"
|
||||
functions: "Функції"
|
||||
# graphics: "Graphics"
|
||||
graphics: "Графіка"
|
||||
if_statements: "Умовні оператори"
|
||||
input_handling: "Обробка введення"
|
||||
math_operations: "Математичні операції"
|
||||
|
@ -1490,7 +1490,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
|
|||
next_photo: "додайте необов’язкове професійне фото."
|
||||
next_active: "відзначте що Ви у пошуках пропозицій, щобвідображатися у пошуку."
|
||||
example_blog: "Блог"
|
||||
example_personal_site: "Особиста Сторінка"
|
||||
example_personal_site: "Персональний сайт"
|
||||
links_header: "Особисті Посилання"
|
||||
links_blurb: "Посилання на інші сторінки або профілі, які б ви хотіли вказати. Наприклад: аккаунт на GitHub'і, LinkedIn, або ваш блог. "
|
||||
links_name: "Назва посилання"
|
||||
|
|
|
@ -280,6 +280,7 @@ _.extend UserSchema.properties,
|
|||
pollMiscPatches: c.int()
|
||||
campaignTranslationPatches: 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'
|
||||
purchased: c.RewardSchema 'purchased with gems or money'
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
#subscription-view
|
||||
|
||||
.invalid-email-message
|
||||
color: red
|
||||
font-size: 12px
|
||||
|
||||
.recipient-emails.invalid
|
||||
border: 1px solid red
|
||||
|
||||
.logged-out-blurb
|
||||
font-size: 18px
|
||||
|
|
16
app/styles/admin/analytics.sass
Normal file
16
app/styles/admin/analytics.sass
Normal 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
|
|
@ -183,4 +183,24 @@ block content
|
|||
p(data-i18n="about.rob_title")
|
||||
| Compiler Engineer
|
||||
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
|
||||
|
|
|
@ -150,7 +150,9 @@ block content
|
|||
if view.recipientSubs.state === 'subscribing'
|
||||
.alert.alert-info(data-i18n="subscribe.subscribing")
|
||||
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
|
||||
button.recipients-subscribe-button.btn.btn-lg.btn-success(data-i18n="subscribe.subscribe_users")
|
||||
if view.recipientSubs.state === 'declined'
|
||||
|
|
|
@ -48,12 +48,11 @@ block content
|
|||
li
|
||||
a(href="/admin/pending-patches", data-i18n="resources.patches") Patches
|
||||
if me.isAdmin()
|
||||
li Analytics
|
||||
li
|
||||
a(href="/admin/analytics") Analytics
|
||||
ul
|
||||
li
|
||||
a(href="/admin/analytics/subscriptions") Subscriptions
|
||||
li
|
||||
a(href="/admin/analytics/users") Users (needs updating)
|
||||
|
||||
if me.isAdmin()
|
||||
hr
|
||||
|
|
|
@ -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
|
61
app/templates/admin/analytics.jade
Normal file
61
app/templates/admin/analytics.jade
Normal 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
|
|
@ -40,7 +40,7 @@ block content
|
|||
a(href="/clans/#{clan.id}", style='font-weight:bold')= clan.get('name')
|
||||
else
|
||||
a(href="/clans/#{clan.id}")= clan.get('name')
|
||||
td= clan.get('members').length
|
||||
td= clan.get('memberCount')
|
||||
td
|
||||
if idNameMap && 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')
|
||||
else
|
||||
a(href="/clans/#{clan.id}")= clan.get('name')
|
||||
td= clan.get('members').length
|
||||
td= clan.get('memberCount')
|
||||
td
|
||||
if idNameMap && idNameMap[clan.get('ownerID')]
|
||||
a(href="/user/#{clan.get('ownerID')}")= idNameMap[clan.get('ownerID')]
|
||||
|
|
|
@ -120,10 +120,3 @@ block modal-footer-content
|
|||
img.pull-right(src="/file/db/level/55144b509f0c4854051769c1/viking_2.png")
|
||||
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
|
||||
.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")
|
||||
|
|
|
@ -3,7 +3,7 @@ extends /templates/base
|
|||
block content
|
||||
|
||||
h2 Hour of Code(Combat)
|
||||
p
|
||||
p
|
||||
strong Hi Teachers!
|
||||
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.
|
||||
|
@ -12,12 +12,12 @@ block content
|
|||
ol
|
||||
li
|
||||
span.spr Navigate to the
|
||||
a.spr(href='/courses/teachers?hoc=true') Courses
|
||||
span page
|
||||
a(href='/courses/teachers?hoc=true') Courses
|
||||
span.spl page
|
||||
li Click the green 'Get FREE course' button under Introduction to Computer Science
|
||||
li Follow the enrollment instructions
|
||||
li Add students via the 'Add Students' tab
|
||||
p
|
||||
p
|
||||
span.spr If you have any problems, please email
|
||||
a(href='mailto:team@codecombat.com') team@codecombat.com
|
||||
br
|
||||
|
@ -66,15 +66,15 @@ block content
|
|||
p(data-i18n="teachers.monitor_progress_5")
|
||||
h4(data-i18n="teachers.sub_includes_7")
|
||||
ul
|
||||
li
|
||||
li
|
||||
strong(data-i18n="clans.track_concepts1")
|
||||
span.spl(data-i18n="clans.track_concepts2a")
|
||||
li(data-i18n="clans.track_concepts3a")
|
||||
li
|
||||
li
|
||||
span(data-i18n="clans.track_concepts4a")
|
||||
strong.spl(data-i18n="clans.track_concepts5")
|
||||
li(data-i18n="clans.track_concepts6a")
|
||||
li
|
||||
li
|
||||
strong(data-i18n="clans.track_concepts7")
|
||||
span.spl(data-i18n="clans.track_concepts8")
|
||||
p
|
||||
|
@ -144,7 +144,7 @@ block content
|
|||
span.spr.spl
|
||||
a(href='/account/subscription', data-i18n="teachers.how_much_2")
|
||||
span.spr.spl(data-i18n="teachers.how_much_3")
|
||||
p
|
||||
p
|
||||
span.spr(data-i18n="teachers.how_much_5")
|
||||
a(href='mailto:team@codecombat.com') team@codecombat.com
|
||||
span.spl(data-i18n="teachers.how_much_6")
|
||||
|
@ -153,7 +153,7 @@ block content
|
|||
a(href='/account/subscription', data-i18n="subscribe.group_discounts")
|
||||
p(data-i18n="subscribe.group_discounts_1")
|
||||
table.table.table-condensed.discount-table
|
||||
tr
|
||||
tr
|
||||
td(data-i18n="subscribe.group_discounts_1st")
|
||||
td(data-i18n="subscribe.group_discounts_full")
|
||||
tr
|
||||
|
|
|
@ -49,9 +49,15 @@ module.exports = class SubscriptionView extends RootView
|
|||
prepaidCode = utils.getQueryVariable '_ppc'
|
||||
@personalSub = new PersonalSub(@supermodel, prepaidCode)
|
||||
@recipientSubs = new RecipientSubs(@supermodel)
|
||||
@emailValidator = new EmailValidator(@superModel)
|
||||
@personalSub.update => @render?()
|
||||
@recipientSubs.update => @render?()
|
||||
|
||||
getRenderData: ->
|
||||
c = super()
|
||||
c.emailValidator = @emailValidator
|
||||
c
|
||||
|
||||
# Personal Subscriptions
|
||||
|
||||
onClickStartSubscription: (e) ->
|
||||
|
@ -82,7 +88,8 @@ module.exports = class SubscriptionView extends RootView
|
|||
|
||||
onClickRecipientsSubscribe: (e) ->
|
||||
emails = @$el.find('.recipient-emails').val().split('\n')
|
||||
@recipientSubs.startSubscribe(emails)
|
||||
valid = @emailValidator.validateEmails(emails, =>@render?())
|
||||
@recipientSubs.startSubscribe(emails) if valid
|
||||
|
||||
onClickRecipientUnsubscribe: (e) ->
|
||||
$(e.target).addClass('hide')
|
||||
|
@ -97,6 +104,31 @@ module.exports = class SubscriptionView extends RootView
|
|||
|
||||
# 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
|
||||
constructor: (@supermodel, @prepaidCode) ->
|
||||
|
||||
|
|
|
@ -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)
|
96
app/views/admin/AnalyticsView.coffee
Normal file
96
app/views/admin/AnalyticsView.coffee
Normal 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
|
|
@ -64,7 +64,6 @@ module.exports = class ClanDetailsView extends RootView
|
|||
@supermodel.loadModel @clan, 'clan', cache: false
|
||||
@supermodel.loadCollection(@members, 'members', {cache: false})
|
||||
@supermodel.loadCollection(@memberAchievements, 'member_achievements', {cache: false})
|
||||
@supermodel.loadCollection(@memberSessions, 'member_sessions', {cache: false})
|
||||
|
||||
getRenderData: ->
|
||||
context = super()
|
||||
|
@ -115,7 +114,7 @@ module.exports = class ClanDetailsView extends RootView
|
|||
lastLevelIndex++
|
||||
levelCount++
|
||||
|
||||
@sortMembers(highestUserLevelCountMap, userConceptsMap) if @clan.get('dashboardType') is 'premium'
|
||||
@sortMembers(highestUserLevelCountMap, userConceptsMap)# if @clan.get('dashboardType') is 'premium'
|
||||
context.members = @members?.models ? []
|
||||
context.lastUserCampaignLevelMap = lastUserCampaignLevelMap
|
||||
context.showExpandedProgress = maxLastUserCampaignLevel <= 30 or @showExpandedProgress
|
||||
|
@ -207,6 +206,8 @@ module.exports = class ClanDetailsView extends RootView
|
|||
@owner = new User _id: @clan.get('ownerID')
|
||||
@listenTo @owner, 'sync', => @render?()
|
||||
@supermodel.loadModel @owner, 'owner', cache: false
|
||||
if @clan.get("dashboardType") is "premium"
|
||||
@supermodel.loadCollection(@memberSessions, 'member_sessions', {cache: false})
|
||||
@render?()
|
||||
|
||||
onMembersSync: ->
|
||||
|
|
|
@ -43,8 +43,8 @@ module.exports = class ClansView extends RootView
|
|||
@idNameMap = {}
|
||||
|
||||
sortClanList = (a, b) ->
|
||||
if a.get('members').length isnt b.get('members').length
|
||||
if a.get('members').length < b.get('members').length then 1 else -1
|
||||
if a.get('memberCount') isnt b.get('memberCount')
|
||||
if a.get('memberCount') < b.get('memberCount') then 1 else -1
|
||||
else
|
||||
b.id.localeCompare(a.id)
|
||||
@publicClans = new CocoCollection([], { url: '/db/clan/-/public', model: Clan, comparator: sortClanList })
|
||||
|
|
|
@ -37,7 +37,7 @@ module.exports = class ThangAvatarView extends CocoView
|
|||
context = super context
|
||||
context.thang = @thang
|
||||
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.includeName = @includeName
|
||||
context
|
||||
|
|
|
@ -448,8 +448,6 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
navigationEvent = route: nextLevelLink, viewClass: viewClass, viewArgs: viewArgs
|
||||
if @level.get('slug') is 'lost-viking' and not (me.get('age') in ['0-13', '14-17'])
|
||||
@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
|
||||
Backbone.Mediator.publish 'router:navigate', navigationEvent
|
||||
|
||||
|
@ -476,7 +474,6 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
onClickContinueFromOffer: (e) ->
|
||||
url = {
|
||||
'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')]
|
||||
Backbone.Mediator.publish 'router:navigate', @navigationEventUponCompletion
|
||||
window.open url, '_blank' if url
|
||||
|
|
|
@ -106,6 +106,7 @@ module.exports = class SpellView extends CocoView
|
|||
@ace.setAnimatedScroll true
|
||||
@ace.setShowFoldWidgets false
|
||||
@ace.setKeyboardHandler @keyBindings[aceConfig.keyBindings ? 'default']
|
||||
@ace.$blockScrolling = Infinity
|
||||
@toggleControls null, @writable
|
||||
@aceSession.selection.on 'changeCursor', @onCursorActivity
|
||||
$(@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) =>
|
||||
# When pressing enter with an active selection, just make a new line under it.
|
||||
if e.command.name is 'enter-skip-delimiters'
|
||||
e.editor.execCommand 'gotolineend'
|
||||
return true
|
||||
selection = @ace.selection.getRange()
|
||||
unless selection.start.column is selection.end.column and selection.start.row is selection.end.row
|
||||
e.editor.execCommand 'gotolineend'
|
||||
return true
|
||||
|
||||
fillACE: ->
|
||||
@ace.setValue @spell.source
|
||||
|
@ -459,7 +462,7 @@ module.exports = class SpellView extends CocoView
|
|||
entry.captureReturn = switch e.language
|
||||
when 'io' then varName + ' := '
|
||||
when 'javascript' then 'var ' + varName + ' = '
|
||||
when 'clojure' then '(let [' + varName + ' '
|
||||
when 'clojure' then '(let [' + varName + ' '
|
||||
else varName + ' = '
|
||||
|
||||
# TODO: Generalize this snippet replacement
|
||||
|
|
|
@ -41,7 +41,7 @@ module.exports = class LevelGuideView extends CocoView
|
|||
@docs = specific.concat(general)
|
||||
@docs = $.extend(true, [], @docs)
|
||||
@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.slug = _.string.slugify(doc.name) for doc in @docs
|
||||
super()
|
||||
|
@ -72,6 +72,12 @@ module.exports = class LevelGuideView extends CocoView
|
|||
@$el.find('.nav-tabs a').click(@clickTab)
|
||||
@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) ->
|
||||
level = @levelSlug # Save ref to level slug
|
||||
@openModalView new SubscribeModal()
|
||||
|
|
|
@ -32,13 +32,17 @@ exports.config =
|
|||
overrides:
|
||||
production:
|
||||
sourceMaps: 'absoluteUrl'
|
||||
onCompile: (files) ->
|
||||
# For some reason, production brunch produces two entries, the first of which is wrong:
|
||||
# //# sourceMappingURL=public/javascripts/app.js.map
|
||||
# //# sourceMappingURL=/javascripts/app.js.map
|
||||
# So we remove the ones that have public in them.
|
||||
exec = require('child_process').exec
|
||||
exec "perl -pi -e 's/\\/\\/# sourceMappingURL=public.*//g' public/javascripts/*.js"
|
||||
plugins:
|
||||
coffeelint:
|
||||
pattern: /\A\Z/
|
||||
afterBrunch: [
|
||||
"coffee scripts/minify.coffee",
|
||||
]
|
||||
fast:
|
||||
onCompile: (files) -> console.log "I feel the need, the need... for speed."
|
||||
plugins:
|
||||
coffeelint:
|
||||
pattern: /\A\Z/
|
||||
vagrant:
|
||||
watcher:
|
||||
usePolling: true
|
||||
|
@ -181,7 +185,6 @@ exports.config =
|
|||
plugins:
|
||||
coffeelint:
|
||||
pattern: /^app\/.*\.coffee$/
|
||||
# pattern: /^dne/ # use this pattern instead if you want to speed compilation
|
||||
options:
|
||||
line_endings:
|
||||
value: 'unix'
|
||||
|
@ -192,16 +195,14 @@ exports.config =
|
|||
level: 'ignore' # PyCharm can't just autostrip for .coffee, needed for .jade
|
||||
no_unnecessary_fat_arrows:
|
||||
level: 'ignore'
|
||||
uglify:
|
||||
mangle:
|
||||
except: ['require']
|
||||
output:
|
||||
semicolons: false
|
||||
sass:
|
||||
mode: 'native'
|
||||
allowCache: true
|
||||
bless:
|
||||
cacheBuster: false
|
||||
assetsmanager:
|
||||
copyTo:
|
||||
'lib/ace': ['node_modules/ace-builds/src-min-noconflict/*']
|
||||
|
||||
modules:
|
||||
definition: (path, data) ->
|
||||
|
|
|
@ -45,7 +45,17 @@ disable = [
|
|||
GLOBAL.window = GLOBAL
|
||||
GLOBAL.document = location: pathname: 'headless_client'
|
||||
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) ->
|
||||
if what is 'message'
|
||||
@onmessage = -> #This webworker api has only one event listener at a time.
|
||||
|
|
18
package.json
18
package.json
|
@ -33,12 +33,14 @@
|
|||
"test": "./node_modules/.bin/karma start",
|
||||
"predeploy": "echo Starting deployment--hold onto your butts.; echo Skipping brunch build --production",
|
||||
"postdeploy": "echo Deployed. Unclench.",
|
||||
"postinstall": "bower install && brunch build",
|
||||
"postinstall": "bower install && brunch build --env fast",
|
||||
"brunch": "brunch",
|
||||
"bower": "bower",
|
||||
"dev": "brunch watch --server",
|
||||
"nodemon": "nodemon",
|
||||
"jasmine-node": "jasmine-node"
|
||||
"jasmine-node": "jasmine-node",
|
||||
"multicore": "coffee multicore.coffee",
|
||||
"nodemon": "nodemon"
|
||||
},
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
|
@ -49,6 +51,7 @@
|
|||
],
|
||||
"dependencies": {
|
||||
"JQDeferred": "~2.1.0",
|
||||
"ace-builds": "https://github.com/ajaxorg/ace-builds/archive/3fb55e8e374ab02ce47c1ae55ffb60a1835f3055.tar.gz",
|
||||
"aether": "~0.3.0",
|
||||
"async": "0.2.x",
|
||||
"aws-sdk": "~2.0.0",
|
||||
|
@ -78,19 +81,21 @@
|
|||
"stripe": "~2.9.0",
|
||||
"tv4": "~1.0.16",
|
||||
"underscore.string": "2.3.x",
|
||||
"webworker-threads": "~0.5.5",
|
||||
"winston": "0.6.x"
|
||||
},
|
||||
"devDependencies": {
|
||||
"after-brunch": "0.0.5",
|
||||
"assetsmanager-brunch": "^1.8.1",
|
||||
"auto-reload-brunch": "> 1.0 < 1.8",
|
||||
"bless-brunch": "https://github.com/ThomasConner/bless-brunch/tarball/master",
|
||||
"bower": "~1.6.4",
|
||||
"brunch": "^1.8.5",
|
||||
"coffee-script-brunch": "^1.8.3",
|
||||
"coffeelint-brunch": "^1.7.1",
|
||||
"compressible": "~1.0.1",
|
||||
"commonjs-require-definition": "0.2.0",
|
||||
"compressible": "~1.0.1",
|
||||
"css-brunch": "^1.7.0",
|
||||
"fs-extra": "^0.26.2",
|
||||
"jade-brunch": "1.7.5",
|
||||
"jasmine-node": "1.13.x",
|
||||
"jasmine-spec-reporter": "~0.3.0",
|
||||
|
@ -110,7 +115,10 @@
|
|||
"requirejs": "~2.1.10",
|
||||
"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",
|
||||
"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",
|
||||
"private": true,
|
||||
|
|
|
@ -17,8 +17,8 @@ try {
|
|||
var scriptStartTime = new Date();
|
||||
var analyticsStringCache = {};
|
||||
|
||||
// Look at last 30 days, same as Mixpanel
|
||||
var numDays = 30;
|
||||
var numDays = 40;
|
||||
var daysInMonth = 30;
|
||||
|
||||
var startDay = new Date();
|
||||
today = startDay.toISOString().substr(0, 10);
|
||||
|
@ -27,6 +27,7 @@ try {
|
|||
|
||||
var levelCompletionFunnel = ['Started Level', 'Saw Victory'];
|
||||
var levelHelpEvents = ['Problem alert help clicked', 'Spell palette help clicked', 'Start help video'];
|
||||
var activeUserEvents = ['Finished Signup', 'Started Level'];
|
||||
|
||||
log("Today is " + today);
|
||||
log("Start day is " + startDay);
|
||||
|
@ -39,7 +40,7 @@ try {
|
|||
for (day in levelCompletionData[level]) {
|
||||
if (today === day) continue; // Never save data for today because it's incomplete
|
||||
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 (day in levelDropCounts[level]) {
|
||||
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]) {
|
||||
if (today === day) continue; // Never save data for today because it's incomplete
|
||||
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]) {
|
||||
if (today === day) continue; // Never save data for today because it's incomplete
|
||||
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));
|
||||
}
|
||||
catch(err) {
|
||||
|
@ -383,7 +417,306 @@ function getLevelSubscriptionCounts(startDay) {
|
|||
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
|
||||
day = day.replace(/-/g, '');
|
||||
|
||||
|
|
61
scripts/minify.coffee
Normal file
61
scripts/minify.coffee
Normal 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")
|
||||
|
|
@ -14,13 +14,67 @@ class AnalyticsPerDayHandler extends Handler
|
|||
|
||||
getByRelationship: (req, res, args...) ->
|
||||
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 @getLevelCompletionsBySlug(req, res) if args[1] is 'level_completions'
|
||||
return @getLevelDropsBySlugs(req, res) if args[1] is 'level_drops'
|
||||
return @getLevelHelpsBySlugs(req, res) if args[1] is 'level_helps'
|
||||
return @getLevelSubscriptionsBySlugs(req, res) if args[1] is 'level_subscriptions'
|
||||
return @getRecurringRevenue(req, res) if args[1] is 'recurring_revenue'
|
||||
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) ->
|
||||
# Send back an ordered array of level per-day starts and finishes
|
||||
# Parameters:
|
||||
|
@ -412,4 +466,33 @@ class AnalyticsPerDayHandler extends Handler
|
|||
@levelSubscriptionsCache[cacheKey] = 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()
|
||||
|
|
|
@ -10,6 +10,8 @@ LevelSessionHandler = require '../levels/sessions/level_session_handler'
|
|||
User = require '../users/User'
|
||||
UserHandler = require '../users/user_handler'
|
||||
|
||||
memberLimit = 200
|
||||
|
||||
ClanHandler = class ClanHandler extends Handler
|
||||
modelClass: Clan
|
||||
jsonSchema: require '../../app/schemas/models/clan.schema'
|
||||
|
@ -94,17 +96,15 @@ ClanHandler = class ClanHandler extends Handler
|
|||
|
||||
getMemberAchievements: (req, res, clanID) ->
|
||||
# TODO: add tests
|
||||
memberLimit = 200
|
||||
Clan.findById clanID, (err, clan) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendNotFoundError(res) unless clan
|
||||
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
|
||||
memberIDs = []
|
||||
for user in users
|
||||
memberIDs.push user.id
|
||||
break unless memberIDs.length < memberLimit
|
||||
EarnedAchievement.find {user: {$in: memberIDs}}, 'achievementName user', (err, documents) =>
|
||||
return @sendDatabaseError(res, err) if err?
|
||||
cleandocs = (EarnedAchievementHandler.formatEntity(req, doc) for doc in documents)
|
||||
|
@ -115,8 +115,8 @@ ClanHandler = class ClanHandler extends Handler
|
|||
Clan.findById clanID, (err, clan) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendNotFoundError(res) unless clan
|
||||
memberIDs = clan.get('members') ? []
|
||||
User.find {_id: {$in: memberIDs}}, 'name nameLower points heroConfig.thangType', {sort: {nameLower: 1}}, (err, users) =>
|
||||
memberIDs = _.map clan.get('members') ? [], (memberID) -> memberID.toHexString?() or memberID
|
||||
User.find {_id: {$in: memberIDs}}, 'name nameLower points heroConfig.thangType', {}, (err, users) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
cleandocs = (UserHandler.formatEntity(req, doc) for doc in users)
|
||||
@sendSuccess(res, cleandocs)
|
||||
|
@ -124,12 +124,12 @@ ClanHandler = class ClanHandler extends Handler
|
|||
getMemberSessions: (req, res, clanID) ->
|
||||
# TODO: add tests
|
||||
# TODO: restrict information returned based on clan type
|
||||
memberLimit = 200
|
||||
Clan.findById clanID, (err, clan) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendNotFoundError(res) unless clan
|
||||
return @sendForbiddenError(res) unless clan.get('dashboardType') is 'premium'
|
||||
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
|
||||
memberIDs = []
|
||||
for user in users
|
||||
|
@ -143,7 +143,7 @@ ClanHandler = class ClanHandler extends Handler
|
|||
getPublicClans: (req, res) ->
|
||||
# Return 100 public clans, sorted by member count, created date
|
||||
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 {$limit: 100}
|
||||
Clan.aggregate(query).exec (err, documents) =>
|
||||
|
|
|
@ -166,6 +166,9 @@ module.exports = class Handler
|
|||
res.end()
|
||||
if 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.push projection if projection
|
||||
q = @modelClass.find(args...)
|
||||
|
|
|
@ -21,6 +21,7 @@ LevelSchema.index(
|
|||
'language_override': 'searchLanguage'
|
||||
'textIndexVersion': 2
|
||||
})
|
||||
|
||||
LevelSchema.index(
|
||||
{
|
||||
original: 1
|
||||
|
@ -32,6 +33,7 @@ LevelSchema.index(
|
|||
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.PermissionsPlugin)
|
||||
|
|
|
@ -44,6 +44,7 @@ LevelSessionSchema.post 'init', (doc) ->
|
|||
|
||||
LevelSessionSchema.pre 'save', (next) ->
|
||||
User = require '../../users/User' # Avoid mutual inclusion cycles
|
||||
Level = require '../Level'
|
||||
@set('changed', new Date())
|
||||
|
||||
id = @get('id')
|
||||
|
@ -54,12 +55,20 @@ LevelSessionSchema.pre 'save', (next) ->
|
|||
|
||||
# Newly completed level
|
||||
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?
|
||||
oldCopy = doc.toObject()
|
||||
oldCopy.stats = _.clone oldCopy.stats
|
||||
oldCopy.stats.gamesCompleted = oldCopy.stats.gamesCompleted - 1
|
||||
User.schema.statics.createNewEarnedAchievements doc, oldCopy
|
||||
update = $inc: {'stats.gamesCompleted': 1}
|
||||
for concept in level?.concepts ? []
|
||||
update.$inc["stats.concepts.#{concept}"] = 1
|
||||
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}"
|
||||
|
||||
# Spent at least 30s playing this level
|
||||
|
|
|
@ -192,7 +192,14 @@ UserSchema.statics.incrementStat = (id, statName, done, inc=1) ->
|
|||
user.incrementStat statName, done, inc
|
||||
|
||||
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)
|
||||
|
||||
UserSchema.statics.unconflictName = unconflictName = (name, done) ->
|
||||
|
|
|
@ -80,14 +80,13 @@ setupPassportMiddleware = (app) ->
|
|||
|
||||
setupCountryRedirectMiddleware = (app, country="china", countryCode="CN", languageCode="zh", serverID="tokyo") ->
|
||||
shouldRedirectToCountryServer = (req) ->
|
||||
firstLanguage = req.acceptedLanguages[0]
|
||||
speaksLanguage = firstLanguage and firstLanguage.indexOf(languageCode) isnt -1
|
||||
speaksLanguage = _.any req.acceptedLanguages, (language) -> language.indexOf languageCode isnt -1
|
||||
unless config[serverID]
|
||||
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.
|
||||
geo = geoip.lookup(ip)
|
||||
#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
|
||||
else
|
||||
#log.info("We are on #{serverID} server. speaksLanguage: #{speaksLanguage}, acceptedLanguages: #{req.acceptedLanguages[0]}")
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
require('coffee-script')
|
||||
require('coffee-script/register')
|
||||
server = require('./server')
|
||||
server.startServer()
|
Loading…
Reference in a new issue