diff --git a/build/bundle.js b/build/bundle.js index 90145f8c..e481c70a 100644 --- a/build/bundle.js +++ b/build/bundle.js @@ -7388,12 +7388,15 @@ GitEngine.prototype.makeOrigin = function(treeString) { // locally, so we have to go up the chain. for now we assume the master on // origin is at least present. var originTree = JSON.parse(unescape(treeString)); - var originMasterTarget = originTree.branches.master.target; - var originMaster = this.makeBranch( - 'o/master', - this.getCommitFromRef(originMasterTarget) - ); - originMaster.set('remote', true); + // make an origin branch for each branch mentioned in the tree + _.each(originTree.branches, function(branchJSON, branchName) { + var originTarget = branchJSON.target; + var originBranch = this.makeBranch( + 'o/' + branchName, + this.getCommitFromRef(originTarget) + ); + originBranch.set('remote', true); + }, this); }; GitEngine.prototype.getOrMakeRecursive = function(tree, createdSoFar, objID) { @@ -8240,7 +8243,7 @@ GitEngine.prototype.pullFinishWithMerge = function( GitEngine.prototype.cloneStarter = function() { this.acceptNoGeneralArgs(); - this.makeOrigin(this.printTree(this.exportTreeForBranch('master'))); + this.makeOrigin(this.printTree()); }; GitEngine.prototype.fakeTeamworkStarter = function() { @@ -8250,15 +8253,25 @@ GitEngine.prototype.fakeTeamworkStarter = function() { }); } - this.validateArgBounds(this.generalArgs, 0, 1); - var numToMake = this.generalArgs[0] || 1; - this.fakeTeamwork(numToMake); + this.validateArgBounds(this.generalArgs, 0, 2); + var branch = this.generalArgs[0] || 'master'; + var numToMake = this.generalArgs[1] || 1; + + // make sure its a branch and exists + var destBranch = this.origin.resolveID(branch); + if (destBranch.get('type') !== 'branch') { + throw new GitError({ + msg: intl.str('git-error-options') + }); + } + + this.fakeTeamwork(numToMake, branch); }; -GitEngine.prototype.fakeTeamwork = function(numToMake) { +GitEngine.prototype.fakeTeamwork = function(numToMake, branch) { var makeOriginCommit = _.bind(function() { var id = this.getUniqueID(); - return this.origin.receiveTeamwork(id, this.animationQueue); + return this.origin.receiveTeamwork(id, branch, this.animationQueue); }, this); var chainStep = _.bind(function() { @@ -8281,7 +8294,8 @@ GitEngine.prototype.fakeTeamwork = function(numToMake) { this.animationQueue.thenFinish(chain, deferred); }; -GitEngine.prototype.receiveTeamwork = function(id, animationQueue) { +GitEngine.prototype.receiveTeamwork = function(id, branch, animationQueue) { + this.checkout(this.resolveID(branch)); var newCommit = this.makeCommit([this.getCommitFromRef('HEAD')], id); this.setTargetLocation(this.HEAD, newCommit); @@ -23780,12 +23794,15 @@ GitEngine.prototype.makeOrigin = function(treeString) { // locally, so we have to go up the chain. for now we assume the master on // origin is at least present. var originTree = JSON.parse(unescape(treeString)); - var originMasterTarget = originTree.branches.master.target; - var originMaster = this.makeBranch( - 'o/master', - this.getCommitFromRef(originMasterTarget) - ); - originMaster.set('remote', true); + // make an origin branch for each branch mentioned in the tree + _.each(originTree.branches, function(branchJSON, branchName) { + var originTarget = branchJSON.target; + var originBranch = this.makeBranch( + 'o/' + branchName, + this.getCommitFromRef(originTarget) + ); + originBranch.set('remote', true); + }, this); }; GitEngine.prototype.getOrMakeRecursive = function(tree, createdSoFar, objID) { @@ -24632,7 +24649,7 @@ GitEngine.prototype.pullFinishWithMerge = function( GitEngine.prototype.cloneStarter = function() { this.acceptNoGeneralArgs(); - this.makeOrigin(this.printTree(this.exportTreeForBranch('master'))); + this.makeOrigin(this.printTree()); }; GitEngine.prototype.fakeTeamworkStarter = function() { @@ -24642,15 +24659,25 @@ GitEngine.prototype.fakeTeamworkStarter = function() { }); } - this.validateArgBounds(this.generalArgs, 0, 1); - var numToMake = this.generalArgs[0] || 1; - this.fakeTeamwork(numToMake); + this.validateArgBounds(this.generalArgs, 0, 2); + var branch = this.generalArgs[0] || 'master'; + var numToMake = this.generalArgs[1] || 1; + + // make sure its a branch and exists + var destBranch = this.origin.resolveID(branch); + if (destBranch.get('type') !== 'branch') { + throw new GitError({ + msg: intl.str('git-error-options') + }); + } + + this.fakeTeamwork(numToMake, branch); }; -GitEngine.prototype.fakeTeamwork = function(numToMake) { +GitEngine.prototype.fakeTeamwork = function(numToMake, branch) { var makeOriginCommit = _.bind(function() { var id = this.getUniqueID(); - return this.origin.receiveTeamwork(id, this.animationQueue); + return this.origin.receiveTeamwork(id, branch, this.animationQueue); }, this); var chainStep = _.bind(function() { @@ -24673,7 +24700,8 @@ GitEngine.prototype.fakeTeamwork = function(numToMake) { this.animationQueue.thenFinish(chain, deferred); }; -GitEngine.prototype.receiveTeamwork = function(id, animationQueue) { +GitEngine.prototype.receiveTeamwork = function(id, branch, animationQueue) { + this.checkout(this.resolveID(branch)); var newCommit = this.makeCommit([this.getCommitFromRef('HEAD')], id); this.setTargetLocation(this.HEAD, newCommit); diff --git a/build/bundle.min.141ecc64.js b/build/bundle.min.141ecc64.js new file mode 100644 index 00000000..fc7c1afc --- /dev/null +++ b/build/bundle.min.141ecc64.js @@ -0,0 +1 @@ +(function(){var e=function(t,n){var r=e.resolve(t,n||"/"),i=e.modules[r];if(!i)throw new Error("Failed to resolve module "+t+", tried "+r);var s=e.cache[r],o=s?s.exports:i();return o};e.paths=[],e.modules={},e.cache={},e.extensions=[".js",".coffee",".json"],e._core={assert:!0,events:!0,fs:!0,path:!0,vm:!0},e.resolve=function(){return function(t,n){function u(t){t=r.normalize(t);if(e.modules[t])return t;for(var n=0;n=0;i--){if(t[i]==="node_modules")continue;var s=t.slice(0,i+1).join("/")+"/node_modules";n.push(s)}return n}n||(n="/");if(e._core[t])return t;var r=e.modules.path();n=r.resolve("/",n);var i=n||"/";if(t.match(/^(?:\.\.?\/|\/)/)){var s=u(r.resolve(i,t))||a(r.resolve(i,t));if(s)return s}var o=f(t,i);if(o)return o;throw new Error("Cannot find module '"+t+"'")}}(),e.alias=function(t,n){var r=e.modules.path(),i=null;try{i=e.resolve(t+"/package.json","/")}catch(s){i=e.resolve(t,"/")}var o=r.dirname(i),u=(Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t})(e.modules);for(var a=0;a=0;r--){var i=e[r];i=="."?e.splice(r,1):i===".."?(e.splice(r,1),n++):n&&(e.splice(r,1),n--)}if(t)for(;n--;n)e.unshift("..");return e}var f=/^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;n.resolve=function(){var e="",t=!1;for(var n=arguments.length;n>=-1&&!t;n--){var r=n>=0?arguments[n]:s.cwd();if(typeof r!="string"||!r)continue;e=r+"/"+e,t=r.charAt(0)==="/"}return e=a(u(e.split("/"),function(e){return!!e}),!t).join("/"),(t?"/":"")+e||"."},n.normalize=function(e){var t=e.charAt(0)==="/",n=e.slice(-1)==="/";return e=a(u(e.split("/"),function(e){return!!e}),!t).join("/"),!e&&!t&&(e="."),e&&n&&(e+="/"),(t?"/":"")+e},n.join=function(){var e=Array.prototype.slice.call(arguments,0);return n.normalize(u(e,function(e,t){return e&&typeof e=="string"}).join("/"))},n.dirname=function(e){var t=f.exec(e)[1]||"",n=!1;return t?t.length===1||n&&t.length<=3&&t.charAt(1)===":"?t:t.substring(0,t.length-1):"."},n.basename=function(e,t){var n=f.exec(e)[2]||"";return t&&n.substr(-1*t.length)===t&&(n=n.substr(0,n.length-t.length)),n},n.extname=function(e){return f.exec(e)[3]||""}}),e.define("__browserify_process",function(e,t,n,r,i,s,o){var s=t.exports={};s.nextTick=function(){var e=typeof window!="undefined"&&window.setImmediate,t=typeof window!="undefined"&&window.postMessage&&window.addEventListener;if(e)return function(e){return window.setImmediate(e)};if(t){var n=[];return window.addEventListener("message",function(e){if(e.source===window&&e.data==="browserify-tick"){e.stopPropagation();if(n.length>0){var t=n.shift();t()}}},!0),function(t){n.push(t),window.postMessage("browserify-tick","*")}}return function(t){setTimeout(t,0)}}(),s.title="browser",s.browser=!0,s.env={},s.argv=[],s.binding=function(t){if(t==="evals")return e("vm");throw new Error("No such module. (Possibly not yet loaded)")},function(){var t="/",n;s.cwd=function(){return t},s.chdir=function(r){n||(n=e("path")),t=n.resolve(r,t)}}()}),e.define("/node_modules/underscore/package.json",function(e,t,n,r,i,s,o){t.exports={main:"underscore.js"}}),e.define("/node_modules/underscore/underscore.js",function(e,t,n,r,i,s,o){(function(){var e=this,r=e._,i={},s=Array.prototype,o=Object.prototype,u=Function.prototype,a=s.push,f=s.slice,l=s.concat,c=o.toString,h=o.hasOwnProperty,p=s.forEach,d=s.map,v=s.reduce,m=s.reduceRight,g=s.filter,y=s.every,b=s.some,w=s.indexOf,E=s.lastIndexOf,S=Array.isArray,x=Object.keys,T=u.bind,N=function(e){if(e instanceof N)return e;if(!(this instanceof N))return new N(e);this._wrapped=e};typeof n!="undefined"?(typeof t!="undefined"&&t.exports&&(n=t.exports=N),n._=N):e._=N,N.VERSION="1.4.4";var C=N.each=N.forEach=function(e,t,n){if(e==null)return;if(p&&e.forEach===p)e.forEach(t,n);else if(e.length===+e.length){for(var r=0,s=e.length;r2;e==null&&(e=[]);if(v&&e.reduce===v)return r&&(t=N.bind(t,r)),i?e.reduce(t,n):e.reduce(t);C(e,function(e,s,o){i?n=t.call(r,n,e,s,o):(n=e,i=!0)});if(!i)throw new TypeError(k);return n},N.reduceRight=N.foldr=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(m&&e.reduceRight===m)return r&&(t=N.bind(t,r)),i?e.reduceRight(t,n):e.reduceRight(t);var s=e.length;if(s!==+s){var o=N.keys(e);s=o.length}C(e,function(u,a,f){a=o?o[--s]:--s,i?n=t.call(r,n,e[a],a,f):(n=e[a],i=!0)});if(!i)throw new TypeError(k);return n},N.find=N.detect=function(e,t,n){var r;return L(e,function(e,i,s){if(t.call(n,e,i,s))return r=e,!0}),r},N.filter=N.select=function(e,t,n){var r=[];return e==null?r:g&&e.filter===g?e.filter(t,n):(C(e,function(e,i,s){t.call(n,e,i,s)&&(r[r.length]=e)}),r)},N.reject=function(e,t,n){return N.filter(e,function(e,r,i){return!t.call(n,e,r,i)},n)},N.every=N.all=function(e,t,n){t||(t=N.identity);var r=!0;return e==null?r:y&&e.every===y?e.every(t,n):(C(e,function(e,s,o){if(!(r=r&&t.call(n,e,s,o)))return i}),!!r)};var L=N.some=N.any=function(e,t,n){t||(t=N.identity);var r=!1;return e==null?r:b&&e.some===b?e.some(t,n):(C(e,function(e,s,o){if(r||(r=t.call(n,e,s,o)))return i}),!!r)};N.contains=N.include=function(e,t){return e==null?!1:w&&e.indexOf===w?e.indexOf(t)!=-1:L(e,function(e){return e===t})},N.invoke=function(e,t){var n=f.call(arguments,2),r=N.isFunction(t);return N.map(e,function(e){return(r?t:e[t]).apply(e,n)})},N.pluck=function(e,t){return N.map(e,function(e){return e[t]})},N.where=function(e,t,n){return N.isEmpty(t)?n?null:[]:N[n?"find":"filter"](e,function(e){for(var n in t)if(t[n]!==e[n])return!1;return!0})},N.findWhere=function(e,t){return N.where(e,t,!0)},N.max=function(e,t,n){if(!t&&N.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.max.apply(Math,e);if(!t&&N.isEmpty(e))return-Infinity;var r={computed:-Infinity,value:-Infinity};return C(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o>=r.computed&&(r={value:e,computed:o})}),r.value},N.min=function(e,t,n){if(!t&&N.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.min.apply(Math,e);if(!t&&N.isEmpty(e))return Infinity;var r={computed:Infinity,value:Infinity};return C(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;or||n===void 0)return 1;if(n>>1;n.call(r,e[u])=0})})},N.difference=function(e){var t=l.apply(s,f.call(arguments,1));return N.filter(e,function(e){return!N.contains(t,e)})},N.zip=function(){var e=f.call(arguments),t=N.max(N.pluck(e,"length")),n=new Array(t);for(var r=0;r=0;n--)t=[e[n].apply(this,t)];return t[0]}},N.after=function(e,t){return e<=0?t():function(){if(--e<1)return t.apply(this,arguments)}},N.keys=x||function(e){if(e!==Object(e))throw new TypeError("Invalid object");var t=[];for(var n in e)N.has(e,n)&&(t[t.length]=n);return t},N.values=function(e){var t=[];for(var n in e)N.has(e,n)&&t.push(e[n]);return t},N.pairs=function(e){var t=[];for(var n in e)N.has(e,n)&&t.push([n,e[n]]);return t},N.invert=function(e){var t={};for(var n in e)N.has(e,n)&&(t[e[n]]=n);return t},N.functions=N.methods=function(e){var t=[];for(var n in e)N.isFunction(e[n])&&t.push(n);return t.sort()},N.extend=function(e){return C(f.call(arguments,1),function(t){if(t)for(var n in t)e[n]=t[n]}),e},N.pick=function(e){var t={},n=l.apply(s,f.call(arguments,1));return C(n,function(n){n in e&&(t[n]=e[n])}),t},N.omit=function(e){var t={},n=l.apply(s,f.call(arguments,1));for(var r in e)N.contains(n,r)||(t[r]=e[r]);return t},N.defaults=function(e){return C(f.call(arguments,1),function(t){if(t)for(var n in t)e[n]==null&&(e[n]=t[n])}),e},N.clone=function(e){return N.isObject(e)?N.isArray(e)?e.slice():N.extend({},e):e},N.tap=function(e,t){return t(e),e};var _=function(e,t,n,r){if(e===t)return e!==0||1/e==1/t;if(e==null||t==null)return e===t;e instanceof N&&(e=e._wrapped),t instanceof N&&(t=t._wrapped);var i=c.call(e);if(i!=c.call(t))return!1;switch(i){case"[object String]":return e==String(t);case"[object Number]":return e!=+e?t!=+t:e==0?1/e==1/t:e==+t;case"[object Date]":case"[object Boolean]":return+e==+t;case"[object RegExp]":return e.source==t.source&&e.global==t.global&&e.multiline==t.multiline&&e.ignoreCase==t.ignoreCase}if(typeof e!="object"||typeof t!="object")return!1;var s=n.length;while(s--)if(n[s]==e)return r[s]==t;n.push(e),r.push(t);var o=0,u=!0;if(i=="[object Array]"){o=e.length,u=o==t.length;if(u)while(o--)if(!(u=_(e[o],t[o],n,r)))break}else{var a=e.constructor,f=t.constructor;if(a!==f&&!(N.isFunction(a)&&a instanceof a&&N.isFunction(f)&&f instanceof f))return!1;for(var l in e)if(N.has(e,l)){o++;if(!(u=N.has(t,l)&&_(e[l],t[l],n,r)))break}if(u){for(l in t)if(N.has(t,l)&&!(o--))break;u=!o}}return n.pop(),r.pop(),u};N.isEqual=function(e,t){return _(e,t,[],[])},N.isEmpty=function(e){if(e==null)return!0;if(N.isArray(e)||N.isString(e))return e.length===0;for(var t in e)if(N.has(e,t))return!1;return!0},N.isElement=function(e){return!!e&&e.nodeType===1},N.isArray=S||function(e){return c.call(e)=="[object Array]"},N.isObject=function(e){return e===Object(e)},C(["Arguments","Function","String","Number","Date","RegExp"],function(e){N["is"+e]=function(t){return c.call(t)=="[object "+e+"]"}}),N.isArguments(arguments)||(N.isArguments=function(e){return!!e&&!!N.has(e,"callee")}),typeof /./!="function"&&(N.isFunction=function(e){return typeof e=="function"}),N.isFinite=function(e){return isFinite(e)&&!isNaN(parseFloat(e))},N.isNaN=function(e){return N.isNumber(e)&&e!=+e},N.isBoolean=function(e){return e===!0||e===!1||c.call(e)=="[object Boolean]"},N.isNull=function(e){return e===null},N.isUndefined=function(e){return e===void 0},N.has=function(e,t){return h.call(e,t)},N.noConflict=function(){return e._=r,this},N.identity=function(e){return e},N.times=function(e,t,n){var r=Array(e);for(var i=0;i":">",'"':""","'":"'","/":"/"}};D.unescape=N.invert(D.escape);var P={escape:new RegExp("["+N.keys(D.escape).join("")+"]","g"),unescape:new RegExp("("+N.keys(D.unescape).join("|")+")","g")};N.each(["escape","unescape"],function(e){N[e]=function(t){return t==null?"":(""+t).replace(P[e],function(t){return D[e][t]})}}),N.result=function(e,t){if(e==null)return null;var n=e[t];return N.isFunction(n)?n.call(e):n},N.mixin=function(e){C(N.functions(e),function(t){var n=N[t]=e[t];N.prototype[t]=function(){var e=[this._wrapped];return a.apply(e,arguments),I.call(this,n.apply(N,e))}})};var H=0;N.uniqueId=function(e){var t=++H+"";return e?e+t:t},N.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var B=/(.)^/,j={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},F=/\\|'|\r|\n|\t|\u2028|\u2029/g;N.template=function(e,t,n){var r;n=N.defaults({},n,N.templateSettings);var i=new RegExp([(n.escape||B).source,(n.interpolate||B).source,(n.evaluate||B).source].join("|")+"|$","g"),s=0,o="__p+='";e.replace(i,function(t,n,r,i,u){return o+=e.slice(s,u).replace(F,function(e){return"\\"+j[e]}),n&&(o+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'"),r&&(o+="'+\n((__t=("+r+"))==null?'':__t)+\n'"),i&&(o+="';\n"+i+"\n__p+='"),s=u+t.length,t}),o+="';\n",n.variable||(o="with(obj||{}){\n"+o+"}\n"),o="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+o+"return __p;\n";try{r=new Function(n.variable||"obj","_",o)}catch(u){throw u.source=o,u}if(t)return r(t,N);var a=function(e){return r.call(this,e,N)};return a.source="function("+(n.variable||"obj")+"){\n"+o+"}",a},N.chain=function(e){return N(e).chain()};var I=function(e){return this._chain?N(e).chain():e};N.mixin(N),C(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=s[e];N.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e=="shift"||e=="splice")&&n.length===0&&delete n[0],I.call(this,n)}}),C(["concat","join","slice"],function(e){var t=s[e];N.prototype[e]=function(){return I.call(this,t.apply(this._wrapped,arguments))}}),N.extend(N.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this)}),e.define("/node_modules/backbone/package.json",function(e,t,n,r,i,s,o){t.exports={main:"backbone.js"}}),e.define("/node_modules/backbone/backbone.js",function(e,t,n,r,i,s,o){(function(){var t=this,r=t.Backbone,i=[],s=i.push,o=i.slice,u=i.splice,a;typeof n!="undefined"?a=n:a=t.Backbone={},a.VERSION="0.9.10";var f=t._;!f&&typeof e!="undefined"&&(f=e("underscore")),a.$=t.jQuery||t.Zepto||t.ender,a.noConflict=function(){return t.Backbone=r,this},a.emulateHTTP=!1,a.emulateJSON=!1;var l=/\s+/,c=function(e,t,n,r){if(!n)return!0;if(typeof n=="object")for(var i in n)e[t].apply(e,[i,n[i]].concat(r));else{if(!l.test(n))return!0;var s=n.split(l);for(var o=0,u=s.length;o').hide().appendTo("body")[0].contentWindow,this.navigate(t)),this._hasPushState?a.$(window).on("popstate",this.checkUrl):this._wantsHashChange&&"onhashchange"in window&&!r?a.$(window).on("hashchange",this.checkUrl):this._wantsHashChange&&(this._checkUrlInterval=setInterval(this.checkUrl,this.interval)),this.fragment=t;var i=this.location,s=i.pathname.replace(/[^\/]$/,"$&/")===this.root;if(this._wantsHashChange&&this._wantsPushState&&!this._hasPushState&&!s)return this.fragment=this.getFragment(null,!0),this.location.replace(this.root+this.location.search+"#"+this.fragment),!0;this._wantsPushState&&this._hasPushState&&s&&i.hash&&(this.fragment=this.getHash().replace(T,""),this.history.replaceState({},document.title,this.root+this.fragment+i.search));if(!this.options.silent)return this.loadUrl()},stop:function(){a.$(window).off("popstate",this.checkUrl).off("hashchange",this.checkUrl),clearInterval(this._checkUrlInterval),x.started=!1},route:function(e,t){this.handlers.unshift({route:e,callback:t})},checkUrl:function(e){var t=this.getFragment();t===this.fragment&&this.iframe&&(t=this.getFragment(this.getHash(this.iframe)));if(t===this.fragment)return!1;this.iframe&&this.navigate(t),this.loadUrl()||this.loadUrl(this.getHash())},loadUrl:function(e){var t=this.fragment=this.getFragment(e),n=f.any(this.handlers,function(e){if(e.route.test(t))return e.callback(t),!0});return n},navigate:function(e,t){if(!x.started)return!1;if(!t||t===!0)t={trigger:t};e=this.getFragment(e||"");if(this.fragment===e)return;this.fragment=e;var n=this.root+e;if(this._hasPushState)this.history[t.replace?"replaceState":"pushState"]({},document.title,n);else{if(!this._wantsHashChange)return this.location.assign(n);this._updateHash(this.location,e,t.replace),this.iframe&&e!==this.getFragment(this.getHash(this.iframe))&&(t.replace||this.iframe.document.open().close(),this._updateHash(this.iframe.location,e,t.replace))}t.trigger&&this.loadUrl(e)},_updateHash:function(e,t,n){if(n){var r=e.href.replace(/(javascript:|#).*$/,"");e.replace(r+"#"+t)}else e.hash="#"+t}}),a.history=new x;var L=a.View=function(e){this.cid=f.uniqueId("view"),this._configure(e||{}),this._ensureElement(),this.initialize.apply(this,arguments),this.delegateEvents()},A=/^(\S+)\s*(.*)$/,O=["model","collection","el","id","attributes","className","tagName","events"];f.extend(L.prototype,p,{tagName:"div",$:function(e){return this.$el.find(e)},initialize:function(){},render:function(){return this},remove:function(){return this.$el.remove(),this.stopListening(),this},setElement:function(e,t){return this.$el&&this.undelegateEvents(),this.$el=e instanceof a.$?e:a.$(e),this.el=this.$el[0],t!==!1&&this.delegateEvents(),this},delegateEvents:function(e){if(!e&&!(e=f.result(this,"events")))return;this.undelegateEvents();for(var t in e){var n=e[t];f.isFunction(n)||(n=this[e[t]]);if(!n)throw new Error('Method "'+e[t]+'" does not exist');var r=t.match(A),i=r[1],s=r[2];n=f.bind(n,this),i+=".delegateEvents"+this.cid,s===""?this.$el.on(i,n):this.$el.on(i,s,n)}},undelegateEvents:function(){this.$el.off(".delegateEvents"+this.cid)},_configure:function(e){this.options&&(e=f.extend({},f.result(this,"options"),e)),f.extend(this,f.pick(e,O)),this.options=e},_ensureElement:function(){if(!this.el){var e=f.extend({},f.result(this,"attributes"));this.id&&(e.id=f.result(this,"id")),this.className&&(e["class"]=f.result(this,"className"));var t=a.$("<"+f.result(this,"tagName")+">").attr(e);this.setElement(t,!1)}else this.setElement(f.result(this,"el"),!1)}});var M={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};a.sync=function(e,t,n){var r=M[e];f.defaults(n||(n={}),{emulateHTTP:a.emulateHTTP,emulateJSON:a.emulateJSON});var i={type:r,dataType:"json"};n.url||(i.url=f.result(t,"url")||D()),n.data==null&&t&&(e==="create"||e==="update"||e==="patch")&&(i.contentType="application/json",i.data=JSON.stringify(n.attrs||t.toJSON(n))),n.emulateJSON&&(i.contentType="application/x-www-form-urlencoded",i.data=i.data?{model:i.data}:{});if(n.emulateHTTP&&(r==="PUT"||r==="DELETE"||r==="PATCH")){i.type="POST",n.emulateJSON&&(i.data._method=r);var s=n.beforeSend;n.beforeSend=function(e){e.setRequestHeader("X-HTTP-Method-Override",r);if(s)return s.apply(this,arguments)}}i.type!=="GET"&&!n.emulateJSON&&(i.processData=!1);var o=n.success;n.success=function(e){o&&o(t,e,n),t.trigger("sync",t,e,n)};var u=n.error;n.error=function(e){u&&u(t,e,n),t.trigger("error",t,e,n)};var l=n.xhr=a.ajax(f.extend(i,n));return t.trigger("request",t,l,n),l},a.ajax=function(){return a.$.ajax.apply(a.$,arguments)};var _=function(e,t){var n=this,r;e&&f.has(e,"constructor")?r=e.constructor:r=function(){return n.apply(this,arguments)},f.extend(r,n,t);var i=function(){this.constructor=r};return i.prototype=n.prototype,r.prototype=new i,e&&f.extend(r.prototype,e),r.__super__=n.prototype,r};d.extend=v.extend=y.extend=L.extend=x.extend=_;var D=function(){throw new Error('A "url" property or function must be specified')}}).call(this)}),e.define("/src/js/util/constants.js",function(e,t,n,r,i,s,o){var u={betweenCommandsDelay:400},a={isAnimating:!1},f={minZoom:.55,maxZoom:1.25,minWidth:600,minHeight:600},l={arrowHeadSize:8,nodeRadius:17,curveControlPointOffset:50,defaultEasing:"easeInOut",defaultAnimationTime:400,rectFill:"hsb(0.8816909813322127,0.7,1)",headRectFill:"#2831FF",rectStroke:"#FFF",rectStrokeWidth:"3",originDash:"- ",multiBranchY:20,upstreamHeadOpacity:.5,upstreamNoneOpacity:.2,edgeUpstreamHeadOpacity:.4,edgeUpstreamNoneOpacity:.15,visBranchStrokeWidth:2,visBranchStrokeColorNone:"#333",defaultNodeFill:"hsba(0.5,0.8,0.7,1)",defaultNodeStrokeWidth:2,defaultNodeStroke:"#FFF",orphanNodeFill:"hsb(0.5,0.8,0.7)"};n.GLOBAL=a,n.TIME=u,n.GRAPHICS=l,n.VIEWPORT=f}),e.define("/src/js/util/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util/constants");n.parseQueryString=function(e){var t={};return e.replace(new RegExp("([^?=&]+)(=([^&]*))?","g"),function(e,n,r,i){t[n]=i}),t},n.isBrowser=function(){var e=String(typeof window)!=="undefined";return e},n.splitTextCommand=function(e,t,n){t=u.bind(t,n),u.each(e.split(";"),function(e,n){e=u.escape(e),e=e.replace(/^(\s+)/,"").replace(/(\s+)$/,"").replace(/"/g,'"').replace(/'/g,"'");if(n>0&&!e.length)return;t(e)})},n.genParseCommand=function(e,t){return function(n){var r,i;return u.each(e,function(e,t){var s=e.exec(n);s&&(r=t,i=s)}),r?{toSet:{eventName:t,method:r,regexResults:i}}:!1}}}),e.define("/src/js/level/sandbox.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../intl"),h=e("../app"),p=e("../util/errors"),d=e("../visuals/visualization").Visualization,v=e("../level/parseWaterfall").ParseWaterfall,m=e("../level/disabledMap").DisabledMap,g=e("../models/commandModel").Command,y=e("../git/gitShim").GitShim,b=e("../views"),w=b.ModalTerminal,E=b.ModalAlert,S=e("../views/builderViews"),x=e("../views/multiView").MultiView,T=f.View.extend({tagName:"div",initialize:function(e){e=e||{},this.options=e,this.initVisualization(e),this.initCommandCollection(e),this.initParseWaterfall(e),this.initGitShim(e),this.initUndoStack(e),e.wait||this.takeControl()},getDefaultVisEl:function(){return $("#mainVisSpace")[0]},getAnimationTime:function(){return 1050},initVisualization:function(e){this.mainVis=new d({el:e.el||this.getDefaultVisEl()})},initUndoStack:function(e){this.undoStack=[]},initCommandCollection:function(e){this.commandCollection=h.getCommandUI().commandCollection},initParseWaterfall:function(e){this.parseWaterfall=new v},initGitShim:function(e){this.gitShim=new y({beforeCB:u.bind(this.beforeCommandCB,this)})},takeControl:function(){h.getEventBaton().stealBaton("commandSubmitted",this.commandSubmitted,this),h.getEventBaton().stealBaton("processSandboxCommand",this.processSandboxCommand,this),h.getEventBaton().stealBaton("levelExited",this.levelExited,this),this.insertGitShim()},releaseControl:function(){h.getEventBaton().releaseBaton("commandSubmitted",this.commandSubmitted,this),h.getEventBaton().releaseBaton("processSandboxCommand",this.processSandboxCommand,this),h.getEventBaton().releaseBaton("levelExited",this.levelExited,this),this.releaseGitShim()},releaseGitShim:function(){this.gitShim&&this.gitShim.removeShim()},insertGitShim:function(){this.gitShim&&this.mainVis.customEvents.on("gitEngineReady",function(){this.gitShim.insertShim()},this)},beforeCommandCB:function(e){this.pushUndo()},pushUndo:function(){this.undoStack.push(this.mainVis.gitEngine.printTree())},undo:function(e,t){var n=this.undoStack.pop();if(!n){e.set("error",new p.GitError({msg:c.str("undo-stack-empty")})),t.resolve();return}this.mainVis.reset(n),setTimeout(function(){e.finishWith(t)},this.mainVis.getAnimationTime())},commandSubmitted:function(e){h.getEvents().trigger("commandSubmittedPassive",e),l.splitTextCommand(e,function(e){this.commandCollection.add(new g({rawStr:e,parseWaterfall:this.parseWaterfall}))},this)},startLevel:function(t,n){var r=t.get("regexResults")||[],i=r[1]||"",s=h.getLevelArbiter().getLevel(i);if(!s){t.addWarning(c.str("level-no-id",{id:i})),h.getEventBaton().trigger("commandSubmitted","levels"),t.set("status","error"),n.resolve();return}this.hide(),this.clear();var o=a.defer(),u=e("../level").Level;this.currentLevel=new u({level:s,deferred:o,command:t}),o.promise.then(function(){t.finishWith(n)})},buildLevel:function(t,n){this.hide(),this.clear();var r=a.defer(),i=e("../level/builder").LevelBuilder;this.levelBuilder=new i({deferred:r}),r.promise.then(function(){t.finishWith(n)})},exitLevel:function(e,t){e.addWarning(c.str("level-cant-exit")),e.set("status","error"),t.resolve()},showLevels:function(e,t){var n=a.defer();h.getLevelDropdown().show(n,e),n.promise.done(function(){e.finishWith(t)})},resetSolved:function(e,t){h.getLevelArbiter().resetSolvedMap(),e.addWarning(c.str("solved-map-reset")),e.finishWith(t)},processSandboxCommand:function(e,t){var n={"reset solved":this.resetSolved,undo:this.undo,"help general":this.helpDialog,help:this.helpDialog,reset:this.reset,delay:this.delay,clear:this.clear,"exit level":this.exitLevel,level:this.startLevel,sandbox:this.exitLevel,levels:this.showLevels,mobileAlert:this.mobileAlert,"build level":this.buildLevel,"export tree":this.exportTree,"import tree":this.importTree,"import level":this.importLevel},r=n[e.get("method")];if(!r)throw new Error("no method for that wut");r.apply(this,[e,t])},hide:function(){this.mainVis.hide()},levelExited:function(){this.show()},show:function(){this.mainVis.show()},importTree:function(e,t){var n=new S.MarkdownPresenter({previewText:c.str("paste-json"),fillerText:" "});n.deferred.promise.then(u.bind(function(e){try{this.mainVis.gitEngine.loadTree(JSON.parse(e))}catch(t){this.mainVis.reset(),new x({childViews:[{type:"ModalAlert",options:{markdowns:["## Error!","","Something is wrong with that JSON! Here is the error:","",String(t)]}}]})}},this)).fail(function(){}).done(function(){e.finishWith(t)})},importLevel:function(t,n){var r=new S.MarkdownPresenter({previewText:c.str("paste-json"),fillerText:" "});r.deferred.promise.then(u.bind(function(r){var i=e("../level").Level;try{var s=JSON.parse(r),o=a.defer();this.currentLevel=new i({level:s,deferred:o,command:t}),this.hide(),o.promise.then(function(){t.finishWith(n)})}catch(u){new x({childViews:[{type:"ModalAlert",options:{markdowns:["## Error!","","Something is wrong with that level JSON, this happened:","",String(u)]}}]}),t.finishWith(n)}},this)).fail(function(){t.finishWith(n)}).done()},exportTree:function(e,t){var n=JSON.stringify(this.mainVis.gitEngine.exportTree(),null,2),r=new x({childViews:[{type:"MarkdownPresenter",options:{previewText:c.str("share-tree"),fillerText:n,noConfirmCancel:!0}}]});r.getPromise().then(function(){e.finishWith(t)}).done()},clear:function(e,t){h.getEvents().trigger("clearOldCommands"),e&&t&&e.finishWith(t)},mobileAlert:function(e,t){alert(c.str("mobile-alert")),e.finishWith(t)},delay:function(e,t){var n=parseInt(e.get("regexResults")[1],10);setTimeout(function(){e.finishWith(t)},n)},reset:function(e,t){this.mainVis.reset(),this.initUndoStack(),setTimeout(function(){e.finishWith(t)},this.mainVis.getAnimationTime())},helpDialog:function(t,n){var r=new x({childViews:c.getDialog(e("../dialogs/sandbox"))});r.getPromise().then(u.bind(function(){t.finishWith(n)},this)).done()}});n.Sandbox=T}),e.define("/node_modules/q/package.json",function(e,t,n,r,i,s,o){t.exports={main:"q.js"}}),e.define("/node_modules/q/q.js",function(e,t,n,r,i,s,o){(function(e){if(typeof bootstrap=="function")bootstrap("promise",e);else if(typeof n=="object")e(void 0,n);else if(typeof define=="function")define(e);else if(typeof ses!="undefined"){if(!ses.ok())return;ses.makeQ=function(){var t={};return e(void 0,t)}}else e(void 0,Q={})})(function(e,t){"use strict";function w(e){return b(e)==="[object StopIteration]"||e instanceof E}function x(e,t){t.stack&&typeof e=="object"&&e!==null&&e.stack&&e.stack.indexOf(S)===-1&&(e.stack=T(e.stack)+"\n"+S+"\n"+T(t.stack))}function T(e){var t=e.split("\n"),n=[];for(var r=0;r=n&&s<=Ct}function k(){if(Error.captureStackTrace){var e,t,n=Error.prepareStackTrace;return Error.prepareStackTrace=function(n,r){e=r[1].getFileName(),t=r[1].getLineNumber()},(new Error).stack,Error.prepareStackTrace=n,r=e,t}}function L(e,t,n){return function(){return typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t+" is deprecated, use "+n+" instead.",(new Error("")).stack),e.apply(e,arguments)}}function A(){function s(r){if(!e)return;n=z(r),d(e,function(e,t){u(function(){n.promiseSend.apply(n,t)})},void 0),e=void 0,t=void 0}var e=[],t=[],n,r=g(A.prototype),i=g(M.prototype);return i.promiseSend=function(r,i,s,o){var a=p(arguments);e?(e.push(a),r==="when"&&o&&t.push(o)):u(function(){n.promiseSend.apply(n,a)})},i.valueOf=function(){return e?i:n.valueOf()},Error.captureStackTrace&&(Error.captureStackTrace(i,A),i.stack=i.stack.substring(i.stack.indexOf("\n")+1)),o(i),r.promise=i,r.resolve=s,r.reject=function(e){s(U(e))},r.notify=function(n){e&&d(t,function(e,t){u(function(){t(n)})},void 0)},r}function O(e){var t=A();return ot(e,t.resolve,t.reject,t.notify).fail(t.reject),t.promise}function M(e,t,n,r){t===void 0&&(t=function(e){return U(new Error("Promise does not support operation: "+e))});var i=g(M.prototype);return i.promiseSend=function(n,r){var s=p(arguments,2),o;try{e[n]?o=e[n].apply(i,s):o=t.apply(i,[n].concat(s))}catch(u){o=U(u)}r&&r(o)},n&&(i.valueOf=n),r&&(i.exception=r),o(i),i}function _(e){return D(e)?e.valueOf():e}function D(e){return e&&typeof e.promiseSend=="function"}function P(e){return e&&typeof e.then=="function"}function H(e){return B(e)||j(e)}function B(e){return!P(_(e))}function j(e){return e=_(e),D(e)&&"exception"in e}function R(){!q&&typeof window!="undefined"&&!window.Touch&&window.console&&console.log("Should be empty:",I),q=!0}function U(e){var t=M({when:function(t){if(t){var n=v(F,this);n!==-1&&(I.splice(n,1),F.splice(n,1))}return t?t(e):U(e)}},function(){return U(e)},function n(){return this},e);return R(),F.push(t),I.push(e),t}function z(e){if(D(e))return e;e=_(e);if(P(e)){var t=A();return e.then(t.resolve,t.reject,t.notify),t.promise}return M({when:function(){return e},get:function(t){return e[t]},put:function(t,n){return e[t]=n,e},del:function(t){return delete e[t],e},post:function(t,n){return e[t].apply(e,n)},apply:function(t,n){return e.apply(t,n)},fapply:function(t){return e.apply(void 0,t)},viewInfo:function(){function r(e){n[e]||(n[e]=typeof t[e])}var t=e,n={};while(t)Object.getOwnPropertyNames(t).forEach(r),t=Object.getPrototypeOf(t);return{type:typeof e,properties:n}},keys:function(){return y(e)}},void 0,function n(){return e})}function W(e){return M({isDef:function(){}},function(){var n=p(arguments);return Z.apply(void 0,[e].concat(n))},function(){return _(e)})}function X(e,t){return e=z(e),t?M({viewInfo:function(){return t}},function(){var n=p(arguments);return Z.apply(void 0,[e].concat(n))},function(){return _(e)}):Z(e,"viewInfo")}function V(e){return X(e).when(function(t){var n;t.type==="function"?n=function(){return rt(e,void 0,arguments)}:n={};var r=t.properties||{};return y(r).forEach(function(t){r[t]==="function"&&(n[t]=function(){return nt(e,t,arguments)})}),z(n)})}function $(e,t,n,r){function o(e){try{return typeof t=="function"?t(e):e}catch(n){return U(n)}}function a(e){if(typeof n=="function"){x(e,l);try{return n(e)}catch(t){return U(t)}}return U(e)}function f(e){return typeof r=="function"?r(e):e}var i=A(),s=!1,l=z(e);return u(function(){l.promiseSend("when",function(e){if(s)return;s=!0,i.resolve(o(e))},function(e){if(s)return;s=!0,i.resolve(a(e))})}),l.promiseSend("when",void 0,void 0,function(e){i.notify(f(e))}),i.promise}function J(e,t,n){return $(e,function(e){return ft(e).then(function(e){return t.apply(void 0,e)},n)},n)}function K(e){return function(){function t(e,t){var s;try{s=n[e](t)}catch(o){return w(o)?o.value:U(o)}return $(s,r,i)}var n=e.apply(this,arguments),r=t.bind(t,"send"),i=t.bind(t,"throw");return r()}}function Q(e){throw new E(e)}function G(e){return function(){return ft([this,ft(arguments)]).spread(function(t,n){return e.apply(t,n)})}}function Y(e){return function(t){var n=p(arguments,1);return Z.apply(void 0,[t,e].concat(n))}}function Z(e,t){var n=A(),r=p(arguments,2);return e=z(e),u(function(){e.promiseSend.apply(e,[t,n.resolve].concat(r))}),n.promise}function et(e,t,n){var r=A();return e=z(e),u(function(){e.promiseSend.apply(e,[t,r.resolve].concat(n))}),r.promise}function tt(e){return function(t){var n=p(arguments,1);return et(t,e,n)}}function st(e,t){var n=p(arguments,2);return rt(e,t,n)}function ot(e){var t=p(arguments,1);return it(e,t)}function ut(e,t){var n=p(arguments,2);return function(){var i=n.concat(p(arguments));return rt(e,t,i)}}function at(e){var t=p(arguments,1);return function(){var r=t.concat(p(arguments));return it(e,r)}}function ft(e){return $(e,function(e){var t=e.length;if(t===0)return z(e);var n=A();return d(e,function(r,i,s){B(i)?(e[s]=_(i),--t===0&&n.resolve(e)):$(i,function(r){e[s]=r,--t===0&&n.resolve(e)}).fail(n.reject)},void 0),n.promise})}function lt(e){return $(e,function(e){return $(ft(m(e,function(e){return $(e,i,i)})),function(){return m(e,z)})})}function ct(e,t){return $(e,void 0,t)}function ht(e,t){return $(e,void 0,void 0,t)}function pt(e,t){return $(e,function(e){return $(t(),function(){return e})},function(e){return $(t(),function(){return U(e)})})}function dt(e,n,r,i){function s(n){u(function(){x(n,e);if(!t.onerror)throw n;t.onerror(n)})}var o=n||r||i?$(e,n,r,i):e;ct(o,s)}function vt(e,t){var n=A(),r=setTimeout(function(){n.reject(new Error("Timed out after "+t+" ms"))},t);return $(e,function(e){clearTimeout(r),n.resolve(e)},function(e){clearTimeout(r),n.reject(e)}),n.promise}function mt(e,t){t===void 0&&(t=e,e=void 0);var n=A();return setTimeout(function(){n.resolve(e)},t),n.promise}function gt(e,t){var n=p(t),r=A();return n.push(r.makeNodeResolver()),it(e,n).fail(r.reject),r.promise}function yt(e){var t=p(arguments,1),n=A();return t.push(n.makeNodeResolver()),it(e,t).fail(n.reject),n.promise}function bt(e){var t=p(arguments,1);return function(){var n=t.concat(p(arguments)),r=A();return n.push(r.makeNodeResolver()),it(e,n).fail(r.reject),r.promise}}function wt(e,t,n){return St(e,t).apply(void 0,n)}function Et(e,t){var n=p(arguments,2);return wt(e,t,n)}function St(e){if(arguments.length>1){var t=arguments[1],n=p(arguments,2),r=e;e=function(){var e=n.concat(p(arguments));return r.apply(t,e)}}return function(){var t=A(),n=p(arguments);return n.push(t.makeNodeResolver()),it(e,n).fail(t.reject),t.promise}}function xt(e,t,n){var r=p(n),i=A();return r.push(i.makeNodeResolver()),nt(e,t,r).fail(i.reject),i.promise}function Tt(e,t){var n=p(arguments,2),r=A();return n.push(r.makeNodeResolver()),nt(e,t,n).fail(r.reject),r.promise}function Nt(e,t){if(!t)return e;e.then(function(e){u(function(){t(null,e)})},function(e){u(function(){t(e)})})}var n=k(),r,i=function(){},o=Object.freeze||i;typeof cajaVM!="undefined"&&(o=cajaVM.def);var u;if(typeof s!="undefined")u=s.nextTick;else if(typeof setImmediate=="function")u=setImmediate;else if(typeof MessageChannel!="undefined"){var a=new MessageChannel,f={},l=f;a.port1.onmessage=function(){f=f.next;var e=f.task;delete f.task,e()},u=function(e){l=l.next={task:e},a.port2.postMessage(0)}}else u=function(e){setTimeout(e,0)};var c;if(Function.prototype.bind){var h=Function.prototype.bind;c=h.bind(h.call)}else c=function(e){return function(){return e.call.apply(e,arguments)}};var p=c(Array.prototype.slice),d=c(Array.prototype.reduce||function(e,t){var n=0,r=this.length;if(arguments.length===1)do{if(n in this){t=this[n++];break}if(++n>=r)throw new TypeError}while(1);for(;n2?e.resolve(p(arguments,1)):e.resolve(n)}},A.prototype.node=L(A.prototype.makeNodeResolver,"node","makeNodeResolver"),t.promise=O,t.makePromise=M,M.prototype.then=function(e,t,n){return $(this,e,t,n)},M.prototype.thenResolve=function(e){return $(this,function(){return e})},d(["isResolved","isFulfilled","isRejected","when","spread","send","get","put","del","post","invoke","keys","apply","call","bind","fapply","fcall","fbind","all","allResolved","view","viewInfo","timeout","delay","catch","finally","fail","fin","progress","end","done","nfcall","nfapply","nfbind","ncall","napply","nbind","npost","ninvoke","nend","nodeify"],function(e,n){M.prototype[n]=function(){return t[n].apply(t,[this].concat(p(arguments)))}},void 0),M.prototype.toSource=function(){return this.toString()},M.prototype.toString=function(){return"[object Promise]"},o(M.prototype),t.nearer=_,t.isPromise=D,t.isPromiseAlike=P,t.isResolved=H,t.isFulfilled=B,t.isRejected=j;var F=[],I=[],q;t.reject=U,t.begin=z,t.resolve=z,t.ref=L(z,"ref","resolve"),t.master=W,t.viewInfo=X,t.view=V,t.when=$,t.spread=J,t.async=K,t["return"]=Q,t.promised=G,t.sender=L(Y,"sender","dispatcher"),t.Method=L(Y,"Method","dispatcher"),t.send=L(Z,"send","dispatch"),t.dispatch=et,t.dispatcher=tt,t.get=tt("get"),t.put=tt("put"),t["delete"]=t.del=tt("del");var nt=t.post=tt("post");t.invoke=function(e,t){var n=p(arguments,2);return nt(e,t,n)};var rt=t.apply=L(tt("apply"),"apply","fapply"),it=t.fapply=tt("fapply");t.call=L(st,"call","fcall"),t["try"]=ot,t.fcall=ot,t.bind=L(ut,"bind","fbind"),t.fbind=at,t.keys=tt("keys"),t.all=ft,t.allResolved=lt,t["catch"]=t.fail=ct,t.progress=ht,t["finally"]=t.fin=pt,t.end=L(dt,"end","done"),t.done=dt,t.timeout=vt,t.delay=mt,t.nfapply=gt,t.nfcall=yt,t.nfbind=bt,t.napply=L(wt,"napply","npost"),t.ncall=L(Et,"ncall","ninvoke"),t.nbind=L(St,"nbind","nfbind"),t.npost=xt,t.ninvoke=Tt,t.nend=L(Nt,"nend","nodeify"),t.nodeify=Nt;var Ct=k()})}),e.define("/src/js/intl/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util/constants"),f=e("../util"),l=e("../intl/strings").strings,c=n.getDefaultLocale=function(){return"en_US"},h=n.getLocale=function(){return a.GLOBAL.locale?a.GLOBAL.locale:c()},p=u.clone(u.templateSettings);p.interpolate=/\{(.+?)\}/g;var d=n.template=function(e,t){return u.template(e,t,p)},v=n.str=function(e,t){t=t||{};var n=h();return l[e]?l[e][n]?d(l[e][n],t):e!=="error-untranslated"?v("error-untranslated"):'No translation for the key "'+e+'"':(console.warn("NO INTL support for key "+e),"NO INTL support for key "+e)},m=n.getIntlKey=function(e,t){if(!e||!e[t])throw new Error("that key "+t+"doesnt exist in this blob"+e);return e[t][c()]||console.warn("WARNING!! This blob does not have intl support:",e,"for this key",t),e[t][h()]},g=n.getDialog=function(e){var t=c();return m(e,"dialog")||e.dialog[t]},y=n.getHint=function(e){return m(e,"hint")||v("error-untranslated")},b=n.getName=function(e){return m(e,"name")||v("error-untranslated")},w=n.getStartDialog=function(e){var t=m(e,"startDialog");if(t)return t;var n={type:"ModalAlert",options:{markdown:v("error-untranslated")}},r=u.clone(e.startDialog[c()]||e.startDialog);return r.childViews.unshift(n),r}}),e.define("/src/js/intl/strings.js",function(e,t,n,r,i,s,o){n.strings={"finish-dialog-finished":{__desc__:"One of the lines in the next level dialog",ja:"最後のレベルをクリアしました!すごい!!",en_US:"Wow! You finished the last level, great!",zh_CN:"我的个天!你完成了最后一关,碉堡了!",fr_FR:"Félicitations, vous avez réussi le dernier niveau !"},"finish-dialog-next":{__desc__:"One of the lines in the next level dialog",en_US:'Would you like to move on to *"{nextLevel}"*, the next level?',ja:'次の章 *"{nextLevel}"* へ進みますか?',zh_CN:"要不前进到下一关 *“{nextLevel}”*?",fr_FR:'Voulez-vous passer à *"{nextLevel}"*, le prochain niveau ?'},"finish-dialog-win":{__desc__:"One of the lines in the next level dialog",en_US:"Awesome! You matched or exceeded our solution.",ja:"素晴らしい!このレベルをクリアしましたね。",zh_CN:"牛鼻啊!你达到或者完爆了我们的答案。",fr_FR:"Fabuleux ! Votre solution a égalé ou surpassé notre solution."},"finish-dialog-lose":{__desc__:"When the user entered more commands than our best, encourage them to do better",en_US:"See if you can whittle it down to {best} :D",ja:"模範解答の回数={best}回でクリアする方法も考えてみましょう :D",zh_CN:"试试看你能否在 {best} 之内搞定 :D",fr_FR:"Voyons si vous pouvez descendre à {best} :D"},"git-status-detached":{__desc__:"One of the lines for git status output",en_US:"Detached head!",zh_CN:"脑袋搬家(Detached head)了!",fr_FR:"head détaché !"},"git-status-onbranch":{__desc__:"One of the lines for git status output",en_US:"On branch {branch}",zh_CN:"切换到分支 {branch}",fr_FR:"Sur la branche {branch}"},"git-status-readytocommit":{__desc__:"One of the lines for git status output",en_US:"Ready to commit! (as always in this demo)",zh_CN:"可以提交啦!(这演示里一直可以提交)",fr_FR:"Prêt à commit ! (comme toujours dans cette démo)"},"git-dummy-msg":{__desc__:"The dummy commit message for all commits. Feel free to put in a shoutout to your school / city / whatever!",en_US:"Quick commit. Go Bears!",zh_CN:"快速提交。上啊月熊!",fr_FR:"Commit rapide. NoMaN Sux!"},"git-error-origin-fetch-uptodate":{__desc__:"One of the error messages for git",en_US:"Already up to date!",fr_FR:"Déjà à jour"},"git-error-origin-fetch-no-ff":{__desc__:"One of the error messages for git",en_US:"Your origin branch is out of sync with the remote branch and fetch cannot be performed. try using --force",fr_FR:"Votre branche origin n'est plus synchronisée avec la branche distante et fetch ne peut pas être appliqué. Essayez avec l'option --force"},"git-error-origin-push-no-ff":{__desc__:"One of the error messages for git",en_US:"The remote repository has diverged from your local repository, so uploading your changes is not a simple fast forward (and thus your push was rejected). Please pull down the new changes in the remote repository, incorporate them into this branch, and try again. You can do so with git pull or git pull --rebase",fr_FR:"Le dépôt distant a divergé de votre référentiel local, donc l'envoi de vos modifications n'est pas en simple avance rapide (et donc votre envoi a été rejeté). Veuillez récupérer les nouveaux changements depuis le dépôt distant, les intégrer dans cette branche, et essayez à nouveau. Vous pouvez le faire avec git pull ou git pull --rebase"},"git-error-remote-branch":{__desc__:"One of the error messages for git",en_US:"You cannot execute that command on a remote branch",fr_FR:"Vous ne pouvez exécuter cette commande sur une branche distante"},"git-error-origin-required":{__desc__:"One of the error messages for git",en_US:"An origin is required for that command",fr_FR:"Une origine est requise pour cette commande"},"git-error-origin-exists":{__desc__:"One of the error messages for git",en_US:"An origin already exists! You cannot make a new one",fr_FR:"Une origine existe déjà ! Vous ne pouvez pas en créer une nouvelle"},"git-error-branch":{__desc__:"One of the error messages for git",en_US:"You can't delete the master branch, the branch you are on, or things that aren't branches",zh_CN:"你不能删除主分支(master),或者你当前所在的分支,或者其他不是分支也不知道能不能吃的东西。",fr_FR:"Vous ne pouvez supprimer la branche master, la branche sur laquelle vous êtes, ou ce qui n'est pas une branche"},"git-merge-msg":{__desc__:"The commit message for a merge commit",en_US:"Merge {target} into {current}",zh_CN:"合并 {target} 到 {current}",fr_FR:"Merge de {target} dans {current}"},"git-error-rebase-none":{__desc__:"One of the error messages for git",en_US:"No commits to rebase! Everything is a merge commit or changes already applied",zh_CN:"没有需要 rebase 的提交!都是个合并提交,或者已经 rebase 过了。",fr_FR:"Aucune commit à rebaser ! Tout est soit un commit de merge, soit des modifications déjà appliquées"},"git-result-nothing":{__desc__:"The message that explains the result of a git command",en_US:"Nothing to do...",zh_CN:"没啥鸟事……",fr_FR:"Rien à effectuer…"},"git-result-fastforward":{__desc__:"The message that explains the result of a git command",en_US:"Fast forwarding...",zh_CN:"快速前进……",fr_FR:"En avance rapide…"},"git-result-uptodate":{__desc__:"The message that explains the result of a git command",en_US:"Branch already up-to-date",zh_CN:"分支已经是最新啦",fr_FR:"Branche déjà à jour"},"git-error-exist":{__desc__:"One of the error messages for git",en_US:"The ref {ref} does not exist or is unknown",zh_CN:"索引 {ref} 不存在,或者找不到。",fr_FR:"La référence {ref} n'existe pas ou est inconnue"},"git-error-relative-ref":{__desc__:"One of the error messages for git",en_US:"Commit {commit} doesnot have a {match}",zh_CN:"提交 {commit} 并没有 {match}",fr_FR:"Le commit {commit} n'a pas de correspondance {match}"},"git-warning-detached":{__desc__:"One of the warning messages for git",en_US:"Warning!! Detached HEAD state",zh_CN:"警告!脑袋搬家(Detached HEAD)状态",fr_FR:"Attention ! HEAD est détaché"},"git-warning-add":{__desc__:"One of the warning messages for git",en_US:"No need to add files in this demo",zh_CN:"此演示中不需要添加文件",fr_FR:"Aucun besoin d'ajouter des fichiers dans cette démo"},"git-error-options":{__desc__:"One of the error messages for git",en_US:"Those options you specified are incompatible or incorrect",zh_CN:"你所指定的参数不兼容或者不准确",fr_FR:"Les options que vous avez spécifiées sont incompatibles ou incorrectes"},"git-error-already-exists":{__desc__:"One of the error messages for git",en_US:"The commit {commit} already exists in your changes set, aborting!",zh_CN:"提交 {commit} 已经存在于你的改动集里,正在中止!",fr_FR:"Le commit {commit} existe déjà dans votre ensemble de modifications, opération avortée !"},"git-error-reset-detached":{__desc__:"One of the error messages for git",en_US:"Can't reset in detached head! Use checkout if you want to move",zh_CN:"不能在分离的 HEAD 里重置!用 checkout 吧",fr_FR:"On ne peut pas effectuer un reset quand head est détaché. Utilisez checkout pour déplacer"},"git-warning-hard":{__desc__:"One of the warning messages for git",en_US:"The default behavior is a --hard reset, feel free to omit that option!",zh_CN:"默认的行为是 --hard 硬重置,尽管省略掉那个选项吧!",fr_FR:"Le comportement par défaut est un --hard reset, soyez libre d'omettre cette option !"},"git-error-staging":{__desc__:"One of the error messages for git",en_US:"There is no concept of adding / staging files, so that option or command is invalid!",zh_CN:"没有添加、缓存文件的必要,所以改选项或者命令是不合法的。",fr_FR:"Il n'y a pas le concept d'ajouter / mettre en staging, donc cette option ou commande est invalide"},"git-revert-msg":{__desc__:"Message for reverting git command",en_US:"Reverting {oldCommit}: {oldMsg}",zh_CN:"撤销 {oldCommit}:{oldMsg}",fr_FR:"Revert {oldCommit}: {oldMsg}"},"git-error-args-many":{__desc__:"One of the error messages for git",en_US:"I expect at most {upper} argument(s) for {what}",zh_CN:"{what} 期望最多 {upper} 个参数",fr_FR:"J'attends au plus {upper} argument(s) pour {what}"},"git-error-args-few":{__desc__:"One of the error messages for git",en_US:"I expect at least {lower} argument(s) for {what}",zh_CN:"{what} 期望最少 {lower} 个参数",fr_FR:"J'attends au moins {upper} argument(s) pour {what}"},"git-error-no-general-args":{__desc__:"One of the error messages for git",en_US:"That command accepts no general arguments",zh_CN:"该命令不接收参数",fr_FR:"Cette commande n'accepte aucun argument général"},"copy-tree-string":{__desc__:"The prompt to copy the tree when sharing",en_US:"Copy the tree string below",zh_CN:"拷贝下面的树字符串",fr_FR:"Copiez la chaîne d'arbre ci-dessous"},"learn-git-branching":{__desc__:"The title of the app, with spaces",en_US:"Learn Git Branching",ja:"日本語版リポジトリ",ko:"Git 브랜치 배우기",zh_CN:"学习Git分支",fr_FR:"Apprenez Git Branching"},"select-a-level":{__desc__:"The prompt to select a level on the drop down view",en_US:"Select a level",zh_CN:"选择一关",fr_FR:"Choisissez un niveau"},"branch-name-short":{__desc__:"When branch names get too long, we need to truncate them. This is the warning for that",en_US:'Sorry, we need to keep branch names short for the visuals. Your branch name was truncated to 9 characters, resulting in "{branch}"',zh_CN:'抱歉,为了显示的需要,我们需要一个短些的分支名称。您使用的将被截断到9个字符,即"{branch}"',fr_FR:'Désolé, nous devons garder les noms de branches courts pour la visualisation. Votre nom de branche a été tronqué à 9 caractères, devenant "{branch}"'},"bad-branch-name":{__desc__:"When the user enters a branch name thats not ok",en_US:'That branch name "{branch}" is not allowed!',zh_CN:'不能给分支起这个名字 "{branch}"',fr_FR:'Ce nom de branche "{branch}" n\'est pas autorisé'},"option-not-supported":{__desc__:"When the user specifies an option that is not supported by our demo",en_US:'The option "{option}" is not supported!',zh_CN:'不支持选项 "{option}"',fr_FR:"L'option \"{option}\" n'est pas supportée"},"git-usage-command":{__desc__:"The line that shows how to format a git command",en_US:"git []",zh_CN:"git <命令> [<参数>]",fr_FR:"git []"},"git-supported-commands":{__desc__:"In the git help command, the header above the supported commands",en_US:"Supported commands:",zh_CN:"支持的命令有:",fr_FR:"Commandes supportées"},"git-usage":{__desc__:"In the dummy git output, the header before showing all the commands",en_US:"Usage:",zh_CN:"使用:",fr_FR:"Utilisation :"},"git-version":{__desc__:"The git version dummy output, kind of silly. PCOTTLE is my unix name but feel free to put yours instead",en_US:"Git Version PCOTTLE.1.0",zh_CN:"Git 版本 PCOTTLE.1.0",fr_FR:"Git version PCOTTLE.1.0"},"refresh-tree-command":{__desc__:"when the tree is visually refreshed",en_US:"Refreshing tree...",zh_CN:"正在刷新树结构...",fr_FR:"Actualisation de l'arbre…"},"locale-command":{__desc__:"when the locale is set to something",en_US:"Locale set to {locale}",zh_CN:"语言更改为 {locale}",fr_FR:"Langue changée à {locale}"},"locale-reset-command":{__desc__:"when the locale is reset",en_US:"Locale reset to default, which is {locale}",zh_CN:"语言重置为默认的 {locale}",fr_FR:"Langue remise par défaut, qui est {locale}"},"show-command":{__desc__:'command output title from "show"',en_US:"Please use one of the following commands for more info:",fr_FR:"Merci d'utiliser une des commandes suivantes pour obtenir plus d'info"},"show-all-commands":{__desc__:'command output title from "show commands"',en_US:"Here is a list of all the commmands available:",fr_FR:"Ci-dessous est la liste de toutes les commandes disponibles :"},"cd-command":{__desc__:"dummy command output for the command in the key",en_US:'Directory changed to "/directories/dont/matter/in/this/demo"',zh_CN:'目录切换到 "/directories/dont/matter/in/this/demo"',fr_FR:'Répertoire changé à "/directories/dont/matter/in/this/demo" (les répertoires ne servent à rien dans cette démo)'},"ls-command":{__desc__:"Dummy command output for the command in the key",en_US:"DontWorryAboutFilesInThisDemo.txt",zh_CN:"DontWorryAboutFilesInThisDemo.txt (译: 在试验里不用担心文件.txt)",fr_FR:"DontWorryAboutFilesInThisDemo.txt (ne vous préoccupez pas des noms de fichier dans cette démo)"},"mobile-alert":{__desc__:"When someone comes to the site on a mobile device, they can not input commands so this is a nasty alert to tell them",en_US:"Can't bring up the keyboard on mobile / tablet :( try visiting on desktop! :D",zh_CN:"无法在移动设备/平板上调出键盘 :( 请试试桌面版 :D",fr_FR:"Impossible de faire apparaître le clavier sur mobile / tablette :( Essayez de passer sur un ordinateur de bureau :D"},"share-tree":{__desc__:"When you export a tree, we want you to share the tree with friends",en_US:'Share this tree with friends! They can load it with "import tree"',zh_CN:'与你的好友分享提交树!他们可以用 "import tree" 加载它',fr_FR:'Partagez cet arbre avec vos amis ! Ils peuvent le charger avec "import tree"'},"paste-json":{__desc__:"When you are importing a level or tree",en_US:"Paste a JSON blob below!",zh_CN:"在下边粘贴一个JSON串",fr_FR:"Collez un blob JSON ci-dessous !"},"solved-map-reset":{__desc__:"When you reset the solved map to clear your solved history, in case someone else wants to use your browser",en_US:"Solved map was reset, you are starting from a clean slate!",zh_CN:"解决列表已重置,您现在从零开始了",fr_FR:"La carte des niveaux résolus a été effacée, vous repartez de zéro !"},"level-cant-exit":{__desc__:"When the user tries to exit a level when they are not in one",en_US:'You are not in a level! You are in a sandbox, start a level with "levels"',zh_CN:'您没在关卡中!您在沙盒中,要开始关卡请输入 "levels"',fr_FR:'Vous n\'êtes pas dans un niveau ! Vous êtes dans le mode bac à sable, commencez un niveau avec "levels"'},"level-no-id":{__desc__:"When you say an id but that level doesnt exist",en_US:'A level for that id "{id}" was not found! Opening up a level selection view',zh_CN:'没找到id为 "{id}" 的关卡!打开关卡选择框',fr_FR:"Le niveau dont l'identifiant est {id} n'a pas été trouvé ! Ouverture de la vue de sélection des niveaux"},"undo-stack-empty":{__desc__:"The undo command can only undo back until the last time the level was reset or the beginning of the level",en_US:"The undo stack is empty!",zh_CN:"还没有什么可以撤销",fr_FR:"La pile d'annulation est vide !"},"already-solved":{__desc__:"When you play in a level that is already solved",en_US:'You have already solved this level, try other levels with "levels" or go back to sandbox with "sandbox"',zh_CN:'你已经解决了本关,输入 "levels" 尝试其他关卡,或者输入 "sandbox" 回到沙盒中',fr_FR:'Vous avez déjà résolu ce niveau, essayez d\'autres niveaux avec "levels" ou revenez au bac à sable avec "sandbox"'},"command-disabled":{__desc__:"When you try a command that is disabled",en_US:"That git command is disabled for this level!",zh_CN:"该命令在本关不允许使用!",fr_FR:"Cette commande git est désactivée pour ce niveau !"},"share-json":{__desc__:"when you have made the level, prompt to share this",en_US:"Here is the JSON for this level! Share it with somenoe or send it to me on Github",zh_CN:"这是一个关卡定义JSON!您可以分享它或者发到我的GitHub上",fr_FR:"Voici le JSON pour ce niveau ! Partagez-le avec quelqu'un ou envoyez-le moi sur Github"},"want-start-dialog":{__desc__:"prompt to add a start dialog",en_US:"You have not specified a start dialog, would you like to add one?",zh_CN:"您还没有定义一开始的介绍,是否添加一个?",fr_FR:"Vous n'avez pas spécifié de dialogue de départ, voulez-vous en ajouter un ?"},"want-hint":{__desc__:"prompt to add a hint",en_US:"You have not specified a hint, would you like to add one?",zh_CN:"您还没有定义提示,是否添加一个?",fr_FR:"Vous n'avez pas spécifié d'indice, voulez-vous en ajouter un ?"},"prompt-hint":{__desc__:"prompt for hint",en_US:"Enter the hint for this level, or leave this blank if you do not want to include one",zh_CN:"请输入关卡提示,或者故意留空",fr_FR:"Entrez l'indice pour ce niveau, ou laissez-le vide pour ne pas l'inclure"},"prompt-name":{__desc__:"prompt for level name",en_US:"Enter the name for the level",zh_CN:"输入关卡名",fr_FR:"Entrez le nom pour ce niveau"},"solution-empty":{__desc__:"If you define a solution without any commands, aka a level that is solved without doing anything",en_US:"Your solution is empty!! Something is amiss",zh_CN:"你的解法是空的!! 这应该是出错了",fr_FR:"Votre solution est vide !! Quelque chose ne tourne pas rond"},"define-start-warning":{__desc__:"When you define the start point again, it overwrites the solution and goal so we add a warning",en_US:"Defining start point... solution and goal will be overwritten if they were defined earlier",zh_CN:"定义开始点... 解决方法和目标会被新的替代",fr_FR:"Redéfinition du point de départ… la solution et la cible seront écrasés s'ils ont déjà été définis"},"help-vague-level":{__desc__:"When you are in a level and you say help, its vague and you need to specify",en_US:'You are in a level, so multiple forms of help are available. Please select either "help level" to learn more about this lesson, "help general" for using Learn GitBranching, or "objective" to learn about how to solve the level.',zh_CN:'您正在关卡中,这里有多种形式的帮助,请选择 "help level" (关卡帮助)或 "help general" (一般帮助)',fr_FR:'Vous êtes dans un niveau, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help level" pour en apprendre plus sur cette leçon, "help general" pour l\'utilisation de Learn GitBranching, ou "objective" pour apprendre comment résoudre le niveau'},"help-vague-builder":{__desc__:"When you are in a level builder, the help command is vague so you need to specify what you mean",en_US:'You are in a level builder, so multiple forms of help are available. Please select either "help general" or "help builder"',zh_CN:'您正在进行关卡构建中,这里有多种形式的帮助,请选择 "help general" (一般帮助)或 "help builder" (关卡构建帮助)',fr_FR:'Vous êtes dans l\'éditeur de niveaux, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help general" soit "help builder"'},"goal-to-reach":{__desc__:"title of window that shoes the goal tree to reach",en_US:"Goal To Reach",zh_CN:"目标",fr_FR:"Cible à atteindre"},"hide-goal":{__desc__:"the helper message for the window that shows the goal tree",en_US:'You can hide this window with "hide goal"',zh_CN:'你可以通过命令 "hide goal" 关闭这个窗口',fr_FR:'Vous pouvez masquer cette fenêtre avec "hide goal"'},"hide-start":{__desc__:"The helper message for the window that shows the start tree for a level",en_US:'You can hide this window with "hide start"',zh_CN:'你可以通过命令 "hide start" 关闭这个窗口',fr_FR:'Vous pouvez masquer cette fenêtre avec "hide start"'},"level-builder":{__desc__:"The name for the environment where you build levels",en_US:"Level Builder",zh_CN:"关卡生成器",fr_FR:"Éditeur de niveaux"},"no-start-dialog":{__desc__:"when the user tries to open a start dialog for a level that does not have one",en_US:"There is no start dialog to show for this level!",zh_CN:"介绍? 这关真没有!",fr_FR:"Il n'y a aucun dialogue de départ à afficher pour ce niveau !"},"no-hint":{__desc__:"when no hint is available for a level",en_US:"Hmm, there doesn't seem to be a hint for this level :-/",zh_CN:"提示?嗯,这关真没有哎~ :-/",fr_FR:"Hum, il ne semble pas y avoir d'indice pour ce niveau :-/"},"error-untranslated-key":{__desc__:"This error happens when we are trying to translate a specific key and the locale version is mission",en_US:"The translation for {key} does not exist yet :( Please hop on github and offer up a translation!",zh_CN:"还没翻译 {key} :( 请在gitHub上贡献你的翻译!",fr_FR:"La traduction pour {key} n'existe pas encore :( Venez sur Github pour en offrir une !"},"error-untranslated":{__desc__:"The general error when we encounter a dialog that is not translated",en_US:"This dialog or text is not yet translated in your locale :( Hop on github to aid in translation!",zh_CN:"这段对话还没有被翻译成你的语言 :( 欢迎在gitHub上贡献你的翻译!",fr_FR:"Ce message n'a pas encore été traduit dans votre langue :( Venez sur Github aider à la traduction !"}}}),e.define("/src/js/app/index.js",function(e,t,n,r,i,s,o){function E(){var t=e("../views"),n=e("../models/collections"),r=e("../views/commandViews"),i=new t.MainHelperBar;this.commandCollection=new n.CommandCollection,this.commandBuffer=new n.CommandBuffer({collection:this.commandCollection}),this.commandPromptView=new r.CommandPromptView({el:$("#commandLineBar")}),this.commandLineHistoryView=new r.CommandLineHistoryView({el:$("#commandLineHistory"),collection:this.commandCollection})}var u=e("underscore"),a=e("backbone"),f=e("../util/constants"),l=e("../util"),c=u.clone(a.Events),h,p,d,v,m,g=function(){var t=e("../level/sandbox").Sandbox,n=e("../level").Level,r=e("../util/eventBaton").EventBaton,i=e("../level/arbiter").LevelArbiter,s=e("../views/levelDropdownView").LevelDropdownView;d=new r,h=new E,p=new t,v=new i,m=new s({wait:!0}),c.on("localeChanged",y),b(d),w(p)},y=function(){if(!window.$)return;$("span.intl-aware").each(function(t,n){var r=e("../intl"),i=$(n).attr("data-intl");$(n).text(r.str(i).toUpperCase())})},b=function(e){var t=function(){$("#commandTextField").focus()};t(),$(window).focus(function(t){e.trigger("windowFocus",t)}),$(document).click(function(t){e.trigger("documentClick",t)}),$(document).bind("keydown",function(t){e.trigger("docKeydown",t)}),$(document).bind("keyup",function(t){e.trigger("docKeyup",t)}),$(window).on("resize",function(e){c.trigger("resize",e)}),e.stealBaton("docKeydown",function(){}),e.stealBaton("docKeyup",function(){}),e.stealBaton("windowFocus",t),e.stealBaton("documentClick",t);var n=function(t){return function(){var n=[t];u.each(arguments,function(e){n.push(e)}),e.trigger.apply(e,n)}};$("#commandTextField").on("keydown",n("keydown")),$("#commandTextField").on("keyup",n("keyup")),$(window).trigger("resize")},w=function(e){var t=l.parseQueryString(window.location.href);t.hasOwnProperty("demo")?e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",["git commit; git checkout -b bugFix C1; git commit; git merge master; git checkout master; git commit; git rebase bugFix;","delay 1000; reset;","level rebase1 --noFinishDialog --noStartCommand --noIntroDialog;","delay 2000; show goal; delay 1000; hide goal;","git checkout bugFix; git rebase master; git checkout side; git rebase bugFix;","git checkout another; git rebase side; git rebase another master;","help; levels"].join(""))}):t.hasOwnProperty("NODEMO")||e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",["git help;","delay 1000;","help;","levels"].join(""))}),t.locale!==undefined&&t.locale.length&&(f.GLOBAL.locale=t.locale,c.trigger("localeChanged"));if(t.command){var n=unescape(t.command);e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",n)})}(/(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent)||/android/i.test(navigator.userAgent))&&e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted","mobile alert")})};e("../util").isBrowser()&&$(document).ready(g),n.getEvents=function(){return c},n.getSandbox=function(){return p},n.getEventBaton=function(){return d},n.getCommandUI=function(){return h},n.getLevelArbiter=function(){return v},n.getLevelDropdown=function(){return m},n.init=g}),e.define("/src/js/level/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("../util"),c=e("../app"),h=e("../intl"),p=e("../log"),d=e("../util/errors"),v=e("../level/sandbox").Sandbox,m=e("../util/constants"),g=e("../visuals/visualization").Visualization,y=e("../level/parseWaterfall").ParseWaterfall,b=e("../level/disabledMap").DisabledMap,w=e("../models/commandModel").Command,E=e("../git/gitShim").GitShim,S=e("../views/multiView").MultiView,x=e("../views").CanvasTerminalHolder,T=e("../views").ConfirmCancelTerminal,N=e("../views").NextLevelConfirm,C=e("../views").LevelToolbar,k=e("../git/treeCompare").TreeCompare,L={"help level":/^help level$/,"start dialog":/^start dialog$/,"show goal":/^(show goal|goal|help goal)$/,"hide goal":/^hide goal$/,"show solution":/^show solution($|\s)/,objective:/^(objective|assignment)$/},A=l.genParseCommand(L,"processLevelCommand"),O=v.extend({initialize:function(e){e=e||{},e.level=e.level||{},this.level=e.level,this.gitCommandsIssued=[],this.commandsThatCount=this.getCommandsThatCount(),this.solved=!1,this.initGoalData(e),this.initName(e),O.__super__.initialize.apply(this,[e]),this.startOffCommand(),this.handleOpen(e.deferred)},handleOpen:function(e){e=e||f.defer();if(this.level.startDialog&&!this.testOption("noIntroDialog")){new S(u.extend({},h.getStartDialog(this.level),{deferred:e}));return}setTimeout(function(){e.resolve()},this.getAnimationTime()*1.2)},objectiveDialog:function(e,t,n){n=n===undefined?this.level:n;if(!n||!n.startDialog){e.set("error",new d.GitError({msg:h.str("no-start-dialog")})),t.resolve();return}debugger;console.log(h.getStartDialog(n));var r=$.extend({},h.getStartDialog(n));r.childViews=r.childViews.slice(-1),new S(u.extend(r,{deferred:t})),t.promise.then(function(){e.set("status","finished")})},startDialog:function(e,t){if(!this.level.startDialog){e.set("error",new d.GitError({msg:h.str("no-start-dialog")})),t.resolve();return}this.handleOpen(t),t.promise.then(function(){e.set("status","finished")})},getEnglishName:function(){return this.level.name.en_US},initName:function(){var e=h.getName(this.level);this.levelToolbar=new C({name:e})},initGoalData:function(e){if(!this.level.goalTreeString||!this.level.solutionCommand)throw new Error("need goal tree and solution")},takeControl:function(){c.getEventBaton().stealBaton("processLevelCommand",this.processLevelCommand,this),O.__super__.takeControl.apply(this)},releaseControl:function(){c.getEventBaton().releaseBaton("processLevelCommand",this.processLevelCommand,this),O.__super__.releaseControl.apply(this)},startOffCommand:function(){this.testOption("noStartCommand")||c.getEventBaton().trigger("commandSubmitted","hint; delay 2000; show goal")},initVisualization:function(e){this.mainVis=new g({el:e.el||this.getDefaultVisEl(),treeString:e.level.startTree})},initGoalVisualization:function(){return this.goalCanvasHolder=new x,this.goalVis=new g({el:this.goalCanvasHolder.getCanvasLocation(),containerElement:this.goalCanvasHolder.getCanvasLocation(),treeString:this.level.goalTreeString,noKeyboardInput:!0,smallCanvas:!0,noClick:!0}),this.goalCanvasHolder},showSolution:function(t,n){var r=this.level.solutionCommand,i=u.bind(function(){this.isShowingSolution=!0,c.getEventBaton().trigger("commandSubmitted",r),p.showLevelSolution(this.getEnglishName())},this),s=t.get("rawStr");this.testOptionOnString(s,"noReset")||(r="reset --forSolution; "+r);if(this.testOptionOnString(s,"force")){i(),t.finishWith(n);return}var o=f.defer(),a=h.getDialog(e("../dialogs/confirmShowSolution"))[0],l=new T({markdowns:a.options.markdowns,deferred:o});o.promise.then(i).fail(function(){t.setResult("")}).done(function(){setTimeout(function(){t.finishWith(n)},l.getAnimationTime())})},showGoal:function(e,t){this.showSideVis(e,t,this.goalCanvasHolder,this.initGoalVisualization)},showSideVis:function(e,t,n,r){var i=function(){e&&e.finishWith(t)};if(!n||!n.inDom)n=r.apply(this);n.slideIn(),setTimeout(i,n.getAnimationTime())},hideGoal:function(e,t){this.hideSideVis(e,t,this.goalCanvasHolder)},hideSideVis:function(e,t,n,r){var i=function(){e&&e.finishWith(t)};n&&n.inDom?(n.die(),setTimeout(i,n.getAnimationTime())):i()},initParseWaterfall:function(e){O.__super__.initParseWaterfall.apply(this,[e]),this.parseWaterfall.addFirst("parseWaterfall",A),this.parseWaterfall.addFirst("instantWaterfall",this.getInstantCommands()),e.level.disabledMap&&this.parseWaterfall.addFirst("instantWaterfall",(new b({disabledMap:e.level.disabledMap})).getInstantCommands())},initGitShim:function(e){this.gitShim=new E({beforeCB:u.bind(this.beforeCommandCB,this),afterCB:u.bind(this.afterCommandCB,this),afterDeferHandler:u.bind(this.afterCommandDefer,this)})},getCommandsThatCount:function(){var t=e("../git/commands"),n=["git commit","git checkout","git rebase","git reset","git branch","git revert","git merge","git cherry-pick"],r={};return u.each(n,function(e){if(!t.regexMap[e])throw new Error("wut no regex");r[e]=t.regexMap[e]}),r},undo:function(){this.gitCommandsIssued.pop(),O.__super__.undo.apply(this,arguments)},afterCommandCB:function(e){if(e.get("error"))return;var t=!1;u.each(this.commandsThatCount,function(n){t=t||n.test(e.get("rawStr"))}),t&&this.gitCommandsIssued.push(e.get("rawStr"))},afterCommandDefer:function(e,t){if(this.solved){t.addWarning(h.str("already-solved")),e.resolve();return}var n=this.mainVis.gitEngine.exportTree(),r=k.dispatchFromLevel(this.level,n);if(!r){e.resolve();return}this.levelSolved(e)},getNumSolutionCommands:function(){var e=this.level.solutionCommand.replace(/^;|;$/g,"");return e.split(";").length},testOption:function(e){return this.options.command&&(new RegExp("--"+e)).test(this.options.command.get("rawStr"))},testOptionOnString:function(e,t){return e&&(new RegExp("--"+t)).test(e)},levelSolved:function(e){this.solved=!0,this.isShowingSolution||(c.getEvents().trigger("levelSolved",this.level.id),p.levelSolved(this.getEnglishName())),this.hideGoal();var t=c.getLevelArbiter().getNextLevel(this.level.id),n=this.gitCommandsIssued.length,r=this.getNumSolutionCommands();m.GLOBAL.isAnimating=!0;var i=this.testOption("noFinishDialog"),s=this.mainVis.gitVisuals.finishAnimation();i||(s=s.then(function(){var e=new N({nextLevel:t,numCommands:n,best:r});return e.getPromise()})),s.then(function(){!i&&t&&(p.choseNextLevel(t.id),c.getEventBaton().trigger("commandSubmitted","level "+t.id))}).fail(function(){}).done(function(){m.GLOBAL.isAnimating=!1,e.resolve()})},die:function(){this.levelToolbar.die(),this.hideGoal(),this.mainVis.die(),this.releaseControl(),this.clear(),delete this.commandCollection,delete this.mainVis,delete this.goalVis,delete this.goalCanvasHolder},getInstantCommands:function(){var e=u.bind(function(){var e=h.getHint(this.level);return!e||!e.length?h.str("no-hint"):e},this);return[[/^help$|^\?$/,function(){throw new d.CommandResult({msg:h.str("help-vague-level")})}],[/^hint$/,function(){throw new d.CommandResult({msg:e()})}]]},reset:function(e,t){this.gitCommandsIssued=[];var n=e?e.get("rawStr"):"";this.testOptionOnString(n,"forSolution")||(this.isShowingSolution=!1),this.solved=!1,O.__super__.reset.apply(this,arguments)},buildLevel:function(e,t){this.exitLevel(),setTimeout(function(){c.getSandbox().buildLevel(e,t)},this.getAnimationTime()*1.5)},importLevel:function(e,t){this.exitLevel(),setTimeout(function(){c.getSandbox().importLevel(e,t)},this.getAnimationTime()*1.5)},startLevel:function(e,t){this.exitLevel(),setTimeout(function(){c.getSandbox().startLevel(e,t)},this.getAnimationTime()*1.5)},exitLevel:function(e,t){this.die();if(!e||!t)return;setTimeout(function(){e.finishWith(t)},this.getAnimationTime()),c.getEventBaton().trigger("levelExited")},processLevelCommand:function(e,t){var n={"show goal":this.showGoal,"hide goal":this.hideGoal,"show solution":this.showSolution,"start dialog":this.startDialog,"help level":this.startDialog,objective:this.objectiveDialog},r=n[e.get("method")];if(!r)throw new Error("woah we dont support that method yet",r);r.apply(this,[e,t])}});n.Level=O,n.regexMap=L}),e.define("/src/js/log/index.js",function(e,t,n,r,i,s,o){var u=function(e,t,n){window._gaq=window._gaq||[],window._gaq.push(["_trackEvent",e,t,n])};n.viewInteracted=function(e){u("views","interacted",e)},n.showLevelSolution=function(e){u("levels","showedLevelSolution",e)},n.choseNextLevel=function(e){u("levels","nextLevelChosen",e)},n.levelSelected=function(e){u("levels","levelSelected",e)},n.levelSolved=function(e){u("levels","levelSolved",e)},n.commandEntered=function(e){u("commands","commandEntered",e)}}),e.define("/src/js/util/errors.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({defaults:{type:"MyError",msg:"Unknown Error"},toString:function(){return this.get("type")+": "+this.get("msg")},getMsg:function(){return this.get("msg")||"Unknown Error"},toResult:function(){return this.get("msg").length?"

"+this.get("msg").replace(/\n/g,"

")+"

":""}}),l=n.CommandProcessError=f.extend({defaults:{type:"Command Process Error"}}),c=n.CommandResult=f.extend({defaults:{type:"Command Result"}}),h=n.Warning=f.extend({defaults:{type:"Warning"}}),p=n.GitError=f.extend({defaults:{type:"Git Error"}}),d=function(e){if(e instanceof l||e instanceof p||e instanceof c||e instanceof h)return;throw e};n.filterError=d}),e.define("/src/js/visuals/visualization.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../models/collections"),l=f.CommitCollection,c=f.BranchCollection,h=e("../util/eventBaton").EventBaton,p=e("../visuals").GitVisuals,d=a.View.extend({initialize:function(e){e=e||{},this.options=e,this.customEvents=u.clone(a.Events),this.containerElement=e.containerElement;var t=this,n=e.containerElement||$("#canvasHolder")[0];new Raphael(n,200,200,function(){var n=this;s.nextTick(function(){t.paperInitialize(n,e)})})},paperInitialize:function(t,n){this.treeString=n.treeString,this.paper=t;var r=e("../app");this.eventBaton=n.noKeyboardInput?new h:r.getEventBaton(),this.commitCollection=new l,this.branchCollection=new c,this.gitVisuals=new p({commitCollection:this.commitCollection,branchCollection:this.branchCollection,paper:this.paper,noClick:this.options.noClick,smallCanvas:this.options.smallCanvas,visualization:this});var i=e("../git").GitEngine;this.gitEngine=new i({collection:this.commitCollection,branches:this.branchCollection,gitVisuals:this.gitVisuals,eventBaton:this.eventBaton}),this.gitEngine.init(),this.gitVisuals.assignGitEngine(this.gitEngine),this.myResize(),$(window).on("resize",u.bind(function(){this.myResize()},this)),this.gitVisuals.drawTreeFirstTime(),this.treeString&&this.gitEngine.loadTreeFromString(this.treeString),this.options.zIndex&&this.setTreeIndex(this.options.zIndex),this.shown=!1,this.setTreeOpacity(0),s.nextTick(u.bind(this.fadeTreeIn,this)),this.customEvents.trigger("gitEngineReady"),this.customEvents.trigger("paperReady")},clearOrigin:function(){delete this.originVis},makeOrigin:function(e){return this.originVis=new d(u.extend({},this.options,{noKeyboardInput:!0,noClick:!0,treeString:e.treeString})),this.originVis},originToo:function(e,t){if(!this.originVis)return;var n=u.bind(function(){this.originVis[e].apply(this.originVis,t)},this);if(this.originVis.paper){n();return}this.originVis.customEvents.on("paperReady",n)},setTreeIndex:function(e){$(this.paper.canvas).css("z-index",e),this.originToo("setTreeIndex",arguments)},setTreeOpacity:function(e){e===0&&(this.shown=!1),$(this.paper.canvas).css("opacity",e),this.originToo("setTreeOpacity",arguments)},getAnimationTime:function(){return 300},fadeTreeIn:function(){this.shown=!0,$(this.paper.canvas).animate({opacity:1},this.getAnimationTime()),this.originToo("fadeTreeIn",arguments)},fadeTreeOut:function(){this.shown=!1,$(this.paper.canvas).animate({opacity:0},this.getAnimationTime()),this.originToo("fadeTreeOut",arguments)},hide:function(){this.fadeTreeOut(),setTimeout(u.bind(function(){$(this.paper.canvas).css("visibility","hidden")},this),this.getAnimationTime()),this.originToo("hide",arguments)},show:function(){$(this.paper.canvas).css("visibility","visible"),setTimeout(u.bind(this.fadeTreeIn,this),10),this.originToo("show",arguments)},showHarsh:function(){$(this.paper.canvas).css("visibility","visible"),this.setTreeOpacity(1),this.originToo("showHarsh",arguments)},resetFromThisTreeNow:function(e){this.treeString=e;var t=this.getOriginInTreeString(e);if(t){var n=this.gitEngine.printTree(t);this.originToo("resetFromThisThreeNow",[n])}},getOriginInTreeString:function(e){var t=JSON.parse(unescape(e));return t.originTree},reset:function(e){var t=e||this.treeString;this.setTreeOpacity(0),t?this.gitEngine.loadTreeFromString(t):this.gitEngine.defaultInit(),this.fadeTreeIn();if(this.originVis)if(t){var n=this.getOriginInTreeString(t);this.originToo("reset",[JSON.stringify(n)])}else this.originToo("reset",arguments)},tearDown:function(){this.gitEngine.tearDown(),this.gitVisuals.tearDown(),delete this.paper,this.originToo("tearDown",arguments)},die:function(){this.fadeTreeOut(),setTimeout(u.bind(function(){this.shown||this.tearDown()},this),this.getAnimationTime()),this.originToo("die",arguments)},myResize:function(){if(!this.paper)return;var e=1,t=this.el,n=t.clientWidth-e,r=t.clientHeight-e;if(!this.containerElement){var i=t.offsetLeft,s=t.offsetTop;$(this.paper.canvas).css({position:"absolute",left:i+"px",top:s+"px"})}this.paper.setSize(n,r),this.gitVisuals.canvasResize(n,r)}});n.Visualization=d}),e.define("/src/js/models/collections.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?f=window.Backbone:f=e("backbone"),l=e("../git").Commit,c=e("../git").Branch,h=e("../models/commandModel").Command,p=e("../models/commandModel").CommandEntry,d=e("../util/constants").TIME,v=f.Collection.extend({model:l}),m=f.Collection.extend({model:h}),g=f.Collection.extend({model:c}),y=f.Collection.extend({model:p,localStorage:f.LocalStorage?new f.LocalStorage("CommandEntries"):null}),b=f.Model.extend({defaults:{collection:null},initialize:function(e){e.collection.bind("add",this.addCommand,this),this.buffer=[],this.timeout=null},addCommand:function(e){this.buffer.push(e),this.touchBuffer()},touchBuffer:function(){if(this.timeout)return;this.setTimeout()},setTimeout:function(){this.timeout=setTimeout(u.bind(function(){this.sipFromBuffer()},this),d.betweenCommandsDelay)},popAndProcess:function(){var e=this.buffer.shift(0);while(e.get("error")&&this.buffer.length)e=this.buffer.shift(0);e.get("error")?this.clear():this.processCommand(e)},processCommand:function(t){t.set("status","processing");var n=a.defer();n.promise.then(u.bind(function(){this.setTimeout()},this));var r=t.get("eventName");if(!r)throw new Error("I need an event to trigger when this guy is parsed and ready");var i=e("../app"),s=i.getEventBaton(),o=s.getNumListeners(r);if(!o){var f=e("../util/errors");t.set("error",new f.GitError({msg:"That command is valid, but not supported in this current environment! Try entering a level or level builder to use that command"})),n.resolve();return}i.getEventBaton().trigger(r,t,n)},clear:function(){clearTimeout(this.timeout),this.timeout=null},sipFromBuffer:function(){if(!this.buffer.length){this.clear();return}this.popAndProcess()}});n.CommitCollection=v,n.CommandCollection=m,n.BranchCollection=g,n.CommandEntryCollection=y,n.CommandBuffer=b}),e.define("/src/js/git/index.js",function(e,t,n,r,i,s,o){function y(e){this.rootCommit=null,this.refs={},this.HEAD=null,this.origin=null,this.localRepo=null,this.branchCollection=e.branches,this.commitCollection=e.collection,this.gitVisuals=e.gitVisuals,this.eventBaton=e.eventBaton,this.eventBaton.stealBaton("processGitCommand",this.dispatch,this),e.animationFactory&&(c=e.animationFactory),this.commandOptions={},this.generalArgs=[],this.initUniqueID()}var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("q"),l=e("../intl"),c=e("../visuals/animation/animationFactory").AnimationFactory,h=e("../visuals/animation").AnimationQueue,p=e("./treeCompare").TreeCompare,d=e("../util/errors"),v=d.GitError,m=d.CommandResult,g=e("../util/eventBaton").EventBaton;y.prototype.initUniqueID=function(){this.uniqueId=function(){var e=0;return function(t){return t?t+e++:e++}}()},y.prototype.assignLocalRepo=function(e){this.localRepo=e},y.prototype.defaultInit=function(){var e=this.getDefaultTree();this.loadTree(e)},y.prototype.getDefaultTree=function(){return JSON.parse(unescape("%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22master%22%2C%22type%22%3A%22branch%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%22C0%22%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C1%22%7D%7D%2C%22HEAD%22%3A%7B%22id%22%3A%22HEAD%22%2C%22target%22%3A%22master%22%2C%22type%22%3A%22general%20ref%22%7D%7D"))},y.prototype.init=function(){this.rootCommit=this.makeCommit(null,null,{rootCommit:!0}),this.commitCollection.add(this.rootCommit);var e=this.makeBranch("master",this.rootCommit);this.HEAD=new b({id:"HEAD",target:e}),this.refs[this.HEAD.get("id")]=this.HEAD,this.commit()},y.prototype.hasOrigin=function(){return!!this.origin},y.prototype.isOrigin=function(){return!!this.localRepo},y.prototype.exportTreeForBranch=function(e){var t=this.exportTree(),n=this.getUpstreamSet(e),r=t.commits;t.commits={},u.each(r,function(e,r){n[r]&&(t.commits[r]=e)});var i=t.branches;return t.branches={},u.each(i,function(n,r){r===e&&(t.branches[r]=n)}),t.HEAD.target=e,t},y.prototype.exportTree=function(){var e={branches:{},commits:{},HEAD:null};u.each(this.branchCollection.toJSON(),function(t){t.target=t.target.get("id"),t.visBranch=undefined,e.branches[t.id]=t}),u.each(this.commitCollection.toJSON(),function(t){u.each(E.prototype.constants.circularFields,function(e){t[e]=undefined},this);var n=[];u.each(t.parents,function(e){n.push(e.get("id"))}),t.parents=n,e.commits[t.id]=t},this);var t=this.HEAD.toJSON();return t.visBranch=undefined,t.lastTarget=t.lastLastTarget=t.visBranch=undefined,t.target=t.target.get("id"),e.HEAD=t,this.hasOrigin()&&(e.originTree=this.origin.exportTree()),e},y.prototype.printTree=function(e){e=e||this.exportTree(),p.reduceTreeFields([e]);var t=JSON.stringify(e);return/'/.test(t)&&(t=escape(t)),t},y.prototype.printAndCopyTree=function(){window.prompt(l.str("Copy the tree string below"),this.printTree())},y.prototype.loadTree=function(e){e=$.extend(!0,{},e),this.removeAll(),this.instantiateFromTree(e),this.reloadGraphics(),this.initUniqueID()},y.prototype.loadTreeFromString=function(e){this.loadTree(JSON.parse(unescape(e)))},y.prototype.instantiateFromTree=function(e){var t={};u.each(e.commits,function(n){var r=this.getOrMakeRecursive(e,t,n.id);this.commitCollection.add(r)},this),u.each(e.branches,function(n){var r=this.getOrMakeRecursive(e,t,n.id);this.branchCollection.add(r,{silent:!0})},this);var n=this.getOrMakeRecursive(e,t,e.HEAD.id);this.HEAD=n,this.rootCommit=t.C0;if(!this.rootCommit)throw new Error("Need root commit of C0 for calculations");this.refs=t,this.gitVisuals.gitReady=!1,this.branchCollection.each(function(e){this.gitVisuals.addBranch(e)},this);if(e.originTree){var r=JSON.stringify(e.originTree);this.makeOrigin(r)}},y.prototype.makeOrigin=function(e){if(this.hasOrigin())throw new v({msg:l.str("git-error-origin-exists")});e=e||this.printTree(this.exportTreeForBranch("master"));var t=this.gitVisuals.getVisualization(),n=t.makeOrigin({localRepo:this,treeString:e});this.animationQueue.set("promiseBased",!0),n.customEvents.on("gitEngineReady",function(){this.origin=n.gitEngine,n.gitEngine.assignLocalRepo(this),this.origin.externalRefresh(),c.playRefreshAnimationAndFinish(this.gitVisuals,this.animationQueue)},this);var r=JSON.parse(unescape(e));u.each(r.branches,function(e,t){var n=e.target,r=this.makeBranch("o/"+t,this.getCommitFromRef(n));r.set("remote",!0)},this)},y.prototype.getOrMakeRecursive=function(e,t,n){if(t[n])return t[n];var r=function(e,t){if(e.commits[t])return"commit";if(e.branches[t])return"branch";if(t=="HEAD")return"HEAD";throw new Error("bad type for "+t)},i=r(e,n);if(i=="HEAD"){var s=e.HEAD,o=new b(u.extend(e.HEAD,{target:this.getOrMakeRecursive(e,t,s.target)}));return t[n]=o,o}if(i=="branch"){var a=e.branches[n],f=new w(u.extend(e.branches[n],{target:this.getOrMakeRecursive(e,t,a.target)}));return t[n]=f,f}if(i=="commit"){var l=e.commits[n],c=[];u.each(l.parents,function(n){c.push(this.getOrMakeRecursive(e,t,n))},this);var h=new E(u.extend(l,{parents:c,gitVisuals:this.gitVisuals}));return t[n]=h,h}throw new Error("ruh rho!! unsupported type for "+n)},y.prototype.tearDown=function(){this.eventBaton.releaseBaton("processGitCommand",this.dispatch,this),this.removeAll()},y.prototype.reloadGraphics=function(){this.gitVisuals.rootCommit=this.refs.C0,this.gitVisuals.initHeadBranch(),this.gitVisuals.drawTreeFromReload(),this.gitVisuals.refreshTreeHarsh()},y.prototype.removeAll=function(){this.branchCollection.reset(),this.commitCollection.reset(),this.refs={},this.HEAD=null,this.rootCommit=null,this.origin&&(this.origin.gitVisuals.getVisualization().tearDown(),delete this.origin,this.gitVisuals.getVisualization().clearOrigin()),this.gitVisuals.resetAll()},y.prototype.getDetachedHead=function(){var e=this.HEAD.get("target"),t=e.get("type");return t!=="branch"},y.prototype.validateBranchName=function(e){e=e.replace(/\s/g,"");if(!/^[a-zA-Z0-9]+$/.test(e))throw new v({msg:l.str("bad-branch-name",{branch:e})});if(/[hH][eE][aA][dD]/.test(e))throw new v({msg:l.str("bad-branch-name",{branch:e})});return e.length>9&&(e=e.slice(0,9),this.command.addWarning(l.str("branch-name-short",{branch:e}))),e},y.prototype.validateAndMakeBranch=function(e,t){e=this.validateBranchName(e);if(this.refs[e])throw new v({msg:l.str("bad-branch-name",{branch:name})});this.makeBranch(e,t)},y.prototype.makeBranch=function(e,t){var n=new w({target:t,id:e});return this.branchCollection.add(n),this.refs[n.get("id")]=n,n},y.prototype.getHead=function(){return u.clone(this.HEAD)},y.prototype.getBranches=function(){var e=[];return this.branchCollection.each(function(t){e.push({id:t.get("id"),selected:this.HEAD.get("target")===t,target:t.get("target"),remote:t.getIsRemote(),obj:t})},this),e},y.prototype.getRemoteBranches=function(){var e=this.getBranches();return u.filter(e,function(e){return e.remote===!0})},y.prototype.getLocalBranches=function(){var e=this.getBranches();return u.filter(e,function(e){return e.remote===!1})},y.prototype.printBranchesWithout=function(e){var t=this.getUpstreamBranchSet(),n=this.getCommitFromRef(e).get("id"),r=[];u.each(t[n],function(e){e.selected=this.HEAD.get("target").get("id")==e.id,r.push(e)},this),this.printBranches(r)},y.prototype.printBranches=function(e){var t="";throw u.each(e,function(e){t+=(e.selected?"* ":"")+e.id+"\n"}),new m({msg:t})},y.prototype.getUniqueID=function(){var e=this.uniqueId("C"),t=u.bind(function(e){return this.refs[e]?!0:this.origin&&this.origin.refs[e]?!0:!1},this);while(t(e))e=this.uniqueId("C");return e},y.prototype.makeCommit=function(e,t,n){t||(t=this.getUniqueID());var r=new E(u.extend({parents:e,id:t,gitVisuals:this.gitVisuals},n||{}));return this.refs[r.get("id")]=r,this.commitCollection.add(r),r},y.prototype.acceptNoGeneralArgs=function(){if(this.generalArgs.length)throw new v({msg:l.str("git-error-no-general-args")})},y.prototype.validateArgBounds=function(e,t,n,r){var i=r===undefined?"git "+this.command.get("method"):this.command.get("method")+" "+r+" ";i="with "+i;if(e.lengthn)throw new v({msg:l.str("git-error-args-many",{upper:String(n),what:i})})},y.prototype.oneArgImpliedHead=function(e,t){this.validateArgBounds(e,0,1,t),e.length===0&&e.push("HEAD")},y.prototype.twoArgsImpliedHead=function(e,t){this.validateArgBounds(e,1,2,t),e.length==1&&e.push("HEAD")},y.prototype.revertStarter=function(){this.validateArgBounds(this.generalArgs,1,NaN),this.revert(this.generalArgs)},y.prototype.revert=function(e){var t=u.map(e,function(e){return this.getCommitFromRef(e)},this),n=f.defer(),r=n.promise,i=this.resolveID("HEAD");r=c.highlightEachWithPromise(r,t,i);var s=this.getCommitFromRef("HEAD"),o=u.bind(function(e){var t=this.rebaseAltID(e.get("id")),n=l.str("git-revert-msg",{oldCommit:this.resolveName(e),oldMsg:e.get("commitMessage")}),r=this.makeCommit([s],t,{commitMessage:n});return s=r,c.playCommitBirthPromiseAnimation(r,this.gitVisuals)},this);u.each(t,function(e){r=r.then(function(){return o(e)})},this),r=r.then(u.bind(function(){return this.setTargetLocation("HEAD",s),c.playRefreshAnimation(this.gitVisuals)},this)),this.animationQueue.thenFinish(r,n)},y.prototype.resetStarter=function(){if(this.commandOptions["--soft"])throw new v({msg:l.str("git-error-staging")});this.commandOptions["--hard"]&&(this.command.addWarning(l.str("git-warning-hard")),this.generalArgs=this.generalArgs.concat(this.commandOptions["--hard"])),this.validateArgBounds(this.generalArgs,1,1);if(this.getDetachedHead())throw new v({msg:l.str("git-error-reset-detached")});this.reset(this.generalArgs[0])},y.prototype.reset=function(e){this.setTargetLocation("HEAD",this.getCommitFromRef(e))},y.prototype.cherrypickStarter=function(){this.validateArgBounds(this.generalArgs,1,Number.MAX_VALUE);var e=this.getUpstreamSet("HEAD"),t=u.map(this.generalArgs,function(t){var n=this.getCommitFromRef(t);if(e[n.get("id")])throw new v({msg:l.str("git-error-already-exists",{commit:n.get("id")})});return n},this),n=f.defer(),r=n.promise,i=this.resolveID("HEAD");r=c.highlightEachWithPromise(r,t,i);var s=u.bind(function(e){var t=this.cherrypick(e);return c.playCommitBirthPromiseAnimation(t,this.gitVisuals)},this);u.each(t,function(e){r=r.then(function(){return s(e)})},this),this.animationQueue.thenFinish(r,n)},y.prototype.checkUpstreamOfSource=function(e,t,n,r,i){var s=t.getUpstreamSet(r),o=e.getCommitFromRef(n).get("id");if(!s[o])throw new v({msg:i||l.str("git-error-origin-fetch-no-ff")})},y.prototype.getTargetGraphDifference=function(e,t,n,r,i){i=i||{},r=t.resolveID(r);var s=e.getUpstreamSet(n),o=t.getCommitFromRef(r),a=t.exportTree(),f=a.commits[o.get("id")];if(e.refs[f.id]){if(i.dontThrowOnNoFetch)return[];throw new v({msg:l.str("git-error-origin-fetch-uptodate")})}f.depth=0;var c=[],h=[f],p=function(e){if(s[e])return;var t=a.commits[e];t.depth=d.depth+1,h.push(t)};while(h.length){var d=h.pop();c.push(d),u.each(d.parents,p)}var m={},g=[];return u.forEach(c,function(e){if(m[e.id])return;m[e.id]=!0,g.push(e)}),g.sort(function(e,t){return t.depth-e.depth})},y.prototype.pushStarter=function(e){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.push()},y.prototype.push=function(e){e=e||{};var t=this.refs.master,n=this.origin.refs.master;this.checkUpstreamOfSource(this,this.origin,n,t,l.str("git-error-origin-push-no-ff"));var r=this.getTargetGraphDifference(this.origin,this,n,t),i=u.bind(function(e,t){var n=u.map(t,function(e){return this.origin.refs[e]},this);return this.origin.makeCommit(n,e)},this),s=u.bind(function(e,t){var n=i(e,t);return c.playCommitBirthPromiseAnimation(n,this.origin.gitVisuals)},this),o=f.defer(),a=o.promise;u.each(r,function(e){a=a.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.refs[e.id],n)},this)),a=a.then(function(){return s(e.id,e.parents)})},this),a=a.then(u.bind(function(){var e=t.get("target").get("id"),r=this.origin.refs[e];return this.origin.setTargetLocation(n,r),c.playRefreshAnimation(this.gitVisuals),c.playRefreshAnimation(this.origin.gitVisuals)},this)),a=a.then(u.bind(function(){var e=this.getCommitFromRef(t),n=t.getRemoteBranchIDFromTracking();return this.setTargetLocation(this.refs[n],e),c.playRefreshAnimation(this.gitVisuals)},this)),e.dontResolvePromise||this.animationQueue.thenFinish(a,o)},y.prototype.fetchStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.fetch()},y.prototype.fetch=function(e){e=e||{};var t=this.refs["o/master"],n=this.origin.refs.master;this.checkUpstreamOfSource(this,this.origin,t,n);var r=this.getTargetGraphDifference(this,this.origin,t,n,e);if(r.length===0){this.command.addWarning(l.str("git-error-origin-fetch-uptodate"));var i=f.defer();return{deferred:i,chain:i.promise}}var s=u.bind(function(e,t){var n=u.map(t,function(e){return this.refs[e]},this);return this.makeCommit(n,e)},this),o=u.bind(function(e,t){var n=s(e,t);return c.playCommitBirthPromiseAnimation(n,this.gitVisuals)},this),a=f.defer(),h=a.promise;return u.each(r,function(e){h=h.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.origin.refs[e.id],t)},this)),h=h.then(function(){return o(e.id,e.parents)})},this),h=h.then(u.bind(function(){var e=n.get("target").get("id"),r=this.refs[e];return this.setTargetLocation(t,r),c.playRefreshAnimation(this.origin.gitVisuals),c.playRefreshAnimation(this.gitVisuals)},this)),e.dontResolvePromise||this.animationQueue.thenFinish(h,a),{chain:h,deferred:a}},y.prototype.pullStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.pull()},y.prototype.pull=function(){var e=this.refs.master,t=this.refs["o/master"],n=this.fetch({dontResolvePromise:!0,dontThrowOnNoFetch:!0});this.commandOptions["--rebase"]?this.pullFinishWithRebase(n,e,t):this.pullFinishWithMerge(n,e,t)},y.prototype.pullFinishWithRebase=function(e,t,n){var r=e.chain,i=e.deferred;r=r.then(function(){return c.getDelayedPromise(300)}),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(n),t)},this)),r=r.then(u.bind(function(){return e.dontResolvePromise=!0,this.rebase(n,t,e)},this)),this.animationQueue.thenFinish(r,i)},y.prototype.pullFinishWithMerge=function(e,t,n){var r=e.chain,i=e.deferred;r=r.then(function(){return c.getDelayedPromise(300)}),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(n),t)},this)),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(t),n)},this)),r=r.then(function(){return c.getDelayedPromise(700)}),r=r.then(u.bind(function(){var e=this.merge("o/master");return e?c.playCommitBirthPromiseAnimation(e,this.gitVisuals):c.playRefreshAnimation(this.gitVisuals)},this)),this.animationQueue.thenFinish(r,i)},y.prototype.cloneStarter=function(){this.acceptNoGeneralArgs(),this.makeOrigin(this.printTree())},y.prototype.fakeTeamworkStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.validateArgBounds(this.generalArgs,0,2);var e=this.generalArgs[0]||"master",t=this.generalArgs[1]||1,n=this.origin.resolveID(e);if(n.get("type")!=="branch")throw new v({msg:l.str("git-error-options")});this.fakeTeamwork(t,e)},y.prototype.fakeTeamwork=function(e,t){var n=u.bind(function(){var e=this.getUniqueID();return this.origin.receiveTeamwork(e,t,this.animationQueue)},this),r=u.bind(function(){var e=n();return c.playCommitBirthPromiseAnimation(e,this.origin.gitVisuals)},this),i=function(){return r()},s=f.defer(),o=s.promise;u.each(u.range(e),function(e){o=o.then(function(){return r()})}),this.animationQueue.thenFinish(o,s)},y.prototype.receiveTeamwork=function(e,t,n){this.checkout(this.resolveID(t));var r=this.makeCommit([this.getCommitFromRef("HEAD")],e);return this.setTargetLocation(this.HEAD,r),r},y.prototype.cherrypick=function(e){var t=this.rebaseAltID(e.get("id")),n=this.makeCommit([this.getCommitFromRef("HEAD")],t);return this.setTargetLocation(this.HEAD,n),n},y.prototype.commitStarter=function(){this.acceptNoGeneralArgs();if(this.commandOptions["-am"]&&(this.commandOptions["-a"]||this.commandOptions["-m"]))throw new v({msg:l.str("git-error-options")});var e=null,t=null;this.commandOptions["-a"]&&this.command.addWarning(l.str("git-warning-add")),this.commandOptions["-am"]&&(t=this.commandOptions["-am"],this.validateArgBounds(t,1,1,"-am"),e=t[0]),this.commandOptions["-m"]&&(t=this.commandOptions["-m"],this.validateArgBounds(t,1,1,"-m"),e=t[0]);var n=this.commit();e&&(e=e.replace(/"/g,'"').replace(/^"/g,"").replace(/"$/g,""),n.set("commitMessage",e));var r=c.playCommitBirthPromiseAnimation(n,this.gitVisuals);this.animationQueue.thenFinish(r)},y.prototype.commit=function(){var e=this.getCommitFromRef(this.HEAD),t=null;this.commandOptions["--amend"]&&(e=this.resolveID("HEAD~1"),t=this.rebaseAltID(this.getCommitFromRef("HEAD").get("id")));var n=this.makeCommit([e],t);return this.getDetachedHead()&&this.command.addWarning(l.str("git-warning-detached")),this.setTargetLocation(this.HEAD,n),n},y.prototype.resolveName=function(e){var t=this.resolveID(e);return t.get("type")=="commit"?"commit "+t.get("id"):t.get("type")=="branch"?'branch "'+t.get("id")+'"':this.resolveName(t.get("target"))},y.prototype.resolveID=function(e){if(e===null||e===undefined)throw new Error("Dont call this with null / undefined");return typeof e!="string"?e:this.resolveStringRef(e)},y.prototype.resolveRelativeRef=function(e,t){var n=/([~\^])(\d*)/g,r;while(r=n.exec(t)){var i=e,s=r[2]?parseInt(r[2],10):1;if(r[1]=="^")i=e.getParent(s-1);else while(i&&s--)i=i.getParent(0);if(!i){var o=l.str("git-error-relative-ref",{commit:e.id,match:r[0]});throw new v({msg:o})}e=i}return e},y.prototype.resolveStringRef=function(e){e=this.crappyUnescape(e);if(this.refs[e])return this.refs[e];var t=null,n=null,r=/^([a-zA-Z0-9]+)(([~\^]\d*)*)/,i=r.exec(e);if(!i)throw new v({msg:l.str("git-error-exist",{ref:e})});t=i[1],n=i[2];if(!this.refs[t])throw new v({msg:l.str("git-error-exist",{ref:e})});var s=this.getCommitFromRef(t);return n&&(s=this.resolveRelativeRef(s,n)),s},y.prototype.getCommitFromRef=function(e){var t=this.resolveID(e);while(t.get("type")!=="commit")t=t.get("target");return t},y.prototype.getType=function(e){return this.resolveID(e).get("type")},y.prototype.setTargetLocation=function(e,t){if(this.getType(e)=="commit")return;e=this.getOneBeforeCommit(e),e.set("target",t)},y.prototype.getUpstreamBranchSet=function(){var e={},t=function(e,t){var n=!1;return u.each(e,function(e){e.id==t&&(n=!0)}),n},n=function(e){var t=[],n=[e];while(n.length){var r=n.pop();t.push(r.get("id")),r.get("parents")&&r.get("parents").length&&(n=n.concat(r.get("parents")))}return t};return this.branchCollection.each(function(r){var i=n(r.get("target"));u.each(i,function(n){e[n]=e[n]||[],t(e[n],r.get("id"))||e[n].push({obj:r,id:r.get("id")})})}),e},y.prototype.getUpstreamHeadSet=function(){var e=this.getUpstreamSet("HEAD"),t=this.getCommitFromRef("HEAD").get("id");return e[t]=!0,e},y.prototype.getOneBeforeCommit=function(e){var t=this.resolveID(e);return t===this.HEAD&&!this.getDetachedHead()&&(t=t.get("target")),t},y.prototype.scrapeBaseID=function(e){var t=/^C(\d+)/.exec(e);if(!t)throw new Error("regex failed on "+e);return"C"+t[1]},y.prototype.rebaseAltID=function(e){var t=[[/^C(\d+)[']{0,2}$/,function(e){return e[0]+"'"}],[/^C(\d+)[']{3}$/,function(e){return e[0].slice(0,-3)+"'^4"}],[/^C(\d+)['][\^](\d+)$/,function(e){return"C"+String(e[1])+"'^"+String(Number(e[2])+1)}]];for(var n=0;n",this.get("commitMessage"),"
","Commit: "+this.get("id")].join("\n")+"\n"},getShowEntry:function(){return[this.getLogEntry(),"diff --git a/bigGameResults.html b/bigGameResults.html","--- bigGameResults.html","+++ bigGameResults.html","@@ 13,27 @@ Winner, Score","- Stanfurd, 14-7","+ Cal, 21-14"].join("\n")+"\n"},validateAtInit:function(){if(!this.get("id"))throw new Error("Need ID!!");this.get("createTime")||this.set("createTime",(new Date).toString()),this.get("commitMessage")||this.set("commitMessage",l.str("git-dummy-msg")),this.set("children",[]);if(!this.get("rootCommit"))if(!this.get("parents")||!this.get("parents").length)throw new Error("needs parents")},addNodeToVisuals:function(){var e=this.get("gitVisuals").addNode(this.get("id"),this);this.set("visNode",e)},addEdgeToVisuals:function(e){this.get("gitVisuals").addEdge(this.get("id"),e.get("id"))},getParent:function(e){return this&&this.attributes&&this.attributes.parents?this.attributes.parents[e]:null},isMainParent:function(e){var t=this.get("parents").indexOf(e);return t===0},initialize:function(e){this.validateAtInit(),this.addNodeToVisuals(),u.each(this.get("parents"),function(e){e.get("children").push(this),this.addEdgeToVisuals(e)},this)}});n.GitEngine=y,n.Commit=E,n.Branch=w,n.Ref=b}),e.define("/src/js/visuals/animation/animationFactory.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("./index").Animation,c=e("./index").PromiseAnimation,h=e("../../util/constants").GRAPHICS,p={},d=function(e,t){var n=h.defaultAnimationTime*1,r=n*2,i=function(){e.refreshTree(n),t.setBirth(),t.parentInFront(),e.visBranchesFront(),t.animateUpdatedPosition(r,"bounce"),t.animateOutgoingEdges(n)};return{animation:i,duration:Math.max(n,r)}},v=function(e,t){var n=h.defaultAnimationTime*.66,r=n*2;return{animation:function(){e.highlightTo(t,r,"easeInOut")},duration:r*1.5}};p.genCommitBirthAnimation=function(e,t,n){if(!e)throw new Error("Need animation queue to add closure to!");var r=t.get("visNode"),i=d(n,r);e.add(new l({closure:i.animation,duration:i.duration}))},p.genCommitBirthPromiseAnimation=function(e,t){var n=e.get("visNode");return new c(d(t,n))},p.highlightEachWithPromise=function(e,t,n){return u.each(t,function(t){e=e.then(u.bind(function(){return this.playHighlightPromiseAnimation(t,n)},this))},this),e},p.playCommitBirthPromiseAnimation=function(e,t){var n=this.genCommitBirthPromiseAnimation(e,t);return n.play(),n.getPromise()},p.playRefreshAnimationAndFinish=function(e,t){var n=new c({closure:function(){e.refreshTree()}});n.play(),t.thenFinish(n.getPromise())},p.playRefreshAnimation=function(e){var t=new c({closure:function(){e.refreshTree()}});return t.play(),t.getPromise()},p.refreshTree=function(e,t){e.add(new l({closure:function(){t.refreshTree()}}))},p.genHighlightPromiseAnimation=function(e,t){var n=t.get("visBranch")||t.get("visNode"),r=e.get("visNode");return new c(v(r,n))},p.playHighlightPromiseAnimation=function(e,t){var n=this.genHighlightPromiseAnimation(e,t);return n.play(),n.getPromise()},p.getDelayedPromise=function(e){var t=f.defer();return setTimeout(t.resolve,e||1e3),t.promise},p.delay=function(e,t){t=t||h.defaultAnimationTime,e.add(new l({closure:function(){},duration:t}))},n.AnimationFactory=p}),e.define("/src/js/visuals/animation/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("backbone"),l=e("../../util/constants").GLOBAL,c=f.Model.extend({defaults:{duration:300,closure:null},validateAtInit:function(){if(!this.get("closure"))throw new Error("give me a closure!")},initialize:function(e){this.validateAtInit()},run:function(){this.get("closure")()}}),h=f.Model.extend({defaults:{animations:null,index:0,callback:null,defer:!1,promiseBased:!1},initialize:function(e){this.set("animations",[]),e.callback||console.warn("no callback")},thenFinish:function(e,t){e.then(u.bind(function(){this.finish()},this)),this.set("promiseBased",!0),t&&t.resolve()},add:function(e){if(!e instanceof c)throw new Error("Need animation not something else");this.get("animations").push(e)},start:function(){this.set("index",0),l.isAnimating=!0,this.next()},finish:function(){l.isAnimating=!1,this.get("callback")()},next:function(){var e=this.get("animations"),t=this.get("index");if(t>=e.length){this.finish();return}var n=e[t],r=n.get("duration");n.run(),this.set("index",t+1),setTimeout(u.bind(function(){this.next()},this),r)}}),p=f.Model.extend({defaults:{deferred:null,closure:null,duration:300},initialize:function(e){if(!e.closure&&!e.animation)throw new Error("need closure or animation");this.set("closure",e.closure||e.animation),this.set("deferred",e.deferred||a.defer())},getPromise:function(){return this.get("deferred").promise},play:function(){this.get("closure")(),setTimeout(u.bind(function(){this.get("deferred").resolve()},this),this.get("duration"))},then:function(e){return this.get("deferred").promise.then(e)}});p.fromAnimation=function(e){return new p({closure:e.get("closure"),duration:e.get("duration")})},n.Animation=c,n.PromiseAnimation=p,n.AnimationQueue=h}),e.define("/src/js/git/treeCompare.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a={};a.dispatchFromLevel=function(e,t){var n=e.goalTreeString;return a.dispatch(e,n,t)},a.dispatch=function(e,t,n){var r=!0;switch(r){case!!e.compareOnlyMaster:return a.compareBranchWithinTrees(n,t,"master");case!!e.compareOnlyBranches:return a.compareAllBranchesWithinTrees(n,t);case!!e.compareAllBranchesHashAgnostic:return a.compareAllBranchesWithinTreesHashAgnostic(n,t);case!!e.compareOnlyMasterHashAgnostic:return a.compareBranchesWithinTreesHashAgnostic(n,t,["master"]);case!!e.compareOnlyMasterHashAgnosticWithAsserts:return a.compareBranchesWithinTreesHashAgnostic(n,t,["master"])&&a.evalAsserts(n,e.goalAsserts);default:return a.compareAllBranchesWithinTreesAndHEAD(n,t)}},a.compareAllBranchesWithinTreesAndHEAD=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t);debugger;return e.HEAD.target==t.HEAD.target&&this.compareAllBranchesWithinTrees(e,t)},a.compareAllBranchesWithinTrees=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t);var n=u.extend({},e.branches,t.branches),r=!0;return u.uniq(n,function(n,i){r=r&&this.compareBranchWithinTrees(e,t,i)},this),r},a.compareBranchesWithinTrees=function(e,t,n){var r=!0;return u.each(n,function(n){r=r&&this.compareBranchWithinTrees(e,t,n)},this),r},a.compareBranchWithinTrees=function(e,t,n){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var r=this.getRecurseCompare(e,t),i=e.branches[n],s=t.branches[n];return u.isEqual(i,s)&&r(e.commits[i.target],t.commits[s.target])},a.compareAllBranchesWithinTreesHashAgnostic=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var n=u.extend({},e.branches,t.branches),r=[];return u.each(n,function(e,t){r.push(t)}),this.compareBranchesWithinTreesHashAgnostic(e,t,r)},a.compareBranchesWithinTreesHashAgnostic=function(e,t,n){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var r=u.bind(function(e,t){return!e||!t?!1:(e=u.clone(e),t=u.clone(t),e.target=this.getBaseRef(e.target),t.target=this.getBaseRef(t.target),u.isEqual(e,t))},this),i=this.getRecurseCompareHashAgnostic(e,t),s=!0;return u.each(n,function(n){var o=e.branches[n],u=t.branches[n];s=s&&r(o,u)&&i(e.commits[o.target],t.commits[u.target])},this),s},a.evalAsserts=function(e,t){var n=!0;return u.each(t,function(t,r){n=n&&this.evalAssertsOnBranch(e,r,t)},this),n},a.evalAssertsOnBranch=function(e,t,n){e=this.convertTreeSafe(e);if(!e.branches[t])return!1;var r=e.branches[t],i=[r.target],s={};while(i.length){var o=i.pop();s[this.getBaseRef(o)]=this.getNumHashes(o),i=i.concat(e.commits[o].parents)}var a=!0;return u.each(n,function(e){try{a=a&&e(s)}catch(t){console.warn("error during assert",t),console.log(t),a=!1}}),a},a.getNumHashes=function(e){var t=[[/^C(\d+)([']{0,3})$/,function(e){return e[2]?e[2].length:0}],[/^C(\d+)['][\^](\d+)$/,function(e){return Number(e[2])}]];for(var n=0;np.VIEWPORT.minWidth&&e.h>p.VIEWPORT.minHeight&&this.finish()}}),O=L.extend({initialize:function(e){if(!e||!e.level)throw new Error("need level");this.eventBatonName="zoomChange",this.markdowns=["## That zoom level of "+e.level+" is not supported :-/","Please zoom back to a supported zoom level with Ctrl + and Ctrl -","","(and of course, pull requests to fix this are appreciated :D)"],O.__super__.initialize.apply(this,[e])},batonFired:function(e){e<=p.VIEWPORT.maxZoom&&e>=p.VIEWPORT.minZoom&&this.finish()}}),M=m.extend({tagName:"div",className:"levelToolbarHolder",template:u.template($("#level-toolbar-template").html()),initialize:function(e){e=e||{},this.JSON={name:e.name||"Some level! (unknown name)"},this.beforeDestination=$($("#commandLineHistory div.toolbar")[0]),this.render(),e.wait||s.nextTick(u.bind(this.show,this))},getAnimationTime:function(){return 700},render:function(){var e=this.template(this.JSON);this.$el.html(e),this.beforeDestination.after(this.el)},die:function(){this.hide(),setTimeout(u.bind(function(){this.tearDown()},this),this.getAnimationTime())},hide:function(){this.$("div.toolbar").toggleClass("hidden",!0)},show:function(){this.$("div.toolbar").toggleClass("hidden",!1)}}),_=m.extend({tagName:"div",className:"helperBar transitionAll",template:u.template($("#helper-bar-template").html()),events:{"click a":"onClick"},onClick:function(e){var t=e.target,n=$(t).attr("data-id"),r="on"+n[0].toUpperCase()+n.slice(1)+"Click";this[r].call(this)},show:function(){this.$el.toggleClass("show",!0)},hide:function(){this.$el.toggleClass("show",!1),this.deferred&&this.deferred.resolve()},getItems:function(){return[]},setupChildren:function(){},fireCommand:function(e){l.getEventBaton().trigger("commandSubmitted",e)},showDeferMe:function(e){this.hide();var t=a.defer();e.deferred=t,t.promise.then(u.bind(function(){this.show()},this)),e.show()},onExitClick:function(){this.hide()},initialize:function(e){e=e||{},this.destination=$("body"),this.JSON={items:this.getItems()},this.render(),this.setupChildren(),e.wait||this.show()}}),D=_.extend({getItems:function(){return[{text:"Git Branching",id:"english"},{text:"日本語版リポジトリ",id:"japanese"},{text:"Git 브랜치 배우기",id:"korean"},{text:"学习Git分支",id:"chinese"},{text:"français",id:"french"},{icon:"signout",id:"exit"}]},fireCommand:function(){h.viewInteracted("intlSelect"),_.prototype.fireCommand.apply(this,arguments)},onJapaneseClick:function(){this.fireCommand("locale ja; levels"),this.hide()},onEnglishClick:function(){this.fireCommand("locale en_US; levels"),this.hide()},onKoreanClick:function(){this.fireCommand("locale ko; levels"),this.hide()},onFrenchClick:function(){this.fireCommand("locale fr_FR; levels"),this.hide()},onChineseClick:function(){this.fireCommand("locale zh_CN; levels"),this.hide()}}),P=_.extend({getItems:function(){return[{text:"Levels",id:"levels"},{text:"Reset",id:"reset"},{text:"Undo",id:"undo"},{text:"Objective",id:"objectve"},{text:"Help",id:"help"},{icon:"signout",id:"exit"}]},fireCommand:function(){h.viewInteracted("helperBar"),_.prototype.fireCommand.apply(this,arguments)},onObjectiveClick:function(){this.fireCommand("objective")},onLevelsClick:function(){this.fireCommand("levels")},onResetClick:function(){this.fireCommand("reset")},onUndoClick:function(){this.fireCommand("undo")},onHelpClick:function(){this.fireCommand("help general; git help")}}),H=_.extend({getItems:function(){return[{icon:"question-sign",id:"commands"},{icon:"globe",id:"intl"}]},onIntlClick:function(){this.showDeferMe(this.intlHelper),h.viewInteracted("openIntlBar")},onCommandsClick:function(){this.showDeferMe(this.commandsHelper),h.viewInteracted("openCommandsBar")},setupChildren:function(){this.commandsHelper=new P({wait:!0}),this.intlHelper=new D({wait:!0})}}),B=m.extend({tagName:"div",className:"canvasTerminalHolder box flex1",template:u.template($("#terminal-window-bare-template").html()),events:{"click div.wrapper":"onClick"},initialize:function(e){e=e||{},this.destination=$("body"),this.JSON={title:e.title||c.str("goal-to-reach"),text:e.text||c.str("hide-goal")},this.render(),this.inDom=!0,e.additionalClass&&this.$el.addClass(e.additionalClass)},getAnimationTime:function(){return 700},onClick:function(){this.die()},die:function(){this.slideOut(),this.inDom=!1,setTimeout(u.bind(function(){this.tearDown()},this),this.getAnimationTime())},slideOut:function(){this.slideToggle(!0)},slideIn:function(){this.slideToggle(!1)},slideToggle:function(e){this.$("div.terminal-window-holder").toggleClass("slideOut",e)},getCanvasLocation:function(){return this.$("div.inside")[0]}});n.BaseView=m,n.GeneralButton=w,n.ModalView=x,n.ModalTerminal=T,n.ModalAlert=N,n.ContainedBase=b,n.ConfirmCancelView=E,n.LeftRightView=S,n.ZoomAlertWindow=O,n.ConfirmCancelTerminal=C,n.WindowSizeAlertWindow=A,n.MainHelperBar=H,n.CanvasTerminalHolder=B,n.LevelToolbar=M,n.NextLevelConfirm=k}),e.define("/src/js/util/keyboard.js",function(e,t,n,r,i,s,o){function c(e){this.events=e.events||u.clone(a.Events),this.aliasMap=e.aliasMap||{},e.wait||this.listen()}var u=e("underscore"),a=e("backbone"),f=e("../app"),l=function(e){var t={37:"left",38:"up",39:"right",40:"down",27:"esc",13:"enter"};return t[e]};c.prototype.listen=function(){if(this.listening)return;this.listening=!0,f.getEventBaton().stealBaton("docKeydown",this.keydown,this)},c.prototype.mute=function(){this.listening=!1,f.getEventBaton().releaseBaton("docKeydown",this.keydown,this)},c.prototype.keydown=function(e){var t=e.which||e.keyCode,n=l(t);if(n===undefined)return;this.fireEvent(n,e)},c.prototype.fireEvent=function(e,t){e=this.aliasMap[e]||e,this.events.trigger(e,t)},c.prototype.passEventBack=function(e){f.getEventBaton().passBatonBackSoft("docKeydown",this.keydown,this,[e])},n.KeyboardListener=c,n.mapKeycodeToKey=l}),e.define("/node_modules/markdown/package.json",function(e,t,n,r,i,s,o){t.exports={main:"./lib/index.js"}}),e.define("/node_modules/markdown/lib/index.js",function(e,t,n,r,i,s,o){n.markdown=e("./markdown"),n.parse=n.markdown.toHTML}),e.define("/node_modules/markdown/lib/markdown.js",function(e,t,n,r,i,s,o){(function(t){function r(){return"Markdown.mk_block( "+uneval(this.toString())+", "+uneval(this.trailing)+", "+uneval(this.lineNumber)+" )"}function i(){var t=e("util");return"Markdown.mk_block( "+t.inspect(this.toString())+", "+t.inspect(this.trailing)+", "+t.inspect(this.lineNumber)+" )"}function o(e){var t=0,n=-1;while((n=e.indexOf("\n",n+1))!==-1)t++;return t}function u(e,t){function i(e){this.len_after=e,this.name="close_"+t}var n=e+"_state",r=e=="strong"?"em_state":"strong_state";return function(s,o){if(this[n][0]==t)return this[n].shift(),[s.length,new i(s.length-t.length)];var u=this[r].slice(),a=this[n].slice();this[n].unshift(t);var f=this.processInline(s.substr(t.length)),l=f[f.length-1],c=this[n].shift();if(l instanceof i){f.pop();var h=s.length-l.len_after;return[h,[e].concat(f)]}return this[r]=u,this[n]=a,[t.length,t]}}function f(e){var t=e.split(""),n=[""],r=!1;while(t.length){var i=t.shift();switch(i){case" ":r?n[n.length-1]+=i:n.push("");break;case"'":case'"':r=!r;break;case"\\":i=t.shift();default:n[n.length-1]+=i}}return n}function h(e){return l(e)&&e.length>1&&typeof e[1]=="object"&&!l(e[1])?e[1]:undefined}function d(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function v(e){if(typeof e=="string")return d(e);var t=e.shift(),n={},r=[];e.length&&typeof e[0]=="object"&&!(e[0]instanceof Array)&&(n=e.shift());while(e.length)r.push(arguments.callee(e.shift()));var i="";for(var s in n)i+=" "+s+'="'+d(n[s])+'"';return t=="img"||t=="br"||t=="hr"?"<"+t+i+"/>":"<"+t+i+">"+r.join("")+""}function m(e,t,n){var r;n=n||{};var i=e.slice(0);typeof n.preprocessTreeNode=="function"&&(i=n.preprocessTreeNode(i,t));var s=h(i);if(s){i[1]={};for(r in s)i[1][r]=s[r];s=i[1]}if(typeof i=="string")return i;switch(i[0]){case"header":i[0]="h"+i[1].level,delete i[1].level;break;case"bulletlist":i[0]="ul";break;case"numberlist":i[0]="ol";break;case"listitem":i[0]="li";break;case"para":i[0]="p";break;case"markdown":i[0]="html",s&&delete s.references;break;case"code_block":i[0]="pre",r=s?2:1;var o=["code"];o.push.apply(o,i.splice(r)),i[r]=o;break;case"inlinecode":i[0]="code";break;case"img":i[1].src=i[1].href,delete i[1].href;break;case"linebreak":i[0]="br";break;case"link":i[0]="a";break;case"link_ref":i[0]="a";var u=t[s.ref];if(!u)return s.original;delete s.ref,s.href=u.href,u.title&&(s.title=u.title),delete s.original;break;case"img_ref":i[0]="img";var u=t[s.ref];if(!u)return s.original;delete s.ref,s.src=u.href,u.title&&(s.title=u.title),delete s.original}r=1;if(s){for(var a in i[1])r=2;r===1&&i.splice(r,1)}for(;r0&&!l(o[0]))&&this.debug(i[s],"didn't return a proper array"),o}return[]},n.prototype.processInline=function(t){return this.dialect.inline.__call__.call(this,String(t))},n.prototype.toTree=function(t,n){var r=t instanceof Array?t:this.split_blocks(t),i=this.tree;try{this.tree=n||this.tree||["markdown"];e:while(r.length){var s=this.processBlock(r.shift(),r);if(!s.length)continue e;this.tree.push.apply(this.tree,s)}return this.tree}finally{n&&(this.tree=i)}},n.prototype.debug=function(){var e=Array.prototype.slice.call(arguments);e.unshift(this.debug_indent),typeof print!="undefined"&&print.apply(print,e),typeof console!="undefined"&&typeof console.log!="undefined"&&console.log.apply(null,e)},n.prototype.loop_re_over_block=function(e,t,n){var r,i=t.valueOf();while(i.length&&(r=e.exec(i))!=null)i=i.substr(r[0].length),n.call(this,r);return i},n.dialects={},n.dialects.Gruber={block:{atxHeader:function(t,n){var r=t.match(/^(#{1,6})\s*(.*?)\s*#*\s*(?:\n|$)/);if(!r)return undefined;var i=["header",{level:r[1].length}];return Array.prototype.push.apply(i,this.processInline(r[2])),r[0].length1&&n.unshift(r);for(var s=0;s1&&typeof i[i.length-1]=="string"?i[i.length-1]+=o:i.push(o)}}function f(e,t){var n=new RegExp("^("+i+"{"+e+"}.*?\\n?)*$"),r=new RegExp("^"+i+"{"+e+"}","gm"),o=[];while(t.length>0){if(n.exec(t[0])){var u=t.shift(),a=u.replace(r,"");o.push(s(a,u.trailing,u.lineNumber))}break}return o}function l(e,t,n){var r=e.list,i=r[r.length-1];if(i[1]instanceof Array&&i[1][0]=="para")return;if(t+1==n.length)i.push(["para"].concat(i.splice(1)));else{var s=i.pop();i.push(["para"].concat(i.splice(1)),s)}}var e="[*+-]|\\d+\\.",t=/[*+-]/,n=/\d+\./,r=new RegExp("^( {0,3})("+e+")[ ]+"),i="(?: {0,3}\\t| {4})";return function(e,n){function s(e){var n=t.exec(e[2])?["bulletlist"]:["numberlist"];return h.push({list:n,indent:e[1]}),n}var i=e.match(r);if(!i)return undefined;var h=[],p=s(i),d,v=!1,m=[h[0].list],g;e:for(;;){var y=e.split(/(?=\n)/),b="";for(var w=0;wh.length)p=s(i),d.push(p),d=p[1]=["listitem"];else{var N=!1;for(g=0;gi[0].length&&(b+=E+S.substr(i[0].length))}b.length&&(a(d,v,this.processInline(b),E),v=!1,b="");var C=f(h.length,n);C.length>0&&(c(h,l,this),d.push.apply(d,this.toTree(C,[])));var k=n[0]&&n[0].valueOf()||"";if(k.match(r)||k.match(/^ /)){e=n.shift();var L=this.dialect.block.horizRule(e,n);if(L){m.push.apply(m,L);break}c(h,l,this),v=!0;continue e}break}return m}}(),blockquote:function(t,n){if(!t.match(/^>/m))return undefined;var r=[];if(t[0]!=">"){var i=t.split(/\n/),s=[];while(i.length&&i[0][0]!=">")s.push(i.shift());t=i.join("\n"),r.push.apply(r,this.processBlock(s.join("\n"),[]))}while(n.length&&n[0][0]==">"){var o=n.shift();t=new String(t+t.trailing+o),t.trailing=o.trailing}var u=t.replace(/^> ?/gm,""),a=this.tree;return r.push(this.toTree(u,["blockquote"])),r},referenceDefn:function(t,n){var r=/^\s*\[(.*?)\]:\s*(\S+)(?:\s+(?:(['"])(.*?)\3|\((.*?)\)))?\n?/;if(!t.match(r))return undefined;h(this.tree)||this.tree.splice(1,0,{});var i=h(this.tree);i.references===undefined&&(i.references={});var o=this.loop_re_over_block(r,t,function(e){e[2]&&e[2][0]=="<"&&e[2][e[2].length-1]==">"&&(e[2]=e[2].substring(1,e[2].length-1));var t=i.references[e[1].toLowerCase()]={href:e[2]};e[4]!==undefined?t.title=e[4]:e[5]!==undefined&&(t.title=e[5])});return o.length&&n.unshift(s(o,t.trailing)),[]},para:function(t,n){return[["para"].concat(this.processInline(t))]}}},n.dialects.Gruber.inline={__oneElement__:function(t,n,r){var i,s,o=0;n=n||this.dialect.inline.__patterns__;var u=new RegExp("([\\s\\S]*?)("+(n.source||n)+")");i=u.exec(t);if(!i)return[t.length,t];if(i[1])return[i[1].length,i[1]];var s;return i[2]in this.dialect.inline&&(s=this.dialect.inline[i[2]].call(this,t.substr(i.index),i,r||[])),s=s||[i[2].length,i[2]],s},__call__:function(t,n){function s(e){typeof e=="string"&&typeof r[r.length-1]=="string"?r[r.length-1]+=e:r.push(e)}var r=[],i;while(t.length>0)i=this.dialect.inline.__oneElement__.call(this,t,n,r),t=t.substr(i.shift()),c(i,s);return r},"]":function(){},"}":function(){},"\\":function(t){return t.match(/^\\[\\`\*_{}\[\]()#\+.!\-]/)?[2,t[1]]:[1,"\\"]},"![":function(t){var n=t.match(/^!\[(.*?)\][ \t]*\([ \t]*(\S*)(?:[ \t]+(["'])(.*?)\3)?[ \t]*\)/);if(n){n[2]&&n[2][0]=="<"&&n[2][n[2].length-1]==">"&&(n[2]=n[2].substring(1,n[2].length-1)),n[2]=this.dialect.inline.__call__.call(this,n[2],/\\/)[0];var r={alt:n[1],href:n[2]||""};return n[4]!==undefined&&(r.title=n[4]),[n[0].length,["img",r]]}return n=t.match(/^!\[(.*?)\][ \t]*\[(.*?)\]/),n?[n[0].length,["img_ref",{alt:n[1],ref:n[2].toLowerCase(),original:n[0]}]]:[2,"!["]},"[":function b(e){var t=String(e),r=n.DialectHelpers.inline_until_char.call(this,e.substr(1),"]");if(!r)return[1,"["];var i=1+r[0],s=r[1],b,o;e=e.substr(i);var u=e.match(/^\s*\([ \t]*(\S+)(?:[ \t]+(["'])(.*?)\2)?[ \t]*\)/);if(u){var a=u[1];i+=u[0].length,a&&a[0]=="<"&&a[a.length-1]==">"&&(a=a.substring(1,a.length-1));if(!u[3]){var f=1;for(var l=0;l]+)|(.*?@.*?\.[a-zA-Z]+))>/))!=null?n[3]?[n[0].length,["link",{href:"mailto:"+n[3]},n[3]]]:n[2]=="mailto"?[n[0].length,["link",{href:n[1]},n[1].substr("mailto:".length)]]:[n[0].length,["link",{href:n[1]},n[1]]]:[1,"<"]},"`":function(t){var n=t.match(/(`+)(([\s\S]*?)\1)/);return n&&n[2]?[n[1].length+n[2].length,["inlinecode",n[3]]]:[1,"`"]}," \n":function(t){return[3,["linebreak"]]}},n.dialects.Gruber.inline["**"]=u("strong","**"),n.dialects.Gruber.inline.__=u("strong","__"),n.dialects.Gruber.inline["*"]=u("em","*"),n.dialects.Gruber.inline._=u("em","_"),n.buildBlockOrder=function(e){var t=[];for(var n in e){if(n=="__order__"||n=="__call__")continue;t.push(n)}e.__order__=t},n.buildInlinePatterns=function(e){var t=[];for(var n in e){if(n.match(/^__.*__$/))continue;var r=n.replace(/([\\.*+?|()\[\]{}])/g,"\\$1").replace(/\n/,"\\n");t.push(n.length==1?r:"(?:"+r+")")}t=t.join("|"),e.__patterns__=t;var i=e.__call__;e.__call__=function(e,n){return n!=undefined?i.call(this,e,n):i.call(this,e,t)}},n.DialectHelpers={},n.DialectHelpers.inline_until_char=function(e,t){var n=0,r=[];for(;;){if(e[n]==t)return n++,[n,r];if(n>=e.length)return null;res=this.dialect.inline.__oneElement__.call(this,e.substr(n)),n+=res[0],r.push.apply(r,res.slice(1))}},n.subclassDialect=function(e){function t(){}function n(){}return t.prototype=e.block,n.prototype=e.inline,{block:new t,inline:new n}},n.buildBlockOrder(n.dialects.Gruber.block),n.buildInlinePatterns(n.dialects.Gruber.inline),n.dialects.Maruku=n.subclassDialect(n.dialects.Gruber),n.dialects.Maruku.processMetaHash=function(t){var n=f(t),r={};for(var i=0;i1)return undefined;if(!t.match(/^(?:\w+:.*\n)*\w+:.*$/))return undefined;h(this.tree)||this.tree.splice(1,0,{});var r=t.split(/\n/);for(p in r){var i=r[p].match(/(\w+):\s*(.*)$/),s=i[1].toLowerCase(),o=i[2];this.tree[1][s]=o}return[]},n.dialects.Maruku.block.block_meta=function(t,n){var r=t.match(/(^|\n) {0,3}\{:\s*((?:\\\}|[^\}])*)\s*\}$/);if(!r)return undefined;var i=this.dialect.processMetaHash(r[2]),s;if(r[1]===""){var o=this.tree[this.tree.length-1];s=h(o);if(typeof o=="string")return undefined;s||(s={},o.splice(1,0,s));for(a in i)s[a]=i[a];return[]}var u=t.replace(/\n.*$/,""),f=this.processBlock(u,[]);s=h(f[0]),s||(s={},f[0].splice(1,0,s));for(a in i)s[a]=i[a];return f},n.dialects.Maruku.block.definition_list=function(t,n){var r=/^((?:[^\s:].*\n)+):\s+([\s\S]+)$/,i=["dl"],s;if(!(a=t.match(r)))return undefined;var o=[t];while(n.length&&r.exec(n[0]))o.push(n.shift());for(var u=0;u-1&&(a(e)?i=i.split("\n").map(function(e){return" "+e}).join("\n").substr(2):i="\n"+i.split("\n").map(function(e){return" "+e}).join("\n"))):i=o("[Circular]","special"));if(typeof n=="undefined"){if(g==="Array"&&t.match(/^\d+$/))return i;n=JSON.stringify(""+t),n.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(n=n.substr(1,n.length-2),n=o(n,"name")):(n=n.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),n=o(n,"string"))}return n+": "+i});s.pop();var E=0,S=w.reduce(function(e,t){return E++,t.indexOf("\n")>=0&&E++,e+t.length+1},0);return S>50?w=y[0]+(m===""?"":m+"\n ")+" "+w.join(",\n ")+" "+y[1]:w=y[0]+m+" "+w.join(", ")+" "+y[1],w}var s=[],o=function(e,t){var n={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},r={special:"cyan",number:"blue","boolean":"yellow","undefined":"grey","null":"bold",string:"green",date:"magenta",regexp:"red"}[t];return r?"["+n[r][0]+"m"+e+"["+n[r][1]+"m":e};return i||(o=function(e,t){return e}),u(e,typeof r=="undefined"?2:r)};var h=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];n.log=function(e){},n.pump=null;var d=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t},v=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.hasOwnProperty.call(e,n)&&t.push(n);return t},m=Object.create||function(e,t){var n;if(e===null)n={__proto__:null};else{if(typeof e!="object")throw new TypeError("typeof prototype["+typeof e+"] != 'object'");var r=function(){};r.prototype=e,n=new r,n.__proto__=e}return typeof t!="undefined"&&Object.defineProperties&&Object.defineProperties(n,t),n};n.inherits=function(e,t){e.super_=t,e.prototype=m(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})};var g=/%[sdj%]/g;n.format=function(e){if(typeof e!="string"){var t=[];for(var r=0;r=s)return e;switch(e){case"%s":return String(i[r++]);case"%d":return Number(i[r++]);case"%j":return JSON.stringify(i[r++]);default:return e}});for(var u=i[r];r0&&this._events[e].length>n&&(this._events[e].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[e].length),console.trace())}this._events[e].push(t)}else this._events[e]=[this._events[e],t];return this},u.prototype.on=u.prototype.addListener,u.prototype.once=function(e,t){var n=this;return n.on(e,function r(){n.removeListener(e,r),t.apply(this,arguments)}),this},u.prototype.removeListener=function(e,t){if("function"!=typeof t)throw new Error("removeListener only takes instances of Function");if(!this._events||!this._events[e])return this;var n=this._events[e];if(a(n)){var r=f(n,t);if(r<0)return this;n.splice(r,1),n.length==0&&delete this._events[e]}else this._events[e]===t&&delete this._events[e];return this},u.prototype.removeAllListeners=function(e){return e&&this._events&&this._events[e]&&(this._events[e]=null),this},u.prototype.listeners=function(e){return this._events||(this._events={}),this._events[e]||(this._events[e]=[]),a(this._events[e])||(this._events[e]=[this._events[e]]),this._events[e]}}),e.define("/src/js/dialogs/nextLevel.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Great Job!!","","You solved the level in *{numCommands}* command(s); ","our solution uses {best}."]}}],ja:[{type:"ModalAlert",options:{markdowns:["## 完成!","","あなたは*{numCommands}*回のコマンドでこの課題をクリアしました; ","模範解答では{best}回です。"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 碉堡了!","","你用 *{numCommands}* 条命令搞定了这一关;我们的答案要用 {best}。"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Beau Travail!!","","Vous avez résolu le niveau en *{numCommands}* commande(s); ","notre solution le fait en {best}."]}}]}}),e.define("/src/js/models/commandModel.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../util/errors"),l=e("../git/commands"),c=l.GitOptionParser,h=e("../level/parseWaterfall").ParseWaterfall,p=f.CommandProcessError,d=f.GitError,v=f.Warning,m=f.CommandResult,g=a.Model.extend({defaults:{status:"inqueue",rawStr:null,result:"",createTime:null,error:null,warnings:null,parseWaterfall:new h,generalArgs:null,supportedMap:null,options:null,method:null},initialize:function(e){this.initDefaults(),this.validateAtInit(),this.on("change:error",this.errorChanged,this),this.get("error")&&this.errorChanged(),this.parseOrCatch()},initDefaults:function(){this.set("generalArgs",[]),this.set("supportedMap",{}),this.set("warnings",[])},validateAtInit:function(){if(this.get("rawStr")===null)throw new Error("Give me a string!");this.get("createTime")||this.set("createTime",(new Date).toString())},setResult:function(e){this.set("result",e)},finishWith:function(e){this.set("status","finished"),e.resolve()},addWarning:function(e){this.get("warnings").push(e),this.set("numWarnings",this.get("numWarnings")?this.get("numWarnings")+1:1)},getFormattedWarnings:function(){if(!this.get("warnings").length)return"";var e='';return"

"+e+this.get("warnings").join("

"+e)+"

"},parseOrCatch:function(){this.expandShortcuts(this.get("rawStr"));try{this.processInstants()}catch(e){f.filterError(e),this.set("error",e);return}if(this.parseAll())return;this.set("error",new p({msg:'The command "'+this.get("rawStr")+"\" isn't supported, sorry!"}))},errorChanged:function(){var e=this.get("error");e instanceof p||e instanceof d?this.set("status","error"):e instanceof m?this.set("status","finished"):e instanceof v&&this.set("status","warning"),this.formatError()},formatError:function(){this.set("result",this.get("error").toResult())},expandShortcuts:function(e){e=this.get("parseWaterfall").expandAllShortcuts(e),this.set("rawStr",e)},processInstants:function(){var e=this.get("rawStr");if(!e.length)throw new m({msg:""});this.get("parseWaterfall").processAllInstants(e)},parseAll:function(){var e=this.get("rawStr"),t=this.get("parseWaterfall").parseAll(e);return t?(u.each(t.toSet,function(e,t){this.set(t,e)},this),!0):!1}}),y=a.Model.extend({defaults:{text:""}});n.CommandEntry=y,n.Command=g}),e.define("/src/js/git/commands.js",function(e,t,n,r,i,s,o){function y(e,t){this.method=e,this.rawOptions=t,this.supportedMap=this.getMasterOptionMap()[e];if(this.supportedMap===undefined)throw new Error("No option map for "+e);this.generalArgs=[],this.explodeAndSet()}var u=e("underscore"),a=e("../intl"),f=e("../util/errors"),l=f.CommandProcessError,c=f.GitError,h=f.Warning,p=f.CommandResult,d={"git commit":/^(gc|git ci)($|\s)/,"git add":/^ga($|\s)/,"git checkout":/^(go|git co)($|\s)/,"git rebase":/^gr($|\s)/,"git branch":/^(gb|git br)($|\s)/,"git status":/^(gst|gs|git st)($|\s)/,"git help":/^git$/},v=[[/^git help($|\s)/,function(){var e=[a.str("git-version"),"
",a.str("git-usage"),u.escape(a.str("git-usage-command")),"
",a.str("git-supported-commands"),"
"],t=y.prototype.getMasterOptionMap();u.each(t,function(t,n){e.push("git "+n),u.each(t,function(t,n){e.push(" "+n)},this)},this);var n=e.join("\n");throw n=n.replace(/\t/g,"   "),new p({msg:n})}]],m={"git commit":/^git +commit($|\s)/,"git add":/^git +add($|\s)/,"git checkout":/^git +checkout($|\s)/,"git rebase":/^git +rebase($|\s)/,"git reset":/^git +reset($|\s)/,"git branch":/^git +branch($|\s)/,"git revert":/^git +revert($|\s)/,"git log":/^git +log($|\s)/,"git merge":/^git +merge($|\s)/,"git show":/^git +show($|\s)/,"git status":/^git +status($|\s)/,"git cherry-pick":/^git +cherry-pick($|\s)/,"git fakeTeamwork":/^git +fakeTeamwork($|\s)/,"git fetch":/^git +fetch *?$/,"git pull":/^git +pull($|\s)/,"git push":/^git +push($|\s)/,"git clone":/^git +clone *?$/},g=function(e){var t,n;u.each(m,function(r,i){r.exec(e)&&(n=e.slice(i.length+1),t=i.slice("git ".length))});if(!t)return!1;var r=new y(t,n);return{toSet:{generalArgs:r.generalArgs,supportedMap:r.supportedMap,method:t,options:n,eventName:"processGitCommand"}}};y.prototype.getMasterOptionMap=function(){return{commit:{"--amend":!1,"-a":!1,"-am":!1,"-m":!1},status:{},log:{},add:{},"cherry-pick":{},branch:{"-d":!1,"-D":!1,"-f":!1,"-a":!1,"-r":!1,"--contains":!1},checkout:{"-b":!1,"-B":!1,"-":!1},reset:{"--hard":!1,"--soft":!1},merge:{},rebase:{"-i":!1},revert:{},show:{},clone:{},fetch:{},pull:{"--rebase":!1},push:{},fakeTeamwork:{}}},y.prototype.explodeAndSet=function(){var e=this.rawOptions.match(/('.*?'|".*?"|\S+)/g)||[];for(var t=0;t","show commands","show solution","show goal"];throw new v({msg:t.join("\n")})}],[/^locale (\w+)$/,function(t){f.GLOBAL.locale=t[1];var n=e("../app").getEvents().trigger("localeChanged");throw new v({msg:l.str("locale-command",{locale:t[1]})})}],[/^refresh$/,function(){var t=e("../app").getEvents();throw t.trigger("refreshTree"),new v({msg:l.str("refresh-tree-command")})}],[/^rollup (\d+)$/,function(t){var n=e("../app").getEvents();throw n.trigger("rollupCommands",t[1]),new v({msg:"Commands combined!"})}],[/^echo "(.*?)"$|^echo (.*?)$/,function(e){var t=e[1]||e[2];throw new v({msg:t})}],[/^show +commands$/,function(e){var t=y(),n=[l.str("show-all-commands"),"
"];throw u.each(t,function(e,t){n.push(t)}),new v({msg:n.join("\n")})}]],g={"reset solved":/^reset solved($|\s)/,help:/^help( +general)?$|^\?$/,reset:/^reset( +--forSolution)?$/,delay:/^delay (\d+)$/,clear:/^clear($|\s)/,"exit level":/^exit level($|\s)/,sandbox:/^sandbox($|\s)/,level:/^level\s?([a-zA-Z0-9]*)/,levels:/^levels($|\s)/,mobileAlert:/^mobile alert($|\s)/,"build level":/^build +level($|\s)/,"export tree":/^export +tree$/,"import tree":/^import +tree$/,"import level":/^import +level$/,undo:/^undo($|\s)/},y=function(){var t=["mobileAlert"],n=u.extend({},e("../git/commands").regexMap,e("../level").regexMap,g);return u.each(t,function(e){delete n[e]}),n};n.instantCommands=m,n.parse=a.genParseCommand(g,"processSandboxCommand"),n.getOptimisticLevelParse=function(){return a.genParseCommand(e("../level").regexMap,"processLevelCommand")},n.getOptimisticLevelBuilderParse=function(){return a.genParseCommand(e("../level/builder").regexMap,"processLevelBuilderCommand")}}),e.define("/src/js/level/builder.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("../util"),c=e("../app"),h=e("../intl"),p=e("../util/errors"),d=e("../visuals/visualization").Visualization,v=e("../level/parseWaterfall").ParseWaterfall,m=e("../level").Level,g=e("../models/commandModel").Command,y=e("../git/gitShim").GitShim,b=e("../views/multiView").MultiView,w=e("../views").CanvasTerminalHolder,E=e("../views").ConfirmCancelTerminal,S=e("../views").NextLevelConfirm,x=e("../views").LevelToolbar,T=e("../views/builderViews").MarkdownPresenter,N=e("../views/builderViews").MultiViewBuilder,C=e("../views/builderViews").MarkdownGrabber,k={"define goal":/^define goal$/,"define name":/^define name$/,"help builder":/^help builder$/,"define start":/^define start$/,"edit dialog":/^edit dialog$/,"show start":/^show start$/,"hide start":/^hide start$/,"define hint":/^define hint$/,finish:/^finish$/},L=l.genParseCommand(k,"processLevelBuilderCommand"),A=m.extend({initialize:function(t){t=t||{},t.level=t.level||{};var n=h.getLocale();t.level.startDialog={},t.level.startDialog[n]={childViews:h.getDialog(e("../dialogs/levelBuilder"))},A.__super__.initialize.apply(this,[t]),this.startDialogObj=undefined,this.definedGoal=!1,delete this.treeCompare,delete this.solved},initName:function(){this.levelToolbar=new x({name:h.str("level-builder")})},initGoalData:function(){this.level.goalTreeString='{"branches":{"master":{"target":"C1","id":"master"},"makeLevel":{"target":"C2","id":"makeLevel"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"}},"HEAD":{"target":"makeLevel","id":"HEAD"}}',this.level.solutionCommand="git checkout -b makeLevel; git commit",A.__super__.initGoalData.apply(this,arguments)},initStartVisualization:function(){return this.startCanvasHolder=new w({additionalClass:"startTree",text:h.str("hide-start")}),this.startVis=new d({el:this.startCanvasHolder.getCanvasLocation(),containerElement:this.startCanvasHolder.getCanvasLocation(),treeString:this.level.startTree,noKeyboardInput:!0,smallCanvas:!0,noClick:!0}),this.startCanvasHolder},startOffCommand:function(){c.getEventBaton().trigger("commandSubmitted","echo :D")},objectiveDialog:function(e,t){var n=[e,t,this.startDialogObj===undefined?null:{startDialog:{en_US:this.startDialogObj}}];A.__super__.objectiveDialog.apply(this,n)},initParseWaterfall:function(e){A.__super__.initParseWaterfall.apply(this,[e]),this.parseWaterfall.addFirst("parseWaterfall",L),this.parseWaterfall.addFirst("instantWaterfall",this.getInstantCommands())},buildLevel:function(e,t){this.exitLevel(),setTimeout(function(){c.getSandbox().buildLevel(e,t)},this.getAnimationTime()*1.5)},getInstantCommands:function(){return[[/^help$|^\?$/,function(){throw new p.CommandResult({msg:h.str("help-vague-builder")})}]]},takeControl:function(){c.getEventBaton().stealBaton("processLevelBuilderCommand",this.processLevelBuilderCommand,this),A.__super__.takeControl.apply(this)},releaseControl:function(){c.getEventBaton().releaseBaton("processLevelBuilderCommand",this.processLevelBuilderCommand,this),A.__super__.releaseControl.apply(this)},showGoal:function(){this.hideStart(),A.__super__.showGoal.apply(this,arguments)},showStart:function(e,t){this.hideGoal(),this.showSideVis(e,t,this.startCanvasHolder,this.initStartVisualization)},resetSolution:function(){this.gitCommandsIssued=[],this.level.solutionCommand=undefined},hideStart:function(e,t){this.hideSideVis(e,t,this.startCanvasHolder)},defineStart:function(e,t){this.hideStart(),e.addWarning(h.str("define-start-warning")),this.resetSolution(),this.level.startTree=this.mainVis.gitEngine.printTree(),this.mainVis.resetFromThisTreeNow(this.level.startTree),this.showStart(e,t)},defineGoal:function(e,t){this.hideGoal();if(!this.gitCommandsIssued.length){e.set("error",new p.GitError({msg:h.str("solution-empty")})),t.resolve();return}this.definedGoal=!0,this.level.solutionCommand=this.gitCommandsIssued.join(";"),this.level.goalTreeString=this.mainVis.gitEngine.printTree(),this.initGoalVisualization(),this.showGoal(e,t)},defineName:function(e,t){this.level.name={en_US:prompt(h.str("prompt-name"))},e&&e.finishWith(t)},defineHint:function(e,t){this.level.hint={en_US:prompt(h.str("prompt-hint"))},e&&e.finishWith(t)},editDialog:function(e,t){var n=f.defer();this.currentBuilder=new N({multiViewJSON:this.startDialogObj,deferred:n}),n.promise.then(u.bind(function(e){this.startDialogObj=e},this)).fail(function(){}).done(function(){e?e.finishWith(t):t.resolve()})},finish:function(e,t){if(!this.gitCommandsIssued.length||!this.definedGoal){e.set("error",new p.GitError({msg:h.str("solution-empty")})),t.resolve();return}while(!this.level.name)this.defineName();var n=f.defer(),r=n.promise;if(this.level.hint===undefined){var i=f.defer();r=r.then(function(){return i.promise});var s=new E({markdowns:[h.str("want-hint")]});s.getPromise().then(u.bind(this.defineHint,this)).fail(u.bind(function(){this.level.hint={en_US:""}},this)).done(function(){i.resolve()})}if(this.startDialogObj===undefined){var o=f.defer();r=r.then(function(){return o.promise});var a=new E({markdowns:[h.str("want-start-dialog")]});a.getPromise().then(u.bind(function(){var e=f.defer();return this.editDialog(undefined,e),e.promise},this)).fail(function(){}).done(function(){o.resolve()})}r=r.done(u.bind(function(){new T({fillerText:JSON.stringify(this.getExportObj(),null,2),previewText:h.str("share-json")}),e.finishWith(t)},this)),n.resolve()},getExportObj:function(){var e=u.extend({},this.level);return delete e.startDialog,this.startDialogObj&&(e.startDialog={en_US:this.startDialogObj}),e},processLevelBuilderCommand:function(e,t){var n={"define goal":this.defineGoal,"define start":this.defineStart,"show start":this.showStart,"hide start":this.hideStart,finish:this.finish,"define hint":this.defineHint,"define name":this.defineName,"edit dialog":this.editDialog,"help builder":A.__super__.startDialog};if(!n[e.get("method")])throw new Error("woah we dont support that method yet");n[e.get("method")].apply(this,arguments)},afterCommandDefer:function(e,t){e.resolve()},die:function(){this.hideStart(),A.__super__.die.apply(this,arguments),delete this.startVis,delete this.startCanvasHolder}});n.LevelBuilder=A,n.regexMap=k}),e.define("/src/js/git/gitShim.js",function(e,t,n,r,i,s,o){function c(e){e=e||{},this.beforeCB=e.beforeCB||function(){},this.afterCB=e.afterCB||function(){};var t=function(e){e.resolve()};this.beforeDeferHandler=e.beforeDeferHandler||t,this.afterDeferHandler=e.afterDeferHandler||t,this.eventBaton=e.eventBaton||f.getEventBaton()}var u=e("underscore"),a=e("q"),f=e("../app"),l=e("../views/multiView").MultiView;c.prototype.insertShim=function(){this.eventBaton.stealBaton("processGitCommand",this.processGitCommand,this)},c.prototype.removeShim=function(){this.eventBaton.releaseBaton("processGitCommand",this.processGitCommand,this)},c.prototype.processGitCommand=function(e,t){this.beforeCB(e);var n=a.defer();n.promise.then(u.bind(function(){this.afterGitCommandProcessed(e,t)},this)).done();var r=u.bind(function(){this.eventBaton.passBatonBack("processGitCommand",this.processGitCommand,this,[e,n])},this),i=a.defer();i.promise.then(r).done(),this.beforeDeferHandler(i,e)},c.prototype.afterGitCommandProcessed=function(e,t){this.afterCB(e);var n=a.defer();n.promise.then(function(){t.resolve()}).done(),this.afterDeferHandler(n,e)},n.GitShim=c}),e.define("/src/js/views/multiView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../views").ModalTerminal,c=e("../views").ContainedBase,h=e("../views").ConfirmCancelView,p=e("../views").LeftRightView,d=e("../views").ModalAlert,v=e("../views/gitDemonstrationView").GitDemonstrationView,m=e("../views/builderViews"),g=m.MarkdownPresenter,y=e("../util/keyboard").KeyboardListener,b=e("../util/errors").GitError,w=f.View.extend({tagName:"div",className:"multiView",navEventDebounce:550,deathTime:700,typeToConstructor:{ModalAlert:d,GitDemonstrationView:v,MarkdownPresenter:g},initialize:function(e){e=e||{},this.childViewJSONs=e.childViews||[{type:"ModalAlert",options:{markdown:"Woah wtf!!"}},{type:"GitDemonstrationView",options:{command:"git checkout -b side; git commit; git commit"}},{type:"ModalAlert",options:{markdown:"Im second"}}],this.deferred=e.deferred||a.defer(),this.childViews=[],this.currentIndex=0,this.navEvents=u.clone(f.Events),this.navEvents.on("negative",this.getNegFunc(),this),this.navEvents.on("positive",this.getPosFunc(),this),this.navEvents.on("quit",this.finish,this),this.navEvents.on("exit",this.finish,this),this.keyboardListener=new y({events:this.navEvents,aliasMap:{left:"negative",right:"positive",enter:"positive",esc:"quit"}}),this.render(),e.wait||this.start()},onWindowFocus:function(){},getAnimationTime:function(){return 700},getPromise:function(){return this.deferred.promise},getPosFunc:function(){return u.debounce(u.bind(function(){this.navForward()},this),this.navEventDebounce,!0)},getNegFunc:function(){return u.debounce(u.bind(function(){this.navBackward()},this),this.navEventDebounce,!0)},lock:function(){this.locked=!0},unlock:function(){this.locked=!1},navForward:function(){if(this.locked)return;if(this.currentIndex===this.childViews.length-1){this.hideViewIndex(this.currentIndex),this.finish();return}this.navIndexChange(1)},navBackward:function(){if(this.currentIndex===0)return;this.navIndexChange(-1)},navIndexChange:function(e){this.hideViewIndex(this.currentIndex),this.currentIndex+=e,this.showViewIndex(this.currentIndex)},hideViewIndex:function(e){this.childViews[e].hide()},showViewIndex:function(e){this.childViews[e].show()},finish:function(){this.keyboardListener.mute(),u.each(this.childViews,function(e){e.die()}),this.deferred.resolve()},start:function(){this.showViewIndex(this.currentIndex)},createChildView:function(e){var t=e.type;if(!this.typeToConstructor[t])throw new Error('no constructor for type "'+t+'"');var n=new this.typeToConstructor[t](u.extend({},e.options,{wait:!0}));return n},addNavToView:function(e,t){var n=new p({events:this.navEvents,destination:e.getDestination(),showLeft:t!==0,lastNav:t===this.childViewJSONs.length-1});e.receiveMetaNav&&e.receiveMetaNav(n,this)},render:function(){u.each(this.childViewJSONs,function(e,t){var n=this.createChildView(e);this.childViews.push(n),this.addNavToView(n,t)},this)}});n.MultiView=w}),e.define("/src/js/views/gitDemonstrationView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../util/keyboard").KeyboardListener,h=e("../models/commandModel").Command,p=e("../views").ModalTerminal,d=e("../views").ContainedBase,v=e("../visuals/visualization").Visualization,m=d.extend({tagName:"div",className:"gitDemonstrationView box horizontal",template:u.template($("#git-demonstration-view").html()),events:{"click div.command > p.uiButton":"positive"},initialize:function(t){t=t||{},this.options=t,this.JSON=u.extend({beforeMarkdowns:["## Git Commits","","Awesome!"],command:"git commit",afterMarkdowns:["Now you have seen it in action","","Go ahead and try the level!"]},t);var n=function(t){return e("markdown").markdown.toHTML(t.join("\n"))};this.JSON.beforeHTML=n(this.JSON.beforeMarkdowns),this.JSON.afterHTML=n(this.JSON.afterMarkdowns),this.container=new p({title:t.title||"Git Demonstration"}),this.render(),this.checkScroll(),this.navEvents=u.clone(f.Events),this.navEvents.on("positive",this.positive,this),this.navEvents.on("negative",this.negative,this),this.keyboardListener=new c({events:this.navEvents,aliasMap:{enter:"positive",right:"positive",left:"negative"},wait:!0}),this.visFinished=!1,this.initVis(),t.wait||this.show()},receiveMetaNav:function(e,t){var n=this;e.navEvents.on("positive",this.positive,this),this.metaContainerView=t},checkScroll:function(){var e=this.$("div.demonstrationText").children(),t=u.map(e,function(e){return e.clientHeight}),n=u.reduce(t,function(e,t){return e+t});n15&&console.warn("graphics are degrading from too many layers");var t=this.getDepthIncrement(e);u.each(this.visNodeMap,function(e){e.setDepthBasedOn(t,this.getHeaderOffset())},this)},w.prototype.animateNodePositions=function(e){u.each(this.visNodeMap,function(t){t.animateUpdatedPosition(e)},this)},w.prototype.addBranchFromEvent=function(e,t,n){var r=u.bind(function(){this.addBranch(e)},this);!this.gitEngine||!this.gitReady?this.defer(r):r()},w.prototype.addBranch=function(e){var t=new m({branch:e,gitVisuals:this,gitEngine:this.gitEngine});this.visBranchCollection.add(t),this.gitReady?t.genGraphics(this.paper):this.defer(u.bind(function(){t.genGraphics(this.paper)},this))},w.prototype.removeVisBranch=function(e){this.visBranchCollection.remove(e)},w.prototype.removeVisNode=function(e){this.visNodeMap[e.getID()]=undefined},w.prototype.removeVisEdge=function(e){this.visEdgeCollection.remove(e)},w.prototype.animateRefs=function(e){this.visBranchCollection.each(function(t){t.animateUpdatedPos(e)},this)},w.prototype.animateEdges=function(e){this.visEdgeCollection.each(function(t){t.animateUpdatedPath(e)},this)},w.prototype.getMinLayers=function(){return this.options.smallCanvas?2:7},w.prototype.getDepthIncrement=function(e){e=Math.max(e,this.getMinLayers());var t=1-this.getHeaderOffset(),n=t/e;return n},w.prototype.shouldHaveHeader=function(){return this.gitEngine.isOrigin()||this.gitEngine.hasOrigin()},w.prototype.getHeaderOffset=function(){return this.shouldHaveHeader()?.05:0},w.prototype.calcDepthRecursive=function(e,t){e.get("visNode").setDepth(t);var n=e.get("children"),r=t;return u.each(n,function(e){var n=this.calcDepthRecursive(e,t+1);r=Math.max(n,r)},this),r},w.prototype.canvasResize=function(e,t){this.resizeFunc||this.genResizeFunc(),this.resizeFunc(e,t)},w.prototype.genResizeFunc=function(){this.resizeFunc=u.debounce(u.bind(function(t,n){this.refreshTree()},this),200,!0)},w.prototype.addNode=function(e,t){this.commitMap[e]=t,t.get("rootCommit")&&(this.rootCommit=t);var n=new v({id:e,commit:t,gitVisuals:this,gitEngine:this.gitEngine});return this.visNodeMap[e]=n,this.gitReady&&n.genGraphics(this.paper),n},w.prototype.addEdge=function(e,t){var n=this.visNodeMap[e],r=this.visNodeMap[t];if(!n||!r)throw new Error("one of the ids in ("+e+", "+t+") does not exist");var i=new y({tail:n,head:r,gitVisuals:this,gitEngine:this.gitEngine});this.visEdgeCollection.add(i),this.gitReady&&i.genGraphics(this.paper)},w.prototype.zIndexReflow=function(){this.visNodesFront(),this.visBranchesFront()},w.prototype.visNodesFront=function(){u.each(this.visNodeMap,function(e){e.toFront()})},w.prototype.visBranchesFront=function(){this.visBranchCollection.each(function(e){e.nonTextToFront(),e.textToFront()}),this.visBranchCollection.each(function(e){e.textToFrontIfInStack()})},w.prototype.drawTreeFromReload=function(){this.gitReady=!0,this.deferFlush(),this.calcTreeCoords()},w.prototype.drawTreeFirstTime=function(){this.gitReady=!0,this.calcTreeCoords(),u.each(this.visNodeMap,function(e){e.genGraphics(this.paper)},this),this.visEdgeCollection.each(function(e){e.genGraphics(this.paper)},this),this.visBranchCollection.each(function(e){e.genGraphics(this.paper)},this),this.zIndexReflow()},n.GitVisuals=w}),e.define("/src/js/visuals/visNode.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=l.extend({defaults:{depth:undefined,maxWidth:null,outgoingEdges:null,circle:null,text:null,id:null,pos:null,radius:null,commit:null,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing,fill:f.defaultNodeFill,"stroke-width":f.defaultNodeStrokeWidth,stroke:f.defaultNodeStroke},getID:function(){return this.get("id")},validateAtInit:function(){if(!this.get("id"))throw new Error("need id for mapping");if(!this.get("commit"))throw new Error("need commit for linking");this.get("pos")||this.set("pos",{x:Math.random(),y:Math.random()})},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine"),this.set("outgoingEdges",[])},setDepth:function(e){this.set("depth",Math.max(this.get("depth")||0,e))},setDepthBasedOn:function(e,t){if(this.get("depth")===undefined)throw new Error("no depth yet!");var n=this.get("pos");n.y=this.get("depth")*e+t},getMaxWidthScaled:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("commit")),t={branch:1,head:.3,none:.1};if(t[e]===undefined)throw new Error("bad stat");return t[e]*this.get("maxWidth")},toFront:function(){this.get("circle").toFront(),this.get("text").toFront()},getOpacity:function(){var e={branch:1,head:f.upstreamHeadOpacity,none:f.upstreamNoneOpacity},t=this.gitVisuals.getCommitUpstreamStatus(this.get("commit"));if(e[t]===undefined)throw new Error("invalid status");return e[t]},getTextScreenCoords:function(){return this.getScreenCoords()},getAttributes:function(){var e=this.getScreenCoords(),t=this.getTextScreenCoords(),n=this.getOpacity(),r=this.getIsInOrigin()?f.originDash:"";return{circle:{cx:e.x,cy:e.y,opacity:n,r:this.getRadius(),fill:this.getFill(),"stroke-width":this.get("stroke-width"),"stroke-dasharray":r,stroke:this.get("stroke")},text:{x:t.x,y:t.y,opacity:n}}},highlightTo:function(e,t,n){var r=e.get("fill"),i={circle:{fill:r,stroke:r,"stroke-dasharray":"","stroke-width":this.get("stroke-width")*5},text:{}};this.animateToAttr(i,t,n)},animateUpdatedPosition:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},animateToSnapshot:function(e,t,n){if(!e[this.getID()])return;this.animateToAttr(e[this.getID()],t,n)},setAttr:function(e,t,n,r){var i=["text","circle"];this.setAttrBase(i,e,t,n,r)},animateToAttr:function(e,t,n){l.prototype.animateToAttr.apply(this,arguments);var r=t!==undefined?t:this.get("animationSpeed"),i=n||this.get("animationEasing");n=="bounce"&&e.circle&&e.circle.cx!==undefined&&e.text&&e.text.x!==undefined&&(this.get("circle").animate(e.circle.cx,r,"easeInOut"),this.get("text").animate(e.text.x,r,"easeInOut"))},getScreenCoords:function(){var e=this.get("pos");return this.gitVisuals.toScreenCoords(e)},getRadius:function(){return this.get("radius")||f.nodeRadius},getParentScreenCoords:function(){return this.get("commit").get("parents")[0].get("visNode").getScreenCoords()},setBirthPosition:function(){var e=this.getParentScreenCoords();this.get("circle").attr({cx:e.x,cy:e.y,opacity:0,r:0}),this.get("text").attr({x:e.x,y:e.y,opacity:0})},setBirthFromSnapshot:function(e){var t=this.get("commit").get("parents")[0].get("visNode").getID(),n=e[t];this.get("circle").attr({opacity:0,r:0,cx:n.circle.cx,cy:n.circle.cy}),this.get("text").attr({opacity:0,x:n.text.x,y:n.text.y});var r={x:n.circle.cx,y:n.circle.cy};this.setOutgoingEdgesBirthPosition(r)},setBirth:function(){this.setBirthPosition(),this.setOutgoingEdgesBirthPosition(this.getParentScreenCoords())},setOutgoingEdgesOpacity:function(e){u.each(this.get("outgoingEdges"),function(t){t.setOpacity(e)})},animateOutgoingEdgesToAttr:function(e,t,n){u.each(this.get("outgoingEdges"),function(t){var n=e[t.getID()];t.animateToAttr(n)},this)},animateOutgoingEdges:function(e,t){u.each(this.get("outgoingEdges"),function(n){n.animateUpdatedPath(e,t)},this)},animateOutgoingEdgesFromSnapshot:function(e,t,n){u.each(this.get("outgoingEdges"),function(r){var i=e[r.getID()];r.animateToAttr(i,t,n)},this)},setOutgoingEdgesBirthPosition:function(e){u.each(this.get("outgoingEdges"),function(t){var n=t.get("head").getScreenCoords(),r=t.genSmoothBezierPathStringFromCoords(e,n);t.get("path").stop(),t.get("path").attr({path:r,opacity:0})},this)},parentInFront:function(){this.get("commit").get("parents")[0].get("visNode").toFront()},getFontSize:function(e){return e.length<3?12:e.length<5?10:8},getFill:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("commit"));return e=="head"?f.headRectFill:e=="none"?f.orphanNodeFill:this.gitVisuals.getBlendedHuesForCommit(this.get("commit"))},attachClickHandlers:function(){if(this.get("gitVisuals").options.noClick)return;var t="git checkout "+this.get("commit").get("id"),n=e("../app");u.each([this.get("circle"),this.get("text")],function(e){e.click(function(){n.getEventBaton().trigger("commandSubmitted",t)}),$(e.node).css("cursor","pointer")})},setOpacity:function(e){e=e===undefined?1:e;var t=["circle","text"];u.each(t,function(t){this.get(t).attr({opacity:e})},this)},remove:function(){this.removeKeys(["circle"],["text"]);var e=this.get("text");e&&e.remove(),this.gitVisuals.removeVisNode(this)},removeAll:function(){this.remove(),u.each(this.get("outgoingEdges"),function(e){e.remove()},this)},getExplodeStepFunc:function(){var e=this.get("circle"),t=20,n=Math.PI+Math.random()*1*Math.PI,r=.2,i=.01,s=t*Math.cos(n),o=t*Math.sin(n),u=e.attr("cx"),a=e.attr("cy"),f=this.gitVisuals.paper.width,l=this.gitVisuals.paper.height,c=.8,h=1,p=function(){o+=r*h-i*o,s-=i*s,u+=s*h,a+=o*h;if(u<0||u>f)s=c*-s,u=u<0?0:f;if(a<0||a>l)o=c*-o,a=a<0?0:l;return e.attr({cx:u,cy:a}),s*s+o*o<.01&&Math.abs(a-l)===0?!1:!0};return p},genGraphics:function(){var e=this.gitVisuals.paper,t=this.getScreenCoords(),n=this.getTextScreenCoords(),r=e.circle(t.x,t.y,this.getRadius()).attr(this.getAttributes().circle),i=e.text(n.x,n.y,String(this.get("id")));i.attr({"font-size":this.getFontSize(this.get("id")),"font-weight":"bold","font-family":"Monaco, Courier, font-monospace",opacity:this.getOpacity()}),this.set("circle",r),this.set("text",i),this.attachClickHandlers()}});n.VisNode=c}),e.define("/src/js/visuals/visBase.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({removeKeys:function(e){u.each(e,function(e){this.get(e)&&this.get(e).remove()},this)},getNonAnimateKeys:function(){return["stroke-dasharray"]},getIsInOrigin:function(){return this.get("gitEngine")?this.get("gitEngine").isOrigin():!1},animateToAttr:function(e,t,n){if(t===0){this.setAttr(e,!0);return}var r=t!==undefined?t:this.get("animationSpeed"),i=n||this.get("animationEasing");this.setAttr(e,!1,r,i)},setAttrBase:function(e,t,n,r,i){u.each(e,function(e){n?this.get(e).attr(t[e]):(this.get(e).stop(),this.get(e).animate(t[e],r,i),u.forEach(this.getNonAnimateKeys(),function(n){t[e]&&t[e][n]!==undefined&&this.get(e).attr(n,t[e][n])},this)),t.css&&$(this.get(e).node).css(t.css)},this)},animateAttrKeys:function(e,t,n,r){e=u.extend({},{include:["circle","arrow","rect","path","text"],exclude:[]},e||{});var i=this.getAttributes();u.each(e.include,function(e){i[e]=u.extend({},i[e],t)}),u.each(e.exclude,function(e){delete i[e]}),this.animateToAttr(i,n,r)}});n.VisBase=f}),e.define("/src/js/visuals/visBranch.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=function(){var e=Math.random(),t="hsb("+String(e)+",0.7,1)";return t},h=l.extend({defaults:{pos:null,text:null,rect:null,arrow:null,isHead:!1,flip:1,fill:f.rectFill,stroke:f.rectStroke,"stroke-width":f.rectStrokeWidth,offsetX:f.nodeRadius*4.75,offsetY:0,arrowHeight:14,arrowInnerSkew:0,arrowEdgeHeight:6,arrowLength:14,arrowOffsetFromCircleX:10,vPad:5,hPad:5,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing},validateAtInit:function(){if(!this.get("branch"))throw new Error("need a branch!")},getID:function(){return this.get("branch").get("id")},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine");if(!this.gitEngine)throw new Error("asd wtf");this.get("branch").set("visBranch",this);var e=this.get("branch").get("id");e=="HEAD"?(this.set("isHead",!0),this.set("flip",-1),this.refreshOffset(),this.set("fill",f.headRectFill)):e!=="master"&&this.set("fill",c())},getCommitPosition:function(){var e=this.gitEngine.getCommitFromRef(this.get("branch")),t=e.get("visNode");return this.set("flip",this.getFlipValue(e,t)),this.refreshOffset(),t.getScreenCoords()},getFlipValue:function(e,t){var n=this.get("gitVisuals").getFlipPos(),r=t.get("pos").x>n;return e.get("id")==="C0"?-1:this.get("isHead")?r?this.isBranchStackEmpty()?-1:1:this.isBranchStackEmpty()?1:-1:r?-1:1},refreshOffset:function(){var e=f.nodeRadius*4.75,t=33,n=10;this.get("flip")===1?(this.set("offsetY",-t),this.set("offsetX",e-n)):(this.set("offsetY",t),this.set("offsetX",e-n))},getArrowTransform:function(){return this.get("flip")===1?"t-2,-20R-35":"t2,20R-35"},getBranchStackIndex:function(){if(this.get("isHead"))return 0;var e=this.getBranchStackArray(),t=-1;return u.each(e,function(e,n){e.obj==this.get("branch")&&(t=n)},this),t},getBranchStackLength:function(){return this.get("isHead")?1:this.getBranchStackArray().length},isBranchStackEmpty:function(){var e=this.gitVisuals.branchStackMap[this.getCommitID()];return e?e.length===0:!0},getCommitID:function(){var e=this.get("branch").get("target");return e.get("type")==="branch"&&(e=e.get("target")),e.get("id")},getBranchStackArray:function(){var e=this.gitVisuals.branchStackMap[this.getCommitID()];return e===undefined?(this.gitVisuals.calcBranchStacks(),this.getBranchStackArray()):e},getTextPosition:function(){var e=this.getCommitPosition(),t=this.getBranchStackIndex();return{x:e.x+this.get("flip")*this.get("offsetX"),y:e.y+t*f.multiBranchY+this.get("offsetY")}},getRectPosition:function(){var e=this.getTextPosition(),t=this.get("flip"),n=this.getTextSize();return{x:e.x-.5*n.w-this.get("hPad"),y:e.y-.5*n.h-this.get("vPad")}},getArrowPath:function(){var e=function(e,t,n){return{x:e.x+t,y:e.y+n}},t=function(e){return String(Math.round(e.x))+","+String(Math.round(e.y))},n=this.get("flip"),r=e(this.getCommitPosition(),n*this.get("arrowOffsetFromCircleX"),0),i=e(r,n*this.get("arrowLength"),-this.get("arrowHeight")),s=e(r,n*this.get("arrowLength"),this.get("arrowHeight")),o=e(i,n*this.get("arrowInnerSkew"),this.get("arrowEdgeHeight")),a=e(s,n*this.get("arrowInnerSkew"),-this.get("arrowEdgeHeight")),f=49,l=e(o,n*f,0),c=e(a,n*f,0),h="";h+="M"+t(l)+" ";var p=[o,i,r,s,a,c];return u.each(p,function(e){h+="L"+t(e)+" "},this),h+="z",h},getTextSize:function(){var e=function(e){var t=e.get("text")?e.get("text").node:null;return t===null?0:t.clientWidth},t=function(e){return e.w||(e.w=75),e.h||(e.h=20),e},n=this.get("text").node;if(this.get("isHead"))return t({w:n.clientWidth,h:n.clientHeight});var r=0;return u.each(this.getBranchStackArray(),function(t){r=Math.max(r,e(t.obj.get("visBranch")))}),t({w:r,h:n.clientHeight})},getSingleRectSize:function(){var e=this.getTextSize(),t=this.get("vPad"),n=this.get("hPad");return{w:e.w+t*2,h:e.h+n*2}},getRectSize:function(){var e=this.getTextSize(),t=this.get("vPad"),n=this.get("hPad"),r=this.getBranchStackLength();return{w:e.w+t*2,h:e.h*r*1.1+n*2}},getIsRemote:function(){return this.get("branch").getIsRemote()},getName:function(){var e=this.get("branch").getName(),t=this.get("branch")===this.gitEngine.HEAD.get("target"),n=this.getIsRemote(),r=t&&!this.getIsInOrigin()&&!n?"*":"";return e+r},nonTextToFront:function(){this.get("arrow").toFront(),this.get("rect").toFront()},textToFront:function(){this.get("text").toFront()},textToFrontIfInStack:function(){this.getBranchStackIndex()!==0&&this.get("text").toFront()},getFill:function(){return this.get("isHead")||this.getBranchStackLength()==1||this.getBranchStackIndex()!==0?this.get("fill"):this.gitVisuals.blendHuesFromBranchStack(this.getBranchStackArray())},remove:function(){this.removeKeys(["text","arrow","rect"]),this.gitVisuals.removeVisBranch(this)},genGraphics:function(e){var t=this.getTextPosition(),n=this.getName(),r;r=e.text(t.x,t.y,String(n)),r.attr({"font-size":14,"font-family":"Monaco, Courier, font-monospace",opacity:this.getTextOpacity()}),this.set("text",r);var i=this.getAttributes(),s=this.getRectPosition(),o=this.getRectSize(),a=e.rect(s.x,s.y,o.w,o.h,8).attr(i.rect);this.set("rect",a);var f=this.getArrowPath(),l=e.path(f).attr(i.arrow);this.set("arrow",l);var c=["text","rect","arrow"];u.each(c,function(e){$(this.get(e).node).css(i.css)},this),this.attachClickHandlers(),a.toFront(),r.toFront()},attachClickHandlers:function(){if(this.get("gitVisuals").options.noClick)return;var e=[this.get("rect"),this.get("text"),this.get("arrow")];u.each(e,function(e){e.click(u.bind(this.onClick,this))},this)},shouldDisableClick:function(){return this.get("isHead")&&!this.gitEngine.getDetachedHead()},onClick:function(){if(this.shouldDisableClick())return;var t="git checkout "+this.get("branch").get("id"),n=e("../app");n.getEventBaton().trigger("commandSubmitted",t)},updateName:function(){this.get("text").attr({text:this.getName()})},getNonTextOpacity:function(){return this.get("isHead")?this.gitEngine.getDetachedHead()?1:0:this.getBranchStackIndex()===0?1:0},getTextOpacity:function(){return this.get("isHead")?this.gitEngine.getDetachedHead()?1:0:1},getAttributes:function(){var e=this.getNonTextOpacity(),t=this.getTextOpacity();this.updateName();var n=this.getTextPosition(),r=this.getRectPosition(),i=this.getRectSize(),s=this.getArrowPath(),o=this.getIsInOrigin()?f.originDash:"",u=this.shouldDisableClick()?"auto":"pointer";return{css:{cursor:u},text:{x:n.x,y:n.y,opacity:t},rect:{x:r.x,y:r.y,width:i.w,height:i.h,opacity:e,fill:this.getFill(),stroke:this.get("stroke"),"stroke-width":this.get("stroke-width")},arrow:{path:s,opacity:e,fill:this.getFill(),stroke:this.get("stroke"),transform:this.getArrowTransform(),"stroke-width":this.get("stroke-width")}}},animateUpdatedPos:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},setAttr:function(e,t,n,r){var i=["text","rect","arrow"];this.setAttrBase(i,e,t,n,r)}}),p=a.Collection.extend({model:h});n.VisBranchCollection=p,n.VisBranch=h,n.randomHueString=c}),e.define("/src/js/visuals/visEdge.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=l.extend({defaults:{tail:null,head:null,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing},validateAtInit:function(){var e=["tail","head"];u.each(e,function(e){if(!this.get(e))throw new Error(e+" is required!")},this)},getID:function(){return this.get("tail").get("id")+"."+this.get("head").get("id")},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine"),this.get("tail").get("outgoingEdges").push(this)},remove:function(){this.removeKeys(["path"]),this.gitVisuals.removeVisEdge(this)},genSmoothBezierPathString:function(e,t){var n=e.getScreenCoords(),r=t.getScreenCoords();return this.genSmoothBezierPathStringFromCoords(n,r)},genSmoothBezierPathStringFromCoords:function(e,t){var n=function(e){return String(Math.round(e.x))+","+String(Math.round(e.y))},r=function(e,t,n){return n=n||f.curveControlPointOffset,{x:e.x,y:e.y+n*t}},i=function(e,t,n){return{x:e.x+t,y:e.y+n}};e=r(e,-1,this.get("tail").getRadius()),t=r(t,1,this.get("head").getRadius());var s="";s+="M"+n(e)+" ",s+="C",s+=n(r(e,-1))+" ",s+=n(r(t,1))+" ",s+=n(t);var o=f.arrowHeadSize||10;return s+=" L"+n(i(t,-o,o)),s+=" L"+n(i(t,o,o)),s+=" L"+n(t),s+="C",s+=n(r(t,1))+" ",s+=n(r(e,-1))+" ",s+=n(e),s},getBezierCurve:function(){return this.genSmoothBezierPathString(this.get("tail"),this.get("head"))},getStrokeColor:function(){return f.visBranchStrokeColorNone},setOpacity:function(e){e=e===undefined?1:e,this.get("path").attr({opacity:e})},genGraphics:function(e){var t=this.getBezierCurve(),n=e.path(t).attr({"stroke-width":f.visBranchStrokeWidth,stroke:this.getStrokeColor(),"stroke-linecap":"round","stroke-linejoin":"round",fill:this.getStrokeColor()});n.toBack(),this.set("path",n)},getOpacity:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("tail")),t={branch:1,head:f.edgeUpstreamHeadOpacity,none:f.edgeUpstreamNoneOpacity};if(t[e]===undefined)throw new Error("bad stat");return t[e]},getAttributes:function(){var e=this.getBezierCurve(),t=this.getOpacity();return{path:{path:e,opacity:t}}},animateUpdatedPath:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},animateToAttr:function(e,t,n){if(t===0){this.get("path").attr(e.path);return}this.get("path").toBack(),this.get("path").stop(),this.get("path").animate(e.path,t!==undefined?t:this.get("animationSpeed"),n||this.get("animationEasing"))}}),h=a.Collection.extend({model:c});n.VisEdgeCollection=h,n.VisEdge=c}),e.define("/src/js/level/disabledMap.js",function(e,t,n,r,i,s,o){function h(e){e=e||{},this.disabledMap=e.disabledMap||{"git cherry-pick":!0,"git rebase":!0}}var u=e("underscore"),a=e("../intl"),f=e("../git/commands"),l=e("../util/errors"),c=l.GitError;h.prototype.getInstantCommands=function(){var e=[],t=function(){throw new c({msg:a.str("command-disabled")})};return u.each(this.disabledMap,function(n,r){var i=f.regexMap[r];if(!i)throw new Error("wuttttt this disbaled command"+r+" has no regex matching");e.push([i,t])}),e},n.DisabledMap=h}),e.define("/src/js/dialogs/confirmShowSolution.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Are you sure you want to see the solution?","","I believe in you! You can do it"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 确定要看答案吗?","","哥相信你!你可以的"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Êtes-vous sûr de vouloir voir la solution ?","","Je crois en vous ! Vous pouvez le faire"]}}]}}),e.define("/src/js/level/arbiter.js",function(e,t,n,r,i,s,o){function h(){this.levelMap={},this.levelSequences=f,this.sequences=[],this.init();var e;try{e=JSON.parse(localStorage.getItem("solvedMap")||"{}")}catch(t){console.warn("local storage failed",t)}this.solvedMap=e||{},c.getEvents().on("levelSolved",this.levelSolved,this)}var u=e("underscore"),a=e("backbone"),f=e("../../levels").levelSequences,l=e("../../levels").sequenceInfo,c=e("../app");h.prototype.init=function(){var e;u.each(this.levelSequences,function(e,t){this.sequences.push(t);if(!e||!e.length)throw new Error("no empty sequences allowed");u.each(e,function(e,n){this.validateLevel(e);var r=t+String(n+1),i=u.extend({},e,{index:n,id:r,sequenceName:t});this.levelMap[r]=i,this.levelSequences[t][n]=i},this)},this)},h.prototype.isLevelSolved=function(e){if(!this.levelMap[e])throw new Error("that level doesnt exist!");return Boolean(this.solvedMap[e])},h.prototype.levelSolved=function(e){if(!e)return;this.solvedMap[e]=!0,this.syncToStorage()},h.prototype.resetSolvedMap=function(){this.solvedMap={},this.syncToStorage(),c.getEvents().trigger("levelSolved")},h.prototype.syncToStorage=function(){try{localStorage.setItem("solvedMap",JSON.stringify(this.solvedMap))}catch(e){console.warn("local storage fialed on set",e)}},h.prototype.validateLevel=function(e){e=e||{};var t=["name","goalTreeString","solutionCommand"],n=["hint","disabledMap","startTree"];u.each(t,function(t){if(e[t]===undefined)throw console.log(e),new Error("I need this field for a level: "+t)})},h.prototype.getSequenceToLevels=function(){return this.levelSequences},h.prototype.getSequences=function(){return u.keys(this.levelSequences)},h.prototype.getLevelsInSequence=function(e){if(!this.levelSequences[e])throw new Error("that sequecne name "+e+"does not exist");return this.levelSequences[e]},h.prototype.getSequenceInfo=function(e){return l[e]},h.prototype.getLevel=function(e){return this.levelMap[e]},h.prototype.getNextLevel=function(e){if(!this.levelMap[e])return console.warn("that level doesnt exist!!!"),null;var t=this.levelMap[e],n=t.sequenceName,r=this.levelSequences[n],i=t.index+1;if(i master -> C1",""],afterMarkdowns:["And now it's","","HEAD -> C1"],command:"git checkout C1",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["To complete this level, let's detach HEAD from `bugFix` and attach it to the commit instead.","","Specify this commit by its hash. The hash for each commit is displayed on the circle that represents the commit."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 在Git中前后移动","","在接触Git的更多高级主题之前,我们先学习用不同的方法在代表你的项目的提交记录树上前后移动。","","一旦能够熟练地在Git中前进后退,你使用其他git命令的威力也会被放大!","","","","",""]}},{type:"ModalAlert",options:{markdowns:["## HEAD","",'我们首先看一下"HEAD". HEAD是当前提交记录的符号名称 -- 其实就是你正在其基础进行工作的提交记录。',"","HEAD总是指向最近一次提交记录,表现为当前工作树。大多数修改工作树的git命令都开始于改变HEAD指向。","","HEAD通常指向分支名(比如bugFix)。你提交时,改变了bugFix的状态,这一变化通过HEAD变得可见。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["在实例中看一下。我们将会观察提交前后HEAD的位置。"],afterMarkdowns:["看! HEAD一直藏在`master`分支后面。"],command:"git checkout C1; git checkout master; git commit; git checkout C2",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["### 分离 HEAD","","分离HEAD就是让其指向一个提交记录而不是分支名。这是命令执行之前的样子: ","","HEAD -> master -> C1",""],afterMarkdowns:["现在变成了","","HEAD -> C1"],command:"git checkout C1",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["想完成此关,从`bugFix`分离出HEAD并让其指向一个提交记录。","","通过hash值指定提交记录。每个提交记录的hash值显示在代表提交记录的圆圈中。"]}}]}}}}),e.define("/levels/rampup/relativeRefs.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"C3","id":"HEAD"}}',solutionCommand:"git checkout bugFix^",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Relative Refs (^)",zh_CN:"相对引用(^)"},hint:{en_US:"Remember the Caret (^) operator!",zh_CN:"记住插入(^)操作符!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Relative Refs","","Moving around in Git by specifying commit hashes can get a bit tedious. In the real world you won't have a nice commit tree visualization next to your terminal, so you'll have to use `git log` to see hashes.","","Furthermore, hashes are usually a lot longer in the real Git world as well. For instance, the hash of the commit that introduced the previous level is `fed2da64c0efc5293610bdd892f82a58e8cbc5d8`. Doesn't exactly roll off the tongue...","","The upside is that Git is smart about hashes. It only requires you to specify enough characters of the hash until it uniquely identifies the commit. So I can type `fed2` instead of the long string above."]}},{type:"ModalAlert",options:{markdowns:["Like I said, specifying commits by their hash isn't the most convenient thing ever, which is why Git has relative refs. They are awesome!","","With relative refs, you can start somewhere memorable (like the branch `bugFix` or `HEAD`) and work from there.","","Relative commits are powerful, but we will introduce two simple ones here:","","* Moving upwards one commit at a time with `^`","* Moving upwards a number of times with `~`"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's look at the Caret (^) operator first. Each time you append that to a ref name, you are telling Git to find the parent of the specified commit.","",'So saying `master^` is equivalent to "the first parent of `master`".',"","`master^^` is the grandparent (second-generation ancestor) of `master`","","Let's check out the commit above master here"],afterMarkdowns:["Boom! Done. Way easier than typing the commit hash"],command:"git checkout master^",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["You can also reference `HEAD` as a relative ref. Let's use that a couple of times to move upwards in the commit tree"],afterMarkdowns:["Easy! We can travel backwards in time with `HEAD^`"],command:"git checkout C3; git checkout HEAD^; git checkout HEAD^; git checkout HEAD^",beforeCommand:"git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["To complete this level, check out the parent commit of `bugFix`. This will detach `HEAD`.","","You can specify the hash if you want, but try using relative refs instead!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 相对引用","","用指定提交记录hash值的方式在Git中移动会变得比较乏味。在现实中,你不会有漂亮的可视化的提交记录树放在终端旁边,所以你不得不用`git log`来查看hasn值。","","另外,hash值在真实的Git环境中也会更长。举个例子,前一关的介绍中的提交记录的hash值是`fed2da64c0efc5293610bdd892f82a58e8cbc5d8`。不要把舌头闪了...","","好的一面是,Git对hash的处理很智能。你只需要提供能够唯一标识提交记录的前几个字符即可。所以,我可以仅输入`fed2`而不是上面的一长串字符。"]}},{type:"ModalAlert",options:{markdowns:["我说过,通过hash指定提交记录不是很方便,所以Git引入了相对引用。这个就很牛掰了!","","使用相对引用,你可以从一个易于记忆的地方(比如分支名`bugFix`或`HEAD`)开始工作。","","相对引用非常给力,这里我介绍两个简单的用法:","","* 使用`^`向上移动1个提交记录","* 使用`~`向上移动多个提交记录"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["首先看看插入(^)操作符。把插入符跟在引用名后面,表示让Git寻找指定提交记录的父提交。","",'所以`master^`相当于"`master`的父提交"。',"","`master^^`是`master`的父父提交(上上代祖先)","","切换到master的父提交"],afterMarkdowns:["唰!搞定。这种方式比输入提交记录的hash值简单多了!"],command:"git checkout master^",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["你也可以`HEAD`把用作相对引用。以下命令使用`HEAD`在提交树中向上移动几次。"],afterMarkdowns:["简单!我们可以一直使用`HEAD^`向上移动。"],command:"git checkout C3; git checkout HEAD^; git checkout HEAD^; git checkout HEAD^",beforeCommand:"git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["要完成此关,切换到`bugFix`的父提交。这会分离出`HEAD`.","","如果你愿意的话,使用hash值也可以过关,但为何不试试使用相对引用呢?"]}}]}}}}),e.define("/levels/rampup/relativeRefs2.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C6","id":"master"},"bugFix":{"target":"C0","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C5":{"parents":["C3"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"C1","id":"HEAD"}}',solutionCommand:"git branch -f master C6;git checkout HEAD~1;git branch -f bugFix HEAD~1",startTree:'{"branches":{"master":{"target":"C4","id":"master"},"bugFix":{"target":"C5","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C5":{"parents":["C3"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"C2","id":"HEAD"}}',hint:{en_US:"You'll need to use at least one direct reference (hash) to complete this level",zh_CN:"这一关至少要用到一次直接引用(hash)"},name:{en_US:"Relative Refs #2 (~)",zh_CN:"相对引用2(~)"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:['### The "~" operator',"","Say you want to move a lot of levels up in the commit tree. It might be tedious to type `^` several times, so Git also has the tilde (~) operator.","","","The tilde operator (optionally) takes in a trailing number that specifies the number of parents you would like to ascend. Let's see it in action"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's specify a number of commits back with `~`."],afterMarkdowns:["Boom! So concise -- relative refs are great."],command:"git checkout HEAD~4",beforeCommand:"git commit; git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["### Branch forcing","","You're an expert on relative refs now, so let's actually *use* them for something.","","One of the most common ways I use relative refs is to move branches around. You can directly reassign a branch to a commit with the `-f` option. So something like:","","`git branch -f master HEAD~3`","","Moves (by force) the master branch to three parents behind HEAD."]}},{type:"ModalAlert",options:{markdowns:["To complete this level, move `HEAD`, `master`, and `bugFix` to their goal destinations shown."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:['### The "~" operator',"","假设需要在提交树中向上移动很多步。使用多个`^`非常无聊,所以Git也引入了波浪(~)操作符。","","","波浪操作符后面可以(可选地)跟一个数字,指定向上移动多少次。看个例子"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用`~`一次后退多步."],afterMarkdowns:["唰!如此简洁--相对引用就是好啊!"],command:"git checkout HEAD~4",beforeCommand:"git commit; git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["### Branch forcing","","你现在是相对引用的高手了,现在*用*他来实际做点事情。","","我使用相对引用最多的就是移动分支。你可以使用`-f`选项把直接让分支指向另一个提交。举个例子:","","`git branch -f master HEAD~3`","","(强制)移动master指向HEAD的第3级父提交。"]}},{type:"ModalAlert",options:{markdowns:["要完成此关,移动`HEAD`,`master`和`bugFix`到目标所示的位置。"]}}]}}}}),e.define("/levels/rampup/reversingChanges.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22master%22%7D%2C%22pushed%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22pushed%22%7D%2C%22local%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22local%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C2%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22pushed%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git reset HEAD~1;git checkout pushed;git revert HEAD",compareOnlyBranches:!0,startTree:'{"branches":{"master":{"target":"C1","id":"master"},"pushed":{"target":"C2","id":"pushed"},"local":{"target":"C3","id":"local"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"}},"HEAD":{"target":"local","id":"HEAD"}}',name:{en_US:"Reversing Changes in Git",ja:"変更を元に戻す",fr_FR:"Annuler des changements avec Git",ko:"Git에서 작업 되돌리기",zh_CN:"在Git中撤销更改"},hint:{en_US:"Notice that revert and reset take different arguments.",fr_FR:"",zh_CN:"注意revert和reset使用不同的参数。",ko:"",ja:""},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Reversing Changes in Git","","There are many ways to reverse changes in Git. And just like committing, reversing changes in Git has both a low-level component (staging individual files or chunks) and a high-level component (how the changes are actually reversed). Our application will focus on the latter.","","There are two primary ways to undo changes in Git -- one is using `git reset` and the other is using `git revert`. We will look at each of these in the next dialog",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","",'`git reset` reverts changes by moving a branch reference backwards in time to an older commit. In this sense you can think of it as "rewriting history;" `git reset` will move a branch backwards as if the commit had never been made in the first place.',"","Let's see what that looks like:"],afterMarkdowns:["Nice! Git simply moved the master branch reference back to `C1`; now our local repository is in a state as if `C2` had never happened"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","",'While reseting works great for local branches on your own machine, its method of "rewriting history" doesn\'t work for remote branches that others are using.',"","In order to reverse changes and *share* those reversed changes with others, we need to use `git revert`. Let's see it in action"],afterMarkdowns:["Weird, a new commit plopped down below the commit we wanted to reverse. That's because this new commit `C2'` introduces *changes* -- it just happens to introduce changes that exactly reverses the commit of `C2`.","","With reverting, you can push out your changes to share with others."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["To complete this level, reverse the two most recent commits on both `local` and `pushed`.","","Keep in mind that `pushed` is a remote branch and `local` is a local branch -- that should help you choose your methods."]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## 変更を元に戻す","","Gitでは変更を元に戻す方法がたくさんあります。コミットと同じように、低レベルな動作(ファイル別だったりファイルの中の一部だったり)も高レベルな動作(変更のまとまりのキャンセル)もできます。このアプリケーションでは後者の方法について紹介します。","","基本的なアンドゥの方法が2つあります - 一つは`git reset`を使う方法で、もう1つは`git revert`を使う方法です。次のダイアログで一つ一つを見ていきます。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","","`git reset`はブランチのポインタを後方に移動することで変更のキャンセルを実現します。履歴を上書きするような動作だと思うと良いでしょうか:`git reset`はそもそも前のコミットなんかなかったかのように、ブランチのポインタを元に戻してくれます。","","どういう感じか見てみましょう。"],afterMarkdowns:["いいですね!Gitは単純にmasterブランチへのポインタを`C1`へ戻しました。これでこのローカルリポジトリにはまるで`C2`なんて無かったかのように変更をキャンセルできました。"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","自分のマシン上のブランチではさっきの`git reset`でうまくいきましたが、この「履歴を上書きする」手段は、他の人も使っているリモートにあるリポジトリに対しては使うことができません。","","変更を巻き戻して他の人とそれを共有するためには、`git revert`を使う必要があります。今度はこれを見てみましょう。"],afterMarkdowns:["あれ、おかしいな。巻き戻したいと思ってたコミットの下に新しいコミットが出来上がってしまったみたいです。なぜか。これは、この新しい`C2'`コミットは`C2`へ戻すのに必要な内容を確かに変更して巻き戻していたのです。","","こんな風にして、巻き戻した内容を他人と共有するためにはrevertを使います。"],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["この章の仕上げに、`local`と`pushed`の両方の直近のコミットを巻き戻してみましょう。","","`pushed`はリモートのブランチで、`local`はローカルであることに注意。正しくコマンドを使い分けましょう。"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Annuler des changements avec Git","","Il y a de nombreuses façons d'annuler des changement avec Git. De même que pour les commits, annuler des changements avec Git a à la fois un aspect bas-niveau (gestion dans le 'staging' des fichiers et morceaux de fichiers) et un aspect de plus haut niveau 9comment les changements sont effectivement annulés). Nous allons nous intéresser à ce dernier point.","","Il y a principalement deux façons d'annuler des changements avec Git -- l'une est `git reset` et l'autre est `git revert`. Nous allons maintenant voir chacune de ces façons",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","","`git reset` annule des changements en déplaçant la référence en arrière dans le temps sur un commit plus ancien. En ce sens, on peut considérer cela comme une façon de \"réécrire l'histoire\"; `git reset` fait remonter une branche en arrière comme si le(s) commit(s) n'avait jamais eu lieu.","","Regardons à quoi cela ressemble :"],afterMarkdowns:["Bravo ! Git a simplement déplacé la référence de la branche master en la faisant revenir sur `C1`; désormais notre dépôt est dans le même état que si `C2` n'avait jamais eu lieu"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","Bien que le reset marche parfaitement pour les branches locales sur notre propre machine, cette façon de \"réécrire l'histoire\" ne marche pas avec les banches distantes (remote) que d'autres personnes utilisent.","","Pour pouvoir annuler des changements et *partager* ces annulations avec d'autres, nous devons utiliser `git revert`. Regardons comment cela fonctionne"],afterMarkdowns:["Étrangement, un nouveau commit est appaaru en bas sous le commit que nous voulions annuler. C'est parce que ce nouveau commit `C2'` introduit des *modifications* -- celles qui correspondent justement à l'annulation de celles du commit `C2`.","","Avec revert, vous pouvez diffuser (push) vos modifications et les partager avec tout le monde."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["Pour accomplir ce niveau, annulez les deux derniers commits à la fois sur `local` et sur `pushed`.","","Ayez à l'esprit que `pushed` est une branche distante et `local` est une branche locale -- cela devrait vous guider dans le choix de la méthode à employer."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 撤销 Git 里面的变动","","在 Git 里撤销修改的方法很多。和 commit 一样,在 Git 里撤销变动同时具有底层部分(暂存一些独立的文件或者片段)和高层部分(具体到变动是究竟怎么被撤销的)。我们这个应用主要关注后者。","","在 Git 里主要用两种方法来撤销变动 —— 一种是 `git reset`,另外一种是 `git revert`。让我们在下一个窗口逐一了解它们。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","",'`git reset`把分支记录回退到上一个提交记录来实现撤销改动。你可以认为这是在"重写历史"。`git reset`往回移动分支,原来指向的提交记录好像重来没有提交过一样。',"","让我们看看具体的操作:"],command:"git reset HEAD~1",afterMarkdowns:["Nice!Git把master分支的指向简单地移回到`C1`;现在我们的本地代码库处于没有提交过`C2`的状态了。"],beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","虽然在你的本地分支中使用`git reset`很方便,但是这种“改写历史”的方法对别人的远端分支是无效的哦!","","为了撤销更改并*传播*给别人,我们需要使用`git revert`。举个例子"],command:"git revert HEAD",afterMarkdowns:["怪哉!在我们要撤销的提交记录后面居然多了一个新提交!这是因为新提交记录`C2'`引入了*更改*——刚好是用来撤销 `C2` 这个提交的。","","借助 revert,现在可以把你的更改传递给别人啦。"],beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["要完成此关,分别撤销`local`分支和`pushed`分支上的最近一次提交。","","记住 `pushed` 是一个远程分支,`local` 是一个本地分支 —— 有了这么明显的提示应该知道用哪种方法了吧?"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git에서 작업 되돌리기","","Git에는 작업한 것을 되돌리는 여러가지 방법이 있습니다. 변경내역을 되돌리는 것도 커밋과 마찬가지로 낮은 수준의 일(개별 파일이나 묶음을 스테이징 하는 것)과 높은 수준의 일(실제 변경이 복구되는 방법)이 있는데요, 여기서는 후자에 집중해 알려드릴게요.","","Git에서 변경한 내용을 되돌리는 방법은 크게 두가지가 있습니다 -- 하나는 `git reset`을 쓰는거고, 다른 하나는 `git revert`를 사용하는 것입니다. 다음 화면에서 하나씩 알아보겠습니다.",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git 리셋(reset)","",'`git reset`은 브랜치로 하여금 예전의 커밋을 가리키도록 이동시키는 방식으로 변경 내용을 되돌립니다. 이런 관점에서 "히스토리를 고쳐쓴다"라고 말할 수 있습니다. 즉, `git reset`은 마치 애초에 커밋하지 않은 것처럼 예전 커밋으로 브랜치를 옮기는 것입니다.',"","어떤 그림인지 한번 보죠:"],afterMarkdowns:["그림에서처럼 master 브랜치가 가리키던 커밋을 `C1`로 다시 옮겼습니다; 이러면 로컬 저장소에는 마치 `C2`커밋이 아예 없었던 것과 마찬가지 상태가 됩니다."],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git 리버트(revert)","",'각자의 컴퓨터에서 작업하는 로컬 브랜치의 경우 리셋(reset)을 잘 쓸 수 있습니다만, "히스토리를 고쳐쓴다"는 점 때문에 다른 사람이 작업하는 리모트 브랜치에는 쓸 수 없습니다.',"","변경분을 되돌리고, 이 되돌린 내용을 다른 사람들과 *공유하기* 위해서는, `git revert`를 써야합니다. 예제로 살펴볼게요."],afterMarkdowns:["어색하게도, 우리가 되돌리려고한 커밋의 아래에 새로운 커밋이 생겼습니다. `C2`라는 새로운 커밋에 *변경내용*이 기록되는데요, 이 변경내역이 정확히 `C2` 커밋 내용의 반대되는 내용입니다.","","리버트를 하면 다른 사람들에게도 변경 내역을 밀어(push) 보낼 수 있습니다."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["이 레벨을 통과하려면, `local` 브랜치와 `pushed` 브랜치에 있는 최근 두 번의 커밋을 되돌려 보세요.","","`pushed`는 리모트 브랜치이고, `local`은 로컬 브랜치임을 신경쓰셔서 작업하세요 -- 어떤 방법을 선택하실지 떠오르시죠?"]}}]}}}}),e.define("/levels/rebase/manyRebases.js",function(e,t,n,r,i,s,o){n.level={compareOnlyMasterHashAgnostic:!0,disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22master%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22bugFix%22%7D%2C%22side%22%3A%7B%22target%22%3A%22C6%27%22%2C%22id%22%3A%22side%22%7D%2C%22another%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22another%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C6%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C6%22%7D%2C%22C7%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C7%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C6%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C6%27%22%7D%2C%22C7%27%22%3A%7B%22parents%22%3A%5B%22C6%27%22%5D%2C%22id%22%3A%22C7%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout bugFix;git rebase master;git checkout side;git rebase bugFix;git checkout another;git rebase side;git rebase another master",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C3","id":"bugFix"},"side":{"target":"C6","id":"side"},"another":{"target":"C7","id":"another"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C0"],"id":"C4"},"C5":{"parents":["C4"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"},"C7":{"parents":["C5"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Rebasing over 9000 times",ko:"9천번이 넘는 리베이스",ja:"Rebasing over 9000 times",zh_CN:"N次Rebase"},hint:{en_US:"Remember, the most efficient way might be to only update master at the end...",ja:"最も効率的なやり方はmasterを最後に更新するだけかもしれない・・・",ko:"아마도 master를 마지막에 업데이트하는 것이 가장 효율적인 방법일 것입니다...",zh_CN:"记住,最后更新master分支可能是最高效的方法。"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["### Rebasing Multiple Branches","","Man, we have a lot of branches going on here! Let's rebase all the work from these branches onto master.","","Upper management is making this a bit trickier though -- they want the commits to all be in sequential order. So this means that our final tree should have `C7'` at the bottom, `C6'` above that, etc etc, etc all in order.","","If you mess up along the way, feel free to use `reset` to start over again. Be sure to check out our solution and see if you can do it in fewer commands!"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["### 複数のブランチをリベースする","","さあ、いくつものブランチが出てきます。このブランチたち全てをmasterブランチにリベースしましょう。","","おエライさん方が今回の仕事を少しトリッキーにしてくれました ― コミットはすべて一列のシーケンシャルな状態にしてほしいそうです。つまり私たちが作るリポジトリの最終的なツリーの状態は、`C7'`が最後に来て、`C6'`がその一つ上に来て、、と順に積み重なるイメージです。","","試行錯誤してツリーが汚くなってきたら、`reset`コマンドを使ってツリーの状態を初期化してください。模範解答をチェックして、それよりも簡単なコマンドで済ませられるかどうか、を考えるのも忘れずに!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["### 多分支衍合","","呐,现在我们有很多分支啦!让我们rebase这些分支的工作到 master 分支上吧。","","但是你的头头找了点麻烦 —— 他们希望得到有序的提交历史,也就是我们最终的结果是 `C7'` 在最底部,`C6'` 在它上面,以此类推。","","假如你搞砸了,没所谓的(虽然我不会告诉你用 `reset` 可以重新开始)。记得看看我们提供的答案,看你能否使用更少的命令完成任务!"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["### 여러 브랜치를 리베이스(rebase)하기 ","","음, 여기 꽤 여러개의 브랜치가 있습니다! 이 브랜치들의 모든 작업내역을 master에 리베이스 해볼까요?","","윗선에서 일을 복잡하게 만드네요 -- 그 분들이 이 모든 커밋들을 순서에 맞게 정렬하라고 합니다. 그럼 결국 우리의 최종 목표 트리는 제일 아래에 `C7'` 커밋, 그 위에 `C6'` 커밋, 또 그 위에 순서대로 보여합니다.","","만일 작업중에 내용이 꼬인다면, `reset`이라고 쳐서 처음부터 다시 시작할 수 있습니다. 모범 답안을 확인해 보시고, 혹시 더 적은 수의 커맨드로 해결할 수 있는지 알아보세요!"]}}]}}}}),e.define("/levels/mixed/grabbingOneCommit.js",function(e,t,n,r,i,s,o){n.level={compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C4>e.C1}]},disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22master%22%7D%2C%22debug%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22debug%22%7D%2C%22printf%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22printf%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22bugFix%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout master;git cherry-pick C4",startTree:'{"branches":{"master":{"target":"C1","id":"master"},"debug":{"target":"C2","id":"debug"},"printf":{"target":"C3","id":"printf"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"bugFix","id":"HEAD"}}',name:{ko:"딱 한개의 커밋만 가져오기",en_US:"Grabbing Just 1 Commit",ja:"Grabbing Just 1 Commit",zh_CN:"只取一个提交"},hint:{en_US:"Remember, interactive rebase or cherry-pick is your friend here",ja:"このレベルではインタラクティブモードのrebaseやcherry-pickがクリアのカギです",ko:"대화식 리베이스(rebase -i)나 or 체리픽(cherry-pick)을 사용하세요",zh_CN:"记住,交互式 rebase 或者 cherry-pick 会很有帮助"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Locally stacked commits","","Here's a development situation that often happens: I'm trying to track down a bug but it is quite elusive. In order to aid in my detective work, I put in a few debug commands and a few print statements.","","All of these debugging / print statements are in their own branches. Finally I track down the bug, fix it, and rejoice!","","Only problem is that I now need to get my `bugFix` back into the `master` branch! I could simply fast-forward `master`, but then `master` would get all my debug statements."]}},{type:"ModalAlert",options:{markdowns:["This is where the magic of Git comes in. There are a few ways to do this, but the two most straightforward ways are:","","* `git rebase -i`","* `git cherry-pick`","","Interactive (the `-i`) rebasing allows you to choose which commits you want to keep or discard. It also allows you to reorder commits. This can be helpful if you want to toss out some work.","","Cherry-picking allows you to pick individual commits and plop them down on top of `HEAD`"]}},{type:"ModalAlert",options:{markdowns:["This is a later level so we will leave it up to you to decide, but in order to complete the level, make sure `master` receives the commit that `bugFix` references."]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ローカルに積み上がったコミット","","実際の開発ではこういうケースがよくあります:「バグの原因調査を試みているがバグの再現性がかなり低い。調査の補助のために、いくつかのデバッグ用の命令やprint文を差し込んでいる。」","","これらのデバッグ用のコードはバグ修正用のブランチにコミットされています。そしてついにバグの原因を突き止めて、修正した!やった!","","あとは`bugFix`ブランチを`master`ブランチに統合できればOK。そこで単純に`master`をfast-forwardすればよいかというと、それでは`master`ブランチの中にデバッグ用のコードも混入してしまいます。"]}},{type:"ModalAlert",options:{markdowns:["ここでGitの魔法が力を発揮します。解決のためにはいくつかの方法がありますが、最も素直な解決方法は2つあって:","","* `git rebase -i`","* `git cherry-pick`","","インタラクティブモードの(`-i`オプションつきの)rebaseによって、保持したいコミットと破棄したいコミットを選り分けることができます。コミットの順序を変更することも可能です。この方法は、一部の変更をどこかへやってしまいたい時に便利です。","","もう一方のcherry-pickを使うと、持っていきたいコミットを選んで`HEAD`の先にストンと落とすことができます。"]}},{type:"ModalAlert",options:{markdowns:["後半の章ですのでどう解決するかをもう自分で考えることができると思います。このレベルをクリアするためには、`bugFix`が持っているコミットを`master`ブランチが受け取る必要がある点には注意してください。"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 本地栈式提交 (Locally stacked commits)","","设想一下一个经常发生的场景:我在追踪一个有点棘手的 bug,为了更好地排查,我添加了一些调试命令和打印语句。","","所有的这些调试和打印语句都只在它们自己的分支里。最终我终于找到这个 bug,揪出来 fix 掉,然后撒花庆祝!","","现在唯一的问题就是要把我在 `bugFix` 分支里的工作合并回 `master` 分支。我可以简单地把 `master` 分支快进(fast-forward),但这样的话 `master` 分支就会包含我这些调试语句了。"]}},{type:"ModalAlert",options:{markdowns:["现在就是 Git 大显神通的时候啦。解决这个问题的方法不止一个,但最直接的两个方法是:","","* `git rebase -i`","* `git cherry-pick`","","交互(`-i`)衍合允许你选择哪些提交是要被保留,哪些要被舍弃。它允许你将提交重新排序。假如你要舍弃一些工作,这个会帮上很大的忙。","","Cherry-picking 能让你选择单独一个提交并且把它放到 `HEAD` 的最前端。"]}},{type:"ModalAlert",options:{markdowns:["本关是可选关卡,玩不玩随便你。但是如果你坚持要刷,确保 `master` 分支能拿到 `bugFix` 分支的相关提交(references)。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 로컬에 쌓인 커밋들","","개발중에 종종 이런 상황이 생깁니다: 잘 띄지 않는 버그를 찾아서 해결하려고, 어떤 부분의 문제인지를 찾기 위해 디버그용 코드와 화면에 정보를 프린트하는 코드 몇 줄 넣습니다. ","","디버깅용 코드나 프린트 명령은 그 브랜치에 들어있습니다. 마침내 버그를 찾아서 고쳤고, 원래 작업하는 브랜치에 합치면 됩니다!","","이제 `bugFix`브랜치의 내용을 `master`에 합쳐 넣으려 하지만, 한 가지 문제가 있습니다. 그냥 간단히 `master`브랜치를 최신 커밋으로 이동시킨다면(fast-forward) 그 불필요한 디버그용 코드들도 함께 들어가 버린다는 문제죠."]}},{type:"ModalAlert",options:{markdowns:["여기에서 Git의 마법이 드러납니다. 이 문제를 해결하는 여러가지 방법이 있습니다만, 가장 간단한 두가지 방법 아래와 같습니다:","","* `git rebase -i`","* `git cherry-pick`","","대화형 (-i 옵션) 리베이스(rebase)로는 어떤 커밋을 취하거나 버릴지를 선택할 수 있습니다. 또 커밋의 순서를 바꿀 수도 있습니다. 이 커맨드로 어떤 작업의 일부만 골라내기에 유용합니다.","","체리픽(cherry-pick)은 개별 커밋을 골라서 `HEAD`위에 떨어뜨릴 수 있습니다."]}},{type:"ModalAlert",options:{markdowns:["이번 레벨을 통과하기 위해 어떤 방법을 쓰시든 자유입니다만, `master`브랜치가 `bugFix` 브랜치의 커밋을 일부 가져오게 해주세요."]}}]}}}}),e.define("/levels/mixed/jugglingCommits.js",function(e,t,n,r,i,s,o){n.level={disabledMap:{"git cherry-pick":!0,"git revert":!0},compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C2>e.C3},function(e){return e.C2>e.C1}]},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%27%27%22%2C%22id%22%3A%22master%22%7D%2C%22newImage%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22newImage%22%7D%2C%22caption%22%3A%7B%22target%22%3A%22C3%27%27%22%2C%22id%22%3A%22caption%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%2C%22C2%27%27%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%27%27%22%7D%2C%22C3%27%27%22%3A%7B%22parents%22%3A%5B%22C2%27%27%27%22%5D%2C%22id%22%3A%22C3%27%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git rebase -i HEAD~2;git commit --amend;git rebase -i HEAD~2;git rebase caption master",startTree:'{"branches":{"master":{"target":"C1","id":"master"},"newImage":{"target":"C2","id":"newImage"},"caption":{"target":"C3","id":"caption"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"caption","id":"HEAD"}}',name:{ko:"커밋들 갖고 놀기",en_US:"Juggling Commits",ja:"Juggling Commits",zh_CN:"提交变换戏法"},hint:{en_US:"The first command is git rebase -i HEAD~2",ja:"最初に打つコマンドはgit rebase -i HEAD~2",ko:"첫번째 명령은 git rebase -i HEAD~2 입니다",zh_CN:"第一个命令是 'git rebase -i HEAD~2'"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Juggling Commits","","Here's another situation that happens quite commonly. You have some changes (`newImage`) and another set of changes (`caption`) that are related, so they are stacked on top of each other in your repository (aka one after another).","","The tricky thing is that sometimes you need to make a small modification to an earlier commit. In this case, design wants us to change the dimensions of `newImage` slightly, even though that commit is way back in our history!!"]}},{type:"ModalAlert",options:{markdowns:["We will overcome this difficulty by doing the following:","","* We will re-order the commits so the one we want to change is on top with `git rebase -i`","* We will `commit --amend` to make the slight modification","* Then we will re-order the commits back to how they were previously with `git rebase -i`","* Finally, we will move master to this updated part of the tree to finish the level (via the method of your choosing)","","There are many ways to accomplish this overall goal (I see you eye-ing cherry-pick), and we will see more of them later, but for now let's focus on this technique."]}},{type:"ModalAlert",options:{markdowns:["Lastly, pay attention to the goal state here -- since we move the commits twice, they both get an apostrophe appended. One more apostrophe is added for the commit we amend, which gives us the final form of the tree ","","That being said, I can compare levels now based on structure and relative apostrophe differences. As long as your tree's `master` branch has the same structure and relative apostrophe differences, I'll give full credit"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Commitsをやりくりする","","開発中に頻繁に起こるケースをもう1つ考えます。ある変更(`newImage`)とまた別の変更(`caption`)があって、それらに依存関係があるとします。この一連の変更が一列に積み重なっているとします。","","ここでトリッキーなのは、以前のコミットに対して微修正をかけなければならないケースがあるということです。今回の教材でも、過去のコミットであるにも関わらず`newImage`ブランチに僅かな修正を加えるような設計の修正が入ったとしましょう。"]}},{type:"ModalAlert",options:{markdowns:["この困難な状況を、以下の手順で克服することを考えます:","","* `git rebase -i`を使って順番を変更する。これで、変更をかけたいコミットを一番先頭に持ってくる。","* `commit --amend`コマンドで僅かな変更を行う","* `git rebase -i`コマンドを再度使って、先頭に持ってきていたコミットを元に戻す","* 最後に、レベルクリアのためにmasterブランチを先頭に持ってくる","","クリアのための方法はいくつもありますが(cherry-pickを使うこともできます)、別の回答はまた後程の章で見ることにんして、今回は上記の方法でやってみることにしましょう。"]}},{type:"ModalAlert",options:{markdowns:["最後に、ゴール時点での状態に気を付けてください。今回2回ほどコミットを動かしますから、コミットへのポインタにはアポストロフィ(')が追加されます。commit --amendコマンドの実行でできたコミットには更にもう1つのアポストロフィが追加されます。 "]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 提交变换戏法","","下面这种情况也是经常出现的。例如你之前已经在 `newImage` 分支上做了一些提交,然后又在 `caption` 分支上做了一些相关的提交,因此它们看起来是一个连一个的(stacked on top of each other in your repository)。","","有点棘手的就是有时候你又想往先前的提交里做些小改动。呐,现在就是设计师想要我们去轻微改变下 `newImage` 的内容(change the dimensions slightly),尽管那个提交是很久很久以前的了。"]}},{type:"ModalAlert",options:{markdowns:["为了实现他的愿望,我们可以按照下面的方法来做:","","* 先用 `git rebase -i` 将提交重新排序,然后把我们想要修改的提交挪到最前","* 然后用 `commit --amend` 来进行一些小修改","* 接着再用 `git rebase -i` 来将他们按最开始的顺序重新排好","* 最后我们把 master 移到修改的最前端(用你自己喜欢的方法),就大功告成啦!","","当然还有许多方法可以完成这个任务(我知道你在看 cherry-pick 啦),之后我们会多点关注这些技巧啦,但现在暂时只专注上面这种方法。"]}},{type:"ModalAlert",options:{markdowns:["啊最后还要提醒你一下最终的形式 —— 因为我们把这个提交移动了两次,所以会分别产生一个省略提交(both get an apostrophe appended)。还有一个省略提交是因为我们为了实现最终效果去修改提交而添加的。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 커밋들 갖고 놀기","","이번에도 꽤 자주 발생하는 상황입니다. `newImage`와 `caption` 브랜치에 각각의 변경내역이 있고 서로 약간 관련이 있어서, 저장소에 차례로 쌓여있는 상황입니다.","","때로는 이전 커밋의 내용을 살짝 바꿔야하는 골치아픈 상황에 빠지게 됩니다. 이번에는 디자인 쪽에서 우리의 작업이력(history)에서는 이미 한참 전의 커밋 내용에 있는 `newImage`의 크기를 살짝 바꿔달라는 요청이 들어왔습니다."]}},{type:"ModalAlert",options:{markdowns:["이 문제를 다음과 같이 풀어봅시다:","","* `git rebase -i` 명령으로 우리가 바꿀 커밋을 가장 최근 순서로 바꾸어 놓습니다","* `commit --amend` 명령으로 커밋 내용을 정정합니다","* 다시 `git rebase -i` 명령으로 이 전의 커밋 순서대로 되돌려 놓습니다","* 마지막으로, master를 지금 트리가 변경된 부분으로 이동합니다. (편하신 방법으로 하세요)","","이 목표를 달성하기 위해서는 많은 방법이 있는데요(체리픽을 고민중이시죠?), 체리픽은 나중에 더 살펴보기로 하고, 우선은 위의 방법으로 해결해보세요."]}},{type:"ModalAlert",options:{markdowns:["최종적으로, 목표 결과를 눈여겨 보세요 -- 우리가 커밋을 두 번 옮겼기 때문에, 두 커밋 모두 따옴표 표시가 붙어있습니다. 정정한(amend) 커밋은 따옴표가 추가로 하나 더 붙어있습니다."]}}]}}}}),e.define("/levels/mixed/jugglingCommits2.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22master%22%7D%2C%22newImage%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22newImage%22%7D%2C%22caption%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22caption%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%27%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout master;git cherry-pick C2;git commit --amend;git cherry-pick C3",disabledMap:{"git revert":!0},startTree:'{"branches":{"master":{"target":"C1","id":"master"},"newImage":{"target":"C2","id":"newImage"},"caption":{"target":"C3","id":"caption"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"caption","id":"HEAD"}}',compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C2>e.C3},function(e){return e.C2>e.C1}]},name:{ko:"커밋 갖고 놀기 #2",en_US:"Juggling Commits #2",ja:"コミットをやりくりする その2",zh_CN:"提交交换戏法 #2"},hint:{en_US:"Don't forget to forward master to the updated changes!",ja:"masterのポインタを先に進めることを忘れずに!",ko:"master를 변경 완료한 커밋으로 이동(forward)시키는 것을 잊지 마세요!",zh_CN:"别忘记了将 master 快进到最新的更新上!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Juggling Commits #2","","*If you haven't completed Juggling Commits #1 (the previous level), please do so before continuing*","","As you saw in the last level, we used `rebase -i` to reorder the commits. Once the commit we wanted to change was on top, we could easily --amend it and re-order back to our preferred order.","","The only issue here is that there is a lot of reordering going on, which can introduce rebase conflicts. Let's look at another method with `git cherry-pick`"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Remember that git cherry-pick will plop down a commit from anywhere in the tree onto HEAD (as long as that commit isn't upstream).","","Here's a small refresher demo:"],afterMarkdowns:["Nice! Let's move on"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["So in this level, let's accomplish the same objective of amending `C2` once but avoid using `rebase -i`. I'll leave it up to you to figure it out! :D","","Remember, the exact number of apostrophe's (') on the commit are not important, only the relative differences. For example, I will give credit to a tree that matches the goal tree but has one extra apostrophe everywhere"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## コミットをやりくりする その2","","*注意 この一つ前のレベル「コミットをやりくりする」をクリアしていない人は、まずそちらの問題をクリアしてきてください*","","前回見てきたように、コミット順序の変更のために、私たちは`rebase -i`コマンドを利用しました。ツリーの先頭に変更対象のコミットがあれば、--amendオプションを使うことで容易に変更を書きかえて、元の順序に戻すことができます。","","この場合に心配なことが一つだけあって、それは複数回の順序の変更が行われるので、rebaseのコンフリクト(衝突)が起こりうることです。こういうケースへの対策として、`git cherry-pick`を使った別の解決法について考えてみましょう。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["git cherry-pickを使うと、ツリーの中から複数のコミットを選んで、HEADの下に新しく作ることができましたね。","","簡単なデモを見てみましょう:"],afterMarkdowns:["できました!次へ進みましょう"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["このレベルでは、`C2`をamendすることで前回と同じ目的を達成しましょう。但し`rebase -i`は使わずにクリアしてください。どんな方法で進めるかはあなたにおまかせします!:D"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 提交变换戏法 #2","","*假如你还没有完成提交变换戏法 #1(前一关),这关不让玩哦!*","","如你在上一关所见,我们使用 `rebase -i` 来重排那些提交。只要把我们想要的提交挪到最顶端,我们就可以很容易地改变它,然后把它们重新排成我们想要的顺序。","","但唯一的问题就是这样做就要排很多次,有可能造成衍合冲突(rebase conflicts)。下面就看看用另外一种方法 `git cherry-pick` 是怎么做的吧。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["要在心理牢记 cherry-pick 可以从提交树的任何地方拿一个提交来放在 HEAD 上(尽管那个提交不在上游)。","","下面是一个小小的演示:"],command:"git cherry-pick C2",afterMarkdowns:["好滴咧,我们继续"],beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["那么这关呢,和上一关一样要改变提交 `C2`,但你要避免使用 `rebase -i`。自己想想要怎么解决吧,骚年! :D"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 커밋 갖고 놀기 #2","","*만약 이전 레벨의 커밋 갖고 놀기 #1을 풀지 않으셨다면, 계속하기에 앞서서 꼭 풀어보세요*","","이전 레벨에서 보셨듯이 `rebase -i` 명령으로 커밋의 순서를 바꿀 수 있습니다. 정정할 커밋이 바로 직전(top)에 있으면 간단히 --amend로 수정할 수 있고, 그리고 나서 다시 원하는 순서로 되돌려 놓으면 됩니다.","","이번에 한가지 문제는 순서를 꽤 많이 바꿔야한다는 점인데요, 그러다가 리베이스중에 충돌이 날 수 있습니다. 이번에는 다른 방법인 `git cherry-pick`으로 해결해 봅시다."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["git cherry-pick으로 HEAD에다 어떤 커밋이든 떨어 뜨려 놓을 수 있다고 알려드린것 기억나세요? (단, 그 커밋이 현재 가리키고 있는 커밋이 아니어야합니다)","","간단한 데모로 다시 알려드리겠습니다:"],afterMarkdowns:["좋아요! 계속할게요"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["그럼 이번 레벨에서는 아까와 마찬가지로 `C2` 커밋의 내용을 정정하되, `rebase -i`를 쓰지 말고 해보세요. ^.~"]}}]}}}}),e.define("/levels/advanced/multipleParents.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C7","id":"master"},"bugWork":{"target":"C2","id":"bugWork"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C2"],"id":"C5"},"C6":{"parents":["C4","C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',solutionCommand:"git branch bugWork master^^2^",startTree:'{"branches":{"master":{"target":"C7","id":"master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C2"],"id":"C5"},"C6":{"parents":["C4","C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Multiple parents",zh_CN:"多个父提交记录"},hint:{en_US:"Use `git branch bugWork` with a target commit to create the missing reference.",zh_CN:"使用`git branch bugWork`加上一个目标提交记录来创建消失的引用。"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["### Specifying Parents","","Like the `~` modifier, the `^` modifier also accepts an optional number after it.","","Rather than specifying the number of generations to go back (what `~` takes), the modifier on `^` specifies which parent reference to follow from a merge commit. Remember that merge commits have multiple parents, so the path to choose is ambiguous.","",'Git will normally follow the "first" parent upwards from a merge commit, but specifying a number with `^` changes this default behavior.',"","Enough talking, let's see it in action.",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have a merge commit. If we checkout `master^` without the modifier, we will follow the first parent after the merge commit. ","","(*In our visuals, the first parent is positioned directly above the merge commit.*)"],afterMarkdowns:["Easy -- this is what we are all used to."],command:"git checkout master^",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Now let's try specifying the second parent instead..."],afterMarkdowns:["See? We followed the other parent upwards."],command:"git checkout master^2",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["The `^` and `~` modifiers can make moving around a commit tree very powerful:"],afterMarkdowns:["Lightning fast!"],command:"git checkout HEAD~; git checkout HEAD^2; git checkout HEAD~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Even crazier, these modifiers can be chained together! Check this out:"],afterMarkdowns:["The same movement as before, but all in one command."],command:"git checkout HEAD~^2~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"ModalAlert",options:{markdowns:["### Put it to practice","","To complete this level, create a new branch at the specified destination.","","Obviously it would be easy to specify the commit directly (with something like `C6`), but I challenge you to use the modifiers we talked about instead!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["### 选择父提交","","和`~`修改符一样,`^`修改符之后也可以跟一个(可选的)数字。","","这不是用来指定向上返回几代(`~`的作用),`^`后的数字指定跟随合并提交记录的哪一个父提交。还记得一个合并提交有多个父提交吧,所有选择哪条路径不是那么清晰。","",'Git默认选择跟随合并提交的"第一个"父提交,使用`^`后跟一个数字来改变这一默认行为。',"","废话不多说,举个例子。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["这里有一个合并提交。如果不加数字修改符直接切换到`master^`,会回到第一个父提交。","","(*在我们的图示中,第一个父提交是指合并提交正上方的那个父提交。*)"],afterMarkdowns:["OK--这恰好是我们想要的。"],command:"git checkout master^",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["现在来试试选择第二个父提交……"],afterMarkdowns:["看见了吧?我们回到了第二个父提交。"],command:"git checkout master^2",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用`^`和`~`可以自由在在提交树中移动:"],afterMarkdowns:["快若闪电!"],command:"git checkout HEAD~; git checkout HEAD^2; git checkout HEAD~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["再疯狂点,这些修改符支持链式操作!试一下这个:"],afterMarkdowns:["和前面的结果一样,但只用了一条命令。"],command:"git checkout HEAD~^2~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"ModalAlert",options:{markdowns:["### 实践一下","","要完成此关,在指定的目标位置创建一个新的分支。","","很明显可以简单的直接使用提交记录的hash值(比如`C6`),但我要求你使用刚刚讲到的相对引用修饰符!"]}}]}}}}),e.define("/levels/rebase/selectiveRebase.js",function(e,t,n,r,i,s,o){n.level={compareAllBranchesHashAgnostic:!0,disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C5%22%2C%22id%22%3A%22master%22%7D%2C%22one%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22one%22%7D%2C%22two%22%3A%7B%22target%22%3A%22C2%27%27%22%2C%22id%22%3A%22two%22%7D%2C%22three%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22three%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C4%27%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C4%27%27%22%7D%2C%22C3%27%27%22%3A%7B%22parents%22%3A%5B%22C4%27%27%22%5D%2C%22id%22%3A%22C3%27%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C3%27%27%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22two%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout one; git cherry-pick C4 C3 C2; git checkout two; git cherry-pick C5 C4 C3 C2; git branch -f three C2",startTree:'{"branches":{"master":{"target":"C5","id":"master"},"one":{"target":"C1","id":"one"},"two":{"target":"C1","id":"two"},"three":{"target":"C1","id":"three"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C4"],"id":"C5"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{ko:"브랜치 스파게티",en_US:"Branch Spaghetti",ja:"ブランチスパゲッティ",zh_CN:"分支浆糊"},hint:{en_US:"Make sure to do everything in the proper order! Branch one first, then two, then three",ja:"全て正しい順番で処理すること!oneが最初で、次がtwo、最後にthreeを片付ける。",ko:"이 문제를 해결하는 방법은 여러가지가 있습니다! 체리픽(cherry-pick)이 가장 쉽지만 오래걸리는 방법이고, 리베이스(rebase -i)가 빠른 방법입니다",zh_CN:"确保你是按照正确的顺序来操作!先操作分支 `one`, 然后 `two`, 最后才是 `three`"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branch Spaghetti","","WOAHHHhhh Nelly! We have quite the goal to reach in this level.","","Here we have `master` that is a few commits ahead of branches `one` `two` and `three`. For whatever reason, we need to update these three other branches with modified versions of the last few commits on master.","","Branch `one` needs a re-ordering and a deletion of `C5`. `two` needs pure reordering, and `three` only needs one commit!","","We will let you figure out how to solve this one -- make sure to check out our solution afterwards with `show solution`. "]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ブランチスパゲッティ","","なんということでしょう。今回のレベルクリアのために、やることがたくさんあります。","","いま`master`が指しているコミットの数個前のコミットに、ブランチ`one`、`two`それから`three`があります。何か事情があって、これらの3つのブランチをmasterが指している最新の状態に更新したいケースを考えます。","","ブランチ`one`に対しては、順序の変更と`C5`の削除が必要です。`two`では順序の変更のみ、`three`に対しては1回だけコミットすればOKです。","","`show solution`コマンドで模範解答を確認できますから、こちらも利用してください。 "]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branch Spaghetti","","哇塞大神!这关我们要来点不同的!","","现在我们的 `master` 分支是比 `one` `two` 和 `three` 要多几个提交。出于某种原因,我们需要把其他三个分支更新到 master 分支上新近的几个不同提交上。(update these three other brances with modified versions of the last few commits on master)","","分支 `one` 需要重新排序和撤销, `two` 需要完全重排,而 `three` 只需要提交一次。","","慢慢摸索会找到答案的 —— 你完事记得用 `show solution` 看看我们的答案哦。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 브랜치 스파게티","","음, 이번에는 만만치 않습니다!","","여기 `master` 브랜치의 몇 번 이전 커밋에 `one`, `two`,`three` 총 3개의 브랜치가 있습니다. 어떤 이유인지는 몰라도, master의 최근 커밋 몇 개를 나머지 세 개의 브랜치에 반영하려고 합니다.","","`one` 브랜치는 순서를 바꾸고 `C5`커밋을 삭제하고, `two`브랜치는 순서만 바꾸며, `three`브랜치는 하나의 커밋만 가져옵시다!","","자유롭게 이 문제를 풀어보시고 나서 `show solution`명령어로 모범 답안을 확인해보세요."]}}]}}}}),e.define("/src/js/views/levelDropdownView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../intl"),h=e("../log"),p=e("../util/keyboard").KeyboardListener,d=e("../app"),v=e("../views").ModalTerminal,m=e("../views").ContainedBase,g=e("../views").BaseView,y=m.extend({tagName:"div",className:"levelDropdownView box vertical",template:u.template($("#level-dropdown-view").html()),initialize:function(e){e=e||{},this.JSON={},this.navEvents=u.clone(f.Events),this.navEvents.on("clickedID",u.debounce(u.bind(this.loadLevelID,this),300,!0)),this.navEvents.on("negative",this.negative,this),this.navEvents.on("positive",this.positive,this),this.navEvents.on("left",this.left,this),this.navEvents.on("right",this.right,this),this.navEvents.on("up",this.up,this),this.navEvents.on("down",this.down,this),this.keyboardListener=new p({events:this.navEvents,aliasMap:{esc:"negative",enter:"positive"},wait:!0}),this.sequences=d.getLevelArbiter().getSequences(),this.sequenceToLevels=d.getLevelArbiter().getSequenceToLevels(),this.container=new v({title:c.str("select-a-level")}),this.render(),d.getEvents().on("resetMapSolved",this.render,this),d.getEvents().on("localeChanged",this.render,this),e.wait||this.show()},render:function(){y.__super__.render.apply(this,arguments),this.buildSequences()},positive:function(){if(!this.selectedID)return;this.loadLevelID(this.selectedID)},left:function(){if(this.turnOnKeyboardSelection())return;this.leftOrRight(-1)},leftOrRight:function(e){this.deselectIconByID(this.selectedID),this.selectedIndex=this.wrapIndex(this.selectedIndex+e,this.getCurrentSequence()),this.selectedID=this.getSelectedID(),this.selectIconByID(this.selectedID)},right:function(){if(this.turnOnKeyboardSelection())return;this.leftOrRight(1)},up:function(){if(this.turnOnKeyboardSelection())return;this.selectedSequence=this.getPreviousSequence(),this.downOrUp()},down:function(){if(this.turnOnKeyboardSelection())return;this.selectedSequence=this.getNextSequence(),this.downOrUp()},downOrUp:function(){this.selectedIndex=this.boundIndex(this.selectedIndex,this.getCurrentSequence()),this.deselectIconByID(this.selectedID),this.selectedID=this.getSelectedID(),this.selectIconByID(this.selectedID)},turnOnKeyboardSelection:function(){return this.selectedID?!1:(this.selectFirst(),!0)},turnOffKeyboardSelection:function(){if(!this.selectedID)return;this.deselectIconByID(this.selectedID),this.selectedID=undefined,this.selectedIndex=undefined,this.selectedSequence=undefined},wrapIndex:function(e,t){return e=e>=t.length?0:e,e=e<0?t.length-1:e,e},boundIndex:function(e,t){return e=e>=t.length?t.length-1:e,e=e<0?0:e,e},getNextSequence:function(){var e=this.getSequenceIndex(this.selectedSequence),t=this.wrapIndex(e+1,this.sequences);return this.sequences[t]},getPreviousSequence:function(){var e=this.getSequenceIndex(this.selectedSequence),t=this.wrapIndex(e-1,this.sequences);return this.sequences[t]},getSequenceIndex:function(e){var t=this.sequences.indexOf(e);if(t<0)throw new Error("didnt find");return t},getIndexForID:function(e){return d.getLevelArbiter().getLevel(e).index},selectFirst:function(){var e=this.sequenceToLevels[this.sequences[0]][0].id;this.selectIconByID(e),this.selectedIndex=0,this.selectedSequence=this.sequences[0]},getCurrentSequence:function(){return this.sequenceToLevels[this.selectedSequence]},getSelectedID:function(){return this.sequenceToLevels[this.selectedSequence][this.selectedIndex].id},selectIconByID:function(e){this.toggleIconSelect(e,!0)},deselectIconByID:function(e){this.toggleIconSelect(e,!1)},toggleIconSelect:function(e,t){this.selectedID=e;var n="#levelIcon-"+e;$(n).toggleClass("selected",t)},negative:function(){this.hide()},testOption:function(e){return this.currentCommand&&(new RegExp("--"+e)).test(this.currentCommand.get("rawStr"))},show:function(e,t){this.currentCommand=t,this.updateSolvedStatus(),this.showDeferred=e,this.keyboardListener.listen(),y.__super__.show.apply(this)},hide:function(){this.showDeferred&&this.showDeferred.resolve(),this.showDeferred=undefined,this.keyboardListener.mute(),this.turnOffKeyboardSelection(),y.__super__.hide.apply(this)},loadLevelID:function(e){if(!this.testOption("noOutput")){d.getEventBaton().trigger("commandSubmitted","level "+e);var t=d.getLevelArbiter().getLevel(e),n=t.name.en_US;h.levelSelected(n)}this.hide()},updateSolvedStatus:function(){u.each(this.seriesViews,function(e){e.updateSolvedStatus()},this)},buildSequences:function(){this.seriesViews=[],u.each(this.sequences,function(e){this.seriesViews.push(new b({destination:this.$el,name:e,navEvents:this.navEvents}))},this)}}),b=g.extend({tagName:"div",className:"seriesView box flex1 vertical",template:u.template($("#series-view").html()),events:{"click div.levelIcon":"click","mouseenter div.levelIcon":"enterIcon","mouseleave div.levelIcon":"leaveIcon"},initialize:function(e){this.name=e.name||"intro",this.navEvents=e.navEvents,this.info=d.getLevelArbiter().getSequenceInfo(this.name),this.levels=d.getLevelArbiter().getLevelsInSequence(this.name),this.levelIDs=[],u.each(this.levels,function(e){this.levelIDs.push(e.id)},this),this.destination=e.destination,this.JSON={displayName:c.getIntlKey(this.info,"displayName"),about:c.getIntlKey(this.info,"about")||" ",ids:this.levelIDs},this.render(),this.updateSolvedStatus()},updateSolvedStatus:function(){var e=this.$("div.levelIcon").each(function(e,t){var n=$(t).attr("data-id");$(t).toggleClass("solved",d.getLevelArbiter().isLevelSolved(n))})},getEventID:function(e){var t=e.target;return $(t).attr("data-id")},resetAbout:function(){this.$("p.about").text(c.getIntlKey(this.info,"about")).css("font-style","inherit")},setAbout:function(e){this.$("p.about").text(e).css("font-style","italic")},enterIcon:function(e){var t=this.getEventID(e),n=d.getLevelArbiter().getLevel(t);this.setAbout(c.getName(n))},leaveIcon:function(){this.resetAbout()},click:function(e){var t=this.getEventID(e);this.navEvents.trigger("clickedID",t)}});n.LevelDropdownView=y}),e.define("/src/js/views/commandViews.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../models/collections").CommandEntryCollection,l=e("../app"),c=e("../models/commandModel").Command,h=e("../models/commandModel").CommandEntry,p=e("../util/errors"),d=p.Warning,v=e("../util"),m=e("../log"),g=e("../util/keyboard"),y=a.View.extend({initialize:function(e){l.getEvents().on("commandSubmittedPassive",this.addToCommandHistory,this),this.commands=new f,this.commands.fetch({success:u.bind(function(){var e=[];this.commands.each(function(t){e.push(t)}),e.reverse(),this.commands.reset(),u.each(e,function(e){this.commands.add(e)},this)},this)}),this.index=-1,this.commandParagraph=this.$("#prompt p.command")[0],this.commandCursor=this.$("#prompt span.cursor")[0],this.focus(),l.getEvents().on("rollupCommands",this.rollupCommands,this),l.getEventBaton().stealBaton("keydown",this.onKeyDown,this),l.getEventBaton().stealBaton("keyup",this.onKeyUp,this)},events:{"blur #commandTextField":"hideCursor","focus #commandTextField":"showCursor"},blur:function(){this.hideCursor()},focus:function(){this.$("#commandTextField").focus(),this.showCursor()},hideCursor:function(){this.toggleCursor(!1)},showCursor:function(){this.toggleCursor(!0)},toggleCursor:function(e){$(this.commandCursor).toggleClass("shown",e)},onKeyDown:function(e){var t=e.target;this.updatePrompt(t)},onKeyUp:function(e){this.onKeyDown(e);var t={enter:u.bind(function(){this.submit()},this),up:u.bind(function(){this.commandSelectChange(1)},this),down:u.bind(function(){this.commandSelectChange(-1)},this)},n=g.mapKeycodeToKey(e.which||e.keyCode);t[n]!==undefined&&(e.preventDefault(),t[n](),this.onKeyDown(e))},badHtmlEncode:function(e){return e.replace(/&/g,"&").replace(/=this.commands.length||this.index<0){this.clear(),this.index=-1;return}var t=this.commands.toArray()[this.index].get("text");this.setTextField(t)},clearLocalStorage:function(){this.commands.each(function(e){a.sync("delete",e,function(){})},this)},setTextField:function(e){this.$("#commandTextField").val(e)},clear:function(){this.setTextField("")},submit:function(){var e=this.$("#commandTextField").val().replace("\n","");this.clear(),this.submitCommand(e),this.index=-1},rollupCommands:function(e){var t=this.commands.toArray().slice(1,Number(e)+1);t.reverse();var n="";u.each(t,function(e){n+=e.get("text")+";"},this);var r=new h({text:n});this.commands.unshift(r),a.sync("create",r,function(){})},addToCommandHistory:function(e){var t=e.length&&this.index===-1||e.length&&this.index!==-1&&this.commands.toArray()[this.index].get("text")!==e;if(!t)return;var n=new h({text:e});this.commands.unshift(n),a.sync("create",n,function(){}),this.commands.length>100&&this.clearLocalStorage(),m.commandEntered(e)},submitCommand:function(e){l.getEventBaton().trigger("commandSubmitted",e)}}),b=a.View.extend({tagName:"div",model:c,template:u.template($("#command-template").html()),events:{click:"clicked"},clicked:function(e){},initialize:function(){this.model.bind("change",this.wasChanged,this),this.model.bind("destroy",this.remove,this)},wasChanged:function(e,t){var n=t.changes,r=u.keys(n);u.difference(r,["status"]).length===0?this.updateStatus():this.render()},updateStatus:function(){var e=["inqueue","processing","finished"],t={};u.each(e,function(e){t[e]=!1}),t[this.model.get("status")]=!0;var n=this.$("p.commandLine");u.each(t,function(e,t){n.toggleClass(t,e)})},render:function(){var e=u.extend({resultType:"",result:"",formattedWarnings:this.model.getFormattedWarnings()},this.model.toJSON());return this.$el.html(this.template(e)),this},remove:function(){$(this.el).hide()}}),w=a.View.extend({initialize:function(e){this.collection=e.collection,this.collection.on("add",this.addOne,this),this.collection.on("reset",this.addAll,this),this.collection.on("all",this.render,this),this.collection.on("change",this.scrollDown,this),l.getEvents().on("commandScrollDown",this.scrollDown,this),l.getEvents().on("clearOldCommands",this.clearOldCommands,this)},addWarning:function(e){var t=new d({msg:e}),n=new c({error:t,rawStr:"Warning:"});this.collection.add(n)},clearOldCommands:function(){var e=[];this.collection.each(function(t){t.get("status")!=="inqueue"&&t.get("status")!=="processing"&&e.push(t)},this),u.each(e,function(e){e.destroy()},this),this.scrollDown()},scrollDown:function(){var e=$("#commandDisplay")[0],t=$("#terminal")[0],n=e.clientHeight>t.clientHeight||$(window).height()"]}},{type:"ModalAlert",options:{markdowns:["## Git 명령어","","연습 모드에서 쓸 수 있는 다양한 git명령어는 다음과 같습니다",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## 공유해주세요!","","`export tree` 와 `import tree`로 여러분의 친구들에게 트리를 공유해주세요","","훌륭한 학습 자료가 있으신가요? `build level`로 레벨을 만들어 보시거나, 친구의 레벨을 `import level`로 가져와서 실험해보세요","","이제 레슨을 시작해봅시다..."]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Bienvenue sur LearnGitBranching!","","Cette application a été conçue pour aider les débutants à saisir ","les puissants concepts derrière les branches en travaillant ","avec git. Nous espérons que vous apprécierez cette application et ","que vous apprendrez peut-être quelque chose d'intéressant !","","# Démo !","","Si vous n'avez pas vu la démo, vous pouvez le faire là :","","[http://pcottle.github.io/learnGitBranching/?demo](http://pcottle.github.io/learnGitBranching/?demo)","","Agacé par ce dialogue ? Ajoutez `?NODEMO` à l'URL pour le supprimer, en lien ci-dessous pour votre commodité :","","[http://pcottle.github.io/learnGitBranching/?NODEMO](?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## Commandes Git","","Il existe une large variété de commandes git disponibles dans le mode bac à sable. Sont inclues",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## Partager, c'est se soucier!","","Partagez des arbres avec vous amis via `export tree` et `import tree`","","Vous avez une grande leçon à partager ? Essayez de construire un niveau avec `build level` ou essayez le niveau d'un ami avec `import level`","","Pour voir la gamme complète des commandes, tapez `show commands`. Il y a quelques perles telles que `undo` et `reset`","","Mais tout de suite commencez sur les `levels`…"]}}]}}),e.define("/src/js/util/mock.js",function(e,t,n,r,i,s,o){n.mock=function(e){var t={},n=function(){};for(var r in e.prototype)t[r]=n;return t}}),e.define("sys",function(e,t,n,r,i,s,o){t.exports=e("util")}),e.define("child_process",function(e,t,n,r,i,s,o){n.spawn=function(){},n.exec=function(){}}),e.define("/src/js/visuals/tree.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({removeKeys:function(e){u.each(e,function(e){this.get(e)&&this.get(e).remove()},this)},animateAttrKeys:function(e,t,n,r){e=u.extend({},{include:["circle","arrow","rect","path","text"],exclude:[]},e||{});var i=this.getAttributes();u.each(e.include,function(e){i[e]=u.extend({},i[e],t)}),u.each(e.exclude,function(e){delete i[e]}),this.animateToAttr(i,n,r)}});n.VisBase=f}),e.define("/src/js/git/headless.js",function(e,t,n,r,i,s,o){function E(){var e={},t=function(){return f.defer().promise};for(var n in c)e[n]=t;return e.playRefreshAnimationAndFinish=function(e,t){console.log("trying to finish"),t.thenFinish(f.defer().promise)},e}var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("../git").GitEngine,c=e("../visuals/animation/animationFactory").AnimationFactory,h=e("../visuals").GitVisuals,p=e("../git/treeCompare").TreeCompare,d=e("../util/eventBaton").EventBaton,v=e("../models/collections"),m=v.CommitCollection,g=v.BranchCollection,y=e("../models/commandModel").Command,b=e("../util/mock").mock,w=e("../util"),S=function(){this.init()};S.prototype.init=function(){this.commitCollection=new m,this.branchCollection=new g;var e=E(),t=b(h);this.gitEngine=new l({collection:this.commitCollection,branches:this.branchCollection,gitVisuals:t,animationFactory:e,eventBaton:new d}),this.gitEngine.init()},S.prototype.sendCommand=function(e){w.splitTextCommand(e,function(e){var t=new y({rawStr:e});this.gitEngine.dispatch(t,f.defer())},this)},n.HeadlessGit=S}),e.define("/src/js/app/index.js",function(e,t,n,r,i,s,o){function E(){var t=e("../views"),n=e("../models/collections"),r=e("../views/commandViews"),i=new t.MainHelperBar;this.commandCollection=new n.CommandCollection,this.commandBuffer=new n.CommandBuffer({collection:this.commandCollection}),this.commandPromptView=new r.CommandPromptView({el:$("#commandLineBar")}),this.commandLineHistoryView=new r.CommandLineHistoryView({el:$("#commandLineHistory"),collection:this.commandCollection})}var u=e("underscore"),a=e("backbone"),f=e("../util/constants"),l=e("../util"),c=u.clone(a.Events),h,p,d,v,m,g=function(){var t=e("../level/sandbox").Sandbox,n=e("../level").Level,r=e("../util/eventBaton").EventBaton,i=e("../level/arbiter").LevelArbiter,s=e("../views/levelDropdownView").LevelDropdownView;d=new r,h=new E,p=new t,v=new i,m=new s({wait:!0}),c.on("localeChanged",y),b(d),w(p)},y=function(){if(!window.$)return;$("span.intl-aware").each(function(t,n){var r=e("../intl"),i=$(n).attr("data-intl");$(n).text(r.str(i).toUpperCase())})},b=function(e){var t=function(){$("#commandTextField").focus()};t(),$(window).focus(function(t){e.trigger("windowFocus",t)}),$(document).click(function(t){e.trigger("documentClick",t)}),$(document).bind("keydown",function(t){e.trigger("docKeydown",t)}),$(document).bind("keyup",function(t){e.trigger("docKeyup",t)}),$(window).on("resize",function(e){c.trigger("resize",e)}),e.stealBaton("docKeydown",function(){}),e.stealBaton("docKeyup",function(){}),e.stealBaton("windowFocus",t),e.stealBaton("documentClick",t);var n=function(t){return function(){var n=[t];u.each(arguments,function(e){n.push(e)}),e.trigger.apply(e,n)}};$("#commandTextField").on("keydown",n("keydown")),$("#commandTextField").on("keyup",n("keyup")),$(window).trigger("resize")},w=function(e){var t=l.parseQueryString(window.location.href);t.hasOwnProperty("demo")?e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",["git commit; git checkout -b bugFix C1; git commit; git merge master; git checkout master; git commit; git rebase bugFix;","delay 1000; reset;","level rebase1 --noFinishDialog --noStartCommand --noIntroDialog;","delay 2000; show goal; delay 1000; hide goal;","git checkout bugFix; git rebase master; git checkout side; git rebase bugFix;","git checkout another; git rebase side; git rebase another master;","help; levels"].join(""))}):t.hasOwnProperty("NODEMO")||e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",["git help;","delay 1000;","help;","levels"].join(""))}),t.locale!==undefined&&t.locale.length&&(f.GLOBAL.locale=t.locale,c.trigger("localeChanged"));if(t.command){var n=unescape(t.command);e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",n)})}(/(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent)||/android/i.test(navigator.userAgent))&&e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted","mobile alert")})};e("../util").isBrowser()&&$(document).ready(g),n.getEvents=function(){return c},n.getSandbox=function(){return p},n.getEventBaton=function(){return d},n.getCommandUI=function(){return h},n.getLevelArbiter=function(){return v},n.getLevelDropdown=function(){return m},n.init=g}),e("/src/js/app/index.js"),e.define("/src/js/dialogs/confirmShowSolution.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Are you sure you want to see the solution?","","I believe in you! You can do it"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 确定要看答案吗?","","哥相信你!你可以的"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Êtes-vous sûr de vouloir voir la solution ?","","Je crois en vous ! Vous pouvez le faire"]}}]}}),e("/src/js/dialogs/confirmShowSolution.js"),e.define("/src/js/dialogs/levelBuilder.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Welcome to the level builder!","","Here are the main steps:",""," * Set up the initial environment with git commands"," * Define the starting tree with ```define start```"," * Enter the series of git commands that compose the (optimal) solution"," * Define the goal tree with ```define goal```. Defining the goal also defines the solution"," * Optionally define a hint with ```define hint```"," * Edit the name with ```define name```"," * Optionally define a nice start dialog with ```edit dialog```"," * Enter the command ```finish``` to output your level JSON!"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 欢迎使用关卡生成器!","","主要步骤如下:",""," * 使用 git 命令布置好初始环境"," * 使用 ```define start``` 命令定义起始树"," * 输入一系列 git 命令,编好答案"," * 使用 ```define goal``` 命令定义目标树。定义目标的同时定义答案"," * 还可以用 ```define hint``` 命令定义一个提示"," * 用 ```define name``` 修改名称"," * 还可以用 ```edit dialog``` 定义一个漂亮的开始对话框"," * 输入 ```finish``` 就可以输出你的关卡数据(JSON)了!"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Bienvenue dans l'éditeur niveaux !","","Voici les étapes principales :",""," * Mettez en place l'environnement initial avec des commandes git"," * Définissez l'arbre de départ avec ```define start```"," * Saisissez la série de commandes git qui composent la solution (optimale)"," * Définissez l'arbre cible avec ```define goal```. Cela définit aussi la solution"," * Optionnellement, définissez un indice avec ```define hint```"," * Changez le nom avec ```define name```"," * Optionellement, definissez un joli dialogue de départ avec ```edit dialog```"," * Entrez la commande ```finish``` pour délivrer votre niveau JSON!"]}}]}}),e("/src/js/dialogs/levelBuilder.js"),e.define("/src/js/dialogs/nextLevel.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Great Job!!","","You solved the level in *{numCommands}* command(s); ","our solution uses {best}."]}}],ja:[{type:"ModalAlert",options:{markdowns:["## 完成!","","あなたは*{numCommands}*回のコマンドでこの課題をクリアしました; ","模範解答では{best}回です。"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 碉堡了!","","你用 *{numCommands}* 条命令搞定了这一关;我们的答案要用 {best}。"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Beau Travail!!","","Vous avez résolu le niveau en *{numCommands}* commande(s); ","notre solution le fait en {best}."]}}]}}),e("/src/js/dialogs/nextLevel.js"),e.define("/src/js/dialogs/sandbox.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Welcome to LearnGitBranching!","","This application is designed to help beginners grasp ","the powerful concepts behind branching when working ","with git. We hope you enjoy this application and maybe ","even learn something!","","# Demo!","","If you have not seen the demo, please check it out here:","","[http://pcottle.github.io/learnGitBranching/?demo](http://pcottle.github.io/learnGitBranching/?demo)","","Annoyed at this dialog? Append `?NODEMO` to the url to get rid of it, linked below for convenience:","","[http://pcottle.github.io/learnGitBranching/?NODEMO](?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## Git commands","","You have a large variety of git commands available in sandbox mode. These include",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## Sharing is caring!","","Share trees with your friends via `export tree` and `import tree`","","Have a great lesson to share? Try building a level with `build level` or try out a friend's level with `import level`","","To see the full range of commands, try `show commands`. There are some gems like `undo` and `reset`","","For now let's get you started on the `levels`..."]}}],ja:[{type:"ModalAlert",options:{markdowns:["## LearnGitBranchingへようこそ","","gitのパワフルなブランチ機能のコンセプトが ","学びやすくなるようにこのアプリケーションを作りました。 ","このアプリケーションを楽しんで使って頂いて、 ","何かを学習して頂けたなら嬉しいです。","","# とりあえず触ってみたい方へ:","","簡単なデモを用意してあるので、もしよければこちらもご覧ください:","","[http://remore.github.io/learnGitBranching-ja/?demo](http://remore.github.io/learnGitBranching-ja/?demo)","","このダイアログ自体を省略するには、以下のようにURLの末尾にクエリストリング`?NODEMO`を付加してアクセスしてください。","","[http://remore.github.io/learnGitBranching-ja/?NODEMO](http://remore.github.io/learnGitBranching-ja/?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## ここで学べるGitのオペレーション","","ここでは、下記の種類のgitコマンドを学ぶことができます。",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## 学習した内容を共有できます","","画面左のコマンドプロンプトから`export tree`や`import tree`とタイプすることで、gitのツリー構造を友達に送ることができます","","何か教材になるようなケースはご存知ないでしょうか。`build level`で課題を作成したり、`import level`で他の人の課題に挑戦してみてください。","","それでは教材の選択画面に進んでみることにします。"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 欢迎光临 LearnGitBranching!","","本应用旨在帮助初学者领会 git 分支背后的强大概念。","希望你能喜欢这个应用,并学到知识!","","# 演示!","","如果你还没看过演示,请到此查看:","","[http://pcottle.github.io/learnGitBranching/?demo](http://pcottle.github.io/learnGitBranching/?demo)","","厌烦这个对话框? 在 URL 后头加上 `?NODEMO` 就看不到它了,也可以直接点下边这个链接:","","[http://pcottle.github.io/learnGitBranching/?NODEMO](http://pcottle.github.io/learnGitBranching/?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## Git 命令","","在沙盒模式里,你有好多命令可用。 包括:",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## 分享即关怀","","使用 `export tree` 和 `import tree` 与朋友分享 Git 树","","有个好课程可以分享?试试用 `build level` 创建一个关卡,或者 `import level` 试试朋友的。","","言归正传,让我们先从 `levels` 开始……"]}}],ko:[{type:"ModalAlert",options:{markdowns:["## Git 브랜치 배우기를 시작합니다!","","이 애플리케이션은 git을 쓸 때 필요한 브랜치에 대한 개념을","탄탄히 잡게끔 도와드리기 위해 만들었습니다. 재밌게 사용해주시기를","바라며, 무언가를 배워가신다면 더 기쁘겠습니다!","","이 애플리케이션은 [Peter Cottle](https://github.io/pcottle)님의 [LearnGitBranching](http://pcottle.github.io/learnGitBranching/)를 번역한 것입니다.","아래 데모를 먼저 보셔도 좋습니다.","",""]}},{type:"ModalAlert",options:{markdowns:["## Git 명령어","","연습 모드에서 쓸 수 있는 다양한 git명령어는 다음과 같습니다",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## 공유해주세요!","","`export tree` 와 `import tree`로 여러분의 친구들에게 트리를 공유해주세요","","훌륭한 학습 자료가 있으신가요? `build level`로 레벨을 만들어 보시거나, 친구의 레벨을 `import level`로 가져와서 실험해보세요","","이제 레슨을 시작해봅시다..."]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Bienvenue sur LearnGitBranching!","","Cette application a été conçue pour aider les débutants à saisir ","les puissants concepts derrière les branches en travaillant ","avec git. Nous espérons que vous apprécierez cette application et ","que vous apprendrez peut-être quelque chose d'intéressant !","","# Démo !","","Si vous n'avez pas vu la démo, vous pouvez le faire là :","","[http://pcottle.github.io/learnGitBranching/?demo](http://pcottle.github.io/learnGitBranching/?demo)","","Agacé par ce dialogue ? Ajoutez `?NODEMO` à l'URL pour le supprimer, en lien ci-dessous pour votre commodité :","","[http://pcottle.github.io/learnGitBranching/?NODEMO](?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## Commandes Git","","Il existe une large variété de commandes git disponibles dans le mode bac à sable. Sont inclues",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## Partager, c'est se soucier!","","Partagez des arbres avec vous amis via `export tree` et `import tree`","","Vous avez une grande leçon à partager ? Essayez de construire un niveau avec `build level` ou essayez le niveau d'un ami avec `import level`","","Pour voir la gamme complète des commandes, tapez `show commands`. Il y a quelques perles telles que `undo` et `reset`","","Mais tout de suite commencez sur les `levels`…"]}}]}}),e("/src/js/dialogs/sandbox.js"),e.define("/src/js/git/commands.js",function(e,t,n,r,i,s,o){function y(e,t){this.method=e,this.rawOptions=t,this.supportedMap=this.getMasterOptionMap()[e];if(this.supportedMap===undefined)throw new Error("No option map for "+e);this.generalArgs=[],this.explodeAndSet()}var u=e("underscore"),a=e("../intl"),f=e("../util/errors"),l=f.CommandProcessError,c=f.GitError,h=f.Warning,p=f.CommandResult,d={"git commit":/^(gc|git ci)($|\s)/,"git add":/^ga($|\s)/,"git checkout":/^(go|git co)($|\s)/,"git rebase":/^gr($|\s)/,"git branch":/^(gb|git br)($|\s)/,"git status":/^(gst|gs|git st)($|\s)/,"git help":/^git$/},v=[[/^git help($|\s)/,function(){var e=[a.str("git-version"),"
",a.str("git-usage"),u.escape(a.str("git-usage-command")),"
",a.str("git-supported-commands"),"
"],t=y.prototype.getMasterOptionMap();u.each(t,function(t,n){e.push("git "+n),u.each(t,function(t,n){e.push(" "+n)},this)},this);var n=e.join("\n");throw n=n.replace(/\t/g,"   "),new p({msg:n})}]],m={"git commit":/^git +commit($|\s)/,"git add":/^git +add($|\s)/,"git checkout":/^git +checkout($|\s)/,"git rebase":/^git +rebase($|\s)/,"git reset":/^git +reset($|\s)/,"git branch":/^git +branch($|\s)/,"git revert":/^git +revert($|\s)/,"git log":/^git +log($|\s)/,"git merge":/^git +merge($|\s)/,"git show":/^git +show($|\s)/,"git status":/^git +status($|\s)/,"git cherry-pick":/^git +cherry-pick($|\s)/,"git fakeTeamwork":/^git +fakeTeamwork($|\s)/,"git fetch":/^git +fetch *?$/,"git pull":/^git +pull($|\s)/,"git push":/^git +push($|\s)/,"git clone":/^git +clone *?$/},g=function(e){var t,n;u.each(m,function(r,i){r.exec(e)&&(n=e.slice(i.length+1),t=i.slice("git ".length))});if(!t)return!1;var r=new y(t,n);return{toSet:{generalArgs:r.generalArgs,supportedMap:r.supportedMap,method:t,options:n,eventName:"processGitCommand"}}};y.prototype.getMasterOptionMap=function(){return{commit:{"--amend":!1,"-a":!1,"-am":!1,"-m":!1},status:{},log:{},add:{},"cherry-pick":{},branch:{"-d":!1,"-D":!1,"-f":!1,"-a":!1,"-r":!1,"--contains":!1},checkout:{"-b":!1,"-B":!1,"-":!1},reset:{"--hard":!1,"--soft":!1},merge:{},rebase:{"-i":!1},revert:{},show:{},clone:{},fetch:{},pull:{"--rebase":!1},push:{},fakeTeamwork:{}}},y.prototype.explodeAndSet=function(){var e=this.rawOptions.match(/('.*?'|".*?"|\S+)/g)||[];for(var t=0;t9&&(e=e.slice(0,9),this.command.addWarning(l.str("branch-name-short",{branch:e}))),e},y.prototype.validateAndMakeBranch=function(e,t){e=this.validateBranchName(e);if(this.refs[e])throw new v({msg:l.str("bad-branch-name",{branch:name})});this.makeBranch(e,t)},y.prototype.makeBranch=function(e,t){var n=new w({target:t,id:e});return this.branchCollection.add(n),this.refs[n.get("id")]=n,n},y.prototype.getHead=function(){return u.clone(this.HEAD)},y.prototype.getBranches=function(){var e=[];return this.branchCollection.each(function(t){e.push({id:t.get("id"),selected:this.HEAD.get("target")===t,target:t.get("target"),remote:t.getIsRemote(),obj:t})},this),e},y.prototype.getRemoteBranches=function(){var e=this.getBranches();return u.filter(e,function(e){return e.remote===!0})},y.prototype.getLocalBranches=function(){var e=this.getBranches();return u.filter(e,function(e){return e.remote===!1})},y.prototype.printBranchesWithout=function(e){var t=this.getUpstreamBranchSet(),n=this.getCommitFromRef(e).get("id"),r=[];u.each(t[n],function(e){e.selected=this.HEAD.get("target").get("id")==e.id,r.push(e)},this),this.printBranches(r)},y.prototype.printBranches=function(e){var t="";throw u.each(e,function(e){t+=(e.selected?"* ":"")+e.id+"\n"}),new m({msg:t})},y.prototype.getUniqueID=function(){var e=this.uniqueId("C"),t=u.bind(function(e){return this.refs[e]?!0:this.origin&&this.origin.refs[e]?!0:!1},this);while(t(e))e=this.uniqueId("C");return e},y.prototype.makeCommit=function(e,t,n){t||(t=this.getUniqueID());var r=new E(u.extend({parents:e,id:t,gitVisuals:this.gitVisuals},n||{}));return this.refs[r.get("id")]=r,this.commitCollection.add(r),r},y.prototype.acceptNoGeneralArgs=function(){if(this.generalArgs.length)throw new v({msg:l.str("git-error-no-general-args")})},y.prototype.validateArgBounds=function(e,t,n,r){var i=r===undefined?"git "+this.command.get("method"):this.command.get("method")+" "+r+" ";i="with "+i;if(e.lengthn)throw new v({msg:l.str("git-error-args-many",{upper:String(n),what:i})})},y.prototype.oneArgImpliedHead=function(e,t){this.validateArgBounds(e,0,1,t),e.length===0&&e.push("HEAD")},y.prototype.twoArgsImpliedHead=function(e,t){this.validateArgBounds(e,1,2,t),e.length==1&&e.push("HEAD")},y.prototype.revertStarter=function(){this.validateArgBounds(this.generalArgs,1,NaN),this.revert(this.generalArgs)},y.prototype.revert=function(e){var t=u.map(e,function(e){return this.getCommitFromRef(e)},this),n=f.defer(),r=n.promise,i=this.resolveID("HEAD");r=c.highlightEachWithPromise(r,t,i);var s=this.getCommitFromRef("HEAD"),o=u.bind(function(e){var t=this.rebaseAltID(e.get("id")),n=l.str("git-revert-msg",{oldCommit:this.resolveName(e),oldMsg:e.get("commitMessage")}),r=this.makeCommit([s],t,{commitMessage:n});return s=r,c.playCommitBirthPromiseAnimation(r,this.gitVisuals)},this);u.each(t,function(e){r=r.then(function(){return o(e)})},this),r=r.then(u.bind(function(){return this.setTargetLocation("HEAD",s),c.playRefreshAnimation(this.gitVisuals)},this)),this.animationQueue.thenFinish(r,n)},y.prototype.resetStarter=function(){if(this.commandOptions["--soft"])throw new v({msg:l.str("git-error-staging")});this.commandOptions["--hard"]&&(this.command.addWarning(l.str("git-warning-hard")),this.generalArgs=this.generalArgs.concat(this.commandOptions["--hard"])),this.validateArgBounds(this.generalArgs,1,1);if(this.getDetachedHead())throw new v({msg:l.str("git-error-reset-detached")});this.reset(this.generalArgs[0])},y.prototype.reset=function(e){this.setTargetLocation("HEAD",this.getCommitFromRef(e))},y.prototype.cherrypickStarter=function(){this.validateArgBounds(this.generalArgs,1,Number.MAX_VALUE);var e=this.getUpstreamSet("HEAD"),t=u.map(this.generalArgs,function(t){var n=this.getCommitFromRef(t);if(e[n.get("id")])throw new v({msg:l.str("git-error-already-exists",{commit:n.get("id")})});return n},this),n=f.defer(),r=n.promise,i=this.resolveID("HEAD");r=c.highlightEachWithPromise(r,t,i);var s=u.bind(function(e){var t=this.cherrypick(e);return c.playCommitBirthPromiseAnimation(t,this.gitVisuals)},this);u.each(t,function(e){r=r.then(function(){return s(e)})},this),this.animationQueue.thenFinish(r,n)},y.prototype.checkUpstreamOfSource=function(e,t,n,r,i){var s=t.getUpstreamSet(r),o=e.getCommitFromRef(n).get("id");if(!s[o])throw new v({msg:i||l.str("git-error-origin-fetch-no-ff")})},y.prototype.getTargetGraphDifference=function(e,t,n,r,i){i=i||{},r=t.resolveID(r);var s=e.getUpstreamSet(n),o=t.getCommitFromRef(r),a=t.exportTree(),f=a.commits[o.get("id")];if(e.refs[f.id]){if(i.dontThrowOnNoFetch)return[];throw new v({msg:l.str("git-error-origin-fetch-uptodate")})}f.depth=0;var c=[],h=[f],p=function(e){if(s[e])return;var t=a.commits[e];t.depth=d.depth+1,h.push(t)};while(h.length){var d=h.pop();c.push(d),u.each(d.parents,p)}var m={},g=[];return u.forEach(c,function(e){if(m[e.id])return;m[e.id]=!0,g.push(e)}),g.sort(function(e,t){return t.depth-e.depth})},y.prototype.pushStarter=function(e){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.push()},y.prototype.push=function(e){e=e||{};var t=this.refs.master,n=this.origin.refs.master;this.checkUpstreamOfSource(this,this.origin,n,t,l.str("git-error-origin-push-no-ff"));var r=this.getTargetGraphDifference(this.origin,this,n,t),i=u.bind(function(e,t){var n=u.map(t,function(e){return this.origin.refs[e]},this);return this.origin.makeCommit(n,e)},this),s=u.bind(function(e,t){var n=i(e,t);return c.playCommitBirthPromiseAnimation(n,this.origin.gitVisuals)},this),o=f.defer(),a=o.promise;u.each(r,function(e){a=a.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.refs[e.id],n)},this)),a=a.then(function(){return s(e.id,e.parents)})},this),a=a.then(u.bind(function(){var e=t.get("target").get("id"),r=this.origin.refs[e];return this.origin.setTargetLocation(n,r),c.playRefreshAnimation(this.gitVisuals),c.playRefreshAnimation(this.origin.gitVisuals)},this)),a=a.then(u.bind(function(){var e=this.getCommitFromRef(t),n=t.getRemoteBranchIDFromTracking();return this.setTargetLocation(this.refs[n],e),c.playRefreshAnimation(this.gitVisuals)},this)),e.dontResolvePromise||this.animationQueue.thenFinish(a,o)},y.prototype.fetchStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.fetch()},y.prototype.fetch=function(e){e=e||{};var t=this.refs["o/master"],n=this.origin.refs.master;this.checkUpstreamOfSource(this,this.origin,t,n);var r=this.getTargetGraphDifference(this,this.origin,t,n,e);if(r.length===0){this.command.addWarning(l.str("git-error-origin-fetch-uptodate"));var i=f.defer();return{deferred:i,chain:i.promise}}var s=u.bind(function(e,t){var n=u.map(t,function(e){return this.refs[e]},this);return this.makeCommit(n,e)},this),o=u.bind(function(e,t){var n=s(e,t);return c.playCommitBirthPromiseAnimation(n,this.gitVisuals)},this),a=f.defer(),h=a.promise;return u.each(r,function(e){h=h.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.origin.refs[e.id],t)},this)),h=h.then(function(){return o(e.id,e.parents)})},this),h=h.then(u.bind(function(){var e=n.get("target").get("id"),r=this.refs[e];return this.setTargetLocation(t,r),c.playRefreshAnimation(this.origin.gitVisuals),c.playRefreshAnimation(this.gitVisuals)},this)),e.dontResolvePromise||this.animationQueue.thenFinish(h,a),{chain:h,deferred:a}},y.prototype.pullStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.pull()},y.prototype.pull=function(){var e=this.refs.master,t=this.refs["o/master"],n=this.fetch({dontResolvePromise:!0,dontThrowOnNoFetch:!0});this.commandOptions["--rebase"]?this.pullFinishWithRebase(n,e,t):this.pullFinishWithMerge(n,e,t)},y.prototype.pullFinishWithRebase=function(e,t,n){var r=e.chain,i=e.deferred;r=r.then(function(){return c.getDelayedPromise(300)}),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(n),t)},this)),r=r.then(u.bind(function(){return e.dontResolvePromise=!0,this.rebase(n,t,e)},this)),this.animationQueue.thenFinish(r,i)},y.prototype.pullFinishWithMerge=function(e,t,n){var r=e.chain,i=e.deferred;r=r.then(function(){return c.getDelayedPromise(300)}),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(n),t)},this)),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(t),n)},this)),r=r.then(function(){return c.getDelayedPromise(700)}),r=r.then(u.bind(function(){var e=this.merge("o/master");return e?c.playCommitBirthPromiseAnimation(e,this.gitVisuals):c.playRefreshAnimation(this.gitVisuals)},this)),this.animationQueue.thenFinish(r,i)},y.prototype.cloneStarter=function(){this.acceptNoGeneralArgs(),this.makeOrigin(this.printTree())},y.prototype.fakeTeamworkStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.validateArgBounds(this.generalArgs,0,2);var e=this.generalArgs[0]||"master",t=this.generalArgs[1]||1,n=this.origin.resolveID(e);if(n.get("type")!=="branch")throw new v({msg:l.str("git-error-options")});this.fakeTeamwork(t,e)},y.prototype.fakeTeamwork=function(e,t){var n=u.bind(function(){var e=this.getUniqueID();return this.origin.receiveTeamwork(e,t,this.animationQueue)},this),r=u.bind(function(){var e=n();return c.playCommitBirthPromiseAnimation(e,this.origin.gitVisuals)},this),i=function(){return r()},s=f.defer(),o=s.promise;u.each(u.range(e),function(e){o=o.then(function(){return r()})}),this.animationQueue.thenFinish(o,s)},y.prototype.receiveTeamwork=function(e,t,n){this.checkout(this.resolveID(t));var r=this.makeCommit([this.getCommitFromRef("HEAD")],e);return this.setTargetLocation(this.HEAD,r),r},y.prototype.cherrypick=function(e){var t=this.rebaseAltID(e.get("id")),n=this.makeCommit([this.getCommitFromRef("HEAD")],t);return this.setTargetLocation(this.HEAD,n),n},y.prototype.commitStarter=function(){this.acceptNoGeneralArgs();if(this.commandOptions["-am"]&&(this.commandOptions["-a"]||this.commandOptions["-m"]))throw new v({msg:l.str("git-error-options")});var e=null,t=null;this.commandOptions["-a"]&&this.command.addWarning(l.str("git-warning-add")),this.commandOptions["-am"]&&(t=this.commandOptions["-am"],this.validateArgBounds(t,1,1,"-am"),e=t[0]),this.commandOptions["-m"]&&(t=this.commandOptions["-m"],this.validateArgBounds(t,1,1,"-m"),e=t[0]);var n=this.commit();e&&(e=e.replace(/"/g,'"').replace(/^"/g,"").replace(/"$/g,""),n.set("commitMessage",e));var r=c.playCommitBirthPromiseAnimation(n,this.gitVisuals);this.animationQueue.thenFinish(r)},y.prototype.commit=function(){var e=this.getCommitFromRef(this.HEAD),t=null;this.commandOptions["--amend"]&&(e=this.resolveID("HEAD~1"),t=this.rebaseAltID(this.getCommitFromRef("HEAD").get("id")));var n=this.makeCommit([e],t);return this.getDetachedHead()&&this.command.addWarning(l.str("git-warning-detached")),this.setTargetLocation(this.HEAD,n),n},y.prototype.resolveName=function(e){var t=this.resolveID(e);return t.get("type")=="commit"?"commit "+t.get("id"):t.get("type")=="branch"?'branch "'+t.get("id")+'"':this.resolveName(t.get("target"))},y.prototype.resolveID=function(e){if(e===null||e===undefined)throw new Error("Dont call this with null / undefined");return typeof e!="string"?e:this.resolveStringRef(e)},y.prototype.resolveRelativeRef=function(e,t){var n=/([~\^])(\d*)/g,r;while(r=n.exec(t)){var i=e,s=r[2]?parseInt(r[2],10):1;if(r[1]=="^")i=e.getParent(s-1);else while(i&&s--)i=i.getParent(0);if(!i){var o=l.str("git-error-relative-ref",{commit:e.id,match:r[0]});throw new v({msg:o})}e=i}return e},y.prototype.resolveStringRef=function(e){e=this.crappyUnescape(e);if(this.refs[e])return this.refs[e];var t=null,n=null,r=/^([a-zA-Z0-9]+)(([~\^]\d*)*)/,i=r.exec(e);if(!i)throw new v({msg:l.str("git-error-exist",{ref:e})});t=i[1],n=i[2];if(!this.refs[t])throw new v({msg:l.str("git-error-exist",{ref:e})});var s=this.getCommitFromRef(t);return n&&(s=this.resolveRelativeRef(s,n)),s},y.prototype.getCommitFromRef=function(e){var t=this.resolveID(e);while(t.get("type")!=="commit")t=t.get("target");return t},y.prototype.getType=function(e){return this.resolveID(e).get("type")},y.prototype.setTargetLocation=function(e,t){if(this.getType(e)=="commit")return;e=this.getOneBeforeCommit(e),e.set("target",t)},y.prototype.getUpstreamBranchSet=function(){var e={},t=function(e,t){var n=!1;return u.each(e,function(e){e.id==t&&(n=!0)}),n},n=function(e){var t=[],n=[e];while(n.length){var r=n.pop();t.push(r.get("id")),r.get("parents")&&r.get("parents").length&&(n=n.concat(r.get("parents")))}return t};return this.branchCollection.each(function(r){var i=n(r.get("target"));u.each(i,function(n){e[n]=e[n]||[],t(e[n],r.get("id"))||e[n].push({obj:r,id:r.get("id")})})}),e},y.prototype.getUpstreamHeadSet=function(){var e=this.getUpstreamSet("HEAD"),t=this.getCommitFromRef("HEAD").get("id");return e[t]=!0,e},y.prototype.getOneBeforeCommit=function(e){var t=this.resolveID(e);return t===this.HEAD&&!this.getDetachedHead()&&(t=t.get("target")),t},y.prototype.scrapeBaseID=function(e){var t=/^C(\d+)/.exec(e);if(!t)throw new Error("regex failed on "+e);return"C"+t[1]},y.prototype.rebaseAltID=function(e){var t=[[/^C(\d+)[']{0,2}$/,function(e){return e[0]+"'"}],[/^C(\d+)[']{3}$/,function(e){return e[0].slice(0,-3)+"'^4"}],[/^C(\d+)['][\^](\d+)$/,function(e){return"C"+String(e[1])+"'^"+String(Number(e[2])+1)}]];for(var n=0;n",this.get("commitMessage"),"
","Commit: "+this.get("id")].join("\n")+"\n"},getShowEntry:function(){return[this.getLogEntry(),"diff --git a/bigGameResults.html b/bigGameResults.html","--- bigGameResults.html","+++ bigGameResults.html","@@ 13,27 @@ Winner, Score","- Stanfurd, 14-7","+ Cal, 21-14"].join("\n")+"\n"},validateAtInit:function(){if(!this.get("id"))throw new Error("Need ID!!");this.get("createTime")||this.set("createTime",(new Date).toString()),this.get("commitMessage")||this.set("commitMessage",l.str("git-dummy-msg")),this.set("children",[]);if(!this.get("rootCommit"))if(!this.get("parents")||!this.get("parents").length)throw new Error("needs parents")},addNodeToVisuals:function(){var e=this.get("gitVisuals").addNode(this.get("id"),this);this.set("visNode",e)},addEdgeToVisuals:function(e){this.get("gitVisuals").addEdge(this.get("id"),e.get("id"))},getParent:function(e){return this&&this.attributes&&this.attributes.parents?this.attributes.parents[e]:null},isMainParent:function(e){var t=this.get("parents").indexOf(e);return t===0},initialize:function(e){this.validateAtInit(),this.addNodeToVisuals(),u.each(this.get("parents"),function(e){e.get("children").push(this),this.addEdgeToVisuals(e)},this)}});n.GitEngine=y,n.Commit=E,n.Branch=w,n.Ref=b}),e("/src/js/git/index.js"),e.define("/src/js/git/treeCompare.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a={};a.dispatchFromLevel=function(e,t){var n=e.goalTreeString;return a.dispatch(e,n,t)},a.dispatch=function(e,t,n){var r=!0;switch(r){case!!e.compareOnlyMaster:return a.compareBranchWithinTrees(n,t,"master");case!!e.compareOnlyBranches:return a.compareAllBranchesWithinTrees(n,t);case!!e.compareAllBranchesHashAgnostic:return a.compareAllBranchesWithinTreesHashAgnostic(n,t);case!!e.compareOnlyMasterHashAgnostic:return a.compareBranchesWithinTreesHashAgnostic(n,t,["master"]);case!!e.compareOnlyMasterHashAgnosticWithAsserts:return a.compareBranchesWithinTreesHashAgnostic(n,t,["master"])&&a.evalAsserts(n,e.goalAsserts);default:return a.compareAllBranchesWithinTreesAndHEAD(n,t)}},a.compareAllBranchesWithinTreesAndHEAD=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t);debugger;return e.HEAD.target==t.HEAD.target&&this.compareAllBranchesWithinTrees(e,t)},a.compareAllBranchesWithinTrees=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t);var n=u.extend({},e.branches,t.branches),r=!0;return u.uniq(n,function(n,i){r=r&&this.compareBranchWithinTrees(e,t,i)},this),r},a.compareBranchesWithinTrees=function(e,t,n){var r=!0;return u.each(n,function(n){r=r&&this.compareBranchWithinTrees(e,t,n)},this),r},a.compareBranchWithinTrees=function(e,t,n){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var r=this.getRecurseCompare(e,t),i=e.branches[n],s=t.branches[n];return u.isEqual(i,s)&&r(e.commits[i.target],t.commits[s.target])},a.compareAllBranchesWithinTreesHashAgnostic=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var n=u.extend({},e.branches,t.branches),r=[];return u.each(n,function(e,t){r.push(t)}),this.compareBranchesWithinTreesHashAgnostic(e,t,r)},a.compareBranchesWithinTreesHashAgnostic=function(e,t,n){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var r=u.bind(function(e,t){return!e||!t?!1:(e=u.clone(e),t=u.clone(t),e.target=this.getBaseRef(e.target),t.target=this.getBaseRef(t.target),u.isEqual(e,t))},this),i=this.getRecurseCompareHashAgnostic(e,t),s=!0;return u.each(n,function(n){var o=e.branches[n],u=t.branches[n];s=s&&r(o,u)&&i(e.commits[o.target],t.commits[u.target])},this),s},a.evalAsserts=function(e,t){var n=!0;return u.each(t,function(t,r){n=n&&this.evalAssertsOnBranch(e,r,t)},this),n},a.evalAssertsOnBranch=function(e,t,n){e=this.convertTreeSafe(e);if(!e.branches[t])return!1;var r=e.branches[t],i=[r.target],s={};while(i.length){var o=i.pop();s[this.getBaseRef(o)]=this.getNumHashes(o),i=i.concat(e.commits[o].parents)}var a=!0;return u.each(n,function(e){try{a=a&&e(s)}catch(t){console.warn("error during assert",t),console.log(t),a=!1}}),a},a.getNumHashes=function(e){var t=[[/^C(\d+)([']{0,3})$/,function(e){return e[2]?e[2].length:0}],[/^C(\d+)['][\^](\d+)$/,function(e){return Number(e[2])}]];for(var n=0;n []",zh_CN:"git <命令> [<参数>]",fr_FR:"git []"},"git-supported-commands":{__desc__:"In the git help command, the header above the supported commands",en_US:"Supported commands:",zh_CN:"支持的命令有:",fr_FR:"Commandes supportées"},"git-usage":{__desc__:"In the dummy git output, the header before showing all the commands",en_US:"Usage:",zh_CN:"使用:",fr_FR:"Utilisation :"},"git-version":{__desc__:"The git version dummy output, kind of silly. PCOTTLE is my unix name but feel free to put yours instead",en_US:"Git Version PCOTTLE.1.0",zh_CN:"Git 版本 PCOTTLE.1.0",fr_FR:"Git version PCOTTLE.1.0"},"refresh-tree-command":{__desc__:"when the tree is visually refreshed",en_US:"Refreshing tree...",zh_CN:"正在刷新树结构...",fr_FR:"Actualisation de l'arbre…"},"locale-command":{__desc__:"when the locale is set to something",en_US:"Locale set to {locale}",zh_CN:"语言更改为 {locale}",fr_FR:"Langue changée à {locale}"},"locale-reset-command":{__desc__:"when the locale is reset",en_US:"Locale reset to default, which is {locale}",zh_CN:"语言重置为默认的 {locale}",fr_FR:"Langue remise par défaut, qui est {locale}"},"show-command":{__desc__:'command output title from "show"',en_US:"Please use one of the following commands for more info:",fr_FR:"Merci d'utiliser une des commandes suivantes pour obtenir plus d'info"},"show-all-commands":{__desc__:'command output title from "show commands"',en_US:"Here is a list of all the commmands available:",fr_FR:"Ci-dessous est la liste de toutes les commandes disponibles :"},"cd-command":{__desc__:"dummy command output for the command in the key",en_US:'Directory changed to "/directories/dont/matter/in/this/demo"',zh_CN:'目录切换到 "/directories/dont/matter/in/this/demo"',fr_FR:'Répertoire changé à "/directories/dont/matter/in/this/demo" (les répertoires ne servent à rien dans cette démo)'},"ls-command":{__desc__:"Dummy command output for the command in the key",en_US:"DontWorryAboutFilesInThisDemo.txt",zh_CN:"DontWorryAboutFilesInThisDemo.txt (译: 在试验里不用担心文件.txt)",fr_FR:"DontWorryAboutFilesInThisDemo.txt (ne vous préoccupez pas des noms de fichier dans cette démo)"},"mobile-alert":{__desc__:"When someone comes to the site on a mobile device, they can not input commands so this is a nasty alert to tell them",en_US:"Can't bring up the keyboard on mobile / tablet :( try visiting on desktop! :D",zh_CN:"无法在移动设备/平板上调出键盘 :( 请试试桌面版 :D",fr_FR:"Impossible de faire apparaître le clavier sur mobile / tablette :( Essayez de passer sur un ordinateur de bureau :D"},"share-tree":{__desc__:"When you export a tree, we want you to share the tree with friends",en_US:'Share this tree with friends! They can load it with "import tree"',zh_CN:'与你的好友分享提交树!他们可以用 "import tree" 加载它',fr_FR:'Partagez cet arbre avec vos amis ! Ils peuvent le charger avec "import tree"'},"paste-json":{__desc__:"When you are importing a level or tree",en_US:"Paste a JSON blob below!",zh_CN:"在下边粘贴一个JSON串",fr_FR:"Collez un blob JSON ci-dessous !"},"solved-map-reset":{__desc__:"When you reset the solved map to clear your solved history, in case someone else wants to use your browser",en_US:"Solved map was reset, you are starting from a clean slate!",zh_CN:"解决列表已重置,您现在从零开始了",fr_FR:"La carte des niveaux résolus a été effacée, vous repartez de zéro !"},"level-cant-exit":{__desc__:"When the user tries to exit a level when they are not in one",en_US:'You are not in a level! You are in a sandbox, start a level with "levels"',zh_CN:'您没在关卡中!您在沙盒中,要开始关卡请输入 "levels"',fr_FR:'Vous n\'êtes pas dans un niveau ! Vous êtes dans le mode bac à sable, commencez un niveau avec "levels"'},"level-no-id":{__desc__:"When you say an id but that level doesnt exist",en_US:'A level for that id "{id}" was not found! Opening up a level selection view',zh_CN:'没找到id为 "{id}" 的关卡!打开关卡选择框',fr_FR:"Le niveau dont l'identifiant est {id} n'a pas été trouvé ! Ouverture de la vue de sélection des niveaux"},"undo-stack-empty":{__desc__:"The undo command can only undo back until the last time the level was reset or the beginning of the level",en_US:"The undo stack is empty!",zh_CN:"还没有什么可以撤销",fr_FR:"La pile d'annulation est vide !"},"already-solved":{__desc__:"When you play in a level that is already solved",en_US:'You have already solved this level, try other levels with "levels" or go back to sandbox with "sandbox"',zh_CN:'你已经解决了本关,输入 "levels" 尝试其他关卡,或者输入 "sandbox" 回到沙盒中',fr_FR:'Vous avez déjà résolu ce niveau, essayez d\'autres niveaux avec "levels" ou revenez au bac à sable avec "sandbox"'},"command-disabled":{__desc__:"When you try a command that is disabled",en_US:"That git command is disabled for this level!",zh_CN:"该命令在本关不允许使用!",fr_FR:"Cette commande git est désactivée pour ce niveau !"},"share-json":{__desc__:"when you have made the level, prompt to share this",en_US:"Here is the JSON for this level! Share it with somenoe or send it to me on Github",zh_CN:"这是一个关卡定义JSON!您可以分享它或者发到我的GitHub上",fr_FR:"Voici le JSON pour ce niveau ! Partagez-le avec quelqu'un ou envoyez-le moi sur Github"},"want-start-dialog":{__desc__:"prompt to add a start dialog",en_US:"You have not specified a start dialog, would you like to add one?",zh_CN:"您还没有定义一开始的介绍,是否添加一个?",fr_FR:"Vous n'avez pas spécifié de dialogue de départ, voulez-vous en ajouter un ?"},"want-hint":{__desc__:"prompt to add a hint",en_US:"You have not specified a hint, would you like to add one?",zh_CN:"您还没有定义提示,是否添加一个?",fr_FR:"Vous n'avez pas spécifié d'indice, voulez-vous en ajouter un ?"},"prompt-hint":{__desc__:"prompt for hint",en_US:"Enter the hint for this level, or leave this blank if you do not want to include one",zh_CN:"请输入关卡提示,或者故意留空",fr_FR:"Entrez l'indice pour ce niveau, ou laissez-le vide pour ne pas l'inclure"},"prompt-name":{__desc__:"prompt for level name",en_US:"Enter the name for the level",zh_CN:"输入关卡名",fr_FR:"Entrez le nom pour ce niveau"},"solution-empty":{__desc__:"If you define a solution without any commands, aka a level that is solved without doing anything",en_US:"Your solution is empty!! Something is amiss",zh_CN:"你的解法是空的!! 这应该是出错了",fr_FR:"Votre solution est vide !! Quelque chose ne tourne pas rond"},"define-start-warning":{__desc__:"When you define the start point again, it overwrites the solution and goal so we add a warning",en_US:"Defining start point... solution and goal will be overwritten if they were defined earlier",zh_CN:"定义开始点... 解决方法和目标会被新的替代",fr_FR:"Redéfinition du point de départ… la solution et la cible seront écrasés s'ils ont déjà été définis"},"help-vague-level":{__desc__:"When you are in a level and you say help, its vague and you need to specify",en_US:'You are in a level, so multiple forms of help are available. Please select either "help level" to learn more about this lesson, "help general" for using Learn GitBranching, or "objective" to learn about how to solve the level.',zh_CN:'您正在关卡中,这里有多种形式的帮助,请选择 "help level" (关卡帮助)或 "help general" (一般帮助)',fr_FR:'Vous êtes dans un niveau, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help level" pour en apprendre plus sur cette leçon, "help general" pour l\'utilisation de Learn GitBranching, ou "objective" pour apprendre comment résoudre le niveau'},"help-vague-builder":{__desc__:"When you are in a level builder, the help command is vague so you need to specify what you mean",en_US:'You are in a level builder, so multiple forms of help are available. Please select either "help general" or "help builder"',zh_CN:'您正在进行关卡构建中,这里有多种形式的帮助,请选择 "help general" (一般帮助)或 "help builder" (关卡构建帮助)',fr_FR:'Vous êtes dans l\'éditeur de niveaux, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help general" soit "help builder"'},"goal-to-reach":{__desc__:"title of window that shoes the goal tree to reach",en_US:"Goal To Reach",zh_CN:"目标",fr_FR:"Cible à atteindre"},"hide-goal":{__desc__:"the helper message for the window that shows the goal tree",en_US:'You can hide this window with "hide goal"',zh_CN:'你可以通过命令 "hide goal" 关闭这个窗口',fr_FR:'Vous pouvez masquer cette fenêtre avec "hide goal"'},"hide-start":{__desc__:"The helper message for the window that shows the start tree for a level",en_US:'You can hide this window with "hide start"',zh_CN:'你可以通过命令 "hide start" 关闭这个窗口',fr_FR:'Vous pouvez masquer cette fenêtre avec "hide start"'},"level-builder":{__desc__:"The name for the environment where you build levels",en_US:"Level Builder",zh_CN:"关卡生成器",fr_FR:"Éditeur de niveaux"},"no-start-dialog":{__desc__:"when the user tries to open a start dialog for a level that does not have one",en_US:"There is no start dialog to show for this level!",zh_CN:"介绍? 这关真没有!",fr_FR:"Il n'y a aucun dialogue de départ à afficher pour ce niveau !"},"no-hint":{__desc__:"when no hint is available for a level",en_US:"Hmm, there doesn't seem to be a hint for this level :-/",zh_CN:"提示?嗯,这关真没有哎~ :-/",fr_FR:"Hum, il ne semble pas y avoir d'indice pour ce niveau :-/"},"error-untranslated-key":{__desc__:"This error happens when we are trying to translate a specific key and the locale version is mission",en_US:"The translation for {key} does not exist yet :( Please hop on github and offer up a translation!",zh_CN:"还没翻译 {key} :( 请在gitHub上贡献你的翻译!",fr_FR:"La traduction pour {key} n'existe pas encore :( Venez sur Github pour en offrir une !"},"error-untranslated":{__desc__:"The general error when we encounter a dialog that is not translated",en_US:"This dialog or text is not yet translated in your locale :( Hop on github to aid in translation!",zh_CN:"这段对话还没有被翻译成你的语言 :( 欢迎在gitHub上贡献你的翻译!",fr_FR:"Ce message n'a pas encore été traduit dans votre langue :( Venez sur Github aider à la traduction !"}}}),e("/src/js/intl/strings.js"),e.define("/src/js/level/arbiter.js",function(e,t,n,r,i,s,o){function h(){this.levelMap={},this.levelSequences=f,this.sequences=[],this.init();var e;try{e=JSON.parse(localStorage.getItem("solvedMap")||"{}")}catch(t){console.warn("local storage failed",t)}this.solvedMap=e||{},c.getEvents().on("levelSolved",this.levelSolved,this)}var u=e("underscore"),a=e("backbone"),f=e("../../levels").levelSequences,l=e("../../levels").sequenceInfo,c=e("../app");h.prototype.init=function(){var e;u.each(this.levelSequences,function(e,t){this.sequences.push(t);if(!e||!e.length)throw new Error("no empty sequences allowed");u.each(e,function(e,n){this.validateLevel(e);var r=t+String(n+1),i=u.extend({},e,{index:n,id:r,sequenceName:t});this.levelMap[r]=i,this.levelSequences[t][n]=i},this)},this)},h.prototype.isLevelSolved=function(e){if(!this.levelMap[e])throw new Error("that level doesnt exist!");return Boolean(this.solvedMap[e])},h.prototype.levelSolved=function(e){if(!e)return;this.solvedMap[e]=!0,this.syncToStorage()},h.prototype.resetSolvedMap=function(){this.solvedMap={},this.syncToStorage(),c.getEvents().trigger("levelSolved")},h.prototype.syncToStorage=function(){try{localStorage.setItem("solvedMap",JSON.stringify(this.solvedMap))}catch(e){console.warn("local storage fialed on set",e)}},h.prototype.validateLevel=function(e){e=e||{};var t=["name","goalTreeString","solutionCommand"],n=["hint","disabledMap","startTree"];u.each(t,function(t){if(e[t]===undefined)throw console.log(e),new Error("I need this field for a level: "+t)})},h.prototype.getSequenceToLevels=function(){return this.levelSequences},h.prototype.getSequences=function(){return u.keys(this.levelSequences)},h.prototype.getLevelsInSequence=function(e){if(!this.levelSequences[e])throw new Error("that sequecne name "+e+"does not exist");return this.levelSequences[e]},h.prototype.getSequenceInfo=function(e){return l[e]},h.prototype.getLevel=function(e){return this.levelMap[e]},h.prototype.getNextLevel=function(e){if(!this.levelMap[e])return console.warn("that level doesnt exist!!!"),null;var t=this.levelMap[e],n=t.sequenceName,r=this.levelSequences[n],i=t.index+1;if(i","show commands","show solution","show goal"];throw new v({msg:t.join("\n")})}],[/^locale (\w+)$/,function(t){f.GLOBAL.locale=t[1];var n=e("../app").getEvents().trigger("localeChanged");throw new v({msg:l.str("locale-command",{locale:t[1]})})}],[/^refresh$/,function(){var t=e("../app").getEvents();throw t.trigger("refreshTree"),new v({msg:l.str("refresh-tree-command")})}],[/^rollup (\d+)$/,function(t){var n=e("../app").getEvents();throw n.trigger("rollupCommands",t[1]),new v({msg:"Commands combined!"})}],[/^echo "(.*?)"$|^echo (.*?)$/,function(e){var t=e[1]||e[2];throw new v({msg:t})}],[/^show +commands$/,function(e){var t=y(),n=[l.str("show-all-commands"),"
"];throw u.each(t,function(e,t){n.push(t)}),new v({msg:n.join("\n")})}]],g={"reset solved":/^reset solved($|\s)/,help:/^help( +general)?$|^\?$/,reset:/^reset( +--forSolution)?$/,delay:/^delay (\d+)$/,clear:/^clear($|\s)/,"exit level":/^exit level($|\s)/,sandbox:/^sandbox($|\s)/,level:/^level\s?([a-zA-Z0-9]*)/,levels:/^levels($|\s)/,mobileAlert:/^mobile alert($|\s)/,"build level":/^build +level($|\s)/,"export tree":/^export +tree$/,"import tree":/^import +tree$/,"import level":/^import +level$/,undo:/^undo($|\s)/},y=function(){var t=["mobileAlert"],n=u.extend({},e("../git/commands").regexMap,e("../level").regexMap,g);return u.each(t,function(e){delete n[e]}),n};n.instantCommands=m,n.parse=a.genParseCommand(g,"processSandboxCommand"),n.getOptimisticLevelParse=function(){return a.genParseCommand(e("../level").regexMap,"processLevelCommand")},n.getOptimisticLevelBuilderParse=function(){return a.genParseCommand(e("../level/builder").regexMap,"processLevelBuilderCommand")}}),e("/src/js/level/sandboxCommands.js"),e.define("/src/js/log/index.js",function(e,t,n,r,i,s,o){var u=function(e,t,n){window._gaq=window._gaq||[],window._gaq.push(["_trackEvent",e,t,n])};n.viewInteracted=function(e){u("views","interacted",e)},n.showLevelSolution=function(e){u("levels","showedLevelSolution",e)},n.choseNextLevel=function(e){u("levels","nextLevelChosen",e)},n.levelSelected=function(e){u("levels","levelSelected",e)},n.levelSolved=function(e){u("levels","levelSolved",e)},n.commandEntered=function(e){u("commands","commandEntered",e)}}),e("/src/js/log/index.js"),e.define("/src/js/models/collections.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?f=window.Backbone:f=e("backbone"),l=e("../git").Commit,c=e("../git").Branch,h=e("../models/commandModel").Command,p=e("../models/commandModel").CommandEntry,d=e("../util/constants").TIME,v=f.Collection.extend({model:l}),m=f.Collection.extend({model:h}),g=f.Collection.extend({model:c}),y=f.Collection.extend({model:p,localStorage:f.LocalStorage?new f.LocalStorage("CommandEntries"):null}),b=f.Model.extend({defaults:{collection:null},initialize:function(e){e.collection.bind("add",this.addCommand,this),this.buffer=[],this.timeout=null},addCommand:function(e){this.buffer.push(e),this.touchBuffer()},touchBuffer:function(){if(this.timeout)return;this.setTimeout()},setTimeout:function(){this.timeout=setTimeout(u.bind(function(){this.sipFromBuffer()},this),d.betweenCommandsDelay)},popAndProcess:function(){var e=this.buffer.shift(0);while(e.get("error")&&this.buffer.length)e=this.buffer.shift(0);e.get("error")?this.clear():this.processCommand(e)},processCommand:function(t){t.set("status","processing");var n=a.defer();n.promise.then(u.bind(function(){this.setTimeout()},this));var r=t.get("eventName");if(!r)throw new Error("I need an event to trigger when this guy is parsed and ready");var i=e("../app"),s=i.getEventBaton(),o=s.getNumListeners(r);if(!o){var f=e("../util/errors");t.set("error",new f.GitError({msg:"That command is valid, but not supported in this current environment! Try entering a level or level builder to use that command"})),n.resolve();return}i.getEventBaton().trigger(r,t,n)},clear:function(){clearTimeout(this.timeout),this.timeout=null},sipFromBuffer:function(){if(!this.buffer.length){this.clear();return}this.popAndProcess()}});n.CommitCollection=v,n.CommandCollection=m,n.BranchCollection=g,n.CommandEntryCollection=y,n.CommandBuffer=b}),e("/src/js/models/collections.js"),e.define("/src/js/models/commandModel.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../util/errors"),l=e("../git/commands"),c=l.GitOptionParser,h=e("../level/parseWaterfall").ParseWaterfall,p=f.CommandProcessError,d=f.GitError,v=f.Warning,m=f.CommandResult,g=a.Model.extend({defaults:{status:"inqueue",rawStr:null,result:"",createTime:null,error:null,warnings:null,parseWaterfall:new h,generalArgs:null,supportedMap:null,options:null,method:null},initialize:function(e){this.initDefaults(),this.validateAtInit(),this.on("change:error",this.errorChanged,this),this.get("error")&&this.errorChanged(),this.parseOrCatch()},initDefaults:function(){this.set("generalArgs",[]),this.set("supportedMap",{}),this.set("warnings",[])},validateAtInit:function(){if(this.get("rawStr")===null)throw new Error("Give me a string!");this.get("createTime")||this.set("createTime",(new Date).toString())},setResult:function(e){this.set("result",e)},finishWith:function(e){this.set("status","finished"),e.resolve()},addWarning:function(e){this.get("warnings").push(e),this.set("numWarnings",this.get("numWarnings")?this.get("numWarnings")+1:1)},getFormattedWarnings:function(){if(!this.get("warnings").length)return"";var e='';return"

"+e+this.get("warnings").join("

"+e)+"

"},parseOrCatch:function(){this.expandShortcuts(this.get("rawStr"));try{this.processInstants()}catch(e){f.filterError(e),this.set("error",e);return}if(this.parseAll())return;this.set("error",new p({msg:'The command "'+this.get("rawStr")+"\" isn't supported, sorry!"}))},errorChanged:function(){var e=this.get("error");e instanceof p||e instanceof d?this.set("status","error"):e instanceof m?this.set("status","finished"):e instanceof v&&this.set("status","warning"),this.formatError()},formatError:function(){this.set("result",this.get("error").toResult())},expandShortcuts:function(e){e=this.get("parseWaterfall").expandAllShortcuts(e),this.set("rawStr",e)},processInstants:function(){var e=this.get("rawStr");if(!e.length)throw new m({msg:""});this.get("parseWaterfall").processAllInstants(e)},parseAll:function(){var e=this.get("rawStr"),t=this.get("parseWaterfall").parseAll(e);return t?(u.each(t.toSet,function(e,t){this.set(t,e)},this),!0):!1}}),y=a.Model.extend({defaults:{text:""}});n.CommandEntry=y,n.Command=g}),e("/src/js/models/commandModel.js"),e.define("/src/js/util/constants.js",function(e,t,n,r,i,s,o){var u={betweenCommandsDelay:400},a={isAnimating:!1},f={minZoom:.55,maxZoom:1.25,minWidth:600,minHeight:600},l={arrowHeadSize:8,nodeRadius:17,curveControlPointOffset:50,defaultEasing:"easeInOut",defaultAnimationTime:400,rectFill:"hsb(0.8816909813322127,0.7,1)",headRectFill:"#2831FF",rectStroke:"#FFF",rectStrokeWidth:"3",originDash:"- ",multiBranchY:20,upstreamHeadOpacity:.5,upstreamNoneOpacity:.2,edgeUpstreamHeadOpacity:.4,edgeUpstreamNoneOpacity:.15,visBranchStrokeWidth:2,visBranchStrokeColorNone:"#333",defaultNodeFill:"hsba(0.5,0.8,0.7,1)",defaultNodeStrokeWidth:2,defaultNodeStroke:"#FFF",orphanNodeFill:"hsb(0.5,0.8,0.7)"};n.GLOBAL=a,n.TIME=u,n.GRAPHICS=l,n.VIEWPORT=f}),e("/src/js/util/constants.js"),e.define("/src/js/util/debug.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a={Tree:e("../visuals/tree"),Visuals:e("../visuals"),Git:e("../git"),CommandModel:e("../models/commandModel"),Levels:e("../git/treeCompare"),Constants:e("../util/constants"),Collections:e("../models/collections"),Async:e("../visuals/animation"),AnimationFactory:e("../visuals/animation/animationFactory"),Main:e("../app"),HeadLess:e("../git/headless"),Q:{Q:e("q")},RebaseView:e("../views/rebaseView"),Views:e("../views"),MultiView:e("../views/multiView"),ZoomLevel:e("../util/zoomLevel"),VisBranch:e("../visuals/visBranch"),Level:e("../level"),Sandbox:e("../level/sandbox"),GitDemonstrationView:e("../views/gitDemonstrationView"),Markdown:e("markdown"),LevelDropdownView:e("../views/levelDropdownView"),BuilderViews:e("../views/builderViews"),Intl:e("../intl")};u.each(a,function(e){for(var t in e)window["debug_"+t]=e[t]}),$(document).ready(function(){window.events=a.Main.getEvents(),window.eventBaton=a.Main.getEventBaton(),window.sandbox=a.Main.getSandbox(),window.modules=a,window.levelDropdown=a.Main.getLevelDropdown(),window.under=u,window.copyTree=function(){return a.Main.getSandbox().mainVis.gitEngine.printAndCopyTree()}})}),e("/src/js/util/debug.js"),e.define("/src/js/util/errors.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({defaults:{type:"MyError",msg:"Unknown Error"},toString:function(){return this.get("type")+": "+this.get("msg")},getMsg:function(){return this.get("msg")||"Unknown Error"},toResult:function(){return this.get("msg").length?"

"+this.get("msg").replace(/\n/g,"

")+"

":""}}),l=n.CommandProcessError=f.extend({defaults:{type:"Command Process Error"}}),c=n.CommandResult=f.extend({defaults:{type:"Command Result"}}),h=n.Warning=f.extend({defaults:{type:"Warning"}}),p=n.GitError=f.extend({defaults:{type:"Git Error"}}),d=function(e){if(e instanceof l||e instanceof p||e instanceof c||e instanceof h)return;throw e};n.filterError=d}),e("/src/js/util/errors.js"),e.define("/src/js/util/eventBaton.js",function(e,t,n,r,i,s,o){function a(){this.eventMap={}}var u=e("underscore");a.prototype.stealBaton=function(e,t,n){if(!e)throw new Error("need name");if(!t)throw new Error("need func!");var r=this.eventMap[e]||[];r.push({func:t,context:n}),this.eventMap[e]=r},a.prototype.sliceOffArgs=function(e,t){var n=[];for(var r=e;r0&&!e.length)return;t(e)})},n.genParseCommand=function(e,t){return function(n){var r,i;return u.each(e,function(e,t){var s=e.exec(n);s&&(r=t,i=s)}),r?{toSet:{eventName:t,method:r,regexResults:i}}:!1}}}),e("/src/js/util/index.js"),e.define("/src/js/util/keyboard.js",function(e,t,n,r,i,s,o){function c(e){this.events=e.events||u.clone(a.Events),this.aliasMap=e.aliasMap||{},e.wait||this.listen()}var u=e("underscore"),a=e("backbone"),f=e("../app"),l=function(e){var t={37:"left",38:"up",39:"right",40:"down",27:"esc",13:"enter"};return t[e]};c.prototype.listen=function(){if(this.listening)return;this.listening=!0,f.getEventBaton().stealBaton("docKeydown",this.keydown,this)},c.prototype.mute=function(){this.listening=!1,f.getEventBaton().releaseBaton("docKeydown",this.keydown,this)},c.prototype.keydown=function(e){var t=e.which||e.keyCode,n=l(t);if(n===undefined)return;this.fireEvent(n,e)},c.prototype.fireEvent=function(e,t){e=this.aliasMap[e]||e,this.events.trigger(e,t)},c.prototype.passEventBack=function(e){f.getEventBaton().passBatonBackSoft("docKeydown",this.keydown,this,[e])},n.KeyboardListener=c,n.mapKeycodeToKey=l}),e("/src/js/util/keyboard.js"),e.define("/src/js/util/mock.js",function(e,t,n,r,i,s,o){n.mock=function(e){var t={},n=function(){};for(var r in e.prototype)t[r]=n;return t}}),e("/src/js/util/mock.js"),e.define("/src/js/util/zoomLevel.js",function(e,t,n,r,i,s,o){function f(){return!window.outerWidth||!window.innerWidth?(a&&(console.warn("Can't detect zoom level correctly :-/"),a=!1),1):window.outerWidth/window.innerWidth}var u=e("underscore"),a=!0,l=!0,c=function(e,t){var n=0;setInterval(function(){var r=f();if(r!==n){if(l){l=!1;return}n=r,e.apply(t,[r])}else l=!0},500)};n.setupZoomPoll=c,n.detectZoom=f}),e("/src/js/util/zoomLevel.js"),e.define("/src/js/views/builderViews.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../intl"),h=e("../util/keyboard").KeyboardListener,p=e("../views"),d=p.ModalTerminal,v=p.ContainedBase,m=v.extend({tagName:"div",className:"textGrabber box vertical",template:u.template($("#text-grabber").html()),initialize:function(e){e=e||{},this.JSON={helperText:e.helperText||"Enter some text"},this.container=e.container||new d({title:"Enter some text"}),this.render(),e.initialText&&this.setText(e.initialText),e.wait||this.show()},getText:function(){return this.$("textarea").val()},setText:function(e){this.$("textarea").val(e)}}),g=v.extend({tagName:"div",className:"markdownGrabber box horizontal",template:u.template($("#markdown-grabber-view").html()),events:{"keyup textarea":"keyup"},initialize:function(e){e=e||{},this.deferred=e.deferred||a.defer(),e.fromObj&&(e.fillerText=e.fromObj.options.markdowns.join("\n")),this.JSON={previewText:e.previewText||"Preview",fillerText:e.fillerText||"## Enter some markdown!\n\n\n"},this.container=e.container||new d({title:e.title||"Enter some markdown"}),this.render();if(!e.withoutButton){var t=a.defer();t.promise.then(u.bind(this.confirmed,this)).fail(u.bind(this.cancelled,this)).done();var n=new p.ConfirmCancelView({deferred:t,destination:this.getDestination()})}this.updatePreview(),e.wait||this.show()},confirmed:function(){this.die(),this.deferred.resolve(this.getRawText())},cancelled:function(){this.die(),this.deferred.resolve()},keyup:function(){this.throttledPreview||(this.throttledPreview=u.throttle(u.bind(this.updatePreview,this),500)),this.throttledPreview()},getRawText:function(){return this.$("textarea").val()},exportToArray:function(){return this.getRawText().split("\n")},getExportObj:function(){return{markdowns:this.exportToArray()}},updatePreview:function(){var t=this.getRawText(),n=e("markdown").markdown.toHTML(t);this.$("div.insidePreview").html(n)}}),y=v.extend({tagName:"div",className:"markdownPresenter box vertical",template:u.template($("#markdown-presenter").html()),initialize:function(e){e=e||{},this.deferred=e.deferred||a.defer(),this.JSON={previewText:e.previewText||"Here is something for you",fillerText:e.fillerText||"# Yay"},this.container=new d({title:"Check this out..."}),this.render();if(!e.noConfirmCancel){var t=new p.ConfirmCancelView({destination:this.getDestination()});t.deferred.promise.then(u.bind(function(){this.deferred.resolve(this.grabText())},this)).fail(u.bind(function(){this.deferred.reject()},this)).done(u.bind(this.die,this))}this.show()},grabText:function(){return this.$("textarea").val()}}),b=v.extend({tagName:"div",className:"demonstrationBuilder box vertical",template:u.template($("#demonstration-builder").html()),events:{"click div.testButton":"testView"},initialize:function(e){e=e||{},this.deferred=e.deferred||a.defer();if(e.fromObj){var t=e.fromObj.options;e=u.extend({},e,t,{beforeMarkdown:t.beforeMarkdowns.join("\n"),afterMarkdown:t.afterMarkdowns.join("\n")})}this.JSON={},this.container=new d({title:"Demonstration Builder"}),this.render(),this.beforeMarkdownView=new g({container:this,withoutButton:!0,fillerText:e.beforeMarkdown,previewText:"Before demonstration Markdown"}),this.beforeCommandView=new m({container:this,helperText:"The git command(s) to set up the demonstration view (before it is displayed)",initialText:e.beforeCommand||"git checkout -b bugFix"}),this.commandView=new m({container:this,helperText:"The git command(s) to demonstrate to the reader",initialText:e.command||"git commit"}),this.afterMarkdownView=new g({container:this,withoutButton:!0,fillerText:e.afterMarkdown,previewText:"After demonstration Markdown"});var n=a.defer(),r=new p.ConfirmCancelView({deferred:n,destination:this.getDestination()});n.promise.then(u.bind(this.confirmed,this)).fail(u.bind(this.cancelled,this)).done()},testView:function(){var t=e("../views/multiView").MultiView;new t({childViews:[{type:"GitDemonstrationView",options:this.getExportObj()}]})},getExportObj:function(){return{beforeMarkdowns:this.beforeMarkdownView.exportToArray(),afterMarkdowns:this.afterMarkdownView.exportToArray(),command:this.commandView.getText(),beforeCommand:this.beforeCommandView.getText()}},confirmed:function(){this.die(),this.deferred.resolve(this.getExportObj())},cancelled:function(){this.die(),this.deferred.resolve()},getInsideElement:function(){return this.$(".insideBuilder")[0]}}),w=v.extend({tagName:"div",className:"multiViewBuilder box vertical",template:u.template($("#multi-view-builder").html()),typeToConstructor:{ModalAlert:g,GitDemonstrationView:b},events:{"click div.deleteButton":"deleteOneView","click div.testButton":"testOneView","click div.editButton":"editOneView","click div.testEntireView":"testEntireView","click div.addView":"addView","click div.saveView":"saveView","click div.cancelView":"cancel"},initialize:function(e){e=e||{},this.deferred=e.deferred||a.defer(),this.multiViewJSON=e.multiViewJSON||{},this.JSON={views:this.getChildViews(),supportedViews:u.keys(this.typeToConstructor)},this.container=new d({title:"Build a MultiView!"}),this.render(),this.show()},saveView:function(){this.hide(),this.deferred.resolve(this.multiViewJSON)},cancel:function(){this.hide(),this.deferred.resolve()},addView:function(e){var t=e.target,n=$(t).attr("data-type"),r=a.defer(),i=this.typeToConstructor[n],s=new i({deferred:r});r.promise.then(u.bind(function(){var e={type:n,options:s.getExportObj()};this.addChildViewObj(e)},this)).fail(function(){}).done()},testOneView:function(t){var n=t.target,r=$(n).attr("data-index"),i=this.getChildViews()[r],s=e("../views/multiView").MultiView;new s({childViews:[i]})},testEntireView:function(){var t=e("../views/multiView").MultiView;new t({childViews:this.getChildViews()})},editOneView:function(e){var t=e.target,n=$(t).attr("data-index"),r=$(t).attr("data-type"),i=a.defer(),s=new this.typeToConstructor[r]({deferred:i,fromObj:this.getChildViews()[n]});i.promise.then(u.bind(function(){var e={type:r,options:s.getExportObj()},t=this.getChildViews();t[n]=e,this.setChildViews(t)},this)).fail(function(){}).done()},deleteOneView:function(e){var t=e.target,n=$(t).attr("data-index"),r=this.getChildViews(),i=r.slice(0,n).concat(r.slice(n+1));this.setChildViews(i),this.update()},addChildViewObj:function(e,t){var n=this.getChildViews();n.push(e),this.setChildViews(n),this.update()},setChildViews:function(e){this.multiViewJSON.childViews=e},getChildViews:function(){return this.multiViewJSON.childViews||[]},update:function(){this.JSON.views=this.getChildViews(),this.renderAgain()}});n.MarkdownGrabber=g,n.DemonstrationBuilder=b,n.TextGrabber=m,n.MultiViewBuilder=w,n.MarkdownPresenter=y}),e("/src/js/views/builderViews.js"),e.define("/src/js/views/commandViews.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../models/collections").CommandEntryCollection,l=e("../app"),c=e("../models/commandModel").Command,h=e("../models/commandModel").CommandEntry,p=e("../util/errors"),d=p.Warning,v=e("../util"),m=e("../log"),g=e("../util/keyboard"),y=a.View.extend({initialize:function(e){l.getEvents().on("commandSubmittedPassive",this.addToCommandHistory,this),this.commands=new f,this.commands.fetch({success:u.bind(function(){var e=[];this.commands.each(function(t){e.push(t)}),e.reverse(),this.commands.reset(),u.each(e,function(e){this.commands.add(e)},this)},this)}),this.index=-1,this.commandParagraph=this.$("#prompt p.command")[0],this.commandCursor=this.$("#prompt span.cursor")[0],this.focus(),l.getEvents().on("rollupCommands",this.rollupCommands,this),l.getEventBaton().stealBaton("keydown",this.onKeyDown,this),l.getEventBaton().stealBaton("keyup",this.onKeyUp,this)},events:{"blur #commandTextField":"hideCursor","focus #commandTextField":"showCursor"},blur:function(){this.hideCursor()},focus:function(){this.$("#commandTextField").focus(),this.showCursor()},hideCursor:function(){this.toggleCursor(!1)},showCursor:function(){this.toggleCursor(!0)},toggleCursor:function(e){$(this.commandCursor).toggleClass("shown",e)},onKeyDown:function(e){var t=e.target;this.updatePrompt(t)},onKeyUp:function(e){this.onKeyDown(e);var t={enter:u.bind(function(){this.submit()},this),up:u.bind(function(){this.commandSelectChange(1)},this),down:u.bind(function(){this.commandSelectChange(-1)},this)},n=g.mapKeycodeToKey(e.which||e.keyCode);t[n]!==undefined&&(e.preventDefault(),t[n](),this.onKeyDown(e))},badHtmlEncode:function(e){return e.replace(/&/g,"&").replace(/=this.commands.length||this.index<0){this.clear(),this.index=-1;return}var t=this.commands.toArray()[this.index].get("text");this.setTextField(t)},clearLocalStorage:function(){this.commands.each(function(e){a.sync("delete",e,function(){})},this)},setTextField:function(e){this.$("#commandTextField").val(e)},clear:function(){this.setTextField("")},submit:function(){var e=this.$("#commandTextField").val().replace("\n","");this.clear(),this.submitCommand(e),this.index=-1},rollupCommands:function(e){var t=this.commands.toArray().slice(1,Number(e)+1);t.reverse();var n="";u.each(t,function(e){n+=e.get("text")+";"},this);var r=new h({text:n});this.commands.unshift(r),a.sync("create",r,function(){})},addToCommandHistory:function(e){var t=e.length&&this.index===-1||e.length&&this.index!==-1&&this.commands.toArray()[this.index].get("text")!==e;if(!t)return;var n=new h({text:e});this.commands.unshift(n),a.sync("create",n,function(){}),this.commands.length>100&&this.clearLocalStorage(),m.commandEntered(e)},submitCommand:function(e){l.getEventBaton().trigger("commandSubmitted",e)}}),b=a.View.extend({tagName:"div",model:c,template:u.template($("#command-template").html()),events:{click:"clicked"},clicked:function(e){},initialize:function(){this.model.bind("change",this.wasChanged,this),this.model.bind("destroy",this.remove,this)},wasChanged:function(e,t){var n=t.changes,r=u.keys(n);u.difference(r,["status"]).length===0?this.updateStatus():this.render()},updateStatus:function(){var e=["inqueue","processing","finished"],t={};u.each(e,function(e){t[e]=!1}),t[this.model.get("status")]=!0;var n=this.$("p.commandLine");u.each(t,function(e,t){n.toggleClass(t,e)})},render:function(){var e=u.extend({resultType:"",result:"",formattedWarnings:this.model.getFormattedWarnings()},this.model.toJSON());return this.$el.html(this.template(e)),this},remove:function(){$(this.el).hide()}}),w=a.View.extend({initialize:function(e){this.collection=e.collection,this.collection.on("add",this.addOne,this),this.collection.on("reset",this.addAll,this),this.collection.on("all",this.render,this),this.collection.on("change",this.scrollDown,this),l.getEvents().on("commandScrollDown",this.scrollDown,this),l.getEvents().on("clearOldCommands",this.clearOldCommands,this)},addWarning:function(e){var t=new d({msg:e}),n=new c({error:t,rawStr:"Warning:"});this.collection.add(n)},clearOldCommands:function(){var e=[];this.collection.each(function(t){t.get("status")!=="inqueue"&&t.get("status")!=="processing"&&e.push(t)},this),u.each(e,function(e){e.destroy()},this),this.scrollDown()},scrollDown:function(){var e=$("#commandDisplay")[0],t=$("#terminal")[0],n=e.clientHeight>t.clientHeight||$(window).height() p.uiButton":"positive"},initialize:function(t){t=t||{},this.options=t,this.JSON=u.extend({beforeMarkdowns:["## Git Commits","","Awesome!"],command:"git commit",afterMarkdowns:["Now you have seen it in action","","Go ahead and try the level!"]},t);var n=function(t){return e("markdown").markdown.toHTML(t.join("\n"))};this.JSON.beforeHTML=n(this.JSON.beforeMarkdowns),this.JSON.afterHTML=n(this.JSON.afterMarkdowns),this.container=new p({title:t.title||"Git Demonstration"}),this.render(),this.checkScroll(),this.navEvents=u.clone(f.Events),this.navEvents.on("positive",this.positive,this),this.navEvents.on("negative",this.negative,this),this.keyboardListener=new c({events:this.navEvents,aliasMap:{enter:"positive",right:"positive",left:"negative"},wait:!0}),this.visFinished=!1,this.initVis(),t.wait||this.show()},receiveMetaNav:function(e,t){var n=this;e.navEvents.on("positive",this.positive,this),this.metaContainerView=t},checkScroll:function(){var e=this.$("div.demonstrationText").children(),t=u.map(e,function(e){return e.clientHeight}),n=u.reduce(t,function(e,t){return e+t});np.VIEWPORT.minWidth&&e.h>p.VIEWPORT.minHeight&&this.finish()}}),O=L.extend({initialize:function(e){if(!e||!e.level)throw new Error("need level");this.eventBatonName="zoomChange",this.markdowns=["## That zoom level of "+e.level+" is not supported :-/","Please zoom back to a supported zoom level with Ctrl + and Ctrl -","","(and of course, pull requests to fix this are appreciated :D)"],O.__super__.initialize.apply(this,[e])},batonFired:function(e){e<=p.VIEWPORT.maxZoom&&e>=p.VIEWPORT.minZoom&&this.finish()}}),M=m.extend({tagName:"div",className:"levelToolbarHolder",template:u.template($("#level-toolbar-template").html()),initialize:function(e){e=e||{},this.JSON={name:e.name||"Some level! (unknown name)"},this.beforeDestination=$($("#commandLineHistory div.toolbar")[0]),this.render(),e.wait||s.nextTick(u.bind(this.show,this))},getAnimationTime:function(){return 700},render:function(){var e=this.template(this.JSON);this.$el.html(e),this.beforeDestination.after(this.el)},die:function(){this.hide(),setTimeout(u.bind(function(){this.tearDown()},this),this.getAnimationTime())},hide:function(){this.$("div.toolbar").toggleClass("hidden",!0)},show:function(){this.$("div.toolbar").toggleClass("hidden",!1)}}),_=m.extend({tagName:"div",className:"helperBar transitionAll",template:u.template($("#helper-bar-template").html()),events:{"click a":"onClick"},onClick:function(e){var t=e.target,n=$(t).attr("data-id"),r="on"+n[0].toUpperCase()+n.slice(1)+"Click";this[r].call(this)},show:function(){this.$el.toggleClass("show",!0)},hide:function(){this.$el.toggleClass("show",!1),this.deferred&&this.deferred.resolve()},getItems:function(){return[]},setupChildren:function(){},fireCommand:function(e){l.getEventBaton().trigger("commandSubmitted",e)},showDeferMe:function(e){this.hide();var t=a.defer();e.deferred=t,t.promise.then(u.bind(function(){this.show()},this)),e.show()},onExitClick:function(){this.hide()},initialize:function(e){e=e||{},this.destination=$("body"),this.JSON={items:this.getItems()},this.render(),this.setupChildren(),e.wait||this.show()}}),D=_.extend({getItems:function(){return[{text:"Git Branching",id:"english"},{text:"日本語版リポジトリ",id:"japanese"},{text:"Git 브랜치 배우기",id:"korean"},{text:"学习Git分支",id:"chinese"},{text:"français",id:"french"},{icon:"signout",id:"exit"}]},fireCommand:function(){h.viewInteracted("intlSelect"),_.prototype.fireCommand.apply(this,arguments)},onJapaneseClick:function(){this.fireCommand("locale ja; levels"),this.hide()},onEnglishClick:function(){this.fireCommand("locale en_US; levels"),this.hide()},onKoreanClick:function(){this.fireCommand("locale ko; levels"),this.hide()},onFrenchClick:function(){this.fireCommand("locale fr_FR; levels"),this.hide()},onChineseClick:function(){this.fireCommand("locale zh_CN; levels"),this.hide()}}),P=_.extend({getItems:function(){return[{text:"Levels",id:"levels"},{text:"Reset",id:"reset"},{text:"Undo",id:"undo"},{text:"Objective",id:"objectve"},{text:"Help",id:"help"},{icon:"signout",id:"exit"}]},fireCommand:function(){h.viewInteracted("helperBar"),_.prototype.fireCommand.apply(this,arguments)},onObjectiveClick:function(){this.fireCommand("objective")},onLevelsClick:function(){this.fireCommand("levels")},onResetClick:function(){this.fireCommand("reset")},onUndoClick:function(){this.fireCommand("undo")},onHelpClick:function(){this.fireCommand("help general; git help")}}),H=_.extend({getItems:function(){return[{icon:"question-sign",id:"commands"},{icon:"globe",id:"intl"}]},onIntlClick:function(){this.showDeferMe(this.intlHelper),h.viewInteracted("openIntlBar")},onCommandsClick:function(){this.showDeferMe(this.commandsHelper),h.viewInteracted("openCommandsBar")},setupChildren:function(){this.commandsHelper=new P({wait:!0}),this.intlHelper=new D({wait:!0})}}),B=m.extend({tagName:"div",className:"canvasTerminalHolder box flex1",template:u.template($("#terminal-window-bare-template").html()),events:{"click div.wrapper":"onClick"},initialize:function(e){e=e||{},this.destination=$("body"),this.JSON={title:e.title||c.str("goal-to-reach"),text:e.text||c.str("hide-goal")},this.render(),this.inDom=!0,e.additionalClass&&this.$el.addClass(e.additionalClass)},getAnimationTime:function(){return 700},onClick:function(){this.die()},die:function(){this.slideOut(),this.inDom=!1,setTimeout(u.bind(function(){this.tearDown()},this),this.getAnimationTime())},slideOut:function(){this.slideToggle(!0)},slideIn:function(){this.slideToggle(!1)},slideToggle:function(e){this.$("div.terminal-window-holder").toggleClass("slideOut",e)},getCanvasLocation:function(){return this.$("div.inside")[0]}});n.BaseView=m,n.GeneralButton=w,n.ModalView=x,n.ModalTerminal=T,n.ModalAlert=N,n.ContainedBase=b,n.ConfirmCancelView=E,n.LeftRightView=S,n.ZoomAlertWindow=O,n.ConfirmCancelTerminal=C,n.WindowSizeAlertWindow=A,n.MainHelperBar=H,n.CanvasTerminalHolder=B,n.LevelToolbar=M,n.NextLevelConfirm=k}),e("/src/js/views/index.js"),e.define("/src/js/views/levelDropdownView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../intl"),h=e("../log"),p=e("../util/keyboard").KeyboardListener,d=e("../app"),v=e("../views").ModalTerminal,m=e("../views").ContainedBase,g=e("../views").BaseView,y=m.extend({tagName:"div",className:"levelDropdownView box vertical",template:u.template($("#level-dropdown-view").html()),initialize:function(e){e=e||{},this.JSON={},this.navEvents=u.clone(f.Events),this.navEvents.on("clickedID",u.debounce(u.bind(this.loadLevelID,this),300,!0)),this.navEvents.on("negative",this.negative,this),this.navEvents.on("positive",this.positive,this),this.navEvents.on("left",this.left,this),this.navEvents.on("right",this.right,this),this.navEvents.on("up",this.up,this),this.navEvents.on("down",this.down,this),this.keyboardListener=new p({events:this.navEvents,aliasMap:{esc:"negative",enter:"positive"},wait:!0}),this.sequences=d.getLevelArbiter().getSequences(),this.sequenceToLevels=d.getLevelArbiter().getSequenceToLevels(),this.container=new v({title:c.str("select-a-level")}),this.render(),d.getEvents().on("resetMapSolved",this.render,this),d.getEvents().on("localeChanged",this.render,this),e.wait||this.show()},render:function(){y.__super__.render.apply(this,arguments),this.buildSequences()},positive:function(){if(!this.selectedID)return;this.loadLevelID(this.selectedID)},left:function(){if(this.turnOnKeyboardSelection())return;this.leftOrRight(-1)},leftOrRight:function(e){this.deselectIconByID(this.selectedID),this.selectedIndex=this.wrapIndex(this.selectedIndex+e,this.getCurrentSequence()),this.selectedID=this.getSelectedID(),this.selectIconByID(this.selectedID)},right:function(){if(this.turnOnKeyboardSelection())return;this.leftOrRight(1)},up:function(){if(this.turnOnKeyboardSelection())return;this.selectedSequence=this.getPreviousSequence(),this.downOrUp()},down:function(){if(this.turnOnKeyboardSelection())return;this.selectedSequence=this.getNextSequence(),this.downOrUp()},downOrUp:function(){this.selectedIndex=this.boundIndex(this.selectedIndex,this.getCurrentSequence()),this.deselectIconByID(this.selectedID),this.selectedID=this.getSelectedID(),this.selectIconByID(this.selectedID)},turnOnKeyboardSelection:function(){return this.selectedID?!1:(this.selectFirst(),!0)},turnOffKeyboardSelection:function(){if(!this.selectedID)return;this.deselectIconByID(this.selectedID),this.selectedID=undefined,this.selectedIndex=undefined,this.selectedSequence=undefined},wrapIndex:function(e,t){return e=e>=t.length?0:e,e=e<0?t.length-1:e,e},boundIndex:function(e,t){return e=e>=t.length?t.length-1:e,e=e<0?0:e,e},getNextSequence:function(){var e=this.getSequenceIndex(this.selectedSequence),t=this.wrapIndex(e+1,this.sequences);return this.sequences[t]},getPreviousSequence:function(){var e=this.getSequenceIndex(this.selectedSequence),t=this.wrapIndex(e-1,this.sequences);return this.sequences[t]},getSequenceIndex:function(e){var t=this.sequences.indexOf(e);if(t<0)throw new Error("didnt find");return t},getIndexForID:function(e){return d.getLevelArbiter().getLevel(e).index},selectFirst:function(){var e=this.sequenceToLevels[this.sequences[0]][0].id;this.selectIconByID(e),this.selectedIndex=0,this.selectedSequence=this.sequences[0]},getCurrentSequence:function(){return this.sequenceToLevels[this.selectedSequence]},getSelectedID:function(){return this.sequenceToLevels[this.selectedSequence][this.selectedIndex].id},selectIconByID:function(e){this.toggleIconSelect(e,!0)},deselectIconByID:function(e){this.toggleIconSelect(e,!1)},toggleIconSelect:function(e,t){this.selectedID=e;var n="#levelIcon-"+e;$(n).toggleClass("selected",t)},negative:function(){this.hide()},testOption:function(e){return this.currentCommand&&(new RegExp("--"+e)).test(this.currentCommand.get("rawStr"))},show:function(e,t){this.currentCommand=t,this.updateSolvedStatus(),this.showDeferred=e,this.keyboardListener.listen(),y.__super__.show.apply(this)},hide:function(){this.showDeferred&&this.showDeferred.resolve(),this.showDeferred=undefined,this.keyboardListener.mute(),this.turnOffKeyboardSelection(),y.__super__.hide.apply(this)},loadLevelID:function(e){if(!this.testOption("noOutput")){d.getEventBaton().trigger("commandSubmitted","level "+e);var t=d.getLevelArbiter().getLevel(e),n=t.name.en_US;h.levelSelected(n)}this.hide()},updateSolvedStatus:function(){u.each(this.seriesViews,function(e){e.updateSolvedStatus()},this)},buildSequences:function(){this.seriesViews=[],u.each(this.sequences,function(e){this.seriesViews.push(new b({destination:this.$el,name:e,navEvents:this.navEvents}))},this)}}),b=g.extend({tagName:"div",className:"seriesView box flex1 vertical",template:u.template($("#series-view").html()),events:{"click div.levelIcon":"click","mouseenter div.levelIcon":"enterIcon","mouseleave div.levelIcon":"leaveIcon"},initialize:function(e){this.name=e.name||"intro",this.navEvents=e.navEvents,this.info=d.getLevelArbiter().getSequenceInfo(this.name),this.levels=d.getLevelArbiter().getLevelsInSequence(this.name),this.levelIDs=[],u.each(this.levels,function(e){this.levelIDs.push(e.id)},this),this.destination=e.destination,this.JSON={displayName:c.getIntlKey(this.info,"displayName"),about:c.getIntlKey(this.info,"about")||" ",ids:this.levelIDs},this.render(),this.updateSolvedStatus()},updateSolvedStatus:function(){var e=this.$("div.levelIcon").each(function(e,t){var n=$(t).attr("data-id");$(t).toggleClass("solved",d.getLevelArbiter().isLevelSolved(n))})},getEventID:function(e){var t=e.target;return $(t).attr("data-id")},resetAbout:function(){this.$("p.about").text(c.getIntlKey(this.info,"about")).css("font-style","inherit")},setAbout:function(e){this.$("p.about").text(e).css("font-style","italic")},enterIcon:function(e){var t=this.getEventID(e),n=d.getLevelArbiter().getLevel(t);this.setAbout(c.getName(n))},leaveIcon:function(){this.resetAbout()},click:function(e){var t=this.getEventID(e);this.navEvents.trigger("clickedID",t)}});n.LevelDropdownView=y}),e("/src/js/views/levelDropdownView.js"),e.define("/src/js/views/multiView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../views").ModalTerminal,c=e("../views").ContainedBase,h=e("../views").ConfirmCancelView,p=e("../views").LeftRightView,d=e("../views").ModalAlert,v=e("../views/gitDemonstrationView").GitDemonstrationView,m=e("../views/builderViews"),g=m.MarkdownPresenter,y=e("../util/keyboard").KeyboardListener,b=e("../util/errors").GitError,w=f.View.extend({tagName:"div",className:"multiView",navEventDebounce:550,deathTime:700,typeToConstructor:{ModalAlert:d,GitDemonstrationView:v,MarkdownPresenter:g},initialize:function(e){e=e||{},this.childViewJSONs=e.childViews||[{type:"ModalAlert",options:{markdown:"Woah wtf!!"}},{type:"GitDemonstrationView",options:{command:"git checkout -b side; git commit; git commit"}},{type:"ModalAlert",options:{markdown:"Im second"}}],this.deferred=e.deferred||a.defer(),this.childViews=[],this.currentIndex=0,this.navEvents=u.clone(f.Events),this.navEvents.on("negative",this.getNegFunc(),this),this.navEvents.on("positive",this.getPosFunc(),this),this.navEvents.on("quit",this.finish,this),this.navEvents.on("exit",this.finish,this),this.keyboardListener=new y({events:this.navEvents,aliasMap:{left:"negative",right:"positive",enter:"positive",esc:"quit"}}),this.render(),e.wait||this.start()},onWindowFocus:function(){},getAnimationTime:function(){return 700},getPromise:function(){return this.deferred.promise},getPosFunc:function(){return u.debounce(u.bind(function(){this.navForward()},this),this.navEventDebounce,!0)},getNegFunc:function(){return u.debounce(u.bind(function(){this.navBackward()},this),this.navEventDebounce,!0)},lock:function(){this.locked=!0},unlock:function(){this.locked=!1},navForward:function(){if(this.locked)return;if(this.currentIndex===this.childViews.length-1){this.hideViewIndex(this.currentIndex),this.finish();return}this.navIndexChange(1)},navBackward:function(){if(this.currentIndex===0)return;this.navIndexChange(-1)},navIndexChange:function(e){this.hideViewIndex(this.currentIndex),this.currentIndex+=e,this.showViewIndex(this.currentIndex)},hideViewIndex:function(e){this.childViews[e].hide()},showViewIndex:function(e){this.childViews[e].show()},finish:function(){this.keyboardListener.mute(),u.each(this.childViews,function(e){e.die()}),this.deferred.resolve()},start:function(){this.showViewIndex(this.currentIndex)},createChildView:function(e){var t=e.type;if(!this.typeToConstructor[t])throw new Error('no constructor for type "'+t+'"');var n=new this.typeToConstructor[t](u.extend({},e.options,{wait:!0}));return n},addNavToView:function(e,t){var n=new p({events:this.navEvents,destination:e.getDestination(),showLeft:t!==0,lastNav:t===this.childViewJSONs.length-1});e.receiveMetaNav&&e.receiveMetaNav(n,this)},render:function(){u.each(this.childViewJSONs,function(e,t){var n=this.createChildView(e);this.childViews.push(n),this.addNavToView(n,t)},this)}});n.MultiView=w}),e("/src/js/views/multiView.js"),e.define("/src/js/views/rebaseView.js",function(e,t,n,r,i,s,o){var u=e("../util/errors").GitError,a=e("underscore"),f=e("q"),l=e("../util").isBrowser()?window.Backbone:e("backbone"),c=e("../views").ModalTerminal,h=e("../views").ContainedBase,p=e("../views").ConfirmCancelView,d=e("../views").LeftRightView,v=h.extend({tagName:"div",template:a.template($("#interactive-rebase-template").html()),initialize:function(e){this.deferred=e.deferred,this.rebaseMap={},this.entryObjMap={},this.rebaseEntries=new g,e.toRebase.reverse(),a.each(e.toRebase,function(e){var t=e.get("id");this.rebaseMap[t]=e,this.entryObjMap[t]=new m({id:t}),this.rebaseEntries.add(this.entryObjMap[t])},this),this.container=new c({title:"Interactive Rebase"}),this.render(),this.show()},confirm:function(){this.die();var e=[];this.$("ul.rebaseEntries li").each(function(t,n){e.push(n.id)});var t=[];a.each(e,function(e){this.entryObjMap[e].get("pick")&&t.unshift(this.rebaseMap[e])},this),t.reverse(),this.deferred.resolve(t),this.$el.html("")},render:function(){var e={num:a.keys(this.rebaseMap).length},t=this.container.getInsideElement();this.$el.html(this.template(e)),$(t).append(this.el);var n=this.$("ul.rebaseEntries");this.rebaseEntries.each(function(e){new y({el:n,model:e})},this),n.sortable({axis:"y",placeholder:"rebaseEntry transitionOpacity ui-state-highlight",appendTo:"parent"}),this.makeButtons()},makeButtons:function(){var e=f.defer();e.promise.then(a.bind(function(){this.confirm()},this)).fail(a.bind(function(){this.hide(),this.deferred.resolve([])},this)).done(),new p({destination:this.$(".confirmCancel"),deferred:e})}}),m=l.Model.extend({defaults:{pick:!0},toggle:function(){this.set("pick",!this.get("pick"))}}),g=l.Collection.extend({model:m}),y=l.View.extend({tagName:"li",template:a.template($("#interactive-rebase-entry-template").html()),toggle:function(){this.model.toggle(),this.listEntry.toggleClass("notPicked",!this.model.get("pick"))},initialize:function(e){this.render()},render:function(){var e=this.model.toJSON();this.$el.append(this.template(this.model.toJSON())),this.listEntry=this.$el.children(":last"),this.listEntry.delegate("#toggleButton","click",a.bind(function(){this.toggle()},this))}});n.InteractiveRebaseView=v}),e("/src/js/views/rebaseView.js"),e.define("/src/js/visuals/animation/animationFactory.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("./index").Animation,c=e("./index").PromiseAnimation,h=e("../../util/constants").GRAPHICS,p={},d=function(e,t){var n=h.defaultAnimationTime*1,r=n*2,i=function(){e.refreshTree(n),t.setBirth(),t.parentInFront(),e.visBranchesFront(),t.animateUpdatedPosition(r,"bounce"),t.animateOutgoingEdges(n)};return{animation:i,duration:Math.max(n,r)}},v=function(e,t){var n=h.defaultAnimationTime*.66,r=n*2;return{animation:function(){e.highlightTo(t,r,"easeInOut")},duration:r*1.5}};p.genCommitBirthAnimation=function(e,t,n){if(!e)throw new Error("Need animation queue to add closure to!");var r=t.get("visNode"),i=d(n,r);e.add(new l({closure:i.animation,duration:i.duration}))},p.genCommitBirthPromiseAnimation=function(e,t){var n=e.get("visNode");return new c(d(t,n))},p.highlightEachWithPromise=function(e,t,n){return u.each(t,function(t){e=e.then(u.bind(function(){return this.playHighlightPromiseAnimation(t,n)},this))},this),e},p.playCommitBirthPromiseAnimation=function(e,t){var n=this.genCommitBirthPromiseAnimation(e,t);return n.play(),n.getPromise()},p.playRefreshAnimationAndFinish=function(e,t){var n=new c({closure:function(){e.refreshTree()}});n.play(),t.thenFinish(n.getPromise())},p.playRefreshAnimation=function(e){var t=new c({closure:function(){e.refreshTree()}});return t.play(),t.getPromise()},p.refreshTree=function(e,t){e.add(new l({closure:function(){t.refreshTree()}}))},p.genHighlightPromiseAnimation=function(e,t){var n=t.get("visBranch")||t.get("visNode"),r=e.get("visNode");return new c(v(r,n))},p.playHighlightPromiseAnimation=function(e,t){var n=this.genHighlightPromiseAnimation(e,t);return n.play(),n.getPromise()},p.getDelayedPromise=function(e){var t=f.defer();return setTimeout(t.resolve,e||1e3),t.promise},p.delay=function(e,t){t=t||h.defaultAnimationTime,e.add(new l({closure:function(){},duration:t}))},n.AnimationFactory=p}),e("/src/js/visuals/animation/animationFactory.js"),e.define("/src/js/visuals/animation/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("backbone"),l=e("../../util/constants").GLOBAL,c=f.Model.extend({defaults:{duration:300,closure:null},validateAtInit:function(){if(!this.get("closure"))throw new Error("give me a closure!")},initialize:function(e){this.validateAtInit()},run:function(){this.get("closure")()}}),h=f.Model.extend({defaults:{animations:null,index:0,callback:null,defer:!1,promiseBased:!1},initialize:function(e){this.set("animations",[]),e.callback||console.warn("no callback")},thenFinish:function(e,t){e.then(u.bind(function(){this.finish()},this)),this.set("promiseBased",!0),t&&t.resolve()},add:function(e){if(!e instanceof c)throw new Error("Need animation not something else");this.get("animations").push(e)},start:function(){this.set("index",0),l.isAnimating=!0,this.next()},finish:function(){l.isAnimating=!1,this.get("callback")()},next:function(){var e=this.get("animations"),t=this.get("index");if(t>=e.length){this.finish();return}var n=e[t],r=n.get("duration");n.run(),this.set("index",t+1),setTimeout(u.bind(function(){this.next()},this),r)}}),p=f.Model.extend({defaults:{deferred:null,closure:null,duration:300},initialize:function(e){if(!e.closure&&!e.animation)throw new Error("need closure or animation");this.set("closure",e.closure||e.animation),this.set("deferred",e.deferred||a.defer())},getPromise:function(){return this.get("deferred").promise},play:function(){this.get("closure")(),setTimeout(u.bind(function(){this.get("deferred").resolve()},this),this.get("duration"))},then:function(e){return this.get("deferred").promise.then(e)}});p.fromAnimation=function(e){return new p({closure:e.get("closure"),duration:e.get("duration")})},n.Animation=c,n.PromiseAnimation=p,n.AnimationQueue=h}),e("/src/js/visuals/animation/index.js"),e.define("/src/js/visuals/index.js",function(e,t,n,r,i,s,o){function w(t){t=t||{},this.options=t,this.visualization=t.visualization,this.commitCollection=t.commitCollection,this.branchCollection=t.branchCollection,this.visNodeMap={},this.visEdgeCollection=new b,this.visBranchCollection=new g,this.commitMap={},this.rootCommit=null,this.branchStackMap=null,this.upstreamBranchSet=null,this.upstreamHeadSet=null,this.paper=t.paper,this.gitReady=!1,this.branchCollection.on("add",this.addBranchFromEvent,this),this.branchCollection.on("remove",this.removeBranch,this),this.deferred=[],this.flipFraction=.65;var n=e("../app");n.getEvents().on("refreshTree",this.refreshTree,this)}function E(e){var t=0,n=0,r=0,i=0,s=e.length;u.each(e,function(e){var s=e.split("(")[1];s=s.split(")")[0],s=s.split(","),r+=parseFloat(s[1]),i+=parseFloat(s[2]);var o=parseFloat(s[0]),u=o*Math.PI*2;t+=Math.cos(u),n+=Math.sin(u)}),t/=s,n/=s,r/=s,i/=s;var o=Math.atan2(n,t)/(Math.PI*2);return o<0&&(o+=1),"hsb("+String(o)+","+String(r)+","+String(i)+")"}var u=e("underscore"),a=e("q"),f=e("backbone"),l=e("../util/constants").GRAPHICS,c=e("../util/constants").GLOBAL,h=e("../models/collections"),p=h.CommitCollection,d=h.BranchCollection,v=e("../visuals/visNode").VisNode,m=e("../visuals/visBranch").VisBranch,g=e("../visuals/visBranch").VisBranchCollection,y=e("../visuals/visEdge").VisEdge,b=e("../visuals/visEdge").VisEdgeCollection;w.prototype.defer=function(e){this.deferred.push(e)},w.prototype.deferFlush=function(){u.each(this.deferred,function(e){e()},this),this.deferred=[]},w.prototype.resetAll=function(){var e=this.visEdgeCollection.toArray();u.each(e,function(e){e.remove()},this);var t=this.visBranchCollection.toArray();u.each(t,function(e){e.remove()},this),u.each(this.visNodeMap,function(e){e.remove()},this),this.visEdgeCollection.reset(),this.visBranchCollection.reset(),this.visNodeMap={},this.rootCommit=null,this.commitMap={}},w.prototype.tearDown=function(){this.resetAll(),this.paper.remove()},w.prototype.assignGitEngine=function(e){this.gitEngine=e,this.initHeadBranch(),this.deferFlush()},w.prototype.getVisualization=function(){return this.visualization},w.prototype.initHeadBranch=function(){this.addBranchFromEvent(this.gitEngine.HEAD)},w.prototype.getScreenPadding=function(){return{widthPadding:l.nodeRadius*1.5,topHeightPadding:l.nodeRadius*1.5,bottomHeightPadding:l.nodeRadius*5}},w.prototype.getPosBoundaries=function(){return this.gitEngine.hasOrigin()?{min:0,max:.5}:this.gitEngine.isOrigin()?{min:.5,max:1}:{min:0,max:1}},w.prototype.getFlipPos=function(){var e=this.getPosBoundaries(),t=e.min,n=e.max;return this.flipFraction*(n-t)+t},w.prototype.toScreenCoords=function(e){if(!this.paper.width)throw new Error("being called too early for screen coords");var t=this.getScreenPadding(),n=function(e,t,n){return n+e*(t-n*2)},r=function(e,t,n,r){return n+e*(t-r-n)};return{x:n(e.x,this.paper.width,t.widthPadding),y:r(e.y,this.paper.height,t.topHeightPadding,t.bottomHeightPadding)}},w.prototype.animateAllAttrKeys=function(e,t,n,r){var i=a.defer(),s=function(i){i.animateAttrKeys(e,t,n,r)};this.visBranchCollection.each(s),this.visEdgeCollection.each(s),u.each(this.visNodeMap,s);var o=n!==undefined?n:l.defaultAnimationTime;return setTimeout(function(){i.resolve()},o),i.promise},w.prototype.finishAnimation=function(){var e=this,t=a.defer(),n=a.defer(),r=l.defaultAnimationTime,i=l.nodeRadius,s="Solved!!\n:D",o=null,f=u.bind(function(){o=this.paper.text(this.paper.width/2,this.paper.height/2,s),o.attr({opacity:0,"font-weight":500,"font-size":"32pt","font-family":"Monaco, Courier, font-monospace",stroke:"#000","stroke-width":2,fill:"#000"}),o.animate({opacity:1},r)},this);return t.promise.then(u.bind(function(){return this.animateAllAttrKeys({exclude:["circle"]},{opacity:0},r*1.1)},this)).then(u.bind(function(){return this.animateAllAttrKeys({exclude:["arrow","rect","path","text"]},{r:i*2},r*1.5)},this)).then(u.bind(function(){return this.animateAllAttrKeys({exclude:["arrow","rect","path","text"]},{r:i*.75},r*.5)},this)).then(u.bind(function(){return f(),this.explodeNodes()},this)).then(u.bind(function(){return this.explodeNodes()},this)).then(u.bind(function(){return this.animateAllAttrKeys({exclude:["arrow","rect","path","text"]},{},r*1.25)},this)).then(u.bind(function(){return o.animate({opacity:0},r,undefined,undefined,function(){o.remove()}),this.animateAllAttrKeys({},{})},this)).then(function(){n.resolve()}).fail(function(e){console.warn("animation error"+e)}).done(),t.resolve(),n.promise},w.prototype.explodeNodes=function(){var e=a.defer(),t=[];u.each(this.visNodeMap,function(e){t.push(e.getExplodeStepFunc())});var n=setInterval(function(){var r=[];u.each(t,function(e){e()&&r.push(e)});if(!r.length){clearInterval(n),e.resolve();return}t=r},.025);return e.promise},w.prototype.animateAllFromAttrToAttr=function(e,t,n){var r=function(r){var i=r.getID();if(u.include(n,i))return;if(!e[i]||!t[i])return;r.animateFromAttrToAttr(e[i],t[i])};this.visBranchCollection.each(r),this.visEdgeCollection.each(r),u.each(this.visNodeMap,r)},w.prototype.genSnapshot=function(){this.fullCalc();var e={};return u.each(this.visNodeMap,function(t){e[t.get("id")]=t.getAttributes()},this),this.visBranchCollection.each(function(t){e[t.getID()]=t.getAttributes()},this),this.visEdgeCollection.each(function(t){e[t.getID()]=t.getAttributes()},this),e},w.prototype.refreshTree=function(e){if(!this.gitReady||!this.gitEngine.rootCommit)return;this.fullCalc(),this.animateAll(e)},w.prototype.refreshTreeHarsh=function(){this.fullCalc(),this.animateAll(0)},w.prototype.animateAll=function(e){this.zIndexReflow(),this.animateEdges(e),this.animateNodePositions(e),this.animateRefs(e)},w.prototype.fullCalc=function(){this.calcTreeCoords(),this.calcGraphicsCoords()},w.prototype.calcTreeCoords=function(){if(!this.rootCommit)throw new Error("grr, no root commit!");this.calcUpstreamSets(),this.calcBranchStacks(),this.calcDepth(),this.calcWidth()},w.prototype.calcGraphicsCoords=function(){this.visBranchCollection.each(function(e){e.updateName()})},w.prototype.calcUpstreamSets=function(){this.upstreamBranchSet=this.gitEngine.getUpstreamBranchSet(),this.upstreamHeadSet=this.gitEngine.getUpstreamHeadSet()},w.prototype.getCommitUpstreamBranches=function(e){return this.branchStackMap[e.get("id")]},w.prototype.getBlendedHuesForCommit=function(e){var t=this.upstreamBranchSet[e.get("id")];if(!t)throw new Error("that commit doesnt have upstream branches!");return this.blendHuesFromBranchStack(t)},w.prototype.blendHuesFromBranchStack=function(e){var t=[];return u.each(e,function(e){var n=e.obj.get("visBranch").get("fill");if(n.slice(0,3)!=="hsb"){var r=Raphael.color(n);n="hsb("+String(r.h)+","+String(r.l),n=n+","+String(r.s)+")"}t.push(n)}),E(t)},w.prototype.getCommitUpstreamStatus=function(e){if(!this.upstreamBranchSet)throw new Error("Can't calculate this yet!");var t=e.get("id"),n=this.upstreamBranchSet,r=this.upstreamHeadSet;return n[t]?"branch":r[t]?"head":"none"},w.prototype.calcBranchStacks=function(){var e=this.gitEngine.getBranches(),t={};u.each(e,function(e){var n=e.target.get("id");t[n]=t[n]||[],t[n].push(e),t[n].sort(function(e,t){var n=e.obj.get("id"),r=t.obj.get("id");return n=="master"||r=="master"?n=="master"?-1:1:n.localeCompare(r)})}),this.branchStackMap=t},w.prototype.calcWidth=function(){this.maxWidthRecursive(this.rootCommit);var e=this.getPosBoundaries();this.assignBoundsRecursive(this.rootCommit,e.min,e.max)},w.prototype.maxWidthRecursive=function(e){var t=0;u.each(e.get("children"),function(n){if(n.isMainParent(e)){var r=this.maxWidthRecursive(n);t+=r}},this);var n=Math.max(1,t);return e.get("visNode").set("maxWidth",n),n},w.prototype.assignBoundsRecursive=function(e,t,n){var r=(n+t)/2;e.get("visNode").get("pos").x=r;if(e.get("children").length===0)return;var i=n-t,s=0,o=e.get("children");u.each(o,function(t){t.isMainParent(e)&&(s+=t.get("visNode").getMaxWidthScaled())},this);var a=t;u.each(o,function(t,n){if(!t.isMainParent(e))return;var r=t.get("visNode").getMaxWidthScaled(),o=r/s*i,u=a,f=u+o;this.assignBoundsRecursive(t,u,f),a=u+o},this)},w.prototype.calcDepth=function(){var e=this.calcDepthRecursive(this.rootCommit,0);e>15&&console.warn("graphics are degrading from too many layers");var t=this.getDepthIncrement(e);u.each(this.visNodeMap,function(e){e.setDepthBasedOn(t,this.getHeaderOffset())},this)},w.prototype.animateNodePositions=function(e){u.each(this.visNodeMap,function(t){t.animateUpdatedPosition(e)},this)},w.prototype.addBranchFromEvent=function(e,t,n){var r=u.bind(function(){this.addBranch(e)},this);!this.gitEngine||!this.gitReady?this.defer(r):r()},w.prototype.addBranch=function(e){var t=new m({branch:e,gitVisuals:this,gitEngine:this.gitEngine});this.visBranchCollection.add(t),this.gitReady?t.genGraphics(this.paper):this.defer(u.bind(function(){t.genGraphics(this.paper)},this))},w.prototype.removeVisBranch=function(e){this.visBranchCollection.remove(e)},w.prototype.removeVisNode=function(e){this.visNodeMap[e.getID()]=undefined},w.prototype.removeVisEdge=function(e){this.visEdgeCollection.remove(e)},w.prototype.animateRefs=function(e){this.visBranchCollection.each(function(t){t.animateUpdatedPos(e)},this)},w.prototype.animateEdges=function(e){this.visEdgeCollection.each(function(t){t.animateUpdatedPath(e)},this)},w.prototype.getMinLayers=function(){return this.options.smallCanvas?2:7},w.prototype.getDepthIncrement=function(e){e=Math.max(e,this.getMinLayers());var t=1-this.getHeaderOffset(),n=t/e;return n},w.prototype.shouldHaveHeader=function(){return this.gitEngine.isOrigin()||this.gitEngine.hasOrigin()},w.prototype.getHeaderOffset=function(){return this.shouldHaveHeader()?.05:0},w.prototype.calcDepthRecursive=function(e,t){e.get("visNode").setDepth(t);var n=e.get("children"),r=t;return u.each(n,function(e){var n=this.calcDepthRecursive(e,t+1);r=Math.max(n,r)},this),r},w.prototype.canvasResize=function(e,t){this.resizeFunc||this.genResizeFunc(),this.resizeFunc(e,t)},w.prototype.genResizeFunc=function(){this.resizeFunc=u.debounce(u.bind(function(t,n){this.refreshTree()},this),200,!0)},w.prototype.addNode=function(e,t){this.commitMap[e]=t,t.get("rootCommit")&&(this.rootCommit=t);var n=new v({id:e,commit:t,gitVisuals:this,gitEngine:this.gitEngine});return this.visNodeMap[e]=n,this.gitReady&&n.genGraphics(this.paper),n},w.prototype.addEdge=function(e,t){var n=this.visNodeMap[e],r=this.visNodeMap[t];if(!n||!r)throw new Error("one of the ids in ("+e+", "+t+") does not exist");var i=new y({tail:n,head:r,gitVisuals:this,gitEngine:this.gitEngine});this.visEdgeCollection.add(i),this.gitReady&&i.genGraphics(this.paper)},w.prototype.zIndexReflow=function(){this.visNodesFront(),this.visBranchesFront()},w.prototype.visNodesFront=function(){u.each(this.visNodeMap,function(e){e.toFront()})},w.prototype.visBranchesFront=function(){this.visBranchCollection.each(function(e){e.nonTextToFront(),e.textToFront()}),this.visBranchCollection.each(function(e){e.textToFrontIfInStack()})},w.prototype.drawTreeFromReload=function(){this.gitReady=!0,this.deferFlush(),this.calcTreeCoords()},w.prototype.drawTreeFirstTime=function(){this.gitReady=!0,this.calcTreeCoords(),u.each(this.visNodeMap,function(e){e.genGraphics(this.paper)},this),this.visEdgeCollection.each(function(e){e.genGraphics(this.paper)},this),this.visBranchCollection.each(function(e){e.genGraphics(this.paper)},this),this.zIndexReflow()},n.GitVisuals=w}),e("/src/js/visuals/index.js"),e.define("/src/js/visuals/tree.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({removeKeys:function(e){u.each(e,function(e){this.get(e)&&this.get(e).remove()},this)},animateAttrKeys:function(e,t,n,r){e=u.extend({},{include:["circle","arrow","rect","path","text"],exclude:[]},e||{});var i=this.getAttributes();u.each(e.include,function(e){i[e]=u.extend({},i[e],t)}),u.each(e.exclude,function(e){delete i[e]}),this.animateToAttr(i,n,r)}});n.VisBase=f}),e("/src/js/visuals/tree.js"),e.define("/src/js/visuals/visBase.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({removeKeys:function(e){u.each(e,function(e){this.get(e)&&this.get(e).remove()},this)},getNonAnimateKeys:function(){return["stroke-dasharray"]},getIsInOrigin:function(){return this.get("gitEngine")?this.get("gitEngine").isOrigin():!1},animateToAttr:function(e,t,n){if(t===0){this.setAttr(e,!0);return}var r=t!==undefined?t:this.get("animationSpeed"),i=n||this.get("animationEasing");this.setAttr(e,!1,r,i)},setAttrBase:function(e,t,n,r,i){u.each(e,function(e){n?this.get(e).attr(t[e]):(this.get(e).stop(),this.get(e).animate(t[e],r,i),u.forEach(this.getNonAnimateKeys(),function(n){t[e]&&t[e][n]!==undefined&&this.get(e).attr(n,t[e][n])},this)),t.css&&$(this.get(e).node).css(t.css)},this)},animateAttrKeys:function(e,t,n,r){e=u.extend({},{include:["circle","arrow","rect","path","text"],exclude:[]},e||{});var i=this.getAttributes();u.each(e.include,function(e){i[e]=u.extend({},i[e],t)}),u.each(e.exclude,function(e){delete i[e]}),this.animateToAttr(i,n,r)}});n.VisBase=f}),e("/src/js/visuals/visBase.js"),e.define("/src/js/visuals/visBranch.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=function(){var e=Math.random(),t="hsb("+String(e)+",0.7,1)";return t},h=l.extend({defaults:{pos:null,text:null,rect:null,arrow:null,isHead:!1,flip:1,fill:f.rectFill,stroke:f.rectStroke,"stroke-width":f.rectStrokeWidth,offsetX:f.nodeRadius*4.75,offsetY:0,arrowHeight:14,arrowInnerSkew:0,arrowEdgeHeight:6,arrowLength:14,arrowOffsetFromCircleX:10,vPad:5,hPad:5,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing},validateAtInit:function(){if(!this.get("branch"))throw new Error("need a branch!")},getID:function(){return this.get("branch").get("id")},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine");if(!this.gitEngine)throw new Error("asd wtf");this.get("branch").set("visBranch",this);var e=this.get("branch").get("id");e=="HEAD"?(this.set("isHead",!0),this.set("flip",-1),this.refreshOffset(),this.set("fill",f.headRectFill)):e!=="master"&&this.set("fill",c())},getCommitPosition:function(){var e=this.gitEngine.getCommitFromRef(this.get("branch")),t=e.get("visNode");return this.set("flip",this.getFlipValue(e,t)),this.refreshOffset(),t.getScreenCoords()},getFlipValue:function(e,t){var n=this.get("gitVisuals").getFlipPos(),r=t.get("pos").x>n;return e.get("id")==="C0"?-1:this.get("isHead")?r?this.isBranchStackEmpty()?-1:1:this.isBranchStackEmpty()?1:-1:r?-1:1},refreshOffset:function(){var e=f.nodeRadius*4.75,t=33,n=10;this.get("flip")===1?(this.set("offsetY",-t),this.set("offsetX",e-n)):(this.set("offsetY",t),this.set("offsetX",e-n))},getArrowTransform:function(){return this.get("flip")===1?"t-2,-20R-35":"t2,20R-35"},getBranchStackIndex:function(){if(this.get("isHead"))return 0;var e=this.getBranchStackArray(),t=-1;return u.each(e,function(e,n){e.obj==this.get("branch")&&(t=n)},this),t},getBranchStackLength:function(){return this.get("isHead")?1:this.getBranchStackArray().length},isBranchStackEmpty:function(){var e=this.gitVisuals.branchStackMap[this.getCommitID()];return e?e.length===0:!0},getCommitID:function(){var e=this.get("branch").get("target");return e.get("type")==="branch"&&(e=e.get("target")),e.get("id")},getBranchStackArray:function(){var e=this.gitVisuals.branchStackMap[this.getCommitID()];return e===undefined?(this.gitVisuals.calcBranchStacks(),this.getBranchStackArray()):e},getTextPosition:function(){var e=this.getCommitPosition(),t=this.getBranchStackIndex();return{x:e.x+this.get("flip")*this.get("offsetX"),y:e.y+t*f.multiBranchY+this.get("offsetY")}},getRectPosition:function(){var e=this.getTextPosition(),t=this.get("flip"),n=this.getTextSize();return{x:e.x-.5*n.w-this.get("hPad"),y:e.y-.5*n.h-this.get("vPad")}},getArrowPath:function(){var e=function(e,t,n){return{x:e.x+t,y:e.y+n}},t=function(e){return String(Math.round(e.x))+","+String(Math.round(e.y))},n=this.get("flip"),r=e(this.getCommitPosition(),n*this.get("arrowOffsetFromCircleX"),0),i=e(r,n*this.get("arrowLength"),-this.get("arrowHeight")),s=e(r,n*this.get("arrowLength"),this.get("arrowHeight")),o=e(i,n*this.get("arrowInnerSkew"),this.get("arrowEdgeHeight")),a=e(s,n*this.get("arrowInnerSkew"),-this.get("arrowEdgeHeight")),f=49,l=e(o,n*f,0),c=e(a,n*f,0),h="";h+="M"+t(l)+" ";var p=[o,i,r,s,a,c];return u.each(p,function(e){h+="L"+t(e)+" "},this),h+="z",h},getTextSize:function(){var e=function(e){var t=e.get("text")?e.get("text").node:null;return t===null?0:t.clientWidth},t=function(e){return e.w||(e.w=75),e.h||(e.h=20),e},n=this.get("text").node;if(this.get("isHead"))return t({w:n.clientWidth,h:n.clientHeight});var r=0;return u.each(this.getBranchStackArray(),function(t){r=Math.max(r,e(t.obj.get("visBranch")))}),t({w:r,h:n.clientHeight})},getSingleRectSize:function(){var e=this.getTextSize(),t=this.get("vPad"),n=this.get("hPad");return{w:e.w+t*2,h:e.h+n*2}},getRectSize:function(){var e=this.getTextSize(),t=this.get("vPad"),n=this.get("hPad"),r=this.getBranchStackLength();return{w:e.w+t*2,h:e.h*r*1.1+n*2}},getIsRemote:function(){return this.get("branch").getIsRemote()},getName:function(){var e=this.get("branch").getName(),t=this.get("branch")===this.gitEngine.HEAD.get("target"),n=this.getIsRemote(),r=t&&!this.getIsInOrigin()&&!n?"*":"";return e+r},nonTextToFront:function(){this.get("arrow").toFront(),this.get("rect").toFront()},textToFront:function(){this.get("text").toFront()},textToFrontIfInStack:function(){this.getBranchStackIndex()!==0&&this.get("text").toFront()},getFill:function(){return this.get("isHead")||this.getBranchStackLength()==1||this.getBranchStackIndex()!==0?this.get("fill"):this.gitVisuals.blendHuesFromBranchStack(this.getBranchStackArray())},remove:function(){this.removeKeys(["text","arrow","rect"]),this.gitVisuals.removeVisBranch(this)},genGraphics:function(e){var t=this.getTextPosition(),n=this.getName(),r;r=e.text(t.x,t.y,String(n)),r.attr({"font-size":14,"font-family":"Monaco, Courier, font-monospace",opacity:this.getTextOpacity()}),this.set("text",r);var i=this.getAttributes(),s=this.getRectPosition(),o=this.getRectSize(),a=e.rect(s.x,s.y,o.w,o.h,8).attr(i.rect);this.set("rect",a);var f=this.getArrowPath(),l=e.path(f).attr(i.arrow);this.set("arrow",l);var c=["text","rect","arrow"];u.each(c,function(e){$(this.get(e).node).css(i.css)},this),this.attachClickHandlers(),a.toFront(),r.toFront()},attachClickHandlers:function(){if(this.get("gitVisuals").options.noClick)return;var e=[this.get("rect"),this.get("text"),this.get("arrow")];u.each(e,function(e){e.click(u.bind(this.onClick,this))},this)},shouldDisableClick:function(){return this.get("isHead")&&!this.gitEngine.getDetachedHead()},onClick:function(){if(this.shouldDisableClick())return;var t="git checkout "+this.get("branch").get("id"),n=e("../app");n.getEventBaton().trigger("commandSubmitted",t)},updateName:function(){this.get("text").attr({text:this.getName()})},getNonTextOpacity:function(){return this.get("isHead")?this.gitEngine.getDetachedHead()?1:0:this.getBranchStackIndex()===0?1:0},getTextOpacity:function(){return this.get("isHead")?this.gitEngine.getDetachedHead()?1:0:1},getAttributes:function(){var e=this.getNonTextOpacity(),t=this.getTextOpacity();this.updateName();var n=this.getTextPosition(),r=this.getRectPosition(),i=this.getRectSize(),s=this.getArrowPath(),o=this.getIsInOrigin()?f.originDash:"",u=this.shouldDisableClick()?"auto":"pointer";return{css:{cursor:u},text:{x:n.x,y:n.y,opacity:t},rect:{x:r.x,y:r.y,width:i.w,height:i.h,opacity:e,fill:this.getFill(),stroke:this.get("stroke"),"stroke-width":this.get("stroke-width")},arrow:{path:s,opacity:e,fill:this.getFill(),stroke:this.get("stroke"),transform:this.getArrowTransform(),"stroke-width":this.get("stroke-width")}}},animateUpdatedPos:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},setAttr:function(e,t,n,r){var i=["text","rect","arrow"];this.setAttrBase(i,e,t,n,r)}}),p=a.Collection.extend({model:h});n.VisBranchCollection=p,n.VisBranch=h,n.randomHueString=c}),e("/src/js/visuals/visBranch.js"),e.define("/src/js/visuals/visEdge.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=l.extend({defaults:{tail:null,head:null,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing},validateAtInit:function(){var e=["tail","head"];u.each(e,function(e){if(!this.get(e))throw new Error(e+" is required!")},this)},getID:function(){return this.get("tail").get("id")+"."+this.get("head").get("id")},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine"),this.get("tail").get("outgoingEdges").push(this)},remove:function(){this.removeKeys(["path"]),this.gitVisuals.removeVisEdge(this)},genSmoothBezierPathString:function(e,t){var n=e.getScreenCoords(),r=t.getScreenCoords();return this.genSmoothBezierPathStringFromCoords(n,r)},genSmoothBezierPathStringFromCoords:function(e,t){var n=function(e){return String(Math.round(e.x))+","+String(Math.round(e.y))},r=function(e,t,n){return n=n||f.curveControlPointOffset,{x:e.x,y:e.y+n*t}},i=function(e,t,n){return{x:e.x+t,y:e.y+n}};e=r(e,-1,this.get("tail").getRadius()),t=r(t,1,this.get("head").getRadius());var s="";s+="M"+n(e)+" ",s+="C",s+=n(r(e,-1))+" ",s+=n(r(t,1))+" ",s+=n(t);var o=f.arrowHeadSize||10;return s+=" L"+n(i(t,-o,o)),s+=" L"+n(i(t,o,o)),s+=" L"+n(t),s+="C",s+=n(r(t,1))+" ",s+=n(r(e,-1))+" ",s+=n(e),s},getBezierCurve:function(){return this.genSmoothBezierPathString(this.get("tail"),this.get("head"))},getStrokeColor:function(){return f.visBranchStrokeColorNone},setOpacity:function(e){e=e===undefined?1:e,this.get("path").attr({opacity:e})},genGraphics:function(e){var t=this.getBezierCurve(),n=e.path(t).attr({"stroke-width":f.visBranchStrokeWidth,stroke:this.getStrokeColor(),"stroke-linecap":"round","stroke-linejoin":"round",fill:this.getStrokeColor()});n.toBack(),this.set("path",n)},getOpacity:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("tail")),t={branch:1,head:f.edgeUpstreamHeadOpacity,none:f.edgeUpstreamNoneOpacity};if(t[e]===undefined)throw new Error("bad stat");return t[e]},getAttributes:function(){var e=this.getBezierCurve(),t=this.getOpacity();return{path:{path:e,opacity:t}}},animateUpdatedPath:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},animateToAttr:function(e,t,n){if(t===0){this.get("path").attr(e.path);return}this.get("path").toBack(),this.get("path").stop(),this.get("path").animate(e.path,t!==undefined?t:this.get("animationSpeed"),n||this.get("animationEasing"))}}),h=a.Collection.extend({model:c});n.VisEdgeCollection=h,n.VisEdge=c}),e("/src/js/visuals/visEdge.js"),e.define("/src/js/visuals/visNode.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=l.extend({defaults:{depth:undefined,maxWidth:null,outgoingEdges:null,circle:null,text:null,id:null,pos:null,radius:null,commit:null,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing,fill:f.defaultNodeFill,"stroke-width":f.defaultNodeStrokeWidth,stroke:f.defaultNodeStroke},getID:function(){return this.get("id")},validateAtInit:function(){if(!this.get("id"))throw new Error("need id for mapping");if(!this.get("commit"))throw new Error("need commit for linking");this.get("pos")||this.set("pos",{x:Math.random(),y:Math.random()})},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine"),this.set("outgoingEdges",[])},setDepth:function(e){this.set("depth",Math.max(this.get("depth")||0,e))},setDepthBasedOn:function(e,t){if(this.get("depth")===undefined)throw new Error("no depth yet!");var n=this.get("pos");n.y=this.get("depth")*e+t},getMaxWidthScaled:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("commit")),t={branch:1,head:.3,none:.1};if(t[e]===undefined)throw new Error("bad stat");return t[e]*this.get("maxWidth")},toFront:function(){this.get("circle").toFront(),this.get("text").toFront()},getOpacity:function(){var e={branch:1,head:f.upstreamHeadOpacity,none:f.upstreamNoneOpacity},t=this.gitVisuals.getCommitUpstreamStatus(this.get("commit"));if(e[t]===undefined)throw new Error("invalid status");return e[t]},getTextScreenCoords:function(){return this.getScreenCoords()},getAttributes:function(){var e=this.getScreenCoords(),t=this.getTextScreenCoords(),n=this.getOpacity(),r=this.getIsInOrigin()?f.originDash:"";return{circle:{cx:e.x,cy:e.y,opacity:n,r:this.getRadius(),fill:this.getFill(),"stroke-width":this.get("stroke-width"),"stroke-dasharray":r,stroke:this.get("stroke")},text:{x:t.x,y:t.y,opacity:n}}},highlightTo:function(e,t,n){var r=e.get("fill"),i={circle:{fill:r,stroke:r,"stroke-dasharray":"","stroke-width":this.get("stroke-width")*5},text:{}};this.animateToAttr(i,t,n)},animateUpdatedPosition:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},animateToSnapshot:function(e,t,n){if(!e[this.getID()])return;this.animateToAttr(e[this.getID()],t,n)},setAttr:function(e,t,n,r){var i=["text","circle"];this.setAttrBase(i,e,t,n,r)},animateToAttr:function(e,t,n){l.prototype.animateToAttr.apply(this,arguments);var r=t!==undefined?t:this.get("animationSpeed"),i=n||this.get("animationEasing");n=="bounce"&&e.circle&&e.circle.cx!==undefined&&e.text&&e.text.x!==undefined&&(this.get("circle").animate(e.circle.cx,r,"easeInOut"),this.get("text").animate(e.text.x,r,"easeInOut"))},getScreenCoords:function(){var e=this.get("pos");return this.gitVisuals.toScreenCoords(e)},getRadius:function(){return this.get("radius")||f.nodeRadius},getParentScreenCoords:function(){return this.get("commit").get("parents")[0].get("visNode").getScreenCoords()},setBirthPosition:function(){var e=this.getParentScreenCoords();this.get("circle").attr({cx:e.x,cy:e.y,opacity:0,r:0}),this.get("text").attr({x:e.x,y:e.y,opacity:0})},setBirthFromSnapshot:function(e){var t=this.get("commit").get("parents")[0].get("visNode").getID(),n=e[t];this.get("circle").attr({opacity:0,r:0,cx:n.circle.cx,cy:n.circle.cy}),this.get("text").attr({opacity:0,x:n.text.x,y:n.text.y});var r={x:n.circle.cx,y:n.circle.cy};this.setOutgoingEdgesBirthPosition(r)},setBirth:function(){this.setBirthPosition(),this.setOutgoingEdgesBirthPosition(this.getParentScreenCoords())},setOutgoingEdgesOpacity:function(e){u.each(this.get("outgoingEdges"),function(t){t.setOpacity(e)})},animateOutgoingEdgesToAttr:function(e,t,n){u.each(this.get("outgoingEdges"),function(t){var n=e[t.getID()];t.animateToAttr(n)},this)},animateOutgoingEdges:function(e,t){u.each(this.get("outgoingEdges"),function(n){n.animateUpdatedPath(e,t)},this)},animateOutgoingEdgesFromSnapshot:function(e,t,n){u.each(this.get("outgoingEdges"),function(r){var i=e[r.getID()];r.animateToAttr(i,t,n)},this)},setOutgoingEdgesBirthPosition:function(e){u.each(this.get("outgoingEdges"),function(t){var n=t.get("head").getScreenCoords(),r=t.genSmoothBezierPathStringFromCoords(e,n);t.get("path").stop(),t.get("path").attr({path:r,opacity:0})},this)},parentInFront:function(){this.get("commit").get("parents")[0].get("visNode").toFront()},getFontSize:function(e){return e.length<3?12:e.length<5?10:8},getFill:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("commit"));return e=="head"?f.headRectFill:e=="none"?f.orphanNodeFill:this.gitVisuals.getBlendedHuesForCommit(this.get("commit"))},attachClickHandlers:function(){if(this.get("gitVisuals").options.noClick)return;var t="git checkout "+this.get("commit").get("id"),n=e("../app");u.each([this.get("circle"),this.get("text")],function(e){e.click(function(){n.getEventBaton().trigger("commandSubmitted",t)}),$(e.node).css("cursor","pointer")})},setOpacity:function(e){e=e===undefined?1:e;var t=["circle","text"];u.each(t,function(t){this.get(t).attr({opacity:e})},this)},remove:function(){this.removeKeys(["circle"],["text"]);var e=this.get("text");e&&e.remove(),this.gitVisuals.removeVisNode(this)},removeAll:function(){this.remove(),u.each(this.get("outgoingEdges"),function(e){e.remove()},this)},getExplodeStepFunc:function(){var e=this.get("circle"),t=20,n=Math.PI+Math.random()*1*Math.PI,r=.2,i=.01,s=t*Math.cos(n),o=t*Math.sin(n),u=e.attr("cx"),a=e.attr("cy"),f=this.gitVisuals.paper.width,l=this.gitVisuals.paper.height,c=.8,h=1,p=function(){o+=r*h-i*o,s-=i*s,u+=s*h,a+=o*h;if(u<0||u>f)s=c*-s,u=u<0?0:f;if(a<0||a>l)o=c*-o,a=a<0?0:l;return e.attr({cx:u,cy:a}),s*s+o*o<.01&&Math.abs(a-l)===0?!1:!0};return p},genGraphics:function(){var e=this.gitVisuals.paper,t=this.getScreenCoords(),n=this.getTextScreenCoords(),r=e.circle(t.x,t.y,this.getRadius()).attr(this.getAttributes().circle),i=e.text(n.x,n.y,String(this.get("id")));i.attr({"font-size":this.getFontSize(this.get("id")),"font-weight":"bold","font-family":"Monaco, Courier, font-monospace",opacity:this.getOpacity()}),this.set("circle",r),this.set("text",i),this.attachClickHandlers()}});n.VisNode=c}),e("/src/js/visuals/visNode.js"),e.define("/src/js/visuals/visualization.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../models/collections"),l=f.CommitCollection,c=f.BranchCollection,h=e("../util/eventBaton").EventBaton,p=e("../visuals").GitVisuals,d=a.View.extend({initialize:function(e){e=e||{},this.options=e,this.customEvents=u.clone(a.Events),this.containerElement=e.containerElement;var t=this,n=e.containerElement||$("#canvasHolder")[0];new Raphael(n,200,200,function(){var n=this;s.nextTick(function(){t.paperInitialize(n,e)})})},paperInitialize:function(t,n){this.treeString=n.treeString,this.paper=t;var r=e("../app");this.eventBaton=n.noKeyboardInput?new h:r.getEventBaton(),this.commitCollection=new l,this.branchCollection=new c,this.gitVisuals=new p({commitCollection:this.commitCollection,branchCollection:this.branchCollection,paper:this.paper,noClick:this.options.noClick,smallCanvas:this.options.smallCanvas,visualization:this});var i=e("../git").GitEngine;this.gitEngine=new i({collection:this.commitCollection,branches:this.branchCollection,gitVisuals:this.gitVisuals,eventBaton:this.eventBaton}),this.gitEngine.init(),this.gitVisuals.assignGitEngine(this.gitEngine),this.myResize(),$(window).on("resize",u.bind(function(){this.myResize()},this)),this.gitVisuals.drawTreeFirstTime(),this.treeString&&this.gitEngine.loadTreeFromString(this.treeString),this.options.zIndex&&this.setTreeIndex(this.options.zIndex),this.shown=!1,this.setTreeOpacity(0),s.nextTick(u.bind(this.fadeTreeIn,this)),this.customEvents.trigger("gitEngineReady"),this.customEvents.trigger("paperReady")},clearOrigin:function(){delete this.originVis},makeOrigin:function(e){return this.originVis=new d(u.extend({},this.options,{noKeyboardInput:!0,noClick:!0,treeString:e.treeString})),this.originVis},originToo:function(e,t){if(!this.originVis)return;var n=u.bind(function(){this.originVis[e].apply(this.originVis,t)},this);if(this.originVis.paper){n();return}this.originVis.customEvents.on("paperReady",n)},setTreeIndex:function(e){$(this.paper.canvas).css("z-index",e),this.originToo("setTreeIndex",arguments)},setTreeOpacity:function(e){e===0&&(this.shown=!1),$(this.paper.canvas).css("opacity",e),this.originToo("setTreeOpacity",arguments)},getAnimationTime:function(){return 300},fadeTreeIn:function(){this.shown=!0,$(this.paper.canvas).animate({opacity:1},this.getAnimationTime()),this.originToo("fadeTreeIn",arguments)},fadeTreeOut:function(){this.shown=!1,$(this.paper.canvas).animate({opacity:0},this.getAnimationTime()),this.originToo("fadeTreeOut",arguments)},hide:function(){this.fadeTreeOut(),setTimeout(u.bind(function(){$(this.paper.canvas).css("visibility","hidden")},this),this.getAnimationTime()),this.originToo("hide",arguments)},show:function(){$(this.paper.canvas).css("visibility","visible"),setTimeout(u.bind(this.fadeTreeIn,this),10),this.originToo("show",arguments)},showHarsh:function(){$(this.paper.canvas).css("visibility","visible"),this.setTreeOpacity(1),this.originToo("showHarsh",arguments)},resetFromThisTreeNow:function(e){this.treeString=e;var t=this.getOriginInTreeString(e);if(t){var n=this.gitEngine.printTree(t);this.originToo("resetFromThisThreeNow",[n])}},getOriginInTreeString:function(e){var t=JSON.parse(unescape(e));return t.originTree},reset:function(e){var t=e||this.treeString;this.setTreeOpacity(0),t?this.gitEngine.loadTreeFromString(t):this.gitEngine.defaultInit(),this.fadeTreeIn();if(this.originVis)if(t){var n=this.getOriginInTreeString(t);this.originToo("reset",[JSON.stringify(n)])}else this.originToo("reset",arguments)},tearDown:function(){this.gitEngine.tearDown(),this.gitVisuals.tearDown(),delete this.paper,this.originToo("tearDown",arguments)},die:function(){this.fadeTreeOut(),setTimeout(u.bind(function(){this.shown||this.tearDown()},this),this.getAnimationTime()),this.originToo("die",arguments)},myResize:function(){if(!this.paper)return;var e=1,t=this.el,n=t.clientWidth-e,r=t.clientHeight-e;if(!this.containerElement){var i=t.offsetLeft,s=t.offsetTop;$(this.paper.canvas).css({position:"absolute",left:i+"px",top:s+"px"})}this.paper.setSize(n,r),this.gitVisuals.canvasResize(n,r)}});n.Visualization=d}),e("/src/js/visuals/visualization.js"),e.define("/src/levels/advanced/multipleParents.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C7","id":"master"},"bugWork":{"target":"C2","id":"bugWork"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C2"],"id":"C5"},"C6":{"parents":["C4","C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',solutionCommand:"git branch bugWork master^^2^",startTree:'{"branches":{"master":{"target":"C7","id":"master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C2"],"id":"C5"},"C6":{"parents":["C4","C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Multiple parents",zh_CN:"多个父提交记录"},hint:{en_US:"Use `git branch bugWork` with a target commit to create the missing reference.",zh_CN:"使用`git branch bugWork`加上一个目标提交记录来创建消失的引用。"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["### Specifying Parents","","Like the `~` modifier, the `^` modifier also accepts an optional number after it.","","Rather than specifying the number of generations to go back (what `~` takes), the modifier on `^` specifies which parent reference to follow from a merge commit. Remember that merge commits have multiple parents, so the path to choose is ambiguous.","",'Git will normally follow the "first" parent upwards from a merge commit, but specifying a number with `^` changes this default behavior.',"","Enough talking, let's see it in action.",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have a merge commit. If we checkout `master^` without the modifier, we will follow the first parent after the merge commit. ","","(*In our visuals, the first parent is positioned directly above the merge commit.*)"],afterMarkdowns:["Easy -- this is what we are all used to."],command:"git checkout master^",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Now let's try specifying the second parent instead..."],afterMarkdowns:["See? We followed the other parent upwards."],command:"git checkout master^2",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["The `^` and `~` modifiers can make moving around a commit tree very powerful:"],afterMarkdowns:["Lightning fast!"],command:"git checkout HEAD~; git checkout HEAD^2; git checkout HEAD~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Even crazier, these modifiers can be chained together! Check this out:"],afterMarkdowns:["The same movement as before, but all in one command."],command:"git checkout HEAD~^2~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"ModalAlert",options:{markdowns:["### Put it to practice","","To complete this level, create a new branch at the specified destination.","","Obviously it would be easy to specify the commit directly (with something like `C6`), but I challenge you to use the modifiers we talked about instead!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["### 选择父提交","","和`~`修改符一样,`^`修改符之后也可以跟一个(可选的)数字。","","这不是用来指定向上返回几代(`~`的作用),`^`后的数字指定跟随合并提交记录的哪一个父提交。还记得一个合并提交有多个父提交吧,所有选择哪条路径不是那么清晰。","",'Git默认选择跟随合并提交的"第一个"父提交,使用`^`后跟一个数字来改变这一默认行为。',"","废话不多说,举个例子。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["这里有一个合并提交。如果不加数字修改符直接切换到`master^`,会回到第一个父提交。","","(*在我们的图示中,第一个父提交是指合并提交正上方的那个父提交。*)"],afterMarkdowns:["OK--这恰好是我们想要的。"],command:"git checkout master^",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["现在来试试选择第二个父提交……"],afterMarkdowns:["看见了吧?我们回到了第二个父提交。"],command:"git checkout master^2",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用`^`和`~`可以自由在在提交树中移动:"],afterMarkdowns:["快若闪电!"],command:"git checkout HEAD~; git checkout HEAD^2; git checkout HEAD~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["再疯狂点,这些修改符支持链式操作!试一下这个:"],afterMarkdowns:["和前面的结果一样,但只用了一条命令。"],command:"git checkout HEAD~^2~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"ModalAlert",options:{markdowns:["### 实践一下","","要完成此关,在指定的目标位置创建一个新的分支。","","很明显可以简单的直接使用提交记录的hash值(比如`C6`),但我要求你使用刚刚讲到的相对引用修饰符!"]}}]}}}}),e("/src/levels/advanced/multipleParents.js"),e.define("/src/levels/index.js",function(e,t,n,r,i,s,o){n.levelSequences={intro:[e("../../levels/intro/commits").level,e("../../levels/intro/branching").level,e("../../levels/intro/merging").level,e("../../levels/intro/rebasing").level],rampup:[e("../../levels/rampup/detachedHead").level,e("../../levels/rampup/relativeRefs").level,e("../../levels/rampup/relativeRefs2").level,e("../../levels/rampup/reversingChanges").level],rebase:[e("../../levels/rebase/manyRebases").level],mixed:[e("../../levels/mixed/grabbingOneCommit").level,e("../../levels/mixed/jugglingCommits").level,e("../../levels/mixed/jugglingCommits2").level],advanced:[e("../../levels/advanced/multipleParents").level,e("../../levels/rebase/selectiveRebase").level]},n.sequenceInfo={intro:{displayName:{en_US:"Introduction Sequence",ja:"まずはここから",fr_FR:"Séquence d'introduction",zh_CN:"基础篇",ko:"기본 명령어"},about:{en_US:"A nicely paced introduction to the majority of git commands",ja:"gitの基本的なコマンド群をほどよいペースで学ぶ",fr_FR:"Une introduction en douceur à la majorité des commandes git",zh_CN:"循序渐进介绍git主要命令",ko:"브랜치 관련 주요 git 명령어를 깔끔하게 알려드립니다"}},rampup:{displayName:{en_US:"Ramping Up",ja:"次のレベルに進もう",fr_FR:"Montée en puissance",zh_CN:"进阶篇"},about:{en_US:"The next serving of 100% git awesomes-ness. Hope you're hungry",ja:"更にgitの素晴らしさを堪能しよう",fr_FR:"Le prochain service git 100% excellence. J'espère que vous êtes affamés",zh_CN:"接下来是git的超赞特性。迫不及待了吧!"}},rebase:{displayName:{en_US:"Master the Rebase Luke!",ja:"Rebaseをモノにする",fr_FR:"Maîtrise Rebase, Luke!",zh_CN:"精通Rebase!",ko:"리베이스 완전정복!"},about:{en_US:"What is this whole rebase hotness everyone is talking about? Find out!",ja:"話題のrebaseってどんなものだろう?って人にオススメ",fr_FR:"Qu'est-ce que ce rebase dont tout le monde parle ? Découvrez-le !",ko:"그 좋다고들 말하는 rebase에 대해 알아봅시다!",zh_CN:"大家都在说的rebase究竟是神马?看看吧!"}},mixed:{displayName:{en_US:"A Mixed Bag",ja:"様々なtips",fr_FR:"Un assortiment",ko:"종합선물세트",zh_CN:"大杂烩?"},about:{en_US:"A mixed bag of Git techniques, tricks, and tips",ja:"gitを使う上での様々なtipsやテクニックなど",fr_FR:"Un assortiment de techniques et astuces pour utiliser Git",ko:"Git을 다루는 다양한 팁과 테크닉을 다양하게 알아봅니다",zh_CN:"Git技术,技巧与贴士杂烩"}},advanced:{displayName:{en_US:"Advanced Topics",fr_FR:"Sujets Avancés",zh_CN:"高级主题"},about:{en_US:"For the truly brave!",fr_FR:"Pour les plus courageux !",zh_CN:"只为真正的勇士!"}}}}),e("/src/levels/index.js"),e.define("/src/levels/intro/branching.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C1","id":"master"},"bugFix":{"target":"C1","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"bugFix","id":"HEAD"}}',solutionCommand:"git branch bugFix;git checkout bugFix",name:{en_US:"Branching in Git",ja:"Gitのブランチ",ko:"Git에서 브랜치 쓰기",fr_FR:"Gérer les branches avec Git",zh_CN:"建立Git分支"},hint:{en_US:'Make a new branch with "git branch [name]" and check it out with "git checkout [name]"',ja:'ブランチの作成("git branch [ブランチ名]")と、チェックアウト("git checkout [ブランチ名]")',fr_FR:'Faites une nouvelle branche avec "git branch [nom]" positionnez-vous dans celle-ci avec "git checkout [nom]"',zh_CN:"用 'git branch [分支名]' 来创建分支,用 'git checkout [分支名]' 切换到分支",ko:'"git branch [브랜치명]"으로 새 브랜치를 만들고, "git checkout [브랜치명]"로 그 브랜치로 이동하세요'},disabledMap:{"git revert":!0},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Branches","","Branches in Git are incredibly lightweight as well. They are simply references to a specific commit -- nothing more. This is why many Git enthusiasts chant the mantra:","","```","branch early, and branch often","```","","Because there is no storage / memory overhead with making many branches, it's easier to logically divide up your work than have big beefy branches.","",'When we start mixing branches and commits, we will see how these two features combine. For now though, just remember that a branch essentially says "I want to include the work of this commit and all parent commits."']}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's see what branches look like in practice.","","Here we will create a new branch named `newImage`"],afterMarkdowns:["There, that's all there is to branching! The branch `newImage` now refers to commit `C1`"],command:"git branch newImage",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's try to put some work on this new branch. Hit the button below"],afterMarkdowns:["Oh no! The `master` branch moved but the `newImage` branch didn't! That's because we weren't \"on\" the new branch, which is why the asterisk (*) was on `master`"],command:"git commit",beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's tell git we want to checkout the branch with","","```","git checkout [name]","```","","This will put us on the new branch before committing our changes"],afterMarkdowns:["There we go! Our changes were recorded on the new branch"],command:"git checkout newImage; git commit",beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["Ok! You are all ready to get branching. Once this window closes,","make a new branch named `bugFix` and switch to that branch"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Gitのブランチ","","Gitではコミットだけでなく、ブランチもまた信じられないほど軽量です。ブランチとは単に特定のコミットを指示したポインタにしか過ぎません。Gitの達人は決まってこう言うのは、そのためです:","","```","早めに、かつ頻繁にブランチを切りなさい","```","","どれほど多くのブランチを作ってもストレージやメモリを全然使わないので、ブランチを肥大化させるよりも論理的に分割していく方が簡単なのです。","","ブランチとコミットをあわせて使い始めると、これら2つのフィーチャがどのように連動して機能するかがわかるでしょう。ここではとりあえず、ブランチは基本的には「あるコミットとその親のコミットたちを含めた全てのコミット」のことを呼ぶと覚えておいてください。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["では実際にブランチがどのようなものかを見ていきましょう。","","`newImage`という名前の新しいブランチを切ってみることにします。"],afterMarkdowns:["以上。必要な手順はこれだけです。いま作成された`newImage`ブランチは`C1`コミットを指しています。"],command:"git branch newImage",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["この新しいブランチに何か変更を加えてみましょう。次のボタンを押してください。"],afterMarkdowns:["あれ?`newImage`ではなくて`master`ブランチが移動してしまいました。これは、私たちが`newImage`のブランチ上で作業していなかったためです。どのブランチで作業しているかは、アスタリスク(*)がついてるかどうかで分かります。"],command:"git commit",beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["今度は作業したいブランチ名をgitに伝えてみましょう。","","```","git checkout [ブランチ名]","```","","このようにして、コミットする前に新しいブランチへと作業ブランチを移動することができます。"],afterMarkdowns:["できましたね。今度は新しいブランチに対して変更を記録することができました。"],command:"git checkout newImage; git commit",beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["OK! もうどんなブランチでも切れますね。このウィンドウを閉じて、","`bugFix`という名前のブランチを作成し、そのブランチをチェックアウトしてみましょう。"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branches Git","","Les branches sous Git sont incroyablement légères aussi. Elles sont simplment des références un commit spécifique -- rien de plus. C'est pourquoi beaucoup d'enthousiastes répètent en cœur :","","```","n'attendez pas pour faire des branches, et faites souvent des branches","```","","Parce qu'il n'y a pas de surcoût (stockage/mémoire) associés aux branches, il est facile de diviser son travail en de nombreuses branches plutôt que d'avoir quelques grosses branches.","","Nous verrons comment les banches et les commits interagissent quand nous les utiliserons ensemble. Pour l'instant, souvenez-vous qu'une branche est un moyen d'exprimer \"Je veux inclure le contenu de ce commit et de tous les commits parents.\""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Regardons à quoi ressemblent les branches en pratique.","","Nous allons nous positionner (checkout) dans une nouvelle branche appellée `newImage`"],afterMarkdowns:["Et voilà, c'est tout ! La branche `newImage` se réfère désormais au commit `C1`"],command:"git branch newImage",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Travaillons mainenant dans cette branche. Appuyez sur le bouton ci-dessous."],afterMarkdowns:["Oh non! La branche `master` a bougé mais pas la branche `newImage` ! C'est parce aue nous n'étions pas \"sur\" la nouvelle branche, comme indiqué par l'asterisque (*) sur `master`"],command:"git commit",beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Indiquons à git que nous voulons nous positionner sur la branche avec ","","```","git checkout [nom]","```","","Ceci nous positionne sur la nouvelle branche avant de faire un commit avec nos modifications"],afterMarkdowns:["C'est parti ! Nos modifications ont été enregistrées sur la nouvelle branche"],command:"git checkout newImage; git commit",beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["Ok! Vous êtes fin prêt pour faire des branches. Après la fermeture de cette fenêtre,","faites une nouvelle branche nommée `bugFix` et positionnez-vous sur cette branche"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Branches",""," Git 的分支非常轻量。它们只是简单地指向某个提交纪录——仅此而已。所以许多Git爱好者会念叨:","","```","早点建分支!经常建分支!","```","","创建分支没有储存或内存上的开销,所以按逻辑分解工作比维护单一的代码树要简单。","","同时使用分支和提交时,我们会看到两者如何配合。现在,只要记住使用分支其实就是在说:“我想包含本次提交及所有的父提交记录。”"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["举个例子看看分支究竟是什么。","","这里,我们切换到到名为`newImage`的新分支。"],command:"git branch newImage",afterMarkdowns:["看,这就是建立分支所需的操作啦!`newImage`分支现在指向提交记录`C1`。"],beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["现在让我们修改一下新分支。点击下面的按钮。"],command:"git commit",afterMarkdowns:["啊摔!`master`分支前进了,但`newImage`分支没有哇!这是因为我们没有“在”这个新分支上,这也是为什么星号(*)只在 `master` 上。"],beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用如下命令告诉git我们想要切换到新的分支","","```","git checkout [name]","```","","这可以让我们在提交修改之前切换到新的分支。"],command:"git checkout newImage; git commit",afterMarkdowns:["好的嘞!新的分支已经记录了我们的修改。"],beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["好啦,你已经准备好使用分支了。当前窗口关闭后,","创建一个叫 `bugFix` 的新分支,然后切换过去。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git 브랜치","","깃의 브랜치도 놀랍도록 가볍습니다. 브랜치는 특정 커밋에 대한 참조(reference)에 지나지 않습니다. 이런 사실 때문에 수많은 Git 애찬론자들이 자주 이렇게 말하곤 합니다:","","```","브랜치를 서둘러서, 그리고 자주 만드세요","```","","브랜치를 많이 만들어도 메모리나 디스크 공간에 부담이 되지 않기 때문에, 여러분의 작업을 커다른 브랜치로 만들기 보다, 작은 단위로 잘게 나누는 것이 좋습니다.","",'브랜치와 커밋을 같이 쓸 때, 어떻게 두 기능이 조화를 이루는지 알아보겠습니다. 하지만 우선은, 단순히 브랜치를 "하나의 커밋과 그 부모 커밋들을 포함하는 작업 내역"이라고 기억하시면 됩니다.']}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["브랜치가 어떤 것인지 연습해보죠.","","`newImage`라는 브랜치를 살펴보겠습니다."],afterMarkdowns:["저 그림에 브랜치의 모든 것이 담겨있습니다! 브랜치 `newImage`가 커밋 `C1`를 가리킵니다"],command:"git branch newImage",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["이 새로운 브랜치에 약간의 작업을 더해봅시다. 아래 버튼을 눌러주세요"],afterMarkdowns:["앗! `master` 브랜치가 움직이고, `newImage` 브랜치는 이동하지 않았네요! 그건 우리가 새 브랜치 위에 있지 않았었기 때문입니다. 별표(*)가 `master`에 있었던 것이죠."],command:"git commit",beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["아래의 명령으로 새 브랜치로 이동해 봅시다.","","```","git checkout [브랜치명]","```","","이렇게 하면 변경분을 커밋하기 전에 새 브랜치로 이동하게 됩니다."],afterMarkdowns:["이거죠! 이제 우리의 변경이 새 브랜치에 기록되었습니다!"],command:"git checkout newImage; git commit",beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["좋아요! 이제 직접 브랜치 작업을 연습해봅시다. 이 창을 닫고,","`bugFix`라는 새 브랜치를 만드시고, 그 브랜치로 이동해보세요"]}}]}}}}),e("/src/levels/intro/branching.js"),e.define("/src/levels/intro/commits.js",function(e,t,n,r,i,s,o){n.level={name:{en_US:"Introduction to Git Commits",fr_FR:"Introduction aux commits avec Git",ja:"Gitのコミット",ko:"Git 커밋 소개",zh_CN:"Git Commits简介"},goalTreeString:'{"branches":{"master":{"target":"C3","id":"master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"master","id":"HEAD"}}',solutionCommand:"git commit;git commit",startTree:'{"branches":{"master":{"target":"C1","id":"master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"master","id":"HEAD"}}',hint:{en_US:"Just type in 'git commit' twice to finish!",fr_FR:"Il suffit de saisir 'git commit' deux fois pour réussir !",zh_CN:"敲两次 'git commit' 就好啦!",ja:"'git commit'コマンドを2回打てば完成!",ko:"'git commit'이라고 두 번 치세요!"},disabledMap:{"git revert":!0},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Commits","A commit in a git repository records a snapshot of all the files in your directory. It's like a giant copy and paste, but even better!","","Git wants to keep commits as lightweight as possible though, so it doesn't just copy the entire directory every time you commit. It actually stores each commit as a set of changes, or a \"delta\", from one version of the repository to the next. That's why most commits have a parent commit above them -- you'll see this later in our visualizations.","",'In order to clone a repository, you have to unpack or "resolve" all these deltas. That\'s why you might see the command line output:',"","`resolving deltas`","","when cloning a repo.","","It's a lot to take in, but for now you can think of commits as snapshots of the project. Commits are very light and switching between them is wicked fast!"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's see what this looks like in practice. On the right we have a visualization of a (small) git repository. There are two commits right now -- the first initial commit, `C0`, and one commit after that `C1` that might have some meaningful changes.","","Hit the button below to make a new commit"],afterMarkdowns:["There we go! Awesome. We just made changes to the repository and saved them as a commit. The commit we just made has a parent, `C1`, which references which commit it was based off of."],command:"git commit",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["Go ahead and try it out on your own! After this window closes, make two commits to complete the level"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Gitのコミット","コミットによって、ディレクトリ中の全てのファイルのスナップショットを記録します。巨大なコピー&ペーストのようなものですが、実はそれよりずっと良いものです。","","Gitではコミットを可能な限り軽量に保つために、コミット毎にフォルダ全体をコピーしません。実際にはGitは、コミットを直前のバージョンから一つ先のバージョンへの「変更の固まり」あるいは「差分」として記録します。後で出てきますが、ほとんどのコミットが親を持っているのはそういう理由からです。","","リポジトリをcloneする時には、内部動作としてはコミットの差分をたどって全ての変更を取得しています。cloneした時に以下のような表示が出るのは:","","`resolving deltas`(訳:差分を解決中)","","このためです。","","もっと説明したいところですが、しばらくはコミットをスナップショットのようなものだと考えてください。コミットは非常に軽量であり、コミット間の移動も非常に高速です。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["これがどういうことか、動きを見ていきましょう。図には(小さな)gitリポジトリが描かれています。コミットが2つあります ― `C0`という名前の初回のコミットがあり、`C1`という名前の次のコミットが続きます。これは何か意味のある変更かもしれません。","","下のボタンを押下して新しいコミットを作ってみましょう。"],afterMarkdowns:["できました! 良いですね。いまリポジトリに新しい変更が加えられ、1つのコミットとして保存されました。作成したコミットには親がいて、このコミットの出発点となった`C1`を指しています。"],command:"git commit",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["実際に手を動かしてみましょう。このウィンドウを閉じたら、試しに2回コミットをしてみましょう。"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Commits Git","Un commit dans un dépôt (repository) git enregistre une image (snapshot) de tous les fichiers du repertoire. Comme un Copier-Coller géant, mais en bien mieux !","","Git fait en sorte que les commits soient aussi légers que possible donc il ne recopie pas tous le répertoire à chaque commit. En fait, git n'enregistre que l'ensemble des changments (\"delta\") depuis la version précédante du dépôt. C'est pour cette raison que la plupart des commits ont un commit parent -- ainsi que nous le verrons plus tard.","",'Pour cloner un dépôt, il faut décompresser ("résoudre") tous ces deltas. C\'est la raison pour laquelle la commande écrit :',"","`resolving deltas`","","lorsque l'on clone un dépôt.","","C'est beaucoup à absorber, mais pour l'instant vous pouvez considérer les commits comme des snapshots du projet. Les commits sont très légers et passer de l'un à l'autre est très rapide !"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Voyons à quoi cela ressemble en pratique. Sur la droite, on peut visualiser un (petit) dépôt git. Il y a pour l'instant deux commits -- le premier commit initial, `C0`, et un commit suivant `C1` qui aurait des changements significatifs.","","Appuyez sur le bouton ci-dessous pour faire un nouveau commit"],afterMarkdowns:["C'est parti ! Super. Nous venons de faire des modifications sur le dépôt et de saugevarder celles-ci dans un commit. Ce commit que nous venons de faire a un parent, `C1`, qui référence le commit sur lequel il est basé."],command:"git commit",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["Allez-y et essayez par vous-même ! Après la fermeture de cettefenêtre, faites deux commits pour terminer ce niveau."]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git 커밋","커밋은 Git 저장소에 여러분의 디렉토리에 있는 모든 파일에 대한 스냅샷을 기록하는 것입니다. 디렉토리 전체에 대한 복사해 붙이기와 비슷하지만 훨씬 유용합니다!","",'Git은 커밋을 가능한한 가볍게 유지하고자 해서, 커밋할 때마다 디렉토리 전체를 복사하는 일은 하지 않습니다. 각 커밋은 저장소의 이전 버전과 다음 버전의 변경내역("delta"라고도 함)을 저장합니다. 그래서 대부분의 커밋이 그 커밋 위에 부모 커밋을 가리키고 있게 되는 것입니다. -- 곧 그림으로 된 화면에서 살펴보게 될 것입니다.',"","저장소를 복제(clone)하려면, 그 모든 변경분(delta)를 풀어내야하는데, 그 때문에 명령행 결과로 아래와 같이 보게됩니다. ","","`resolving deltas`","","알아야할 것이 꽤 많습니다만, 일단은 커밋을 프로젝트의 각각의 스냅샷들로 생각하시는 걸로 충분합니다. 커밋은 매우 가볍고 커밋 사이의 전환도 매우 빠르다는 것을 기억해주세요!"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["연습할 때 어떻게 보이는지 확인해보죠. 오른쪽 화면에 git 저장소를 그림으로 표현해 놓았습니다. 현재 두번 커밋한 상태입니다 -- 첫번째 커밋으로 `C0`, 그 다음으로 `C1`이라는 어떤 의미있는 변화가 있는 커밋이 있습니다.","","아래 버튼을 눌러 새로운 커밋을 만들어보세요"],afterMarkdowns:["이렇게 보입니다! 멋지죠. 우리는 방금 저장소 내용을 변경해서 한번의 커밋으로 저장했습니다. 방금 만든 커밋은 부모는 `C1`이고, 어떤 커밋을 기반으로 변경된 것인지를 가리킵니다."],command:"git commit",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["계속해서 직접 한번 해보세요! 이 창을 닫고, 커밋을 두 번 하면 다음 레벨로 넘어갑니다"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Commits","git仓库中的一次提交(commit)记录目录下所有文件的快照。感觉像是大量的复制和粘贴,但 git 做的不只这么简单!","",'Git 希望提交记录尽可能地轻量,所以每次进行提交时,它不会简单地复制整个目录。实际上它把每次提交记录保存为从代码库的一个版本到下一个版本的变化集,或者说一个"增量(delta)"。所以,大部分提交记录都有一个父提交(parent commit)-- 我们会很快演示这一点。',"","克隆(clone)代码库时,需要解包(unpack)或者“解析(resolve)”所有的差异。所以在克隆代码库时,可能会看见如下命令行输出:","","`resolving deltas`","","要学的东西有很多,但现在你可以把提交记录看作是项目的快照。提交记录非常轻量且可以快速切换!"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["在实践中学习commit。右边是一个(小)git代码库的图示。当前有两个提交记录—— 初始提交`C0`和其后可能包含有用修改的提交`C1`。","","点击下面的按钮生成新的提交记录。"],command:"git commit",afterMarkdowns:["看!碉堡吧!我们修改了代码,并保存为一次提交记录。刚刚做的提交`C2`有一个父提交(parent)`C1`,代表此次修改的基础。"],beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["接下来你可以随便测试。当前窗口关闭后,完成两次提交就可以过关!"]}}]}}}}),e("/src/levels/intro/commits.js"),e.define("/src/levels/intro/merging.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C4","id":"master"},"bugFix":{"target":"C2","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3","C2"],"id":"C4"}},"HEAD":{"target":"master","id":"HEAD"}}',solutionCommand:"git checkout -b bugFix;git commit;git checkout master;git commit;git merge bugFix",name:{en_US:"Merging in Git",fr_FR:"Faire des 'merge' (fusions de branches) avec Git",ko:"Git에서 브랜치 합치기(Merge)",ja:"ブランチとマージ",zh_CN:"分支与合并"},hint:{en_US:"Remember to commit in the order specified (bugFix before master)",ja:"指示された順番でコミットすること(masterの前にbugFixで)",fr_FR:"Pensez à faire des commits dans l'ordre indiqué (bugFix avant master)",zh_CN:"记住按指定的顺序提交(bugFix先于master)",ko:"말씀드린 순서대로 커밋해주세요 (bugFix에 먼저 커밋하고 master에 커밋)"},disabledMap:{"git revert":!0},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branches and Merging","","Great! We now know how to commit and branch. Now we need to learn some kind of way of combining the work from two different branches together. This will allow us to branch off, develop a new feature, and then combine it back in.","",'The first method to combine work that we will examine is `git merge`. Merging in Git creates a special commit that has two unique parents. A commit with two parents essentially means "I want to include all the work from this parent over here and this one over here, *and* the set of all their parents."',"","It's easier with visuals, let's check it out in the next view"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have two branches; each has one commit that's unique. This means that neither branch includes the entire set of \"work\" in the repository that we have done. Let's fix that with merge.","","We will `merge` the branch `bugFix` into `master`"],afterMarkdowns:["Woah! See that? First of all, `master` now points to a commit that has two parents. If you follow the arrows upstream from `master`, you will hit every commit along the way to the root. This means that `master` contains all the work in the repository now.","","Also, see how the colors of the commits changed? To help with learning, I have included some color coordination. Each branch has a unique color. Each commit turns a color that is the blended combination of all the branches that contain that commit.","","So here we see that the `master` branch color is blended into all the commits, but the `bugFix` color is not. Let's fix that..."],command:"git merge bugFix",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's merge `master` into `bugFix`:"],afterMarkdowns:["Since `bugFix` was downstream of `master`, git didn't have to do any work; it simply just moved `bugFix` to the same commit `master` was attached to.","","Now all the commits are the same color, which means each branch contains all the work in the repository! Woohoo!"],command:"git checkout bugFix; git merge master",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["To complete this level, do the following steps:","","* Make a new branch called `bugFix`","* Checkout the `bugFix` branch with `git checkout bugFix`","* Commit once","* Go back to `master` with `git checkout`","* Commit another time","* Merge the branch `bugFix` into `master` with `git merge`","",'*Remember, you can always re-display this dialog with "help level"!*']}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ブランチとマージ","","いい調子ですね。これまでにコミットとブランチについて学びました。そろそろ2つのブランチを1つにまとめるやり方について見ていきましょう。これができれば新しいフィーチャの開発のために新しいブランチを切って、開発が終わったら変更を元のブランチへ統合することができるようになります。","","はじめに紹介するのは、`git merge`を使ったマージのやり方です。mergeコマンドによって、2つの独立した親を持つ特別なコミットを作ることができます。2つの親を持つコミットが持つ意味とは、「全く別々の場所にいるこの親とその親(*かつ*、それらの親の祖先全て)が持つ全ての変更を含んでいますよ」ということです。","","見てみた方が早いので、次の画面で確認してみましょう。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["それぞれ別のコミットを指している2つのブランチがあります。変更が別々のブランチに分散していて統合されていないケースです。これをマージで1つにまとめてみましょう。","","`bugFix`ブランチを`master`ブランチにマージしてみます。"],afterMarkdowns:["わあ。見ましたか?まず初めに、`master`ブランチが2つのコミットを親に持つ新しいコミットを指してますね。`master`から親をたどっていくと、最も古いコミットにたどり着くまでに全てのコミットを含んでいる様が確認できます。これで、全ての変更を含む`master`が完成しました。","","色がどう変わったかにも注目して下さい。学習を助けるために、ブランチ毎に色をつけています。それぞれのブランチは自分の色を持っていて、どのブランチから派生して出てくるか次第でコミットごとの色が決まります。","","今回のコミットには`master`ブランチの色が使われました。しかし`bugFix`ブランチの色がまだ変わってないようなので、これを変えてみましょう。"],command:"git merge bugFix",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["`master`ブランチを`bugFix`ブランチにマージしてみます。"],afterMarkdowns:["`bugFix`ブランチは`master`ブランチの派生元だったので、gitは実際大したことはしていません:`bugFix`ブランチを指していたポインタを`master`が指していたコミットへと移動させただけです。","","これで全てのコミットが同じ色になりました。つまり、リポジトリの中の全ての変更をそれぞれのブランチが持ったことになります。やったね!"],command:"git checkout bugFix; git merge master",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["以下の作業で理解度の確認をしてみましょう。 steps:","","* `bugFix`という名前で新しいブランチを切る","* `git checkout bugFix`コマンドで`bugFix`ブランチをチェックアウトする","* 一回だけコミット","* `git checkout`で`master`へ戻る","* もう1回コミットする","* `git merge`コマンドを使って、`bugFix`ブランチを`master`ブランチへとマージする","",'*注:"help level"コマンドでこのヘルプにいつでも戻ってこれます*']}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branches et Merges","","Super! Nous savons désormais comment faire des commits et de branches. Maintenant nous devons apprendre comment combiner ensemble les contenus de deux branches différentes. Ceci nous permettra de créer une nouvelle branche, développer une nouvelle fonctionnalité sur cette dernière, puis intégrer cette fonctionnalité en combinant le contenu de cette branche de développement à la branche d'origine(master par exemple).","","La première méthode que nous alons voir pour combiner le conenu de deux branches est `git merge`. Faire un 'merge' en git Git crée un commit spécial qui a deux parents. Un commit avec deux parents indique en susbtance \"Je veux inclure le contenu de ce parent et le conenu de cet autre parent, *et* l'ensemble de leurs parents.\"","","C'est plus facile en visualisant, regardons dans la vue suivante"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have two branches; each has one commit that's unique. This means that neither branch includes the entire set of \"work\" in the repository that we have done. Let's fix that with merge.","","We will `merge` the branch `bugFix` into `master`"],afterMarkdowns:["Woah! See that? First of all, `master` now points to a commit that has two parents. If you follow the arrows upstream from `master`, you will hit every commit along the way to the root. This means that `master` contains all the work in the repository now.","","Also, see how the colors of the commits changed? To help with learning, I have included some color coordination. Each branch has a unique color. Each commit turns a color that is the blended combination of all the branches that contain that commit.","","So here we see that the `master` branch color is blended into all the commits, but the `bugFix` color is not. Let's fix that..."],command:"git merge bugFix",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Faisons un merge de `master` dans `bugFix`:"],afterMarkdowns:["Puisque `bugFix` était un descendant de `master`, git n'avait aucun travail à effectuer; il a simplement déplacé `bugFix` au même commit auquel `master` est attaché.","","Maintenant tous les commits sont de la même couleur, ce qui indique que chaque branche contient tout le contenu du dépôt ! Woohoo!"],command:"git checkout bugFix; git merge master",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["Pour accomplir ce niveau, effectuez les opérations suivantes :","","* Faites une nouvelle branche appelée `bugFix`","* Positionnez-vous sur la branche `bugFix` avec `git checkout bugFix`","* Faites un commit","* Retournez sur la branche `master` (commande `git checkout`)","* Faites un nouveau commit","* Fusionnez la branche `bugFix` dans `master` avec `git merge`","",'*Rappelez-vous que vous pouvez à tout moment réafficher ces indications avec "help level"!*']}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branches and Merging","","Great! 我们已经知道怎么提交和使用分支了。接下来要学的一招是如何合并两个不同分支的工作。这让我们可以新建一个分支,在其上开发新功能,然后合并回主线。","","`git merge`是我们要学习的合并工作的第一个方法。合并产生一个特殊的提交记录,它包含两个唯一父提交。有两个父提交的提交记录本质上是:“我想把这两个父提交本身及它们的父提交集合都包含进来。”","","有图有真相,看看下面的图示就明白了。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["当前有两个分支:各有一个唯一的提交。这意味着没有一个分支包含我们对代码库的所有修改。让我们合并这两个分支来解决这个问题。","","我们要把 `bugFix` 合并到 `master` "],command:"git merge bugFix",afterMarkdowns:["哇!看见木有?首先,`master` 现在指向一个拥有两个父提交的提交记录。假如从 `master` 开始沿着箭头向上游走,在到达起点的路上会经过所有的提交记录。这说明有 `master` 包含了对代码库的所有修改。","","还有,看见各个提交记录的颜色变化了吗?为了帮助学习,我使用了颜色混合。每个分支都有特定的颜色。每个提交记录都变成了含有此提交的所有分支的混合色。","","所以,`master` 分支的颜色被混入到所有的提交记录,但 `bugFix` 没有。接下来就改一下这里吧。"],beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["让我们把 `master` 分支合并到 `bugFix` 吧。"],command:"git checkout bugFix; git merge master",afterMarkdowns:["因为 `bugFix` 分支在 `master` 分支的下游,git什么都不用做,只是简单地把`bugfix`分支移动到`master`指向的提交记录。","","现在所有的提交记录的颜色都是一样的啦,这表明每一个分支都包含了代码库的所有修改!走起!"],beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["想完成此关,执行收下操作:","","* 创建新分支 `bugFix` ","* 用 `git checkout bugFix` 切换到 `bugFix`分支","* 提交一次","* 用 `git checkout` 切换回 `master` ","* 再提交一次","* 用 `git merge` 合并 `bugFix`分支进 `master`","",'*记住,总是可以用 "help level" 命令来重新显示这个对话框!*']}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 브랜치와 합치기(Merge)","","좋습니다! 지금까지 커밋하고 브랜치를 만드는 방법을 알아봤습니다. 이제 두 별도의 브랜치를 합치는 몇가지 방법을 알아볼 차례입니다. 이제부터 배우는 방법으로 브랜치를 따고, 새 기능을 개발 한 다음 합칠 수 있게 될 것입니다.","",'처음으로 살펴볼 방법은 `git merge`입니다. Git의 합치기(merge)는 두 개의 부모(parent)를 가리키는 특별한 커밋을 만들어 냅니다. 두개의 부모가 있는 커밋이라는 것은 "한 부모의 모든 작업내역과 나머지 부모의 모든 작업, *그리고* 그 두 부모의 모든 부모들의 작업내역을 포함한다"라는 의미가 있습니다. ',"","그림으로 보는게 이해하기 쉬워요. 다음 화면을 봅시다."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["여기에 브랜치가 두 개 있습니다. 각 브랜치에 독립된 커밋이 하나씩 있구요. 그 말은 이 저장소에 지금까지 작업한 내역이 나뉘어 담겨 있다는 얘기입니다. 두 브랜치를 합쳐서(merge) 이 문제를 해결해 볼까요?","","`bugFix` 브랜치를 `master` 브랜치에 합쳐(merge) 보겠습니다."],afterMarkdowns:["보셨어요? 우선, `master`가 두 부모가 있는 커밋을 가리키고 있습니다. ","","또, 커밋들의 색이 바뀐 것을 눈치 채셨나요? 이해를 돕기위해 색상으로 구분해 표현했습니다. 각 브랜치는 그 브랜치만의 색상으로 그렸습니다. 브랜치가 합쳐지는 커밋의 경우에는, 그 브랜치들의 색을 조합한 색상으로 표시 했습니다.","","그런식으로 여기에 `bugFix`브랜치 쪽을 제외한 나머지 커밋만 `master` 브랜치의 색으로 칠해져 있습니다. 이걸 고쳐보죠..."],command:"git merge bugFix",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["이제 `master` 브랜치에 `bugFix`를 합쳐(merge) 봅시다:"],afterMarkdowns:["`bugFix`가 `master`의 부모쪽에 있었기 때문에, git이 별다른 일을 할 필요가 없었습니다; 간단히 `bugFix`를 `master`가 붙어 있는 커밋으로 이동시켰을 뿐입니다.","","짜잔! 이제 모든 커밋의 색이 같아졌고, 이는 두 브랜치가 모두 저장소의 모든 작업 내역을 포함하고 있다는 뜻입니다."],command:"git checkout bugFix; git merge master",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["아래 작업을 해서 이 레벨을 통과하세요:","","* `bugFix`라는 새 브랜치를 만듭니다","* `git checkout bugFix`를 입력해 `bugFix` 브랜치로 이동(checkout)합니다.","* 커밋 한 번 하세요","* `git checkout` 명령어를 이용해 `master`브랜치로 돌아갑니다","* 커밋 또 하세요","* `git merge` 명령어로 `bugFix`브랜치를 `master`에 합쳐 넣습니다.","",'*아 그리고, "help level" 명령어로 이 안내창을 다시 볼 수 있다는 것을 기억해 두세요!*']}}]}}}}),e("/src/levels/intro/merging.js"),e.define("/src/levels/intro/rebasing.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22master%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22bugFix%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C2%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22bugFix%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout -b bugFix;git commit;git checkout master;git commit;git checkout bugFix;git rebase master",name:{en_US:"Rebase Introduction",ja:"Rebaseの解説",fr_FR:"Introduction à rebase",ko:"리베이스(rebase)의 기본",zh_CN:"Rebase简介"},hint:{en_US:"Make sure you commit from bugFix first",ja:"初めにbugFixを指した状態でコミットする",fr_FR:"Assurez-vous de bien faire votre en premier votre commit sur bugFix",ko:"bugFix 브랜치에서 먼저 커밋하세요",zh_CN:"确保你先在 bugFix 分支进行提交"},disabledMap:{"git revert":!0},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Rebase","",'The second way of combining work between branches is *rebasing.* Rebasing essentially takes a set of commits, "copies" them, and plops them down somewhere else.',"","While this sounds confusing, the advantage of rebasing is that it can be used to make a nice linear sequence of commits. The commit log / history of the repository will be a lot cleaner if only rebasing is allowed.","","Let's see it in action..."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have two branches yet again; note that the bugFix branch is currently selected (note the asterisk)","","We would like to move our work from bugFix directly onto the work from master. That way it would look like these two features were developed sequentially, when in reality they were developed in parallel.","","Let's do that with the `git rebase` command"],afterMarkdowns:["Awesome! Now the work from our bugFix branch is right on top of master and we have a nice linear sequence of commits.","",'Note that the commit C3 still exists somewhere (it has a faded appearance in the tree), and C3\' is the "copy" that we rebased onto master.',"","The only problem is that master hasn't been updated either, let's do that now..."],command:"git rebase master",beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Now we are checked out on the `master` branch. Let's go ahead and rebase onto `bugFix`..."],afterMarkdowns:["There! Since `master` was downstream of `bugFix`, git simply moved the `master` branch reference forward in history."],command:"git rebase bugFix",beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["To complete this level, do the following","","* Checkout a new branch named `bugFix`","* Commit once","* Go back to master and commit again","* Check out bugFix again and rebase onto master","","Good luck!"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Rebase","","ブランチを一つにまとめる方法として前回はマージを紹介しましたが、今回紹介するリベースを使うこともできます。リベースの動作は、マージするコミットのコピーをとって、どこかにストンと落とすというイメージです。","","ピンと来ないかもしれませんが、リベースのメリットは一本の連続したシーケンシャルなコミットに整形できることです。リベースだけ使っていると、コミットのログや履歴が非常にクリーンな状態に保たれます。","","早速実際にどう動くのかを見てみましょう。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["前回と同様の2つのブランチを考えます:仮にいまbugFixブランチをチェックアウトしているとします。(アスタリスクつきのもの)","","bugFixに入ってる作業内容をそのまま直接masterブランチ上の内容に移動したいとします。こうすることで、実際には並行して開発された2つの別々のブランチ上のフィーチャを、あたかも1本のブランチ上でシーケンシャルに開発されていたかのように見せることができます。","","`git rebase`コマンドでそれをやってみましょう。"],afterMarkdowns:["できた!これでbugFixブランチの作業内容はmasterブランチのすぐ先に移動したので、見た目が一本になってスッキリしました。","","気を付けてほしいのは、C3コミットはどこかに残ってるということ(ツリーの中で半透明にしてあります)、そしてC3'は(C3との接続が切れているC3の)コピーがmasterブランチ上に作られているということです。","","一つ問題が残ってて、masterブランチがまだ最新化されていませんね。ちょっと直してみましょう。。"],command:"git rebase master",beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["masterブランチはチェックアウトしてあります。この状態からmasterブランチを`bugFix`へとリベースしてみましょう。"],afterMarkdowns:["できた!`master`は`bugFix`の直前のコミットだったので、gitは単純に`master`ブランチのポインタを前に進めただけでした。"],command:"git rebase bugFix",beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["以下の作業で理解度の確認をしてみましょう。","","* `bugFix`という名前の新しいブランチをチェックアウトする","* 一回だけコミット","* masterブランチに戻ってもう1回コミット","* bugFixをもう1回チェックアウトして、master上にリベース","","幸運を祈る!"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Rebase","",'La seconde façon de combiner les contenus de deux branches est *rebase*. Rebase prend un enselble de commits, les "recopie", et les ajoute en bout de chaine à un autre endroit.',"","Bien que cela puisse sembler compliqué, l'avantage de rebase est de permettre d'obtenir une simple séquence linéeire de commits. Les logs/l'historique du dépôt seront bien plus propres si seul rebase est autorisé (plutôt que merge).","","Voyons rebase en action…"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Ici nous avons encore une fois deux branches; notez que nous sommes sur la branche bugFix (cf. l'asterisque)","","Nous voudrions transferer notre travail sur la branche 'bugFix' directement sur le travail dans 'master'. Ainsi on aurait l'impression que ces deux travaux ont été développés séquentiellement alors qu'en réalité ils ont été réalisés en parallèle.","","Faisons cela avec la commande `git rebase`"],afterMarkdowns:["Super! Désormais, le travail de la branche 'bugFix' est juste en haut de la branche 'master' et non avons une belle séquence linéaire de commits.","","Notez que le commit C3 existe toujours quelquepart (il est en grisé sur l'arbre), et C3' est la \"copie\" que nous avons créée sur master avec rebase.","","Le seul problème est que master n'a pas été mis à jour, faisons cela maintenant…"],command:"git rebase master",beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Nous sommes désormais positionnés sur la branche `master`. Continuons en faisant le rebase sur `bugFix`…","Et voilà ! Puisque `master` était un ascendant de `bugFix`, git a simplement déplacé la référence de la branche `master` en avant dans le temps."],command:"git rebase bugFix",beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["Pour acomplir ce niveau, faites les opérations suivantes","","* Positionnez-vous (checkout) sur une nouvelle branche nommée `bugFix`","* Faites un commit","* Retournez sur master et faites un nouveau commit","* Positionnez-vous à nouveau sur bugFix et faites un rebase sur master","","Bonne chance !"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Rebase","",'*rebasing*是在分支之间合并工作的第二种方法。Rebasing就是取出一系列的提交记录,"复制"它们,然后把在别的某个地方放下来。',"","虽然听上去难以理解,rebasing 的优势是可以创造更线性的提交历史。假如只允许使用rebasing,代码库的提交日志/历史会更好看。","","让我们亲身体会下……"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["这里,还是有两个分支;注意当前分支是 bugFix(看那颗星)","","我们想要把 bugfix 里面的工作直接移到 master 分支上。使用这个方法,两个分支的功能看起来像是按顺序开发,实际上它们是平行开发的。","","用 `git rebase`实现此目标"],command:"git rebase master",afterMarkdowns:["碉堡吧,现在 bugFix 分支上的工作在 master 的最前端,同时我们也得到了一个更线性的提交序列。","","注意,提交记录 C3 仍然存在(阴影的那货就是你了,还看什么看),而我们已经将 C3 复制到了master。","","现在唯一的问题是 master 分支还没有更新……下面就来更新它吧"],beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["现在,切换到 `master` 分支。接下来就把它 rebase 到 `bugFix` 吧……"],command:"git rebase bugFix",afterMarkdowns:["完成!因为 `master` 是 `bugFix` 的下游,所以 git 只把 `master` 分支的记录前移到 `bugFix` 上。"],beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["想完成此关,执行以下操作:","","* 新建`bugFix`分支","* 提交一次","* 切换回 master 分支再提交一次","* 再次切换到 bugFix 分支,rebase 到 master 上","","祝你好运啦!"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git 리베이스(Rebase)","","브랜치끼리의 작업을 접목하는 두번째 방법은 *리베이스(rebase)*입니다. 리베이스는 기본적으로 커밋들을 모아서 복사한 뒤, 다른 곳에 떨궈 놓는 것입니다.","","조금 어려게 느껴질 수 있지만, 리베이스를 하면 커밋들의 흐름을 보기 좋게 한 줄로 만들 수 있다는 장점이 있습니다. 리베이스를 쓰면 저장소의 커밋 로그와 이력이 한결 깨끗해집니다.","","어떻게 동작하는지 살펴볼까요..."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["여기 또 브랜치 두 개가 있습니다; bugFix브랜치가 현재 선택됐다는 점 눈여겨 보세요 (별표 표시)","","bugFix 브랜치에서의 작업을 master 브랜치 위로 직접 옮겨 놓으려고 합니다. 그렇게 하면, 실제로는 두 기능을 따로따로 개발했지만, 마치 순서대로 개발한 것처럼 보이게 됩니다.","","`git rebase` 명령어로 함께 해보죠."],afterMarkdowns:["오! 이제 bugFix 브랜치의 작업 내용이 master의 바로 위에 깔끔한 한 줄의 커밋으로 보이게 됐습니다.","","C3 커밋은 어딘가에 아직 남아있고(그림에서 흐려짐), C3'는 master 위에 올려 놓은 복사본입니다.","","master가 아직 그대로라는 문제가 남아있는데요, 바로 해결해보죠..."],command:"git rebase master",beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["우리는 지금 `master` 브랜치를 선택한 상태입니다. `bugFix` 브랜치쪽으로 리베이스 해보겠습니다..."],afterMarkdowns:["보세요! `master`가 `bugFix`의 부모쪽에 있었기 때문에, 단순히 그 브랜치를 더 앞쪽의 커밋을 가리키게 이동하는 것이 전부입니다."],command:"git rebase bugFix",beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["이하 작업을 하면 이번 레벨을 통과합니다","","* `bugFix`라는 새 브랜치를 만들어 선택하세요","* 커밋 한 번 합니다","* master로 돌아가서 또 커밋합니다","* bugFix를 다시 선택하고 master에 리베이스 하세요","","화이팅!"]}}]}}}}),e("/src/levels/intro/rebasing.js"),e.define("/src/levels/mixed/grabbingOneCommit.js",function(e,t,n,r,i,s,o){n.level={compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C4>e.C1}]},disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22master%22%7D%2C%22debug%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22debug%22%7D%2C%22printf%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22printf%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22bugFix%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout master;git cherry-pick C4",startTree:'{"branches":{"master":{"target":"C1","id":"master"},"debug":{"target":"C2","id":"debug"},"printf":{"target":"C3","id":"printf"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"bugFix","id":"HEAD"}}',name:{ko:"딱 한개의 커밋만 가져오기",en_US:"Grabbing Just 1 Commit",ja:"Grabbing Just 1 Commit",zh_CN:"只取一个提交"},hint:{en_US:"Remember, interactive rebase or cherry-pick is your friend here",ja:"このレベルではインタラクティブモードのrebaseやcherry-pickがクリアのカギです",ko:"대화식 리베이스(rebase -i)나 or 체리픽(cherry-pick)을 사용하세요",zh_CN:"记住,交互式 rebase 或者 cherry-pick 会很有帮助"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Locally stacked commits","","Here's a development situation that often happens: I'm trying to track down a bug but it is quite elusive. In order to aid in my detective work, I put in a few debug commands and a few print statements.","","All of these debugging / print statements are in their own branches. Finally I track down the bug, fix it, and rejoice!","","Only problem is that I now need to get my `bugFix` back into the `master` branch! I could simply fast-forward `master`, but then `master` would get all my debug statements."]}},{type:"ModalAlert",options:{markdowns:["This is where the magic of Git comes in. There are a few ways to do this, but the two most straightforward ways are:","","* `git rebase -i`","* `git cherry-pick`","","Interactive (the `-i`) rebasing allows you to choose which commits you want to keep or discard. It also allows you to reorder commits. This can be helpful if you want to toss out some work.","","Cherry-picking allows you to pick individual commits and plop them down on top of `HEAD`"]}},{type:"ModalAlert",options:{markdowns:["This is a later level so we will leave it up to you to decide, but in order to complete the level, make sure `master` receives the commit that `bugFix` references."]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ローカルに積み上がったコミット","","実際の開発ではこういうケースがよくあります:「バグの原因調査を試みているがバグの再現性がかなり低い。調査の補助のために、いくつかのデバッグ用の命令やprint文を差し込んでいる。」","","これらのデバッグ用のコードはバグ修正用のブランチにコミットされています。そしてついにバグの原因を突き止めて、修正した!やった!","","あとは`bugFix`ブランチを`master`ブランチに統合できればOK。そこで単純に`master`をfast-forwardすればよいかというと、それでは`master`ブランチの中にデバッグ用のコードも混入してしまいます。"]}},{type:"ModalAlert",options:{markdowns:["ここでGitの魔法が力を発揮します。解決のためにはいくつかの方法がありますが、最も素直な解決方法は2つあって:","","* `git rebase -i`","* `git cherry-pick`","","インタラクティブモードの(`-i`オプションつきの)rebaseによって、保持したいコミットと破棄したいコミットを選り分けることができます。コミットの順序を変更することも可能です。この方法は、一部の変更をどこかへやってしまいたい時に便利です。","","もう一方のcherry-pickを使うと、持っていきたいコミットを選んで`HEAD`の先にストンと落とすことができます。"]}},{type:"ModalAlert",options:{markdowns:["後半の章ですのでどう解決するかをもう自分で考えることができると思います。このレベルをクリアするためには、`bugFix`が持っているコミットを`master`ブランチが受け取る必要がある点には注意してください。"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 本地栈式提交 (Locally stacked commits)","","设想一下一个经常发生的场景:我在追踪一个有点棘手的 bug,为了更好地排查,我添加了一些调试命令和打印语句。","","所有的这些调试和打印语句都只在它们自己的分支里。最终我终于找到这个 bug,揪出来 fix 掉,然后撒花庆祝!","","现在唯一的问题就是要把我在 `bugFix` 分支里的工作合并回 `master` 分支。我可以简单地把 `master` 分支快进(fast-forward),但这样的话 `master` 分支就会包含我这些调试语句了。"]}},{type:"ModalAlert",options:{markdowns:["现在就是 Git 大显神通的时候啦。解决这个问题的方法不止一个,但最直接的两个方法是:","","* `git rebase -i`","* `git cherry-pick`","","交互(`-i`)衍合允许你选择哪些提交是要被保留,哪些要被舍弃。它允许你将提交重新排序。假如你要舍弃一些工作,这个会帮上很大的忙。","","Cherry-picking 能让你选择单独一个提交并且把它放到 `HEAD` 的最前端。"]}},{type:"ModalAlert",options:{markdowns:["本关是可选关卡,玩不玩随便你。但是如果你坚持要刷,确保 `master` 分支能拿到 `bugFix` 分支的相关提交(references)。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 로컬에 쌓인 커밋들","","개발중에 종종 이런 상황이 생깁니다: 잘 띄지 않는 버그를 찾아서 해결하려고, 어떤 부분의 문제인지를 찾기 위해 디버그용 코드와 화면에 정보를 프린트하는 코드 몇 줄 넣습니다. ","","디버깅용 코드나 프린트 명령은 그 브랜치에 들어있습니다. 마침내 버그를 찾아서 고쳤고, 원래 작업하는 브랜치에 합치면 됩니다!","","이제 `bugFix`브랜치의 내용을 `master`에 합쳐 넣으려 하지만, 한 가지 문제가 있습니다. 그냥 간단히 `master`브랜치를 최신 커밋으로 이동시킨다면(fast-forward) 그 불필요한 디버그용 코드들도 함께 들어가 버린다는 문제죠."]}},{type:"ModalAlert",options:{markdowns:["여기에서 Git의 마법이 드러납니다. 이 문제를 해결하는 여러가지 방법이 있습니다만, 가장 간단한 두가지 방법 아래와 같습니다:","","* `git rebase -i`","* `git cherry-pick`","","대화형 (-i 옵션) 리베이스(rebase)로는 어떤 커밋을 취하거나 버릴지를 선택할 수 있습니다. 또 커밋의 순서를 바꿀 수도 있습니다. 이 커맨드로 어떤 작업의 일부만 골라내기에 유용합니다.","","체리픽(cherry-pick)은 개별 커밋을 골라서 `HEAD`위에 떨어뜨릴 수 있습니다."]}},{type:"ModalAlert",options:{markdowns:["이번 레벨을 통과하기 위해 어떤 방법을 쓰시든 자유입니다만, `master`브랜치가 `bugFix` 브랜치의 커밋을 일부 가져오게 해주세요."]}}]}}}}),e("/src/levels/mixed/grabbingOneCommit.js"),e.define("/src/levels/mixed/jugglingCommits.js",function(e,t,n,r,i,s,o){n.level={disabledMap:{"git cherry-pick":!0,"git revert":!0},compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C2>e.C3},function(e){return e.C2>e.C1}]},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%27%27%22%2C%22id%22%3A%22master%22%7D%2C%22newImage%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22newImage%22%7D%2C%22caption%22%3A%7B%22target%22%3A%22C3%27%27%22%2C%22id%22%3A%22caption%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%2C%22C2%27%27%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%27%27%22%7D%2C%22C3%27%27%22%3A%7B%22parents%22%3A%5B%22C2%27%27%27%22%5D%2C%22id%22%3A%22C3%27%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git rebase -i HEAD~2;git commit --amend;git rebase -i HEAD~2;git rebase caption master",startTree:'{"branches":{"master":{"target":"C1","id":"master"},"newImage":{"target":"C2","id":"newImage"},"caption":{"target":"C3","id":"caption"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"caption","id":"HEAD"}}',name:{ko:"커밋들 갖고 놀기",en_US:"Juggling Commits",ja:"Juggling Commits",zh_CN:"提交变换戏法"},hint:{en_US:"The first command is git rebase -i HEAD~2",ja:"最初に打つコマンドはgit rebase -i HEAD~2",ko:"첫번째 명령은 git rebase -i HEAD~2 입니다",zh_CN:"第一个命令是 'git rebase -i HEAD~2'"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Juggling Commits","","Here's another situation that happens quite commonly. You have some changes (`newImage`) and another set of changes (`caption`) that are related, so they are stacked on top of each other in your repository (aka one after another).","","The tricky thing is that sometimes you need to make a small modification to an earlier commit. In this case, design wants us to change the dimensions of `newImage` slightly, even though that commit is way back in our history!!"]}},{type:"ModalAlert",options:{markdowns:["We will overcome this difficulty by doing the following:","","* We will re-order the commits so the one we want to change is on top with `git rebase -i`","* We will `commit --amend` to make the slight modification","* Then we will re-order the commits back to how they were previously with `git rebase -i`","* Finally, we will move master to this updated part of the tree to finish the level (via the method of your choosing)","","There are many ways to accomplish this overall goal (I see you eye-ing cherry-pick), and we will see more of them later, but for now let's focus on this technique."]}},{type:"ModalAlert",options:{markdowns:["Lastly, pay attention to the goal state here -- since we move the commits twice, they both get an apostrophe appended. One more apostrophe is added for the commit we amend, which gives us the final form of the tree ","","That being said, I can compare levels now based on structure and relative apostrophe differences. As long as your tree's `master` branch has the same structure and relative apostrophe differences, I'll give full credit"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Commitsをやりくりする","","開発中に頻繁に起こるケースをもう1つ考えます。ある変更(`newImage`)とまた別の変更(`caption`)があって、それらに依存関係があるとします。この一連の変更が一列に積み重なっているとします。","","ここでトリッキーなのは、以前のコミットに対して微修正をかけなければならないケースがあるということです。今回の教材でも、過去のコミットであるにも関わらず`newImage`ブランチに僅かな修正を加えるような設計の修正が入ったとしましょう。"]}},{type:"ModalAlert",options:{markdowns:["この困難な状況を、以下の手順で克服することを考えます:","","* `git rebase -i`を使って順番を変更する。これで、変更をかけたいコミットを一番先頭に持ってくる。","* `commit --amend`コマンドで僅かな変更を行う","* `git rebase -i`コマンドを再度使って、先頭に持ってきていたコミットを元に戻す","* 最後に、レベルクリアのためにmasterブランチを先頭に持ってくる","","クリアのための方法はいくつもありますが(cherry-pickを使うこともできます)、別の回答はまた後程の章で見ることにんして、今回は上記の方法でやってみることにしましょう。"]}},{type:"ModalAlert",options:{markdowns:["最後に、ゴール時点での状態に気を付けてください。今回2回ほどコミットを動かしますから、コミットへのポインタにはアポストロフィ(')が追加されます。commit --amendコマンドの実行でできたコミットには更にもう1つのアポストロフィが追加されます。 "]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 提交变换戏法","","下面这种情况也是经常出现的。例如你之前已经在 `newImage` 分支上做了一些提交,然后又在 `caption` 分支上做了一些相关的提交,因此它们看起来是一个连一个的(stacked on top of each other in your repository)。","","有点棘手的就是有时候你又想往先前的提交里做些小改动。呐,现在就是设计师想要我们去轻微改变下 `newImage` 的内容(change the dimensions slightly),尽管那个提交是很久很久以前的了。"]}},{type:"ModalAlert",options:{markdowns:["为了实现他的愿望,我们可以按照下面的方法来做:","","* 先用 `git rebase -i` 将提交重新排序,然后把我们想要修改的提交挪到最前","* 然后用 `commit --amend` 来进行一些小修改","* 接着再用 `git rebase -i` 来将他们按最开始的顺序重新排好","* 最后我们把 master 移到修改的最前端(用你自己喜欢的方法),就大功告成啦!","","当然还有许多方法可以完成这个任务(我知道你在看 cherry-pick 啦),之后我们会多点关注这些技巧啦,但现在暂时只专注上面这种方法。"]}},{type:"ModalAlert",options:{markdowns:["啊最后还要提醒你一下最终的形式 —— 因为我们把这个提交移动了两次,所以会分别产生一个省略提交(both get an apostrophe appended)。还有一个省略提交是因为我们为了实现最终效果去修改提交而添加的。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 커밋들 갖고 놀기","","이번에도 꽤 자주 발생하는 상황입니다. `newImage`와 `caption` 브랜치에 각각의 변경내역이 있고 서로 약간 관련이 있어서, 저장소에 차례로 쌓여있는 상황입니다.","","때로는 이전 커밋의 내용을 살짝 바꿔야하는 골치아픈 상황에 빠지게 됩니다. 이번에는 디자인 쪽에서 우리의 작업이력(history)에서는 이미 한참 전의 커밋 내용에 있는 `newImage`의 크기를 살짝 바꿔달라는 요청이 들어왔습니다."]}},{type:"ModalAlert",options:{markdowns:["이 문제를 다음과 같이 풀어봅시다:","","* `git rebase -i` 명령으로 우리가 바꿀 커밋을 가장 최근 순서로 바꾸어 놓습니다","* `commit --amend` 명령으로 커밋 내용을 정정합니다","* 다시 `git rebase -i` 명령으로 이 전의 커밋 순서대로 되돌려 놓습니다","* 마지막으로, master를 지금 트리가 변경된 부분으로 이동합니다. (편하신 방법으로 하세요)","","이 목표를 달성하기 위해서는 많은 방법이 있는데요(체리픽을 고민중이시죠?), 체리픽은 나중에 더 살펴보기로 하고, 우선은 위의 방법으로 해결해보세요."]}},{type:"ModalAlert",options:{markdowns:["최종적으로, 목표 결과를 눈여겨 보세요 -- 우리가 커밋을 두 번 옮겼기 때문에, 두 커밋 모두 따옴표 표시가 붙어있습니다. 정정한(amend) 커밋은 따옴표가 추가로 하나 더 붙어있습니다."]}}]}}}}),e("/src/levels/mixed/jugglingCommits.js"),e.define("/src/levels/mixed/jugglingCommits2.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22master%22%7D%2C%22newImage%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22newImage%22%7D%2C%22caption%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22caption%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%27%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout master;git cherry-pick C2;git commit --amend;git cherry-pick C3",disabledMap:{"git revert":!0},startTree:'{"branches":{"master":{"target":"C1","id":"master"},"newImage":{"target":"C2","id":"newImage"},"caption":{"target":"C3","id":"caption"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"caption","id":"HEAD"}}',compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C2>e.C3},function(e){return e.C2>e.C1}]},name:{ko:"커밋 갖고 놀기 #2",en_US:"Juggling Commits #2",ja:"コミットをやりくりする その2",zh_CN:"提交交换戏法 #2"},hint:{en_US:"Don't forget to forward master to the updated changes!",ja:"masterのポインタを先に進めることを忘れずに!",ko:"master를 변경 완료한 커밋으로 이동(forward)시키는 것을 잊지 마세요!",zh_CN:"别忘记了将 master 快进到最新的更新上!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Juggling Commits #2","","*If you haven't completed Juggling Commits #1 (the previous level), please do so before continuing*","","As you saw in the last level, we used `rebase -i` to reorder the commits. Once the commit we wanted to change was on top, we could easily --amend it and re-order back to our preferred order.","","The only issue here is that there is a lot of reordering going on, which can introduce rebase conflicts. Let's look at another method with `git cherry-pick`"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Remember that git cherry-pick will plop down a commit from anywhere in the tree onto HEAD (as long as that commit isn't upstream).","","Here's a small refresher demo:"],afterMarkdowns:["Nice! Let's move on"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["So in this level, let's accomplish the same objective of amending `C2` once but avoid using `rebase -i`. I'll leave it up to you to figure it out! :D","","Remember, the exact number of apostrophe's (') on the commit are not important, only the relative differences. For example, I will give credit to a tree that matches the goal tree but has one extra apostrophe everywhere"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## コミットをやりくりする その2","","*注意 この一つ前のレベル「コミットをやりくりする」をクリアしていない人は、まずそちらの問題をクリアしてきてください*","","前回見てきたように、コミット順序の変更のために、私たちは`rebase -i`コマンドを利用しました。ツリーの先頭に変更対象のコミットがあれば、--amendオプションを使うことで容易に変更を書きかえて、元の順序に戻すことができます。","","この場合に心配なことが一つだけあって、それは複数回の順序の変更が行われるので、rebaseのコンフリクト(衝突)が起こりうることです。こういうケースへの対策として、`git cherry-pick`を使った別の解決法について考えてみましょう。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["git cherry-pickを使うと、ツリーの中から複数のコミットを選んで、HEADの下に新しく作ることができましたね。","","簡単なデモを見てみましょう:"],afterMarkdowns:["できました!次へ進みましょう"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["このレベルでは、`C2`をamendすることで前回と同じ目的を達成しましょう。但し`rebase -i`は使わずにクリアしてください。どんな方法で進めるかはあなたにおまかせします!:D"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 提交变换戏法 #2","","*假如你还没有完成提交变换戏法 #1(前一关),这关不让玩哦!*","","如你在上一关所见,我们使用 `rebase -i` 来重排那些提交。只要把我们想要的提交挪到最顶端,我们就可以很容易地改变它,然后把它们重新排成我们想要的顺序。","","但唯一的问题就是这样做就要排很多次,有可能造成衍合冲突(rebase conflicts)。下面就看看用另外一种方法 `git cherry-pick` 是怎么做的吧。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["要在心理牢记 cherry-pick 可以从提交树的任何地方拿一个提交来放在 HEAD 上(尽管那个提交不在上游)。","","下面是一个小小的演示:"],command:"git cherry-pick C2",afterMarkdowns:["好滴咧,我们继续"],beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["那么这关呢,和上一关一样要改变提交 `C2`,但你要避免使用 `rebase -i`。自己想想要怎么解决吧,骚年! :D"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 커밋 갖고 놀기 #2","","*만약 이전 레벨의 커밋 갖고 놀기 #1을 풀지 않으셨다면, 계속하기에 앞서서 꼭 풀어보세요*","","이전 레벨에서 보셨듯이 `rebase -i` 명령으로 커밋의 순서를 바꿀 수 있습니다. 정정할 커밋이 바로 직전(top)에 있으면 간단히 --amend로 수정할 수 있고, 그리고 나서 다시 원하는 순서로 되돌려 놓으면 됩니다.","","이번에 한가지 문제는 순서를 꽤 많이 바꿔야한다는 점인데요, 그러다가 리베이스중에 충돌이 날 수 있습니다. 이번에는 다른 방법인 `git cherry-pick`으로 해결해 봅시다."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["git cherry-pick으로 HEAD에다 어떤 커밋이든 떨어 뜨려 놓을 수 있다고 알려드린것 기억나세요? (단, 그 커밋이 현재 가리키고 있는 커밋이 아니어야합니다)","","간단한 데모로 다시 알려드리겠습니다:"],afterMarkdowns:["좋아요! 계속할게요"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["그럼 이번 레벨에서는 아까와 마찬가지로 `C2` 커밋의 내용을 정정하되, `rebase -i`를 쓰지 말고 해보세요. ^.~"]}}]}}}}),e("/src/levels/mixed/jugglingCommits2.js"),e.define("/src/levels/rampup/detachedHead.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"C4","id":"HEAD"}}',solutionCommand:"git checkout C4",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Detach yo' HEAD",zh_CN:"分离HEAD"},hint:{en_US:"Use the label (hash) on the commit for help!",zh_CN:"使用提交记录上的标签(hash)来求助!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Moving around in Git","","Before we get to some of the more advanced features of Git, it's important to understand different ways to move through the commit tree that represents your project.","","Once you're comfortable moving around, your powers with other git commands will be amplified!","","","","",""]}},{type:"ModalAlert",options:{markdowns:["## HEAD","","First we have to talk about \"HEAD\". HEAD is the symbolic name for the currently checked out commit -- it's essentially what commit you're working on top of.","","HEAD always points to the most recent commit which is reflected in the working tree. Most git commands which make changes to the working tree will start by changing HEAD.","","Normally HEAD points to a branch name (like bugFix). When you commit, the status of bugFix is altered and this change is visible through HEAD."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's see this in action. Here we will reveal HEAD before and after a commit."],afterMarkdowns:["See! HEAD was hiding underneath our `master` branch all along."],command:"git checkout C1; git checkout master; git commit; git checkout C2",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["### Detaching HEAD","","Detaching HEAD just means attaching it to a commit instead of a branch. This is what it looks like beforehand:","","HEAD -> master -> C1",""],afterMarkdowns:["And now it's","","HEAD -> C1"],command:"git checkout C1",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["To complete this level, let's detach HEAD from `bugFix` and attach it to the commit instead.","","Specify this commit by its hash. The hash for each commit is displayed on the circle that represents the commit."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 在Git中前后移动","","在接触Git的更多高级主题之前,我们先学习用不同的方法在代表你的项目的提交记录树上前后移动。","","一旦能够熟练地在Git中前进后退,你使用其他git命令的威力也会被放大!","","","","",""]}},{type:"ModalAlert",options:{markdowns:["## HEAD","",'我们首先看一下"HEAD". HEAD是当前提交记录的符号名称 -- 其实就是你正在其基础进行工作的提交记录。',"","HEAD总是指向最近一次提交记录,表现为当前工作树。大多数修改工作树的git命令都开始于改变HEAD指向。","","HEAD通常指向分支名(比如bugFix)。你提交时,改变了bugFix的状态,这一变化通过HEAD变得可见。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["在实例中看一下。我们将会观察提交前后HEAD的位置。"],afterMarkdowns:["看! HEAD一直藏在`master`分支后面。"],command:"git checkout C1; git checkout master; git commit; git checkout C2",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["### 分离 HEAD","","分离HEAD就是让其指向一个提交记录而不是分支名。这是命令执行之前的样子: ","","HEAD -> master -> C1",""],afterMarkdowns:["现在变成了","","HEAD -> C1"],command:"git checkout C1",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["想完成此关,从`bugFix`分离出HEAD并让其指向一个提交记录。","","通过hash值指定提交记录。每个提交记录的hash值显示在代表提交记录的圆圈中。"]}}]}}}}),e("/src/levels/rampup/detachedHead.js"),e.define("/src/levels/rampup/relativeRefs.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"C3","id":"HEAD"}}',solutionCommand:"git checkout bugFix^",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Relative Refs (^)",zh_CN:"相对引用(^)"},hint:{en_US:"Remember the Caret (^) operator!",zh_CN:"记住插入(^)操作符!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Relative Refs","","Moving around in Git by specifying commit hashes can get a bit tedious. In the real world you won't have a nice commit tree visualization next to your terminal, so you'll have to use `git log` to see hashes.","","Furthermore, hashes are usually a lot longer in the real Git world as well. For instance, the hash of the commit that introduced the previous level is `fed2da64c0efc5293610bdd892f82a58e8cbc5d8`. Doesn't exactly roll off the tongue...","","The upside is that Git is smart about hashes. It only requires you to specify enough characters of the hash until it uniquely identifies the commit. So I can type `fed2` instead of the long string above."]}},{type:"ModalAlert",options:{markdowns:["Like I said, specifying commits by their hash isn't the most convenient thing ever, which is why Git has relative refs. They are awesome!","","With relative refs, you can start somewhere memorable (like the branch `bugFix` or `HEAD`) and work from there.","","Relative commits are powerful, but we will introduce two simple ones here:","","* Moving upwards one commit at a time with `^`","* Moving upwards a number of times with `~`"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's look at the Caret (^) operator first. Each time you append that to a ref name, you are telling Git to find the parent of the specified commit.","",'So saying `master^` is equivalent to "the first parent of `master`".',"","`master^^` is the grandparent (second-generation ancestor) of `master`","","Let's check out the commit above master here"],afterMarkdowns:["Boom! Done. Way easier than typing the commit hash"],command:"git checkout master^",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["You can also reference `HEAD` as a relative ref. Let's use that a couple of times to move upwards in the commit tree"],afterMarkdowns:["Easy! We can travel backwards in time with `HEAD^`"],command:"git checkout C3; git checkout HEAD^; git checkout HEAD^; git checkout HEAD^",beforeCommand:"git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["To complete this level, check out the parent commit of `bugFix`. This will detach `HEAD`.","","You can specify the hash if you want, but try using relative refs instead!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 相对引用","","用指定提交记录hash值的方式在Git中移动会变得比较乏味。在现实中,你不会有漂亮的可视化的提交记录树放在终端旁边,所以你不得不用`git log`来查看hasn值。","","另外,hash值在真实的Git环境中也会更长。举个例子,前一关的介绍中的提交记录的hash值是`fed2da64c0efc5293610bdd892f82a58e8cbc5d8`。不要把舌头闪了...","","好的一面是,Git对hash的处理很智能。你只需要提供能够唯一标识提交记录的前几个字符即可。所以,我可以仅输入`fed2`而不是上面的一长串字符。"]}},{type:"ModalAlert",options:{markdowns:["我说过,通过hash指定提交记录不是很方便,所以Git引入了相对引用。这个就很牛掰了!","","使用相对引用,你可以从一个易于记忆的地方(比如分支名`bugFix`或`HEAD`)开始工作。","","相对引用非常给力,这里我介绍两个简单的用法:","","* 使用`^`向上移动1个提交记录","* 使用`~`向上移动多个提交记录"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["首先看看插入(^)操作符。把插入符跟在引用名后面,表示让Git寻找指定提交记录的父提交。","",'所以`master^`相当于"`master`的父提交"。',"","`master^^`是`master`的父父提交(上上代祖先)","","切换到master的父提交"],afterMarkdowns:["唰!搞定。这种方式比输入提交记录的hash值简单多了!"],command:"git checkout master^",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["你也可以`HEAD`把用作相对引用。以下命令使用`HEAD`在提交树中向上移动几次。"],afterMarkdowns:["简单!我们可以一直使用`HEAD^`向上移动。"],command:"git checkout C3; git checkout HEAD^; git checkout HEAD^; git checkout HEAD^",beforeCommand:"git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["要完成此关,切换到`bugFix`的父提交。这会分离出`HEAD`.","","如果你愿意的话,使用hash值也可以过关,但为何不试试使用相对引用呢?"]}}]}}}}),e("/src/levels/rampup/relativeRefs.js"),e.define("/src/levels/rampup/relativeRefs2.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C6","id":"master"},"bugFix":{"target":"C0","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C5":{"parents":["C3"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"C1","id":"HEAD"}}',solutionCommand:"git branch -f master C6;git checkout HEAD~1;git branch -f bugFix HEAD~1",startTree:'{"branches":{"master":{"target":"C4","id":"master"},"bugFix":{"target":"C5","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C5":{"parents":["C3"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"C2","id":"HEAD"}}',hint:{en_US:"You'll need to use at least one direct reference (hash) to complete this level",zh_CN:"这一关至少要用到一次直接引用(hash)"},name:{en_US:"Relative Refs #2 (~)",zh_CN:"相对引用2(~)"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:['### The "~" operator',"","Say you want to move a lot of levels up in the commit tree. It might be tedious to type `^` several times, so Git also has the tilde (~) operator.","","","The tilde operator (optionally) takes in a trailing number that specifies the number of parents you would like to ascend. Let's see it in action"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's specify a number of commits back with `~`."],afterMarkdowns:["Boom! So concise -- relative refs are great."],command:"git checkout HEAD~4",beforeCommand:"git commit; git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["### Branch forcing","","You're an expert on relative refs now, so let's actually *use* them for something.","","One of the most common ways I use relative refs is to move branches around. You can directly reassign a branch to a commit with the `-f` option. So something like:","","`git branch -f master HEAD~3`","","Moves (by force) the master branch to three parents behind HEAD."]}},{type:"ModalAlert",options:{markdowns:["To complete this level, move `HEAD`, `master`, and `bugFix` to their goal destinations shown."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:['### The "~" operator',"","假设需要在提交树中向上移动很多步。使用多个`^`非常无聊,所以Git也引入了波浪(~)操作符。","","","波浪操作符后面可以(可选地)跟一个数字,指定向上移动多少次。看个例子"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用`~`一次后退多步."],afterMarkdowns:["唰!如此简洁--相对引用就是好啊!"],command:"git checkout HEAD~4",beforeCommand:"git commit; git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["### Branch forcing","","你现在是相对引用的高手了,现在*用*他来实际做点事情。","","我使用相对引用最多的就是移动分支。你可以使用`-f`选项把直接让分支指向另一个提交。举个例子:","","`git branch -f master HEAD~3`","","(强制)移动master指向HEAD的第3级父提交。"]}},{type:"ModalAlert",options:{markdowns:["要完成此关,移动`HEAD`,`master`和`bugFix`到目标所示的位置。"]}}]}}}}),e("/src/levels/rampup/relativeRefs2.js"),e.define("/src/levels/rampup/reversingChanges.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22master%22%7D%2C%22pushed%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22pushed%22%7D%2C%22local%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22local%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C2%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22pushed%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git reset HEAD~1;git checkout pushed;git revert HEAD",compareOnlyBranches:!0,startTree:'{"branches":{"master":{"target":"C1","id":"master"},"pushed":{"target":"C2","id":"pushed"},"local":{"target":"C3","id":"local"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"}},"HEAD":{"target":"local","id":"HEAD"}}',name:{en_US:"Reversing Changes in Git",ja:"変更を元に戻す",fr_FR:"Annuler des changements avec Git",ko:"Git에서 작업 되돌리기",zh_CN:"在Git中撤销更改"},hint:{en_US:"Notice that revert and reset take different arguments.",fr_FR:"",zh_CN:"注意revert和reset使用不同的参数。",ko:"",ja:""},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Reversing Changes in Git","","There are many ways to reverse changes in Git. And just like committing, reversing changes in Git has both a low-level component (staging individual files or chunks) and a high-level component (how the changes are actually reversed). Our application will focus on the latter.","","There are two primary ways to undo changes in Git -- one is using `git reset` and the other is using `git revert`. We will look at each of these in the next dialog",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","",'`git reset` reverts changes by moving a branch reference backwards in time to an older commit. In this sense you can think of it as "rewriting history;" `git reset` will move a branch backwards as if the commit had never been made in the first place.',"","Let's see what that looks like:"],afterMarkdowns:["Nice! Git simply moved the master branch reference back to `C1`; now our local repository is in a state as if `C2` had never happened"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","",'While reseting works great for local branches on your own machine, its method of "rewriting history" doesn\'t work for remote branches that others are using.',"","In order to reverse changes and *share* those reversed changes with others, we need to use `git revert`. Let's see it in action"],afterMarkdowns:["Weird, a new commit plopped down below the commit we wanted to reverse. That's because this new commit `C2'` introduces *changes* -- it just happens to introduce changes that exactly reverses the commit of `C2`.","","With reverting, you can push out your changes to share with others."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["To complete this level, reverse the two most recent commits on both `local` and `pushed`.","","Keep in mind that `pushed` is a remote branch and `local` is a local branch -- that should help you choose your methods."]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## 変更を元に戻す","","Gitでは変更を元に戻す方法がたくさんあります。コミットと同じように、低レベルな動作(ファイル別だったりファイルの中の一部だったり)も高レベルな動作(変更のまとまりのキャンセル)もできます。このアプリケーションでは後者の方法について紹介します。","","基本的なアンドゥの方法が2つあります - 一つは`git reset`を使う方法で、もう1つは`git revert`を使う方法です。次のダイアログで一つ一つを見ていきます。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","","`git reset`はブランチのポインタを後方に移動することで変更のキャンセルを実現します。履歴を上書きするような動作だと思うと良いでしょうか:`git reset`はそもそも前のコミットなんかなかったかのように、ブランチのポインタを元に戻してくれます。","","どういう感じか見てみましょう。"],afterMarkdowns:["いいですね!Gitは単純にmasterブランチへのポインタを`C1`へ戻しました。これでこのローカルリポジトリにはまるで`C2`なんて無かったかのように変更をキャンセルできました。"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","自分のマシン上のブランチではさっきの`git reset`でうまくいきましたが、この「履歴を上書きする」手段は、他の人も使っているリモートにあるリポジトリに対しては使うことができません。","","変更を巻き戻して他の人とそれを共有するためには、`git revert`を使う必要があります。今度はこれを見てみましょう。"],afterMarkdowns:["あれ、おかしいな。巻き戻したいと思ってたコミットの下に新しいコミットが出来上がってしまったみたいです。なぜか。これは、この新しい`C2'`コミットは`C2`へ戻すのに必要な内容を確かに変更して巻き戻していたのです。","","こんな風にして、巻き戻した内容を他人と共有するためにはrevertを使います。"],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["この章の仕上げに、`local`と`pushed`の両方の直近のコミットを巻き戻してみましょう。","","`pushed`はリモートのブランチで、`local`はローカルであることに注意。正しくコマンドを使い分けましょう。"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Annuler des changements avec Git","","Il y a de nombreuses façons d'annuler des changement avec Git. De même que pour les commits, annuler des changements avec Git a à la fois un aspect bas-niveau (gestion dans le 'staging' des fichiers et morceaux de fichiers) et un aspect de plus haut niveau 9comment les changements sont effectivement annulés). Nous allons nous intéresser à ce dernier point.","","Il y a principalement deux façons d'annuler des changements avec Git -- l'une est `git reset` et l'autre est `git revert`. Nous allons maintenant voir chacune de ces façons",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","","`git reset` annule des changements en déplaçant la référence en arrière dans le temps sur un commit plus ancien. En ce sens, on peut considérer cela comme une façon de \"réécrire l'histoire\"; `git reset` fait remonter une branche en arrière comme si le(s) commit(s) n'avait jamais eu lieu.","","Regardons à quoi cela ressemble :"],afterMarkdowns:["Bravo ! Git a simplement déplacé la référence de la branche master en la faisant revenir sur `C1`; désormais notre dépôt est dans le même état que si `C2` n'avait jamais eu lieu"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","Bien que le reset marche parfaitement pour les branches locales sur notre propre machine, cette façon de \"réécrire l'histoire\" ne marche pas avec les banches distantes (remote) que d'autres personnes utilisent.","","Pour pouvoir annuler des changements et *partager* ces annulations avec d'autres, nous devons utiliser `git revert`. Regardons comment cela fonctionne"],afterMarkdowns:["Étrangement, un nouveau commit est appaaru en bas sous le commit que nous voulions annuler. C'est parce que ce nouveau commit `C2'` introduit des *modifications* -- celles qui correspondent justement à l'annulation de celles du commit `C2`.","","Avec revert, vous pouvez diffuser (push) vos modifications et les partager avec tout le monde."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["Pour accomplir ce niveau, annulez les deux derniers commits à la fois sur `local` et sur `pushed`.","","Ayez à l'esprit que `pushed` est une branche distante et `local` est une branche locale -- cela devrait vous guider dans le choix de la méthode à employer."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 撤销 Git 里面的变动","","在 Git 里撤销修改的方法很多。和 commit 一样,在 Git 里撤销变动同时具有底层部分(暂存一些独立的文件或者片段)和高层部分(具体到变动是究竟怎么被撤销的)。我们这个应用主要关注后者。","","在 Git 里主要用两种方法来撤销变动 —— 一种是 `git reset`,另外一种是 `git revert`。让我们在下一个窗口逐一了解它们。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","",'`git reset`把分支记录回退到上一个提交记录来实现撤销改动。你可以认为这是在"重写历史"。`git reset`往回移动分支,原来指向的提交记录好像重来没有提交过一样。',"","让我们看看具体的操作:"],command:"git reset HEAD~1",afterMarkdowns:["Nice!Git把master分支的指向简单地移回到`C1`;现在我们的本地代码库处于没有提交过`C2`的状态了。"],beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","虽然在你的本地分支中使用`git reset`很方便,但是这种“改写历史”的方法对别人的远端分支是无效的哦!","","为了撤销更改并*传播*给别人,我们需要使用`git revert`。举个例子"],command:"git revert HEAD",afterMarkdowns:["怪哉!在我们要撤销的提交记录后面居然多了一个新提交!这是因为新提交记录`C2'`引入了*更改*——刚好是用来撤销 `C2` 这个提交的。","","借助 revert,现在可以把你的更改传递给别人啦。"],beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["要完成此关,分别撤销`local`分支和`pushed`分支上的最近一次提交。","","记住 `pushed` 是一个远程分支,`local` 是一个本地分支 —— 有了这么明显的提示应该知道用哪种方法了吧?"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git에서 작업 되돌리기","","Git에는 작업한 것을 되돌리는 여러가지 방법이 있습니다. 변경내역을 되돌리는 것도 커밋과 마찬가지로 낮은 수준의 일(개별 파일이나 묶음을 스테이징 하는 것)과 높은 수준의 일(실제 변경이 복구되는 방법)이 있는데요, 여기서는 후자에 집중해 알려드릴게요.","","Git에서 변경한 내용을 되돌리는 방법은 크게 두가지가 있습니다 -- 하나는 `git reset`을 쓰는거고, 다른 하나는 `git revert`를 사용하는 것입니다. 다음 화면에서 하나씩 알아보겠습니다.",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git 리셋(reset)","",'`git reset`은 브랜치로 하여금 예전의 커밋을 가리키도록 이동시키는 방식으로 변경 내용을 되돌립니다. 이런 관점에서 "히스토리를 고쳐쓴다"라고 말할 수 있습니다. 즉, `git reset`은 마치 애초에 커밋하지 않은 것처럼 예전 커밋으로 브랜치를 옮기는 것입니다.',"","어떤 그림인지 한번 보죠:"],afterMarkdowns:["그림에서처럼 master 브랜치가 가리키던 커밋을 `C1`로 다시 옮겼습니다; 이러면 로컬 저장소에는 마치 `C2`커밋이 아예 없었던 것과 마찬가지 상태가 됩니다."],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git 리버트(revert)","",'각자의 컴퓨터에서 작업하는 로컬 브랜치의 경우 리셋(reset)을 잘 쓸 수 있습니다만, "히스토리를 고쳐쓴다"는 점 때문에 다른 사람이 작업하는 리모트 브랜치에는 쓸 수 없습니다.',"","변경분을 되돌리고, 이 되돌린 내용을 다른 사람들과 *공유하기* 위해서는, `git revert`를 써야합니다. 예제로 살펴볼게요."],afterMarkdowns:["어색하게도, 우리가 되돌리려고한 커밋의 아래에 새로운 커밋이 생겼습니다. `C2`라는 새로운 커밋에 *변경내용*이 기록되는데요, 이 변경내역이 정확히 `C2` 커밋 내용의 반대되는 내용입니다.","","리버트를 하면 다른 사람들에게도 변경 내역을 밀어(push) 보낼 수 있습니다."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["이 레벨을 통과하려면, `local` 브랜치와 `pushed` 브랜치에 있는 최근 두 번의 커밋을 되돌려 보세요.","","`pushed`는 리모트 브랜치이고, `local`은 로컬 브랜치임을 신경쓰셔서 작업하세요 -- 어떤 방법을 선택하실지 떠오르시죠?"]}}]}}}}),e("/src/levels/rampup/reversingChanges.js"),e.define("/src/levels/rebase/manyRebases.js",function(e,t,n,r,i,s,o){n.level={compareOnlyMasterHashAgnostic:!0,disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22master%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22bugFix%22%7D%2C%22side%22%3A%7B%22target%22%3A%22C6%27%22%2C%22id%22%3A%22side%22%7D%2C%22another%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22another%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C6%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C6%22%7D%2C%22C7%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C7%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C6%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C6%27%22%7D%2C%22C7%27%22%3A%7B%22parents%22%3A%5B%22C6%27%22%5D%2C%22id%22%3A%22C7%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout bugFix;git rebase master;git checkout side;git rebase bugFix;git checkout another;git rebase side;git rebase another master",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C3","id":"bugFix"},"side":{"target":"C6","id":"side"},"another":{"target":"C7","id":"another"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C0"],"id":"C4"},"C5":{"parents":["C4"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"},"C7":{"parents":["C5"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Rebasing over 9000 times",ko:"9천번이 넘는 리베이스",ja:"Rebasing over 9000 times",zh_CN:"N次Rebase"},hint:{en_US:"Remember, the most efficient way might be to only update master at the end...",ja:"最も効率的なやり方はmasterを最後に更新するだけかもしれない・・・",ko:"아마도 master를 마지막에 업데이트하는 것이 가장 효율적인 방법일 것입니다...",zh_CN:"记住,最后更新master分支可能是最高效的方法。"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["### Rebasing Multiple Branches","","Man, we have a lot of branches going on here! Let's rebase all the work from these branches onto master.","","Upper management is making this a bit trickier though -- they want the commits to all be in sequential order. So this means that our final tree should have `C7'` at the bottom, `C6'` above that, etc etc, etc all in order.","","If you mess up along the way, feel free to use `reset` to start over again. Be sure to check out our solution and see if you can do it in fewer commands!"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["### 複数のブランチをリベースする","","さあ、いくつものブランチが出てきます。このブランチたち全てをmasterブランチにリベースしましょう。","","おエライさん方が今回の仕事を少しトリッキーにしてくれました ― コミットはすべて一列のシーケンシャルな状態にしてほしいそうです。つまり私たちが作るリポジトリの最終的なツリーの状態は、`C7'`が最後に来て、`C6'`がその一つ上に来て、、と順に積み重なるイメージです。","","試行錯誤してツリーが汚くなってきたら、`reset`コマンドを使ってツリーの状態を初期化してください。模範解答をチェックして、それよりも簡単なコマンドで済ませられるかどうか、を考えるのも忘れずに!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["### 多分支衍合","","呐,现在我们有很多分支啦!让我们rebase这些分支的工作到 master 分支上吧。","","但是你的头头找了点麻烦 —— 他们希望得到有序的提交历史,也就是我们最终的结果是 `C7'` 在最底部,`C6'` 在它上面,以此类推。","","假如你搞砸了,没所谓的(虽然我不会告诉你用 `reset` 可以重新开始)。记得看看我们提供的答案,看你能否使用更少的命令完成任务!"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["### 여러 브랜치를 리베이스(rebase)하기 ","","음, 여기 꽤 여러개의 브랜치가 있습니다! 이 브랜치들의 모든 작업내역을 master에 리베이스 해볼까요?","","윗선에서 일을 복잡하게 만드네요 -- 그 분들이 이 모든 커밋들을 순서에 맞게 정렬하라고 합니다. 그럼 결국 우리의 최종 목표 트리는 제일 아래에 `C7'` 커밋, 그 위에 `C6'` 커밋, 또 그 위에 순서대로 보여합니다.","","만일 작업중에 내용이 꼬인다면, `reset`이라고 쳐서 처음부터 다시 시작할 수 있습니다. 모범 답안을 확인해 보시고, 혹시 더 적은 수의 커맨드로 해결할 수 있는지 알아보세요!"]}}]}}}}),e("/src/levels/rebase/manyRebases.js"),e.define("/src/levels/rebase/selectiveRebase.js",function(e,t,n,r,i,s,o){n.level={compareAllBranchesHashAgnostic:!0,disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C5%22%2C%22id%22%3A%22master%22%7D%2C%22one%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22one%22%7D%2C%22two%22%3A%7B%22target%22%3A%22C2%27%27%22%2C%22id%22%3A%22two%22%7D%2C%22three%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22three%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C4%27%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C4%27%27%22%7D%2C%22C3%27%27%22%3A%7B%22parents%22%3A%5B%22C4%27%27%22%5D%2C%22id%22%3A%22C3%27%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C3%27%27%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22two%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout one; git cherry-pick C4 C3 C2; git checkout two; git cherry-pick C5 C4 C3 C2; git branch -f three C2",startTree:'{"branches":{"master":{"target":"C5","id":"master"},"one":{"target":"C1","id":"one"},"two":{"target":"C1","id":"two"},"three":{"target":"C1","id":"three"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C4"],"id":"C5"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{ko:"브랜치 스파게티",en_US:"Branch Spaghetti",ja:"ブランチスパゲッティ",zh_CN:"分支浆糊"},hint:{en_US:"Make sure to do everything in the proper order! Branch one first, then two, then three",ja:"全て正しい順番で処理すること!oneが最初で、次がtwo、最後にthreeを片付ける。",ko:"이 문제를 해결하는 방법은 여러가지가 있습니다! 체리픽(cherry-pick)이 가장 쉽지만 오래걸리는 방법이고, 리베이스(rebase -i)가 빠른 방법입니다",zh_CN:"确保你是按照正确的顺序来操作!先操作分支 `one`, 然后 `two`, 最后才是 `three`"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branch Spaghetti","","WOAHHHhhh Nelly! We have quite the goal to reach in this level.","","Here we have `master` that is a few commits ahead of branches `one` `two` and `three`. For whatever reason, we need to update these three other branches with modified versions of the last few commits on master.","","Branch `one` needs a re-ordering and a deletion of `C5`. `two` needs pure reordering, and `three` only needs one commit!","","We will let you figure out how to solve this one -- make sure to check out our solution afterwards with `show solution`. "]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ブランチスパゲッティ","","なんということでしょう。今回のレベルクリアのために、やることがたくさんあります。","","いま`master`が指しているコミットの数個前のコミットに、ブランチ`one`、`two`それから`three`があります。何か事情があって、これらの3つのブランチをmasterが指している最新の状態に更新したいケースを考えます。","","ブランチ`one`に対しては、順序の変更と`C5`の削除が必要です。`two`では順序の変更のみ、`three`に対しては1回だけコミットすればOKです。","","`show solution`コマンドで模範解答を確認できますから、こちらも利用してください。 "]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branch Spaghetti","","哇塞大神!这关我们要来点不同的!","","现在我们的 `master` 分支是比 `one` `two` 和 `three` 要多几个提交。出于某种原因,我们需要把其他三个分支更新到 master 分支上新近的几个不同提交上。(update these three other brances with modified versions of the last few commits on master)","","分支 `one` 需要重新排序和撤销, `two` 需要完全重排,而 `three` 只需要提交一次。","","慢慢摸索会找到答案的 —— 你完事记得用 `show solution` 看看我们的答案哦。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 브랜치 스파게티","","음, 이번에는 만만치 않습니다!","","여기 `master` 브랜치의 몇 번 이전 커밋에 `one`, `two`,`three` 총 3개의 브랜치가 있습니다. 어떤 이유인지는 몰라도, master의 최근 커밋 몇 개를 나머지 세 개의 브랜치에 반영하려고 합니다.","","`one` 브랜치는 순서를 바꾸고 `C5`커밋을 삭제하고, `two`브랜치는 순서만 바꾸며, `three`브랜치는 하나의 커밋만 가져옵시다!","","자유롭게 이 문제를 풀어보시고 나서 `show solution`명령어로 모범 답안을 확인해보세요."]}}]}}}}),e("/src/levels/rebase/selectiveRebase.js")})(); \ No newline at end of file diff --git a/build/bundle.min.ef516df2.js b/build/bundle.min.ef516df2.js deleted file mode 100644 index a8b4b8c2..00000000 --- a/build/bundle.min.ef516df2.js +++ /dev/null @@ -1 +0,0 @@ -(function(){var e=function(t,n){var r=e.resolve(t,n||"/"),i=e.modules[r];if(!i)throw new Error("Failed to resolve module "+t+", tried "+r);var s=e.cache[r],o=s?s.exports:i();return o};e.paths=[],e.modules={},e.cache={},e.extensions=[".js",".coffee",".json"],e._core={assert:!0,events:!0,fs:!0,path:!0,vm:!0},e.resolve=function(){return function(t,n){function u(t){t=r.normalize(t);if(e.modules[t])return t;for(var n=0;n=0;i--){if(t[i]==="node_modules")continue;var s=t.slice(0,i+1).join("/")+"/node_modules";n.push(s)}return n}n||(n="/");if(e._core[t])return t;var r=e.modules.path();n=r.resolve("/",n);var i=n||"/";if(t.match(/^(?:\.\.?\/|\/)/)){var s=u(r.resolve(i,t))||a(r.resolve(i,t));if(s)return s}var o=f(t,i);if(o)return o;throw new Error("Cannot find module '"+t+"'")}}(),e.alias=function(t,n){var r=e.modules.path(),i=null;try{i=e.resolve(t+"/package.json","/")}catch(s){i=e.resolve(t,"/")}var o=r.dirname(i),u=(Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t})(e.modules);for(var a=0;a=0;r--){var i=e[r];i=="."?e.splice(r,1):i===".."?(e.splice(r,1),n++):n&&(e.splice(r,1),n--)}if(t)for(;n--;n)e.unshift("..");return e}var f=/^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;n.resolve=function(){var e="",t=!1;for(var n=arguments.length;n>=-1&&!t;n--){var r=n>=0?arguments[n]:s.cwd();if(typeof r!="string"||!r)continue;e=r+"/"+e,t=r.charAt(0)==="/"}return e=a(u(e.split("/"),function(e){return!!e}),!t).join("/"),(t?"/":"")+e||"."},n.normalize=function(e){var t=e.charAt(0)==="/",n=e.slice(-1)==="/";return e=a(u(e.split("/"),function(e){return!!e}),!t).join("/"),!e&&!t&&(e="."),e&&n&&(e+="/"),(t?"/":"")+e},n.join=function(){var e=Array.prototype.slice.call(arguments,0);return n.normalize(u(e,function(e,t){return e&&typeof e=="string"}).join("/"))},n.dirname=function(e){var t=f.exec(e)[1]||"",n=!1;return t?t.length===1||n&&t.length<=3&&t.charAt(1)===":"?t:t.substring(0,t.length-1):"."},n.basename=function(e,t){var n=f.exec(e)[2]||"";return t&&n.substr(-1*t.length)===t&&(n=n.substr(0,n.length-t.length)),n},n.extname=function(e){return f.exec(e)[3]||""}}),e.define("__browserify_process",function(e,t,n,r,i,s,o){var s=t.exports={};s.nextTick=function(){var e=typeof window!="undefined"&&window.setImmediate,t=typeof window!="undefined"&&window.postMessage&&window.addEventListener;if(e)return function(e){return window.setImmediate(e)};if(t){var n=[];return window.addEventListener("message",function(e){if(e.source===window&&e.data==="browserify-tick"){e.stopPropagation();if(n.length>0){var t=n.shift();t()}}},!0),function(t){n.push(t),window.postMessage("browserify-tick","*")}}return function(t){setTimeout(t,0)}}(),s.title="browser",s.browser=!0,s.env={},s.argv=[],s.binding=function(t){if(t==="evals")return e("vm");throw new Error("No such module. (Possibly not yet loaded)")},function(){var t="/",n;s.cwd=function(){return t},s.chdir=function(r){n||(n=e("path")),t=n.resolve(r,t)}}()}),e.define("/node_modules/underscore/package.json",function(e,t,n,r,i,s,o){t.exports={main:"underscore.js"}}),e.define("/node_modules/underscore/underscore.js",function(e,t,n,r,i,s,o){(function(){var e=this,r=e._,i={},s=Array.prototype,o=Object.prototype,u=Function.prototype,a=s.push,f=s.slice,l=s.concat,c=o.toString,h=o.hasOwnProperty,p=s.forEach,d=s.map,v=s.reduce,m=s.reduceRight,g=s.filter,y=s.every,b=s.some,w=s.indexOf,E=s.lastIndexOf,S=Array.isArray,x=Object.keys,T=u.bind,N=function(e){if(e instanceof N)return e;if(!(this instanceof N))return new N(e);this._wrapped=e};typeof n!="undefined"?(typeof t!="undefined"&&t.exports&&(n=t.exports=N),n._=N):e._=N,N.VERSION="1.4.4";var C=N.each=N.forEach=function(e,t,n){if(e==null)return;if(p&&e.forEach===p)e.forEach(t,n);else if(e.length===+e.length){for(var r=0,s=e.length;r2;e==null&&(e=[]);if(v&&e.reduce===v)return r&&(t=N.bind(t,r)),i?e.reduce(t,n):e.reduce(t);C(e,function(e,s,o){i?n=t.call(r,n,e,s,o):(n=e,i=!0)});if(!i)throw new TypeError(k);return n},N.reduceRight=N.foldr=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(m&&e.reduceRight===m)return r&&(t=N.bind(t,r)),i?e.reduceRight(t,n):e.reduceRight(t);var s=e.length;if(s!==+s){var o=N.keys(e);s=o.length}C(e,function(u,a,f){a=o?o[--s]:--s,i?n=t.call(r,n,e[a],a,f):(n=e[a],i=!0)});if(!i)throw new TypeError(k);return n},N.find=N.detect=function(e,t,n){var r;return L(e,function(e,i,s){if(t.call(n,e,i,s))return r=e,!0}),r},N.filter=N.select=function(e,t,n){var r=[];return e==null?r:g&&e.filter===g?e.filter(t,n):(C(e,function(e,i,s){t.call(n,e,i,s)&&(r[r.length]=e)}),r)},N.reject=function(e,t,n){return N.filter(e,function(e,r,i){return!t.call(n,e,r,i)},n)},N.every=N.all=function(e,t,n){t||(t=N.identity);var r=!0;return e==null?r:y&&e.every===y?e.every(t,n):(C(e,function(e,s,o){if(!(r=r&&t.call(n,e,s,o)))return i}),!!r)};var L=N.some=N.any=function(e,t,n){t||(t=N.identity);var r=!1;return e==null?r:b&&e.some===b?e.some(t,n):(C(e,function(e,s,o){if(r||(r=t.call(n,e,s,o)))return i}),!!r)};N.contains=N.include=function(e,t){return e==null?!1:w&&e.indexOf===w?e.indexOf(t)!=-1:L(e,function(e){return e===t})},N.invoke=function(e,t){var n=f.call(arguments,2),r=N.isFunction(t);return N.map(e,function(e){return(r?t:e[t]).apply(e,n)})},N.pluck=function(e,t){return N.map(e,function(e){return e[t]})},N.where=function(e,t,n){return N.isEmpty(t)?n?null:[]:N[n?"find":"filter"](e,function(e){for(var n in t)if(t[n]!==e[n])return!1;return!0})},N.findWhere=function(e,t){return N.where(e,t,!0)},N.max=function(e,t,n){if(!t&&N.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.max.apply(Math,e);if(!t&&N.isEmpty(e))return-Infinity;var r={computed:-Infinity,value:-Infinity};return C(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o>=r.computed&&(r={value:e,computed:o})}),r.value},N.min=function(e,t,n){if(!t&&N.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.min.apply(Math,e);if(!t&&N.isEmpty(e))return Infinity;var r={computed:Infinity,value:Infinity};return C(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;or||n===void 0)return 1;if(n>>1;n.call(r,e[u])=0})})},N.difference=function(e){var t=l.apply(s,f.call(arguments,1));return N.filter(e,function(e){return!N.contains(t,e)})},N.zip=function(){var e=f.call(arguments),t=N.max(N.pluck(e,"length")),n=new Array(t);for(var r=0;r=0;n--)t=[e[n].apply(this,t)];return t[0]}},N.after=function(e,t){return e<=0?t():function(){if(--e<1)return t.apply(this,arguments)}},N.keys=x||function(e){if(e!==Object(e))throw new TypeError("Invalid object");var t=[];for(var n in e)N.has(e,n)&&(t[t.length]=n);return t},N.values=function(e){var t=[];for(var n in e)N.has(e,n)&&t.push(e[n]);return t},N.pairs=function(e){var t=[];for(var n in e)N.has(e,n)&&t.push([n,e[n]]);return t},N.invert=function(e){var t={};for(var n in e)N.has(e,n)&&(t[e[n]]=n);return t},N.functions=N.methods=function(e){var t=[];for(var n in e)N.isFunction(e[n])&&t.push(n);return t.sort()},N.extend=function(e){return C(f.call(arguments,1),function(t){if(t)for(var n in t)e[n]=t[n]}),e},N.pick=function(e){var t={},n=l.apply(s,f.call(arguments,1));return C(n,function(n){n in e&&(t[n]=e[n])}),t},N.omit=function(e){var t={},n=l.apply(s,f.call(arguments,1));for(var r in e)N.contains(n,r)||(t[r]=e[r]);return t},N.defaults=function(e){return C(f.call(arguments,1),function(t){if(t)for(var n in t)e[n]==null&&(e[n]=t[n])}),e},N.clone=function(e){return N.isObject(e)?N.isArray(e)?e.slice():N.extend({},e):e},N.tap=function(e,t){return t(e),e};var _=function(e,t,n,r){if(e===t)return e!==0||1/e==1/t;if(e==null||t==null)return e===t;e instanceof N&&(e=e._wrapped),t instanceof N&&(t=t._wrapped);var i=c.call(e);if(i!=c.call(t))return!1;switch(i){case"[object String]":return e==String(t);case"[object Number]":return e!=+e?t!=+t:e==0?1/e==1/t:e==+t;case"[object Date]":case"[object Boolean]":return+e==+t;case"[object RegExp]":return e.source==t.source&&e.global==t.global&&e.multiline==t.multiline&&e.ignoreCase==t.ignoreCase}if(typeof e!="object"||typeof t!="object")return!1;var s=n.length;while(s--)if(n[s]==e)return r[s]==t;n.push(e),r.push(t);var o=0,u=!0;if(i=="[object Array]"){o=e.length,u=o==t.length;if(u)while(o--)if(!(u=_(e[o],t[o],n,r)))break}else{var a=e.constructor,f=t.constructor;if(a!==f&&!(N.isFunction(a)&&a instanceof a&&N.isFunction(f)&&f instanceof f))return!1;for(var l in e)if(N.has(e,l)){o++;if(!(u=N.has(t,l)&&_(e[l],t[l],n,r)))break}if(u){for(l in t)if(N.has(t,l)&&!(o--))break;u=!o}}return n.pop(),r.pop(),u};N.isEqual=function(e,t){return _(e,t,[],[])},N.isEmpty=function(e){if(e==null)return!0;if(N.isArray(e)||N.isString(e))return e.length===0;for(var t in e)if(N.has(e,t))return!1;return!0},N.isElement=function(e){return!!e&&e.nodeType===1},N.isArray=S||function(e){return c.call(e)=="[object Array]"},N.isObject=function(e){return e===Object(e)},C(["Arguments","Function","String","Number","Date","RegExp"],function(e){N["is"+e]=function(t){return c.call(t)=="[object "+e+"]"}}),N.isArguments(arguments)||(N.isArguments=function(e){return!!e&&!!N.has(e,"callee")}),typeof /./!="function"&&(N.isFunction=function(e){return typeof e=="function"}),N.isFinite=function(e){return isFinite(e)&&!isNaN(parseFloat(e))},N.isNaN=function(e){return N.isNumber(e)&&e!=+e},N.isBoolean=function(e){return e===!0||e===!1||c.call(e)=="[object Boolean]"},N.isNull=function(e){return e===null},N.isUndefined=function(e){return e===void 0},N.has=function(e,t){return h.call(e,t)},N.noConflict=function(){return e._=r,this},N.identity=function(e){return e},N.times=function(e,t,n){var r=Array(e);for(var i=0;i":">",'"':""","'":"'","/":"/"}};D.unescape=N.invert(D.escape);var P={escape:new RegExp("["+N.keys(D.escape).join("")+"]","g"),unescape:new RegExp("("+N.keys(D.unescape).join("|")+")","g")};N.each(["escape","unescape"],function(e){N[e]=function(t){return t==null?"":(""+t).replace(P[e],function(t){return D[e][t]})}}),N.result=function(e,t){if(e==null)return null;var n=e[t];return N.isFunction(n)?n.call(e):n},N.mixin=function(e){C(N.functions(e),function(t){var n=N[t]=e[t];N.prototype[t]=function(){var e=[this._wrapped];return a.apply(e,arguments),I.call(this,n.apply(N,e))}})};var H=0;N.uniqueId=function(e){var t=++H+"";return e?e+t:t},N.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var B=/(.)^/,j={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},F=/\\|'|\r|\n|\t|\u2028|\u2029/g;N.template=function(e,t,n){var r;n=N.defaults({},n,N.templateSettings);var i=new RegExp([(n.escape||B).source,(n.interpolate||B).source,(n.evaluate||B).source].join("|")+"|$","g"),s=0,o="__p+='";e.replace(i,function(t,n,r,i,u){return o+=e.slice(s,u).replace(F,function(e){return"\\"+j[e]}),n&&(o+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'"),r&&(o+="'+\n((__t=("+r+"))==null?'':__t)+\n'"),i&&(o+="';\n"+i+"\n__p+='"),s=u+t.length,t}),o+="';\n",n.variable||(o="with(obj||{}){\n"+o+"}\n"),o="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+o+"return __p;\n";try{r=new Function(n.variable||"obj","_",o)}catch(u){throw u.source=o,u}if(t)return r(t,N);var a=function(e){return r.call(this,e,N)};return a.source="function("+(n.variable||"obj")+"){\n"+o+"}",a},N.chain=function(e){return N(e).chain()};var I=function(e){return this._chain?N(e).chain():e};N.mixin(N),C(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=s[e];N.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e=="shift"||e=="splice")&&n.length===0&&delete n[0],I.call(this,n)}}),C(["concat","join","slice"],function(e){var t=s[e];N.prototype[e]=function(){return I.call(this,t.apply(this._wrapped,arguments))}}),N.extend(N.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this)}),e.define("/node_modules/backbone/package.json",function(e,t,n,r,i,s,o){t.exports={main:"backbone.js"}}),e.define("/node_modules/backbone/backbone.js",function(e,t,n,r,i,s,o){(function(){var t=this,r=t.Backbone,i=[],s=i.push,o=i.slice,u=i.splice,a;typeof n!="undefined"?a=n:a=t.Backbone={},a.VERSION="0.9.10";var f=t._;!f&&typeof e!="undefined"&&(f=e("underscore")),a.$=t.jQuery||t.Zepto||t.ender,a.noConflict=function(){return t.Backbone=r,this},a.emulateHTTP=!1,a.emulateJSON=!1;var l=/\s+/,c=function(e,t,n,r){if(!n)return!0;if(typeof n=="object")for(var i in n)e[t].apply(e,[i,n[i]].concat(r));else{if(!l.test(n))return!0;var s=n.split(l);for(var o=0,u=s.length;o').hide().appendTo("body")[0].contentWindow,this.navigate(t)),this._hasPushState?a.$(window).on("popstate",this.checkUrl):this._wantsHashChange&&"onhashchange"in window&&!r?a.$(window).on("hashchange",this.checkUrl):this._wantsHashChange&&(this._checkUrlInterval=setInterval(this.checkUrl,this.interval)),this.fragment=t;var i=this.location,s=i.pathname.replace(/[^\/]$/,"$&/")===this.root;if(this._wantsHashChange&&this._wantsPushState&&!this._hasPushState&&!s)return this.fragment=this.getFragment(null,!0),this.location.replace(this.root+this.location.search+"#"+this.fragment),!0;this._wantsPushState&&this._hasPushState&&s&&i.hash&&(this.fragment=this.getHash().replace(T,""),this.history.replaceState({},document.title,this.root+this.fragment+i.search));if(!this.options.silent)return this.loadUrl()},stop:function(){a.$(window).off("popstate",this.checkUrl).off("hashchange",this.checkUrl),clearInterval(this._checkUrlInterval),x.started=!1},route:function(e,t){this.handlers.unshift({route:e,callback:t})},checkUrl:function(e){var t=this.getFragment();t===this.fragment&&this.iframe&&(t=this.getFragment(this.getHash(this.iframe)));if(t===this.fragment)return!1;this.iframe&&this.navigate(t),this.loadUrl()||this.loadUrl(this.getHash())},loadUrl:function(e){var t=this.fragment=this.getFragment(e),n=f.any(this.handlers,function(e){if(e.route.test(t))return e.callback(t),!0});return n},navigate:function(e,t){if(!x.started)return!1;if(!t||t===!0)t={trigger:t};e=this.getFragment(e||"");if(this.fragment===e)return;this.fragment=e;var n=this.root+e;if(this._hasPushState)this.history[t.replace?"replaceState":"pushState"]({},document.title,n);else{if(!this._wantsHashChange)return this.location.assign(n);this._updateHash(this.location,e,t.replace),this.iframe&&e!==this.getFragment(this.getHash(this.iframe))&&(t.replace||this.iframe.document.open().close(),this._updateHash(this.iframe.location,e,t.replace))}t.trigger&&this.loadUrl(e)},_updateHash:function(e,t,n){if(n){var r=e.href.replace(/(javascript:|#).*$/,"");e.replace(r+"#"+t)}else e.hash="#"+t}}),a.history=new x;var L=a.View=function(e){this.cid=f.uniqueId("view"),this._configure(e||{}),this._ensureElement(),this.initialize.apply(this,arguments),this.delegateEvents()},A=/^(\S+)\s*(.*)$/,O=["model","collection","el","id","attributes","className","tagName","events"];f.extend(L.prototype,p,{tagName:"div",$:function(e){return this.$el.find(e)},initialize:function(){},render:function(){return this},remove:function(){return this.$el.remove(),this.stopListening(),this},setElement:function(e,t){return this.$el&&this.undelegateEvents(),this.$el=e instanceof a.$?e:a.$(e),this.el=this.$el[0],t!==!1&&this.delegateEvents(),this},delegateEvents:function(e){if(!e&&!(e=f.result(this,"events")))return;this.undelegateEvents();for(var t in e){var n=e[t];f.isFunction(n)||(n=this[e[t]]);if(!n)throw new Error('Method "'+e[t]+'" does not exist');var r=t.match(A),i=r[1],s=r[2];n=f.bind(n,this),i+=".delegateEvents"+this.cid,s===""?this.$el.on(i,n):this.$el.on(i,s,n)}},undelegateEvents:function(){this.$el.off(".delegateEvents"+this.cid)},_configure:function(e){this.options&&(e=f.extend({},f.result(this,"options"),e)),f.extend(this,f.pick(e,O)),this.options=e},_ensureElement:function(){if(!this.el){var e=f.extend({},f.result(this,"attributes"));this.id&&(e.id=f.result(this,"id")),this.className&&(e["class"]=f.result(this,"className"));var t=a.$("<"+f.result(this,"tagName")+">").attr(e);this.setElement(t,!1)}else this.setElement(f.result(this,"el"),!1)}});var M={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};a.sync=function(e,t,n){var r=M[e];f.defaults(n||(n={}),{emulateHTTP:a.emulateHTTP,emulateJSON:a.emulateJSON});var i={type:r,dataType:"json"};n.url||(i.url=f.result(t,"url")||D()),n.data==null&&t&&(e==="create"||e==="update"||e==="patch")&&(i.contentType="application/json",i.data=JSON.stringify(n.attrs||t.toJSON(n))),n.emulateJSON&&(i.contentType="application/x-www-form-urlencoded",i.data=i.data?{model:i.data}:{});if(n.emulateHTTP&&(r==="PUT"||r==="DELETE"||r==="PATCH")){i.type="POST",n.emulateJSON&&(i.data._method=r);var s=n.beforeSend;n.beforeSend=function(e){e.setRequestHeader("X-HTTP-Method-Override",r);if(s)return s.apply(this,arguments)}}i.type!=="GET"&&!n.emulateJSON&&(i.processData=!1);var o=n.success;n.success=function(e){o&&o(t,e,n),t.trigger("sync",t,e,n)};var u=n.error;n.error=function(e){u&&u(t,e,n),t.trigger("error",t,e,n)};var l=n.xhr=a.ajax(f.extend(i,n));return t.trigger("request",t,l,n),l},a.ajax=function(){return a.$.ajax.apply(a.$,arguments)};var _=function(e,t){var n=this,r;e&&f.has(e,"constructor")?r=e.constructor:r=function(){return n.apply(this,arguments)},f.extend(r,n,t);var i=function(){this.constructor=r};return i.prototype=n.prototype,r.prototype=new i,e&&f.extend(r.prototype,e),r.__super__=n.prototype,r};d.extend=v.extend=y.extend=L.extend=x.extend=_;var D=function(){throw new Error('A "url" property or function must be specified')}}).call(this)}),e.define("/src/js/util/constants.js",function(e,t,n,r,i,s,o){var u={betweenCommandsDelay:400},a={isAnimating:!1},f={minZoom:.55,maxZoom:1.25,minWidth:600,minHeight:600},l={arrowHeadSize:8,nodeRadius:17,curveControlPointOffset:50,defaultEasing:"easeInOut",defaultAnimationTime:400,rectFill:"hsb(0.8816909813322127,0.7,1)",headRectFill:"#2831FF",rectStroke:"#FFF",rectStrokeWidth:"3",originDash:"- ",multiBranchY:20,upstreamHeadOpacity:.5,upstreamNoneOpacity:.2,edgeUpstreamHeadOpacity:.4,edgeUpstreamNoneOpacity:.15,visBranchStrokeWidth:2,visBranchStrokeColorNone:"#333",defaultNodeFill:"hsba(0.5,0.8,0.7,1)",defaultNodeStrokeWidth:2,defaultNodeStroke:"#FFF",orphanNodeFill:"hsb(0.5,0.8,0.7)"};n.GLOBAL=a,n.TIME=u,n.GRAPHICS=l,n.VIEWPORT=f}),e.define("/src/js/util/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util/constants");n.parseQueryString=function(e){var t={};return e.replace(new RegExp("([^?=&]+)(=([^&]*))?","g"),function(e,n,r,i){t[n]=i}),t},n.isBrowser=function(){var e=String(typeof window)!=="undefined";return e},n.splitTextCommand=function(e,t,n){t=u.bind(t,n),u.each(e.split(";"),function(e,n){e=u.escape(e),e=e.replace(/^(\s+)/,"").replace(/(\s+)$/,"").replace(/"/g,'"').replace(/'/g,"'");if(n>0&&!e.length)return;t(e)})},n.genParseCommand=function(e,t){return function(n){var r,i;return u.each(e,function(e,t){var s=e.exec(n);s&&(r=t,i=s)}),r?{toSet:{eventName:t,method:r,regexResults:i}}:!1}}}),e.define("/src/js/level/sandbox.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../intl"),h=e("../app"),p=e("../util/errors"),d=e("../visuals/visualization").Visualization,v=e("../level/parseWaterfall").ParseWaterfall,m=e("../level/disabledMap").DisabledMap,g=e("../models/commandModel").Command,y=e("../git/gitShim").GitShim,b=e("../views"),w=b.ModalTerminal,E=b.ModalAlert,S=e("../views/builderViews"),x=e("../views/multiView").MultiView,T=f.View.extend({tagName:"div",initialize:function(e){e=e||{},this.options=e,this.initVisualization(e),this.initCommandCollection(e),this.initParseWaterfall(e),this.initGitShim(e),this.initUndoStack(e),e.wait||this.takeControl()},getDefaultVisEl:function(){return $("#mainVisSpace")[0]},getAnimationTime:function(){return 1050},initVisualization:function(e){this.mainVis=new d({el:e.el||this.getDefaultVisEl()})},initUndoStack:function(e){this.undoStack=[]},initCommandCollection:function(e){this.commandCollection=h.getCommandUI().commandCollection},initParseWaterfall:function(e){this.parseWaterfall=new v},initGitShim:function(e){this.gitShim=new y({beforeCB:u.bind(this.beforeCommandCB,this)})},takeControl:function(){h.getEventBaton().stealBaton("commandSubmitted",this.commandSubmitted,this),h.getEventBaton().stealBaton("processSandboxCommand",this.processSandboxCommand,this),h.getEventBaton().stealBaton("levelExited",this.levelExited,this),this.insertGitShim()},releaseControl:function(){h.getEventBaton().releaseBaton("commandSubmitted",this.commandSubmitted,this),h.getEventBaton().releaseBaton("processSandboxCommand",this.processSandboxCommand,this),h.getEventBaton().releaseBaton("levelExited",this.levelExited,this),this.releaseGitShim()},releaseGitShim:function(){this.gitShim&&this.gitShim.removeShim()},insertGitShim:function(){this.gitShim&&this.mainVis.customEvents.on("gitEngineReady",function(){this.gitShim.insertShim()},this)},beforeCommandCB:function(e){this.pushUndo()},pushUndo:function(){this.undoStack.push(this.mainVis.gitEngine.printTree())},undo:function(e,t){var n=this.undoStack.pop();if(!n){e.set("error",new p.GitError({msg:c.str("undo-stack-empty")})),t.resolve();return}this.mainVis.reset(n),setTimeout(function(){e.finishWith(t)},this.mainVis.getAnimationTime())},commandSubmitted:function(e){h.getEvents().trigger("commandSubmittedPassive",e),l.splitTextCommand(e,function(e){this.commandCollection.add(new g({rawStr:e,parseWaterfall:this.parseWaterfall}))},this)},startLevel:function(t,n){var r=t.get("regexResults")||[],i=r[1]||"",s=h.getLevelArbiter().getLevel(i);if(!s){t.addWarning(c.str("level-no-id",{id:i})),h.getEventBaton().trigger("commandSubmitted","levels"),t.set("status","error"),n.resolve();return}this.hide(),this.clear();var o=a.defer(),u=e("../level").Level;this.currentLevel=new u({level:s,deferred:o,command:t}),o.promise.then(function(){t.finishWith(n)})},buildLevel:function(t,n){this.hide(),this.clear();var r=a.defer(),i=e("../level/builder").LevelBuilder;this.levelBuilder=new i({deferred:r}),r.promise.then(function(){t.finishWith(n)})},exitLevel:function(e,t){e.addWarning(c.str("level-cant-exit")),e.set("status","error"),t.resolve()},showLevels:function(e,t){var n=a.defer();h.getLevelDropdown().show(n,e),n.promise.done(function(){e.finishWith(t)})},resetSolved:function(e,t){h.getLevelArbiter().resetSolvedMap(),e.addWarning(c.str("solved-map-reset")),e.finishWith(t)},processSandboxCommand:function(e,t){var n={"reset solved":this.resetSolved,undo:this.undo,"help general":this.helpDialog,help:this.helpDialog,reset:this.reset,delay:this.delay,clear:this.clear,"exit level":this.exitLevel,level:this.startLevel,sandbox:this.exitLevel,levels:this.showLevels,mobileAlert:this.mobileAlert,"build level":this.buildLevel,"export tree":this.exportTree,"import tree":this.importTree,"import level":this.importLevel},r=n[e.get("method")];if(!r)throw new Error("no method for that wut");r.apply(this,[e,t])},hide:function(){this.mainVis.hide()},levelExited:function(){this.show()},show:function(){this.mainVis.show()},importTree:function(e,t){var n=new S.MarkdownPresenter({previewText:c.str("paste-json"),fillerText:" "});n.deferred.promise.then(u.bind(function(e){try{this.mainVis.gitEngine.loadTree(JSON.parse(e))}catch(t){this.mainVis.reset(),new x({childViews:[{type:"ModalAlert",options:{markdowns:["## Error!","","Something is wrong with that JSON! Here is the error:","",String(t)]}}]})}},this)).fail(function(){}).done(function(){e.finishWith(t)})},importLevel:function(t,n){var r=new S.MarkdownPresenter({previewText:c.str("paste-json"),fillerText:" "});r.deferred.promise.then(u.bind(function(r){var i=e("../level").Level;try{var s=JSON.parse(r),o=a.defer();this.currentLevel=new i({level:s,deferred:o,command:t}),this.hide(),o.promise.then(function(){t.finishWith(n)})}catch(u){new x({childViews:[{type:"ModalAlert",options:{markdowns:["## Error!","","Something is wrong with that level JSON, this happened:","",String(u)]}}]}),t.finishWith(n)}},this)).fail(function(){t.finishWith(n)}).done()},exportTree:function(e,t){var n=JSON.stringify(this.mainVis.gitEngine.exportTree(),null,2),r=new x({childViews:[{type:"MarkdownPresenter",options:{previewText:c.str("share-tree"),fillerText:n,noConfirmCancel:!0}}]});r.getPromise().then(function(){e.finishWith(t)}).done()},clear:function(e,t){h.getEvents().trigger("clearOldCommands"),e&&t&&e.finishWith(t)},mobileAlert:function(e,t){alert(c.str("mobile-alert")),e.finishWith(t)},delay:function(e,t){var n=parseInt(e.get("regexResults")[1],10);setTimeout(function(){e.finishWith(t)},n)},reset:function(e,t){this.mainVis.reset(),this.initUndoStack(),setTimeout(function(){e.finishWith(t)},this.mainVis.getAnimationTime())},helpDialog:function(t,n){var r=new x({childViews:c.getDialog(e("../dialogs/sandbox"))});r.getPromise().then(u.bind(function(){t.finishWith(n)},this)).done()}});n.Sandbox=T}),e.define("/node_modules/q/package.json",function(e,t,n,r,i,s,o){t.exports={main:"q.js"}}),e.define("/node_modules/q/q.js",function(e,t,n,r,i,s,o){(function(e){if(typeof bootstrap=="function")bootstrap("promise",e);else if(typeof n=="object")e(void 0,n);else if(typeof define=="function")define(e);else if(typeof ses!="undefined"){if(!ses.ok())return;ses.makeQ=function(){var t={};return e(void 0,t)}}else e(void 0,Q={})})(function(e,t){"use strict";function w(e){return b(e)==="[object StopIteration]"||e instanceof E}function x(e,t){t.stack&&typeof e=="object"&&e!==null&&e.stack&&e.stack.indexOf(S)===-1&&(e.stack=T(e.stack)+"\n"+S+"\n"+T(t.stack))}function T(e){var t=e.split("\n"),n=[];for(var r=0;r=n&&s<=Ct}function k(){if(Error.captureStackTrace){var e,t,n=Error.prepareStackTrace;return Error.prepareStackTrace=function(n,r){e=r[1].getFileName(),t=r[1].getLineNumber()},(new Error).stack,Error.prepareStackTrace=n,r=e,t}}function L(e,t,n){return function(){return typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t+" is deprecated, use "+n+" instead.",(new Error("")).stack),e.apply(e,arguments)}}function A(){function s(r){if(!e)return;n=z(r),d(e,function(e,t){u(function(){n.promiseSend.apply(n,t)})},void 0),e=void 0,t=void 0}var e=[],t=[],n,r=g(A.prototype),i=g(M.prototype);return i.promiseSend=function(r,i,s,o){var a=p(arguments);e?(e.push(a),r==="when"&&o&&t.push(o)):u(function(){n.promiseSend.apply(n,a)})},i.valueOf=function(){return e?i:n.valueOf()},Error.captureStackTrace&&(Error.captureStackTrace(i,A),i.stack=i.stack.substring(i.stack.indexOf("\n")+1)),o(i),r.promise=i,r.resolve=s,r.reject=function(e){s(U(e))},r.notify=function(n){e&&d(t,function(e,t){u(function(){t(n)})},void 0)},r}function O(e){var t=A();return ot(e,t.resolve,t.reject,t.notify).fail(t.reject),t.promise}function M(e,t,n,r){t===void 0&&(t=function(e){return U(new Error("Promise does not support operation: "+e))});var i=g(M.prototype);return i.promiseSend=function(n,r){var s=p(arguments,2),o;try{e[n]?o=e[n].apply(i,s):o=t.apply(i,[n].concat(s))}catch(u){o=U(u)}r&&r(o)},n&&(i.valueOf=n),r&&(i.exception=r),o(i),i}function _(e){return D(e)?e.valueOf():e}function D(e){return e&&typeof e.promiseSend=="function"}function P(e){return e&&typeof e.then=="function"}function H(e){return B(e)||j(e)}function B(e){return!P(_(e))}function j(e){return e=_(e),D(e)&&"exception"in e}function R(){!q&&typeof window!="undefined"&&!window.Touch&&window.console&&console.log("Should be empty:",I),q=!0}function U(e){var t=M({when:function(t){if(t){var n=v(F,this);n!==-1&&(I.splice(n,1),F.splice(n,1))}return t?t(e):U(e)}},function(){return U(e)},function n(){return this},e);return R(),F.push(t),I.push(e),t}function z(e){if(D(e))return e;e=_(e);if(P(e)){var t=A();return e.then(t.resolve,t.reject,t.notify),t.promise}return M({when:function(){return e},get:function(t){return e[t]},put:function(t,n){return e[t]=n,e},del:function(t){return delete e[t],e},post:function(t,n){return e[t].apply(e,n)},apply:function(t,n){return e.apply(t,n)},fapply:function(t){return e.apply(void 0,t)},viewInfo:function(){function r(e){n[e]||(n[e]=typeof t[e])}var t=e,n={};while(t)Object.getOwnPropertyNames(t).forEach(r),t=Object.getPrototypeOf(t);return{type:typeof e,properties:n}},keys:function(){return y(e)}},void 0,function n(){return e})}function W(e){return M({isDef:function(){}},function(){var n=p(arguments);return Z.apply(void 0,[e].concat(n))},function(){return _(e)})}function X(e,t){return e=z(e),t?M({viewInfo:function(){return t}},function(){var n=p(arguments);return Z.apply(void 0,[e].concat(n))},function(){return _(e)}):Z(e,"viewInfo")}function V(e){return X(e).when(function(t){var n;t.type==="function"?n=function(){return rt(e,void 0,arguments)}:n={};var r=t.properties||{};return y(r).forEach(function(t){r[t]==="function"&&(n[t]=function(){return nt(e,t,arguments)})}),z(n)})}function $(e,t,n,r){function o(e){try{return typeof t=="function"?t(e):e}catch(n){return U(n)}}function a(e){if(typeof n=="function"){x(e,l);try{return n(e)}catch(t){return U(t)}}return U(e)}function f(e){return typeof r=="function"?r(e):e}var i=A(),s=!1,l=z(e);return u(function(){l.promiseSend("when",function(e){if(s)return;s=!0,i.resolve(o(e))},function(e){if(s)return;s=!0,i.resolve(a(e))})}),l.promiseSend("when",void 0,void 0,function(e){i.notify(f(e))}),i.promise}function J(e,t,n){return $(e,function(e){return ft(e).then(function(e){return t.apply(void 0,e)},n)},n)}function K(e){return function(){function t(e,t){var s;try{s=n[e](t)}catch(o){return w(o)?o.value:U(o)}return $(s,r,i)}var n=e.apply(this,arguments),r=t.bind(t,"send"),i=t.bind(t,"throw");return r()}}function Q(e){throw new E(e)}function G(e){return function(){return ft([this,ft(arguments)]).spread(function(t,n){return e.apply(t,n)})}}function Y(e){return function(t){var n=p(arguments,1);return Z.apply(void 0,[t,e].concat(n))}}function Z(e,t){var n=A(),r=p(arguments,2);return e=z(e),u(function(){e.promiseSend.apply(e,[t,n.resolve].concat(r))}),n.promise}function et(e,t,n){var r=A();return e=z(e),u(function(){e.promiseSend.apply(e,[t,r.resolve].concat(n))}),r.promise}function tt(e){return function(t){var n=p(arguments,1);return et(t,e,n)}}function st(e,t){var n=p(arguments,2);return rt(e,t,n)}function ot(e){var t=p(arguments,1);return it(e,t)}function ut(e,t){var n=p(arguments,2);return function(){var i=n.concat(p(arguments));return rt(e,t,i)}}function at(e){var t=p(arguments,1);return function(){var r=t.concat(p(arguments));return it(e,r)}}function ft(e){return $(e,function(e){var t=e.length;if(t===0)return z(e);var n=A();return d(e,function(r,i,s){B(i)?(e[s]=_(i),--t===0&&n.resolve(e)):$(i,function(r){e[s]=r,--t===0&&n.resolve(e)}).fail(n.reject)},void 0),n.promise})}function lt(e){return $(e,function(e){return $(ft(m(e,function(e){return $(e,i,i)})),function(){return m(e,z)})})}function ct(e,t){return $(e,void 0,t)}function ht(e,t){return $(e,void 0,void 0,t)}function pt(e,t){return $(e,function(e){return $(t(),function(){return e})},function(e){return $(t(),function(){return U(e)})})}function dt(e,n,r,i){function s(n){u(function(){x(n,e);if(!t.onerror)throw n;t.onerror(n)})}var o=n||r||i?$(e,n,r,i):e;ct(o,s)}function vt(e,t){var n=A(),r=setTimeout(function(){n.reject(new Error("Timed out after "+t+" ms"))},t);return $(e,function(e){clearTimeout(r),n.resolve(e)},function(e){clearTimeout(r),n.reject(e)}),n.promise}function mt(e,t){t===void 0&&(t=e,e=void 0);var n=A();return setTimeout(function(){n.resolve(e)},t),n.promise}function gt(e,t){var n=p(t),r=A();return n.push(r.makeNodeResolver()),it(e,n).fail(r.reject),r.promise}function yt(e){var t=p(arguments,1),n=A();return t.push(n.makeNodeResolver()),it(e,t).fail(n.reject),n.promise}function bt(e){var t=p(arguments,1);return function(){var n=t.concat(p(arguments)),r=A();return n.push(r.makeNodeResolver()),it(e,n).fail(r.reject),r.promise}}function wt(e,t,n){return St(e,t).apply(void 0,n)}function Et(e,t){var n=p(arguments,2);return wt(e,t,n)}function St(e){if(arguments.length>1){var t=arguments[1],n=p(arguments,2),r=e;e=function(){var e=n.concat(p(arguments));return r.apply(t,e)}}return function(){var t=A(),n=p(arguments);return n.push(t.makeNodeResolver()),it(e,n).fail(t.reject),t.promise}}function xt(e,t,n){var r=p(n),i=A();return r.push(i.makeNodeResolver()),nt(e,t,r).fail(i.reject),i.promise}function Tt(e,t){var n=p(arguments,2),r=A();return n.push(r.makeNodeResolver()),nt(e,t,n).fail(r.reject),r.promise}function Nt(e,t){if(!t)return e;e.then(function(e){u(function(){t(null,e)})},function(e){u(function(){t(e)})})}var n=k(),r,i=function(){},o=Object.freeze||i;typeof cajaVM!="undefined"&&(o=cajaVM.def);var u;if(typeof s!="undefined")u=s.nextTick;else if(typeof setImmediate=="function")u=setImmediate;else if(typeof MessageChannel!="undefined"){var a=new MessageChannel,f={},l=f;a.port1.onmessage=function(){f=f.next;var e=f.task;delete f.task,e()},u=function(e){l=l.next={task:e},a.port2.postMessage(0)}}else u=function(e){setTimeout(e,0)};var c;if(Function.prototype.bind){var h=Function.prototype.bind;c=h.bind(h.call)}else c=function(e){return function(){return e.call.apply(e,arguments)}};var p=c(Array.prototype.slice),d=c(Array.prototype.reduce||function(e,t){var n=0,r=this.length;if(arguments.length===1)do{if(n in this){t=this[n++];break}if(++n>=r)throw new TypeError}while(1);for(;n2?e.resolve(p(arguments,1)):e.resolve(n)}},A.prototype.node=L(A.prototype.makeNodeResolver,"node","makeNodeResolver"),t.promise=O,t.makePromise=M,M.prototype.then=function(e,t,n){return $(this,e,t,n)},M.prototype.thenResolve=function(e){return $(this,function(){return e})},d(["isResolved","isFulfilled","isRejected","when","spread","send","get","put","del","post","invoke","keys","apply","call","bind","fapply","fcall","fbind","all","allResolved","view","viewInfo","timeout","delay","catch","finally","fail","fin","progress","end","done","nfcall","nfapply","nfbind","ncall","napply","nbind","npost","ninvoke","nend","nodeify"],function(e,n){M.prototype[n]=function(){return t[n].apply(t,[this].concat(p(arguments)))}},void 0),M.prototype.toSource=function(){return this.toString()},M.prototype.toString=function(){return"[object Promise]"},o(M.prototype),t.nearer=_,t.isPromise=D,t.isPromiseAlike=P,t.isResolved=H,t.isFulfilled=B,t.isRejected=j;var F=[],I=[],q;t.reject=U,t.begin=z,t.resolve=z,t.ref=L(z,"ref","resolve"),t.master=W,t.viewInfo=X,t.view=V,t.when=$,t.spread=J,t.async=K,t["return"]=Q,t.promised=G,t.sender=L(Y,"sender","dispatcher"),t.Method=L(Y,"Method","dispatcher"),t.send=L(Z,"send","dispatch"),t.dispatch=et,t.dispatcher=tt,t.get=tt("get"),t.put=tt("put"),t["delete"]=t.del=tt("del");var nt=t.post=tt("post");t.invoke=function(e,t){var n=p(arguments,2);return nt(e,t,n)};var rt=t.apply=L(tt("apply"),"apply","fapply"),it=t.fapply=tt("fapply");t.call=L(st,"call","fcall"),t["try"]=ot,t.fcall=ot,t.bind=L(ut,"bind","fbind"),t.fbind=at,t.keys=tt("keys"),t.all=ft,t.allResolved=lt,t["catch"]=t.fail=ct,t.progress=ht,t["finally"]=t.fin=pt,t.end=L(dt,"end","done"),t.done=dt,t.timeout=vt,t.delay=mt,t.nfapply=gt,t.nfcall=yt,t.nfbind=bt,t.napply=L(wt,"napply","npost"),t.ncall=L(Et,"ncall","ninvoke"),t.nbind=L(St,"nbind","nfbind"),t.npost=xt,t.ninvoke=Tt,t.nend=L(Nt,"nend","nodeify"),t.nodeify=Nt;var Ct=k()})}),e.define("/src/js/intl/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util/constants"),f=e("../util"),l=e("../intl/strings").strings,c=n.getDefaultLocale=function(){return"en_US"},h=n.getLocale=function(){return a.GLOBAL.locale?a.GLOBAL.locale:c()},p=u.clone(u.templateSettings);p.interpolate=/\{(.+?)\}/g;var d=n.template=function(e,t){return u.template(e,t,p)},v=n.str=function(e,t){t=t||{};var n=h();return l[e]?l[e][n]?d(l[e][n],t):e!=="error-untranslated"?v("error-untranslated"):'No translation for the key "'+e+'"':(console.warn("NO INTL support for key "+e),"NO INTL support for key "+e)},m=n.getIntlKey=function(e,t){if(!e||!e[t])throw new Error("that key "+t+"doesnt exist in this blob"+e);return e[t][c()]||console.warn("WARNING!! This blob does not have intl support:",e,"for this key",t),e[t][h()]},g=n.getDialog=function(e){var t=c();return m(e,"dialog")||e.dialog[t]},y=n.getHint=function(e){return m(e,"hint")||v("error-untranslated")},b=n.getName=function(e){return m(e,"name")||v("error-untranslated")},w=n.getStartDialog=function(e){var t=m(e,"startDialog");if(t)return t;var n={type:"ModalAlert",options:{markdown:v("error-untranslated")}},r=u.clone(e.startDialog[c()]||e.startDialog);return r.childViews.unshift(n),r}}),e.define("/src/js/intl/strings.js",function(e,t,n,r,i,s,o){n.strings={"finish-dialog-finished":{__desc__:"One of the lines in the next level dialog",ja:"最後のレベルをクリアしました!すごい!!",en_US:"Wow! You finished the last level, great!",zh_CN:"我的个天!你完成了最后一关,碉堡了!",fr_FR:"Félicitations, vous avez réussi le dernier niveau !"},"finish-dialog-next":{__desc__:"One of the lines in the next level dialog",en_US:'Would you like to move on to *"{nextLevel}"*, the next level?',ja:'次の章 *"{nextLevel}"* へ進みますか?',zh_CN:"要不前进到下一关 *“{nextLevel}”*?",fr_FR:'Voulez-vous passer à *"{nextLevel}"*, le prochain niveau ?'},"finish-dialog-win":{__desc__:"One of the lines in the next level dialog",en_US:"Awesome! You matched or exceeded our solution.",ja:"素晴らしい!このレベルをクリアしましたね。",zh_CN:"牛鼻啊!你达到或者完爆了我们的答案。",fr_FR:"Fabuleux ! Votre solution a égalé ou surpassé notre solution."},"finish-dialog-lose":{__desc__:"When the user entered more commands than our best, encourage them to do better",en_US:"See if you can whittle it down to {best} :D",ja:"模範解答の回数={best}回でクリアする方法も考えてみましょう :D",zh_CN:"试试看你能否在 {best} 之内搞定 :D",fr_FR:"Voyons si vous pouvez descendre à {best} :D"},"git-status-detached":{__desc__:"One of the lines for git status output",en_US:"Detached head!",zh_CN:"脑袋搬家(Detached head)了!",fr_FR:"head détaché !"},"git-status-onbranch":{__desc__:"One of the lines for git status output",en_US:"On branch {branch}",zh_CN:"切换到分支 {branch}",fr_FR:"Sur la branche {branch}"},"git-status-readytocommit":{__desc__:"One of the lines for git status output",en_US:"Ready to commit! (as always in this demo)",zh_CN:"可以提交啦!(这演示里一直可以提交)",fr_FR:"Prêt à commit ! (comme toujours dans cette démo)"},"git-dummy-msg":{__desc__:"The dummy commit message for all commits. Feel free to put in a shoutout to your school / city / whatever!",en_US:"Quick commit. Go Bears!",zh_CN:"快速提交。上啊月熊!",fr_FR:"Commit rapide. NoMaN Sux!"},"git-error-origin-fetch-uptodate":{__desc__:"One of the error messages for git",en_US:"Already up to date!",fr_FR:"Déjà à jour"},"git-error-origin-fetch-no-ff":{__desc__:"One of the error messages for git",en_US:"Your origin branch is out of sync with the remote branch and fetch cannot be performed. try using --force",fr_FR:"Votre branche origin n'est plus synchronisée avec la branche distante et fetch ne peut pas être appliqué. Essayez avec l'option --force"},"git-error-origin-push-no-ff":{__desc__:"One of the error messages for git",en_US:"The remote repository has diverged from your local repository, so uploading your changes is not a simple fast forward (and thus your push was rejected). Please pull down the new changes in the remote repository, incorporate them into this branch, and try again. You can do so with git pull or git pull --rebase",fr_FR:"Le dépôt distant a divergé de votre référentiel local, donc l'envoi de vos modifications n'est pas en simple avance rapide (et donc votre envoi a été rejeté). Veuillez récupérer les nouveaux changements depuis le dépôt distant, les intégrer dans cette branche, et essayez à nouveau. Vous pouvez le faire avec git pull ou git pull --rebase"},"git-error-remote-branch":{__desc__:"One of the error messages for git",en_US:"You cannot execute that command on a remote branch",fr_FR:"Vous ne pouvez exécuter cette commande sur une branche distante"},"git-error-origin-required":{__desc__:"One of the error messages for git",en_US:"An origin is required for that command",fr_FR:"Une origine est requise pour cette commande"},"git-error-origin-exists":{__desc__:"One of the error messages for git",en_US:"An origin already exists! You cannot make a new one",fr_FR:"Une origine existe déjà ! Vous ne pouvez pas en créer une nouvelle"},"git-error-branch":{__desc__:"One of the error messages for git",en_US:"You can't delete the master branch, the branch you are on, or things that aren't branches",zh_CN:"你不能删除主分支(master),或者你当前所在的分支,或者其他不是分支也不知道能不能吃的东西。",fr_FR:"Vous ne pouvez supprimer la branche master, la branche sur laquelle vous êtes, ou ce qui n'est pas une branche"},"git-merge-msg":{__desc__:"The commit message for a merge commit",en_US:"Merge {target} into {current}",zh_CN:"合并 {target} 到 {current}",fr_FR:"Merge de {target} dans {current}"},"git-error-rebase-none":{__desc__:"One of the error messages for git",en_US:"No commits to rebase! Everything is a merge commit or changes already applied",zh_CN:"没有需要 rebase 的提交!都是个合并提交,或者已经 rebase 过了。",fr_FR:"Aucune commit à rebaser ! Tout est soit un commit de merge, soit des modifications déjà appliquées"},"git-result-nothing":{__desc__:"The message that explains the result of a git command",en_US:"Nothing to do...",zh_CN:"没啥鸟事……",fr_FR:"Rien à effectuer…"},"git-result-fastforward":{__desc__:"The message that explains the result of a git command",en_US:"Fast forwarding...",zh_CN:"快速前进……",fr_FR:"En avance rapide…"},"git-result-uptodate":{__desc__:"The message that explains the result of a git command",en_US:"Branch already up-to-date",zh_CN:"分支已经是最新啦",fr_FR:"Branche déjà à jour"},"git-error-exist":{__desc__:"One of the error messages for git",en_US:"The ref {ref} does not exist or is unknown",zh_CN:"索引 {ref} 不存在,或者找不到。",fr_FR:"La référence {ref} n'existe pas ou est inconnue"},"git-error-relative-ref":{__desc__:"One of the error messages for git",en_US:"Commit {commit} doesnot have a {match}",zh_CN:"提交 {commit} 并没有 {match}",fr_FR:"Le commit {commit} n'a pas de correspondance {match}"},"git-warning-detached":{__desc__:"One of the warning messages for git",en_US:"Warning!! Detached HEAD state",zh_CN:"警告!脑袋搬家(Detached HEAD)状态",fr_FR:"Attention ! HEAD est détaché"},"git-warning-add":{__desc__:"One of the warning messages for git",en_US:"No need to add files in this demo",zh_CN:"此演示中不需要添加文件",fr_FR:"Aucun besoin d'ajouter des fichiers dans cette démo"},"git-error-options":{__desc__:"One of the error messages for git",en_US:"Those options you specified are incompatible or incorrect",zh_CN:"你所指定的参数不兼容或者不准确",fr_FR:"Les options que vous avez spécifiées sont incompatibles ou incorrectes"},"git-error-already-exists":{__desc__:"One of the error messages for git",en_US:"The commit {commit} already exists in your changes set, aborting!",zh_CN:"提交 {commit} 已经存在于你的改动集里,正在中止!",fr_FR:"Le commit {commit} existe déjà dans votre ensemble de modifications, opération avortée !"},"git-error-reset-detached":{__desc__:"One of the error messages for git",en_US:"Can't reset in detached head! Use checkout if you want to move",zh_CN:"不能在分离的 HEAD 里重置!用 checkout 吧",fr_FR:"On ne peut pas effectuer un reset quand head est détaché. Utilisez checkout pour déplacer"},"git-warning-hard":{__desc__:"One of the warning messages for git",en_US:"The default behavior is a --hard reset, feel free to omit that option!",zh_CN:"默认的行为是 --hard 硬重置,尽管省略掉那个选项吧!",fr_FR:"Le comportement par défaut est un --hard reset, soyez libre d'omettre cette option !"},"git-error-staging":{__desc__:"One of the error messages for git",en_US:"There is no concept of adding / staging files, so that option or command is invalid!",zh_CN:"没有添加、缓存文件的必要,所以改选项或者命令是不合法的。",fr_FR:"Il n'y a pas le concept d'ajouter / mettre en staging, donc cette option ou commande est invalide"},"git-revert-msg":{__desc__:"Message for reverting git command",en_US:"Reverting {oldCommit}: {oldMsg}",zh_CN:"撤销 {oldCommit}:{oldMsg}",fr_FR:"Revert {oldCommit}: {oldMsg}"},"git-error-args-many":{__desc__:"One of the error messages for git",en_US:"I expect at most {upper} argument(s) for {what}",zh_CN:"{what} 期望最多 {upper} 个参数",fr_FR:"J'attends au plus {upper} argument(s) pour {what}"},"git-error-args-few":{__desc__:"One of the error messages for git",en_US:"I expect at least {lower} argument(s) for {what}",zh_CN:"{what} 期望最少 {lower} 个参数",fr_FR:"J'attends au moins {upper} argument(s) pour {what}"},"git-error-no-general-args":{__desc__:"One of the error messages for git",en_US:"That command accepts no general arguments",zh_CN:"该命令不接收参数",fr_FR:"Cette commande n'accepte aucun argument général"},"copy-tree-string":{__desc__:"The prompt to copy the tree when sharing",en_US:"Copy the tree string below",zh_CN:"拷贝下面的树字符串",fr_FR:"Copiez la chaîne d'arbre ci-dessous"},"learn-git-branching":{__desc__:"The title of the app, with spaces",en_US:"Learn Git Branching",ja:"日本語版リポジトリ",ko:"Git 브랜치 배우기",zh_CN:"学习Git分支",fr_FR:"Apprenez Git Branching"},"select-a-level":{__desc__:"The prompt to select a level on the drop down view",en_US:"Select a level",zh_CN:"选择一关",fr_FR:"Choisissez un niveau"},"branch-name-short":{__desc__:"When branch names get too long, we need to truncate them. This is the warning for that",en_US:'Sorry, we need to keep branch names short for the visuals. Your branch name was truncated to 9 characters, resulting in "{branch}"',zh_CN:'抱歉,为了显示的需要,我们需要一个短些的分支名称。您使用的将被截断到9个字符,即"{branch}"',fr_FR:'Désolé, nous devons garder les noms de branches courts pour la visualisation. Votre nom de branche a été tronqué à 9 caractères, devenant "{branch}"'},"bad-branch-name":{__desc__:"When the user enters a branch name thats not ok",en_US:'That branch name "{branch}" is not allowed!',zh_CN:'不能给分支起这个名字 "{branch}"',fr_FR:'Ce nom de branche "{branch}" n\'est pas autorisé'},"option-not-supported":{__desc__:"When the user specifies an option that is not supported by our demo",en_US:'The option "{option}" is not supported!',zh_CN:'不支持选项 "{option}"',fr_FR:"L'option \"{option}\" n'est pas supportée"},"git-usage-command":{__desc__:"The line that shows how to format a git command",en_US:"git []",zh_CN:"git <命令> [<参数>]",fr_FR:"git []"},"git-supported-commands":{__desc__:"In the git help command, the header above the supported commands",en_US:"Supported commands:",zh_CN:"支持的命令有:",fr_FR:"Commandes supportées"},"git-usage":{__desc__:"In the dummy git output, the header before showing all the commands",en_US:"Usage:",zh_CN:"使用:",fr_FR:"Utilisation :"},"git-version":{__desc__:"The git version dummy output, kind of silly. PCOTTLE is my unix name but feel free to put yours instead",en_US:"Git Version PCOTTLE.1.0",zh_CN:"Git 版本 PCOTTLE.1.0",fr_FR:"Git version PCOTTLE.1.0"},"refresh-tree-command":{__desc__:"when the tree is visually refreshed",en_US:"Refreshing tree...",zh_CN:"正在刷新树结构...",fr_FR:"Actualisation de l'arbre…"},"locale-command":{__desc__:"when the locale is set to something",en_US:"Locale set to {locale}",zh_CN:"语言更改为 {locale}",fr_FR:"Langue changée à {locale}"},"locale-reset-command":{__desc__:"when the locale is reset",en_US:"Locale reset to default, which is {locale}",zh_CN:"语言重置为默认的 {locale}",fr_FR:"Langue remise par défaut, qui est {locale}"},"show-command":{__desc__:'command output title from "show"',en_US:"Please use one of the following commands for more info:",fr_FR:"Merci d'utiliser une des commandes suivantes pour obtenir plus d'info"},"show-all-commands":{__desc__:'command output title from "show commands"',en_US:"Here is a list of all the commmands available:",fr_FR:"Ci-dessous est la liste de toutes les commandes disponibles :"},"cd-command":{__desc__:"dummy command output for the command in the key",en_US:'Directory changed to "/directories/dont/matter/in/this/demo"',zh_CN:'目录切换到 "/directories/dont/matter/in/this/demo"',fr_FR:'Répertoire changé à "/directories/dont/matter/in/this/demo" (les répertoires ne servent à rien dans cette démo)'},"ls-command":{__desc__:"Dummy command output for the command in the key",en_US:"DontWorryAboutFilesInThisDemo.txt",zh_CN:"DontWorryAboutFilesInThisDemo.txt (译: 在试验里不用担心文件.txt)",fr_FR:"DontWorryAboutFilesInThisDemo.txt (ne vous préoccupez pas des noms de fichier dans cette démo)"},"mobile-alert":{__desc__:"When someone comes to the site on a mobile device, they can not input commands so this is a nasty alert to tell them",en_US:"Can't bring up the keyboard on mobile / tablet :( try visiting on desktop! :D",zh_CN:"无法在移动设备/平板上调出键盘 :( 请试试桌面版 :D",fr_FR:"Impossible de faire apparaître le clavier sur mobile / tablette :( Essayez de passer sur un ordinateur de bureau :D"},"share-tree":{__desc__:"When you export a tree, we want you to share the tree with friends",en_US:'Share this tree with friends! They can load it with "import tree"',zh_CN:'与你的好友分享提交树!他们可以用 "import tree" 加载它',fr_FR:'Partagez cet arbre avec vos amis ! Ils peuvent le charger avec "import tree"'},"paste-json":{__desc__:"When you are importing a level or tree",en_US:"Paste a JSON blob below!",zh_CN:"在下边粘贴一个JSON串",fr_FR:"Collez un blob JSON ci-dessous !"},"solved-map-reset":{__desc__:"When you reset the solved map to clear your solved history, in case someone else wants to use your browser",en_US:"Solved map was reset, you are starting from a clean slate!",zh_CN:"解决列表已重置,您现在从零开始了",fr_FR:"La carte des niveaux résolus a été effacée, vous repartez de zéro !"},"level-cant-exit":{__desc__:"When the user tries to exit a level when they are not in one",en_US:'You are not in a level! You are in a sandbox, start a level with "levels"',zh_CN:'您没在关卡中!您在沙盒中,要开始关卡请输入 "levels"',fr_FR:'Vous n\'êtes pas dans un niveau ! Vous êtes dans le mode bac à sable, commencez un niveau avec "levels"'},"level-no-id":{__desc__:"When you say an id but that level doesnt exist",en_US:'A level for that id "{id}" was not found! Opening up a level selection view',zh_CN:'没找到id为 "{id}" 的关卡!打开关卡选择框',fr_FR:"Le niveau dont l'identifiant est {id} n'a pas été trouvé ! Ouverture de la vue de sélection des niveaux"},"undo-stack-empty":{__desc__:"The undo command can only undo back until the last time the level was reset or the beginning of the level",en_US:"The undo stack is empty!",zh_CN:"还没有什么可以撤销",fr_FR:"La pile d'annulation est vide !"},"already-solved":{__desc__:"When you play in a level that is already solved",en_US:'You have already solved this level, try other levels with "levels" or go back to sandbox with "sandbox"',zh_CN:'你已经解决了本关,输入 "levels" 尝试其他关卡,或者输入 "sandbox" 回到沙盒中',fr_FR:'Vous avez déjà résolu ce niveau, essayez d\'autres niveaux avec "levels" ou revenez au bac à sable avec "sandbox"'},"command-disabled":{__desc__:"When you try a command that is disabled",en_US:"That git command is disabled for this level!",zh_CN:"该命令在本关不允许使用!",fr_FR:"Cette commande git est désactivée pour ce niveau !"},"share-json":{__desc__:"when you have made the level, prompt to share this",en_US:"Here is the JSON for this level! Share it with somenoe or send it to me on Github",zh_CN:"这是一个关卡定义JSON!您可以分享它或者发到我的GitHub上",fr_FR:"Voici le JSON pour ce niveau ! Partagez-le avec quelqu'un ou envoyez-le moi sur Github"},"want-start-dialog":{__desc__:"prompt to add a start dialog",en_US:"You have not specified a start dialog, would you like to add one?",zh_CN:"您还没有定义一开始的介绍,是否添加一个?",fr_FR:"Vous n'avez pas spécifié de dialogue de départ, voulez-vous en ajouter un ?"},"want-hint":{__desc__:"prompt to add a hint",en_US:"You have not specified a hint, would you like to add one?",zh_CN:"您还没有定义提示,是否添加一个?",fr_FR:"Vous n'avez pas spécifié d'indice, voulez-vous en ajouter un ?"},"prompt-hint":{__desc__:"prompt for hint",en_US:"Enter the hint for this level, or leave this blank if you do not want to include one",zh_CN:"请输入关卡提示,或者故意留空",fr_FR:"Entrez l'indice pour ce niveau, ou laissez-le vide pour ne pas l'inclure"},"prompt-name":{__desc__:"prompt for level name",en_US:"Enter the name for the level",zh_CN:"输入关卡名",fr_FR:"Entrez le nom pour ce niveau"},"solution-empty":{__desc__:"If you define a solution without any commands, aka a level that is solved without doing anything",en_US:"Your solution is empty!! Something is amiss",zh_CN:"你的解法是空的!! 这应该是出错了",fr_FR:"Votre solution est vide !! Quelque chose ne tourne pas rond"},"define-start-warning":{__desc__:"When you define the start point again, it overwrites the solution and goal so we add a warning",en_US:"Defining start point... solution and goal will be overwritten if they were defined earlier",zh_CN:"定义开始点... 解决方法和目标会被新的替代",fr_FR:"Redéfinition du point de départ… la solution et la cible seront écrasés s'ils ont déjà été définis"},"help-vague-level":{__desc__:"When you are in a level and you say help, its vague and you need to specify",en_US:'You are in a level, so multiple forms of help are available. Please select either "help level" to learn more about this lesson, "help general" for using Learn GitBranching, or "objective" to learn about how to solve the level.',zh_CN:'您正在关卡中,这里有多种形式的帮助,请选择 "help level" (关卡帮助)或 "help general" (一般帮助)',fr_FR:'Vous êtes dans un niveau, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help level" pour en apprendre plus sur cette leçon, "help general" pour l\'utilisation de Learn GitBranching, ou "objective" pour apprendre comment résoudre le niveau'},"help-vague-builder":{__desc__:"When you are in a level builder, the help command is vague so you need to specify what you mean",en_US:'You are in a level builder, so multiple forms of help are available. Please select either "help general" or "help builder"',zh_CN:'您正在进行关卡构建中,这里有多种形式的帮助,请选择 "help general" (一般帮助)或 "help builder" (关卡构建帮助)',fr_FR:'Vous êtes dans l\'éditeur de niveaux, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help general" soit "help builder"'},"goal-to-reach":{__desc__:"title of window that shoes the goal tree to reach",en_US:"Goal To Reach",zh_CN:"目标",fr_FR:"Cible à atteindre"},"hide-goal":{__desc__:"the helper message for the window that shows the goal tree",en_US:'You can hide this window with "hide goal"',zh_CN:'你可以通过命令 "hide goal" 关闭这个窗口',fr_FR:'Vous pouvez masquer cette fenêtre avec "hide goal"'},"hide-start":{__desc__:"The helper message for the window that shows the start tree for a level",en_US:'You can hide this window with "hide start"',zh_CN:'你可以通过命令 "hide start" 关闭这个窗口',fr_FR:'Vous pouvez masquer cette fenêtre avec "hide start"'},"level-builder":{__desc__:"The name for the environment where you build levels",en_US:"Level Builder",zh_CN:"关卡生成器",fr_FR:"Éditeur de niveaux"},"no-start-dialog":{__desc__:"when the user tries to open a start dialog for a level that does not have one",en_US:"There is no start dialog to show for this level!",zh_CN:"介绍? 这关真没有!",fr_FR:"Il n'y a aucun dialogue de départ à afficher pour ce niveau !"},"no-hint":{__desc__:"when no hint is available for a level",en_US:"Hmm, there doesn't seem to be a hint for this level :-/",zh_CN:"提示?嗯,这关真没有哎~ :-/",fr_FR:"Hum, il ne semble pas y avoir d'indice pour ce niveau :-/"},"error-untranslated-key":{__desc__:"This error happens when we are trying to translate a specific key and the locale version is mission",en_US:"The translation for {key} does not exist yet :( Please hop on github and offer up a translation!",zh_CN:"还没翻译 {key} :( 请在gitHub上贡献你的翻译!",fr_FR:"La traduction pour {key} n'existe pas encore :( Venez sur Github pour en offrir une !"},"error-untranslated":{__desc__:"The general error when we encounter a dialog that is not translated",en_US:"This dialog or text is not yet translated in your locale :( Hop on github to aid in translation!",zh_CN:"这段对话还没有被翻译成你的语言 :( 欢迎在gitHub上贡献你的翻译!",fr_FR:"Ce message n'a pas encore été traduit dans votre langue :( Venez sur Github aider à la traduction !"}}}),e.define("/src/js/app/index.js",function(e,t,n,r,i,s,o){function E(){var t=e("../views"),n=e("../models/collections"),r=e("../views/commandViews"),i=new t.MainHelperBar;this.commandCollection=new n.CommandCollection,this.commandBuffer=new n.CommandBuffer({collection:this.commandCollection}),this.commandPromptView=new r.CommandPromptView({el:$("#commandLineBar")}),this.commandLineHistoryView=new r.CommandLineHistoryView({el:$("#commandLineHistory"),collection:this.commandCollection})}var u=e("underscore"),a=e("backbone"),f=e("../util/constants"),l=e("../util"),c=u.clone(a.Events),h,p,d,v,m,g=function(){var t=e("../level/sandbox").Sandbox,n=e("../level").Level,r=e("../util/eventBaton").EventBaton,i=e("../level/arbiter").LevelArbiter,s=e("../views/levelDropdownView").LevelDropdownView;d=new r,h=new E,p=new t,v=new i,m=new s({wait:!0}),c.on("localeChanged",y),b(d),w(p)},y=function(){if(!window.$)return;$("span.intl-aware").each(function(t,n){var r=e("../intl"),i=$(n).attr("data-intl");$(n).text(r.str(i).toUpperCase())})},b=function(e){var t=function(){$("#commandTextField").focus()};t(),$(window).focus(function(t){e.trigger("windowFocus",t)}),$(document).click(function(t){e.trigger("documentClick",t)}),$(document).bind("keydown",function(t){e.trigger("docKeydown",t)}),$(document).bind("keyup",function(t){e.trigger("docKeyup",t)}),$(window).on("resize",function(e){c.trigger("resize",e)}),e.stealBaton("docKeydown",function(){}),e.stealBaton("docKeyup",function(){}),e.stealBaton("windowFocus",t),e.stealBaton("documentClick",t);var n=function(t){return function(){var n=[t];u.each(arguments,function(e){n.push(e)}),e.trigger.apply(e,n)}};$("#commandTextField").on("keydown",n("keydown")),$("#commandTextField").on("keyup",n("keyup")),$(window).trigger("resize")},w=function(e){var t=l.parseQueryString(window.location.href);t.hasOwnProperty("demo")?e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",["git commit; git checkout -b bugFix C1; git commit; git merge master; git checkout master; git commit; git rebase bugFix;","delay 1000; reset;","level rebase1 --noFinishDialog --noStartCommand --noIntroDialog;","delay 2000; show goal; delay 1000; hide goal;","git checkout bugFix; git rebase master; git checkout side; git rebase bugFix;","git checkout another; git rebase side; git rebase another master;","help; levels"].join(""))}):t.hasOwnProperty("NODEMO")||e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",["git help;","delay 1000;","help;","levels"].join(""))}),t.locale!==undefined&&t.locale.length&&(f.GLOBAL.locale=t.locale,c.trigger("localeChanged"));if(t.command){var n=unescape(t.command);e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",n)})}(/(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent)||/android/i.test(navigator.userAgent))&&e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted","mobile alert")})};e("../util").isBrowser()&&$(document).ready(g),n.getEvents=function(){return c},n.getSandbox=function(){return p},n.getEventBaton=function(){return d},n.getCommandUI=function(){return h},n.getLevelArbiter=function(){return v},n.getLevelDropdown=function(){return m},n.init=g}),e.define("/src/js/level/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("../util"),c=e("../app"),h=e("../intl"),p=e("../log"),d=e("../util/errors"),v=e("../level/sandbox").Sandbox,m=e("../util/constants"),g=e("../visuals/visualization").Visualization,y=e("../level/parseWaterfall").ParseWaterfall,b=e("../level/disabledMap").DisabledMap,w=e("../models/commandModel").Command,E=e("../git/gitShim").GitShim,S=e("../views/multiView").MultiView,x=e("../views").CanvasTerminalHolder,T=e("../views").ConfirmCancelTerminal,N=e("../views").NextLevelConfirm,C=e("../views").LevelToolbar,k=e("../git/treeCompare").TreeCompare,L={"help level":/^help level$/,"start dialog":/^start dialog$/,"show goal":/^(show goal|goal|help goal)$/,"hide goal":/^hide goal$/,"show solution":/^show solution($|\s)/,objective:/^(objective|assignment)$/},A=l.genParseCommand(L,"processLevelCommand"),O=v.extend({initialize:function(e){e=e||{},e.level=e.level||{},this.level=e.level,this.gitCommandsIssued=[],this.commandsThatCount=this.getCommandsThatCount(),this.solved=!1,this.initGoalData(e),this.initName(e),O.__super__.initialize.apply(this,[e]),this.startOffCommand(),this.handleOpen(e.deferred)},handleOpen:function(e){e=e||f.defer();if(this.level.startDialog&&!this.testOption("noIntroDialog")){new S(u.extend({},h.getStartDialog(this.level),{deferred:e}));return}setTimeout(function(){e.resolve()},this.getAnimationTime()*1.2)},objectiveDialog:function(e,t,n){n=n===undefined?this.level:n;if(!n||!n.startDialog){e.set("error",new d.GitError({msg:h.str("no-start-dialog")})),t.resolve();return}debugger;console.log(h.getStartDialog(n));var r=$.extend({},h.getStartDialog(n));r.childViews=r.childViews.slice(-1),new S(u.extend(r,{deferred:t})),t.promise.then(function(){e.set("status","finished")})},startDialog:function(e,t){if(!this.level.startDialog){e.set("error",new d.GitError({msg:h.str("no-start-dialog")})),t.resolve();return}this.handleOpen(t),t.promise.then(function(){e.set("status","finished")})},getEnglishName:function(){return this.level.name.en_US},initName:function(){var e=h.getName(this.level);this.levelToolbar=new C({name:e})},initGoalData:function(e){if(!this.level.goalTreeString||!this.level.solutionCommand)throw new Error("need goal tree and solution")},takeControl:function(){c.getEventBaton().stealBaton("processLevelCommand",this.processLevelCommand,this),O.__super__.takeControl.apply(this)},releaseControl:function(){c.getEventBaton().releaseBaton("processLevelCommand",this.processLevelCommand,this),O.__super__.releaseControl.apply(this)},startOffCommand:function(){this.testOption("noStartCommand")||c.getEventBaton().trigger("commandSubmitted","hint; delay 2000; show goal")},initVisualization:function(e){this.mainVis=new g({el:e.el||this.getDefaultVisEl(),treeString:e.level.startTree})},initGoalVisualization:function(){return this.goalCanvasHolder=new x,this.goalVis=new g({el:this.goalCanvasHolder.getCanvasLocation(),containerElement:this.goalCanvasHolder.getCanvasLocation(),treeString:this.level.goalTreeString,noKeyboardInput:!0,smallCanvas:!0,noClick:!0}),this.goalCanvasHolder},showSolution:function(t,n){var r=this.level.solutionCommand,i=u.bind(function(){this.isShowingSolution=!0,c.getEventBaton().trigger("commandSubmitted",r),p.showLevelSolution(this.getEnglishName())},this),s=t.get("rawStr");this.testOptionOnString(s,"noReset")||(r="reset --forSolution; "+r);if(this.testOptionOnString(s,"force")){i(),t.finishWith(n);return}var o=f.defer(),a=h.getDialog(e("../dialogs/confirmShowSolution"))[0],l=new T({markdowns:a.options.markdowns,deferred:o});o.promise.then(i).fail(function(){t.setResult("")}).done(function(){setTimeout(function(){t.finishWith(n)},l.getAnimationTime())})},showGoal:function(e,t){this.showSideVis(e,t,this.goalCanvasHolder,this.initGoalVisualization)},showSideVis:function(e,t,n,r){var i=function(){e&&e.finishWith(t)};if(!n||!n.inDom)n=r.apply(this);n.slideIn(),setTimeout(i,n.getAnimationTime())},hideGoal:function(e,t){this.hideSideVis(e,t,this.goalCanvasHolder)},hideSideVis:function(e,t,n,r){var i=function(){e&&e.finishWith(t)};n&&n.inDom?(n.die(),setTimeout(i,n.getAnimationTime())):i()},initParseWaterfall:function(e){O.__super__.initParseWaterfall.apply(this,[e]),this.parseWaterfall.addFirst("parseWaterfall",A),this.parseWaterfall.addFirst("instantWaterfall",this.getInstantCommands()),e.level.disabledMap&&this.parseWaterfall.addFirst("instantWaterfall",(new b({disabledMap:e.level.disabledMap})).getInstantCommands())},initGitShim:function(e){this.gitShim=new E({beforeCB:u.bind(this.beforeCommandCB,this),afterCB:u.bind(this.afterCommandCB,this),afterDeferHandler:u.bind(this.afterCommandDefer,this)})},getCommandsThatCount:function(){var t=e("../git/commands"),n=["git commit","git checkout","git rebase","git reset","git branch","git revert","git merge","git cherry-pick"],r={};return u.each(n,function(e){if(!t.regexMap[e])throw new Error("wut no regex");r[e]=t.regexMap[e]}),r},undo:function(){this.gitCommandsIssued.pop(),O.__super__.undo.apply(this,arguments)},afterCommandCB:function(e){if(e.get("error"))return;var t=!1;u.each(this.commandsThatCount,function(n){t=t||n.test(e.get("rawStr"))}),t&&this.gitCommandsIssued.push(e.get("rawStr"))},afterCommandDefer:function(e,t){if(this.solved){t.addWarning(h.str("already-solved")),e.resolve();return}var n=this.mainVis.gitEngine.exportTree(),r=k.dispatchFromLevel(this.level,n);if(!r){e.resolve();return}this.levelSolved(e)},getNumSolutionCommands:function(){var e=this.level.solutionCommand.replace(/^;|;$/g,"");return e.split(";").length},testOption:function(e){return this.options.command&&(new RegExp("--"+e)).test(this.options.command.get("rawStr"))},testOptionOnString:function(e,t){return e&&(new RegExp("--"+t)).test(e)},levelSolved:function(e){this.solved=!0,this.isShowingSolution||(c.getEvents().trigger("levelSolved",this.level.id),p.levelSolved(this.getEnglishName())),this.hideGoal();var t=c.getLevelArbiter().getNextLevel(this.level.id),n=this.gitCommandsIssued.length,r=this.getNumSolutionCommands();m.GLOBAL.isAnimating=!0;var i=this.testOption("noFinishDialog"),s=this.mainVis.gitVisuals.finishAnimation();i||(s=s.then(function(){var e=new N({nextLevel:t,numCommands:n,best:r});return e.getPromise()})),s.then(function(){!i&&t&&(p.choseNextLevel(t.id),c.getEventBaton().trigger("commandSubmitted","level "+t.id))}).fail(function(){}).done(function(){m.GLOBAL.isAnimating=!1,e.resolve()})},die:function(){this.levelToolbar.die(),this.hideGoal(),this.mainVis.die(),this.releaseControl(),this.clear(),delete this.commandCollection,delete this.mainVis,delete this.goalVis,delete this.goalCanvasHolder},getInstantCommands:function(){var e=u.bind(function(){var e=h.getHint(this.level);return!e||!e.length?h.str("no-hint"):e},this);return[[/^help$|^\?$/,function(){throw new d.CommandResult({msg:h.str("help-vague-level")})}],[/^hint$/,function(){throw new d.CommandResult({msg:e()})}]]},reset:function(e,t){this.gitCommandsIssued=[];var n=e?e.get("rawStr"):"";this.testOptionOnString(n,"forSolution")||(this.isShowingSolution=!1),this.solved=!1,O.__super__.reset.apply(this,arguments)},buildLevel:function(e,t){this.exitLevel(),setTimeout(function(){c.getSandbox().buildLevel(e,t)},this.getAnimationTime()*1.5)},importLevel:function(e,t){this.exitLevel(),setTimeout(function(){c.getSandbox().importLevel(e,t)},this.getAnimationTime()*1.5)},startLevel:function(e,t){this.exitLevel(),setTimeout(function(){c.getSandbox().startLevel(e,t)},this.getAnimationTime()*1.5)},exitLevel:function(e,t){this.die();if(!e||!t)return;setTimeout(function(){e.finishWith(t)},this.getAnimationTime()),c.getEventBaton().trigger("levelExited")},processLevelCommand:function(e,t){var n={"show goal":this.showGoal,"hide goal":this.hideGoal,"show solution":this.showSolution,"start dialog":this.startDialog,"help level":this.startDialog,objective:this.objectiveDialog},r=n[e.get("method")];if(!r)throw new Error("woah we dont support that method yet",r);r.apply(this,[e,t])}});n.Level=O,n.regexMap=L}),e.define("/src/js/log/index.js",function(e,t,n,r,i,s,o){var u=function(e,t,n){window._gaq=window._gaq||[],window._gaq.push(["_trackEvent",e,t,n])};n.viewInteracted=function(e){u("views","interacted",e)},n.showLevelSolution=function(e){u("levels","showedLevelSolution",e)},n.choseNextLevel=function(e){u("levels","nextLevelChosen",e)},n.levelSelected=function(e){u("levels","levelSelected",e)},n.levelSolved=function(e){u("levels","levelSolved",e)},n.commandEntered=function(e){u("commands","commandEntered",e)}}),e.define("/src/js/util/errors.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({defaults:{type:"MyError",msg:"Unknown Error"},toString:function(){return this.get("type")+": "+this.get("msg")},getMsg:function(){return this.get("msg")||"Unknown Error"},toResult:function(){return this.get("msg").length?"

"+this.get("msg").replace(/\n/g,"

")+"

":""}}),l=n.CommandProcessError=f.extend({defaults:{type:"Command Process Error"}}),c=n.CommandResult=f.extend({defaults:{type:"Command Result"}}),h=n.Warning=f.extend({defaults:{type:"Warning"}}),p=n.GitError=f.extend({defaults:{type:"Git Error"}}),d=function(e){if(e instanceof l||e instanceof p||e instanceof c||e instanceof h)return;throw e};n.filterError=d}),e.define("/src/js/visuals/visualization.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../models/collections"),l=f.CommitCollection,c=f.BranchCollection,h=e("../util/eventBaton").EventBaton,p=e("../visuals").GitVisuals,d=a.View.extend({initialize:function(e){e=e||{},this.options=e,this.customEvents=u.clone(a.Events),this.containerElement=e.containerElement;var t=this,n=e.containerElement||$("#canvasHolder")[0];new Raphael(n,200,200,function(){var n=this;s.nextTick(function(){t.paperInitialize(n,e)})})},paperInitialize:function(t,n){this.treeString=n.treeString,this.paper=t;var r=e("../app");this.eventBaton=n.noKeyboardInput?new h:r.getEventBaton(),this.commitCollection=new l,this.branchCollection=new c,this.gitVisuals=new p({commitCollection:this.commitCollection,branchCollection:this.branchCollection,paper:this.paper,noClick:this.options.noClick,smallCanvas:this.options.smallCanvas,visualization:this});var i=e("../git").GitEngine;this.gitEngine=new i({collection:this.commitCollection,branches:this.branchCollection,gitVisuals:this.gitVisuals,eventBaton:this.eventBaton}),this.gitEngine.init(),this.gitVisuals.assignGitEngine(this.gitEngine),this.myResize(),$(window).on("resize",u.bind(function(){this.myResize()},this)),this.gitVisuals.drawTreeFirstTime(),this.treeString&&this.gitEngine.loadTreeFromString(this.treeString),this.options.zIndex&&this.setTreeIndex(this.options.zIndex),this.shown=!1,this.setTreeOpacity(0),s.nextTick(u.bind(this.fadeTreeIn,this)),this.customEvents.trigger("gitEngineReady"),this.customEvents.trigger("paperReady")},clearOrigin:function(){delete this.originVis},makeOrigin:function(e){return this.originVis=new d(u.extend({},this.options,{noKeyboardInput:!0,noClick:!0,treeString:e.treeString})),this.originVis},originToo:function(e,t){if(!this.originVis)return;var n=u.bind(function(){this.originVis[e].apply(this.originVis,t)},this);if(this.originVis.paper){n();return}this.originVis.customEvents.on("paperReady",n)},setTreeIndex:function(e){$(this.paper.canvas).css("z-index",e),this.originToo("setTreeIndex",arguments)},setTreeOpacity:function(e){e===0&&(this.shown=!1),$(this.paper.canvas).css("opacity",e),this.originToo("setTreeOpacity",arguments)},getAnimationTime:function(){return 300},fadeTreeIn:function(){this.shown=!0,$(this.paper.canvas).animate({opacity:1},this.getAnimationTime()),this.originToo("fadeTreeIn",arguments)},fadeTreeOut:function(){this.shown=!1,$(this.paper.canvas).animate({opacity:0},this.getAnimationTime()),this.originToo("fadeTreeOut",arguments)},hide:function(){this.fadeTreeOut(),setTimeout(u.bind(function(){$(this.paper.canvas).css("visibility","hidden")},this),this.getAnimationTime()),this.originToo("hide",arguments)},show:function(){$(this.paper.canvas).css("visibility","visible"),setTimeout(u.bind(this.fadeTreeIn,this),10),this.originToo("show",arguments)},showHarsh:function(){$(this.paper.canvas).css("visibility","visible"),this.setTreeOpacity(1),this.originToo("showHarsh",arguments)},resetFromThisTreeNow:function(e){this.treeString=e;var t=this.getOriginInTreeString(e);if(t){var n=this.gitEngine.printTree(t);this.originToo("resetFromThisThreeNow",[n])}},getOriginInTreeString:function(e){var t=JSON.parse(unescape(e));return t.originTree},reset:function(e){var t=e||this.treeString;this.setTreeOpacity(0),t?this.gitEngine.loadTreeFromString(t):this.gitEngine.defaultInit(),this.fadeTreeIn();if(this.originVis)if(t){var n=this.getOriginInTreeString(t);this.originToo("reset",[JSON.stringify(n)])}else this.originToo("reset",arguments)},tearDown:function(){this.gitEngine.tearDown(),this.gitVisuals.tearDown(),delete this.paper,this.originToo("tearDown",arguments)},die:function(){this.fadeTreeOut(),setTimeout(u.bind(function(){this.shown||this.tearDown()},this),this.getAnimationTime()),this.originToo("die",arguments)},myResize:function(){if(!this.paper)return;var e=1,t=this.el,n=t.clientWidth-e,r=t.clientHeight-e;if(!this.containerElement){var i=t.offsetLeft,s=t.offsetTop;$(this.paper.canvas).css({position:"absolute",left:i+"px",top:s+"px"})}this.paper.setSize(n,r),this.gitVisuals.canvasResize(n,r)}});n.Visualization=d}),e.define("/src/js/models/collections.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?f=window.Backbone:f=e("backbone"),l=e("../git").Commit,c=e("../git").Branch,h=e("../models/commandModel").Command,p=e("../models/commandModel").CommandEntry,d=e("../util/constants").TIME,v=f.Collection.extend({model:l}),m=f.Collection.extend({model:h}),g=f.Collection.extend({model:c}),y=f.Collection.extend({model:p,localStorage:f.LocalStorage?new f.LocalStorage("CommandEntries"):null}),b=f.Model.extend({defaults:{collection:null},initialize:function(e){e.collection.bind("add",this.addCommand,this),this.buffer=[],this.timeout=null},addCommand:function(e){this.buffer.push(e),this.touchBuffer()},touchBuffer:function(){if(this.timeout)return;this.setTimeout()},setTimeout:function(){this.timeout=setTimeout(u.bind(function(){this.sipFromBuffer()},this),d.betweenCommandsDelay)},popAndProcess:function(){var e=this.buffer.shift(0);while(e.get("error")&&this.buffer.length)e=this.buffer.shift(0);e.get("error")?this.clear():this.processCommand(e)},processCommand:function(t){t.set("status","processing");var n=a.defer();n.promise.then(u.bind(function(){this.setTimeout()},this));var r=t.get("eventName");if(!r)throw new Error("I need an event to trigger when this guy is parsed and ready");var i=e("../app"),s=i.getEventBaton(),o=s.getNumListeners(r);if(!o){var f=e("../util/errors");t.set("error",new f.GitError({msg:"That command is valid, but not supported in this current environment! Try entering a level or level builder to use that command"})),n.resolve();return}i.getEventBaton().trigger(r,t,n)},clear:function(){clearTimeout(this.timeout),this.timeout=null},sipFromBuffer:function(){if(!this.buffer.length){this.clear();return}this.popAndProcess()}});n.CommitCollection=v,n.CommandCollection=m,n.BranchCollection=g,n.CommandEntryCollection=y,n.CommandBuffer=b}),e.define("/src/js/git/index.js",function(e,t,n,r,i,s,o){function y(e){this.rootCommit=null,this.refs={},this.HEAD=null,this.origin=null,this.localRepo=null,this.branchCollection=e.branches,this.commitCollection=e.collection,this.gitVisuals=e.gitVisuals,this.eventBaton=e.eventBaton,this.eventBaton.stealBaton("processGitCommand",this.dispatch,this),e.animationFactory&&(c=e.animationFactory),this.commandOptions={},this.generalArgs=[],this.initUniqueID()}var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("q"),l=e("../intl"),c=e("../visuals/animation/animationFactory").AnimationFactory,h=e("../visuals/animation").AnimationQueue,p=e("./treeCompare").TreeCompare,d=e("../util/errors"),v=d.GitError,m=d.CommandResult,g=e("../util/eventBaton").EventBaton;y.prototype.initUniqueID=function(){this.uniqueId=function(){var e=0;return function(t){return t?t+e++:e++}}()},y.prototype.assignLocalRepo=function(e){this.localRepo=e},y.prototype.defaultInit=function(){var e=this.getDefaultTree();this.loadTree(e)},y.prototype.getDefaultTree=function(){return JSON.parse(unescape("%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22master%22%2C%22type%22%3A%22branch%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%22C0%22%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C1%22%7D%7D%2C%22HEAD%22%3A%7B%22id%22%3A%22HEAD%22%2C%22target%22%3A%22master%22%2C%22type%22%3A%22general%20ref%22%7D%7D"))},y.prototype.init=function(){this.rootCommit=this.makeCommit(null,null,{rootCommit:!0}),this.commitCollection.add(this.rootCommit);var e=this.makeBranch("master",this.rootCommit);this.HEAD=new b({id:"HEAD",target:e}),this.refs[this.HEAD.get("id")]=this.HEAD,this.commit()},y.prototype.hasOrigin=function(){return!!this.origin},y.prototype.isOrigin=function(){return!!this.localRepo},y.prototype.exportTreeForBranch=function(e){var t=this.exportTree(),n=this.getUpstreamSet(e),r=t.commits;t.commits={},u.each(r,function(e,r){n[r]&&(t.commits[r]=e)});var i=t.branches;return t.branches={},u.each(i,function(n,r){r===e&&(t.branches[r]=n)}),t.HEAD.target=e,t},y.prototype.exportTree=function(){var e={branches:{},commits:{},HEAD:null};u.each(this.branchCollection.toJSON(),function(t){t.target=t.target.get("id"),t.visBranch=undefined,e.branches[t.id]=t}),u.each(this.commitCollection.toJSON(),function(t){u.each(E.prototype.constants.circularFields,function(e){t[e]=undefined},this);var n=[];u.each(t.parents,function(e){n.push(e.get("id"))}),t.parents=n,e.commits[t.id]=t},this);var t=this.HEAD.toJSON();return t.visBranch=undefined,t.lastTarget=t.lastLastTarget=t.visBranch=undefined,t.target=t.target.get("id"),e.HEAD=t,this.hasOrigin()&&(e.originTree=this.origin.exportTree()),e},y.prototype.printTree=function(e){e=e||this.exportTree(),p.reduceTreeFields([e]);var t=JSON.stringify(e);return/'/.test(t)&&(t=escape(t)),t},y.prototype.printAndCopyTree=function(){window.prompt(l.str("Copy the tree string below"),this.printTree())},y.prototype.loadTree=function(e){e=$.extend(!0,{},e),this.removeAll(),this.instantiateFromTree(e),this.reloadGraphics(),this.initUniqueID()},y.prototype.loadTreeFromString=function(e){this.loadTree(JSON.parse(unescape(e)))},y.prototype.instantiateFromTree=function(e){var t={};u.each(e.commits,function(n){var r=this.getOrMakeRecursive(e,t,n.id);this.commitCollection.add(r)},this),u.each(e.branches,function(n){var r=this.getOrMakeRecursive(e,t,n.id);this.branchCollection.add(r,{silent:!0})},this);var n=this.getOrMakeRecursive(e,t,e.HEAD.id);this.HEAD=n,this.rootCommit=t.C0;if(!this.rootCommit)throw new Error("Need root commit of C0 for calculations");this.refs=t,this.gitVisuals.gitReady=!1,this.branchCollection.each(function(e){this.gitVisuals.addBranch(e)},this);if(e.originTree){var r=JSON.stringify(e.originTree);this.makeOrigin(r)}},y.prototype.makeOrigin=function(e){if(this.hasOrigin())throw new v({msg:l.str("git-error-origin-exists")});e=e||this.printTree(this.exportTreeForBranch("master"));var t=this.gitVisuals.getVisualization(),n=t.makeOrigin({localRepo:this,treeString:e});this.animationQueue.set("promiseBased",!0),n.customEvents.on("gitEngineReady",function(){this.origin=n.gitEngine,n.gitEngine.assignLocalRepo(this),this.origin.externalRefresh(),c.playRefreshAnimationAndFinish(this.gitVisuals,this.animationQueue)},this);var r=JSON.parse(unescape(e)),i=r.branches.master.target,s=this.makeBranch("o/master",this.getCommitFromRef(i));s.set("remote",!0)},y.prototype.getOrMakeRecursive=function(e,t,n){if(t[n])return t[n];var r=function(e,t){if(e.commits[t])return"commit";if(e.branches[t])return"branch";if(t=="HEAD")return"HEAD";throw new Error("bad type for "+t)},i=r(e,n);if(i=="HEAD"){var s=e.HEAD,o=new b(u.extend(e.HEAD,{target:this.getOrMakeRecursive(e,t,s.target)}));return t[n]=o,o}if(i=="branch"){var a=e.branches[n],f=new w(u.extend(e.branches[n],{target:this.getOrMakeRecursive(e,t,a.target)}));return t[n]=f,f}if(i=="commit"){var l=e.commits[n],c=[];u.each(l.parents,function(n){c.push(this.getOrMakeRecursive(e,t,n))},this);var h=new E(u.extend(l,{parents:c,gitVisuals:this.gitVisuals}));return t[n]=h,h}throw new Error("ruh rho!! unsupported type for "+n)},y.prototype.tearDown=function(){this.eventBaton.releaseBaton("processGitCommand",this.dispatch,this),this.removeAll()},y.prototype.reloadGraphics=function(){this.gitVisuals.rootCommit=this.refs.C0,this.gitVisuals.initHeadBranch(),this.gitVisuals.drawTreeFromReload(),this.gitVisuals.refreshTreeHarsh()},y.prototype.removeAll=function(){this.branchCollection.reset(),this.commitCollection.reset(),this.refs={},this.HEAD=null,this.rootCommit=null,this.origin&&(this.origin.gitVisuals.getVisualization().tearDown(),delete this.origin,this.gitVisuals.getVisualization().clearOrigin()),this.gitVisuals.resetAll()},y.prototype.getDetachedHead=function(){var e=this.HEAD.get("target"),t=e.get("type");return t!=="branch"},y.prototype.validateBranchName=function(e){e=e.replace(/\s/g,"");if(!/^[a-zA-Z0-9]+$/.test(e))throw new v({msg:l.str("bad-branch-name",{branch:e})});if(/[hH][eE][aA][dD]/.test(e))throw new v({msg:l.str("bad-branch-name",{branch:e})});return e.length>9&&(e=e.slice(0,9),this.command.addWarning(l.str("branch-name-short",{branch:e}))),e},y.prototype.validateAndMakeBranch=function(e,t){e=this.validateBranchName(e);if(this.refs[e])throw new v({msg:l.str("bad-branch-name",{branch:name})});this.makeBranch(e,t)},y.prototype.makeBranch=function(e,t){var n=new w({target:t,id:e});return this.branchCollection.add(n),this.refs[n.get("id")]=n,n},y.prototype.getHead=function(){return u.clone(this.HEAD)},y.prototype.getBranches=function(){var e=[];return this.branchCollection.each(function(t){e.push({id:t.get("id"),selected:this.HEAD.get("target")===t,target:t.get("target"),remote:t.getIsRemote(),obj:t})},this),e},y.prototype.getRemoteBranches=function(){var e=this.getBranches();return u.filter(e,function(e){return e.remote===!0})},y.prototype.getLocalBranches=function(){var e=this.getBranches();return u.filter(e,function(e){return e.remote===!1})},y.prototype.printBranchesWithout=function(e){var t=this.getUpstreamBranchSet(),n=this.getCommitFromRef(e).get("id"),r=[];u.each(t[n],function(e){e.selected=this.HEAD.get("target").get("id")==e.id,r.push(e)},this),this.printBranches(r)},y.prototype.printBranches=function(e){var t="";throw u.each(e,function(e){t+=(e.selected?"* ":"")+e.id+"\n"}),new m({msg:t})},y.prototype.getUniqueID=function(){var e=this.uniqueId("C"),t=u.bind(function(e){return this.refs[e]?!0:this.origin&&this.origin.refs[e]?!0:!1},this);while(t(e))e=this.uniqueId("C");return e},y.prototype.makeCommit=function(e,t,n){t||(t=this.getUniqueID());var r=new E(u.extend({parents:e,id:t,gitVisuals:this.gitVisuals},n||{}));return this.refs[r.get("id")]=r,this.commitCollection.add(r),r},y.prototype.acceptNoGeneralArgs=function(){if(this.generalArgs.length)throw new v({msg:l.str("git-error-no-general-args")})},y.prototype.validateArgBounds=function(e,t,n,r){var i=r===undefined?"git "+this.command.get("method"):this.command.get("method")+" "+r+" ";i="with "+i;if(e.lengthn)throw new v({msg:l.str("git-error-args-many",{upper:String(n),what:i})})},y.prototype.oneArgImpliedHead=function(e,t){this.validateArgBounds(e,0,1,t),e.length===0&&e.push("HEAD")},y.prototype.twoArgsImpliedHead=function(e,t){this.validateArgBounds(e,1,2,t),e.length==1&&e.push("HEAD")},y.prototype.revertStarter=function(){this.validateArgBounds(this.generalArgs,1,NaN),this.revert(this.generalArgs)},y.prototype.revert=function(e){var t=u.map(e,function(e){return this.getCommitFromRef(e)},this),n=f.defer(),r=n.promise,i=this.resolveID("HEAD");r=c.highlightEachWithPromise(r,t,i);var s=this.getCommitFromRef("HEAD"),o=u.bind(function(e){var t=this.rebaseAltID(e.get("id")),n=l.str("git-revert-msg",{oldCommit:this.resolveName(e),oldMsg:e.get("commitMessage")}),r=this.makeCommit([s],t,{commitMessage:n});return s=r,c.playCommitBirthPromiseAnimation(r,this.gitVisuals)},this);u.each(t,function(e){r=r.then(function(){return o(e)})},this),r=r.then(u.bind(function(){return this.setTargetLocation("HEAD",s),c.playRefreshAnimation(this.gitVisuals)},this)),this.animationQueue.thenFinish(r,n)},y.prototype.resetStarter=function(){if(this.commandOptions["--soft"])throw new v({msg:l.str("git-error-staging")});this.commandOptions["--hard"]&&(this.command.addWarning(l.str("git-warning-hard")),this.generalArgs=this.generalArgs.concat(this.commandOptions["--hard"])),this.validateArgBounds(this.generalArgs,1,1);if(this.getDetachedHead())throw new v({msg:l.str("git-error-reset-detached")});this.reset(this.generalArgs[0])},y.prototype.reset=function(e){this.setTargetLocation("HEAD",this.getCommitFromRef(e))},y.prototype.cherrypickStarter=function(){this.validateArgBounds(this.generalArgs,1,Number.MAX_VALUE);var e=this.getUpstreamSet("HEAD"),t=u.map(this.generalArgs,function(t){var n=this.getCommitFromRef(t);if(e[n.get("id")])throw new v({msg:l.str("git-error-already-exists",{commit:n.get("id")})});return n},this),n=f.defer(),r=n.promise,i=this.resolveID("HEAD");r=c.highlightEachWithPromise(r,t,i);var s=u.bind(function(e){var t=this.cherrypick(e);return c.playCommitBirthPromiseAnimation(t,this.gitVisuals)},this);u.each(t,function(e){r=r.then(function(){return s(e)})},this),this.animationQueue.thenFinish(r,n)},y.prototype.checkUpstreamOfSource=function(e,t,n,r,i){var s=t.getUpstreamSet(r),o=e.getCommitFromRef(n).get("id");if(!s[o])throw new v({msg:i||l.str("git-error-origin-fetch-no-ff")})},y.prototype.getTargetGraphDifference=function(e,t,n,r,i){i=i||{},r=t.resolveID(r);var s=e.getUpstreamSet(n),o=t.getCommitFromRef(r),a=t.exportTree(),f=a.commits[o.get("id")];if(e.refs[f.id]){if(i.dontThrowOnNoFetch)return[];throw new v({msg:l.str("git-error-origin-fetch-uptodate")})}f.depth=0;var c=[],h=[f],p=function(e){if(s[e])return;var t=a.commits[e];t.depth=d.depth+1,h.push(t)};while(h.length){var d=h.pop();c.push(d),u.each(d.parents,p)}var m={},g=[];return u.forEach(c,function(e){if(m[e.id])return;m[e.id]=!0,g.push(e)}),g.sort(function(e,t){return t.depth-e.depth})},y.prototype.pushStarter=function(e){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.push()},y.prototype.push=function(e){e=e||{};var t=this.refs.master,n=this.origin.refs.master;this.checkUpstreamOfSource(this,this.origin,n,t,l.str("git-error-origin-push-no-ff"));var r=this.getTargetGraphDifference(this.origin,this,n,t),i=u.bind(function(e,t){var n=u.map(t,function(e){return this.origin.refs[e]},this);return this.origin.makeCommit(n,e)},this),s=u.bind(function(e,t){var n=i(e,t);return c.playCommitBirthPromiseAnimation(n,this.origin.gitVisuals)},this),o=f.defer(),a=o.promise;u.each(r,function(e){a=a.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.refs[e.id],n)},this)),a=a.then(function(){return s(e.id,e.parents)})},this),a=a.then(u.bind(function(){var e=t.get("target").get("id"),r=this.origin.refs[e];return this.origin.setTargetLocation(n,r),c.playRefreshAnimation(this.gitVisuals),c.playRefreshAnimation(this.origin.gitVisuals)},this)),a=a.then(u.bind(function(){var e=this.getCommitFromRef(t),n=t.getRemoteBranchIDFromTracking();return this.setTargetLocation(this.refs[n],e),c.playRefreshAnimation(this.gitVisuals)},this)),e.dontResolvePromise||this.animationQueue.thenFinish(a,o)},y.prototype.fetchStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.fetch()},y.prototype.fetch=function(e){e=e||{};var t=this.refs["o/master"],n=this.origin.refs.master;this.checkUpstreamOfSource(this,this.origin,t,n);var r=this.getTargetGraphDifference(this,this.origin,t,n,e);if(r.length===0){this.command.addWarning(l.str("git-error-origin-fetch-uptodate"));var i=f.defer();return{deferred:i,chain:i.promise}}var s=u.bind(function(e,t){var n=u.map(t,function(e){return this.refs[e]},this);return this.makeCommit(n,e)},this),o=u.bind(function(e,t){var n=s(e,t);return c.playCommitBirthPromiseAnimation(n,this.gitVisuals)},this),a=f.defer(),h=a.promise;return u.each(r,function(e){h=h.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.origin.refs[e.id],t)},this)),h=h.then(function(){return o(e.id,e.parents)})},this),h=h.then(u.bind(function(){var e=n.get("target").get("id"),r=this.refs[e];return this.setTargetLocation(t,r),c.playRefreshAnimation(this.origin.gitVisuals),c.playRefreshAnimation(this.gitVisuals)},this)),e.dontResolvePromise||this.animationQueue.thenFinish(h,a),{chain:h,deferred:a}},y.prototype.pullStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.pull()},y.prototype.pull=function(){var e=this.refs.master,t=this.refs["o/master"],n=this.fetch({dontResolvePromise:!0,dontThrowOnNoFetch:!0});this.commandOptions["--rebase"]?this.pullFinishWithRebase(n,e,t):this.pullFinishWithMerge(n,e,t)},y.prototype.pullFinishWithRebase=function(e,t,n){var r=e.chain,i=e.deferred;r=r.then(function(){return c.getDelayedPromise(300)}),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(n),t)},this)),r=r.then(u.bind(function(){return e.dontResolvePromise=!0,this.rebase(n,t,e)},this)),this.animationQueue.thenFinish(r,i)},y.prototype.pullFinishWithMerge=function(e,t,n){var r=e.chain,i=e.deferred;r=r.then(function(){return c.getDelayedPromise(300)}),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(n),t)},this)),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(t),n)},this)),r=r.then(function(){return c.getDelayedPromise(700)}),r=r.then(u.bind(function(){var e=this.merge("o/master");return e?c.playCommitBirthPromiseAnimation(e,this.gitVisuals):c.playRefreshAnimation(this.gitVisuals)},this)),this.animationQueue.thenFinish(r,i)},y.prototype.cloneStarter=function(){this.acceptNoGeneralArgs(),this.makeOrigin(this.printTree(this.exportTreeForBranch("master")))},y.prototype.fakeTeamworkStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.validateArgBounds(this.generalArgs,0,1);var e=this.generalArgs[0]||1;this.fakeTeamwork(e)},y.prototype.fakeTeamwork=function(e){var t=u.bind(function(){var e=this.getUniqueID();return this.origin.receiveTeamwork(e,this.animationQueue)},this),n=u.bind(function(){var e=t();return c.playCommitBirthPromiseAnimation(e,this.origin.gitVisuals)},this),r=function(){return n()},i=f.defer(),s=i.promise;u.each(u.range(e),function(e){s=s.then(function(){return n()})}),this.animationQueue.thenFinish(s,i)},y.prototype.receiveTeamwork=function(e,t){var n=this.makeCommit([this.getCommitFromRef("HEAD")],e);return this.setTargetLocation(this.HEAD,n),n},y.prototype.cherrypick=function(e){var t=this.rebaseAltID(e.get("id")),n=this.makeCommit([this.getCommitFromRef("HEAD")],t);return this.setTargetLocation(this.HEAD,n),n},y.prototype.commitStarter=function(){this.acceptNoGeneralArgs();if(this.commandOptions["-am"]&&(this.commandOptions["-a"]||this.commandOptions["-m"]))throw new v({msg:l.str("git-error-options")});var e=null,t=null;this.commandOptions["-a"]&&this.command.addWarning(l.str("git-warning-add")),this.commandOptions["-am"]&&(t=this.commandOptions["-am"],this.validateArgBounds(t,1,1,"-am"),e=t[0]),this.commandOptions["-m"]&&(t=this.commandOptions["-m"],this.validateArgBounds(t,1,1,"-m"),e=t[0]);var n=this.commit();e&&(e=e.replace(/"/g,'"').replace(/^"/g,"").replace(/"$/g,""),n.set("commitMessage",e));var r=c.playCommitBirthPromiseAnimation(n,this.gitVisuals);this.animationQueue.thenFinish(r)},y.prototype.commit=function(){var e=this.getCommitFromRef(this.HEAD),t=null;this.commandOptions["--amend"]&&(e=this.resolveID("HEAD~1"),t=this.rebaseAltID(this.getCommitFromRef("HEAD").get("id")));var n=this.makeCommit([e],t);return this.getDetachedHead()&&this.command.addWarning(l.str("git-warning-detached")),this.setTargetLocation(this.HEAD,n),n},y.prototype.resolveName=function(e){var t=this.resolveID(e);return t.get("type")=="commit"?"commit "+t.get("id"):t.get("type")=="branch"?'branch "'+t.get("id")+'"':this.resolveName(t.get("target"))},y.prototype.resolveID=function(e){if(e===null||e===undefined)throw new Error("Dont call this with null / undefined");return typeof e!="string"?e:this.resolveStringRef(e)},y.prototype.resolveRelativeRef=function(e,t){var n=/([~\^])(\d*)/g,r;while(r=n.exec(t)){var i=e,s=r[2]?parseInt(r[2],10):1;if(r[1]=="^")i=e.getParent(s-1);else while(i&&s--)i=i.getParent(0);if(!i){var o=l.str("git-error-relative-ref",{commit:e.id,match:r[0]});throw new v({msg:o})}e=i}return e},y.prototype.resolveStringRef=function(e){e=this.crappyUnescape(e);if(this.refs[e])return this.refs[e];var t=null,n=null,r=/^([a-zA-Z0-9]+)(([~\^]\d*)*)/,i=r.exec(e);if(!i)throw new v({msg:l.str("git-error-exist",{ref:e})});t=i[1],n=i[2];if(!this.refs[t])throw new v({msg:l.str("git-error-exist",{ref:e})});var s=this.getCommitFromRef(t);return n&&(s=this.resolveRelativeRef(s,n)),s},y.prototype.getCommitFromRef=function(e){var t=this.resolveID(e);while(t.get("type")!=="commit")t=t.get("target");return t},y.prototype.getType=function(e){return this.resolveID(e).get("type")},y.prototype.setTargetLocation=function(e,t){if(this.getType(e)=="commit")return;e=this.getOneBeforeCommit(e),e.set("target",t)},y.prototype.getUpstreamBranchSet=function(){var e={},t=function(e,t){var n=!1;return u.each(e,function(e){e.id==t&&(n=!0)}),n},n=function(e){var t=[],n=[e];while(n.length){var r=n.pop();t.push(r.get("id")),r.get("parents")&&r.get("parents").length&&(n=n.concat(r.get("parents")))}return t};return this.branchCollection.each(function(r){var i=n(r.get("target"));u.each(i,function(n){e[n]=e[n]||[],t(e[n],r.get("id"))||e[n].push({obj:r,id:r.get("id")})})}),e},y.prototype.getUpstreamHeadSet=function(){var e=this.getUpstreamSet("HEAD"),t=this.getCommitFromRef("HEAD").get("id");return e[t]=!0,e},y.prototype.getOneBeforeCommit=function(e){var t=this.resolveID(e);return t===this.HEAD&&!this.getDetachedHead()&&(t=t.get("target")),t},y.prototype.scrapeBaseID=function(e){var t=/^C(\d+)/.exec(e);if(!t)throw new Error("regex failed on "+e);return"C"+t[1]},y.prototype.rebaseAltID=function(e){var t=[[/^C(\d+)[']{0,2}$/,function(e){return e[0]+"'"}],[/^C(\d+)[']{3}$/,function(e){return e[0].slice(0,-3)+"'^4"}],[/^C(\d+)['][\^](\d+)$/,function(e){return"C"+String(e[1])+"'^"+String(Number(e[2])+1)}]];for(var n=0;n",this.get("commitMessage"),"
","Commit: "+this.get("id")].join("\n")+"\n"},getShowEntry:function(){return[this.getLogEntry(),"diff --git a/bigGameResults.html b/bigGameResults.html","--- bigGameResults.html","+++ bigGameResults.html","@@ 13,27 @@ Winner, Score","- Stanfurd, 14-7","+ Cal, 21-14"].join("\n")+"\n"},validateAtInit:function(){if(!this.get("id"))throw new Error("Need ID!!");this.get("createTime")||this.set("createTime",(new Date).toString()),this.get("commitMessage")||this.set("commitMessage",l.str("git-dummy-msg")),this.set("children",[]);if(!this.get("rootCommit"))if(!this.get("parents")||!this.get("parents").length)throw new Error("needs parents")},addNodeToVisuals:function(){var e=this.get("gitVisuals").addNode(this.get("id"),this);this.set("visNode",e)},addEdgeToVisuals:function(e){this.get("gitVisuals").addEdge(this.get("id"),e.get("id"))},getParent:function(e){return this&&this.attributes&&this.attributes.parents?this.attributes.parents[e]:null},isMainParent:function(e){var t=this.get("parents").indexOf(e);return t===0},initialize:function(e){this.validateAtInit(),this.addNodeToVisuals(),u.each(this.get("parents"),function(e){e.get("children").push(this),this.addEdgeToVisuals(e)},this)}});n.GitEngine=y,n.Commit=E,n.Branch=w,n.Ref=b}),e.define("/src/js/visuals/animation/animationFactory.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("./index").Animation,c=e("./index").PromiseAnimation,h=e("../../util/constants").GRAPHICS,p={},d=function(e,t){var n=h.defaultAnimationTime*1,r=n*2,i=function(){e.refreshTree(n),t.setBirth(),t.parentInFront(),e.visBranchesFront(),t.animateUpdatedPosition(r,"bounce"),t.animateOutgoingEdges(n)};return{animation:i,duration:Math.max(n,r)}},v=function(e,t){var n=h.defaultAnimationTime*.66,r=n*2;return{animation:function(){e.highlightTo(t,r,"easeInOut")},duration:r*1.5}};p.genCommitBirthAnimation=function(e,t,n){if(!e)throw new Error("Need animation queue to add closure to!");var r=t.get("visNode"),i=d(n,r);e.add(new l({closure:i.animation,duration:i.duration}))},p.genCommitBirthPromiseAnimation=function(e,t){var n=e.get("visNode");return new c(d(t,n))},p.highlightEachWithPromise=function(e,t,n){return u.each(t,function(t){e=e.then(u.bind(function(){return this.playHighlightPromiseAnimation(t,n)},this))},this),e},p.playCommitBirthPromiseAnimation=function(e,t){var n=this.genCommitBirthPromiseAnimation(e,t);return n.play(),n.getPromise()},p.playRefreshAnimationAndFinish=function(e,t){var n=new c({closure:function(){e.refreshTree()}});n.play(),t.thenFinish(n.getPromise())},p.playRefreshAnimation=function(e){var t=new c({closure:function(){e.refreshTree()}});return t.play(),t.getPromise()},p.refreshTree=function(e,t){e.add(new l({closure:function(){t.refreshTree()}}))},p.genHighlightPromiseAnimation=function(e,t){var n=t.get("visBranch")||t.get("visNode"),r=e.get("visNode");return new c(v(r,n))},p.playHighlightPromiseAnimation=function(e,t){var n=this.genHighlightPromiseAnimation(e,t);return n.play(),n.getPromise()},p.getDelayedPromise=function(e){var t=f.defer();return setTimeout(t.resolve,e||1e3),t.promise},p.delay=function(e,t){t=t||h.defaultAnimationTime,e.add(new l({closure:function(){},duration:t}))},n.AnimationFactory=p}),e.define("/src/js/visuals/animation/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("backbone"),l=e("../../util/constants").GLOBAL,c=f.Model.extend({defaults:{duration:300,closure:null},validateAtInit:function(){if(!this.get("closure"))throw new Error("give me a closure!")},initialize:function(e){this.validateAtInit()},run:function(){this.get("closure")()}}),h=f.Model.extend({defaults:{animations:null,index:0,callback:null,defer:!1,promiseBased:!1},initialize:function(e){this.set("animations",[]),e.callback||console.warn("no callback")},thenFinish:function(e,t){e.then(u.bind(function(){this.finish()},this)),this.set("promiseBased",!0),t&&t.resolve()},add:function(e){if(!e instanceof c)throw new Error("Need animation not something else");this.get("animations").push(e)},start:function(){this.set("index",0),l.isAnimating=!0,this.next()},finish:function(){l.isAnimating=!1,this.get("callback")()},next:function(){var e=this.get("animations"),t=this.get("index");if(t>=e.length){this.finish();return}var n=e[t],r=n.get("duration");n.run(),this.set("index",t+1),setTimeout(u.bind(function(){this.next()},this),r)}}),p=f.Model.extend({defaults:{deferred:null,closure:null,duration:300},initialize:function(e){if(!e.closure&&!e.animation)throw new Error("need closure or animation");this.set("closure",e.closure||e.animation),this.set("deferred",e.deferred||a.defer())},getPromise:function(){return this.get("deferred").promise},play:function(){this.get("closure")(),setTimeout(u.bind(function(){this.get("deferred").resolve()},this),this.get("duration"))},then:function(e){return this.get("deferred").promise.then(e)}});p.fromAnimation=function(e){return new p({closure:e.get("closure"),duration:e.get("duration")})},n.Animation=c,n.PromiseAnimation=p,n.AnimationQueue=h}),e.define("/src/js/git/treeCompare.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a={};a.dispatchFromLevel=function(e,t){var n=e.goalTreeString;return a.dispatch(e,n,t)},a.dispatch=function(e,t,n){var r=!0;switch(r){case!!e.compareOnlyMaster:return a.compareBranchWithinTrees(n,t,"master");case!!e.compareOnlyBranches:return a.compareAllBranchesWithinTrees(n,t);case!!e.compareAllBranchesHashAgnostic:return a.compareAllBranchesWithinTreesHashAgnostic(n,t);case!!e.compareOnlyMasterHashAgnostic:return a.compareBranchesWithinTreesHashAgnostic(n,t,["master"]);case!!e.compareOnlyMasterHashAgnosticWithAsserts:return a.compareBranchesWithinTreesHashAgnostic(n,t,["master"])&&a.evalAsserts(n,e.goalAsserts);default:return a.compareAllBranchesWithinTreesAndHEAD(n,t)}},a.compareAllBranchesWithinTreesAndHEAD=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t);debugger;return e.HEAD.target==t.HEAD.target&&this.compareAllBranchesWithinTrees(e,t)},a.compareAllBranchesWithinTrees=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t);var n=u.extend({},e.branches,t.branches),r=!0;return u.uniq(n,function(n,i){r=r&&this.compareBranchWithinTrees(e,t,i)},this),r},a.compareBranchesWithinTrees=function(e,t,n){var r=!0;return u.each(n,function(n){r=r&&this.compareBranchWithinTrees(e,t,n)},this),r},a.compareBranchWithinTrees=function(e,t,n){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var r=this.getRecurseCompare(e,t),i=e.branches[n],s=t.branches[n];return u.isEqual(i,s)&&r(e.commits[i.target],t.commits[s.target])},a.compareAllBranchesWithinTreesHashAgnostic=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var n=u.extend({},e.branches,t.branches),r=[];return u.each(n,function(e,t){r.push(t)}),this.compareBranchesWithinTreesHashAgnostic(e,t,r)},a.compareBranchesWithinTreesHashAgnostic=function(e,t,n){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var r=u.bind(function(e,t){return!e||!t?!1:(e=u.clone(e),t=u.clone(t),e.target=this.getBaseRef(e.target),t.target=this.getBaseRef(t.target),u.isEqual(e,t))},this),i=this.getRecurseCompareHashAgnostic(e,t),s=!0;return u.each(n,function(n){var o=e.branches[n],u=t.branches[n];s=s&&r(o,u)&&i(e.commits[o.target],t.commits[u.target])},this),s},a.evalAsserts=function(e,t){var n=!0;return u.each(t,function(t,r){n=n&&this.evalAssertsOnBranch(e,r,t)},this),n},a.evalAssertsOnBranch=function(e,t,n){e=this.convertTreeSafe(e);if(!e.branches[t])return!1;var r=e.branches[t],i=[r.target],s={};while(i.length){var o=i.pop();s[this.getBaseRef(o)]=this.getNumHashes(o),i=i.concat(e.commits[o].parents)}var a=!0;return u.each(n,function(e){try{a=a&&e(s)}catch(t){console.warn("error during assert",t),console.log(t),a=!1}}),a},a.getNumHashes=function(e){var t=[[/^C(\d+)([']{0,3})$/,function(e){return e[2]?e[2].length:0}],[/^C(\d+)['][\^](\d+)$/,function(e){return Number(e[2])}]];for(var n=0;np.VIEWPORT.minWidth&&e.h>p.VIEWPORT.minHeight&&this.finish()}}),O=L.extend({initialize:function(e){if(!e||!e.level)throw new Error("need level");this.eventBatonName="zoomChange",this.markdowns=["## That zoom level of "+e.level+" is not supported :-/","Please zoom back to a supported zoom level with Ctrl + and Ctrl -","","(and of course, pull requests to fix this are appreciated :D)"],O.__super__.initialize.apply(this,[e])},batonFired:function(e){e<=p.VIEWPORT.maxZoom&&e>=p.VIEWPORT.minZoom&&this.finish()}}),M=m.extend({tagName:"div",className:"levelToolbarHolder",template:u.template($("#level-toolbar-template").html()),initialize:function(e){e=e||{},this.JSON={name:e.name||"Some level! (unknown name)"},this.beforeDestination=$($("#commandLineHistory div.toolbar")[0]),this.render(),e.wait||s.nextTick(u.bind(this.show,this))},getAnimationTime:function(){return 700},render:function(){var e=this.template(this.JSON);this.$el.html(e),this.beforeDestination.after(this.el)},die:function(){this.hide(),setTimeout(u.bind(function(){this.tearDown()},this),this.getAnimationTime())},hide:function(){this.$("div.toolbar").toggleClass("hidden",!0)},show:function(){this.$("div.toolbar").toggleClass("hidden",!1)}}),_=m.extend({tagName:"div",className:"helperBar transitionAll",template:u.template($("#helper-bar-template").html()),events:{"click a":"onClick"},onClick:function(e){var t=e.target,n=$(t).attr("data-id"),r="on"+n[0].toUpperCase()+n.slice(1)+"Click";this[r].call(this)},show:function(){this.$el.toggleClass("show",!0)},hide:function(){this.$el.toggleClass("show",!1),this.deferred&&this.deferred.resolve()},getItems:function(){return[]},setupChildren:function(){},fireCommand:function(e){l.getEventBaton().trigger("commandSubmitted",e)},showDeferMe:function(e){this.hide();var t=a.defer();e.deferred=t,t.promise.then(u.bind(function(){this.show()},this)),e.show()},onExitClick:function(){this.hide()},initialize:function(e){e=e||{},this.destination=$("body"),this.JSON={items:this.getItems()},this.render(),this.setupChildren(),e.wait||this.show()}}),D=_.extend({getItems:function(){return[{text:"Git Branching",id:"english"},{text:"日本語版リポジトリ",id:"japanese"},{text:"Git 브랜치 배우기",id:"korean"},{text:"学习Git分支",id:"chinese"},{text:"français",id:"french"},{icon:"signout",id:"exit"}]},fireCommand:function(){h.viewInteracted("intlSelect"),_.prototype.fireCommand.apply(this,arguments)},onJapaneseClick:function(){this.fireCommand("locale ja; levels"),this.hide()},onEnglishClick:function(){this.fireCommand("locale en_US; levels"),this.hide()},onKoreanClick:function(){this.fireCommand("locale ko; levels"),this.hide()},onFrenchClick:function(){this.fireCommand("locale fr_FR; levels"),this.hide()},onChineseClick:function(){this.fireCommand("locale zh_CN; levels"),this.hide()}}),P=_.extend({getItems:function(){return[{text:"Levels",id:"levels"},{text:"Reset",id:"reset"},{text:"Undo",id:"undo"},{text:"Objective",id:"objectve"},{text:"Help",id:"help"},{icon:"signout",id:"exit"}]},fireCommand:function(){h.viewInteracted("helperBar"),_.prototype.fireCommand.apply(this,arguments)},onObjectiveClick:function(){this.fireCommand("objective")},onLevelsClick:function(){this.fireCommand("levels")},onResetClick:function(){this.fireCommand("reset")},onUndoClick:function(){this.fireCommand("undo")},onHelpClick:function(){this.fireCommand("help general; git help")}}),H=_.extend({getItems:function(){return[{icon:"question-sign",id:"commands"},{icon:"globe",id:"intl"}]},onIntlClick:function(){this.showDeferMe(this.intlHelper),h.viewInteracted("openIntlBar")},onCommandsClick:function(){this.showDeferMe(this.commandsHelper),h.viewInteracted("openCommandsBar")},setupChildren:function(){this.commandsHelper=new P({wait:!0}),this.intlHelper=new D({wait:!0})}}),B=m.extend({tagName:"div",className:"canvasTerminalHolder box flex1",template:u.template($("#terminal-window-bare-template").html()),events:{"click div.wrapper":"onClick"},initialize:function(e){e=e||{},this.destination=$("body"),this.JSON={title:e.title||c.str("goal-to-reach"),text:e.text||c.str("hide-goal")},this.render(),this.inDom=!0,e.additionalClass&&this.$el.addClass(e.additionalClass)},getAnimationTime:function(){return 700},onClick:function(){this.die()},die:function(){this.slideOut(),this.inDom=!1,setTimeout(u.bind(function(){this.tearDown()},this),this.getAnimationTime())},slideOut:function(){this.slideToggle(!0)},slideIn:function(){this.slideToggle(!1)},slideToggle:function(e){this.$("div.terminal-window-holder").toggleClass("slideOut",e)},getCanvasLocation:function(){return this.$("div.inside")[0]}});n.BaseView=m,n.GeneralButton=w,n.ModalView=x,n.ModalTerminal=T,n.ModalAlert=N,n.ContainedBase=b,n.ConfirmCancelView=E,n.LeftRightView=S,n.ZoomAlertWindow=O,n.ConfirmCancelTerminal=C,n.WindowSizeAlertWindow=A,n.MainHelperBar=H,n.CanvasTerminalHolder=B,n.LevelToolbar=M,n.NextLevelConfirm=k}),e.define("/src/js/util/keyboard.js",function(e,t,n,r,i,s,o){function c(e){this.events=e.events||u.clone(a.Events),this.aliasMap=e.aliasMap||{},e.wait||this.listen()}var u=e("underscore"),a=e("backbone"),f=e("../app"),l=function(e){var t={37:"left",38:"up",39:"right",40:"down",27:"esc",13:"enter"};return t[e]};c.prototype.listen=function(){if(this.listening)return;this.listening=!0,f.getEventBaton().stealBaton("docKeydown",this.keydown,this)},c.prototype.mute=function(){this.listening=!1,f.getEventBaton().releaseBaton("docKeydown",this.keydown,this)},c.prototype.keydown=function(e){var t=e.which||e.keyCode,n=l(t);if(n===undefined)return;this.fireEvent(n,e)},c.prototype.fireEvent=function(e,t){e=this.aliasMap[e]||e,this.events.trigger(e,t)},c.prototype.passEventBack=function(e){f.getEventBaton().passBatonBackSoft("docKeydown",this.keydown,this,[e])},n.KeyboardListener=c,n.mapKeycodeToKey=l}),e.define("/node_modules/markdown/package.json",function(e,t,n,r,i,s,o){t.exports={main:"./lib/index.js"}}),e.define("/node_modules/markdown/lib/index.js",function(e,t,n,r,i,s,o){n.markdown=e("./markdown"),n.parse=n.markdown.toHTML}),e.define("/node_modules/markdown/lib/markdown.js",function(e,t,n,r,i,s,o){(function(t){function r(){return"Markdown.mk_block( "+uneval(this.toString())+", "+uneval(this.trailing)+", "+uneval(this.lineNumber)+" )"}function i(){var t=e("util");return"Markdown.mk_block( "+t.inspect(this.toString())+", "+t.inspect(this.trailing)+", "+t.inspect(this.lineNumber)+" )"}function o(e){var t=0,n=-1;while((n=e.indexOf("\n",n+1))!==-1)t++;return t}function u(e,t){function i(e){this.len_after=e,this.name="close_"+t}var n=e+"_state",r=e=="strong"?"em_state":"strong_state";return function(s,o){if(this[n][0]==t)return this[n].shift(),[s.length,new i(s.length-t.length)];var u=this[r].slice(),a=this[n].slice();this[n].unshift(t);var f=this.processInline(s.substr(t.length)),l=f[f.length-1],c=this[n].shift();if(l instanceof i){f.pop();var h=s.length-l.len_after;return[h,[e].concat(f)]}return this[r]=u,this[n]=a,[t.length,t]}}function f(e){var t=e.split(""),n=[""],r=!1;while(t.length){var i=t.shift();switch(i){case" ":r?n[n.length-1]+=i:n.push("");break;case"'":case'"':r=!r;break;case"\\":i=t.shift();default:n[n.length-1]+=i}}return n}function h(e){return l(e)&&e.length>1&&typeof e[1]=="object"&&!l(e[1])?e[1]:undefined}function d(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function v(e){if(typeof e=="string")return d(e);var t=e.shift(),n={},r=[];e.length&&typeof e[0]=="object"&&!(e[0]instanceof Array)&&(n=e.shift());while(e.length)r.push(arguments.callee(e.shift()));var i="";for(var s in n)i+=" "+s+'="'+d(n[s])+'"';return t=="img"||t=="br"||t=="hr"?"<"+t+i+"/>":"<"+t+i+">"+r.join("")+""}function m(e,t,n){var r;n=n||{};var i=e.slice(0);typeof n.preprocessTreeNode=="function"&&(i=n.preprocessTreeNode(i,t));var s=h(i);if(s){i[1]={};for(r in s)i[1][r]=s[r];s=i[1]}if(typeof i=="string")return i;switch(i[0]){case"header":i[0]="h"+i[1].level,delete i[1].level;break;case"bulletlist":i[0]="ul";break;case"numberlist":i[0]="ol";break;case"listitem":i[0]="li";break;case"para":i[0]="p";break;case"markdown":i[0]="html",s&&delete s.references;break;case"code_block":i[0]="pre",r=s?2:1;var o=["code"];o.push.apply(o,i.splice(r)),i[r]=o;break;case"inlinecode":i[0]="code";break;case"img":i[1].src=i[1].href,delete i[1].href;break;case"linebreak":i[0]="br";break;case"link":i[0]="a";break;case"link_ref":i[0]="a";var u=t[s.ref];if(!u)return s.original;delete s.ref,s.href=u.href,u.title&&(s.title=u.title),delete s.original;break;case"img_ref":i[0]="img";var u=t[s.ref];if(!u)return s.original;delete s.ref,s.src=u.href,u.title&&(s.title=u.title),delete s.original}r=1;if(s){for(var a in i[1])r=2;r===1&&i.splice(r,1)}for(;r0&&!l(o[0]))&&this.debug(i[s],"didn't return a proper array"),o}return[]},n.prototype.processInline=function(t){return this.dialect.inline.__call__.call(this,String(t))},n.prototype.toTree=function(t,n){var r=t instanceof Array?t:this.split_blocks(t),i=this.tree;try{this.tree=n||this.tree||["markdown"];e:while(r.length){var s=this.processBlock(r.shift(),r);if(!s.length)continue e;this.tree.push.apply(this.tree,s)}return this.tree}finally{n&&(this.tree=i)}},n.prototype.debug=function(){var e=Array.prototype.slice.call(arguments);e.unshift(this.debug_indent),typeof print!="undefined"&&print.apply(print,e),typeof console!="undefined"&&typeof console.log!="undefined"&&console.log.apply(null,e)},n.prototype.loop_re_over_block=function(e,t,n){var r,i=t.valueOf();while(i.length&&(r=e.exec(i))!=null)i=i.substr(r[0].length),n.call(this,r);return i},n.dialects={},n.dialects.Gruber={block:{atxHeader:function(t,n){var r=t.match(/^(#{1,6})\s*(.*?)\s*#*\s*(?:\n|$)/);if(!r)return undefined;var i=["header",{level:r[1].length}];return Array.prototype.push.apply(i,this.processInline(r[2])),r[0].length1&&n.unshift(r);for(var s=0;s1&&typeof i[i.length-1]=="string"?i[i.length-1]+=o:i.push(o)}}function f(e,t){var n=new RegExp("^("+i+"{"+e+"}.*?\\n?)*$"),r=new RegExp("^"+i+"{"+e+"}","gm"),o=[];while(t.length>0){if(n.exec(t[0])){var u=t.shift(),a=u.replace(r,"");o.push(s(a,u.trailing,u.lineNumber))}break}return o}function l(e,t,n){var r=e.list,i=r[r.length-1];if(i[1]instanceof Array&&i[1][0]=="para")return;if(t+1==n.length)i.push(["para"].concat(i.splice(1)));else{var s=i.pop();i.push(["para"].concat(i.splice(1)),s)}}var e="[*+-]|\\d+\\.",t=/[*+-]/,n=/\d+\./,r=new RegExp("^( {0,3})("+e+")[ ]+"),i="(?: {0,3}\\t| {4})";return function(e,n){function s(e){var n=t.exec(e[2])?["bulletlist"]:["numberlist"];return h.push({list:n,indent:e[1]}),n}var i=e.match(r);if(!i)return undefined;var h=[],p=s(i),d,v=!1,m=[h[0].list],g;e:for(;;){var y=e.split(/(?=\n)/),b="";for(var w=0;wh.length)p=s(i),d.push(p),d=p[1]=["listitem"];else{var N=!1;for(g=0;gi[0].length&&(b+=E+S.substr(i[0].length))}b.length&&(a(d,v,this.processInline(b),E),v=!1,b="");var C=f(h.length,n);C.length>0&&(c(h,l,this),d.push.apply(d,this.toTree(C,[])));var k=n[0]&&n[0].valueOf()||"";if(k.match(r)||k.match(/^ /)){e=n.shift();var L=this.dialect.block.horizRule(e,n);if(L){m.push.apply(m,L);break}c(h,l,this),v=!0;continue e}break}return m}}(),blockquote:function(t,n){if(!t.match(/^>/m))return undefined;var r=[];if(t[0]!=">"){var i=t.split(/\n/),s=[];while(i.length&&i[0][0]!=">")s.push(i.shift());t=i.join("\n"),r.push.apply(r,this.processBlock(s.join("\n"),[]))}while(n.length&&n[0][0]==">"){var o=n.shift();t=new String(t+t.trailing+o),t.trailing=o.trailing}var u=t.replace(/^> ?/gm,""),a=this.tree;return r.push(this.toTree(u,["blockquote"])),r},referenceDefn:function(t,n){var r=/^\s*\[(.*?)\]:\s*(\S+)(?:\s+(?:(['"])(.*?)\3|\((.*?)\)))?\n?/;if(!t.match(r))return undefined;h(this.tree)||this.tree.splice(1,0,{});var i=h(this.tree);i.references===undefined&&(i.references={});var o=this.loop_re_over_block(r,t,function(e){e[2]&&e[2][0]=="<"&&e[2][e[2].length-1]==">"&&(e[2]=e[2].substring(1,e[2].length-1));var t=i.references[e[1].toLowerCase()]={href:e[2]};e[4]!==undefined?t.title=e[4]:e[5]!==undefined&&(t.title=e[5])});return o.length&&n.unshift(s(o,t.trailing)),[]},para:function(t,n){return[["para"].concat(this.processInline(t))]}}},n.dialects.Gruber.inline={__oneElement__:function(t,n,r){var i,s,o=0;n=n||this.dialect.inline.__patterns__;var u=new RegExp("([\\s\\S]*?)("+(n.source||n)+")");i=u.exec(t);if(!i)return[t.length,t];if(i[1])return[i[1].length,i[1]];var s;return i[2]in this.dialect.inline&&(s=this.dialect.inline[i[2]].call(this,t.substr(i.index),i,r||[])),s=s||[i[2].length,i[2]],s},__call__:function(t,n){function s(e){typeof e=="string"&&typeof r[r.length-1]=="string"?r[r.length-1]+=e:r.push(e)}var r=[],i;while(t.length>0)i=this.dialect.inline.__oneElement__.call(this,t,n,r),t=t.substr(i.shift()),c(i,s);return r},"]":function(){},"}":function(){},"\\":function(t){return t.match(/^\\[\\`\*_{}\[\]()#\+.!\-]/)?[2,t[1]]:[1,"\\"]},"![":function(t){var n=t.match(/^!\[(.*?)\][ \t]*\([ \t]*(\S*)(?:[ \t]+(["'])(.*?)\3)?[ \t]*\)/);if(n){n[2]&&n[2][0]=="<"&&n[2][n[2].length-1]==">"&&(n[2]=n[2].substring(1,n[2].length-1)),n[2]=this.dialect.inline.__call__.call(this,n[2],/\\/)[0];var r={alt:n[1],href:n[2]||""};return n[4]!==undefined&&(r.title=n[4]),[n[0].length,["img",r]]}return n=t.match(/^!\[(.*?)\][ \t]*\[(.*?)\]/),n?[n[0].length,["img_ref",{alt:n[1],ref:n[2].toLowerCase(),original:n[0]}]]:[2,"!["]},"[":function b(e){var t=String(e),r=n.DialectHelpers.inline_until_char.call(this,e.substr(1),"]");if(!r)return[1,"["];var i=1+r[0],s=r[1],b,o;e=e.substr(i);var u=e.match(/^\s*\([ \t]*(\S+)(?:[ \t]+(["'])(.*?)\2)?[ \t]*\)/);if(u){var a=u[1];i+=u[0].length,a&&a[0]=="<"&&a[a.length-1]==">"&&(a=a.substring(1,a.length-1));if(!u[3]){var f=1;for(var l=0;l]+)|(.*?@.*?\.[a-zA-Z]+))>/))!=null?n[3]?[n[0].length,["link",{href:"mailto:"+n[3]},n[3]]]:n[2]=="mailto"?[n[0].length,["link",{href:n[1]},n[1].substr("mailto:".length)]]:[n[0].length,["link",{href:n[1]},n[1]]]:[1,"<"]},"`":function(t){var n=t.match(/(`+)(([\s\S]*?)\1)/);return n&&n[2]?[n[1].length+n[2].length,["inlinecode",n[3]]]:[1,"`"]}," \n":function(t){return[3,["linebreak"]]}},n.dialects.Gruber.inline["**"]=u("strong","**"),n.dialects.Gruber.inline.__=u("strong","__"),n.dialects.Gruber.inline["*"]=u("em","*"),n.dialects.Gruber.inline._=u("em","_"),n.buildBlockOrder=function(e){var t=[];for(var n in e){if(n=="__order__"||n=="__call__")continue;t.push(n)}e.__order__=t},n.buildInlinePatterns=function(e){var t=[];for(var n in e){if(n.match(/^__.*__$/))continue;var r=n.replace(/([\\.*+?|()\[\]{}])/g,"\\$1").replace(/\n/,"\\n");t.push(n.length==1?r:"(?:"+r+")")}t=t.join("|"),e.__patterns__=t;var i=e.__call__;e.__call__=function(e,n){return n!=undefined?i.call(this,e,n):i.call(this,e,t)}},n.DialectHelpers={},n.DialectHelpers.inline_until_char=function(e,t){var n=0,r=[];for(;;){if(e[n]==t)return n++,[n,r];if(n>=e.length)return null;res=this.dialect.inline.__oneElement__.call(this,e.substr(n)),n+=res[0],r.push.apply(r,res.slice(1))}},n.subclassDialect=function(e){function t(){}function n(){}return t.prototype=e.block,n.prototype=e.inline,{block:new t,inline:new n}},n.buildBlockOrder(n.dialects.Gruber.block),n.buildInlinePatterns(n.dialects.Gruber.inline),n.dialects.Maruku=n.subclassDialect(n.dialects.Gruber),n.dialects.Maruku.processMetaHash=function(t){var n=f(t),r={};for(var i=0;i1)return undefined;if(!t.match(/^(?:\w+:.*\n)*\w+:.*$/))return undefined;h(this.tree)||this.tree.splice(1,0,{});var r=t.split(/\n/);for(p in r){var i=r[p].match(/(\w+):\s*(.*)$/),s=i[1].toLowerCase(),o=i[2];this.tree[1][s]=o}return[]},n.dialects.Maruku.block.block_meta=function(t,n){var r=t.match(/(^|\n) {0,3}\{:\s*((?:\\\}|[^\}])*)\s*\}$/);if(!r)return undefined;var i=this.dialect.processMetaHash(r[2]),s;if(r[1]===""){var o=this.tree[this.tree.length-1];s=h(o);if(typeof o=="string")return undefined;s||(s={},o.splice(1,0,s));for(a in i)s[a]=i[a];return[]}var u=t.replace(/\n.*$/,""),f=this.processBlock(u,[]);s=h(f[0]),s||(s={},f[0].splice(1,0,s));for(a in i)s[a]=i[a];return f},n.dialects.Maruku.block.definition_list=function(t,n){var r=/^((?:[^\s:].*\n)+):\s+([\s\S]+)$/,i=["dl"],s;if(!(a=t.match(r)))return undefined;var o=[t];while(n.length&&r.exec(n[0]))o.push(n.shift());for(var u=0;u-1&&(a(e)?i=i.split("\n").map(function(e){return" "+e}).join("\n").substr(2):i="\n"+i.split("\n").map(function(e){return" "+e}).join("\n"))):i=o("[Circular]","special"));if(typeof n=="undefined"){if(g==="Array"&&t.match(/^\d+$/))return i;n=JSON.stringify(""+t),n.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(n=n.substr(1,n.length-2),n=o(n,"name")):(n=n.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),n=o(n,"string"))}return n+": "+i});s.pop();var E=0,S=w.reduce(function(e,t){return E++,t.indexOf("\n")>=0&&E++,e+t.length+1},0);return S>50?w=y[0]+(m===""?"":m+"\n ")+" "+w.join(",\n ")+" "+y[1]:w=y[0]+m+" "+w.join(", ")+" "+y[1],w}var s=[],o=function(e,t){var n={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},r={special:"cyan",number:"blue","boolean":"yellow","undefined":"grey","null":"bold",string:"green",date:"magenta",regexp:"red"}[t];return r?"["+n[r][0]+"m"+e+"["+n[r][1]+"m":e};return i||(o=function(e,t){return e}),u(e,typeof r=="undefined"?2:r)};var h=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];n.log=function(e){},n.pump=null;var d=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t},v=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.hasOwnProperty.call(e,n)&&t.push(n);return t},m=Object.create||function(e,t){var n;if(e===null)n={__proto__:null};else{if(typeof e!="object")throw new TypeError("typeof prototype["+typeof e+"] != 'object'");var r=function(){};r.prototype=e,n=new r,n.__proto__=e}return typeof t!="undefined"&&Object.defineProperties&&Object.defineProperties(n,t),n};n.inherits=function(e,t){e.super_=t,e.prototype=m(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})};var g=/%[sdj%]/g;n.format=function(e){if(typeof e!="string"){var t=[];for(var r=0;r=s)return e;switch(e){case"%s":return String(i[r++]);case"%d":return Number(i[r++]);case"%j":return JSON.stringify(i[r++]);default:return e}});for(var u=i[r];r0&&this._events[e].length>n&&(this._events[e].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[e].length),console.trace())}this._events[e].push(t)}else this._events[e]=[this._events[e],t];return this},u.prototype.on=u.prototype.addListener,u.prototype.once=function(e,t){var n=this;return n.on(e,function r(){n.removeListener(e,r),t.apply(this,arguments)}),this},u.prototype.removeListener=function(e,t){if("function"!=typeof t)throw new Error("removeListener only takes instances of Function");if(!this._events||!this._events[e])return this;var n=this._events[e];if(a(n)){var r=f(n,t);if(r<0)return this;n.splice(r,1),n.length==0&&delete this._events[e]}else this._events[e]===t&&delete this._events[e];return this},u.prototype.removeAllListeners=function(e){return e&&this._events&&this._events[e]&&(this._events[e]=null),this},u.prototype.listeners=function(e){return this._events||(this._events={}),this._events[e]||(this._events[e]=[]),a(this._events[e])||(this._events[e]=[this._events[e]]),this._events[e]}}),e.define("/src/js/dialogs/nextLevel.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Great Job!!","","You solved the level in *{numCommands}* command(s); ","our solution uses {best}."]}}],ja:[{type:"ModalAlert",options:{markdowns:["## 完成!","","あなたは*{numCommands}*回のコマンドでこの課題をクリアしました; ","模範解答では{best}回です。"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 碉堡了!","","你用 *{numCommands}* 条命令搞定了这一关;我们的答案要用 {best}。"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Beau Travail!!","","Vous avez résolu le niveau en *{numCommands}* commande(s); ","notre solution le fait en {best}."]}}]}}),e.define("/src/js/models/commandModel.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../util/errors"),l=e("../git/commands"),c=l.GitOptionParser,h=e("../level/parseWaterfall").ParseWaterfall,p=f.CommandProcessError,d=f.GitError,v=f.Warning,m=f.CommandResult,g=a.Model.extend({defaults:{status:"inqueue",rawStr:null,result:"",createTime:null,error:null,warnings:null,parseWaterfall:new h,generalArgs:null,supportedMap:null,options:null,method:null},initialize:function(e){this.initDefaults(),this.validateAtInit(),this.on("change:error",this.errorChanged,this),this.get("error")&&this.errorChanged(),this.parseOrCatch()},initDefaults:function(){this.set("generalArgs",[]),this.set("supportedMap",{}),this.set("warnings",[])},validateAtInit:function(){if(this.get("rawStr")===null)throw new Error("Give me a string!");this.get("createTime")||this.set("createTime",(new Date).toString())},setResult:function(e){this.set("result",e)},finishWith:function(e){this.set("status","finished"),e.resolve()},addWarning:function(e){this.get("warnings").push(e),this.set("numWarnings",this.get("numWarnings")?this.get("numWarnings")+1:1)},getFormattedWarnings:function(){if(!this.get("warnings").length)return"";var e='';return"

"+e+this.get("warnings").join("

"+e)+"

"},parseOrCatch:function(){this.expandShortcuts(this.get("rawStr"));try{this.processInstants()}catch(e){f.filterError(e),this.set("error",e);return}if(this.parseAll())return;this.set("error",new p({msg:'The command "'+this.get("rawStr")+"\" isn't supported, sorry!"}))},errorChanged:function(){var e=this.get("error");e instanceof p||e instanceof d?this.set("status","error"):e instanceof m?this.set("status","finished"):e instanceof v&&this.set("status","warning"),this.formatError()},formatError:function(){this.set("result",this.get("error").toResult())},expandShortcuts:function(e){e=this.get("parseWaterfall").expandAllShortcuts(e),this.set("rawStr",e)},processInstants:function(){var e=this.get("rawStr");if(!e.length)throw new m({msg:""});this.get("parseWaterfall").processAllInstants(e)},parseAll:function(){var e=this.get("rawStr"),t=this.get("parseWaterfall").parseAll(e);return t?(u.each(t.toSet,function(e,t){this.set(t,e)},this),!0):!1}}),y=a.Model.extend({defaults:{text:""}});n.CommandEntry=y,n.Command=g}),e.define("/src/js/git/commands.js",function(e,t,n,r,i,s,o){function y(e,t){this.method=e,this.rawOptions=t,this.supportedMap=this.getMasterOptionMap()[e];if(this.supportedMap===undefined)throw new Error("No option map for "+e);this.generalArgs=[],this.explodeAndSet()}var u=e("underscore"),a=e("../intl"),f=e("../util/errors"),l=f.CommandProcessError,c=f.GitError,h=f.Warning,p=f.CommandResult,d={"git commit":/^(gc|git ci)($|\s)/,"git add":/^ga($|\s)/,"git checkout":/^(go|git co)($|\s)/,"git rebase":/^gr($|\s)/,"git branch":/^(gb|git br)($|\s)/,"git status":/^(gst|gs|git st)($|\s)/,"git help":/^git$/},v=[[/^git help($|\s)/,function(){var e=[a.str("git-version"),"
",a.str("git-usage"),u.escape(a.str("git-usage-command")),"
",a.str("git-supported-commands"),"
"],t=y.prototype.getMasterOptionMap();u.each(t,function(t,n){e.push("git "+n),u.each(t,function(t,n){e.push(" "+n)},this)},this);var n=e.join("\n");throw n=n.replace(/\t/g,"   "),new p({msg:n})}]],m={"git commit":/^git +commit($|\s)/,"git add":/^git +add($|\s)/,"git checkout":/^git +checkout($|\s)/,"git rebase":/^git +rebase($|\s)/,"git reset":/^git +reset($|\s)/,"git branch":/^git +branch($|\s)/,"git revert":/^git +revert($|\s)/,"git log":/^git +log($|\s)/,"git merge":/^git +merge($|\s)/,"git show":/^git +show($|\s)/,"git status":/^git +status($|\s)/,"git cherry-pick":/^git +cherry-pick($|\s)/,"git fakeTeamwork":/^git +fakeTeamwork($|\s)/,"git fetch":/^git +fetch *?$/,"git pull":/^git +pull($|\s)/,"git push":/^git +push($|\s)/,"git clone":/^git +clone *?$/},g=function(e){var t,n;u.each(m,function(r,i){r.exec(e)&&(n=e.slice(i.length+1),t=i.slice("git ".length))});if(!t)return!1;var r=new y(t,n);return{toSet:{generalArgs:r.generalArgs,supportedMap:r.supportedMap,method:t,options:n,eventName:"processGitCommand"}}};y.prototype.getMasterOptionMap=function(){return{commit:{"--amend":!1,"-a":!1,"-am":!1,"-m":!1},status:{},log:{},add:{},"cherry-pick":{},branch:{"-d":!1,"-D":!1,"-f":!1,"-a":!1,"-r":!1,"--contains":!1},checkout:{"-b":!1,"-B":!1,"-":!1},reset:{"--hard":!1,"--soft":!1},merge:{},rebase:{"-i":!1},revert:{},show:{},clone:{},fetch:{},pull:{"--rebase":!1},push:{},fakeTeamwork:{}}},y.prototype.explodeAndSet=function(){var e=this.rawOptions.match(/('.*?'|".*?"|\S+)/g)||[];for(var t=0;t","show commands","show solution","show goal"];throw new v({msg:t.join("\n")})}],[/^locale (\w+)$/,function(t){f.GLOBAL.locale=t[1];var n=e("../app").getEvents().trigger("localeChanged");throw new v({msg:l.str("locale-command",{locale:t[1]})})}],[/^refresh$/,function(){var t=e("../app").getEvents();throw t.trigger("refreshTree"),new v({msg:l.str("refresh-tree-command")})}],[/^rollup (\d+)$/,function(t){var n=e("../app").getEvents();throw n.trigger("rollupCommands",t[1]),new v({msg:"Commands combined!"})}],[/^echo "(.*?)"$|^echo (.*?)$/,function(e){var t=e[1]||e[2];throw new v({msg:t})}],[/^show +commands$/,function(e){var t=y(),n=[l.str("show-all-commands"),"
"];throw u.each(t,function(e,t){n.push(t)}),new v({msg:n.join("\n")})}]],g={"reset solved":/^reset solved($|\s)/,help:/^help( +general)?$|^\?$/,reset:/^reset( +--forSolution)?$/,delay:/^delay (\d+)$/,clear:/^clear($|\s)/,"exit level":/^exit level($|\s)/,sandbox:/^sandbox($|\s)/,level:/^level\s?([a-zA-Z0-9]*)/,levels:/^levels($|\s)/,mobileAlert:/^mobile alert($|\s)/,"build level":/^build +level($|\s)/,"export tree":/^export +tree$/,"import tree":/^import +tree$/,"import level":/^import +level$/,undo:/^undo($|\s)/},y=function(){var t=["mobileAlert"],n=u.extend({},e("../git/commands").regexMap,e("../level").regexMap,g);return u.each(t,function(e){delete n[e]}),n};n.instantCommands=m,n.parse=a.genParseCommand(g,"processSandboxCommand"),n.getOptimisticLevelParse=function(){return a.genParseCommand(e("../level").regexMap,"processLevelCommand")},n.getOptimisticLevelBuilderParse=function(){return a.genParseCommand(e("../level/builder").regexMap,"processLevelBuilderCommand")}}),e.define("/src/js/level/builder.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("../util"),c=e("../app"),h=e("../intl"),p=e("../util/errors"),d=e("../visuals/visualization").Visualization,v=e("../level/parseWaterfall").ParseWaterfall,m=e("../level").Level,g=e("../models/commandModel").Command,y=e("../git/gitShim").GitShim,b=e("../views/multiView").MultiView,w=e("../views").CanvasTerminalHolder,E=e("../views").ConfirmCancelTerminal,S=e("../views").NextLevelConfirm,x=e("../views").LevelToolbar,T=e("../views/builderViews").MarkdownPresenter,N=e("../views/builderViews").MultiViewBuilder,C=e("../views/builderViews").MarkdownGrabber,k={"define goal":/^define goal$/,"define name":/^define name$/,"help builder":/^help builder$/,"define start":/^define start$/,"edit dialog":/^edit dialog$/,"show start":/^show start$/,"hide start":/^hide start$/,"define hint":/^define hint$/,finish:/^finish$/},L=l.genParseCommand(k,"processLevelBuilderCommand"),A=m.extend({initialize:function(t){t=t||{},t.level=t.level||{};var n=h.getLocale();t.level.startDialog={},t.level.startDialog[n]={childViews:h.getDialog(e("../dialogs/levelBuilder"))},A.__super__.initialize.apply(this,[t]),this.startDialogObj=undefined,this.definedGoal=!1,delete this.treeCompare,delete this.solved},initName:function(){this.levelToolbar=new x({name:h.str("level-builder")})},initGoalData:function(){this.level.goalTreeString='{"branches":{"master":{"target":"C1","id":"master"},"makeLevel":{"target":"C2","id":"makeLevel"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"}},"HEAD":{"target":"makeLevel","id":"HEAD"}}',this.level.solutionCommand="git checkout -b makeLevel; git commit",A.__super__.initGoalData.apply(this,arguments)},initStartVisualization:function(){return this.startCanvasHolder=new w({additionalClass:"startTree",text:h.str("hide-start")}),this.startVis=new d({el:this.startCanvasHolder.getCanvasLocation(),containerElement:this.startCanvasHolder.getCanvasLocation(),treeString:this.level.startTree,noKeyboardInput:!0,smallCanvas:!0,noClick:!0}),this.startCanvasHolder},startOffCommand:function(){c.getEventBaton().trigger("commandSubmitted","echo :D")},objectiveDialog:function(e,t){var n=[e,t,this.startDialogObj===undefined?null:{startDialog:{en_US:this.startDialogObj}}];A.__super__.objectiveDialog.apply(this,n)},initParseWaterfall:function(e){A.__super__.initParseWaterfall.apply(this,[e]),this.parseWaterfall.addFirst("parseWaterfall",L),this.parseWaterfall.addFirst("instantWaterfall",this.getInstantCommands())},buildLevel:function(e,t){this.exitLevel(),setTimeout(function(){c.getSandbox().buildLevel(e,t)},this.getAnimationTime()*1.5)},getInstantCommands:function(){return[[/^help$|^\?$/,function(){throw new p.CommandResult({msg:h.str("help-vague-builder")})}]]},takeControl:function(){c.getEventBaton().stealBaton("processLevelBuilderCommand",this.processLevelBuilderCommand,this),A.__super__.takeControl.apply(this)},releaseControl:function(){c.getEventBaton().releaseBaton("processLevelBuilderCommand",this.processLevelBuilderCommand,this),A.__super__.releaseControl.apply(this)},showGoal:function(){this.hideStart(),A.__super__.showGoal.apply(this,arguments)},showStart:function(e,t){this.hideGoal(),this.showSideVis(e,t,this.startCanvasHolder,this.initStartVisualization)},resetSolution:function(){this.gitCommandsIssued=[],this.level.solutionCommand=undefined},hideStart:function(e,t){this.hideSideVis(e,t,this.startCanvasHolder)},defineStart:function(e,t){this.hideStart(),e.addWarning(h.str("define-start-warning")),this.resetSolution(),this.level.startTree=this.mainVis.gitEngine.printTree(),this.mainVis.resetFromThisTreeNow(this.level.startTree),this.showStart(e,t)},defineGoal:function(e,t){this.hideGoal();if(!this.gitCommandsIssued.length){e.set("error",new p.GitError({msg:h.str("solution-empty")})),t.resolve();return}this.definedGoal=!0,this.level.solutionCommand=this.gitCommandsIssued.join(";"),this.level.goalTreeString=this.mainVis.gitEngine.printTree(),this.initGoalVisualization(),this.showGoal(e,t)},defineName:function(e,t){this.level.name={en_US:prompt(h.str("prompt-name"))},e&&e.finishWith(t)},defineHint:function(e,t){this.level.hint={en_US:prompt(h.str("prompt-hint"))},e&&e.finishWith(t)},editDialog:function(e,t){var n=f.defer();this.currentBuilder=new N({multiViewJSON:this.startDialogObj,deferred:n}),n.promise.then(u.bind(function(e){this.startDialogObj=e},this)).fail(function(){}).done(function(){e?e.finishWith(t):t.resolve()})},finish:function(e,t){if(!this.gitCommandsIssued.length||!this.definedGoal){e.set("error",new p.GitError({msg:h.str("solution-empty")})),t.resolve();return}while(!this.level.name)this.defineName();var n=f.defer(),r=n.promise;if(this.level.hint===undefined){var i=f.defer();r=r.then(function(){return i.promise});var s=new E({markdowns:[h.str("want-hint")]});s.getPromise().then(u.bind(this.defineHint,this)).fail(u.bind(function(){this.level.hint={en_US:""}},this)).done(function(){i.resolve()})}if(this.startDialogObj===undefined){var o=f.defer();r=r.then(function(){return o.promise});var a=new E({markdowns:[h.str("want-start-dialog")]});a.getPromise().then(u.bind(function(){var e=f.defer();return this.editDialog(undefined,e),e.promise},this)).fail(function(){}).done(function(){o.resolve()})}r=r.done(u.bind(function(){new T({fillerText:JSON.stringify(this.getExportObj(),null,2),previewText:h.str("share-json")}),e.finishWith(t)},this)),n.resolve()},getExportObj:function(){var e=u.extend({},this.level);return delete e.startDialog,this.startDialogObj&&(e.startDialog={en_US:this.startDialogObj}),e},processLevelBuilderCommand:function(e,t){var n={"define goal":this.defineGoal,"define start":this.defineStart,"show start":this.showStart,"hide start":this.hideStart,finish:this.finish,"define hint":this.defineHint,"define name":this.defineName,"edit dialog":this.editDialog,"help builder":A.__super__.startDialog};if(!n[e.get("method")])throw new Error("woah we dont support that method yet");n[e.get("method")].apply(this,arguments)},afterCommandDefer:function(e,t){e.resolve()},die:function(){this.hideStart(),A.__super__.die.apply(this,arguments),delete this.startVis,delete this.startCanvasHolder}});n.LevelBuilder=A,n.regexMap=k}),e.define("/src/js/git/gitShim.js",function(e,t,n,r,i,s,o){function c(e){e=e||{},this.beforeCB=e.beforeCB||function(){},this.afterCB=e.afterCB||function(){};var t=function(e){e.resolve()};this.beforeDeferHandler=e.beforeDeferHandler||t,this.afterDeferHandler=e.afterDeferHandler||t,this.eventBaton=e.eventBaton||f.getEventBaton()}var u=e("underscore"),a=e("q"),f=e("../app"),l=e("../views/multiView").MultiView;c.prototype.insertShim=function(){this.eventBaton.stealBaton("processGitCommand",this.processGitCommand,this)},c.prototype.removeShim=function(){this.eventBaton.releaseBaton("processGitCommand",this.processGitCommand,this)},c.prototype.processGitCommand=function(e,t){this.beforeCB(e);var n=a.defer();n.promise.then(u.bind(function(){this.afterGitCommandProcessed(e,t)},this)).done();var r=u.bind(function(){this.eventBaton.passBatonBack("processGitCommand",this.processGitCommand,this,[e,n])},this),i=a.defer();i.promise.then(r).done(),this.beforeDeferHandler(i,e)},c.prototype.afterGitCommandProcessed=function(e,t){this.afterCB(e);var n=a.defer();n.promise.then(function(){t.resolve()}).done(),this.afterDeferHandler(n,e)},n.GitShim=c}),e.define("/src/js/views/multiView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../views").ModalTerminal,c=e("../views").ContainedBase,h=e("../views").ConfirmCancelView,p=e("../views").LeftRightView,d=e("../views").ModalAlert,v=e("../views/gitDemonstrationView").GitDemonstrationView,m=e("../views/builderViews"),g=m.MarkdownPresenter,y=e("../util/keyboard").KeyboardListener,b=e("../util/errors").GitError,w=f.View.extend({tagName:"div",className:"multiView",navEventDebounce:550,deathTime:700,typeToConstructor:{ModalAlert:d,GitDemonstrationView:v,MarkdownPresenter:g},initialize:function(e){e=e||{},this.childViewJSONs=e.childViews||[{type:"ModalAlert",options:{markdown:"Woah wtf!!"}},{type:"GitDemonstrationView",options:{command:"git checkout -b side; git commit; git commit"}},{type:"ModalAlert",options:{markdown:"Im second"}}],this.deferred=e.deferred||a.defer(),this.childViews=[],this.currentIndex=0,this.navEvents=u.clone(f.Events),this.navEvents.on("negative",this.getNegFunc(),this),this.navEvents.on("positive",this.getPosFunc(),this),this.navEvents.on("quit",this.finish,this),this.navEvents.on("exit",this.finish,this),this.keyboardListener=new y({events:this.navEvents,aliasMap:{left:"negative",right:"positive",enter:"positive",esc:"quit"}}),this.render(),e.wait||this.start()},onWindowFocus:function(){},getAnimationTime:function(){return 700},getPromise:function(){return this.deferred.promise},getPosFunc:function(){return u.debounce(u.bind(function(){this.navForward()},this),this.navEventDebounce,!0)},getNegFunc:function(){return u.debounce(u.bind(function(){this.navBackward()},this),this.navEventDebounce,!0)},lock:function(){this.locked=!0},unlock:function(){this.locked=!1},navForward:function(){if(this.locked)return;if(this.currentIndex===this.childViews.length-1){this.hideViewIndex(this.currentIndex),this.finish();return}this.navIndexChange(1)},navBackward:function(){if(this.currentIndex===0)return;this.navIndexChange(-1)},navIndexChange:function(e){this.hideViewIndex(this.currentIndex),this.currentIndex+=e,this.showViewIndex(this.currentIndex)},hideViewIndex:function(e){this.childViews[e].hide()},showViewIndex:function(e){this.childViews[e].show()},finish:function(){this.keyboardListener.mute(),u.each(this.childViews,function(e){e.die()}),this.deferred.resolve()},start:function(){this.showViewIndex(this.currentIndex)},createChildView:function(e){var t=e.type;if(!this.typeToConstructor[t])throw new Error('no constructor for type "'+t+'"');var n=new this.typeToConstructor[t](u.extend({},e.options,{wait:!0}));return n},addNavToView:function(e,t){var n=new p({events:this.navEvents,destination:e.getDestination(),showLeft:t!==0,lastNav:t===this.childViewJSONs.length-1});e.receiveMetaNav&&e.receiveMetaNav(n,this)},render:function(){u.each(this.childViewJSONs,function(e,t){var n=this.createChildView(e);this.childViews.push(n),this.addNavToView(n,t)},this)}});n.MultiView=w}),e.define("/src/js/views/gitDemonstrationView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../util/keyboard").KeyboardListener,h=e("../models/commandModel").Command,p=e("../views").ModalTerminal,d=e("../views").ContainedBase,v=e("../visuals/visualization").Visualization,m=d.extend({tagName:"div",className:"gitDemonstrationView box horizontal",template:u.template($("#git-demonstration-view").html()),events:{"click div.command > p.uiButton":"positive"},initialize:function(t){t=t||{},this.options=t,this.JSON=u.extend({beforeMarkdowns:["## Git Commits","","Awesome!"],command:"git commit",afterMarkdowns:["Now you have seen it in action","","Go ahead and try the level!"]},t);var n=function(t){return e("markdown").markdown.toHTML(t.join("\n"))};this.JSON.beforeHTML=n(this.JSON.beforeMarkdowns),this.JSON.afterHTML=n(this.JSON.afterMarkdowns),this.container=new p({title:t.title||"Git Demonstration"}),this.render(),this.checkScroll(),this.navEvents=u.clone(f.Events),this.navEvents.on("positive",this.positive,this),this.navEvents.on("negative",this.negative,this),this.keyboardListener=new c({events:this.navEvents,aliasMap:{enter:"positive",right:"positive",left:"negative"},wait:!0}),this.visFinished=!1,this.initVis(),t.wait||this.show()},receiveMetaNav:function(e,t){var n=this;e.navEvents.on("positive",this.positive,this),this.metaContainerView=t},checkScroll:function(){var e=this.$("div.demonstrationText").children(),t=u.map(e,function(e){return e.clientHeight}),n=u.reduce(t,function(e,t){return e+t});n15&&console.warn("graphics are degrading from too many layers");var t=this.getDepthIncrement(e);u.each(this.visNodeMap,function(e){e.setDepthBasedOn(t,this.getHeaderOffset())},this)},w.prototype.animateNodePositions=function(e){u.each(this.visNodeMap,function(t){t.animateUpdatedPosition(e)},this)},w.prototype.addBranchFromEvent=function(e,t,n){var r=u.bind(function(){this.addBranch(e)},this);!this.gitEngine||!this.gitReady?this.defer(r):r()},w.prototype.addBranch=function(e){var t=new m({branch:e,gitVisuals:this,gitEngine:this.gitEngine});this.visBranchCollection.add(t),this.gitReady?t.genGraphics(this.paper):this.defer(u.bind(function(){t.genGraphics(this.paper)},this))},w.prototype.removeVisBranch=function(e){this.visBranchCollection.remove(e)},w.prototype.removeVisNode=function(e){this.visNodeMap[e.getID()]=undefined},w.prototype.removeVisEdge=function(e){this.visEdgeCollection.remove(e)},w.prototype.animateRefs=function(e){this.visBranchCollection.each(function(t){t.animateUpdatedPos(e)},this)},w.prototype.animateEdges=function(e){this.visEdgeCollection.each(function(t){t.animateUpdatedPath(e)},this)},w.prototype.getMinLayers=function(){return this.options.smallCanvas?2:7},w.prototype.getDepthIncrement=function(e){e=Math.max(e,this.getMinLayers());var t=1-this.getHeaderOffset(),n=t/e;return n},w.prototype.shouldHaveHeader=function(){return this.gitEngine.isOrigin()||this.gitEngine.hasOrigin()},w.prototype.getHeaderOffset=function(){return this.shouldHaveHeader()?.05:0},w.prototype.calcDepthRecursive=function(e,t){e.get("visNode").setDepth(t);var n=e.get("children"),r=t;return u.each(n,function(e){var n=this.calcDepthRecursive(e,t+1);r=Math.max(n,r)},this),r},w.prototype.canvasResize=function(e,t){this.resizeFunc||this.genResizeFunc(),this.resizeFunc(e,t)},w.prototype.genResizeFunc=function(){this.resizeFunc=u.debounce(u.bind(function(t,n){this.refreshTree()},this),200,!0)},w.prototype.addNode=function(e,t){this.commitMap[e]=t,t.get("rootCommit")&&(this.rootCommit=t);var n=new v({id:e,commit:t,gitVisuals:this,gitEngine:this.gitEngine});return this.visNodeMap[e]=n,this.gitReady&&n.genGraphics(this.paper),n},w.prototype.addEdge=function(e,t){var n=this.visNodeMap[e],r=this.visNodeMap[t];if(!n||!r)throw new Error("one of the ids in ("+e+", "+t+") does not exist");var i=new y({tail:n,head:r,gitVisuals:this,gitEngine:this.gitEngine});this.visEdgeCollection.add(i),this.gitReady&&i.genGraphics(this.paper)},w.prototype.zIndexReflow=function(){this.visNodesFront(),this.visBranchesFront()},w.prototype.visNodesFront=function(){u.each(this.visNodeMap,function(e){e.toFront()})},w.prototype.visBranchesFront=function(){this.visBranchCollection.each(function(e){e.nonTextToFront(),e.textToFront()}),this.visBranchCollection.each(function(e){e.textToFrontIfInStack()})},w.prototype.drawTreeFromReload=function(){this.gitReady=!0,this.deferFlush(),this.calcTreeCoords()},w.prototype.drawTreeFirstTime=function(){this.gitReady=!0,this.calcTreeCoords(),u.each(this.visNodeMap,function(e){e.genGraphics(this.paper)},this),this.visEdgeCollection.each(function(e){e.genGraphics(this.paper)},this),this.visBranchCollection.each(function(e){e.genGraphics(this.paper)},this),this.zIndexReflow()},n.GitVisuals=w}),e.define("/src/js/visuals/visNode.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=l.extend({defaults:{depth:undefined,maxWidth:null,outgoingEdges:null,circle:null,text:null,id:null,pos:null,radius:null,commit:null,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing,fill:f.defaultNodeFill,"stroke-width":f.defaultNodeStrokeWidth,stroke:f.defaultNodeStroke},getID:function(){return this.get("id")},validateAtInit:function(){if(!this.get("id"))throw new Error("need id for mapping");if(!this.get("commit"))throw new Error("need commit for linking");this.get("pos")||this.set("pos",{x:Math.random(),y:Math.random()})},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine"),this.set("outgoingEdges",[])},setDepth:function(e){this.set("depth",Math.max(this.get("depth")||0,e))},setDepthBasedOn:function(e,t){if(this.get("depth")===undefined)throw new Error("no depth yet!");var n=this.get("pos");n.y=this.get("depth")*e+t},getMaxWidthScaled:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("commit")),t={branch:1,head:.3,none:.1};if(t[e]===undefined)throw new Error("bad stat");return t[e]*this.get("maxWidth")},toFront:function(){this.get("circle").toFront(),this.get("text").toFront()},getOpacity:function(){var e={branch:1,head:f.upstreamHeadOpacity,none:f.upstreamNoneOpacity},t=this.gitVisuals.getCommitUpstreamStatus(this.get("commit"));if(e[t]===undefined)throw new Error("invalid status");return e[t]},getTextScreenCoords:function(){return this.getScreenCoords()},getAttributes:function(){var e=this.getScreenCoords(),t=this.getTextScreenCoords(),n=this.getOpacity(),r=this.getIsInOrigin()?f.originDash:"";return{circle:{cx:e.x,cy:e.y,opacity:n,r:this.getRadius(),fill:this.getFill(),"stroke-width":this.get("stroke-width"),"stroke-dasharray":r,stroke:this.get("stroke")},text:{x:t.x,y:t.y,opacity:n}}},highlightTo:function(e,t,n){var r=e.get("fill"),i={circle:{fill:r,stroke:r,"stroke-dasharray":"","stroke-width":this.get("stroke-width")*5},text:{}};this.animateToAttr(i,t,n)},animateUpdatedPosition:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},animateToSnapshot:function(e,t,n){if(!e[this.getID()])return;this.animateToAttr(e[this.getID()],t,n)},setAttr:function(e,t,n,r){var i=["text","circle"];this.setAttrBase(i,e,t,n,r)},animateToAttr:function(e,t,n){l.prototype.animateToAttr.apply(this,arguments);var r=t!==undefined?t:this.get("animationSpeed"),i=n||this.get("animationEasing");n=="bounce"&&e.circle&&e.circle.cx!==undefined&&e.text&&e.text.x!==undefined&&(this.get("circle").animate(e.circle.cx,r,"easeInOut"),this.get("text").animate(e.text.x,r,"easeInOut"))},getScreenCoords:function(){var e=this.get("pos");return this.gitVisuals.toScreenCoords(e)},getRadius:function(){return this.get("radius")||f.nodeRadius},getParentScreenCoords:function(){return this.get("commit").get("parents")[0].get("visNode").getScreenCoords()},setBirthPosition:function(){var e=this.getParentScreenCoords();this.get("circle").attr({cx:e.x,cy:e.y,opacity:0,r:0}),this.get("text").attr({x:e.x,y:e.y,opacity:0})},setBirthFromSnapshot:function(e){var t=this.get("commit").get("parents")[0].get("visNode").getID(),n=e[t];this.get("circle").attr({opacity:0,r:0,cx:n.circle.cx,cy:n.circle.cy}),this.get("text").attr({opacity:0,x:n.text.x,y:n.text.y});var r={x:n.circle.cx,y:n.circle.cy};this.setOutgoingEdgesBirthPosition(r)},setBirth:function(){this.setBirthPosition(),this.setOutgoingEdgesBirthPosition(this.getParentScreenCoords())},setOutgoingEdgesOpacity:function(e){u.each(this.get("outgoingEdges"),function(t){t.setOpacity(e)})},animateOutgoingEdgesToAttr:function(e,t,n){u.each(this.get("outgoingEdges"),function(t){var n=e[t.getID()];t.animateToAttr(n)},this)},animateOutgoingEdges:function(e,t){u.each(this.get("outgoingEdges"),function(n){n.animateUpdatedPath(e,t)},this)},animateOutgoingEdgesFromSnapshot:function(e,t,n){u.each(this.get("outgoingEdges"),function(r){var i=e[r.getID()];r.animateToAttr(i,t,n)},this)},setOutgoingEdgesBirthPosition:function(e){u.each(this.get("outgoingEdges"),function(t){var n=t.get("head").getScreenCoords(),r=t.genSmoothBezierPathStringFromCoords(e,n);t.get("path").stop(),t.get("path").attr({path:r,opacity:0})},this)},parentInFront:function(){this.get("commit").get("parents")[0].get("visNode").toFront()},getFontSize:function(e){return e.length<3?12:e.length<5?10:8},getFill:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("commit"));return e=="head"?f.headRectFill:e=="none"?f.orphanNodeFill:this.gitVisuals.getBlendedHuesForCommit(this.get("commit"))},attachClickHandlers:function(){if(this.get("gitVisuals").options.noClick)return;var t="git checkout "+this.get("commit").get("id"),n=e("../app");u.each([this.get("circle"),this.get("text")],function(e){e.click(function(){n.getEventBaton().trigger("commandSubmitted",t)}),$(e.node).css("cursor","pointer")})},setOpacity:function(e){e=e===undefined?1:e;var t=["circle","text"];u.each(t,function(t){this.get(t).attr({opacity:e})},this)},remove:function(){this.removeKeys(["circle"],["text"]);var e=this.get("text");e&&e.remove(),this.gitVisuals.removeVisNode(this)},removeAll:function(){this.remove(),u.each(this.get("outgoingEdges"),function(e){e.remove()},this)},getExplodeStepFunc:function(){var e=this.get("circle"),t=20,n=Math.PI+Math.random()*1*Math.PI,r=.2,i=.01,s=t*Math.cos(n),o=t*Math.sin(n),u=e.attr("cx"),a=e.attr("cy"),f=this.gitVisuals.paper.width,l=this.gitVisuals.paper.height,c=.8,h=1,p=function(){o+=r*h-i*o,s-=i*s,u+=s*h,a+=o*h;if(u<0||u>f)s=c*-s,u=u<0?0:f;if(a<0||a>l)o=c*-o,a=a<0?0:l;return e.attr({cx:u,cy:a}),s*s+o*o<.01&&Math.abs(a-l)===0?!1:!0};return p},genGraphics:function(){var e=this.gitVisuals.paper,t=this.getScreenCoords(),n=this.getTextScreenCoords(),r=e.circle(t.x,t.y,this.getRadius()).attr(this.getAttributes().circle),i=e.text(n.x,n.y,String(this.get("id")));i.attr({"font-size":this.getFontSize(this.get("id")),"font-weight":"bold","font-family":"Monaco, Courier, font-monospace",opacity:this.getOpacity()}),this.set("circle",r),this.set("text",i),this.attachClickHandlers()}});n.VisNode=c}),e.define("/src/js/visuals/visBase.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({removeKeys:function(e){u.each(e,function(e){this.get(e)&&this.get(e).remove()},this)},getNonAnimateKeys:function(){return["stroke-dasharray"]},getIsInOrigin:function(){return this.get("gitEngine")?this.get("gitEngine").isOrigin():!1},animateToAttr:function(e,t,n){if(t===0){this.setAttr(e,!0);return}var r=t!==undefined?t:this.get("animationSpeed"),i=n||this.get("animationEasing");this.setAttr(e,!1,r,i)},setAttrBase:function(e,t,n,r,i){u.each(e,function(e){n?this.get(e).attr(t[e]):(this.get(e).stop(),this.get(e).animate(t[e],r,i),u.forEach(this.getNonAnimateKeys(),function(n){t[e]&&t[e][n]!==undefined&&this.get(e).attr(n,t[e][n])},this)),t.css&&$(this.get(e).node).css(t.css)},this)},animateAttrKeys:function(e,t,n,r){e=u.extend({},{include:["circle","arrow","rect","path","text"],exclude:[]},e||{});var i=this.getAttributes();u.each(e.include,function(e){i[e]=u.extend({},i[e],t)}),u.each(e.exclude,function(e){delete i[e]}),this.animateToAttr(i,n,r)}});n.VisBase=f}),e.define("/src/js/visuals/visBranch.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=function(){var e=Math.random(),t="hsb("+String(e)+",0.7,1)";return t},h=l.extend({defaults:{pos:null,text:null,rect:null,arrow:null,isHead:!1,flip:1,fill:f.rectFill,stroke:f.rectStroke,"stroke-width":f.rectStrokeWidth,offsetX:f.nodeRadius*4.75,offsetY:0,arrowHeight:14,arrowInnerSkew:0,arrowEdgeHeight:6,arrowLength:14,arrowOffsetFromCircleX:10,vPad:5,hPad:5,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing},validateAtInit:function(){if(!this.get("branch"))throw new Error("need a branch!")},getID:function(){return this.get("branch").get("id")},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine");if(!this.gitEngine)throw new Error("asd wtf");this.get("branch").set("visBranch",this);var e=this.get("branch").get("id");e=="HEAD"?(this.set("isHead",!0),this.set("flip",-1),this.refreshOffset(),this.set("fill",f.headRectFill)):e!=="master"&&this.set("fill",c())},getCommitPosition:function(){var e=this.gitEngine.getCommitFromRef(this.get("branch")),t=e.get("visNode");return this.set("flip",this.getFlipValue(e,t)),this.refreshOffset(),t.getScreenCoords()},getFlipValue:function(e,t){var n=this.get("gitVisuals").getFlipPos(),r=t.get("pos").x>n;return e.get("id")==="C0"?-1:this.get("isHead")?r?this.isBranchStackEmpty()?-1:1:this.isBranchStackEmpty()?1:-1:r?-1:1},refreshOffset:function(){var e=f.nodeRadius*4.75,t=33,n=10;this.get("flip")===1?(this.set("offsetY",-t),this.set("offsetX",e-n)):(this.set("offsetY",t),this.set("offsetX",e-n))},getArrowTransform:function(){return this.get("flip")===1?"t-2,-20R-35":"t2,20R-35"},getBranchStackIndex:function(){if(this.get("isHead"))return 0;var e=this.getBranchStackArray(),t=-1;return u.each(e,function(e,n){e.obj==this.get("branch")&&(t=n)},this),t},getBranchStackLength:function(){return this.get("isHead")?1:this.getBranchStackArray().length},isBranchStackEmpty:function(){var e=this.gitVisuals.branchStackMap[this.getCommitID()];return e?e.length===0:!0},getCommitID:function(){var e=this.get("branch").get("target");return e.get("type")==="branch"&&(e=e.get("target")),e.get("id")},getBranchStackArray:function(){var e=this.gitVisuals.branchStackMap[this.getCommitID()];return e===undefined?(this.gitVisuals.calcBranchStacks(),this.getBranchStackArray()):e},getTextPosition:function(){var e=this.getCommitPosition(),t=this.getBranchStackIndex();return{x:e.x+this.get("flip")*this.get("offsetX"),y:e.y+t*f.multiBranchY+this.get("offsetY")}},getRectPosition:function(){var e=this.getTextPosition(),t=this.get("flip"),n=this.getTextSize();return{x:e.x-.5*n.w-this.get("hPad"),y:e.y-.5*n.h-this.get("vPad")}},getArrowPath:function(){var e=function(e,t,n){return{x:e.x+t,y:e.y+n}},t=function(e){return String(Math.round(e.x))+","+String(Math.round(e.y))},n=this.get("flip"),r=e(this.getCommitPosition(),n*this.get("arrowOffsetFromCircleX"),0),i=e(r,n*this.get("arrowLength"),-this.get("arrowHeight")),s=e(r,n*this.get("arrowLength"),this.get("arrowHeight")),o=e(i,n*this.get("arrowInnerSkew"),this.get("arrowEdgeHeight")),a=e(s,n*this.get("arrowInnerSkew"),-this.get("arrowEdgeHeight")),f=49,l=e(o,n*f,0),c=e(a,n*f,0),h="";h+="M"+t(l)+" ";var p=[o,i,r,s,a,c];return u.each(p,function(e){h+="L"+t(e)+" "},this),h+="z",h},getTextSize:function(){var e=function(e){var t=e.get("text")?e.get("text").node:null;return t===null?0:t.clientWidth},t=function(e){return e.w||(e.w=75),e.h||(e.h=20),e},n=this.get("text").node;if(this.get("isHead"))return t({w:n.clientWidth,h:n.clientHeight});var r=0;return u.each(this.getBranchStackArray(),function(t){r=Math.max(r,e(t.obj.get("visBranch")))}),t({w:r,h:n.clientHeight})},getSingleRectSize:function(){var e=this.getTextSize(),t=this.get("vPad"),n=this.get("hPad");return{w:e.w+t*2,h:e.h+n*2}},getRectSize:function(){var e=this.getTextSize(),t=this.get("vPad"),n=this.get("hPad"),r=this.getBranchStackLength();return{w:e.w+t*2,h:e.h*r*1.1+n*2}},getIsRemote:function(){return this.get("branch").getIsRemote()},getName:function(){var e=this.get("branch").getName(),t=this.get("branch")===this.gitEngine.HEAD.get("target"),n=this.getIsRemote(),r=t&&!this.getIsInOrigin()&&!n?"*":"";return e+r},nonTextToFront:function(){this.get("arrow").toFront(),this.get("rect").toFront()},textToFront:function(){this.get("text").toFront()},textToFrontIfInStack:function(){this.getBranchStackIndex()!==0&&this.get("text").toFront()},getFill:function(){return this.get("isHead")||this.getBranchStackLength()==1||this.getBranchStackIndex()!==0?this.get("fill"):this.gitVisuals.blendHuesFromBranchStack(this.getBranchStackArray())},remove:function(){this.removeKeys(["text","arrow","rect"]),this.gitVisuals.removeVisBranch(this)},genGraphics:function(e){var t=this.getTextPosition(),n=this.getName(),r;r=e.text(t.x,t.y,String(n)),r.attr({"font-size":14,"font-family":"Monaco, Courier, font-monospace",opacity:this.getTextOpacity()}),this.set("text",r);var i=this.getAttributes(),s=this.getRectPosition(),o=this.getRectSize(),a=e.rect(s.x,s.y,o.w,o.h,8).attr(i.rect);this.set("rect",a);var f=this.getArrowPath(),l=e.path(f).attr(i.arrow);this.set("arrow",l);var c=["text","rect","arrow"];u.each(c,function(e){$(this.get(e).node).css(i.css)},this),this.attachClickHandlers(),a.toFront(),r.toFront()},attachClickHandlers:function(){if(this.get("gitVisuals").options.noClick)return;var e=[this.get("rect"),this.get("text"),this.get("arrow")];u.each(e,function(e){e.click(u.bind(this.onClick,this))},this)},shouldDisableClick:function(){return this.get("isHead")&&!this.gitEngine.getDetachedHead()},onClick:function(){if(this.shouldDisableClick())return;var t="git checkout "+this.get("branch").get("id"),n=e("../app");n.getEventBaton().trigger("commandSubmitted",t)},updateName:function(){this.get("text").attr({text:this.getName()})},getNonTextOpacity:function(){return this.get("isHead")?this.gitEngine.getDetachedHead()?1:0:this.getBranchStackIndex()===0?1:0},getTextOpacity:function(){return this.get("isHead")?this.gitEngine.getDetachedHead()?1:0:1},getAttributes:function(){var e=this.getNonTextOpacity(),t=this.getTextOpacity();this.updateName();var n=this.getTextPosition(),r=this.getRectPosition(),i=this.getRectSize(),s=this.getArrowPath(),o=this.getIsInOrigin()?f.originDash:"",u=this.shouldDisableClick()?"auto":"pointer";return{css:{cursor:u},text:{x:n.x,y:n.y,opacity:t},rect:{x:r.x,y:r.y,width:i.w,height:i.h,opacity:e,fill:this.getFill(),stroke:this.get("stroke"),"stroke-width":this.get("stroke-width")},arrow:{path:s,opacity:e,fill:this.getFill(),stroke:this.get("stroke"),transform:this.getArrowTransform(),"stroke-width":this.get("stroke-width")}}},animateUpdatedPos:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},setAttr:function(e,t,n,r){var i=["text","rect","arrow"];this.setAttrBase(i,e,t,n,r)}}),p=a.Collection.extend({model:h});n.VisBranchCollection=p,n.VisBranch=h,n.randomHueString=c}),e.define("/src/js/visuals/visEdge.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=l.extend({defaults:{tail:null,head:null,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing},validateAtInit:function(){var e=["tail","head"];u.each(e,function(e){if(!this.get(e))throw new Error(e+" is required!")},this)},getID:function(){return this.get("tail").get("id")+"."+this.get("head").get("id")},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine"),this.get("tail").get("outgoingEdges").push(this)},remove:function(){this.removeKeys(["path"]),this.gitVisuals.removeVisEdge(this)},genSmoothBezierPathString:function(e,t){var n=e.getScreenCoords(),r=t.getScreenCoords();return this.genSmoothBezierPathStringFromCoords(n,r)},genSmoothBezierPathStringFromCoords:function(e,t){var n=function(e){return String(Math.round(e.x))+","+String(Math.round(e.y))},r=function(e,t,n){return n=n||f.curveControlPointOffset,{x:e.x,y:e.y+n*t}},i=function(e,t,n){return{x:e.x+t,y:e.y+n}};e=r(e,-1,this.get("tail").getRadius()),t=r(t,1,this.get("head").getRadius());var s="";s+="M"+n(e)+" ",s+="C",s+=n(r(e,-1))+" ",s+=n(r(t,1))+" ",s+=n(t);var o=f.arrowHeadSize||10;return s+=" L"+n(i(t,-o,o)),s+=" L"+n(i(t,o,o)),s+=" L"+n(t),s+="C",s+=n(r(t,1))+" ",s+=n(r(e,-1))+" ",s+=n(e),s},getBezierCurve:function(){return this.genSmoothBezierPathString(this.get("tail"),this.get("head"))},getStrokeColor:function(){return f.visBranchStrokeColorNone},setOpacity:function(e){e=e===undefined?1:e,this.get("path").attr({opacity:e})},genGraphics:function(e){var t=this.getBezierCurve(),n=e.path(t).attr({"stroke-width":f.visBranchStrokeWidth,stroke:this.getStrokeColor(),"stroke-linecap":"round","stroke-linejoin":"round",fill:this.getStrokeColor()});n.toBack(),this.set("path",n)},getOpacity:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("tail")),t={branch:1,head:f.edgeUpstreamHeadOpacity,none:f.edgeUpstreamNoneOpacity};if(t[e]===undefined)throw new Error("bad stat");return t[e]},getAttributes:function(){var e=this.getBezierCurve(),t=this.getOpacity();return{path:{path:e,opacity:t}}},animateUpdatedPath:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},animateToAttr:function(e,t,n){if(t===0){this.get("path").attr(e.path);return}this.get("path").toBack(),this.get("path").stop(),this.get("path").animate(e.path,t!==undefined?t:this.get("animationSpeed"),n||this.get("animationEasing"))}}),h=a.Collection.extend({model:c});n.VisEdgeCollection=h,n.VisEdge=c}),e.define("/src/js/level/disabledMap.js",function(e,t,n,r,i,s,o){function h(e){e=e||{},this.disabledMap=e.disabledMap||{"git cherry-pick":!0,"git rebase":!0}}var u=e("underscore"),a=e("../intl"),f=e("../git/commands"),l=e("../util/errors"),c=l.GitError;h.prototype.getInstantCommands=function(){var e=[],t=function(){throw new c({msg:a.str("command-disabled")})};return u.each(this.disabledMap,function(n,r){var i=f.regexMap[r];if(!i)throw new Error("wuttttt this disbaled command"+r+" has no regex matching");e.push([i,t])}),e},n.DisabledMap=h}),e.define("/src/js/dialogs/confirmShowSolution.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Are you sure you want to see the solution?","","I believe in you! You can do it"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 确定要看答案吗?","","哥相信你!你可以的"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Êtes-vous sûr de vouloir voir la solution ?","","Je crois en vous ! Vous pouvez le faire"]}}]}}),e.define("/src/js/level/arbiter.js",function(e,t,n,r,i,s,o){function h(){this.levelMap={},this.levelSequences=f,this.sequences=[],this.init();var e;try{e=JSON.parse(localStorage.getItem("solvedMap")||"{}")}catch(t){console.warn("local storage failed",t)}this.solvedMap=e||{},c.getEvents().on("levelSolved",this.levelSolved,this)}var u=e("underscore"),a=e("backbone"),f=e("../../levels").levelSequences,l=e("../../levels").sequenceInfo,c=e("../app");h.prototype.init=function(){var e;u.each(this.levelSequences,function(e,t){this.sequences.push(t);if(!e||!e.length)throw new Error("no empty sequences allowed");u.each(e,function(e,n){this.validateLevel(e);var r=t+String(n+1),i=u.extend({},e,{index:n,id:r,sequenceName:t});this.levelMap[r]=i,this.levelSequences[t][n]=i},this)},this)},h.prototype.isLevelSolved=function(e){if(!this.levelMap[e])throw new Error("that level doesnt exist!");return Boolean(this.solvedMap[e])},h.prototype.levelSolved=function(e){if(!e)return;this.solvedMap[e]=!0,this.syncToStorage()},h.prototype.resetSolvedMap=function(){this.solvedMap={},this.syncToStorage(),c.getEvents().trigger("levelSolved")},h.prototype.syncToStorage=function(){try{localStorage.setItem("solvedMap",JSON.stringify(this.solvedMap))}catch(e){console.warn("local storage fialed on set",e)}},h.prototype.validateLevel=function(e){e=e||{};var t=["name","goalTreeString","solutionCommand"],n=["hint","disabledMap","startTree"];u.each(t,function(t){if(e[t]===undefined)throw console.log(e),new Error("I need this field for a level: "+t)})},h.prototype.getSequenceToLevels=function(){return this.levelSequences},h.prototype.getSequences=function(){return u.keys(this.levelSequences)},h.prototype.getLevelsInSequence=function(e){if(!this.levelSequences[e])throw new Error("that sequecne name "+e+"does not exist");return this.levelSequences[e]},h.prototype.getSequenceInfo=function(e){return l[e]},h.prototype.getLevel=function(e){return this.levelMap[e]},h.prototype.getNextLevel=function(e){if(!this.levelMap[e])return console.warn("that level doesnt exist!!!"),null;var t=this.levelMap[e],n=t.sequenceName,r=this.levelSequences[n],i=t.index+1;if(i master -> C1",""],afterMarkdowns:["And now it's","","HEAD -> C1"],command:"git checkout C1",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["To complete this level, let's detach HEAD from `bugFix` and attach it to the commit instead.","","Specify this commit by its hash. The hash for each commit is displayed on the circle that represents the commit."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 在Git中前后移动","","在接触Git的更多高级主题之前,我们先学习用不同的方法在代表你的项目的提交记录树上前后移动。","","一旦能够熟练地在Git中前进后退,你使用其他git命令的威力也会被放大!","","","","",""]}},{type:"ModalAlert",options:{markdowns:["## HEAD","",'我们首先看一下"HEAD". HEAD是当前提交记录的符号名称 -- 其实就是你正在其基础进行工作的提交记录。',"","HEAD总是指向最近一次提交记录,表现为当前工作树。大多数修改工作树的git命令都开始于改变HEAD指向。","","HEAD通常指向分支名(比如bugFix)。你提交时,改变了bugFix的状态,这一变化通过HEAD变得可见。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["在实例中看一下。我们将会观察提交前后HEAD的位置。"],afterMarkdowns:["看! HEAD一直藏在`master`分支后面。"],command:"git checkout C1; git checkout master; git commit; git checkout C2",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["### 分离 HEAD","","分离HEAD就是让其指向一个提交记录而不是分支名。这是命令执行之前的样子: ","","HEAD -> master -> C1",""],afterMarkdowns:["现在变成了","","HEAD -> C1"],command:"git checkout C1",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["想完成此关,从`bugFix`分离出HEAD并让其指向一个提交记录。","","通过hash值指定提交记录。每个提交记录的hash值显示在代表提交记录的圆圈中。"]}}]}}}}),e.define("/levels/rampup/relativeRefs.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"C3","id":"HEAD"}}',solutionCommand:"git checkout bugFix^",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Relative Refs (^)",zh_CN:"相对引用(^)"},hint:{en_US:"Remember the Caret (^) operator!",zh_CN:"记住插入(^)操作符!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Relative Refs","","Moving around in Git by specifying commit hashes can get a bit tedious. In the real world you won't have a nice commit tree visualization next to your terminal, so you'll have to use `git log` to see hashes.","","Furthermore, hashes are usually a lot longer in the real Git world as well. For instance, the hash of the commit that introduced the previous level is `fed2da64c0efc5293610bdd892f82a58e8cbc5d8`. Doesn't exactly roll off the tongue...","","The upside is that Git is smart about hashes. It only requires you to specify enough characters of the hash until it uniquely identifies the commit. So I can type `fed2` instead of the long string above."]}},{type:"ModalAlert",options:{markdowns:["Like I said, specifying commits by their hash isn't the most convenient thing ever, which is why Git has relative refs. They are awesome!","","With relative refs, you can start somewhere memorable (like the branch `bugFix` or `HEAD`) and work from there.","","Relative commits are powerful, but we will introduce two simple ones here:","","* Moving upwards one commit at a time with `^`","* Moving upwards a number of times with `~`"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's look at the Caret (^) operator first. Each time you append that to a ref name, you are telling Git to find the parent of the specified commit.","",'So saying `master^` is equivalent to "the first parent of `master`".',"","`master^^` is the grandparent (second-generation ancestor) of `master`","","Let's check out the commit above master here"],afterMarkdowns:["Boom! Done. Way easier than typing the commit hash"],command:"git checkout master^",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["You can also reference `HEAD` as a relative ref. Let's use that a couple of times to move upwards in the commit tree"],afterMarkdowns:["Easy! We can travel backwards in time with `HEAD^`"],command:"git checkout C3; git checkout HEAD^; git checkout HEAD^; git checkout HEAD^",beforeCommand:"git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["To complete this level, check out the parent commit of `bugFix`. This will detach `HEAD`.","","You can specify the hash if you want, but try using relative refs instead!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 相对引用","","用指定提交记录hash值的方式在Git中移动会变得比较乏味。在现实中,你不会有漂亮的可视化的提交记录树放在终端旁边,所以你不得不用`git log`来查看hasn值。","","另外,hash值在真实的Git环境中也会更长。举个例子,前一关的介绍中的提交记录的hash值是`fed2da64c0efc5293610bdd892f82a58e8cbc5d8`。不要把舌头闪了...","","好的一面是,Git对hash的处理很智能。你只需要提供能够唯一标识提交记录的前几个字符即可。所以,我可以仅输入`fed2`而不是上面的一长串字符。"]}},{type:"ModalAlert",options:{markdowns:["我说过,通过hash指定提交记录不是很方便,所以Git引入了相对引用。这个就很牛掰了!","","使用相对引用,你可以从一个易于记忆的地方(比如分支名`bugFix`或`HEAD`)开始工作。","","相对引用非常给力,这里我介绍两个简单的用法:","","* 使用`^`向上移动1个提交记录","* 使用`~`向上移动多个提交记录"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["首先看看插入(^)操作符。把插入符跟在引用名后面,表示让Git寻找指定提交记录的父提交。","",'所以`master^`相当于"`master`的父提交"。',"","`master^^`是`master`的父父提交(上上代祖先)","","切换到master的父提交"],afterMarkdowns:["唰!搞定。这种方式比输入提交记录的hash值简单多了!"],command:"git checkout master^",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["你也可以`HEAD`把用作相对引用。以下命令使用`HEAD`在提交树中向上移动几次。"],afterMarkdowns:["简单!我们可以一直使用`HEAD^`向上移动。"],command:"git checkout C3; git checkout HEAD^; git checkout HEAD^; git checkout HEAD^",beforeCommand:"git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["要完成此关,切换到`bugFix`的父提交。这会分离出`HEAD`.","","如果你愿意的话,使用hash值也可以过关,但为何不试试使用相对引用呢?"]}}]}}}}),e.define("/levels/rampup/relativeRefs2.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C6","id":"master"},"bugFix":{"target":"C0","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C5":{"parents":["C3"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"C1","id":"HEAD"}}',solutionCommand:"git branch -f master C6;git checkout HEAD~1;git branch -f bugFix HEAD~1",startTree:'{"branches":{"master":{"target":"C4","id":"master"},"bugFix":{"target":"C5","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C5":{"parents":["C3"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"C2","id":"HEAD"}}',hint:{en_US:"You'll need to use at least one direct reference (hash) to complete this level",zh_CN:"这一关至少要用到一次直接引用(hash)"},name:{en_US:"Relative Refs #2 (~)",zh_CN:"相对引用2(~)"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:['### The "~" operator',"","Say you want to move a lot of levels up in the commit tree. It might be tedious to type `^` several times, so Git also has the tilde (~) operator.","","","The tilde operator (optionally) takes in a trailing number that specifies the number of parents you would like to ascend. Let's see it in action"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's specify a number of commits back with `~`."],afterMarkdowns:["Boom! So concise -- relative refs are great."],command:"git checkout HEAD~4",beforeCommand:"git commit; git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["### Branch forcing","","You're an expert on relative refs now, so let's actually *use* them for something.","","One of the most common ways I use relative refs is to move branches around. You can directly reassign a branch to a commit with the `-f` option. So something like:","","`git branch -f master HEAD~3`","","Moves (by force) the master branch to three parents behind HEAD."]}},{type:"ModalAlert",options:{markdowns:["To complete this level, move `HEAD`, `master`, and `bugFix` to their goal destinations shown."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:['### The "~" operator',"","假设需要在提交树中向上移动很多步。使用多个`^`非常无聊,所以Git也引入了波浪(~)操作符。","","","波浪操作符后面可以(可选地)跟一个数字,指定向上移动多少次。看个例子"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用`~`一次后退多步."],afterMarkdowns:["唰!如此简洁--相对引用就是好啊!"],command:"git checkout HEAD~4",beforeCommand:"git commit; git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["### Branch forcing","","你现在是相对引用的高手了,现在*用*他来实际做点事情。","","我使用相对引用最多的就是移动分支。你可以使用`-f`选项把直接让分支指向另一个提交。举个例子:","","`git branch -f master HEAD~3`","","(强制)移动master指向HEAD的第3级父提交。"]}},{type:"ModalAlert",options:{markdowns:["要完成此关,移动`HEAD`,`master`和`bugFix`到目标所示的位置。"]}}]}}}}),e.define("/levels/rampup/reversingChanges.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22master%22%7D%2C%22pushed%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22pushed%22%7D%2C%22local%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22local%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C2%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22pushed%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git reset HEAD~1;git checkout pushed;git revert HEAD",compareOnlyBranches:!0,startTree:'{"branches":{"master":{"target":"C1","id":"master"},"pushed":{"target":"C2","id":"pushed"},"local":{"target":"C3","id":"local"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"}},"HEAD":{"target":"local","id":"HEAD"}}',name:{en_US:"Reversing Changes in Git",ja:"変更を元に戻す",fr_FR:"Annuler des changements avec Git",ko:"Git에서 작업 되돌리기",zh_CN:"在Git中撤销更改"},hint:{en_US:"Notice that revert and reset take different arguments.",fr_FR:"",zh_CN:"注意revert和reset使用不同的参数。",ko:"",ja:""},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Reversing Changes in Git","","There are many ways to reverse changes in Git. And just like committing, reversing changes in Git has both a low-level component (staging individual files or chunks) and a high-level component (how the changes are actually reversed). Our application will focus on the latter.","","There are two primary ways to undo changes in Git -- one is using `git reset` and the other is using `git revert`. We will look at each of these in the next dialog",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","",'`git reset` reverts changes by moving a branch reference backwards in time to an older commit. In this sense you can think of it as "rewriting history;" `git reset` will move a branch backwards as if the commit had never been made in the first place.',"","Let's see what that looks like:"],afterMarkdowns:["Nice! Git simply moved the master branch reference back to `C1`; now our local repository is in a state as if `C2` had never happened"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","",'While reseting works great for local branches on your own machine, its method of "rewriting history" doesn\'t work for remote branches that others are using.',"","In order to reverse changes and *share* those reversed changes with others, we need to use `git revert`. Let's see it in action"],afterMarkdowns:["Weird, a new commit plopped down below the commit we wanted to reverse. That's because this new commit `C2'` introduces *changes* -- it just happens to introduce changes that exactly reverses the commit of `C2`.","","With reverting, you can push out your changes to share with others."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["To complete this level, reverse the two most recent commits on both `local` and `pushed`.","","Keep in mind that `pushed` is a remote branch and `local` is a local branch -- that should help you choose your methods."]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## 変更を元に戻す","","Gitでは変更を元に戻す方法がたくさんあります。コミットと同じように、低レベルな動作(ファイル別だったりファイルの中の一部だったり)も高レベルな動作(変更のまとまりのキャンセル)もできます。このアプリケーションでは後者の方法について紹介します。","","基本的なアンドゥの方法が2つあります - 一つは`git reset`を使う方法で、もう1つは`git revert`を使う方法です。次のダイアログで一つ一つを見ていきます。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","","`git reset`はブランチのポインタを後方に移動することで変更のキャンセルを実現します。履歴を上書きするような動作だと思うと良いでしょうか:`git reset`はそもそも前のコミットなんかなかったかのように、ブランチのポインタを元に戻してくれます。","","どういう感じか見てみましょう。"],afterMarkdowns:["いいですね!Gitは単純にmasterブランチへのポインタを`C1`へ戻しました。これでこのローカルリポジトリにはまるで`C2`なんて無かったかのように変更をキャンセルできました。"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","自分のマシン上のブランチではさっきの`git reset`でうまくいきましたが、この「履歴を上書きする」手段は、他の人も使っているリモートにあるリポジトリに対しては使うことができません。","","変更を巻き戻して他の人とそれを共有するためには、`git revert`を使う必要があります。今度はこれを見てみましょう。"],afterMarkdowns:["あれ、おかしいな。巻き戻したいと思ってたコミットの下に新しいコミットが出来上がってしまったみたいです。なぜか。これは、この新しい`C2'`コミットは`C2`へ戻すのに必要な内容を確かに変更して巻き戻していたのです。","","こんな風にして、巻き戻した内容を他人と共有するためにはrevertを使います。"],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["この章の仕上げに、`local`と`pushed`の両方の直近のコミットを巻き戻してみましょう。","","`pushed`はリモートのブランチで、`local`はローカルであることに注意。正しくコマンドを使い分けましょう。"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Annuler des changements avec Git","","Il y a de nombreuses façons d'annuler des changement avec Git. De même que pour les commits, annuler des changements avec Git a à la fois un aspect bas-niveau (gestion dans le 'staging' des fichiers et morceaux de fichiers) et un aspect de plus haut niveau 9comment les changements sont effectivement annulés). Nous allons nous intéresser à ce dernier point.","","Il y a principalement deux façons d'annuler des changements avec Git -- l'une est `git reset` et l'autre est `git revert`. Nous allons maintenant voir chacune de ces façons",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","","`git reset` annule des changements en déplaçant la référence en arrière dans le temps sur un commit plus ancien. En ce sens, on peut considérer cela comme une façon de \"réécrire l'histoire\"; `git reset` fait remonter une branche en arrière comme si le(s) commit(s) n'avait jamais eu lieu.","","Regardons à quoi cela ressemble :"],afterMarkdowns:["Bravo ! Git a simplement déplacé la référence de la branche master en la faisant revenir sur `C1`; désormais notre dépôt est dans le même état que si `C2` n'avait jamais eu lieu"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","Bien que le reset marche parfaitement pour les branches locales sur notre propre machine, cette façon de \"réécrire l'histoire\" ne marche pas avec les banches distantes (remote) que d'autres personnes utilisent.","","Pour pouvoir annuler des changements et *partager* ces annulations avec d'autres, nous devons utiliser `git revert`. Regardons comment cela fonctionne"],afterMarkdowns:["Étrangement, un nouveau commit est appaaru en bas sous le commit que nous voulions annuler. C'est parce que ce nouveau commit `C2'` introduit des *modifications* -- celles qui correspondent justement à l'annulation de celles du commit `C2`.","","Avec revert, vous pouvez diffuser (push) vos modifications et les partager avec tout le monde."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["Pour accomplir ce niveau, annulez les deux derniers commits à la fois sur `local` et sur `pushed`.","","Ayez à l'esprit que `pushed` est une branche distante et `local` est une branche locale -- cela devrait vous guider dans le choix de la méthode à employer."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 撤销 Git 里面的变动","","在 Git 里撤销修改的方法很多。和 commit 一样,在 Git 里撤销变动同时具有底层部分(暂存一些独立的文件或者片段)和高层部分(具体到变动是究竟怎么被撤销的)。我们这个应用主要关注后者。","","在 Git 里主要用两种方法来撤销变动 —— 一种是 `git reset`,另外一种是 `git revert`。让我们在下一个窗口逐一了解它们。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","",'`git reset`把分支记录回退到上一个提交记录来实现撤销改动。你可以认为这是在"重写历史"。`git reset`往回移动分支,原来指向的提交记录好像重来没有提交过一样。',"","让我们看看具体的操作:"],command:"git reset HEAD~1",afterMarkdowns:["Nice!Git把master分支的指向简单地移回到`C1`;现在我们的本地代码库处于没有提交过`C2`的状态了。"],beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","虽然在你的本地分支中使用`git reset`很方便,但是这种“改写历史”的方法对别人的远端分支是无效的哦!","","为了撤销更改并*传播*给别人,我们需要使用`git revert`。举个例子"],command:"git revert HEAD",afterMarkdowns:["怪哉!在我们要撤销的提交记录后面居然多了一个新提交!这是因为新提交记录`C2'`引入了*更改*——刚好是用来撤销 `C2` 这个提交的。","","借助 revert,现在可以把你的更改传递给别人啦。"],beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["要完成此关,分别撤销`local`分支和`pushed`分支上的最近一次提交。","","记住 `pushed` 是一个远程分支,`local` 是一个本地分支 —— 有了这么明显的提示应该知道用哪种方法了吧?"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git에서 작업 되돌리기","","Git에는 작업한 것을 되돌리는 여러가지 방법이 있습니다. 변경내역을 되돌리는 것도 커밋과 마찬가지로 낮은 수준의 일(개별 파일이나 묶음을 스테이징 하는 것)과 높은 수준의 일(실제 변경이 복구되는 방법)이 있는데요, 여기서는 후자에 집중해 알려드릴게요.","","Git에서 변경한 내용을 되돌리는 방법은 크게 두가지가 있습니다 -- 하나는 `git reset`을 쓰는거고, 다른 하나는 `git revert`를 사용하는 것입니다. 다음 화면에서 하나씩 알아보겠습니다.",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git 리셋(reset)","",'`git reset`은 브랜치로 하여금 예전의 커밋을 가리키도록 이동시키는 방식으로 변경 내용을 되돌립니다. 이런 관점에서 "히스토리를 고쳐쓴다"라고 말할 수 있습니다. 즉, `git reset`은 마치 애초에 커밋하지 않은 것처럼 예전 커밋으로 브랜치를 옮기는 것입니다.',"","어떤 그림인지 한번 보죠:"],afterMarkdowns:["그림에서처럼 master 브랜치가 가리키던 커밋을 `C1`로 다시 옮겼습니다; 이러면 로컬 저장소에는 마치 `C2`커밋이 아예 없었던 것과 마찬가지 상태가 됩니다."],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git 리버트(revert)","",'각자의 컴퓨터에서 작업하는 로컬 브랜치의 경우 리셋(reset)을 잘 쓸 수 있습니다만, "히스토리를 고쳐쓴다"는 점 때문에 다른 사람이 작업하는 리모트 브랜치에는 쓸 수 없습니다.',"","변경분을 되돌리고, 이 되돌린 내용을 다른 사람들과 *공유하기* 위해서는, `git revert`를 써야합니다. 예제로 살펴볼게요."],afterMarkdowns:["어색하게도, 우리가 되돌리려고한 커밋의 아래에 새로운 커밋이 생겼습니다. `C2`라는 새로운 커밋에 *변경내용*이 기록되는데요, 이 변경내역이 정확히 `C2` 커밋 내용의 반대되는 내용입니다.","","리버트를 하면 다른 사람들에게도 변경 내역을 밀어(push) 보낼 수 있습니다."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["이 레벨을 통과하려면, `local` 브랜치와 `pushed` 브랜치에 있는 최근 두 번의 커밋을 되돌려 보세요.","","`pushed`는 리모트 브랜치이고, `local`은 로컬 브랜치임을 신경쓰셔서 작업하세요 -- 어떤 방법을 선택하실지 떠오르시죠?"]}}]}}}}),e.define("/levels/rebase/manyRebases.js",function(e,t,n,r,i,s,o){n.level={compareOnlyMasterHashAgnostic:!0,disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22master%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22bugFix%22%7D%2C%22side%22%3A%7B%22target%22%3A%22C6%27%22%2C%22id%22%3A%22side%22%7D%2C%22another%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22another%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C6%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C6%22%7D%2C%22C7%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C7%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C6%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C6%27%22%7D%2C%22C7%27%22%3A%7B%22parents%22%3A%5B%22C6%27%22%5D%2C%22id%22%3A%22C7%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout bugFix;git rebase master;git checkout side;git rebase bugFix;git checkout another;git rebase side;git rebase another master",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C3","id":"bugFix"},"side":{"target":"C6","id":"side"},"another":{"target":"C7","id":"another"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C0"],"id":"C4"},"C5":{"parents":["C4"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"},"C7":{"parents":["C5"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Rebasing over 9000 times",ko:"9천번이 넘는 리베이스",ja:"Rebasing over 9000 times",zh_CN:"N次Rebase"},hint:{en_US:"Remember, the most efficient way might be to only update master at the end...",ja:"最も効率的なやり方はmasterを最後に更新するだけかもしれない・・・",ko:"아마도 master를 마지막에 업데이트하는 것이 가장 효율적인 방법일 것입니다...",zh_CN:"记住,最后更新master分支可能是最高效的方法。"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["### Rebasing Multiple Branches","","Man, we have a lot of branches going on here! Let's rebase all the work from these branches onto master.","","Upper management is making this a bit trickier though -- they want the commits to all be in sequential order. So this means that our final tree should have `C7'` at the bottom, `C6'` above that, etc etc, etc all in order.","","If you mess up along the way, feel free to use `reset` to start over again. Be sure to check out our solution and see if you can do it in fewer commands!"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["### 複数のブランチをリベースする","","さあ、いくつものブランチが出てきます。このブランチたち全てをmasterブランチにリベースしましょう。","","おエライさん方が今回の仕事を少しトリッキーにしてくれました ― コミットはすべて一列のシーケンシャルな状態にしてほしいそうです。つまり私たちが作るリポジトリの最終的なツリーの状態は、`C7'`が最後に来て、`C6'`がその一つ上に来て、、と順に積み重なるイメージです。","","試行錯誤してツリーが汚くなってきたら、`reset`コマンドを使ってツリーの状態を初期化してください。模範解答をチェックして、それよりも簡単なコマンドで済ませられるかどうか、を考えるのも忘れずに!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["### 多分支衍合","","呐,现在我们有很多分支啦!让我们rebase这些分支的工作到 master 分支上吧。","","但是你的头头找了点麻烦 —— 他们希望得到有序的提交历史,也就是我们最终的结果是 `C7'` 在最底部,`C6'` 在它上面,以此类推。","","假如你搞砸了,没所谓的(虽然我不会告诉你用 `reset` 可以重新开始)。记得看看我们提供的答案,看你能否使用更少的命令完成任务!"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["### 여러 브랜치를 리베이스(rebase)하기 ","","음, 여기 꽤 여러개의 브랜치가 있습니다! 이 브랜치들의 모든 작업내역을 master에 리베이스 해볼까요?","","윗선에서 일을 복잡하게 만드네요 -- 그 분들이 이 모든 커밋들을 순서에 맞게 정렬하라고 합니다. 그럼 결국 우리의 최종 목표 트리는 제일 아래에 `C7'` 커밋, 그 위에 `C6'` 커밋, 또 그 위에 순서대로 보여합니다.","","만일 작업중에 내용이 꼬인다면, `reset`이라고 쳐서 처음부터 다시 시작할 수 있습니다. 모범 답안을 확인해 보시고, 혹시 더 적은 수의 커맨드로 해결할 수 있는지 알아보세요!"]}}]}}}}),e.define("/levels/mixed/grabbingOneCommit.js",function(e,t,n,r,i,s,o){n.level={compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C4>e.C1}]},disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22master%22%7D%2C%22debug%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22debug%22%7D%2C%22printf%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22printf%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22bugFix%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout master;git cherry-pick C4",startTree:'{"branches":{"master":{"target":"C1","id":"master"},"debug":{"target":"C2","id":"debug"},"printf":{"target":"C3","id":"printf"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"bugFix","id":"HEAD"}}',name:{ko:"딱 한개의 커밋만 가져오기",en_US:"Grabbing Just 1 Commit",ja:"Grabbing Just 1 Commit",zh_CN:"只取一个提交"},hint:{en_US:"Remember, interactive rebase or cherry-pick is your friend here",ja:"このレベルではインタラクティブモードのrebaseやcherry-pickがクリアのカギです",ko:"대화식 리베이스(rebase -i)나 or 체리픽(cherry-pick)을 사용하세요",zh_CN:"记住,交互式 rebase 或者 cherry-pick 会很有帮助"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Locally stacked commits","","Here's a development situation that often happens: I'm trying to track down a bug but it is quite elusive. In order to aid in my detective work, I put in a few debug commands and a few print statements.","","All of these debugging / print statements are in their own branches. Finally I track down the bug, fix it, and rejoice!","","Only problem is that I now need to get my `bugFix` back into the `master` branch! I could simply fast-forward `master`, but then `master` would get all my debug statements."]}},{type:"ModalAlert",options:{markdowns:["This is where the magic of Git comes in. There are a few ways to do this, but the two most straightforward ways are:","","* `git rebase -i`","* `git cherry-pick`","","Interactive (the `-i`) rebasing allows you to choose which commits you want to keep or discard. It also allows you to reorder commits. This can be helpful if you want to toss out some work.","","Cherry-picking allows you to pick individual commits and plop them down on top of `HEAD`"]}},{type:"ModalAlert",options:{markdowns:["This is a later level so we will leave it up to you to decide, but in order to complete the level, make sure `master` receives the commit that `bugFix` references."]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ローカルに積み上がったコミット","","実際の開発ではこういうケースがよくあります:「バグの原因調査を試みているがバグの再現性がかなり低い。調査の補助のために、いくつかのデバッグ用の命令やprint文を差し込んでいる。」","","これらのデバッグ用のコードはバグ修正用のブランチにコミットされています。そしてついにバグの原因を突き止めて、修正した!やった!","","あとは`bugFix`ブランチを`master`ブランチに統合できればOK。そこで単純に`master`をfast-forwardすればよいかというと、それでは`master`ブランチの中にデバッグ用のコードも混入してしまいます。"]}},{type:"ModalAlert",options:{markdowns:["ここでGitの魔法が力を発揮します。解決のためにはいくつかの方法がありますが、最も素直な解決方法は2つあって:","","* `git rebase -i`","* `git cherry-pick`","","インタラクティブモードの(`-i`オプションつきの)rebaseによって、保持したいコミットと破棄したいコミットを選り分けることができます。コミットの順序を変更することも可能です。この方法は、一部の変更をどこかへやってしまいたい時に便利です。","","もう一方のcherry-pickを使うと、持っていきたいコミットを選んで`HEAD`の先にストンと落とすことができます。"]}},{type:"ModalAlert",options:{markdowns:["後半の章ですのでどう解決するかをもう自分で考えることができると思います。このレベルをクリアするためには、`bugFix`が持っているコミットを`master`ブランチが受け取る必要がある点には注意してください。"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 本地栈式提交 (Locally stacked commits)","","设想一下一个经常发生的场景:我在追踪一个有点棘手的 bug,为了更好地排查,我添加了一些调试命令和打印语句。","","所有的这些调试和打印语句都只在它们自己的分支里。最终我终于找到这个 bug,揪出来 fix 掉,然后撒花庆祝!","","现在唯一的问题就是要把我在 `bugFix` 分支里的工作合并回 `master` 分支。我可以简单地把 `master` 分支快进(fast-forward),但这样的话 `master` 分支就会包含我这些调试语句了。"]}},{type:"ModalAlert",options:{markdowns:["现在就是 Git 大显神通的时候啦。解决这个问题的方法不止一个,但最直接的两个方法是:","","* `git rebase -i`","* `git cherry-pick`","","交互(`-i`)衍合允许你选择哪些提交是要被保留,哪些要被舍弃。它允许你将提交重新排序。假如你要舍弃一些工作,这个会帮上很大的忙。","","Cherry-picking 能让你选择单独一个提交并且把它放到 `HEAD` 的最前端。"]}},{type:"ModalAlert",options:{markdowns:["本关是可选关卡,玩不玩随便你。但是如果你坚持要刷,确保 `master` 分支能拿到 `bugFix` 分支的相关提交(references)。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 로컬에 쌓인 커밋들","","개발중에 종종 이런 상황이 생깁니다: 잘 띄지 않는 버그를 찾아서 해결하려고, 어떤 부분의 문제인지를 찾기 위해 디버그용 코드와 화면에 정보를 프린트하는 코드 몇 줄 넣습니다. ","","디버깅용 코드나 프린트 명령은 그 브랜치에 들어있습니다. 마침내 버그를 찾아서 고쳤고, 원래 작업하는 브랜치에 합치면 됩니다!","","이제 `bugFix`브랜치의 내용을 `master`에 합쳐 넣으려 하지만, 한 가지 문제가 있습니다. 그냥 간단히 `master`브랜치를 최신 커밋으로 이동시킨다면(fast-forward) 그 불필요한 디버그용 코드들도 함께 들어가 버린다는 문제죠."]}},{type:"ModalAlert",options:{markdowns:["여기에서 Git의 마법이 드러납니다. 이 문제를 해결하는 여러가지 방법이 있습니다만, 가장 간단한 두가지 방법 아래와 같습니다:","","* `git rebase -i`","* `git cherry-pick`","","대화형 (-i 옵션) 리베이스(rebase)로는 어떤 커밋을 취하거나 버릴지를 선택할 수 있습니다. 또 커밋의 순서를 바꿀 수도 있습니다. 이 커맨드로 어떤 작업의 일부만 골라내기에 유용합니다.","","체리픽(cherry-pick)은 개별 커밋을 골라서 `HEAD`위에 떨어뜨릴 수 있습니다."]}},{type:"ModalAlert",options:{markdowns:["이번 레벨을 통과하기 위해 어떤 방법을 쓰시든 자유입니다만, `master`브랜치가 `bugFix` 브랜치의 커밋을 일부 가져오게 해주세요."]}}]}}}}),e.define("/levels/mixed/jugglingCommits.js",function(e,t,n,r,i,s,o){n.level={disabledMap:{"git cherry-pick":!0,"git revert":!0},compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C2>e.C3},function(e){return e.C2>e.C1}]},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%27%27%22%2C%22id%22%3A%22master%22%7D%2C%22newImage%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22newImage%22%7D%2C%22caption%22%3A%7B%22target%22%3A%22C3%27%27%22%2C%22id%22%3A%22caption%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%2C%22C2%27%27%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%27%27%22%7D%2C%22C3%27%27%22%3A%7B%22parents%22%3A%5B%22C2%27%27%27%22%5D%2C%22id%22%3A%22C3%27%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git rebase -i HEAD~2;git commit --amend;git rebase -i HEAD~2;git rebase caption master",startTree:'{"branches":{"master":{"target":"C1","id":"master"},"newImage":{"target":"C2","id":"newImage"},"caption":{"target":"C3","id":"caption"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"caption","id":"HEAD"}}',name:{ko:"커밋들 갖고 놀기",en_US:"Juggling Commits",ja:"Juggling Commits",zh_CN:"提交变换戏法"},hint:{en_US:"The first command is git rebase -i HEAD~2",ja:"最初に打つコマンドはgit rebase -i HEAD~2",ko:"첫번째 명령은 git rebase -i HEAD~2 입니다",zh_CN:"第一个命令是 'git rebase -i HEAD~2'"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Juggling Commits","","Here's another situation that happens quite commonly. You have some changes (`newImage`) and another set of changes (`caption`) that are related, so they are stacked on top of each other in your repository (aka one after another).","","The tricky thing is that sometimes you need to make a small modification to an earlier commit. In this case, design wants us to change the dimensions of `newImage` slightly, even though that commit is way back in our history!!"]}},{type:"ModalAlert",options:{markdowns:["We will overcome this difficulty by doing the following:","","* We will re-order the commits so the one we want to change is on top with `git rebase -i`","* We will `commit --amend` to make the slight modification","* Then we will re-order the commits back to how they were previously with `git rebase -i`","* Finally, we will move master to this updated part of the tree to finish the level (via the method of your choosing)","","There are many ways to accomplish this overall goal (I see you eye-ing cherry-pick), and we will see more of them later, but for now let's focus on this technique."]}},{type:"ModalAlert",options:{markdowns:["Lastly, pay attention to the goal state here -- since we move the commits twice, they both get an apostrophe appended. One more apostrophe is added for the commit we amend, which gives us the final form of the tree ","","That being said, I can compare levels now based on structure and relative apostrophe differences. As long as your tree's `master` branch has the same structure and relative apostrophe differences, I'll give full credit"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Commitsをやりくりする","","開発中に頻繁に起こるケースをもう1つ考えます。ある変更(`newImage`)とまた別の変更(`caption`)があって、それらに依存関係があるとします。この一連の変更が一列に積み重なっているとします。","","ここでトリッキーなのは、以前のコミットに対して微修正をかけなければならないケースがあるということです。今回の教材でも、過去のコミットであるにも関わらず`newImage`ブランチに僅かな修正を加えるような設計の修正が入ったとしましょう。"]}},{type:"ModalAlert",options:{markdowns:["この困難な状況を、以下の手順で克服することを考えます:","","* `git rebase -i`を使って順番を変更する。これで、変更をかけたいコミットを一番先頭に持ってくる。","* `commit --amend`コマンドで僅かな変更を行う","* `git rebase -i`コマンドを再度使って、先頭に持ってきていたコミットを元に戻す","* 最後に、レベルクリアのためにmasterブランチを先頭に持ってくる","","クリアのための方法はいくつもありますが(cherry-pickを使うこともできます)、別の回答はまた後程の章で見ることにんして、今回は上記の方法でやってみることにしましょう。"]}},{type:"ModalAlert",options:{markdowns:["最後に、ゴール時点での状態に気を付けてください。今回2回ほどコミットを動かしますから、コミットへのポインタにはアポストロフィ(')が追加されます。commit --amendコマンドの実行でできたコミットには更にもう1つのアポストロフィが追加されます。 "]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 提交变换戏法","","下面这种情况也是经常出现的。例如你之前已经在 `newImage` 分支上做了一些提交,然后又在 `caption` 分支上做了一些相关的提交,因此它们看起来是一个连一个的(stacked on top of each other in your repository)。","","有点棘手的就是有时候你又想往先前的提交里做些小改动。呐,现在就是设计师想要我们去轻微改变下 `newImage` 的内容(change the dimensions slightly),尽管那个提交是很久很久以前的了。"]}},{type:"ModalAlert",options:{markdowns:["为了实现他的愿望,我们可以按照下面的方法来做:","","* 先用 `git rebase -i` 将提交重新排序,然后把我们想要修改的提交挪到最前","* 然后用 `commit --amend` 来进行一些小修改","* 接着再用 `git rebase -i` 来将他们按最开始的顺序重新排好","* 最后我们把 master 移到修改的最前端(用你自己喜欢的方法),就大功告成啦!","","当然还有许多方法可以完成这个任务(我知道你在看 cherry-pick 啦),之后我们会多点关注这些技巧啦,但现在暂时只专注上面这种方法。"]}},{type:"ModalAlert",options:{markdowns:["啊最后还要提醒你一下最终的形式 —— 因为我们把这个提交移动了两次,所以会分别产生一个省略提交(both get an apostrophe appended)。还有一个省略提交是因为我们为了实现最终效果去修改提交而添加的。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 커밋들 갖고 놀기","","이번에도 꽤 자주 발생하는 상황입니다. `newImage`와 `caption` 브랜치에 각각의 변경내역이 있고 서로 약간 관련이 있어서, 저장소에 차례로 쌓여있는 상황입니다.","","때로는 이전 커밋의 내용을 살짝 바꿔야하는 골치아픈 상황에 빠지게 됩니다. 이번에는 디자인 쪽에서 우리의 작업이력(history)에서는 이미 한참 전의 커밋 내용에 있는 `newImage`의 크기를 살짝 바꿔달라는 요청이 들어왔습니다."]}},{type:"ModalAlert",options:{markdowns:["이 문제를 다음과 같이 풀어봅시다:","","* `git rebase -i` 명령으로 우리가 바꿀 커밋을 가장 최근 순서로 바꾸어 놓습니다","* `commit --amend` 명령으로 커밋 내용을 정정합니다","* 다시 `git rebase -i` 명령으로 이 전의 커밋 순서대로 되돌려 놓습니다","* 마지막으로, master를 지금 트리가 변경된 부분으로 이동합니다. (편하신 방법으로 하세요)","","이 목표를 달성하기 위해서는 많은 방법이 있는데요(체리픽을 고민중이시죠?), 체리픽은 나중에 더 살펴보기로 하고, 우선은 위의 방법으로 해결해보세요."]}},{type:"ModalAlert",options:{markdowns:["최종적으로, 목표 결과를 눈여겨 보세요 -- 우리가 커밋을 두 번 옮겼기 때문에, 두 커밋 모두 따옴표 표시가 붙어있습니다. 정정한(amend) 커밋은 따옴표가 추가로 하나 더 붙어있습니다."]}}]}}}}),e.define("/levels/mixed/jugglingCommits2.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22master%22%7D%2C%22newImage%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22newImage%22%7D%2C%22caption%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22caption%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%27%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout master;git cherry-pick C2;git commit --amend;git cherry-pick C3",disabledMap:{"git revert":!0},startTree:'{"branches":{"master":{"target":"C1","id":"master"},"newImage":{"target":"C2","id":"newImage"},"caption":{"target":"C3","id":"caption"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"caption","id":"HEAD"}}',compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C2>e.C3},function(e){return e.C2>e.C1}]},name:{ko:"커밋 갖고 놀기 #2",en_US:"Juggling Commits #2",ja:"コミットをやりくりする その2",zh_CN:"提交交换戏法 #2"},hint:{en_US:"Don't forget to forward master to the updated changes!",ja:"masterのポインタを先に進めることを忘れずに!",ko:"master를 변경 완료한 커밋으로 이동(forward)시키는 것을 잊지 마세요!",zh_CN:"别忘记了将 master 快进到最新的更新上!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Juggling Commits #2","","*If you haven't completed Juggling Commits #1 (the previous level), please do so before continuing*","","As you saw in the last level, we used `rebase -i` to reorder the commits. Once the commit we wanted to change was on top, we could easily --amend it and re-order back to our preferred order.","","The only issue here is that there is a lot of reordering going on, which can introduce rebase conflicts. Let's look at another method with `git cherry-pick`"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Remember that git cherry-pick will plop down a commit from anywhere in the tree onto HEAD (as long as that commit isn't upstream).","","Here's a small refresher demo:"],afterMarkdowns:["Nice! Let's move on"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["So in this level, let's accomplish the same objective of amending `C2` once but avoid using `rebase -i`. I'll leave it up to you to figure it out! :D","","Remember, the exact number of apostrophe's (') on the commit are not important, only the relative differences. For example, I will give credit to a tree that matches the goal tree but has one extra apostrophe everywhere"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## コミットをやりくりする その2","","*注意 この一つ前のレベル「コミットをやりくりする」をクリアしていない人は、まずそちらの問題をクリアしてきてください*","","前回見てきたように、コミット順序の変更のために、私たちは`rebase -i`コマンドを利用しました。ツリーの先頭に変更対象のコミットがあれば、--amendオプションを使うことで容易に変更を書きかえて、元の順序に戻すことができます。","","この場合に心配なことが一つだけあって、それは複数回の順序の変更が行われるので、rebaseのコンフリクト(衝突)が起こりうることです。こういうケースへの対策として、`git cherry-pick`を使った別の解決法について考えてみましょう。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["git cherry-pickを使うと、ツリーの中から複数のコミットを選んで、HEADの下に新しく作ることができましたね。","","簡単なデモを見てみましょう:"],afterMarkdowns:["できました!次へ進みましょう"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["このレベルでは、`C2`をamendすることで前回と同じ目的を達成しましょう。但し`rebase -i`は使わずにクリアしてください。どんな方法で進めるかはあなたにおまかせします!:D"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 提交变换戏法 #2","","*假如你还没有完成提交变换戏法 #1(前一关),这关不让玩哦!*","","如你在上一关所见,我们使用 `rebase -i` 来重排那些提交。只要把我们想要的提交挪到最顶端,我们就可以很容易地改变它,然后把它们重新排成我们想要的顺序。","","但唯一的问题就是这样做就要排很多次,有可能造成衍合冲突(rebase conflicts)。下面就看看用另外一种方法 `git cherry-pick` 是怎么做的吧。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["要在心理牢记 cherry-pick 可以从提交树的任何地方拿一个提交来放在 HEAD 上(尽管那个提交不在上游)。","","下面是一个小小的演示:"],command:"git cherry-pick C2",afterMarkdowns:["好滴咧,我们继续"],beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["那么这关呢,和上一关一样要改变提交 `C2`,但你要避免使用 `rebase -i`。自己想想要怎么解决吧,骚年! :D"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 커밋 갖고 놀기 #2","","*만약 이전 레벨의 커밋 갖고 놀기 #1을 풀지 않으셨다면, 계속하기에 앞서서 꼭 풀어보세요*","","이전 레벨에서 보셨듯이 `rebase -i` 명령으로 커밋의 순서를 바꿀 수 있습니다. 정정할 커밋이 바로 직전(top)에 있으면 간단히 --amend로 수정할 수 있고, 그리고 나서 다시 원하는 순서로 되돌려 놓으면 됩니다.","","이번에 한가지 문제는 순서를 꽤 많이 바꿔야한다는 점인데요, 그러다가 리베이스중에 충돌이 날 수 있습니다. 이번에는 다른 방법인 `git cherry-pick`으로 해결해 봅시다."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["git cherry-pick으로 HEAD에다 어떤 커밋이든 떨어 뜨려 놓을 수 있다고 알려드린것 기억나세요? (단, 그 커밋이 현재 가리키고 있는 커밋이 아니어야합니다)","","간단한 데모로 다시 알려드리겠습니다:"],afterMarkdowns:["좋아요! 계속할게요"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["그럼 이번 레벨에서는 아까와 마찬가지로 `C2` 커밋의 내용을 정정하되, `rebase -i`를 쓰지 말고 해보세요. ^.~"]}}]}}}}),e.define("/levels/advanced/multipleParents.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C7","id":"master"},"bugWork":{"target":"C2","id":"bugWork"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C2"],"id":"C5"},"C6":{"parents":["C4","C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',solutionCommand:"git branch bugWork master^^2^",startTree:'{"branches":{"master":{"target":"C7","id":"master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C2"],"id":"C5"},"C6":{"parents":["C4","C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Multiple parents",zh_CN:"多个父提交记录"},hint:{en_US:"Use `git branch bugWork` with a target commit to create the missing reference.",zh_CN:"使用`git branch bugWork`加上一个目标提交记录来创建消失的引用。"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["### Specifying Parents","","Like the `~` modifier, the `^` modifier also accepts an optional number after it.","","Rather than specifying the number of generations to go back (what `~` takes), the modifier on `^` specifies which parent reference to follow from a merge commit. Remember that merge commits have multiple parents, so the path to choose is ambiguous.","",'Git will normally follow the "first" parent upwards from a merge commit, but specifying a number with `^` changes this default behavior.',"","Enough talking, let's see it in action.",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have a merge commit. If we checkout `master^` without the modifier, we will follow the first parent after the merge commit. ","","(*In our visuals, the first parent is positioned directly above the merge commit.*)"],afterMarkdowns:["Easy -- this is what we are all used to."],command:"git checkout master^",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Now let's try specifying the second parent instead..."],afterMarkdowns:["See? We followed the other parent upwards."],command:"git checkout master^2",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["The `^` and `~` modifiers can make moving around a commit tree very powerful:"],afterMarkdowns:["Lightning fast!"],command:"git checkout HEAD~; git checkout HEAD^2; git checkout HEAD~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Even crazier, these modifiers can be chained together! Check this out:"],afterMarkdowns:["The same movement as before, but all in one command."],command:"git checkout HEAD~^2~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"ModalAlert",options:{markdowns:["### Put it to practice","","To complete this level, create a new branch at the specified destination.","","Obviously it would be easy to specify the commit directly (with something like `C6`), but I challenge you to use the modifiers we talked about instead!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["### 选择父提交","","和`~`修改符一样,`^`修改符之后也可以跟一个(可选的)数字。","","这不是用来指定向上返回几代(`~`的作用),`^`后的数字指定跟随合并提交记录的哪一个父提交。还记得一个合并提交有多个父提交吧,所有选择哪条路径不是那么清晰。","",'Git默认选择跟随合并提交的"第一个"父提交,使用`^`后跟一个数字来改变这一默认行为。',"","废话不多说,举个例子。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["这里有一个合并提交。如果不加数字修改符直接切换到`master^`,会回到第一个父提交。","","(*在我们的图示中,第一个父提交是指合并提交正上方的那个父提交。*)"],afterMarkdowns:["OK--这恰好是我们想要的。"],command:"git checkout master^",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["现在来试试选择第二个父提交……"],afterMarkdowns:["看见了吧?我们回到了第二个父提交。"],command:"git checkout master^2",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用`^`和`~`可以自由在在提交树中移动:"],afterMarkdowns:["快若闪电!"],command:"git checkout HEAD~; git checkout HEAD^2; git checkout HEAD~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["再疯狂点,这些修改符支持链式操作!试一下这个:"],afterMarkdowns:["和前面的结果一样,但只用了一条命令。"],command:"git checkout HEAD~^2~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"ModalAlert",options:{markdowns:["### 实践一下","","要完成此关,在指定的目标位置创建一个新的分支。","","很明显可以简单的直接使用提交记录的hash值(比如`C6`),但我要求你使用刚刚讲到的相对引用修饰符!"]}}]}}}}),e.define("/levels/rebase/selectiveRebase.js",function(e,t,n,r,i,s,o){n.level={compareAllBranchesHashAgnostic:!0,disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C5%22%2C%22id%22%3A%22master%22%7D%2C%22one%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22one%22%7D%2C%22two%22%3A%7B%22target%22%3A%22C2%27%27%22%2C%22id%22%3A%22two%22%7D%2C%22three%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22three%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C4%27%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C4%27%27%22%7D%2C%22C3%27%27%22%3A%7B%22parents%22%3A%5B%22C4%27%27%22%5D%2C%22id%22%3A%22C3%27%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C3%27%27%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22two%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout one; git cherry-pick C4 C3 C2; git checkout two; git cherry-pick C5 C4 C3 C2; git branch -f three C2",startTree:'{"branches":{"master":{"target":"C5","id":"master"},"one":{"target":"C1","id":"one"},"two":{"target":"C1","id":"two"},"three":{"target":"C1","id":"three"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C4"],"id":"C5"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{ko:"브랜치 스파게티",en_US:"Branch Spaghetti",ja:"ブランチスパゲッティ",zh_CN:"分支浆糊"},hint:{en_US:"Make sure to do everything in the proper order! Branch one first, then two, then three",ja:"全て正しい順番で処理すること!oneが最初で、次がtwo、最後にthreeを片付ける。",ko:"이 문제를 해결하는 방법은 여러가지가 있습니다! 체리픽(cherry-pick)이 가장 쉽지만 오래걸리는 방법이고, 리베이스(rebase -i)가 빠른 방법입니다",zh_CN:"确保你是按照正确的顺序来操作!先操作分支 `one`, 然后 `two`, 最后才是 `three`"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branch Spaghetti","","WOAHHHhhh Nelly! We have quite the goal to reach in this level.","","Here we have `master` that is a few commits ahead of branches `one` `two` and `three`. For whatever reason, we need to update these three other branches with modified versions of the last few commits on master.","","Branch `one` needs a re-ordering and a deletion of `C5`. `two` needs pure reordering, and `three` only needs one commit!","","We will let you figure out how to solve this one -- make sure to check out our solution afterwards with `show solution`. "]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ブランチスパゲッティ","","なんということでしょう。今回のレベルクリアのために、やることがたくさんあります。","","いま`master`が指しているコミットの数個前のコミットに、ブランチ`one`、`two`それから`three`があります。何か事情があって、これらの3つのブランチをmasterが指している最新の状態に更新したいケースを考えます。","","ブランチ`one`に対しては、順序の変更と`C5`の削除が必要です。`two`では順序の変更のみ、`three`に対しては1回だけコミットすればOKです。","","`show solution`コマンドで模範解答を確認できますから、こちらも利用してください。 "]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branch Spaghetti","","哇塞大神!这关我们要来点不同的!","","现在我们的 `master` 分支是比 `one` `two` 和 `three` 要多几个提交。出于某种原因,我们需要把其他三个分支更新到 master 分支上新近的几个不同提交上。(update these three other brances with modified versions of the last few commits on master)","","分支 `one` 需要重新排序和撤销, `two` 需要完全重排,而 `three` 只需要提交一次。","","慢慢摸索会找到答案的 —— 你完事记得用 `show solution` 看看我们的答案哦。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 브랜치 스파게티","","음, 이번에는 만만치 않습니다!","","여기 `master` 브랜치의 몇 번 이전 커밋에 `one`, `two`,`three` 총 3개의 브랜치가 있습니다. 어떤 이유인지는 몰라도, master의 최근 커밋 몇 개를 나머지 세 개의 브랜치에 반영하려고 합니다.","","`one` 브랜치는 순서를 바꾸고 `C5`커밋을 삭제하고, `two`브랜치는 순서만 바꾸며, `three`브랜치는 하나의 커밋만 가져옵시다!","","자유롭게 이 문제를 풀어보시고 나서 `show solution`명령어로 모범 답안을 확인해보세요."]}}]}}}}),e.define("/src/js/views/levelDropdownView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../intl"),h=e("../log"),p=e("../util/keyboard").KeyboardListener,d=e("../app"),v=e("../views").ModalTerminal,m=e("../views").ContainedBase,g=e("../views").BaseView,y=m.extend({tagName:"div",className:"levelDropdownView box vertical",template:u.template($("#level-dropdown-view").html()),initialize:function(e){e=e||{},this.JSON={},this.navEvents=u.clone(f.Events),this.navEvents.on("clickedID",u.debounce(u.bind(this.loadLevelID,this),300,!0)),this.navEvents.on("negative",this.negative,this),this.navEvents.on("positive",this.positive,this),this.navEvents.on("left",this.left,this),this.navEvents.on("right",this.right,this),this.navEvents.on("up",this.up,this),this.navEvents.on("down",this.down,this),this.keyboardListener=new p({events:this.navEvents,aliasMap:{esc:"negative",enter:"positive"},wait:!0}),this.sequences=d.getLevelArbiter().getSequences(),this.sequenceToLevels=d.getLevelArbiter().getSequenceToLevels(),this.container=new v({title:c.str("select-a-level")}),this.render(),d.getEvents().on("resetMapSolved",this.render,this),d.getEvents().on("localeChanged",this.render,this),e.wait||this.show()},render:function(){y.__super__.render.apply(this,arguments),this.buildSequences()},positive:function(){if(!this.selectedID)return;this.loadLevelID(this.selectedID)},left:function(){if(this.turnOnKeyboardSelection())return;this.leftOrRight(-1)},leftOrRight:function(e){this.deselectIconByID(this.selectedID),this.selectedIndex=this.wrapIndex(this.selectedIndex+e,this.getCurrentSequence()),this.selectedID=this.getSelectedID(),this.selectIconByID(this.selectedID)},right:function(){if(this.turnOnKeyboardSelection())return;this.leftOrRight(1)},up:function(){if(this.turnOnKeyboardSelection())return;this.selectedSequence=this.getPreviousSequence(),this.downOrUp()},down:function(){if(this.turnOnKeyboardSelection())return;this.selectedSequence=this.getNextSequence(),this.downOrUp()},downOrUp:function(){this.selectedIndex=this.boundIndex(this.selectedIndex,this.getCurrentSequence()),this.deselectIconByID(this.selectedID),this.selectedID=this.getSelectedID(),this.selectIconByID(this.selectedID)},turnOnKeyboardSelection:function(){return this.selectedID?!1:(this.selectFirst(),!0)},turnOffKeyboardSelection:function(){if(!this.selectedID)return;this.deselectIconByID(this.selectedID),this.selectedID=undefined,this.selectedIndex=undefined,this.selectedSequence=undefined},wrapIndex:function(e,t){return e=e>=t.length?0:e,e=e<0?t.length-1:e,e},boundIndex:function(e,t){return e=e>=t.length?t.length-1:e,e=e<0?0:e,e},getNextSequence:function(){var e=this.getSequenceIndex(this.selectedSequence),t=this.wrapIndex(e+1,this.sequences);return this.sequences[t]},getPreviousSequence:function(){var e=this.getSequenceIndex(this.selectedSequence),t=this.wrapIndex(e-1,this.sequences);return this.sequences[t]},getSequenceIndex:function(e){var t=this.sequences.indexOf(e);if(t<0)throw new Error("didnt find");return t},getIndexForID:function(e){return d.getLevelArbiter().getLevel(e).index},selectFirst:function(){var e=this.sequenceToLevels[this.sequences[0]][0].id;this.selectIconByID(e),this.selectedIndex=0,this.selectedSequence=this.sequences[0]},getCurrentSequence:function(){return this.sequenceToLevels[this.selectedSequence]},getSelectedID:function(){return this.sequenceToLevels[this.selectedSequence][this.selectedIndex].id},selectIconByID:function(e){this.toggleIconSelect(e,!0)},deselectIconByID:function(e){this.toggleIconSelect(e,!1)},toggleIconSelect:function(e,t){this.selectedID=e;var n="#levelIcon-"+e;$(n).toggleClass("selected",t)},negative:function(){this.hide()},testOption:function(e){return this.currentCommand&&(new RegExp("--"+e)).test(this.currentCommand.get("rawStr"))},show:function(e,t){this.currentCommand=t,this.updateSolvedStatus(),this.showDeferred=e,this.keyboardListener.listen(),y.__super__.show.apply(this)},hide:function(){this.showDeferred&&this.showDeferred.resolve(),this.showDeferred=undefined,this.keyboardListener.mute(),this.turnOffKeyboardSelection(),y.__super__.hide.apply(this)},loadLevelID:function(e){if(!this.testOption("noOutput")){d.getEventBaton().trigger("commandSubmitted","level "+e);var t=d.getLevelArbiter().getLevel(e),n=t.name.en_US;h.levelSelected(n)}this.hide()},updateSolvedStatus:function(){u.each(this.seriesViews,function(e){e.updateSolvedStatus()},this)},buildSequences:function(){this.seriesViews=[],u.each(this.sequences,function(e){this.seriesViews.push(new b({destination:this.$el,name:e,navEvents:this.navEvents}))},this)}}),b=g.extend({tagName:"div",className:"seriesView box flex1 vertical",template:u.template($("#series-view").html()),events:{"click div.levelIcon":"click","mouseenter div.levelIcon":"enterIcon","mouseleave div.levelIcon":"leaveIcon"},initialize:function(e){this.name=e.name||"intro",this.navEvents=e.navEvents,this.info=d.getLevelArbiter().getSequenceInfo(this.name),this.levels=d.getLevelArbiter().getLevelsInSequence(this.name),this.levelIDs=[],u.each(this.levels,function(e){this.levelIDs.push(e.id)},this),this.destination=e.destination,this.JSON={displayName:c.getIntlKey(this.info,"displayName"),about:c.getIntlKey(this.info,"about")||" ",ids:this.levelIDs},this.render(),this.updateSolvedStatus()},updateSolvedStatus:function(){var e=this.$("div.levelIcon").each(function(e,t){var n=$(t).attr("data-id");$(t).toggleClass("solved",d.getLevelArbiter().isLevelSolved(n))})},getEventID:function(e){var t=e.target;return $(t).attr("data-id")},resetAbout:function(){this.$("p.about").text(c.getIntlKey(this.info,"about")).css("font-style","inherit")},setAbout:function(e){this.$("p.about").text(e).css("font-style","italic")},enterIcon:function(e){var t=this.getEventID(e),n=d.getLevelArbiter().getLevel(t);this.setAbout(c.getName(n))},leaveIcon:function(){this.resetAbout()},click:function(e){var t=this.getEventID(e);this.navEvents.trigger("clickedID",t)}});n.LevelDropdownView=y}),e.define("/src/js/views/commandViews.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../models/collections").CommandEntryCollection,l=e("../app"),c=e("../models/commandModel").Command,h=e("../models/commandModel").CommandEntry,p=e("../util/errors"),d=p.Warning,v=e("../util"),m=e("../log"),g=e("../util/keyboard"),y=a.View.extend({initialize:function(e){l.getEvents().on("commandSubmittedPassive",this.addToCommandHistory,this),this.commands=new f,this.commands.fetch({success:u.bind(function(){var e=[];this.commands.each(function(t){e.push(t)}),e.reverse(),this.commands.reset(),u.each(e,function(e){this.commands.add(e)},this)},this)}),this.index=-1,this.commandParagraph=this.$("#prompt p.command")[0],this.commandCursor=this.$("#prompt span.cursor")[0],this.focus(),l.getEvents().on("rollupCommands",this.rollupCommands,this),l.getEventBaton().stealBaton("keydown",this.onKeyDown,this),l.getEventBaton().stealBaton("keyup",this.onKeyUp,this)},events:{"blur #commandTextField":"hideCursor","focus #commandTextField":"showCursor"},blur:function(){this.hideCursor()},focus:function(){this.$("#commandTextField").focus(),this.showCursor()},hideCursor:function(){this.toggleCursor(!1)},showCursor:function(){this.toggleCursor(!0)},toggleCursor:function(e){$(this.commandCursor).toggleClass("shown",e)},onKeyDown:function(e){var t=e.target;this.updatePrompt(t)},onKeyUp:function(e){this.onKeyDown(e);var t={enter:u.bind(function(){this.submit()},this),up:u.bind(function(){this.commandSelectChange(1)},this),down:u.bind(function(){this.commandSelectChange(-1)},this)},n=g.mapKeycodeToKey(e.which||e.keyCode);t[n]!==undefined&&(e.preventDefault(),t[n](),this.onKeyDown(e))},badHtmlEncode:function(e){return e.replace(/&/g,"&").replace(/=this.commands.length||this.index<0){this.clear(),this.index=-1;return}var t=this.commands.toArray()[this.index].get("text");this.setTextField(t)},clearLocalStorage:function(){this.commands.each(function(e){a.sync("delete",e,function(){})},this)},setTextField:function(e){this.$("#commandTextField").val(e)},clear:function(){this.setTextField("")},submit:function(){var e=this.$("#commandTextField").val().replace("\n","");this.clear(),this.submitCommand(e),this.index=-1},rollupCommands:function(e){var t=this.commands.toArray().slice(1,Number(e)+1);t.reverse();var n="";u.each(t,function(e){n+=e.get("text")+";"},this);var r=new h({text:n});this.commands.unshift(r),a.sync("create",r,function(){})},addToCommandHistory:function(e){var t=e.length&&this.index===-1||e.length&&this.index!==-1&&this.commands.toArray()[this.index].get("text")!==e;if(!t)return;var n=new h({text:e});this.commands.unshift(n),a.sync("create",n,function(){}),this.commands.length>100&&this.clearLocalStorage(),m.commandEntered(e)},submitCommand:function(e){l.getEventBaton().trigger("commandSubmitted",e)}}),b=a.View.extend({tagName:"div",model:c,template:u.template($("#command-template").html()),events:{click:"clicked"},clicked:function(e){},initialize:function(){this.model.bind("change",this.wasChanged,this),this.model.bind("destroy",this.remove,this)},wasChanged:function(e,t){var n=t.changes,r=u.keys(n);u.difference(r,["status"]).length===0?this.updateStatus():this.render()},updateStatus:function(){var e=["inqueue","processing","finished"],t={};u.each(e,function(e){t[e]=!1}),t[this.model.get("status")]=!0;var n=this.$("p.commandLine");u.each(t,function(e,t){n.toggleClass(t,e)})},render:function(){var e=u.extend({resultType:"",result:"",formattedWarnings:this.model.getFormattedWarnings()},this.model.toJSON());return this.$el.html(this.template(e)),this},remove:function(){$(this.el).hide()}}),w=a.View.extend({initialize:function(e){this.collection=e.collection,this.collection.on("add",this.addOne,this),this.collection.on("reset",this.addAll,this),this.collection.on("all",this.render,this),this.collection.on("change",this.scrollDown,this),l.getEvents().on("commandScrollDown",this.scrollDown,this),l.getEvents().on("clearOldCommands",this.clearOldCommands,this)},addWarning:function(e){var t=new d({msg:e}),n=new c({error:t,rawStr:"Warning:"});this.collection.add(n)},clearOldCommands:function(){var e=[];this.collection.each(function(t){t.get("status")!=="inqueue"&&t.get("status")!=="processing"&&e.push(t)},this),u.each(e,function(e){e.destroy()},this),this.scrollDown()},scrollDown:function(){var e=$("#commandDisplay")[0],t=$("#terminal")[0],n=e.clientHeight>t.clientHeight||$(window).height()"]}},{type:"ModalAlert",options:{markdowns:["## Git 명령어","","연습 모드에서 쓸 수 있는 다양한 git명령어는 다음과 같습니다",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## 공유해주세요!","","`export tree` 와 `import tree`로 여러분의 친구들에게 트리를 공유해주세요","","훌륭한 학습 자료가 있으신가요? `build level`로 레벨을 만들어 보시거나, 친구의 레벨을 `import level`로 가져와서 실험해보세요","","이제 레슨을 시작해봅시다..."]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Bienvenue sur LearnGitBranching!","","Cette application a été conçue pour aider les débutants à saisir ","les puissants concepts derrière les branches en travaillant ","avec git. Nous espérons que vous apprécierez cette application et ","que vous apprendrez peut-être quelque chose d'intéressant !","","# Démo !","","Si vous n'avez pas vu la démo, vous pouvez le faire là :","","[http://pcottle.github.io/learnGitBranching/?demo](http://pcottle.github.io/learnGitBranching/?demo)","","Agacé par ce dialogue ? Ajoutez `?NODEMO` à l'URL pour le supprimer, en lien ci-dessous pour votre commodité :","","[http://pcottle.github.io/learnGitBranching/?NODEMO](?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## Commandes Git","","Il existe une large variété de commandes git disponibles dans le mode bac à sable. Sont inclues",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## Partager, c'est se soucier!","","Partagez des arbres avec vous amis via `export tree` et `import tree`","","Vous avez une grande leçon à partager ? Essayez de construire un niveau avec `build level` ou essayez le niveau d'un ami avec `import level`","","Pour voir la gamme complète des commandes, tapez `show commands`. Il y a quelques perles telles que `undo` et `reset`","","Mais tout de suite commencez sur les `levels`…"]}}]}}),e.define("/src/js/util/mock.js",function(e,t,n,r,i,s,o){n.mock=function(e){var t={},n=function(){};for(var r in e.prototype)t[r]=n;return t}}),e.define("sys",function(e,t,n,r,i,s,o){t.exports=e("util")}),e.define("child_process",function(e,t,n,r,i,s,o){n.spawn=function(){},n.exec=function(){}}),e.define("/src/js/visuals/tree.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({removeKeys:function(e){u.each(e,function(e){this.get(e)&&this.get(e).remove()},this)},animateAttrKeys:function(e,t,n,r){e=u.extend({},{include:["circle","arrow","rect","path","text"],exclude:[]},e||{});var i=this.getAttributes();u.each(e.include,function(e){i[e]=u.extend({},i[e],t)}),u.each(e.exclude,function(e){delete i[e]}),this.animateToAttr(i,n,r)}});n.VisBase=f}),e.define("/src/js/git/headless.js",function(e,t,n,r,i,s,o){function E(){var e={},t=function(){return f.defer().promise};for(var n in c)e[n]=t;return e.playRefreshAnimationAndFinish=function(e,t){console.log("trying to finish"),t.thenFinish(f.defer().promise)},e}var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("../git").GitEngine,c=e("../visuals/animation/animationFactory").AnimationFactory,h=e("../visuals").GitVisuals,p=e("../git/treeCompare").TreeCompare,d=e("../util/eventBaton").EventBaton,v=e("../models/collections"),m=v.CommitCollection,g=v.BranchCollection,y=e("../models/commandModel").Command,b=e("../util/mock").mock,w=e("../util"),S=function(){this.init()};S.prototype.init=function(){this.commitCollection=new m,this.branchCollection=new g;var e=E(),t=b(h);this.gitEngine=new l({collection:this.commitCollection,branches:this.branchCollection,gitVisuals:t,animationFactory:e,eventBaton:new d}),this.gitEngine.init()},S.prototype.sendCommand=function(e){w.splitTextCommand(e,function(e){var t=new y({rawStr:e});this.gitEngine.dispatch(t,f.defer())},this)},n.HeadlessGit=S}),e.define("/src/js/app/index.js",function(e,t,n,r,i,s,o){function E(){var t=e("../views"),n=e("../models/collections"),r=e("../views/commandViews"),i=new t.MainHelperBar;this.commandCollection=new n.CommandCollection,this.commandBuffer=new n.CommandBuffer({collection:this.commandCollection}),this.commandPromptView=new r.CommandPromptView({el:$("#commandLineBar")}),this.commandLineHistoryView=new r.CommandLineHistoryView({el:$("#commandLineHistory"),collection:this.commandCollection})}var u=e("underscore"),a=e("backbone"),f=e("../util/constants"),l=e("../util"),c=u.clone(a.Events),h,p,d,v,m,g=function(){var t=e("../level/sandbox").Sandbox,n=e("../level").Level,r=e("../util/eventBaton").EventBaton,i=e("../level/arbiter").LevelArbiter,s=e("../views/levelDropdownView").LevelDropdownView;d=new r,h=new E,p=new t,v=new i,m=new s({wait:!0}),c.on("localeChanged",y),b(d),w(p)},y=function(){if(!window.$)return;$("span.intl-aware").each(function(t,n){var r=e("../intl"),i=$(n).attr("data-intl");$(n).text(r.str(i).toUpperCase())})},b=function(e){var t=function(){$("#commandTextField").focus()};t(),$(window).focus(function(t){e.trigger("windowFocus",t)}),$(document).click(function(t){e.trigger("documentClick",t)}),$(document).bind("keydown",function(t){e.trigger("docKeydown",t)}),$(document).bind("keyup",function(t){e.trigger("docKeyup",t)}),$(window).on("resize",function(e){c.trigger("resize",e)}),e.stealBaton("docKeydown",function(){}),e.stealBaton("docKeyup",function(){}),e.stealBaton("windowFocus",t),e.stealBaton("documentClick",t);var n=function(t){return function(){var n=[t];u.each(arguments,function(e){n.push(e)}),e.trigger.apply(e,n)}};$("#commandTextField").on("keydown",n("keydown")),$("#commandTextField").on("keyup",n("keyup")),$(window).trigger("resize")},w=function(e){var t=l.parseQueryString(window.location.href);t.hasOwnProperty("demo")?e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",["git commit; git checkout -b bugFix C1; git commit; git merge master; git checkout master; git commit; git rebase bugFix;","delay 1000; reset;","level rebase1 --noFinishDialog --noStartCommand --noIntroDialog;","delay 2000; show goal; delay 1000; hide goal;","git checkout bugFix; git rebase master; git checkout side; git rebase bugFix;","git checkout another; git rebase side; git rebase another master;","help; levels"].join(""))}):t.hasOwnProperty("NODEMO")||e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",["git help;","delay 1000;","help;","levels"].join(""))}),t.locale!==undefined&&t.locale.length&&(f.GLOBAL.locale=t.locale,c.trigger("localeChanged"));if(t.command){var n=unescape(t.command);e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",n)})}(/(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent)||/android/i.test(navigator.userAgent))&&e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted","mobile alert")})};e("../util").isBrowser()&&$(document).ready(g),n.getEvents=function(){return c},n.getSandbox=function(){return p},n.getEventBaton=function(){return d},n.getCommandUI=function(){return h},n.getLevelArbiter=function(){return v},n.getLevelDropdown=function(){return m},n.init=g}),e("/src/js/app/index.js"),e.define("/src/js/dialogs/confirmShowSolution.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Are you sure you want to see the solution?","","I believe in you! You can do it"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 确定要看答案吗?","","哥相信你!你可以的"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Êtes-vous sûr de vouloir voir la solution ?","","Je crois en vous ! Vous pouvez le faire"]}}]}}),e("/src/js/dialogs/confirmShowSolution.js"),e.define("/src/js/dialogs/levelBuilder.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Welcome to the level builder!","","Here are the main steps:",""," * Set up the initial environment with git commands"," * Define the starting tree with ```define start```"," * Enter the series of git commands that compose the (optimal) solution"," * Define the goal tree with ```define goal```. Defining the goal also defines the solution"," * Optionally define a hint with ```define hint```"," * Edit the name with ```define name```"," * Optionally define a nice start dialog with ```edit dialog```"," * Enter the command ```finish``` to output your level JSON!"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 欢迎使用关卡生成器!","","主要步骤如下:",""," * 使用 git 命令布置好初始环境"," * 使用 ```define start``` 命令定义起始树"," * 输入一系列 git 命令,编好答案"," * 使用 ```define goal``` 命令定义目标树。定义目标的同时定义答案"," * 还可以用 ```define hint``` 命令定义一个提示"," * 用 ```define name``` 修改名称"," * 还可以用 ```edit dialog``` 定义一个漂亮的开始对话框"," * 输入 ```finish``` 就可以输出你的关卡数据(JSON)了!"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Bienvenue dans l'éditeur niveaux !","","Voici les étapes principales :",""," * Mettez en place l'environnement initial avec des commandes git"," * Définissez l'arbre de départ avec ```define start```"," * Saisissez la série de commandes git qui composent la solution (optimale)"," * Définissez l'arbre cible avec ```define goal```. Cela définit aussi la solution"," * Optionnellement, définissez un indice avec ```define hint```"," * Changez le nom avec ```define name```"," * Optionellement, definissez un joli dialogue de départ avec ```edit dialog```"," * Entrez la commande ```finish``` pour délivrer votre niveau JSON!"]}}]}}),e("/src/js/dialogs/levelBuilder.js"),e.define("/src/js/dialogs/nextLevel.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Great Job!!","","You solved the level in *{numCommands}* command(s); ","our solution uses {best}."]}}],ja:[{type:"ModalAlert",options:{markdowns:["## 完成!","","あなたは*{numCommands}*回のコマンドでこの課題をクリアしました; ","模範解答では{best}回です。"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 碉堡了!","","你用 *{numCommands}* 条命令搞定了这一关;我们的答案要用 {best}。"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Beau Travail!!","","Vous avez résolu le niveau en *{numCommands}* commande(s); ","notre solution le fait en {best}."]}}]}}),e("/src/js/dialogs/nextLevel.js"),e.define("/src/js/dialogs/sandbox.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Welcome to LearnGitBranching!","","This application is designed to help beginners grasp ","the powerful concepts behind branching when working ","with git. We hope you enjoy this application and maybe ","even learn something!","","# Demo!","","If you have not seen the demo, please check it out here:","","[http://pcottle.github.io/learnGitBranching/?demo](http://pcottle.github.io/learnGitBranching/?demo)","","Annoyed at this dialog? Append `?NODEMO` to the url to get rid of it, linked below for convenience:","","[http://pcottle.github.io/learnGitBranching/?NODEMO](?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## Git commands","","You have a large variety of git commands available in sandbox mode. These include",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## Sharing is caring!","","Share trees with your friends via `export tree` and `import tree`","","Have a great lesson to share? Try building a level with `build level` or try out a friend's level with `import level`","","To see the full range of commands, try `show commands`. There are some gems like `undo` and `reset`","","For now let's get you started on the `levels`..."]}}],ja:[{type:"ModalAlert",options:{markdowns:["## LearnGitBranchingへようこそ","","gitのパワフルなブランチ機能のコンセプトが ","学びやすくなるようにこのアプリケーションを作りました。 ","このアプリケーションを楽しんで使って頂いて、 ","何かを学習して頂けたなら嬉しいです。","","# とりあえず触ってみたい方へ:","","簡単なデモを用意してあるので、もしよければこちらもご覧ください:","","[http://remore.github.io/learnGitBranching-ja/?demo](http://remore.github.io/learnGitBranching-ja/?demo)","","このダイアログ自体を省略するには、以下のようにURLの末尾にクエリストリング`?NODEMO`を付加してアクセスしてください。","","[http://remore.github.io/learnGitBranching-ja/?NODEMO](http://remore.github.io/learnGitBranching-ja/?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## ここで学べるGitのオペレーション","","ここでは、下記の種類のgitコマンドを学ぶことができます。",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## 学習した内容を共有できます","","画面左のコマンドプロンプトから`export tree`や`import tree`とタイプすることで、gitのツリー構造を友達に送ることができます","","何か教材になるようなケースはご存知ないでしょうか。`build level`で課題を作成したり、`import level`で他の人の課題に挑戦してみてください。","","それでは教材の選択画面に進んでみることにします。"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 欢迎光临 LearnGitBranching!","","本应用旨在帮助初学者领会 git 分支背后的强大概念。","希望你能喜欢这个应用,并学到知识!","","# 演示!","","如果你还没看过演示,请到此查看:","","[http://pcottle.github.io/learnGitBranching/?demo](http://pcottle.github.io/learnGitBranching/?demo)","","厌烦这个对话框? 在 URL 后头加上 `?NODEMO` 就看不到它了,也可以直接点下边这个链接:","","[http://pcottle.github.io/learnGitBranching/?NODEMO](http://pcottle.github.io/learnGitBranching/?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## Git 命令","","在沙盒模式里,你有好多命令可用。 包括:",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## 分享即关怀","","使用 `export tree` 和 `import tree` 与朋友分享 Git 树","","有个好课程可以分享?试试用 `build level` 创建一个关卡,或者 `import level` 试试朋友的。","","言归正传,让我们先从 `levels` 开始……"]}}],ko:[{type:"ModalAlert",options:{markdowns:["## Git 브랜치 배우기를 시작합니다!","","이 애플리케이션은 git을 쓸 때 필요한 브랜치에 대한 개념을","탄탄히 잡게끔 도와드리기 위해 만들었습니다. 재밌게 사용해주시기를","바라며, 무언가를 배워가신다면 더 기쁘겠습니다!","","이 애플리케이션은 [Peter Cottle](https://github.io/pcottle)님의 [LearnGitBranching](http://pcottle.github.io/learnGitBranching/)를 번역한 것입니다.","아래 데모를 먼저 보셔도 좋습니다.","",""]}},{type:"ModalAlert",options:{markdowns:["## Git 명령어","","연습 모드에서 쓸 수 있는 다양한 git명령어는 다음과 같습니다",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## 공유해주세요!","","`export tree` 와 `import tree`로 여러분의 친구들에게 트리를 공유해주세요","","훌륭한 학습 자료가 있으신가요? `build level`로 레벨을 만들어 보시거나, 친구의 레벨을 `import level`로 가져와서 실험해보세요","","이제 레슨을 시작해봅시다..."]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Bienvenue sur LearnGitBranching!","","Cette application a été conçue pour aider les débutants à saisir ","les puissants concepts derrière les branches en travaillant ","avec git. Nous espérons que vous apprécierez cette application et ","que vous apprendrez peut-être quelque chose d'intéressant !","","# Démo !","","Si vous n'avez pas vu la démo, vous pouvez le faire là :","","[http://pcottle.github.io/learnGitBranching/?demo](http://pcottle.github.io/learnGitBranching/?demo)","","Agacé par ce dialogue ? Ajoutez `?NODEMO` à l'URL pour le supprimer, en lien ci-dessous pour votre commodité :","","[http://pcottle.github.io/learnGitBranching/?NODEMO](?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## Commandes Git","","Il existe une large variété de commandes git disponibles dans le mode bac à sable. Sont inclues",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## Partager, c'est se soucier!","","Partagez des arbres avec vous amis via `export tree` et `import tree`","","Vous avez une grande leçon à partager ? Essayez de construire un niveau avec `build level` ou essayez le niveau d'un ami avec `import level`","","Pour voir la gamme complète des commandes, tapez `show commands`. Il y a quelques perles telles que `undo` et `reset`","","Mais tout de suite commencez sur les `levels`…"]}}]}}),e("/src/js/dialogs/sandbox.js"),e.define("/src/js/git/commands.js",function(e,t,n,r,i,s,o){function y(e,t){this.method=e,this.rawOptions=t,this.supportedMap=this.getMasterOptionMap()[e];if(this.supportedMap===undefined)throw new Error("No option map for "+e);this.generalArgs=[],this.explodeAndSet()}var u=e("underscore"),a=e("../intl"),f=e("../util/errors"),l=f.CommandProcessError,c=f.GitError,h=f.Warning,p=f.CommandResult,d={"git commit":/^(gc|git ci)($|\s)/,"git add":/^ga($|\s)/,"git checkout":/^(go|git co)($|\s)/,"git rebase":/^gr($|\s)/,"git branch":/^(gb|git br)($|\s)/,"git status":/^(gst|gs|git st)($|\s)/,"git help":/^git$/},v=[[/^git help($|\s)/,function(){var e=[a.str("git-version"),"
",a.str("git-usage"),u.escape(a.str("git-usage-command")),"
",a.str("git-supported-commands"),"
"],t=y.prototype.getMasterOptionMap();u.each(t,function(t,n){e.push("git "+n),u.each(t,function(t,n){e.push(" "+n)},this)},this);var n=e.join("\n");throw n=n.replace(/\t/g,"   "),new p({msg:n})}]],m={"git commit":/^git +commit($|\s)/,"git add":/^git +add($|\s)/,"git checkout":/^git +checkout($|\s)/,"git rebase":/^git +rebase($|\s)/,"git reset":/^git +reset($|\s)/,"git branch":/^git +branch($|\s)/,"git revert":/^git +revert($|\s)/,"git log":/^git +log($|\s)/,"git merge":/^git +merge($|\s)/,"git show":/^git +show($|\s)/,"git status":/^git +status($|\s)/,"git cherry-pick":/^git +cherry-pick($|\s)/,"git fakeTeamwork":/^git +fakeTeamwork($|\s)/,"git fetch":/^git +fetch *?$/,"git pull":/^git +pull($|\s)/,"git push":/^git +push($|\s)/,"git clone":/^git +clone *?$/},g=function(e){var t,n;u.each(m,function(r,i){r.exec(e)&&(n=e.slice(i.length+1),t=i.slice("git ".length))});if(!t)return!1;var r=new y(t,n);return{toSet:{generalArgs:r.generalArgs,supportedMap:r.supportedMap,method:t,options:n,eventName:"processGitCommand"}}};y.prototype.getMasterOptionMap=function(){return{commit:{"--amend":!1,"-a":!1,"-am":!1,"-m":!1},status:{},log:{},add:{},"cherry-pick":{},branch:{"-d":!1,"-D":!1,"-f":!1,"-a":!1,"-r":!1,"--contains":!1},checkout:{"-b":!1,"-B":!1,"-":!1},reset:{"--hard":!1,"--soft":!1},merge:{},rebase:{"-i":!1},revert:{},show:{},clone:{},fetch:{},pull:{"--rebase":!1},push:{},fakeTeamwork:{}}},y.prototype.explodeAndSet=function(){var e=this.rawOptions.match(/('.*?'|".*?"|\S+)/g)||[];for(var t=0;t9&&(e=e.slice(0,9),this.command.addWarning(l.str("branch-name-short",{branch:e}))),e},y.prototype.validateAndMakeBranch=function(e,t){e=this.validateBranchName(e);if(this.refs[e])throw new v({msg:l.str("bad-branch-name",{branch:name})});this.makeBranch(e,t)},y.prototype.makeBranch=function(e,t){var n=new w({target:t,id:e});return this.branchCollection.add(n),this.refs[n.get("id")]=n,n},y.prototype.getHead=function(){return u.clone(this.HEAD)},y.prototype.getBranches=function(){var e=[];return this.branchCollection.each(function(t){e.push({id:t.get("id"),selected:this.HEAD.get("target")===t,target:t.get("target"),remote:t.getIsRemote(),obj:t})},this),e},y.prototype.getRemoteBranches=function(){var e=this.getBranches();return u.filter(e,function(e){return e.remote===!0})},y.prototype.getLocalBranches=function(){var e=this.getBranches();return u.filter(e,function(e){return e.remote===!1})},y.prototype.printBranchesWithout=function(e){var t=this.getUpstreamBranchSet(),n=this.getCommitFromRef(e).get("id"),r=[];u.each(t[n],function(e){e.selected=this.HEAD.get("target").get("id")==e.id,r.push(e)},this),this.printBranches(r)},y.prototype.printBranches=function(e){var t="";throw u.each(e,function(e){t+=(e.selected?"* ":"")+e.id+"\n"}),new m({msg:t})},y.prototype.getUniqueID=function(){var e=this.uniqueId("C"),t=u.bind(function(e){return this.refs[e]?!0:this.origin&&this.origin.refs[e]?!0:!1},this);while(t(e))e=this.uniqueId("C");return e},y.prototype.makeCommit=function(e,t,n){t||(t=this.getUniqueID());var r=new E(u.extend({parents:e,id:t,gitVisuals:this.gitVisuals},n||{}));return this.refs[r.get("id")]=r,this.commitCollection.add(r),r},y.prototype.acceptNoGeneralArgs=function(){if(this.generalArgs.length)throw new v({msg:l.str("git-error-no-general-args")})},y.prototype.validateArgBounds=function(e,t,n,r){var i=r===undefined?"git "+this.command.get("method"):this.command.get("method")+" "+r+" ";i="with "+i;if(e.lengthn)throw new v({msg:l.str("git-error-args-many",{upper:String(n),what:i})})},y.prototype.oneArgImpliedHead=function(e,t){this.validateArgBounds(e,0,1,t),e.length===0&&e.push("HEAD")},y.prototype.twoArgsImpliedHead=function(e,t){this.validateArgBounds(e,1,2,t),e.length==1&&e.push("HEAD")},y.prototype.revertStarter=function(){this.validateArgBounds(this.generalArgs,1,NaN),this.revert(this.generalArgs)},y.prototype.revert=function(e){var t=u.map(e,function(e){return this.getCommitFromRef(e)},this),n=f.defer(),r=n.promise,i=this.resolveID("HEAD");r=c.highlightEachWithPromise(r,t,i);var s=this.getCommitFromRef("HEAD"),o=u.bind(function(e){var t=this.rebaseAltID(e.get("id")),n=l.str("git-revert-msg",{oldCommit:this.resolveName(e),oldMsg:e.get("commitMessage")}),r=this.makeCommit([s],t,{commitMessage:n});return s=r,c.playCommitBirthPromiseAnimation(r,this.gitVisuals)},this);u.each(t,function(e){r=r.then(function(){return o(e)})},this),r=r.then(u.bind(function(){return this.setTargetLocation("HEAD",s),c.playRefreshAnimation(this.gitVisuals)},this)),this.animationQueue.thenFinish(r,n)},y.prototype.resetStarter=function(){if(this.commandOptions["--soft"])throw new v({msg:l.str("git-error-staging")});this.commandOptions["--hard"]&&(this.command.addWarning(l.str("git-warning-hard")),this.generalArgs=this.generalArgs.concat(this.commandOptions["--hard"])),this.validateArgBounds(this.generalArgs,1,1);if(this.getDetachedHead())throw new v({msg:l.str("git-error-reset-detached")});this.reset(this.generalArgs[0])},y.prototype.reset=function(e){this.setTargetLocation("HEAD",this.getCommitFromRef(e))},y.prototype.cherrypickStarter=function(){this.validateArgBounds(this.generalArgs,1,Number.MAX_VALUE);var e=this.getUpstreamSet("HEAD"),t=u.map(this.generalArgs,function(t){var n=this.getCommitFromRef(t);if(e[n.get("id")])throw new v({msg:l.str("git-error-already-exists",{commit:n.get("id")})});return n},this),n=f.defer(),r=n.promise,i=this.resolveID("HEAD");r=c.highlightEachWithPromise(r,t,i);var s=u.bind(function(e){var t=this.cherrypick(e);return c.playCommitBirthPromiseAnimation(t,this.gitVisuals)},this);u.each(t,function(e){r=r.then(function(){return s(e)})},this),this.animationQueue.thenFinish(r,n)},y.prototype.checkUpstreamOfSource=function(e,t,n,r,i){var s=t.getUpstreamSet(r),o=e.getCommitFromRef(n).get("id");if(!s[o])throw new v({msg:i||l.str("git-error-origin-fetch-no-ff")})},y.prototype.getTargetGraphDifference=function(e,t,n,r,i){i=i||{},r=t.resolveID(r);var s=e.getUpstreamSet(n),o=t.getCommitFromRef(r),a=t.exportTree(),f=a.commits[o.get("id")];if(e.refs[f.id]){if(i.dontThrowOnNoFetch)return[];throw new v({msg:l.str("git-error-origin-fetch-uptodate")})}f.depth=0;var c=[],h=[f],p=function(e){if(s[e])return;var t=a.commits[e];t.depth=d.depth+1,h.push(t)};while(h.length){var d=h.pop();c.push(d),u.each(d.parents,p)}var m={},g=[];return u.forEach(c,function(e){if(m[e.id])return;m[e.id]=!0,g.push(e)}),g.sort(function(e,t){return t.depth-e.depth})},y.prototype.pushStarter=function(e){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.push()},y.prototype.push=function(e){e=e||{};var t=this.refs.master,n=this.origin.refs.master;this.checkUpstreamOfSource(this,this.origin,n,t,l.str("git-error-origin-push-no-ff"));var r=this.getTargetGraphDifference(this.origin,this,n,t),i=u.bind(function(e,t){var n=u.map(t,function(e){return this.origin.refs[e]},this);return this.origin.makeCommit(n,e)},this),s=u.bind(function(e,t){var n=i(e,t);return c.playCommitBirthPromiseAnimation(n,this.origin.gitVisuals)},this),o=f.defer(),a=o.promise;u.each(r,function(e){a=a.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.refs[e.id],n)},this)),a=a.then(function(){return s(e.id,e.parents)})},this),a=a.then(u.bind(function(){var e=t.get("target").get("id"),r=this.origin.refs[e];return this.origin.setTargetLocation(n,r),c.playRefreshAnimation(this.gitVisuals),c.playRefreshAnimation(this.origin.gitVisuals)},this)),a=a.then(u.bind(function(){var e=this.getCommitFromRef(t),n=t.getRemoteBranchIDFromTracking();return this.setTargetLocation(this.refs[n],e),c.playRefreshAnimation(this.gitVisuals)},this)),e.dontResolvePromise||this.animationQueue.thenFinish(a,o)},y.prototype.fetchStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.fetch()},y.prototype.fetch=function(e){e=e||{};var t=this.refs["o/master"],n=this.origin.refs.master;this.checkUpstreamOfSource(this,this.origin,t,n);var r=this.getTargetGraphDifference(this,this.origin,t,n,e);if(r.length===0){this.command.addWarning(l.str("git-error-origin-fetch-uptodate"));var i=f.defer();return{deferred:i,chain:i.promise}}var s=u.bind(function(e,t){var n=u.map(t,function(e){return this.refs[e]},this);return this.makeCommit(n,e)},this),o=u.bind(function(e,t){var n=s(e,t);return c.playCommitBirthPromiseAnimation(n,this.gitVisuals)},this),a=f.defer(),h=a.promise;return u.each(r,function(e){h=h.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.origin.refs[e.id],t)},this)),h=h.then(function(){return o(e.id,e.parents)})},this),h=h.then(u.bind(function(){var e=n.get("target").get("id"),r=this.refs[e];return this.setTargetLocation(t,r),c.playRefreshAnimation(this.origin.gitVisuals),c.playRefreshAnimation(this.gitVisuals)},this)),e.dontResolvePromise||this.animationQueue.thenFinish(h,a),{chain:h,deferred:a}},y.prototype.pullStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.pull()},y.prototype.pull=function(){var e=this.refs.master,t=this.refs["o/master"],n=this.fetch({dontResolvePromise:!0,dontThrowOnNoFetch:!0});this.commandOptions["--rebase"]?this.pullFinishWithRebase(n,e,t):this.pullFinishWithMerge(n,e,t)},y.prototype.pullFinishWithRebase=function(e,t,n){var r=e.chain,i=e.deferred;r=r.then(function(){return c.getDelayedPromise(300)}),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(n),t)},this)),r=r.then(u.bind(function(){return e.dontResolvePromise=!0,this.rebase(n,t,e)},this)),this.animationQueue.thenFinish(r,i)},y.prototype.pullFinishWithMerge=function(e,t,n){var r=e.chain,i=e.deferred;r=r.then(function(){return c.getDelayedPromise(300)}),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(n),t)},this)),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(t),n)},this)),r=r.then(function(){return c.getDelayedPromise(700)}),r=r.then(u.bind(function(){var e=this.merge("o/master");return e?c.playCommitBirthPromiseAnimation(e,this.gitVisuals):c.playRefreshAnimation(this.gitVisuals)},this)),this.animationQueue.thenFinish(r,i)},y.prototype.cloneStarter=function(){this.acceptNoGeneralArgs(),this.makeOrigin(this.printTree(this.exportTreeForBranch("master")))},y.prototype.fakeTeamworkStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.validateArgBounds(this.generalArgs,0,1);var e=this.generalArgs[0]||1;this.fakeTeamwork(e)},y.prototype.fakeTeamwork=function(e){var t=u.bind(function(){var e=this.getUniqueID();return this.origin.receiveTeamwork(e,this.animationQueue)},this),n=u.bind(function(){var e=t();return c.playCommitBirthPromiseAnimation(e,this.origin.gitVisuals)},this),r=function(){return n()},i=f.defer(),s=i.promise;u.each(u.range(e),function(e){s=s.then(function(){return n()})}),this.animationQueue.thenFinish(s,i)},y.prototype.receiveTeamwork=function(e,t){var n=this.makeCommit([this.getCommitFromRef("HEAD")],e);return this.setTargetLocation(this.HEAD,n),n},y.prototype.cherrypick=function(e){var t=this.rebaseAltID(e.get("id")),n=this.makeCommit([this.getCommitFromRef("HEAD")],t);return this.setTargetLocation(this.HEAD,n),n},y.prototype.commitStarter=function(){this.acceptNoGeneralArgs();if(this.commandOptions["-am"]&&(this.commandOptions["-a"]||this.commandOptions["-m"]))throw new v({msg:l.str("git-error-options")});var e=null,t=null;this.commandOptions["-a"]&&this.command.addWarning(l.str("git-warning-add")),this.commandOptions["-am"]&&(t=this.commandOptions["-am"],this.validateArgBounds(t,1,1,"-am"),e=t[0]),this.commandOptions["-m"]&&(t=this.commandOptions["-m"],this.validateArgBounds(t,1,1,"-m"),e=t[0]);var n=this.commit();e&&(e=e.replace(/"/g,'"').replace(/^"/g,"").replace(/"$/g,""),n.set("commitMessage",e));var r=c.playCommitBirthPromiseAnimation(n,this.gitVisuals);this.animationQueue.thenFinish(r)},y.prototype.commit=function(){var e=this.getCommitFromRef(this.HEAD),t=null;this.commandOptions["--amend"]&&(e=this.resolveID("HEAD~1"),t=this.rebaseAltID(this.getCommitFromRef("HEAD").get("id")));var n=this.makeCommit([e],t);return this.getDetachedHead()&&this.command.addWarning(l.str("git-warning-detached")),this.setTargetLocation(this.HEAD,n),n},y.prototype.resolveName=function(e){var t=this.resolveID(e);return t.get("type")=="commit"?"commit "+t.get("id"):t.get("type")=="branch"?'branch "'+t.get("id")+'"':this.resolveName(t.get("target"))},y.prototype.resolveID=function(e){if(e===null||e===undefined)throw new Error("Dont call this with null / undefined");return typeof e!="string"?e:this.resolveStringRef(e)},y.prototype.resolveRelativeRef=function(e,t){var n=/([~\^])(\d*)/g,r;while(r=n.exec(t)){var i=e,s=r[2]?parseInt(r[2],10):1;if(r[1]=="^")i=e.getParent(s-1);else while(i&&s--)i=i.getParent(0);if(!i){var o=l.str("git-error-relative-ref",{commit:e.id,match:r[0]});throw new v({msg:o})}e=i}return e},y.prototype.resolveStringRef=function(e){e=this.crappyUnescape(e);if(this.refs[e])return this.refs[e];var t=null,n=null,r=/^([a-zA-Z0-9]+)(([~\^]\d*)*)/,i=r.exec(e);if(!i)throw new v({msg:l.str("git-error-exist",{ref:e})});t=i[1],n=i[2];if(!this.refs[t])throw new v({msg:l.str("git-error-exist",{ref:e})});var s=this.getCommitFromRef(t);return n&&(s=this.resolveRelativeRef(s,n)),s},y.prototype.getCommitFromRef=function(e){var t=this.resolveID(e);while(t.get("type")!=="commit")t=t.get("target");return t},y.prototype.getType=function(e){return this.resolveID(e).get("type")},y.prototype.setTargetLocation=function(e,t){if(this.getType(e)=="commit")return;e=this.getOneBeforeCommit(e),e.set("target",t)},y.prototype.getUpstreamBranchSet=function(){var e={},t=function(e,t){var n=!1;return u.each(e,function(e){e.id==t&&(n=!0)}),n},n=function(e){var t=[],n=[e];while(n.length){var r=n.pop();t.push(r.get("id")),r.get("parents")&&r.get("parents").length&&(n=n.concat(r.get("parents")))}return t};return this.branchCollection.each(function(r){var i=n(r.get("target"));u.each(i,function(n){e[n]=e[n]||[],t(e[n],r.get("id"))||e[n].push({obj:r,id:r.get("id")})})}),e},y.prototype.getUpstreamHeadSet=function(){var e=this.getUpstreamSet("HEAD"),t=this.getCommitFromRef("HEAD").get("id");return e[t]=!0,e},y.prototype.getOneBeforeCommit=function(e){var t=this.resolveID(e);return t===this.HEAD&&!this.getDetachedHead()&&(t=t.get("target")),t},y.prototype.scrapeBaseID=function(e){var t=/^C(\d+)/.exec(e);if(!t)throw new Error("regex failed on "+e);return"C"+t[1]},y.prototype.rebaseAltID=function(e){var t=[[/^C(\d+)[']{0,2}$/,function(e){return e[0]+"'"}],[/^C(\d+)[']{3}$/,function(e){return e[0].slice(0,-3)+"'^4"}],[/^C(\d+)['][\^](\d+)$/,function(e){return"C"+String(e[1])+"'^"+String(Number(e[2])+1)}]];for(var n=0;n",this.get("commitMessage"),"
","Commit: "+this.get("id")].join("\n")+"\n"},getShowEntry:function(){return[this.getLogEntry(),"diff --git a/bigGameResults.html b/bigGameResults.html","--- bigGameResults.html","+++ bigGameResults.html","@@ 13,27 @@ Winner, Score","- Stanfurd, 14-7","+ Cal, 21-14"].join("\n")+"\n"},validateAtInit:function(){if(!this.get("id"))throw new Error("Need ID!!");this.get("createTime")||this.set("createTime",(new Date).toString()),this.get("commitMessage")||this.set("commitMessage",l.str("git-dummy-msg")),this.set("children",[]);if(!this.get("rootCommit"))if(!this.get("parents")||!this.get("parents").length)throw new Error("needs parents")},addNodeToVisuals:function(){var e=this.get("gitVisuals").addNode(this.get("id"),this);this.set("visNode",e)},addEdgeToVisuals:function(e){this.get("gitVisuals").addEdge(this.get("id"),e.get("id"))},getParent:function(e){return this&&this.attributes&&this.attributes.parents?this.attributes.parents[e]:null},isMainParent:function(e){var t=this.get("parents").indexOf(e);return t===0},initialize:function(e){this.validateAtInit(),this.addNodeToVisuals(),u.each(this.get("parents"),function(e){e.get("children").push(this),this.addEdgeToVisuals(e)},this)}});n.GitEngine=y,n.Commit=E,n.Branch=w,n.Ref=b}),e("/src/js/git/index.js"),e.define("/src/js/git/treeCompare.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a={};a.dispatchFromLevel=function(e,t){var n=e.goalTreeString;return a.dispatch(e,n,t)},a.dispatch=function(e,t,n){var r=!0;switch(r){case!!e.compareOnlyMaster:return a.compareBranchWithinTrees(n,t,"master");case!!e.compareOnlyBranches:return a.compareAllBranchesWithinTrees(n,t);case!!e.compareAllBranchesHashAgnostic:return a.compareAllBranchesWithinTreesHashAgnostic(n,t);case!!e.compareOnlyMasterHashAgnostic:return a.compareBranchesWithinTreesHashAgnostic(n,t,["master"]);case!!e.compareOnlyMasterHashAgnosticWithAsserts:return a.compareBranchesWithinTreesHashAgnostic(n,t,["master"])&&a.evalAsserts(n,e.goalAsserts);default:return a.compareAllBranchesWithinTreesAndHEAD(n,t)}},a.compareAllBranchesWithinTreesAndHEAD=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t);debugger;return e.HEAD.target==t.HEAD.target&&this.compareAllBranchesWithinTrees(e,t)},a.compareAllBranchesWithinTrees=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t);var n=u.extend({},e.branches,t.branches),r=!0;return u.uniq(n,function(n,i){r=r&&this.compareBranchWithinTrees(e,t,i)},this),r},a.compareBranchesWithinTrees=function(e,t,n){var r=!0;return u.each(n,function(n){r=r&&this.compareBranchWithinTrees(e,t,n)},this),r},a.compareBranchWithinTrees=function(e,t,n){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var r=this.getRecurseCompare(e,t),i=e.branches[n],s=t.branches[n];return u.isEqual(i,s)&&r(e.commits[i.target],t.commits[s.target])},a.compareAllBranchesWithinTreesHashAgnostic=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var n=u.extend({},e.branches,t.branches),r=[];return u.each(n,function(e,t){r.push(t)}),this.compareBranchesWithinTreesHashAgnostic(e,t,r)},a.compareBranchesWithinTreesHashAgnostic=function(e,t,n){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var r=u.bind(function(e,t){return!e||!t?!1:(e=u.clone(e),t=u.clone(t),e.target=this.getBaseRef(e.target),t.target=this.getBaseRef(t.target),u.isEqual(e,t))},this),i=this.getRecurseCompareHashAgnostic(e,t),s=!0;return u.each(n,function(n){var o=e.branches[n],u=t.branches[n];s=s&&r(o,u)&&i(e.commits[o.target],t.commits[u.target])},this),s},a.evalAsserts=function(e,t){var n=!0;return u.each(t,function(t,r){n=n&&this.evalAssertsOnBranch(e,r,t)},this),n},a.evalAssertsOnBranch=function(e,t,n){e=this.convertTreeSafe(e);if(!e.branches[t])return!1;var r=e.branches[t],i=[r.target],s={};while(i.length){var o=i.pop();s[this.getBaseRef(o)]=this.getNumHashes(o),i=i.concat(e.commits[o].parents)}var a=!0;return u.each(n,function(e){try{a=a&&e(s)}catch(t){console.warn("error during assert",t),console.log(t),a=!1}}),a},a.getNumHashes=function(e){var t=[[/^C(\d+)([']{0,3})$/,function(e){return e[2]?e[2].length:0}],[/^C(\d+)['][\^](\d+)$/,function(e){return Number(e[2])}]];for(var n=0;n []",zh_CN:"git <命令> [<参数>]",fr_FR:"git []"},"git-supported-commands":{__desc__:"In the git help command, the header above the supported commands",en_US:"Supported commands:",zh_CN:"支持的命令有:",fr_FR:"Commandes supportées"},"git-usage":{__desc__:"In the dummy git output, the header before showing all the commands",en_US:"Usage:",zh_CN:"使用:",fr_FR:"Utilisation :"},"git-version":{__desc__:"The git version dummy output, kind of silly. PCOTTLE is my unix name but feel free to put yours instead",en_US:"Git Version PCOTTLE.1.0",zh_CN:"Git 版本 PCOTTLE.1.0",fr_FR:"Git version PCOTTLE.1.0"},"refresh-tree-command":{__desc__:"when the tree is visually refreshed",en_US:"Refreshing tree...",zh_CN:"正在刷新树结构...",fr_FR:"Actualisation de l'arbre…"},"locale-command":{__desc__:"when the locale is set to something",en_US:"Locale set to {locale}",zh_CN:"语言更改为 {locale}",fr_FR:"Langue changée à {locale}"},"locale-reset-command":{__desc__:"when the locale is reset",en_US:"Locale reset to default, which is {locale}",zh_CN:"语言重置为默认的 {locale}",fr_FR:"Langue remise par défaut, qui est {locale}"},"show-command":{__desc__:'command output title from "show"',en_US:"Please use one of the following commands for more info:",fr_FR:"Merci d'utiliser une des commandes suivantes pour obtenir plus d'info"},"show-all-commands":{__desc__:'command output title from "show commands"',en_US:"Here is a list of all the commmands available:",fr_FR:"Ci-dessous est la liste de toutes les commandes disponibles :"},"cd-command":{__desc__:"dummy command output for the command in the key",en_US:'Directory changed to "/directories/dont/matter/in/this/demo"',zh_CN:'目录切换到 "/directories/dont/matter/in/this/demo"',fr_FR:'Répertoire changé à "/directories/dont/matter/in/this/demo" (les répertoires ne servent à rien dans cette démo)'},"ls-command":{__desc__:"Dummy command output for the command in the key",en_US:"DontWorryAboutFilesInThisDemo.txt",zh_CN:"DontWorryAboutFilesInThisDemo.txt (译: 在试验里不用担心文件.txt)",fr_FR:"DontWorryAboutFilesInThisDemo.txt (ne vous préoccupez pas des noms de fichier dans cette démo)"},"mobile-alert":{__desc__:"When someone comes to the site on a mobile device, they can not input commands so this is a nasty alert to tell them",en_US:"Can't bring up the keyboard on mobile / tablet :( try visiting on desktop! :D",zh_CN:"无法在移动设备/平板上调出键盘 :( 请试试桌面版 :D",fr_FR:"Impossible de faire apparaître le clavier sur mobile / tablette :( Essayez de passer sur un ordinateur de bureau :D"},"share-tree":{__desc__:"When you export a tree, we want you to share the tree with friends",en_US:'Share this tree with friends! They can load it with "import tree"',zh_CN:'与你的好友分享提交树!他们可以用 "import tree" 加载它',fr_FR:'Partagez cet arbre avec vos amis ! Ils peuvent le charger avec "import tree"'},"paste-json":{__desc__:"When you are importing a level or tree",en_US:"Paste a JSON blob below!",zh_CN:"在下边粘贴一个JSON串",fr_FR:"Collez un blob JSON ci-dessous !"},"solved-map-reset":{__desc__:"When you reset the solved map to clear your solved history, in case someone else wants to use your browser",en_US:"Solved map was reset, you are starting from a clean slate!",zh_CN:"解决列表已重置,您现在从零开始了",fr_FR:"La carte des niveaux résolus a été effacée, vous repartez de zéro !"},"level-cant-exit":{__desc__:"When the user tries to exit a level when they are not in one",en_US:'You are not in a level! You are in a sandbox, start a level with "levels"',zh_CN:'您没在关卡中!您在沙盒中,要开始关卡请输入 "levels"',fr_FR:'Vous n\'êtes pas dans un niveau ! Vous êtes dans le mode bac à sable, commencez un niveau avec "levels"'},"level-no-id":{__desc__:"When you say an id but that level doesnt exist",en_US:'A level for that id "{id}" was not found! Opening up a level selection view',zh_CN:'没找到id为 "{id}" 的关卡!打开关卡选择框',fr_FR:"Le niveau dont l'identifiant est {id} n'a pas été trouvé ! Ouverture de la vue de sélection des niveaux"},"undo-stack-empty":{__desc__:"The undo command can only undo back until the last time the level was reset or the beginning of the level",en_US:"The undo stack is empty!",zh_CN:"还没有什么可以撤销",fr_FR:"La pile d'annulation est vide !"},"already-solved":{__desc__:"When you play in a level that is already solved",en_US:'You have already solved this level, try other levels with "levels" or go back to sandbox with "sandbox"',zh_CN:'你已经解决了本关,输入 "levels" 尝试其他关卡,或者输入 "sandbox" 回到沙盒中',fr_FR:'Vous avez déjà résolu ce niveau, essayez d\'autres niveaux avec "levels" ou revenez au bac à sable avec "sandbox"'},"command-disabled":{__desc__:"When you try a command that is disabled",en_US:"That git command is disabled for this level!",zh_CN:"该命令在本关不允许使用!",fr_FR:"Cette commande git est désactivée pour ce niveau !"},"share-json":{__desc__:"when you have made the level, prompt to share this",en_US:"Here is the JSON for this level! Share it with somenoe or send it to me on Github",zh_CN:"这是一个关卡定义JSON!您可以分享它或者发到我的GitHub上",fr_FR:"Voici le JSON pour ce niveau ! Partagez-le avec quelqu'un ou envoyez-le moi sur Github"},"want-start-dialog":{__desc__:"prompt to add a start dialog",en_US:"You have not specified a start dialog, would you like to add one?",zh_CN:"您还没有定义一开始的介绍,是否添加一个?",fr_FR:"Vous n'avez pas spécifié de dialogue de départ, voulez-vous en ajouter un ?"},"want-hint":{__desc__:"prompt to add a hint",en_US:"You have not specified a hint, would you like to add one?",zh_CN:"您还没有定义提示,是否添加一个?",fr_FR:"Vous n'avez pas spécifié d'indice, voulez-vous en ajouter un ?"},"prompt-hint":{__desc__:"prompt for hint",en_US:"Enter the hint for this level, or leave this blank if you do not want to include one",zh_CN:"请输入关卡提示,或者故意留空",fr_FR:"Entrez l'indice pour ce niveau, ou laissez-le vide pour ne pas l'inclure"},"prompt-name":{__desc__:"prompt for level name",en_US:"Enter the name for the level",zh_CN:"输入关卡名",fr_FR:"Entrez le nom pour ce niveau"},"solution-empty":{__desc__:"If you define a solution without any commands, aka a level that is solved without doing anything",en_US:"Your solution is empty!! Something is amiss",zh_CN:"你的解法是空的!! 这应该是出错了",fr_FR:"Votre solution est vide !! Quelque chose ne tourne pas rond"},"define-start-warning":{__desc__:"When you define the start point again, it overwrites the solution and goal so we add a warning",en_US:"Defining start point... solution and goal will be overwritten if they were defined earlier",zh_CN:"定义开始点... 解决方法和目标会被新的替代",fr_FR:"Redéfinition du point de départ… la solution et la cible seront écrasés s'ils ont déjà été définis"},"help-vague-level":{__desc__:"When you are in a level and you say help, its vague and you need to specify",en_US:'You are in a level, so multiple forms of help are available. Please select either "help level" to learn more about this lesson, "help general" for using Learn GitBranching, or "objective" to learn about how to solve the level.',zh_CN:'您正在关卡中,这里有多种形式的帮助,请选择 "help level" (关卡帮助)或 "help general" (一般帮助)',fr_FR:'Vous êtes dans un niveau, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help level" pour en apprendre plus sur cette leçon, "help general" pour l\'utilisation de Learn GitBranching, ou "objective" pour apprendre comment résoudre le niveau'},"help-vague-builder":{__desc__:"When you are in a level builder, the help command is vague so you need to specify what you mean",en_US:'You are in a level builder, so multiple forms of help are available. Please select either "help general" or "help builder"',zh_CN:'您正在进行关卡构建中,这里有多种形式的帮助,请选择 "help general" (一般帮助)或 "help builder" (关卡构建帮助)',fr_FR:'Vous êtes dans l\'éditeur de niveaux, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help general" soit "help builder"'},"goal-to-reach":{__desc__:"title of window that shoes the goal tree to reach",en_US:"Goal To Reach",zh_CN:"目标",fr_FR:"Cible à atteindre"},"hide-goal":{__desc__:"the helper message for the window that shows the goal tree",en_US:'You can hide this window with "hide goal"',zh_CN:'你可以通过命令 "hide goal" 关闭这个窗口',fr_FR:'Vous pouvez masquer cette fenêtre avec "hide goal"'},"hide-start":{__desc__:"The helper message for the window that shows the start tree for a level",en_US:'You can hide this window with "hide start"',zh_CN:'你可以通过命令 "hide start" 关闭这个窗口',fr_FR:'Vous pouvez masquer cette fenêtre avec "hide start"'},"level-builder":{__desc__:"The name for the environment where you build levels",en_US:"Level Builder",zh_CN:"关卡生成器",fr_FR:"Éditeur de niveaux"},"no-start-dialog":{__desc__:"when the user tries to open a start dialog for a level that does not have one",en_US:"There is no start dialog to show for this level!",zh_CN:"介绍? 这关真没有!",fr_FR:"Il n'y a aucun dialogue de départ à afficher pour ce niveau !"},"no-hint":{__desc__:"when no hint is available for a level",en_US:"Hmm, there doesn't seem to be a hint for this level :-/",zh_CN:"提示?嗯,这关真没有哎~ :-/",fr_FR:"Hum, il ne semble pas y avoir d'indice pour ce niveau :-/"},"error-untranslated-key":{__desc__:"This error happens when we are trying to translate a specific key and the locale version is mission",en_US:"The translation for {key} does not exist yet :( Please hop on github and offer up a translation!",zh_CN:"还没翻译 {key} :( 请在gitHub上贡献你的翻译!",fr_FR:"La traduction pour {key} n'existe pas encore :( Venez sur Github pour en offrir une !"},"error-untranslated":{__desc__:"The general error when we encounter a dialog that is not translated",en_US:"This dialog or text is not yet translated in your locale :( Hop on github to aid in translation!",zh_CN:"这段对话还没有被翻译成你的语言 :( 欢迎在gitHub上贡献你的翻译!",fr_FR:"Ce message n'a pas encore été traduit dans votre langue :( Venez sur Github aider à la traduction !"}}}),e("/src/js/intl/strings.js"),e.define("/src/js/level/arbiter.js",function(e,t,n,r,i,s,o){function h(){this.levelMap={},this.levelSequences=f,this.sequences=[],this.init();var e;try{e=JSON.parse(localStorage.getItem("solvedMap")||"{}")}catch(t){console.warn("local storage failed",t)}this.solvedMap=e||{},c.getEvents().on("levelSolved",this.levelSolved,this)}var u=e("underscore"),a=e("backbone"),f=e("../../levels").levelSequences,l=e("../../levels").sequenceInfo,c=e("../app");h.prototype.init=function(){var e;u.each(this.levelSequences,function(e,t){this.sequences.push(t);if(!e||!e.length)throw new Error("no empty sequences allowed");u.each(e,function(e,n){this.validateLevel(e);var r=t+String(n+1),i=u.extend({},e,{index:n,id:r,sequenceName:t});this.levelMap[r]=i,this.levelSequences[t][n]=i},this)},this)},h.prototype.isLevelSolved=function(e){if(!this.levelMap[e])throw new Error("that level doesnt exist!");return Boolean(this.solvedMap[e])},h.prototype.levelSolved=function(e){if(!e)return;this.solvedMap[e]=!0,this.syncToStorage()},h.prototype.resetSolvedMap=function(){this.solvedMap={},this.syncToStorage(),c.getEvents().trigger("levelSolved")},h.prototype.syncToStorage=function(){try{localStorage.setItem("solvedMap",JSON.stringify(this.solvedMap))}catch(e){console.warn("local storage fialed on set",e)}},h.prototype.validateLevel=function(e){e=e||{};var t=["name","goalTreeString","solutionCommand"],n=["hint","disabledMap","startTree"];u.each(t,function(t){if(e[t]===undefined)throw console.log(e),new Error("I need this field for a level: "+t)})},h.prototype.getSequenceToLevels=function(){return this.levelSequences},h.prototype.getSequences=function(){return u.keys(this.levelSequences)},h.prototype.getLevelsInSequence=function(e){if(!this.levelSequences[e])throw new Error("that sequecne name "+e+"does not exist");return this.levelSequences[e]},h.prototype.getSequenceInfo=function(e){return l[e]},h.prototype.getLevel=function(e){return this.levelMap[e]},h.prototype.getNextLevel=function(e){if(!this.levelMap[e])return console.warn("that level doesnt exist!!!"),null;var t=this.levelMap[e],n=t.sequenceName,r=this.levelSequences[n],i=t.index+1;if(i","show commands","show solution","show goal"];throw new v({msg:t.join("\n")})}],[/^locale (\w+)$/,function(t){f.GLOBAL.locale=t[1];var n=e("../app").getEvents().trigger("localeChanged");throw new v({msg:l.str("locale-command",{locale:t[1]})})}],[/^refresh$/,function(){var t=e("../app").getEvents();throw t.trigger("refreshTree"),new v({msg:l.str("refresh-tree-command")})}],[/^rollup (\d+)$/,function(t){var n=e("../app").getEvents();throw n.trigger("rollupCommands",t[1]),new v({msg:"Commands combined!"})}],[/^echo "(.*?)"$|^echo (.*?)$/,function(e){var t=e[1]||e[2];throw new v({msg:t})}],[/^show +commands$/,function(e){var t=y(),n=[l.str("show-all-commands"),"
"];throw u.each(t,function(e,t){n.push(t)}),new v({msg:n.join("\n")})}]],g={"reset solved":/^reset solved($|\s)/,help:/^help( +general)?$|^\?$/,reset:/^reset( +--forSolution)?$/,delay:/^delay (\d+)$/,clear:/^clear($|\s)/,"exit level":/^exit level($|\s)/,sandbox:/^sandbox($|\s)/,level:/^level\s?([a-zA-Z0-9]*)/,levels:/^levels($|\s)/,mobileAlert:/^mobile alert($|\s)/,"build level":/^build +level($|\s)/,"export tree":/^export +tree$/,"import tree":/^import +tree$/,"import level":/^import +level$/,undo:/^undo($|\s)/},y=function(){var t=["mobileAlert"],n=u.extend({},e("../git/commands").regexMap,e("../level").regexMap,g);return u.each(t,function(e){delete n[e]}),n};n.instantCommands=m,n.parse=a.genParseCommand(g,"processSandboxCommand"),n.getOptimisticLevelParse=function(){return a.genParseCommand(e("../level").regexMap,"processLevelCommand")},n.getOptimisticLevelBuilderParse=function(){return a.genParseCommand(e("../level/builder").regexMap,"processLevelBuilderCommand")}}),e("/src/js/level/sandboxCommands.js"),e.define("/src/js/log/index.js",function(e,t,n,r,i,s,o){var u=function(e,t,n){window._gaq=window._gaq||[],window._gaq.push(["_trackEvent",e,t,n])};n.viewInteracted=function(e){u("views","interacted",e)},n.showLevelSolution=function(e){u("levels","showedLevelSolution",e)},n.choseNextLevel=function(e){u("levels","nextLevelChosen",e)},n.levelSelected=function(e){u("levels","levelSelected",e)},n.levelSolved=function(e){u("levels","levelSolved",e)},n.commandEntered=function(e){u("commands","commandEntered",e)}}),e("/src/js/log/index.js"),e.define("/src/js/models/collections.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?f=window.Backbone:f=e("backbone"),l=e("../git").Commit,c=e("../git").Branch,h=e("../models/commandModel").Command,p=e("../models/commandModel").CommandEntry,d=e("../util/constants").TIME,v=f.Collection.extend({model:l}),m=f.Collection.extend({model:h}),g=f.Collection.extend({model:c}),y=f.Collection.extend({model:p,localStorage:f.LocalStorage?new f.LocalStorage("CommandEntries"):null}),b=f.Model.extend({defaults:{collection:null},initialize:function(e){e.collection.bind("add",this.addCommand,this),this.buffer=[],this.timeout=null},addCommand:function(e){this.buffer.push(e),this.touchBuffer()},touchBuffer:function(){if(this.timeout)return;this.setTimeout()},setTimeout:function(){this.timeout=setTimeout(u.bind(function(){this.sipFromBuffer()},this),d.betweenCommandsDelay)},popAndProcess:function(){var e=this.buffer.shift(0);while(e.get("error")&&this.buffer.length)e=this.buffer.shift(0);e.get("error")?this.clear():this.processCommand(e)},processCommand:function(t){t.set("status","processing");var n=a.defer();n.promise.then(u.bind(function(){this.setTimeout()},this));var r=t.get("eventName");if(!r)throw new Error("I need an event to trigger when this guy is parsed and ready");var i=e("../app"),s=i.getEventBaton(),o=s.getNumListeners(r);if(!o){var f=e("../util/errors");t.set("error",new f.GitError({msg:"That command is valid, but not supported in this current environment! Try entering a level or level builder to use that command"})),n.resolve();return}i.getEventBaton().trigger(r,t,n)},clear:function(){clearTimeout(this.timeout),this.timeout=null},sipFromBuffer:function(){if(!this.buffer.length){this.clear();return}this.popAndProcess()}});n.CommitCollection=v,n.CommandCollection=m,n.BranchCollection=g,n.CommandEntryCollection=y,n.CommandBuffer=b}),e("/src/js/models/collections.js"),e.define("/src/js/models/commandModel.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../util/errors"),l=e("../git/commands"),c=l.GitOptionParser,h=e("../level/parseWaterfall").ParseWaterfall,p=f.CommandProcessError,d=f.GitError,v=f.Warning,m=f.CommandResult,g=a.Model.extend({defaults:{status:"inqueue",rawStr:null,result:"",createTime:null,error:null,warnings:null,parseWaterfall:new h,generalArgs:null,supportedMap:null,options:null,method:null},initialize:function(e){this.initDefaults(),this.validateAtInit(),this.on("change:error",this.errorChanged,this),this.get("error")&&this.errorChanged(),this.parseOrCatch()},initDefaults:function(){this.set("generalArgs",[]),this.set("supportedMap",{}),this.set("warnings",[])},validateAtInit:function(){if(this.get("rawStr")===null)throw new Error("Give me a string!");this.get("createTime")||this.set("createTime",(new Date).toString())},setResult:function(e){this.set("result",e)},finishWith:function(e){this.set("status","finished"),e.resolve()},addWarning:function(e){this.get("warnings").push(e),this.set("numWarnings",this.get("numWarnings")?this.get("numWarnings")+1:1)},getFormattedWarnings:function(){if(!this.get("warnings").length)return"";var e='';return"

"+e+this.get("warnings").join("

"+e)+"

"},parseOrCatch:function(){this.expandShortcuts(this.get("rawStr"));try{this.processInstants()}catch(e){f.filterError(e),this.set("error",e);return}if(this.parseAll())return;this.set("error",new p({msg:'The command "'+this.get("rawStr")+"\" isn't supported, sorry!"}))},errorChanged:function(){var e=this.get("error");e instanceof p||e instanceof d?this.set("status","error"):e instanceof m?this.set("status","finished"):e instanceof v&&this.set("status","warning"),this.formatError()},formatError:function(){this.set("result",this.get("error").toResult())},expandShortcuts:function(e){e=this.get("parseWaterfall").expandAllShortcuts(e),this.set("rawStr",e)},processInstants:function(){var e=this.get("rawStr");if(!e.length)throw new m({msg:""});this.get("parseWaterfall").processAllInstants(e)},parseAll:function(){var e=this.get("rawStr"),t=this.get("parseWaterfall").parseAll(e);return t?(u.each(t.toSet,function(e,t){this.set(t,e)},this),!0):!1}}),y=a.Model.extend({defaults:{text:""}});n.CommandEntry=y,n.Command=g}),e("/src/js/models/commandModel.js"),e.define("/src/js/util/constants.js",function(e,t,n,r,i,s,o){var u={betweenCommandsDelay:400},a={isAnimating:!1},f={minZoom:.55,maxZoom:1.25,minWidth:600,minHeight:600},l={arrowHeadSize:8,nodeRadius:17,curveControlPointOffset:50,defaultEasing:"easeInOut",defaultAnimationTime:400,rectFill:"hsb(0.8816909813322127,0.7,1)",headRectFill:"#2831FF",rectStroke:"#FFF",rectStrokeWidth:"3",originDash:"- ",multiBranchY:20,upstreamHeadOpacity:.5,upstreamNoneOpacity:.2,edgeUpstreamHeadOpacity:.4,edgeUpstreamNoneOpacity:.15,visBranchStrokeWidth:2,visBranchStrokeColorNone:"#333",defaultNodeFill:"hsba(0.5,0.8,0.7,1)",defaultNodeStrokeWidth:2,defaultNodeStroke:"#FFF",orphanNodeFill:"hsb(0.5,0.8,0.7)"};n.GLOBAL=a,n.TIME=u,n.GRAPHICS=l,n.VIEWPORT=f}),e("/src/js/util/constants.js"),e.define("/src/js/util/debug.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a={Tree:e("../visuals/tree"),Visuals:e("../visuals"),Git:e("../git"),CommandModel:e("../models/commandModel"),Levels:e("../git/treeCompare"),Constants:e("../util/constants"),Collections:e("../models/collections"),Async:e("../visuals/animation"),AnimationFactory:e("../visuals/animation/animationFactory"),Main:e("../app"),HeadLess:e("../git/headless"),Q:{Q:e("q")},RebaseView:e("../views/rebaseView"),Views:e("../views"),MultiView:e("../views/multiView"),ZoomLevel:e("../util/zoomLevel"),VisBranch:e("../visuals/visBranch"),Level:e("../level"),Sandbox:e("../level/sandbox"),GitDemonstrationView:e("../views/gitDemonstrationView"),Markdown:e("markdown"),LevelDropdownView:e("../views/levelDropdownView"),BuilderViews:e("../views/builderViews"),Intl:e("../intl")};u.each(a,function(e){for(var t in e)window["debug_"+t]=e[t]}),$(document).ready(function(){window.events=a.Main.getEvents(),window.eventBaton=a.Main.getEventBaton(),window.sandbox=a.Main.getSandbox(),window.modules=a,window.levelDropdown=a.Main.getLevelDropdown(),window.under=u,window.copyTree=function(){return a.Main.getSandbox().mainVis.gitEngine.printAndCopyTree()}})}),e("/src/js/util/debug.js"),e.define("/src/js/util/errors.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({defaults:{type:"MyError",msg:"Unknown Error"},toString:function(){return this.get("type")+": "+this.get("msg")},getMsg:function(){return this.get("msg")||"Unknown Error"},toResult:function(){return this.get("msg").length?"

"+this.get("msg").replace(/\n/g,"

")+"

":""}}),l=n.CommandProcessError=f.extend({defaults:{type:"Command Process Error"}}),c=n.CommandResult=f.extend({defaults:{type:"Command Result"}}),h=n.Warning=f.extend({defaults:{type:"Warning"}}),p=n.GitError=f.extend({defaults:{type:"Git Error"}}),d=function(e){if(e instanceof l||e instanceof p||e instanceof c||e instanceof h)return;throw e};n.filterError=d}),e("/src/js/util/errors.js"),e.define("/src/js/util/eventBaton.js",function(e,t,n,r,i,s,o){function a(){this.eventMap={}}var u=e("underscore");a.prototype.stealBaton=function(e,t,n){if(!e)throw new Error("need name");if(!t)throw new Error("need func!");var r=this.eventMap[e]||[];r.push({func:t,context:n}),this.eventMap[e]=r},a.prototype.sliceOffArgs=function(e,t){var n=[];for(var r=e;r0&&!e.length)return;t(e)})},n.genParseCommand=function(e,t){return function(n){var r,i;return u.each(e,function(e,t){var s=e.exec(n);s&&(r=t,i=s)}),r?{toSet:{eventName:t,method:r,regexResults:i}}:!1}}}),e("/src/js/util/index.js"),e.define("/src/js/util/keyboard.js",function(e,t,n,r,i,s,o){function c(e){this.events=e.events||u.clone(a.Events),this.aliasMap=e.aliasMap||{},e.wait||this.listen()}var u=e("underscore"),a=e("backbone"),f=e("../app"),l=function(e){var t={37:"left",38:"up",39:"right",40:"down",27:"esc",13:"enter"};return t[e]};c.prototype.listen=function(){if(this.listening)return;this.listening=!0,f.getEventBaton().stealBaton("docKeydown",this.keydown,this)},c.prototype.mute=function(){this.listening=!1,f.getEventBaton().releaseBaton("docKeydown",this.keydown,this)},c.prototype.keydown=function(e){var t=e.which||e.keyCode,n=l(t);if(n===undefined)return;this.fireEvent(n,e)},c.prototype.fireEvent=function(e,t){e=this.aliasMap[e]||e,this.events.trigger(e,t)},c.prototype.passEventBack=function(e){f.getEventBaton().passBatonBackSoft("docKeydown",this.keydown,this,[e])},n.KeyboardListener=c,n.mapKeycodeToKey=l}),e("/src/js/util/keyboard.js"),e.define("/src/js/util/mock.js",function(e,t,n,r,i,s,o){n.mock=function(e){var t={},n=function(){};for(var r in e.prototype)t[r]=n;return t}}),e("/src/js/util/mock.js"),e.define("/src/js/util/zoomLevel.js",function(e,t,n,r,i,s,o){function f(){return!window.outerWidth||!window.innerWidth?(a&&(console.warn("Can't detect zoom level correctly :-/"),a=!1),1):window.outerWidth/window.innerWidth}var u=e("underscore"),a=!0,l=!0,c=function(e,t){var n=0;setInterval(function(){var r=f();if(r!==n){if(l){l=!1;return}n=r,e.apply(t,[r])}else l=!0},500)};n.setupZoomPoll=c,n.detectZoom=f}),e("/src/js/util/zoomLevel.js"),e.define("/src/js/views/builderViews.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../intl"),h=e("../util/keyboard").KeyboardListener,p=e("../views"),d=p.ModalTerminal,v=p.ContainedBase,m=v.extend({tagName:"div",className:"textGrabber box vertical",template:u.template($("#text-grabber").html()),initialize:function(e){e=e||{},this.JSON={helperText:e.helperText||"Enter some text"},this.container=e.container||new d({title:"Enter some text"}),this.render(),e.initialText&&this.setText(e.initialText),e.wait||this.show()},getText:function(){return this.$("textarea").val()},setText:function(e){this.$("textarea").val(e)}}),g=v.extend({tagName:"div",className:"markdownGrabber box horizontal",template:u.template($("#markdown-grabber-view").html()),events:{"keyup textarea":"keyup"},initialize:function(e){e=e||{},this.deferred=e.deferred||a.defer(),e.fromObj&&(e.fillerText=e.fromObj.options.markdowns.join("\n")),this.JSON={previewText:e.previewText||"Preview",fillerText:e.fillerText||"## Enter some markdown!\n\n\n"},this.container=e.container||new d({title:e.title||"Enter some markdown"}),this.render();if(!e.withoutButton){var t=a.defer();t.promise.then(u.bind(this.confirmed,this)).fail(u.bind(this.cancelled,this)).done();var n=new p.ConfirmCancelView({deferred:t,destination:this.getDestination()})}this.updatePreview(),e.wait||this.show()},confirmed:function(){this.die(),this.deferred.resolve(this.getRawText())},cancelled:function(){this.die(),this.deferred.resolve()},keyup:function(){this.throttledPreview||(this.throttledPreview=u.throttle(u.bind(this.updatePreview,this),500)),this.throttledPreview()},getRawText:function(){return this.$("textarea").val()},exportToArray:function(){return this.getRawText().split("\n")},getExportObj:function(){return{markdowns:this.exportToArray()}},updatePreview:function(){var t=this.getRawText(),n=e("markdown").markdown.toHTML(t);this.$("div.insidePreview").html(n)}}),y=v.extend({tagName:"div",className:"markdownPresenter box vertical",template:u.template($("#markdown-presenter").html()),initialize:function(e){e=e||{},this.deferred=e.deferred||a.defer(),this.JSON={previewText:e.previewText||"Here is something for you",fillerText:e.fillerText||"# Yay"},this.container=new d({title:"Check this out..."}),this.render();if(!e.noConfirmCancel){var t=new p.ConfirmCancelView({destination:this.getDestination()});t.deferred.promise.then(u.bind(function(){this.deferred.resolve(this.grabText())},this)).fail(u.bind(function(){this.deferred.reject()},this)).done(u.bind(this.die,this))}this.show()},grabText:function(){return this.$("textarea").val()}}),b=v.extend({tagName:"div",className:"demonstrationBuilder box vertical",template:u.template($("#demonstration-builder").html()),events:{"click div.testButton":"testView"},initialize:function(e){e=e||{},this.deferred=e.deferred||a.defer();if(e.fromObj){var t=e.fromObj.options;e=u.extend({},e,t,{beforeMarkdown:t.beforeMarkdowns.join("\n"),afterMarkdown:t.afterMarkdowns.join("\n")})}this.JSON={},this.container=new d({title:"Demonstration Builder"}),this.render(),this.beforeMarkdownView=new g({container:this,withoutButton:!0,fillerText:e.beforeMarkdown,previewText:"Before demonstration Markdown"}),this.beforeCommandView=new m({container:this,helperText:"The git command(s) to set up the demonstration view (before it is displayed)",initialText:e.beforeCommand||"git checkout -b bugFix"}),this.commandView=new m({container:this,helperText:"The git command(s) to demonstrate to the reader",initialText:e.command||"git commit"}),this.afterMarkdownView=new g({container:this,withoutButton:!0,fillerText:e.afterMarkdown,previewText:"After demonstration Markdown"});var n=a.defer(),r=new p.ConfirmCancelView({deferred:n,destination:this.getDestination()});n.promise.then(u.bind(this.confirmed,this)).fail(u.bind(this.cancelled,this)).done()},testView:function(){var t=e("../views/multiView").MultiView;new t({childViews:[{type:"GitDemonstrationView",options:this.getExportObj()}]})},getExportObj:function(){return{beforeMarkdowns:this.beforeMarkdownView.exportToArray(),afterMarkdowns:this.afterMarkdownView.exportToArray(),command:this.commandView.getText(),beforeCommand:this.beforeCommandView.getText()}},confirmed:function(){this.die(),this.deferred.resolve(this.getExportObj())},cancelled:function(){this.die(),this.deferred.resolve()},getInsideElement:function(){return this.$(".insideBuilder")[0]}}),w=v.extend({tagName:"div",className:"multiViewBuilder box vertical",template:u.template($("#multi-view-builder").html()),typeToConstructor:{ModalAlert:g,GitDemonstrationView:b},events:{"click div.deleteButton":"deleteOneView","click div.testButton":"testOneView","click div.editButton":"editOneView","click div.testEntireView":"testEntireView","click div.addView":"addView","click div.saveView":"saveView","click div.cancelView":"cancel"},initialize:function(e){e=e||{},this.deferred=e.deferred||a.defer(),this.multiViewJSON=e.multiViewJSON||{},this.JSON={views:this.getChildViews(),supportedViews:u.keys(this.typeToConstructor)},this.container=new d({title:"Build a MultiView!"}),this.render(),this.show()},saveView:function(){this.hide(),this.deferred.resolve(this.multiViewJSON)},cancel:function(){this.hide(),this.deferred.resolve()},addView:function(e){var t=e.target,n=$(t).attr("data-type"),r=a.defer(),i=this.typeToConstructor[n],s=new i({deferred:r});r.promise.then(u.bind(function(){var e={type:n,options:s.getExportObj()};this.addChildViewObj(e)},this)).fail(function(){}).done()},testOneView:function(t){var n=t.target,r=$(n).attr("data-index"),i=this.getChildViews()[r],s=e("../views/multiView").MultiView;new s({childViews:[i]})},testEntireView:function(){var t=e("../views/multiView").MultiView;new t({childViews:this.getChildViews()})},editOneView:function(e){var t=e.target,n=$(t).attr("data-index"),r=$(t).attr("data-type"),i=a.defer(),s=new this.typeToConstructor[r]({deferred:i,fromObj:this.getChildViews()[n]});i.promise.then(u.bind(function(){var e={type:r,options:s.getExportObj()},t=this.getChildViews();t[n]=e,this.setChildViews(t)},this)).fail(function(){}).done()},deleteOneView:function(e){var t=e.target,n=$(t).attr("data-index"),r=this.getChildViews(),i=r.slice(0,n).concat(r.slice(n+1));this.setChildViews(i),this.update()},addChildViewObj:function(e,t){var n=this.getChildViews();n.push(e),this.setChildViews(n),this.update()},setChildViews:function(e){this.multiViewJSON.childViews=e},getChildViews:function(){return this.multiViewJSON.childViews||[]},update:function(){this.JSON.views=this.getChildViews(),this.renderAgain()}});n.MarkdownGrabber=g,n.DemonstrationBuilder=b,n.TextGrabber=m,n.MultiViewBuilder=w,n.MarkdownPresenter=y}),e("/src/js/views/builderViews.js"),e.define("/src/js/views/commandViews.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../models/collections").CommandEntryCollection,l=e("../app"),c=e("../models/commandModel").Command,h=e("../models/commandModel").CommandEntry,p=e("../util/errors"),d=p.Warning,v=e("../util"),m=e("../log"),g=e("../util/keyboard"),y=a.View.extend({initialize:function(e){l.getEvents().on("commandSubmittedPassive",this.addToCommandHistory,this),this.commands=new f,this.commands.fetch({success:u.bind(function(){var e=[];this.commands.each(function(t){e.push(t)}),e.reverse(),this.commands.reset(),u.each(e,function(e){this.commands.add(e)},this)},this)}),this.index=-1,this.commandParagraph=this.$("#prompt p.command")[0],this.commandCursor=this.$("#prompt span.cursor")[0],this.focus(),l.getEvents().on("rollupCommands",this.rollupCommands,this),l.getEventBaton().stealBaton("keydown",this.onKeyDown,this),l.getEventBaton().stealBaton("keyup",this.onKeyUp,this)},events:{"blur #commandTextField":"hideCursor","focus #commandTextField":"showCursor"},blur:function(){this.hideCursor()},focus:function(){this.$("#commandTextField").focus(),this.showCursor()},hideCursor:function(){this.toggleCursor(!1)},showCursor:function(){this.toggleCursor(!0)},toggleCursor:function(e){$(this.commandCursor).toggleClass("shown",e)},onKeyDown:function(e){var t=e.target;this.updatePrompt(t)},onKeyUp:function(e){this.onKeyDown(e);var t={enter:u.bind(function(){this.submit()},this),up:u.bind(function(){this.commandSelectChange(1)},this),down:u.bind(function(){this.commandSelectChange(-1)},this)},n=g.mapKeycodeToKey(e.which||e.keyCode);t[n]!==undefined&&(e.preventDefault(),t[n](),this.onKeyDown(e))},badHtmlEncode:function(e){return e.replace(/&/g,"&").replace(/=this.commands.length||this.index<0){this.clear(),this.index=-1;return}var t=this.commands.toArray()[this.index].get("text");this.setTextField(t)},clearLocalStorage:function(){this.commands.each(function(e){a.sync("delete",e,function(){})},this)},setTextField:function(e){this.$("#commandTextField").val(e)},clear:function(){this.setTextField("")},submit:function(){var e=this.$("#commandTextField").val().replace("\n","");this.clear(),this.submitCommand(e),this.index=-1},rollupCommands:function(e){var t=this.commands.toArray().slice(1,Number(e)+1);t.reverse();var n="";u.each(t,function(e){n+=e.get("text")+";"},this);var r=new h({text:n});this.commands.unshift(r),a.sync("create",r,function(){})},addToCommandHistory:function(e){var t=e.length&&this.index===-1||e.length&&this.index!==-1&&this.commands.toArray()[this.index].get("text")!==e;if(!t)return;var n=new h({text:e});this.commands.unshift(n),a.sync("create",n,function(){}),this.commands.length>100&&this.clearLocalStorage(),m.commandEntered(e)},submitCommand:function(e){l.getEventBaton().trigger("commandSubmitted",e)}}),b=a.View.extend({tagName:"div",model:c,template:u.template($("#command-template").html()),events:{click:"clicked"},clicked:function(e){},initialize:function(){this.model.bind("change",this.wasChanged,this),this.model.bind("destroy",this.remove,this)},wasChanged:function(e,t){var n=t.changes,r=u.keys(n);u.difference(r,["status"]).length===0?this.updateStatus():this.render()},updateStatus:function(){var e=["inqueue","processing","finished"],t={};u.each(e,function(e){t[e]=!1}),t[this.model.get("status")]=!0;var n=this.$("p.commandLine");u.each(t,function(e,t){n.toggleClass(t,e)})},render:function(){var e=u.extend({resultType:"",result:"",formattedWarnings:this.model.getFormattedWarnings()},this.model.toJSON());return this.$el.html(this.template(e)),this},remove:function(){$(this.el).hide()}}),w=a.View.extend({initialize:function(e){this.collection=e.collection,this.collection.on("add",this.addOne,this),this.collection.on("reset",this.addAll,this),this.collection.on("all",this.render,this),this.collection.on("change",this.scrollDown,this),l.getEvents().on("commandScrollDown",this.scrollDown,this),l.getEvents().on("clearOldCommands",this.clearOldCommands,this)},addWarning:function(e){var t=new d({msg:e}),n=new c({error:t,rawStr:"Warning:"});this.collection.add(n)},clearOldCommands:function(){var e=[];this.collection.each(function(t){t.get("status")!=="inqueue"&&t.get("status")!=="processing"&&e.push(t)},this),u.each(e,function(e){e.destroy()},this),this.scrollDown()},scrollDown:function(){var e=$("#commandDisplay")[0],t=$("#terminal")[0],n=e.clientHeight>t.clientHeight||$(window).height() p.uiButton":"positive"},initialize:function(t){t=t||{},this.options=t,this.JSON=u.extend({beforeMarkdowns:["## Git Commits","","Awesome!"],command:"git commit",afterMarkdowns:["Now you have seen it in action","","Go ahead and try the level!"]},t);var n=function(t){return e("markdown").markdown.toHTML(t.join("\n"))};this.JSON.beforeHTML=n(this.JSON.beforeMarkdowns),this.JSON.afterHTML=n(this.JSON.afterMarkdowns),this.container=new p({title:t.title||"Git Demonstration"}),this.render(),this.checkScroll(),this.navEvents=u.clone(f.Events),this.navEvents.on("positive",this.positive,this),this.navEvents.on("negative",this.negative,this),this.keyboardListener=new c({events:this.navEvents,aliasMap:{enter:"positive",right:"positive",left:"negative"},wait:!0}),this.visFinished=!1,this.initVis(),t.wait||this.show()},receiveMetaNav:function(e,t){var n=this;e.navEvents.on("positive",this.positive,this),this.metaContainerView=t},checkScroll:function(){var e=this.$("div.demonstrationText").children(),t=u.map(e,function(e){return e.clientHeight}),n=u.reduce(t,function(e,t){return e+t});np.VIEWPORT.minWidth&&e.h>p.VIEWPORT.minHeight&&this.finish()}}),O=L.extend({initialize:function(e){if(!e||!e.level)throw new Error("need level");this.eventBatonName="zoomChange",this.markdowns=["## That zoom level of "+e.level+" is not supported :-/","Please zoom back to a supported zoom level with Ctrl + and Ctrl -","","(and of course, pull requests to fix this are appreciated :D)"],O.__super__.initialize.apply(this,[e])},batonFired:function(e){e<=p.VIEWPORT.maxZoom&&e>=p.VIEWPORT.minZoom&&this.finish()}}),M=m.extend({tagName:"div",className:"levelToolbarHolder",template:u.template($("#level-toolbar-template").html()),initialize:function(e){e=e||{},this.JSON={name:e.name||"Some level! (unknown name)"},this.beforeDestination=$($("#commandLineHistory div.toolbar")[0]),this.render(),e.wait||s.nextTick(u.bind(this.show,this))},getAnimationTime:function(){return 700},render:function(){var e=this.template(this.JSON);this.$el.html(e),this.beforeDestination.after(this.el)},die:function(){this.hide(),setTimeout(u.bind(function(){this.tearDown()},this),this.getAnimationTime())},hide:function(){this.$("div.toolbar").toggleClass("hidden",!0)},show:function(){this.$("div.toolbar").toggleClass("hidden",!1)}}),_=m.extend({tagName:"div",className:"helperBar transitionAll",template:u.template($("#helper-bar-template").html()),events:{"click a":"onClick"},onClick:function(e){var t=e.target,n=$(t).attr("data-id"),r="on"+n[0].toUpperCase()+n.slice(1)+"Click";this[r].call(this)},show:function(){this.$el.toggleClass("show",!0)},hide:function(){this.$el.toggleClass("show",!1),this.deferred&&this.deferred.resolve()},getItems:function(){return[]},setupChildren:function(){},fireCommand:function(e){l.getEventBaton().trigger("commandSubmitted",e)},showDeferMe:function(e){this.hide();var t=a.defer();e.deferred=t,t.promise.then(u.bind(function(){this.show()},this)),e.show()},onExitClick:function(){this.hide()},initialize:function(e){e=e||{},this.destination=$("body"),this.JSON={items:this.getItems()},this.render(),this.setupChildren(),e.wait||this.show()}}),D=_.extend({getItems:function(){return[{text:"Git Branching",id:"english"},{text:"日本語版リポジトリ",id:"japanese"},{text:"Git 브랜치 배우기",id:"korean"},{text:"学习Git分支",id:"chinese"},{text:"français",id:"french"},{icon:"signout",id:"exit"}]},fireCommand:function(){h.viewInteracted("intlSelect"),_.prototype.fireCommand.apply(this,arguments)},onJapaneseClick:function(){this.fireCommand("locale ja; levels"),this.hide()},onEnglishClick:function(){this.fireCommand("locale en_US; levels"),this.hide()},onKoreanClick:function(){this.fireCommand("locale ko; levels"),this.hide()},onFrenchClick:function(){this.fireCommand("locale fr_FR; levels"),this.hide()},onChineseClick:function(){this.fireCommand("locale zh_CN; levels"),this.hide()}}),P=_.extend({getItems:function(){return[{text:"Levels",id:"levels"},{text:"Reset",id:"reset"},{text:"Undo",id:"undo"},{text:"Objective",id:"objectve"},{text:"Help",id:"help"},{icon:"signout",id:"exit"}]},fireCommand:function(){h.viewInteracted("helperBar"),_.prototype.fireCommand.apply(this,arguments)},onObjectiveClick:function(){this.fireCommand("objective")},onLevelsClick:function(){this.fireCommand("levels")},onResetClick:function(){this.fireCommand("reset")},onUndoClick:function(){this.fireCommand("undo")},onHelpClick:function(){this.fireCommand("help general; git help")}}),H=_.extend({getItems:function(){return[{icon:"question-sign",id:"commands"},{icon:"globe",id:"intl"}]},onIntlClick:function(){this.showDeferMe(this.intlHelper),h.viewInteracted("openIntlBar")},onCommandsClick:function(){this.showDeferMe(this.commandsHelper),h.viewInteracted("openCommandsBar")},setupChildren:function(){this.commandsHelper=new P({wait:!0}),this.intlHelper=new D({wait:!0})}}),B=m.extend({tagName:"div",className:"canvasTerminalHolder box flex1",template:u.template($("#terminal-window-bare-template").html()),events:{"click div.wrapper":"onClick"},initialize:function(e){e=e||{},this.destination=$("body"),this.JSON={title:e.title||c.str("goal-to-reach"),text:e.text||c.str("hide-goal")},this.render(),this.inDom=!0,e.additionalClass&&this.$el.addClass(e.additionalClass)},getAnimationTime:function(){return 700},onClick:function(){this.die()},die:function(){this.slideOut(),this.inDom=!1,setTimeout(u.bind(function(){this.tearDown()},this),this.getAnimationTime())},slideOut:function(){this.slideToggle(!0)},slideIn:function(){this.slideToggle(!1)},slideToggle:function(e){this.$("div.terminal-window-holder").toggleClass("slideOut",e)},getCanvasLocation:function(){return this.$("div.inside")[0]}});n.BaseView=m,n.GeneralButton=w,n.ModalView=x,n.ModalTerminal=T,n.ModalAlert=N,n.ContainedBase=b,n.ConfirmCancelView=E,n.LeftRightView=S,n.ZoomAlertWindow=O,n.ConfirmCancelTerminal=C,n.WindowSizeAlertWindow=A,n.MainHelperBar=H,n.CanvasTerminalHolder=B,n.LevelToolbar=M,n.NextLevelConfirm=k}),e("/src/js/views/index.js"),e.define("/src/js/views/levelDropdownView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../intl"),h=e("../log"),p=e("../util/keyboard").KeyboardListener,d=e("../app"),v=e("../views").ModalTerminal,m=e("../views").ContainedBase,g=e("../views").BaseView,y=m.extend({tagName:"div",className:"levelDropdownView box vertical",template:u.template($("#level-dropdown-view").html()),initialize:function(e){e=e||{},this.JSON={},this.navEvents=u.clone(f.Events),this.navEvents.on("clickedID",u.debounce(u.bind(this.loadLevelID,this),300,!0)),this.navEvents.on("negative",this.negative,this),this.navEvents.on("positive",this.positive,this),this.navEvents.on("left",this.left,this),this.navEvents.on("right",this.right,this),this.navEvents.on("up",this.up,this),this.navEvents.on("down",this.down,this),this.keyboardListener=new p({events:this.navEvents,aliasMap:{esc:"negative",enter:"positive"},wait:!0}),this.sequences=d.getLevelArbiter().getSequences(),this.sequenceToLevels=d.getLevelArbiter().getSequenceToLevels(),this.container=new v({title:c.str("select-a-level")}),this.render(),d.getEvents().on("resetMapSolved",this.render,this),d.getEvents().on("localeChanged",this.render,this),e.wait||this.show()},render:function(){y.__super__.render.apply(this,arguments),this.buildSequences()},positive:function(){if(!this.selectedID)return;this.loadLevelID(this.selectedID)},left:function(){if(this.turnOnKeyboardSelection())return;this.leftOrRight(-1)},leftOrRight:function(e){this.deselectIconByID(this.selectedID),this.selectedIndex=this.wrapIndex(this.selectedIndex+e,this.getCurrentSequence()),this.selectedID=this.getSelectedID(),this.selectIconByID(this.selectedID)},right:function(){if(this.turnOnKeyboardSelection())return;this.leftOrRight(1)},up:function(){if(this.turnOnKeyboardSelection())return;this.selectedSequence=this.getPreviousSequence(),this.downOrUp()},down:function(){if(this.turnOnKeyboardSelection())return;this.selectedSequence=this.getNextSequence(),this.downOrUp()},downOrUp:function(){this.selectedIndex=this.boundIndex(this.selectedIndex,this.getCurrentSequence()),this.deselectIconByID(this.selectedID),this.selectedID=this.getSelectedID(),this.selectIconByID(this.selectedID)},turnOnKeyboardSelection:function(){return this.selectedID?!1:(this.selectFirst(),!0)},turnOffKeyboardSelection:function(){if(!this.selectedID)return;this.deselectIconByID(this.selectedID),this.selectedID=undefined,this.selectedIndex=undefined,this.selectedSequence=undefined},wrapIndex:function(e,t){return e=e>=t.length?0:e,e=e<0?t.length-1:e,e},boundIndex:function(e,t){return e=e>=t.length?t.length-1:e,e=e<0?0:e,e},getNextSequence:function(){var e=this.getSequenceIndex(this.selectedSequence),t=this.wrapIndex(e+1,this.sequences);return this.sequences[t]},getPreviousSequence:function(){var e=this.getSequenceIndex(this.selectedSequence),t=this.wrapIndex(e-1,this.sequences);return this.sequences[t]},getSequenceIndex:function(e){var t=this.sequences.indexOf(e);if(t<0)throw new Error("didnt find");return t},getIndexForID:function(e){return d.getLevelArbiter().getLevel(e).index},selectFirst:function(){var e=this.sequenceToLevels[this.sequences[0]][0].id;this.selectIconByID(e),this.selectedIndex=0,this.selectedSequence=this.sequences[0]},getCurrentSequence:function(){return this.sequenceToLevels[this.selectedSequence]},getSelectedID:function(){return this.sequenceToLevels[this.selectedSequence][this.selectedIndex].id},selectIconByID:function(e){this.toggleIconSelect(e,!0)},deselectIconByID:function(e){this.toggleIconSelect(e,!1)},toggleIconSelect:function(e,t){this.selectedID=e;var n="#levelIcon-"+e;$(n).toggleClass("selected",t)},negative:function(){this.hide()},testOption:function(e){return this.currentCommand&&(new RegExp("--"+e)).test(this.currentCommand.get("rawStr"))},show:function(e,t){this.currentCommand=t,this.updateSolvedStatus(),this.showDeferred=e,this.keyboardListener.listen(),y.__super__.show.apply(this)},hide:function(){this.showDeferred&&this.showDeferred.resolve(),this.showDeferred=undefined,this.keyboardListener.mute(),this.turnOffKeyboardSelection(),y.__super__.hide.apply(this)},loadLevelID:function(e){if(!this.testOption("noOutput")){d.getEventBaton().trigger("commandSubmitted","level "+e);var t=d.getLevelArbiter().getLevel(e),n=t.name.en_US;h.levelSelected(n)}this.hide()},updateSolvedStatus:function(){u.each(this.seriesViews,function(e){e.updateSolvedStatus()},this)},buildSequences:function(){this.seriesViews=[],u.each(this.sequences,function(e){this.seriesViews.push(new b({destination:this.$el,name:e,navEvents:this.navEvents}))},this)}}),b=g.extend({tagName:"div",className:"seriesView box flex1 vertical",template:u.template($("#series-view").html()),events:{"click div.levelIcon":"click","mouseenter div.levelIcon":"enterIcon","mouseleave div.levelIcon":"leaveIcon"},initialize:function(e){this.name=e.name||"intro",this.navEvents=e.navEvents,this.info=d.getLevelArbiter().getSequenceInfo(this.name),this.levels=d.getLevelArbiter().getLevelsInSequence(this.name),this.levelIDs=[],u.each(this.levels,function(e){this.levelIDs.push(e.id)},this),this.destination=e.destination,this.JSON={displayName:c.getIntlKey(this.info,"displayName"),about:c.getIntlKey(this.info,"about")||" ",ids:this.levelIDs},this.render(),this.updateSolvedStatus()},updateSolvedStatus:function(){var e=this.$("div.levelIcon").each(function(e,t){var n=$(t).attr("data-id");$(t).toggleClass("solved",d.getLevelArbiter().isLevelSolved(n))})},getEventID:function(e){var t=e.target;return $(t).attr("data-id")},resetAbout:function(){this.$("p.about").text(c.getIntlKey(this.info,"about")).css("font-style","inherit")},setAbout:function(e){this.$("p.about").text(e).css("font-style","italic")},enterIcon:function(e){var t=this.getEventID(e),n=d.getLevelArbiter().getLevel(t);this.setAbout(c.getName(n))},leaveIcon:function(){this.resetAbout()},click:function(e){var t=this.getEventID(e);this.navEvents.trigger("clickedID",t)}});n.LevelDropdownView=y}),e("/src/js/views/levelDropdownView.js"),e.define("/src/js/views/multiView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../views").ModalTerminal,c=e("../views").ContainedBase,h=e("../views").ConfirmCancelView,p=e("../views").LeftRightView,d=e("../views").ModalAlert,v=e("../views/gitDemonstrationView").GitDemonstrationView,m=e("../views/builderViews"),g=m.MarkdownPresenter,y=e("../util/keyboard").KeyboardListener,b=e("../util/errors").GitError,w=f.View.extend({tagName:"div",className:"multiView",navEventDebounce:550,deathTime:700,typeToConstructor:{ModalAlert:d,GitDemonstrationView:v,MarkdownPresenter:g},initialize:function(e){e=e||{},this.childViewJSONs=e.childViews||[{type:"ModalAlert",options:{markdown:"Woah wtf!!"}},{type:"GitDemonstrationView",options:{command:"git checkout -b side; git commit; git commit"}},{type:"ModalAlert",options:{markdown:"Im second"}}],this.deferred=e.deferred||a.defer(),this.childViews=[],this.currentIndex=0,this.navEvents=u.clone(f.Events),this.navEvents.on("negative",this.getNegFunc(),this),this.navEvents.on("positive",this.getPosFunc(),this),this.navEvents.on("quit",this.finish,this),this.navEvents.on("exit",this.finish,this),this.keyboardListener=new y({events:this.navEvents,aliasMap:{left:"negative",right:"positive",enter:"positive",esc:"quit"}}),this.render(),e.wait||this.start()},onWindowFocus:function(){},getAnimationTime:function(){return 700},getPromise:function(){return this.deferred.promise},getPosFunc:function(){return u.debounce(u.bind(function(){this.navForward()},this),this.navEventDebounce,!0)},getNegFunc:function(){return u.debounce(u.bind(function(){this.navBackward()},this),this.navEventDebounce,!0)},lock:function(){this.locked=!0},unlock:function(){this.locked=!1},navForward:function(){if(this.locked)return;if(this.currentIndex===this.childViews.length-1){this.hideViewIndex(this.currentIndex),this.finish();return}this.navIndexChange(1)},navBackward:function(){if(this.currentIndex===0)return;this.navIndexChange(-1)},navIndexChange:function(e){this.hideViewIndex(this.currentIndex),this.currentIndex+=e,this.showViewIndex(this.currentIndex)},hideViewIndex:function(e){this.childViews[e].hide()},showViewIndex:function(e){this.childViews[e].show()},finish:function(){this.keyboardListener.mute(),u.each(this.childViews,function(e){e.die()}),this.deferred.resolve()},start:function(){this.showViewIndex(this.currentIndex)},createChildView:function(e){var t=e.type;if(!this.typeToConstructor[t])throw new Error('no constructor for type "'+t+'"');var n=new this.typeToConstructor[t](u.extend({},e.options,{wait:!0}));return n},addNavToView:function(e,t){var n=new p({events:this.navEvents,destination:e.getDestination(),showLeft:t!==0,lastNav:t===this.childViewJSONs.length-1});e.receiveMetaNav&&e.receiveMetaNav(n,this)},render:function(){u.each(this.childViewJSONs,function(e,t){var n=this.createChildView(e);this.childViews.push(n),this.addNavToView(n,t)},this)}});n.MultiView=w}),e("/src/js/views/multiView.js"),e.define("/src/js/views/rebaseView.js",function(e,t,n,r,i,s,o){var u=e("../util/errors").GitError,a=e("underscore"),f=e("q"),l=e("../util").isBrowser()?window.Backbone:e("backbone"),c=e("../views").ModalTerminal,h=e("../views").ContainedBase,p=e("../views").ConfirmCancelView,d=e("../views").LeftRightView,v=h.extend({tagName:"div",template:a.template($("#interactive-rebase-template").html()),initialize:function(e){this.deferred=e.deferred,this.rebaseMap={},this.entryObjMap={},this.rebaseEntries=new g,e.toRebase.reverse(),a.each(e.toRebase,function(e){var t=e.get("id");this.rebaseMap[t]=e,this.entryObjMap[t]=new m({id:t}),this.rebaseEntries.add(this.entryObjMap[t])},this),this.container=new c({title:"Interactive Rebase"}),this.render(),this.show()},confirm:function(){this.die();var e=[];this.$("ul.rebaseEntries li").each(function(t,n){e.push(n.id)});var t=[];a.each(e,function(e){this.entryObjMap[e].get("pick")&&t.unshift(this.rebaseMap[e])},this),t.reverse(),this.deferred.resolve(t),this.$el.html("")},render:function(){var e={num:a.keys(this.rebaseMap).length},t=this.container.getInsideElement();this.$el.html(this.template(e)),$(t).append(this.el);var n=this.$("ul.rebaseEntries");this.rebaseEntries.each(function(e){new y({el:n,model:e})},this),n.sortable({axis:"y",placeholder:"rebaseEntry transitionOpacity ui-state-highlight",appendTo:"parent"}),this.makeButtons()},makeButtons:function(){var e=f.defer();e.promise.then(a.bind(function(){this.confirm()},this)).fail(a.bind(function(){this.hide(),this.deferred.resolve([])},this)).done(),new p({destination:this.$(".confirmCancel"),deferred:e})}}),m=l.Model.extend({defaults:{pick:!0},toggle:function(){this.set("pick",!this.get("pick"))}}),g=l.Collection.extend({model:m}),y=l.View.extend({tagName:"li",template:a.template($("#interactive-rebase-entry-template").html()),toggle:function(){this.model.toggle(),this.listEntry.toggleClass("notPicked",!this.model.get("pick"))},initialize:function(e){this.render()},render:function(){var e=this.model.toJSON();this.$el.append(this.template(this.model.toJSON())),this.listEntry=this.$el.children(":last"),this.listEntry.delegate("#toggleButton","click",a.bind(function(){this.toggle()},this))}});n.InteractiveRebaseView=v}),e("/src/js/views/rebaseView.js"),e.define("/src/js/visuals/animation/animationFactory.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("./index").Animation,c=e("./index").PromiseAnimation,h=e("../../util/constants").GRAPHICS,p={},d=function(e,t){var n=h.defaultAnimationTime*1,r=n*2,i=function(){e.refreshTree(n),t.setBirth(),t.parentInFront(),e.visBranchesFront(),t.animateUpdatedPosition(r,"bounce"),t.animateOutgoingEdges(n)};return{animation:i,duration:Math.max(n,r)}},v=function(e,t){var n=h.defaultAnimationTime*.66,r=n*2;return{animation:function(){e.highlightTo(t,r,"easeInOut")},duration:r*1.5}};p.genCommitBirthAnimation=function(e,t,n){if(!e)throw new Error("Need animation queue to add closure to!");var r=t.get("visNode"),i=d(n,r);e.add(new l({closure:i.animation,duration:i.duration}))},p.genCommitBirthPromiseAnimation=function(e,t){var n=e.get("visNode");return new c(d(t,n))},p.highlightEachWithPromise=function(e,t,n){return u.each(t,function(t){e=e.then(u.bind(function(){return this.playHighlightPromiseAnimation(t,n)},this))},this),e},p.playCommitBirthPromiseAnimation=function(e,t){var n=this.genCommitBirthPromiseAnimation(e,t);return n.play(),n.getPromise()},p.playRefreshAnimationAndFinish=function(e,t){var n=new c({closure:function(){e.refreshTree()}});n.play(),t.thenFinish(n.getPromise())},p.playRefreshAnimation=function(e){var t=new c({closure:function(){e.refreshTree()}});return t.play(),t.getPromise()},p.refreshTree=function(e,t){e.add(new l({closure:function(){t.refreshTree()}}))},p.genHighlightPromiseAnimation=function(e,t){var n=t.get("visBranch")||t.get("visNode"),r=e.get("visNode");return new c(v(r,n))},p.playHighlightPromiseAnimation=function(e,t){var n=this.genHighlightPromiseAnimation(e,t);return n.play(),n.getPromise()},p.getDelayedPromise=function(e){var t=f.defer();return setTimeout(t.resolve,e||1e3),t.promise},p.delay=function(e,t){t=t||h.defaultAnimationTime,e.add(new l({closure:function(){},duration:t}))},n.AnimationFactory=p}),e("/src/js/visuals/animation/animationFactory.js"),e.define("/src/js/visuals/animation/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("backbone"),l=e("../../util/constants").GLOBAL,c=f.Model.extend({defaults:{duration:300,closure:null},validateAtInit:function(){if(!this.get("closure"))throw new Error("give me a closure!")},initialize:function(e){this.validateAtInit()},run:function(){this.get("closure")()}}),h=f.Model.extend({defaults:{animations:null,index:0,callback:null,defer:!1,promiseBased:!1},initialize:function(e){this.set("animations",[]),e.callback||console.warn("no callback")},thenFinish:function(e,t){e.then(u.bind(function(){this.finish()},this)),this.set("promiseBased",!0),t&&t.resolve()},add:function(e){if(!e instanceof c)throw new Error("Need animation not something else");this.get("animations").push(e)},start:function(){this.set("index",0),l.isAnimating=!0,this.next()},finish:function(){l.isAnimating=!1,this.get("callback")()},next:function(){var e=this.get("animations"),t=this.get("index");if(t>=e.length){this.finish();return}var n=e[t],r=n.get("duration");n.run(),this.set("index",t+1),setTimeout(u.bind(function(){this.next()},this),r)}}),p=f.Model.extend({defaults:{deferred:null,closure:null,duration:300},initialize:function(e){if(!e.closure&&!e.animation)throw new Error("need closure or animation");this.set("closure",e.closure||e.animation),this.set("deferred",e.deferred||a.defer())},getPromise:function(){return this.get("deferred").promise},play:function(){this.get("closure")(),setTimeout(u.bind(function(){this.get("deferred").resolve()},this),this.get("duration"))},then:function(e){return this.get("deferred").promise.then(e)}});p.fromAnimation=function(e){return new p({closure:e.get("closure"),duration:e.get("duration")})},n.Animation=c,n.PromiseAnimation=p,n.AnimationQueue=h}),e("/src/js/visuals/animation/index.js"),e.define("/src/js/visuals/index.js",function(e,t,n,r,i,s,o){function w(t){t=t||{},this.options=t,this.visualization=t.visualization,this.commitCollection=t.commitCollection,this.branchCollection=t.branchCollection,this.visNodeMap={},this.visEdgeCollection=new b,this.visBranchCollection=new g,this.commitMap={},this.rootCommit=null,this.branchStackMap=null,this.upstreamBranchSet=null,this.upstreamHeadSet=null,this.paper=t.paper,this.gitReady=!1,this.branchCollection.on("add",this.addBranchFromEvent,this),this.branchCollection.on("remove",this.removeBranch,this),this.deferred=[],this.flipFraction=.65;var n=e("../app");n.getEvents().on("refreshTree",this.refreshTree,this)}function E(e){var t=0,n=0,r=0,i=0,s=e.length;u.each(e,function(e){var s=e.split("(")[1];s=s.split(")")[0],s=s.split(","),r+=parseFloat(s[1]),i+=parseFloat(s[2]);var o=parseFloat(s[0]),u=o*Math.PI*2;t+=Math.cos(u),n+=Math.sin(u)}),t/=s,n/=s,r/=s,i/=s;var o=Math.atan2(n,t)/(Math.PI*2);return o<0&&(o+=1),"hsb("+String(o)+","+String(r)+","+String(i)+")"}var u=e("underscore"),a=e("q"),f=e("backbone"),l=e("../util/constants").GRAPHICS,c=e("../util/constants").GLOBAL,h=e("../models/collections"),p=h.CommitCollection,d=h.BranchCollection,v=e("../visuals/visNode").VisNode,m=e("../visuals/visBranch").VisBranch,g=e("../visuals/visBranch").VisBranchCollection,y=e("../visuals/visEdge").VisEdge,b=e("../visuals/visEdge").VisEdgeCollection;w.prototype.defer=function(e){this.deferred.push(e)},w.prototype.deferFlush=function(){u.each(this.deferred,function(e){e()},this),this.deferred=[]},w.prototype.resetAll=function(){var e=this.visEdgeCollection.toArray();u.each(e,function(e){e.remove()},this);var t=this.visBranchCollection.toArray();u.each(t,function(e){e.remove()},this),u.each(this.visNodeMap,function(e){e.remove()},this),this.visEdgeCollection.reset(),this.visBranchCollection.reset(),this.visNodeMap={},this.rootCommit=null,this.commitMap={}},w.prototype.tearDown=function(){this.resetAll(),this.paper.remove()},w.prototype.assignGitEngine=function(e){this.gitEngine=e,this.initHeadBranch(),this.deferFlush()},w.prototype.getVisualization=function(){return this.visualization},w.prototype.initHeadBranch=function(){this.addBranchFromEvent(this.gitEngine.HEAD)},w.prototype.getScreenPadding=function(){return{widthPadding:l.nodeRadius*1.5,topHeightPadding:l.nodeRadius*1.5,bottomHeightPadding:l.nodeRadius*5}},w.prototype.getPosBoundaries=function(){return this.gitEngine.hasOrigin()?{min:0,max:.5}:this.gitEngine.isOrigin()?{min:.5,max:1}:{min:0,max:1}},w.prototype.getFlipPos=function(){var e=this.getPosBoundaries(),t=e.min,n=e.max;return this.flipFraction*(n-t)+t},w.prototype.toScreenCoords=function(e){if(!this.paper.width)throw new Error("being called too early for screen coords");var t=this.getScreenPadding(),n=function(e,t,n){return n+e*(t-n*2)},r=function(e,t,n,r){return n+e*(t-r-n)};return{x:n(e.x,this.paper.width,t.widthPadding),y:r(e.y,this.paper.height,t.topHeightPadding,t.bottomHeightPadding)}},w.prototype.animateAllAttrKeys=function(e,t,n,r){var i=a.defer(),s=function(i){i.animateAttrKeys(e,t,n,r)};this.visBranchCollection.each(s),this.visEdgeCollection.each(s),u.each(this.visNodeMap,s);var o=n!==undefined?n:l.defaultAnimationTime;return setTimeout(function(){i.resolve()},o),i.promise},w.prototype.finishAnimation=function(){var e=this,t=a.defer(),n=a.defer(),r=l.defaultAnimationTime,i=l.nodeRadius,s="Solved!!\n:D",o=null,f=u.bind(function(){o=this.paper.text(this.paper.width/2,this.paper.height/2,s),o.attr({opacity:0,"font-weight":500,"font-size":"32pt","font-family":"Monaco, Courier, font-monospace",stroke:"#000","stroke-width":2,fill:"#000"}),o.animate({opacity:1},r)},this);return t.promise.then(u.bind(function(){return this.animateAllAttrKeys({exclude:["circle"]},{opacity:0},r*1.1)},this)).then(u.bind(function(){return this.animateAllAttrKeys({exclude:["arrow","rect","path","text"]},{r:i*2},r*1.5)},this)).then(u.bind(function(){return this.animateAllAttrKeys({exclude:["arrow","rect","path","text"]},{r:i*.75},r*.5)},this)).then(u.bind(function(){return f(),this.explodeNodes()},this)).then(u.bind(function(){return this.explodeNodes()},this)).then(u.bind(function(){return this.animateAllAttrKeys({exclude:["arrow","rect","path","text"]},{},r*1.25)},this)).then(u.bind(function(){return o.animate({opacity:0},r,undefined,undefined,function(){o.remove()}),this.animateAllAttrKeys({},{})},this)).then(function(){n.resolve()}).fail(function(e){console.warn("animation error"+e)}).done(),t.resolve(),n.promise},w.prototype.explodeNodes=function(){var e=a.defer(),t=[];u.each(this.visNodeMap,function(e){t.push(e.getExplodeStepFunc())});var n=setInterval(function(){var r=[];u.each(t,function(e){e()&&r.push(e)});if(!r.length){clearInterval(n),e.resolve();return}t=r},.025);return e.promise},w.prototype.animateAllFromAttrToAttr=function(e,t,n){var r=function(r){var i=r.getID();if(u.include(n,i))return;if(!e[i]||!t[i])return;r.animateFromAttrToAttr(e[i],t[i])};this.visBranchCollection.each(r),this.visEdgeCollection.each(r),u.each(this.visNodeMap,r)},w.prototype.genSnapshot=function(){this.fullCalc();var e={};return u.each(this.visNodeMap,function(t){e[t.get("id")]=t.getAttributes()},this),this.visBranchCollection.each(function(t){e[t.getID()]=t.getAttributes()},this),this.visEdgeCollection.each(function(t){e[t.getID()]=t.getAttributes()},this),e},w.prototype.refreshTree=function(e){if(!this.gitReady||!this.gitEngine.rootCommit)return;this.fullCalc(),this.animateAll(e)},w.prototype.refreshTreeHarsh=function(){this.fullCalc(),this.animateAll(0)},w.prototype.animateAll=function(e){this.zIndexReflow(),this.animateEdges(e),this.animateNodePositions(e),this.animateRefs(e)},w.prototype.fullCalc=function(){this.calcTreeCoords(),this.calcGraphicsCoords()},w.prototype.calcTreeCoords=function(){if(!this.rootCommit)throw new Error("grr, no root commit!");this.calcUpstreamSets(),this.calcBranchStacks(),this.calcDepth(),this.calcWidth()},w.prototype.calcGraphicsCoords=function(){this.visBranchCollection.each(function(e){e.updateName()})},w.prototype.calcUpstreamSets=function(){this.upstreamBranchSet=this.gitEngine.getUpstreamBranchSet(),this.upstreamHeadSet=this.gitEngine.getUpstreamHeadSet()},w.prototype.getCommitUpstreamBranches=function(e){return this.branchStackMap[e.get("id")]},w.prototype.getBlendedHuesForCommit=function(e){var t=this.upstreamBranchSet[e.get("id")];if(!t)throw new Error("that commit doesnt have upstream branches!");return this.blendHuesFromBranchStack(t)},w.prototype.blendHuesFromBranchStack=function(e){var t=[];return u.each(e,function(e){var n=e.obj.get("visBranch").get("fill");if(n.slice(0,3)!=="hsb"){var r=Raphael.color(n);n="hsb("+String(r.h)+","+String(r.l),n=n+","+String(r.s)+")"}t.push(n)}),E(t)},w.prototype.getCommitUpstreamStatus=function(e){if(!this.upstreamBranchSet)throw new Error("Can't calculate this yet!");var t=e.get("id"),n=this.upstreamBranchSet,r=this.upstreamHeadSet;return n[t]?"branch":r[t]?"head":"none"},w.prototype.calcBranchStacks=function(){var e=this.gitEngine.getBranches(),t={};u.each(e,function(e){var n=e.target.get("id");t[n]=t[n]||[],t[n].push(e),t[n].sort(function(e,t){var n=e.obj.get("id"),r=t.obj.get("id");return n=="master"||r=="master"?n=="master"?-1:1:n.localeCompare(r)})}),this.branchStackMap=t},w.prototype.calcWidth=function(){this.maxWidthRecursive(this.rootCommit);var e=this.getPosBoundaries();this.assignBoundsRecursive(this.rootCommit,e.min,e.max)},w.prototype.maxWidthRecursive=function(e){var t=0;u.each(e.get("children"),function(n){if(n.isMainParent(e)){var r=this.maxWidthRecursive(n);t+=r}},this);var n=Math.max(1,t);return e.get("visNode").set("maxWidth",n),n},w.prototype.assignBoundsRecursive=function(e,t,n){var r=(n+t)/2;e.get("visNode").get("pos").x=r;if(e.get("children").length===0)return;var i=n-t,s=0,o=e.get("children");u.each(o,function(t){t.isMainParent(e)&&(s+=t.get("visNode").getMaxWidthScaled())},this);var a=t;u.each(o,function(t,n){if(!t.isMainParent(e))return;var r=t.get("visNode").getMaxWidthScaled(),o=r/s*i,u=a,f=u+o;this.assignBoundsRecursive(t,u,f),a=u+o},this)},w.prototype.calcDepth=function(){var e=this.calcDepthRecursive(this.rootCommit,0);e>15&&console.warn("graphics are degrading from too many layers");var t=this.getDepthIncrement(e);u.each(this.visNodeMap,function(e){e.setDepthBasedOn(t,this.getHeaderOffset())},this)},w.prototype.animateNodePositions=function(e){u.each(this.visNodeMap,function(t){t.animateUpdatedPosition(e)},this)},w.prototype.addBranchFromEvent=function(e,t,n){var r=u.bind(function(){this.addBranch(e)},this);!this.gitEngine||!this.gitReady?this.defer(r):r()},w.prototype.addBranch=function(e){var t=new m({branch:e,gitVisuals:this,gitEngine:this.gitEngine});this.visBranchCollection.add(t),this.gitReady?t.genGraphics(this.paper):this.defer(u.bind(function(){t.genGraphics(this.paper)},this))},w.prototype.removeVisBranch=function(e){this.visBranchCollection.remove(e)},w.prototype.removeVisNode=function(e){this.visNodeMap[e.getID()]=undefined},w.prototype.removeVisEdge=function(e){this.visEdgeCollection.remove(e)},w.prototype.animateRefs=function(e){this.visBranchCollection.each(function(t){t.animateUpdatedPos(e)},this)},w.prototype.animateEdges=function(e){this.visEdgeCollection.each(function(t){t.animateUpdatedPath(e)},this)},w.prototype.getMinLayers=function(){return this.options.smallCanvas?2:7},w.prototype.getDepthIncrement=function(e){e=Math.max(e,this.getMinLayers());var t=1-this.getHeaderOffset(),n=t/e;return n},w.prototype.shouldHaveHeader=function(){return this.gitEngine.isOrigin()||this.gitEngine.hasOrigin()},w.prototype.getHeaderOffset=function(){return this.shouldHaveHeader()?.05:0},w.prototype.calcDepthRecursive=function(e,t){e.get("visNode").setDepth(t);var n=e.get("children"),r=t;return u.each(n,function(e){var n=this.calcDepthRecursive(e,t+1);r=Math.max(n,r)},this),r},w.prototype.canvasResize=function(e,t){this.resizeFunc||this.genResizeFunc(),this.resizeFunc(e,t)},w.prototype.genResizeFunc=function(){this.resizeFunc=u.debounce(u.bind(function(t,n){this.refreshTree()},this),200,!0)},w.prototype.addNode=function(e,t){this.commitMap[e]=t,t.get("rootCommit")&&(this.rootCommit=t);var n=new v({id:e,commit:t,gitVisuals:this,gitEngine:this.gitEngine});return this.visNodeMap[e]=n,this.gitReady&&n.genGraphics(this.paper),n},w.prototype.addEdge=function(e,t){var n=this.visNodeMap[e],r=this.visNodeMap[t];if(!n||!r)throw new Error("one of the ids in ("+e+", "+t+") does not exist");var i=new y({tail:n,head:r,gitVisuals:this,gitEngine:this.gitEngine});this.visEdgeCollection.add(i),this.gitReady&&i.genGraphics(this.paper)},w.prototype.zIndexReflow=function(){this.visNodesFront(),this.visBranchesFront()},w.prototype.visNodesFront=function(){u.each(this.visNodeMap,function(e){e.toFront()})},w.prototype.visBranchesFront=function(){this.visBranchCollection.each(function(e){e.nonTextToFront(),e.textToFront()}),this.visBranchCollection.each(function(e){e.textToFrontIfInStack()})},w.prototype.drawTreeFromReload=function(){this.gitReady=!0,this.deferFlush(),this.calcTreeCoords()},w.prototype.drawTreeFirstTime=function(){this.gitReady=!0,this.calcTreeCoords(),u.each(this.visNodeMap,function(e){e.genGraphics(this.paper)},this),this.visEdgeCollection.each(function(e){e.genGraphics(this.paper)},this),this.visBranchCollection.each(function(e){e.genGraphics(this.paper)},this),this.zIndexReflow()},n.GitVisuals=w}),e("/src/js/visuals/index.js"),e.define("/src/js/visuals/tree.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({removeKeys:function(e){u.each(e,function(e){this.get(e)&&this.get(e).remove()},this)},animateAttrKeys:function(e,t,n,r){e=u.extend({},{include:["circle","arrow","rect","path","text"],exclude:[]},e||{});var i=this.getAttributes();u.each(e.include,function(e){i[e]=u.extend({},i[e],t)}),u.each(e.exclude,function(e){delete i[e]}),this.animateToAttr(i,n,r)}});n.VisBase=f}),e("/src/js/visuals/tree.js"),e.define("/src/js/visuals/visBase.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({removeKeys:function(e){u.each(e,function(e){this.get(e)&&this.get(e).remove()},this)},getNonAnimateKeys:function(){return["stroke-dasharray"]},getIsInOrigin:function(){return this.get("gitEngine")?this.get("gitEngine").isOrigin():!1},animateToAttr:function(e,t,n){if(t===0){this.setAttr(e,!0);return}var r=t!==undefined?t:this.get("animationSpeed"),i=n||this.get("animationEasing");this.setAttr(e,!1,r,i)},setAttrBase:function(e,t,n,r,i){u.each(e,function(e){n?this.get(e).attr(t[e]):(this.get(e).stop(),this.get(e).animate(t[e],r,i),u.forEach(this.getNonAnimateKeys(),function(n){t[e]&&t[e][n]!==undefined&&this.get(e).attr(n,t[e][n])},this)),t.css&&$(this.get(e).node).css(t.css)},this)},animateAttrKeys:function(e,t,n,r){e=u.extend({},{include:["circle","arrow","rect","path","text"],exclude:[]},e||{});var i=this.getAttributes();u.each(e.include,function(e){i[e]=u.extend({},i[e],t)}),u.each(e.exclude,function(e){delete i[e]}),this.animateToAttr(i,n,r)}});n.VisBase=f}),e("/src/js/visuals/visBase.js"),e.define("/src/js/visuals/visBranch.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=function(){var e=Math.random(),t="hsb("+String(e)+",0.7,1)";return t},h=l.extend({defaults:{pos:null,text:null,rect:null,arrow:null,isHead:!1,flip:1,fill:f.rectFill,stroke:f.rectStroke,"stroke-width":f.rectStrokeWidth,offsetX:f.nodeRadius*4.75,offsetY:0,arrowHeight:14,arrowInnerSkew:0,arrowEdgeHeight:6,arrowLength:14,arrowOffsetFromCircleX:10,vPad:5,hPad:5,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing},validateAtInit:function(){if(!this.get("branch"))throw new Error("need a branch!")},getID:function(){return this.get("branch").get("id")},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine");if(!this.gitEngine)throw new Error("asd wtf");this.get("branch").set("visBranch",this);var e=this.get("branch").get("id");e=="HEAD"?(this.set("isHead",!0),this.set("flip",-1),this.refreshOffset(),this.set("fill",f.headRectFill)):e!=="master"&&this.set("fill",c())},getCommitPosition:function(){var e=this.gitEngine.getCommitFromRef(this.get("branch")),t=e.get("visNode");return this.set("flip",this.getFlipValue(e,t)),this.refreshOffset(),t.getScreenCoords()},getFlipValue:function(e,t){var n=this.get("gitVisuals").getFlipPos(),r=t.get("pos").x>n;return e.get("id")==="C0"?-1:this.get("isHead")?r?this.isBranchStackEmpty()?-1:1:this.isBranchStackEmpty()?1:-1:r?-1:1},refreshOffset:function(){var e=f.nodeRadius*4.75,t=33,n=10;this.get("flip")===1?(this.set("offsetY",-t),this.set("offsetX",e-n)):(this.set("offsetY",t),this.set("offsetX",e-n))},getArrowTransform:function(){return this.get("flip")===1?"t-2,-20R-35":"t2,20R-35"},getBranchStackIndex:function(){if(this.get("isHead"))return 0;var e=this.getBranchStackArray(),t=-1;return u.each(e,function(e,n){e.obj==this.get("branch")&&(t=n)},this),t},getBranchStackLength:function(){return this.get("isHead")?1:this.getBranchStackArray().length},isBranchStackEmpty:function(){var e=this.gitVisuals.branchStackMap[this.getCommitID()];return e?e.length===0:!0},getCommitID:function(){var e=this.get("branch").get("target");return e.get("type")==="branch"&&(e=e.get("target")),e.get("id")},getBranchStackArray:function(){var e=this.gitVisuals.branchStackMap[this.getCommitID()];return e===undefined?(this.gitVisuals.calcBranchStacks(),this.getBranchStackArray()):e},getTextPosition:function(){var e=this.getCommitPosition(),t=this.getBranchStackIndex();return{x:e.x+this.get("flip")*this.get("offsetX"),y:e.y+t*f.multiBranchY+this.get("offsetY")}},getRectPosition:function(){var e=this.getTextPosition(),t=this.get("flip"),n=this.getTextSize();return{x:e.x-.5*n.w-this.get("hPad"),y:e.y-.5*n.h-this.get("vPad")}},getArrowPath:function(){var e=function(e,t,n){return{x:e.x+t,y:e.y+n}},t=function(e){return String(Math.round(e.x))+","+String(Math.round(e.y))},n=this.get("flip"),r=e(this.getCommitPosition(),n*this.get("arrowOffsetFromCircleX"),0),i=e(r,n*this.get("arrowLength"),-this.get("arrowHeight")),s=e(r,n*this.get("arrowLength"),this.get("arrowHeight")),o=e(i,n*this.get("arrowInnerSkew"),this.get("arrowEdgeHeight")),a=e(s,n*this.get("arrowInnerSkew"),-this.get("arrowEdgeHeight")),f=49,l=e(o,n*f,0),c=e(a,n*f,0),h="";h+="M"+t(l)+" ";var p=[o,i,r,s,a,c];return u.each(p,function(e){h+="L"+t(e)+" "},this),h+="z",h},getTextSize:function(){var e=function(e){var t=e.get("text")?e.get("text").node:null;return t===null?0:t.clientWidth},t=function(e){return e.w||(e.w=75),e.h||(e.h=20),e},n=this.get("text").node;if(this.get("isHead"))return t({w:n.clientWidth,h:n.clientHeight});var r=0;return u.each(this.getBranchStackArray(),function(t){r=Math.max(r,e(t.obj.get("visBranch")))}),t({w:r,h:n.clientHeight})},getSingleRectSize:function(){var e=this.getTextSize(),t=this.get("vPad"),n=this.get("hPad");return{w:e.w+t*2,h:e.h+n*2}},getRectSize:function(){var e=this.getTextSize(),t=this.get("vPad"),n=this.get("hPad"),r=this.getBranchStackLength();return{w:e.w+t*2,h:e.h*r*1.1+n*2}},getIsRemote:function(){return this.get("branch").getIsRemote()},getName:function(){var e=this.get("branch").getName(),t=this.get("branch")===this.gitEngine.HEAD.get("target"),n=this.getIsRemote(),r=t&&!this.getIsInOrigin()&&!n?"*":"";return e+r},nonTextToFront:function(){this.get("arrow").toFront(),this.get("rect").toFront()},textToFront:function(){this.get("text").toFront()},textToFrontIfInStack:function(){this.getBranchStackIndex()!==0&&this.get("text").toFront()},getFill:function(){return this.get("isHead")||this.getBranchStackLength()==1||this.getBranchStackIndex()!==0?this.get("fill"):this.gitVisuals.blendHuesFromBranchStack(this.getBranchStackArray())},remove:function(){this.removeKeys(["text","arrow","rect"]),this.gitVisuals.removeVisBranch(this)},genGraphics:function(e){var t=this.getTextPosition(),n=this.getName(),r;r=e.text(t.x,t.y,String(n)),r.attr({"font-size":14,"font-family":"Monaco, Courier, font-monospace",opacity:this.getTextOpacity()}),this.set("text",r);var i=this.getAttributes(),s=this.getRectPosition(),o=this.getRectSize(),a=e.rect(s.x,s.y,o.w,o.h,8).attr(i.rect);this.set("rect",a);var f=this.getArrowPath(),l=e.path(f).attr(i.arrow);this.set("arrow",l);var c=["text","rect","arrow"];u.each(c,function(e){$(this.get(e).node).css(i.css)},this),this.attachClickHandlers(),a.toFront(),r.toFront()},attachClickHandlers:function(){if(this.get("gitVisuals").options.noClick)return;var e=[this.get("rect"),this.get("text"),this.get("arrow")];u.each(e,function(e){e.click(u.bind(this.onClick,this))},this)},shouldDisableClick:function(){return this.get("isHead")&&!this.gitEngine.getDetachedHead()},onClick:function(){if(this.shouldDisableClick())return;var t="git checkout "+this.get("branch").get("id"),n=e("../app");n.getEventBaton().trigger("commandSubmitted",t)},updateName:function(){this.get("text").attr({text:this.getName()})},getNonTextOpacity:function(){return this.get("isHead")?this.gitEngine.getDetachedHead()?1:0:this.getBranchStackIndex()===0?1:0},getTextOpacity:function(){return this.get("isHead")?this.gitEngine.getDetachedHead()?1:0:1},getAttributes:function(){var e=this.getNonTextOpacity(),t=this.getTextOpacity();this.updateName();var n=this.getTextPosition(),r=this.getRectPosition(),i=this.getRectSize(),s=this.getArrowPath(),o=this.getIsInOrigin()?f.originDash:"",u=this.shouldDisableClick()?"auto":"pointer";return{css:{cursor:u},text:{x:n.x,y:n.y,opacity:t},rect:{x:r.x,y:r.y,width:i.w,height:i.h,opacity:e,fill:this.getFill(),stroke:this.get("stroke"),"stroke-width":this.get("stroke-width")},arrow:{path:s,opacity:e,fill:this.getFill(),stroke:this.get("stroke"),transform:this.getArrowTransform(),"stroke-width":this.get("stroke-width")}}},animateUpdatedPos:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},setAttr:function(e,t,n,r){var i=["text","rect","arrow"];this.setAttrBase(i,e,t,n,r)}}),p=a.Collection.extend({model:h});n.VisBranchCollection=p,n.VisBranch=h,n.randomHueString=c}),e("/src/js/visuals/visBranch.js"),e.define("/src/js/visuals/visEdge.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=l.extend({defaults:{tail:null,head:null,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing},validateAtInit:function(){var e=["tail","head"];u.each(e,function(e){if(!this.get(e))throw new Error(e+" is required!")},this)},getID:function(){return this.get("tail").get("id")+"."+this.get("head").get("id")},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine"),this.get("tail").get("outgoingEdges").push(this)},remove:function(){this.removeKeys(["path"]),this.gitVisuals.removeVisEdge(this)},genSmoothBezierPathString:function(e,t){var n=e.getScreenCoords(),r=t.getScreenCoords();return this.genSmoothBezierPathStringFromCoords(n,r)},genSmoothBezierPathStringFromCoords:function(e,t){var n=function(e){return String(Math.round(e.x))+","+String(Math.round(e.y))},r=function(e,t,n){return n=n||f.curveControlPointOffset,{x:e.x,y:e.y+n*t}},i=function(e,t,n){return{x:e.x+t,y:e.y+n}};e=r(e,-1,this.get("tail").getRadius()),t=r(t,1,this.get("head").getRadius());var s="";s+="M"+n(e)+" ",s+="C",s+=n(r(e,-1))+" ",s+=n(r(t,1))+" ",s+=n(t);var o=f.arrowHeadSize||10;return s+=" L"+n(i(t,-o,o)),s+=" L"+n(i(t,o,o)),s+=" L"+n(t),s+="C",s+=n(r(t,1))+" ",s+=n(r(e,-1))+" ",s+=n(e),s},getBezierCurve:function(){return this.genSmoothBezierPathString(this.get("tail"),this.get("head"))},getStrokeColor:function(){return f.visBranchStrokeColorNone},setOpacity:function(e){e=e===undefined?1:e,this.get("path").attr({opacity:e})},genGraphics:function(e){var t=this.getBezierCurve(),n=e.path(t).attr({"stroke-width":f.visBranchStrokeWidth,stroke:this.getStrokeColor(),"stroke-linecap":"round","stroke-linejoin":"round",fill:this.getStrokeColor()});n.toBack(),this.set("path",n)},getOpacity:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("tail")),t={branch:1,head:f.edgeUpstreamHeadOpacity,none:f.edgeUpstreamNoneOpacity};if(t[e]===undefined)throw new Error("bad stat");return t[e]},getAttributes:function(){var e=this.getBezierCurve(),t=this.getOpacity();return{path:{path:e,opacity:t}}},animateUpdatedPath:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},animateToAttr:function(e,t,n){if(t===0){this.get("path").attr(e.path);return}this.get("path").toBack(),this.get("path").stop(),this.get("path").animate(e.path,t!==undefined?t:this.get("animationSpeed"),n||this.get("animationEasing"))}}),h=a.Collection.extend({model:c});n.VisEdgeCollection=h,n.VisEdge=c}),e("/src/js/visuals/visEdge.js"),e.define("/src/js/visuals/visNode.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=l.extend({defaults:{depth:undefined,maxWidth:null,outgoingEdges:null,circle:null,text:null,id:null,pos:null,radius:null,commit:null,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing,fill:f.defaultNodeFill,"stroke-width":f.defaultNodeStrokeWidth,stroke:f.defaultNodeStroke},getID:function(){return this.get("id")},validateAtInit:function(){if(!this.get("id"))throw new Error("need id for mapping");if(!this.get("commit"))throw new Error("need commit for linking");this.get("pos")||this.set("pos",{x:Math.random(),y:Math.random()})},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine"),this.set("outgoingEdges",[])},setDepth:function(e){this.set("depth",Math.max(this.get("depth")||0,e))},setDepthBasedOn:function(e,t){if(this.get("depth")===undefined)throw new Error("no depth yet!");var n=this.get("pos");n.y=this.get("depth")*e+t},getMaxWidthScaled:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("commit")),t={branch:1,head:.3,none:.1};if(t[e]===undefined)throw new Error("bad stat");return t[e]*this.get("maxWidth")},toFront:function(){this.get("circle").toFront(),this.get("text").toFront()},getOpacity:function(){var e={branch:1,head:f.upstreamHeadOpacity,none:f.upstreamNoneOpacity},t=this.gitVisuals.getCommitUpstreamStatus(this.get("commit"));if(e[t]===undefined)throw new Error("invalid status");return e[t]},getTextScreenCoords:function(){return this.getScreenCoords()},getAttributes:function(){var e=this.getScreenCoords(),t=this.getTextScreenCoords(),n=this.getOpacity(),r=this.getIsInOrigin()?f.originDash:"";return{circle:{cx:e.x,cy:e.y,opacity:n,r:this.getRadius(),fill:this.getFill(),"stroke-width":this.get("stroke-width"),"stroke-dasharray":r,stroke:this.get("stroke")},text:{x:t.x,y:t.y,opacity:n}}},highlightTo:function(e,t,n){var r=e.get("fill"),i={circle:{fill:r,stroke:r,"stroke-dasharray":"","stroke-width":this.get("stroke-width")*5},text:{}};this.animateToAttr(i,t,n)},animateUpdatedPosition:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},animateToSnapshot:function(e,t,n){if(!e[this.getID()])return;this.animateToAttr(e[this.getID()],t,n)},setAttr:function(e,t,n,r){var i=["text","circle"];this.setAttrBase(i,e,t,n,r)},animateToAttr:function(e,t,n){l.prototype.animateToAttr.apply(this,arguments);var r=t!==undefined?t:this.get("animationSpeed"),i=n||this.get("animationEasing");n=="bounce"&&e.circle&&e.circle.cx!==undefined&&e.text&&e.text.x!==undefined&&(this.get("circle").animate(e.circle.cx,r,"easeInOut"),this.get("text").animate(e.text.x,r,"easeInOut"))},getScreenCoords:function(){var e=this.get("pos");return this.gitVisuals.toScreenCoords(e)},getRadius:function(){return this.get("radius")||f.nodeRadius},getParentScreenCoords:function(){return this.get("commit").get("parents")[0].get("visNode").getScreenCoords()},setBirthPosition:function(){var e=this.getParentScreenCoords();this.get("circle").attr({cx:e.x,cy:e.y,opacity:0,r:0}),this.get("text").attr({x:e.x,y:e.y,opacity:0})},setBirthFromSnapshot:function(e){var t=this.get("commit").get("parents")[0].get("visNode").getID(),n=e[t];this.get("circle").attr({opacity:0,r:0,cx:n.circle.cx,cy:n.circle.cy}),this.get("text").attr({opacity:0,x:n.text.x,y:n.text.y});var r={x:n.circle.cx,y:n.circle.cy};this.setOutgoingEdgesBirthPosition(r)},setBirth:function(){this.setBirthPosition(),this.setOutgoingEdgesBirthPosition(this.getParentScreenCoords())},setOutgoingEdgesOpacity:function(e){u.each(this.get("outgoingEdges"),function(t){t.setOpacity(e)})},animateOutgoingEdgesToAttr:function(e,t,n){u.each(this.get("outgoingEdges"),function(t){var n=e[t.getID()];t.animateToAttr(n)},this)},animateOutgoingEdges:function(e,t){u.each(this.get("outgoingEdges"),function(n){n.animateUpdatedPath(e,t)},this)},animateOutgoingEdgesFromSnapshot:function(e,t,n){u.each(this.get("outgoingEdges"),function(r){var i=e[r.getID()];r.animateToAttr(i,t,n)},this)},setOutgoingEdgesBirthPosition:function(e){u.each(this.get("outgoingEdges"),function(t){var n=t.get("head").getScreenCoords(),r=t.genSmoothBezierPathStringFromCoords(e,n);t.get("path").stop(),t.get("path").attr({path:r,opacity:0})},this)},parentInFront:function(){this.get("commit").get("parents")[0].get("visNode").toFront()},getFontSize:function(e){return e.length<3?12:e.length<5?10:8},getFill:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("commit"));return e=="head"?f.headRectFill:e=="none"?f.orphanNodeFill:this.gitVisuals.getBlendedHuesForCommit(this.get("commit"))},attachClickHandlers:function(){if(this.get("gitVisuals").options.noClick)return;var t="git checkout "+this.get("commit").get("id"),n=e("../app");u.each([this.get("circle"),this.get("text")],function(e){e.click(function(){n.getEventBaton().trigger("commandSubmitted",t)}),$(e.node).css("cursor","pointer")})},setOpacity:function(e){e=e===undefined?1:e;var t=["circle","text"];u.each(t,function(t){this.get(t).attr({opacity:e})},this)},remove:function(){this.removeKeys(["circle"],["text"]);var e=this.get("text");e&&e.remove(),this.gitVisuals.removeVisNode(this)},removeAll:function(){this.remove(),u.each(this.get("outgoingEdges"),function(e){e.remove()},this)},getExplodeStepFunc:function(){var e=this.get("circle"),t=20,n=Math.PI+Math.random()*1*Math.PI,r=.2,i=.01,s=t*Math.cos(n),o=t*Math.sin(n),u=e.attr("cx"),a=e.attr("cy"),f=this.gitVisuals.paper.width,l=this.gitVisuals.paper.height,c=.8,h=1,p=function(){o+=r*h-i*o,s-=i*s,u+=s*h,a+=o*h;if(u<0||u>f)s=c*-s,u=u<0?0:f;if(a<0||a>l)o=c*-o,a=a<0?0:l;return e.attr({cx:u,cy:a}),s*s+o*o<.01&&Math.abs(a-l)===0?!1:!0};return p},genGraphics:function(){var e=this.gitVisuals.paper,t=this.getScreenCoords(),n=this.getTextScreenCoords(),r=e.circle(t.x,t.y,this.getRadius()).attr(this.getAttributes().circle),i=e.text(n.x,n.y,String(this.get("id")));i.attr({"font-size":this.getFontSize(this.get("id")),"font-weight":"bold","font-family":"Monaco, Courier, font-monospace",opacity:this.getOpacity()}),this.set("circle",r),this.set("text",i),this.attachClickHandlers()}});n.VisNode=c}),e("/src/js/visuals/visNode.js"),e.define("/src/js/visuals/visualization.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../models/collections"),l=f.CommitCollection,c=f.BranchCollection,h=e("../util/eventBaton").EventBaton,p=e("../visuals").GitVisuals,d=a.View.extend({initialize:function(e){e=e||{},this.options=e,this.customEvents=u.clone(a.Events),this.containerElement=e.containerElement;var t=this,n=e.containerElement||$("#canvasHolder")[0];new Raphael(n,200,200,function(){var n=this;s.nextTick(function(){t.paperInitialize(n,e)})})},paperInitialize:function(t,n){this.treeString=n.treeString,this.paper=t;var r=e("../app");this.eventBaton=n.noKeyboardInput?new h:r.getEventBaton(),this.commitCollection=new l,this.branchCollection=new c,this.gitVisuals=new p({commitCollection:this.commitCollection,branchCollection:this.branchCollection,paper:this.paper,noClick:this.options.noClick,smallCanvas:this.options.smallCanvas,visualization:this});var i=e("../git").GitEngine;this.gitEngine=new i({collection:this.commitCollection,branches:this.branchCollection,gitVisuals:this.gitVisuals,eventBaton:this.eventBaton}),this.gitEngine.init(),this.gitVisuals.assignGitEngine(this.gitEngine),this.myResize(),$(window).on("resize",u.bind(function(){this.myResize()},this)),this.gitVisuals.drawTreeFirstTime(),this.treeString&&this.gitEngine.loadTreeFromString(this.treeString),this.options.zIndex&&this.setTreeIndex(this.options.zIndex),this.shown=!1,this.setTreeOpacity(0),s.nextTick(u.bind(this.fadeTreeIn,this)),this.customEvents.trigger("gitEngineReady"),this.customEvents.trigger("paperReady")},clearOrigin:function(){delete this.originVis},makeOrigin:function(e){return this.originVis=new d(u.extend({},this.options,{noKeyboardInput:!0,noClick:!0,treeString:e.treeString})),this.originVis},originToo:function(e,t){if(!this.originVis)return;var n=u.bind(function(){this.originVis[e].apply(this.originVis,t)},this);if(this.originVis.paper){n();return}this.originVis.customEvents.on("paperReady",n)},setTreeIndex:function(e){$(this.paper.canvas).css("z-index",e),this.originToo("setTreeIndex",arguments)},setTreeOpacity:function(e){e===0&&(this.shown=!1),$(this.paper.canvas).css("opacity",e),this.originToo("setTreeOpacity",arguments)},getAnimationTime:function(){return 300},fadeTreeIn:function(){this.shown=!0,$(this.paper.canvas).animate({opacity:1},this.getAnimationTime()),this.originToo("fadeTreeIn",arguments)},fadeTreeOut:function(){this.shown=!1,$(this.paper.canvas).animate({opacity:0},this.getAnimationTime()),this.originToo("fadeTreeOut",arguments)},hide:function(){this.fadeTreeOut(),setTimeout(u.bind(function(){$(this.paper.canvas).css("visibility","hidden")},this),this.getAnimationTime()),this.originToo("hide",arguments)},show:function(){$(this.paper.canvas).css("visibility","visible"),setTimeout(u.bind(this.fadeTreeIn,this),10),this.originToo("show",arguments)},showHarsh:function(){$(this.paper.canvas).css("visibility","visible"),this.setTreeOpacity(1),this.originToo("showHarsh",arguments)},resetFromThisTreeNow:function(e){this.treeString=e;var t=this.getOriginInTreeString(e);if(t){var n=this.gitEngine.printTree(t);this.originToo("resetFromThisThreeNow",[n])}},getOriginInTreeString:function(e){var t=JSON.parse(unescape(e));return t.originTree},reset:function(e){var t=e||this.treeString;this.setTreeOpacity(0),t?this.gitEngine.loadTreeFromString(t):this.gitEngine.defaultInit(),this.fadeTreeIn();if(this.originVis)if(t){var n=this.getOriginInTreeString(t);this.originToo("reset",[JSON.stringify(n)])}else this.originToo("reset",arguments)},tearDown:function(){this.gitEngine.tearDown(),this.gitVisuals.tearDown(),delete this.paper,this.originToo("tearDown",arguments)},die:function(){this.fadeTreeOut(),setTimeout(u.bind(function(){this.shown||this.tearDown()},this),this.getAnimationTime()),this.originToo("die",arguments)},myResize:function(){if(!this.paper)return;var e=1,t=this.el,n=t.clientWidth-e,r=t.clientHeight-e;if(!this.containerElement){var i=t.offsetLeft,s=t.offsetTop;$(this.paper.canvas).css({position:"absolute",left:i+"px",top:s+"px"})}this.paper.setSize(n,r),this.gitVisuals.canvasResize(n,r)}});n.Visualization=d}),e("/src/js/visuals/visualization.js"),e.define("/src/levels/advanced/multipleParents.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C7","id":"master"},"bugWork":{"target":"C2","id":"bugWork"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C2"],"id":"C5"},"C6":{"parents":["C4","C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',solutionCommand:"git branch bugWork master^^2^",startTree:'{"branches":{"master":{"target":"C7","id":"master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C2"],"id":"C5"},"C6":{"parents":["C4","C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Multiple parents",zh_CN:"多个父提交记录"},hint:{en_US:"Use `git branch bugWork` with a target commit to create the missing reference.",zh_CN:"使用`git branch bugWork`加上一个目标提交记录来创建消失的引用。"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["### Specifying Parents","","Like the `~` modifier, the `^` modifier also accepts an optional number after it.","","Rather than specifying the number of generations to go back (what `~` takes), the modifier on `^` specifies which parent reference to follow from a merge commit. Remember that merge commits have multiple parents, so the path to choose is ambiguous.","",'Git will normally follow the "first" parent upwards from a merge commit, but specifying a number with `^` changes this default behavior.',"","Enough talking, let's see it in action.",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have a merge commit. If we checkout `master^` without the modifier, we will follow the first parent after the merge commit. ","","(*In our visuals, the first parent is positioned directly above the merge commit.*)"],afterMarkdowns:["Easy -- this is what we are all used to."],command:"git checkout master^",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Now let's try specifying the second parent instead..."],afterMarkdowns:["See? We followed the other parent upwards."],command:"git checkout master^2",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["The `^` and `~` modifiers can make moving around a commit tree very powerful:"],afterMarkdowns:["Lightning fast!"],command:"git checkout HEAD~; git checkout HEAD^2; git checkout HEAD~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Even crazier, these modifiers can be chained together! Check this out:"],afterMarkdowns:["The same movement as before, but all in one command."],command:"git checkout HEAD~^2~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"ModalAlert",options:{markdowns:["### Put it to practice","","To complete this level, create a new branch at the specified destination.","","Obviously it would be easy to specify the commit directly (with something like `C6`), but I challenge you to use the modifiers we talked about instead!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["### 选择父提交","","和`~`修改符一样,`^`修改符之后也可以跟一个(可选的)数字。","","这不是用来指定向上返回几代(`~`的作用),`^`后的数字指定跟随合并提交记录的哪一个父提交。还记得一个合并提交有多个父提交吧,所有选择哪条路径不是那么清晰。","",'Git默认选择跟随合并提交的"第一个"父提交,使用`^`后跟一个数字来改变这一默认行为。',"","废话不多说,举个例子。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["这里有一个合并提交。如果不加数字修改符直接切换到`master^`,会回到第一个父提交。","","(*在我们的图示中,第一个父提交是指合并提交正上方的那个父提交。*)"],afterMarkdowns:["OK--这恰好是我们想要的。"],command:"git checkout master^",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["现在来试试选择第二个父提交……"],afterMarkdowns:["看见了吧?我们回到了第二个父提交。"],command:"git checkout master^2",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用`^`和`~`可以自由在在提交树中移动:"],afterMarkdowns:["快若闪电!"],command:"git checkout HEAD~; git checkout HEAD^2; git checkout HEAD~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["再疯狂点,这些修改符支持链式操作!试一下这个:"],afterMarkdowns:["和前面的结果一样,但只用了一条命令。"],command:"git checkout HEAD~^2~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"ModalAlert",options:{markdowns:["### 实践一下","","要完成此关,在指定的目标位置创建一个新的分支。","","很明显可以简单的直接使用提交记录的hash值(比如`C6`),但我要求你使用刚刚讲到的相对引用修饰符!"]}}]}}}}),e("/src/levels/advanced/multipleParents.js"),e.define("/src/levels/index.js",function(e,t,n,r,i,s,o){n.levelSequences={intro:[e("../../levels/intro/commits").level,e("../../levels/intro/branching").level,e("../../levels/intro/merging").level,e("../../levels/intro/rebasing").level],rampup:[e("../../levels/rampup/detachedHead").level,e("../../levels/rampup/relativeRefs").level,e("../../levels/rampup/relativeRefs2").level,e("../../levels/rampup/reversingChanges").level],rebase:[e("../../levels/rebase/manyRebases").level],mixed:[e("../../levels/mixed/grabbingOneCommit").level,e("../../levels/mixed/jugglingCommits").level,e("../../levels/mixed/jugglingCommits2").level],advanced:[e("../../levels/advanced/multipleParents").level,e("../../levels/rebase/selectiveRebase").level]},n.sequenceInfo={intro:{displayName:{en_US:"Introduction Sequence",ja:"まずはここから",fr_FR:"Séquence d'introduction",zh_CN:"基础篇",ko:"기본 명령어"},about:{en_US:"A nicely paced introduction to the majority of git commands",ja:"gitの基本的なコマンド群をほどよいペースで学ぶ",fr_FR:"Une introduction en douceur à la majorité des commandes git",zh_CN:"循序渐进介绍git主要命令",ko:"브랜치 관련 주요 git 명령어를 깔끔하게 알려드립니다"}},rampup:{displayName:{en_US:"Ramping Up",ja:"次のレベルに進もう",fr_FR:"Montée en puissance",zh_CN:"进阶篇"},about:{en_US:"The next serving of 100% git awesomes-ness. Hope you're hungry",ja:"更にgitの素晴らしさを堪能しよう",fr_FR:"Le prochain service git 100% excellence. J'espère que vous êtes affamés",zh_CN:"接下来是git的超赞特性。迫不及待了吧!"}},rebase:{displayName:{en_US:"Master the Rebase Luke!",ja:"Rebaseをモノにする",fr_FR:"Maîtrise Rebase, Luke!",zh_CN:"精通Rebase!",ko:"리베이스 완전정복!"},about:{en_US:"What is this whole rebase hotness everyone is talking about? Find out!",ja:"話題のrebaseってどんなものだろう?って人にオススメ",fr_FR:"Qu'est-ce que ce rebase dont tout le monde parle ? Découvrez-le !",ko:"그 좋다고들 말하는 rebase에 대해 알아봅시다!",zh_CN:"大家都在说的rebase究竟是神马?看看吧!"}},mixed:{displayName:{en_US:"A Mixed Bag",ja:"様々なtips",fr_FR:"Un assortiment",ko:"종합선물세트",zh_CN:"大杂烩?"},about:{en_US:"A mixed bag of Git techniques, tricks, and tips",ja:"gitを使う上での様々なtipsやテクニックなど",fr_FR:"Un assortiment de techniques et astuces pour utiliser Git",ko:"Git을 다루는 다양한 팁과 테크닉을 다양하게 알아봅니다",zh_CN:"Git技术,技巧与贴士杂烩"}},advanced:{displayName:{en_US:"Advanced Topics",fr_FR:"Sujets Avancés",zh_CN:"高级主题"},about:{en_US:"For the truly brave!",fr_FR:"Pour les plus courageux !",zh_CN:"只为真正的勇士!"}}}}),e("/src/levels/index.js"),e.define("/src/levels/intro/branching.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C1","id":"master"},"bugFix":{"target":"C1","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"bugFix","id":"HEAD"}}',solutionCommand:"git branch bugFix;git checkout bugFix",name:{en_US:"Branching in Git",ja:"Gitのブランチ",ko:"Git에서 브랜치 쓰기",fr_FR:"Gérer les branches avec Git",zh_CN:"建立Git分支"},hint:{en_US:'Make a new branch with "git branch [name]" and check it out with "git checkout [name]"',ja:'ブランチの作成("git branch [ブランチ名]")と、チェックアウト("git checkout [ブランチ名]")',fr_FR:'Faites une nouvelle branche avec "git branch [nom]" positionnez-vous dans celle-ci avec "git checkout [nom]"',zh_CN:"用 'git branch [分支名]' 来创建分支,用 'git checkout [分支名]' 切换到分支",ko:'"git branch [브랜치명]"으로 새 브랜치를 만들고, "git checkout [브랜치명]"로 그 브랜치로 이동하세요'},disabledMap:{"git revert":!0},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Branches","","Branches in Git are incredibly lightweight as well. They are simply references to a specific commit -- nothing more. This is why many Git enthusiasts chant the mantra:","","```","branch early, and branch often","```","","Because there is no storage / memory overhead with making many branches, it's easier to logically divide up your work than have big beefy branches.","",'When we start mixing branches and commits, we will see how these two features combine. For now though, just remember that a branch essentially says "I want to include the work of this commit and all parent commits."']}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's see what branches look like in practice.","","Here we will create a new branch named `newImage`"],afterMarkdowns:["There, that's all there is to branching! The branch `newImage` now refers to commit `C1`"],command:"git branch newImage",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's try to put some work on this new branch. Hit the button below"],afterMarkdowns:["Oh no! The `master` branch moved but the `newImage` branch didn't! That's because we weren't \"on\" the new branch, which is why the asterisk (*) was on `master`"],command:"git commit",beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's tell git we want to checkout the branch with","","```","git checkout [name]","```","","This will put us on the new branch before committing our changes"],afterMarkdowns:["There we go! Our changes were recorded on the new branch"],command:"git checkout newImage; git commit",beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["Ok! You are all ready to get branching. Once this window closes,","make a new branch named `bugFix` and switch to that branch"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Gitのブランチ","","Gitではコミットだけでなく、ブランチもまた信じられないほど軽量です。ブランチとは単に特定のコミットを指示したポインタにしか過ぎません。Gitの達人は決まってこう言うのは、そのためです:","","```","早めに、かつ頻繁にブランチを切りなさい","```","","どれほど多くのブランチを作ってもストレージやメモリを全然使わないので、ブランチを肥大化させるよりも論理的に分割していく方が簡単なのです。","","ブランチとコミットをあわせて使い始めると、これら2つのフィーチャがどのように連動して機能するかがわかるでしょう。ここではとりあえず、ブランチは基本的には「あるコミットとその親のコミットたちを含めた全てのコミット」のことを呼ぶと覚えておいてください。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["では実際にブランチがどのようなものかを見ていきましょう。","","`newImage`という名前の新しいブランチを切ってみることにします。"],afterMarkdowns:["以上。必要な手順はこれだけです。いま作成された`newImage`ブランチは`C1`コミットを指しています。"],command:"git branch newImage",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["この新しいブランチに何か変更を加えてみましょう。次のボタンを押してください。"],afterMarkdowns:["あれ?`newImage`ではなくて`master`ブランチが移動してしまいました。これは、私たちが`newImage`のブランチ上で作業していなかったためです。どのブランチで作業しているかは、アスタリスク(*)がついてるかどうかで分かります。"],command:"git commit",beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["今度は作業したいブランチ名をgitに伝えてみましょう。","","```","git checkout [ブランチ名]","```","","このようにして、コミットする前に新しいブランチへと作業ブランチを移動することができます。"],afterMarkdowns:["できましたね。今度は新しいブランチに対して変更を記録することができました。"],command:"git checkout newImage; git commit",beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["OK! もうどんなブランチでも切れますね。このウィンドウを閉じて、","`bugFix`という名前のブランチを作成し、そのブランチをチェックアウトしてみましょう。"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branches Git","","Les branches sous Git sont incroyablement légères aussi. Elles sont simplment des références un commit spécifique -- rien de plus. C'est pourquoi beaucoup d'enthousiastes répètent en cœur :","","```","n'attendez pas pour faire des branches, et faites souvent des branches","```","","Parce qu'il n'y a pas de surcoût (stockage/mémoire) associés aux branches, il est facile de diviser son travail en de nombreuses branches plutôt que d'avoir quelques grosses branches.","","Nous verrons comment les banches et les commits interagissent quand nous les utiliserons ensemble. Pour l'instant, souvenez-vous qu'une branche est un moyen d'exprimer \"Je veux inclure le contenu de ce commit et de tous les commits parents.\""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Regardons à quoi ressemblent les branches en pratique.","","Nous allons nous positionner (checkout) dans une nouvelle branche appellée `newImage`"],afterMarkdowns:["Et voilà, c'est tout ! La branche `newImage` se réfère désormais au commit `C1`"],command:"git branch newImage",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Travaillons mainenant dans cette branche. Appuyez sur le bouton ci-dessous."],afterMarkdowns:["Oh non! La branche `master` a bougé mais pas la branche `newImage` ! C'est parce aue nous n'étions pas \"sur\" la nouvelle branche, comme indiqué par l'asterisque (*) sur `master`"],command:"git commit",beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Indiquons à git que nous voulons nous positionner sur la branche avec ","","```","git checkout [nom]","```","","Ceci nous positionne sur la nouvelle branche avant de faire un commit avec nos modifications"],afterMarkdowns:["C'est parti ! Nos modifications ont été enregistrées sur la nouvelle branche"],command:"git checkout newImage; git commit",beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["Ok! Vous êtes fin prêt pour faire des branches. Après la fermeture de cette fenêtre,","faites une nouvelle branche nommée `bugFix` et positionnez-vous sur cette branche"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Branches",""," Git 的分支非常轻量。它们只是简单地指向某个提交纪录——仅此而已。所以许多Git爱好者会念叨:","","```","早点建分支!经常建分支!","```","","创建分支没有储存或内存上的开销,所以按逻辑分解工作比维护单一的代码树要简单。","","同时使用分支和提交时,我们会看到两者如何配合。现在,只要记住使用分支其实就是在说:“我想包含本次提交及所有的父提交记录。”"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["举个例子看看分支究竟是什么。","","这里,我们切换到到名为`newImage`的新分支。"],command:"git branch newImage",afterMarkdowns:["看,这就是建立分支所需的操作啦!`newImage`分支现在指向提交记录`C1`。"],beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["现在让我们修改一下新分支。点击下面的按钮。"],command:"git commit",afterMarkdowns:["啊摔!`master`分支前进了,但`newImage`分支没有哇!这是因为我们没有“在”这个新分支上,这也是为什么星号(*)只在 `master` 上。"],beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用如下命令告诉git我们想要切换到新的分支","","```","git checkout [name]","```","","这可以让我们在提交修改之前切换到新的分支。"],command:"git checkout newImage; git commit",afterMarkdowns:["好的嘞!新的分支已经记录了我们的修改。"],beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["好啦,你已经准备好使用分支了。当前窗口关闭后,","创建一个叫 `bugFix` 的新分支,然后切换过去。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git 브랜치","","깃의 브랜치도 놀랍도록 가볍습니다. 브랜치는 특정 커밋에 대한 참조(reference)에 지나지 않습니다. 이런 사실 때문에 수많은 Git 애찬론자들이 자주 이렇게 말하곤 합니다:","","```","브랜치를 서둘러서, 그리고 자주 만드세요","```","","브랜치를 많이 만들어도 메모리나 디스크 공간에 부담이 되지 않기 때문에, 여러분의 작업을 커다른 브랜치로 만들기 보다, 작은 단위로 잘게 나누는 것이 좋습니다.","",'브랜치와 커밋을 같이 쓸 때, 어떻게 두 기능이 조화를 이루는지 알아보겠습니다. 하지만 우선은, 단순히 브랜치를 "하나의 커밋과 그 부모 커밋들을 포함하는 작업 내역"이라고 기억하시면 됩니다.']}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["브랜치가 어떤 것인지 연습해보죠.","","`newImage`라는 브랜치를 살펴보겠습니다."],afterMarkdowns:["저 그림에 브랜치의 모든 것이 담겨있습니다! 브랜치 `newImage`가 커밋 `C1`를 가리킵니다"],command:"git branch newImage",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["이 새로운 브랜치에 약간의 작업을 더해봅시다. 아래 버튼을 눌러주세요"],afterMarkdowns:["앗! `master` 브랜치가 움직이고, `newImage` 브랜치는 이동하지 않았네요! 그건 우리가 새 브랜치 위에 있지 않았었기 때문입니다. 별표(*)가 `master`에 있었던 것이죠."],command:"git commit",beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["아래의 명령으로 새 브랜치로 이동해 봅시다.","","```","git checkout [브랜치명]","```","","이렇게 하면 변경분을 커밋하기 전에 새 브랜치로 이동하게 됩니다."],afterMarkdowns:["이거죠! 이제 우리의 변경이 새 브랜치에 기록되었습니다!"],command:"git checkout newImage; git commit",beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["좋아요! 이제 직접 브랜치 작업을 연습해봅시다. 이 창을 닫고,","`bugFix`라는 새 브랜치를 만드시고, 그 브랜치로 이동해보세요"]}}]}}}}),e("/src/levels/intro/branching.js"),e.define("/src/levels/intro/commits.js",function(e,t,n,r,i,s,o){n.level={name:{en_US:"Introduction to Git Commits",fr_FR:"Introduction aux commits avec Git",ja:"Gitのコミット",ko:"Git 커밋 소개",zh_CN:"Git Commits简介"},goalTreeString:'{"branches":{"master":{"target":"C3","id":"master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"master","id":"HEAD"}}',solutionCommand:"git commit;git commit",startTree:'{"branches":{"master":{"target":"C1","id":"master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"master","id":"HEAD"}}',hint:{en_US:"Just type in 'git commit' twice to finish!",fr_FR:"Il suffit de saisir 'git commit' deux fois pour réussir !",zh_CN:"敲两次 'git commit' 就好啦!",ja:"'git commit'コマンドを2回打てば完成!",ko:"'git commit'이라고 두 번 치세요!"},disabledMap:{"git revert":!0},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Commits","A commit in a git repository records a snapshot of all the files in your directory. It's like a giant copy and paste, but even better!","","Git wants to keep commits as lightweight as possible though, so it doesn't just copy the entire directory every time you commit. It actually stores each commit as a set of changes, or a \"delta\", from one version of the repository to the next. That's why most commits have a parent commit above them -- you'll see this later in our visualizations.","",'In order to clone a repository, you have to unpack or "resolve" all these deltas. That\'s why you might see the command line output:',"","`resolving deltas`","","when cloning a repo.","","It's a lot to take in, but for now you can think of commits as snapshots of the project. Commits are very light and switching between them is wicked fast!"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's see what this looks like in practice. On the right we have a visualization of a (small) git repository. There are two commits right now -- the first initial commit, `C0`, and one commit after that `C1` that might have some meaningful changes.","","Hit the button below to make a new commit"],afterMarkdowns:["There we go! Awesome. We just made changes to the repository and saved them as a commit. The commit we just made has a parent, `C1`, which references which commit it was based off of."],command:"git commit",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["Go ahead and try it out on your own! After this window closes, make two commits to complete the level"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Gitのコミット","コミットによって、ディレクトリ中の全てのファイルのスナップショットを記録します。巨大なコピー&ペーストのようなものですが、実はそれよりずっと良いものです。","","Gitではコミットを可能な限り軽量に保つために、コミット毎にフォルダ全体をコピーしません。実際にはGitは、コミットを直前のバージョンから一つ先のバージョンへの「変更の固まり」あるいは「差分」として記録します。後で出てきますが、ほとんどのコミットが親を持っているのはそういう理由からです。","","リポジトリをcloneする時には、内部動作としてはコミットの差分をたどって全ての変更を取得しています。cloneした時に以下のような表示が出るのは:","","`resolving deltas`(訳:差分を解決中)","","このためです。","","もっと説明したいところですが、しばらくはコミットをスナップショットのようなものだと考えてください。コミットは非常に軽量であり、コミット間の移動も非常に高速です。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["これがどういうことか、動きを見ていきましょう。図には(小さな)gitリポジトリが描かれています。コミットが2つあります ― `C0`という名前の初回のコミットがあり、`C1`という名前の次のコミットが続きます。これは何か意味のある変更かもしれません。","","下のボタンを押下して新しいコミットを作ってみましょう。"],afterMarkdowns:["できました! 良いですね。いまリポジトリに新しい変更が加えられ、1つのコミットとして保存されました。作成したコミットには親がいて、このコミットの出発点となった`C1`を指しています。"],command:"git commit",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["実際に手を動かしてみましょう。このウィンドウを閉じたら、試しに2回コミットをしてみましょう。"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Commits Git","Un commit dans un dépôt (repository) git enregistre une image (snapshot) de tous les fichiers du repertoire. Comme un Copier-Coller géant, mais en bien mieux !","","Git fait en sorte que les commits soient aussi légers que possible donc il ne recopie pas tous le répertoire à chaque commit. En fait, git n'enregistre que l'ensemble des changments (\"delta\") depuis la version précédante du dépôt. C'est pour cette raison que la plupart des commits ont un commit parent -- ainsi que nous le verrons plus tard.","",'Pour cloner un dépôt, il faut décompresser ("résoudre") tous ces deltas. C\'est la raison pour laquelle la commande écrit :',"","`resolving deltas`","","lorsque l'on clone un dépôt.","","C'est beaucoup à absorber, mais pour l'instant vous pouvez considérer les commits comme des snapshots du projet. Les commits sont très légers et passer de l'un à l'autre est très rapide !"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Voyons à quoi cela ressemble en pratique. Sur la droite, on peut visualiser un (petit) dépôt git. Il y a pour l'instant deux commits -- le premier commit initial, `C0`, et un commit suivant `C1` qui aurait des changements significatifs.","","Appuyez sur le bouton ci-dessous pour faire un nouveau commit"],afterMarkdowns:["C'est parti ! Super. Nous venons de faire des modifications sur le dépôt et de saugevarder celles-ci dans un commit. Ce commit que nous venons de faire a un parent, `C1`, qui référence le commit sur lequel il est basé."],command:"git commit",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["Allez-y et essayez par vous-même ! Après la fermeture de cettefenêtre, faites deux commits pour terminer ce niveau."]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git 커밋","커밋은 Git 저장소에 여러분의 디렉토리에 있는 모든 파일에 대한 스냅샷을 기록하는 것입니다. 디렉토리 전체에 대한 복사해 붙이기와 비슷하지만 훨씬 유용합니다!","",'Git은 커밋을 가능한한 가볍게 유지하고자 해서, 커밋할 때마다 디렉토리 전체를 복사하는 일은 하지 않습니다. 각 커밋은 저장소의 이전 버전과 다음 버전의 변경내역("delta"라고도 함)을 저장합니다. 그래서 대부분의 커밋이 그 커밋 위에 부모 커밋을 가리키고 있게 되는 것입니다. -- 곧 그림으로 된 화면에서 살펴보게 될 것입니다.',"","저장소를 복제(clone)하려면, 그 모든 변경분(delta)를 풀어내야하는데, 그 때문에 명령행 결과로 아래와 같이 보게됩니다. ","","`resolving deltas`","","알아야할 것이 꽤 많습니다만, 일단은 커밋을 프로젝트의 각각의 스냅샷들로 생각하시는 걸로 충분합니다. 커밋은 매우 가볍고 커밋 사이의 전환도 매우 빠르다는 것을 기억해주세요!"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["연습할 때 어떻게 보이는지 확인해보죠. 오른쪽 화면에 git 저장소를 그림으로 표현해 놓았습니다. 현재 두번 커밋한 상태입니다 -- 첫번째 커밋으로 `C0`, 그 다음으로 `C1`이라는 어떤 의미있는 변화가 있는 커밋이 있습니다.","","아래 버튼을 눌러 새로운 커밋을 만들어보세요"],afterMarkdowns:["이렇게 보입니다! 멋지죠. 우리는 방금 저장소 내용을 변경해서 한번의 커밋으로 저장했습니다. 방금 만든 커밋은 부모는 `C1`이고, 어떤 커밋을 기반으로 변경된 것인지를 가리킵니다."],command:"git commit",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["계속해서 직접 한번 해보세요! 이 창을 닫고, 커밋을 두 번 하면 다음 레벨로 넘어갑니다"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Commits","git仓库中的一次提交(commit)记录目录下所有文件的快照。感觉像是大量的复制和粘贴,但 git 做的不只这么简单!","",'Git 希望提交记录尽可能地轻量,所以每次进行提交时,它不会简单地复制整个目录。实际上它把每次提交记录保存为从代码库的一个版本到下一个版本的变化集,或者说一个"增量(delta)"。所以,大部分提交记录都有一个父提交(parent commit)-- 我们会很快演示这一点。',"","克隆(clone)代码库时,需要解包(unpack)或者“解析(resolve)”所有的差异。所以在克隆代码库时,可能会看见如下命令行输出:","","`resolving deltas`","","要学的东西有很多,但现在你可以把提交记录看作是项目的快照。提交记录非常轻量且可以快速切换!"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["在实践中学习commit。右边是一个(小)git代码库的图示。当前有两个提交记录—— 初始提交`C0`和其后可能包含有用修改的提交`C1`。","","点击下面的按钮生成新的提交记录。"],command:"git commit",afterMarkdowns:["看!碉堡吧!我们修改了代码,并保存为一次提交记录。刚刚做的提交`C2`有一个父提交(parent)`C1`,代表此次修改的基础。"],beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["接下来你可以随便测试。当前窗口关闭后,完成两次提交就可以过关!"]}}]}}}}),e("/src/levels/intro/commits.js"),e.define("/src/levels/intro/merging.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C4","id":"master"},"bugFix":{"target":"C2","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3","C2"],"id":"C4"}},"HEAD":{"target":"master","id":"HEAD"}}',solutionCommand:"git checkout -b bugFix;git commit;git checkout master;git commit;git merge bugFix",name:{en_US:"Merging in Git",fr_FR:"Faire des 'merge' (fusions de branches) avec Git",ko:"Git에서 브랜치 합치기(Merge)",ja:"ブランチとマージ",zh_CN:"分支与合并"},hint:{en_US:"Remember to commit in the order specified (bugFix before master)",ja:"指示された順番でコミットすること(masterの前にbugFixで)",fr_FR:"Pensez à faire des commits dans l'ordre indiqué (bugFix avant master)",zh_CN:"记住按指定的顺序提交(bugFix先于master)",ko:"말씀드린 순서대로 커밋해주세요 (bugFix에 먼저 커밋하고 master에 커밋)"},disabledMap:{"git revert":!0},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branches and Merging","","Great! We now know how to commit and branch. Now we need to learn some kind of way of combining the work from two different branches together. This will allow us to branch off, develop a new feature, and then combine it back in.","",'The first method to combine work that we will examine is `git merge`. Merging in Git creates a special commit that has two unique parents. A commit with two parents essentially means "I want to include all the work from this parent over here and this one over here, *and* the set of all their parents."',"","It's easier with visuals, let's check it out in the next view"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have two branches; each has one commit that's unique. This means that neither branch includes the entire set of \"work\" in the repository that we have done. Let's fix that with merge.","","We will `merge` the branch `bugFix` into `master`"],afterMarkdowns:["Woah! See that? First of all, `master` now points to a commit that has two parents. If you follow the arrows upstream from `master`, you will hit every commit along the way to the root. This means that `master` contains all the work in the repository now.","","Also, see how the colors of the commits changed? To help with learning, I have included some color coordination. Each branch has a unique color. Each commit turns a color that is the blended combination of all the branches that contain that commit.","","So here we see that the `master` branch color is blended into all the commits, but the `bugFix` color is not. Let's fix that..."],command:"git merge bugFix",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's merge `master` into `bugFix`:"],afterMarkdowns:["Since `bugFix` was downstream of `master`, git didn't have to do any work; it simply just moved `bugFix` to the same commit `master` was attached to.","","Now all the commits are the same color, which means each branch contains all the work in the repository! Woohoo!"],command:"git checkout bugFix; git merge master",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["To complete this level, do the following steps:","","* Make a new branch called `bugFix`","* Checkout the `bugFix` branch with `git checkout bugFix`","* Commit once","* Go back to `master` with `git checkout`","* Commit another time","* Merge the branch `bugFix` into `master` with `git merge`","",'*Remember, you can always re-display this dialog with "help level"!*']}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ブランチとマージ","","いい調子ですね。これまでにコミットとブランチについて学びました。そろそろ2つのブランチを1つにまとめるやり方について見ていきましょう。これができれば新しいフィーチャの開発のために新しいブランチを切って、開発が終わったら変更を元のブランチへ統合することができるようになります。","","はじめに紹介するのは、`git merge`を使ったマージのやり方です。mergeコマンドによって、2つの独立した親を持つ特別なコミットを作ることができます。2つの親を持つコミットが持つ意味とは、「全く別々の場所にいるこの親とその親(*かつ*、それらの親の祖先全て)が持つ全ての変更を含んでいますよ」ということです。","","見てみた方が早いので、次の画面で確認してみましょう。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["それぞれ別のコミットを指している2つのブランチがあります。変更が別々のブランチに分散していて統合されていないケースです。これをマージで1つにまとめてみましょう。","","`bugFix`ブランチを`master`ブランチにマージしてみます。"],afterMarkdowns:["わあ。見ましたか?まず初めに、`master`ブランチが2つのコミットを親に持つ新しいコミットを指してますね。`master`から親をたどっていくと、最も古いコミットにたどり着くまでに全てのコミットを含んでいる様が確認できます。これで、全ての変更を含む`master`が完成しました。","","色がどう変わったかにも注目して下さい。学習を助けるために、ブランチ毎に色をつけています。それぞれのブランチは自分の色を持っていて、どのブランチから派生して出てくるか次第でコミットごとの色が決まります。","","今回のコミットには`master`ブランチの色が使われました。しかし`bugFix`ブランチの色がまだ変わってないようなので、これを変えてみましょう。"],command:"git merge bugFix",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["`master`ブランチを`bugFix`ブランチにマージしてみます。"],afterMarkdowns:["`bugFix`ブランチは`master`ブランチの派生元だったので、gitは実際大したことはしていません:`bugFix`ブランチを指していたポインタを`master`が指していたコミットへと移動させただけです。","","これで全てのコミットが同じ色になりました。つまり、リポジトリの中の全ての変更をそれぞれのブランチが持ったことになります。やったね!"],command:"git checkout bugFix; git merge master",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["以下の作業で理解度の確認をしてみましょう。 steps:","","* `bugFix`という名前で新しいブランチを切る","* `git checkout bugFix`コマンドで`bugFix`ブランチをチェックアウトする","* 一回だけコミット","* `git checkout`で`master`へ戻る","* もう1回コミットする","* `git merge`コマンドを使って、`bugFix`ブランチを`master`ブランチへとマージする","",'*注:"help level"コマンドでこのヘルプにいつでも戻ってこれます*']}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branches et Merges","","Super! Nous savons désormais comment faire des commits et de branches. Maintenant nous devons apprendre comment combiner ensemble les contenus de deux branches différentes. Ceci nous permettra de créer une nouvelle branche, développer une nouvelle fonctionnalité sur cette dernière, puis intégrer cette fonctionnalité en combinant le contenu de cette branche de développement à la branche d'origine(master par exemple).","","La première méthode que nous alons voir pour combiner le conenu de deux branches est `git merge`. Faire un 'merge' en git Git crée un commit spécial qui a deux parents. Un commit avec deux parents indique en susbtance \"Je veux inclure le contenu de ce parent et le conenu de cet autre parent, *et* l'ensemble de leurs parents.\"","","C'est plus facile en visualisant, regardons dans la vue suivante"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have two branches; each has one commit that's unique. This means that neither branch includes the entire set of \"work\" in the repository that we have done. Let's fix that with merge.","","We will `merge` the branch `bugFix` into `master`"],afterMarkdowns:["Woah! See that? First of all, `master` now points to a commit that has two parents. If you follow the arrows upstream from `master`, you will hit every commit along the way to the root. This means that `master` contains all the work in the repository now.","","Also, see how the colors of the commits changed? To help with learning, I have included some color coordination. Each branch has a unique color. Each commit turns a color that is the blended combination of all the branches that contain that commit.","","So here we see that the `master` branch color is blended into all the commits, but the `bugFix` color is not. Let's fix that..."],command:"git merge bugFix",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Faisons un merge de `master` dans `bugFix`:"],afterMarkdowns:["Puisque `bugFix` était un descendant de `master`, git n'avait aucun travail à effectuer; il a simplement déplacé `bugFix` au même commit auquel `master` est attaché.","","Maintenant tous les commits sont de la même couleur, ce qui indique que chaque branche contient tout le contenu du dépôt ! Woohoo!"],command:"git checkout bugFix; git merge master",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["Pour accomplir ce niveau, effectuez les opérations suivantes :","","* Faites une nouvelle branche appelée `bugFix`","* Positionnez-vous sur la branche `bugFix` avec `git checkout bugFix`","* Faites un commit","* Retournez sur la branche `master` (commande `git checkout`)","* Faites un nouveau commit","* Fusionnez la branche `bugFix` dans `master` avec `git merge`","",'*Rappelez-vous que vous pouvez à tout moment réafficher ces indications avec "help level"!*']}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branches and Merging","","Great! 我们已经知道怎么提交和使用分支了。接下来要学的一招是如何合并两个不同分支的工作。这让我们可以新建一个分支,在其上开发新功能,然后合并回主线。","","`git merge`是我们要学习的合并工作的第一个方法。合并产生一个特殊的提交记录,它包含两个唯一父提交。有两个父提交的提交记录本质上是:“我想把这两个父提交本身及它们的父提交集合都包含进来。”","","有图有真相,看看下面的图示就明白了。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["当前有两个分支:各有一个唯一的提交。这意味着没有一个分支包含我们对代码库的所有修改。让我们合并这两个分支来解决这个问题。","","我们要把 `bugFix` 合并到 `master` "],command:"git merge bugFix",afterMarkdowns:["哇!看见木有?首先,`master` 现在指向一个拥有两个父提交的提交记录。假如从 `master` 开始沿着箭头向上游走,在到达起点的路上会经过所有的提交记录。这说明有 `master` 包含了对代码库的所有修改。","","还有,看见各个提交记录的颜色变化了吗?为了帮助学习,我使用了颜色混合。每个分支都有特定的颜色。每个提交记录都变成了含有此提交的所有分支的混合色。","","所以,`master` 分支的颜色被混入到所有的提交记录,但 `bugFix` 没有。接下来就改一下这里吧。"],beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["让我们把 `master` 分支合并到 `bugFix` 吧。"],command:"git checkout bugFix; git merge master",afterMarkdowns:["因为 `bugFix` 分支在 `master` 分支的下游,git什么都不用做,只是简单地把`bugfix`分支移动到`master`指向的提交记录。","","现在所有的提交记录的颜色都是一样的啦,这表明每一个分支都包含了代码库的所有修改!走起!"],beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["想完成此关,执行收下操作:","","* 创建新分支 `bugFix` ","* 用 `git checkout bugFix` 切换到 `bugFix`分支","* 提交一次","* 用 `git checkout` 切换回 `master` ","* 再提交一次","* 用 `git merge` 合并 `bugFix`分支进 `master`","",'*记住,总是可以用 "help level" 命令来重新显示这个对话框!*']}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 브랜치와 합치기(Merge)","","좋습니다! 지금까지 커밋하고 브랜치를 만드는 방법을 알아봤습니다. 이제 두 별도의 브랜치를 합치는 몇가지 방법을 알아볼 차례입니다. 이제부터 배우는 방법으로 브랜치를 따고, 새 기능을 개발 한 다음 합칠 수 있게 될 것입니다.","",'처음으로 살펴볼 방법은 `git merge`입니다. Git의 합치기(merge)는 두 개의 부모(parent)를 가리키는 특별한 커밋을 만들어 냅니다. 두개의 부모가 있는 커밋이라는 것은 "한 부모의 모든 작업내역과 나머지 부모의 모든 작업, *그리고* 그 두 부모의 모든 부모들의 작업내역을 포함한다"라는 의미가 있습니다. ',"","그림으로 보는게 이해하기 쉬워요. 다음 화면을 봅시다."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["여기에 브랜치가 두 개 있습니다. 각 브랜치에 독립된 커밋이 하나씩 있구요. 그 말은 이 저장소에 지금까지 작업한 내역이 나뉘어 담겨 있다는 얘기입니다. 두 브랜치를 합쳐서(merge) 이 문제를 해결해 볼까요?","","`bugFix` 브랜치를 `master` 브랜치에 합쳐(merge) 보겠습니다."],afterMarkdowns:["보셨어요? 우선, `master`가 두 부모가 있는 커밋을 가리키고 있습니다. ","","또, 커밋들의 색이 바뀐 것을 눈치 채셨나요? 이해를 돕기위해 색상으로 구분해 표현했습니다. 각 브랜치는 그 브랜치만의 색상으로 그렸습니다. 브랜치가 합쳐지는 커밋의 경우에는, 그 브랜치들의 색을 조합한 색상으로 표시 했습니다.","","그런식으로 여기에 `bugFix`브랜치 쪽을 제외한 나머지 커밋만 `master` 브랜치의 색으로 칠해져 있습니다. 이걸 고쳐보죠..."],command:"git merge bugFix",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["이제 `master` 브랜치에 `bugFix`를 합쳐(merge) 봅시다:"],afterMarkdowns:["`bugFix`가 `master`의 부모쪽에 있었기 때문에, git이 별다른 일을 할 필요가 없었습니다; 간단히 `bugFix`를 `master`가 붙어 있는 커밋으로 이동시켰을 뿐입니다.","","짜잔! 이제 모든 커밋의 색이 같아졌고, 이는 두 브랜치가 모두 저장소의 모든 작업 내역을 포함하고 있다는 뜻입니다."],command:"git checkout bugFix; git merge master",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["아래 작업을 해서 이 레벨을 통과하세요:","","* `bugFix`라는 새 브랜치를 만듭니다","* `git checkout bugFix`를 입력해 `bugFix` 브랜치로 이동(checkout)합니다.","* 커밋 한 번 하세요","* `git checkout` 명령어를 이용해 `master`브랜치로 돌아갑니다","* 커밋 또 하세요","* `git merge` 명령어로 `bugFix`브랜치를 `master`에 합쳐 넣습니다.","",'*아 그리고, "help level" 명령어로 이 안내창을 다시 볼 수 있다는 것을 기억해 두세요!*']}}]}}}}),e("/src/levels/intro/merging.js"),e.define("/src/levels/intro/rebasing.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22master%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22bugFix%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C2%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22bugFix%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout -b bugFix;git commit;git checkout master;git commit;git checkout bugFix;git rebase master",name:{en_US:"Rebase Introduction",ja:"Rebaseの解説",fr_FR:"Introduction à rebase",ko:"리베이스(rebase)의 기본",zh_CN:"Rebase简介"},hint:{en_US:"Make sure you commit from bugFix first",ja:"初めにbugFixを指した状態でコミットする",fr_FR:"Assurez-vous de bien faire votre en premier votre commit sur bugFix",ko:"bugFix 브랜치에서 먼저 커밋하세요",zh_CN:"确保你先在 bugFix 分支进行提交"},disabledMap:{"git revert":!0},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Rebase","",'The second way of combining work between branches is *rebasing.* Rebasing essentially takes a set of commits, "copies" them, and plops them down somewhere else.',"","While this sounds confusing, the advantage of rebasing is that it can be used to make a nice linear sequence of commits. The commit log / history of the repository will be a lot cleaner if only rebasing is allowed.","","Let's see it in action..."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have two branches yet again; note that the bugFix branch is currently selected (note the asterisk)","","We would like to move our work from bugFix directly onto the work from master. That way it would look like these two features were developed sequentially, when in reality they were developed in parallel.","","Let's do that with the `git rebase` command"],afterMarkdowns:["Awesome! Now the work from our bugFix branch is right on top of master and we have a nice linear sequence of commits.","",'Note that the commit C3 still exists somewhere (it has a faded appearance in the tree), and C3\' is the "copy" that we rebased onto master.',"","The only problem is that master hasn't been updated either, let's do that now..."],command:"git rebase master",beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Now we are checked out on the `master` branch. Let's go ahead and rebase onto `bugFix`..."],afterMarkdowns:["There! Since `master` was downstream of `bugFix`, git simply moved the `master` branch reference forward in history."],command:"git rebase bugFix",beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["To complete this level, do the following","","* Checkout a new branch named `bugFix`","* Commit once","* Go back to master and commit again","* Check out bugFix again and rebase onto master","","Good luck!"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Rebase","","ブランチを一つにまとめる方法として前回はマージを紹介しましたが、今回紹介するリベースを使うこともできます。リベースの動作は、マージするコミットのコピーをとって、どこかにストンと落とすというイメージです。","","ピンと来ないかもしれませんが、リベースのメリットは一本の連続したシーケンシャルなコミットに整形できることです。リベースだけ使っていると、コミットのログや履歴が非常にクリーンな状態に保たれます。","","早速実際にどう動くのかを見てみましょう。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["前回と同様の2つのブランチを考えます:仮にいまbugFixブランチをチェックアウトしているとします。(アスタリスクつきのもの)","","bugFixに入ってる作業内容をそのまま直接masterブランチ上の内容に移動したいとします。こうすることで、実際には並行して開発された2つの別々のブランチ上のフィーチャを、あたかも1本のブランチ上でシーケンシャルに開発されていたかのように見せることができます。","","`git rebase`コマンドでそれをやってみましょう。"],afterMarkdowns:["できた!これでbugFixブランチの作業内容はmasterブランチのすぐ先に移動したので、見た目が一本になってスッキリしました。","","気を付けてほしいのは、C3コミットはどこかに残ってるということ(ツリーの中で半透明にしてあります)、そしてC3'は(C3との接続が切れているC3の)コピーがmasterブランチ上に作られているということです。","","一つ問題が残ってて、masterブランチがまだ最新化されていませんね。ちょっと直してみましょう。。"],command:"git rebase master",beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["masterブランチはチェックアウトしてあります。この状態からmasterブランチを`bugFix`へとリベースしてみましょう。"],afterMarkdowns:["できた!`master`は`bugFix`の直前のコミットだったので、gitは単純に`master`ブランチのポインタを前に進めただけでした。"],command:"git rebase bugFix",beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["以下の作業で理解度の確認をしてみましょう。","","* `bugFix`という名前の新しいブランチをチェックアウトする","* 一回だけコミット","* masterブランチに戻ってもう1回コミット","* bugFixをもう1回チェックアウトして、master上にリベース","","幸運を祈る!"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Rebase","",'La seconde façon de combiner les contenus de deux branches est *rebase*. Rebase prend un enselble de commits, les "recopie", et les ajoute en bout de chaine à un autre endroit.',"","Bien que cela puisse sembler compliqué, l'avantage de rebase est de permettre d'obtenir une simple séquence linéeire de commits. Les logs/l'historique du dépôt seront bien plus propres si seul rebase est autorisé (plutôt que merge).","","Voyons rebase en action…"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Ici nous avons encore une fois deux branches; notez que nous sommes sur la branche bugFix (cf. l'asterisque)","","Nous voudrions transferer notre travail sur la branche 'bugFix' directement sur le travail dans 'master'. Ainsi on aurait l'impression que ces deux travaux ont été développés séquentiellement alors qu'en réalité ils ont été réalisés en parallèle.","","Faisons cela avec la commande `git rebase`"],afterMarkdowns:["Super! Désormais, le travail de la branche 'bugFix' est juste en haut de la branche 'master' et non avons une belle séquence linéaire de commits.","","Notez que le commit C3 existe toujours quelquepart (il est en grisé sur l'arbre), et C3' est la \"copie\" que nous avons créée sur master avec rebase.","","Le seul problème est que master n'a pas été mis à jour, faisons cela maintenant…"],command:"git rebase master",beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Nous sommes désormais positionnés sur la branche `master`. Continuons en faisant le rebase sur `bugFix`…","Et voilà ! Puisque `master` était un ascendant de `bugFix`, git a simplement déplacé la référence de la branche `master` en avant dans le temps."],command:"git rebase bugFix",beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["Pour acomplir ce niveau, faites les opérations suivantes","","* Positionnez-vous (checkout) sur une nouvelle branche nommée `bugFix`","* Faites un commit","* Retournez sur master et faites un nouveau commit","* Positionnez-vous à nouveau sur bugFix et faites un rebase sur master","","Bonne chance !"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Rebase","",'*rebasing*是在分支之间合并工作的第二种方法。Rebasing就是取出一系列的提交记录,"复制"它们,然后把在别的某个地方放下来。',"","虽然听上去难以理解,rebasing 的优势是可以创造更线性的提交历史。假如只允许使用rebasing,代码库的提交日志/历史会更好看。","","让我们亲身体会下……"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["这里,还是有两个分支;注意当前分支是 bugFix(看那颗星)","","我们想要把 bugfix 里面的工作直接移到 master 分支上。使用这个方法,两个分支的功能看起来像是按顺序开发,实际上它们是平行开发的。","","用 `git rebase`实现此目标"],command:"git rebase master",afterMarkdowns:["碉堡吧,现在 bugFix 分支上的工作在 master 的最前端,同时我们也得到了一个更线性的提交序列。","","注意,提交记录 C3 仍然存在(阴影的那货就是你了,还看什么看),而我们已经将 C3 复制到了master。","","现在唯一的问题是 master 分支还没有更新……下面就来更新它吧"],beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["现在,切换到 `master` 分支。接下来就把它 rebase 到 `bugFix` 吧……"],command:"git rebase bugFix",afterMarkdowns:["完成!因为 `master` 是 `bugFix` 的下游,所以 git 只把 `master` 分支的记录前移到 `bugFix` 上。"],beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["想完成此关,执行以下操作:","","* 新建`bugFix`分支","* 提交一次","* 切换回 master 分支再提交一次","* 再次切换到 bugFix 分支,rebase 到 master 上","","祝你好运啦!"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git 리베이스(Rebase)","","브랜치끼리의 작업을 접목하는 두번째 방법은 *리베이스(rebase)*입니다. 리베이스는 기본적으로 커밋들을 모아서 복사한 뒤, 다른 곳에 떨궈 놓는 것입니다.","","조금 어려게 느껴질 수 있지만, 리베이스를 하면 커밋들의 흐름을 보기 좋게 한 줄로 만들 수 있다는 장점이 있습니다. 리베이스를 쓰면 저장소의 커밋 로그와 이력이 한결 깨끗해집니다.","","어떻게 동작하는지 살펴볼까요..."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["여기 또 브랜치 두 개가 있습니다; bugFix브랜치가 현재 선택됐다는 점 눈여겨 보세요 (별표 표시)","","bugFix 브랜치에서의 작업을 master 브랜치 위로 직접 옮겨 놓으려고 합니다. 그렇게 하면, 실제로는 두 기능을 따로따로 개발했지만, 마치 순서대로 개발한 것처럼 보이게 됩니다.","","`git rebase` 명령어로 함께 해보죠."],afterMarkdowns:["오! 이제 bugFix 브랜치의 작업 내용이 master의 바로 위에 깔끔한 한 줄의 커밋으로 보이게 됐습니다.","","C3 커밋은 어딘가에 아직 남아있고(그림에서 흐려짐), C3'는 master 위에 올려 놓은 복사본입니다.","","master가 아직 그대로라는 문제가 남아있는데요, 바로 해결해보죠..."],command:"git rebase master",beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["우리는 지금 `master` 브랜치를 선택한 상태입니다. `bugFix` 브랜치쪽으로 리베이스 해보겠습니다..."],afterMarkdowns:["보세요! `master`가 `bugFix`의 부모쪽에 있었기 때문에, 단순히 그 브랜치를 더 앞쪽의 커밋을 가리키게 이동하는 것이 전부입니다."],command:"git rebase bugFix",beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["이하 작업을 하면 이번 레벨을 통과합니다","","* `bugFix`라는 새 브랜치를 만들어 선택하세요","* 커밋 한 번 합니다","* master로 돌아가서 또 커밋합니다","* bugFix를 다시 선택하고 master에 리베이스 하세요","","화이팅!"]}}]}}}}),e("/src/levels/intro/rebasing.js"),e.define("/src/levels/mixed/grabbingOneCommit.js",function(e,t,n,r,i,s,o){n.level={compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C4>e.C1}]},disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22master%22%7D%2C%22debug%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22debug%22%7D%2C%22printf%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22printf%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22bugFix%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout master;git cherry-pick C4",startTree:'{"branches":{"master":{"target":"C1","id":"master"},"debug":{"target":"C2","id":"debug"},"printf":{"target":"C3","id":"printf"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"bugFix","id":"HEAD"}}',name:{ko:"딱 한개의 커밋만 가져오기",en_US:"Grabbing Just 1 Commit",ja:"Grabbing Just 1 Commit",zh_CN:"只取一个提交"},hint:{en_US:"Remember, interactive rebase or cherry-pick is your friend here",ja:"このレベルではインタラクティブモードのrebaseやcherry-pickがクリアのカギです",ko:"대화식 리베이스(rebase -i)나 or 체리픽(cherry-pick)을 사용하세요",zh_CN:"记住,交互式 rebase 或者 cherry-pick 会很有帮助"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Locally stacked commits","","Here's a development situation that often happens: I'm trying to track down a bug but it is quite elusive. In order to aid in my detective work, I put in a few debug commands and a few print statements.","","All of these debugging / print statements are in their own branches. Finally I track down the bug, fix it, and rejoice!","","Only problem is that I now need to get my `bugFix` back into the `master` branch! I could simply fast-forward `master`, but then `master` would get all my debug statements."]}},{type:"ModalAlert",options:{markdowns:["This is where the magic of Git comes in. There are a few ways to do this, but the two most straightforward ways are:","","* `git rebase -i`","* `git cherry-pick`","","Interactive (the `-i`) rebasing allows you to choose which commits you want to keep or discard. It also allows you to reorder commits. This can be helpful if you want to toss out some work.","","Cherry-picking allows you to pick individual commits and plop them down on top of `HEAD`"]}},{type:"ModalAlert",options:{markdowns:["This is a later level so we will leave it up to you to decide, but in order to complete the level, make sure `master` receives the commit that `bugFix` references."]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ローカルに積み上がったコミット","","実際の開発ではこういうケースがよくあります:「バグの原因調査を試みているがバグの再現性がかなり低い。調査の補助のために、いくつかのデバッグ用の命令やprint文を差し込んでいる。」","","これらのデバッグ用のコードはバグ修正用のブランチにコミットされています。そしてついにバグの原因を突き止めて、修正した!やった!","","あとは`bugFix`ブランチを`master`ブランチに統合できればOK。そこで単純に`master`をfast-forwardすればよいかというと、それでは`master`ブランチの中にデバッグ用のコードも混入してしまいます。"]}},{type:"ModalAlert",options:{markdowns:["ここでGitの魔法が力を発揮します。解決のためにはいくつかの方法がありますが、最も素直な解決方法は2つあって:","","* `git rebase -i`","* `git cherry-pick`","","インタラクティブモードの(`-i`オプションつきの)rebaseによって、保持したいコミットと破棄したいコミットを選り分けることができます。コミットの順序を変更することも可能です。この方法は、一部の変更をどこかへやってしまいたい時に便利です。","","もう一方のcherry-pickを使うと、持っていきたいコミットを選んで`HEAD`の先にストンと落とすことができます。"]}},{type:"ModalAlert",options:{markdowns:["後半の章ですのでどう解決するかをもう自分で考えることができると思います。このレベルをクリアするためには、`bugFix`が持っているコミットを`master`ブランチが受け取る必要がある点には注意してください。"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 本地栈式提交 (Locally stacked commits)","","设想一下一个经常发生的场景:我在追踪一个有点棘手的 bug,为了更好地排查,我添加了一些调试命令和打印语句。","","所有的这些调试和打印语句都只在它们自己的分支里。最终我终于找到这个 bug,揪出来 fix 掉,然后撒花庆祝!","","现在唯一的问题就是要把我在 `bugFix` 分支里的工作合并回 `master` 分支。我可以简单地把 `master` 分支快进(fast-forward),但这样的话 `master` 分支就会包含我这些调试语句了。"]}},{type:"ModalAlert",options:{markdowns:["现在就是 Git 大显神通的时候啦。解决这个问题的方法不止一个,但最直接的两个方法是:","","* `git rebase -i`","* `git cherry-pick`","","交互(`-i`)衍合允许你选择哪些提交是要被保留,哪些要被舍弃。它允许你将提交重新排序。假如你要舍弃一些工作,这个会帮上很大的忙。","","Cherry-picking 能让你选择单独一个提交并且把它放到 `HEAD` 的最前端。"]}},{type:"ModalAlert",options:{markdowns:["本关是可选关卡,玩不玩随便你。但是如果你坚持要刷,确保 `master` 分支能拿到 `bugFix` 分支的相关提交(references)。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 로컬에 쌓인 커밋들","","개발중에 종종 이런 상황이 생깁니다: 잘 띄지 않는 버그를 찾아서 해결하려고, 어떤 부분의 문제인지를 찾기 위해 디버그용 코드와 화면에 정보를 프린트하는 코드 몇 줄 넣습니다. ","","디버깅용 코드나 프린트 명령은 그 브랜치에 들어있습니다. 마침내 버그를 찾아서 고쳤고, 원래 작업하는 브랜치에 합치면 됩니다!","","이제 `bugFix`브랜치의 내용을 `master`에 합쳐 넣으려 하지만, 한 가지 문제가 있습니다. 그냥 간단히 `master`브랜치를 최신 커밋으로 이동시킨다면(fast-forward) 그 불필요한 디버그용 코드들도 함께 들어가 버린다는 문제죠."]}},{type:"ModalAlert",options:{markdowns:["여기에서 Git의 마법이 드러납니다. 이 문제를 해결하는 여러가지 방법이 있습니다만, 가장 간단한 두가지 방법 아래와 같습니다:","","* `git rebase -i`","* `git cherry-pick`","","대화형 (-i 옵션) 리베이스(rebase)로는 어떤 커밋을 취하거나 버릴지를 선택할 수 있습니다. 또 커밋의 순서를 바꿀 수도 있습니다. 이 커맨드로 어떤 작업의 일부만 골라내기에 유용합니다.","","체리픽(cherry-pick)은 개별 커밋을 골라서 `HEAD`위에 떨어뜨릴 수 있습니다."]}},{type:"ModalAlert",options:{markdowns:["이번 레벨을 통과하기 위해 어떤 방법을 쓰시든 자유입니다만, `master`브랜치가 `bugFix` 브랜치의 커밋을 일부 가져오게 해주세요."]}}]}}}}),e("/src/levels/mixed/grabbingOneCommit.js"),e.define("/src/levels/mixed/jugglingCommits.js",function(e,t,n,r,i,s,o){n.level={disabledMap:{"git cherry-pick":!0,"git revert":!0},compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C2>e.C3},function(e){return e.C2>e.C1}]},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%27%27%22%2C%22id%22%3A%22master%22%7D%2C%22newImage%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22newImage%22%7D%2C%22caption%22%3A%7B%22target%22%3A%22C3%27%27%22%2C%22id%22%3A%22caption%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%2C%22C2%27%27%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%27%27%22%7D%2C%22C3%27%27%22%3A%7B%22parents%22%3A%5B%22C2%27%27%27%22%5D%2C%22id%22%3A%22C3%27%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git rebase -i HEAD~2;git commit --amend;git rebase -i HEAD~2;git rebase caption master",startTree:'{"branches":{"master":{"target":"C1","id":"master"},"newImage":{"target":"C2","id":"newImage"},"caption":{"target":"C3","id":"caption"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"caption","id":"HEAD"}}',name:{ko:"커밋들 갖고 놀기",en_US:"Juggling Commits",ja:"Juggling Commits",zh_CN:"提交变换戏法"},hint:{en_US:"The first command is git rebase -i HEAD~2",ja:"最初に打つコマンドはgit rebase -i HEAD~2",ko:"첫번째 명령은 git rebase -i HEAD~2 입니다",zh_CN:"第一个命令是 'git rebase -i HEAD~2'"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Juggling Commits","","Here's another situation that happens quite commonly. You have some changes (`newImage`) and another set of changes (`caption`) that are related, so they are stacked on top of each other in your repository (aka one after another).","","The tricky thing is that sometimes you need to make a small modification to an earlier commit. In this case, design wants us to change the dimensions of `newImage` slightly, even though that commit is way back in our history!!"]}},{type:"ModalAlert",options:{markdowns:["We will overcome this difficulty by doing the following:","","* We will re-order the commits so the one we want to change is on top with `git rebase -i`","* We will `commit --amend` to make the slight modification","* Then we will re-order the commits back to how they were previously with `git rebase -i`","* Finally, we will move master to this updated part of the tree to finish the level (via the method of your choosing)","","There are many ways to accomplish this overall goal (I see you eye-ing cherry-pick), and we will see more of them later, but for now let's focus on this technique."]}},{type:"ModalAlert",options:{markdowns:["Lastly, pay attention to the goal state here -- since we move the commits twice, they both get an apostrophe appended. One more apostrophe is added for the commit we amend, which gives us the final form of the tree ","","That being said, I can compare levels now based on structure and relative apostrophe differences. As long as your tree's `master` branch has the same structure and relative apostrophe differences, I'll give full credit"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Commitsをやりくりする","","開発中に頻繁に起こるケースをもう1つ考えます。ある変更(`newImage`)とまた別の変更(`caption`)があって、それらに依存関係があるとします。この一連の変更が一列に積み重なっているとします。","","ここでトリッキーなのは、以前のコミットに対して微修正をかけなければならないケースがあるということです。今回の教材でも、過去のコミットであるにも関わらず`newImage`ブランチに僅かな修正を加えるような設計の修正が入ったとしましょう。"]}},{type:"ModalAlert",options:{markdowns:["この困難な状況を、以下の手順で克服することを考えます:","","* `git rebase -i`を使って順番を変更する。これで、変更をかけたいコミットを一番先頭に持ってくる。","* `commit --amend`コマンドで僅かな変更を行う","* `git rebase -i`コマンドを再度使って、先頭に持ってきていたコミットを元に戻す","* 最後に、レベルクリアのためにmasterブランチを先頭に持ってくる","","クリアのための方法はいくつもありますが(cherry-pickを使うこともできます)、別の回答はまた後程の章で見ることにんして、今回は上記の方法でやってみることにしましょう。"]}},{type:"ModalAlert",options:{markdowns:["最後に、ゴール時点での状態に気を付けてください。今回2回ほどコミットを動かしますから、コミットへのポインタにはアポストロフィ(')が追加されます。commit --amendコマンドの実行でできたコミットには更にもう1つのアポストロフィが追加されます。 "]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 提交变换戏法","","下面这种情况也是经常出现的。例如你之前已经在 `newImage` 分支上做了一些提交,然后又在 `caption` 分支上做了一些相关的提交,因此它们看起来是一个连一个的(stacked on top of each other in your repository)。","","有点棘手的就是有时候你又想往先前的提交里做些小改动。呐,现在就是设计师想要我们去轻微改变下 `newImage` 的内容(change the dimensions slightly),尽管那个提交是很久很久以前的了。"]}},{type:"ModalAlert",options:{markdowns:["为了实现他的愿望,我们可以按照下面的方法来做:","","* 先用 `git rebase -i` 将提交重新排序,然后把我们想要修改的提交挪到最前","* 然后用 `commit --amend` 来进行一些小修改","* 接着再用 `git rebase -i` 来将他们按最开始的顺序重新排好","* 最后我们把 master 移到修改的最前端(用你自己喜欢的方法),就大功告成啦!","","当然还有许多方法可以完成这个任务(我知道你在看 cherry-pick 啦),之后我们会多点关注这些技巧啦,但现在暂时只专注上面这种方法。"]}},{type:"ModalAlert",options:{markdowns:["啊最后还要提醒你一下最终的形式 —— 因为我们把这个提交移动了两次,所以会分别产生一个省略提交(both get an apostrophe appended)。还有一个省略提交是因为我们为了实现最终效果去修改提交而添加的。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 커밋들 갖고 놀기","","이번에도 꽤 자주 발생하는 상황입니다. `newImage`와 `caption` 브랜치에 각각의 변경내역이 있고 서로 약간 관련이 있어서, 저장소에 차례로 쌓여있는 상황입니다.","","때로는 이전 커밋의 내용을 살짝 바꿔야하는 골치아픈 상황에 빠지게 됩니다. 이번에는 디자인 쪽에서 우리의 작업이력(history)에서는 이미 한참 전의 커밋 내용에 있는 `newImage`의 크기를 살짝 바꿔달라는 요청이 들어왔습니다."]}},{type:"ModalAlert",options:{markdowns:["이 문제를 다음과 같이 풀어봅시다:","","* `git rebase -i` 명령으로 우리가 바꿀 커밋을 가장 최근 순서로 바꾸어 놓습니다","* `commit --amend` 명령으로 커밋 내용을 정정합니다","* 다시 `git rebase -i` 명령으로 이 전의 커밋 순서대로 되돌려 놓습니다","* 마지막으로, master를 지금 트리가 변경된 부분으로 이동합니다. (편하신 방법으로 하세요)","","이 목표를 달성하기 위해서는 많은 방법이 있는데요(체리픽을 고민중이시죠?), 체리픽은 나중에 더 살펴보기로 하고, 우선은 위의 방법으로 해결해보세요."]}},{type:"ModalAlert",options:{markdowns:["최종적으로, 목표 결과를 눈여겨 보세요 -- 우리가 커밋을 두 번 옮겼기 때문에, 두 커밋 모두 따옴표 표시가 붙어있습니다. 정정한(amend) 커밋은 따옴표가 추가로 하나 더 붙어있습니다."]}}]}}}}),e("/src/levels/mixed/jugglingCommits.js"),e.define("/src/levels/mixed/jugglingCommits2.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22master%22%7D%2C%22newImage%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22newImage%22%7D%2C%22caption%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22caption%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%27%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout master;git cherry-pick C2;git commit --amend;git cherry-pick C3",disabledMap:{"git revert":!0},startTree:'{"branches":{"master":{"target":"C1","id":"master"},"newImage":{"target":"C2","id":"newImage"},"caption":{"target":"C3","id":"caption"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"caption","id":"HEAD"}}',compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C2>e.C3},function(e){return e.C2>e.C1}]},name:{ko:"커밋 갖고 놀기 #2",en_US:"Juggling Commits #2",ja:"コミットをやりくりする その2",zh_CN:"提交交换戏法 #2"},hint:{en_US:"Don't forget to forward master to the updated changes!",ja:"masterのポインタを先に進めることを忘れずに!",ko:"master를 변경 완료한 커밋으로 이동(forward)시키는 것을 잊지 마세요!",zh_CN:"别忘记了将 master 快进到最新的更新上!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Juggling Commits #2","","*If you haven't completed Juggling Commits #1 (the previous level), please do so before continuing*","","As you saw in the last level, we used `rebase -i` to reorder the commits. Once the commit we wanted to change was on top, we could easily --amend it and re-order back to our preferred order.","","The only issue here is that there is a lot of reordering going on, which can introduce rebase conflicts. Let's look at another method with `git cherry-pick`"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Remember that git cherry-pick will plop down a commit from anywhere in the tree onto HEAD (as long as that commit isn't upstream).","","Here's a small refresher demo:"],afterMarkdowns:["Nice! Let's move on"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["So in this level, let's accomplish the same objective of amending `C2` once but avoid using `rebase -i`. I'll leave it up to you to figure it out! :D","","Remember, the exact number of apostrophe's (') on the commit are not important, only the relative differences. For example, I will give credit to a tree that matches the goal tree but has one extra apostrophe everywhere"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## コミットをやりくりする その2","","*注意 この一つ前のレベル「コミットをやりくりする」をクリアしていない人は、まずそちらの問題をクリアしてきてください*","","前回見てきたように、コミット順序の変更のために、私たちは`rebase -i`コマンドを利用しました。ツリーの先頭に変更対象のコミットがあれば、--amendオプションを使うことで容易に変更を書きかえて、元の順序に戻すことができます。","","この場合に心配なことが一つだけあって、それは複数回の順序の変更が行われるので、rebaseのコンフリクト(衝突)が起こりうることです。こういうケースへの対策として、`git cherry-pick`を使った別の解決法について考えてみましょう。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["git cherry-pickを使うと、ツリーの中から複数のコミットを選んで、HEADの下に新しく作ることができましたね。","","簡単なデモを見てみましょう:"],afterMarkdowns:["できました!次へ進みましょう"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["このレベルでは、`C2`をamendすることで前回と同じ目的を達成しましょう。但し`rebase -i`は使わずにクリアしてください。どんな方法で進めるかはあなたにおまかせします!:D"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 提交变换戏法 #2","","*假如你还没有完成提交变换戏法 #1(前一关),这关不让玩哦!*","","如你在上一关所见,我们使用 `rebase -i` 来重排那些提交。只要把我们想要的提交挪到最顶端,我们就可以很容易地改变它,然后把它们重新排成我们想要的顺序。","","但唯一的问题就是这样做就要排很多次,有可能造成衍合冲突(rebase conflicts)。下面就看看用另外一种方法 `git cherry-pick` 是怎么做的吧。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["要在心理牢记 cherry-pick 可以从提交树的任何地方拿一个提交来放在 HEAD 上(尽管那个提交不在上游)。","","下面是一个小小的演示:"],command:"git cherry-pick C2",afterMarkdowns:["好滴咧,我们继续"],beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["那么这关呢,和上一关一样要改变提交 `C2`,但你要避免使用 `rebase -i`。自己想想要怎么解决吧,骚年! :D"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 커밋 갖고 놀기 #2","","*만약 이전 레벨의 커밋 갖고 놀기 #1을 풀지 않으셨다면, 계속하기에 앞서서 꼭 풀어보세요*","","이전 레벨에서 보셨듯이 `rebase -i` 명령으로 커밋의 순서를 바꿀 수 있습니다. 정정할 커밋이 바로 직전(top)에 있으면 간단히 --amend로 수정할 수 있고, 그리고 나서 다시 원하는 순서로 되돌려 놓으면 됩니다.","","이번에 한가지 문제는 순서를 꽤 많이 바꿔야한다는 점인데요, 그러다가 리베이스중에 충돌이 날 수 있습니다. 이번에는 다른 방법인 `git cherry-pick`으로 해결해 봅시다."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["git cherry-pick으로 HEAD에다 어떤 커밋이든 떨어 뜨려 놓을 수 있다고 알려드린것 기억나세요? (단, 그 커밋이 현재 가리키고 있는 커밋이 아니어야합니다)","","간단한 데모로 다시 알려드리겠습니다:"],afterMarkdowns:["좋아요! 계속할게요"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["그럼 이번 레벨에서는 아까와 마찬가지로 `C2` 커밋의 내용을 정정하되, `rebase -i`를 쓰지 말고 해보세요. ^.~"]}}]}}}}),e("/src/levels/mixed/jugglingCommits2.js"),e.define("/src/levels/rampup/detachedHead.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"C4","id":"HEAD"}}',solutionCommand:"git checkout C4",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Detach yo' HEAD",zh_CN:"分离HEAD"},hint:{en_US:"Use the label (hash) on the commit for help!",zh_CN:"使用提交记录上的标签(hash)来求助!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Moving around in Git","","Before we get to some of the more advanced features of Git, it's important to understand different ways to move through the commit tree that represents your project.","","Once you're comfortable moving around, your powers with other git commands will be amplified!","","","","",""]}},{type:"ModalAlert",options:{markdowns:["## HEAD","","First we have to talk about \"HEAD\". HEAD is the symbolic name for the currently checked out commit -- it's essentially what commit you're working on top of.","","HEAD always points to the most recent commit which is reflected in the working tree. Most git commands which make changes to the working tree will start by changing HEAD.","","Normally HEAD points to a branch name (like bugFix). When you commit, the status of bugFix is altered and this change is visible through HEAD."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's see this in action. Here we will reveal HEAD before and after a commit."],afterMarkdowns:["See! HEAD was hiding underneath our `master` branch all along."],command:"git checkout C1; git checkout master; git commit; git checkout C2",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["### Detaching HEAD","","Detaching HEAD just means attaching it to a commit instead of a branch. This is what it looks like beforehand:","","HEAD -> master -> C1",""],afterMarkdowns:["And now it's","","HEAD -> C1"],command:"git checkout C1",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["To complete this level, let's detach HEAD from `bugFix` and attach it to the commit instead.","","Specify this commit by its hash. The hash for each commit is displayed on the circle that represents the commit."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 在Git中前后移动","","在接触Git的更多高级主题之前,我们先学习用不同的方法在代表你的项目的提交记录树上前后移动。","","一旦能够熟练地在Git中前进后退,你使用其他git命令的威力也会被放大!","","","","",""]}},{type:"ModalAlert",options:{markdowns:["## HEAD","",'我们首先看一下"HEAD". HEAD是当前提交记录的符号名称 -- 其实就是你正在其基础进行工作的提交记录。',"","HEAD总是指向最近一次提交记录,表现为当前工作树。大多数修改工作树的git命令都开始于改变HEAD指向。","","HEAD通常指向分支名(比如bugFix)。你提交时,改变了bugFix的状态,这一变化通过HEAD变得可见。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["在实例中看一下。我们将会观察提交前后HEAD的位置。"],afterMarkdowns:["看! HEAD一直藏在`master`分支后面。"],command:"git checkout C1; git checkout master; git commit; git checkout C2",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["### 分离 HEAD","","分离HEAD就是让其指向一个提交记录而不是分支名。这是命令执行之前的样子: ","","HEAD -> master -> C1",""],afterMarkdowns:["现在变成了","","HEAD -> C1"],command:"git checkout C1",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["想完成此关,从`bugFix`分离出HEAD并让其指向一个提交记录。","","通过hash值指定提交记录。每个提交记录的hash值显示在代表提交记录的圆圈中。"]}}]}}}}),e("/src/levels/rampup/detachedHead.js"),e.define("/src/levels/rampup/relativeRefs.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"C3","id":"HEAD"}}',solutionCommand:"git checkout bugFix^",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Relative Refs (^)",zh_CN:"相对引用(^)"},hint:{en_US:"Remember the Caret (^) operator!",zh_CN:"记住插入(^)操作符!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Relative Refs","","Moving around in Git by specifying commit hashes can get a bit tedious. In the real world you won't have a nice commit tree visualization next to your terminal, so you'll have to use `git log` to see hashes.","","Furthermore, hashes are usually a lot longer in the real Git world as well. For instance, the hash of the commit that introduced the previous level is `fed2da64c0efc5293610bdd892f82a58e8cbc5d8`. Doesn't exactly roll off the tongue...","","The upside is that Git is smart about hashes. It only requires you to specify enough characters of the hash until it uniquely identifies the commit. So I can type `fed2` instead of the long string above."]}},{type:"ModalAlert",options:{markdowns:["Like I said, specifying commits by their hash isn't the most convenient thing ever, which is why Git has relative refs. They are awesome!","","With relative refs, you can start somewhere memorable (like the branch `bugFix` or `HEAD`) and work from there.","","Relative commits are powerful, but we will introduce two simple ones here:","","* Moving upwards one commit at a time with `^`","* Moving upwards a number of times with `~`"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's look at the Caret (^) operator first. Each time you append that to a ref name, you are telling Git to find the parent of the specified commit.","",'So saying `master^` is equivalent to "the first parent of `master`".',"","`master^^` is the grandparent (second-generation ancestor) of `master`","","Let's check out the commit above master here"],afterMarkdowns:["Boom! Done. Way easier than typing the commit hash"],command:"git checkout master^",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["You can also reference `HEAD` as a relative ref. Let's use that a couple of times to move upwards in the commit tree"],afterMarkdowns:["Easy! We can travel backwards in time with `HEAD^`"],command:"git checkout C3; git checkout HEAD^; git checkout HEAD^; git checkout HEAD^",beforeCommand:"git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["To complete this level, check out the parent commit of `bugFix`. This will detach `HEAD`.","","You can specify the hash if you want, but try using relative refs instead!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 相对引用","","用指定提交记录hash值的方式在Git中移动会变得比较乏味。在现实中,你不会有漂亮的可视化的提交记录树放在终端旁边,所以你不得不用`git log`来查看hasn值。","","另外,hash值在真实的Git环境中也会更长。举个例子,前一关的介绍中的提交记录的hash值是`fed2da64c0efc5293610bdd892f82a58e8cbc5d8`。不要把舌头闪了...","","好的一面是,Git对hash的处理很智能。你只需要提供能够唯一标识提交记录的前几个字符即可。所以,我可以仅输入`fed2`而不是上面的一长串字符。"]}},{type:"ModalAlert",options:{markdowns:["我说过,通过hash指定提交记录不是很方便,所以Git引入了相对引用。这个就很牛掰了!","","使用相对引用,你可以从一个易于记忆的地方(比如分支名`bugFix`或`HEAD`)开始工作。","","相对引用非常给力,这里我介绍两个简单的用法:","","* 使用`^`向上移动1个提交记录","* 使用`~`向上移动多个提交记录"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["首先看看插入(^)操作符。把插入符跟在引用名后面,表示让Git寻找指定提交记录的父提交。","",'所以`master^`相当于"`master`的父提交"。',"","`master^^`是`master`的父父提交(上上代祖先)","","切换到master的父提交"],afterMarkdowns:["唰!搞定。这种方式比输入提交记录的hash值简单多了!"],command:"git checkout master^",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["你也可以`HEAD`把用作相对引用。以下命令使用`HEAD`在提交树中向上移动几次。"],afterMarkdowns:["简单!我们可以一直使用`HEAD^`向上移动。"],command:"git checkout C3; git checkout HEAD^; git checkout HEAD^; git checkout HEAD^",beforeCommand:"git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["要完成此关,切换到`bugFix`的父提交。这会分离出`HEAD`.","","如果你愿意的话,使用hash值也可以过关,但为何不试试使用相对引用呢?"]}}]}}}}),e("/src/levels/rampup/relativeRefs.js"),e.define("/src/levels/rampup/relativeRefs2.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C6","id":"master"},"bugFix":{"target":"C0","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C5":{"parents":["C3"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"C1","id":"HEAD"}}',solutionCommand:"git branch -f master C6;git checkout HEAD~1;git branch -f bugFix HEAD~1",startTree:'{"branches":{"master":{"target":"C4","id":"master"},"bugFix":{"target":"C5","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C5":{"parents":["C3"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"C2","id":"HEAD"}}',hint:{en_US:"You'll need to use at least one direct reference (hash) to complete this level",zh_CN:"这一关至少要用到一次直接引用(hash)"},name:{en_US:"Relative Refs #2 (~)",zh_CN:"相对引用2(~)"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:['### The "~" operator',"","Say you want to move a lot of levels up in the commit tree. It might be tedious to type `^` several times, so Git also has the tilde (~) operator.","","","The tilde operator (optionally) takes in a trailing number that specifies the number of parents you would like to ascend. Let's see it in action"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's specify a number of commits back with `~`."],afterMarkdowns:["Boom! So concise -- relative refs are great."],command:"git checkout HEAD~4",beforeCommand:"git commit; git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["### Branch forcing","","You're an expert on relative refs now, so let's actually *use* them for something.","","One of the most common ways I use relative refs is to move branches around. You can directly reassign a branch to a commit with the `-f` option. So something like:","","`git branch -f master HEAD~3`","","Moves (by force) the master branch to three parents behind HEAD."]}},{type:"ModalAlert",options:{markdowns:["To complete this level, move `HEAD`, `master`, and `bugFix` to their goal destinations shown."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:['### The "~" operator',"","假设需要在提交树中向上移动很多步。使用多个`^`非常无聊,所以Git也引入了波浪(~)操作符。","","","波浪操作符后面可以(可选地)跟一个数字,指定向上移动多少次。看个例子"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用`~`一次后退多步."],afterMarkdowns:["唰!如此简洁--相对引用就是好啊!"],command:"git checkout HEAD~4",beforeCommand:"git commit; git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["### Branch forcing","","你现在是相对引用的高手了,现在*用*他来实际做点事情。","","我使用相对引用最多的就是移动分支。你可以使用`-f`选项把直接让分支指向另一个提交。举个例子:","","`git branch -f master HEAD~3`","","(强制)移动master指向HEAD的第3级父提交。"]}},{type:"ModalAlert",options:{markdowns:["要完成此关,移动`HEAD`,`master`和`bugFix`到目标所示的位置。"]}}]}}}}),e("/src/levels/rampup/relativeRefs2.js"),e.define("/src/levels/rampup/reversingChanges.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22master%22%7D%2C%22pushed%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22pushed%22%7D%2C%22local%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22local%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C2%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22pushed%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git reset HEAD~1;git checkout pushed;git revert HEAD",compareOnlyBranches:!0,startTree:'{"branches":{"master":{"target":"C1","id":"master"},"pushed":{"target":"C2","id":"pushed"},"local":{"target":"C3","id":"local"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"}},"HEAD":{"target":"local","id":"HEAD"}}',name:{en_US:"Reversing Changes in Git",ja:"変更を元に戻す",fr_FR:"Annuler des changements avec Git",ko:"Git에서 작업 되돌리기",zh_CN:"在Git中撤销更改"},hint:{en_US:"Notice that revert and reset take different arguments.",fr_FR:"",zh_CN:"注意revert和reset使用不同的参数。",ko:"",ja:""},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Reversing Changes in Git","","There are many ways to reverse changes in Git. And just like committing, reversing changes in Git has both a low-level component (staging individual files or chunks) and a high-level component (how the changes are actually reversed). Our application will focus on the latter.","","There are two primary ways to undo changes in Git -- one is using `git reset` and the other is using `git revert`. We will look at each of these in the next dialog",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","",'`git reset` reverts changes by moving a branch reference backwards in time to an older commit. In this sense you can think of it as "rewriting history;" `git reset` will move a branch backwards as if the commit had never been made in the first place.',"","Let's see what that looks like:"],afterMarkdowns:["Nice! Git simply moved the master branch reference back to `C1`; now our local repository is in a state as if `C2` had never happened"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","",'While reseting works great for local branches on your own machine, its method of "rewriting history" doesn\'t work for remote branches that others are using.',"","In order to reverse changes and *share* those reversed changes with others, we need to use `git revert`. Let's see it in action"],afterMarkdowns:["Weird, a new commit plopped down below the commit we wanted to reverse. That's because this new commit `C2'` introduces *changes* -- it just happens to introduce changes that exactly reverses the commit of `C2`.","","With reverting, you can push out your changes to share with others."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["To complete this level, reverse the two most recent commits on both `local` and `pushed`.","","Keep in mind that `pushed` is a remote branch and `local` is a local branch -- that should help you choose your methods."]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## 変更を元に戻す","","Gitでは変更を元に戻す方法がたくさんあります。コミットと同じように、低レベルな動作(ファイル別だったりファイルの中の一部だったり)も高レベルな動作(変更のまとまりのキャンセル)もできます。このアプリケーションでは後者の方法について紹介します。","","基本的なアンドゥの方法が2つあります - 一つは`git reset`を使う方法で、もう1つは`git revert`を使う方法です。次のダイアログで一つ一つを見ていきます。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","","`git reset`はブランチのポインタを後方に移動することで変更のキャンセルを実現します。履歴を上書きするような動作だと思うと良いでしょうか:`git reset`はそもそも前のコミットなんかなかったかのように、ブランチのポインタを元に戻してくれます。","","どういう感じか見てみましょう。"],afterMarkdowns:["いいですね!Gitは単純にmasterブランチへのポインタを`C1`へ戻しました。これでこのローカルリポジトリにはまるで`C2`なんて無かったかのように変更をキャンセルできました。"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","自分のマシン上のブランチではさっきの`git reset`でうまくいきましたが、この「履歴を上書きする」手段は、他の人も使っているリモートにあるリポジトリに対しては使うことができません。","","変更を巻き戻して他の人とそれを共有するためには、`git revert`を使う必要があります。今度はこれを見てみましょう。"],afterMarkdowns:["あれ、おかしいな。巻き戻したいと思ってたコミットの下に新しいコミットが出来上がってしまったみたいです。なぜか。これは、この新しい`C2'`コミットは`C2`へ戻すのに必要な内容を確かに変更して巻き戻していたのです。","","こんな風にして、巻き戻した内容を他人と共有するためにはrevertを使います。"],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["この章の仕上げに、`local`と`pushed`の両方の直近のコミットを巻き戻してみましょう。","","`pushed`はリモートのブランチで、`local`はローカルであることに注意。正しくコマンドを使い分けましょう。"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Annuler des changements avec Git","","Il y a de nombreuses façons d'annuler des changement avec Git. De même que pour les commits, annuler des changements avec Git a à la fois un aspect bas-niveau (gestion dans le 'staging' des fichiers et morceaux de fichiers) et un aspect de plus haut niveau 9comment les changements sont effectivement annulés). Nous allons nous intéresser à ce dernier point.","","Il y a principalement deux façons d'annuler des changements avec Git -- l'une est `git reset` et l'autre est `git revert`. Nous allons maintenant voir chacune de ces façons",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","","`git reset` annule des changements en déplaçant la référence en arrière dans le temps sur un commit plus ancien. En ce sens, on peut considérer cela comme une façon de \"réécrire l'histoire\"; `git reset` fait remonter une branche en arrière comme si le(s) commit(s) n'avait jamais eu lieu.","","Regardons à quoi cela ressemble :"],afterMarkdowns:["Bravo ! Git a simplement déplacé la référence de la branche master en la faisant revenir sur `C1`; désormais notre dépôt est dans le même état que si `C2` n'avait jamais eu lieu"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","Bien que le reset marche parfaitement pour les branches locales sur notre propre machine, cette façon de \"réécrire l'histoire\" ne marche pas avec les banches distantes (remote) que d'autres personnes utilisent.","","Pour pouvoir annuler des changements et *partager* ces annulations avec d'autres, nous devons utiliser `git revert`. Regardons comment cela fonctionne"],afterMarkdowns:["Étrangement, un nouveau commit est appaaru en bas sous le commit que nous voulions annuler. C'est parce que ce nouveau commit `C2'` introduit des *modifications* -- celles qui correspondent justement à l'annulation de celles du commit `C2`.","","Avec revert, vous pouvez diffuser (push) vos modifications et les partager avec tout le monde."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["Pour accomplir ce niveau, annulez les deux derniers commits à la fois sur `local` et sur `pushed`.","","Ayez à l'esprit que `pushed` est une branche distante et `local` est une branche locale -- cela devrait vous guider dans le choix de la méthode à employer."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 撤销 Git 里面的变动","","在 Git 里撤销修改的方法很多。和 commit 一样,在 Git 里撤销变动同时具有底层部分(暂存一些独立的文件或者片段)和高层部分(具体到变动是究竟怎么被撤销的)。我们这个应用主要关注后者。","","在 Git 里主要用两种方法来撤销变动 —— 一种是 `git reset`,另外一种是 `git revert`。让我们在下一个窗口逐一了解它们。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","",'`git reset`把分支记录回退到上一个提交记录来实现撤销改动。你可以认为这是在"重写历史"。`git reset`往回移动分支,原来指向的提交记录好像重来没有提交过一样。',"","让我们看看具体的操作:"],command:"git reset HEAD~1",afterMarkdowns:["Nice!Git把master分支的指向简单地移回到`C1`;现在我们的本地代码库处于没有提交过`C2`的状态了。"],beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","虽然在你的本地分支中使用`git reset`很方便,但是这种“改写历史”的方法对别人的远端分支是无效的哦!","","为了撤销更改并*传播*给别人,我们需要使用`git revert`。举个例子"],command:"git revert HEAD",afterMarkdowns:["怪哉!在我们要撤销的提交记录后面居然多了一个新提交!这是因为新提交记录`C2'`引入了*更改*——刚好是用来撤销 `C2` 这个提交的。","","借助 revert,现在可以把你的更改传递给别人啦。"],beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["要完成此关,分别撤销`local`分支和`pushed`分支上的最近一次提交。","","记住 `pushed` 是一个远程分支,`local` 是一个本地分支 —— 有了这么明显的提示应该知道用哪种方法了吧?"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git에서 작업 되돌리기","","Git에는 작업한 것을 되돌리는 여러가지 방법이 있습니다. 변경내역을 되돌리는 것도 커밋과 마찬가지로 낮은 수준의 일(개별 파일이나 묶음을 스테이징 하는 것)과 높은 수준의 일(실제 변경이 복구되는 방법)이 있는데요, 여기서는 후자에 집중해 알려드릴게요.","","Git에서 변경한 내용을 되돌리는 방법은 크게 두가지가 있습니다 -- 하나는 `git reset`을 쓰는거고, 다른 하나는 `git revert`를 사용하는 것입니다. 다음 화면에서 하나씩 알아보겠습니다.",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git 리셋(reset)","",'`git reset`은 브랜치로 하여금 예전의 커밋을 가리키도록 이동시키는 방식으로 변경 내용을 되돌립니다. 이런 관점에서 "히스토리를 고쳐쓴다"라고 말할 수 있습니다. 즉, `git reset`은 마치 애초에 커밋하지 않은 것처럼 예전 커밋으로 브랜치를 옮기는 것입니다.',"","어떤 그림인지 한번 보죠:"],afterMarkdowns:["그림에서처럼 master 브랜치가 가리키던 커밋을 `C1`로 다시 옮겼습니다; 이러면 로컬 저장소에는 마치 `C2`커밋이 아예 없었던 것과 마찬가지 상태가 됩니다."],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git 리버트(revert)","",'각자의 컴퓨터에서 작업하는 로컬 브랜치의 경우 리셋(reset)을 잘 쓸 수 있습니다만, "히스토리를 고쳐쓴다"는 점 때문에 다른 사람이 작업하는 리모트 브랜치에는 쓸 수 없습니다.',"","변경분을 되돌리고, 이 되돌린 내용을 다른 사람들과 *공유하기* 위해서는, `git revert`를 써야합니다. 예제로 살펴볼게요."],afterMarkdowns:["어색하게도, 우리가 되돌리려고한 커밋의 아래에 새로운 커밋이 생겼습니다. `C2`라는 새로운 커밋에 *변경내용*이 기록되는데요, 이 변경내역이 정확히 `C2` 커밋 내용의 반대되는 내용입니다.","","리버트를 하면 다른 사람들에게도 변경 내역을 밀어(push) 보낼 수 있습니다."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["이 레벨을 통과하려면, `local` 브랜치와 `pushed` 브랜치에 있는 최근 두 번의 커밋을 되돌려 보세요.","","`pushed`는 리모트 브랜치이고, `local`은 로컬 브랜치임을 신경쓰셔서 작업하세요 -- 어떤 방법을 선택하실지 떠오르시죠?"]}}]}}}}),e("/src/levels/rampup/reversingChanges.js"),e.define("/src/levels/rebase/manyRebases.js",function(e,t,n,r,i,s,o){n.level={compareOnlyMasterHashAgnostic:!0,disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22master%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22bugFix%22%7D%2C%22side%22%3A%7B%22target%22%3A%22C6%27%22%2C%22id%22%3A%22side%22%7D%2C%22another%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22another%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C6%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C6%22%7D%2C%22C7%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C7%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C6%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C6%27%22%7D%2C%22C7%27%22%3A%7B%22parents%22%3A%5B%22C6%27%22%5D%2C%22id%22%3A%22C7%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout bugFix;git rebase master;git checkout side;git rebase bugFix;git checkout another;git rebase side;git rebase another master",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C3","id":"bugFix"},"side":{"target":"C6","id":"side"},"another":{"target":"C7","id":"another"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C0"],"id":"C4"},"C5":{"parents":["C4"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"},"C7":{"parents":["C5"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Rebasing over 9000 times",ko:"9천번이 넘는 리베이스",ja:"Rebasing over 9000 times",zh_CN:"N次Rebase"},hint:{en_US:"Remember, the most efficient way might be to only update master at the end...",ja:"最も効率的なやり方はmasterを最後に更新するだけかもしれない・・・",ko:"아마도 master를 마지막에 업데이트하는 것이 가장 효율적인 방법일 것입니다...",zh_CN:"记住,最后更新master分支可能是最高效的方法。"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["### Rebasing Multiple Branches","","Man, we have a lot of branches going on here! Let's rebase all the work from these branches onto master.","","Upper management is making this a bit trickier though -- they want the commits to all be in sequential order. So this means that our final tree should have `C7'` at the bottom, `C6'` above that, etc etc, etc all in order.","","If you mess up along the way, feel free to use `reset` to start over again. Be sure to check out our solution and see if you can do it in fewer commands!"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["### 複数のブランチをリベースする","","さあ、いくつものブランチが出てきます。このブランチたち全てをmasterブランチにリベースしましょう。","","おエライさん方が今回の仕事を少しトリッキーにしてくれました ― コミットはすべて一列のシーケンシャルな状態にしてほしいそうです。つまり私たちが作るリポジトリの最終的なツリーの状態は、`C7'`が最後に来て、`C6'`がその一つ上に来て、、と順に積み重なるイメージです。","","試行錯誤してツリーが汚くなってきたら、`reset`コマンドを使ってツリーの状態を初期化してください。模範解答をチェックして、それよりも簡単なコマンドで済ませられるかどうか、を考えるのも忘れずに!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["### 多分支衍合","","呐,现在我们有很多分支啦!让我们rebase这些分支的工作到 master 分支上吧。","","但是你的头头找了点麻烦 —— 他们希望得到有序的提交历史,也就是我们最终的结果是 `C7'` 在最底部,`C6'` 在它上面,以此类推。","","假如你搞砸了,没所谓的(虽然我不会告诉你用 `reset` 可以重新开始)。记得看看我们提供的答案,看你能否使用更少的命令完成任务!"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["### 여러 브랜치를 리베이스(rebase)하기 ","","음, 여기 꽤 여러개의 브랜치가 있습니다! 이 브랜치들의 모든 작업내역을 master에 리베이스 해볼까요?","","윗선에서 일을 복잡하게 만드네요 -- 그 분들이 이 모든 커밋들을 순서에 맞게 정렬하라고 합니다. 그럼 결국 우리의 최종 목표 트리는 제일 아래에 `C7'` 커밋, 그 위에 `C6'` 커밋, 또 그 위에 순서대로 보여합니다.","","만일 작업중에 내용이 꼬인다면, `reset`이라고 쳐서 처음부터 다시 시작할 수 있습니다. 모범 답안을 확인해 보시고, 혹시 더 적은 수의 커맨드로 해결할 수 있는지 알아보세요!"]}}]}}}}),e("/src/levels/rebase/manyRebases.js"),e.define("/src/levels/rebase/selectiveRebase.js",function(e,t,n,r,i,s,o){n.level={compareAllBranchesHashAgnostic:!0,disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C5%22%2C%22id%22%3A%22master%22%7D%2C%22one%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22one%22%7D%2C%22two%22%3A%7B%22target%22%3A%22C2%27%27%22%2C%22id%22%3A%22two%22%7D%2C%22three%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22three%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C4%27%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C4%27%27%22%7D%2C%22C3%27%27%22%3A%7B%22parents%22%3A%5B%22C4%27%27%22%5D%2C%22id%22%3A%22C3%27%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C3%27%27%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22two%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout one; git cherry-pick C4 C3 C2; git checkout two; git cherry-pick C5 C4 C3 C2; git branch -f three C2",startTree:'{"branches":{"master":{"target":"C5","id":"master"},"one":{"target":"C1","id":"one"},"two":{"target":"C1","id":"two"},"three":{"target":"C1","id":"three"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C4"],"id":"C5"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{ko:"브랜치 스파게티",en_US:"Branch Spaghetti",ja:"ブランチスパゲッティ",zh_CN:"分支浆糊"},hint:{en_US:"Make sure to do everything in the proper order! Branch one first, then two, then three",ja:"全て正しい順番で処理すること!oneが最初で、次がtwo、最後にthreeを片付ける。",ko:"이 문제를 해결하는 방법은 여러가지가 있습니다! 체리픽(cherry-pick)이 가장 쉽지만 오래걸리는 방법이고, 리베이스(rebase -i)가 빠른 방법입니다",zh_CN:"确保你是按照正确的顺序来操作!先操作分支 `one`, 然后 `two`, 最后才是 `three`"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branch Spaghetti","","WOAHHHhhh Nelly! We have quite the goal to reach in this level.","","Here we have `master` that is a few commits ahead of branches `one` `two` and `three`. For whatever reason, we need to update these three other branches with modified versions of the last few commits on master.","","Branch `one` needs a re-ordering and a deletion of `C5`. `two` needs pure reordering, and `three` only needs one commit!","","We will let you figure out how to solve this one -- make sure to check out our solution afterwards with `show solution`. "]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ブランチスパゲッティ","","なんということでしょう。今回のレベルクリアのために、やることがたくさんあります。","","いま`master`が指しているコミットの数個前のコミットに、ブランチ`one`、`two`それから`three`があります。何か事情があって、これらの3つのブランチをmasterが指している最新の状態に更新したいケースを考えます。","","ブランチ`one`に対しては、順序の変更と`C5`の削除が必要です。`two`では順序の変更のみ、`three`に対しては1回だけコミットすればOKです。","","`show solution`コマンドで模範解答を確認できますから、こちらも利用してください。 "]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branch Spaghetti","","哇塞大神!这关我们要来点不同的!","","现在我们的 `master` 分支是比 `one` `two` 和 `three` 要多几个提交。出于某种原因,我们需要把其他三个分支更新到 master 分支上新近的几个不同提交上。(update these three other brances with modified versions of the last few commits on master)","","分支 `one` 需要重新排序和撤销, `two` 需要完全重排,而 `three` 只需要提交一次。","","慢慢摸索会找到答案的 —— 你完事记得用 `show solution` 看看我们的答案哦。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 브랜치 스파게티","","음, 이번에는 만만치 않습니다!","","여기 `master` 브랜치의 몇 번 이전 커밋에 `one`, `two`,`three` 총 3개의 브랜치가 있습니다. 어떤 이유인지는 몰라도, master의 최근 커밋 몇 개를 나머지 세 개의 브랜치에 반영하려고 합니다.","","`one` 브랜치는 순서를 바꾸고 `C5`커밋을 삭제하고, `two`브랜치는 순서만 바꾸며, `three`브랜치는 하나의 커밋만 가져옵시다!","","자유롭게 이 문제를 풀어보시고 나서 `show solution`명령어로 모범 답안을 확인해보세요."]}}]}}}}),e("/src/levels/rebase/selectiveRebase.js")})(); \ No newline at end of file diff --git a/build/bundle.min.js b/build/bundle.min.js index a8b4b8c2..fc7c1afc 100644 --- a/build/bundle.min.js +++ b/build/bundle.min.js @@ -1 +1 @@ -(function(){var e=function(t,n){var r=e.resolve(t,n||"/"),i=e.modules[r];if(!i)throw new Error("Failed to resolve module "+t+", tried "+r);var s=e.cache[r],o=s?s.exports:i();return o};e.paths=[],e.modules={},e.cache={},e.extensions=[".js",".coffee",".json"],e._core={assert:!0,events:!0,fs:!0,path:!0,vm:!0},e.resolve=function(){return function(t,n){function u(t){t=r.normalize(t);if(e.modules[t])return t;for(var n=0;n=0;i--){if(t[i]==="node_modules")continue;var s=t.slice(0,i+1).join("/")+"/node_modules";n.push(s)}return n}n||(n="/");if(e._core[t])return t;var r=e.modules.path();n=r.resolve("/",n);var i=n||"/";if(t.match(/^(?:\.\.?\/|\/)/)){var s=u(r.resolve(i,t))||a(r.resolve(i,t));if(s)return s}var o=f(t,i);if(o)return o;throw new Error("Cannot find module '"+t+"'")}}(),e.alias=function(t,n){var r=e.modules.path(),i=null;try{i=e.resolve(t+"/package.json","/")}catch(s){i=e.resolve(t,"/")}var o=r.dirname(i),u=(Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t})(e.modules);for(var a=0;a=0;r--){var i=e[r];i=="."?e.splice(r,1):i===".."?(e.splice(r,1),n++):n&&(e.splice(r,1),n--)}if(t)for(;n--;n)e.unshift("..");return e}var f=/^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;n.resolve=function(){var e="",t=!1;for(var n=arguments.length;n>=-1&&!t;n--){var r=n>=0?arguments[n]:s.cwd();if(typeof r!="string"||!r)continue;e=r+"/"+e,t=r.charAt(0)==="/"}return e=a(u(e.split("/"),function(e){return!!e}),!t).join("/"),(t?"/":"")+e||"."},n.normalize=function(e){var t=e.charAt(0)==="/",n=e.slice(-1)==="/";return e=a(u(e.split("/"),function(e){return!!e}),!t).join("/"),!e&&!t&&(e="."),e&&n&&(e+="/"),(t?"/":"")+e},n.join=function(){var e=Array.prototype.slice.call(arguments,0);return n.normalize(u(e,function(e,t){return e&&typeof e=="string"}).join("/"))},n.dirname=function(e){var t=f.exec(e)[1]||"",n=!1;return t?t.length===1||n&&t.length<=3&&t.charAt(1)===":"?t:t.substring(0,t.length-1):"."},n.basename=function(e,t){var n=f.exec(e)[2]||"";return t&&n.substr(-1*t.length)===t&&(n=n.substr(0,n.length-t.length)),n},n.extname=function(e){return f.exec(e)[3]||""}}),e.define("__browserify_process",function(e,t,n,r,i,s,o){var s=t.exports={};s.nextTick=function(){var e=typeof window!="undefined"&&window.setImmediate,t=typeof window!="undefined"&&window.postMessage&&window.addEventListener;if(e)return function(e){return window.setImmediate(e)};if(t){var n=[];return window.addEventListener("message",function(e){if(e.source===window&&e.data==="browserify-tick"){e.stopPropagation();if(n.length>0){var t=n.shift();t()}}},!0),function(t){n.push(t),window.postMessage("browserify-tick","*")}}return function(t){setTimeout(t,0)}}(),s.title="browser",s.browser=!0,s.env={},s.argv=[],s.binding=function(t){if(t==="evals")return e("vm");throw new Error("No such module. (Possibly not yet loaded)")},function(){var t="/",n;s.cwd=function(){return t},s.chdir=function(r){n||(n=e("path")),t=n.resolve(r,t)}}()}),e.define("/node_modules/underscore/package.json",function(e,t,n,r,i,s,o){t.exports={main:"underscore.js"}}),e.define("/node_modules/underscore/underscore.js",function(e,t,n,r,i,s,o){(function(){var e=this,r=e._,i={},s=Array.prototype,o=Object.prototype,u=Function.prototype,a=s.push,f=s.slice,l=s.concat,c=o.toString,h=o.hasOwnProperty,p=s.forEach,d=s.map,v=s.reduce,m=s.reduceRight,g=s.filter,y=s.every,b=s.some,w=s.indexOf,E=s.lastIndexOf,S=Array.isArray,x=Object.keys,T=u.bind,N=function(e){if(e instanceof N)return e;if(!(this instanceof N))return new N(e);this._wrapped=e};typeof n!="undefined"?(typeof t!="undefined"&&t.exports&&(n=t.exports=N),n._=N):e._=N,N.VERSION="1.4.4";var C=N.each=N.forEach=function(e,t,n){if(e==null)return;if(p&&e.forEach===p)e.forEach(t,n);else if(e.length===+e.length){for(var r=0,s=e.length;r2;e==null&&(e=[]);if(v&&e.reduce===v)return r&&(t=N.bind(t,r)),i?e.reduce(t,n):e.reduce(t);C(e,function(e,s,o){i?n=t.call(r,n,e,s,o):(n=e,i=!0)});if(!i)throw new TypeError(k);return n},N.reduceRight=N.foldr=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(m&&e.reduceRight===m)return r&&(t=N.bind(t,r)),i?e.reduceRight(t,n):e.reduceRight(t);var s=e.length;if(s!==+s){var o=N.keys(e);s=o.length}C(e,function(u,a,f){a=o?o[--s]:--s,i?n=t.call(r,n,e[a],a,f):(n=e[a],i=!0)});if(!i)throw new TypeError(k);return n},N.find=N.detect=function(e,t,n){var r;return L(e,function(e,i,s){if(t.call(n,e,i,s))return r=e,!0}),r},N.filter=N.select=function(e,t,n){var r=[];return e==null?r:g&&e.filter===g?e.filter(t,n):(C(e,function(e,i,s){t.call(n,e,i,s)&&(r[r.length]=e)}),r)},N.reject=function(e,t,n){return N.filter(e,function(e,r,i){return!t.call(n,e,r,i)},n)},N.every=N.all=function(e,t,n){t||(t=N.identity);var r=!0;return e==null?r:y&&e.every===y?e.every(t,n):(C(e,function(e,s,o){if(!(r=r&&t.call(n,e,s,o)))return i}),!!r)};var L=N.some=N.any=function(e,t,n){t||(t=N.identity);var r=!1;return e==null?r:b&&e.some===b?e.some(t,n):(C(e,function(e,s,o){if(r||(r=t.call(n,e,s,o)))return i}),!!r)};N.contains=N.include=function(e,t){return e==null?!1:w&&e.indexOf===w?e.indexOf(t)!=-1:L(e,function(e){return e===t})},N.invoke=function(e,t){var n=f.call(arguments,2),r=N.isFunction(t);return N.map(e,function(e){return(r?t:e[t]).apply(e,n)})},N.pluck=function(e,t){return N.map(e,function(e){return e[t]})},N.where=function(e,t,n){return N.isEmpty(t)?n?null:[]:N[n?"find":"filter"](e,function(e){for(var n in t)if(t[n]!==e[n])return!1;return!0})},N.findWhere=function(e,t){return N.where(e,t,!0)},N.max=function(e,t,n){if(!t&&N.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.max.apply(Math,e);if(!t&&N.isEmpty(e))return-Infinity;var r={computed:-Infinity,value:-Infinity};return C(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o>=r.computed&&(r={value:e,computed:o})}),r.value},N.min=function(e,t,n){if(!t&&N.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.min.apply(Math,e);if(!t&&N.isEmpty(e))return Infinity;var r={computed:Infinity,value:Infinity};return C(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;or||n===void 0)return 1;if(n>>1;n.call(r,e[u])=0})})},N.difference=function(e){var t=l.apply(s,f.call(arguments,1));return N.filter(e,function(e){return!N.contains(t,e)})},N.zip=function(){var e=f.call(arguments),t=N.max(N.pluck(e,"length")),n=new Array(t);for(var r=0;r=0;n--)t=[e[n].apply(this,t)];return t[0]}},N.after=function(e,t){return e<=0?t():function(){if(--e<1)return t.apply(this,arguments)}},N.keys=x||function(e){if(e!==Object(e))throw new TypeError("Invalid object");var t=[];for(var n in e)N.has(e,n)&&(t[t.length]=n);return t},N.values=function(e){var t=[];for(var n in e)N.has(e,n)&&t.push(e[n]);return t},N.pairs=function(e){var t=[];for(var n in e)N.has(e,n)&&t.push([n,e[n]]);return t},N.invert=function(e){var t={};for(var n in e)N.has(e,n)&&(t[e[n]]=n);return t},N.functions=N.methods=function(e){var t=[];for(var n in e)N.isFunction(e[n])&&t.push(n);return t.sort()},N.extend=function(e){return C(f.call(arguments,1),function(t){if(t)for(var n in t)e[n]=t[n]}),e},N.pick=function(e){var t={},n=l.apply(s,f.call(arguments,1));return C(n,function(n){n in e&&(t[n]=e[n])}),t},N.omit=function(e){var t={},n=l.apply(s,f.call(arguments,1));for(var r in e)N.contains(n,r)||(t[r]=e[r]);return t},N.defaults=function(e){return C(f.call(arguments,1),function(t){if(t)for(var n in t)e[n]==null&&(e[n]=t[n])}),e},N.clone=function(e){return N.isObject(e)?N.isArray(e)?e.slice():N.extend({},e):e},N.tap=function(e,t){return t(e),e};var _=function(e,t,n,r){if(e===t)return e!==0||1/e==1/t;if(e==null||t==null)return e===t;e instanceof N&&(e=e._wrapped),t instanceof N&&(t=t._wrapped);var i=c.call(e);if(i!=c.call(t))return!1;switch(i){case"[object String]":return e==String(t);case"[object Number]":return e!=+e?t!=+t:e==0?1/e==1/t:e==+t;case"[object Date]":case"[object Boolean]":return+e==+t;case"[object RegExp]":return e.source==t.source&&e.global==t.global&&e.multiline==t.multiline&&e.ignoreCase==t.ignoreCase}if(typeof e!="object"||typeof t!="object")return!1;var s=n.length;while(s--)if(n[s]==e)return r[s]==t;n.push(e),r.push(t);var o=0,u=!0;if(i=="[object Array]"){o=e.length,u=o==t.length;if(u)while(o--)if(!(u=_(e[o],t[o],n,r)))break}else{var a=e.constructor,f=t.constructor;if(a!==f&&!(N.isFunction(a)&&a instanceof a&&N.isFunction(f)&&f instanceof f))return!1;for(var l in e)if(N.has(e,l)){o++;if(!(u=N.has(t,l)&&_(e[l],t[l],n,r)))break}if(u){for(l in t)if(N.has(t,l)&&!(o--))break;u=!o}}return n.pop(),r.pop(),u};N.isEqual=function(e,t){return _(e,t,[],[])},N.isEmpty=function(e){if(e==null)return!0;if(N.isArray(e)||N.isString(e))return e.length===0;for(var t in e)if(N.has(e,t))return!1;return!0},N.isElement=function(e){return!!e&&e.nodeType===1},N.isArray=S||function(e){return c.call(e)=="[object Array]"},N.isObject=function(e){return e===Object(e)},C(["Arguments","Function","String","Number","Date","RegExp"],function(e){N["is"+e]=function(t){return c.call(t)=="[object "+e+"]"}}),N.isArguments(arguments)||(N.isArguments=function(e){return!!e&&!!N.has(e,"callee")}),typeof /./!="function"&&(N.isFunction=function(e){return typeof e=="function"}),N.isFinite=function(e){return isFinite(e)&&!isNaN(parseFloat(e))},N.isNaN=function(e){return N.isNumber(e)&&e!=+e},N.isBoolean=function(e){return e===!0||e===!1||c.call(e)=="[object Boolean]"},N.isNull=function(e){return e===null},N.isUndefined=function(e){return e===void 0},N.has=function(e,t){return h.call(e,t)},N.noConflict=function(){return e._=r,this},N.identity=function(e){return e},N.times=function(e,t,n){var r=Array(e);for(var i=0;i":">",'"':""","'":"'","/":"/"}};D.unescape=N.invert(D.escape);var P={escape:new RegExp("["+N.keys(D.escape).join("")+"]","g"),unescape:new RegExp("("+N.keys(D.unescape).join("|")+")","g")};N.each(["escape","unescape"],function(e){N[e]=function(t){return t==null?"":(""+t).replace(P[e],function(t){return D[e][t]})}}),N.result=function(e,t){if(e==null)return null;var n=e[t];return N.isFunction(n)?n.call(e):n},N.mixin=function(e){C(N.functions(e),function(t){var n=N[t]=e[t];N.prototype[t]=function(){var e=[this._wrapped];return a.apply(e,arguments),I.call(this,n.apply(N,e))}})};var H=0;N.uniqueId=function(e){var t=++H+"";return e?e+t:t},N.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var B=/(.)^/,j={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},F=/\\|'|\r|\n|\t|\u2028|\u2029/g;N.template=function(e,t,n){var r;n=N.defaults({},n,N.templateSettings);var i=new RegExp([(n.escape||B).source,(n.interpolate||B).source,(n.evaluate||B).source].join("|")+"|$","g"),s=0,o="__p+='";e.replace(i,function(t,n,r,i,u){return o+=e.slice(s,u).replace(F,function(e){return"\\"+j[e]}),n&&(o+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'"),r&&(o+="'+\n((__t=("+r+"))==null?'':__t)+\n'"),i&&(o+="';\n"+i+"\n__p+='"),s=u+t.length,t}),o+="';\n",n.variable||(o="with(obj||{}){\n"+o+"}\n"),o="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+o+"return __p;\n";try{r=new Function(n.variable||"obj","_",o)}catch(u){throw u.source=o,u}if(t)return r(t,N);var a=function(e){return r.call(this,e,N)};return a.source="function("+(n.variable||"obj")+"){\n"+o+"}",a},N.chain=function(e){return N(e).chain()};var I=function(e){return this._chain?N(e).chain():e};N.mixin(N),C(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=s[e];N.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e=="shift"||e=="splice")&&n.length===0&&delete n[0],I.call(this,n)}}),C(["concat","join","slice"],function(e){var t=s[e];N.prototype[e]=function(){return I.call(this,t.apply(this._wrapped,arguments))}}),N.extend(N.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this)}),e.define("/node_modules/backbone/package.json",function(e,t,n,r,i,s,o){t.exports={main:"backbone.js"}}),e.define("/node_modules/backbone/backbone.js",function(e,t,n,r,i,s,o){(function(){var t=this,r=t.Backbone,i=[],s=i.push,o=i.slice,u=i.splice,a;typeof n!="undefined"?a=n:a=t.Backbone={},a.VERSION="0.9.10";var f=t._;!f&&typeof e!="undefined"&&(f=e("underscore")),a.$=t.jQuery||t.Zepto||t.ender,a.noConflict=function(){return t.Backbone=r,this},a.emulateHTTP=!1,a.emulateJSON=!1;var l=/\s+/,c=function(e,t,n,r){if(!n)return!0;if(typeof n=="object")for(var i in n)e[t].apply(e,[i,n[i]].concat(r));else{if(!l.test(n))return!0;var s=n.split(l);for(var o=0,u=s.length;o').hide().appendTo("body")[0].contentWindow,this.navigate(t)),this._hasPushState?a.$(window).on("popstate",this.checkUrl):this._wantsHashChange&&"onhashchange"in window&&!r?a.$(window).on("hashchange",this.checkUrl):this._wantsHashChange&&(this._checkUrlInterval=setInterval(this.checkUrl,this.interval)),this.fragment=t;var i=this.location,s=i.pathname.replace(/[^\/]$/,"$&/")===this.root;if(this._wantsHashChange&&this._wantsPushState&&!this._hasPushState&&!s)return this.fragment=this.getFragment(null,!0),this.location.replace(this.root+this.location.search+"#"+this.fragment),!0;this._wantsPushState&&this._hasPushState&&s&&i.hash&&(this.fragment=this.getHash().replace(T,""),this.history.replaceState({},document.title,this.root+this.fragment+i.search));if(!this.options.silent)return this.loadUrl()},stop:function(){a.$(window).off("popstate",this.checkUrl).off("hashchange",this.checkUrl),clearInterval(this._checkUrlInterval),x.started=!1},route:function(e,t){this.handlers.unshift({route:e,callback:t})},checkUrl:function(e){var t=this.getFragment();t===this.fragment&&this.iframe&&(t=this.getFragment(this.getHash(this.iframe)));if(t===this.fragment)return!1;this.iframe&&this.navigate(t),this.loadUrl()||this.loadUrl(this.getHash())},loadUrl:function(e){var t=this.fragment=this.getFragment(e),n=f.any(this.handlers,function(e){if(e.route.test(t))return e.callback(t),!0});return n},navigate:function(e,t){if(!x.started)return!1;if(!t||t===!0)t={trigger:t};e=this.getFragment(e||"");if(this.fragment===e)return;this.fragment=e;var n=this.root+e;if(this._hasPushState)this.history[t.replace?"replaceState":"pushState"]({},document.title,n);else{if(!this._wantsHashChange)return this.location.assign(n);this._updateHash(this.location,e,t.replace),this.iframe&&e!==this.getFragment(this.getHash(this.iframe))&&(t.replace||this.iframe.document.open().close(),this._updateHash(this.iframe.location,e,t.replace))}t.trigger&&this.loadUrl(e)},_updateHash:function(e,t,n){if(n){var r=e.href.replace(/(javascript:|#).*$/,"");e.replace(r+"#"+t)}else e.hash="#"+t}}),a.history=new x;var L=a.View=function(e){this.cid=f.uniqueId("view"),this._configure(e||{}),this._ensureElement(),this.initialize.apply(this,arguments),this.delegateEvents()},A=/^(\S+)\s*(.*)$/,O=["model","collection","el","id","attributes","className","tagName","events"];f.extend(L.prototype,p,{tagName:"div",$:function(e){return this.$el.find(e)},initialize:function(){},render:function(){return this},remove:function(){return this.$el.remove(),this.stopListening(),this},setElement:function(e,t){return this.$el&&this.undelegateEvents(),this.$el=e instanceof a.$?e:a.$(e),this.el=this.$el[0],t!==!1&&this.delegateEvents(),this},delegateEvents:function(e){if(!e&&!(e=f.result(this,"events")))return;this.undelegateEvents();for(var t in e){var n=e[t];f.isFunction(n)||(n=this[e[t]]);if(!n)throw new Error('Method "'+e[t]+'" does not exist');var r=t.match(A),i=r[1],s=r[2];n=f.bind(n,this),i+=".delegateEvents"+this.cid,s===""?this.$el.on(i,n):this.$el.on(i,s,n)}},undelegateEvents:function(){this.$el.off(".delegateEvents"+this.cid)},_configure:function(e){this.options&&(e=f.extend({},f.result(this,"options"),e)),f.extend(this,f.pick(e,O)),this.options=e},_ensureElement:function(){if(!this.el){var e=f.extend({},f.result(this,"attributes"));this.id&&(e.id=f.result(this,"id")),this.className&&(e["class"]=f.result(this,"className"));var t=a.$("<"+f.result(this,"tagName")+">").attr(e);this.setElement(t,!1)}else this.setElement(f.result(this,"el"),!1)}});var M={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};a.sync=function(e,t,n){var r=M[e];f.defaults(n||(n={}),{emulateHTTP:a.emulateHTTP,emulateJSON:a.emulateJSON});var i={type:r,dataType:"json"};n.url||(i.url=f.result(t,"url")||D()),n.data==null&&t&&(e==="create"||e==="update"||e==="patch")&&(i.contentType="application/json",i.data=JSON.stringify(n.attrs||t.toJSON(n))),n.emulateJSON&&(i.contentType="application/x-www-form-urlencoded",i.data=i.data?{model:i.data}:{});if(n.emulateHTTP&&(r==="PUT"||r==="DELETE"||r==="PATCH")){i.type="POST",n.emulateJSON&&(i.data._method=r);var s=n.beforeSend;n.beforeSend=function(e){e.setRequestHeader("X-HTTP-Method-Override",r);if(s)return s.apply(this,arguments)}}i.type!=="GET"&&!n.emulateJSON&&(i.processData=!1);var o=n.success;n.success=function(e){o&&o(t,e,n),t.trigger("sync",t,e,n)};var u=n.error;n.error=function(e){u&&u(t,e,n),t.trigger("error",t,e,n)};var l=n.xhr=a.ajax(f.extend(i,n));return t.trigger("request",t,l,n),l},a.ajax=function(){return a.$.ajax.apply(a.$,arguments)};var _=function(e,t){var n=this,r;e&&f.has(e,"constructor")?r=e.constructor:r=function(){return n.apply(this,arguments)},f.extend(r,n,t);var i=function(){this.constructor=r};return i.prototype=n.prototype,r.prototype=new i,e&&f.extend(r.prototype,e),r.__super__=n.prototype,r};d.extend=v.extend=y.extend=L.extend=x.extend=_;var D=function(){throw new Error('A "url" property or function must be specified')}}).call(this)}),e.define("/src/js/util/constants.js",function(e,t,n,r,i,s,o){var u={betweenCommandsDelay:400},a={isAnimating:!1},f={minZoom:.55,maxZoom:1.25,minWidth:600,minHeight:600},l={arrowHeadSize:8,nodeRadius:17,curveControlPointOffset:50,defaultEasing:"easeInOut",defaultAnimationTime:400,rectFill:"hsb(0.8816909813322127,0.7,1)",headRectFill:"#2831FF",rectStroke:"#FFF",rectStrokeWidth:"3",originDash:"- ",multiBranchY:20,upstreamHeadOpacity:.5,upstreamNoneOpacity:.2,edgeUpstreamHeadOpacity:.4,edgeUpstreamNoneOpacity:.15,visBranchStrokeWidth:2,visBranchStrokeColorNone:"#333",defaultNodeFill:"hsba(0.5,0.8,0.7,1)",defaultNodeStrokeWidth:2,defaultNodeStroke:"#FFF",orphanNodeFill:"hsb(0.5,0.8,0.7)"};n.GLOBAL=a,n.TIME=u,n.GRAPHICS=l,n.VIEWPORT=f}),e.define("/src/js/util/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util/constants");n.parseQueryString=function(e){var t={};return e.replace(new RegExp("([^?=&]+)(=([^&]*))?","g"),function(e,n,r,i){t[n]=i}),t},n.isBrowser=function(){var e=String(typeof window)!=="undefined";return e},n.splitTextCommand=function(e,t,n){t=u.bind(t,n),u.each(e.split(";"),function(e,n){e=u.escape(e),e=e.replace(/^(\s+)/,"").replace(/(\s+)$/,"").replace(/"/g,'"').replace(/'/g,"'");if(n>0&&!e.length)return;t(e)})},n.genParseCommand=function(e,t){return function(n){var r,i;return u.each(e,function(e,t){var s=e.exec(n);s&&(r=t,i=s)}),r?{toSet:{eventName:t,method:r,regexResults:i}}:!1}}}),e.define("/src/js/level/sandbox.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../intl"),h=e("../app"),p=e("../util/errors"),d=e("../visuals/visualization").Visualization,v=e("../level/parseWaterfall").ParseWaterfall,m=e("../level/disabledMap").DisabledMap,g=e("../models/commandModel").Command,y=e("../git/gitShim").GitShim,b=e("../views"),w=b.ModalTerminal,E=b.ModalAlert,S=e("../views/builderViews"),x=e("../views/multiView").MultiView,T=f.View.extend({tagName:"div",initialize:function(e){e=e||{},this.options=e,this.initVisualization(e),this.initCommandCollection(e),this.initParseWaterfall(e),this.initGitShim(e),this.initUndoStack(e),e.wait||this.takeControl()},getDefaultVisEl:function(){return $("#mainVisSpace")[0]},getAnimationTime:function(){return 1050},initVisualization:function(e){this.mainVis=new d({el:e.el||this.getDefaultVisEl()})},initUndoStack:function(e){this.undoStack=[]},initCommandCollection:function(e){this.commandCollection=h.getCommandUI().commandCollection},initParseWaterfall:function(e){this.parseWaterfall=new v},initGitShim:function(e){this.gitShim=new y({beforeCB:u.bind(this.beforeCommandCB,this)})},takeControl:function(){h.getEventBaton().stealBaton("commandSubmitted",this.commandSubmitted,this),h.getEventBaton().stealBaton("processSandboxCommand",this.processSandboxCommand,this),h.getEventBaton().stealBaton("levelExited",this.levelExited,this),this.insertGitShim()},releaseControl:function(){h.getEventBaton().releaseBaton("commandSubmitted",this.commandSubmitted,this),h.getEventBaton().releaseBaton("processSandboxCommand",this.processSandboxCommand,this),h.getEventBaton().releaseBaton("levelExited",this.levelExited,this),this.releaseGitShim()},releaseGitShim:function(){this.gitShim&&this.gitShim.removeShim()},insertGitShim:function(){this.gitShim&&this.mainVis.customEvents.on("gitEngineReady",function(){this.gitShim.insertShim()},this)},beforeCommandCB:function(e){this.pushUndo()},pushUndo:function(){this.undoStack.push(this.mainVis.gitEngine.printTree())},undo:function(e,t){var n=this.undoStack.pop();if(!n){e.set("error",new p.GitError({msg:c.str("undo-stack-empty")})),t.resolve();return}this.mainVis.reset(n),setTimeout(function(){e.finishWith(t)},this.mainVis.getAnimationTime())},commandSubmitted:function(e){h.getEvents().trigger("commandSubmittedPassive",e),l.splitTextCommand(e,function(e){this.commandCollection.add(new g({rawStr:e,parseWaterfall:this.parseWaterfall}))},this)},startLevel:function(t,n){var r=t.get("regexResults")||[],i=r[1]||"",s=h.getLevelArbiter().getLevel(i);if(!s){t.addWarning(c.str("level-no-id",{id:i})),h.getEventBaton().trigger("commandSubmitted","levels"),t.set("status","error"),n.resolve();return}this.hide(),this.clear();var o=a.defer(),u=e("../level").Level;this.currentLevel=new u({level:s,deferred:o,command:t}),o.promise.then(function(){t.finishWith(n)})},buildLevel:function(t,n){this.hide(),this.clear();var r=a.defer(),i=e("../level/builder").LevelBuilder;this.levelBuilder=new i({deferred:r}),r.promise.then(function(){t.finishWith(n)})},exitLevel:function(e,t){e.addWarning(c.str("level-cant-exit")),e.set("status","error"),t.resolve()},showLevels:function(e,t){var n=a.defer();h.getLevelDropdown().show(n,e),n.promise.done(function(){e.finishWith(t)})},resetSolved:function(e,t){h.getLevelArbiter().resetSolvedMap(),e.addWarning(c.str("solved-map-reset")),e.finishWith(t)},processSandboxCommand:function(e,t){var n={"reset solved":this.resetSolved,undo:this.undo,"help general":this.helpDialog,help:this.helpDialog,reset:this.reset,delay:this.delay,clear:this.clear,"exit level":this.exitLevel,level:this.startLevel,sandbox:this.exitLevel,levels:this.showLevels,mobileAlert:this.mobileAlert,"build level":this.buildLevel,"export tree":this.exportTree,"import tree":this.importTree,"import level":this.importLevel},r=n[e.get("method")];if(!r)throw new Error("no method for that wut");r.apply(this,[e,t])},hide:function(){this.mainVis.hide()},levelExited:function(){this.show()},show:function(){this.mainVis.show()},importTree:function(e,t){var n=new S.MarkdownPresenter({previewText:c.str("paste-json"),fillerText:" "});n.deferred.promise.then(u.bind(function(e){try{this.mainVis.gitEngine.loadTree(JSON.parse(e))}catch(t){this.mainVis.reset(),new x({childViews:[{type:"ModalAlert",options:{markdowns:["## Error!","","Something is wrong with that JSON! Here is the error:","",String(t)]}}]})}},this)).fail(function(){}).done(function(){e.finishWith(t)})},importLevel:function(t,n){var r=new S.MarkdownPresenter({previewText:c.str("paste-json"),fillerText:" "});r.deferred.promise.then(u.bind(function(r){var i=e("../level").Level;try{var s=JSON.parse(r),o=a.defer();this.currentLevel=new i({level:s,deferred:o,command:t}),this.hide(),o.promise.then(function(){t.finishWith(n)})}catch(u){new x({childViews:[{type:"ModalAlert",options:{markdowns:["## Error!","","Something is wrong with that level JSON, this happened:","",String(u)]}}]}),t.finishWith(n)}},this)).fail(function(){t.finishWith(n)}).done()},exportTree:function(e,t){var n=JSON.stringify(this.mainVis.gitEngine.exportTree(),null,2),r=new x({childViews:[{type:"MarkdownPresenter",options:{previewText:c.str("share-tree"),fillerText:n,noConfirmCancel:!0}}]});r.getPromise().then(function(){e.finishWith(t)}).done()},clear:function(e,t){h.getEvents().trigger("clearOldCommands"),e&&t&&e.finishWith(t)},mobileAlert:function(e,t){alert(c.str("mobile-alert")),e.finishWith(t)},delay:function(e,t){var n=parseInt(e.get("regexResults")[1],10);setTimeout(function(){e.finishWith(t)},n)},reset:function(e,t){this.mainVis.reset(),this.initUndoStack(),setTimeout(function(){e.finishWith(t)},this.mainVis.getAnimationTime())},helpDialog:function(t,n){var r=new x({childViews:c.getDialog(e("../dialogs/sandbox"))});r.getPromise().then(u.bind(function(){t.finishWith(n)},this)).done()}});n.Sandbox=T}),e.define("/node_modules/q/package.json",function(e,t,n,r,i,s,o){t.exports={main:"q.js"}}),e.define("/node_modules/q/q.js",function(e,t,n,r,i,s,o){(function(e){if(typeof bootstrap=="function")bootstrap("promise",e);else if(typeof n=="object")e(void 0,n);else if(typeof define=="function")define(e);else if(typeof ses!="undefined"){if(!ses.ok())return;ses.makeQ=function(){var t={};return e(void 0,t)}}else e(void 0,Q={})})(function(e,t){"use strict";function w(e){return b(e)==="[object StopIteration]"||e instanceof E}function x(e,t){t.stack&&typeof e=="object"&&e!==null&&e.stack&&e.stack.indexOf(S)===-1&&(e.stack=T(e.stack)+"\n"+S+"\n"+T(t.stack))}function T(e){var t=e.split("\n"),n=[];for(var r=0;r=n&&s<=Ct}function k(){if(Error.captureStackTrace){var e,t,n=Error.prepareStackTrace;return Error.prepareStackTrace=function(n,r){e=r[1].getFileName(),t=r[1].getLineNumber()},(new Error).stack,Error.prepareStackTrace=n,r=e,t}}function L(e,t,n){return function(){return typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t+" is deprecated, use "+n+" instead.",(new Error("")).stack),e.apply(e,arguments)}}function A(){function s(r){if(!e)return;n=z(r),d(e,function(e,t){u(function(){n.promiseSend.apply(n,t)})},void 0),e=void 0,t=void 0}var e=[],t=[],n,r=g(A.prototype),i=g(M.prototype);return i.promiseSend=function(r,i,s,o){var a=p(arguments);e?(e.push(a),r==="when"&&o&&t.push(o)):u(function(){n.promiseSend.apply(n,a)})},i.valueOf=function(){return e?i:n.valueOf()},Error.captureStackTrace&&(Error.captureStackTrace(i,A),i.stack=i.stack.substring(i.stack.indexOf("\n")+1)),o(i),r.promise=i,r.resolve=s,r.reject=function(e){s(U(e))},r.notify=function(n){e&&d(t,function(e,t){u(function(){t(n)})},void 0)},r}function O(e){var t=A();return ot(e,t.resolve,t.reject,t.notify).fail(t.reject),t.promise}function M(e,t,n,r){t===void 0&&(t=function(e){return U(new Error("Promise does not support operation: "+e))});var i=g(M.prototype);return i.promiseSend=function(n,r){var s=p(arguments,2),o;try{e[n]?o=e[n].apply(i,s):o=t.apply(i,[n].concat(s))}catch(u){o=U(u)}r&&r(o)},n&&(i.valueOf=n),r&&(i.exception=r),o(i),i}function _(e){return D(e)?e.valueOf():e}function D(e){return e&&typeof e.promiseSend=="function"}function P(e){return e&&typeof e.then=="function"}function H(e){return B(e)||j(e)}function B(e){return!P(_(e))}function j(e){return e=_(e),D(e)&&"exception"in e}function R(){!q&&typeof window!="undefined"&&!window.Touch&&window.console&&console.log("Should be empty:",I),q=!0}function U(e){var t=M({when:function(t){if(t){var n=v(F,this);n!==-1&&(I.splice(n,1),F.splice(n,1))}return t?t(e):U(e)}},function(){return U(e)},function n(){return this},e);return R(),F.push(t),I.push(e),t}function z(e){if(D(e))return e;e=_(e);if(P(e)){var t=A();return e.then(t.resolve,t.reject,t.notify),t.promise}return M({when:function(){return e},get:function(t){return e[t]},put:function(t,n){return e[t]=n,e},del:function(t){return delete e[t],e},post:function(t,n){return e[t].apply(e,n)},apply:function(t,n){return e.apply(t,n)},fapply:function(t){return e.apply(void 0,t)},viewInfo:function(){function r(e){n[e]||(n[e]=typeof t[e])}var t=e,n={};while(t)Object.getOwnPropertyNames(t).forEach(r),t=Object.getPrototypeOf(t);return{type:typeof e,properties:n}},keys:function(){return y(e)}},void 0,function n(){return e})}function W(e){return M({isDef:function(){}},function(){var n=p(arguments);return Z.apply(void 0,[e].concat(n))},function(){return _(e)})}function X(e,t){return e=z(e),t?M({viewInfo:function(){return t}},function(){var n=p(arguments);return Z.apply(void 0,[e].concat(n))},function(){return _(e)}):Z(e,"viewInfo")}function V(e){return X(e).when(function(t){var n;t.type==="function"?n=function(){return rt(e,void 0,arguments)}:n={};var r=t.properties||{};return y(r).forEach(function(t){r[t]==="function"&&(n[t]=function(){return nt(e,t,arguments)})}),z(n)})}function $(e,t,n,r){function o(e){try{return typeof t=="function"?t(e):e}catch(n){return U(n)}}function a(e){if(typeof n=="function"){x(e,l);try{return n(e)}catch(t){return U(t)}}return U(e)}function f(e){return typeof r=="function"?r(e):e}var i=A(),s=!1,l=z(e);return u(function(){l.promiseSend("when",function(e){if(s)return;s=!0,i.resolve(o(e))},function(e){if(s)return;s=!0,i.resolve(a(e))})}),l.promiseSend("when",void 0,void 0,function(e){i.notify(f(e))}),i.promise}function J(e,t,n){return $(e,function(e){return ft(e).then(function(e){return t.apply(void 0,e)},n)},n)}function K(e){return function(){function t(e,t){var s;try{s=n[e](t)}catch(o){return w(o)?o.value:U(o)}return $(s,r,i)}var n=e.apply(this,arguments),r=t.bind(t,"send"),i=t.bind(t,"throw");return r()}}function Q(e){throw new E(e)}function G(e){return function(){return ft([this,ft(arguments)]).spread(function(t,n){return e.apply(t,n)})}}function Y(e){return function(t){var n=p(arguments,1);return Z.apply(void 0,[t,e].concat(n))}}function Z(e,t){var n=A(),r=p(arguments,2);return e=z(e),u(function(){e.promiseSend.apply(e,[t,n.resolve].concat(r))}),n.promise}function et(e,t,n){var r=A();return e=z(e),u(function(){e.promiseSend.apply(e,[t,r.resolve].concat(n))}),r.promise}function tt(e){return function(t){var n=p(arguments,1);return et(t,e,n)}}function st(e,t){var n=p(arguments,2);return rt(e,t,n)}function ot(e){var t=p(arguments,1);return it(e,t)}function ut(e,t){var n=p(arguments,2);return function(){var i=n.concat(p(arguments));return rt(e,t,i)}}function at(e){var t=p(arguments,1);return function(){var r=t.concat(p(arguments));return it(e,r)}}function ft(e){return $(e,function(e){var t=e.length;if(t===0)return z(e);var n=A();return d(e,function(r,i,s){B(i)?(e[s]=_(i),--t===0&&n.resolve(e)):$(i,function(r){e[s]=r,--t===0&&n.resolve(e)}).fail(n.reject)},void 0),n.promise})}function lt(e){return $(e,function(e){return $(ft(m(e,function(e){return $(e,i,i)})),function(){return m(e,z)})})}function ct(e,t){return $(e,void 0,t)}function ht(e,t){return $(e,void 0,void 0,t)}function pt(e,t){return $(e,function(e){return $(t(),function(){return e})},function(e){return $(t(),function(){return U(e)})})}function dt(e,n,r,i){function s(n){u(function(){x(n,e);if(!t.onerror)throw n;t.onerror(n)})}var o=n||r||i?$(e,n,r,i):e;ct(o,s)}function vt(e,t){var n=A(),r=setTimeout(function(){n.reject(new Error("Timed out after "+t+" ms"))},t);return $(e,function(e){clearTimeout(r),n.resolve(e)},function(e){clearTimeout(r),n.reject(e)}),n.promise}function mt(e,t){t===void 0&&(t=e,e=void 0);var n=A();return setTimeout(function(){n.resolve(e)},t),n.promise}function gt(e,t){var n=p(t),r=A();return n.push(r.makeNodeResolver()),it(e,n).fail(r.reject),r.promise}function yt(e){var t=p(arguments,1),n=A();return t.push(n.makeNodeResolver()),it(e,t).fail(n.reject),n.promise}function bt(e){var t=p(arguments,1);return function(){var n=t.concat(p(arguments)),r=A();return n.push(r.makeNodeResolver()),it(e,n).fail(r.reject),r.promise}}function wt(e,t,n){return St(e,t).apply(void 0,n)}function Et(e,t){var n=p(arguments,2);return wt(e,t,n)}function St(e){if(arguments.length>1){var t=arguments[1],n=p(arguments,2),r=e;e=function(){var e=n.concat(p(arguments));return r.apply(t,e)}}return function(){var t=A(),n=p(arguments);return n.push(t.makeNodeResolver()),it(e,n).fail(t.reject),t.promise}}function xt(e,t,n){var r=p(n),i=A();return r.push(i.makeNodeResolver()),nt(e,t,r).fail(i.reject),i.promise}function Tt(e,t){var n=p(arguments,2),r=A();return n.push(r.makeNodeResolver()),nt(e,t,n).fail(r.reject),r.promise}function Nt(e,t){if(!t)return e;e.then(function(e){u(function(){t(null,e)})},function(e){u(function(){t(e)})})}var n=k(),r,i=function(){},o=Object.freeze||i;typeof cajaVM!="undefined"&&(o=cajaVM.def);var u;if(typeof s!="undefined")u=s.nextTick;else if(typeof setImmediate=="function")u=setImmediate;else if(typeof MessageChannel!="undefined"){var a=new MessageChannel,f={},l=f;a.port1.onmessage=function(){f=f.next;var e=f.task;delete f.task,e()},u=function(e){l=l.next={task:e},a.port2.postMessage(0)}}else u=function(e){setTimeout(e,0)};var c;if(Function.prototype.bind){var h=Function.prototype.bind;c=h.bind(h.call)}else c=function(e){return function(){return e.call.apply(e,arguments)}};var p=c(Array.prototype.slice),d=c(Array.prototype.reduce||function(e,t){var n=0,r=this.length;if(arguments.length===1)do{if(n in this){t=this[n++];break}if(++n>=r)throw new TypeError}while(1);for(;n2?e.resolve(p(arguments,1)):e.resolve(n)}},A.prototype.node=L(A.prototype.makeNodeResolver,"node","makeNodeResolver"),t.promise=O,t.makePromise=M,M.prototype.then=function(e,t,n){return $(this,e,t,n)},M.prototype.thenResolve=function(e){return $(this,function(){return e})},d(["isResolved","isFulfilled","isRejected","when","spread","send","get","put","del","post","invoke","keys","apply","call","bind","fapply","fcall","fbind","all","allResolved","view","viewInfo","timeout","delay","catch","finally","fail","fin","progress","end","done","nfcall","nfapply","nfbind","ncall","napply","nbind","npost","ninvoke","nend","nodeify"],function(e,n){M.prototype[n]=function(){return t[n].apply(t,[this].concat(p(arguments)))}},void 0),M.prototype.toSource=function(){return this.toString()},M.prototype.toString=function(){return"[object Promise]"},o(M.prototype),t.nearer=_,t.isPromise=D,t.isPromiseAlike=P,t.isResolved=H,t.isFulfilled=B,t.isRejected=j;var F=[],I=[],q;t.reject=U,t.begin=z,t.resolve=z,t.ref=L(z,"ref","resolve"),t.master=W,t.viewInfo=X,t.view=V,t.when=$,t.spread=J,t.async=K,t["return"]=Q,t.promised=G,t.sender=L(Y,"sender","dispatcher"),t.Method=L(Y,"Method","dispatcher"),t.send=L(Z,"send","dispatch"),t.dispatch=et,t.dispatcher=tt,t.get=tt("get"),t.put=tt("put"),t["delete"]=t.del=tt("del");var nt=t.post=tt("post");t.invoke=function(e,t){var n=p(arguments,2);return nt(e,t,n)};var rt=t.apply=L(tt("apply"),"apply","fapply"),it=t.fapply=tt("fapply");t.call=L(st,"call","fcall"),t["try"]=ot,t.fcall=ot,t.bind=L(ut,"bind","fbind"),t.fbind=at,t.keys=tt("keys"),t.all=ft,t.allResolved=lt,t["catch"]=t.fail=ct,t.progress=ht,t["finally"]=t.fin=pt,t.end=L(dt,"end","done"),t.done=dt,t.timeout=vt,t.delay=mt,t.nfapply=gt,t.nfcall=yt,t.nfbind=bt,t.napply=L(wt,"napply","npost"),t.ncall=L(Et,"ncall","ninvoke"),t.nbind=L(St,"nbind","nfbind"),t.npost=xt,t.ninvoke=Tt,t.nend=L(Nt,"nend","nodeify"),t.nodeify=Nt;var Ct=k()})}),e.define("/src/js/intl/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util/constants"),f=e("../util"),l=e("../intl/strings").strings,c=n.getDefaultLocale=function(){return"en_US"},h=n.getLocale=function(){return a.GLOBAL.locale?a.GLOBAL.locale:c()},p=u.clone(u.templateSettings);p.interpolate=/\{(.+?)\}/g;var d=n.template=function(e,t){return u.template(e,t,p)},v=n.str=function(e,t){t=t||{};var n=h();return l[e]?l[e][n]?d(l[e][n],t):e!=="error-untranslated"?v("error-untranslated"):'No translation for the key "'+e+'"':(console.warn("NO INTL support for key "+e),"NO INTL support for key "+e)},m=n.getIntlKey=function(e,t){if(!e||!e[t])throw new Error("that key "+t+"doesnt exist in this blob"+e);return e[t][c()]||console.warn("WARNING!! This blob does not have intl support:",e,"for this key",t),e[t][h()]},g=n.getDialog=function(e){var t=c();return m(e,"dialog")||e.dialog[t]},y=n.getHint=function(e){return m(e,"hint")||v("error-untranslated")},b=n.getName=function(e){return m(e,"name")||v("error-untranslated")},w=n.getStartDialog=function(e){var t=m(e,"startDialog");if(t)return t;var n={type:"ModalAlert",options:{markdown:v("error-untranslated")}},r=u.clone(e.startDialog[c()]||e.startDialog);return r.childViews.unshift(n),r}}),e.define("/src/js/intl/strings.js",function(e,t,n,r,i,s,o){n.strings={"finish-dialog-finished":{__desc__:"One of the lines in the next level dialog",ja:"最後のレベルをクリアしました!すごい!!",en_US:"Wow! You finished the last level, great!",zh_CN:"我的个天!你完成了最后一关,碉堡了!",fr_FR:"Félicitations, vous avez réussi le dernier niveau !"},"finish-dialog-next":{__desc__:"One of the lines in the next level dialog",en_US:'Would you like to move on to *"{nextLevel}"*, the next level?',ja:'次の章 *"{nextLevel}"* へ進みますか?',zh_CN:"要不前进到下一关 *“{nextLevel}”*?",fr_FR:'Voulez-vous passer à *"{nextLevel}"*, le prochain niveau ?'},"finish-dialog-win":{__desc__:"One of the lines in the next level dialog",en_US:"Awesome! You matched or exceeded our solution.",ja:"素晴らしい!このレベルをクリアしましたね。",zh_CN:"牛鼻啊!你达到或者完爆了我们的答案。",fr_FR:"Fabuleux ! Votre solution a égalé ou surpassé notre solution."},"finish-dialog-lose":{__desc__:"When the user entered more commands than our best, encourage them to do better",en_US:"See if you can whittle it down to {best} :D",ja:"模範解答の回数={best}回でクリアする方法も考えてみましょう :D",zh_CN:"试试看你能否在 {best} 之内搞定 :D",fr_FR:"Voyons si vous pouvez descendre à {best} :D"},"git-status-detached":{__desc__:"One of the lines for git status output",en_US:"Detached head!",zh_CN:"脑袋搬家(Detached head)了!",fr_FR:"head détaché !"},"git-status-onbranch":{__desc__:"One of the lines for git status output",en_US:"On branch {branch}",zh_CN:"切换到分支 {branch}",fr_FR:"Sur la branche {branch}"},"git-status-readytocommit":{__desc__:"One of the lines for git status output",en_US:"Ready to commit! (as always in this demo)",zh_CN:"可以提交啦!(这演示里一直可以提交)",fr_FR:"Prêt à commit ! (comme toujours dans cette démo)"},"git-dummy-msg":{__desc__:"The dummy commit message for all commits. Feel free to put in a shoutout to your school / city / whatever!",en_US:"Quick commit. Go Bears!",zh_CN:"快速提交。上啊月熊!",fr_FR:"Commit rapide. NoMaN Sux!"},"git-error-origin-fetch-uptodate":{__desc__:"One of the error messages for git",en_US:"Already up to date!",fr_FR:"Déjà à jour"},"git-error-origin-fetch-no-ff":{__desc__:"One of the error messages for git",en_US:"Your origin branch is out of sync with the remote branch and fetch cannot be performed. try using --force",fr_FR:"Votre branche origin n'est plus synchronisée avec la branche distante et fetch ne peut pas être appliqué. Essayez avec l'option --force"},"git-error-origin-push-no-ff":{__desc__:"One of the error messages for git",en_US:"The remote repository has diverged from your local repository, so uploading your changes is not a simple fast forward (and thus your push was rejected). Please pull down the new changes in the remote repository, incorporate them into this branch, and try again. You can do so with git pull or git pull --rebase",fr_FR:"Le dépôt distant a divergé de votre référentiel local, donc l'envoi de vos modifications n'est pas en simple avance rapide (et donc votre envoi a été rejeté). Veuillez récupérer les nouveaux changements depuis le dépôt distant, les intégrer dans cette branche, et essayez à nouveau. Vous pouvez le faire avec git pull ou git pull --rebase"},"git-error-remote-branch":{__desc__:"One of the error messages for git",en_US:"You cannot execute that command on a remote branch",fr_FR:"Vous ne pouvez exécuter cette commande sur une branche distante"},"git-error-origin-required":{__desc__:"One of the error messages for git",en_US:"An origin is required for that command",fr_FR:"Une origine est requise pour cette commande"},"git-error-origin-exists":{__desc__:"One of the error messages for git",en_US:"An origin already exists! You cannot make a new one",fr_FR:"Une origine existe déjà ! Vous ne pouvez pas en créer une nouvelle"},"git-error-branch":{__desc__:"One of the error messages for git",en_US:"You can't delete the master branch, the branch you are on, or things that aren't branches",zh_CN:"你不能删除主分支(master),或者你当前所在的分支,或者其他不是分支也不知道能不能吃的东西。",fr_FR:"Vous ne pouvez supprimer la branche master, la branche sur laquelle vous êtes, ou ce qui n'est pas une branche"},"git-merge-msg":{__desc__:"The commit message for a merge commit",en_US:"Merge {target} into {current}",zh_CN:"合并 {target} 到 {current}",fr_FR:"Merge de {target} dans {current}"},"git-error-rebase-none":{__desc__:"One of the error messages for git",en_US:"No commits to rebase! Everything is a merge commit or changes already applied",zh_CN:"没有需要 rebase 的提交!都是个合并提交,或者已经 rebase 过了。",fr_FR:"Aucune commit à rebaser ! Tout est soit un commit de merge, soit des modifications déjà appliquées"},"git-result-nothing":{__desc__:"The message that explains the result of a git command",en_US:"Nothing to do...",zh_CN:"没啥鸟事……",fr_FR:"Rien à effectuer…"},"git-result-fastforward":{__desc__:"The message that explains the result of a git command",en_US:"Fast forwarding...",zh_CN:"快速前进……",fr_FR:"En avance rapide…"},"git-result-uptodate":{__desc__:"The message that explains the result of a git command",en_US:"Branch already up-to-date",zh_CN:"分支已经是最新啦",fr_FR:"Branche déjà à jour"},"git-error-exist":{__desc__:"One of the error messages for git",en_US:"The ref {ref} does not exist or is unknown",zh_CN:"索引 {ref} 不存在,或者找不到。",fr_FR:"La référence {ref} n'existe pas ou est inconnue"},"git-error-relative-ref":{__desc__:"One of the error messages for git",en_US:"Commit {commit} doesnot have a {match}",zh_CN:"提交 {commit} 并没有 {match}",fr_FR:"Le commit {commit} n'a pas de correspondance {match}"},"git-warning-detached":{__desc__:"One of the warning messages for git",en_US:"Warning!! Detached HEAD state",zh_CN:"警告!脑袋搬家(Detached HEAD)状态",fr_FR:"Attention ! HEAD est détaché"},"git-warning-add":{__desc__:"One of the warning messages for git",en_US:"No need to add files in this demo",zh_CN:"此演示中不需要添加文件",fr_FR:"Aucun besoin d'ajouter des fichiers dans cette démo"},"git-error-options":{__desc__:"One of the error messages for git",en_US:"Those options you specified are incompatible or incorrect",zh_CN:"你所指定的参数不兼容或者不准确",fr_FR:"Les options que vous avez spécifiées sont incompatibles ou incorrectes"},"git-error-already-exists":{__desc__:"One of the error messages for git",en_US:"The commit {commit} already exists in your changes set, aborting!",zh_CN:"提交 {commit} 已经存在于你的改动集里,正在中止!",fr_FR:"Le commit {commit} existe déjà dans votre ensemble de modifications, opération avortée !"},"git-error-reset-detached":{__desc__:"One of the error messages for git",en_US:"Can't reset in detached head! Use checkout if you want to move",zh_CN:"不能在分离的 HEAD 里重置!用 checkout 吧",fr_FR:"On ne peut pas effectuer un reset quand head est détaché. Utilisez checkout pour déplacer"},"git-warning-hard":{__desc__:"One of the warning messages for git",en_US:"The default behavior is a --hard reset, feel free to omit that option!",zh_CN:"默认的行为是 --hard 硬重置,尽管省略掉那个选项吧!",fr_FR:"Le comportement par défaut est un --hard reset, soyez libre d'omettre cette option !"},"git-error-staging":{__desc__:"One of the error messages for git",en_US:"There is no concept of adding / staging files, so that option or command is invalid!",zh_CN:"没有添加、缓存文件的必要,所以改选项或者命令是不合法的。",fr_FR:"Il n'y a pas le concept d'ajouter / mettre en staging, donc cette option ou commande est invalide"},"git-revert-msg":{__desc__:"Message for reverting git command",en_US:"Reverting {oldCommit}: {oldMsg}",zh_CN:"撤销 {oldCommit}:{oldMsg}",fr_FR:"Revert {oldCommit}: {oldMsg}"},"git-error-args-many":{__desc__:"One of the error messages for git",en_US:"I expect at most {upper} argument(s) for {what}",zh_CN:"{what} 期望最多 {upper} 个参数",fr_FR:"J'attends au plus {upper} argument(s) pour {what}"},"git-error-args-few":{__desc__:"One of the error messages for git",en_US:"I expect at least {lower} argument(s) for {what}",zh_CN:"{what} 期望最少 {lower} 个参数",fr_FR:"J'attends au moins {upper} argument(s) pour {what}"},"git-error-no-general-args":{__desc__:"One of the error messages for git",en_US:"That command accepts no general arguments",zh_CN:"该命令不接收参数",fr_FR:"Cette commande n'accepte aucun argument général"},"copy-tree-string":{__desc__:"The prompt to copy the tree when sharing",en_US:"Copy the tree string below",zh_CN:"拷贝下面的树字符串",fr_FR:"Copiez la chaîne d'arbre ci-dessous"},"learn-git-branching":{__desc__:"The title of the app, with spaces",en_US:"Learn Git Branching",ja:"日本語版リポジトリ",ko:"Git 브랜치 배우기",zh_CN:"学习Git分支",fr_FR:"Apprenez Git Branching"},"select-a-level":{__desc__:"The prompt to select a level on the drop down view",en_US:"Select a level",zh_CN:"选择一关",fr_FR:"Choisissez un niveau"},"branch-name-short":{__desc__:"When branch names get too long, we need to truncate them. This is the warning for that",en_US:'Sorry, we need to keep branch names short for the visuals. Your branch name was truncated to 9 characters, resulting in "{branch}"',zh_CN:'抱歉,为了显示的需要,我们需要一个短些的分支名称。您使用的将被截断到9个字符,即"{branch}"',fr_FR:'Désolé, nous devons garder les noms de branches courts pour la visualisation. Votre nom de branche a été tronqué à 9 caractères, devenant "{branch}"'},"bad-branch-name":{__desc__:"When the user enters a branch name thats not ok",en_US:'That branch name "{branch}" is not allowed!',zh_CN:'不能给分支起这个名字 "{branch}"',fr_FR:'Ce nom de branche "{branch}" n\'est pas autorisé'},"option-not-supported":{__desc__:"When the user specifies an option that is not supported by our demo",en_US:'The option "{option}" is not supported!',zh_CN:'不支持选项 "{option}"',fr_FR:"L'option \"{option}\" n'est pas supportée"},"git-usage-command":{__desc__:"The line that shows how to format a git command",en_US:"git []",zh_CN:"git <命令> [<参数>]",fr_FR:"git []"},"git-supported-commands":{__desc__:"In the git help command, the header above the supported commands",en_US:"Supported commands:",zh_CN:"支持的命令有:",fr_FR:"Commandes supportées"},"git-usage":{__desc__:"In the dummy git output, the header before showing all the commands",en_US:"Usage:",zh_CN:"使用:",fr_FR:"Utilisation :"},"git-version":{__desc__:"The git version dummy output, kind of silly. PCOTTLE is my unix name but feel free to put yours instead",en_US:"Git Version PCOTTLE.1.0",zh_CN:"Git 版本 PCOTTLE.1.0",fr_FR:"Git version PCOTTLE.1.0"},"refresh-tree-command":{__desc__:"when the tree is visually refreshed",en_US:"Refreshing tree...",zh_CN:"正在刷新树结构...",fr_FR:"Actualisation de l'arbre…"},"locale-command":{__desc__:"when the locale is set to something",en_US:"Locale set to {locale}",zh_CN:"语言更改为 {locale}",fr_FR:"Langue changée à {locale}"},"locale-reset-command":{__desc__:"when the locale is reset",en_US:"Locale reset to default, which is {locale}",zh_CN:"语言重置为默认的 {locale}",fr_FR:"Langue remise par défaut, qui est {locale}"},"show-command":{__desc__:'command output title from "show"',en_US:"Please use one of the following commands for more info:",fr_FR:"Merci d'utiliser une des commandes suivantes pour obtenir plus d'info"},"show-all-commands":{__desc__:'command output title from "show commands"',en_US:"Here is a list of all the commmands available:",fr_FR:"Ci-dessous est la liste de toutes les commandes disponibles :"},"cd-command":{__desc__:"dummy command output for the command in the key",en_US:'Directory changed to "/directories/dont/matter/in/this/demo"',zh_CN:'目录切换到 "/directories/dont/matter/in/this/demo"',fr_FR:'Répertoire changé à "/directories/dont/matter/in/this/demo" (les répertoires ne servent à rien dans cette démo)'},"ls-command":{__desc__:"Dummy command output for the command in the key",en_US:"DontWorryAboutFilesInThisDemo.txt",zh_CN:"DontWorryAboutFilesInThisDemo.txt (译: 在试验里不用担心文件.txt)",fr_FR:"DontWorryAboutFilesInThisDemo.txt (ne vous préoccupez pas des noms de fichier dans cette démo)"},"mobile-alert":{__desc__:"When someone comes to the site on a mobile device, they can not input commands so this is a nasty alert to tell them",en_US:"Can't bring up the keyboard on mobile / tablet :( try visiting on desktop! :D",zh_CN:"无法在移动设备/平板上调出键盘 :( 请试试桌面版 :D",fr_FR:"Impossible de faire apparaître le clavier sur mobile / tablette :( Essayez de passer sur un ordinateur de bureau :D"},"share-tree":{__desc__:"When you export a tree, we want you to share the tree with friends",en_US:'Share this tree with friends! They can load it with "import tree"',zh_CN:'与你的好友分享提交树!他们可以用 "import tree" 加载它',fr_FR:'Partagez cet arbre avec vos amis ! Ils peuvent le charger avec "import tree"'},"paste-json":{__desc__:"When you are importing a level or tree",en_US:"Paste a JSON blob below!",zh_CN:"在下边粘贴一个JSON串",fr_FR:"Collez un blob JSON ci-dessous !"},"solved-map-reset":{__desc__:"When you reset the solved map to clear your solved history, in case someone else wants to use your browser",en_US:"Solved map was reset, you are starting from a clean slate!",zh_CN:"解决列表已重置,您现在从零开始了",fr_FR:"La carte des niveaux résolus a été effacée, vous repartez de zéro !"},"level-cant-exit":{__desc__:"When the user tries to exit a level when they are not in one",en_US:'You are not in a level! You are in a sandbox, start a level with "levels"',zh_CN:'您没在关卡中!您在沙盒中,要开始关卡请输入 "levels"',fr_FR:'Vous n\'êtes pas dans un niveau ! Vous êtes dans le mode bac à sable, commencez un niveau avec "levels"'},"level-no-id":{__desc__:"When you say an id but that level doesnt exist",en_US:'A level for that id "{id}" was not found! Opening up a level selection view',zh_CN:'没找到id为 "{id}" 的关卡!打开关卡选择框',fr_FR:"Le niveau dont l'identifiant est {id} n'a pas été trouvé ! Ouverture de la vue de sélection des niveaux"},"undo-stack-empty":{__desc__:"The undo command can only undo back until the last time the level was reset or the beginning of the level",en_US:"The undo stack is empty!",zh_CN:"还没有什么可以撤销",fr_FR:"La pile d'annulation est vide !"},"already-solved":{__desc__:"When you play in a level that is already solved",en_US:'You have already solved this level, try other levels with "levels" or go back to sandbox with "sandbox"',zh_CN:'你已经解决了本关,输入 "levels" 尝试其他关卡,或者输入 "sandbox" 回到沙盒中',fr_FR:'Vous avez déjà résolu ce niveau, essayez d\'autres niveaux avec "levels" ou revenez au bac à sable avec "sandbox"'},"command-disabled":{__desc__:"When you try a command that is disabled",en_US:"That git command is disabled for this level!",zh_CN:"该命令在本关不允许使用!",fr_FR:"Cette commande git est désactivée pour ce niveau !"},"share-json":{__desc__:"when you have made the level, prompt to share this",en_US:"Here is the JSON for this level! Share it with somenoe or send it to me on Github",zh_CN:"这是一个关卡定义JSON!您可以分享它或者发到我的GitHub上",fr_FR:"Voici le JSON pour ce niveau ! Partagez-le avec quelqu'un ou envoyez-le moi sur Github"},"want-start-dialog":{__desc__:"prompt to add a start dialog",en_US:"You have not specified a start dialog, would you like to add one?",zh_CN:"您还没有定义一开始的介绍,是否添加一个?",fr_FR:"Vous n'avez pas spécifié de dialogue de départ, voulez-vous en ajouter un ?"},"want-hint":{__desc__:"prompt to add a hint",en_US:"You have not specified a hint, would you like to add one?",zh_CN:"您还没有定义提示,是否添加一个?",fr_FR:"Vous n'avez pas spécifié d'indice, voulez-vous en ajouter un ?"},"prompt-hint":{__desc__:"prompt for hint",en_US:"Enter the hint for this level, or leave this blank if you do not want to include one",zh_CN:"请输入关卡提示,或者故意留空",fr_FR:"Entrez l'indice pour ce niveau, ou laissez-le vide pour ne pas l'inclure"},"prompt-name":{__desc__:"prompt for level name",en_US:"Enter the name for the level",zh_CN:"输入关卡名",fr_FR:"Entrez le nom pour ce niveau"},"solution-empty":{__desc__:"If you define a solution without any commands, aka a level that is solved without doing anything",en_US:"Your solution is empty!! Something is amiss",zh_CN:"你的解法是空的!! 这应该是出错了",fr_FR:"Votre solution est vide !! Quelque chose ne tourne pas rond"},"define-start-warning":{__desc__:"When you define the start point again, it overwrites the solution and goal so we add a warning",en_US:"Defining start point... solution and goal will be overwritten if they were defined earlier",zh_CN:"定义开始点... 解决方法和目标会被新的替代",fr_FR:"Redéfinition du point de départ… la solution et la cible seront écrasés s'ils ont déjà été définis"},"help-vague-level":{__desc__:"When you are in a level and you say help, its vague and you need to specify",en_US:'You are in a level, so multiple forms of help are available. Please select either "help level" to learn more about this lesson, "help general" for using Learn GitBranching, or "objective" to learn about how to solve the level.',zh_CN:'您正在关卡中,这里有多种形式的帮助,请选择 "help level" (关卡帮助)或 "help general" (一般帮助)',fr_FR:'Vous êtes dans un niveau, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help level" pour en apprendre plus sur cette leçon, "help general" pour l\'utilisation de Learn GitBranching, ou "objective" pour apprendre comment résoudre le niveau'},"help-vague-builder":{__desc__:"When you are in a level builder, the help command is vague so you need to specify what you mean",en_US:'You are in a level builder, so multiple forms of help are available. Please select either "help general" or "help builder"',zh_CN:'您正在进行关卡构建中,这里有多种形式的帮助,请选择 "help general" (一般帮助)或 "help builder" (关卡构建帮助)',fr_FR:'Vous êtes dans l\'éditeur de niveaux, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help general" soit "help builder"'},"goal-to-reach":{__desc__:"title of window that shoes the goal tree to reach",en_US:"Goal To Reach",zh_CN:"目标",fr_FR:"Cible à atteindre"},"hide-goal":{__desc__:"the helper message for the window that shows the goal tree",en_US:'You can hide this window with "hide goal"',zh_CN:'你可以通过命令 "hide goal" 关闭这个窗口',fr_FR:'Vous pouvez masquer cette fenêtre avec "hide goal"'},"hide-start":{__desc__:"The helper message for the window that shows the start tree for a level",en_US:'You can hide this window with "hide start"',zh_CN:'你可以通过命令 "hide start" 关闭这个窗口',fr_FR:'Vous pouvez masquer cette fenêtre avec "hide start"'},"level-builder":{__desc__:"The name for the environment where you build levels",en_US:"Level Builder",zh_CN:"关卡生成器",fr_FR:"Éditeur de niveaux"},"no-start-dialog":{__desc__:"when the user tries to open a start dialog for a level that does not have one",en_US:"There is no start dialog to show for this level!",zh_CN:"介绍? 这关真没有!",fr_FR:"Il n'y a aucun dialogue de départ à afficher pour ce niveau !"},"no-hint":{__desc__:"when no hint is available for a level",en_US:"Hmm, there doesn't seem to be a hint for this level :-/",zh_CN:"提示?嗯,这关真没有哎~ :-/",fr_FR:"Hum, il ne semble pas y avoir d'indice pour ce niveau :-/"},"error-untranslated-key":{__desc__:"This error happens when we are trying to translate a specific key and the locale version is mission",en_US:"The translation for {key} does not exist yet :( Please hop on github and offer up a translation!",zh_CN:"还没翻译 {key} :( 请在gitHub上贡献你的翻译!",fr_FR:"La traduction pour {key} n'existe pas encore :( Venez sur Github pour en offrir une !"},"error-untranslated":{__desc__:"The general error when we encounter a dialog that is not translated",en_US:"This dialog or text is not yet translated in your locale :( Hop on github to aid in translation!",zh_CN:"这段对话还没有被翻译成你的语言 :( 欢迎在gitHub上贡献你的翻译!",fr_FR:"Ce message n'a pas encore été traduit dans votre langue :( Venez sur Github aider à la traduction !"}}}),e.define("/src/js/app/index.js",function(e,t,n,r,i,s,o){function E(){var t=e("../views"),n=e("../models/collections"),r=e("../views/commandViews"),i=new t.MainHelperBar;this.commandCollection=new n.CommandCollection,this.commandBuffer=new n.CommandBuffer({collection:this.commandCollection}),this.commandPromptView=new r.CommandPromptView({el:$("#commandLineBar")}),this.commandLineHistoryView=new r.CommandLineHistoryView({el:$("#commandLineHistory"),collection:this.commandCollection})}var u=e("underscore"),a=e("backbone"),f=e("../util/constants"),l=e("../util"),c=u.clone(a.Events),h,p,d,v,m,g=function(){var t=e("../level/sandbox").Sandbox,n=e("../level").Level,r=e("../util/eventBaton").EventBaton,i=e("../level/arbiter").LevelArbiter,s=e("../views/levelDropdownView").LevelDropdownView;d=new r,h=new E,p=new t,v=new i,m=new s({wait:!0}),c.on("localeChanged",y),b(d),w(p)},y=function(){if(!window.$)return;$("span.intl-aware").each(function(t,n){var r=e("../intl"),i=$(n).attr("data-intl");$(n).text(r.str(i).toUpperCase())})},b=function(e){var t=function(){$("#commandTextField").focus()};t(),$(window).focus(function(t){e.trigger("windowFocus",t)}),$(document).click(function(t){e.trigger("documentClick",t)}),$(document).bind("keydown",function(t){e.trigger("docKeydown",t)}),$(document).bind("keyup",function(t){e.trigger("docKeyup",t)}),$(window).on("resize",function(e){c.trigger("resize",e)}),e.stealBaton("docKeydown",function(){}),e.stealBaton("docKeyup",function(){}),e.stealBaton("windowFocus",t),e.stealBaton("documentClick",t);var n=function(t){return function(){var n=[t];u.each(arguments,function(e){n.push(e)}),e.trigger.apply(e,n)}};$("#commandTextField").on("keydown",n("keydown")),$("#commandTextField").on("keyup",n("keyup")),$(window).trigger("resize")},w=function(e){var t=l.parseQueryString(window.location.href);t.hasOwnProperty("demo")?e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",["git commit; git checkout -b bugFix C1; git commit; git merge master; git checkout master; git commit; git rebase bugFix;","delay 1000; reset;","level rebase1 --noFinishDialog --noStartCommand --noIntroDialog;","delay 2000; show goal; delay 1000; hide goal;","git checkout bugFix; git rebase master; git checkout side; git rebase bugFix;","git checkout another; git rebase side; git rebase another master;","help; levels"].join(""))}):t.hasOwnProperty("NODEMO")||e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",["git help;","delay 1000;","help;","levels"].join(""))}),t.locale!==undefined&&t.locale.length&&(f.GLOBAL.locale=t.locale,c.trigger("localeChanged"));if(t.command){var n=unescape(t.command);e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",n)})}(/(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent)||/android/i.test(navigator.userAgent))&&e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted","mobile alert")})};e("../util").isBrowser()&&$(document).ready(g),n.getEvents=function(){return c},n.getSandbox=function(){return p},n.getEventBaton=function(){return d},n.getCommandUI=function(){return h},n.getLevelArbiter=function(){return v},n.getLevelDropdown=function(){return m},n.init=g}),e.define("/src/js/level/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("../util"),c=e("../app"),h=e("../intl"),p=e("../log"),d=e("../util/errors"),v=e("../level/sandbox").Sandbox,m=e("../util/constants"),g=e("../visuals/visualization").Visualization,y=e("../level/parseWaterfall").ParseWaterfall,b=e("../level/disabledMap").DisabledMap,w=e("../models/commandModel").Command,E=e("../git/gitShim").GitShim,S=e("../views/multiView").MultiView,x=e("../views").CanvasTerminalHolder,T=e("../views").ConfirmCancelTerminal,N=e("../views").NextLevelConfirm,C=e("../views").LevelToolbar,k=e("../git/treeCompare").TreeCompare,L={"help level":/^help level$/,"start dialog":/^start dialog$/,"show goal":/^(show goal|goal|help goal)$/,"hide goal":/^hide goal$/,"show solution":/^show solution($|\s)/,objective:/^(objective|assignment)$/},A=l.genParseCommand(L,"processLevelCommand"),O=v.extend({initialize:function(e){e=e||{},e.level=e.level||{},this.level=e.level,this.gitCommandsIssued=[],this.commandsThatCount=this.getCommandsThatCount(),this.solved=!1,this.initGoalData(e),this.initName(e),O.__super__.initialize.apply(this,[e]),this.startOffCommand(),this.handleOpen(e.deferred)},handleOpen:function(e){e=e||f.defer();if(this.level.startDialog&&!this.testOption("noIntroDialog")){new S(u.extend({},h.getStartDialog(this.level),{deferred:e}));return}setTimeout(function(){e.resolve()},this.getAnimationTime()*1.2)},objectiveDialog:function(e,t,n){n=n===undefined?this.level:n;if(!n||!n.startDialog){e.set("error",new d.GitError({msg:h.str("no-start-dialog")})),t.resolve();return}debugger;console.log(h.getStartDialog(n));var r=$.extend({},h.getStartDialog(n));r.childViews=r.childViews.slice(-1),new S(u.extend(r,{deferred:t})),t.promise.then(function(){e.set("status","finished")})},startDialog:function(e,t){if(!this.level.startDialog){e.set("error",new d.GitError({msg:h.str("no-start-dialog")})),t.resolve();return}this.handleOpen(t),t.promise.then(function(){e.set("status","finished")})},getEnglishName:function(){return this.level.name.en_US},initName:function(){var e=h.getName(this.level);this.levelToolbar=new C({name:e})},initGoalData:function(e){if(!this.level.goalTreeString||!this.level.solutionCommand)throw new Error("need goal tree and solution")},takeControl:function(){c.getEventBaton().stealBaton("processLevelCommand",this.processLevelCommand,this),O.__super__.takeControl.apply(this)},releaseControl:function(){c.getEventBaton().releaseBaton("processLevelCommand",this.processLevelCommand,this),O.__super__.releaseControl.apply(this)},startOffCommand:function(){this.testOption("noStartCommand")||c.getEventBaton().trigger("commandSubmitted","hint; delay 2000; show goal")},initVisualization:function(e){this.mainVis=new g({el:e.el||this.getDefaultVisEl(),treeString:e.level.startTree})},initGoalVisualization:function(){return this.goalCanvasHolder=new x,this.goalVis=new g({el:this.goalCanvasHolder.getCanvasLocation(),containerElement:this.goalCanvasHolder.getCanvasLocation(),treeString:this.level.goalTreeString,noKeyboardInput:!0,smallCanvas:!0,noClick:!0}),this.goalCanvasHolder},showSolution:function(t,n){var r=this.level.solutionCommand,i=u.bind(function(){this.isShowingSolution=!0,c.getEventBaton().trigger("commandSubmitted",r),p.showLevelSolution(this.getEnglishName())},this),s=t.get("rawStr");this.testOptionOnString(s,"noReset")||(r="reset --forSolution; "+r);if(this.testOptionOnString(s,"force")){i(),t.finishWith(n);return}var o=f.defer(),a=h.getDialog(e("../dialogs/confirmShowSolution"))[0],l=new T({markdowns:a.options.markdowns,deferred:o});o.promise.then(i).fail(function(){t.setResult("")}).done(function(){setTimeout(function(){t.finishWith(n)},l.getAnimationTime())})},showGoal:function(e,t){this.showSideVis(e,t,this.goalCanvasHolder,this.initGoalVisualization)},showSideVis:function(e,t,n,r){var i=function(){e&&e.finishWith(t)};if(!n||!n.inDom)n=r.apply(this);n.slideIn(),setTimeout(i,n.getAnimationTime())},hideGoal:function(e,t){this.hideSideVis(e,t,this.goalCanvasHolder)},hideSideVis:function(e,t,n,r){var i=function(){e&&e.finishWith(t)};n&&n.inDom?(n.die(),setTimeout(i,n.getAnimationTime())):i()},initParseWaterfall:function(e){O.__super__.initParseWaterfall.apply(this,[e]),this.parseWaterfall.addFirst("parseWaterfall",A),this.parseWaterfall.addFirst("instantWaterfall",this.getInstantCommands()),e.level.disabledMap&&this.parseWaterfall.addFirst("instantWaterfall",(new b({disabledMap:e.level.disabledMap})).getInstantCommands())},initGitShim:function(e){this.gitShim=new E({beforeCB:u.bind(this.beforeCommandCB,this),afterCB:u.bind(this.afterCommandCB,this),afterDeferHandler:u.bind(this.afterCommandDefer,this)})},getCommandsThatCount:function(){var t=e("../git/commands"),n=["git commit","git checkout","git rebase","git reset","git branch","git revert","git merge","git cherry-pick"],r={};return u.each(n,function(e){if(!t.regexMap[e])throw new Error("wut no regex");r[e]=t.regexMap[e]}),r},undo:function(){this.gitCommandsIssued.pop(),O.__super__.undo.apply(this,arguments)},afterCommandCB:function(e){if(e.get("error"))return;var t=!1;u.each(this.commandsThatCount,function(n){t=t||n.test(e.get("rawStr"))}),t&&this.gitCommandsIssued.push(e.get("rawStr"))},afterCommandDefer:function(e,t){if(this.solved){t.addWarning(h.str("already-solved")),e.resolve();return}var n=this.mainVis.gitEngine.exportTree(),r=k.dispatchFromLevel(this.level,n);if(!r){e.resolve();return}this.levelSolved(e)},getNumSolutionCommands:function(){var e=this.level.solutionCommand.replace(/^;|;$/g,"");return e.split(";").length},testOption:function(e){return this.options.command&&(new RegExp("--"+e)).test(this.options.command.get("rawStr"))},testOptionOnString:function(e,t){return e&&(new RegExp("--"+t)).test(e)},levelSolved:function(e){this.solved=!0,this.isShowingSolution||(c.getEvents().trigger("levelSolved",this.level.id),p.levelSolved(this.getEnglishName())),this.hideGoal();var t=c.getLevelArbiter().getNextLevel(this.level.id),n=this.gitCommandsIssued.length,r=this.getNumSolutionCommands();m.GLOBAL.isAnimating=!0;var i=this.testOption("noFinishDialog"),s=this.mainVis.gitVisuals.finishAnimation();i||(s=s.then(function(){var e=new N({nextLevel:t,numCommands:n,best:r});return e.getPromise()})),s.then(function(){!i&&t&&(p.choseNextLevel(t.id),c.getEventBaton().trigger("commandSubmitted","level "+t.id))}).fail(function(){}).done(function(){m.GLOBAL.isAnimating=!1,e.resolve()})},die:function(){this.levelToolbar.die(),this.hideGoal(),this.mainVis.die(),this.releaseControl(),this.clear(),delete this.commandCollection,delete this.mainVis,delete this.goalVis,delete this.goalCanvasHolder},getInstantCommands:function(){var e=u.bind(function(){var e=h.getHint(this.level);return!e||!e.length?h.str("no-hint"):e},this);return[[/^help$|^\?$/,function(){throw new d.CommandResult({msg:h.str("help-vague-level")})}],[/^hint$/,function(){throw new d.CommandResult({msg:e()})}]]},reset:function(e,t){this.gitCommandsIssued=[];var n=e?e.get("rawStr"):"";this.testOptionOnString(n,"forSolution")||(this.isShowingSolution=!1),this.solved=!1,O.__super__.reset.apply(this,arguments)},buildLevel:function(e,t){this.exitLevel(),setTimeout(function(){c.getSandbox().buildLevel(e,t)},this.getAnimationTime()*1.5)},importLevel:function(e,t){this.exitLevel(),setTimeout(function(){c.getSandbox().importLevel(e,t)},this.getAnimationTime()*1.5)},startLevel:function(e,t){this.exitLevel(),setTimeout(function(){c.getSandbox().startLevel(e,t)},this.getAnimationTime()*1.5)},exitLevel:function(e,t){this.die();if(!e||!t)return;setTimeout(function(){e.finishWith(t)},this.getAnimationTime()),c.getEventBaton().trigger("levelExited")},processLevelCommand:function(e,t){var n={"show goal":this.showGoal,"hide goal":this.hideGoal,"show solution":this.showSolution,"start dialog":this.startDialog,"help level":this.startDialog,objective:this.objectiveDialog},r=n[e.get("method")];if(!r)throw new Error("woah we dont support that method yet",r);r.apply(this,[e,t])}});n.Level=O,n.regexMap=L}),e.define("/src/js/log/index.js",function(e,t,n,r,i,s,o){var u=function(e,t,n){window._gaq=window._gaq||[],window._gaq.push(["_trackEvent",e,t,n])};n.viewInteracted=function(e){u("views","interacted",e)},n.showLevelSolution=function(e){u("levels","showedLevelSolution",e)},n.choseNextLevel=function(e){u("levels","nextLevelChosen",e)},n.levelSelected=function(e){u("levels","levelSelected",e)},n.levelSolved=function(e){u("levels","levelSolved",e)},n.commandEntered=function(e){u("commands","commandEntered",e)}}),e.define("/src/js/util/errors.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({defaults:{type:"MyError",msg:"Unknown Error"},toString:function(){return this.get("type")+": "+this.get("msg")},getMsg:function(){return this.get("msg")||"Unknown Error"},toResult:function(){return this.get("msg").length?"

"+this.get("msg").replace(/\n/g,"

")+"

":""}}),l=n.CommandProcessError=f.extend({defaults:{type:"Command Process Error"}}),c=n.CommandResult=f.extend({defaults:{type:"Command Result"}}),h=n.Warning=f.extend({defaults:{type:"Warning"}}),p=n.GitError=f.extend({defaults:{type:"Git Error"}}),d=function(e){if(e instanceof l||e instanceof p||e instanceof c||e instanceof h)return;throw e};n.filterError=d}),e.define("/src/js/visuals/visualization.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../models/collections"),l=f.CommitCollection,c=f.BranchCollection,h=e("../util/eventBaton").EventBaton,p=e("../visuals").GitVisuals,d=a.View.extend({initialize:function(e){e=e||{},this.options=e,this.customEvents=u.clone(a.Events),this.containerElement=e.containerElement;var t=this,n=e.containerElement||$("#canvasHolder")[0];new Raphael(n,200,200,function(){var n=this;s.nextTick(function(){t.paperInitialize(n,e)})})},paperInitialize:function(t,n){this.treeString=n.treeString,this.paper=t;var r=e("../app");this.eventBaton=n.noKeyboardInput?new h:r.getEventBaton(),this.commitCollection=new l,this.branchCollection=new c,this.gitVisuals=new p({commitCollection:this.commitCollection,branchCollection:this.branchCollection,paper:this.paper,noClick:this.options.noClick,smallCanvas:this.options.smallCanvas,visualization:this});var i=e("../git").GitEngine;this.gitEngine=new i({collection:this.commitCollection,branches:this.branchCollection,gitVisuals:this.gitVisuals,eventBaton:this.eventBaton}),this.gitEngine.init(),this.gitVisuals.assignGitEngine(this.gitEngine),this.myResize(),$(window).on("resize",u.bind(function(){this.myResize()},this)),this.gitVisuals.drawTreeFirstTime(),this.treeString&&this.gitEngine.loadTreeFromString(this.treeString),this.options.zIndex&&this.setTreeIndex(this.options.zIndex),this.shown=!1,this.setTreeOpacity(0),s.nextTick(u.bind(this.fadeTreeIn,this)),this.customEvents.trigger("gitEngineReady"),this.customEvents.trigger("paperReady")},clearOrigin:function(){delete this.originVis},makeOrigin:function(e){return this.originVis=new d(u.extend({},this.options,{noKeyboardInput:!0,noClick:!0,treeString:e.treeString})),this.originVis},originToo:function(e,t){if(!this.originVis)return;var n=u.bind(function(){this.originVis[e].apply(this.originVis,t)},this);if(this.originVis.paper){n();return}this.originVis.customEvents.on("paperReady",n)},setTreeIndex:function(e){$(this.paper.canvas).css("z-index",e),this.originToo("setTreeIndex",arguments)},setTreeOpacity:function(e){e===0&&(this.shown=!1),$(this.paper.canvas).css("opacity",e),this.originToo("setTreeOpacity",arguments)},getAnimationTime:function(){return 300},fadeTreeIn:function(){this.shown=!0,$(this.paper.canvas).animate({opacity:1},this.getAnimationTime()),this.originToo("fadeTreeIn",arguments)},fadeTreeOut:function(){this.shown=!1,$(this.paper.canvas).animate({opacity:0},this.getAnimationTime()),this.originToo("fadeTreeOut",arguments)},hide:function(){this.fadeTreeOut(),setTimeout(u.bind(function(){$(this.paper.canvas).css("visibility","hidden")},this),this.getAnimationTime()),this.originToo("hide",arguments)},show:function(){$(this.paper.canvas).css("visibility","visible"),setTimeout(u.bind(this.fadeTreeIn,this),10),this.originToo("show",arguments)},showHarsh:function(){$(this.paper.canvas).css("visibility","visible"),this.setTreeOpacity(1),this.originToo("showHarsh",arguments)},resetFromThisTreeNow:function(e){this.treeString=e;var t=this.getOriginInTreeString(e);if(t){var n=this.gitEngine.printTree(t);this.originToo("resetFromThisThreeNow",[n])}},getOriginInTreeString:function(e){var t=JSON.parse(unescape(e));return t.originTree},reset:function(e){var t=e||this.treeString;this.setTreeOpacity(0),t?this.gitEngine.loadTreeFromString(t):this.gitEngine.defaultInit(),this.fadeTreeIn();if(this.originVis)if(t){var n=this.getOriginInTreeString(t);this.originToo("reset",[JSON.stringify(n)])}else this.originToo("reset",arguments)},tearDown:function(){this.gitEngine.tearDown(),this.gitVisuals.tearDown(),delete this.paper,this.originToo("tearDown",arguments)},die:function(){this.fadeTreeOut(),setTimeout(u.bind(function(){this.shown||this.tearDown()},this),this.getAnimationTime()),this.originToo("die",arguments)},myResize:function(){if(!this.paper)return;var e=1,t=this.el,n=t.clientWidth-e,r=t.clientHeight-e;if(!this.containerElement){var i=t.offsetLeft,s=t.offsetTop;$(this.paper.canvas).css({position:"absolute",left:i+"px",top:s+"px"})}this.paper.setSize(n,r),this.gitVisuals.canvasResize(n,r)}});n.Visualization=d}),e.define("/src/js/models/collections.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?f=window.Backbone:f=e("backbone"),l=e("../git").Commit,c=e("../git").Branch,h=e("../models/commandModel").Command,p=e("../models/commandModel").CommandEntry,d=e("../util/constants").TIME,v=f.Collection.extend({model:l}),m=f.Collection.extend({model:h}),g=f.Collection.extend({model:c}),y=f.Collection.extend({model:p,localStorage:f.LocalStorage?new f.LocalStorage("CommandEntries"):null}),b=f.Model.extend({defaults:{collection:null},initialize:function(e){e.collection.bind("add",this.addCommand,this),this.buffer=[],this.timeout=null},addCommand:function(e){this.buffer.push(e),this.touchBuffer()},touchBuffer:function(){if(this.timeout)return;this.setTimeout()},setTimeout:function(){this.timeout=setTimeout(u.bind(function(){this.sipFromBuffer()},this),d.betweenCommandsDelay)},popAndProcess:function(){var e=this.buffer.shift(0);while(e.get("error")&&this.buffer.length)e=this.buffer.shift(0);e.get("error")?this.clear():this.processCommand(e)},processCommand:function(t){t.set("status","processing");var n=a.defer();n.promise.then(u.bind(function(){this.setTimeout()},this));var r=t.get("eventName");if(!r)throw new Error("I need an event to trigger when this guy is parsed and ready");var i=e("../app"),s=i.getEventBaton(),o=s.getNumListeners(r);if(!o){var f=e("../util/errors");t.set("error",new f.GitError({msg:"That command is valid, but not supported in this current environment! Try entering a level or level builder to use that command"})),n.resolve();return}i.getEventBaton().trigger(r,t,n)},clear:function(){clearTimeout(this.timeout),this.timeout=null},sipFromBuffer:function(){if(!this.buffer.length){this.clear();return}this.popAndProcess()}});n.CommitCollection=v,n.CommandCollection=m,n.BranchCollection=g,n.CommandEntryCollection=y,n.CommandBuffer=b}),e.define("/src/js/git/index.js",function(e,t,n,r,i,s,o){function y(e){this.rootCommit=null,this.refs={},this.HEAD=null,this.origin=null,this.localRepo=null,this.branchCollection=e.branches,this.commitCollection=e.collection,this.gitVisuals=e.gitVisuals,this.eventBaton=e.eventBaton,this.eventBaton.stealBaton("processGitCommand",this.dispatch,this),e.animationFactory&&(c=e.animationFactory),this.commandOptions={},this.generalArgs=[],this.initUniqueID()}var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("q"),l=e("../intl"),c=e("../visuals/animation/animationFactory").AnimationFactory,h=e("../visuals/animation").AnimationQueue,p=e("./treeCompare").TreeCompare,d=e("../util/errors"),v=d.GitError,m=d.CommandResult,g=e("../util/eventBaton").EventBaton;y.prototype.initUniqueID=function(){this.uniqueId=function(){var e=0;return function(t){return t?t+e++:e++}}()},y.prototype.assignLocalRepo=function(e){this.localRepo=e},y.prototype.defaultInit=function(){var e=this.getDefaultTree();this.loadTree(e)},y.prototype.getDefaultTree=function(){return JSON.parse(unescape("%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22master%22%2C%22type%22%3A%22branch%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%22C0%22%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C1%22%7D%7D%2C%22HEAD%22%3A%7B%22id%22%3A%22HEAD%22%2C%22target%22%3A%22master%22%2C%22type%22%3A%22general%20ref%22%7D%7D"))},y.prototype.init=function(){this.rootCommit=this.makeCommit(null,null,{rootCommit:!0}),this.commitCollection.add(this.rootCommit);var e=this.makeBranch("master",this.rootCommit);this.HEAD=new b({id:"HEAD",target:e}),this.refs[this.HEAD.get("id")]=this.HEAD,this.commit()},y.prototype.hasOrigin=function(){return!!this.origin},y.prototype.isOrigin=function(){return!!this.localRepo},y.prototype.exportTreeForBranch=function(e){var t=this.exportTree(),n=this.getUpstreamSet(e),r=t.commits;t.commits={},u.each(r,function(e,r){n[r]&&(t.commits[r]=e)});var i=t.branches;return t.branches={},u.each(i,function(n,r){r===e&&(t.branches[r]=n)}),t.HEAD.target=e,t},y.prototype.exportTree=function(){var e={branches:{},commits:{},HEAD:null};u.each(this.branchCollection.toJSON(),function(t){t.target=t.target.get("id"),t.visBranch=undefined,e.branches[t.id]=t}),u.each(this.commitCollection.toJSON(),function(t){u.each(E.prototype.constants.circularFields,function(e){t[e]=undefined},this);var n=[];u.each(t.parents,function(e){n.push(e.get("id"))}),t.parents=n,e.commits[t.id]=t},this);var t=this.HEAD.toJSON();return t.visBranch=undefined,t.lastTarget=t.lastLastTarget=t.visBranch=undefined,t.target=t.target.get("id"),e.HEAD=t,this.hasOrigin()&&(e.originTree=this.origin.exportTree()),e},y.prototype.printTree=function(e){e=e||this.exportTree(),p.reduceTreeFields([e]);var t=JSON.stringify(e);return/'/.test(t)&&(t=escape(t)),t},y.prototype.printAndCopyTree=function(){window.prompt(l.str("Copy the tree string below"),this.printTree())},y.prototype.loadTree=function(e){e=$.extend(!0,{},e),this.removeAll(),this.instantiateFromTree(e),this.reloadGraphics(),this.initUniqueID()},y.prototype.loadTreeFromString=function(e){this.loadTree(JSON.parse(unescape(e)))},y.prototype.instantiateFromTree=function(e){var t={};u.each(e.commits,function(n){var r=this.getOrMakeRecursive(e,t,n.id);this.commitCollection.add(r)},this),u.each(e.branches,function(n){var r=this.getOrMakeRecursive(e,t,n.id);this.branchCollection.add(r,{silent:!0})},this);var n=this.getOrMakeRecursive(e,t,e.HEAD.id);this.HEAD=n,this.rootCommit=t.C0;if(!this.rootCommit)throw new Error("Need root commit of C0 for calculations");this.refs=t,this.gitVisuals.gitReady=!1,this.branchCollection.each(function(e){this.gitVisuals.addBranch(e)},this);if(e.originTree){var r=JSON.stringify(e.originTree);this.makeOrigin(r)}},y.prototype.makeOrigin=function(e){if(this.hasOrigin())throw new v({msg:l.str("git-error-origin-exists")});e=e||this.printTree(this.exportTreeForBranch("master"));var t=this.gitVisuals.getVisualization(),n=t.makeOrigin({localRepo:this,treeString:e});this.animationQueue.set("promiseBased",!0),n.customEvents.on("gitEngineReady",function(){this.origin=n.gitEngine,n.gitEngine.assignLocalRepo(this),this.origin.externalRefresh(),c.playRefreshAnimationAndFinish(this.gitVisuals,this.animationQueue)},this);var r=JSON.parse(unescape(e)),i=r.branches.master.target,s=this.makeBranch("o/master",this.getCommitFromRef(i));s.set("remote",!0)},y.prototype.getOrMakeRecursive=function(e,t,n){if(t[n])return t[n];var r=function(e,t){if(e.commits[t])return"commit";if(e.branches[t])return"branch";if(t=="HEAD")return"HEAD";throw new Error("bad type for "+t)},i=r(e,n);if(i=="HEAD"){var s=e.HEAD,o=new b(u.extend(e.HEAD,{target:this.getOrMakeRecursive(e,t,s.target)}));return t[n]=o,o}if(i=="branch"){var a=e.branches[n],f=new w(u.extend(e.branches[n],{target:this.getOrMakeRecursive(e,t,a.target)}));return t[n]=f,f}if(i=="commit"){var l=e.commits[n],c=[];u.each(l.parents,function(n){c.push(this.getOrMakeRecursive(e,t,n))},this);var h=new E(u.extend(l,{parents:c,gitVisuals:this.gitVisuals}));return t[n]=h,h}throw new Error("ruh rho!! unsupported type for "+n)},y.prototype.tearDown=function(){this.eventBaton.releaseBaton("processGitCommand",this.dispatch,this),this.removeAll()},y.prototype.reloadGraphics=function(){this.gitVisuals.rootCommit=this.refs.C0,this.gitVisuals.initHeadBranch(),this.gitVisuals.drawTreeFromReload(),this.gitVisuals.refreshTreeHarsh()},y.prototype.removeAll=function(){this.branchCollection.reset(),this.commitCollection.reset(),this.refs={},this.HEAD=null,this.rootCommit=null,this.origin&&(this.origin.gitVisuals.getVisualization().tearDown(),delete this.origin,this.gitVisuals.getVisualization().clearOrigin()),this.gitVisuals.resetAll()},y.prototype.getDetachedHead=function(){var e=this.HEAD.get("target"),t=e.get("type");return t!=="branch"},y.prototype.validateBranchName=function(e){e=e.replace(/\s/g,"");if(!/^[a-zA-Z0-9]+$/.test(e))throw new v({msg:l.str("bad-branch-name",{branch:e})});if(/[hH][eE][aA][dD]/.test(e))throw new v({msg:l.str("bad-branch-name",{branch:e})});return e.length>9&&(e=e.slice(0,9),this.command.addWarning(l.str("branch-name-short",{branch:e}))),e},y.prototype.validateAndMakeBranch=function(e,t){e=this.validateBranchName(e);if(this.refs[e])throw new v({msg:l.str("bad-branch-name",{branch:name})});this.makeBranch(e,t)},y.prototype.makeBranch=function(e,t){var n=new w({target:t,id:e});return this.branchCollection.add(n),this.refs[n.get("id")]=n,n},y.prototype.getHead=function(){return u.clone(this.HEAD)},y.prototype.getBranches=function(){var e=[];return this.branchCollection.each(function(t){e.push({id:t.get("id"),selected:this.HEAD.get("target")===t,target:t.get("target"),remote:t.getIsRemote(),obj:t})},this),e},y.prototype.getRemoteBranches=function(){var e=this.getBranches();return u.filter(e,function(e){return e.remote===!0})},y.prototype.getLocalBranches=function(){var e=this.getBranches();return u.filter(e,function(e){return e.remote===!1})},y.prototype.printBranchesWithout=function(e){var t=this.getUpstreamBranchSet(),n=this.getCommitFromRef(e).get("id"),r=[];u.each(t[n],function(e){e.selected=this.HEAD.get("target").get("id")==e.id,r.push(e)},this),this.printBranches(r)},y.prototype.printBranches=function(e){var t="";throw u.each(e,function(e){t+=(e.selected?"* ":"")+e.id+"\n"}),new m({msg:t})},y.prototype.getUniqueID=function(){var e=this.uniqueId("C"),t=u.bind(function(e){return this.refs[e]?!0:this.origin&&this.origin.refs[e]?!0:!1},this);while(t(e))e=this.uniqueId("C");return e},y.prototype.makeCommit=function(e,t,n){t||(t=this.getUniqueID());var r=new E(u.extend({parents:e,id:t,gitVisuals:this.gitVisuals},n||{}));return this.refs[r.get("id")]=r,this.commitCollection.add(r),r},y.prototype.acceptNoGeneralArgs=function(){if(this.generalArgs.length)throw new v({msg:l.str("git-error-no-general-args")})},y.prototype.validateArgBounds=function(e,t,n,r){var i=r===undefined?"git "+this.command.get("method"):this.command.get("method")+" "+r+" ";i="with "+i;if(e.lengthn)throw new v({msg:l.str("git-error-args-many",{upper:String(n),what:i})})},y.prototype.oneArgImpliedHead=function(e,t){this.validateArgBounds(e,0,1,t),e.length===0&&e.push("HEAD")},y.prototype.twoArgsImpliedHead=function(e,t){this.validateArgBounds(e,1,2,t),e.length==1&&e.push("HEAD")},y.prototype.revertStarter=function(){this.validateArgBounds(this.generalArgs,1,NaN),this.revert(this.generalArgs)},y.prototype.revert=function(e){var t=u.map(e,function(e){return this.getCommitFromRef(e)},this),n=f.defer(),r=n.promise,i=this.resolveID("HEAD");r=c.highlightEachWithPromise(r,t,i);var s=this.getCommitFromRef("HEAD"),o=u.bind(function(e){var t=this.rebaseAltID(e.get("id")),n=l.str("git-revert-msg",{oldCommit:this.resolveName(e),oldMsg:e.get("commitMessage")}),r=this.makeCommit([s],t,{commitMessage:n});return s=r,c.playCommitBirthPromiseAnimation(r,this.gitVisuals)},this);u.each(t,function(e){r=r.then(function(){return o(e)})},this),r=r.then(u.bind(function(){return this.setTargetLocation("HEAD",s),c.playRefreshAnimation(this.gitVisuals)},this)),this.animationQueue.thenFinish(r,n)},y.prototype.resetStarter=function(){if(this.commandOptions["--soft"])throw new v({msg:l.str("git-error-staging")});this.commandOptions["--hard"]&&(this.command.addWarning(l.str("git-warning-hard")),this.generalArgs=this.generalArgs.concat(this.commandOptions["--hard"])),this.validateArgBounds(this.generalArgs,1,1);if(this.getDetachedHead())throw new v({msg:l.str("git-error-reset-detached")});this.reset(this.generalArgs[0])},y.prototype.reset=function(e){this.setTargetLocation("HEAD",this.getCommitFromRef(e))},y.prototype.cherrypickStarter=function(){this.validateArgBounds(this.generalArgs,1,Number.MAX_VALUE);var e=this.getUpstreamSet("HEAD"),t=u.map(this.generalArgs,function(t){var n=this.getCommitFromRef(t);if(e[n.get("id")])throw new v({msg:l.str("git-error-already-exists",{commit:n.get("id")})});return n},this),n=f.defer(),r=n.promise,i=this.resolveID("HEAD");r=c.highlightEachWithPromise(r,t,i);var s=u.bind(function(e){var t=this.cherrypick(e);return c.playCommitBirthPromiseAnimation(t,this.gitVisuals)},this);u.each(t,function(e){r=r.then(function(){return s(e)})},this),this.animationQueue.thenFinish(r,n)},y.prototype.checkUpstreamOfSource=function(e,t,n,r,i){var s=t.getUpstreamSet(r),o=e.getCommitFromRef(n).get("id");if(!s[o])throw new v({msg:i||l.str("git-error-origin-fetch-no-ff")})},y.prototype.getTargetGraphDifference=function(e,t,n,r,i){i=i||{},r=t.resolveID(r);var s=e.getUpstreamSet(n),o=t.getCommitFromRef(r),a=t.exportTree(),f=a.commits[o.get("id")];if(e.refs[f.id]){if(i.dontThrowOnNoFetch)return[];throw new v({msg:l.str("git-error-origin-fetch-uptodate")})}f.depth=0;var c=[],h=[f],p=function(e){if(s[e])return;var t=a.commits[e];t.depth=d.depth+1,h.push(t)};while(h.length){var d=h.pop();c.push(d),u.each(d.parents,p)}var m={},g=[];return u.forEach(c,function(e){if(m[e.id])return;m[e.id]=!0,g.push(e)}),g.sort(function(e,t){return t.depth-e.depth})},y.prototype.pushStarter=function(e){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.push()},y.prototype.push=function(e){e=e||{};var t=this.refs.master,n=this.origin.refs.master;this.checkUpstreamOfSource(this,this.origin,n,t,l.str("git-error-origin-push-no-ff"));var r=this.getTargetGraphDifference(this.origin,this,n,t),i=u.bind(function(e,t){var n=u.map(t,function(e){return this.origin.refs[e]},this);return this.origin.makeCommit(n,e)},this),s=u.bind(function(e,t){var n=i(e,t);return c.playCommitBirthPromiseAnimation(n,this.origin.gitVisuals)},this),o=f.defer(),a=o.promise;u.each(r,function(e){a=a.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.refs[e.id],n)},this)),a=a.then(function(){return s(e.id,e.parents)})},this),a=a.then(u.bind(function(){var e=t.get("target").get("id"),r=this.origin.refs[e];return this.origin.setTargetLocation(n,r),c.playRefreshAnimation(this.gitVisuals),c.playRefreshAnimation(this.origin.gitVisuals)},this)),a=a.then(u.bind(function(){var e=this.getCommitFromRef(t),n=t.getRemoteBranchIDFromTracking();return this.setTargetLocation(this.refs[n],e),c.playRefreshAnimation(this.gitVisuals)},this)),e.dontResolvePromise||this.animationQueue.thenFinish(a,o)},y.prototype.fetchStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.fetch()},y.prototype.fetch=function(e){e=e||{};var t=this.refs["o/master"],n=this.origin.refs.master;this.checkUpstreamOfSource(this,this.origin,t,n);var r=this.getTargetGraphDifference(this,this.origin,t,n,e);if(r.length===0){this.command.addWarning(l.str("git-error-origin-fetch-uptodate"));var i=f.defer();return{deferred:i,chain:i.promise}}var s=u.bind(function(e,t){var n=u.map(t,function(e){return this.refs[e]},this);return this.makeCommit(n,e)},this),o=u.bind(function(e,t){var n=s(e,t);return c.playCommitBirthPromiseAnimation(n,this.gitVisuals)},this),a=f.defer(),h=a.promise;return u.each(r,function(e){h=h.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.origin.refs[e.id],t)},this)),h=h.then(function(){return o(e.id,e.parents)})},this),h=h.then(u.bind(function(){var e=n.get("target").get("id"),r=this.refs[e];return this.setTargetLocation(t,r),c.playRefreshAnimation(this.origin.gitVisuals),c.playRefreshAnimation(this.gitVisuals)},this)),e.dontResolvePromise||this.animationQueue.thenFinish(h,a),{chain:h,deferred:a}},y.prototype.pullStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.pull()},y.prototype.pull=function(){var e=this.refs.master,t=this.refs["o/master"],n=this.fetch({dontResolvePromise:!0,dontThrowOnNoFetch:!0});this.commandOptions["--rebase"]?this.pullFinishWithRebase(n,e,t):this.pullFinishWithMerge(n,e,t)},y.prototype.pullFinishWithRebase=function(e,t,n){var r=e.chain,i=e.deferred;r=r.then(function(){return c.getDelayedPromise(300)}),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(n),t)},this)),r=r.then(u.bind(function(){return e.dontResolvePromise=!0,this.rebase(n,t,e)},this)),this.animationQueue.thenFinish(r,i)},y.prototype.pullFinishWithMerge=function(e,t,n){var r=e.chain,i=e.deferred;r=r.then(function(){return c.getDelayedPromise(300)}),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(n),t)},this)),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(t),n)},this)),r=r.then(function(){return c.getDelayedPromise(700)}),r=r.then(u.bind(function(){var e=this.merge("o/master");return e?c.playCommitBirthPromiseAnimation(e,this.gitVisuals):c.playRefreshAnimation(this.gitVisuals)},this)),this.animationQueue.thenFinish(r,i)},y.prototype.cloneStarter=function(){this.acceptNoGeneralArgs(),this.makeOrigin(this.printTree(this.exportTreeForBranch("master")))},y.prototype.fakeTeamworkStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.validateArgBounds(this.generalArgs,0,1);var e=this.generalArgs[0]||1;this.fakeTeamwork(e)},y.prototype.fakeTeamwork=function(e){var t=u.bind(function(){var e=this.getUniqueID();return this.origin.receiveTeamwork(e,this.animationQueue)},this),n=u.bind(function(){var e=t();return c.playCommitBirthPromiseAnimation(e,this.origin.gitVisuals)},this),r=function(){return n()},i=f.defer(),s=i.promise;u.each(u.range(e),function(e){s=s.then(function(){return n()})}),this.animationQueue.thenFinish(s,i)},y.prototype.receiveTeamwork=function(e,t){var n=this.makeCommit([this.getCommitFromRef("HEAD")],e);return this.setTargetLocation(this.HEAD,n),n},y.prototype.cherrypick=function(e){var t=this.rebaseAltID(e.get("id")),n=this.makeCommit([this.getCommitFromRef("HEAD")],t);return this.setTargetLocation(this.HEAD,n),n},y.prototype.commitStarter=function(){this.acceptNoGeneralArgs();if(this.commandOptions["-am"]&&(this.commandOptions["-a"]||this.commandOptions["-m"]))throw new v({msg:l.str("git-error-options")});var e=null,t=null;this.commandOptions["-a"]&&this.command.addWarning(l.str("git-warning-add")),this.commandOptions["-am"]&&(t=this.commandOptions["-am"],this.validateArgBounds(t,1,1,"-am"),e=t[0]),this.commandOptions["-m"]&&(t=this.commandOptions["-m"],this.validateArgBounds(t,1,1,"-m"),e=t[0]);var n=this.commit();e&&(e=e.replace(/"/g,'"').replace(/^"/g,"").replace(/"$/g,""),n.set("commitMessage",e));var r=c.playCommitBirthPromiseAnimation(n,this.gitVisuals);this.animationQueue.thenFinish(r)},y.prototype.commit=function(){var e=this.getCommitFromRef(this.HEAD),t=null;this.commandOptions["--amend"]&&(e=this.resolveID("HEAD~1"),t=this.rebaseAltID(this.getCommitFromRef("HEAD").get("id")));var n=this.makeCommit([e],t);return this.getDetachedHead()&&this.command.addWarning(l.str("git-warning-detached")),this.setTargetLocation(this.HEAD,n),n},y.prototype.resolveName=function(e){var t=this.resolveID(e);return t.get("type")=="commit"?"commit "+t.get("id"):t.get("type")=="branch"?'branch "'+t.get("id")+'"':this.resolveName(t.get("target"))},y.prototype.resolveID=function(e){if(e===null||e===undefined)throw new Error("Dont call this with null / undefined");return typeof e!="string"?e:this.resolveStringRef(e)},y.prototype.resolveRelativeRef=function(e,t){var n=/([~\^])(\d*)/g,r;while(r=n.exec(t)){var i=e,s=r[2]?parseInt(r[2],10):1;if(r[1]=="^")i=e.getParent(s-1);else while(i&&s--)i=i.getParent(0);if(!i){var o=l.str("git-error-relative-ref",{commit:e.id,match:r[0]});throw new v({msg:o})}e=i}return e},y.prototype.resolveStringRef=function(e){e=this.crappyUnescape(e);if(this.refs[e])return this.refs[e];var t=null,n=null,r=/^([a-zA-Z0-9]+)(([~\^]\d*)*)/,i=r.exec(e);if(!i)throw new v({msg:l.str("git-error-exist",{ref:e})});t=i[1],n=i[2];if(!this.refs[t])throw new v({msg:l.str("git-error-exist",{ref:e})});var s=this.getCommitFromRef(t);return n&&(s=this.resolveRelativeRef(s,n)),s},y.prototype.getCommitFromRef=function(e){var t=this.resolveID(e);while(t.get("type")!=="commit")t=t.get("target");return t},y.prototype.getType=function(e){return this.resolveID(e).get("type")},y.prototype.setTargetLocation=function(e,t){if(this.getType(e)=="commit")return;e=this.getOneBeforeCommit(e),e.set("target",t)},y.prototype.getUpstreamBranchSet=function(){var e={},t=function(e,t){var n=!1;return u.each(e,function(e){e.id==t&&(n=!0)}),n},n=function(e){var t=[],n=[e];while(n.length){var r=n.pop();t.push(r.get("id")),r.get("parents")&&r.get("parents").length&&(n=n.concat(r.get("parents")))}return t};return this.branchCollection.each(function(r){var i=n(r.get("target"));u.each(i,function(n){e[n]=e[n]||[],t(e[n],r.get("id"))||e[n].push({obj:r,id:r.get("id")})})}),e},y.prototype.getUpstreamHeadSet=function(){var e=this.getUpstreamSet("HEAD"),t=this.getCommitFromRef("HEAD").get("id");return e[t]=!0,e},y.prototype.getOneBeforeCommit=function(e){var t=this.resolveID(e);return t===this.HEAD&&!this.getDetachedHead()&&(t=t.get("target")),t},y.prototype.scrapeBaseID=function(e){var t=/^C(\d+)/.exec(e);if(!t)throw new Error("regex failed on "+e);return"C"+t[1]},y.prototype.rebaseAltID=function(e){var t=[[/^C(\d+)[']{0,2}$/,function(e){return e[0]+"'"}],[/^C(\d+)[']{3}$/,function(e){return e[0].slice(0,-3)+"'^4"}],[/^C(\d+)['][\^](\d+)$/,function(e){return"C"+String(e[1])+"'^"+String(Number(e[2])+1)}]];for(var n=0;n",this.get("commitMessage"),"
","Commit: "+this.get("id")].join("\n")+"\n"},getShowEntry:function(){return[this.getLogEntry(),"diff --git a/bigGameResults.html b/bigGameResults.html","--- bigGameResults.html","+++ bigGameResults.html","@@ 13,27 @@ Winner, Score","- Stanfurd, 14-7","+ Cal, 21-14"].join("\n")+"\n"},validateAtInit:function(){if(!this.get("id"))throw new Error("Need ID!!");this.get("createTime")||this.set("createTime",(new Date).toString()),this.get("commitMessage")||this.set("commitMessage",l.str("git-dummy-msg")),this.set("children",[]);if(!this.get("rootCommit"))if(!this.get("parents")||!this.get("parents").length)throw new Error("needs parents")},addNodeToVisuals:function(){var e=this.get("gitVisuals").addNode(this.get("id"),this);this.set("visNode",e)},addEdgeToVisuals:function(e){this.get("gitVisuals").addEdge(this.get("id"),e.get("id"))},getParent:function(e){return this&&this.attributes&&this.attributes.parents?this.attributes.parents[e]:null},isMainParent:function(e){var t=this.get("parents").indexOf(e);return t===0},initialize:function(e){this.validateAtInit(),this.addNodeToVisuals(),u.each(this.get("parents"),function(e){e.get("children").push(this),this.addEdgeToVisuals(e)},this)}});n.GitEngine=y,n.Commit=E,n.Branch=w,n.Ref=b}),e.define("/src/js/visuals/animation/animationFactory.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("./index").Animation,c=e("./index").PromiseAnimation,h=e("../../util/constants").GRAPHICS,p={},d=function(e,t){var n=h.defaultAnimationTime*1,r=n*2,i=function(){e.refreshTree(n),t.setBirth(),t.parentInFront(),e.visBranchesFront(),t.animateUpdatedPosition(r,"bounce"),t.animateOutgoingEdges(n)};return{animation:i,duration:Math.max(n,r)}},v=function(e,t){var n=h.defaultAnimationTime*.66,r=n*2;return{animation:function(){e.highlightTo(t,r,"easeInOut")},duration:r*1.5}};p.genCommitBirthAnimation=function(e,t,n){if(!e)throw new Error("Need animation queue to add closure to!");var r=t.get("visNode"),i=d(n,r);e.add(new l({closure:i.animation,duration:i.duration}))},p.genCommitBirthPromiseAnimation=function(e,t){var n=e.get("visNode");return new c(d(t,n))},p.highlightEachWithPromise=function(e,t,n){return u.each(t,function(t){e=e.then(u.bind(function(){return this.playHighlightPromiseAnimation(t,n)},this))},this),e},p.playCommitBirthPromiseAnimation=function(e,t){var n=this.genCommitBirthPromiseAnimation(e,t);return n.play(),n.getPromise()},p.playRefreshAnimationAndFinish=function(e,t){var n=new c({closure:function(){e.refreshTree()}});n.play(),t.thenFinish(n.getPromise())},p.playRefreshAnimation=function(e){var t=new c({closure:function(){e.refreshTree()}});return t.play(),t.getPromise()},p.refreshTree=function(e,t){e.add(new l({closure:function(){t.refreshTree()}}))},p.genHighlightPromiseAnimation=function(e,t){var n=t.get("visBranch")||t.get("visNode"),r=e.get("visNode");return new c(v(r,n))},p.playHighlightPromiseAnimation=function(e,t){var n=this.genHighlightPromiseAnimation(e,t);return n.play(),n.getPromise()},p.getDelayedPromise=function(e){var t=f.defer();return setTimeout(t.resolve,e||1e3),t.promise},p.delay=function(e,t){t=t||h.defaultAnimationTime,e.add(new l({closure:function(){},duration:t}))},n.AnimationFactory=p}),e.define("/src/js/visuals/animation/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("backbone"),l=e("../../util/constants").GLOBAL,c=f.Model.extend({defaults:{duration:300,closure:null},validateAtInit:function(){if(!this.get("closure"))throw new Error("give me a closure!")},initialize:function(e){this.validateAtInit()},run:function(){this.get("closure")()}}),h=f.Model.extend({defaults:{animations:null,index:0,callback:null,defer:!1,promiseBased:!1},initialize:function(e){this.set("animations",[]),e.callback||console.warn("no callback")},thenFinish:function(e,t){e.then(u.bind(function(){this.finish()},this)),this.set("promiseBased",!0),t&&t.resolve()},add:function(e){if(!e instanceof c)throw new Error("Need animation not something else");this.get("animations").push(e)},start:function(){this.set("index",0),l.isAnimating=!0,this.next()},finish:function(){l.isAnimating=!1,this.get("callback")()},next:function(){var e=this.get("animations"),t=this.get("index");if(t>=e.length){this.finish();return}var n=e[t],r=n.get("duration");n.run(),this.set("index",t+1),setTimeout(u.bind(function(){this.next()},this),r)}}),p=f.Model.extend({defaults:{deferred:null,closure:null,duration:300},initialize:function(e){if(!e.closure&&!e.animation)throw new Error("need closure or animation");this.set("closure",e.closure||e.animation),this.set("deferred",e.deferred||a.defer())},getPromise:function(){return this.get("deferred").promise},play:function(){this.get("closure")(),setTimeout(u.bind(function(){this.get("deferred").resolve()},this),this.get("duration"))},then:function(e){return this.get("deferred").promise.then(e)}});p.fromAnimation=function(e){return new p({closure:e.get("closure"),duration:e.get("duration")})},n.Animation=c,n.PromiseAnimation=p,n.AnimationQueue=h}),e.define("/src/js/git/treeCompare.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a={};a.dispatchFromLevel=function(e,t){var n=e.goalTreeString;return a.dispatch(e,n,t)},a.dispatch=function(e,t,n){var r=!0;switch(r){case!!e.compareOnlyMaster:return a.compareBranchWithinTrees(n,t,"master");case!!e.compareOnlyBranches:return a.compareAllBranchesWithinTrees(n,t);case!!e.compareAllBranchesHashAgnostic:return a.compareAllBranchesWithinTreesHashAgnostic(n,t);case!!e.compareOnlyMasterHashAgnostic:return a.compareBranchesWithinTreesHashAgnostic(n,t,["master"]);case!!e.compareOnlyMasterHashAgnosticWithAsserts:return a.compareBranchesWithinTreesHashAgnostic(n,t,["master"])&&a.evalAsserts(n,e.goalAsserts);default:return a.compareAllBranchesWithinTreesAndHEAD(n,t)}},a.compareAllBranchesWithinTreesAndHEAD=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t);debugger;return e.HEAD.target==t.HEAD.target&&this.compareAllBranchesWithinTrees(e,t)},a.compareAllBranchesWithinTrees=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t);var n=u.extend({},e.branches,t.branches),r=!0;return u.uniq(n,function(n,i){r=r&&this.compareBranchWithinTrees(e,t,i)},this),r},a.compareBranchesWithinTrees=function(e,t,n){var r=!0;return u.each(n,function(n){r=r&&this.compareBranchWithinTrees(e,t,n)},this),r},a.compareBranchWithinTrees=function(e,t,n){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var r=this.getRecurseCompare(e,t),i=e.branches[n],s=t.branches[n];return u.isEqual(i,s)&&r(e.commits[i.target],t.commits[s.target])},a.compareAllBranchesWithinTreesHashAgnostic=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var n=u.extend({},e.branches,t.branches),r=[];return u.each(n,function(e,t){r.push(t)}),this.compareBranchesWithinTreesHashAgnostic(e,t,r)},a.compareBranchesWithinTreesHashAgnostic=function(e,t,n){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var r=u.bind(function(e,t){return!e||!t?!1:(e=u.clone(e),t=u.clone(t),e.target=this.getBaseRef(e.target),t.target=this.getBaseRef(t.target),u.isEqual(e,t))},this),i=this.getRecurseCompareHashAgnostic(e,t),s=!0;return u.each(n,function(n){var o=e.branches[n],u=t.branches[n];s=s&&r(o,u)&&i(e.commits[o.target],t.commits[u.target])},this),s},a.evalAsserts=function(e,t){var n=!0;return u.each(t,function(t,r){n=n&&this.evalAssertsOnBranch(e,r,t)},this),n},a.evalAssertsOnBranch=function(e,t,n){e=this.convertTreeSafe(e);if(!e.branches[t])return!1;var r=e.branches[t],i=[r.target],s={};while(i.length){var o=i.pop();s[this.getBaseRef(o)]=this.getNumHashes(o),i=i.concat(e.commits[o].parents)}var a=!0;return u.each(n,function(e){try{a=a&&e(s)}catch(t){console.warn("error during assert",t),console.log(t),a=!1}}),a},a.getNumHashes=function(e){var t=[[/^C(\d+)([']{0,3})$/,function(e){return e[2]?e[2].length:0}],[/^C(\d+)['][\^](\d+)$/,function(e){return Number(e[2])}]];for(var n=0;np.VIEWPORT.minWidth&&e.h>p.VIEWPORT.minHeight&&this.finish()}}),O=L.extend({initialize:function(e){if(!e||!e.level)throw new Error("need level");this.eventBatonName="zoomChange",this.markdowns=["## That zoom level of "+e.level+" is not supported :-/","Please zoom back to a supported zoom level with Ctrl + and Ctrl -","","(and of course, pull requests to fix this are appreciated :D)"],O.__super__.initialize.apply(this,[e])},batonFired:function(e){e<=p.VIEWPORT.maxZoom&&e>=p.VIEWPORT.minZoom&&this.finish()}}),M=m.extend({tagName:"div",className:"levelToolbarHolder",template:u.template($("#level-toolbar-template").html()),initialize:function(e){e=e||{},this.JSON={name:e.name||"Some level! (unknown name)"},this.beforeDestination=$($("#commandLineHistory div.toolbar")[0]),this.render(),e.wait||s.nextTick(u.bind(this.show,this))},getAnimationTime:function(){return 700},render:function(){var e=this.template(this.JSON);this.$el.html(e),this.beforeDestination.after(this.el)},die:function(){this.hide(),setTimeout(u.bind(function(){this.tearDown()},this),this.getAnimationTime())},hide:function(){this.$("div.toolbar").toggleClass("hidden",!0)},show:function(){this.$("div.toolbar").toggleClass("hidden",!1)}}),_=m.extend({tagName:"div",className:"helperBar transitionAll",template:u.template($("#helper-bar-template").html()),events:{"click a":"onClick"},onClick:function(e){var t=e.target,n=$(t).attr("data-id"),r="on"+n[0].toUpperCase()+n.slice(1)+"Click";this[r].call(this)},show:function(){this.$el.toggleClass("show",!0)},hide:function(){this.$el.toggleClass("show",!1),this.deferred&&this.deferred.resolve()},getItems:function(){return[]},setupChildren:function(){},fireCommand:function(e){l.getEventBaton().trigger("commandSubmitted",e)},showDeferMe:function(e){this.hide();var t=a.defer();e.deferred=t,t.promise.then(u.bind(function(){this.show()},this)),e.show()},onExitClick:function(){this.hide()},initialize:function(e){e=e||{},this.destination=$("body"),this.JSON={items:this.getItems()},this.render(),this.setupChildren(),e.wait||this.show()}}),D=_.extend({getItems:function(){return[{text:"Git Branching",id:"english"},{text:"日本語版リポジトリ",id:"japanese"},{text:"Git 브랜치 배우기",id:"korean"},{text:"学习Git分支",id:"chinese"},{text:"français",id:"french"},{icon:"signout",id:"exit"}]},fireCommand:function(){h.viewInteracted("intlSelect"),_.prototype.fireCommand.apply(this,arguments)},onJapaneseClick:function(){this.fireCommand("locale ja; levels"),this.hide()},onEnglishClick:function(){this.fireCommand("locale en_US; levels"),this.hide()},onKoreanClick:function(){this.fireCommand("locale ko; levels"),this.hide()},onFrenchClick:function(){this.fireCommand("locale fr_FR; levels"),this.hide()},onChineseClick:function(){this.fireCommand("locale zh_CN; levels"),this.hide()}}),P=_.extend({getItems:function(){return[{text:"Levels",id:"levels"},{text:"Reset",id:"reset"},{text:"Undo",id:"undo"},{text:"Objective",id:"objectve"},{text:"Help",id:"help"},{icon:"signout",id:"exit"}]},fireCommand:function(){h.viewInteracted("helperBar"),_.prototype.fireCommand.apply(this,arguments)},onObjectiveClick:function(){this.fireCommand("objective")},onLevelsClick:function(){this.fireCommand("levels")},onResetClick:function(){this.fireCommand("reset")},onUndoClick:function(){this.fireCommand("undo")},onHelpClick:function(){this.fireCommand("help general; git help")}}),H=_.extend({getItems:function(){return[{icon:"question-sign",id:"commands"},{icon:"globe",id:"intl"}]},onIntlClick:function(){this.showDeferMe(this.intlHelper),h.viewInteracted("openIntlBar")},onCommandsClick:function(){this.showDeferMe(this.commandsHelper),h.viewInteracted("openCommandsBar")},setupChildren:function(){this.commandsHelper=new P({wait:!0}),this.intlHelper=new D({wait:!0})}}),B=m.extend({tagName:"div",className:"canvasTerminalHolder box flex1",template:u.template($("#terminal-window-bare-template").html()),events:{"click div.wrapper":"onClick"},initialize:function(e){e=e||{},this.destination=$("body"),this.JSON={title:e.title||c.str("goal-to-reach"),text:e.text||c.str("hide-goal")},this.render(),this.inDom=!0,e.additionalClass&&this.$el.addClass(e.additionalClass)},getAnimationTime:function(){return 700},onClick:function(){this.die()},die:function(){this.slideOut(),this.inDom=!1,setTimeout(u.bind(function(){this.tearDown()},this),this.getAnimationTime())},slideOut:function(){this.slideToggle(!0)},slideIn:function(){this.slideToggle(!1)},slideToggle:function(e){this.$("div.terminal-window-holder").toggleClass("slideOut",e)},getCanvasLocation:function(){return this.$("div.inside")[0]}});n.BaseView=m,n.GeneralButton=w,n.ModalView=x,n.ModalTerminal=T,n.ModalAlert=N,n.ContainedBase=b,n.ConfirmCancelView=E,n.LeftRightView=S,n.ZoomAlertWindow=O,n.ConfirmCancelTerminal=C,n.WindowSizeAlertWindow=A,n.MainHelperBar=H,n.CanvasTerminalHolder=B,n.LevelToolbar=M,n.NextLevelConfirm=k}),e.define("/src/js/util/keyboard.js",function(e,t,n,r,i,s,o){function c(e){this.events=e.events||u.clone(a.Events),this.aliasMap=e.aliasMap||{},e.wait||this.listen()}var u=e("underscore"),a=e("backbone"),f=e("../app"),l=function(e){var t={37:"left",38:"up",39:"right",40:"down",27:"esc",13:"enter"};return t[e]};c.prototype.listen=function(){if(this.listening)return;this.listening=!0,f.getEventBaton().stealBaton("docKeydown",this.keydown,this)},c.prototype.mute=function(){this.listening=!1,f.getEventBaton().releaseBaton("docKeydown",this.keydown,this)},c.prototype.keydown=function(e){var t=e.which||e.keyCode,n=l(t);if(n===undefined)return;this.fireEvent(n,e)},c.prototype.fireEvent=function(e,t){e=this.aliasMap[e]||e,this.events.trigger(e,t)},c.prototype.passEventBack=function(e){f.getEventBaton().passBatonBackSoft("docKeydown",this.keydown,this,[e])},n.KeyboardListener=c,n.mapKeycodeToKey=l}),e.define("/node_modules/markdown/package.json",function(e,t,n,r,i,s,o){t.exports={main:"./lib/index.js"}}),e.define("/node_modules/markdown/lib/index.js",function(e,t,n,r,i,s,o){n.markdown=e("./markdown"),n.parse=n.markdown.toHTML}),e.define("/node_modules/markdown/lib/markdown.js",function(e,t,n,r,i,s,o){(function(t){function r(){return"Markdown.mk_block( "+uneval(this.toString())+", "+uneval(this.trailing)+", "+uneval(this.lineNumber)+" )"}function i(){var t=e("util");return"Markdown.mk_block( "+t.inspect(this.toString())+", "+t.inspect(this.trailing)+", "+t.inspect(this.lineNumber)+" )"}function o(e){var t=0,n=-1;while((n=e.indexOf("\n",n+1))!==-1)t++;return t}function u(e,t){function i(e){this.len_after=e,this.name="close_"+t}var n=e+"_state",r=e=="strong"?"em_state":"strong_state";return function(s,o){if(this[n][0]==t)return this[n].shift(),[s.length,new i(s.length-t.length)];var u=this[r].slice(),a=this[n].slice();this[n].unshift(t);var f=this.processInline(s.substr(t.length)),l=f[f.length-1],c=this[n].shift();if(l instanceof i){f.pop();var h=s.length-l.len_after;return[h,[e].concat(f)]}return this[r]=u,this[n]=a,[t.length,t]}}function f(e){var t=e.split(""),n=[""],r=!1;while(t.length){var i=t.shift();switch(i){case" ":r?n[n.length-1]+=i:n.push("");break;case"'":case'"':r=!r;break;case"\\":i=t.shift();default:n[n.length-1]+=i}}return n}function h(e){return l(e)&&e.length>1&&typeof e[1]=="object"&&!l(e[1])?e[1]:undefined}function d(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function v(e){if(typeof e=="string")return d(e);var t=e.shift(),n={},r=[];e.length&&typeof e[0]=="object"&&!(e[0]instanceof Array)&&(n=e.shift());while(e.length)r.push(arguments.callee(e.shift()));var i="";for(var s in n)i+=" "+s+'="'+d(n[s])+'"';return t=="img"||t=="br"||t=="hr"?"<"+t+i+"/>":"<"+t+i+">"+r.join("")+""}function m(e,t,n){var r;n=n||{};var i=e.slice(0);typeof n.preprocessTreeNode=="function"&&(i=n.preprocessTreeNode(i,t));var s=h(i);if(s){i[1]={};for(r in s)i[1][r]=s[r];s=i[1]}if(typeof i=="string")return i;switch(i[0]){case"header":i[0]="h"+i[1].level,delete i[1].level;break;case"bulletlist":i[0]="ul";break;case"numberlist":i[0]="ol";break;case"listitem":i[0]="li";break;case"para":i[0]="p";break;case"markdown":i[0]="html",s&&delete s.references;break;case"code_block":i[0]="pre",r=s?2:1;var o=["code"];o.push.apply(o,i.splice(r)),i[r]=o;break;case"inlinecode":i[0]="code";break;case"img":i[1].src=i[1].href,delete i[1].href;break;case"linebreak":i[0]="br";break;case"link":i[0]="a";break;case"link_ref":i[0]="a";var u=t[s.ref];if(!u)return s.original;delete s.ref,s.href=u.href,u.title&&(s.title=u.title),delete s.original;break;case"img_ref":i[0]="img";var u=t[s.ref];if(!u)return s.original;delete s.ref,s.src=u.href,u.title&&(s.title=u.title),delete s.original}r=1;if(s){for(var a in i[1])r=2;r===1&&i.splice(r,1)}for(;r0&&!l(o[0]))&&this.debug(i[s],"didn't return a proper array"),o}return[]},n.prototype.processInline=function(t){return this.dialect.inline.__call__.call(this,String(t))},n.prototype.toTree=function(t,n){var r=t instanceof Array?t:this.split_blocks(t),i=this.tree;try{this.tree=n||this.tree||["markdown"];e:while(r.length){var s=this.processBlock(r.shift(),r);if(!s.length)continue e;this.tree.push.apply(this.tree,s)}return this.tree}finally{n&&(this.tree=i)}},n.prototype.debug=function(){var e=Array.prototype.slice.call(arguments);e.unshift(this.debug_indent),typeof print!="undefined"&&print.apply(print,e),typeof console!="undefined"&&typeof console.log!="undefined"&&console.log.apply(null,e)},n.prototype.loop_re_over_block=function(e,t,n){var r,i=t.valueOf();while(i.length&&(r=e.exec(i))!=null)i=i.substr(r[0].length),n.call(this,r);return i},n.dialects={},n.dialects.Gruber={block:{atxHeader:function(t,n){var r=t.match(/^(#{1,6})\s*(.*?)\s*#*\s*(?:\n|$)/);if(!r)return undefined;var i=["header",{level:r[1].length}];return Array.prototype.push.apply(i,this.processInline(r[2])),r[0].length1&&n.unshift(r);for(var s=0;s1&&typeof i[i.length-1]=="string"?i[i.length-1]+=o:i.push(o)}}function f(e,t){var n=new RegExp("^("+i+"{"+e+"}.*?\\n?)*$"),r=new RegExp("^"+i+"{"+e+"}","gm"),o=[];while(t.length>0){if(n.exec(t[0])){var u=t.shift(),a=u.replace(r,"");o.push(s(a,u.trailing,u.lineNumber))}break}return o}function l(e,t,n){var r=e.list,i=r[r.length-1];if(i[1]instanceof Array&&i[1][0]=="para")return;if(t+1==n.length)i.push(["para"].concat(i.splice(1)));else{var s=i.pop();i.push(["para"].concat(i.splice(1)),s)}}var e="[*+-]|\\d+\\.",t=/[*+-]/,n=/\d+\./,r=new RegExp("^( {0,3})("+e+")[ ]+"),i="(?: {0,3}\\t| {4})";return function(e,n){function s(e){var n=t.exec(e[2])?["bulletlist"]:["numberlist"];return h.push({list:n,indent:e[1]}),n}var i=e.match(r);if(!i)return undefined;var h=[],p=s(i),d,v=!1,m=[h[0].list],g;e:for(;;){var y=e.split(/(?=\n)/),b="";for(var w=0;wh.length)p=s(i),d.push(p),d=p[1]=["listitem"];else{var N=!1;for(g=0;gi[0].length&&(b+=E+S.substr(i[0].length))}b.length&&(a(d,v,this.processInline(b),E),v=!1,b="");var C=f(h.length,n);C.length>0&&(c(h,l,this),d.push.apply(d,this.toTree(C,[])));var k=n[0]&&n[0].valueOf()||"";if(k.match(r)||k.match(/^ /)){e=n.shift();var L=this.dialect.block.horizRule(e,n);if(L){m.push.apply(m,L);break}c(h,l,this),v=!0;continue e}break}return m}}(),blockquote:function(t,n){if(!t.match(/^>/m))return undefined;var r=[];if(t[0]!=">"){var i=t.split(/\n/),s=[];while(i.length&&i[0][0]!=">")s.push(i.shift());t=i.join("\n"),r.push.apply(r,this.processBlock(s.join("\n"),[]))}while(n.length&&n[0][0]==">"){var o=n.shift();t=new String(t+t.trailing+o),t.trailing=o.trailing}var u=t.replace(/^> ?/gm,""),a=this.tree;return r.push(this.toTree(u,["blockquote"])),r},referenceDefn:function(t,n){var r=/^\s*\[(.*?)\]:\s*(\S+)(?:\s+(?:(['"])(.*?)\3|\((.*?)\)))?\n?/;if(!t.match(r))return undefined;h(this.tree)||this.tree.splice(1,0,{});var i=h(this.tree);i.references===undefined&&(i.references={});var o=this.loop_re_over_block(r,t,function(e){e[2]&&e[2][0]=="<"&&e[2][e[2].length-1]==">"&&(e[2]=e[2].substring(1,e[2].length-1));var t=i.references[e[1].toLowerCase()]={href:e[2]};e[4]!==undefined?t.title=e[4]:e[5]!==undefined&&(t.title=e[5])});return o.length&&n.unshift(s(o,t.trailing)),[]},para:function(t,n){return[["para"].concat(this.processInline(t))]}}},n.dialects.Gruber.inline={__oneElement__:function(t,n,r){var i,s,o=0;n=n||this.dialect.inline.__patterns__;var u=new RegExp("([\\s\\S]*?)("+(n.source||n)+")");i=u.exec(t);if(!i)return[t.length,t];if(i[1])return[i[1].length,i[1]];var s;return i[2]in this.dialect.inline&&(s=this.dialect.inline[i[2]].call(this,t.substr(i.index),i,r||[])),s=s||[i[2].length,i[2]],s},__call__:function(t,n){function s(e){typeof e=="string"&&typeof r[r.length-1]=="string"?r[r.length-1]+=e:r.push(e)}var r=[],i;while(t.length>0)i=this.dialect.inline.__oneElement__.call(this,t,n,r),t=t.substr(i.shift()),c(i,s);return r},"]":function(){},"}":function(){},"\\":function(t){return t.match(/^\\[\\`\*_{}\[\]()#\+.!\-]/)?[2,t[1]]:[1,"\\"]},"![":function(t){var n=t.match(/^!\[(.*?)\][ \t]*\([ \t]*(\S*)(?:[ \t]+(["'])(.*?)\3)?[ \t]*\)/);if(n){n[2]&&n[2][0]=="<"&&n[2][n[2].length-1]==">"&&(n[2]=n[2].substring(1,n[2].length-1)),n[2]=this.dialect.inline.__call__.call(this,n[2],/\\/)[0];var r={alt:n[1],href:n[2]||""};return n[4]!==undefined&&(r.title=n[4]),[n[0].length,["img",r]]}return n=t.match(/^!\[(.*?)\][ \t]*\[(.*?)\]/),n?[n[0].length,["img_ref",{alt:n[1],ref:n[2].toLowerCase(),original:n[0]}]]:[2,"!["]},"[":function b(e){var t=String(e),r=n.DialectHelpers.inline_until_char.call(this,e.substr(1),"]");if(!r)return[1,"["];var i=1+r[0],s=r[1],b,o;e=e.substr(i);var u=e.match(/^\s*\([ \t]*(\S+)(?:[ \t]+(["'])(.*?)\2)?[ \t]*\)/);if(u){var a=u[1];i+=u[0].length,a&&a[0]=="<"&&a[a.length-1]==">"&&(a=a.substring(1,a.length-1));if(!u[3]){var f=1;for(var l=0;l]+)|(.*?@.*?\.[a-zA-Z]+))>/))!=null?n[3]?[n[0].length,["link",{href:"mailto:"+n[3]},n[3]]]:n[2]=="mailto"?[n[0].length,["link",{href:n[1]},n[1].substr("mailto:".length)]]:[n[0].length,["link",{href:n[1]},n[1]]]:[1,"<"]},"`":function(t){var n=t.match(/(`+)(([\s\S]*?)\1)/);return n&&n[2]?[n[1].length+n[2].length,["inlinecode",n[3]]]:[1,"`"]}," \n":function(t){return[3,["linebreak"]]}},n.dialects.Gruber.inline["**"]=u("strong","**"),n.dialects.Gruber.inline.__=u("strong","__"),n.dialects.Gruber.inline["*"]=u("em","*"),n.dialects.Gruber.inline._=u("em","_"),n.buildBlockOrder=function(e){var t=[];for(var n in e){if(n=="__order__"||n=="__call__")continue;t.push(n)}e.__order__=t},n.buildInlinePatterns=function(e){var t=[];for(var n in e){if(n.match(/^__.*__$/))continue;var r=n.replace(/([\\.*+?|()\[\]{}])/g,"\\$1").replace(/\n/,"\\n");t.push(n.length==1?r:"(?:"+r+")")}t=t.join("|"),e.__patterns__=t;var i=e.__call__;e.__call__=function(e,n){return n!=undefined?i.call(this,e,n):i.call(this,e,t)}},n.DialectHelpers={},n.DialectHelpers.inline_until_char=function(e,t){var n=0,r=[];for(;;){if(e[n]==t)return n++,[n,r];if(n>=e.length)return null;res=this.dialect.inline.__oneElement__.call(this,e.substr(n)),n+=res[0],r.push.apply(r,res.slice(1))}},n.subclassDialect=function(e){function t(){}function n(){}return t.prototype=e.block,n.prototype=e.inline,{block:new t,inline:new n}},n.buildBlockOrder(n.dialects.Gruber.block),n.buildInlinePatterns(n.dialects.Gruber.inline),n.dialects.Maruku=n.subclassDialect(n.dialects.Gruber),n.dialects.Maruku.processMetaHash=function(t){var n=f(t),r={};for(var i=0;i1)return undefined;if(!t.match(/^(?:\w+:.*\n)*\w+:.*$/))return undefined;h(this.tree)||this.tree.splice(1,0,{});var r=t.split(/\n/);for(p in r){var i=r[p].match(/(\w+):\s*(.*)$/),s=i[1].toLowerCase(),o=i[2];this.tree[1][s]=o}return[]},n.dialects.Maruku.block.block_meta=function(t,n){var r=t.match(/(^|\n) {0,3}\{:\s*((?:\\\}|[^\}])*)\s*\}$/);if(!r)return undefined;var i=this.dialect.processMetaHash(r[2]),s;if(r[1]===""){var o=this.tree[this.tree.length-1];s=h(o);if(typeof o=="string")return undefined;s||(s={},o.splice(1,0,s));for(a in i)s[a]=i[a];return[]}var u=t.replace(/\n.*$/,""),f=this.processBlock(u,[]);s=h(f[0]),s||(s={},f[0].splice(1,0,s));for(a in i)s[a]=i[a];return f},n.dialects.Maruku.block.definition_list=function(t,n){var r=/^((?:[^\s:].*\n)+):\s+([\s\S]+)$/,i=["dl"],s;if(!(a=t.match(r)))return undefined;var o=[t];while(n.length&&r.exec(n[0]))o.push(n.shift());for(var u=0;u-1&&(a(e)?i=i.split("\n").map(function(e){return" "+e}).join("\n").substr(2):i="\n"+i.split("\n").map(function(e){return" "+e}).join("\n"))):i=o("[Circular]","special"));if(typeof n=="undefined"){if(g==="Array"&&t.match(/^\d+$/))return i;n=JSON.stringify(""+t),n.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(n=n.substr(1,n.length-2),n=o(n,"name")):(n=n.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),n=o(n,"string"))}return n+": "+i});s.pop();var E=0,S=w.reduce(function(e,t){return E++,t.indexOf("\n")>=0&&E++,e+t.length+1},0);return S>50?w=y[0]+(m===""?"":m+"\n ")+" "+w.join(",\n ")+" "+y[1]:w=y[0]+m+" "+w.join(", ")+" "+y[1],w}var s=[],o=function(e,t){var n={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},r={special:"cyan",number:"blue","boolean":"yellow","undefined":"grey","null":"bold",string:"green",date:"magenta",regexp:"red"}[t];return r?"["+n[r][0]+"m"+e+"["+n[r][1]+"m":e};return i||(o=function(e,t){return e}),u(e,typeof r=="undefined"?2:r)};var h=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];n.log=function(e){},n.pump=null;var d=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t},v=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.hasOwnProperty.call(e,n)&&t.push(n);return t},m=Object.create||function(e,t){var n;if(e===null)n={__proto__:null};else{if(typeof e!="object")throw new TypeError("typeof prototype["+typeof e+"] != 'object'");var r=function(){};r.prototype=e,n=new r,n.__proto__=e}return typeof t!="undefined"&&Object.defineProperties&&Object.defineProperties(n,t),n};n.inherits=function(e,t){e.super_=t,e.prototype=m(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})};var g=/%[sdj%]/g;n.format=function(e){if(typeof e!="string"){var t=[];for(var r=0;r=s)return e;switch(e){case"%s":return String(i[r++]);case"%d":return Number(i[r++]);case"%j":return JSON.stringify(i[r++]);default:return e}});for(var u=i[r];r0&&this._events[e].length>n&&(this._events[e].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[e].length),console.trace())}this._events[e].push(t)}else this._events[e]=[this._events[e],t];return this},u.prototype.on=u.prototype.addListener,u.prototype.once=function(e,t){var n=this;return n.on(e,function r(){n.removeListener(e,r),t.apply(this,arguments)}),this},u.prototype.removeListener=function(e,t){if("function"!=typeof t)throw new Error("removeListener only takes instances of Function");if(!this._events||!this._events[e])return this;var n=this._events[e];if(a(n)){var r=f(n,t);if(r<0)return this;n.splice(r,1),n.length==0&&delete this._events[e]}else this._events[e]===t&&delete this._events[e];return this},u.prototype.removeAllListeners=function(e){return e&&this._events&&this._events[e]&&(this._events[e]=null),this},u.prototype.listeners=function(e){return this._events||(this._events={}),this._events[e]||(this._events[e]=[]),a(this._events[e])||(this._events[e]=[this._events[e]]),this._events[e]}}),e.define("/src/js/dialogs/nextLevel.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Great Job!!","","You solved the level in *{numCommands}* command(s); ","our solution uses {best}."]}}],ja:[{type:"ModalAlert",options:{markdowns:["## 完成!","","あなたは*{numCommands}*回のコマンドでこの課題をクリアしました; ","模範解答では{best}回です。"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 碉堡了!","","你用 *{numCommands}* 条命令搞定了这一关;我们的答案要用 {best}。"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Beau Travail!!","","Vous avez résolu le niveau en *{numCommands}* commande(s); ","notre solution le fait en {best}."]}}]}}),e.define("/src/js/models/commandModel.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../util/errors"),l=e("../git/commands"),c=l.GitOptionParser,h=e("../level/parseWaterfall").ParseWaterfall,p=f.CommandProcessError,d=f.GitError,v=f.Warning,m=f.CommandResult,g=a.Model.extend({defaults:{status:"inqueue",rawStr:null,result:"",createTime:null,error:null,warnings:null,parseWaterfall:new h,generalArgs:null,supportedMap:null,options:null,method:null},initialize:function(e){this.initDefaults(),this.validateAtInit(),this.on("change:error",this.errorChanged,this),this.get("error")&&this.errorChanged(),this.parseOrCatch()},initDefaults:function(){this.set("generalArgs",[]),this.set("supportedMap",{}),this.set("warnings",[])},validateAtInit:function(){if(this.get("rawStr")===null)throw new Error("Give me a string!");this.get("createTime")||this.set("createTime",(new Date).toString())},setResult:function(e){this.set("result",e)},finishWith:function(e){this.set("status","finished"),e.resolve()},addWarning:function(e){this.get("warnings").push(e),this.set("numWarnings",this.get("numWarnings")?this.get("numWarnings")+1:1)},getFormattedWarnings:function(){if(!this.get("warnings").length)return"";var e='';return"

"+e+this.get("warnings").join("

"+e)+"

"},parseOrCatch:function(){this.expandShortcuts(this.get("rawStr"));try{this.processInstants()}catch(e){f.filterError(e),this.set("error",e);return}if(this.parseAll())return;this.set("error",new p({msg:'The command "'+this.get("rawStr")+"\" isn't supported, sorry!"}))},errorChanged:function(){var e=this.get("error");e instanceof p||e instanceof d?this.set("status","error"):e instanceof m?this.set("status","finished"):e instanceof v&&this.set("status","warning"),this.formatError()},formatError:function(){this.set("result",this.get("error").toResult())},expandShortcuts:function(e){e=this.get("parseWaterfall").expandAllShortcuts(e),this.set("rawStr",e)},processInstants:function(){var e=this.get("rawStr");if(!e.length)throw new m({msg:""});this.get("parseWaterfall").processAllInstants(e)},parseAll:function(){var e=this.get("rawStr"),t=this.get("parseWaterfall").parseAll(e);return t?(u.each(t.toSet,function(e,t){this.set(t,e)},this),!0):!1}}),y=a.Model.extend({defaults:{text:""}});n.CommandEntry=y,n.Command=g}),e.define("/src/js/git/commands.js",function(e,t,n,r,i,s,o){function y(e,t){this.method=e,this.rawOptions=t,this.supportedMap=this.getMasterOptionMap()[e];if(this.supportedMap===undefined)throw new Error("No option map for "+e);this.generalArgs=[],this.explodeAndSet()}var u=e("underscore"),a=e("../intl"),f=e("../util/errors"),l=f.CommandProcessError,c=f.GitError,h=f.Warning,p=f.CommandResult,d={"git commit":/^(gc|git ci)($|\s)/,"git add":/^ga($|\s)/,"git checkout":/^(go|git co)($|\s)/,"git rebase":/^gr($|\s)/,"git branch":/^(gb|git br)($|\s)/,"git status":/^(gst|gs|git st)($|\s)/,"git help":/^git$/},v=[[/^git help($|\s)/,function(){var e=[a.str("git-version"),"
",a.str("git-usage"),u.escape(a.str("git-usage-command")),"
",a.str("git-supported-commands"),"
"],t=y.prototype.getMasterOptionMap();u.each(t,function(t,n){e.push("git "+n),u.each(t,function(t,n){e.push(" "+n)},this)},this);var n=e.join("\n");throw n=n.replace(/\t/g,"   "),new p({msg:n})}]],m={"git commit":/^git +commit($|\s)/,"git add":/^git +add($|\s)/,"git checkout":/^git +checkout($|\s)/,"git rebase":/^git +rebase($|\s)/,"git reset":/^git +reset($|\s)/,"git branch":/^git +branch($|\s)/,"git revert":/^git +revert($|\s)/,"git log":/^git +log($|\s)/,"git merge":/^git +merge($|\s)/,"git show":/^git +show($|\s)/,"git status":/^git +status($|\s)/,"git cherry-pick":/^git +cherry-pick($|\s)/,"git fakeTeamwork":/^git +fakeTeamwork($|\s)/,"git fetch":/^git +fetch *?$/,"git pull":/^git +pull($|\s)/,"git push":/^git +push($|\s)/,"git clone":/^git +clone *?$/},g=function(e){var t,n;u.each(m,function(r,i){r.exec(e)&&(n=e.slice(i.length+1),t=i.slice("git ".length))});if(!t)return!1;var r=new y(t,n);return{toSet:{generalArgs:r.generalArgs,supportedMap:r.supportedMap,method:t,options:n,eventName:"processGitCommand"}}};y.prototype.getMasterOptionMap=function(){return{commit:{"--amend":!1,"-a":!1,"-am":!1,"-m":!1},status:{},log:{},add:{},"cherry-pick":{},branch:{"-d":!1,"-D":!1,"-f":!1,"-a":!1,"-r":!1,"--contains":!1},checkout:{"-b":!1,"-B":!1,"-":!1},reset:{"--hard":!1,"--soft":!1},merge:{},rebase:{"-i":!1},revert:{},show:{},clone:{},fetch:{},pull:{"--rebase":!1},push:{},fakeTeamwork:{}}},y.prototype.explodeAndSet=function(){var e=this.rawOptions.match(/('.*?'|".*?"|\S+)/g)||[];for(var t=0;t","show commands","show solution","show goal"];throw new v({msg:t.join("\n")})}],[/^locale (\w+)$/,function(t){f.GLOBAL.locale=t[1];var n=e("../app").getEvents().trigger("localeChanged");throw new v({msg:l.str("locale-command",{locale:t[1]})})}],[/^refresh$/,function(){var t=e("../app").getEvents();throw t.trigger("refreshTree"),new v({msg:l.str("refresh-tree-command")})}],[/^rollup (\d+)$/,function(t){var n=e("../app").getEvents();throw n.trigger("rollupCommands",t[1]),new v({msg:"Commands combined!"})}],[/^echo "(.*?)"$|^echo (.*?)$/,function(e){var t=e[1]||e[2];throw new v({msg:t})}],[/^show +commands$/,function(e){var t=y(),n=[l.str("show-all-commands"),"
"];throw u.each(t,function(e,t){n.push(t)}),new v({msg:n.join("\n")})}]],g={"reset solved":/^reset solved($|\s)/,help:/^help( +general)?$|^\?$/,reset:/^reset( +--forSolution)?$/,delay:/^delay (\d+)$/,clear:/^clear($|\s)/,"exit level":/^exit level($|\s)/,sandbox:/^sandbox($|\s)/,level:/^level\s?([a-zA-Z0-9]*)/,levels:/^levels($|\s)/,mobileAlert:/^mobile alert($|\s)/,"build level":/^build +level($|\s)/,"export tree":/^export +tree$/,"import tree":/^import +tree$/,"import level":/^import +level$/,undo:/^undo($|\s)/},y=function(){var t=["mobileAlert"],n=u.extend({},e("../git/commands").regexMap,e("../level").regexMap,g);return u.each(t,function(e){delete n[e]}),n};n.instantCommands=m,n.parse=a.genParseCommand(g,"processSandboxCommand"),n.getOptimisticLevelParse=function(){return a.genParseCommand(e("../level").regexMap,"processLevelCommand")},n.getOptimisticLevelBuilderParse=function(){return a.genParseCommand(e("../level/builder").regexMap,"processLevelBuilderCommand")}}),e.define("/src/js/level/builder.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("../util"),c=e("../app"),h=e("../intl"),p=e("../util/errors"),d=e("../visuals/visualization").Visualization,v=e("../level/parseWaterfall").ParseWaterfall,m=e("../level").Level,g=e("../models/commandModel").Command,y=e("../git/gitShim").GitShim,b=e("../views/multiView").MultiView,w=e("../views").CanvasTerminalHolder,E=e("../views").ConfirmCancelTerminal,S=e("../views").NextLevelConfirm,x=e("../views").LevelToolbar,T=e("../views/builderViews").MarkdownPresenter,N=e("../views/builderViews").MultiViewBuilder,C=e("../views/builderViews").MarkdownGrabber,k={"define goal":/^define goal$/,"define name":/^define name$/,"help builder":/^help builder$/,"define start":/^define start$/,"edit dialog":/^edit dialog$/,"show start":/^show start$/,"hide start":/^hide start$/,"define hint":/^define hint$/,finish:/^finish$/},L=l.genParseCommand(k,"processLevelBuilderCommand"),A=m.extend({initialize:function(t){t=t||{},t.level=t.level||{};var n=h.getLocale();t.level.startDialog={},t.level.startDialog[n]={childViews:h.getDialog(e("../dialogs/levelBuilder"))},A.__super__.initialize.apply(this,[t]),this.startDialogObj=undefined,this.definedGoal=!1,delete this.treeCompare,delete this.solved},initName:function(){this.levelToolbar=new x({name:h.str("level-builder")})},initGoalData:function(){this.level.goalTreeString='{"branches":{"master":{"target":"C1","id":"master"},"makeLevel":{"target":"C2","id":"makeLevel"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"}},"HEAD":{"target":"makeLevel","id":"HEAD"}}',this.level.solutionCommand="git checkout -b makeLevel; git commit",A.__super__.initGoalData.apply(this,arguments)},initStartVisualization:function(){return this.startCanvasHolder=new w({additionalClass:"startTree",text:h.str("hide-start")}),this.startVis=new d({el:this.startCanvasHolder.getCanvasLocation(),containerElement:this.startCanvasHolder.getCanvasLocation(),treeString:this.level.startTree,noKeyboardInput:!0,smallCanvas:!0,noClick:!0}),this.startCanvasHolder},startOffCommand:function(){c.getEventBaton().trigger("commandSubmitted","echo :D")},objectiveDialog:function(e,t){var n=[e,t,this.startDialogObj===undefined?null:{startDialog:{en_US:this.startDialogObj}}];A.__super__.objectiveDialog.apply(this,n)},initParseWaterfall:function(e){A.__super__.initParseWaterfall.apply(this,[e]),this.parseWaterfall.addFirst("parseWaterfall",L),this.parseWaterfall.addFirst("instantWaterfall",this.getInstantCommands())},buildLevel:function(e,t){this.exitLevel(),setTimeout(function(){c.getSandbox().buildLevel(e,t)},this.getAnimationTime()*1.5)},getInstantCommands:function(){return[[/^help$|^\?$/,function(){throw new p.CommandResult({msg:h.str("help-vague-builder")})}]]},takeControl:function(){c.getEventBaton().stealBaton("processLevelBuilderCommand",this.processLevelBuilderCommand,this),A.__super__.takeControl.apply(this)},releaseControl:function(){c.getEventBaton().releaseBaton("processLevelBuilderCommand",this.processLevelBuilderCommand,this),A.__super__.releaseControl.apply(this)},showGoal:function(){this.hideStart(),A.__super__.showGoal.apply(this,arguments)},showStart:function(e,t){this.hideGoal(),this.showSideVis(e,t,this.startCanvasHolder,this.initStartVisualization)},resetSolution:function(){this.gitCommandsIssued=[],this.level.solutionCommand=undefined},hideStart:function(e,t){this.hideSideVis(e,t,this.startCanvasHolder)},defineStart:function(e,t){this.hideStart(),e.addWarning(h.str("define-start-warning")),this.resetSolution(),this.level.startTree=this.mainVis.gitEngine.printTree(),this.mainVis.resetFromThisTreeNow(this.level.startTree),this.showStart(e,t)},defineGoal:function(e,t){this.hideGoal();if(!this.gitCommandsIssued.length){e.set("error",new p.GitError({msg:h.str("solution-empty")})),t.resolve();return}this.definedGoal=!0,this.level.solutionCommand=this.gitCommandsIssued.join(";"),this.level.goalTreeString=this.mainVis.gitEngine.printTree(),this.initGoalVisualization(),this.showGoal(e,t)},defineName:function(e,t){this.level.name={en_US:prompt(h.str("prompt-name"))},e&&e.finishWith(t)},defineHint:function(e,t){this.level.hint={en_US:prompt(h.str("prompt-hint"))},e&&e.finishWith(t)},editDialog:function(e,t){var n=f.defer();this.currentBuilder=new N({multiViewJSON:this.startDialogObj,deferred:n}),n.promise.then(u.bind(function(e){this.startDialogObj=e},this)).fail(function(){}).done(function(){e?e.finishWith(t):t.resolve()})},finish:function(e,t){if(!this.gitCommandsIssued.length||!this.definedGoal){e.set("error",new p.GitError({msg:h.str("solution-empty")})),t.resolve();return}while(!this.level.name)this.defineName();var n=f.defer(),r=n.promise;if(this.level.hint===undefined){var i=f.defer();r=r.then(function(){return i.promise});var s=new E({markdowns:[h.str("want-hint")]});s.getPromise().then(u.bind(this.defineHint,this)).fail(u.bind(function(){this.level.hint={en_US:""}},this)).done(function(){i.resolve()})}if(this.startDialogObj===undefined){var o=f.defer();r=r.then(function(){return o.promise});var a=new E({markdowns:[h.str("want-start-dialog")]});a.getPromise().then(u.bind(function(){var e=f.defer();return this.editDialog(undefined,e),e.promise},this)).fail(function(){}).done(function(){o.resolve()})}r=r.done(u.bind(function(){new T({fillerText:JSON.stringify(this.getExportObj(),null,2),previewText:h.str("share-json")}),e.finishWith(t)},this)),n.resolve()},getExportObj:function(){var e=u.extend({},this.level);return delete e.startDialog,this.startDialogObj&&(e.startDialog={en_US:this.startDialogObj}),e},processLevelBuilderCommand:function(e,t){var n={"define goal":this.defineGoal,"define start":this.defineStart,"show start":this.showStart,"hide start":this.hideStart,finish:this.finish,"define hint":this.defineHint,"define name":this.defineName,"edit dialog":this.editDialog,"help builder":A.__super__.startDialog};if(!n[e.get("method")])throw new Error("woah we dont support that method yet");n[e.get("method")].apply(this,arguments)},afterCommandDefer:function(e,t){e.resolve()},die:function(){this.hideStart(),A.__super__.die.apply(this,arguments),delete this.startVis,delete this.startCanvasHolder}});n.LevelBuilder=A,n.regexMap=k}),e.define("/src/js/git/gitShim.js",function(e,t,n,r,i,s,o){function c(e){e=e||{},this.beforeCB=e.beforeCB||function(){},this.afterCB=e.afterCB||function(){};var t=function(e){e.resolve()};this.beforeDeferHandler=e.beforeDeferHandler||t,this.afterDeferHandler=e.afterDeferHandler||t,this.eventBaton=e.eventBaton||f.getEventBaton()}var u=e("underscore"),a=e("q"),f=e("../app"),l=e("../views/multiView").MultiView;c.prototype.insertShim=function(){this.eventBaton.stealBaton("processGitCommand",this.processGitCommand,this)},c.prototype.removeShim=function(){this.eventBaton.releaseBaton("processGitCommand",this.processGitCommand,this)},c.prototype.processGitCommand=function(e,t){this.beforeCB(e);var n=a.defer();n.promise.then(u.bind(function(){this.afterGitCommandProcessed(e,t)},this)).done();var r=u.bind(function(){this.eventBaton.passBatonBack("processGitCommand",this.processGitCommand,this,[e,n])},this),i=a.defer();i.promise.then(r).done(),this.beforeDeferHandler(i,e)},c.prototype.afterGitCommandProcessed=function(e,t){this.afterCB(e);var n=a.defer();n.promise.then(function(){t.resolve()}).done(),this.afterDeferHandler(n,e)},n.GitShim=c}),e.define("/src/js/views/multiView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../views").ModalTerminal,c=e("../views").ContainedBase,h=e("../views").ConfirmCancelView,p=e("../views").LeftRightView,d=e("../views").ModalAlert,v=e("../views/gitDemonstrationView").GitDemonstrationView,m=e("../views/builderViews"),g=m.MarkdownPresenter,y=e("../util/keyboard").KeyboardListener,b=e("../util/errors").GitError,w=f.View.extend({tagName:"div",className:"multiView",navEventDebounce:550,deathTime:700,typeToConstructor:{ModalAlert:d,GitDemonstrationView:v,MarkdownPresenter:g},initialize:function(e){e=e||{},this.childViewJSONs=e.childViews||[{type:"ModalAlert",options:{markdown:"Woah wtf!!"}},{type:"GitDemonstrationView",options:{command:"git checkout -b side; git commit; git commit"}},{type:"ModalAlert",options:{markdown:"Im second"}}],this.deferred=e.deferred||a.defer(),this.childViews=[],this.currentIndex=0,this.navEvents=u.clone(f.Events),this.navEvents.on("negative",this.getNegFunc(),this),this.navEvents.on("positive",this.getPosFunc(),this),this.navEvents.on("quit",this.finish,this),this.navEvents.on("exit",this.finish,this),this.keyboardListener=new y({events:this.navEvents,aliasMap:{left:"negative",right:"positive",enter:"positive",esc:"quit"}}),this.render(),e.wait||this.start()},onWindowFocus:function(){},getAnimationTime:function(){return 700},getPromise:function(){return this.deferred.promise},getPosFunc:function(){return u.debounce(u.bind(function(){this.navForward()},this),this.navEventDebounce,!0)},getNegFunc:function(){return u.debounce(u.bind(function(){this.navBackward()},this),this.navEventDebounce,!0)},lock:function(){this.locked=!0},unlock:function(){this.locked=!1},navForward:function(){if(this.locked)return;if(this.currentIndex===this.childViews.length-1){this.hideViewIndex(this.currentIndex),this.finish();return}this.navIndexChange(1)},navBackward:function(){if(this.currentIndex===0)return;this.navIndexChange(-1)},navIndexChange:function(e){this.hideViewIndex(this.currentIndex),this.currentIndex+=e,this.showViewIndex(this.currentIndex)},hideViewIndex:function(e){this.childViews[e].hide()},showViewIndex:function(e){this.childViews[e].show()},finish:function(){this.keyboardListener.mute(),u.each(this.childViews,function(e){e.die()}),this.deferred.resolve()},start:function(){this.showViewIndex(this.currentIndex)},createChildView:function(e){var t=e.type;if(!this.typeToConstructor[t])throw new Error('no constructor for type "'+t+'"');var n=new this.typeToConstructor[t](u.extend({},e.options,{wait:!0}));return n},addNavToView:function(e,t){var n=new p({events:this.navEvents,destination:e.getDestination(),showLeft:t!==0,lastNav:t===this.childViewJSONs.length-1});e.receiveMetaNav&&e.receiveMetaNav(n,this)},render:function(){u.each(this.childViewJSONs,function(e,t){var n=this.createChildView(e);this.childViews.push(n),this.addNavToView(n,t)},this)}});n.MultiView=w}),e.define("/src/js/views/gitDemonstrationView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../util/keyboard").KeyboardListener,h=e("../models/commandModel").Command,p=e("../views").ModalTerminal,d=e("../views").ContainedBase,v=e("../visuals/visualization").Visualization,m=d.extend({tagName:"div",className:"gitDemonstrationView box horizontal",template:u.template($("#git-demonstration-view").html()),events:{"click div.command > p.uiButton":"positive"},initialize:function(t){t=t||{},this.options=t,this.JSON=u.extend({beforeMarkdowns:["## Git Commits","","Awesome!"],command:"git commit",afterMarkdowns:["Now you have seen it in action","","Go ahead and try the level!"]},t);var n=function(t){return e("markdown").markdown.toHTML(t.join("\n"))};this.JSON.beforeHTML=n(this.JSON.beforeMarkdowns),this.JSON.afterHTML=n(this.JSON.afterMarkdowns),this.container=new p({title:t.title||"Git Demonstration"}),this.render(),this.checkScroll(),this.navEvents=u.clone(f.Events),this.navEvents.on("positive",this.positive,this),this.navEvents.on("negative",this.negative,this),this.keyboardListener=new c({events:this.navEvents,aliasMap:{enter:"positive",right:"positive",left:"negative"},wait:!0}),this.visFinished=!1,this.initVis(),t.wait||this.show()},receiveMetaNav:function(e,t){var n=this;e.navEvents.on("positive",this.positive,this),this.metaContainerView=t},checkScroll:function(){var e=this.$("div.demonstrationText").children(),t=u.map(e,function(e){return e.clientHeight}),n=u.reduce(t,function(e,t){return e+t});n15&&console.warn("graphics are degrading from too many layers");var t=this.getDepthIncrement(e);u.each(this.visNodeMap,function(e){e.setDepthBasedOn(t,this.getHeaderOffset())},this)},w.prototype.animateNodePositions=function(e){u.each(this.visNodeMap,function(t){t.animateUpdatedPosition(e)},this)},w.prototype.addBranchFromEvent=function(e,t,n){var r=u.bind(function(){this.addBranch(e)},this);!this.gitEngine||!this.gitReady?this.defer(r):r()},w.prototype.addBranch=function(e){var t=new m({branch:e,gitVisuals:this,gitEngine:this.gitEngine});this.visBranchCollection.add(t),this.gitReady?t.genGraphics(this.paper):this.defer(u.bind(function(){t.genGraphics(this.paper)},this))},w.prototype.removeVisBranch=function(e){this.visBranchCollection.remove(e)},w.prototype.removeVisNode=function(e){this.visNodeMap[e.getID()]=undefined},w.prototype.removeVisEdge=function(e){this.visEdgeCollection.remove(e)},w.prototype.animateRefs=function(e){this.visBranchCollection.each(function(t){t.animateUpdatedPos(e)},this)},w.prototype.animateEdges=function(e){this.visEdgeCollection.each(function(t){t.animateUpdatedPath(e)},this)},w.prototype.getMinLayers=function(){return this.options.smallCanvas?2:7},w.prototype.getDepthIncrement=function(e){e=Math.max(e,this.getMinLayers());var t=1-this.getHeaderOffset(),n=t/e;return n},w.prototype.shouldHaveHeader=function(){return this.gitEngine.isOrigin()||this.gitEngine.hasOrigin()},w.prototype.getHeaderOffset=function(){return this.shouldHaveHeader()?.05:0},w.prototype.calcDepthRecursive=function(e,t){e.get("visNode").setDepth(t);var n=e.get("children"),r=t;return u.each(n,function(e){var n=this.calcDepthRecursive(e,t+1);r=Math.max(n,r)},this),r},w.prototype.canvasResize=function(e,t){this.resizeFunc||this.genResizeFunc(),this.resizeFunc(e,t)},w.prototype.genResizeFunc=function(){this.resizeFunc=u.debounce(u.bind(function(t,n){this.refreshTree()},this),200,!0)},w.prototype.addNode=function(e,t){this.commitMap[e]=t,t.get("rootCommit")&&(this.rootCommit=t);var n=new v({id:e,commit:t,gitVisuals:this,gitEngine:this.gitEngine});return this.visNodeMap[e]=n,this.gitReady&&n.genGraphics(this.paper),n},w.prototype.addEdge=function(e,t){var n=this.visNodeMap[e],r=this.visNodeMap[t];if(!n||!r)throw new Error("one of the ids in ("+e+", "+t+") does not exist");var i=new y({tail:n,head:r,gitVisuals:this,gitEngine:this.gitEngine});this.visEdgeCollection.add(i),this.gitReady&&i.genGraphics(this.paper)},w.prototype.zIndexReflow=function(){this.visNodesFront(),this.visBranchesFront()},w.prototype.visNodesFront=function(){u.each(this.visNodeMap,function(e){e.toFront()})},w.prototype.visBranchesFront=function(){this.visBranchCollection.each(function(e){e.nonTextToFront(),e.textToFront()}),this.visBranchCollection.each(function(e){e.textToFrontIfInStack()})},w.prototype.drawTreeFromReload=function(){this.gitReady=!0,this.deferFlush(),this.calcTreeCoords()},w.prototype.drawTreeFirstTime=function(){this.gitReady=!0,this.calcTreeCoords(),u.each(this.visNodeMap,function(e){e.genGraphics(this.paper)},this),this.visEdgeCollection.each(function(e){e.genGraphics(this.paper)},this),this.visBranchCollection.each(function(e){e.genGraphics(this.paper)},this),this.zIndexReflow()},n.GitVisuals=w}),e.define("/src/js/visuals/visNode.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=l.extend({defaults:{depth:undefined,maxWidth:null,outgoingEdges:null,circle:null,text:null,id:null,pos:null,radius:null,commit:null,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing,fill:f.defaultNodeFill,"stroke-width":f.defaultNodeStrokeWidth,stroke:f.defaultNodeStroke},getID:function(){return this.get("id")},validateAtInit:function(){if(!this.get("id"))throw new Error("need id for mapping");if(!this.get("commit"))throw new Error("need commit for linking");this.get("pos")||this.set("pos",{x:Math.random(),y:Math.random()})},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine"),this.set("outgoingEdges",[])},setDepth:function(e){this.set("depth",Math.max(this.get("depth")||0,e))},setDepthBasedOn:function(e,t){if(this.get("depth")===undefined)throw new Error("no depth yet!");var n=this.get("pos");n.y=this.get("depth")*e+t},getMaxWidthScaled:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("commit")),t={branch:1,head:.3,none:.1};if(t[e]===undefined)throw new Error("bad stat");return t[e]*this.get("maxWidth")},toFront:function(){this.get("circle").toFront(),this.get("text").toFront()},getOpacity:function(){var e={branch:1,head:f.upstreamHeadOpacity,none:f.upstreamNoneOpacity},t=this.gitVisuals.getCommitUpstreamStatus(this.get("commit"));if(e[t]===undefined)throw new Error("invalid status");return e[t]},getTextScreenCoords:function(){return this.getScreenCoords()},getAttributes:function(){var e=this.getScreenCoords(),t=this.getTextScreenCoords(),n=this.getOpacity(),r=this.getIsInOrigin()?f.originDash:"";return{circle:{cx:e.x,cy:e.y,opacity:n,r:this.getRadius(),fill:this.getFill(),"stroke-width":this.get("stroke-width"),"stroke-dasharray":r,stroke:this.get("stroke")},text:{x:t.x,y:t.y,opacity:n}}},highlightTo:function(e,t,n){var r=e.get("fill"),i={circle:{fill:r,stroke:r,"stroke-dasharray":"","stroke-width":this.get("stroke-width")*5},text:{}};this.animateToAttr(i,t,n)},animateUpdatedPosition:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},animateToSnapshot:function(e,t,n){if(!e[this.getID()])return;this.animateToAttr(e[this.getID()],t,n)},setAttr:function(e,t,n,r){var i=["text","circle"];this.setAttrBase(i,e,t,n,r)},animateToAttr:function(e,t,n){l.prototype.animateToAttr.apply(this,arguments);var r=t!==undefined?t:this.get("animationSpeed"),i=n||this.get("animationEasing");n=="bounce"&&e.circle&&e.circle.cx!==undefined&&e.text&&e.text.x!==undefined&&(this.get("circle").animate(e.circle.cx,r,"easeInOut"),this.get("text").animate(e.text.x,r,"easeInOut"))},getScreenCoords:function(){var e=this.get("pos");return this.gitVisuals.toScreenCoords(e)},getRadius:function(){return this.get("radius")||f.nodeRadius},getParentScreenCoords:function(){return this.get("commit").get("parents")[0].get("visNode").getScreenCoords()},setBirthPosition:function(){var e=this.getParentScreenCoords();this.get("circle").attr({cx:e.x,cy:e.y,opacity:0,r:0}),this.get("text").attr({x:e.x,y:e.y,opacity:0})},setBirthFromSnapshot:function(e){var t=this.get("commit").get("parents")[0].get("visNode").getID(),n=e[t];this.get("circle").attr({opacity:0,r:0,cx:n.circle.cx,cy:n.circle.cy}),this.get("text").attr({opacity:0,x:n.text.x,y:n.text.y});var r={x:n.circle.cx,y:n.circle.cy};this.setOutgoingEdgesBirthPosition(r)},setBirth:function(){this.setBirthPosition(),this.setOutgoingEdgesBirthPosition(this.getParentScreenCoords())},setOutgoingEdgesOpacity:function(e){u.each(this.get("outgoingEdges"),function(t){t.setOpacity(e)})},animateOutgoingEdgesToAttr:function(e,t,n){u.each(this.get("outgoingEdges"),function(t){var n=e[t.getID()];t.animateToAttr(n)},this)},animateOutgoingEdges:function(e,t){u.each(this.get("outgoingEdges"),function(n){n.animateUpdatedPath(e,t)},this)},animateOutgoingEdgesFromSnapshot:function(e,t,n){u.each(this.get("outgoingEdges"),function(r){var i=e[r.getID()];r.animateToAttr(i,t,n)},this)},setOutgoingEdgesBirthPosition:function(e){u.each(this.get("outgoingEdges"),function(t){var n=t.get("head").getScreenCoords(),r=t.genSmoothBezierPathStringFromCoords(e,n);t.get("path").stop(),t.get("path").attr({path:r,opacity:0})},this)},parentInFront:function(){this.get("commit").get("parents")[0].get("visNode").toFront()},getFontSize:function(e){return e.length<3?12:e.length<5?10:8},getFill:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("commit"));return e=="head"?f.headRectFill:e=="none"?f.orphanNodeFill:this.gitVisuals.getBlendedHuesForCommit(this.get("commit"))},attachClickHandlers:function(){if(this.get("gitVisuals").options.noClick)return;var t="git checkout "+this.get("commit").get("id"),n=e("../app");u.each([this.get("circle"),this.get("text")],function(e){e.click(function(){n.getEventBaton().trigger("commandSubmitted",t)}),$(e.node).css("cursor","pointer")})},setOpacity:function(e){e=e===undefined?1:e;var t=["circle","text"];u.each(t,function(t){this.get(t).attr({opacity:e})},this)},remove:function(){this.removeKeys(["circle"],["text"]);var e=this.get("text");e&&e.remove(),this.gitVisuals.removeVisNode(this)},removeAll:function(){this.remove(),u.each(this.get("outgoingEdges"),function(e){e.remove()},this)},getExplodeStepFunc:function(){var e=this.get("circle"),t=20,n=Math.PI+Math.random()*1*Math.PI,r=.2,i=.01,s=t*Math.cos(n),o=t*Math.sin(n),u=e.attr("cx"),a=e.attr("cy"),f=this.gitVisuals.paper.width,l=this.gitVisuals.paper.height,c=.8,h=1,p=function(){o+=r*h-i*o,s-=i*s,u+=s*h,a+=o*h;if(u<0||u>f)s=c*-s,u=u<0?0:f;if(a<0||a>l)o=c*-o,a=a<0?0:l;return e.attr({cx:u,cy:a}),s*s+o*o<.01&&Math.abs(a-l)===0?!1:!0};return p},genGraphics:function(){var e=this.gitVisuals.paper,t=this.getScreenCoords(),n=this.getTextScreenCoords(),r=e.circle(t.x,t.y,this.getRadius()).attr(this.getAttributes().circle),i=e.text(n.x,n.y,String(this.get("id")));i.attr({"font-size":this.getFontSize(this.get("id")),"font-weight":"bold","font-family":"Monaco, Courier, font-monospace",opacity:this.getOpacity()}),this.set("circle",r),this.set("text",i),this.attachClickHandlers()}});n.VisNode=c}),e.define("/src/js/visuals/visBase.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({removeKeys:function(e){u.each(e,function(e){this.get(e)&&this.get(e).remove()},this)},getNonAnimateKeys:function(){return["stroke-dasharray"]},getIsInOrigin:function(){return this.get("gitEngine")?this.get("gitEngine").isOrigin():!1},animateToAttr:function(e,t,n){if(t===0){this.setAttr(e,!0);return}var r=t!==undefined?t:this.get("animationSpeed"),i=n||this.get("animationEasing");this.setAttr(e,!1,r,i)},setAttrBase:function(e,t,n,r,i){u.each(e,function(e){n?this.get(e).attr(t[e]):(this.get(e).stop(),this.get(e).animate(t[e],r,i),u.forEach(this.getNonAnimateKeys(),function(n){t[e]&&t[e][n]!==undefined&&this.get(e).attr(n,t[e][n])},this)),t.css&&$(this.get(e).node).css(t.css)},this)},animateAttrKeys:function(e,t,n,r){e=u.extend({},{include:["circle","arrow","rect","path","text"],exclude:[]},e||{});var i=this.getAttributes();u.each(e.include,function(e){i[e]=u.extend({},i[e],t)}),u.each(e.exclude,function(e){delete i[e]}),this.animateToAttr(i,n,r)}});n.VisBase=f}),e.define("/src/js/visuals/visBranch.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=function(){var e=Math.random(),t="hsb("+String(e)+",0.7,1)";return t},h=l.extend({defaults:{pos:null,text:null,rect:null,arrow:null,isHead:!1,flip:1,fill:f.rectFill,stroke:f.rectStroke,"stroke-width":f.rectStrokeWidth,offsetX:f.nodeRadius*4.75,offsetY:0,arrowHeight:14,arrowInnerSkew:0,arrowEdgeHeight:6,arrowLength:14,arrowOffsetFromCircleX:10,vPad:5,hPad:5,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing},validateAtInit:function(){if(!this.get("branch"))throw new Error("need a branch!")},getID:function(){return this.get("branch").get("id")},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine");if(!this.gitEngine)throw new Error("asd wtf");this.get("branch").set("visBranch",this);var e=this.get("branch").get("id");e=="HEAD"?(this.set("isHead",!0),this.set("flip",-1),this.refreshOffset(),this.set("fill",f.headRectFill)):e!=="master"&&this.set("fill",c())},getCommitPosition:function(){var e=this.gitEngine.getCommitFromRef(this.get("branch")),t=e.get("visNode");return this.set("flip",this.getFlipValue(e,t)),this.refreshOffset(),t.getScreenCoords()},getFlipValue:function(e,t){var n=this.get("gitVisuals").getFlipPos(),r=t.get("pos").x>n;return e.get("id")==="C0"?-1:this.get("isHead")?r?this.isBranchStackEmpty()?-1:1:this.isBranchStackEmpty()?1:-1:r?-1:1},refreshOffset:function(){var e=f.nodeRadius*4.75,t=33,n=10;this.get("flip")===1?(this.set("offsetY",-t),this.set("offsetX",e-n)):(this.set("offsetY",t),this.set("offsetX",e-n))},getArrowTransform:function(){return this.get("flip")===1?"t-2,-20R-35":"t2,20R-35"},getBranchStackIndex:function(){if(this.get("isHead"))return 0;var e=this.getBranchStackArray(),t=-1;return u.each(e,function(e,n){e.obj==this.get("branch")&&(t=n)},this),t},getBranchStackLength:function(){return this.get("isHead")?1:this.getBranchStackArray().length},isBranchStackEmpty:function(){var e=this.gitVisuals.branchStackMap[this.getCommitID()];return e?e.length===0:!0},getCommitID:function(){var e=this.get("branch").get("target");return e.get("type")==="branch"&&(e=e.get("target")),e.get("id")},getBranchStackArray:function(){var e=this.gitVisuals.branchStackMap[this.getCommitID()];return e===undefined?(this.gitVisuals.calcBranchStacks(),this.getBranchStackArray()):e},getTextPosition:function(){var e=this.getCommitPosition(),t=this.getBranchStackIndex();return{x:e.x+this.get("flip")*this.get("offsetX"),y:e.y+t*f.multiBranchY+this.get("offsetY")}},getRectPosition:function(){var e=this.getTextPosition(),t=this.get("flip"),n=this.getTextSize();return{x:e.x-.5*n.w-this.get("hPad"),y:e.y-.5*n.h-this.get("vPad")}},getArrowPath:function(){var e=function(e,t,n){return{x:e.x+t,y:e.y+n}},t=function(e){return String(Math.round(e.x))+","+String(Math.round(e.y))},n=this.get("flip"),r=e(this.getCommitPosition(),n*this.get("arrowOffsetFromCircleX"),0),i=e(r,n*this.get("arrowLength"),-this.get("arrowHeight")),s=e(r,n*this.get("arrowLength"),this.get("arrowHeight")),o=e(i,n*this.get("arrowInnerSkew"),this.get("arrowEdgeHeight")),a=e(s,n*this.get("arrowInnerSkew"),-this.get("arrowEdgeHeight")),f=49,l=e(o,n*f,0),c=e(a,n*f,0),h="";h+="M"+t(l)+" ";var p=[o,i,r,s,a,c];return u.each(p,function(e){h+="L"+t(e)+" "},this),h+="z",h},getTextSize:function(){var e=function(e){var t=e.get("text")?e.get("text").node:null;return t===null?0:t.clientWidth},t=function(e){return e.w||(e.w=75),e.h||(e.h=20),e},n=this.get("text").node;if(this.get("isHead"))return t({w:n.clientWidth,h:n.clientHeight});var r=0;return u.each(this.getBranchStackArray(),function(t){r=Math.max(r,e(t.obj.get("visBranch")))}),t({w:r,h:n.clientHeight})},getSingleRectSize:function(){var e=this.getTextSize(),t=this.get("vPad"),n=this.get("hPad");return{w:e.w+t*2,h:e.h+n*2}},getRectSize:function(){var e=this.getTextSize(),t=this.get("vPad"),n=this.get("hPad"),r=this.getBranchStackLength();return{w:e.w+t*2,h:e.h*r*1.1+n*2}},getIsRemote:function(){return this.get("branch").getIsRemote()},getName:function(){var e=this.get("branch").getName(),t=this.get("branch")===this.gitEngine.HEAD.get("target"),n=this.getIsRemote(),r=t&&!this.getIsInOrigin()&&!n?"*":"";return e+r},nonTextToFront:function(){this.get("arrow").toFront(),this.get("rect").toFront()},textToFront:function(){this.get("text").toFront()},textToFrontIfInStack:function(){this.getBranchStackIndex()!==0&&this.get("text").toFront()},getFill:function(){return this.get("isHead")||this.getBranchStackLength()==1||this.getBranchStackIndex()!==0?this.get("fill"):this.gitVisuals.blendHuesFromBranchStack(this.getBranchStackArray())},remove:function(){this.removeKeys(["text","arrow","rect"]),this.gitVisuals.removeVisBranch(this)},genGraphics:function(e){var t=this.getTextPosition(),n=this.getName(),r;r=e.text(t.x,t.y,String(n)),r.attr({"font-size":14,"font-family":"Monaco, Courier, font-monospace",opacity:this.getTextOpacity()}),this.set("text",r);var i=this.getAttributes(),s=this.getRectPosition(),o=this.getRectSize(),a=e.rect(s.x,s.y,o.w,o.h,8).attr(i.rect);this.set("rect",a);var f=this.getArrowPath(),l=e.path(f).attr(i.arrow);this.set("arrow",l);var c=["text","rect","arrow"];u.each(c,function(e){$(this.get(e).node).css(i.css)},this),this.attachClickHandlers(),a.toFront(),r.toFront()},attachClickHandlers:function(){if(this.get("gitVisuals").options.noClick)return;var e=[this.get("rect"),this.get("text"),this.get("arrow")];u.each(e,function(e){e.click(u.bind(this.onClick,this))},this)},shouldDisableClick:function(){return this.get("isHead")&&!this.gitEngine.getDetachedHead()},onClick:function(){if(this.shouldDisableClick())return;var t="git checkout "+this.get("branch").get("id"),n=e("../app");n.getEventBaton().trigger("commandSubmitted",t)},updateName:function(){this.get("text").attr({text:this.getName()})},getNonTextOpacity:function(){return this.get("isHead")?this.gitEngine.getDetachedHead()?1:0:this.getBranchStackIndex()===0?1:0},getTextOpacity:function(){return this.get("isHead")?this.gitEngine.getDetachedHead()?1:0:1},getAttributes:function(){var e=this.getNonTextOpacity(),t=this.getTextOpacity();this.updateName();var n=this.getTextPosition(),r=this.getRectPosition(),i=this.getRectSize(),s=this.getArrowPath(),o=this.getIsInOrigin()?f.originDash:"",u=this.shouldDisableClick()?"auto":"pointer";return{css:{cursor:u},text:{x:n.x,y:n.y,opacity:t},rect:{x:r.x,y:r.y,width:i.w,height:i.h,opacity:e,fill:this.getFill(),stroke:this.get("stroke"),"stroke-width":this.get("stroke-width")},arrow:{path:s,opacity:e,fill:this.getFill(),stroke:this.get("stroke"),transform:this.getArrowTransform(),"stroke-width":this.get("stroke-width")}}},animateUpdatedPos:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},setAttr:function(e,t,n,r){var i=["text","rect","arrow"];this.setAttrBase(i,e,t,n,r)}}),p=a.Collection.extend({model:h});n.VisBranchCollection=p,n.VisBranch=h,n.randomHueString=c}),e.define("/src/js/visuals/visEdge.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=l.extend({defaults:{tail:null,head:null,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing},validateAtInit:function(){var e=["tail","head"];u.each(e,function(e){if(!this.get(e))throw new Error(e+" is required!")},this)},getID:function(){return this.get("tail").get("id")+"."+this.get("head").get("id")},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine"),this.get("tail").get("outgoingEdges").push(this)},remove:function(){this.removeKeys(["path"]),this.gitVisuals.removeVisEdge(this)},genSmoothBezierPathString:function(e,t){var n=e.getScreenCoords(),r=t.getScreenCoords();return this.genSmoothBezierPathStringFromCoords(n,r)},genSmoothBezierPathStringFromCoords:function(e,t){var n=function(e){return String(Math.round(e.x))+","+String(Math.round(e.y))},r=function(e,t,n){return n=n||f.curveControlPointOffset,{x:e.x,y:e.y+n*t}},i=function(e,t,n){return{x:e.x+t,y:e.y+n}};e=r(e,-1,this.get("tail").getRadius()),t=r(t,1,this.get("head").getRadius());var s="";s+="M"+n(e)+" ",s+="C",s+=n(r(e,-1))+" ",s+=n(r(t,1))+" ",s+=n(t);var o=f.arrowHeadSize||10;return s+=" L"+n(i(t,-o,o)),s+=" L"+n(i(t,o,o)),s+=" L"+n(t),s+="C",s+=n(r(t,1))+" ",s+=n(r(e,-1))+" ",s+=n(e),s},getBezierCurve:function(){return this.genSmoothBezierPathString(this.get("tail"),this.get("head"))},getStrokeColor:function(){return f.visBranchStrokeColorNone},setOpacity:function(e){e=e===undefined?1:e,this.get("path").attr({opacity:e})},genGraphics:function(e){var t=this.getBezierCurve(),n=e.path(t).attr({"stroke-width":f.visBranchStrokeWidth,stroke:this.getStrokeColor(),"stroke-linecap":"round","stroke-linejoin":"round",fill:this.getStrokeColor()});n.toBack(),this.set("path",n)},getOpacity:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("tail")),t={branch:1,head:f.edgeUpstreamHeadOpacity,none:f.edgeUpstreamNoneOpacity};if(t[e]===undefined)throw new Error("bad stat");return t[e]},getAttributes:function(){var e=this.getBezierCurve(),t=this.getOpacity();return{path:{path:e,opacity:t}}},animateUpdatedPath:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},animateToAttr:function(e,t,n){if(t===0){this.get("path").attr(e.path);return}this.get("path").toBack(),this.get("path").stop(),this.get("path").animate(e.path,t!==undefined?t:this.get("animationSpeed"),n||this.get("animationEasing"))}}),h=a.Collection.extend({model:c});n.VisEdgeCollection=h,n.VisEdge=c}),e.define("/src/js/level/disabledMap.js",function(e,t,n,r,i,s,o){function h(e){e=e||{},this.disabledMap=e.disabledMap||{"git cherry-pick":!0,"git rebase":!0}}var u=e("underscore"),a=e("../intl"),f=e("../git/commands"),l=e("../util/errors"),c=l.GitError;h.prototype.getInstantCommands=function(){var e=[],t=function(){throw new c({msg:a.str("command-disabled")})};return u.each(this.disabledMap,function(n,r){var i=f.regexMap[r];if(!i)throw new Error("wuttttt this disbaled command"+r+" has no regex matching");e.push([i,t])}),e},n.DisabledMap=h}),e.define("/src/js/dialogs/confirmShowSolution.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Are you sure you want to see the solution?","","I believe in you! You can do it"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 确定要看答案吗?","","哥相信你!你可以的"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Êtes-vous sûr de vouloir voir la solution ?","","Je crois en vous ! Vous pouvez le faire"]}}]}}),e.define("/src/js/level/arbiter.js",function(e,t,n,r,i,s,o){function h(){this.levelMap={},this.levelSequences=f,this.sequences=[],this.init();var e;try{e=JSON.parse(localStorage.getItem("solvedMap")||"{}")}catch(t){console.warn("local storage failed",t)}this.solvedMap=e||{},c.getEvents().on("levelSolved",this.levelSolved,this)}var u=e("underscore"),a=e("backbone"),f=e("../../levels").levelSequences,l=e("../../levels").sequenceInfo,c=e("../app");h.prototype.init=function(){var e;u.each(this.levelSequences,function(e,t){this.sequences.push(t);if(!e||!e.length)throw new Error("no empty sequences allowed");u.each(e,function(e,n){this.validateLevel(e);var r=t+String(n+1),i=u.extend({},e,{index:n,id:r,sequenceName:t});this.levelMap[r]=i,this.levelSequences[t][n]=i},this)},this)},h.prototype.isLevelSolved=function(e){if(!this.levelMap[e])throw new Error("that level doesnt exist!");return Boolean(this.solvedMap[e])},h.prototype.levelSolved=function(e){if(!e)return;this.solvedMap[e]=!0,this.syncToStorage()},h.prototype.resetSolvedMap=function(){this.solvedMap={},this.syncToStorage(),c.getEvents().trigger("levelSolved")},h.prototype.syncToStorage=function(){try{localStorage.setItem("solvedMap",JSON.stringify(this.solvedMap))}catch(e){console.warn("local storage fialed on set",e)}},h.prototype.validateLevel=function(e){e=e||{};var t=["name","goalTreeString","solutionCommand"],n=["hint","disabledMap","startTree"];u.each(t,function(t){if(e[t]===undefined)throw console.log(e),new Error("I need this field for a level: "+t)})},h.prototype.getSequenceToLevels=function(){return this.levelSequences},h.prototype.getSequences=function(){return u.keys(this.levelSequences)},h.prototype.getLevelsInSequence=function(e){if(!this.levelSequences[e])throw new Error("that sequecne name "+e+"does not exist");return this.levelSequences[e]},h.prototype.getSequenceInfo=function(e){return l[e]},h.prototype.getLevel=function(e){return this.levelMap[e]},h.prototype.getNextLevel=function(e){if(!this.levelMap[e])return console.warn("that level doesnt exist!!!"),null;var t=this.levelMap[e],n=t.sequenceName,r=this.levelSequences[n],i=t.index+1;if(i master -> C1",""],afterMarkdowns:["And now it's","","HEAD -> C1"],command:"git checkout C1",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["To complete this level, let's detach HEAD from `bugFix` and attach it to the commit instead.","","Specify this commit by its hash. The hash for each commit is displayed on the circle that represents the commit."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 在Git中前后移动","","在接触Git的更多高级主题之前,我们先学习用不同的方法在代表你的项目的提交记录树上前后移动。","","一旦能够熟练地在Git中前进后退,你使用其他git命令的威力也会被放大!","","","","",""]}},{type:"ModalAlert",options:{markdowns:["## HEAD","",'我们首先看一下"HEAD". HEAD是当前提交记录的符号名称 -- 其实就是你正在其基础进行工作的提交记录。',"","HEAD总是指向最近一次提交记录,表现为当前工作树。大多数修改工作树的git命令都开始于改变HEAD指向。","","HEAD通常指向分支名(比如bugFix)。你提交时,改变了bugFix的状态,这一变化通过HEAD变得可见。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["在实例中看一下。我们将会观察提交前后HEAD的位置。"],afterMarkdowns:["看! HEAD一直藏在`master`分支后面。"],command:"git checkout C1; git checkout master; git commit; git checkout C2",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["### 分离 HEAD","","分离HEAD就是让其指向一个提交记录而不是分支名。这是命令执行之前的样子: ","","HEAD -> master -> C1",""],afterMarkdowns:["现在变成了","","HEAD -> C1"],command:"git checkout C1",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["想完成此关,从`bugFix`分离出HEAD并让其指向一个提交记录。","","通过hash值指定提交记录。每个提交记录的hash值显示在代表提交记录的圆圈中。"]}}]}}}}),e.define("/levels/rampup/relativeRefs.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"C3","id":"HEAD"}}',solutionCommand:"git checkout bugFix^",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Relative Refs (^)",zh_CN:"相对引用(^)"},hint:{en_US:"Remember the Caret (^) operator!",zh_CN:"记住插入(^)操作符!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Relative Refs","","Moving around in Git by specifying commit hashes can get a bit tedious. In the real world you won't have a nice commit tree visualization next to your terminal, so you'll have to use `git log` to see hashes.","","Furthermore, hashes are usually a lot longer in the real Git world as well. For instance, the hash of the commit that introduced the previous level is `fed2da64c0efc5293610bdd892f82a58e8cbc5d8`. Doesn't exactly roll off the tongue...","","The upside is that Git is smart about hashes. It only requires you to specify enough characters of the hash until it uniquely identifies the commit. So I can type `fed2` instead of the long string above."]}},{type:"ModalAlert",options:{markdowns:["Like I said, specifying commits by their hash isn't the most convenient thing ever, which is why Git has relative refs. They are awesome!","","With relative refs, you can start somewhere memorable (like the branch `bugFix` or `HEAD`) and work from there.","","Relative commits are powerful, but we will introduce two simple ones here:","","* Moving upwards one commit at a time with `^`","* Moving upwards a number of times with `~`"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's look at the Caret (^) operator first. Each time you append that to a ref name, you are telling Git to find the parent of the specified commit.","",'So saying `master^` is equivalent to "the first parent of `master`".',"","`master^^` is the grandparent (second-generation ancestor) of `master`","","Let's check out the commit above master here"],afterMarkdowns:["Boom! Done. Way easier than typing the commit hash"],command:"git checkout master^",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["You can also reference `HEAD` as a relative ref. Let's use that a couple of times to move upwards in the commit tree"],afterMarkdowns:["Easy! We can travel backwards in time with `HEAD^`"],command:"git checkout C3; git checkout HEAD^; git checkout HEAD^; git checkout HEAD^",beforeCommand:"git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["To complete this level, check out the parent commit of `bugFix`. This will detach `HEAD`.","","You can specify the hash if you want, but try using relative refs instead!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 相对引用","","用指定提交记录hash值的方式在Git中移动会变得比较乏味。在现实中,你不会有漂亮的可视化的提交记录树放在终端旁边,所以你不得不用`git log`来查看hasn值。","","另外,hash值在真实的Git环境中也会更长。举个例子,前一关的介绍中的提交记录的hash值是`fed2da64c0efc5293610bdd892f82a58e8cbc5d8`。不要把舌头闪了...","","好的一面是,Git对hash的处理很智能。你只需要提供能够唯一标识提交记录的前几个字符即可。所以,我可以仅输入`fed2`而不是上面的一长串字符。"]}},{type:"ModalAlert",options:{markdowns:["我说过,通过hash指定提交记录不是很方便,所以Git引入了相对引用。这个就很牛掰了!","","使用相对引用,你可以从一个易于记忆的地方(比如分支名`bugFix`或`HEAD`)开始工作。","","相对引用非常给力,这里我介绍两个简单的用法:","","* 使用`^`向上移动1个提交记录","* 使用`~`向上移动多个提交记录"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["首先看看插入(^)操作符。把插入符跟在引用名后面,表示让Git寻找指定提交记录的父提交。","",'所以`master^`相当于"`master`的父提交"。',"","`master^^`是`master`的父父提交(上上代祖先)","","切换到master的父提交"],afterMarkdowns:["唰!搞定。这种方式比输入提交记录的hash值简单多了!"],command:"git checkout master^",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["你也可以`HEAD`把用作相对引用。以下命令使用`HEAD`在提交树中向上移动几次。"],afterMarkdowns:["简单!我们可以一直使用`HEAD^`向上移动。"],command:"git checkout C3; git checkout HEAD^; git checkout HEAD^; git checkout HEAD^",beforeCommand:"git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["要完成此关,切换到`bugFix`的父提交。这会分离出`HEAD`.","","如果你愿意的话,使用hash值也可以过关,但为何不试试使用相对引用呢?"]}}]}}}}),e.define("/levels/rampup/relativeRefs2.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C6","id":"master"},"bugFix":{"target":"C0","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C5":{"parents":["C3"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"C1","id":"HEAD"}}',solutionCommand:"git branch -f master C6;git checkout HEAD~1;git branch -f bugFix HEAD~1",startTree:'{"branches":{"master":{"target":"C4","id":"master"},"bugFix":{"target":"C5","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C5":{"parents":["C3"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"C2","id":"HEAD"}}',hint:{en_US:"You'll need to use at least one direct reference (hash) to complete this level",zh_CN:"这一关至少要用到一次直接引用(hash)"},name:{en_US:"Relative Refs #2 (~)",zh_CN:"相对引用2(~)"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:['### The "~" operator',"","Say you want to move a lot of levels up in the commit tree. It might be tedious to type `^` several times, so Git also has the tilde (~) operator.","","","The tilde operator (optionally) takes in a trailing number that specifies the number of parents you would like to ascend. Let's see it in action"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's specify a number of commits back with `~`."],afterMarkdowns:["Boom! So concise -- relative refs are great."],command:"git checkout HEAD~4",beforeCommand:"git commit; git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["### Branch forcing","","You're an expert on relative refs now, so let's actually *use* them for something.","","One of the most common ways I use relative refs is to move branches around. You can directly reassign a branch to a commit with the `-f` option. So something like:","","`git branch -f master HEAD~3`","","Moves (by force) the master branch to three parents behind HEAD."]}},{type:"ModalAlert",options:{markdowns:["To complete this level, move `HEAD`, `master`, and `bugFix` to their goal destinations shown."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:['### The "~" operator',"","假设需要在提交树中向上移动很多步。使用多个`^`非常无聊,所以Git也引入了波浪(~)操作符。","","","波浪操作符后面可以(可选地)跟一个数字,指定向上移动多少次。看个例子"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用`~`一次后退多步."],afterMarkdowns:["唰!如此简洁--相对引用就是好啊!"],command:"git checkout HEAD~4",beforeCommand:"git commit; git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["### Branch forcing","","你现在是相对引用的高手了,现在*用*他来实际做点事情。","","我使用相对引用最多的就是移动分支。你可以使用`-f`选项把直接让分支指向另一个提交。举个例子:","","`git branch -f master HEAD~3`","","(强制)移动master指向HEAD的第3级父提交。"]}},{type:"ModalAlert",options:{markdowns:["要完成此关,移动`HEAD`,`master`和`bugFix`到目标所示的位置。"]}}]}}}}),e.define("/levels/rampup/reversingChanges.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22master%22%7D%2C%22pushed%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22pushed%22%7D%2C%22local%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22local%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C2%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22pushed%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git reset HEAD~1;git checkout pushed;git revert HEAD",compareOnlyBranches:!0,startTree:'{"branches":{"master":{"target":"C1","id":"master"},"pushed":{"target":"C2","id":"pushed"},"local":{"target":"C3","id":"local"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"}},"HEAD":{"target":"local","id":"HEAD"}}',name:{en_US:"Reversing Changes in Git",ja:"変更を元に戻す",fr_FR:"Annuler des changements avec Git",ko:"Git에서 작업 되돌리기",zh_CN:"在Git中撤销更改"},hint:{en_US:"Notice that revert and reset take different arguments.",fr_FR:"",zh_CN:"注意revert和reset使用不同的参数。",ko:"",ja:""},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Reversing Changes in Git","","There are many ways to reverse changes in Git. And just like committing, reversing changes in Git has both a low-level component (staging individual files or chunks) and a high-level component (how the changes are actually reversed). Our application will focus on the latter.","","There are two primary ways to undo changes in Git -- one is using `git reset` and the other is using `git revert`. We will look at each of these in the next dialog",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","",'`git reset` reverts changes by moving a branch reference backwards in time to an older commit. In this sense you can think of it as "rewriting history;" `git reset` will move a branch backwards as if the commit had never been made in the first place.',"","Let's see what that looks like:"],afterMarkdowns:["Nice! Git simply moved the master branch reference back to `C1`; now our local repository is in a state as if `C2` had never happened"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","",'While reseting works great for local branches on your own machine, its method of "rewriting history" doesn\'t work for remote branches that others are using.',"","In order to reverse changes and *share* those reversed changes with others, we need to use `git revert`. Let's see it in action"],afterMarkdowns:["Weird, a new commit plopped down below the commit we wanted to reverse. That's because this new commit `C2'` introduces *changes* -- it just happens to introduce changes that exactly reverses the commit of `C2`.","","With reverting, you can push out your changes to share with others."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["To complete this level, reverse the two most recent commits on both `local` and `pushed`.","","Keep in mind that `pushed` is a remote branch and `local` is a local branch -- that should help you choose your methods."]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## 変更を元に戻す","","Gitでは変更を元に戻す方法がたくさんあります。コミットと同じように、低レベルな動作(ファイル別だったりファイルの中の一部だったり)も高レベルな動作(変更のまとまりのキャンセル)もできます。このアプリケーションでは後者の方法について紹介します。","","基本的なアンドゥの方法が2つあります - 一つは`git reset`を使う方法で、もう1つは`git revert`を使う方法です。次のダイアログで一つ一つを見ていきます。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","","`git reset`はブランチのポインタを後方に移動することで変更のキャンセルを実現します。履歴を上書きするような動作だと思うと良いでしょうか:`git reset`はそもそも前のコミットなんかなかったかのように、ブランチのポインタを元に戻してくれます。","","どういう感じか見てみましょう。"],afterMarkdowns:["いいですね!Gitは単純にmasterブランチへのポインタを`C1`へ戻しました。これでこのローカルリポジトリにはまるで`C2`なんて無かったかのように変更をキャンセルできました。"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","自分のマシン上のブランチではさっきの`git reset`でうまくいきましたが、この「履歴を上書きする」手段は、他の人も使っているリモートにあるリポジトリに対しては使うことができません。","","変更を巻き戻して他の人とそれを共有するためには、`git revert`を使う必要があります。今度はこれを見てみましょう。"],afterMarkdowns:["あれ、おかしいな。巻き戻したいと思ってたコミットの下に新しいコミットが出来上がってしまったみたいです。なぜか。これは、この新しい`C2'`コミットは`C2`へ戻すのに必要な内容を確かに変更して巻き戻していたのです。","","こんな風にして、巻き戻した内容を他人と共有するためにはrevertを使います。"],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["この章の仕上げに、`local`と`pushed`の両方の直近のコミットを巻き戻してみましょう。","","`pushed`はリモートのブランチで、`local`はローカルであることに注意。正しくコマンドを使い分けましょう。"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Annuler des changements avec Git","","Il y a de nombreuses façons d'annuler des changement avec Git. De même que pour les commits, annuler des changements avec Git a à la fois un aspect bas-niveau (gestion dans le 'staging' des fichiers et morceaux de fichiers) et un aspect de plus haut niveau 9comment les changements sont effectivement annulés). Nous allons nous intéresser à ce dernier point.","","Il y a principalement deux façons d'annuler des changements avec Git -- l'une est `git reset` et l'autre est `git revert`. Nous allons maintenant voir chacune de ces façons",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","","`git reset` annule des changements en déplaçant la référence en arrière dans le temps sur un commit plus ancien. En ce sens, on peut considérer cela comme une façon de \"réécrire l'histoire\"; `git reset` fait remonter une branche en arrière comme si le(s) commit(s) n'avait jamais eu lieu.","","Regardons à quoi cela ressemble :"],afterMarkdowns:["Bravo ! Git a simplement déplacé la référence de la branche master en la faisant revenir sur `C1`; désormais notre dépôt est dans le même état que si `C2` n'avait jamais eu lieu"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","Bien que le reset marche parfaitement pour les branches locales sur notre propre machine, cette façon de \"réécrire l'histoire\" ne marche pas avec les banches distantes (remote) que d'autres personnes utilisent.","","Pour pouvoir annuler des changements et *partager* ces annulations avec d'autres, nous devons utiliser `git revert`. Regardons comment cela fonctionne"],afterMarkdowns:["Étrangement, un nouveau commit est appaaru en bas sous le commit que nous voulions annuler. C'est parce que ce nouveau commit `C2'` introduit des *modifications* -- celles qui correspondent justement à l'annulation de celles du commit `C2`.","","Avec revert, vous pouvez diffuser (push) vos modifications et les partager avec tout le monde."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["Pour accomplir ce niveau, annulez les deux derniers commits à la fois sur `local` et sur `pushed`.","","Ayez à l'esprit que `pushed` est une branche distante et `local` est une branche locale -- cela devrait vous guider dans le choix de la méthode à employer."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 撤销 Git 里面的变动","","在 Git 里撤销修改的方法很多。和 commit 一样,在 Git 里撤销变动同时具有底层部分(暂存一些独立的文件或者片段)和高层部分(具体到变动是究竟怎么被撤销的)。我们这个应用主要关注后者。","","在 Git 里主要用两种方法来撤销变动 —— 一种是 `git reset`,另外一种是 `git revert`。让我们在下一个窗口逐一了解它们。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","",'`git reset`把分支记录回退到上一个提交记录来实现撤销改动。你可以认为这是在"重写历史"。`git reset`往回移动分支,原来指向的提交记录好像重来没有提交过一样。',"","让我们看看具体的操作:"],command:"git reset HEAD~1",afterMarkdowns:["Nice!Git把master分支的指向简单地移回到`C1`;现在我们的本地代码库处于没有提交过`C2`的状态了。"],beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","虽然在你的本地分支中使用`git reset`很方便,但是这种“改写历史”的方法对别人的远端分支是无效的哦!","","为了撤销更改并*传播*给别人,我们需要使用`git revert`。举个例子"],command:"git revert HEAD",afterMarkdowns:["怪哉!在我们要撤销的提交记录后面居然多了一个新提交!这是因为新提交记录`C2'`引入了*更改*——刚好是用来撤销 `C2` 这个提交的。","","借助 revert,现在可以把你的更改传递给别人啦。"],beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["要完成此关,分别撤销`local`分支和`pushed`分支上的最近一次提交。","","记住 `pushed` 是一个远程分支,`local` 是一个本地分支 —— 有了这么明显的提示应该知道用哪种方法了吧?"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git에서 작업 되돌리기","","Git에는 작업한 것을 되돌리는 여러가지 방법이 있습니다. 변경내역을 되돌리는 것도 커밋과 마찬가지로 낮은 수준의 일(개별 파일이나 묶음을 스테이징 하는 것)과 높은 수준의 일(실제 변경이 복구되는 방법)이 있는데요, 여기서는 후자에 집중해 알려드릴게요.","","Git에서 변경한 내용을 되돌리는 방법은 크게 두가지가 있습니다 -- 하나는 `git reset`을 쓰는거고, 다른 하나는 `git revert`를 사용하는 것입니다. 다음 화면에서 하나씩 알아보겠습니다.",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git 리셋(reset)","",'`git reset`은 브랜치로 하여금 예전의 커밋을 가리키도록 이동시키는 방식으로 변경 내용을 되돌립니다. 이런 관점에서 "히스토리를 고쳐쓴다"라고 말할 수 있습니다. 즉, `git reset`은 마치 애초에 커밋하지 않은 것처럼 예전 커밋으로 브랜치를 옮기는 것입니다.',"","어떤 그림인지 한번 보죠:"],afterMarkdowns:["그림에서처럼 master 브랜치가 가리키던 커밋을 `C1`로 다시 옮겼습니다; 이러면 로컬 저장소에는 마치 `C2`커밋이 아예 없었던 것과 마찬가지 상태가 됩니다."],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git 리버트(revert)","",'각자의 컴퓨터에서 작업하는 로컬 브랜치의 경우 리셋(reset)을 잘 쓸 수 있습니다만, "히스토리를 고쳐쓴다"는 점 때문에 다른 사람이 작업하는 리모트 브랜치에는 쓸 수 없습니다.',"","변경분을 되돌리고, 이 되돌린 내용을 다른 사람들과 *공유하기* 위해서는, `git revert`를 써야합니다. 예제로 살펴볼게요."],afterMarkdowns:["어색하게도, 우리가 되돌리려고한 커밋의 아래에 새로운 커밋이 생겼습니다. `C2`라는 새로운 커밋에 *변경내용*이 기록되는데요, 이 변경내역이 정확히 `C2` 커밋 내용의 반대되는 내용입니다.","","리버트를 하면 다른 사람들에게도 변경 내역을 밀어(push) 보낼 수 있습니다."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["이 레벨을 통과하려면, `local` 브랜치와 `pushed` 브랜치에 있는 최근 두 번의 커밋을 되돌려 보세요.","","`pushed`는 리모트 브랜치이고, `local`은 로컬 브랜치임을 신경쓰셔서 작업하세요 -- 어떤 방법을 선택하실지 떠오르시죠?"]}}]}}}}),e.define("/levels/rebase/manyRebases.js",function(e,t,n,r,i,s,o){n.level={compareOnlyMasterHashAgnostic:!0,disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22master%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22bugFix%22%7D%2C%22side%22%3A%7B%22target%22%3A%22C6%27%22%2C%22id%22%3A%22side%22%7D%2C%22another%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22another%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C6%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C6%22%7D%2C%22C7%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C7%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C6%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C6%27%22%7D%2C%22C7%27%22%3A%7B%22parents%22%3A%5B%22C6%27%22%5D%2C%22id%22%3A%22C7%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout bugFix;git rebase master;git checkout side;git rebase bugFix;git checkout another;git rebase side;git rebase another master",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C3","id":"bugFix"},"side":{"target":"C6","id":"side"},"another":{"target":"C7","id":"another"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C0"],"id":"C4"},"C5":{"parents":["C4"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"},"C7":{"parents":["C5"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Rebasing over 9000 times",ko:"9천번이 넘는 리베이스",ja:"Rebasing over 9000 times",zh_CN:"N次Rebase"},hint:{en_US:"Remember, the most efficient way might be to only update master at the end...",ja:"最も効率的なやり方はmasterを最後に更新するだけかもしれない・・・",ko:"아마도 master를 마지막에 업데이트하는 것이 가장 효율적인 방법일 것입니다...",zh_CN:"记住,最后更新master分支可能是最高效的方法。"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["### Rebasing Multiple Branches","","Man, we have a lot of branches going on here! Let's rebase all the work from these branches onto master.","","Upper management is making this a bit trickier though -- they want the commits to all be in sequential order. So this means that our final tree should have `C7'` at the bottom, `C6'` above that, etc etc, etc all in order.","","If you mess up along the way, feel free to use `reset` to start over again. Be sure to check out our solution and see if you can do it in fewer commands!"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["### 複数のブランチをリベースする","","さあ、いくつものブランチが出てきます。このブランチたち全てをmasterブランチにリベースしましょう。","","おエライさん方が今回の仕事を少しトリッキーにしてくれました ― コミットはすべて一列のシーケンシャルな状態にしてほしいそうです。つまり私たちが作るリポジトリの最終的なツリーの状態は、`C7'`が最後に来て、`C6'`がその一つ上に来て、、と順に積み重なるイメージです。","","試行錯誤してツリーが汚くなってきたら、`reset`コマンドを使ってツリーの状態を初期化してください。模範解答をチェックして、それよりも簡単なコマンドで済ませられるかどうか、を考えるのも忘れずに!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["### 多分支衍合","","呐,现在我们有很多分支啦!让我们rebase这些分支的工作到 master 分支上吧。","","但是你的头头找了点麻烦 —— 他们希望得到有序的提交历史,也就是我们最终的结果是 `C7'` 在最底部,`C6'` 在它上面,以此类推。","","假如你搞砸了,没所谓的(虽然我不会告诉你用 `reset` 可以重新开始)。记得看看我们提供的答案,看你能否使用更少的命令完成任务!"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["### 여러 브랜치를 리베이스(rebase)하기 ","","음, 여기 꽤 여러개의 브랜치가 있습니다! 이 브랜치들의 모든 작업내역을 master에 리베이스 해볼까요?","","윗선에서 일을 복잡하게 만드네요 -- 그 분들이 이 모든 커밋들을 순서에 맞게 정렬하라고 합니다. 그럼 결국 우리의 최종 목표 트리는 제일 아래에 `C7'` 커밋, 그 위에 `C6'` 커밋, 또 그 위에 순서대로 보여합니다.","","만일 작업중에 내용이 꼬인다면, `reset`이라고 쳐서 처음부터 다시 시작할 수 있습니다. 모범 답안을 확인해 보시고, 혹시 더 적은 수의 커맨드로 해결할 수 있는지 알아보세요!"]}}]}}}}),e.define("/levels/mixed/grabbingOneCommit.js",function(e,t,n,r,i,s,o){n.level={compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C4>e.C1}]},disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22master%22%7D%2C%22debug%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22debug%22%7D%2C%22printf%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22printf%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22bugFix%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout master;git cherry-pick C4",startTree:'{"branches":{"master":{"target":"C1","id":"master"},"debug":{"target":"C2","id":"debug"},"printf":{"target":"C3","id":"printf"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"bugFix","id":"HEAD"}}',name:{ko:"딱 한개의 커밋만 가져오기",en_US:"Grabbing Just 1 Commit",ja:"Grabbing Just 1 Commit",zh_CN:"只取一个提交"},hint:{en_US:"Remember, interactive rebase or cherry-pick is your friend here",ja:"このレベルではインタラクティブモードのrebaseやcherry-pickがクリアのカギです",ko:"대화식 리베이스(rebase -i)나 or 체리픽(cherry-pick)을 사용하세요",zh_CN:"记住,交互式 rebase 或者 cherry-pick 会很有帮助"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Locally stacked commits","","Here's a development situation that often happens: I'm trying to track down a bug but it is quite elusive. In order to aid in my detective work, I put in a few debug commands and a few print statements.","","All of these debugging / print statements are in their own branches. Finally I track down the bug, fix it, and rejoice!","","Only problem is that I now need to get my `bugFix` back into the `master` branch! I could simply fast-forward `master`, but then `master` would get all my debug statements."]}},{type:"ModalAlert",options:{markdowns:["This is where the magic of Git comes in. There are a few ways to do this, but the two most straightforward ways are:","","* `git rebase -i`","* `git cherry-pick`","","Interactive (the `-i`) rebasing allows you to choose which commits you want to keep or discard. It also allows you to reorder commits. This can be helpful if you want to toss out some work.","","Cherry-picking allows you to pick individual commits and plop them down on top of `HEAD`"]}},{type:"ModalAlert",options:{markdowns:["This is a later level so we will leave it up to you to decide, but in order to complete the level, make sure `master` receives the commit that `bugFix` references."]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ローカルに積み上がったコミット","","実際の開発ではこういうケースがよくあります:「バグの原因調査を試みているがバグの再現性がかなり低い。調査の補助のために、いくつかのデバッグ用の命令やprint文を差し込んでいる。」","","これらのデバッグ用のコードはバグ修正用のブランチにコミットされています。そしてついにバグの原因を突き止めて、修正した!やった!","","あとは`bugFix`ブランチを`master`ブランチに統合できればOK。そこで単純に`master`をfast-forwardすればよいかというと、それでは`master`ブランチの中にデバッグ用のコードも混入してしまいます。"]}},{type:"ModalAlert",options:{markdowns:["ここでGitの魔法が力を発揮します。解決のためにはいくつかの方法がありますが、最も素直な解決方法は2つあって:","","* `git rebase -i`","* `git cherry-pick`","","インタラクティブモードの(`-i`オプションつきの)rebaseによって、保持したいコミットと破棄したいコミットを選り分けることができます。コミットの順序を変更することも可能です。この方法は、一部の変更をどこかへやってしまいたい時に便利です。","","もう一方のcherry-pickを使うと、持っていきたいコミットを選んで`HEAD`の先にストンと落とすことができます。"]}},{type:"ModalAlert",options:{markdowns:["後半の章ですのでどう解決するかをもう自分で考えることができると思います。このレベルをクリアするためには、`bugFix`が持っているコミットを`master`ブランチが受け取る必要がある点には注意してください。"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 本地栈式提交 (Locally stacked commits)","","设想一下一个经常发生的场景:我在追踪一个有点棘手的 bug,为了更好地排查,我添加了一些调试命令和打印语句。","","所有的这些调试和打印语句都只在它们自己的分支里。最终我终于找到这个 bug,揪出来 fix 掉,然后撒花庆祝!","","现在唯一的问题就是要把我在 `bugFix` 分支里的工作合并回 `master` 分支。我可以简单地把 `master` 分支快进(fast-forward),但这样的话 `master` 分支就会包含我这些调试语句了。"]}},{type:"ModalAlert",options:{markdowns:["现在就是 Git 大显神通的时候啦。解决这个问题的方法不止一个,但最直接的两个方法是:","","* `git rebase -i`","* `git cherry-pick`","","交互(`-i`)衍合允许你选择哪些提交是要被保留,哪些要被舍弃。它允许你将提交重新排序。假如你要舍弃一些工作,这个会帮上很大的忙。","","Cherry-picking 能让你选择单独一个提交并且把它放到 `HEAD` 的最前端。"]}},{type:"ModalAlert",options:{markdowns:["本关是可选关卡,玩不玩随便你。但是如果你坚持要刷,确保 `master` 分支能拿到 `bugFix` 分支的相关提交(references)。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 로컬에 쌓인 커밋들","","개발중에 종종 이런 상황이 생깁니다: 잘 띄지 않는 버그를 찾아서 해결하려고, 어떤 부분의 문제인지를 찾기 위해 디버그용 코드와 화면에 정보를 프린트하는 코드 몇 줄 넣습니다. ","","디버깅용 코드나 프린트 명령은 그 브랜치에 들어있습니다. 마침내 버그를 찾아서 고쳤고, 원래 작업하는 브랜치에 합치면 됩니다!","","이제 `bugFix`브랜치의 내용을 `master`에 합쳐 넣으려 하지만, 한 가지 문제가 있습니다. 그냥 간단히 `master`브랜치를 최신 커밋으로 이동시킨다면(fast-forward) 그 불필요한 디버그용 코드들도 함께 들어가 버린다는 문제죠."]}},{type:"ModalAlert",options:{markdowns:["여기에서 Git의 마법이 드러납니다. 이 문제를 해결하는 여러가지 방법이 있습니다만, 가장 간단한 두가지 방법 아래와 같습니다:","","* `git rebase -i`","* `git cherry-pick`","","대화형 (-i 옵션) 리베이스(rebase)로는 어떤 커밋을 취하거나 버릴지를 선택할 수 있습니다. 또 커밋의 순서를 바꿀 수도 있습니다. 이 커맨드로 어떤 작업의 일부만 골라내기에 유용합니다.","","체리픽(cherry-pick)은 개별 커밋을 골라서 `HEAD`위에 떨어뜨릴 수 있습니다."]}},{type:"ModalAlert",options:{markdowns:["이번 레벨을 통과하기 위해 어떤 방법을 쓰시든 자유입니다만, `master`브랜치가 `bugFix` 브랜치의 커밋을 일부 가져오게 해주세요."]}}]}}}}),e.define("/levels/mixed/jugglingCommits.js",function(e,t,n,r,i,s,o){n.level={disabledMap:{"git cherry-pick":!0,"git revert":!0},compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C2>e.C3},function(e){return e.C2>e.C1}]},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%27%27%22%2C%22id%22%3A%22master%22%7D%2C%22newImage%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22newImage%22%7D%2C%22caption%22%3A%7B%22target%22%3A%22C3%27%27%22%2C%22id%22%3A%22caption%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%2C%22C2%27%27%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%27%27%22%7D%2C%22C3%27%27%22%3A%7B%22parents%22%3A%5B%22C2%27%27%27%22%5D%2C%22id%22%3A%22C3%27%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git rebase -i HEAD~2;git commit --amend;git rebase -i HEAD~2;git rebase caption master",startTree:'{"branches":{"master":{"target":"C1","id":"master"},"newImage":{"target":"C2","id":"newImage"},"caption":{"target":"C3","id":"caption"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"caption","id":"HEAD"}}',name:{ko:"커밋들 갖고 놀기",en_US:"Juggling Commits",ja:"Juggling Commits",zh_CN:"提交变换戏法"},hint:{en_US:"The first command is git rebase -i HEAD~2",ja:"最初に打つコマンドはgit rebase -i HEAD~2",ko:"첫번째 명령은 git rebase -i HEAD~2 입니다",zh_CN:"第一个命令是 'git rebase -i HEAD~2'"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Juggling Commits","","Here's another situation that happens quite commonly. You have some changes (`newImage`) and another set of changes (`caption`) that are related, so they are stacked on top of each other in your repository (aka one after another).","","The tricky thing is that sometimes you need to make a small modification to an earlier commit. In this case, design wants us to change the dimensions of `newImage` slightly, even though that commit is way back in our history!!"]}},{type:"ModalAlert",options:{markdowns:["We will overcome this difficulty by doing the following:","","* We will re-order the commits so the one we want to change is on top with `git rebase -i`","* We will `commit --amend` to make the slight modification","* Then we will re-order the commits back to how they were previously with `git rebase -i`","* Finally, we will move master to this updated part of the tree to finish the level (via the method of your choosing)","","There are many ways to accomplish this overall goal (I see you eye-ing cherry-pick), and we will see more of them later, but for now let's focus on this technique."]}},{type:"ModalAlert",options:{markdowns:["Lastly, pay attention to the goal state here -- since we move the commits twice, they both get an apostrophe appended. One more apostrophe is added for the commit we amend, which gives us the final form of the tree ","","That being said, I can compare levels now based on structure and relative apostrophe differences. As long as your tree's `master` branch has the same structure and relative apostrophe differences, I'll give full credit"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Commitsをやりくりする","","開発中に頻繁に起こるケースをもう1つ考えます。ある変更(`newImage`)とまた別の変更(`caption`)があって、それらに依存関係があるとします。この一連の変更が一列に積み重なっているとします。","","ここでトリッキーなのは、以前のコミットに対して微修正をかけなければならないケースがあるということです。今回の教材でも、過去のコミットであるにも関わらず`newImage`ブランチに僅かな修正を加えるような設計の修正が入ったとしましょう。"]}},{type:"ModalAlert",options:{markdowns:["この困難な状況を、以下の手順で克服することを考えます:","","* `git rebase -i`を使って順番を変更する。これで、変更をかけたいコミットを一番先頭に持ってくる。","* `commit --amend`コマンドで僅かな変更を行う","* `git rebase -i`コマンドを再度使って、先頭に持ってきていたコミットを元に戻す","* 最後に、レベルクリアのためにmasterブランチを先頭に持ってくる","","クリアのための方法はいくつもありますが(cherry-pickを使うこともできます)、別の回答はまた後程の章で見ることにんして、今回は上記の方法でやってみることにしましょう。"]}},{type:"ModalAlert",options:{markdowns:["最後に、ゴール時点での状態に気を付けてください。今回2回ほどコミットを動かしますから、コミットへのポインタにはアポストロフィ(')が追加されます。commit --amendコマンドの実行でできたコミットには更にもう1つのアポストロフィが追加されます。 "]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 提交变换戏法","","下面这种情况也是经常出现的。例如你之前已经在 `newImage` 分支上做了一些提交,然后又在 `caption` 分支上做了一些相关的提交,因此它们看起来是一个连一个的(stacked on top of each other in your repository)。","","有点棘手的就是有时候你又想往先前的提交里做些小改动。呐,现在就是设计师想要我们去轻微改变下 `newImage` 的内容(change the dimensions slightly),尽管那个提交是很久很久以前的了。"]}},{type:"ModalAlert",options:{markdowns:["为了实现他的愿望,我们可以按照下面的方法来做:","","* 先用 `git rebase -i` 将提交重新排序,然后把我们想要修改的提交挪到最前","* 然后用 `commit --amend` 来进行一些小修改","* 接着再用 `git rebase -i` 来将他们按最开始的顺序重新排好","* 最后我们把 master 移到修改的最前端(用你自己喜欢的方法),就大功告成啦!","","当然还有许多方法可以完成这个任务(我知道你在看 cherry-pick 啦),之后我们会多点关注这些技巧啦,但现在暂时只专注上面这种方法。"]}},{type:"ModalAlert",options:{markdowns:["啊最后还要提醒你一下最终的形式 —— 因为我们把这个提交移动了两次,所以会分别产生一个省略提交(both get an apostrophe appended)。还有一个省略提交是因为我们为了实现最终效果去修改提交而添加的。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 커밋들 갖고 놀기","","이번에도 꽤 자주 발생하는 상황입니다. `newImage`와 `caption` 브랜치에 각각의 변경내역이 있고 서로 약간 관련이 있어서, 저장소에 차례로 쌓여있는 상황입니다.","","때로는 이전 커밋의 내용을 살짝 바꿔야하는 골치아픈 상황에 빠지게 됩니다. 이번에는 디자인 쪽에서 우리의 작업이력(history)에서는 이미 한참 전의 커밋 내용에 있는 `newImage`의 크기를 살짝 바꿔달라는 요청이 들어왔습니다."]}},{type:"ModalAlert",options:{markdowns:["이 문제를 다음과 같이 풀어봅시다:","","* `git rebase -i` 명령으로 우리가 바꿀 커밋을 가장 최근 순서로 바꾸어 놓습니다","* `commit --amend` 명령으로 커밋 내용을 정정합니다","* 다시 `git rebase -i` 명령으로 이 전의 커밋 순서대로 되돌려 놓습니다","* 마지막으로, master를 지금 트리가 변경된 부분으로 이동합니다. (편하신 방법으로 하세요)","","이 목표를 달성하기 위해서는 많은 방법이 있는데요(체리픽을 고민중이시죠?), 체리픽은 나중에 더 살펴보기로 하고, 우선은 위의 방법으로 해결해보세요."]}},{type:"ModalAlert",options:{markdowns:["최종적으로, 목표 결과를 눈여겨 보세요 -- 우리가 커밋을 두 번 옮겼기 때문에, 두 커밋 모두 따옴표 표시가 붙어있습니다. 정정한(amend) 커밋은 따옴표가 추가로 하나 더 붙어있습니다."]}}]}}}}),e.define("/levels/mixed/jugglingCommits2.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22master%22%7D%2C%22newImage%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22newImage%22%7D%2C%22caption%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22caption%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%27%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout master;git cherry-pick C2;git commit --amend;git cherry-pick C3",disabledMap:{"git revert":!0},startTree:'{"branches":{"master":{"target":"C1","id":"master"},"newImage":{"target":"C2","id":"newImage"},"caption":{"target":"C3","id":"caption"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"caption","id":"HEAD"}}',compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C2>e.C3},function(e){return e.C2>e.C1}]},name:{ko:"커밋 갖고 놀기 #2",en_US:"Juggling Commits #2",ja:"コミットをやりくりする その2",zh_CN:"提交交换戏法 #2"},hint:{en_US:"Don't forget to forward master to the updated changes!",ja:"masterのポインタを先に進めることを忘れずに!",ko:"master를 변경 완료한 커밋으로 이동(forward)시키는 것을 잊지 마세요!",zh_CN:"别忘记了将 master 快进到最新的更新上!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Juggling Commits #2","","*If you haven't completed Juggling Commits #1 (the previous level), please do so before continuing*","","As you saw in the last level, we used `rebase -i` to reorder the commits. Once the commit we wanted to change was on top, we could easily --amend it and re-order back to our preferred order.","","The only issue here is that there is a lot of reordering going on, which can introduce rebase conflicts. Let's look at another method with `git cherry-pick`"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Remember that git cherry-pick will plop down a commit from anywhere in the tree onto HEAD (as long as that commit isn't upstream).","","Here's a small refresher demo:"],afterMarkdowns:["Nice! Let's move on"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["So in this level, let's accomplish the same objective of amending `C2` once but avoid using `rebase -i`. I'll leave it up to you to figure it out! :D","","Remember, the exact number of apostrophe's (') on the commit are not important, only the relative differences. For example, I will give credit to a tree that matches the goal tree but has one extra apostrophe everywhere"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## コミットをやりくりする その2","","*注意 この一つ前のレベル「コミットをやりくりする」をクリアしていない人は、まずそちらの問題をクリアしてきてください*","","前回見てきたように、コミット順序の変更のために、私たちは`rebase -i`コマンドを利用しました。ツリーの先頭に変更対象のコミットがあれば、--amendオプションを使うことで容易に変更を書きかえて、元の順序に戻すことができます。","","この場合に心配なことが一つだけあって、それは複数回の順序の変更が行われるので、rebaseのコンフリクト(衝突)が起こりうることです。こういうケースへの対策として、`git cherry-pick`を使った別の解決法について考えてみましょう。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["git cherry-pickを使うと、ツリーの中から複数のコミットを選んで、HEADの下に新しく作ることができましたね。","","簡単なデモを見てみましょう:"],afterMarkdowns:["できました!次へ進みましょう"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["このレベルでは、`C2`をamendすることで前回と同じ目的を達成しましょう。但し`rebase -i`は使わずにクリアしてください。どんな方法で進めるかはあなたにおまかせします!:D"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 提交变换戏法 #2","","*假如你还没有完成提交变换戏法 #1(前一关),这关不让玩哦!*","","如你在上一关所见,我们使用 `rebase -i` 来重排那些提交。只要把我们想要的提交挪到最顶端,我们就可以很容易地改变它,然后把它们重新排成我们想要的顺序。","","但唯一的问题就是这样做就要排很多次,有可能造成衍合冲突(rebase conflicts)。下面就看看用另外一种方法 `git cherry-pick` 是怎么做的吧。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["要在心理牢记 cherry-pick 可以从提交树的任何地方拿一个提交来放在 HEAD 上(尽管那个提交不在上游)。","","下面是一个小小的演示:"],command:"git cherry-pick C2",afterMarkdowns:["好滴咧,我们继续"],beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["那么这关呢,和上一关一样要改变提交 `C2`,但你要避免使用 `rebase -i`。自己想想要怎么解决吧,骚年! :D"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 커밋 갖고 놀기 #2","","*만약 이전 레벨의 커밋 갖고 놀기 #1을 풀지 않으셨다면, 계속하기에 앞서서 꼭 풀어보세요*","","이전 레벨에서 보셨듯이 `rebase -i` 명령으로 커밋의 순서를 바꿀 수 있습니다. 정정할 커밋이 바로 직전(top)에 있으면 간단히 --amend로 수정할 수 있고, 그리고 나서 다시 원하는 순서로 되돌려 놓으면 됩니다.","","이번에 한가지 문제는 순서를 꽤 많이 바꿔야한다는 점인데요, 그러다가 리베이스중에 충돌이 날 수 있습니다. 이번에는 다른 방법인 `git cherry-pick`으로 해결해 봅시다."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["git cherry-pick으로 HEAD에다 어떤 커밋이든 떨어 뜨려 놓을 수 있다고 알려드린것 기억나세요? (단, 그 커밋이 현재 가리키고 있는 커밋이 아니어야합니다)","","간단한 데모로 다시 알려드리겠습니다:"],afterMarkdowns:["좋아요! 계속할게요"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["그럼 이번 레벨에서는 아까와 마찬가지로 `C2` 커밋의 내용을 정정하되, `rebase -i`를 쓰지 말고 해보세요. ^.~"]}}]}}}}),e.define("/levels/advanced/multipleParents.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C7","id":"master"},"bugWork":{"target":"C2","id":"bugWork"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C2"],"id":"C5"},"C6":{"parents":["C4","C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',solutionCommand:"git branch bugWork master^^2^",startTree:'{"branches":{"master":{"target":"C7","id":"master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C2"],"id":"C5"},"C6":{"parents":["C4","C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Multiple parents",zh_CN:"多个父提交记录"},hint:{en_US:"Use `git branch bugWork` with a target commit to create the missing reference.",zh_CN:"使用`git branch bugWork`加上一个目标提交记录来创建消失的引用。"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["### Specifying Parents","","Like the `~` modifier, the `^` modifier also accepts an optional number after it.","","Rather than specifying the number of generations to go back (what `~` takes), the modifier on `^` specifies which parent reference to follow from a merge commit. Remember that merge commits have multiple parents, so the path to choose is ambiguous.","",'Git will normally follow the "first" parent upwards from a merge commit, but specifying a number with `^` changes this default behavior.',"","Enough talking, let's see it in action.",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have a merge commit. If we checkout `master^` without the modifier, we will follow the first parent after the merge commit. ","","(*In our visuals, the first parent is positioned directly above the merge commit.*)"],afterMarkdowns:["Easy -- this is what we are all used to."],command:"git checkout master^",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Now let's try specifying the second parent instead..."],afterMarkdowns:["See? We followed the other parent upwards."],command:"git checkout master^2",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["The `^` and `~` modifiers can make moving around a commit tree very powerful:"],afterMarkdowns:["Lightning fast!"],command:"git checkout HEAD~; git checkout HEAD^2; git checkout HEAD~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Even crazier, these modifiers can be chained together! Check this out:"],afterMarkdowns:["The same movement as before, but all in one command."],command:"git checkout HEAD~^2~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"ModalAlert",options:{markdowns:["### Put it to practice","","To complete this level, create a new branch at the specified destination.","","Obviously it would be easy to specify the commit directly (with something like `C6`), but I challenge you to use the modifiers we talked about instead!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["### 选择父提交","","和`~`修改符一样,`^`修改符之后也可以跟一个(可选的)数字。","","这不是用来指定向上返回几代(`~`的作用),`^`后的数字指定跟随合并提交记录的哪一个父提交。还记得一个合并提交有多个父提交吧,所有选择哪条路径不是那么清晰。","",'Git默认选择跟随合并提交的"第一个"父提交,使用`^`后跟一个数字来改变这一默认行为。',"","废话不多说,举个例子。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["这里有一个合并提交。如果不加数字修改符直接切换到`master^`,会回到第一个父提交。","","(*在我们的图示中,第一个父提交是指合并提交正上方的那个父提交。*)"],afterMarkdowns:["OK--这恰好是我们想要的。"],command:"git checkout master^",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["现在来试试选择第二个父提交……"],afterMarkdowns:["看见了吧?我们回到了第二个父提交。"],command:"git checkout master^2",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用`^`和`~`可以自由在在提交树中移动:"],afterMarkdowns:["快若闪电!"],command:"git checkout HEAD~; git checkout HEAD^2; git checkout HEAD~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["再疯狂点,这些修改符支持链式操作!试一下这个:"],afterMarkdowns:["和前面的结果一样,但只用了一条命令。"],command:"git checkout HEAD~^2~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"ModalAlert",options:{markdowns:["### 实践一下","","要完成此关,在指定的目标位置创建一个新的分支。","","很明显可以简单的直接使用提交记录的hash值(比如`C6`),但我要求你使用刚刚讲到的相对引用修饰符!"]}}]}}}}),e.define("/levels/rebase/selectiveRebase.js",function(e,t,n,r,i,s,o){n.level={compareAllBranchesHashAgnostic:!0,disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C5%22%2C%22id%22%3A%22master%22%7D%2C%22one%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22one%22%7D%2C%22two%22%3A%7B%22target%22%3A%22C2%27%27%22%2C%22id%22%3A%22two%22%7D%2C%22three%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22three%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C4%27%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C4%27%27%22%7D%2C%22C3%27%27%22%3A%7B%22parents%22%3A%5B%22C4%27%27%22%5D%2C%22id%22%3A%22C3%27%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C3%27%27%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22two%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout one; git cherry-pick C4 C3 C2; git checkout two; git cherry-pick C5 C4 C3 C2; git branch -f three C2",startTree:'{"branches":{"master":{"target":"C5","id":"master"},"one":{"target":"C1","id":"one"},"two":{"target":"C1","id":"two"},"three":{"target":"C1","id":"three"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C4"],"id":"C5"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{ko:"브랜치 스파게티",en_US:"Branch Spaghetti",ja:"ブランチスパゲッティ",zh_CN:"分支浆糊"},hint:{en_US:"Make sure to do everything in the proper order! Branch one first, then two, then three",ja:"全て正しい順番で処理すること!oneが最初で、次がtwo、最後にthreeを片付ける。",ko:"이 문제를 해결하는 방법은 여러가지가 있습니다! 체리픽(cherry-pick)이 가장 쉽지만 오래걸리는 방법이고, 리베이스(rebase -i)가 빠른 방법입니다",zh_CN:"确保你是按照正确的顺序来操作!先操作分支 `one`, 然后 `two`, 最后才是 `three`"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branch Spaghetti","","WOAHHHhhh Nelly! We have quite the goal to reach in this level.","","Here we have `master` that is a few commits ahead of branches `one` `two` and `three`. For whatever reason, we need to update these three other branches with modified versions of the last few commits on master.","","Branch `one` needs a re-ordering and a deletion of `C5`. `two` needs pure reordering, and `three` only needs one commit!","","We will let you figure out how to solve this one -- make sure to check out our solution afterwards with `show solution`. "]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ブランチスパゲッティ","","なんということでしょう。今回のレベルクリアのために、やることがたくさんあります。","","いま`master`が指しているコミットの数個前のコミットに、ブランチ`one`、`two`それから`three`があります。何か事情があって、これらの3つのブランチをmasterが指している最新の状態に更新したいケースを考えます。","","ブランチ`one`に対しては、順序の変更と`C5`の削除が必要です。`two`では順序の変更のみ、`three`に対しては1回だけコミットすればOKです。","","`show solution`コマンドで模範解答を確認できますから、こちらも利用してください。 "]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branch Spaghetti","","哇塞大神!这关我们要来点不同的!","","现在我们的 `master` 分支是比 `one` `two` 和 `three` 要多几个提交。出于某种原因,我们需要把其他三个分支更新到 master 分支上新近的几个不同提交上。(update these three other brances with modified versions of the last few commits on master)","","分支 `one` 需要重新排序和撤销, `two` 需要完全重排,而 `three` 只需要提交一次。","","慢慢摸索会找到答案的 —— 你完事记得用 `show solution` 看看我们的答案哦。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 브랜치 스파게티","","음, 이번에는 만만치 않습니다!","","여기 `master` 브랜치의 몇 번 이전 커밋에 `one`, `two`,`three` 총 3개의 브랜치가 있습니다. 어떤 이유인지는 몰라도, master의 최근 커밋 몇 개를 나머지 세 개의 브랜치에 반영하려고 합니다.","","`one` 브랜치는 순서를 바꾸고 `C5`커밋을 삭제하고, `two`브랜치는 순서만 바꾸며, `three`브랜치는 하나의 커밋만 가져옵시다!","","자유롭게 이 문제를 풀어보시고 나서 `show solution`명령어로 모범 답안을 확인해보세요."]}}]}}}}),e.define("/src/js/views/levelDropdownView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../intl"),h=e("../log"),p=e("../util/keyboard").KeyboardListener,d=e("../app"),v=e("../views").ModalTerminal,m=e("../views").ContainedBase,g=e("../views").BaseView,y=m.extend({tagName:"div",className:"levelDropdownView box vertical",template:u.template($("#level-dropdown-view").html()),initialize:function(e){e=e||{},this.JSON={},this.navEvents=u.clone(f.Events),this.navEvents.on("clickedID",u.debounce(u.bind(this.loadLevelID,this),300,!0)),this.navEvents.on("negative",this.negative,this),this.navEvents.on("positive",this.positive,this),this.navEvents.on("left",this.left,this),this.navEvents.on("right",this.right,this),this.navEvents.on("up",this.up,this),this.navEvents.on("down",this.down,this),this.keyboardListener=new p({events:this.navEvents,aliasMap:{esc:"negative",enter:"positive"},wait:!0}),this.sequences=d.getLevelArbiter().getSequences(),this.sequenceToLevels=d.getLevelArbiter().getSequenceToLevels(),this.container=new v({title:c.str("select-a-level")}),this.render(),d.getEvents().on("resetMapSolved",this.render,this),d.getEvents().on("localeChanged",this.render,this),e.wait||this.show()},render:function(){y.__super__.render.apply(this,arguments),this.buildSequences()},positive:function(){if(!this.selectedID)return;this.loadLevelID(this.selectedID)},left:function(){if(this.turnOnKeyboardSelection())return;this.leftOrRight(-1)},leftOrRight:function(e){this.deselectIconByID(this.selectedID),this.selectedIndex=this.wrapIndex(this.selectedIndex+e,this.getCurrentSequence()),this.selectedID=this.getSelectedID(),this.selectIconByID(this.selectedID)},right:function(){if(this.turnOnKeyboardSelection())return;this.leftOrRight(1)},up:function(){if(this.turnOnKeyboardSelection())return;this.selectedSequence=this.getPreviousSequence(),this.downOrUp()},down:function(){if(this.turnOnKeyboardSelection())return;this.selectedSequence=this.getNextSequence(),this.downOrUp()},downOrUp:function(){this.selectedIndex=this.boundIndex(this.selectedIndex,this.getCurrentSequence()),this.deselectIconByID(this.selectedID),this.selectedID=this.getSelectedID(),this.selectIconByID(this.selectedID)},turnOnKeyboardSelection:function(){return this.selectedID?!1:(this.selectFirst(),!0)},turnOffKeyboardSelection:function(){if(!this.selectedID)return;this.deselectIconByID(this.selectedID),this.selectedID=undefined,this.selectedIndex=undefined,this.selectedSequence=undefined},wrapIndex:function(e,t){return e=e>=t.length?0:e,e=e<0?t.length-1:e,e},boundIndex:function(e,t){return e=e>=t.length?t.length-1:e,e=e<0?0:e,e},getNextSequence:function(){var e=this.getSequenceIndex(this.selectedSequence),t=this.wrapIndex(e+1,this.sequences);return this.sequences[t]},getPreviousSequence:function(){var e=this.getSequenceIndex(this.selectedSequence),t=this.wrapIndex(e-1,this.sequences);return this.sequences[t]},getSequenceIndex:function(e){var t=this.sequences.indexOf(e);if(t<0)throw new Error("didnt find");return t},getIndexForID:function(e){return d.getLevelArbiter().getLevel(e).index},selectFirst:function(){var e=this.sequenceToLevels[this.sequences[0]][0].id;this.selectIconByID(e),this.selectedIndex=0,this.selectedSequence=this.sequences[0]},getCurrentSequence:function(){return this.sequenceToLevels[this.selectedSequence]},getSelectedID:function(){return this.sequenceToLevels[this.selectedSequence][this.selectedIndex].id},selectIconByID:function(e){this.toggleIconSelect(e,!0)},deselectIconByID:function(e){this.toggleIconSelect(e,!1)},toggleIconSelect:function(e,t){this.selectedID=e;var n="#levelIcon-"+e;$(n).toggleClass("selected",t)},negative:function(){this.hide()},testOption:function(e){return this.currentCommand&&(new RegExp("--"+e)).test(this.currentCommand.get("rawStr"))},show:function(e,t){this.currentCommand=t,this.updateSolvedStatus(),this.showDeferred=e,this.keyboardListener.listen(),y.__super__.show.apply(this)},hide:function(){this.showDeferred&&this.showDeferred.resolve(),this.showDeferred=undefined,this.keyboardListener.mute(),this.turnOffKeyboardSelection(),y.__super__.hide.apply(this)},loadLevelID:function(e){if(!this.testOption("noOutput")){d.getEventBaton().trigger("commandSubmitted","level "+e);var t=d.getLevelArbiter().getLevel(e),n=t.name.en_US;h.levelSelected(n)}this.hide()},updateSolvedStatus:function(){u.each(this.seriesViews,function(e){e.updateSolvedStatus()},this)},buildSequences:function(){this.seriesViews=[],u.each(this.sequences,function(e){this.seriesViews.push(new b({destination:this.$el,name:e,navEvents:this.navEvents}))},this)}}),b=g.extend({tagName:"div",className:"seriesView box flex1 vertical",template:u.template($("#series-view").html()),events:{"click div.levelIcon":"click","mouseenter div.levelIcon":"enterIcon","mouseleave div.levelIcon":"leaveIcon"},initialize:function(e){this.name=e.name||"intro",this.navEvents=e.navEvents,this.info=d.getLevelArbiter().getSequenceInfo(this.name),this.levels=d.getLevelArbiter().getLevelsInSequence(this.name),this.levelIDs=[],u.each(this.levels,function(e){this.levelIDs.push(e.id)},this),this.destination=e.destination,this.JSON={displayName:c.getIntlKey(this.info,"displayName"),about:c.getIntlKey(this.info,"about")||" ",ids:this.levelIDs},this.render(),this.updateSolvedStatus()},updateSolvedStatus:function(){var e=this.$("div.levelIcon").each(function(e,t){var n=$(t).attr("data-id");$(t).toggleClass("solved",d.getLevelArbiter().isLevelSolved(n))})},getEventID:function(e){var t=e.target;return $(t).attr("data-id")},resetAbout:function(){this.$("p.about").text(c.getIntlKey(this.info,"about")).css("font-style","inherit")},setAbout:function(e){this.$("p.about").text(e).css("font-style","italic")},enterIcon:function(e){var t=this.getEventID(e),n=d.getLevelArbiter().getLevel(t);this.setAbout(c.getName(n))},leaveIcon:function(){this.resetAbout()},click:function(e){var t=this.getEventID(e);this.navEvents.trigger("clickedID",t)}});n.LevelDropdownView=y}),e.define("/src/js/views/commandViews.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../models/collections").CommandEntryCollection,l=e("../app"),c=e("../models/commandModel").Command,h=e("../models/commandModel").CommandEntry,p=e("../util/errors"),d=p.Warning,v=e("../util"),m=e("../log"),g=e("../util/keyboard"),y=a.View.extend({initialize:function(e){l.getEvents().on("commandSubmittedPassive",this.addToCommandHistory,this),this.commands=new f,this.commands.fetch({success:u.bind(function(){var e=[];this.commands.each(function(t){e.push(t)}),e.reverse(),this.commands.reset(),u.each(e,function(e){this.commands.add(e)},this)},this)}),this.index=-1,this.commandParagraph=this.$("#prompt p.command")[0],this.commandCursor=this.$("#prompt span.cursor")[0],this.focus(),l.getEvents().on("rollupCommands",this.rollupCommands,this),l.getEventBaton().stealBaton("keydown",this.onKeyDown,this),l.getEventBaton().stealBaton("keyup",this.onKeyUp,this)},events:{"blur #commandTextField":"hideCursor","focus #commandTextField":"showCursor"},blur:function(){this.hideCursor()},focus:function(){this.$("#commandTextField").focus(),this.showCursor()},hideCursor:function(){this.toggleCursor(!1)},showCursor:function(){this.toggleCursor(!0)},toggleCursor:function(e){$(this.commandCursor).toggleClass("shown",e)},onKeyDown:function(e){var t=e.target;this.updatePrompt(t)},onKeyUp:function(e){this.onKeyDown(e);var t={enter:u.bind(function(){this.submit()},this),up:u.bind(function(){this.commandSelectChange(1)},this),down:u.bind(function(){this.commandSelectChange(-1)},this)},n=g.mapKeycodeToKey(e.which||e.keyCode);t[n]!==undefined&&(e.preventDefault(),t[n](),this.onKeyDown(e))},badHtmlEncode:function(e){return e.replace(/&/g,"&").replace(/=this.commands.length||this.index<0){this.clear(),this.index=-1;return}var t=this.commands.toArray()[this.index].get("text");this.setTextField(t)},clearLocalStorage:function(){this.commands.each(function(e){a.sync("delete",e,function(){})},this)},setTextField:function(e){this.$("#commandTextField").val(e)},clear:function(){this.setTextField("")},submit:function(){var e=this.$("#commandTextField").val().replace("\n","");this.clear(),this.submitCommand(e),this.index=-1},rollupCommands:function(e){var t=this.commands.toArray().slice(1,Number(e)+1);t.reverse();var n="";u.each(t,function(e){n+=e.get("text")+";"},this);var r=new h({text:n});this.commands.unshift(r),a.sync("create",r,function(){})},addToCommandHistory:function(e){var t=e.length&&this.index===-1||e.length&&this.index!==-1&&this.commands.toArray()[this.index].get("text")!==e;if(!t)return;var n=new h({text:e});this.commands.unshift(n),a.sync("create",n,function(){}),this.commands.length>100&&this.clearLocalStorage(),m.commandEntered(e)},submitCommand:function(e){l.getEventBaton().trigger("commandSubmitted",e)}}),b=a.View.extend({tagName:"div",model:c,template:u.template($("#command-template").html()),events:{click:"clicked"},clicked:function(e){},initialize:function(){this.model.bind("change",this.wasChanged,this),this.model.bind("destroy",this.remove,this)},wasChanged:function(e,t){var n=t.changes,r=u.keys(n);u.difference(r,["status"]).length===0?this.updateStatus():this.render()},updateStatus:function(){var e=["inqueue","processing","finished"],t={};u.each(e,function(e){t[e]=!1}),t[this.model.get("status")]=!0;var n=this.$("p.commandLine");u.each(t,function(e,t){n.toggleClass(t,e)})},render:function(){var e=u.extend({resultType:"",result:"",formattedWarnings:this.model.getFormattedWarnings()},this.model.toJSON());return this.$el.html(this.template(e)),this},remove:function(){$(this.el).hide()}}),w=a.View.extend({initialize:function(e){this.collection=e.collection,this.collection.on("add",this.addOne,this),this.collection.on("reset",this.addAll,this),this.collection.on("all",this.render,this),this.collection.on("change",this.scrollDown,this),l.getEvents().on("commandScrollDown",this.scrollDown,this),l.getEvents().on("clearOldCommands",this.clearOldCommands,this)},addWarning:function(e){var t=new d({msg:e}),n=new c({error:t,rawStr:"Warning:"});this.collection.add(n)},clearOldCommands:function(){var e=[];this.collection.each(function(t){t.get("status")!=="inqueue"&&t.get("status")!=="processing"&&e.push(t)},this),u.each(e,function(e){e.destroy()},this),this.scrollDown()},scrollDown:function(){var e=$("#commandDisplay")[0],t=$("#terminal")[0],n=e.clientHeight>t.clientHeight||$(window).height()"]}},{type:"ModalAlert",options:{markdowns:["## Git 명령어","","연습 모드에서 쓸 수 있는 다양한 git명령어는 다음과 같습니다",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## 공유해주세요!","","`export tree` 와 `import tree`로 여러분의 친구들에게 트리를 공유해주세요","","훌륭한 학습 자료가 있으신가요? `build level`로 레벨을 만들어 보시거나, 친구의 레벨을 `import level`로 가져와서 실험해보세요","","이제 레슨을 시작해봅시다..."]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Bienvenue sur LearnGitBranching!","","Cette application a été conçue pour aider les débutants à saisir ","les puissants concepts derrière les branches en travaillant ","avec git. Nous espérons que vous apprécierez cette application et ","que vous apprendrez peut-être quelque chose d'intéressant !","","# Démo !","","Si vous n'avez pas vu la démo, vous pouvez le faire là :","","[http://pcottle.github.io/learnGitBranching/?demo](http://pcottle.github.io/learnGitBranching/?demo)","","Agacé par ce dialogue ? Ajoutez `?NODEMO` à l'URL pour le supprimer, en lien ci-dessous pour votre commodité :","","[http://pcottle.github.io/learnGitBranching/?NODEMO](?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## Commandes Git","","Il existe une large variété de commandes git disponibles dans le mode bac à sable. Sont inclues",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## Partager, c'est se soucier!","","Partagez des arbres avec vous amis via `export tree` et `import tree`","","Vous avez une grande leçon à partager ? Essayez de construire un niveau avec `build level` ou essayez le niveau d'un ami avec `import level`","","Pour voir la gamme complète des commandes, tapez `show commands`. Il y a quelques perles telles que `undo` et `reset`","","Mais tout de suite commencez sur les `levels`…"]}}]}}),e.define("/src/js/util/mock.js",function(e,t,n,r,i,s,o){n.mock=function(e){var t={},n=function(){};for(var r in e.prototype)t[r]=n;return t}}),e.define("sys",function(e,t,n,r,i,s,o){t.exports=e("util")}),e.define("child_process",function(e,t,n,r,i,s,o){n.spawn=function(){},n.exec=function(){}}),e.define("/src/js/visuals/tree.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({removeKeys:function(e){u.each(e,function(e){this.get(e)&&this.get(e).remove()},this)},animateAttrKeys:function(e,t,n,r){e=u.extend({},{include:["circle","arrow","rect","path","text"],exclude:[]},e||{});var i=this.getAttributes();u.each(e.include,function(e){i[e]=u.extend({},i[e],t)}),u.each(e.exclude,function(e){delete i[e]}),this.animateToAttr(i,n,r)}});n.VisBase=f}),e.define("/src/js/git/headless.js",function(e,t,n,r,i,s,o){function E(){var e={},t=function(){return f.defer().promise};for(var n in c)e[n]=t;return e.playRefreshAnimationAndFinish=function(e,t){console.log("trying to finish"),t.thenFinish(f.defer().promise)},e}var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("../git").GitEngine,c=e("../visuals/animation/animationFactory").AnimationFactory,h=e("../visuals").GitVisuals,p=e("../git/treeCompare").TreeCompare,d=e("../util/eventBaton").EventBaton,v=e("../models/collections"),m=v.CommitCollection,g=v.BranchCollection,y=e("../models/commandModel").Command,b=e("../util/mock").mock,w=e("../util"),S=function(){this.init()};S.prototype.init=function(){this.commitCollection=new m,this.branchCollection=new g;var e=E(),t=b(h);this.gitEngine=new l({collection:this.commitCollection,branches:this.branchCollection,gitVisuals:t,animationFactory:e,eventBaton:new d}),this.gitEngine.init()},S.prototype.sendCommand=function(e){w.splitTextCommand(e,function(e){var t=new y({rawStr:e});this.gitEngine.dispatch(t,f.defer())},this)},n.HeadlessGit=S}),e.define("/src/js/app/index.js",function(e,t,n,r,i,s,o){function E(){var t=e("../views"),n=e("../models/collections"),r=e("../views/commandViews"),i=new t.MainHelperBar;this.commandCollection=new n.CommandCollection,this.commandBuffer=new n.CommandBuffer({collection:this.commandCollection}),this.commandPromptView=new r.CommandPromptView({el:$("#commandLineBar")}),this.commandLineHistoryView=new r.CommandLineHistoryView({el:$("#commandLineHistory"),collection:this.commandCollection})}var u=e("underscore"),a=e("backbone"),f=e("../util/constants"),l=e("../util"),c=u.clone(a.Events),h,p,d,v,m,g=function(){var t=e("../level/sandbox").Sandbox,n=e("../level").Level,r=e("../util/eventBaton").EventBaton,i=e("../level/arbiter").LevelArbiter,s=e("../views/levelDropdownView").LevelDropdownView;d=new r,h=new E,p=new t,v=new i,m=new s({wait:!0}),c.on("localeChanged",y),b(d),w(p)},y=function(){if(!window.$)return;$("span.intl-aware").each(function(t,n){var r=e("../intl"),i=$(n).attr("data-intl");$(n).text(r.str(i).toUpperCase())})},b=function(e){var t=function(){$("#commandTextField").focus()};t(),$(window).focus(function(t){e.trigger("windowFocus",t)}),$(document).click(function(t){e.trigger("documentClick",t)}),$(document).bind("keydown",function(t){e.trigger("docKeydown",t)}),$(document).bind("keyup",function(t){e.trigger("docKeyup",t)}),$(window).on("resize",function(e){c.trigger("resize",e)}),e.stealBaton("docKeydown",function(){}),e.stealBaton("docKeyup",function(){}),e.stealBaton("windowFocus",t),e.stealBaton("documentClick",t);var n=function(t){return function(){var n=[t];u.each(arguments,function(e){n.push(e)}),e.trigger.apply(e,n)}};$("#commandTextField").on("keydown",n("keydown")),$("#commandTextField").on("keyup",n("keyup")),$(window).trigger("resize")},w=function(e){var t=l.parseQueryString(window.location.href);t.hasOwnProperty("demo")?e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",["git commit; git checkout -b bugFix C1; git commit; git merge master; git checkout master; git commit; git rebase bugFix;","delay 1000; reset;","level rebase1 --noFinishDialog --noStartCommand --noIntroDialog;","delay 2000; show goal; delay 1000; hide goal;","git checkout bugFix; git rebase master; git checkout side; git rebase bugFix;","git checkout another; git rebase side; git rebase another master;","help; levels"].join(""))}):t.hasOwnProperty("NODEMO")||e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",["git help;","delay 1000;","help;","levels"].join(""))}),t.locale!==undefined&&t.locale.length&&(f.GLOBAL.locale=t.locale,c.trigger("localeChanged"));if(t.command){var n=unescape(t.command);e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",n)})}(/(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent)||/android/i.test(navigator.userAgent))&&e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted","mobile alert")})};e("../util").isBrowser()&&$(document).ready(g),n.getEvents=function(){return c},n.getSandbox=function(){return p},n.getEventBaton=function(){return d},n.getCommandUI=function(){return h},n.getLevelArbiter=function(){return v},n.getLevelDropdown=function(){return m},n.init=g}),e("/src/js/app/index.js"),e.define("/src/js/dialogs/confirmShowSolution.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Are you sure you want to see the solution?","","I believe in you! You can do it"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 确定要看答案吗?","","哥相信你!你可以的"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Êtes-vous sûr de vouloir voir la solution ?","","Je crois en vous ! Vous pouvez le faire"]}}]}}),e("/src/js/dialogs/confirmShowSolution.js"),e.define("/src/js/dialogs/levelBuilder.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Welcome to the level builder!","","Here are the main steps:",""," * Set up the initial environment with git commands"," * Define the starting tree with ```define start```"," * Enter the series of git commands that compose the (optimal) solution"," * Define the goal tree with ```define goal```. Defining the goal also defines the solution"," * Optionally define a hint with ```define hint```"," * Edit the name with ```define name```"," * Optionally define a nice start dialog with ```edit dialog```"," * Enter the command ```finish``` to output your level JSON!"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 欢迎使用关卡生成器!","","主要步骤如下:",""," * 使用 git 命令布置好初始环境"," * 使用 ```define start``` 命令定义起始树"," * 输入一系列 git 命令,编好答案"," * 使用 ```define goal``` 命令定义目标树。定义目标的同时定义答案"," * 还可以用 ```define hint``` 命令定义一个提示"," * 用 ```define name``` 修改名称"," * 还可以用 ```edit dialog``` 定义一个漂亮的开始对话框"," * 输入 ```finish``` 就可以输出你的关卡数据(JSON)了!"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Bienvenue dans l'éditeur niveaux !","","Voici les étapes principales :",""," * Mettez en place l'environnement initial avec des commandes git"," * Définissez l'arbre de départ avec ```define start```"," * Saisissez la série de commandes git qui composent la solution (optimale)"," * Définissez l'arbre cible avec ```define goal```. Cela définit aussi la solution"," * Optionnellement, définissez un indice avec ```define hint```"," * Changez le nom avec ```define name```"," * Optionellement, definissez un joli dialogue de départ avec ```edit dialog```"," * Entrez la commande ```finish``` pour délivrer votre niveau JSON!"]}}]}}),e("/src/js/dialogs/levelBuilder.js"),e.define("/src/js/dialogs/nextLevel.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Great Job!!","","You solved the level in *{numCommands}* command(s); ","our solution uses {best}."]}}],ja:[{type:"ModalAlert",options:{markdowns:["## 完成!","","あなたは*{numCommands}*回のコマンドでこの課題をクリアしました; ","模範解答では{best}回です。"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 碉堡了!","","你用 *{numCommands}* 条命令搞定了这一关;我们的答案要用 {best}。"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Beau Travail!!","","Vous avez résolu le niveau en *{numCommands}* commande(s); ","notre solution le fait en {best}."]}}]}}),e("/src/js/dialogs/nextLevel.js"),e.define("/src/js/dialogs/sandbox.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Welcome to LearnGitBranching!","","This application is designed to help beginners grasp ","the powerful concepts behind branching when working ","with git. We hope you enjoy this application and maybe ","even learn something!","","# Demo!","","If you have not seen the demo, please check it out here:","","[http://pcottle.github.io/learnGitBranching/?demo](http://pcottle.github.io/learnGitBranching/?demo)","","Annoyed at this dialog? Append `?NODEMO` to the url to get rid of it, linked below for convenience:","","[http://pcottle.github.io/learnGitBranching/?NODEMO](?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## Git commands","","You have a large variety of git commands available in sandbox mode. These include",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## Sharing is caring!","","Share trees with your friends via `export tree` and `import tree`","","Have a great lesson to share? Try building a level with `build level` or try out a friend's level with `import level`","","To see the full range of commands, try `show commands`. There are some gems like `undo` and `reset`","","For now let's get you started on the `levels`..."]}}],ja:[{type:"ModalAlert",options:{markdowns:["## LearnGitBranchingへようこそ","","gitのパワフルなブランチ機能のコンセプトが ","学びやすくなるようにこのアプリケーションを作りました。 ","このアプリケーションを楽しんで使って頂いて、 ","何かを学習して頂けたなら嬉しいです。","","# とりあえず触ってみたい方へ:","","簡単なデモを用意してあるので、もしよければこちらもご覧ください:","","[http://remore.github.io/learnGitBranching-ja/?demo](http://remore.github.io/learnGitBranching-ja/?demo)","","このダイアログ自体を省略するには、以下のようにURLの末尾にクエリストリング`?NODEMO`を付加してアクセスしてください。","","[http://remore.github.io/learnGitBranching-ja/?NODEMO](http://remore.github.io/learnGitBranching-ja/?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## ここで学べるGitのオペレーション","","ここでは、下記の種類のgitコマンドを学ぶことができます。",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## 学習した内容を共有できます","","画面左のコマンドプロンプトから`export tree`や`import tree`とタイプすることで、gitのツリー構造を友達に送ることができます","","何か教材になるようなケースはご存知ないでしょうか。`build level`で課題を作成したり、`import level`で他の人の課題に挑戦してみてください。","","それでは教材の選択画面に進んでみることにします。"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 欢迎光临 LearnGitBranching!","","本应用旨在帮助初学者领会 git 分支背后的强大概念。","希望你能喜欢这个应用,并学到知识!","","# 演示!","","如果你还没看过演示,请到此查看:","","[http://pcottle.github.io/learnGitBranching/?demo](http://pcottle.github.io/learnGitBranching/?demo)","","厌烦这个对话框? 在 URL 后头加上 `?NODEMO` 就看不到它了,也可以直接点下边这个链接:","","[http://pcottle.github.io/learnGitBranching/?NODEMO](http://pcottle.github.io/learnGitBranching/?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## Git 命令","","在沙盒模式里,你有好多命令可用。 包括:",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## 分享即关怀","","使用 `export tree` 和 `import tree` 与朋友分享 Git 树","","有个好课程可以分享?试试用 `build level` 创建一个关卡,或者 `import level` 试试朋友的。","","言归正传,让我们先从 `levels` 开始……"]}}],ko:[{type:"ModalAlert",options:{markdowns:["## Git 브랜치 배우기를 시작합니다!","","이 애플리케이션은 git을 쓸 때 필요한 브랜치에 대한 개념을","탄탄히 잡게끔 도와드리기 위해 만들었습니다. 재밌게 사용해주시기를","바라며, 무언가를 배워가신다면 더 기쁘겠습니다!","","이 애플리케이션은 [Peter Cottle](https://github.io/pcottle)님의 [LearnGitBranching](http://pcottle.github.io/learnGitBranching/)를 번역한 것입니다.","아래 데모를 먼저 보셔도 좋습니다.","",""]}},{type:"ModalAlert",options:{markdowns:["## Git 명령어","","연습 모드에서 쓸 수 있는 다양한 git명령어는 다음과 같습니다",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## 공유해주세요!","","`export tree` 와 `import tree`로 여러분의 친구들에게 트리를 공유해주세요","","훌륭한 학습 자료가 있으신가요? `build level`로 레벨을 만들어 보시거나, 친구의 레벨을 `import level`로 가져와서 실험해보세요","","이제 레슨을 시작해봅시다..."]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Bienvenue sur LearnGitBranching!","","Cette application a été conçue pour aider les débutants à saisir ","les puissants concepts derrière les branches en travaillant ","avec git. Nous espérons que vous apprécierez cette application et ","que vous apprendrez peut-être quelque chose d'intéressant !","","# Démo !","","Si vous n'avez pas vu la démo, vous pouvez le faire là :","","[http://pcottle.github.io/learnGitBranching/?demo](http://pcottle.github.io/learnGitBranching/?demo)","","Agacé par ce dialogue ? Ajoutez `?NODEMO` à l'URL pour le supprimer, en lien ci-dessous pour votre commodité :","","[http://pcottle.github.io/learnGitBranching/?NODEMO](?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## Commandes Git","","Il existe une large variété de commandes git disponibles dans le mode bac à sable. Sont inclues",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## Partager, c'est se soucier!","","Partagez des arbres avec vous amis via `export tree` et `import tree`","","Vous avez une grande leçon à partager ? Essayez de construire un niveau avec `build level` ou essayez le niveau d'un ami avec `import level`","","Pour voir la gamme complète des commandes, tapez `show commands`. Il y a quelques perles telles que `undo` et `reset`","","Mais tout de suite commencez sur les `levels`…"]}}]}}),e("/src/js/dialogs/sandbox.js"),e.define("/src/js/git/commands.js",function(e,t,n,r,i,s,o){function y(e,t){this.method=e,this.rawOptions=t,this.supportedMap=this.getMasterOptionMap()[e];if(this.supportedMap===undefined)throw new Error("No option map for "+e);this.generalArgs=[],this.explodeAndSet()}var u=e("underscore"),a=e("../intl"),f=e("../util/errors"),l=f.CommandProcessError,c=f.GitError,h=f.Warning,p=f.CommandResult,d={"git commit":/^(gc|git ci)($|\s)/,"git add":/^ga($|\s)/,"git checkout":/^(go|git co)($|\s)/,"git rebase":/^gr($|\s)/,"git branch":/^(gb|git br)($|\s)/,"git status":/^(gst|gs|git st)($|\s)/,"git help":/^git$/},v=[[/^git help($|\s)/,function(){var e=[a.str("git-version"),"
",a.str("git-usage"),u.escape(a.str("git-usage-command")),"
",a.str("git-supported-commands"),"
"],t=y.prototype.getMasterOptionMap();u.each(t,function(t,n){e.push("git "+n),u.each(t,function(t,n){e.push(" "+n)},this)},this);var n=e.join("\n");throw n=n.replace(/\t/g,"   "),new p({msg:n})}]],m={"git commit":/^git +commit($|\s)/,"git add":/^git +add($|\s)/,"git checkout":/^git +checkout($|\s)/,"git rebase":/^git +rebase($|\s)/,"git reset":/^git +reset($|\s)/,"git branch":/^git +branch($|\s)/,"git revert":/^git +revert($|\s)/,"git log":/^git +log($|\s)/,"git merge":/^git +merge($|\s)/,"git show":/^git +show($|\s)/,"git status":/^git +status($|\s)/,"git cherry-pick":/^git +cherry-pick($|\s)/,"git fakeTeamwork":/^git +fakeTeamwork($|\s)/,"git fetch":/^git +fetch *?$/,"git pull":/^git +pull($|\s)/,"git push":/^git +push($|\s)/,"git clone":/^git +clone *?$/},g=function(e){var t,n;u.each(m,function(r,i){r.exec(e)&&(n=e.slice(i.length+1),t=i.slice("git ".length))});if(!t)return!1;var r=new y(t,n);return{toSet:{generalArgs:r.generalArgs,supportedMap:r.supportedMap,method:t,options:n,eventName:"processGitCommand"}}};y.prototype.getMasterOptionMap=function(){return{commit:{"--amend":!1,"-a":!1,"-am":!1,"-m":!1},status:{},log:{},add:{},"cherry-pick":{},branch:{"-d":!1,"-D":!1,"-f":!1,"-a":!1,"-r":!1,"--contains":!1},checkout:{"-b":!1,"-B":!1,"-":!1},reset:{"--hard":!1,"--soft":!1},merge:{},rebase:{"-i":!1},revert:{},show:{},clone:{},fetch:{},pull:{"--rebase":!1},push:{},fakeTeamwork:{}}},y.prototype.explodeAndSet=function(){var e=this.rawOptions.match(/('.*?'|".*?"|\S+)/g)||[];for(var t=0;t9&&(e=e.slice(0,9),this.command.addWarning(l.str("branch-name-short",{branch:e}))),e},y.prototype.validateAndMakeBranch=function(e,t){e=this.validateBranchName(e);if(this.refs[e])throw new v({msg:l.str("bad-branch-name",{branch:name})});this.makeBranch(e,t)},y.prototype.makeBranch=function(e,t){var n=new w({target:t,id:e});return this.branchCollection.add(n),this.refs[n.get("id")]=n,n},y.prototype.getHead=function(){return u.clone(this.HEAD)},y.prototype.getBranches=function(){var e=[];return this.branchCollection.each(function(t){e.push({id:t.get("id"),selected:this.HEAD.get("target")===t,target:t.get("target"),remote:t.getIsRemote(),obj:t})},this),e},y.prototype.getRemoteBranches=function(){var e=this.getBranches();return u.filter(e,function(e){return e.remote===!0})},y.prototype.getLocalBranches=function(){var e=this.getBranches();return u.filter(e,function(e){return e.remote===!1})},y.prototype.printBranchesWithout=function(e){var t=this.getUpstreamBranchSet(),n=this.getCommitFromRef(e).get("id"),r=[];u.each(t[n],function(e){e.selected=this.HEAD.get("target").get("id")==e.id,r.push(e)},this),this.printBranches(r)},y.prototype.printBranches=function(e){var t="";throw u.each(e,function(e){t+=(e.selected?"* ":"")+e.id+"\n"}),new m({msg:t})},y.prototype.getUniqueID=function(){var e=this.uniqueId("C"),t=u.bind(function(e){return this.refs[e]?!0:this.origin&&this.origin.refs[e]?!0:!1},this);while(t(e))e=this.uniqueId("C");return e},y.prototype.makeCommit=function(e,t,n){t||(t=this.getUniqueID());var r=new E(u.extend({parents:e,id:t,gitVisuals:this.gitVisuals},n||{}));return this.refs[r.get("id")]=r,this.commitCollection.add(r),r},y.prototype.acceptNoGeneralArgs=function(){if(this.generalArgs.length)throw new v({msg:l.str("git-error-no-general-args")})},y.prototype.validateArgBounds=function(e,t,n,r){var i=r===undefined?"git "+this.command.get("method"):this.command.get("method")+" "+r+" ";i="with "+i;if(e.lengthn)throw new v({msg:l.str("git-error-args-many",{upper:String(n),what:i})})},y.prototype.oneArgImpliedHead=function(e,t){this.validateArgBounds(e,0,1,t),e.length===0&&e.push("HEAD")},y.prototype.twoArgsImpliedHead=function(e,t){this.validateArgBounds(e,1,2,t),e.length==1&&e.push("HEAD")},y.prototype.revertStarter=function(){this.validateArgBounds(this.generalArgs,1,NaN),this.revert(this.generalArgs)},y.prototype.revert=function(e){var t=u.map(e,function(e){return this.getCommitFromRef(e)},this),n=f.defer(),r=n.promise,i=this.resolveID("HEAD");r=c.highlightEachWithPromise(r,t,i);var s=this.getCommitFromRef("HEAD"),o=u.bind(function(e){var t=this.rebaseAltID(e.get("id")),n=l.str("git-revert-msg",{oldCommit:this.resolveName(e),oldMsg:e.get("commitMessage")}),r=this.makeCommit([s],t,{commitMessage:n});return s=r,c.playCommitBirthPromiseAnimation(r,this.gitVisuals)},this);u.each(t,function(e){r=r.then(function(){return o(e)})},this),r=r.then(u.bind(function(){return this.setTargetLocation("HEAD",s),c.playRefreshAnimation(this.gitVisuals)},this)),this.animationQueue.thenFinish(r,n)},y.prototype.resetStarter=function(){if(this.commandOptions["--soft"])throw new v({msg:l.str("git-error-staging")});this.commandOptions["--hard"]&&(this.command.addWarning(l.str("git-warning-hard")),this.generalArgs=this.generalArgs.concat(this.commandOptions["--hard"])),this.validateArgBounds(this.generalArgs,1,1);if(this.getDetachedHead())throw new v({msg:l.str("git-error-reset-detached")});this.reset(this.generalArgs[0])},y.prototype.reset=function(e){this.setTargetLocation("HEAD",this.getCommitFromRef(e))},y.prototype.cherrypickStarter=function(){this.validateArgBounds(this.generalArgs,1,Number.MAX_VALUE);var e=this.getUpstreamSet("HEAD"),t=u.map(this.generalArgs,function(t){var n=this.getCommitFromRef(t);if(e[n.get("id")])throw new v({msg:l.str("git-error-already-exists",{commit:n.get("id")})});return n},this),n=f.defer(),r=n.promise,i=this.resolveID("HEAD");r=c.highlightEachWithPromise(r,t,i);var s=u.bind(function(e){var t=this.cherrypick(e);return c.playCommitBirthPromiseAnimation(t,this.gitVisuals)},this);u.each(t,function(e){r=r.then(function(){return s(e)})},this),this.animationQueue.thenFinish(r,n)},y.prototype.checkUpstreamOfSource=function(e,t,n,r,i){var s=t.getUpstreamSet(r),o=e.getCommitFromRef(n).get("id");if(!s[o])throw new v({msg:i||l.str("git-error-origin-fetch-no-ff")})},y.prototype.getTargetGraphDifference=function(e,t,n,r,i){i=i||{},r=t.resolveID(r);var s=e.getUpstreamSet(n),o=t.getCommitFromRef(r),a=t.exportTree(),f=a.commits[o.get("id")];if(e.refs[f.id]){if(i.dontThrowOnNoFetch)return[];throw new v({msg:l.str("git-error-origin-fetch-uptodate")})}f.depth=0;var c=[],h=[f],p=function(e){if(s[e])return;var t=a.commits[e];t.depth=d.depth+1,h.push(t)};while(h.length){var d=h.pop();c.push(d),u.each(d.parents,p)}var m={},g=[];return u.forEach(c,function(e){if(m[e.id])return;m[e.id]=!0,g.push(e)}),g.sort(function(e,t){return t.depth-e.depth})},y.prototype.pushStarter=function(e){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.push()},y.prototype.push=function(e){e=e||{};var t=this.refs.master,n=this.origin.refs.master;this.checkUpstreamOfSource(this,this.origin,n,t,l.str("git-error-origin-push-no-ff"));var r=this.getTargetGraphDifference(this.origin,this,n,t),i=u.bind(function(e,t){var n=u.map(t,function(e){return this.origin.refs[e]},this);return this.origin.makeCommit(n,e)},this),s=u.bind(function(e,t){var n=i(e,t);return c.playCommitBirthPromiseAnimation(n,this.origin.gitVisuals)},this),o=f.defer(),a=o.promise;u.each(r,function(e){a=a.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.refs[e.id],n)},this)),a=a.then(function(){return s(e.id,e.parents)})},this),a=a.then(u.bind(function(){var e=t.get("target").get("id"),r=this.origin.refs[e];return this.origin.setTargetLocation(n,r),c.playRefreshAnimation(this.gitVisuals),c.playRefreshAnimation(this.origin.gitVisuals)},this)),a=a.then(u.bind(function(){var e=this.getCommitFromRef(t),n=t.getRemoteBranchIDFromTracking();return this.setTargetLocation(this.refs[n],e),c.playRefreshAnimation(this.gitVisuals)},this)),e.dontResolvePromise||this.animationQueue.thenFinish(a,o)},y.prototype.fetchStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.fetch()},y.prototype.fetch=function(e){e=e||{};var t=this.refs["o/master"],n=this.origin.refs.master;this.checkUpstreamOfSource(this,this.origin,t,n);var r=this.getTargetGraphDifference(this,this.origin,t,n,e);if(r.length===0){this.command.addWarning(l.str("git-error-origin-fetch-uptodate"));var i=f.defer();return{deferred:i,chain:i.promise}}var s=u.bind(function(e,t){var n=u.map(t,function(e){return this.refs[e]},this);return this.makeCommit(n,e)},this),o=u.bind(function(e,t){var n=s(e,t);return c.playCommitBirthPromiseAnimation(n,this.gitVisuals)},this),a=f.defer(),h=a.promise;return u.each(r,function(e){h=h.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.origin.refs[e.id],t)},this)),h=h.then(function(){return o(e.id,e.parents)})},this),h=h.then(u.bind(function(){var e=n.get("target").get("id"),r=this.refs[e];return this.setTargetLocation(t,r),c.playRefreshAnimation(this.origin.gitVisuals),c.playRefreshAnimation(this.gitVisuals)},this)),e.dontResolvePromise||this.animationQueue.thenFinish(h,a),{chain:h,deferred:a}},y.prototype.pullStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.pull()},y.prototype.pull=function(){var e=this.refs.master,t=this.refs["o/master"],n=this.fetch({dontResolvePromise:!0,dontThrowOnNoFetch:!0});this.commandOptions["--rebase"]?this.pullFinishWithRebase(n,e,t):this.pullFinishWithMerge(n,e,t)},y.prototype.pullFinishWithRebase=function(e,t,n){var r=e.chain,i=e.deferred;r=r.then(function(){return c.getDelayedPromise(300)}),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(n),t)},this)),r=r.then(u.bind(function(){return e.dontResolvePromise=!0,this.rebase(n,t,e)},this)),this.animationQueue.thenFinish(r,i)},y.prototype.pullFinishWithMerge=function(e,t,n){var r=e.chain,i=e.deferred;r=r.then(function(){return c.getDelayedPromise(300)}),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(n),t)},this)),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(t),n)},this)),r=r.then(function(){return c.getDelayedPromise(700)}),r=r.then(u.bind(function(){var e=this.merge("o/master");return e?c.playCommitBirthPromiseAnimation(e,this.gitVisuals):c.playRefreshAnimation(this.gitVisuals)},this)),this.animationQueue.thenFinish(r,i)},y.prototype.cloneStarter=function(){this.acceptNoGeneralArgs(),this.makeOrigin(this.printTree(this.exportTreeForBranch("master")))},y.prototype.fakeTeamworkStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.validateArgBounds(this.generalArgs,0,1);var e=this.generalArgs[0]||1;this.fakeTeamwork(e)},y.prototype.fakeTeamwork=function(e){var t=u.bind(function(){var e=this.getUniqueID();return this.origin.receiveTeamwork(e,this.animationQueue)},this),n=u.bind(function(){var e=t();return c.playCommitBirthPromiseAnimation(e,this.origin.gitVisuals)},this),r=function(){return n()},i=f.defer(),s=i.promise;u.each(u.range(e),function(e){s=s.then(function(){return n()})}),this.animationQueue.thenFinish(s,i)},y.prototype.receiveTeamwork=function(e,t){var n=this.makeCommit([this.getCommitFromRef("HEAD")],e);return this.setTargetLocation(this.HEAD,n),n},y.prototype.cherrypick=function(e){var t=this.rebaseAltID(e.get("id")),n=this.makeCommit([this.getCommitFromRef("HEAD")],t);return this.setTargetLocation(this.HEAD,n),n},y.prototype.commitStarter=function(){this.acceptNoGeneralArgs();if(this.commandOptions["-am"]&&(this.commandOptions["-a"]||this.commandOptions["-m"]))throw new v({msg:l.str("git-error-options")});var e=null,t=null;this.commandOptions["-a"]&&this.command.addWarning(l.str("git-warning-add")),this.commandOptions["-am"]&&(t=this.commandOptions["-am"],this.validateArgBounds(t,1,1,"-am"),e=t[0]),this.commandOptions["-m"]&&(t=this.commandOptions["-m"],this.validateArgBounds(t,1,1,"-m"),e=t[0]);var n=this.commit();e&&(e=e.replace(/"/g,'"').replace(/^"/g,"").replace(/"$/g,""),n.set("commitMessage",e));var r=c.playCommitBirthPromiseAnimation(n,this.gitVisuals);this.animationQueue.thenFinish(r)},y.prototype.commit=function(){var e=this.getCommitFromRef(this.HEAD),t=null;this.commandOptions["--amend"]&&(e=this.resolveID("HEAD~1"),t=this.rebaseAltID(this.getCommitFromRef("HEAD").get("id")));var n=this.makeCommit([e],t);return this.getDetachedHead()&&this.command.addWarning(l.str("git-warning-detached")),this.setTargetLocation(this.HEAD,n),n},y.prototype.resolveName=function(e){var t=this.resolveID(e);return t.get("type")=="commit"?"commit "+t.get("id"):t.get("type")=="branch"?'branch "'+t.get("id")+'"':this.resolveName(t.get("target"))},y.prototype.resolveID=function(e){if(e===null||e===undefined)throw new Error("Dont call this with null / undefined");return typeof e!="string"?e:this.resolveStringRef(e)},y.prototype.resolveRelativeRef=function(e,t){var n=/([~\^])(\d*)/g,r;while(r=n.exec(t)){var i=e,s=r[2]?parseInt(r[2],10):1;if(r[1]=="^")i=e.getParent(s-1);else while(i&&s--)i=i.getParent(0);if(!i){var o=l.str("git-error-relative-ref",{commit:e.id,match:r[0]});throw new v({msg:o})}e=i}return e},y.prototype.resolveStringRef=function(e){e=this.crappyUnescape(e);if(this.refs[e])return this.refs[e];var t=null,n=null,r=/^([a-zA-Z0-9]+)(([~\^]\d*)*)/,i=r.exec(e);if(!i)throw new v({msg:l.str("git-error-exist",{ref:e})});t=i[1],n=i[2];if(!this.refs[t])throw new v({msg:l.str("git-error-exist",{ref:e})});var s=this.getCommitFromRef(t);return n&&(s=this.resolveRelativeRef(s,n)),s},y.prototype.getCommitFromRef=function(e){var t=this.resolveID(e);while(t.get("type")!=="commit")t=t.get("target");return t},y.prototype.getType=function(e){return this.resolveID(e).get("type")},y.prototype.setTargetLocation=function(e,t){if(this.getType(e)=="commit")return;e=this.getOneBeforeCommit(e),e.set("target",t)},y.prototype.getUpstreamBranchSet=function(){var e={},t=function(e,t){var n=!1;return u.each(e,function(e){e.id==t&&(n=!0)}),n},n=function(e){var t=[],n=[e];while(n.length){var r=n.pop();t.push(r.get("id")),r.get("parents")&&r.get("parents").length&&(n=n.concat(r.get("parents")))}return t};return this.branchCollection.each(function(r){var i=n(r.get("target"));u.each(i,function(n){e[n]=e[n]||[],t(e[n],r.get("id"))||e[n].push({obj:r,id:r.get("id")})})}),e},y.prototype.getUpstreamHeadSet=function(){var e=this.getUpstreamSet("HEAD"),t=this.getCommitFromRef("HEAD").get("id");return e[t]=!0,e},y.prototype.getOneBeforeCommit=function(e){var t=this.resolveID(e);return t===this.HEAD&&!this.getDetachedHead()&&(t=t.get("target")),t},y.prototype.scrapeBaseID=function(e){var t=/^C(\d+)/.exec(e);if(!t)throw new Error("regex failed on "+e);return"C"+t[1]},y.prototype.rebaseAltID=function(e){var t=[[/^C(\d+)[']{0,2}$/,function(e){return e[0]+"'"}],[/^C(\d+)[']{3}$/,function(e){return e[0].slice(0,-3)+"'^4"}],[/^C(\d+)['][\^](\d+)$/,function(e){return"C"+String(e[1])+"'^"+String(Number(e[2])+1)}]];for(var n=0;n",this.get("commitMessage"),"
","Commit: "+this.get("id")].join("\n")+"\n"},getShowEntry:function(){return[this.getLogEntry(),"diff --git a/bigGameResults.html b/bigGameResults.html","--- bigGameResults.html","+++ bigGameResults.html","@@ 13,27 @@ Winner, Score","- Stanfurd, 14-7","+ Cal, 21-14"].join("\n")+"\n"},validateAtInit:function(){if(!this.get("id"))throw new Error("Need ID!!");this.get("createTime")||this.set("createTime",(new Date).toString()),this.get("commitMessage")||this.set("commitMessage",l.str("git-dummy-msg")),this.set("children",[]);if(!this.get("rootCommit"))if(!this.get("parents")||!this.get("parents").length)throw new Error("needs parents")},addNodeToVisuals:function(){var e=this.get("gitVisuals").addNode(this.get("id"),this);this.set("visNode",e)},addEdgeToVisuals:function(e){this.get("gitVisuals").addEdge(this.get("id"),e.get("id"))},getParent:function(e){return this&&this.attributes&&this.attributes.parents?this.attributes.parents[e]:null},isMainParent:function(e){var t=this.get("parents").indexOf(e);return t===0},initialize:function(e){this.validateAtInit(),this.addNodeToVisuals(),u.each(this.get("parents"),function(e){e.get("children").push(this),this.addEdgeToVisuals(e)},this)}});n.GitEngine=y,n.Commit=E,n.Branch=w,n.Ref=b}),e("/src/js/git/index.js"),e.define("/src/js/git/treeCompare.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a={};a.dispatchFromLevel=function(e,t){var n=e.goalTreeString;return a.dispatch(e,n,t)},a.dispatch=function(e,t,n){var r=!0;switch(r){case!!e.compareOnlyMaster:return a.compareBranchWithinTrees(n,t,"master");case!!e.compareOnlyBranches:return a.compareAllBranchesWithinTrees(n,t);case!!e.compareAllBranchesHashAgnostic:return a.compareAllBranchesWithinTreesHashAgnostic(n,t);case!!e.compareOnlyMasterHashAgnostic:return a.compareBranchesWithinTreesHashAgnostic(n,t,["master"]);case!!e.compareOnlyMasterHashAgnosticWithAsserts:return a.compareBranchesWithinTreesHashAgnostic(n,t,["master"])&&a.evalAsserts(n,e.goalAsserts);default:return a.compareAllBranchesWithinTreesAndHEAD(n,t)}},a.compareAllBranchesWithinTreesAndHEAD=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t);debugger;return e.HEAD.target==t.HEAD.target&&this.compareAllBranchesWithinTrees(e,t)},a.compareAllBranchesWithinTrees=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t);var n=u.extend({},e.branches,t.branches),r=!0;return u.uniq(n,function(n,i){r=r&&this.compareBranchWithinTrees(e,t,i)},this),r},a.compareBranchesWithinTrees=function(e,t,n){var r=!0;return u.each(n,function(n){r=r&&this.compareBranchWithinTrees(e,t,n)},this),r},a.compareBranchWithinTrees=function(e,t,n){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var r=this.getRecurseCompare(e,t),i=e.branches[n],s=t.branches[n];return u.isEqual(i,s)&&r(e.commits[i.target],t.commits[s.target])},a.compareAllBranchesWithinTreesHashAgnostic=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var n=u.extend({},e.branches,t.branches),r=[];return u.each(n,function(e,t){r.push(t)}),this.compareBranchesWithinTreesHashAgnostic(e,t,r)},a.compareBranchesWithinTreesHashAgnostic=function(e,t,n){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var r=u.bind(function(e,t){return!e||!t?!1:(e=u.clone(e),t=u.clone(t),e.target=this.getBaseRef(e.target),t.target=this.getBaseRef(t.target),u.isEqual(e,t))},this),i=this.getRecurseCompareHashAgnostic(e,t),s=!0;return u.each(n,function(n){var o=e.branches[n],u=t.branches[n];s=s&&r(o,u)&&i(e.commits[o.target],t.commits[u.target])},this),s},a.evalAsserts=function(e,t){var n=!0;return u.each(t,function(t,r){n=n&&this.evalAssertsOnBranch(e,r,t)},this),n},a.evalAssertsOnBranch=function(e,t,n){e=this.convertTreeSafe(e);if(!e.branches[t])return!1;var r=e.branches[t],i=[r.target],s={};while(i.length){var o=i.pop();s[this.getBaseRef(o)]=this.getNumHashes(o),i=i.concat(e.commits[o].parents)}var a=!0;return u.each(n,function(e){try{a=a&&e(s)}catch(t){console.warn("error during assert",t),console.log(t),a=!1}}),a},a.getNumHashes=function(e){var t=[[/^C(\d+)([']{0,3})$/,function(e){return e[2]?e[2].length:0}],[/^C(\d+)['][\^](\d+)$/,function(e){return Number(e[2])}]];for(var n=0;n []",zh_CN:"git <命令> [<参数>]",fr_FR:"git []"},"git-supported-commands":{__desc__:"In the git help command, the header above the supported commands",en_US:"Supported commands:",zh_CN:"支持的命令有:",fr_FR:"Commandes supportées"},"git-usage":{__desc__:"In the dummy git output, the header before showing all the commands",en_US:"Usage:",zh_CN:"使用:",fr_FR:"Utilisation :"},"git-version":{__desc__:"The git version dummy output, kind of silly. PCOTTLE is my unix name but feel free to put yours instead",en_US:"Git Version PCOTTLE.1.0",zh_CN:"Git 版本 PCOTTLE.1.0",fr_FR:"Git version PCOTTLE.1.0"},"refresh-tree-command":{__desc__:"when the tree is visually refreshed",en_US:"Refreshing tree...",zh_CN:"正在刷新树结构...",fr_FR:"Actualisation de l'arbre…"},"locale-command":{__desc__:"when the locale is set to something",en_US:"Locale set to {locale}",zh_CN:"语言更改为 {locale}",fr_FR:"Langue changée à {locale}"},"locale-reset-command":{__desc__:"when the locale is reset",en_US:"Locale reset to default, which is {locale}",zh_CN:"语言重置为默认的 {locale}",fr_FR:"Langue remise par défaut, qui est {locale}"},"show-command":{__desc__:'command output title from "show"',en_US:"Please use one of the following commands for more info:",fr_FR:"Merci d'utiliser une des commandes suivantes pour obtenir plus d'info"},"show-all-commands":{__desc__:'command output title from "show commands"',en_US:"Here is a list of all the commmands available:",fr_FR:"Ci-dessous est la liste de toutes les commandes disponibles :"},"cd-command":{__desc__:"dummy command output for the command in the key",en_US:'Directory changed to "/directories/dont/matter/in/this/demo"',zh_CN:'目录切换到 "/directories/dont/matter/in/this/demo"',fr_FR:'Répertoire changé à "/directories/dont/matter/in/this/demo" (les répertoires ne servent à rien dans cette démo)'},"ls-command":{__desc__:"Dummy command output for the command in the key",en_US:"DontWorryAboutFilesInThisDemo.txt",zh_CN:"DontWorryAboutFilesInThisDemo.txt (译: 在试验里不用担心文件.txt)",fr_FR:"DontWorryAboutFilesInThisDemo.txt (ne vous préoccupez pas des noms de fichier dans cette démo)"},"mobile-alert":{__desc__:"When someone comes to the site on a mobile device, they can not input commands so this is a nasty alert to tell them",en_US:"Can't bring up the keyboard on mobile / tablet :( try visiting on desktop! :D",zh_CN:"无法在移动设备/平板上调出键盘 :( 请试试桌面版 :D",fr_FR:"Impossible de faire apparaître le clavier sur mobile / tablette :( Essayez de passer sur un ordinateur de bureau :D"},"share-tree":{__desc__:"When you export a tree, we want you to share the tree with friends",en_US:'Share this tree with friends! They can load it with "import tree"',zh_CN:'与你的好友分享提交树!他们可以用 "import tree" 加载它',fr_FR:'Partagez cet arbre avec vos amis ! Ils peuvent le charger avec "import tree"'},"paste-json":{__desc__:"When you are importing a level or tree",en_US:"Paste a JSON blob below!",zh_CN:"在下边粘贴一个JSON串",fr_FR:"Collez un blob JSON ci-dessous !"},"solved-map-reset":{__desc__:"When you reset the solved map to clear your solved history, in case someone else wants to use your browser",en_US:"Solved map was reset, you are starting from a clean slate!",zh_CN:"解决列表已重置,您现在从零开始了",fr_FR:"La carte des niveaux résolus a été effacée, vous repartez de zéro !"},"level-cant-exit":{__desc__:"When the user tries to exit a level when they are not in one",en_US:'You are not in a level! You are in a sandbox, start a level with "levels"',zh_CN:'您没在关卡中!您在沙盒中,要开始关卡请输入 "levels"',fr_FR:'Vous n\'êtes pas dans un niveau ! Vous êtes dans le mode bac à sable, commencez un niveau avec "levels"'},"level-no-id":{__desc__:"When you say an id but that level doesnt exist",en_US:'A level for that id "{id}" was not found! Opening up a level selection view',zh_CN:'没找到id为 "{id}" 的关卡!打开关卡选择框',fr_FR:"Le niveau dont l'identifiant est {id} n'a pas été trouvé ! Ouverture de la vue de sélection des niveaux"},"undo-stack-empty":{__desc__:"The undo command can only undo back until the last time the level was reset or the beginning of the level",en_US:"The undo stack is empty!",zh_CN:"还没有什么可以撤销",fr_FR:"La pile d'annulation est vide !"},"already-solved":{__desc__:"When you play in a level that is already solved",en_US:'You have already solved this level, try other levels with "levels" or go back to sandbox with "sandbox"',zh_CN:'你已经解决了本关,输入 "levels" 尝试其他关卡,或者输入 "sandbox" 回到沙盒中',fr_FR:'Vous avez déjà résolu ce niveau, essayez d\'autres niveaux avec "levels" ou revenez au bac à sable avec "sandbox"'},"command-disabled":{__desc__:"When you try a command that is disabled",en_US:"That git command is disabled for this level!",zh_CN:"该命令在本关不允许使用!",fr_FR:"Cette commande git est désactivée pour ce niveau !"},"share-json":{__desc__:"when you have made the level, prompt to share this",en_US:"Here is the JSON for this level! Share it with somenoe or send it to me on Github",zh_CN:"这是一个关卡定义JSON!您可以分享它或者发到我的GitHub上",fr_FR:"Voici le JSON pour ce niveau ! Partagez-le avec quelqu'un ou envoyez-le moi sur Github"},"want-start-dialog":{__desc__:"prompt to add a start dialog",en_US:"You have not specified a start dialog, would you like to add one?",zh_CN:"您还没有定义一开始的介绍,是否添加一个?",fr_FR:"Vous n'avez pas spécifié de dialogue de départ, voulez-vous en ajouter un ?"},"want-hint":{__desc__:"prompt to add a hint",en_US:"You have not specified a hint, would you like to add one?",zh_CN:"您还没有定义提示,是否添加一个?",fr_FR:"Vous n'avez pas spécifié d'indice, voulez-vous en ajouter un ?"},"prompt-hint":{__desc__:"prompt for hint",en_US:"Enter the hint for this level, or leave this blank if you do not want to include one",zh_CN:"请输入关卡提示,或者故意留空",fr_FR:"Entrez l'indice pour ce niveau, ou laissez-le vide pour ne pas l'inclure"},"prompt-name":{__desc__:"prompt for level name",en_US:"Enter the name for the level",zh_CN:"输入关卡名",fr_FR:"Entrez le nom pour ce niveau"},"solution-empty":{__desc__:"If you define a solution without any commands, aka a level that is solved without doing anything",en_US:"Your solution is empty!! Something is amiss",zh_CN:"你的解法是空的!! 这应该是出错了",fr_FR:"Votre solution est vide !! Quelque chose ne tourne pas rond"},"define-start-warning":{__desc__:"When you define the start point again, it overwrites the solution and goal so we add a warning",en_US:"Defining start point... solution and goal will be overwritten if they were defined earlier",zh_CN:"定义开始点... 解决方法和目标会被新的替代",fr_FR:"Redéfinition du point de départ… la solution et la cible seront écrasés s'ils ont déjà été définis"},"help-vague-level":{__desc__:"When you are in a level and you say help, its vague and you need to specify",en_US:'You are in a level, so multiple forms of help are available. Please select either "help level" to learn more about this lesson, "help general" for using Learn GitBranching, or "objective" to learn about how to solve the level.',zh_CN:'您正在关卡中,这里有多种形式的帮助,请选择 "help level" (关卡帮助)或 "help general" (一般帮助)',fr_FR:'Vous êtes dans un niveau, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help level" pour en apprendre plus sur cette leçon, "help general" pour l\'utilisation de Learn GitBranching, ou "objective" pour apprendre comment résoudre le niveau'},"help-vague-builder":{__desc__:"When you are in a level builder, the help command is vague so you need to specify what you mean",en_US:'You are in a level builder, so multiple forms of help are available. Please select either "help general" or "help builder"',zh_CN:'您正在进行关卡构建中,这里有多种形式的帮助,请选择 "help general" (一般帮助)或 "help builder" (关卡构建帮助)',fr_FR:'Vous êtes dans l\'éditeur de niveaux, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help general" soit "help builder"'},"goal-to-reach":{__desc__:"title of window that shoes the goal tree to reach",en_US:"Goal To Reach",zh_CN:"目标",fr_FR:"Cible à atteindre"},"hide-goal":{__desc__:"the helper message for the window that shows the goal tree",en_US:'You can hide this window with "hide goal"',zh_CN:'你可以通过命令 "hide goal" 关闭这个窗口',fr_FR:'Vous pouvez masquer cette fenêtre avec "hide goal"'},"hide-start":{__desc__:"The helper message for the window that shows the start tree for a level",en_US:'You can hide this window with "hide start"',zh_CN:'你可以通过命令 "hide start" 关闭这个窗口',fr_FR:'Vous pouvez masquer cette fenêtre avec "hide start"'},"level-builder":{__desc__:"The name for the environment where you build levels",en_US:"Level Builder",zh_CN:"关卡生成器",fr_FR:"Éditeur de niveaux"},"no-start-dialog":{__desc__:"when the user tries to open a start dialog for a level that does not have one",en_US:"There is no start dialog to show for this level!",zh_CN:"介绍? 这关真没有!",fr_FR:"Il n'y a aucun dialogue de départ à afficher pour ce niveau !"},"no-hint":{__desc__:"when no hint is available for a level",en_US:"Hmm, there doesn't seem to be a hint for this level :-/",zh_CN:"提示?嗯,这关真没有哎~ :-/",fr_FR:"Hum, il ne semble pas y avoir d'indice pour ce niveau :-/"},"error-untranslated-key":{__desc__:"This error happens when we are trying to translate a specific key and the locale version is mission",en_US:"The translation for {key} does not exist yet :( Please hop on github and offer up a translation!",zh_CN:"还没翻译 {key} :( 请在gitHub上贡献你的翻译!",fr_FR:"La traduction pour {key} n'existe pas encore :( Venez sur Github pour en offrir une !"},"error-untranslated":{__desc__:"The general error when we encounter a dialog that is not translated",en_US:"This dialog or text is not yet translated in your locale :( Hop on github to aid in translation!",zh_CN:"这段对话还没有被翻译成你的语言 :( 欢迎在gitHub上贡献你的翻译!",fr_FR:"Ce message n'a pas encore été traduit dans votre langue :( Venez sur Github aider à la traduction !"}}}),e("/src/js/intl/strings.js"),e.define("/src/js/level/arbiter.js",function(e,t,n,r,i,s,o){function h(){this.levelMap={},this.levelSequences=f,this.sequences=[],this.init();var e;try{e=JSON.parse(localStorage.getItem("solvedMap")||"{}")}catch(t){console.warn("local storage failed",t)}this.solvedMap=e||{},c.getEvents().on("levelSolved",this.levelSolved,this)}var u=e("underscore"),a=e("backbone"),f=e("../../levels").levelSequences,l=e("../../levels").sequenceInfo,c=e("../app");h.prototype.init=function(){var e;u.each(this.levelSequences,function(e,t){this.sequences.push(t);if(!e||!e.length)throw new Error("no empty sequences allowed");u.each(e,function(e,n){this.validateLevel(e);var r=t+String(n+1),i=u.extend({},e,{index:n,id:r,sequenceName:t});this.levelMap[r]=i,this.levelSequences[t][n]=i},this)},this)},h.prototype.isLevelSolved=function(e){if(!this.levelMap[e])throw new Error("that level doesnt exist!");return Boolean(this.solvedMap[e])},h.prototype.levelSolved=function(e){if(!e)return;this.solvedMap[e]=!0,this.syncToStorage()},h.prototype.resetSolvedMap=function(){this.solvedMap={},this.syncToStorage(),c.getEvents().trigger("levelSolved")},h.prototype.syncToStorage=function(){try{localStorage.setItem("solvedMap",JSON.stringify(this.solvedMap))}catch(e){console.warn("local storage fialed on set",e)}},h.prototype.validateLevel=function(e){e=e||{};var t=["name","goalTreeString","solutionCommand"],n=["hint","disabledMap","startTree"];u.each(t,function(t){if(e[t]===undefined)throw console.log(e),new Error("I need this field for a level: "+t)})},h.prototype.getSequenceToLevels=function(){return this.levelSequences},h.prototype.getSequences=function(){return u.keys(this.levelSequences)},h.prototype.getLevelsInSequence=function(e){if(!this.levelSequences[e])throw new Error("that sequecne name "+e+"does not exist");return this.levelSequences[e]},h.prototype.getSequenceInfo=function(e){return l[e]},h.prototype.getLevel=function(e){return this.levelMap[e]},h.prototype.getNextLevel=function(e){if(!this.levelMap[e])return console.warn("that level doesnt exist!!!"),null;var t=this.levelMap[e],n=t.sequenceName,r=this.levelSequences[n],i=t.index+1;if(i","show commands","show solution","show goal"];throw new v({msg:t.join("\n")})}],[/^locale (\w+)$/,function(t){f.GLOBAL.locale=t[1];var n=e("../app").getEvents().trigger("localeChanged");throw new v({msg:l.str("locale-command",{locale:t[1]})})}],[/^refresh$/,function(){var t=e("../app").getEvents();throw t.trigger("refreshTree"),new v({msg:l.str("refresh-tree-command")})}],[/^rollup (\d+)$/,function(t){var n=e("../app").getEvents();throw n.trigger("rollupCommands",t[1]),new v({msg:"Commands combined!"})}],[/^echo "(.*?)"$|^echo (.*?)$/,function(e){var t=e[1]||e[2];throw new v({msg:t})}],[/^show +commands$/,function(e){var t=y(),n=[l.str("show-all-commands"),"
"];throw u.each(t,function(e,t){n.push(t)}),new v({msg:n.join("\n")})}]],g={"reset solved":/^reset solved($|\s)/,help:/^help( +general)?$|^\?$/,reset:/^reset( +--forSolution)?$/,delay:/^delay (\d+)$/,clear:/^clear($|\s)/,"exit level":/^exit level($|\s)/,sandbox:/^sandbox($|\s)/,level:/^level\s?([a-zA-Z0-9]*)/,levels:/^levels($|\s)/,mobileAlert:/^mobile alert($|\s)/,"build level":/^build +level($|\s)/,"export tree":/^export +tree$/,"import tree":/^import +tree$/,"import level":/^import +level$/,undo:/^undo($|\s)/},y=function(){var t=["mobileAlert"],n=u.extend({},e("../git/commands").regexMap,e("../level").regexMap,g);return u.each(t,function(e){delete n[e]}),n};n.instantCommands=m,n.parse=a.genParseCommand(g,"processSandboxCommand"),n.getOptimisticLevelParse=function(){return a.genParseCommand(e("../level").regexMap,"processLevelCommand")},n.getOptimisticLevelBuilderParse=function(){return a.genParseCommand(e("../level/builder").regexMap,"processLevelBuilderCommand")}}),e("/src/js/level/sandboxCommands.js"),e.define("/src/js/log/index.js",function(e,t,n,r,i,s,o){var u=function(e,t,n){window._gaq=window._gaq||[],window._gaq.push(["_trackEvent",e,t,n])};n.viewInteracted=function(e){u("views","interacted",e)},n.showLevelSolution=function(e){u("levels","showedLevelSolution",e)},n.choseNextLevel=function(e){u("levels","nextLevelChosen",e)},n.levelSelected=function(e){u("levels","levelSelected",e)},n.levelSolved=function(e){u("levels","levelSolved",e)},n.commandEntered=function(e){u("commands","commandEntered",e)}}),e("/src/js/log/index.js"),e.define("/src/js/models/collections.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?f=window.Backbone:f=e("backbone"),l=e("../git").Commit,c=e("../git").Branch,h=e("../models/commandModel").Command,p=e("../models/commandModel").CommandEntry,d=e("../util/constants").TIME,v=f.Collection.extend({model:l}),m=f.Collection.extend({model:h}),g=f.Collection.extend({model:c}),y=f.Collection.extend({model:p,localStorage:f.LocalStorage?new f.LocalStorage("CommandEntries"):null}),b=f.Model.extend({defaults:{collection:null},initialize:function(e){e.collection.bind("add",this.addCommand,this),this.buffer=[],this.timeout=null},addCommand:function(e){this.buffer.push(e),this.touchBuffer()},touchBuffer:function(){if(this.timeout)return;this.setTimeout()},setTimeout:function(){this.timeout=setTimeout(u.bind(function(){this.sipFromBuffer()},this),d.betweenCommandsDelay)},popAndProcess:function(){var e=this.buffer.shift(0);while(e.get("error")&&this.buffer.length)e=this.buffer.shift(0);e.get("error")?this.clear():this.processCommand(e)},processCommand:function(t){t.set("status","processing");var n=a.defer();n.promise.then(u.bind(function(){this.setTimeout()},this));var r=t.get("eventName");if(!r)throw new Error("I need an event to trigger when this guy is parsed and ready");var i=e("../app"),s=i.getEventBaton(),o=s.getNumListeners(r);if(!o){var f=e("../util/errors");t.set("error",new f.GitError({msg:"That command is valid, but not supported in this current environment! Try entering a level or level builder to use that command"})),n.resolve();return}i.getEventBaton().trigger(r,t,n)},clear:function(){clearTimeout(this.timeout),this.timeout=null},sipFromBuffer:function(){if(!this.buffer.length){this.clear();return}this.popAndProcess()}});n.CommitCollection=v,n.CommandCollection=m,n.BranchCollection=g,n.CommandEntryCollection=y,n.CommandBuffer=b}),e("/src/js/models/collections.js"),e.define("/src/js/models/commandModel.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../util/errors"),l=e("../git/commands"),c=l.GitOptionParser,h=e("../level/parseWaterfall").ParseWaterfall,p=f.CommandProcessError,d=f.GitError,v=f.Warning,m=f.CommandResult,g=a.Model.extend({defaults:{status:"inqueue",rawStr:null,result:"",createTime:null,error:null,warnings:null,parseWaterfall:new h,generalArgs:null,supportedMap:null,options:null,method:null},initialize:function(e){this.initDefaults(),this.validateAtInit(),this.on("change:error",this.errorChanged,this),this.get("error")&&this.errorChanged(),this.parseOrCatch()},initDefaults:function(){this.set("generalArgs",[]),this.set("supportedMap",{}),this.set("warnings",[])},validateAtInit:function(){if(this.get("rawStr")===null)throw new Error("Give me a string!");this.get("createTime")||this.set("createTime",(new Date).toString())},setResult:function(e){this.set("result",e)},finishWith:function(e){this.set("status","finished"),e.resolve()},addWarning:function(e){this.get("warnings").push(e),this.set("numWarnings",this.get("numWarnings")?this.get("numWarnings")+1:1)},getFormattedWarnings:function(){if(!this.get("warnings").length)return"";var e='';return"

"+e+this.get("warnings").join("

"+e)+"

"},parseOrCatch:function(){this.expandShortcuts(this.get("rawStr"));try{this.processInstants()}catch(e){f.filterError(e),this.set("error",e);return}if(this.parseAll())return;this.set("error",new p({msg:'The command "'+this.get("rawStr")+"\" isn't supported, sorry!"}))},errorChanged:function(){var e=this.get("error");e instanceof p||e instanceof d?this.set("status","error"):e instanceof m?this.set("status","finished"):e instanceof v&&this.set("status","warning"),this.formatError()},formatError:function(){this.set("result",this.get("error").toResult())},expandShortcuts:function(e){e=this.get("parseWaterfall").expandAllShortcuts(e),this.set("rawStr",e)},processInstants:function(){var e=this.get("rawStr");if(!e.length)throw new m({msg:""});this.get("parseWaterfall").processAllInstants(e)},parseAll:function(){var e=this.get("rawStr"),t=this.get("parseWaterfall").parseAll(e);return t?(u.each(t.toSet,function(e,t){this.set(t,e)},this),!0):!1}}),y=a.Model.extend({defaults:{text:""}});n.CommandEntry=y,n.Command=g}),e("/src/js/models/commandModel.js"),e.define("/src/js/util/constants.js",function(e,t,n,r,i,s,o){var u={betweenCommandsDelay:400},a={isAnimating:!1},f={minZoom:.55,maxZoom:1.25,minWidth:600,minHeight:600},l={arrowHeadSize:8,nodeRadius:17,curveControlPointOffset:50,defaultEasing:"easeInOut",defaultAnimationTime:400,rectFill:"hsb(0.8816909813322127,0.7,1)",headRectFill:"#2831FF",rectStroke:"#FFF",rectStrokeWidth:"3",originDash:"- ",multiBranchY:20,upstreamHeadOpacity:.5,upstreamNoneOpacity:.2,edgeUpstreamHeadOpacity:.4,edgeUpstreamNoneOpacity:.15,visBranchStrokeWidth:2,visBranchStrokeColorNone:"#333",defaultNodeFill:"hsba(0.5,0.8,0.7,1)",defaultNodeStrokeWidth:2,defaultNodeStroke:"#FFF",orphanNodeFill:"hsb(0.5,0.8,0.7)"};n.GLOBAL=a,n.TIME=u,n.GRAPHICS=l,n.VIEWPORT=f}),e("/src/js/util/constants.js"),e.define("/src/js/util/debug.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a={Tree:e("../visuals/tree"),Visuals:e("../visuals"),Git:e("../git"),CommandModel:e("../models/commandModel"),Levels:e("../git/treeCompare"),Constants:e("../util/constants"),Collections:e("../models/collections"),Async:e("../visuals/animation"),AnimationFactory:e("../visuals/animation/animationFactory"),Main:e("../app"),HeadLess:e("../git/headless"),Q:{Q:e("q")},RebaseView:e("../views/rebaseView"),Views:e("../views"),MultiView:e("../views/multiView"),ZoomLevel:e("../util/zoomLevel"),VisBranch:e("../visuals/visBranch"),Level:e("../level"),Sandbox:e("../level/sandbox"),GitDemonstrationView:e("../views/gitDemonstrationView"),Markdown:e("markdown"),LevelDropdownView:e("../views/levelDropdownView"),BuilderViews:e("../views/builderViews"),Intl:e("../intl")};u.each(a,function(e){for(var t in e)window["debug_"+t]=e[t]}),$(document).ready(function(){window.events=a.Main.getEvents(),window.eventBaton=a.Main.getEventBaton(),window.sandbox=a.Main.getSandbox(),window.modules=a,window.levelDropdown=a.Main.getLevelDropdown(),window.under=u,window.copyTree=function(){return a.Main.getSandbox().mainVis.gitEngine.printAndCopyTree()}})}),e("/src/js/util/debug.js"),e.define("/src/js/util/errors.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({defaults:{type:"MyError",msg:"Unknown Error"},toString:function(){return this.get("type")+": "+this.get("msg")},getMsg:function(){return this.get("msg")||"Unknown Error"},toResult:function(){return this.get("msg").length?"

"+this.get("msg").replace(/\n/g,"

")+"

":""}}),l=n.CommandProcessError=f.extend({defaults:{type:"Command Process Error"}}),c=n.CommandResult=f.extend({defaults:{type:"Command Result"}}),h=n.Warning=f.extend({defaults:{type:"Warning"}}),p=n.GitError=f.extend({defaults:{type:"Git Error"}}),d=function(e){if(e instanceof l||e instanceof p||e instanceof c||e instanceof h)return;throw e};n.filterError=d}),e("/src/js/util/errors.js"),e.define("/src/js/util/eventBaton.js",function(e,t,n,r,i,s,o){function a(){this.eventMap={}}var u=e("underscore");a.prototype.stealBaton=function(e,t,n){if(!e)throw new Error("need name");if(!t)throw new Error("need func!");var r=this.eventMap[e]||[];r.push({func:t,context:n}),this.eventMap[e]=r},a.prototype.sliceOffArgs=function(e,t){var n=[];for(var r=e;r0&&!e.length)return;t(e)})},n.genParseCommand=function(e,t){return function(n){var r,i;return u.each(e,function(e,t){var s=e.exec(n);s&&(r=t,i=s)}),r?{toSet:{eventName:t,method:r,regexResults:i}}:!1}}}),e("/src/js/util/index.js"),e.define("/src/js/util/keyboard.js",function(e,t,n,r,i,s,o){function c(e){this.events=e.events||u.clone(a.Events),this.aliasMap=e.aliasMap||{},e.wait||this.listen()}var u=e("underscore"),a=e("backbone"),f=e("../app"),l=function(e){var t={37:"left",38:"up",39:"right",40:"down",27:"esc",13:"enter"};return t[e]};c.prototype.listen=function(){if(this.listening)return;this.listening=!0,f.getEventBaton().stealBaton("docKeydown",this.keydown,this)},c.prototype.mute=function(){this.listening=!1,f.getEventBaton().releaseBaton("docKeydown",this.keydown,this)},c.prototype.keydown=function(e){var t=e.which||e.keyCode,n=l(t);if(n===undefined)return;this.fireEvent(n,e)},c.prototype.fireEvent=function(e,t){e=this.aliasMap[e]||e,this.events.trigger(e,t)},c.prototype.passEventBack=function(e){f.getEventBaton().passBatonBackSoft("docKeydown",this.keydown,this,[e])},n.KeyboardListener=c,n.mapKeycodeToKey=l}),e("/src/js/util/keyboard.js"),e.define("/src/js/util/mock.js",function(e,t,n,r,i,s,o){n.mock=function(e){var t={},n=function(){};for(var r in e.prototype)t[r]=n;return t}}),e("/src/js/util/mock.js"),e.define("/src/js/util/zoomLevel.js",function(e,t,n,r,i,s,o){function f(){return!window.outerWidth||!window.innerWidth?(a&&(console.warn("Can't detect zoom level correctly :-/"),a=!1),1):window.outerWidth/window.innerWidth}var u=e("underscore"),a=!0,l=!0,c=function(e,t){var n=0;setInterval(function(){var r=f();if(r!==n){if(l){l=!1;return}n=r,e.apply(t,[r])}else l=!0},500)};n.setupZoomPoll=c,n.detectZoom=f}),e("/src/js/util/zoomLevel.js"),e.define("/src/js/views/builderViews.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../intl"),h=e("../util/keyboard").KeyboardListener,p=e("../views"),d=p.ModalTerminal,v=p.ContainedBase,m=v.extend({tagName:"div",className:"textGrabber box vertical",template:u.template($("#text-grabber").html()),initialize:function(e){e=e||{},this.JSON={helperText:e.helperText||"Enter some text"},this.container=e.container||new d({title:"Enter some text"}),this.render(),e.initialText&&this.setText(e.initialText),e.wait||this.show()},getText:function(){return this.$("textarea").val()},setText:function(e){this.$("textarea").val(e)}}),g=v.extend({tagName:"div",className:"markdownGrabber box horizontal",template:u.template($("#markdown-grabber-view").html()),events:{"keyup textarea":"keyup"},initialize:function(e){e=e||{},this.deferred=e.deferred||a.defer(),e.fromObj&&(e.fillerText=e.fromObj.options.markdowns.join("\n")),this.JSON={previewText:e.previewText||"Preview",fillerText:e.fillerText||"## Enter some markdown!\n\n\n"},this.container=e.container||new d({title:e.title||"Enter some markdown"}),this.render();if(!e.withoutButton){var t=a.defer();t.promise.then(u.bind(this.confirmed,this)).fail(u.bind(this.cancelled,this)).done();var n=new p.ConfirmCancelView({deferred:t,destination:this.getDestination()})}this.updatePreview(),e.wait||this.show()},confirmed:function(){this.die(),this.deferred.resolve(this.getRawText())},cancelled:function(){this.die(),this.deferred.resolve()},keyup:function(){this.throttledPreview||(this.throttledPreview=u.throttle(u.bind(this.updatePreview,this),500)),this.throttledPreview()},getRawText:function(){return this.$("textarea").val()},exportToArray:function(){return this.getRawText().split("\n")},getExportObj:function(){return{markdowns:this.exportToArray()}},updatePreview:function(){var t=this.getRawText(),n=e("markdown").markdown.toHTML(t);this.$("div.insidePreview").html(n)}}),y=v.extend({tagName:"div",className:"markdownPresenter box vertical",template:u.template($("#markdown-presenter").html()),initialize:function(e){e=e||{},this.deferred=e.deferred||a.defer(),this.JSON={previewText:e.previewText||"Here is something for you",fillerText:e.fillerText||"# Yay"},this.container=new d({title:"Check this out..."}),this.render();if(!e.noConfirmCancel){var t=new p.ConfirmCancelView({destination:this.getDestination()});t.deferred.promise.then(u.bind(function(){this.deferred.resolve(this.grabText())},this)).fail(u.bind(function(){this.deferred.reject()},this)).done(u.bind(this.die,this))}this.show()},grabText:function(){return this.$("textarea").val()}}),b=v.extend({tagName:"div",className:"demonstrationBuilder box vertical",template:u.template($("#demonstration-builder").html()),events:{"click div.testButton":"testView"},initialize:function(e){e=e||{},this.deferred=e.deferred||a.defer();if(e.fromObj){var t=e.fromObj.options;e=u.extend({},e,t,{beforeMarkdown:t.beforeMarkdowns.join("\n"),afterMarkdown:t.afterMarkdowns.join("\n")})}this.JSON={},this.container=new d({title:"Demonstration Builder"}),this.render(),this.beforeMarkdownView=new g({container:this,withoutButton:!0,fillerText:e.beforeMarkdown,previewText:"Before demonstration Markdown"}),this.beforeCommandView=new m({container:this,helperText:"The git command(s) to set up the demonstration view (before it is displayed)",initialText:e.beforeCommand||"git checkout -b bugFix"}),this.commandView=new m({container:this,helperText:"The git command(s) to demonstrate to the reader",initialText:e.command||"git commit"}),this.afterMarkdownView=new g({container:this,withoutButton:!0,fillerText:e.afterMarkdown,previewText:"After demonstration Markdown"});var n=a.defer(),r=new p.ConfirmCancelView({deferred:n,destination:this.getDestination()});n.promise.then(u.bind(this.confirmed,this)).fail(u.bind(this.cancelled,this)).done()},testView:function(){var t=e("../views/multiView").MultiView;new t({childViews:[{type:"GitDemonstrationView",options:this.getExportObj()}]})},getExportObj:function(){return{beforeMarkdowns:this.beforeMarkdownView.exportToArray(),afterMarkdowns:this.afterMarkdownView.exportToArray(),command:this.commandView.getText(),beforeCommand:this.beforeCommandView.getText()}},confirmed:function(){this.die(),this.deferred.resolve(this.getExportObj())},cancelled:function(){this.die(),this.deferred.resolve()},getInsideElement:function(){return this.$(".insideBuilder")[0]}}),w=v.extend({tagName:"div",className:"multiViewBuilder box vertical",template:u.template($("#multi-view-builder").html()),typeToConstructor:{ModalAlert:g,GitDemonstrationView:b},events:{"click div.deleteButton":"deleteOneView","click div.testButton":"testOneView","click div.editButton":"editOneView","click div.testEntireView":"testEntireView","click div.addView":"addView","click div.saveView":"saveView","click div.cancelView":"cancel"},initialize:function(e){e=e||{},this.deferred=e.deferred||a.defer(),this.multiViewJSON=e.multiViewJSON||{},this.JSON={views:this.getChildViews(),supportedViews:u.keys(this.typeToConstructor)},this.container=new d({title:"Build a MultiView!"}),this.render(),this.show()},saveView:function(){this.hide(),this.deferred.resolve(this.multiViewJSON)},cancel:function(){this.hide(),this.deferred.resolve()},addView:function(e){var t=e.target,n=$(t).attr("data-type"),r=a.defer(),i=this.typeToConstructor[n],s=new i({deferred:r});r.promise.then(u.bind(function(){var e={type:n,options:s.getExportObj()};this.addChildViewObj(e)},this)).fail(function(){}).done()},testOneView:function(t){var n=t.target,r=$(n).attr("data-index"),i=this.getChildViews()[r],s=e("../views/multiView").MultiView;new s({childViews:[i]})},testEntireView:function(){var t=e("../views/multiView").MultiView;new t({childViews:this.getChildViews()})},editOneView:function(e){var t=e.target,n=$(t).attr("data-index"),r=$(t).attr("data-type"),i=a.defer(),s=new this.typeToConstructor[r]({deferred:i,fromObj:this.getChildViews()[n]});i.promise.then(u.bind(function(){var e={type:r,options:s.getExportObj()},t=this.getChildViews();t[n]=e,this.setChildViews(t)},this)).fail(function(){}).done()},deleteOneView:function(e){var t=e.target,n=$(t).attr("data-index"),r=this.getChildViews(),i=r.slice(0,n).concat(r.slice(n+1));this.setChildViews(i),this.update()},addChildViewObj:function(e,t){var n=this.getChildViews();n.push(e),this.setChildViews(n),this.update()},setChildViews:function(e){this.multiViewJSON.childViews=e},getChildViews:function(){return this.multiViewJSON.childViews||[]},update:function(){this.JSON.views=this.getChildViews(),this.renderAgain()}});n.MarkdownGrabber=g,n.DemonstrationBuilder=b,n.TextGrabber=m,n.MultiViewBuilder=w,n.MarkdownPresenter=y}),e("/src/js/views/builderViews.js"),e.define("/src/js/views/commandViews.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../models/collections").CommandEntryCollection,l=e("../app"),c=e("../models/commandModel").Command,h=e("../models/commandModel").CommandEntry,p=e("../util/errors"),d=p.Warning,v=e("../util"),m=e("../log"),g=e("../util/keyboard"),y=a.View.extend({initialize:function(e){l.getEvents().on("commandSubmittedPassive",this.addToCommandHistory,this),this.commands=new f,this.commands.fetch({success:u.bind(function(){var e=[];this.commands.each(function(t){e.push(t)}),e.reverse(),this.commands.reset(),u.each(e,function(e){this.commands.add(e)},this)},this)}),this.index=-1,this.commandParagraph=this.$("#prompt p.command")[0],this.commandCursor=this.$("#prompt span.cursor")[0],this.focus(),l.getEvents().on("rollupCommands",this.rollupCommands,this),l.getEventBaton().stealBaton("keydown",this.onKeyDown,this),l.getEventBaton().stealBaton("keyup",this.onKeyUp,this)},events:{"blur #commandTextField":"hideCursor","focus #commandTextField":"showCursor"},blur:function(){this.hideCursor()},focus:function(){this.$("#commandTextField").focus(),this.showCursor()},hideCursor:function(){this.toggleCursor(!1)},showCursor:function(){this.toggleCursor(!0)},toggleCursor:function(e){$(this.commandCursor).toggleClass("shown",e)},onKeyDown:function(e){var t=e.target;this.updatePrompt(t)},onKeyUp:function(e){this.onKeyDown(e);var t={enter:u.bind(function(){this.submit()},this),up:u.bind(function(){this.commandSelectChange(1)},this),down:u.bind(function(){this.commandSelectChange(-1)},this)},n=g.mapKeycodeToKey(e.which||e.keyCode);t[n]!==undefined&&(e.preventDefault(),t[n](),this.onKeyDown(e))},badHtmlEncode:function(e){return e.replace(/&/g,"&").replace(/=this.commands.length||this.index<0){this.clear(),this.index=-1;return}var t=this.commands.toArray()[this.index].get("text");this.setTextField(t)},clearLocalStorage:function(){this.commands.each(function(e){a.sync("delete",e,function(){})},this)},setTextField:function(e){this.$("#commandTextField").val(e)},clear:function(){this.setTextField("")},submit:function(){var e=this.$("#commandTextField").val().replace("\n","");this.clear(),this.submitCommand(e),this.index=-1},rollupCommands:function(e){var t=this.commands.toArray().slice(1,Number(e)+1);t.reverse();var n="";u.each(t,function(e){n+=e.get("text")+";"},this);var r=new h({text:n});this.commands.unshift(r),a.sync("create",r,function(){})},addToCommandHistory:function(e){var t=e.length&&this.index===-1||e.length&&this.index!==-1&&this.commands.toArray()[this.index].get("text")!==e;if(!t)return;var n=new h({text:e});this.commands.unshift(n),a.sync("create",n,function(){}),this.commands.length>100&&this.clearLocalStorage(),m.commandEntered(e)},submitCommand:function(e){l.getEventBaton().trigger("commandSubmitted",e)}}),b=a.View.extend({tagName:"div",model:c,template:u.template($("#command-template").html()),events:{click:"clicked"},clicked:function(e){},initialize:function(){this.model.bind("change",this.wasChanged,this),this.model.bind("destroy",this.remove,this)},wasChanged:function(e,t){var n=t.changes,r=u.keys(n);u.difference(r,["status"]).length===0?this.updateStatus():this.render()},updateStatus:function(){var e=["inqueue","processing","finished"],t={};u.each(e,function(e){t[e]=!1}),t[this.model.get("status")]=!0;var n=this.$("p.commandLine");u.each(t,function(e,t){n.toggleClass(t,e)})},render:function(){var e=u.extend({resultType:"",result:"",formattedWarnings:this.model.getFormattedWarnings()},this.model.toJSON());return this.$el.html(this.template(e)),this},remove:function(){$(this.el).hide()}}),w=a.View.extend({initialize:function(e){this.collection=e.collection,this.collection.on("add",this.addOne,this),this.collection.on("reset",this.addAll,this),this.collection.on("all",this.render,this),this.collection.on("change",this.scrollDown,this),l.getEvents().on("commandScrollDown",this.scrollDown,this),l.getEvents().on("clearOldCommands",this.clearOldCommands,this)},addWarning:function(e){var t=new d({msg:e}),n=new c({error:t,rawStr:"Warning:"});this.collection.add(n)},clearOldCommands:function(){var e=[];this.collection.each(function(t){t.get("status")!=="inqueue"&&t.get("status")!=="processing"&&e.push(t)},this),u.each(e,function(e){e.destroy()},this),this.scrollDown()},scrollDown:function(){var e=$("#commandDisplay")[0],t=$("#terminal")[0],n=e.clientHeight>t.clientHeight||$(window).height() p.uiButton":"positive"},initialize:function(t){t=t||{},this.options=t,this.JSON=u.extend({beforeMarkdowns:["## Git Commits","","Awesome!"],command:"git commit",afterMarkdowns:["Now you have seen it in action","","Go ahead and try the level!"]},t);var n=function(t){return e("markdown").markdown.toHTML(t.join("\n"))};this.JSON.beforeHTML=n(this.JSON.beforeMarkdowns),this.JSON.afterHTML=n(this.JSON.afterMarkdowns),this.container=new p({title:t.title||"Git Demonstration"}),this.render(),this.checkScroll(),this.navEvents=u.clone(f.Events),this.navEvents.on("positive",this.positive,this),this.navEvents.on("negative",this.negative,this),this.keyboardListener=new c({events:this.navEvents,aliasMap:{enter:"positive",right:"positive",left:"negative"},wait:!0}),this.visFinished=!1,this.initVis(),t.wait||this.show()},receiveMetaNav:function(e,t){var n=this;e.navEvents.on("positive",this.positive,this),this.metaContainerView=t},checkScroll:function(){var e=this.$("div.demonstrationText").children(),t=u.map(e,function(e){return e.clientHeight}),n=u.reduce(t,function(e,t){return e+t});np.VIEWPORT.minWidth&&e.h>p.VIEWPORT.minHeight&&this.finish()}}),O=L.extend({initialize:function(e){if(!e||!e.level)throw new Error("need level");this.eventBatonName="zoomChange",this.markdowns=["## That zoom level of "+e.level+" is not supported :-/","Please zoom back to a supported zoom level with Ctrl + and Ctrl -","","(and of course, pull requests to fix this are appreciated :D)"],O.__super__.initialize.apply(this,[e])},batonFired:function(e){e<=p.VIEWPORT.maxZoom&&e>=p.VIEWPORT.minZoom&&this.finish()}}),M=m.extend({tagName:"div",className:"levelToolbarHolder",template:u.template($("#level-toolbar-template").html()),initialize:function(e){e=e||{},this.JSON={name:e.name||"Some level! (unknown name)"},this.beforeDestination=$($("#commandLineHistory div.toolbar")[0]),this.render(),e.wait||s.nextTick(u.bind(this.show,this))},getAnimationTime:function(){return 700},render:function(){var e=this.template(this.JSON);this.$el.html(e),this.beforeDestination.after(this.el)},die:function(){this.hide(),setTimeout(u.bind(function(){this.tearDown()},this),this.getAnimationTime())},hide:function(){this.$("div.toolbar").toggleClass("hidden",!0)},show:function(){this.$("div.toolbar").toggleClass("hidden",!1)}}),_=m.extend({tagName:"div",className:"helperBar transitionAll",template:u.template($("#helper-bar-template").html()),events:{"click a":"onClick"},onClick:function(e){var t=e.target,n=$(t).attr("data-id"),r="on"+n[0].toUpperCase()+n.slice(1)+"Click";this[r].call(this)},show:function(){this.$el.toggleClass("show",!0)},hide:function(){this.$el.toggleClass("show",!1),this.deferred&&this.deferred.resolve()},getItems:function(){return[]},setupChildren:function(){},fireCommand:function(e){l.getEventBaton().trigger("commandSubmitted",e)},showDeferMe:function(e){this.hide();var t=a.defer();e.deferred=t,t.promise.then(u.bind(function(){this.show()},this)),e.show()},onExitClick:function(){this.hide()},initialize:function(e){e=e||{},this.destination=$("body"),this.JSON={items:this.getItems()},this.render(),this.setupChildren(),e.wait||this.show()}}),D=_.extend({getItems:function(){return[{text:"Git Branching",id:"english"},{text:"日本語版リポジトリ",id:"japanese"},{text:"Git 브랜치 배우기",id:"korean"},{text:"学习Git分支",id:"chinese"},{text:"français",id:"french"},{icon:"signout",id:"exit"}]},fireCommand:function(){h.viewInteracted("intlSelect"),_.prototype.fireCommand.apply(this,arguments)},onJapaneseClick:function(){this.fireCommand("locale ja; levels"),this.hide()},onEnglishClick:function(){this.fireCommand("locale en_US; levels"),this.hide()},onKoreanClick:function(){this.fireCommand("locale ko; levels"),this.hide()},onFrenchClick:function(){this.fireCommand("locale fr_FR; levels"),this.hide()},onChineseClick:function(){this.fireCommand("locale zh_CN; levels"),this.hide()}}),P=_.extend({getItems:function(){return[{text:"Levels",id:"levels"},{text:"Reset",id:"reset"},{text:"Undo",id:"undo"},{text:"Objective",id:"objectve"},{text:"Help",id:"help"},{icon:"signout",id:"exit"}]},fireCommand:function(){h.viewInteracted("helperBar"),_.prototype.fireCommand.apply(this,arguments)},onObjectiveClick:function(){this.fireCommand("objective")},onLevelsClick:function(){this.fireCommand("levels")},onResetClick:function(){this.fireCommand("reset")},onUndoClick:function(){this.fireCommand("undo")},onHelpClick:function(){this.fireCommand("help general; git help")}}),H=_.extend({getItems:function(){return[{icon:"question-sign",id:"commands"},{icon:"globe",id:"intl"}]},onIntlClick:function(){this.showDeferMe(this.intlHelper),h.viewInteracted("openIntlBar")},onCommandsClick:function(){this.showDeferMe(this.commandsHelper),h.viewInteracted("openCommandsBar")},setupChildren:function(){this.commandsHelper=new P({wait:!0}),this.intlHelper=new D({wait:!0})}}),B=m.extend({tagName:"div",className:"canvasTerminalHolder box flex1",template:u.template($("#terminal-window-bare-template").html()),events:{"click div.wrapper":"onClick"},initialize:function(e){e=e||{},this.destination=$("body"),this.JSON={title:e.title||c.str("goal-to-reach"),text:e.text||c.str("hide-goal")},this.render(),this.inDom=!0,e.additionalClass&&this.$el.addClass(e.additionalClass)},getAnimationTime:function(){return 700},onClick:function(){this.die()},die:function(){this.slideOut(),this.inDom=!1,setTimeout(u.bind(function(){this.tearDown()},this),this.getAnimationTime())},slideOut:function(){this.slideToggle(!0)},slideIn:function(){this.slideToggle(!1)},slideToggle:function(e){this.$("div.terminal-window-holder").toggleClass("slideOut",e)},getCanvasLocation:function(){return this.$("div.inside")[0]}});n.BaseView=m,n.GeneralButton=w,n.ModalView=x,n.ModalTerminal=T,n.ModalAlert=N,n.ContainedBase=b,n.ConfirmCancelView=E,n.LeftRightView=S,n.ZoomAlertWindow=O,n.ConfirmCancelTerminal=C,n.WindowSizeAlertWindow=A,n.MainHelperBar=H,n.CanvasTerminalHolder=B,n.LevelToolbar=M,n.NextLevelConfirm=k}),e("/src/js/views/index.js"),e.define("/src/js/views/levelDropdownView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../intl"),h=e("../log"),p=e("../util/keyboard").KeyboardListener,d=e("../app"),v=e("../views").ModalTerminal,m=e("../views").ContainedBase,g=e("../views").BaseView,y=m.extend({tagName:"div",className:"levelDropdownView box vertical",template:u.template($("#level-dropdown-view").html()),initialize:function(e){e=e||{},this.JSON={},this.navEvents=u.clone(f.Events),this.navEvents.on("clickedID",u.debounce(u.bind(this.loadLevelID,this),300,!0)),this.navEvents.on("negative",this.negative,this),this.navEvents.on("positive",this.positive,this),this.navEvents.on("left",this.left,this),this.navEvents.on("right",this.right,this),this.navEvents.on("up",this.up,this),this.navEvents.on("down",this.down,this),this.keyboardListener=new p({events:this.navEvents,aliasMap:{esc:"negative",enter:"positive"},wait:!0}),this.sequences=d.getLevelArbiter().getSequences(),this.sequenceToLevels=d.getLevelArbiter().getSequenceToLevels(),this.container=new v({title:c.str("select-a-level")}),this.render(),d.getEvents().on("resetMapSolved",this.render,this),d.getEvents().on("localeChanged",this.render,this),e.wait||this.show()},render:function(){y.__super__.render.apply(this,arguments),this.buildSequences()},positive:function(){if(!this.selectedID)return;this.loadLevelID(this.selectedID)},left:function(){if(this.turnOnKeyboardSelection())return;this.leftOrRight(-1)},leftOrRight:function(e){this.deselectIconByID(this.selectedID),this.selectedIndex=this.wrapIndex(this.selectedIndex+e,this.getCurrentSequence()),this.selectedID=this.getSelectedID(),this.selectIconByID(this.selectedID)},right:function(){if(this.turnOnKeyboardSelection())return;this.leftOrRight(1)},up:function(){if(this.turnOnKeyboardSelection())return;this.selectedSequence=this.getPreviousSequence(),this.downOrUp()},down:function(){if(this.turnOnKeyboardSelection())return;this.selectedSequence=this.getNextSequence(),this.downOrUp()},downOrUp:function(){this.selectedIndex=this.boundIndex(this.selectedIndex,this.getCurrentSequence()),this.deselectIconByID(this.selectedID),this.selectedID=this.getSelectedID(),this.selectIconByID(this.selectedID)},turnOnKeyboardSelection:function(){return this.selectedID?!1:(this.selectFirst(),!0)},turnOffKeyboardSelection:function(){if(!this.selectedID)return;this.deselectIconByID(this.selectedID),this.selectedID=undefined,this.selectedIndex=undefined,this.selectedSequence=undefined},wrapIndex:function(e,t){return e=e>=t.length?0:e,e=e<0?t.length-1:e,e},boundIndex:function(e,t){return e=e>=t.length?t.length-1:e,e=e<0?0:e,e},getNextSequence:function(){var e=this.getSequenceIndex(this.selectedSequence),t=this.wrapIndex(e+1,this.sequences);return this.sequences[t]},getPreviousSequence:function(){var e=this.getSequenceIndex(this.selectedSequence),t=this.wrapIndex(e-1,this.sequences);return this.sequences[t]},getSequenceIndex:function(e){var t=this.sequences.indexOf(e);if(t<0)throw new Error("didnt find");return t},getIndexForID:function(e){return d.getLevelArbiter().getLevel(e).index},selectFirst:function(){var e=this.sequenceToLevels[this.sequences[0]][0].id;this.selectIconByID(e),this.selectedIndex=0,this.selectedSequence=this.sequences[0]},getCurrentSequence:function(){return this.sequenceToLevels[this.selectedSequence]},getSelectedID:function(){return this.sequenceToLevels[this.selectedSequence][this.selectedIndex].id},selectIconByID:function(e){this.toggleIconSelect(e,!0)},deselectIconByID:function(e){this.toggleIconSelect(e,!1)},toggleIconSelect:function(e,t){this.selectedID=e;var n="#levelIcon-"+e;$(n).toggleClass("selected",t)},negative:function(){this.hide()},testOption:function(e){return this.currentCommand&&(new RegExp("--"+e)).test(this.currentCommand.get("rawStr"))},show:function(e,t){this.currentCommand=t,this.updateSolvedStatus(),this.showDeferred=e,this.keyboardListener.listen(),y.__super__.show.apply(this)},hide:function(){this.showDeferred&&this.showDeferred.resolve(),this.showDeferred=undefined,this.keyboardListener.mute(),this.turnOffKeyboardSelection(),y.__super__.hide.apply(this)},loadLevelID:function(e){if(!this.testOption("noOutput")){d.getEventBaton().trigger("commandSubmitted","level "+e);var t=d.getLevelArbiter().getLevel(e),n=t.name.en_US;h.levelSelected(n)}this.hide()},updateSolvedStatus:function(){u.each(this.seriesViews,function(e){e.updateSolvedStatus()},this)},buildSequences:function(){this.seriesViews=[],u.each(this.sequences,function(e){this.seriesViews.push(new b({destination:this.$el,name:e,navEvents:this.navEvents}))},this)}}),b=g.extend({tagName:"div",className:"seriesView box flex1 vertical",template:u.template($("#series-view").html()),events:{"click div.levelIcon":"click","mouseenter div.levelIcon":"enterIcon","mouseleave div.levelIcon":"leaveIcon"},initialize:function(e){this.name=e.name||"intro",this.navEvents=e.navEvents,this.info=d.getLevelArbiter().getSequenceInfo(this.name),this.levels=d.getLevelArbiter().getLevelsInSequence(this.name),this.levelIDs=[],u.each(this.levels,function(e){this.levelIDs.push(e.id)},this),this.destination=e.destination,this.JSON={displayName:c.getIntlKey(this.info,"displayName"),about:c.getIntlKey(this.info,"about")||" ",ids:this.levelIDs},this.render(),this.updateSolvedStatus()},updateSolvedStatus:function(){var e=this.$("div.levelIcon").each(function(e,t){var n=$(t).attr("data-id");$(t).toggleClass("solved",d.getLevelArbiter().isLevelSolved(n))})},getEventID:function(e){var t=e.target;return $(t).attr("data-id")},resetAbout:function(){this.$("p.about").text(c.getIntlKey(this.info,"about")).css("font-style","inherit")},setAbout:function(e){this.$("p.about").text(e).css("font-style","italic")},enterIcon:function(e){var t=this.getEventID(e),n=d.getLevelArbiter().getLevel(t);this.setAbout(c.getName(n))},leaveIcon:function(){this.resetAbout()},click:function(e){var t=this.getEventID(e);this.navEvents.trigger("clickedID",t)}});n.LevelDropdownView=y}),e("/src/js/views/levelDropdownView.js"),e.define("/src/js/views/multiView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../views").ModalTerminal,c=e("../views").ContainedBase,h=e("../views").ConfirmCancelView,p=e("../views").LeftRightView,d=e("../views").ModalAlert,v=e("../views/gitDemonstrationView").GitDemonstrationView,m=e("../views/builderViews"),g=m.MarkdownPresenter,y=e("../util/keyboard").KeyboardListener,b=e("../util/errors").GitError,w=f.View.extend({tagName:"div",className:"multiView",navEventDebounce:550,deathTime:700,typeToConstructor:{ModalAlert:d,GitDemonstrationView:v,MarkdownPresenter:g},initialize:function(e){e=e||{},this.childViewJSONs=e.childViews||[{type:"ModalAlert",options:{markdown:"Woah wtf!!"}},{type:"GitDemonstrationView",options:{command:"git checkout -b side; git commit; git commit"}},{type:"ModalAlert",options:{markdown:"Im second"}}],this.deferred=e.deferred||a.defer(),this.childViews=[],this.currentIndex=0,this.navEvents=u.clone(f.Events),this.navEvents.on("negative",this.getNegFunc(),this),this.navEvents.on("positive",this.getPosFunc(),this),this.navEvents.on("quit",this.finish,this),this.navEvents.on("exit",this.finish,this),this.keyboardListener=new y({events:this.navEvents,aliasMap:{left:"negative",right:"positive",enter:"positive",esc:"quit"}}),this.render(),e.wait||this.start()},onWindowFocus:function(){},getAnimationTime:function(){return 700},getPromise:function(){return this.deferred.promise},getPosFunc:function(){return u.debounce(u.bind(function(){this.navForward()},this),this.navEventDebounce,!0)},getNegFunc:function(){return u.debounce(u.bind(function(){this.navBackward()},this),this.navEventDebounce,!0)},lock:function(){this.locked=!0},unlock:function(){this.locked=!1},navForward:function(){if(this.locked)return;if(this.currentIndex===this.childViews.length-1){this.hideViewIndex(this.currentIndex),this.finish();return}this.navIndexChange(1)},navBackward:function(){if(this.currentIndex===0)return;this.navIndexChange(-1)},navIndexChange:function(e){this.hideViewIndex(this.currentIndex),this.currentIndex+=e,this.showViewIndex(this.currentIndex)},hideViewIndex:function(e){this.childViews[e].hide()},showViewIndex:function(e){this.childViews[e].show()},finish:function(){this.keyboardListener.mute(),u.each(this.childViews,function(e){e.die()}),this.deferred.resolve()},start:function(){this.showViewIndex(this.currentIndex)},createChildView:function(e){var t=e.type;if(!this.typeToConstructor[t])throw new Error('no constructor for type "'+t+'"');var n=new this.typeToConstructor[t](u.extend({},e.options,{wait:!0}));return n},addNavToView:function(e,t){var n=new p({events:this.navEvents,destination:e.getDestination(),showLeft:t!==0,lastNav:t===this.childViewJSONs.length-1});e.receiveMetaNav&&e.receiveMetaNav(n,this)},render:function(){u.each(this.childViewJSONs,function(e,t){var n=this.createChildView(e);this.childViews.push(n),this.addNavToView(n,t)},this)}});n.MultiView=w}),e("/src/js/views/multiView.js"),e.define("/src/js/views/rebaseView.js",function(e,t,n,r,i,s,o){var u=e("../util/errors").GitError,a=e("underscore"),f=e("q"),l=e("../util").isBrowser()?window.Backbone:e("backbone"),c=e("../views").ModalTerminal,h=e("../views").ContainedBase,p=e("../views").ConfirmCancelView,d=e("../views").LeftRightView,v=h.extend({tagName:"div",template:a.template($("#interactive-rebase-template").html()),initialize:function(e){this.deferred=e.deferred,this.rebaseMap={},this.entryObjMap={},this.rebaseEntries=new g,e.toRebase.reverse(),a.each(e.toRebase,function(e){var t=e.get("id");this.rebaseMap[t]=e,this.entryObjMap[t]=new m({id:t}),this.rebaseEntries.add(this.entryObjMap[t])},this),this.container=new c({title:"Interactive Rebase"}),this.render(),this.show()},confirm:function(){this.die();var e=[];this.$("ul.rebaseEntries li").each(function(t,n){e.push(n.id)});var t=[];a.each(e,function(e){this.entryObjMap[e].get("pick")&&t.unshift(this.rebaseMap[e])},this),t.reverse(),this.deferred.resolve(t),this.$el.html("")},render:function(){var e={num:a.keys(this.rebaseMap).length},t=this.container.getInsideElement();this.$el.html(this.template(e)),$(t).append(this.el);var n=this.$("ul.rebaseEntries");this.rebaseEntries.each(function(e){new y({el:n,model:e})},this),n.sortable({axis:"y",placeholder:"rebaseEntry transitionOpacity ui-state-highlight",appendTo:"parent"}),this.makeButtons()},makeButtons:function(){var e=f.defer();e.promise.then(a.bind(function(){this.confirm()},this)).fail(a.bind(function(){this.hide(),this.deferred.resolve([])},this)).done(),new p({destination:this.$(".confirmCancel"),deferred:e})}}),m=l.Model.extend({defaults:{pick:!0},toggle:function(){this.set("pick",!this.get("pick"))}}),g=l.Collection.extend({model:m}),y=l.View.extend({tagName:"li",template:a.template($("#interactive-rebase-entry-template").html()),toggle:function(){this.model.toggle(),this.listEntry.toggleClass("notPicked",!this.model.get("pick"))},initialize:function(e){this.render()},render:function(){var e=this.model.toJSON();this.$el.append(this.template(this.model.toJSON())),this.listEntry=this.$el.children(":last"),this.listEntry.delegate("#toggleButton","click",a.bind(function(){this.toggle()},this))}});n.InteractiveRebaseView=v}),e("/src/js/views/rebaseView.js"),e.define("/src/js/visuals/animation/animationFactory.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("./index").Animation,c=e("./index").PromiseAnimation,h=e("../../util/constants").GRAPHICS,p={},d=function(e,t){var n=h.defaultAnimationTime*1,r=n*2,i=function(){e.refreshTree(n),t.setBirth(),t.parentInFront(),e.visBranchesFront(),t.animateUpdatedPosition(r,"bounce"),t.animateOutgoingEdges(n)};return{animation:i,duration:Math.max(n,r)}},v=function(e,t){var n=h.defaultAnimationTime*.66,r=n*2;return{animation:function(){e.highlightTo(t,r,"easeInOut")},duration:r*1.5}};p.genCommitBirthAnimation=function(e,t,n){if(!e)throw new Error("Need animation queue to add closure to!");var r=t.get("visNode"),i=d(n,r);e.add(new l({closure:i.animation,duration:i.duration}))},p.genCommitBirthPromiseAnimation=function(e,t){var n=e.get("visNode");return new c(d(t,n))},p.highlightEachWithPromise=function(e,t,n){return u.each(t,function(t){e=e.then(u.bind(function(){return this.playHighlightPromiseAnimation(t,n)},this))},this),e},p.playCommitBirthPromiseAnimation=function(e,t){var n=this.genCommitBirthPromiseAnimation(e,t);return n.play(),n.getPromise()},p.playRefreshAnimationAndFinish=function(e,t){var n=new c({closure:function(){e.refreshTree()}});n.play(),t.thenFinish(n.getPromise())},p.playRefreshAnimation=function(e){var t=new c({closure:function(){e.refreshTree()}});return t.play(),t.getPromise()},p.refreshTree=function(e,t){e.add(new l({closure:function(){t.refreshTree()}}))},p.genHighlightPromiseAnimation=function(e,t){var n=t.get("visBranch")||t.get("visNode"),r=e.get("visNode");return new c(v(r,n))},p.playHighlightPromiseAnimation=function(e,t){var n=this.genHighlightPromiseAnimation(e,t);return n.play(),n.getPromise()},p.getDelayedPromise=function(e){var t=f.defer();return setTimeout(t.resolve,e||1e3),t.promise},p.delay=function(e,t){t=t||h.defaultAnimationTime,e.add(new l({closure:function(){},duration:t}))},n.AnimationFactory=p}),e("/src/js/visuals/animation/animationFactory.js"),e.define("/src/js/visuals/animation/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("backbone"),l=e("../../util/constants").GLOBAL,c=f.Model.extend({defaults:{duration:300,closure:null},validateAtInit:function(){if(!this.get("closure"))throw new Error("give me a closure!")},initialize:function(e){this.validateAtInit()},run:function(){this.get("closure")()}}),h=f.Model.extend({defaults:{animations:null,index:0,callback:null,defer:!1,promiseBased:!1},initialize:function(e){this.set("animations",[]),e.callback||console.warn("no callback")},thenFinish:function(e,t){e.then(u.bind(function(){this.finish()},this)),this.set("promiseBased",!0),t&&t.resolve()},add:function(e){if(!e instanceof c)throw new Error("Need animation not something else");this.get("animations").push(e)},start:function(){this.set("index",0),l.isAnimating=!0,this.next()},finish:function(){l.isAnimating=!1,this.get("callback")()},next:function(){var e=this.get("animations"),t=this.get("index");if(t>=e.length){this.finish();return}var n=e[t],r=n.get("duration");n.run(),this.set("index",t+1),setTimeout(u.bind(function(){this.next()},this),r)}}),p=f.Model.extend({defaults:{deferred:null,closure:null,duration:300},initialize:function(e){if(!e.closure&&!e.animation)throw new Error("need closure or animation");this.set("closure",e.closure||e.animation),this.set("deferred",e.deferred||a.defer())},getPromise:function(){return this.get("deferred").promise},play:function(){this.get("closure")(),setTimeout(u.bind(function(){this.get("deferred").resolve()},this),this.get("duration"))},then:function(e){return this.get("deferred").promise.then(e)}});p.fromAnimation=function(e){return new p({closure:e.get("closure"),duration:e.get("duration")})},n.Animation=c,n.PromiseAnimation=p,n.AnimationQueue=h}),e("/src/js/visuals/animation/index.js"),e.define("/src/js/visuals/index.js",function(e,t,n,r,i,s,o){function w(t){t=t||{},this.options=t,this.visualization=t.visualization,this.commitCollection=t.commitCollection,this.branchCollection=t.branchCollection,this.visNodeMap={},this.visEdgeCollection=new b,this.visBranchCollection=new g,this.commitMap={},this.rootCommit=null,this.branchStackMap=null,this.upstreamBranchSet=null,this.upstreamHeadSet=null,this.paper=t.paper,this.gitReady=!1,this.branchCollection.on("add",this.addBranchFromEvent,this),this.branchCollection.on("remove",this.removeBranch,this),this.deferred=[],this.flipFraction=.65;var n=e("../app");n.getEvents().on("refreshTree",this.refreshTree,this)}function E(e){var t=0,n=0,r=0,i=0,s=e.length;u.each(e,function(e){var s=e.split("(")[1];s=s.split(")")[0],s=s.split(","),r+=parseFloat(s[1]),i+=parseFloat(s[2]);var o=parseFloat(s[0]),u=o*Math.PI*2;t+=Math.cos(u),n+=Math.sin(u)}),t/=s,n/=s,r/=s,i/=s;var o=Math.atan2(n,t)/(Math.PI*2);return o<0&&(o+=1),"hsb("+String(o)+","+String(r)+","+String(i)+")"}var u=e("underscore"),a=e("q"),f=e("backbone"),l=e("../util/constants").GRAPHICS,c=e("../util/constants").GLOBAL,h=e("../models/collections"),p=h.CommitCollection,d=h.BranchCollection,v=e("../visuals/visNode").VisNode,m=e("../visuals/visBranch").VisBranch,g=e("../visuals/visBranch").VisBranchCollection,y=e("../visuals/visEdge").VisEdge,b=e("../visuals/visEdge").VisEdgeCollection;w.prototype.defer=function(e){this.deferred.push(e)},w.prototype.deferFlush=function(){u.each(this.deferred,function(e){e()},this),this.deferred=[]},w.prototype.resetAll=function(){var e=this.visEdgeCollection.toArray();u.each(e,function(e){e.remove()},this);var t=this.visBranchCollection.toArray();u.each(t,function(e){e.remove()},this),u.each(this.visNodeMap,function(e){e.remove()},this),this.visEdgeCollection.reset(),this.visBranchCollection.reset(),this.visNodeMap={},this.rootCommit=null,this.commitMap={}},w.prototype.tearDown=function(){this.resetAll(),this.paper.remove()},w.prototype.assignGitEngine=function(e){this.gitEngine=e,this.initHeadBranch(),this.deferFlush()},w.prototype.getVisualization=function(){return this.visualization},w.prototype.initHeadBranch=function(){this.addBranchFromEvent(this.gitEngine.HEAD)},w.prototype.getScreenPadding=function(){return{widthPadding:l.nodeRadius*1.5,topHeightPadding:l.nodeRadius*1.5,bottomHeightPadding:l.nodeRadius*5}},w.prototype.getPosBoundaries=function(){return this.gitEngine.hasOrigin()?{min:0,max:.5}:this.gitEngine.isOrigin()?{min:.5,max:1}:{min:0,max:1}},w.prototype.getFlipPos=function(){var e=this.getPosBoundaries(),t=e.min,n=e.max;return this.flipFraction*(n-t)+t},w.prototype.toScreenCoords=function(e){if(!this.paper.width)throw new Error("being called too early for screen coords");var t=this.getScreenPadding(),n=function(e,t,n){return n+e*(t-n*2)},r=function(e,t,n,r){return n+e*(t-r-n)};return{x:n(e.x,this.paper.width,t.widthPadding),y:r(e.y,this.paper.height,t.topHeightPadding,t.bottomHeightPadding)}},w.prototype.animateAllAttrKeys=function(e,t,n,r){var i=a.defer(),s=function(i){i.animateAttrKeys(e,t,n,r)};this.visBranchCollection.each(s),this.visEdgeCollection.each(s),u.each(this.visNodeMap,s);var o=n!==undefined?n:l.defaultAnimationTime;return setTimeout(function(){i.resolve()},o),i.promise},w.prototype.finishAnimation=function(){var e=this,t=a.defer(),n=a.defer(),r=l.defaultAnimationTime,i=l.nodeRadius,s="Solved!!\n:D",o=null,f=u.bind(function(){o=this.paper.text(this.paper.width/2,this.paper.height/2,s),o.attr({opacity:0,"font-weight":500,"font-size":"32pt","font-family":"Monaco, Courier, font-monospace",stroke:"#000","stroke-width":2,fill:"#000"}),o.animate({opacity:1},r)},this);return t.promise.then(u.bind(function(){return this.animateAllAttrKeys({exclude:["circle"]},{opacity:0},r*1.1)},this)).then(u.bind(function(){return this.animateAllAttrKeys({exclude:["arrow","rect","path","text"]},{r:i*2},r*1.5)},this)).then(u.bind(function(){return this.animateAllAttrKeys({exclude:["arrow","rect","path","text"]},{r:i*.75},r*.5)},this)).then(u.bind(function(){return f(),this.explodeNodes()},this)).then(u.bind(function(){return this.explodeNodes()},this)).then(u.bind(function(){return this.animateAllAttrKeys({exclude:["arrow","rect","path","text"]},{},r*1.25)},this)).then(u.bind(function(){return o.animate({opacity:0},r,undefined,undefined,function(){o.remove()}),this.animateAllAttrKeys({},{})},this)).then(function(){n.resolve()}).fail(function(e){console.warn("animation error"+e)}).done(),t.resolve(),n.promise},w.prototype.explodeNodes=function(){var e=a.defer(),t=[];u.each(this.visNodeMap,function(e){t.push(e.getExplodeStepFunc())});var n=setInterval(function(){var r=[];u.each(t,function(e){e()&&r.push(e)});if(!r.length){clearInterval(n),e.resolve();return}t=r},.025);return e.promise},w.prototype.animateAllFromAttrToAttr=function(e,t,n){var r=function(r){var i=r.getID();if(u.include(n,i))return;if(!e[i]||!t[i])return;r.animateFromAttrToAttr(e[i],t[i])};this.visBranchCollection.each(r),this.visEdgeCollection.each(r),u.each(this.visNodeMap,r)},w.prototype.genSnapshot=function(){this.fullCalc();var e={};return u.each(this.visNodeMap,function(t){e[t.get("id")]=t.getAttributes()},this),this.visBranchCollection.each(function(t){e[t.getID()]=t.getAttributes()},this),this.visEdgeCollection.each(function(t){e[t.getID()]=t.getAttributes()},this),e},w.prototype.refreshTree=function(e){if(!this.gitReady||!this.gitEngine.rootCommit)return;this.fullCalc(),this.animateAll(e)},w.prototype.refreshTreeHarsh=function(){this.fullCalc(),this.animateAll(0)},w.prototype.animateAll=function(e){this.zIndexReflow(),this.animateEdges(e),this.animateNodePositions(e),this.animateRefs(e)},w.prototype.fullCalc=function(){this.calcTreeCoords(),this.calcGraphicsCoords()},w.prototype.calcTreeCoords=function(){if(!this.rootCommit)throw new Error("grr, no root commit!");this.calcUpstreamSets(),this.calcBranchStacks(),this.calcDepth(),this.calcWidth()},w.prototype.calcGraphicsCoords=function(){this.visBranchCollection.each(function(e){e.updateName()})},w.prototype.calcUpstreamSets=function(){this.upstreamBranchSet=this.gitEngine.getUpstreamBranchSet(),this.upstreamHeadSet=this.gitEngine.getUpstreamHeadSet()},w.prototype.getCommitUpstreamBranches=function(e){return this.branchStackMap[e.get("id")]},w.prototype.getBlendedHuesForCommit=function(e){var t=this.upstreamBranchSet[e.get("id")];if(!t)throw new Error("that commit doesnt have upstream branches!");return this.blendHuesFromBranchStack(t)},w.prototype.blendHuesFromBranchStack=function(e){var t=[];return u.each(e,function(e){var n=e.obj.get("visBranch").get("fill");if(n.slice(0,3)!=="hsb"){var r=Raphael.color(n);n="hsb("+String(r.h)+","+String(r.l),n=n+","+String(r.s)+")"}t.push(n)}),E(t)},w.prototype.getCommitUpstreamStatus=function(e){if(!this.upstreamBranchSet)throw new Error("Can't calculate this yet!");var t=e.get("id"),n=this.upstreamBranchSet,r=this.upstreamHeadSet;return n[t]?"branch":r[t]?"head":"none"},w.prototype.calcBranchStacks=function(){var e=this.gitEngine.getBranches(),t={};u.each(e,function(e){var n=e.target.get("id");t[n]=t[n]||[],t[n].push(e),t[n].sort(function(e,t){var n=e.obj.get("id"),r=t.obj.get("id");return n=="master"||r=="master"?n=="master"?-1:1:n.localeCompare(r)})}),this.branchStackMap=t},w.prototype.calcWidth=function(){this.maxWidthRecursive(this.rootCommit);var e=this.getPosBoundaries();this.assignBoundsRecursive(this.rootCommit,e.min,e.max)},w.prototype.maxWidthRecursive=function(e){var t=0;u.each(e.get("children"),function(n){if(n.isMainParent(e)){var r=this.maxWidthRecursive(n);t+=r}},this);var n=Math.max(1,t);return e.get("visNode").set("maxWidth",n),n},w.prototype.assignBoundsRecursive=function(e,t,n){var r=(n+t)/2;e.get("visNode").get("pos").x=r;if(e.get("children").length===0)return;var i=n-t,s=0,o=e.get("children");u.each(o,function(t){t.isMainParent(e)&&(s+=t.get("visNode").getMaxWidthScaled())},this);var a=t;u.each(o,function(t,n){if(!t.isMainParent(e))return;var r=t.get("visNode").getMaxWidthScaled(),o=r/s*i,u=a,f=u+o;this.assignBoundsRecursive(t,u,f),a=u+o},this)},w.prototype.calcDepth=function(){var e=this.calcDepthRecursive(this.rootCommit,0);e>15&&console.warn("graphics are degrading from too many layers");var t=this.getDepthIncrement(e);u.each(this.visNodeMap,function(e){e.setDepthBasedOn(t,this.getHeaderOffset())},this)},w.prototype.animateNodePositions=function(e){u.each(this.visNodeMap,function(t){t.animateUpdatedPosition(e)},this)},w.prototype.addBranchFromEvent=function(e,t,n){var r=u.bind(function(){this.addBranch(e)},this);!this.gitEngine||!this.gitReady?this.defer(r):r()},w.prototype.addBranch=function(e){var t=new m({branch:e,gitVisuals:this,gitEngine:this.gitEngine});this.visBranchCollection.add(t),this.gitReady?t.genGraphics(this.paper):this.defer(u.bind(function(){t.genGraphics(this.paper)},this))},w.prototype.removeVisBranch=function(e){this.visBranchCollection.remove(e)},w.prototype.removeVisNode=function(e){this.visNodeMap[e.getID()]=undefined},w.prototype.removeVisEdge=function(e){this.visEdgeCollection.remove(e)},w.prototype.animateRefs=function(e){this.visBranchCollection.each(function(t){t.animateUpdatedPos(e)},this)},w.prototype.animateEdges=function(e){this.visEdgeCollection.each(function(t){t.animateUpdatedPath(e)},this)},w.prototype.getMinLayers=function(){return this.options.smallCanvas?2:7},w.prototype.getDepthIncrement=function(e){e=Math.max(e,this.getMinLayers());var t=1-this.getHeaderOffset(),n=t/e;return n},w.prototype.shouldHaveHeader=function(){return this.gitEngine.isOrigin()||this.gitEngine.hasOrigin()},w.prototype.getHeaderOffset=function(){return this.shouldHaveHeader()?.05:0},w.prototype.calcDepthRecursive=function(e,t){e.get("visNode").setDepth(t);var n=e.get("children"),r=t;return u.each(n,function(e){var n=this.calcDepthRecursive(e,t+1);r=Math.max(n,r)},this),r},w.prototype.canvasResize=function(e,t){this.resizeFunc||this.genResizeFunc(),this.resizeFunc(e,t)},w.prototype.genResizeFunc=function(){this.resizeFunc=u.debounce(u.bind(function(t,n){this.refreshTree()},this),200,!0)},w.prototype.addNode=function(e,t){this.commitMap[e]=t,t.get("rootCommit")&&(this.rootCommit=t);var n=new v({id:e,commit:t,gitVisuals:this,gitEngine:this.gitEngine});return this.visNodeMap[e]=n,this.gitReady&&n.genGraphics(this.paper),n},w.prototype.addEdge=function(e,t){var n=this.visNodeMap[e],r=this.visNodeMap[t];if(!n||!r)throw new Error("one of the ids in ("+e+", "+t+") does not exist");var i=new y({tail:n,head:r,gitVisuals:this,gitEngine:this.gitEngine});this.visEdgeCollection.add(i),this.gitReady&&i.genGraphics(this.paper)},w.prototype.zIndexReflow=function(){this.visNodesFront(),this.visBranchesFront()},w.prototype.visNodesFront=function(){u.each(this.visNodeMap,function(e){e.toFront()})},w.prototype.visBranchesFront=function(){this.visBranchCollection.each(function(e){e.nonTextToFront(),e.textToFront()}),this.visBranchCollection.each(function(e){e.textToFrontIfInStack()})},w.prototype.drawTreeFromReload=function(){this.gitReady=!0,this.deferFlush(),this.calcTreeCoords()},w.prototype.drawTreeFirstTime=function(){this.gitReady=!0,this.calcTreeCoords(),u.each(this.visNodeMap,function(e){e.genGraphics(this.paper)},this),this.visEdgeCollection.each(function(e){e.genGraphics(this.paper)},this),this.visBranchCollection.each(function(e){e.genGraphics(this.paper)},this),this.zIndexReflow()},n.GitVisuals=w}),e("/src/js/visuals/index.js"),e.define("/src/js/visuals/tree.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({removeKeys:function(e){u.each(e,function(e){this.get(e)&&this.get(e).remove()},this)},animateAttrKeys:function(e,t,n,r){e=u.extend({},{include:["circle","arrow","rect","path","text"],exclude:[]},e||{});var i=this.getAttributes();u.each(e.include,function(e){i[e]=u.extend({},i[e],t)}),u.each(e.exclude,function(e){delete i[e]}),this.animateToAttr(i,n,r)}});n.VisBase=f}),e("/src/js/visuals/tree.js"),e.define("/src/js/visuals/visBase.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({removeKeys:function(e){u.each(e,function(e){this.get(e)&&this.get(e).remove()},this)},getNonAnimateKeys:function(){return["stroke-dasharray"]},getIsInOrigin:function(){return this.get("gitEngine")?this.get("gitEngine").isOrigin():!1},animateToAttr:function(e,t,n){if(t===0){this.setAttr(e,!0);return}var r=t!==undefined?t:this.get("animationSpeed"),i=n||this.get("animationEasing");this.setAttr(e,!1,r,i)},setAttrBase:function(e,t,n,r,i){u.each(e,function(e){n?this.get(e).attr(t[e]):(this.get(e).stop(),this.get(e).animate(t[e],r,i),u.forEach(this.getNonAnimateKeys(),function(n){t[e]&&t[e][n]!==undefined&&this.get(e).attr(n,t[e][n])},this)),t.css&&$(this.get(e).node).css(t.css)},this)},animateAttrKeys:function(e,t,n,r){e=u.extend({},{include:["circle","arrow","rect","path","text"],exclude:[]},e||{});var i=this.getAttributes();u.each(e.include,function(e){i[e]=u.extend({},i[e],t)}),u.each(e.exclude,function(e){delete i[e]}),this.animateToAttr(i,n,r)}});n.VisBase=f}),e("/src/js/visuals/visBase.js"),e.define("/src/js/visuals/visBranch.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=function(){var e=Math.random(),t="hsb("+String(e)+",0.7,1)";return t},h=l.extend({defaults:{pos:null,text:null,rect:null,arrow:null,isHead:!1,flip:1,fill:f.rectFill,stroke:f.rectStroke,"stroke-width":f.rectStrokeWidth,offsetX:f.nodeRadius*4.75,offsetY:0,arrowHeight:14,arrowInnerSkew:0,arrowEdgeHeight:6,arrowLength:14,arrowOffsetFromCircleX:10,vPad:5,hPad:5,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing},validateAtInit:function(){if(!this.get("branch"))throw new Error("need a branch!")},getID:function(){return this.get("branch").get("id")},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine");if(!this.gitEngine)throw new Error("asd wtf");this.get("branch").set("visBranch",this);var e=this.get("branch").get("id");e=="HEAD"?(this.set("isHead",!0),this.set("flip",-1),this.refreshOffset(),this.set("fill",f.headRectFill)):e!=="master"&&this.set("fill",c())},getCommitPosition:function(){var e=this.gitEngine.getCommitFromRef(this.get("branch")),t=e.get("visNode");return this.set("flip",this.getFlipValue(e,t)),this.refreshOffset(),t.getScreenCoords()},getFlipValue:function(e,t){var n=this.get("gitVisuals").getFlipPos(),r=t.get("pos").x>n;return e.get("id")==="C0"?-1:this.get("isHead")?r?this.isBranchStackEmpty()?-1:1:this.isBranchStackEmpty()?1:-1:r?-1:1},refreshOffset:function(){var e=f.nodeRadius*4.75,t=33,n=10;this.get("flip")===1?(this.set("offsetY",-t),this.set("offsetX",e-n)):(this.set("offsetY",t),this.set("offsetX",e-n))},getArrowTransform:function(){return this.get("flip")===1?"t-2,-20R-35":"t2,20R-35"},getBranchStackIndex:function(){if(this.get("isHead"))return 0;var e=this.getBranchStackArray(),t=-1;return u.each(e,function(e,n){e.obj==this.get("branch")&&(t=n)},this),t},getBranchStackLength:function(){return this.get("isHead")?1:this.getBranchStackArray().length},isBranchStackEmpty:function(){var e=this.gitVisuals.branchStackMap[this.getCommitID()];return e?e.length===0:!0},getCommitID:function(){var e=this.get("branch").get("target");return e.get("type")==="branch"&&(e=e.get("target")),e.get("id")},getBranchStackArray:function(){var e=this.gitVisuals.branchStackMap[this.getCommitID()];return e===undefined?(this.gitVisuals.calcBranchStacks(),this.getBranchStackArray()):e},getTextPosition:function(){var e=this.getCommitPosition(),t=this.getBranchStackIndex();return{x:e.x+this.get("flip")*this.get("offsetX"),y:e.y+t*f.multiBranchY+this.get("offsetY")}},getRectPosition:function(){var e=this.getTextPosition(),t=this.get("flip"),n=this.getTextSize();return{x:e.x-.5*n.w-this.get("hPad"),y:e.y-.5*n.h-this.get("vPad")}},getArrowPath:function(){var e=function(e,t,n){return{x:e.x+t,y:e.y+n}},t=function(e){return String(Math.round(e.x))+","+String(Math.round(e.y))},n=this.get("flip"),r=e(this.getCommitPosition(),n*this.get("arrowOffsetFromCircleX"),0),i=e(r,n*this.get("arrowLength"),-this.get("arrowHeight")),s=e(r,n*this.get("arrowLength"),this.get("arrowHeight")),o=e(i,n*this.get("arrowInnerSkew"),this.get("arrowEdgeHeight")),a=e(s,n*this.get("arrowInnerSkew"),-this.get("arrowEdgeHeight")),f=49,l=e(o,n*f,0),c=e(a,n*f,0),h="";h+="M"+t(l)+" ";var p=[o,i,r,s,a,c];return u.each(p,function(e){h+="L"+t(e)+" "},this),h+="z",h},getTextSize:function(){var e=function(e){var t=e.get("text")?e.get("text").node:null;return t===null?0:t.clientWidth},t=function(e){return e.w||(e.w=75),e.h||(e.h=20),e},n=this.get("text").node;if(this.get("isHead"))return t({w:n.clientWidth,h:n.clientHeight});var r=0;return u.each(this.getBranchStackArray(),function(t){r=Math.max(r,e(t.obj.get("visBranch")))}),t({w:r,h:n.clientHeight})},getSingleRectSize:function(){var e=this.getTextSize(),t=this.get("vPad"),n=this.get("hPad");return{w:e.w+t*2,h:e.h+n*2}},getRectSize:function(){var e=this.getTextSize(),t=this.get("vPad"),n=this.get("hPad"),r=this.getBranchStackLength();return{w:e.w+t*2,h:e.h*r*1.1+n*2}},getIsRemote:function(){return this.get("branch").getIsRemote()},getName:function(){var e=this.get("branch").getName(),t=this.get("branch")===this.gitEngine.HEAD.get("target"),n=this.getIsRemote(),r=t&&!this.getIsInOrigin()&&!n?"*":"";return e+r},nonTextToFront:function(){this.get("arrow").toFront(),this.get("rect").toFront()},textToFront:function(){this.get("text").toFront()},textToFrontIfInStack:function(){this.getBranchStackIndex()!==0&&this.get("text").toFront()},getFill:function(){return this.get("isHead")||this.getBranchStackLength()==1||this.getBranchStackIndex()!==0?this.get("fill"):this.gitVisuals.blendHuesFromBranchStack(this.getBranchStackArray())},remove:function(){this.removeKeys(["text","arrow","rect"]),this.gitVisuals.removeVisBranch(this)},genGraphics:function(e){var t=this.getTextPosition(),n=this.getName(),r;r=e.text(t.x,t.y,String(n)),r.attr({"font-size":14,"font-family":"Monaco, Courier, font-monospace",opacity:this.getTextOpacity()}),this.set("text",r);var i=this.getAttributes(),s=this.getRectPosition(),o=this.getRectSize(),a=e.rect(s.x,s.y,o.w,o.h,8).attr(i.rect);this.set("rect",a);var f=this.getArrowPath(),l=e.path(f).attr(i.arrow);this.set("arrow",l);var c=["text","rect","arrow"];u.each(c,function(e){$(this.get(e).node).css(i.css)},this),this.attachClickHandlers(),a.toFront(),r.toFront()},attachClickHandlers:function(){if(this.get("gitVisuals").options.noClick)return;var e=[this.get("rect"),this.get("text"),this.get("arrow")];u.each(e,function(e){e.click(u.bind(this.onClick,this))},this)},shouldDisableClick:function(){return this.get("isHead")&&!this.gitEngine.getDetachedHead()},onClick:function(){if(this.shouldDisableClick())return;var t="git checkout "+this.get("branch").get("id"),n=e("../app");n.getEventBaton().trigger("commandSubmitted",t)},updateName:function(){this.get("text").attr({text:this.getName()})},getNonTextOpacity:function(){return this.get("isHead")?this.gitEngine.getDetachedHead()?1:0:this.getBranchStackIndex()===0?1:0},getTextOpacity:function(){return this.get("isHead")?this.gitEngine.getDetachedHead()?1:0:1},getAttributes:function(){var e=this.getNonTextOpacity(),t=this.getTextOpacity();this.updateName();var n=this.getTextPosition(),r=this.getRectPosition(),i=this.getRectSize(),s=this.getArrowPath(),o=this.getIsInOrigin()?f.originDash:"",u=this.shouldDisableClick()?"auto":"pointer";return{css:{cursor:u},text:{x:n.x,y:n.y,opacity:t},rect:{x:r.x,y:r.y,width:i.w,height:i.h,opacity:e,fill:this.getFill(),stroke:this.get("stroke"),"stroke-width":this.get("stroke-width")},arrow:{path:s,opacity:e,fill:this.getFill(),stroke:this.get("stroke"),transform:this.getArrowTransform(),"stroke-width":this.get("stroke-width")}}},animateUpdatedPos:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},setAttr:function(e,t,n,r){var i=["text","rect","arrow"];this.setAttrBase(i,e,t,n,r)}}),p=a.Collection.extend({model:h});n.VisBranchCollection=p,n.VisBranch=h,n.randomHueString=c}),e("/src/js/visuals/visBranch.js"),e.define("/src/js/visuals/visEdge.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=l.extend({defaults:{tail:null,head:null,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing},validateAtInit:function(){var e=["tail","head"];u.each(e,function(e){if(!this.get(e))throw new Error(e+" is required!")},this)},getID:function(){return this.get("tail").get("id")+"."+this.get("head").get("id")},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine"),this.get("tail").get("outgoingEdges").push(this)},remove:function(){this.removeKeys(["path"]),this.gitVisuals.removeVisEdge(this)},genSmoothBezierPathString:function(e,t){var n=e.getScreenCoords(),r=t.getScreenCoords();return this.genSmoothBezierPathStringFromCoords(n,r)},genSmoothBezierPathStringFromCoords:function(e,t){var n=function(e){return String(Math.round(e.x))+","+String(Math.round(e.y))},r=function(e,t,n){return n=n||f.curveControlPointOffset,{x:e.x,y:e.y+n*t}},i=function(e,t,n){return{x:e.x+t,y:e.y+n}};e=r(e,-1,this.get("tail").getRadius()),t=r(t,1,this.get("head").getRadius());var s="";s+="M"+n(e)+" ",s+="C",s+=n(r(e,-1))+" ",s+=n(r(t,1))+" ",s+=n(t);var o=f.arrowHeadSize||10;return s+=" L"+n(i(t,-o,o)),s+=" L"+n(i(t,o,o)),s+=" L"+n(t),s+="C",s+=n(r(t,1))+" ",s+=n(r(e,-1))+" ",s+=n(e),s},getBezierCurve:function(){return this.genSmoothBezierPathString(this.get("tail"),this.get("head"))},getStrokeColor:function(){return f.visBranchStrokeColorNone},setOpacity:function(e){e=e===undefined?1:e,this.get("path").attr({opacity:e})},genGraphics:function(e){var t=this.getBezierCurve(),n=e.path(t).attr({"stroke-width":f.visBranchStrokeWidth,stroke:this.getStrokeColor(),"stroke-linecap":"round","stroke-linejoin":"round",fill:this.getStrokeColor()});n.toBack(),this.set("path",n)},getOpacity:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("tail")),t={branch:1,head:f.edgeUpstreamHeadOpacity,none:f.edgeUpstreamNoneOpacity};if(t[e]===undefined)throw new Error("bad stat");return t[e]},getAttributes:function(){var e=this.getBezierCurve(),t=this.getOpacity();return{path:{path:e,opacity:t}}},animateUpdatedPath:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},animateToAttr:function(e,t,n){if(t===0){this.get("path").attr(e.path);return}this.get("path").toBack(),this.get("path").stop(),this.get("path").animate(e.path,t!==undefined?t:this.get("animationSpeed"),n||this.get("animationEasing"))}}),h=a.Collection.extend({model:c});n.VisEdgeCollection=h,n.VisEdge=c}),e("/src/js/visuals/visEdge.js"),e.define("/src/js/visuals/visNode.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=l.extend({defaults:{depth:undefined,maxWidth:null,outgoingEdges:null,circle:null,text:null,id:null,pos:null,radius:null,commit:null,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing,fill:f.defaultNodeFill,"stroke-width":f.defaultNodeStrokeWidth,stroke:f.defaultNodeStroke},getID:function(){return this.get("id")},validateAtInit:function(){if(!this.get("id"))throw new Error("need id for mapping");if(!this.get("commit"))throw new Error("need commit for linking");this.get("pos")||this.set("pos",{x:Math.random(),y:Math.random()})},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine"),this.set("outgoingEdges",[])},setDepth:function(e){this.set("depth",Math.max(this.get("depth")||0,e))},setDepthBasedOn:function(e,t){if(this.get("depth")===undefined)throw new Error("no depth yet!");var n=this.get("pos");n.y=this.get("depth")*e+t},getMaxWidthScaled:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("commit")),t={branch:1,head:.3,none:.1};if(t[e]===undefined)throw new Error("bad stat");return t[e]*this.get("maxWidth")},toFront:function(){this.get("circle").toFront(),this.get("text").toFront()},getOpacity:function(){var e={branch:1,head:f.upstreamHeadOpacity,none:f.upstreamNoneOpacity},t=this.gitVisuals.getCommitUpstreamStatus(this.get("commit"));if(e[t]===undefined)throw new Error("invalid status");return e[t]},getTextScreenCoords:function(){return this.getScreenCoords()},getAttributes:function(){var e=this.getScreenCoords(),t=this.getTextScreenCoords(),n=this.getOpacity(),r=this.getIsInOrigin()?f.originDash:"";return{circle:{cx:e.x,cy:e.y,opacity:n,r:this.getRadius(),fill:this.getFill(),"stroke-width":this.get("stroke-width"),"stroke-dasharray":r,stroke:this.get("stroke")},text:{x:t.x,y:t.y,opacity:n}}},highlightTo:function(e,t,n){var r=e.get("fill"),i={circle:{fill:r,stroke:r,"stroke-dasharray":"","stroke-width":this.get("stroke-width")*5},text:{}};this.animateToAttr(i,t,n)},animateUpdatedPosition:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},animateToSnapshot:function(e,t,n){if(!e[this.getID()])return;this.animateToAttr(e[this.getID()],t,n)},setAttr:function(e,t,n,r){var i=["text","circle"];this.setAttrBase(i,e,t,n,r)},animateToAttr:function(e,t,n){l.prototype.animateToAttr.apply(this,arguments);var r=t!==undefined?t:this.get("animationSpeed"),i=n||this.get("animationEasing");n=="bounce"&&e.circle&&e.circle.cx!==undefined&&e.text&&e.text.x!==undefined&&(this.get("circle").animate(e.circle.cx,r,"easeInOut"),this.get("text").animate(e.text.x,r,"easeInOut"))},getScreenCoords:function(){var e=this.get("pos");return this.gitVisuals.toScreenCoords(e)},getRadius:function(){return this.get("radius")||f.nodeRadius},getParentScreenCoords:function(){return this.get("commit").get("parents")[0].get("visNode").getScreenCoords()},setBirthPosition:function(){var e=this.getParentScreenCoords();this.get("circle").attr({cx:e.x,cy:e.y,opacity:0,r:0}),this.get("text").attr({x:e.x,y:e.y,opacity:0})},setBirthFromSnapshot:function(e){var t=this.get("commit").get("parents")[0].get("visNode").getID(),n=e[t];this.get("circle").attr({opacity:0,r:0,cx:n.circle.cx,cy:n.circle.cy}),this.get("text").attr({opacity:0,x:n.text.x,y:n.text.y});var r={x:n.circle.cx,y:n.circle.cy};this.setOutgoingEdgesBirthPosition(r)},setBirth:function(){this.setBirthPosition(),this.setOutgoingEdgesBirthPosition(this.getParentScreenCoords())},setOutgoingEdgesOpacity:function(e){u.each(this.get("outgoingEdges"),function(t){t.setOpacity(e)})},animateOutgoingEdgesToAttr:function(e,t,n){u.each(this.get("outgoingEdges"),function(t){var n=e[t.getID()];t.animateToAttr(n)},this)},animateOutgoingEdges:function(e,t){u.each(this.get("outgoingEdges"),function(n){n.animateUpdatedPath(e,t)},this)},animateOutgoingEdgesFromSnapshot:function(e,t,n){u.each(this.get("outgoingEdges"),function(r){var i=e[r.getID()];r.animateToAttr(i,t,n)},this)},setOutgoingEdgesBirthPosition:function(e){u.each(this.get("outgoingEdges"),function(t){var n=t.get("head").getScreenCoords(),r=t.genSmoothBezierPathStringFromCoords(e,n);t.get("path").stop(),t.get("path").attr({path:r,opacity:0})},this)},parentInFront:function(){this.get("commit").get("parents")[0].get("visNode").toFront()},getFontSize:function(e){return e.length<3?12:e.length<5?10:8},getFill:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("commit"));return e=="head"?f.headRectFill:e=="none"?f.orphanNodeFill:this.gitVisuals.getBlendedHuesForCommit(this.get("commit"))},attachClickHandlers:function(){if(this.get("gitVisuals").options.noClick)return;var t="git checkout "+this.get("commit").get("id"),n=e("../app");u.each([this.get("circle"),this.get("text")],function(e){e.click(function(){n.getEventBaton().trigger("commandSubmitted",t)}),$(e.node).css("cursor","pointer")})},setOpacity:function(e){e=e===undefined?1:e;var t=["circle","text"];u.each(t,function(t){this.get(t).attr({opacity:e})},this)},remove:function(){this.removeKeys(["circle"],["text"]);var e=this.get("text");e&&e.remove(),this.gitVisuals.removeVisNode(this)},removeAll:function(){this.remove(),u.each(this.get("outgoingEdges"),function(e){e.remove()},this)},getExplodeStepFunc:function(){var e=this.get("circle"),t=20,n=Math.PI+Math.random()*1*Math.PI,r=.2,i=.01,s=t*Math.cos(n),o=t*Math.sin(n),u=e.attr("cx"),a=e.attr("cy"),f=this.gitVisuals.paper.width,l=this.gitVisuals.paper.height,c=.8,h=1,p=function(){o+=r*h-i*o,s-=i*s,u+=s*h,a+=o*h;if(u<0||u>f)s=c*-s,u=u<0?0:f;if(a<0||a>l)o=c*-o,a=a<0?0:l;return e.attr({cx:u,cy:a}),s*s+o*o<.01&&Math.abs(a-l)===0?!1:!0};return p},genGraphics:function(){var e=this.gitVisuals.paper,t=this.getScreenCoords(),n=this.getTextScreenCoords(),r=e.circle(t.x,t.y,this.getRadius()).attr(this.getAttributes().circle),i=e.text(n.x,n.y,String(this.get("id")));i.attr({"font-size":this.getFontSize(this.get("id")),"font-weight":"bold","font-family":"Monaco, Courier, font-monospace",opacity:this.getOpacity()}),this.set("circle",r),this.set("text",i),this.attachClickHandlers()}});n.VisNode=c}),e("/src/js/visuals/visNode.js"),e.define("/src/js/visuals/visualization.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../models/collections"),l=f.CommitCollection,c=f.BranchCollection,h=e("../util/eventBaton").EventBaton,p=e("../visuals").GitVisuals,d=a.View.extend({initialize:function(e){e=e||{},this.options=e,this.customEvents=u.clone(a.Events),this.containerElement=e.containerElement;var t=this,n=e.containerElement||$("#canvasHolder")[0];new Raphael(n,200,200,function(){var n=this;s.nextTick(function(){t.paperInitialize(n,e)})})},paperInitialize:function(t,n){this.treeString=n.treeString,this.paper=t;var r=e("../app");this.eventBaton=n.noKeyboardInput?new h:r.getEventBaton(),this.commitCollection=new l,this.branchCollection=new c,this.gitVisuals=new p({commitCollection:this.commitCollection,branchCollection:this.branchCollection,paper:this.paper,noClick:this.options.noClick,smallCanvas:this.options.smallCanvas,visualization:this});var i=e("../git").GitEngine;this.gitEngine=new i({collection:this.commitCollection,branches:this.branchCollection,gitVisuals:this.gitVisuals,eventBaton:this.eventBaton}),this.gitEngine.init(),this.gitVisuals.assignGitEngine(this.gitEngine),this.myResize(),$(window).on("resize",u.bind(function(){this.myResize()},this)),this.gitVisuals.drawTreeFirstTime(),this.treeString&&this.gitEngine.loadTreeFromString(this.treeString),this.options.zIndex&&this.setTreeIndex(this.options.zIndex),this.shown=!1,this.setTreeOpacity(0),s.nextTick(u.bind(this.fadeTreeIn,this)),this.customEvents.trigger("gitEngineReady"),this.customEvents.trigger("paperReady")},clearOrigin:function(){delete this.originVis},makeOrigin:function(e){return this.originVis=new d(u.extend({},this.options,{noKeyboardInput:!0,noClick:!0,treeString:e.treeString})),this.originVis},originToo:function(e,t){if(!this.originVis)return;var n=u.bind(function(){this.originVis[e].apply(this.originVis,t)},this);if(this.originVis.paper){n();return}this.originVis.customEvents.on("paperReady",n)},setTreeIndex:function(e){$(this.paper.canvas).css("z-index",e),this.originToo("setTreeIndex",arguments)},setTreeOpacity:function(e){e===0&&(this.shown=!1),$(this.paper.canvas).css("opacity",e),this.originToo("setTreeOpacity",arguments)},getAnimationTime:function(){return 300},fadeTreeIn:function(){this.shown=!0,$(this.paper.canvas).animate({opacity:1},this.getAnimationTime()),this.originToo("fadeTreeIn",arguments)},fadeTreeOut:function(){this.shown=!1,$(this.paper.canvas).animate({opacity:0},this.getAnimationTime()),this.originToo("fadeTreeOut",arguments)},hide:function(){this.fadeTreeOut(),setTimeout(u.bind(function(){$(this.paper.canvas).css("visibility","hidden")},this),this.getAnimationTime()),this.originToo("hide",arguments)},show:function(){$(this.paper.canvas).css("visibility","visible"),setTimeout(u.bind(this.fadeTreeIn,this),10),this.originToo("show",arguments)},showHarsh:function(){$(this.paper.canvas).css("visibility","visible"),this.setTreeOpacity(1),this.originToo("showHarsh",arguments)},resetFromThisTreeNow:function(e){this.treeString=e;var t=this.getOriginInTreeString(e);if(t){var n=this.gitEngine.printTree(t);this.originToo("resetFromThisThreeNow",[n])}},getOriginInTreeString:function(e){var t=JSON.parse(unescape(e));return t.originTree},reset:function(e){var t=e||this.treeString;this.setTreeOpacity(0),t?this.gitEngine.loadTreeFromString(t):this.gitEngine.defaultInit(),this.fadeTreeIn();if(this.originVis)if(t){var n=this.getOriginInTreeString(t);this.originToo("reset",[JSON.stringify(n)])}else this.originToo("reset",arguments)},tearDown:function(){this.gitEngine.tearDown(),this.gitVisuals.tearDown(),delete this.paper,this.originToo("tearDown",arguments)},die:function(){this.fadeTreeOut(),setTimeout(u.bind(function(){this.shown||this.tearDown()},this),this.getAnimationTime()),this.originToo("die",arguments)},myResize:function(){if(!this.paper)return;var e=1,t=this.el,n=t.clientWidth-e,r=t.clientHeight-e;if(!this.containerElement){var i=t.offsetLeft,s=t.offsetTop;$(this.paper.canvas).css({position:"absolute",left:i+"px",top:s+"px"})}this.paper.setSize(n,r),this.gitVisuals.canvasResize(n,r)}});n.Visualization=d}),e("/src/js/visuals/visualization.js"),e.define("/src/levels/advanced/multipleParents.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C7","id":"master"},"bugWork":{"target":"C2","id":"bugWork"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C2"],"id":"C5"},"C6":{"parents":["C4","C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',solutionCommand:"git branch bugWork master^^2^",startTree:'{"branches":{"master":{"target":"C7","id":"master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C2"],"id":"C5"},"C6":{"parents":["C4","C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Multiple parents",zh_CN:"多个父提交记录"},hint:{en_US:"Use `git branch bugWork` with a target commit to create the missing reference.",zh_CN:"使用`git branch bugWork`加上一个目标提交记录来创建消失的引用。"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["### Specifying Parents","","Like the `~` modifier, the `^` modifier also accepts an optional number after it.","","Rather than specifying the number of generations to go back (what `~` takes), the modifier on `^` specifies which parent reference to follow from a merge commit. Remember that merge commits have multiple parents, so the path to choose is ambiguous.","",'Git will normally follow the "first" parent upwards from a merge commit, but specifying a number with `^` changes this default behavior.',"","Enough talking, let's see it in action.",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have a merge commit. If we checkout `master^` without the modifier, we will follow the first parent after the merge commit. ","","(*In our visuals, the first parent is positioned directly above the merge commit.*)"],afterMarkdowns:["Easy -- this is what we are all used to."],command:"git checkout master^",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Now let's try specifying the second parent instead..."],afterMarkdowns:["See? We followed the other parent upwards."],command:"git checkout master^2",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["The `^` and `~` modifiers can make moving around a commit tree very powerful:"],afterMarkdowns:["Lightning fast!"],command:"git checkout HEAD~; git checkout HEAD^2; git checkout HEAD~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Even crazier, these modifiers can be chained together! Check this out:"],afterMarkdowns:["The same movement as before, but all in one command."],command:"git checkout HEAD~^2~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"ModalAlert",options:{markdowns:["### Put it to practice","","To complete this level, create a new branch at the specified destination.","","Obviously it would be easy to specify the commit directly (with something like `C6`), but I challenge you to use the modifiers we talked about instead!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["### 选择父提交","","和`~`修改符一样,`^`修改符之后也可以跟一个(可选的)数字。","","这不是用来指定向上返回几代(`~`的作用),`^`后的数字指定跟随合并提交记录的哪一个父提交。还记得一个合并提交有多个父提交吧,所有选择哪条路径不是那么清晰。","",'Git默认选择跟随合并提交的"第一个"父提交,使用`^`后跟一个数字来改变这一默认行为。',"","废话不多说,举个例子。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["这里有一个合并提交。如果不加数字修改符直接切换到`master^`,会回到第一个父提交。","","(*在我们的图示中,第一个父提交是指合并提交正上方的那个父提交。*)"],afterMarkdowns:["OK--这恰好是我们想要的。"],command:"git checkout master^",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["现在来试试选择第二个父提交……"],afterMarkdowns:["看见了吧?我们回到了第二个父提交。"],command:"git checkout master^2",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用`^`和`~`可以自由在在提交树中移动:"],afterMarkdowns:["快若闪电!"],command:"git checkout HEAD~; git checkout HEAD^2; git checkout HEAD~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["再疯狂点,这些修改符支持链式操作!试一下这个:"],afterMarkdowns:["和前面的结果一样,但只用了一条命令。"],command:"git checkout HEAD~^2~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"ModalAlert",options:{markdowns:["### 实践一下","","要完成此关,在指定的目标位置创建一个新的分支。","","很明显可以简单的直接使用提交记录的hash值(比如`C6`),但我要求你使用刚刚讲到的相对引用修饰符!"]}}]}}}}),e("/src/levels/advanced/multipleParents.js"),e.define("/src/levels/index.js",function(e,t,n,r,i,s,o){n.levelSequences={intro:[e("../../levels/intro/commits").level,e("../../levels/intro/branching").level,e("../../levels/intro/merging").level,e("../../levels/intro/rebasing").level],rampup:[e("../../levels/rampup/detachedHead").level,e("../../levels/rampup/relativeRefs").level,e("../../levels/rampup/relativeRefs2").level,e("../../levels/rampup/reversingChanges").level],rebase:[e("../../levels/rebase/manyRebases").level],mixed:[e("../../levels/mixed/grabbingOneCommit").level,e("../../levels/mixed/jugglingCommits").level,e("../../levels/mixed/jugglingCommits2").level],advanced:[e("../../levels/advanced/multipleParents").level,e("../../levels/rebase/selectiveRebase").level]},n.sequenceInfo={intro:{displayName:{en_US:"Introduction Sequence",ja:"まずはここから",fr_FR:"Séquence d'introduction",zh_CN:"基础篇",ko:"기본 명령어"},about:{en_US:"A nicely paced introduction to the majority of git commands",ja:"gitの基本的なコマンド群をほどよいペースで学ぶ",fr_FR:"Une introduction en douceur à la majorité des commandes git",zh_CN:"循序渐进介绍git主要命令",ko:"브랜치 관련 주요 git 명령어를 깔끔하게 알려드립니다"}},rampup:{displayName:{en_US:"Ramping Up",ja:"次のレベルに進もう",fr_FR:"Montée en puissance",zh_CN:"进阶篇"},about:{en_US:"The next serving of 100% git awesomes-ness. Hope you're hungry",ja:"更にgitの素晴らしさを堪能しよう",fr_FR:"Le prochain service git 100% excellence. J'espère que vous êtes affamés",zh_CN:"接下来是git的超赞特性。迫不及待了吧!"}},rebase:{displayName:{en_US:"Master the Rebase Luke!",ja:"Rebaseをモノにする",fr_FR:"Maîtrise Rebase, Luke!",zh_CN:"精通Rebase!",ko:"리베이스 완전정복!"},about:{en_US:"What is this whole rebase hotness everyone is talking about? Find out!",ja:"話題のrebaseってどんなものだろう?って人にオススメ",fr_FR:"Qu'est-ce que ce rebase dont tout le monde parle ? Découvrez-le !",ko:"그 좋다고들 말하는 rebase에 대해 알아봅시다!",zh_CN:"大家都在说的rebase究竟是神马?看看吧!"}},mixed:{displayName:{en_US:"A Mixed Bag",ja:"様々なtips",fr_FR:"Un assortiment",ko:"종합선물세트",zh_CN:"大杂烩?"},about:{en_US:"A mixed bag of Git techniques, tricks, and tips",ja:"gitを使う上での様々なtipsやテクニックなど",fr_FR:"Un assortiment de techniques et astuces pour utiliser Git",ko:"Git을 다루는 다양한 팁과 테크닉을 다양하게 알아봅니다",zh_CN:"Git技术,技巧与贴士杂烩"}},advanced:{displayName:{en_US:"Advanced Topics",fr_FR:"Sujets Avancés",zh_CN:"高级主题"},about:{en_US:"For the truly brave!",fr_FR:"Pour les plus courageux !",zh_CN:"只为真正的勇士!"}}}}),e("/src/levels/index.js"),e.define("/src/levels/intro/branching.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C1","id":"master"},"bugFix":{"target":"C1","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"bugFix","id":"HEAD"}}',solutionCommand:"git branch bugFix;git checkout bugFix",name:{en_US:"Branching in Git",ja:"Gitのブランチ",ko:"Git에서 브랜치 쓰기",fr_FR:"Gérer les branches avec Git",zh_CN:"建立Git分支"},hint:{en_US:'Make a new branch with "git branch [name]" and check it out with "git checkout [name]"',ja:'ブランチの作成("git branch [ブランチ名]")と、チェックアウト("git checkout [ブランチ名]")',fr_FR:'Faites une nouvelle branche avec "git branch [nom]" positionnez-vous dans celle-ci avec "git checkout [nom]"',zh_CN:"用 'git branch [分支名]' 来创建分支,用 'git checkout [分支名]' 切换到分支",ko:'"git branch [브랜치명]"으로 새 브랜치를 만들고, "git checkout [브랜치명]"로 그 브랜치로 이동하세요'},disabledMap:{"git revert":!0},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Branches","","Branches in Git are incredibly lightweight as well. They are simply references to a specific commit -- nothing more. This is why many Git enthusiasts chant the mantra:","","```","branch early, and branch often","```","","Because there is no storage / memory overhead with making many branches, it's easier to logically divide up your work than have big beefy branches.","",'When we start mixing branches and commits, we will see how these two features combine. For now though, just remember that a branch essentially says "I want to include the work of this commit and all parent commits."']}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's see what branches look like in practice.","","Here we will create a new branch named `newImage`"],afterMarkdowns:["There, that's all there is to branching! The branch `newImage` now refers to commit `C1`"],command:"git branch newImage",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's try to put some work on this new branch. Hit the button below"],afterMarkdowns:["Oh no! The `master` branch moved but the `newImage` branch didn't! That's because we weren't \"on\" the new branch, which is why the asterisk (*) was on `master`"],command:"git commit",beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's tell git we want to checkout the branch with","","```","git checkout [name]","```","","This will put us on the new branch before committing our changes"],afterMarkdowns:["There we go! Our changes were recorded on the new branch"],command:"git checkout newImage; git commit",beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["Ok! You are all ready to get branching. Once this window closes,","make a new branch named `bugFix` and switch to that branch"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Gitのブランチ","","Gitではコミットだけでなく、ブランチもまた信じられないほど軽量です。ブランチとは単に特定のコミットを指示したポインタにしか過ぎません。Gitの達人は決まってこう言うのは、そのためです:","","```","早めに、かつ頻繁にブランチを切りなさい","```","","どれほど多くのブランチを作ってもストレージやメモリを全然使わないので、ブランチを肥大化させるよりも論理的に分割していく方が簡単なのです。","","ブランチとコミットをあわせて使い始めると、これら2つのフィーチャがどのように連動して機能するかがわかるでしょう。ここではとりあえず、ブランチは基本的には「あるコミットとその親のコミットたちを含めた全てのコミット」のことを呼ぶと覚えておいてください。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["では実際にブランチがどのようなものかを見ていきましょう。","","`newImage`という名前の新しいブランチを切ってみることにします。"],afterMarkdowns:["以上。必要な手順はこれだけです。いま作成された`newImage`ブランチは`C1`コミットを指しています。"],command:"git branch newImage",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["この新しいブランチに何か変更を加えてみましょう。次のボタンを押してください。"],afterMarkdowns:["あれ?`newImage`ではなくて`master`ブランチが移動してしまいました。これは、私たちが`newImage`のブランチ上で作業していなかったためです。どのブランチで作業しているかは、アスタリスク(*)がついてるかどうかで分かります。"],command:"git commit",beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["今度は作業したいブランチ名をgitに伝えてみましょう。","","```","git checkout [ブランチ名]","```","","このようにして、コミットする前に新しいブランチへと作業ブランチを移動することができます。"],afterMarkdowns:["できましたね。今度は新しいブランチに対して変更を記録することができました。"],command:"git checkout newImage; git commit",beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["OK! もうどんなブランチでも切れますね。このウィンドウを閉じて、","`bugFix`という名前のブランチを作成し、そのブランチをチェックアウトしてみましょう。"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branches Git","","Les branches sous Git sont incroyablement légères aussi. Elles sont simplment des références un commit spécifique -- rien de plus. C'est pourquoi beaucoup d'enthousiastes répètent en cœur :","","```","n'attendez pas pour faire des branches, et faites souvent des branches","```","","Parce qu'il n'y a pas de surcoût (stockage/mémoire) associés aux branches, il est facile de diviser son travail en de nombreuses branches plutôt que d'avoir quelques grosses branches.","","Nous verrons comment les banches et les commits interagissent quand nous les utiliserons ensemble. Pour l'instant, souvenez-vous qu'une branche est un moyen d'exprimer \"Je veux inclure le contenu de ce commit et de tous les commits parents.\""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Regardons à quoi ressemblent les branches en pratique.","","Nous allons nous positionner (checkout) dans une nouvelle branche appellée `newImage`"],afterMarkdowns:["Et voilà, c'est tout ! La branche `newImage` se réfère désormais au commit `C1`"],command:"git branch newImage",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Travaillons mainenant dans cette branche. Appuyez sur le bouton ci-dessous."],afterMarkdowns:["Oh non! La branche `master` a bougé mais pas la branche `newImage` ! C'est parce aue nous n'étions pas \"sur\" la nouvelle branche, comme indiqué par l'asterisque (*) sur `master`"],command:"git commit",beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Indiquons à git que nous voulons nous positionner sur la branche avec ","","```","git checkout [nom]","```","","Ceci nous positionne sur la nouvelle branche avant de faire un commit avec nos modifications"],afterMarkdowns:["C'est parti ! Nos modifications ont été enregistrées sur la nouvelle branche"],command:"git checkout newImage; git commit",beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["Ok! Vous êtes fin prêt pour faire des branches. Après la fermeture de cette fenêtre,","faites une nouvelle branche nommée `bugFix` et positionnez-vous sur cette branche"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Branches",""," Git 的分支非常轻量。它们只是简单地指向某个提交纪录——仅此而已。所以许多Git爱好者会念叨:","","```","早点建分支!经常建分支!","```","","创建分支没有储存或内存上的开销,所以按逻辑分解工作比维护单一的代码树要简单。","","同时使用分支和提交时,我们会看到两者如何配合。现在,只要记住使用分支其实就是在说:“我想包含本次提交及所有的父提交记录。”"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["举个例子看看分支究竟是什么。","","这里,我们切换到到名为`newImage`的新分支。"],command:"git branch newImage",afterMarkdowns:["看,这就是建立分支所需的操作啦!`newImage`分支现在指向提交记录`C1`。"],beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["现在让我们修改一下新分支。点击下面的按钮。"],command:"git commit",afterMarkdowns:["啊摔!`master`分支前进了,但`newImage`分支没有哇!这是因为我们没有“在”这个新分支上,这也是为什么星号(*)只在 `master` 上。"],beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用如下命令告诉git我们想要切换到新的分支","","```","git checkout [name]","```","","这可以让我们在提交修改之前切换到新的分支。"],command:"git checkout newImage; git commit",afterMarkdowns:["好的嘞!新的分支已经记录了我们的修改。"],beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["好啦,你已经准备好使用分支了。当前窗口关闭后,","创建一个叫 `bugFix` 的新分支,然后切换过去。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git 브랜치","","깃의 브랜치도 놀랍도록 가볍습니다. 브랜치는 특정 커밋에 대한 참조(reference)에 지나지 않습니다. 이런 사실 때문에 수많은 Git 애찬론자들이 자주 이렇게 말하곤 합니다:","","```","브랜치를 서둘러서, 그리고 자주 만드세요","```","","브랜치를 많이 만들어도 메모리나 디스크 공간에 부담이 되지 않기 때문에, 여러분의 작업을 커다른 브랜치로 만들기 보다, 작은 단위로 잘게 나누는 것이 좋습니다.","",'브랜치와 커밋을 같이 쓸 때, 어떻게 두 기능이 조화를 이루는지 알아보겠습니다. 하지만 우선은, 단순히 브랜치를 "하나의 커밋과 그 부모 커밋들을 포함하는 작업 내역"이라고 기억하시면 됩니다.']}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["브랜치가 어떤 것인지 연습해보죠.","","`newImage`라는 브랜치를 살펴보겠습니다."],afterMarkdowns:["저 그림에 브랜치의 모든 것이 담겨있습니다! 브랜치 `newImage`가 커밋 `C1`를 가리킵니다"],command:"git branch newImage",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["이 새로운 브랜치에 약간의 작업을 더해봅시다. 아래 버튼을 눌러주세요"],afterMarkdowns:["앗! `master` 브랜치가 움직이고, `newImage` 브랜치는 이동하지 않았네요! 그건 우리가 새 브랜치 위에 있지 않았었기 때문입니다. 별표(*)가 `master`에 있었던 것이죠."],command:"git commit",beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["아래의 명령으로 새 브랜치로 이동해 봅시다.","","```","git checkout [브랜치명]","```","","이렇게 하면 변경분을 커밋하기 전에 새 브랜치로 이동하게 됩니다."],afterMarkdowns:["이거죠! 이제 우리의 변경이 새 브랜치에 기록되었습니다!"],command:"git checkout newImage; git commit",beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["좋아요! 이제 직접 브랜치 작업을 연습해봅시다. 이 창을 닫고,","`bugFix`라는 새 브랜치를 만드시고, 그 브랜치로 이동해보세요"]}}]}}}}),e("/src/levels/intro/branching.js"),e.define("/src/levels/intro/commits.js",function(e,t,n,r,i,s,o){n.level={name:{en_US:"Introduction to Git Commits",fr_FR:"Introduction aux commits avec Git",ja:"Gitのコミット",ko:"Git 커밋 소개",zh_CN:"Git Commits简介"},goalTreeString:'{"branches":{"master":{"target":"C3","id":"master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"master","id":"HEAD"}}',solutionCommand:"git commit;git commit",startTree:'{"branches":{"master":{"target":"C1","id":"master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"master","id":"HEAD"}}',hint:{en_US:"Just type in 'git commit' twice to finish!",fr_FR:"Il suffit de saisir 'git commit' deux fois pour réussir !",zh_CN:"敲两次 'git commit' 就好啦!",ja:"'git commit'コマンドを2回打てば完成!",ko:"'git commit'이라고 두 번 치세요!"},disabledMap:{"git revert":!0},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Commits","A commit in a git repository records a snapshot of all the files in your directory. It's like a giant copy and paste, but even better!","","Git wants to keep commits as lightweight as possible though, so it doesn't just copy the entire directory every time you commit. It actually stores each commit as a set of changes, or a \"delta\", from one version of the repository to the next. That's why most commits have a parent commit above them -- you'll see this later in our visualizations.","",'In order to clone a repository, you have to unpack or "resolve" all these deltas. That\'s why you might see the command line output:',"","`resolving deltas`","","when cloning a repo.","","It's a lot to take in, but for now you can think of commits as snapshots of the project. Commits are very light and switching between them is wicked fast!"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's see what this looks like in practice. On the right we have a visualization of a (small) git repository. There are two commits right now -- the first initial commit, `C0`, and one commit after that `C1` that might have some meaningful changes.","","Hit the button below to make a new commit"],afterMarkdowns:["There we go! Awesome. We just made changes to the repository and saved them as a commit. The commit we just made has a parent, `C1`, which references which commit it was based off of."],command:"git commit",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["Go ahead and try it out on your own! After this window closes, make two commits to complete the level"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Gitのコミット","コミットによって、ディレクトリ中の全てのファイルのスナップショットを記録します。巨大なコピー&ペーストのようなものですが、実はそれよりずっと良いものです。","","Gitではコミットを可能な限り軽量に保つために、コミット毎にフォルダ全体をコピーしません。実際にはGitは、コミットを直前のバージョンから一つ先のバージョンへの「変更の固まり」あるいは「差分」として記録します。後で出てきますが、ほとんどのコミットが親を持っているのはそういう理由からです。","","リポジトリをcloneする時には、内部動作としてはコミットの差分をたどって全ての変更を取得しています。cloneした時に以下のような表示が出るのは:","","`resolving deltas`(訳:差分を解決中)","","このためです。","","もっと説明したいところですが、しばらくはコミットをスナップショットのようなものだと考えてください。コミットは非常に軽量であり、コミット間の移動も非常に高速です。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["これがどういうことか、動きを見ていきましょう。図には(小さな)gitリポジトリが描かれています。コミットが2つあります ― `C0`という名前の初回のコミットがあり、`C1`という名前の次のコミットが続きます。これは何か意味のある変更かもしれません。","","下のボタンを押下して新しいコミットを作ってみましょう。"],afterMarkdowns:["できました! 良いですね。いまリポジトリに新しい変更が加えられ、1つのコミットとして保存されました。作成したコミットには親がいて、このコミットの出発点となった`C1`を指しています。"],command:"git commit",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["実際に手を動かしてみましょう。このウィンドウを閉じたら、試しに2回コミットをしてみましょう。"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Commits Git","Un commit dans un dépôt (repository) git enregistre une image (snapshot) de tous les fichiers du repertoire. Comme un Copier-Coller géant, mais en bien mieux !","","Git fait en sorte que les commits soient aussi légers que possible donc il ne recopie pas tous le répertoire à chaque commit. En fait, git n'enregistre que l'ensemble des changments (\"delta\") depuis la version précédante du dépôt. C'est pour cette raison que la plupart des commits ont un commit parent -- ainsi que nous le verrons plus tard.","",'Pour cloner un dépôt, il faut décompresser ("résoudre") tous ces deltas. C\'est la raison pour laquelle la commande écrit :',"","`resolving deltas`","","lorsque l'on clone un dépôt.","","C'est beaucoup à absorber, mais pour l'instant vous pouvez considérer les commits comme des snapshots du projet. Les commits sont très légers et passer de l'un à l'autre est très rapide !"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Voyons à quoi cela ressemble en pratique. Sur la droite, on peut visualiser un (petit) dépôt git. Il y a pour l'instant deux commits -- le premier commit initial, `C0`, et un commit suivant `C1` qui aurait des changements significatifs.","","Appuyez sur le bouton ci-dessous pour faire un nouveau commit"],afterMarkdowns:["C'est parti ! Super. Nous venons de faire des modifications sur le dépôt et de saugevarder celles-ci dans un commit. Ce commit que nous venons de faire a un parent, `C1`, qui référence le commit sur lequel il est basé."],command:"git commit",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["Allez-y et essayez par vous-même ! Après la fermeture de cettefenêtre, faites deux commits pour terminer ce niveau."]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git 커밋","커밋은 Git 저장소에 여러분의 디렉토리에 있는 모든 파일에 대한 스냅샷을 기록하는 것입니다. 디렉토리 전체에 대한 복사해 붙이기와 비슷하지만 훨씬 유용합니다!","",'Git은 커밋을 가능한한 가볍게 유지하고자 해서, 커밋할 때마다 디렉토리 전체를 복사하는 일은 하지 않습니다. 각 커밋은 저장소의 이전 버전과 다음 버전의 변경내역("delta"라고도 함)을 저장합니다. 그래서 대부분의 커밋이 그 커밋 위에 부모 커밋을 가리키고 있게 되는 것입니다. -- 곧 그림으로 된 화면에서 살펴보게 될 것입니다.',"","저장소를 복제(clone)하려면, 그 모든 변경분(delta)를 풀어내야하는데, 그 때문에 명령행 결과로 아래와 같이 보게됩니다. ","","`resolving deltas`","","알아야할 것이 꽤 많습니다만, 일단은 커밋을 프로젝트의 각각의 스냅샷들로 생각하시는 걸로 충분합니다. 커밋은 매우 가볍고 커밋 사이의 전환도 매우 빠르다는 것을 기억해주세요!"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["연습할 때 어떻게 보이는지 확인해보죠. 오른쪽 화면에 git 저장소를 그림으로 표현해 놓았습니다. 현재 두번 커밋한 상태입니다 -- 첫번째 커밋으로 `C0`, 그 다음으로 `C1`이라는 어떤 의미있는 변화가 있는 커밋이 있습니다.","","아래 버튼을 눌러 새로운 커밋을 만들어보세요"],afterMarkdowns:["이렇게 보입니다! 멋지죠. 우리는 방금 저장소 내용을 변경해서 한번의 커밋으로 저장했습니다. 방금 만든 커밋은 부모는 `C1`이고, 어떤 커밋을 기반으로 변경된 것인지를 가리킵니다."],command:"git commit",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["계속해서 직접 한번 해보세요! 이 창을 닫고, 커밋을 두 번 하면 다음 레벨로 넘어갑니다"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Commits","git仓库中的一次提交(commit)记录目录下所有文件的快照。感觉像是大量的复制和粘贴,但 git 做的不只这么简单!","",'Git 希望提交记录尽可能地轻量,所以每次进行提交时,它不会简单地复制整个目录。实际上它把每次提交记录保存为从代码库的一个版本到下一个版本的变化集,或者说一个"增量(delta)"。所以,大部分提交记录都有一个父提交(parent commit)-- 我们会很快演示这一点。',"","克隆(clone)代码库时,需要解包(unpack)或者“解析(resolve)”所有的差异。所以在克隆代码库时,可能会看见如下命令行输出:","","`resolving deltas`","","要学的东西有很多,但现在你可以把提交记录看作是项目的快照。提交记录非常轻量且可以快速切换!"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["在实践中学习commit。右边是一个(小)git代码库的图示。当前有两个提交记录—— 初始提交`C0`和其后可能包含有用修改的提交`C1`。","","点击下面的按钮生成新的提交记录。"],command:"git commit",afterMarkdowns:["看!碉堡吧!我们修改了代码,并保存为一次提交记录。刚刚做的提交`C2`有一个父提交(parent)`C1`,代表此次修改的基础。"],beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["接下来你可以随便测试。当前窗口关闭后,完成两次提交就可以过关!"]}}]}}}}),e("/src/levels/intro/commits.js"),e.define("/src/levels/intro/merging.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C4","id":"master"},"bugFix":{"target":"C2","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3","C2"],"id":"C4"}},"HEAD":{"target":"master","id":"HEAD"}}',solutionCommand:"git checkout -b bugFix;git commit;git checkout master;git commit;git merge bugFix",name:{en_US:"Merging in Git",fr_FR:"Faire des 'merge' (fusions de branches) avec Git",ko:"Git에서 브랜치 합치기(Merge)",ja:"ブランチとマージ",zh_CN:"分支与合并"},hint:{en_US:"Remember to commit in the order specified (bugFix before master)",ja:"指示された順番でコミットすること(masterの前にbugFixで)",fr_FR:"Pensez à faire des commits dans l'ordre indiqué (bugFix avant master)",zh_CN:"记住按指定的顺序提交(bugFix先于master)",ko:"말씀드린 순서대로 커밋해주세요 (bugFix에 먼저 커밋하고 master에 커밋)"},disabledMap:{"git revert":!0},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branches and Merging","","Great! We now know how to commit and branch. Now we need to learn some kind of way of combining the work from two different branches together. This will allow us to branch off, develop a new feature, and then combine it back in.","",'The first method to combine work that we will examine is `git merge`. Merging in Git creates a special commit that has two unique parents. A commit with two parents essentially means "I want to include all the work from this parent over here and this one over here, *and* the set of all their parents."',"","It's easier with visuals, let's check it out in the next view"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have two branches; each has one commit that's unique. This means that neither branch includes the entire set of \"work\" in the repository that we have done. Let's fix that with merge.","","We will `merge` the branch `bugFix` into `master`"],afterMarkdowns:["Woah! See that? First of all, `master` now points to a commit that has two parents. If you follow the arrows upstream from `master`, you will hit every commit along the way to the root. This means that `master` contains all the work in the repository now.","","Also, see how the colors of the commits changed? To help with learning, I have included some color coordination. Each branch has a unique color. Each commit turns a color that is the blended combination of all the branches that contain that commit.","","So here we see that the `master` branch color is blended into all the commits, but the `bugFix` color is not. Let's fix that..."],command:"git merge bugFix",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's merge `master` into `bugFix`:"],afterMarkdowns:["Since `bugFix` was downstream of `master`, git didn't have to do any work; it simply just moved `bugFix` to the same commit `master` was attached to.","","Now all the commits are the same color, which means each branch contains all the work in the repository! Woohoo!"],command:"git checkout bugFix; git merge master",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["To complete this level, do the following steps:","","* Make a new branch called `bugFix`","* Checkout the `bugFix` branch with `git checkout bugFix`","* Commit once","* Go back to `master` with `git checkout`","* Commit another time","* Merge the branch `bugFix` into `master` with `git merge`","",'*Remember, you can always re-display this dialog with "help level"!*']}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ブランチとマージ","","いい調子ですね。これまでにコミットとブランチについて学びました。そろそろ2つのブランチを1つにまとめるやり方について見ていきましょう。これができれば新しいフィーチャの開発のために新しいブランチを切って、開発が終わったら変更を元のブランチへ統合することができるようになります。","","はじめに紹介するのは、`git merge`を使ったマージのやり方です。mergeコマンドによって、2つの独立した親を持つ特別なコミットを作ることができます。2つの親を持つコミットが持つ意味とは、「全く別々の場所にいるこの親とその親(*かつ*、それらの親の祖先全て)が持つ全ての変更を含んでいますよ」ということです。","","見てみた方が早いので、次の画面で確認してみましょう。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["それぞれ別のコミットを指している2つのブランチがあります。変更が別々のブランチに分散していて統合されていないケースです。これをマージで1つにまとめてみましょう。","","`bugFix`ブランチを`master`ブランチにマージしてみます。"],afterMarkdowns:["わあ。見ましたか?まず初めに、`master`ブランチが2つのコミットを親に持つ新しいコミットを指してますね。`master`から親をたどっていくと、最も古いコミットにたどり着くまでに全てのコミットを含んでいる様が確認できます。これで、全ての変更を含む`master`が完成しました。","","色がどう変わったかにも注目して下さい。学習を助けるために、ブランチ毎に色をつけています。それぞれのブランチは自分の色を持っていて、どのブランチから派生して出てくるか次第でコミットごとの色が決まります。","","今回のコミットには`master`ブランチの色が使われました。しかし`bugFix`ブランチの色がまだ変わってないようなので、これを変えてみましょう。"],command:"git merge bugFix",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["`master`ブランチを`bugFix`ブランチにマージしてみます。"],afterMarkdowns:["`bugFix`ブランチは`master`ブランチの派生元だったので、gitは実際大したことはしていません:`bugFix`ブランチを指していたポインタを`master`が指していたコミットへと移動させただけです。","","これで全てのコミットが同じ色になりました。つまり、リポジトリの中の全ての変更をそれぞれのブランチが持ったことになります。やったね!"],command:"git checkout bugFix; git merge master",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["以下の作業で理解度の確認をしてみましょう。 steps:","","* `bugFix`という名前で新しいブランチを切る","* `git checkout bugFix`コマンドで`bugFix`ブランチをチェックアウトする","* 一回だけコミット","* `git checkout`で`master`へ戻る","* もう1回コミットする","* `git merge`コマンドを使って、`bugFix`ブランチを`master`ブランチへとマージする","",'*注:"help level"コマンドでこのヘルプにいつでも戻ってこれます*']}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branches et Merges","","Super! Nous savons désormais comment faire des commits et de branches. Maintenant nous devons apprendre comment combiner ensemble les contenus de deux branches différentes. Ceci nous permettra de créer une nouvelle branche, développer une nouvelle fonctionnalité sur cette dernière, puis intégrer cette fonctionnalité en combinant le contenu de cette branche de développement à la branche d'origine(master par exemple).","","La première méthode que nous alons voir pour combiner le conenu de deux branches est `git merge`. Faire un 'merge' en git Git crée un commit spécial qui a deux parents. Un commit avec deux parents indique en susbtance \"Je veux inclure le contenu de ce parent et le conenu de cet autre parent, *et* l'ensemble de leurs parents.\"","","C'est plus facile en visualisant, regardons dans la vue suivante"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have two branches; each has one commit that's unique. This means that neither branch includes the entire set of \"work\" in the repository that we have done. Let's fix that with merge.","","We will `merge` the branch `bugFix` into `master`"],afterMarkdowns:["Woah! See that? First of all, `master` now points to a commit that has two parents. If you follow the arrows upstream from `master`, you will hit every commit along the way to the root. This means that `master` contains all the work in the repository now.","","Also, see how the colors of the commits changed? To help with learning, I have included some color coordination. Each branch has a unique color. Each commit turns a color that is the blended combination of all the branches that contain that commit.","","So here we see that the `master` branch color is blended into all the commits, but the `bugFix` color is not. Let's fix that..."],command:"git merge bugFix",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Faisons un merge de `master` dans `bugFix`:"],afterMarkdowns:["Puisque `bugFix` était un descendant de `master`, git n'avait aucun travail à effectuer; il a simplement déplacé `bugFix` au même commit auquel `master` est attaché.","","Maintenant tous les commits sont de la même couleur, ce qui indique que chaque branche contient tout le contenu du dépôt ! Woohoo!"],command:"git checkout bugFix; git merge master",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["Pour accomplir ce niveau, effectuez les opérations suivantes :","","* Faites une nouvelle branche appelée `bugFix`","* Positionnez-vous sur la branche `bugFix` avec `git checkout bugFix`","* Faites un commit","* Retournez sur la branche `master` (commande `git checkout`)","* Faites un nouveau commit","* Fusionnez la branche `bugFix` dans `master` avec `git merge`","",'*Rappelez-vous que vous pouvez à tout moment réafficher ces indications avec "help level"!*']}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branches and Merging","","Great! 我们已经知道怎么提交和使用分支了。接下来要学的一招是如何合并两个不同分支的工作。这让我们可以新建一个分支,在其上开发新功能,然后合并回主线。","","`git merge`是我们要学习的合并工作的第一个方法。合并产生一个特殊的提交记录,它包含两个唯一父提交。有两个父提交的提交记录本质上是:“我想把这两个父提交本身及它们的父提交集合都包含进来。”","","有图有真相,看看下面的图示就明白了。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["当前有两个分支:各有一个唯一的提交。这意味着没有一个分支包含我们对代码库的所有修改。让我们合并这两个分支来解决这个问题。","","我们要把 `bugFix` 合并到 `master` "],command:"git merge bugFix",afterMarkdowns:["哇!看见木有?首先,`master` 现在指向一个拥有两个父提交的提交记录。假如从 `master` 开始沿着箭头向上游走,在到达起点的路上会经过所有的提交记录。这说明有 `master` 包含了对代码库的所有修改。","","还有,看见各个提交记录的颜色变化了吗?为了帮助学习,我使用了颜色混合。每个分支都有特定的颜色。每个提交记录都变成了含有此提交的所有分支的混合色。","","所以,`master` 分支的颜色被混入到所有的提交记录,但 `bugFix` 没有。接下来就改一下这里吧。"],beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["让我们把 `master` 分支合并到 `bugFix` 吧。"],command:"git checkout bugFix; git merge master",afterMarkdowns:["因为 `bugFix` 分支在 `master` 分支的下游,git什么都不用做,只是简单地把`bugfix`分支移动到`master`指向的提交记录。","","现在所有的提交记录的颜色都是一样的啦,这表明每一个分支都包含了代码库的所有修改!走起!"],beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["想完成此关,执行收下操作:","","* 创建新分支 `bugFix` ","* 用 `git checkout bugFix` 切换到 `bugFix`分支","* 提交一次","* 用 `git checkout` 切换回 `master` ","* 再提交一次","* 用 `git merge` 合并 `bugFix`分支进 `master`","",'*记住,总是可以用 "help level" 命令来重新显示这个对话框!*']}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 브랜치와 합치기(Merge)","","좋습니다! 지금까지 커밋하고 브랜치를 만드는 방법을 알아봤습니다. 이제 두 별도의 브랜치를 합치는 몇가지 방법을 알아볼 차례입니다. 이제부터 배우는 방법으로 브랜치를 따고, 새 기능을 개발 한 다음 합칠 수 있게 될 것입니다.","",'처음으로 살펴볼 방법은 `git merge`입니다. Git의 합치기(merge)는 두 개의 부모(parent)를 가리키는 특별한 커밋을 만들어 냅니다. 두개의 부모가 있는 커밋이라는 것은 "한 부모의 모든 작업내역과 나머지 부모의 모든 작업, *그리고* 그 두 부모의 모든 부모들의 작업내역을 포함한다"라는 의미가 있습니다. ',"","그림으로 보는게 이해하기 쉬워요. 다음 화면을 봅시다."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["여기에 브랜치가 두 개 있습니다. 각 브랜치에 독립된 커밋이 하나씩 있구요. 그 말은 이 저장소에 지금까지 작업한 내역이 나뉘어 담겨 있다는 얘기입니다. 두 브랜치를 합쳐서(merge) 이 문제를 해결해 볼까요?","","`bugFix` 브랜치를 `master` 브랜치에 합쳐(merge) 보겠습니다."],afterMarkdowns:["보셨어요? 우선, `master`가 두 부모가 있는 커밋을 가리키고 있습니다. ","","또, 커밋들의 색이 바뀐 것을 눈치 채셨나요? 이해를 돕기위해 색상으로 구분해 표현했습니다. 각 브랜치는 그 브랜치만의 색상으로 그렸습니다. 브랜치가 합쳐지는 커밋의 경우에는, 그 브랜치들의 색을 조합한 색상으로 표시 했습니다.","","그런식으로 여기에 `bugFix`브랜치 쪽을 제외한 나머지 커밋만 `master` 브랜치의 색으로 칠해져 있습니다. 이걸 고쳐보죠..."],command:"git merge bugFix",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["이제 `master` 브랜치에 `bugFix`를 합쳐(merge) 봅시다:"],afterMarkdowns:["`bugFix`가 `master`의 부모쪽에 있었기 때문에, git이 별다른 일을 할 필요가 없었습니다; 간단히 `bugFix`를 `master`가 붙어 있는 커밋으로 이동시켰을 뿐입니다.","","짜잔! 이제 모든 커밋의 색이 같아졌고, 이는 두 브랜치가 모두 저장소의 모든 작업 내역을 포함하고 있다는 뜻입니다."],command:"git checkout bugFix; git merge master",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["아래 작업을 해서 이 레벨을 통과하세요:","","* `bugFix`라는 새 브랜치를 만듭니다","* `git checkout bugFix`를 입력해 `bugFix` 브랜치로 이동(checkout)합니다.","* 커밋 한 번 하세요","* `git checkout` 명령어를 이용해 `master`브랜치로 돌아갑니다","* 커밋 또 하세요","* `git merge` 명령어로 `bugFix`브랜치를 `master`에 합쳐 넣습니다.","",'*아 그리고, "help level" 명령어로 이 안내창을 다시 볼 수 있다는 것을 기억해 두세요!*']}}]}}}}),e("/src/levels/intro/merging.js"),e.define("/src/levels/intro/rebasing.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22master%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22bugFix%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C2%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22bugFix%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout -b bugFix;git commit;git checkout master;git commit;git checkout bugFix;git rebase master",name:{en_US:"Rebase Introduction",ja:"Rebaseの解説",fr_FR:"Introduction à rebase",ko:"리베이스(rebase)의 기본",zh_CN:"Rebase简介"},hint:{en_US:"Make sure you commit from bugFix first",ja:"初めにbugFixを指した状態でコミットする",fr_FR:"Assurez-vous de bien faire votre en premier votre commit sur bugFix",ko:"bugFix 브랜치에서 먼저 커밋하세요",zh_CN:"确保你先在 bugFix 分支进行提交"},disabledMap:{"git revert":!0},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Rebase","",'The second way of combining work between branches is *rebasing.* Rebasing essentially takes a set of commits, "copies" them, and plops them down somewhere else.',"","While this sounds confusing, the advantage of rebasing is that it can be used to make a nice linear sequence of commits. The commit log / history of the repository will be a lot cleaner if only rebasing is allowed.","","Let's see it in action..."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have two branches yet again; note that the bugFix branch is currently selected (note the asterisk)","","We would like to move our work from bugFix directly onto the work from master. That way it would look like these two features were developed sequentially, when in reality they were developed in parallel.","","Let's do that with the `git rebase` command"],afterMarkdowns:["Awesome! Now the work from our bugFix branch is right on top of master and we have a nice linear sequence of commits.","",'Note that the commit C3 still exists somewhere (it has a faded appearance in the tree), and C3\' is the "copy" that we rebased onto master.',"","The only problem is that master hasn't been updated either, let's do that now..."],command:"git rebase master",beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Now we are checked out on the `master` branch. Let's go ahead and rebase onto `bugFix`..."],afterMarkdowns:["There! Since `master` was downstream of `bugFix`, git simply moved the `master` branch reference forward in history."],command:"git rebase bugFix",beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["To complete this level, do the following","","* Checkout a new branch named `bugFix`","* Commit once","* Go back to master and commit again","* Check out bugFix again and rebase onto master","","Good luck!"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Rebase","","ブランチを一つにまとめる方法として前回はマージを紹介しましたが、今回紹介するリベースを使うこともできます。リベースの動作は、マージするコミットのコピーをとって、どこかにストンと落とすというイメージです。","","ピンと来ないかもしれませんが、リベースのメリットは一本の連続したシーケンシャルなコミットに整形できることです。リベースだけ使っていると、コミットのログや履歴が非常にクリーンな状態に保たれます。","","早速実際にどう動くのかを見てみましょう。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["前回と同様の2つのブランチを考えます:仮にいまbugFixブランチをチェックアウトしているとします。(アスタリスクつきのもの)","","bugFixに入ってる作業内容をそのまま直接masterブランチ上の内容に移動したいとします。こうすることで、実際には並行して開発された2つの別々のブランチ上のフィーチャを、あたかも1本のブランチ上でシーケンシャルに開発されていたかのように見せることができます。","","`git rebase`コマンドでそれをやってみましょう。"],afterMarkdowns:["できた!これでbugFixブランチの作業内容はmasterブランチのすぐ先に移動したので、見た目が一本になってスッキリしました。","","気を付けてほしいのは、C3コミットはどこかに残ってるということ(ツリーの中で半透明にしてあります)、そしてC3'は(C3との接続が切れているC3の)コピーがmasterブランチ上に作られているということです。","","一つ問題が残ってて、masterブランチがまだ最新化されていませんね。ちょっと直してみましょう。。"],command:"git rebase master",beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["masterブランチはチェックアウトしてあります。この状態からmasterブランチを`bugFix`へとリベースしてみましょう。"],afterMarkdowns:["できた!`master`は`bugFix`の直前のコミットだったので、gitは単純に`master`ブランチのポインタを前に進めただけでした。"],command:"git rebase bugFix",beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["以下の作業で理解度の確認をしてみましょう。","","* `bugFix`という名前の新しいブランチをチェックアウトする","* 一回だけコミット","* masterブランチに戻ってもう1回コミット","* bugFixをもう1回チェックアウトして、master上にリベース","","幸運を祈る!"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Rebase","",'La seconde façon de combiner les contenus de deux branches est *rebase*. Rebase prend un enselble de commits, les "recopie", et les ajoute en bout de chaine à un autre endroit.',"","Bien que cela puisse sembler compliqué, l'avantage de rebase est de permettre d'obtenir une simple séquence linéeire de commits. Les logs/l'historique du dépôt seront bien plus propres si seul rebase est autorisé (plutôt que merge).","","Voyons rebase en action…"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Ici nous avons encore une fois deux branches; notez que nous sommes sur la branche bugFix (cf. l'asterisque)","","Nous voudrions transferer notre travail sur la branche 'bugFix' directement sur le travail dans 'master'. Ainsi on aurait l'impression que ces deux travaux ont été développés séquentiellement alors qu'en réalité ils ont été réalisés en parallèle.","","Faisons cela avec la commande `git rebase`"],afterMarkdowns:["Super! Désormais, le travail de la branche 'bugFix' est juste en haut de la branche 'master' et non avons une belle séquence linéaire de commits.","","Notez que le commit C3 existe toujours quelquepart (il est en grisé sur l'arbre), et C3' est la \"copie\" que nous avons créée sur master avec rebase.","","Le seul problème est que master n'a pas été mis à jour, faisons cela maintenant…"],command:"git rebase master",beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Nous sommes désormais positionnés sur la branche `master`. Continuons en faisant le rebase sur `bugFix`…","Et voilà ! Puisque `master` était un ascendant de `bugFix`, git a simplement déplacé la référence de la branche `master` en avant dans le temps."],command:"git rebase bugFix",beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["Pour acomplir ce niveau, faites les opérations suivantes","","* Positionnez-vous (checkout) sur une nouvelle branche nommée `bugFix`","* Faites un commit","* Retournez sur master et faites un nouveau commit","* Positionnez-vous à nouveau sur bugFix et faites un rebase sur master","","Bonne chance !"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Rebase","",'*rebasing*是在分支之间合并工作的第二种方法。Rebasing就是取出一系列的提交记录,"复制"它们,然后把在别的某个地方放下来。',"","虽然听上去难以理解,rebasing 的优势是可以创造更线性的提交历史。假如只允许使用rebasing,代码库的提交日志/历史会更好看。","","让我们亲身体会下……"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["这里,还是有两个分支;注意当前分支是 bugFix(看那颗星)","","我们想要把 bugfix 里面的工作直接移到 master 分支上。使用这个方法,两个分支的功能看起来像是按顺序开发,实际上它们是平行开发的。","","用 `git rebase`实现此目标"],command:"git rebase master",afterMarkdowns:["碉堡吧,现在 bugFix 分支上的工作在 master 的最前端,同时我们也得到了一个更线性的提交序列。","","注意,提交记录 C3 仍然存在(阴影的那货就是你了,还看什么看),而我们已经将 C3 复制到了master。","","现在唯一的问题是 master 分支还没有更新……下面就来更新它吧"],beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["现在,切换到 `master` 分支。接下来就把它 rebase 到 `bugFix` 吧……"],command:"git rebase bugFix",afterMarkdowns:["完成!因为 `master` 是 `bugFix` 的下游,所以 git 只把 `master` 分支的记录前移到 `bugFix` 上。"],beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["想完成此关,执行以下操作:","","* 新建`bugFix`分支","* 提交一次","* 切换回 master 分支再提交一次","* 再次切换到 bugFix 分支,rebase 到 master 上","","祝你好运啦!"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git 리베이스(Rebase)","","브랜치끼리의 작업을 접목하는 두번째 방법은 *리베이스(rebase)*입니다. 리베이스는 기본적으로 커밋들을 모아서 복사한 뒤, 다른 곳에 떨궈 놓는 것입니다.","","조금 어려게 느껴질 수 있지만, 리베이스를 하면 커밋들의 흐름을 보기 좋게 한 줄로 만들 수 있다는 장점이 있습니다. 리베이스를 쓰면 저장소의 커밋 로그와 이력이 한결 깨끗해집니다.","","어떻게 동작하는지 살펴볼까요..."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["여기 또 브랜치 두 개가 있습니다; bugFix브랜치가 현재 선택됐다는 점 눈여겨 보세요 (별표 표시)","","bugFix 브랜치에서의 작업을 master 브랜치 위로 직접 옮겨 놓으려고 합니다. 그렇게 하면, 실제로는 두 기능을 따로따로 개발했지만, 마치 순서대로 개발한 것처럼 보이게 됩니다.","","`git rebase` 명령어로 함께 해보죠."],afterMarkdowns:["오! 이제 bugFix 브랜치의 작업 내용이 master의 바로 위에 깔끔한 한 줄의 커밋으로 보이게 됐습니다.","","C3 커밋은 어딘가에 아직 남아있고(그림에서 흐려짐), C3'는 master 위에 올려 놓은 복사본입니다.","","master가 아직 그대로라는 문제가 남아있는데요, 바로 해결해보죠..."],command:"git rebase master",beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["우리는 지금 `master` 브랜치를 선택한 상태입니다. `bugFix` 브랜치쪽으로 리베이스 해보겠습니다..."],afterMarkdowns:["보세요! `master`가 `bugFix`의 부모쪽에 있었기 때문에, 단순히 그 브랜치를 더 앞쪽의 커밋을 가리키게 이동하는 것이 전부입니다."],command:"git rebase bugFix",beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["이하 작업을 하면 이번 레벨을 통과합니다","","* `bugFix`라는 새 브랜치를 만들어 선택하세요","* 커밋 한 번 합니다","* master로 돌아가서 또 커밋합니다","* bugFix를 다시 선택하고 master에 리베이스 하세요","","화이팅!"]}}]}}}}),e("/src/levels/intro/rebasing.js"),e.define("/src/levels/mixed/grabbingOneCommit.js",function(e,t,n,r,i,s,o){n.level={compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C4>e.C1}]},disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22master%22%7D%2C%22debug%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22debug%22%7D%2C%22printf%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22printf%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22bugFix%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout master;git cherry-pick C4",startTree:'{"branches":{"master":{"target":"C1","id":"master"},"debug":{"target":"C2","id":"debug"},"printf":{"target":"C3","id":"printf"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"bugFix","id":"HEAD"}}',name:{ko:"딱 한개의 커밋만 가져오기",en_US:"Grabbing Just 1 Commit",ja:"Grabbing Just 1 Commit",zh_CN:"只取一个提交"},hint:{en_US:"Remember, interactive rebase or cherry-pick is your friend here",ja:"このレベルではインタラクティブモードのrebaseやcherry-pickがクリアのカギです",ko:"대화식 리베이스(rebase -i)나 or 체리픽(cherry-pick)을 사용하세요",zh_CN:"记住,交互式 rebase 或者 cherry-pick 会很有帮助"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Locally stacked commits","","Here's a development situation that often happens: I'm trying to track down a bug but it is quite elusive. In order to aid in my detective work, I put in a few debug commands and a few print statements.","","All of these debugging / print statements are in their own branches. Finally I track down the bug, fix it, and rejoice!","","Only problem is that I now need to get my `bugFix` back into the `master` branch! I could simply fast-forward `master`, but then `master` would get all my debug statements."]}},{type:"ModalAlert",options:{markdowns:["This is where the magic of Git comes in. There are a few ways to do this, but the two most straightforward ways are:","","* `git rebase -i`","* `git cherry-pick`","","Interactive (the `-i`) rebasing allows you to choose which commits you want to keep or discard. It also allows you to reorder commits. This can be helpful if you want to toss out some work.","","Cherry-picking allows you to pick individual commits and plop them down on top of `HEAD`"]}},{type:"ModalAlert",options:{markdowns:["This is a later level so we will leave it up to you to decide, but in order to complete the level, make sure `master` receives the commit that `bugFix` references."]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ローカルに積み上がったコミット","","実際の開発ではこういうケースがよくあります:「バグの原因調査を試みているがバグの再現性がかなり低い。調査の補助のために、いくつかのデバッグ用の命令やprint文を差し込んでいる。」","","これらのデバッグ用のコードはバグ修正用のブランチにコミットされています。そしてついにバグの原因を突き止めて、修正した!やった!","","あとは`bugFix`ブランチを`master`ブランチに統合できればOK。そこで単純に`master`をfast-forwardすればよいかというと、それでは`master`ブランチの中にデバッグ用のコードも混入してしまいます。"]}},{type:"ModalAlert",options:{markdowns:["ここでGitの魔法が力を発揮します。解決のためにはいくつかの方法がありますが、最も素直な解決方法は2つあって:","","* `git rebase -i`","* `git cherry-pick`","","インタラクティブモードの(`-i`オプションつきの)rebaseによって、保持したいコミットと破棄したいコミットを選り分けることができます。コミットの順序を変更することも可能です。この方法は、一部の変更をどこかへやってしまいたい時に便利です。","","もう一方のcherry-pickを使うと、持っていきたいコミットを選んで`HEAD`の先にストンと落とすことができます。"]}},{type:"ModalAlert",options:{markdowns:["後半の章ですのでどう解決するかをもう自分で考えることができると思います。このレベルをクリアするためには、`bugFix`が持っているコミットを`master`ブランチが受け取る必要がある点には注意してください。"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 本地栈式提交 (Locally stacked commits)","","设想一下一个经常发生的场景:我在追踪一个有点棘手的 bug,为了更好地排查,我添加了一些调试命令和打印语句。","","所有的这些调试和打印语句都只在它们自己的分支里。最终我终于找到这个 bug,揪出来 fix 掉,然后撒花庆祝!","","现在唯一的问题就是要把我在 `bugFix` 分支里的工作合并回 `master` 分支。我可以简单地把 `master` 分支快进(fast-forward),但这样的话 `master` 分支就会包含我这些调试语句了。"]}},{type:"ModalAlert",options:{markdowns:["现在就是 Git 大显神通的时候啦。解决这个问题的方法不止一个,但最直接的两个方法是:","","* `git rebase -i`","* `git cherry-pick`","","交互(`-i`)衍合允许你选择哪些提交是要被保留,哪些要被舍弃。它允许你将提交重新排序。假如你要舍弃一些工作,这个会帮上很大的忙。","","Cherry-picking 能让你选择单独一个提交并且把它放到 `HEAD` 的最前端。"]}},{type:"ModalAlert",options:{markdowns:["本关是可选关卡,玩不玩随便你。但是如果你坚持要刷,确保 `master` 分支能拿到 `bugFix` 分支的相关提交(references)。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 로컬에 쌓인 커밋들","","개발중에 종종 이런 상황이 생깁니다: 잘 띄지 않는 버그를 찾아서 해결하려고, 어떤 부분의 문제인지를 찾기 위해 디버그용 코드와 화면에 정보를 프린트하는 코드 몇 줄 넣습니다. ","","디버깅용 코드나 프린트 명령은 그 브랜치에 들어있습니다. 마침내 버그를 찾아서 고쳤고, 원래 작업하는 브랜치에 합치면 됩니다!","","이제 `bugFix`브랜치의 내용을 `master`에 합쳐 넣으려 하지만, 한 가지 문제가 있습니다. 그냥 간단히 `master`브랜치를 최신 커밋으로 이동시킨다면(fast-forward) 그 불필요한 디버그용 코드들도 함께 들어가 버린다는 문제죠."]}},{type:"ModalAlert",options:{markdowns:["여기에서 Git의 마법이 드러납니다. 이 문제를 해결하는 여러가지 방법이 있습니다만, 가장 간단한 두가지 방법 아래와 같습니다:","","* `git rebase -i`","* `git cherry-pick`","","대화형 (-i 옵션) 리베이스(rebase)로는 어떤 커밋을 취하거나 버릴지를 선택할 수 있습니다. 또 커밋의 순서를 바꿀 수도 있습니다. 이 커맨드로 어떤 작업의 일부만 골라내기에 유용합니다.","","체리픽(cherry-pick)은 개별 커밋을 골라서 `HEAD`위에 떨어뜨릴 수 있습니다."]}},{type:"ModalAlert",options:{markdowns:["이번 레벨을 통과하기 위해 어떤 방법을 쓰시든 자유입니다만, `master`브랜치가 `bugFix` 브랜치의 커밋을 일부 가져오게 해주세요."]}}]}}}}),e("/src/levels/mixed/grabbingOneCommit.js"),e.define("/src/levels/mixed/jugglingCommits.js",function(e,t,n,r,i,s,o){n.level={disabledMap:{"git cherry-pick":!0,"git revert":!0},compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C2>e.C3},function(e){return e.C2>e.C1}]},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%27%27%22%2C%22id%22%3A%22master%22%7D%2C%22newImage%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22newImage%22%7D%2C%22caption%22%3A%7B%22target%22%3A%22C3%27%27%22%2C%22id%22%3A%22caption%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%2C%22C2%27%27%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%27%27%22%7D%2C%22C3%27%27%22%3A%7B%22parents%22%3A%5B%22C2%27%27%27%22%5D%2C%22id%22%3A%22C3%27%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git rebase -i HEAD~2;git commit --amend;git rebase -i HEAD~2;git rebase caption master",startTree:'{"branches":{"master":{"target":"C1","id":"master"},"newImage":{"target":"C2","id":"newImage"},"caption":{"target":"C3","id":"caption"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"caption","id":"HEAD"}}',name:{ko:"커밋들 갖고 놀기",en_US:"Juggling Commits",ja:"Juggling Commits",zh_CN:"提交变换戏法"},hint:{en_US:"The first command is git rebase -i HEAD~2",ja:"最初に打つコマンドはgit rebase -i HEAD~2",ko:"첫번째 명령은 git rebase -i HEAD~2 입니다",zh_CN:"第一个命令是 'git rebase -i HEAD~2'"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Juggling Commits","","Here's another situation that happens quite commonly. You have some changes (`newImage`) and another set of changes (`caption`) that are related, so they are stacked on top of each other in your repository (aka one after another).","","The tricky thing is that sometimes you need to make a small modification to an earlier commit. In this case, design wants us to change the dimensions of `newImage` slightly, even though that commit is way back in our history!!"]}},{type:"ModalAlert",options:{markdowns:["We will overcome this difficulty by doing the following:","","* We will re-order the commits so the one we want to change is on top with `git rebase -i`","* We will `commit --amend` to make the slight modification","* Then we will re-order the commits back to how they were previously with `git rebase -i`","* Finally, we will move master to this updated part of the tree to finish the level (via the method of your choosing)","","There are many ways to accomplish this overall goal (I see you eye-ing cherry-pick), and we will see more of them later, but for now let's focus on this technique."]}},{type:"ModalAlert",options:{markdowns:["Lastly, pay attention to the goal state here -- since we move the commits twice, they both get an apostrophe appended. One more apostrophe is added for the commit we amend, which gives us the final form of the tree ","","That being said, I can compare levels now based on structure and relative apostrophe differences. As long as your tree's `master` branch has the same structure and relative apostrophe differences, I'll give full credit"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Commitsをやりくりする","","開発中に頻繁に起こるケースをもう1つ考えます。ある変更(`newImage`)とまた別の変更(`caption`)があって、それらに依存関係があるとします。この一連の変更が一列に積み重なっているとします。","","ここでトリッキーなのは、以前のコミットに対して微修正をかけなければならないケースがあるということです。今回の教材でも、過去のコミットであるにも関わらず`newImage`ブランチに僅かな修正を加えるような設計の修正が入ったとしましょう。"]}},{type:"ModalAlert",options:{markdowns:["この困難な状況を、以下の手順で克服することを考えます:","","* `git rebase -i`を使って順番を変更する。これで、変更をかけたいコミットを一番先頭に持ってくる。","* `commit --amend`コマンドで僅かな変更を行う","* `git rebase -i`コマンドを再度使って、先頭に持ってきていたコミットを元に戻す","* 最後に、レベルクリアのためにmasterブランチを先頭に持ってくる","","クリアのための方法はいくつもありますが(cherry-pickを使うこともできます)、別の回答はまた後程の章で見ることにんして、今回は上記の方法でやってみることにしましょう。"]}},{type:"ModalAlert",options:{markdowns:["最後に、ゴール時点での状態に気を付けてください。今回2回ほどコミットを動かしますから、コミットへのポインタにはアポストロフィ(')が追加されます。commit --amendコマンドの実行でできたコミットには更にもう1つのアポストロフィが追加されます。 "]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 提交变换戏法","","下面这种情况也是经常出现的。例如你之前已经在 `newImage` 分支上做了一些提交,然后又在 `caption` 分支上做了一些相关的提交,因此它们看起来是一个连一个的(stacked on top of each other in your repository)。","","有点棘手的就是有时候你又想往先前的提交里做些小改动。呐,现在就是设计师想要我们去轻微改变下 `newImage` 的内容(change the dimensions slightly),尽管那个提交是很久很久以前的了。"]}},{type:"ModalAlert",options:{markdowns:["为了实现他的愿望,我们可以按照下面的方法来做:","","* 先用 `git rebase -i` 将提交重新排序,然后把我们想要修改的提交挪到最前","* 然后用 `commit --amend` 来进行一些小修改","* 接着再用 `git rebase -i` 来将他们按最开始的顺序重新排好","* 最后我们把 master 移到修改的最前端(用你自己喜欢的方法),就大功告成啦!","","当然还有许多方法可以完成这个任务(我知道你在看 cherry-pick 啦),之后我们会多点关注这些技巧啦,但现在暂时只专注上面这种方法。"]}},{type:"ModalAlert",options:{markdowns:["啊最后还要提醒你一下最终的形式 —— 因为我们把这个提交移动了两次,所以会分别产生一个省略提交(both get an apostrophe appended)。还有一个省略提交是因为我们为了实现最终效果去修改提交而添加的。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 커밋들 갖고 놀기","","이번에도 꽤 자주 발생하는 상황입니다. `newImage`와 `caption` 브랜치에 각각의 변경내역이 있고 서로 약간 관련이 있어서, 저장소에 차례로 쌓여있는 상황입니다.","","때로는 이전 커밋의 내용을 살짝 바꿔야하는 골치아픈 상황에 빠지게 됩니다. 이번에는 디자인 쪽에서 우리의 작업이력(history)에서는 이미 한참 전의 커밋 내용에 있는 `newImage`의 크기를 살짝 바꿔달라는 요청이 들어왔습니다."]}},{type:"ModalAlert",options:{markdowns:["이 문제를 다음과 같이 풀어봅시다:","","* `git rebase -i` 명령으로 우리가 바꿀 커밋을 가장 최근 순서로 바꾸어 놓습니다","* `commit --amend` 명령으로 커밋 내용을 정정합니다","* 다시 `git rebase -i` 명령으로 이 전의 커밋 순서대로 되돌려 놓습니다","* 마지막으로, master를 지금 트리가 변경된 부분으로 이동합니다. (편하신 방법으로 하세요)","","이 목표를 달성하기 위해서는 많은 방법이 있는데요(체리픽을 고민중이시죠?), 체리픽은 나중에 더 살펴보기로 하고, 우선은 위의 방법으로 해결해보세요."]}},{type:"ModalAlert",options:{markdowns:["최종적으로, 목표 결과를 눈여겨 보세요 -- 우리가 커밋을 두 번 옮겼기 때문에, 두 커밋 모두 따옴표 표시가 붙어있습니다. 정정한(amend) 커밋은 따옴표가 추가로 하나 더 붙어있습니다."]}}]}}}}),e("/src/levels/mixed/jugglingCommits.js"),e.define("/src/levels/mixed/jugglingCommits2.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22master%22%7D%2C%22newImage%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22newImage%22%7D%2C%22caption%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22caption%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%27%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout master;git cherry-pick C2;git commit --amend;git cherry-pick C3",disabledMap:{"git revert":!0},startTree:'{"branches":{"master":{"target":"C1","id":"master"},"newImage":{"target":"C2","id":"newImage"},"caption":{"target":"C3","id":"caption"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"caption","id":"HEAD"}}',compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C2>e.C3},function(e){return e.C2>e.C1}]},name:{ko:"커밋 갖고 놀기 #2",en_US:"Juggling Commits #2",ja:"コミットをやりくりする その2",zh_CN:"提交交换戏法 #2"},hint:{en_US:"Don't forget to forward master to the updated changes!",ja:"masterのポインタを先に進めることを忘れずに!",ko:"master를 변경 완료한 커밋으로 이동(forward)시키는 것을 잊지 마세요!",zh_CN:"别忘记了将 master 快进到最新的更新上!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Juggling Commits #2","","*If you haven't completed Juggling Commits #1 (the previous level), please do so before continuing*","","As you saw in the last level, we used `rebase -i` to reorder the commits. Once the commit we wanted to change was on top, we could easily --amend it and re-order back to our preferred order.","","The only issue here is that there is a lot of reordering going on, which can introduce rebase conflicts. Let's look at another method with `git cherry-pick`"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Remember that git cherry-pick will plop down a commit from anywhere in the tree onto HEAD (as long as that commit isn't upstream).","","Here's a small refresher demo:"],afterMarkdowns:["Nice! Let's move on"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["So in this level, let's accomplish the same objective of amending `C2` once but avoid using `rebase -i`. I'll leave it up to you to figure it out! :D","","Remember, the exact number of apostrophe's (') on the commit are not important, only the relative differences. For example, I will give credit to a tree that matches the goal tree but has one extra apostrophe everywhere"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## コミットをやりくりする その2","","*注意 この一つ前のレベル「コミットをやりくりする」をクリアしていない人は、まずそちらの問題をクリアしてきてください*","","前回見てきたように、コミット順序の変更のために、私たちは`rebase -i`コマンドを利用しました。ツリーの先頭に変更対象のコミットがあれば、--amendオプションを使うことで容易に変更を書きかえて、元の順序に戻すことができます。","","この場合に心配なことが一つだけあって、それは複数回の順序の変更が行われるので、rebaseのコンフリクト(衝突)が起こりうることです。こういうケースへの対策として、`git cherry-pick`を使った別の解決法について考えてみましょう。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["git cherry-pickを使うと、ツリーの中から複数のコミットを選んで、HEADの下に新しく作ることができましたね。","","簡単なデモを見てみましょう:"],afterMarkdowns:["できました!次へ進みましょう"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["このレベルでは、`C2`をamendすることで前回と同じ目的を達成しましょう。但し`rebase -i`は使わずにクリアしてください。どんな方法で進めるかはあなたにおまかせします!:D"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 提交变换戏法 #2","","*假如你还没有完成提交变换戏法 #1(前一关),这关不让玩哦!*","","如你在上一关所见,我们使用 `rebase -i` 来重排那些提交。只要把我们想要的提交挪到最顶端,我们就可以很容易地改变它,然后把它们重新排成我们想要的顺序。","","但唯一的问题就是这样做就要排很多次,有可能造成衍合冲突(rebase conflicts)。下面就看看用另外一种方法 `git cherry-pick` 是怎么做的吧。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["要在心理牢记 cherry-pick 可以从提交树的任何地方拿一个提交来放在 HEAD 上(尽管那个提交不在上游)。","","下面是一个小小的演示:"],command:"git cherry-pick C2",afterMarkdowns:["好滴咧,我们继续"],beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["那么这关呢,和上一关一样要改变提交 `C2`,但你要避免使用 `rebase -i`。自己想想要怎么解决吧,骚年! :D"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 커밋 갖고 놀기 #2","","*만약 이전 레벨의 커밋 갖고 놀기 #1을 풀지 않으셨다면, 계속하기에 앞서서 꼭 풀어보세요*","","이전 레벨에서 보셨듯이 `rebase -i` 명령으로 커밋의 순서를 바꿀 수 있습니다. 정정할 커밋이 바로 직전(top)에 있으면 간단히 --amend로 수정할 수 있고, 그리고 나서 다시 원하는 순서로 되돌려 놓으면 됩니다.","","이번에 한가지 문제는 순서를 꽤 많이 바꿔야한다는 점인데요, 그러다가 리베이스중에 충돌이 날 수 있습니다. 이번에는 다른 방법인 `git cherry-pick`으로 해결해 봅시다."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["git cherry-pick으로 HEAD에다 어떤 커밋이든 떨어 뜨려 놓을 수 있다고 알려드린것 기억나세요? (단, 그 커밋이 현재 가리키고 있는 커밋이 아니어야합니다)","","간단한 데모로 다시 알려드리겠습니다:"],afterMarkdowns:["좋아요! 계속할게요"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["그럼 이번 레벨에서는 아까와 마찬가지로 `C2` 커밋의 내용을 정정하되, `rebase -i`를 쓰지 말고 해보세요. ^.~"]}}]}}}}),e("/src/levels/mixed/jugglingCommits2.js"),e.define("/src/levels/rampup/detachedHead.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"C4","id":"HEAD"}}',solutionCommand:"git checkout C4",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Detach yo' HEAD",zh_CN:"分离HEAD"},hint:{en_US:"Use the label (hash) on the commit for help!",zh_CN:"使用提交记录上的标签(hash)来求助!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Moving around in Git","","Before we get to some of the more advanced features of Git, it's important to understand different ways to move through the commit tree that represents your project.","","Once you're comfortable moving around, your powers with other git commands will be amplified!","","","","",""]}},{type:"ModalAlert",options:{markdowns:["## HEAD","","First we have to talk about \"HEAD\". HEAD is the symbolic name for the currently checked out commit -- it's essentially what commit you're working on top of.","","HEAD always points to the most recent commit which is reflected in the working tree. Most git commands which make changes to the working tree will start by changing HEAD.","","Normally HEAD points to a branch name (like bugFix). When you commit, the status of bugFix is altered and this change is visible through HEAD."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's see this in action. Here we will reveal HEAD before and after a commit."],afterMarkdowns:["See! HEAD was hiding underneath our `master` branch all along."],command:"git checkout C1; git checkout master; git commit; git checkout C2",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["### Detaching HEAD","","Detaching HEAD just means attaching it to a commit instead of a branch. This is what it looks like beforehand:","","HEAD -> master -> C1",""],afterMarkdowns:["And now it's","","HEAD -> C1"],command:"git checkout C1",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["To complete this level, let's detach HEAD from `bugFix` and attach it to the commit instead.","","Specify this commit by its hash. The hash for each commit is displayed on the circle that represents the commit."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 在Git中前后移动","","在接触Git的更多高级主题之前,我们先学习用不同的方法在代表你的项目的提交记录树上前后移动。","","一旦能够熟练地在Git中前进后退,你使用其他git命令的威力也会被放大!","","","","",""]}},{type:"ModalAlert",options:{markdowns:["## HEAD","",'我们首先看一下"HEAD". HEAD是当前提交记录的符号名称 -- 其实就是你正在其基础进行工作的提交记录。',"","HEAD总是指向最近一次提交记录,表现为当前工作树。大多数修改工作树的git命令都开始于改变HEAD指向。","","HEAD通常指向分支名(比如bugFix)。你提交时,改变了bugFix的状态,这一变化通过HEAD变得可见。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["在实例中看一下。我们将会观察提交前后HEAD的位置。"],afterMarkdowns:["看! HEAD一直藏在`master`分支后面。"],command:"git checkout C1; git checkout master; git commit; git checkout C2",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["### 分离 HEAD","","分离HEAD就是让其指向一个提交记录而不是分支名。这是命令执行之前的样子: ","","HEAD -> master -> C1",""],afterMarkdowns:["现在变成了","","HEAD -> C1"],command:"git checkout C1",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["想完成此关,从`bugFix`分离出HEAD并让其指向一个提交记录。","","通过hash值指定提交记录。每个提交记录的hash值显示在代表提交记录的圆圈中。"]}}]}}}}),e("/src/levels/rampup/detachedHead.js"),e.define("/src/levels/rampup/relativeRefs.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"C3","id":"HEAD"}}',solutionCommand:"git checkout bugFix^",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Relative Refs (^)",zh_CN:"相对引用(^)"},hint:{en_US:"Remember the Caret (^) operator!",zh_CN:"记住插入(^)操作符!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Relative Refs","","Moving around in Git by specifying commit hashes can get a bit tedious. In the real world you won't have a nice commit tree visualization next to your terminal, so you'll have to use `git log` to see hashes.","","Furthermore, hashes are usually a lot longer in the real Git world as well. For instance, the hash of the commit that introduced the previous level is `fed2da64c0efc5293610bdd892f82a58e8cbc5d8`. Doesn't exactly roll off the tongue...","","The upside is that Git is smart about hashes. It only requires you to specify enough characters of the hash until it uniquely identifies the commit. So I can type `fed2` instead of the long string above."]}},{type:"ModalAlert",options:{markdowns:["Like I said, specifying commits by their hash isn't the most convenient thing ever, which is why Git has relative refs. They are awesome!","","With relative refs, you can start somewhere memorable (like the branch `bugFix` or `HEAD`) and work from there.","","Relative commits are powerful, but we will introduce two simple ones here:","","* Moving upwards one commit at a time with `^`","* Moving upwards a number of times with `~`"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's look at the Caret (^) operator first. Each time you append that to a ref name, you are telling Git to find the parent of the specified commit.","",'So saying `master^` is equivalent to "the first parent of `master`".',"","`master^^` is the grandparent (second-generation ancestor) of `master`","","Let's check out the commit above master here"],afterMarkdowns:["Boom! Done. Way easier than typing the commit hash"],command:"git checkout master^",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["You can also reference `HEAD` as a relative ref. Let's use that a couple of times to move upwards in the commit tree"],afterMarkdowns:["Easy! We can travel backwards in time with `HEAD^`"],command:"git checkout C3; git checkout HEAD^; git checkout HEAD^; git checkout HEAD^",beforeCommand:"git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["To complete this level, check out the parent commit of `bugFix`. This will detach `HEAD`.","","You can specify the hash if you want, but try using relative refs instead!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 相对引用","","用指定提交记录hash值的方式在Git中移动会变得比较乏味。在现实中,你不会有漂亮的可视化的提交记录树放在终端旁边,所以你不得不用`git log`来查看hasn值。","","另外,hash值在真实的Git环境中也会更长。举个例子,前一关的介绍中的提交记录的hash值是`fed2da64c0efc5293610bdd892f82a58e8cbc5d8`。不要把舌头闪了...","","好的一面是,Git对hash的处理很智能。你只需要提供能够唯一标识提交记录的前几个字符即可。所以,我可以仅输入`fed2`而不是上面的一长串字符。"]}},{type:"ModalAlert",options:{markdowns:["我说过,通过hash指定提交记录不是很方便,所以Git引入了相对引用。这个就很牛掰了!","","使用相对引用,你可以从一个易于记忆的地方(比如分支名`bugFix`或`HEAD`)开始工作。","","相对引用非常给力,这里我介绍两个简单的用法:","","* 使用`^`向上移动1个提交记录","* 使用`~`向上移动多个提交记录"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["首先看看插入(^)操作符。把插入符跟在引用名后面,表示让Git寻找指定提交记录的父提交。","",'所以`master^`相当于"`master`的父提交"。',"","`master^^`是`master`的父父提交(上上代祖先)","","切换到master的父提交"],afterMarkdowns:["唰!搞定。这种方式比输入提交记录的hash值简单多了!"],command:"git checkout master^",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["你也可以`HEAD`把用作相对引用。以下命令使用`HEAD`在提交树中向上移动几次。"],afterMarkdowns:["简单!我们可以一直使用`HEAD^`向上移动。"],command:"git checkout C3; git checkout HEAD^; git checkout HEAD^; git checkout HEAD^",beforeCommand:"git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["要完成此关,切换到`bugFix`的父提交。这会分离出`HEAD`.","","如果你愿意的话,使用hash值也可以过关,但为何不试试使用相对引用呢?"]}}]}}}}),e("/src/levels/rampup/relativeRefs.js"),e.define("/src/levels/rampup/relativeRefs2.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C6","id":"master"},"bugFix":{"target":"C0","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C5":{"parents":["C3"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"C1","id":"HEAD"}}',solutionCommand:"git branch -f master C6;git checkout HEAD~1;git branch -f bugFix HEAD~1",startTree:'{"branches":{"master":{"target":"C4","id":"master"},"bugFix":{"target":"C5","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C5":{"parents":["C3"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"C2","id":"HEAD"}}',hint:{en_US:"You'll need to use at least one direct reference (hash) to complete this level",zh_CN:"这一关至少要用到一次直接引用(hash)"},name:{en_US:"Relative Refs #2 (~)",zh_CN:"相对引用2(~)"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:['### The "~" operator',"","Say you want to move a lot of levels up in the commit tree. It might be tedious to type `^` several times, so Git also has the tilde (~) operator.","","","The tilde operator (optionally) takes in a trailing number that specifies the number of parents you would like to ascend. Let's see it in action"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's specify a number of commits back with `~`."],afterMarkdowns:["Boom! So concise -- relative refs are great."],command:"git checkout HEAD~4",beforeCommand:"git commit; git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["### Branch forcing","","You're an expert on relative refs now, so let's actually *use* them for something.","","One of the most common ways I use relative refs is to move branches around. You can directly reassign a branch to a commit with the `-f` option. So something like:","","`git branch -f master HEAD~3`","","Moves (by force) the master branch to three parents behind HEAD."]}},{type:"ModalAlert",options:{markdowns:["To complete this level, move `HEAD`, `master`, and `bugFix` to their goal destinations shown."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:['### The "~" operator',"","假设需要在提交树中向上移动很多步。使用多个`^`非常无聊,所以Git也引入了波浪(~)操作符。","","","波浪操作符后面可以(可选地)跟一个数字,指定向上移动多少次。看个例子"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用`~`一次后退多步."],afterMarkdowns:["唰!如此简洁--相对引用就是好啊!"],command:"git checkout HEAD~4",beforeCommand:"git commit; git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["### Branch forcing","","你现在是相对引用的高手了,现在*用*他来实际做点事情。","","我使用相对引用最多的就是移动分支。你可以使用`-f`选项把直接让分支指向另一个提交。举个例子:","","`git branch -f master HEAD~3`","","(强制)移动master指向HEAD的第3级父提交。"]}},{type:"ModalAlert",options:{markdowns:["要完成此关,移动`HEAD`,`master`和`bugFix`到目标所示的位置。"]}}]}}}}),e("/src/levels/rampup/relativeRefs2.js"),e.define("/src/levels/rampup/reversingChanges.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22master%22%7D%2C%22pushed%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22pushed%22%7D%2C%22local%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22local%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C2%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22pushed%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git reset HEAD~1;git checkout pushed;git revert HEAD",compareOnlyBranches:!0,startTree:'{"branches":{"master":{"target":"C1","id":"master"},"pushed":{"target":"C2","id":"pushed"},"local":{"target":"C3","id":"local"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"}},"HEAD":{"target":"local","id":"HEAD"}}',name:{en_US:"Reversing Changes in Git",ja:"変更を元に戻す",fr_FR:"Annuler des changements avec Git",ko:"Git에서 작업 되돌리기",zh_CN:"在Git中撤销更改"},hint:{en_US:"Notice that revert and reset take different arguments.",fr_FR:"",zh_CN:"注意revert和reset使用不同的参数。",ko:"",ja:""},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Reversing Changes in Git","","There are many ways to reverse changes in Git. And just like committing, reversing changes in Git has both a low-level component (staging individual files or chunks) and a high-level component (how the changes are actually reversed). Our application will focus on the latter.","","There are two primary ways to undo changes in Git -- one is using `git reset` and the other is using `git revert`. We will look at each of these in the next dialog",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","",'`git reset` reverts changes by moving a branch reference backwards in time to an older commit. In this sense you can think of it as "rewriting history;" `git reset` will move a branch backwards as if the commit had never been made in the first place.',"","Let's see what that looks like:"],afterMarkdowns:["Nice! Git simply moved the master branch reference back to `C1`; now our local repository is in a state as if `C2` had never happened"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","",'While reseting works great for local branches on your own machine, its method of "rewriting history" doesn\'t work for remote branches that others are using.',"","In order to reverse changes and *share* those reversed changes with others, we need to use `git revert`. Let's see it in action"],afterMarkdowns:["Weird, a new commit plopped down below the commit we wanted to reverse. That's because this new commit `C2'` introduces *changes* -- it just happens to introduce changes that exactly reverses the commit of `C2`.","","With reverting, you can push out your changes to share with others."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["To complete this level, reverse the two most recent commits on both `local` and `pushed`.","","Keep in mind that `pushed` is a remote branch and `local` is a local branch -- that should help you choose your methods."]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## 変更を元に戻す","","Gitでは変更を元に戻す方法がたくさんあります。コミットと同じように、低レベルな動作(ファイル別だったりファイルの中の一部だったり)も高レベルな動作(変更のまとまりのキャンセル)もできます。このアプリケーションでは後者の方法について紹介します。","","基本的なアンドゥの方法が2つあります - 一つは`git reset`を使う方法で、もう1つは`git revert`を使う方法です。次のダイアログで一つ一つを見ていきます。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","","`git reset`はブランチのポインタを後方に移動することで変更のキャンセルを実現します。履歴を上書きするような動作だと思うと良いでしょうか:`git reset`はそもそも前のコミットなんかなかったかのように、ブランチのポインタを元に戻してくれます。","","どういう感じか見てみましょう。"],afterMarkdowns:["いいですね!Gitは単純にmasterブランチへのポインタを`C1`へ戻しました。これでこのローカルリポジトリにはまるで`C2`なんて無かったかのように変更をキャンセルできました。"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","自分のマシン上のブランチではさっきの`git reset`でうまくいきましたが、この「履歴を上書きする」手段は、他の人も使っているリモートにあるリポジトリに対しては使うことができません。","","変更を巻き戻して他の人とそれを共有するためには、`git revert`を使う必要があります。今度はこれを見てみましょう。"],afterMarkdowns:["あれ、おかしいな。巻き戻したいと思ってたコミットの下に新しいコミットが出来上がってしまったみたいです。なぜか。これは、この新しい`C2'`コミットは`C2`へ戻すのに必要な内容を確かに変更して巻き戻していたのです。","","こんな風にして、巻き戻した内容を他人と共有するためにはrevertを使います。"],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["この章の仕上げに、`local`と`pushed`の両方の直近のコミットを巻き戻してみましょう。","","`pushed`はリモートのブランチで、`local`はローカルであることに注意。正しくコマンドを使い分けましょう。"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Annuler des changements avec Git","","Il y a de nombreuses façons d'annuler des changement avec Git. De même que pour les commits, annuler des changements avec Git a à la fois un aspect bas-niveau (gestion dans le 'staging' des fichiers et morceaux de fichiers) et un aspect de plus haut niveau 9comment les changements sont effectivement annulés). Nous allons nous intéresser à ce dernier point.","","Il y a principalement deux façons d'annuler des changements avec Git -- l'une est `git reset` et l'autre est `git revert`. Nous allons maintenant voir chacune de ces façons",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","","`git reset` annule des changements en déplaçant la référence en arrière dans le temps sur un commit plus ancien. En ce sens, on peut considérer cela comme une façon de \"réécrire l'histoire\"; `git reset` fait remonter une branche en arrière comme si le(s) commit(s) n'avait jamais eu lieu.","","Regardons à quoi cela ressemble :"],afterMarkdowns:["Bravo ! Git a simplement déplacé la référence de la branche master en la faisant revenir sur `C1`; désormais notre dépôt est dans le même état que si `C2` n'avait jamais eu lieu"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","Bien que le reset marche parfaitement pour les branches locales sur notre propre machine, cette façon de \"réécrire l'histoire\" ne marche pas avec les banches distantes (remote) que d'autres personnes utilisent.","","Pour pouvoir annuler des changements et *partager* ces annulations avec d'autres, nous devons utiliser `git revert`. Regardons comment cela fonctionne"],afterMarkdowns:["Étrangement, un nouveau commit est appaaru en bas sous le commit que nous voulions annuler. C'est parce que ce nouveau commit `C2'` introduit des *modifications* -- celles qui correspondent justement à l'annulation de celles du commit `C2`.","","Avec revert, vous pouvez diffuser (push) vos modifications et les partager avec tout le monde."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["Pour accomplir ce niveau, annulez les deux derniers commits à la fois sur `local` et sur `pushed`.","","Ayez à l'esprit que `pushed` est une branche distante et `local` est une branche locale -- cela devrait vous guider dans le choix de la méthode à employer."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 撤销 Git 里面的变动","","在 Git 里撤销修改的方法很多。和 commit 一样,在 Git 里撤销变动同时具有底层部分(暂存一些独立的文件或者片段)和高层部分(具体到变动是究竟怎么被撤销的)。我们这个应用主要关注后者。","","在 Git 里主要用两种方法来撤销变动 —— 一种是 `git reset`,另外一种是 `git revert`。让我们在下一个窗口逐一了解它们。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","",'`git reset`把分支记录回退到上一个提交记录来实现撤销改动。你可以认为这是在"重写历史"。`git reset`往回移动分支,原来指向的提交记录好像重来没有提交过一样。',"","让我们看看具体的操作:"],command:"git reset HEAD~1",afterMarkdowns:["Nice!Git把master分支的指向简单地移回到`C1`;现在我们的本地代码库处于没有提交过`C2`的状态了。"],beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","虽然在你的本地分支中使用`git reset`很方便,但是这种“改写历史”的方法对别人的远端分支是无效的哦!","","为了撤销更改并*传播*给别人,我们需要使用`git revert`。举个例子"],command:"git revert HEAD",afterMarkdowns:["怪哉!在我们要撤销的提交记录后面居然多了一个新提交!这是因为新提交记录`C2'`引入了*更改*——刚好是用来撤销 `C2` 这个提交的。","","借助 revert,现在可以把你的更改传递给别人啦。"],beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["要完成此关,分别撤销`local`分支和`pushed`分支上的最近一次提交。","","记住 `pushed` 是一个远程分支,`local` 是一个本地分支 —— 有了这么明显的提示应该知道用哪种方法了吧?"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git에서 작업 되돌리기","","Git에는 작업한 것을 되돌리는 여러가지 방법이 있습니다. 변경내역을 되돌리는 것도 커밋과 마찬가지로 낮은 수준의 일(개별 파일이나 묶음을 스테이징 하는 것)과 높은 수준의 일(실제 변경이 복구되는 방법)이 있는데요, 여기서는 후자에 집중해 알려드릴게요.","","Git에서 변경한 내용을 되돌리는 방법은 크게 두가지가 있습니다 -- 하나는 `git reset`을 쓰는거고, 다른 하나는 `git revert`를 사용하는 것입니다. 다음 화면에서 하나씩 알아보겠습니다.",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git 리셋(reset)","",'`git reset`은 브랜치로 하여금 예전의 커밋을 가리키도록 이동시키는 방식으로 변경 내용을 되돌립니다. 이런 관점에서 "히스토리를 고쳐쓴다"라고 말할 수 있습니다. 즉, `git reset`은 마치 애초에 커밋하지 않은 것처럼 예전 커밋으로 브랜치를 옮기는 것입니다.',"","어떤 그림인지 한번 보죠:"],afterMarkdowns:["그림에서처럼 master 브랜치가 가리키던 커밋을 `C1`로 다시 옮겼습니다; 이러면 로컬 저장소에는 마치 `C2`커밋이 아예 없었던 것과 마찬가지 상태가 됩니다."],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git 리버트(revert)","",'각자의 컴퓨터에서 작업하는 로컬 브랜치의 경우 리셋(reset)을 잘 쓸 수 있습니다만, "히스토리를 고쳐쓴다"는 점 때문에 다른 사람이 작업하는 리모트 브랜치에는 쓸 수 없습니다.',"","변경분을 되돌리고, 이 되돌린 내용을 다른 사람들과 *공유하기* 위해서는, `git revert`를 써야합니다. 예제로 살펴볼게요."],afterMarkdowns:["어색하게도, 우리가 되돌리려고한 커밋의 아래에 새로운 커밋이 생겼습니다. `C2`라는 새로운 커밋에 *변경내용*이 기록되는데요, 이 변경내역이 정확히 `C2` 커밋 내용의 반대되는 내용입니다.","","리버트를 하면 다른 사람들에게도 변경 내역을 밀어(push) 보낼 수 있습니다."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["이 레벨을 통과하려면, `local` 브랜치와 `pushed` 브랜치에 있는 최근 두 번의 커밋을 되돌려 보세요.","","`pushed`는 리모트 브랜치이고, `local`은 로컬 브랜치임을 신경쓰셔서 작업하세요 -- 어떤 방법을 선택하실지 떠오르시죠?"]}}]}}}}),e("/src/levels/rampup/reversingChanges.js"),e.define("/src/levels/rebase/manyRebases.js",function(e,t,n,r,i,s,o){n.level={compareOnlyMasterHashAgnostic:!0,disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22master%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22bugFix%22%7D%2C%22side%22%3A%7B%22target%22%3A%22C6%27%22%2C%22id%22%3A%22side%22%7D%2C%22another%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22another%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C6%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C6%22%7D%2C%22C7%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C7%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C6%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C6%27%22%7D%2C%22C7%27%22%3A%7B%22parents%22%3A%5B%22C6%27%22%5D%2C%22id%22%3A%22C7%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout bugFix;git rebase master;git checkout side;git rebase bugFix;git checkout another;git rebase side;git rebase another master",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C3","id":"bugFix"},"side":{"target":"C6","id":"side"},"another":{"target":"C7","id":"another"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C0"],"id":"C4"},"C5":{"parents":["C4"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"},"C7":{"parents":["C5"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Rebasing over 9000 times",ko:"9천번이 넘는 리베이스",ja:"Rebasing over 9000 times",zh_CN:"N次Rebase"},hint:{en_US:"Remember, the most efficient way might be to only update master at the end...",ja:"最も効率的なやり方はmasterを最後に更新するだけかもしれない・・・",ko:"아마도 master를 마지막에 업데이트하는 것이 가장 효율적인 방법일 것입니다...",zh_CN:"记住,最后更新master分支可能是最高效的方法。"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["### Rebasing Multiple Branches","","Man, we have a lot of branches going on here! Let's rebase all the work from these branches onto master.","","Upper management is making this a bit trickier though -- they want the commits to all be in sequential order. So this means that our final tree should have `C7'` at the bottom, `C6'` above that, etc etc, etc all in order.","","If you mess up along the way, feel free to use `reset` to start over again. Be sure to check out our solution and see if you can do it in fewer commands!"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["### 複数のブランチをリベースする","","さあ、いくつものブランチが出てきます。このブランチたち全てをmasterブランチにリベースしましょう。","","おエライさん方が今回の仕事を少しトリッキーにしてくれました ― コミットはすべて一列のシーケンシャルな状態にしてほしいそうです。つまり私たちが作るリポジトリの最終的なツリーの状態は、`C7'`が最後に来て、`C6'`がその一つ上に来て、、と順に積み重なるイメージです。","","試行錯誤してツリーが汚くなってきたら、`reset`コマンドを使ってツリーの状態を初期化してください。模範解答をチェックして、それよりも簡単なコマンドで済ませられるかどうか、を考えるのも忘れずに!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["### 多分支衍合","","呐,现在我们有很多分支啦!让我们rebase这些分支的工作到 master 分支上吧。","","但是你的头头找了点麻烦 —— 他们希望得到有序的提交历史,也就是我们最终的结果是 `C7'` 在最底部,`C6'` 在它上面,以此类推。","","假如你搞砸了,没所谓的(虽然我不会告诉你用 `reset` 可以重新开始)。记得看看我们提供的答案,看你能否使用更少的命令完成任务!"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["### 여러 브랜치를 리베이스(rebase)하기 ","","음, 여기 꽤 여러개의 브랜치가 있습니다! 이 브랜치들의 모든 작업내역을 master에 리베이스 해볼까요?","","윗선에서 일을 복잡하게 만드네요 -- 그 분들이 이 모든 커밋들을 순서에 맞게 정렬하라고 합니다. 그럼 결국 우리의 최종 목표 트리는 제일 아래에 `C7'` 커밋, 그 위에 `C6'` 커밋, 또 그 위에 순서대로 보여합니다.","","만일 작업중에 내용이 꼬인다면, `reset`이라고 쳐서 처음부터 다시 시작할 수 있습니다. 모범 답안을 확인해 보시고, 혹시 더 적은 수의 커맨드로 해결할 수 있는지 알아보세요!"]}}]}}}}),e("/src/levels/rebase/manyRebases.js"),e.define("/src/levels/rebase/selectiveRebase.js",function(e,t,n,r,i,s,o){n.level={compareAllBranchesHashAgnostic:!0,disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C5%22%2C%22id%22%3A%22master%22%7D%2C%22one%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22one%22%7D%2C%22two%22%3A%7B%22target%22%3A%22C2%27%27%22%2C%22id%22%3A%22two%22%7D%2C%22three%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22three%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C4%27%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C4%27%27%22%7D%2C%22C3%27%27%22%3A%7B%22parents%22%3A%5B%22C4%27%27%22%5D%2C%22id%22%3A%22C3%27%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C3%27%27%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22two%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout one; git cherry-pick C4 C3 C2; git checkout two; git cherry-pick C5 C4 C3 C2; git branch -f three C2",startTree:'{"branches":{"master":{"target":"C5","id":"master"},"one":{"target":"C1","id":"one"},"two":{"target":"C1","id":"two"},"three":{"target":"C1","id":"three"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C4"],"id":"C5"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{ko:"브랜치 스파게티",en_US:"Branch Spaghetti",ja:"ブランチスパゲッティ",zh_CN:"分支浆糊"},hint:{en_US:"Make sure to do everything in the proper order! Branch one first, then two, then three",ja:"全て正しい順番で処理すること!oneが最初で、次がtwo、最後にthreeを片付ける。",ko:"이 문제를 해결하는 방법은 여러가지가 있습니다! 체리픽(cherry-pick)이 가장 쉽지만 오래걸리는 방법이고, 리베이스(rebase -i)가 빠른 방법입니다",zh_CN:"确保你是按照正确的顺序来操作!先操作分支 `one`, 然后 `two`, 最后才是 `three`"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branch Spaghetti","","WOAHHHhhh Nelly! We have quite the goal to reach in this level.","","Here we have `master` that is a few commits ahead of branches `one` `two` and `three`. For whatever reason, we need to update these three other branches with modified versions of the last few commits on master.","","Branch `one` needs a re-ordering and a deletion of `C5`. `two` needs pure reordering, and `three` only needs one commit!","","We will let you figure out how to solve this one -- make sure to check out our solution afterwards with `show solution`. "]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ブランチスパゲッティ","","なんということでしょう。今回のレベルクリアのために、やることがたくさんあります。","","いま`master`が指しているコミットの数個前のコミットに、ブランチ`one`、`two`それから`three`があります。何か事情があって、これらの3つのブランチをmasterが指している最新の状態に更新したいケースを考えます。","","ブランチ`one`に対しては、順序の変更と`C5`の削除が必要です。`two`では順序の変更のみ、`three`に対しては1回だけコミットすればOKです。","","`show solution`コマンドで模範解答を確認できますから、こちらも利用してください。 "]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branch Spaghetti","","哇塞大神!这关我们要来点不同的!","","现在我们的 `master` 分支是比 `one` `two` 和 `three` 要多几个提交。出于某种原因,我们需要把其他三个分支更新到 master 分支上新近的几个不同提交上。(update these three other brances with modified versions of the last few commits on master)","","分支 `one` 需要重新排序和撤销, `two` 需要完全重排,而 `three` 只需要提交一次。","","慢慢摸索会找到答案的 —— 你完事记得用 `show solution` 看看我们的答案哦。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 브랜치 스파게티","","음, 이번에는 만만치 않습니다!","","여기 `master` 브랜치의 몇 번 이전 커밋에 `one`, `two`,`three` 총 3개의 브랜치가 있습니다. 어떤 이유인지는 몰라도, master의 최근 커밋 몇 개를 나머지 세 개의 브랜치에 반영하려고 합니다.","","`one` 브랜치는 순서를 바꾸고 `C5`커밋을 삭제하고, `two`브랜치는 순서만 바꾸며, `three`브랜치는 하나의 커밋만 가져옵시다!","","자유롭게 이 문제를 풀어보시고 나서 `show solution`명령어로 모범 답안을 확인해보세요."]}}]}}}}),e("/src/levels/rebase/selectiveRebase.js")})(); \ No newline at end of file +(function(){var e=function(t,n){var r=e.resolve(t,n||"/"),i=e.modules[r];if(!i)throw new Error("Failed to resolve module "+t+", tried "+r);var s=e.cache[r],o=s?s.exports:i();return o};e.paths=[],e.modules={},e.cache={},e.extensions=[".js",".coffee",".json"],e._core={assert:!0,events:!0,fs:!0,path:!0,vm:!0},e.resolve=function(){return function(t,n){function u(t){t=r.normalize(t);if(e.modules[t])return t;for(var n=0;n=0;i--){if(t[i]==="node_modules")continue;var s=t.slice(0,i+1).join("/")+"/node_modules";n.push(s)}return n}n||(n="/");if(e._core[t])return t;var r=e.modules.path();n=r.resolve("/",n);var i=n||"/";if(t.match(/^(?:\.\.?\/|\/)/)){var s=u(r.resolve(i,t))||a(r.resolve(i,t));if(s)return s}var o=f(t,i);if(o)return o;throw new Error("Cannot find module '"+t+"'")}}(),e.alias=function(t,n){var r=e.modules.path(),i=null;try{i=e.resolve(t+"/package.json","/")}catch(s){i=e.resolve(t,"/")}var o=r.dirname(i),u=(Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t})(e.modules);for(var a=0;a=0;r--){var i=e[r];i=="."?e.splice(r,1):i===".."?(e.splice(r,1),n++):n&&(e.splice(r,1),n--)}if(t)for(;n--;n)e.unshift("..");return e}var f=/^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;n.resolve=function(){var e="",t=!1;for(var n=arguments.length;n>=-1&&!t;n--){var r=n>=0?arguments[n]:s.cwd();if(typeof r!="string"||!r)continue;e=r+"/"+e,t=r.charAt(0)==="/"}return e=a(u(e.split("/"),function(e){return!!e}),!t).join("/"),(t?"/":"")+e||"."},n.normalize=function(e){var t=e.charAt(0)==="/",n=e.slice(-1)==="/";return e=a(u(e.split("/"),function(e){return!!e}),!t).join("/"),!e&&!t&&(e="."),e&&n&&(e+="/"),(t?"/":"")+e},n.join=function(){var e=Array.prototype.slice.call(arguments,0);return n.normalize(u(e,function(e,t){return e&&typeof e=="string"}).join("/"))},n.dirname=function(e){var t=f.exec(e)[1]||"",n=!1;return t?t.length===1||n&&t.length<=3&&t.charAt(1)===":"?t:t.substring(0,t.length-1):"."},n.basename=function(e,t){var n=f.exec(e)[2]||"";return t&&n.substr(-1*t.length)===t&&(n=n.substr(0,n.length-t.length)),n},n.extname=function(e){return f.exec(e)[3]||""}}),e.define("__browserify_process",function(e,t,n,r,i,s,o){var s=t.exports={};s.nextTick=function(){var e=typeof window!="undefined"&&window.setImmediate,t=typeof window!="undefined"&&window.postMessage&&window.addEventListener;if(e)return function(e){return window.setImmediate(e)};if(t){var n=[];return window.addEventListener("message",function(e){if(e.source===window&&e.data==="browserify-tick"){e.stopPropagation();if(n.length>0){var t=n.shift();t()}}},!0),function(t){n.push(t),window.postMessage("browserify-tick","*")}}return function(t){setTimeout(t,0)}}(),s.title="browser",s.browser=!0,s.env={},s.argv=[],s.binding=function(t){if(t==="evals")return e("vm");throw new Error("No such module. (Possibly not yet loaded)")},function(){var t="/",n;s.cwd=function(){return t},s.chdir=function(r){n||(n=e("path")),t=n.resolve(r,t)}}()}),e.define("/node_modules/underscore/package.json",function(e,t,n,r,i,s,o){t.exports={main:"underscore.js"}}),e.define("/node_modules/underscore/underscore.js",function(e,t,n,r,i,s,o){(function(){var e=this,r=e._,i={},s=Array.prototype,o=Object.prototype,u=Function.prototype,a=s.push,f=s.slice,l=s.concat,c=o.toString,h=o.hasOwnProperty,p=s.forEach,d=s.map,v=s.reduce,m=s.reduceRight,g=s.filter,y=s.every,b=s.some,w=s.indexOf,E=s.lastIndexOf,S=Array.isArray,x=Object.keys,T=u.bind,N=function(e){if(e instanceof N)return e;if(!(this instanceof N))return new N(e);this._wrapped=e};typeof n!="undefined"?(typeof t!="undefined"&&t.exports&&(n=t.exports=N),n._=N):e._=N,N.VERSION="1.4.4";var C=N.each=N.forEach=function(e,t,n){if(e==null)return;if(p&&e.forEach===p)e.forEach(t,n);else if(e.length===+e.length){for(var r=0,s=e.length;r2;e==null&&(e=[]);if(v&&e.reduce===v)return r&&(t=N.bind(t,r)),i?e.reduce(t,n):e.reduce(t);C(e,function(e,s,o){i?n=t.call(r,n,e,s,o):(n=e,i=!0)});if(!i)throw new TypeError(k);return n},N.reduceRight=N.foldr=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(m&&e.reduceRight===m)return r&&(t=N.bind(t,r)),i?e.reduceRight(t,n):e.reduceRight(t);var s=e.length;if(s!==+s){var o=N.keys(e);s=o.length}C(e,function(u,a,f){a=o?o[--s]:--s,i?n=t.call(r,n,e[a],a,f):(n=e[a],i=!0)});if(!i)throw new TypeError(k);return n},N.find=N.detect=function(e,t,n){var r;return L(e,function(e,i,s){if(t.call(n,e,i,s))return r=e,!0}),r},N.filter=N.select=function(e,t,n){var r=[];return e==null?r:g&&e.filter===g?e.filter(t,n):(C(e,function(e,i,s){t.call(n,e,i,s)&&(r[r.length]=e)}),r)},N.reject=function(e,t,n){return N.filter(e,function(e,r,i){return!t.call(n,e,r,i)},n)},N.every=N.all=function(e,t,n){t||(t=N.identity);var r=!0;return e==null?r:y&&e.every===y?e.every(t,n):(C(e,function(e,s,o){if(!(r=r&&t.call(n,e,s,o)))return i}),!!r)};var L=N.some=N.any=function(e,t,n){t||(t=N.identity);var r=!1;return e==null?r:b&&e.some===b?e.some(t,n):(C(e,function(e,s,o){if(r||(r=t.call(n,e,s,o)))return i}),!!r)};N.contains=N.include=function(e,t){return e==null?!1:w&&e.indexOf===w?e.indexOf(t)!=-1:L(e,function(e){return e===t})},N.invoke=function(e,t){var n=f.call(arguments,2),r=N.isFunction(t);return N.map(e,function(e){return(r?t:e[t]).apply(e,n)})},N.pluck=function(e,t){return N.map(e,function(e){return e[t]})},N.where=function(e,t,n){return N.isEmpty(t)?n?null:[]:N[n?"find":"filter"](e,function(e){for(var n in t)if(t[n]!==e[n])return!1;return!0})},N.findWhere=function(e,t){return N.where(e,t,!0)},N.max=function(e,t,n){if(!t&&N.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.max.apply(Math,e);if(!t&&N.isEmpty(e))return-Infinity;var r={computed:-Infinity,value:-Infinity};return C(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o>=r.computed&&(r={value:e,computed:o})}),r.value},N.min=function(e,t,n){if(!t&&N.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.min.apply(Math,e);if(!t&&N.isEmpty(e))return Infinity;var r={computed:Infinity,value:Infinity};return C(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;or||n===void 0)return 1;if(n>>1;n.call(r,e[u])=0})})},N.difference=function(e){var t=l.apply(s,f.call(arguments,1));return N.filter(e,function(e){return!N.contains(t,e)})},N.zip=function(){var e=f.call(arguments),t=N.max(N.pluck(e,"length")),n=new Array(t);for(var r=0;r=0;n--)t=[e[n].apply(this,t)];return t[0]}},N.after=function(e,t){return e<=0?t():function(){if(--e<1)return t.apply(this,arguments)}},N.keys=x||function(e){if(e!==Object(e))throw new TypeError("Invalid object");var t=[];for(var n in e)N.has(e,n)&&(t[t.length]=n);return t},N.values=function(e){var t=[];for(var n in e)N.has(e,n)&&t.push(e[n]);return t},N.pairs=function(e){var t=[];for(var n in e)N.has(e,n)&&t.push([n,e[n]]);return t},N.invert=function(e){var t={};for(var n in e)N.has(e,n)&&(t[e[n]]=n);return t},N.functions=N.methods=function(e){var t=[];for(var n in e)N.isFunction(e[n])&&t.push(n);return t.sort()},N.extend=function(e){return C(f.call(arguments,1),function(t){if(t)for(var n in t)e[n]=t[n]}),e},N.pick=function(e){var t={},n=l.apply(s,f.call(arguments,1));return C(n,function(n){n in e&&(t[n]=e[n])}),t},N.omit=function(e){var t={},n=l.apply(s,f.call(arguments,1));for(var r in e)N.contains(n,r)||(t[r]=e[r]);return t},N.defaults=function(e){return C(f.call(arguments,1),function(t){if(t)for(var n in t)e[n]==null&&(e[n]=t[n])}),e},N.clone=function(e){return N.isObject(e)?N.isArray(e)?e.slice():N.extend({},e):e},N.tap=function(e,t){return t(e),e};var _=function(e,t,n,r){if(e===t)return e!==0||1/e==1/t;if(e==null||t==null)return e===t;e instanceof N&&(e=e._wrapped),t instanceof N&&(t=t._wrapped);var i=c.call(e);if(i!=c.call(t))return!1;switch(i){case"[object String]":return e==String(t);case"[object Number]":return e!=+e?t!=+t:e==0?1/e==1/t:e==+t;case"[object Date]":case"[object Boolean]":return+e==+t;case"[object RegExp]":return e.source==t.source&&e.global==t.global&&e.multiline==t.multiline&&e.ignoreCase==t.ignoreCase}if(typeof e!="object"||typeof t!="object")return!1;var s=n.length;while(s--)if(n[s]==e)return r[s]==t;n.push(e),r.push(t);var o=0,u=!0;if(i=="[object Array]"){o=e.length,u=o==t.length;if(u)while(o--)if(!(u=_(e[o],t[o],n,r)))break}else{var a=e.constructor,f=t.constructor;if(a!==f&&!(N.isFunction(a)&&a instanceof a&&N.isFunction(f)&&f instanceof f))return!1;for(var l in e)if(N.has(e,l)){o++;if(!(u=N.has(t,l)&&_(e[l],t[l],n,r)))break}if(u){for(l in t)if(N.has(t,l)&&!(o--))break;u=!o}}return n.pop(),r.pop(),u};N.isEqual=function(e,t){return _(e,t,[],[])},N.isEmpty=function(e){if(e==null)return!0;if(N.isArray(e)||N.isString(e))return e.length===0;for(var t in e)if(N.has(e,t))return!1;return!0},N.isElement=function(e){return!!e&&e.nodeType===1},N.isArray=S||function(e){return c.call(e)=="[object Array]"},N.isObject=function(e){return e===Object(e)},C(["Arguments","Function","String","Number","Date","RegExp"],function(e){N["is"+e]=function(t){return c.call(t)=="[object "+e+"]"}}),N.isArguments(arguments)||(N.isArguments=function(e){return!!e&&!!N.has(e,"callee")}),typeof /./!="function"&&(N.isFunction=function(e){return typeof e=="function"}),N.isFinite=function(e){return isFinite(e)&&!isNaN(parseFloat(e))},N.isNaN=function(e){return N.isNumber(e)&&e!=+e},N.isBoolean=function(e){return e===!0||e===!1||c.call(e)=="[object Boolean]"},N.isNull=function(e){return e===null},N.isUndefined=function(e){return e===void 0},N.has=function(e,t){return h.call(e,t)},N.noConflict=function(){return e._=r,this},N.identity=function(e){return e},N.times=function(e,t,n){var r=Array(e);for(var i=0;i":">",'"':""","'":"'","/":"/"}};D.unescape=N.invert(D.escape);var P={escape:new RegExp("["+N.keys(D.escape).join("")+"]","g"),unescape:new RegExp("("+N.keys(D.unescape).join("|")+")","g")};N.each(["escape","unescape"],function(e){N[e]=function(t){return t==null?"":(""+t).replace(P[e],function(t){return D[e][t]})}}),N.result=function(e,t){if(e==null)return null;var n=e[t];return N.isFunction(n)?n.call(e):n},N.mixin=function(e){C(N.functions(e),function(t){var n=N[t]=e[t];N.prototype[t]=function(){var e=[this._wrapped];return a.apply(e,arguments),I.call(this,n.apply(N,e))}})};var H=0;N.uniqueId=function(e){var t=++H+"";return e?e+t:t},N.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var B=/(.)^/,j={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},F=/\\|'|\r|\n|\t|\u2028|\u2029/g;N.template=function(e,t,n){var r;n=N.defaults({},n,N.templateSettings);var i=new RegExp([(n.escape||B).source,(n.interpolate||B).source,(n.evaluate||B).source].join("|")+"|$","g"),s=0,o="__p+='";e.replace(i,function(t,n,r,i,u){return o+=e.slice(s,u).replace(F,function(e){return"\\"+j[e]}),n&&(o+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'"),r&&(o+="'+\n((__t=("+r+"))==null?'':__t)+\n'"),i&&(o+="';\n"+i+"\n__p+='"),s=u+t.length,t}),o+="';\n",n.variable||(o="with(obj||{}){\n"+o+"}\n"),o="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+o+"return __p;\n";try{r=new Function(n.variable||"obj","_",o)}catch(u){throw u.source=o,u}if(t)return r(t,N);var a=function(e){return r.call(this,e,N)};return a.source="function("+(n.variable||"obj")+"){\n"+o+"}",a},N.chain=function(e){return N(e).chain()};var I=function(e){return this._chain?N(e).chain():e};N.mixin(N),C(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=s[e];N.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e=="shift"||e=="splice")&&n.length===0&&delete n[0],I.call(this,n)}}),C(["concat","join","slice"],function(e){var t=s[e];N.prototype[e]=function(){return I.call(this,t.apply(this._wrapped,arguments))}}),N.extend(N.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this)}),e.define("/node_modules/backbone/package.json",function(e,t,n,r,i,s,o){t.exports={main:"backbone.js"}}),e.define("/node_modules/backbone/backbone.js",function(e,t,n,r,i,s,o){(function(){var t=this,r=t.Backbone,i=[],s=i.push,o=i.slice,u=i.splice,a;typeof n!="undefined"?a=n:a=t.Backbone={},a.VERSION="0.9.10";var f=t._;!f&&typeof e!="undefined"&&(f=e("underscore")),a.$=t.jQuery||t.Zepto||t.ender,a.noConflict=function(){return t.Backbone=r,this},a.emulateHTTP=!1,a.emulateJSON=!1;var l=/\s+/,c=function(e,t,n,r){if(!n)return!0;if(typeof n=="object")for(var i in n)e[t].apply(e,[i,n[i]].concat(r));else{if(!l.test(n))return!0;var s=n.split(l);for(var o=0,u=s.length;o').hide().appendTo("body")[0].contentWindow,this.navigate(t)),this._hasPushState?a.$(window).on("popstate",this.checkUrl):this._wantsHashChange&&"onhashchange"in window&&!r?a.$(window).on("hashchange",this.checkUrl):this._wantsHashChange&&(this._checkUrlInterval=setInterval(this.checkUrl,this.interval)),this.fragment=t;var i=this.location,s=i.pathname.replace(/[^\/]$/,"$&/")===this.root;if(this._wantsHashChange&&this._wantsPushState&&!this._hasPushState&&!s)return this.fragment=this.getFragment(null,!0),this.location.replace(this.root+this.location.search+"#"+this.fragment),!0;this._wantsPushState&&this._hasPushState&&s&&i.hash&&(this.fragment=this.getHash().replace(T,""),this.history.replaceState({},document.title,this.root+this.fragment+i.search));if(!this.options.silent)return this.loadUrl()},stop:function(){a.$(window).off("popstate",this.checkUrl).off("hashchange",this.checkUrl),clearInterval(this._checkUrlInterval),x.started=!1},route:function(e,t){this.handlers.unshift({route:e,callback:t})},checkUrl:function(e){var t=this.getFragment();t===this.fragment&&this.iframe&&(t=this.getFragment(this.getHash(this.iframe)));if(t===this.fragment)return!1;this.iframe&&this.navigate(t),this.loadUrl()||this.loadUrl(this.getHash())},loadUrl:function(e){var t=this.fragment=this.getFragment(e),n=f.any(this.handlers,function(e){if(e.route.test(t))return e.callback(t),!0});return n},navigate:function(e,t){if(!x.started)return!1;if(!t||t===!0)t={trigger:t};e=this.getFragment(e||"");if(this.fragment===e)return;this.fragment=e;var n=this.root+e;if(this._hasPushState)this.history[t.replace?"replaceState":"pushState"]({},document.title,n);else{if(!this._wantsHashChange)return this.location.assign(n);this._updateHash(this.location,e,t.replace),this.iframe&&e!==this.getFragment(this.getHash(this.iframe))&&(t.replace||this.iframe.document.open().close(),this._updateHash(this.iframe.location,e,t.replace))}t.trigger&&this.loadUrl(e)},_updateHash:function(e,t,n){if(n){var r=e.href.replace(/(javascript:|#).*$/,"");e.replace(r+"#"+t)}else e.hash="#"+t}}),a.history=new x;var L=a.View=function(e){this.cid=f.uniqueId("view"),this._configure(e||{}),this._ensureElement(),this.initialize.apply(this,arguments),this.delegateEvents()},A=/^(\S+)\s*(.*)$/,O=["model","collection","el","id","attributes","className","tagName","events"];f.extend(L.prototype,p,{tagName:"div",$:function(e){return this.$el.find(e)},initialize:function(){},render:function(){return this},remove:function(){return this.$el.remove(),this.stopListening(),this},setElement:function(e,t){return this.$el&&this.undelegateEvents(),this.$el=e instanceof a.$?e:a.$(e),this.el=this.$el[0],t!==!1&&this.delegateEvents(),this},delegateEvents:function(e){if(!e&&!(e=f.result(this,"events")))return;this.undelegateEvents();for(var t in e){var n=e[t];f.isFunction(n)||(n=this[e[t]]);if(!n)throw new Error('Method "'+e[t]+'" does not exist');var r=t.match(A),i=r[1],s=r[2];n=f.bind(n,this),i+=".delegateEvents"+this.cid,s===""?this.$el.on(i,n):this.$el.on(i,s,n)}},undelegateEvents:function(){this.$el.off(".delegateEvents"+this.cid)},_configure:function(e){this.options&&(e=f.extend({},f.result(this,"options"),e)),f.extend(this,f.pick(e,O)),this.options=e},_ensureElement:function(){if(!this.el){var e=f.extend({},f.result(this,"attributes"));this.id&&(e.id=f.result(this,"id")),this.className&&(e["class"]=f.result(this,"className"));var t=a.$("<"+f.result(this,"tagName")+">").attr(e);this.setElement(t,!1)}else this.setElement(f.result(this,"el"),!1)}});var M={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};a.sync=function(e,t,n){var r=M[e];f.defaults(n||(n={}),{emulateHTTP:a.emulateHTTP,emulateJSON:a.emulateJSON});var i={type:r,dataType:"json"};n.url||(i.url=f.result(t,"url")||D()),n.data==null&&t&&(e==="create"||e==="update"||e==="patch")&&(i.contentType="application/json",i.data=JSON.stringify(n.attrs||t.toJSON(n))),n.emulateJSON&&(i.contentType="application/x-www-form-urlencoded",i.data=i.data?{model:i.data}:{});if(n.emulateHTTP&&(r==="PUT"||r==="DELETE"||r==="PATCH")){i.type="POST",n.emulateJSON&&(i.data._method=r);var s=n.beforeSend;n.beforeSend=function(e){e.setRequestHeader("X-HTTP-Method-Override",r);if(s)return s.apply(this,arguments)}}i.type!=="GET"&&!n.emulateJSON&&(i.processData=!1);var o=n.success;n.success=function(e){o&&o(t,e,n),t.trigger("sync",t,e,n)};var u=n.error;n.error=function(e){u&&u(t,e,n),t.trigger("error",t,e,n)};var l=n.xhr=a.ajax(f.extend(i,n));return t.trigger("request",t,l,n),l},a.ajax=function(){return a.$.ajax.apply(a.$,arguments)};var _=function(e,t){var n=this,r;e&&f.has(e,"constructor")?r=e.constructor:r=function(){return n.apply(this,arguments)},f.extend(r,n,t);var i=function(){this.constructor=r};return i.prototype=n.prototype,r.prototype=new i,e&&f.extend(r.prototype,e),r.__super__=n.prototype,r};d.extend=v.extend=y.extend=L.extend=x.extend=_;var D=function(){throw new Error('A "url" property or function must be specified')}}).call(this)}),e.define("/src/js/util/constants.js",function(e,t,n,r,i,s,o){var u={betweenCommandsDelay:400},a={isAnimating:!1},f={minZoom:.55,maxZoom:1.25,minWidth:600,minHeight:600},l={arrowHeadSize:8,nodeRadius:17,curveControlPointOffset:50,defaultEasing:"easeInOut",defaultAnimationTime:400,rectFill:"hsb(0.8816909813322127,0.7,1)",headRectFill:"#2831FF",rectStroke:"#FFF",rectStrokeWidth:"3",originDash:"- ",multiBranchY:20,upstreamHeadOpacity:.5,upstreamNoneOpacity:.2,edgeUpstreamHeadOpacity:.4,edgeUpstreamNoneOpacity:.15,visBranchStrokeWidth:2,visBranchStrokeColorNone:"#333",defaultNodeFill:"hsba(0.5,0.8,0.7,1)",defaultNodeStrokeWidth:2,defaultNodeStroke:"#FFF",orphanNodeFill:"hsb(0.5,0.8,0.7)"};n.GLOBAL=a,n.TIME=u,n.GRAPHICS=l,n.VIEWPORT=f}),e.define("/src/js/util/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util/constants");n.parseQueryString=function(e){var t={};return e.replace(new RegExp("([^?=&]+)(=([^&]*))?","g"),function(e,n,r,i){t[n]=i}),t},n.isBrowser=function(){var e=String(typeof window)!=="undefined";return e},n.splitTextCommand=function(e,t,n){t=u.bind(t,n),u.each(e.split(";"),function(e,n){e=u.escape(e),e=e.replace(/^(\s+)/,"").replace(/(\s+)$/,"").replace(/"/g,'"').replace(/'/g,"'");if(n>0&&!e.length)return;t(e)})},n.genParseCommand=function(e,t){return function(n){var r,i;return u.each(e,function(e,t){var s=e.exec(n);s&&(r=t,i=s)}),r?{toSet:{eventName:t,method:r,regexResults:i}}:!1}}}),e.define("/src/js/level/sandbox.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../intl"),h=e("../app"),p=e("../util/errors"),d=e("../visuals/visualization").Visualization,v=e("../level/parseWaterfall").ParseWaterfall,m=e("../level/disabledMap").DisabledMap,g=e("../models/commandModel").Command,y=e("../git/gitShim").GitShim,b=e("../views"),w=b.ModalTerminal,E=b.ModalAlert,S=e("../views/builderViews"),x=e("../views/multiView").MultiView,T=f.View.extend({tagName:"div",initialize:function(e){e=e||{},this.options=e,this.initVisualization(e),this.initCommandCollection(e),this.initParseWaterfall(e),this.initGitShim(e),this.initUndoStack(e),e.wait||this.takeControl()},getDefaultVisEl:function(){return $("#mainVisSpace")[0]},getAnimationTime:function(){return 1050},initVisualization:function(e){this.mainVis=new d({el:e.el||this.getDefaultVisEl()})},initUndoStack:function(e){this.undoStack=[]},initCommandCollection:function(e){this.commandCollection=h.getCommandUI().commandCollection},initParseWaterfall:function(e){this.parseWaterfall=new v},initGitShim:function(e){this.gitShim=new y({beforeCB:u.bind(this.beforeCommandCB,this)})},takeControl:function(){h.getEventBaton().stealBaton("commandSubmitted",this.commandSubmitted,this),h.getEventBaton().stealBaton("processSandboxCommand",this.processSandboxCommand,this),h.getEventBaton().stealBaton("levelExited",this.levelExited,this),this.insertGitShim()},releaseControl:function(){h.getEventBaton().releaseBaton("commandSubmitted",this.commandSubmitted,this),h.getEventBaton().releaseBaton("processSandboxCommand",this.processSandboxCommand,this),h.getEventBaton().releaseBaton("levelExited",this.levelExited,this),this.releaseGitShim()},releaseGitShim:function(){this.gitShim&&this.gitShim.removeShim()},insertGitShim:function(){this.gitShim&&this.mainVis.customEvents.on("gitEngineReady",function(){this.gitShim.insertShim()},this)},beforeCommandCB:function(e){this.pushUndo()},pushUndo:function(){this.undoStack.push(this.mainVis.gitEngine.printTree())},undo:function(e,t){var n=this.undoStack.pop();if(!n){e.set("error",new p.GitError({msg:c.str("undo-stack-empty")})),t.resolve();return}this.mainVis.reset(n),setTimeout(function(){e.finishWith(t)},this.mainVis.getAnimationTime())},commandSubmitted:function(e){h.getEvents().trigger("commandSubmittedPassive",e),l.splitTextCommand(e,function(e){this.commandCollection.add(new g({rawStr:e,parseWaterfall:this.parseWaterfall}))},this)},startLevel:function(t,n){var r=t.get("regexResults")||[],i=r[1]||"",s=h.getLevelArbiter().getLevel(i);if(!s){t.addWarning(c.str("level-no-id",{id:i})),h.getEventBaton().trigger("commandSubmitted","levels"),t.set("status","error"),n.resolve();return}this.hide(),this.clear();var o=a.defer(),u=e("../level").Level;this.currentLevel=new u({level:s,deferred:o,command:t}),o.promise.then(function(){t.finishWith(n)})},buildLevel:function(t,n){this.hide(),this.clear();var r=a.defer(),i=e("../level/builder").LevelBuilder;this.levelBuilder=new i({deferred:r}),r.promise.then(function(){t.finishWith(n)})},exitLevel:function(e,t){e.addWarning(c.str("level-cant-exit")),e.set("status","error"),t.resolve()},showLevels:function(e,t){var n=a.defer();h.getLevelDropdown().show(n,e),n.promise.done(function(){e.finishWith(t)})},resetSolved:function(e,t){h.getLevelArbiter().resetSolvedMap(),e.addWarning(c.str("solved-map-reset")),e.finishWith(t)},processSandboxCommand:function(e,t){var n={"reset solved":this.resetSolved,undo:this.undo,"help general":this.helpDialog,help:this.helpDialog,reset:this.reset,delay:this.delay,clear:this.clear,"exit level":this.exitLevel,level:this.startLevel,sandbox:this.exitLevel,levels:this.showLevels,mobileAlert:this.mobileAlert,"build level":this.buildLevel,"export tree":this.exportTree,"import tree":this.importTree,"import level":this.importLevel},r=n[e.get("method")];if(!r)throw new Error("no method for that wut");r.apply(this,[e,t])},hide:function(){this.mainVis.hide()},levelExited:function(){this.show()},show:function(){this.mainVis.show()},importTree:function(e,t){var n=new S.MarkdownPresenter({previewText:c.str("paste-json"),fillerText:" "});n.deferred.promise.then(u.bind(function(e){try{this.mainVis.gitEngine.loadTree(JSON.parse(e))}catch(t){this.mainVis.reset(),new x({childViews:[{type:"ModalAlert",options:{markdowns:["## Error!","","Something is wrong with that JSON! Here is the error:","",String(t)]}}]})}},this)).fail(function(){}).done(function(){e.finishWith(t)})},importLevel:function(t,n){var r=new S.MarkdownPresenter({previewText:c.str("paste-json"),fillerText:" "});r.deferred.promise.then(u.bind(function(r){var i=e("../level").Level;try{var s=JSON.parse(r),o=a.defer();this.currentLevel=new i({level:s,deferred:o,command:t}),this.hide(),o.promise.then(function(){t.finishWith(n)})}catch(u){new x({childViews:[{type:"ModalAlert",options:{markdowns:["## Error!","","Something is wrong with that level JSON, this happened:","",String(u)]}}]}),t.finishWith(n)}},this)).fail(function(){t.finishWith(n)}).done()},exportTree:function(e,t){var n=JSON.stringify(this.mainVis.gitEngine.exportTree(),null,2),r=new x({childViews:[{type:"MarkdownPresenter",options:{previewText:c.str("share-tree"),fillerText:n,noConfirmCancel:!0}}]});r.getPromise().then(function(){e.finishWith(t)}).done()},clear:function(e,t){h.getEvents().trigger("clearOldCommands"),e&&t&&e.finishWith(t)},mobileAlert:function(e,t){alert(c.str("mobile-alert")),e.finishWith(t)},delay:function(e,t){var n=parseInt(e.get("regexResults")[1],10);setTimeout(function(){e.finishWith(t)},n)},reset:function(e,t){this.mainVis.reset(),this.initUndoStack(),setTimeout(function(){e.finishWith(t)},this.mainVis.getAnimationTime())},helpDialog:function(t,n){var r=new x({childViews:c.getDialog(e("../dialogs/sandbox"))});r.getPromise().then(u.bind(function(){t.finishWith(n)},this)).done()}});n.Sandbox=T}),e.define("/node_modules/q/package.json",function(e,t,n,r,i,s,o){t.exports={main:"q.js"}}),e.define("/node_modules/q/q.js",function(e,t,n,r,i,s,o){(function(e){if(typeof bootstrap=="function")bootstrap("promise",e);else if(typeof n=="object")e(void 0,n);else if(typeof define=="function")define(e);else if(typeof ses!="undefined"){if(!ses.ok())return;ses.makeQ=function(){var t={};return e(void 0,t)}}else e(void 0,Q={})})(function(e,t){"use strict";function w(e){return b(e)==="[object StopIteration]"||e instanceof E}function x(e,t){t.stack&&typeof e=="object"&&e!==null&&e.stack&&e.stack.indexOf(S)===-1&&(e.stack=T(e.stack)+"\n"+S+"\n"+T(t.stack))}function T(e){var t=e.split("\n"),n=[];for(var r=0;r=n&&s<=Ct}function k(){if(Error.captureStackTrace){var e,t,n=Error.prepareStackTrace;return Error.prepareStackTrace=function(n,r){e=r[1].getFileName(),t=r[1].getLineNumber()},(new Error).stack,Error.prepareStackTrace=n,r=e,t}}function L(e,t,n){return function(){return typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t+" is deprecated, use "+n+" instead.",(new Error("")).stack),e.apply(e,arguments)}}function A(){function s(r){if(!e)return;n=z(r),d(e,function(e,t){u(function(){n.promiseSend.apply(n,t)})},void 0),e=void 0,t=void 0}var e=[],t=[],n,r=g(A.prototype),i=g(M.prototype);return i.promiseSend=function(r,i,s,o){var a=p(arguments);e?(e.push(a),r==="when"&&o&&t.push(o)):u(function(){n.promiseSend.apply(n,a)})},i.valueOf=function(){return e?i:n.valueOf()},Error.captureStackTrace&&(Error.captureStackTrace(i,A),i.stack=i.stack.substring(i.stack.indexOf("\n")+1)),o(i),r.promise=i,r.resolve=s,r.reject=function(e){s(U(e))},r.notify=function(n){e&&d(t,function(e,t){u(function(){t(n)})},void 0)},r}function O(e){var t=A();return ot(e,t.resolve,t.reject,t.notify).fail(t.reject),t.promise}function M(e,t,n,r){t===void 0&&(t=function(e){return U(new Error("Promise does not support operation: "+e))});var i=g(M.prototype);return i.promiseSend=function(n,r){var s=p(arguments,2),o;try{e[n]?o=e[n].apply(i,s):o=t.apply(i,[n].concat(s))}catch(u){o=U(u)}r&&r(o)},n&&(i.valueOf=n),r&&(i.exception=r),o(i),i}function _(e){return D(e)?e.valueOf():e}function D(e){return e&&typeof e.promiseSend=="function"}function P(e){return e&&typeof e.then=="function"}function H(e){return B(e)||j(e)}function B(e){return!P(_(e))}function j(e){return e=_(e),D(e)&&"exception"in e}function R(){!q&&typeof window!="undefined"&&!window.Touch&&window.console&&console.log("Should be empty:",I),q=!0}function U(e){var t=M({when:function(t){if(t){var n=v(F,this);n!==-1&&(I.splice(n,1),F.splice(n,1))}return t?t(e):U(e)}},function(){return U(e)},function n(){return this},e);return R(),F.push(t),I.push(e),t}function z(e){if(D(e))return e;e=_(e);if(P(e)){var t=A();return e.then(t.resolve,t.reject,t.notify),t.promise}return M({when:function(){return e},get:function(t){return e[t]},put:function(t,n){return e[t]=n,e},del:function(t){return delete e[t],e},post:function(t,n){return e[t].apply(e,n)},apply:function(t,n){return e.apply(t,n)},fapply:function(t){return e.apply(void 0,t)},viewInfo:function(){function r(e){n[e]||(n[e]=typeof t[e])}var t=e,n={};while(t)Object.getOwnPropertyNames(t).forEach(r),t=Object.getPrototypeOf(t);return{type:typeof e,properties:n}},keys:function(){return y(e)}},void 0,function n(){return e})}function W(e){return M({isDef:function(){}},function(){var n=p(arguments);return Z.apply(void 0,[e].concat(n))},function(){return _(e)})}function X(e,t){return e=z(e),t?M({viewInfo:function(){return t}},function(){var n=p(arguments);return Z.apply(void 0,[e].concat(n))},function(){return _(e)}):Z(e,"viewInfo")}function V(e){return X(e).when(function(t){var n;t.type==="function"?n=function(){return rt(e,void 0,arguments)}:n={};var r=t.properties||{};return y(r).forEach(function(t){r[t]==="function"&&(n[t]=function(){return nt(e,t,arguments)})}),z(n)})}function $(e,t,n,r){function o(e){try{return typeof t=="function"?t(e):e}catch(n){return U(n)}}function a(e){if(typeof n=="function"){x(e,l);try{return n(e)}catch(t){return U(t)}}return U(e)}function f(e){return typeof r=="function"?r(e):e}var i=A(),s=!1,l=z(e);return u(function(){l.promiseSend("when",function(e){if(s)return;s=!0,i.resolve(o(e))},function(e){if(s)return;s=!0,i.resolve(a(e))})}),l.promiseSend("when",void 0,void 0,function(e){i.notify(f(e))}),i.promise}function J(e,t,n){return $(e,function(e){return ft(e).then(function(e){return t.apply(void 0,e)},n)},n)}function K(e){return function(){function t(e,t){var s;try{s=n[e](t)}catch(o){return w(o)?o.value:U(o)}return $(s,r,i)}var n=e.apply(this,arguments),r=t.bind(t,"send"),i=t.bind(t,"throw");return r()}}function Q(e){throw new E(e)}function G(e){return function(){return ft([this,ft(arguments)]).spread(function(t,n){return e.apply(t,n)})}}function Y(e){return function(t){var n=p(arguments,1);return Z.apply(void 0,[t,e].concat(n))}}function Z(e,t){var n=A(),r=p(arguments,2);return e=z(e),u(function(){e.promiseSend.apply(e,[t,n.resolve].concat(r))}),n.promise}function et(e,t,n){var r=A();return e=z(e),u(function(){e.promiseSend.apply(e,[t,r.resolve].concat(n))}),r.promise}function tt(e){return function(t){var n=p(arguments,1);return et(t,e,n)}}function st(e,t){var n=p(arguments,2);return rt(e,t,n)}function ot(e){var t=p(arguments,1);return it(e,t)}function ut(e,t){var n=p(arguments,2);return function(){var i=n.concat(p(arguments));return rt(e,t,i)}}function at(e){var t=p(arguments,1);return function(){var r=t.concat(p(arguments));return it(e,r)}}function ft(e){return $(e,function(e){var t=e.length;if(t===0)return z(e);var n=A();return d(e,function(r,i,s){B(i)?(e[s]=_(i),--t===0&&n.resolve(e)):$(i,function(r){e[s]=r,--t===0&&n.resolve(e)}).fail(n.reject)},void 0),n.promise})}function lt(e){return $(e,function(e){return $(ft(m(e,function(e){return $(e,i,i)})),function(){return m(e,z)})})}function ct(e,t){return $(e,void 0,t)}function ht(e,t){return $(e,void 0,void 0,t)}function pt(e,t){return $(e,function(e){return $(t(),function(){return e})},function(e){return $(t(),function(){return U(e)})})}function dt(e,n,r,i){function s(n){u(function(){x(n,e);if(!t.onerror)throw n;t.onerror(n)})}var o=n||r||i?$(e,n,r,i):e;ct(o,s)}function vt(e,t){var n=A(),r=setTimeout(function(){n.reject(new Error("Timed out after "+t+" ms"))},t);return $(e,function(e){clearTimeout(r),n.resolve(e)},function(e){clearTimeout(r),n.reject(e)}),n.promise}function mt(e,t){t===void 0&&(t=e,e=void 0);var n=A();return setTimeout(function(){n.resolve(e)},t),n.promise}function gt(e,t){var n=p(t),r=A();return n.push(r.makeNodeResolver()),it(e,n).fail(r.reject),r.promise}function yt(e){var t=p(arguments,1),n=A();return t.push(n.makeNodeResolver()),it(e,t).fail(n.reject),n.promise}function bt(e){var t=p(arguments,1);return function(){var n=t.concat(p(arguments)),r=A();return n.push(r.makeNodeResolver()),it(e,n).fail(r.reject),r.promise}}function wt(e,t,n){return St(e,t).apply(void 0,n)}function Et(e,t){var n=p(arguments,2);return wt(e,t,n)}function St(e){if(arguments.length>1){var t=arguments[1],n=p(arguments,2),r=e;e=function(){var e=n.concat(p(arguments));return r.apply(t,e)}}return function(){var t=A(),n=p(arguments);return n.push(t.makeNodeResolver()),it(e,n).fail(t.reject),t.promise}}function xt(e,t,n){var r=p(n),i=A();return r.push(i.makeNodeResolver()),nt(e,t,r).fail(i.reject),i.promise}function Tt(e,t){var n=p(arguments,2),r=A();return n.push(r.makeNodeResolver()),nt(e,t,n).fail(r.reject),r.promise}function Nt(e,t){if(!t)return e;e.then(function(e){u(function(){t(null,e)})},function(e){u(function(){t(e)})})}var n=k(),r,i=function(){},o=Object.freeze||i;typeof cajaVM!="undefined"&&(o=cajaVM.def);var u;if(typeof s!="undefined")u=s.nextTick;else if(typeof setImmediate=="function")u=setImmediate;else if(typeof MessageChannel!="undefined"){var a=new MessageChannel,f={},l=f;a.port1.onmessage=function(){f=f.next;var e=f.task;delete f.task,e()},u=function(e){l=l.next={task:e},a.port2.postMessage(0)}}else u=function(e){setTimeout(e,0)};var c;if(Function.prototype.bind){var h=Function.prototype.bind;c=h.bind(h.call)}else c=function(e){return function(){return e.call.apply(e,arguments)}};var p=c(Array.prototype.slice),d=c(Array.prototype.reduce||function(e,t){var n=0,r=this.length;if(arguments.length===1)do{if(n in this){t=this[n++];break}if(++n>=r)throw new TypeError}while(1);for(;n2?e.resolve(p(arguments,1)):e.resolve(n)}},A.prototype.node=L(A.prototype.makeNodeResolver,"node","makeNodeResolver"),t.promise=O,t.makePromise=M,M.prototype.then=function(e,t,n){return $(this,e,t,n)},M.prototype.thenResolve=function(e){return $(this,function(){return e})},d(["isResolved","isFulfilled","isRejected","when","spread","send","get","put","del","post","invoke","keys","apply","call","bind","fapply","fcall","fbind","all","allResolved","view","viewInfo","timeout","delay","catch","finally","fail","fin","progress","end","done","nfcall","nfapply","nfbind","ncall","napply","nbind","npost","ninvoke","nend","nodeify"],function(e,n){M.prototype[n]=function(){return t[n].apply(t,[this].concat(p(arguments)))}},void 0),M.prototype.toSource=function(){return this.toString()},M.prototype.toString=function(){return"[object Promise]"},o(M.prototype),t.nearer=_,t.isPromise=D,t.isPromiseAlike=P,t.isResolved=H,t.isFulfilled=B,t.isRejected=j;var F=[],I=[],q;t.reject=U,t.begin=z,t.resolve=z,t.ref=L(z,"ref","resolve"),t.master=W,t.viewInfo=X,t.view=V,t.when=$,t.spread=J,t.async=K,t["return"]=Q,t.promised=G,t.sender=L(Y,"sender","dispatcher"),t.Method=L(Y,"Method","dispatcher"),t.send=L(Z,"send","dispatch"),t.dispatch=et,t.dispatcher=tt,t.get=tt("get"),t.put=tt("put"),t["delete"]=t.del=tt("del");var nt=t.post=tt("post");t.invoke=function(e,t){var n=p(arguments,2);return nt(e,t,n)};var rt=t.apply=L(tt("apply"),"apply","fapply"),it=t.fapply=tt("fapply");t.call=L(st,"call","fcall"),t["try"]=ot,t.fcall=ot,t.bind=L(ut,"bind","fbind"),t.fbind=at,t.keys=tt("keys"),t.all=ft,t.allResolved=lt,t["catch"]=t.fail=ct,t.progress=ht,t["finally"]=t.fin=pt,t.end=L(dt,"end","done"),t.done=dt,t.timeout=vt,t.delay=mt,t.nfapply=gt,t.nfcall=yt,t.nfbind=bt,t.napply=L(wt,"napply","npost"),t.ncall=L(Et,"ncall","ninvoke"),t.nbind=L(St,"nbind","nfbind"),t.npost=xt,t.ninvoke=Tt,t.nend=L(Nt,"nend","nodeify"),t.nodeify=Nt;var Ct=k()})}),e.define("/src/js/intl/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util/constants"),f=e("../util"),l=e("../intl/strings").strings,c=n.getDefaultLocale=function(){return"en_US"},h=n.getLocale=function(){return a.GLOBAL.locale?a.GLOBAL.locale:c()},p=u.clone(u.templateSettings);p.interpolate=/\{(.+?)\}/g;var d=n.template=function(e,t){return u.template(e,t,p)},v=n.str=function(e,t){t=t||{};var n=h();return l[e]?l[e][n]?d(l[e][n],t):e!=="error-untranslated"?v("error-untranslated"):'No translation for the key "'+e+'"':(console.warn("NO INTL support for key "+e),"NO INTL support for key "+e)},m=n.getIntlKey=function(e,t){if(!e||!e[t])throw new Error("that key "+t+"doesnt exist in this blob"+e);return e[t][c()]||console.warn("WARNING!! This blob does not have intl support:",e,"for this key",t),e[t][h()]},g=n.getDialog=function(e){var t=c();return m(e,"dialog")||e.dialog[t]},y=n.getHint=function(e){return m(e,"hint")||v("error-untranslated")},b=n.getName=function(e){return m(e,"name")||v("error-untranslated")},w=n.getStartDialog=function(e){var t=m(e,"startDialog");if(t)return t;var n={type:"ModalAlert",options:{markdown:v("error-untranslated")}},r=u.clone(e.startDialog[c()]||e.startDialog);return r.childViews.unshift(n),r}}),e.define("/src/js/intl/strings.js",function(e,t,n,r,i,s,o){n.strings={"finish-dialog-finished":{__desc__:"One of the lines in the next level dialog",ja:"最後のレベルをクリアしました!すごい!!",en_US:"Wow! You finished the last level, great!",zh_CN:"我的个天!你完成了最后一关,碉堡了!",fr_FR:"Félicitations, vous avez réussi le dernier niveau !"},"finish-dialog-next":{__desc__:"One of the lines in the next level dialog",en_US:'Would you like to move on to *"{nextLevel}"*, the next level?',ja:'次の章 *"{nextLevel}"* へ進みますか?',zh_CN:"要不前进到下一关 *“{nextLevel}”*?",fr_FR:'Voulez-vous passer à *"{nextLevel}"*, le prochain niveau ?'},"finish-dialog-win":{__desc__:"One of the lines in the next level dialog",en_US:"Awesome! You matched or exceeded our solution.",ja:"素晴らしい!このレベルをクリアしましたね。",zh_CN:"牛鼻啊!你达到或者完爆了我们的答案。",fr_FR:"Fabuleux ! Votre solution a égalé ou surpassé notre solution."},"finish-dialog-lose":{__desc__:"When the user entered more commands than our best, encourage them to do better",en_US:"See if you can whittle it down to {best} :D",ja:"模範解答の回数={best}回でクリアする方法も考えてみましょう :D",zh_CN:"试试看你能否在 {best} 之内搞定 :D",fr_FR:"Voyons si vous pouvez descendre à {best} :D"},"git-status-detached":{__desc__:"One of the lines for git status output",en_US:"Detached head!",zh_CN:"脑袋搬家(Detached head)了!",fr_FR:"head détaché !"},"git-status-onbranch":{__desc__:"One of the lines for git status output",en_US:"On branch {branch}",zh_CN:"切换到分支 {branch}",fr_FR:"Sur la branche {branch}"},"git-status-readytocommit":{__desc__:"One of the lines for git status output",en_US:"Ready to commit! (as always in this demo)",zh_CN:"可以提交啦!(这演示里一直可以提交)",fr_FR:"Prêt à commit ! (comme toujours dans cette démo)"},"git-dummy-msg":{__desc__:"The dummy commit message for all commits. Feel free to put in a shoutout to your school / city / whatever!",en_US:"Quick commit. Go Bears!",zh_CN:"快速提交。上啊月熊!",fr_FR:"Commit rapide. NoMaN Sux!"},"git-error-origin-fetch-uptodate":{__desc__:"One of the error messages for git",en_US:"Already up to date!",fr_FR:"Déjà à jour"},"git-error-origin-fetch-no-ff":{__desc__:"One of the error messages for git",en_US:"Your origin branch is out of sync with the remote branch and fetch cannot be performed. try using --force",fr_FR:"Votre branche origin n'est plus synchronisée avec la branche distante et fetch ne peut pas être appliqué. Essayez avec l'option --force"},"git-error-origin-push-no-ff":{__desc__:"One of the error messages for git",en_US:"The remote repository has diverged from your local repository, so uploading your changes is not a simple fast forward (and thus your push was rejected). Please pull down the new changes in the remote repository, incorporate them into this branch, and try again. You can do so with git pull or git pull --rebase",fr_FR:"Le dépôt distant a divergé de votre référentiel local, donc l'envoi de vos modifications n'est pas en simple avance rapide (et donc votre envoi a été rejeté). Veuillez récupérer les nouveaux changements depuis le dépôt distant, les intégrer dans cette branche, et essayez à nouveau. Vous pouvez le faire avec git pull ou git pull --rebase"},"git-error-remote-branch":{__desc__:"One of the error messages for git",en_US:"You cannot execute that command on a remote branch",fr_FR:"Vous ne pouvez exécuter cette commande sur une branche distante"},"git-error-origin-required":{__desc__:"One of the error messages for git",en_US:"An origin is required for that command",fr_FR:"Une origine est requise pour cette commande"},"git-error-origin-exists":{__desc__:"One of the error messages for git",en_US:"An origin already exists! You cannot make a new one",fr_FR:"Une origine existe déjà ! Vous ne pouvez pas en créer une nouvelle"},"git-error-branch":{__desc__:"One of the error messages for git",en_US:"You can't delete the master branch, the branch you are on, or things that aren't branches",zh_CN:"你不能删除主分支(master),或者你当前所在的分支,或者其他不是分支也不知道能不能吃的东西。",fr_FR:"Vous ne pouvez supprimer la branche master, la branche sur laquelle vous êtes, ou ce qui n'est pas une branche"},"git-merge-msg":{__desc__:"The commit message for a merge commit",en_US:"Merge {target} into {current}",zh_CN:"合并 {target} 到 {current}",fr_FR:"Merge de {target} dans {current}"},"git-error-rebase-none":{__desc__:"One of the error messages for git",en_US:"No commits to rebase! Everything is a merge commit or changes already applied",zh_CN:"没有需要 rebase 的提交!都是个合并提交,或者已经 rebase 过了。",fr_FR:"Aucune commit à rebaser ! Tout est soit un commit de merge, soit des modifications déjà appliquées"},"git-result-nothing":{__desc__:"The message that explains the result of a git command",en_US:"Nothing to do...",zh_CN:"没啥鸟事……",fr_FR:"Rien à effectuer…"},"git-result-fastforward":{__desc__:"The message that explains the result of a git command",en_US:"Fast forwarding...",zh_CN:"快速前进……",fr_FR:"En avance rapide…"},"git-result-uptodate":{__desc__:"The message that explains the result of a git command",en_US:"Branch already up-to-date",zh_CN:"分支已经是最新啦",fr_FR:"Branche déjà à jour"},"git-error-exist":{__desc__:"One of the error messages for git",en_US:"The ref {ref} does not exist or is unknown",zh_CN:"索引 {ref} 不存在,或者找不到。",fr_FR:"La référence {ref} n'existe pas ou est inconnue"},"git-error-relative-ref":{__desc__:"One of the error messages for git",en_US:"Commit {commit} doesnot have a {match}",zh_CN:"提交 {commit} 并没有 {match}",fr_FR:"Le commit {commit} n'a pas de correspondance {match}"},"git-warning-detached":{__desc__:"One of the warning messages for git",en_US:"Warning!! Detached HEAD state",zh_CN:"警告!脑袋搬家(Detached HEAD)状态",fr_FR:"Attention ! HEAD est détaché"},"git-warning-add":{__desc__:"One of the warning messages for git",en_US:"No need to add files in this demo",zh_CN:"此演示中不需要添加文件",fr_FR:"Aucun besoin d'ajouter des fichiers dans cette démo"},"git-error-options":{__desc__:"One of the error messages for git",en_US:"Those options you specified are incompatible or incorrect",zh_CN:"你所指定的参数不兼容或者不准确",fr_FR:"Les options que vous avez spécifiées sont incompatibles ou incorrectes"},"git-error-already-exists":{__desc__:"One of the error messages for git",en_US:"The commit {commit} already exists in your changes set, aborting!",zh_CN:"提交 {commit} 已经存在于你的改动集里,正在中止!",fr_FR:"Le commit {commit} existe déjà dans votre ensemble de modifications, opération avortée !"},"git-error-reset-detached":{__desc__:"One of the error messages for git",en_US:"Can't reset in detached head! Use checkout if you want to move",zh_CN:"不能在分离的 HEAD 里重置!用 checkout 吧",fr_FR:"On ne peut pas effectuer un reset quand head est détaché. Utilisez checkout pour déplacer"},"git-warning-hard":{__desc__:"One of the warning messages for git",en_US:"The default behavior is a --hard reset, feel free to omit that option!",zh_CN:"默认的行为是 --hard 硬重置,尽管省略掉那个选项吧!",fr_FR:"Le comportement par défaut est un --hard reset, soyez libre d'omettre cette option !"},"git-error-staging":{__desc__:"One of the error messages for git",en_US:"There is no concept of adding / staging files, so that option or command is invalid!",zh_CN:"没有添加、缓存文件的必要,所以改选项或者命令是不合法的。",fr_FR:"Il n'y a pas le concept d'ajouter / mettre en staging, donc cette option ou commande est invalide"},"git-revert-msg":{__desc__:"Message for reverting git command",en_US:"Reverting {oldCommit}: {oldMsg}",zh_CN:"撤销 {oldCommit}:{oldMsg}",fr_FR:"Revert {oldCommit}: {oldMsg}"},"git-error-args-many":{__desc__:"One of the error messages for git",en_US:"I expect at most {upper} argument(s) for {what}",zh_CN:"{what} 期望最多 {upper} 个参数",fr_FR:"J'attends au plus {upper} argument(s) pour {what}"},"git-error-args-few":{__desc__:"One of the error messages for git",en_US:"I expect at least {lower} argument(s) for {what}",zh_CN:"{what} 期望最少 {lower} 个参数",fr_FR:"J'attends au moins {upper} argument(s) pour {what}"},"git-error-no-general-args":{__desc__:"One of the error messages for git",en_US:"That command accepts no general arguments",zh_CN:"该命令不接收参数",fr_FR:"Cette commande n'accepte aucun argument général"},"copy-tree-string":{__desc__:"The prompt to copy the tree when sharing",en_US:"Copy the tree string below",zh_CN:"拷贝下面的树字符串",fr_FR:"Copiez la chaîne d'arbre ci-dessous"},"learn-git-branching":{__desc__:"The title of the app, with spaces",en_US:"Learn Git Branching",ja:"日本語版リポジトリ",ko:"Git 브랜치 배우기",zh_CN:"学习Git分支",fr_FR:"Apprenez Git Branching"},"select-a-level":{__desc__:"The prompt to select a level on the drop down view",en_US:"Select a level",zh_CN:"选择一关",fr_FR:"Choisissez un niveau"},"branch-name-short":{__desc__:"When branch names get too long, we need to truncate them. This is the warning for that",en_US:'Sorry, we need to keep branch names short for the visuals. Your branch name was truncated to 9 characters, resulting in "{branch}"',zh_CN:'抱歉,为了显示的需要,我们需要一个短些的分支名称。您使用的将被截断到9个字符,即"{branch}"',fr_FR:'Désolé, nous devons garder les noms de branches courts pour la visualisation. Votre nom de branche a été tronqué à 9 caractères, devenant "{branch}"'},"bad-branch-name":{__desc__:"When the user enters a branch name thats not ok",en_US:'That branch name "{branch}" is not allowed!',zh_CN:'不能给分支起这个名字 "{branch}"',fr_FR:'Ce nom de branche "{branch}" n\'est pas autorisé'},"option-not-supported":{__desc__:"When the user specifies an option that is not supported by our demo",en_US:'The option "{option}" is not supported!',zh_CN:'不支持选项 "{option}"',fr_FR:"L'option \"{option}\" n'est pas supportée"},"git-usage-command":{__desc__:"The line that shows how to format a git command",en_US:"git []",zh_CN:"git <命令> [<参数>]",fr_FR:"git []"},"git-supported-commands":{__desc__:"In the git help command, the header above the supported commands",en_US:"Supported commands:",zh_CN:"支持的命令有:",fr_FR:"Commandes supportées"},"git-usage":{__desc__:"In the dummy git output, the header before showing all the commands",en_US:"Usage:",zh_CN:"使用:",fr_FR:"Utilisation :"},"git-version":{__desc__:"The git version dummy output, kind of silly. PCOTTLE is my unix name but feel free to put yours instead",en_US:"Git Version PCOTTLE.1.0",zh_CN:"Git 版本 PCOTTLE.1.0",fr_FR:"Git version PCOTTLE.1.0"},"refresh-tree-command":{__desc__:"when the tree is visually refreshed",en_US:"Refreshing tree...",zh_CN:"正在刷新树结构...",fr_FR:"Actualisation de l'arbre…"},"locale-command":{__desc__:"when the locale is set to something",en_US:"Locale set to {locale}",zh_CN:"语言更改为 {locale}",fr_FR:"Langue changée à {locale}"},"locale-reset-command":{__desc__:"when the locale is reset",en_US:"Locale reset to default, which is {locale}",zh_CN:"语言重置为默认的 {locale}",fr_FR:"Langue remise par défaut, qui est {locale}"},"show-command":{__desc__:'command output title from "show"',en_US:"Please use one of the following commands for more info:",fr_FR:"Merci d'utiliser une des commandes suivantes pour obtenir plus d'info"},"show-all-commands":{__desc__:'command output title from "show commands"',en_US:"Here is a list of all the commmands available:",fr_FR:"Ci-dessous est la liste de toutes les commandes disponibles :"},"cd-command":{__desc__:"dummy command output for the command in the key",en_US:'Directory changed to "/directories/dont/matter/in/this/demo"',zh_CN:'目录切换到 "/directories/dont/matter/in/this/demo"',fr_FR:'Répertoire changé à "/directories/dont/matter/in/this/demo" (les répertoires ne servent à rien dans cette démo)'},"ls-command":{__desc__:"Dummy command output for the command in the key",en_US:"DontWorryAboutFilesInThisDemo.txt",zh_CN:"DontWorryAboutFilesInThisDemo.txt (译: 在试验里不用担心文件.txt)",fr_FR:"DontWorryAboutFilesInThisDemo.txt (ne vous préoccupez pas des noms de fichier dans cette démo)"},"mobile-alert":{__desc__:"When someone comes to the site on a mobile device, they can not input commands so this is a nasty alert to tell them",en_US:"Can't bring up the keyboard on mobile / tablet :( try visiting on desktop! :D",zh_CN:"无法在移动设备/平板上调出键盘 :( 请试试桌面版 :D",fr_FR:"Impossible de faire apparaître le clavier sur mobile / tablette :( Essayez de passer sur un ordinateur de bureau :D"},"share-tree":{__desc__:"When you export a tree, we want you to share the tree with friends",en_US:'Share this tree with friends! They can load it with "import tree"',zh_CN:'与你的好友分享提交树!他们可以用 "import tree" 加载它',fr_FR:'Partagez cet arbre avec vos amis ! Ils peuvent le charger avec "import tree"'},"paste-json":{__desc__:"When you are importing a level or tree",en_US:"Paste a JSON blob below!",zh_CN:"在下边粘贴一个JSON串",fr_FR:"Collez un blob JSON ci-dessous !"},"solved-map-reset":{__desc__:"When you reset the solved map to clear your solved history, in case someone else wants to use your browser",en_US:"Solved map was reset, you are starting from a clean slate!",zh_CN:"解决列表已重置,您现在从零开始了",fr_FR:"La carte des niveaux résolus a été effacée, vous repartez de zéro !"},"level-cant-exit":{__desc__:"When the user tries to exit a level when they are not in one",en_US:'You are not in a level! You are in a sandbox, start a level with "levels"',zh_CN:'您没在关卡中!您在沙盒中,要开始关卡请输入 "levels"',fr_FR:'Vous n\'êtes pas dans un niveau ! Vous êtes dans le mode bac à sable, commencez un niveau avec "levels"'},"level-no-id":{__desc__:"When you say an id but that level doesnt exist",en_US:'A level for that id "{id}" was not found! Opening up a level selection view',zh_CN:'没找到id为 "{id}" 的关卡!打开关卡选择框',fr_FR:"Le niveau dont l'identifiant est {id} n'a pas été trouvé ! Ouverture de la vue de sélection des niveaux"},"undo-stack-empty":{__desc__:"The undo command can only undo back until the last time the level was reset or the beginning of the level",en_US:"The undo stack is empty!",zh_CN:"还没有什么可以撤销",fr_FR:"La pile d'annulation est vide !"},"already-solved":{__desc__:"When you play in a level that is already solved",en_US:'You have already solved this level, try other levels with "levels" or go back to sandbox with "sandbox"',zh_CN:'你已经解决了本关,输入 "levels" 尝试其他关卡,或者输入 "sandbox" 回到沙盒中',fr_FR:'Vous avez déjà résolu ce niveau, essayez d\'autres niveaux avec "levels" ou revenez au bac à sable avec "sandbox"'},"command-disabled":{__desc__:"When you try a command that is disabled",en_US:"That git command is disabled for this level!",zh_CN:"该命令在本关不允许使用!",fr_FR:"Cette commande git est désactivée pour ce niveau !"},"share-json":{__desc__:"when you have made the level, prompt to share this",en_US:"Here is the JSON for this level! Share it with somenoe or send it to me on Github",zh_CN:"这是一个关卡定义JSON!您可以分享它或者发到我的GitHub上",fr_FR:"Voici le JSON pour ce niveau ! Partagez-le avec quelqu'un ou envoyez-le moi sur Github"},"want-start-dialog":{__desc__:"prompt to add a start dialog",en_US:"You have not specified a start dialog, would you like to add one?",zh_CN:"您还没有定义一开始的介绍,是否添加一个?",fr_FR:"Vous n'avez pas spécifié de dialogue de départ, voulez-vous en ajouter un ?"},"want-hint":{__desc__:"prompt to add a hint",en_US:"You have not specified a hint, would you like to add one?",zh_CN:"您还没有定义提示,是否添加一个?",fr_FR:"Vous n'avez pas spécifié d'indice, voulez-vous en ajouter un ?"},"prompt-hint":{__desc__:"prompt for hint",en_US:"Enter the hint for this level, or leave this blank if you do not want to include one",zh_CN:"请输入关卡提示,或者故意留空",fr_FR:"Entrez l'indice pour ce niveau, ou laissez-le vide pour ne pas l'inclure"},"prompt-name":{__desc__:"prompt for level name",en_US:"Enter the name for the level",zh_CN:"输入关卡名",fr_FR:"Entrez le nom pour ce niveau"},"solution-empty":{__desc__:"If you define a solution without any commands, aka a level that is solved without doing anything",en_US:"Your solution is empty!! Something is amiss",zh_CN:"你的解法是空的!! 这应该是出错了",fr_FR:"Votre solution est vide !! Quelque chose ne tourne pas rond"},"define-start-warning":{__desc__:"When you define the start point again, it overwrites the solution and goal so we add a warning",en_US:"Defining start point... solution and goal will be overwritten if they were defined earlier",zh_CN:"定义开始点... 解决方法和目标会被新的替代",fr_FR:"Redéfinition du point de départ… la solution et la cible seront écrasés s'ils ont déjà été définis"},"help-vague-level":{__desc__:"When you are in a level and you say help, its vague and you need to specify",en_US:'You are in a level, so multiple forms of help are available. Please select either "help level" to learn more about this lesson, "help general" for using Learn GitBranching, or "objective" to learn about how to solve the level.',zh_CN:'您正在关卡中,这里有多种形式的帮助,请选择 "help level" (关卡帮助)或 "help general" (一般帮助)',fr_FR:'Vous êtes dans un niveau, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help level" pour en apprendre plus sur cette leçon, "help general" pour l\'utilisation de Learn GitBranching, ou "objective" pour apprendre comment résoudre le niveau'},"help-vague-builder":{__desc__:"When you are in a level builder, the help command is vague so you need to specify what you mean",en_US:'You are in a level builder, so multiple forms of help are available. Please select either "help general" or "help builder"',zh_CN:'您正在进行关卡构建中,这里有多种形式的帮助,请选择 "help general" (一般帮助)或 "help builder" (关卡构建帮助)',fr_FR:'Vous êtes dans l\'éditeur de niveaux, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help general" soit "help builder"'},"goal-to-reach":{__desc__:"title of window that shoes the goal tree to reach",en_US:"Goal To Reach",zh_CN:"目标",fr_FR:"Cible à atteindre"},"hide-goal":{__desc__:"the helper message for the window that shows the goal tree",en_US:'You can hide this window with "hide goal"',zh_CN:'你可以通过命令 "hide goal" 关闭这个窗口',fr_FR:'Vous pouvez masquer cette fenêtre avec "hide goal"'},"hide-start":{__desc__:"The helper message for the window that shows the start tree for a level",en_US:'You can hide this window with "hide start"',zh_CN:'你可以通过命令 "hide start" 关闭这个窗口',fr_FR:'Vous pouvez masquer cette fenêtre avec "hide start"'},"level-builder":{__desc__:"The name for the environment where you build levels",en_US:"Level Builder",zh_CN:"关卡生成器",fr_FR:"Éditeur de niveaux"},"no-start-dialog":{__desc__:"when the user tries to open a start dialog for a level that does not have one",en_US:"There is no start dialog to show for this level!",zh_CN:"介绍? 这关真没有!",fr_FR:"Il n'y a aucun dialogue de départ à afficher pour ce niveau !"},"no-hint":{__desc__:"when no hint is available for a level",en_US:"Hmm, there doesn't seem to be a hint for this level :-/",zh_CN:"提示?嗯,这关真没有哎~ :-/",fr_FR:"Hum, il ne semble pas y avoir d'indice pour ce niveau :-/"},"error-untranslated-key":{__desc__:"This error happens when we are trying to translate a specific key and the locale version is mission",en_US:"The translation for {key} does not exist yet :( Please hop on github and offer up a translation!",zh_CN:"还没翻译 {key} :( 请在gitHub上贡献你的翻译!",fr_FR:"La traduction pour {key} n'existe pas encore :( Venez sur Github pour en offrir une !"},"error-untranslated":{__desc__:"The general error when we encounter a dialog that is not translated",en_US:"This dialog or text is not yet translated in your locale :( Hop on github to aid in translation!",zh_CN:"这段对话还没有被翻译成你的语言 :( 欢迎在gitHub上贡献你的翻译!",fr_FR:"Ce message n'a pas encore été traduit dans votre langue :( Venez sur Github aider à la traduction !"}}}),e.define("/src/js/app/index.js",function(e,t,n,r,i,s,o){function E(){var t=e("../views"),n=e("../models/collections"),r=e("../views/commandViews"),i=new t.MainHelperBar;this.commandCollection=new n.CommandCollection,this.commandBuffer=new n.CommandBuffer({collection:this.commandCollection}),this.commandPromptView=new r.CommandPromptView({el:$("#commandLineBar")}),this.commandLineHistoryView=new r.CommandLineHistoryView({el:$("#commandLineHistory"),collection:this.commandCollection})}var u=e("underscore"),a=e("backbone"),f=e("../util/constants"),l=e("../util"),c=u.clone(a.Events),h,p,d,v,m,g=function(){var t=e("../level/sandbox").Sandbox,n=e("../level").Level,r=e("../util/eventBaton").EventBaton,i=e("../level/arbiter").LevelArbiter,s=e("../views/levelDropdownView").LevelDropdownView;d=new r,h=new E,p=new t,v=new i,m=new s({wait:!0}),c.on("localeChanged",y),b(d),w(p)},y=function(){if(!window.$)return;$("span.intl-aware").each(function(t,n){var r=e("../intl"),i=$(n).attr("data-intl");$(n).text(r.str(i).toUpperCase())})},b=function(e){var t=function(){$("#commandTextField").focus()};t(),$(window).focus(function(t){e.trigger("windowFocus",t)}),$(document).click(function(t){e.trigger("documentClick",t)}),$(document).bind("keydown",function(t){e.trigger("docKeydown",t)}),$(document).bind("keyup",function(t){e.trigger("docKeyup",t)}),$(window).on("resize",function(e){c.trigger("resize",e)}),e.stealBaton("docKeydown",function(){}),e.stealBaton("docKeyup",function(){}),e.stealBaton("windowFocus",t),e.stealBaton("documentClick",t);var n=function(t){return function(){var n=[t];u.each(arguments,function(e){n.push(e)}),e.trigger.apply(e,n)}};$("#commandTextField").on("keydown",n("keydown")),$("#commandTextField").on("keyup",n("keyup")),$(window).trigger("resize")},w=function(e){var t=l.parseQueryString(window.location.href);t.hasOwnProperty("demo")?e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",["git commit; git checkout -b bugFix C1; git commit; git merge master; git checkout master; git commit; git rebase bugFix;","delay 1000; reset;","level rebase1 --noFinishDialog --noStartCommand --noIntroDialog;","delay 2000; show goal; delay 1000; hide goal;","git checkout bugFix; git rebase master; git checkout side; git rebase bugFix;","git checkout another; git rebase side; git rebase another master;","help; levels"].join(""))}):t.hasOwnProperty("NODEMO")||e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",["git help;","delay 1000;","help;","levels"].join(""))}),t.locale!==undefined&&t.locale.length&&(f.GLOBAL.locale=t.locale,c.trigger("localeChanged"));if(t.command){var n=unescape(t.command);e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",n)})}(/(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent)||/android/i.test(navigator.userAgent))&&e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted","mobile alert")})};e("../util").isBrowser()&&$(document).ready(g),n.getEvents=function(){return c},n.getSandbox=function(){return p},n.getEventBaton=function(){return d},n.getCommandUI=function(){return h},n.getLevelArbiter=function(){return v},n.getLevelDropdown=function(){return m},n.init=g}),e.define("/src/js/level/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("../util"),c=e("../app"),h=e("../intl"),p=e("../log"),d=e("../util/errors"),v=e("../level/sandbox").Sandbox,m=e("../util/constants"),g=e("../visuals/visualization").Visualization,y=e("../level/parseWaterfall").ParseWaterfall,b=e("../level/disabledMap").DisabledMap,w=e("../models/commandModel").Command,E=e("../git/gitShim").GitShim,S=e("../views/multiView").MultiView,x=e("../views").CanvasTerminalHolder,T=e("../views").ConfirmCancelTerminal,N=e("../views").NextLevelConfirm,C=e("../views").LevelToolbar,k=e("../git/treeCompare").TreeCompare,L={"help level":/^help level$/,"start dialog":/^start dialog$/,"show goal":/^(show goal|goal|help goal)$/,"hide goal":/^hide goal$/,"show solution":/^show solution($|\s)/,objective:/^(objective|assignment)$/},A=l.genParseCommand(L,"processLevelCommand"),O=v.extend({initialize:function(e){e=e||{},e.level=e.level||{},this.level=e.level,this.gitCommandsIssued=[],this.commandsThatCount=this.getCommandsThatCount(),this.solved=!1,this.initGoalData(e),this.initName(e),O.__super__.initialize.apply(this,[e]),this.startOffCommand(),this.handleOpen(e.deferred)},handleOpen:function(e){e=e||f.defer();if(this.level.startDialog&&!this.testOption("noIntroDialog")){new S(u.extend({},h.getStartDialog(this.level),{deferred:e}));return}setTimeout(function(){e.resolve()},this.getAnimationTime()*1.2)},objectiveDialog:function(e,t,n){n=n===undefined?this.level:n;if(!n||!n.startDialog){e.set("error",new d.GitError({msg:h.str("no-start-dialog")})),t.resolve();return}debugger;console.log(h.getStartDialog(n));var r=$.extend({},h.getStartDialog(n));r.childViews=r.childViews.slice(-1),new S(u.extend(r,{deferred:t})),t.promise.then(function(){e.set("status","finished")})},startDialog:function(e,t){if(!this.level.startDialog){e.set("error",new d.GitError({msg:h.str("no-start-dialog")})),t.resolve();return}this.handleOpen(t),t.promise.then(function(){e.set("status","finished")})},getEnglishName:function(){return this.level.name.en_US},initName:function(){var e=h.getName(this.level);this.levelToolbar=new C({name:e})},initGoalData:function(e){if(!this.level.goalTreeString||!this.level.solutionCommand)throw new Error("need goal tree and solution")},takeControl:function(){c.getEventBaton().stealBaton("processLevelCommand",this.processLevelCommand,this),O.__super__.takeControl.apply(this)},releaseControl:function(){c.getEventBaton().releaseBaton("processLevelCommand",this.processLevelCommand,this),O.__super__.releaseControl.apply(this)},startOffCommand:function(){this.testOption("noStartCommand")||c.getEventBaton().trigger("commandSubmitted","hint; delay 2000; show goal")},initVisualization:function(e){this.mainVis=new g({el:e.el||this.getDefaultVisEl(),treeString:e.level.startTree})},initGoalVisualization:function(){return this.goalCanvasHolder=new x,this.goalVis=new g({el:this.goalCanvasHolder.getCanvasLocation(),containerElement:this.goalCanvasHolder.getCanvasLocation(),treeString:this.level.goalTreeString,noKeyboardInput:!0,smallCanvas:!0,noClick:!0}),this.goalCanvasHolder},showSolution:function(t,n){var r=this.level.solutionCommand,i=u.bind(function(){this.isShowingSolution=!0,c.getEventBaton().trigger("commandSubmitted",r),p.showLevelSolution(this.getEnglishName())},this),s=t.get("rawStr");this.testOptionOnString(s,"noReset")||(r="reset --forSolution; "+r);if(this.testOptionOnString(s,"force")){i(),t.finishWith(n);return}var o=f.defer(),a=h.getDialog(e("../dialogs/confirmShowSolution"))[0],l=new T({markdowns:a.options.markdowns,deferred:o});o.promise.then(i).fail(function(){t.setResult("")}).done(function(){setTimeout(function(){t.finishWith(n)},l.getAnimationTime())})},showGoal:function(e,t){this.showSideVis(e,t,this.goalCanvasHolder,this.initGoalVisualization)},showSideVis:function(e,t,n,r){var i=function(){e&&e.finishWith(t)};if(!n||!n.inDom)n=r.apply(this);n.slideIn(),setTimeout(i,n.getAnimationTime())},hideGoal:function(e,t){this.hideSideVis(e,t,this.goalCanvasHolder)},hideSideVis:function(e,t,n,r){var i=function(){e&&e.finishWith(t)};n&&n.inDom?(n.die(),setTimeout(i,n.getAnimationTime())):i()},initParseWaterfall:function(e){O.__super__.initParseWaterfall.apply(this,[e]),this.parseWaterfall.addFirst("parseWaterfall",A),this.parseWaterfall.addFirst("instantWaterfall",this.getInstantCommands()),e.level.disabledMap&&this.parseWaterfall.addFirst("instantWaterfall",(new b({disabledMap:e.level.disabledMap})).getInstantCommands())},initGitShim:function(e){this.gitShim=new E({beforeCB:u.bind(this.beforeCommandCB,this),afterCB:u.bind(this.afterCommandCB,this),afterDeferHandler:u.bind(this.afterCommandDefer,this)})},getCommandsThatCount:function(){var t=e("../git/commands"),n=["git commit","git checkout","git rebase","git reset","git branch","git revert","git merge","git cherry-pick"],r={};return u.each(n,function(e){if(!t.regexMap[e])throw new Error("wut no regex");r[e]=t.regexMap[e]}),r},undo:function(){this.gitCommandsIssued.pop(),O.__super__.undo.apply(this,arguments)},afterCommandCB:function(e){if(e.get("error"))return;var t=!1;u.each(this.commandsThatCount,function(n){t=t||n.test(e.get("rawStr"))}),t&&this.gitCommandsIssued.push(e.get("rawStr"))},afterCommandDefer:function(e,t){if(this.solved){t.addWarning(h.str("already-solved")),e.resolve();return}var n=this.mainVis.gitEngine.exportTree(),r=k.dispatchFromLevel(this.level,n);if(!r){e.resolve();return}this.levelSolved(e)},getNumSolutionCommands:function(){var e=this.level.solutionCommand.replace(/^;|;$/g,"");return e.split(";").length},testOption:function(e){return this.options.command&&(new RegExp("--"+e)).test(this.options.command.get("rawStr"))},testOptionOnString:function(e,t){return e&&(new RegExp("--"+t)).test(e)},levelSolved:function(e){this.solved=!0,this.isShowingSolution||(c.getEvents().trigger("levelSolved",this.level.id),p.levelSolved(this.getEnglishName())),this.hideGoal();var t=c.getLevelArbiter().getNextLevel(this.level.id),n=this.gitCommandsIssued.length,r=this.getNumSolutionCommands();m.GLOBAL.isAnimating=!0;var i=this.testOption("noFinishDialog"),s=this.mainVis.gitVisuals.finishAnimation();i||(s=s.then(function(){var e=new N({nextLevel:t,numCommands:n,best:r});return e.getPromise()})),s.then(function(){!i&&t&&(p.choseNextLevel(t.id),c.getEventBaton().trigger("commandSubmitted","level "+t.id))}).fail(function(){}).done(function(){m.GLOBAL.isAnimating=!1,e.resolve()})},die:function(){this.levelToolbar.die(),this.hideGoal(),this.mainVis.die(),this.releaseControl(),this.clear(),delete this.commandCollection,delete this.mainVis,delete this.goalVis,delete this.goalCanvasHolder},getInstantCommands:function(){var e=u.bind(function(){var e=h.getHint(this.level);return!e||!e.length?h.str("no-hint"):e},this);return[[/^help$|^\?$/,function(){throw new d.CommandResult({msg:h.str("help-vague-level")})}],[/^hint$/,function(){throw new d.CommandResult({msg:e()})}]]},reset:function(e,t){this.gitCommandsIssued=[];var n=e?e.get("rawStr"):"";this.testOptionOnString(n,"forSolution")||(this.isShowingSolution=!1),this.solved=!1,O.__super__.reset.apply(this,arguments)},buildLevel:function(e,t){this.exitLevel(),setTimeout(function(){c.getSandbox().buildLevel(e,t)},this.getAnimationTime()*1.5)},importLevel:function(e,t){this.exitLevel(),setTimeout(function(){c.getSandbox().importLevel(e,t)},this.getAnimationTime()*1.5)},startLevel:function(e,t){this.exitLevel(),setTimeout(function(){c.getSandbox().startLevel(e,t)},this.getAnimationTime()*1.5)},exitLevel:function(e,t){this.die();if(!e||!t)return;setTimeout(function(){e.finishWith(t)},this.getAnimationTime()),c.getEventBaton().trigger("levelExited")},processLevelCommand:function(e,t){var n={"show goal":this.showGoal,"hide goal":this.hideGoal,"show solution":this.showSolution,"start dialog":this.startDialog,"help level":this.startDialog,objective:this.objectiveDialog},r=n[e.get("method")];if(!r)throw new Error("woah we dont support that method yet",r);r.apply(this,[e,t])}});n.Level=O,n.regexMap=L}),e.define("/src/js/log/index.js",function(e,t,n,r,i,s,o){var u=function(e,t,n){window._gaq=window._gaq||[],window._gaq.push(["_trackEvent",e,t,n])};n.viewInteracted=function(e){u("views","interacted",e)},n.showLevelSolution=function(e){u("levels","showedLevelSolution",e)},n.choseNextLevel=function(e){u("levels","nextLevelChosen",e)},n.levelSelected=function(e){u("levels","levelSelected",e)},n.levelSolved=function(e){u("levels","levelSolved",e)},n.commandEntered=function(e){u("commands","commandEntered",e)}}),e.define("/src/js/util/errors.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({defaults:{type:"MyError",msg:"Unknown Error"},toString:function(){return this.get("type")+": "+this.get("msg")},getMsg:function(){return this.get("msg")||"Unknown Error"},toResult:function(){return this.get("msg").length?"

"+this.get("msg").replace(/\n/g,"

")+"

":""}}),l=n.CommandProcessError=f.extend({defaults:{type:"Command Process Error"}}),c=n.CommandResult=f.extend({defaults:{type:"Command Result"}}),h=n.Warning=f.extend({defaults:{type:"Warning"}}),p=n.GitError=f.extend({defaults:{type:"Git Error"}}),d=function(e){if(e instanceof l||e instanceof p||e instanceof c||e instanceof h)return;throw e};n.filterError=d}),e.define("/src/js/visuals/visualization.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../models/collections"),l=f.CommitCollection,c=f.BranchCollection,h=e("../util/eventBaton").EventBaton,p=e("../visuals").GitVisuals,d=a.View.extend({initialize:function(e){e=e||{},this.options=e,this.customEvents=u.clone(a.Events),this.containerElement=e.containerElement;var t=this,n=e.containerElement||$("#canvasHolder")[0];new Raphael(n,200,200,function(){var n=this;s.nextTick(function(){t.paperInitialize(n,e)})})},paperInitialize:function(t,n){this.treeString=n.treeString,this.paper=t;var r=e("../app");this.eventBaton=n.noKeyboardInput?new h:r.getEventBaton(),this.commitCollection=new l,this.branchCollection=new c,this.gitVisuals=new p({commitCollection:this.commitCollection,branchCollection:this.branchCollection,paper:this.paper,noClick:this.options.noClick,smallCanvas:this.options.smallCanvas,visualization:this});var i=e("../git").GitEngine;this.gitEngine=new i({collection:this.commitCollection,branches:this.branchCollection,gitVisuals:this.gitVisuals,eventBaton:this.eventBaton}),this.gitEngine.init(),this.gitVisuals.assignGitEngine(this.gitEngine),this.myResize(),$(window).on("resize",u.bind(function(){this.myResize()},this)),this.gitVisuals.drawTreeFirstTime(),this.treeString&&this.gitEngine.loadTreeFromString(this.treeString),this.options.zIndex&&this.setTreeIndex(this.options.zIndex),this.shown=!1,this.setTreeOpacity(0),s.nextTick(u.bind(this.fadeTreeIn,this)),this.customEvents.trigger("gitEngineReady"),this.customEvents.trigger("paperReady")},clearOrigin:function(){delete this.originVis},makeOrigin:function(e){return this.originVis=new d(u.extend({},this.options,{noKeyboardInput:!0,noClick:!0,treeString:e.treeString})),this.originVis},originToo:function(e,t){if(!this.originVis)return;var n=u.bind(function(){this.originVis[e].apply(this.originVis,t)},this);if(this.originVis.paper){n();return}this.originVis.customEvents.on("paperReady",n)},setTreeIndex:function(e){$(this.paper.canvas).css("z-index",e),this.originToo("setTreeIndex",arguments)},setTreeOpacity:function(e){e===0&&(this.shown=!1),$(this.paper.canvas).css("opacity",e),this.originToo("setTreeOpacity",arguments)},getAnimationTime:function(){return 300},fadeTreeIn:function(){this.shown=!0,$(this.paper.canvas).animate({opacity:1},this.getAnimationTime()),this.originToo("fadeTreeIn",arguments)},fadeTreeOut:function(){this.shown=!1,$(this.paper.canvas).animate({opacity:0},this.getAnimationTime()),this.originToo("fadeTreeOut",arguments)},hide:function(){this.fadeTreeOut(),setTimeout(u.bind(function(){$(this.paper.canvas).css("visibility","hidden")},this),this.getAnimationTime()),this.originToo("hide",arguments)},show:function(){$(this.paper.canvas).css("visibility","visible"),setTimeout(u.bind(this.fadeTreeIn,this),10),this.originToo("show",arguments)},showHarsh:function(){$(this.paper.canvas).css("visibility","visible"),this.setTreeOpacity(1),this.originToo("showHarsh",arguments)},resetFromThisTreeNow:function(e){this.treeString=e;var t=this.getOriginInTreeString(e);if(t){var n=this.gitEngine.printTree(t);this.originToo("resetFromThisThreeNow",[n])}},getOriginInTreeString:function(e){var t=JSON.parse(unescape(e));return t.originTree},reset:function(e){var t=e||this.treeString;this.setTreeOpacity(0),t?this.gitEngine.loadTreeFromString(t):this.gitEngine.defaultInit(),this.fadeTreeIn();if(this.originVis)if(t){var n=this.getOriginInTreeString(t);this.originToo("reset",[JSON.stringify(n)])}else this.originToo("reset",arguments)},tearDown:function(){this.gitEngine.tearDown(),this.gitVisuals.tearDown(),delete this.paper,this.originToo("tearDown",arguments)},die:function(){this.fadeTreeOut(),setTimeout(u.bind(function(){this.shown||this.tearDown()},this),this.getAnimationTime()),this.originToo("die",arguments)},myResize:function(){if(!this.paper)return;var e=1,t=this.el,n=t.clientWidth-e,r=t.clientHeight-e;if(!this.containerElement){var i=t.offsetLeft,s=t.offsetTop;$(this.paper.canvas).css({position:"absolute",left:i+"px",top:s+"px"})}this.paper.setSize(n,r),this.gitVisuals.canvasResize(n,r)}});n.Visualization=d}),e.define("/src/js/models/collections.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?f=window.Backbone:f=e("backbone"),l=e("../git").Commit,c=e("../git").Branch,h=e("../models/commandModel").Command,p=e("../models/commandModel").CommandEntry,d=e("../util/constants").TIME,v=f.Collection.extend({model:l}),m=f.Collection.extend({model:h}),g=f.Collection.extend({model:c}),y=f.Collection.extend({model:p,localStorage:f.LocalStorage?new f.LocalStorage("CommandEntries"):null}),b=f.Model.extend({defaults:{collection:null},initialize:function(e){e.collection.bind("add",this.addCommand,this),this.buffer=[],this.timeout=null},addCommand:function(e){this.buffer.push(e),this.touchBuffer()},touchBuffer:function(){if(this.timeout)return;this.setTimeout()},setTimeout:function(){this.timeout=setTimeout(u.bind(function(){this.sipFromBuffer()},this),d.betweenCommandsDelay)},popAndProcess:function(){var e=this.buffer.shift(0);while(e.get("error")&&this.buffer.length)e=this.buffer.shift(0);e.get("error")?this.clear():this.processCommand(e)},processCommand:function(t){t.set("status","processing");var n=a.defer();n.promise.then(u.bind(function(){this.setTimeout()},this));var r=t.get("eventName");if(!r)throw new Error("I need an event to trigger when this guy is parsed and ready");var i=e("../app"),s=i.getEventBaton(),o=s.getNumListeners(r);if(!o){var f=e("../util/errors");t.set("error",new f.GitError({msg:"That command is valid, but not supported in this current environment! Try entering a level or level builder to use that command"})),n.resolve();return}i.getEventBaton().trigger(r,t,n)},clear:function(){clearTimeout(this.timeout),this.timeout=null},sipFromBuffer:function(){if(!this.buffer.length){this.clear();return}this.popAndProcess()}});n.CommitCollection=v,n.CommandCollection=m,n.BranchCollection=g,n.CommandEntryCollection=y,n.CommandBuffer=b}),e.define("/src/js/git/index.js",function(e,t,n,r,i,s,o){function y(e){this.rootCommit=null,this.refs={},this.HEAD=null,this.origin=null,this.localRepo=null,this.branchCollection=e.branches,this.commitCollection=e.collection,this.gitVisuals=e.gitVisuals,this.eventBaton=e.eventBaton,this.eventBaton.stealBaton("processGitCommand",this.dispatch,this),e.animationFactory&&(c=e.animationFactory),this.commandOptions={},this.generalArgs=[],this.initUniqueID()}var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("q"),l=e("../intl"),c=e("../visuals/animation/animationFactory").AnimationFactory,h=e("../visuals/animation").AnimationQueue,p=e("./treeCompare").TreeCompare,d=e("../util/errors"),v=d.GitError,m=d.CommandResult,g=e("../util/eventBaton").EventBaton;y.prototype.initUniqueID=function(){this.uniqueId=function(){var e=0;return function(t){return t?t+e++:e++}}()},y.prototype.assignLocalRepo=function(e){this.localRepo=e},y.prototype.defaultInit=function(){var e=this.getDefaultTree();this.loadTree(e)},y.prototype.getDefaultTree=function(){return JSON.parse(unescape("%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22master%22%2C%22type%22%3A%22branch%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%22C0%22%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C1%22%7D%7D%2C%22HEAD%22%3A%7B%22id%22%3A%22HEAD%22%2C%22target%22%3A%22master%22%2C%22type%22%3A%22general%20ref%22%7D%7D"))},y.prototype.init=function(){this.rootCommit=this.makeCommit(null,null,{rootCommit:!0}),this.commitCollection.add(this.rootCommit);var e=this.makeBranch("master",this.rootCommit);this.HEAD=new b({id:"HEAD",target:e}),this.refs[this.HEAD.get("id")]=this.HEAD,this.commit()},y.prototype.hasOrigin=function(){return!!this.origin},y.prototype.isOrigin=function(){return!!this.localRepo},y.prototype.exportTreeForBranch=function(e){var t=this.exportTree(),n=this.getUpstreamSet(e),r=t.commits;t.commits={},u.each(r,function(e,r){n[r]&&(t.commits[r]=e)});var i=t.branches;return t.branches={},u.each(i,function(n,r){r===e&&(t.branches[r]=n)}),t.HEAD.target=e,t},y.prototype.exportTree=function(){var e={branches:{},commits:{},HEAD:null};u.each(this.branchCollection.toJSON(),function(t){t.target=t.target.get("id"),t.visBranch=undefined,e.branches[t.id]=t}),u.each(this.commitCollection.toJSON(),function(t){u.each(E.prototype.constants.circularFields,function(e){t[e]=undefined},this);var n=[];u.each(t.parents,function(e){n.push(e.get("id"))}),t.parents=n,e.commits[t.id]=t},this);var t=this.HEAD.toJSON();return t.visBranch=undefined,t.lastTarget=t.lastLastTarget=t.visBranch=undefined,t.target=t.target.get("id"),e.HEAD=t,this.hasOrigin()&&(e.originTree=this.origin.exportTree()),e},y.prototype.printTree=function(e){e=e||this.exportTree(),p.reduceTreeFields([e]);var t=JSON.stringify(e);return/'/.test(t)&&(t=escape(t)),t},y.prototype.printAndCopyTree=function(){window.prompt(l.str("Copy the tree string below"),this.printTree())},y.prototype.loadTree=function(e){e=$.extend(!0,{},e),this.removeAll(),this.instantiateFromTree(e),this.reloadGraphics(),this.initUniqueID()},y.prototype.loadTreeFromString=function(e){this.loadTree(JSON.parse(unescape(e)))},y.prototype.instantiateFromTree=function(e){var t={};u.each(e.commits,function(n){var r=this.getOrMakeRecursive(e,t,n.id);this.commitCollection.add(r)},this),u.each(e.branches,function(n){var r=this.getOrMakeRecursive(e,t,n.id);this.branchCollection.add(r,{silent:!0})},this);var n=this.getOrMakeRecursive(e,t,e.HEAD.id);this.HEAD=n,this.rootCommit=t.C0;if(!this.rootCommit)throw new Error("Need root commit of C0 for calculations");this.refs=t,this.gitVisuals.gitReady=!1,this.branchCollection.each(function(e){this.gitVisuals.addBranch(e)},this);if(e.originTree){var r=JSON.stringify(e.originTree);this.makeOrigin(r)}},y.prototype.makeOrigin=function(e){if(this.hasOrigin())throw new v({msg:l.str("git-error-origin-exists")});e=e||this.printTree(this.exportTreeForBranch("master"));var t=this.gitVisuals.getVisualization(),n=t.makeOrigin({localRepo:this,treeString:e});this.animationQueue.set("promiseBased",!0),n.customEvents.on("gitEngineReady",function(){this.origin=n.gitEngine,n.gitEngine.assignLocalRepo(this),this.origin.externalRefresh(),c.playRefreshAnimationAndFinish(this.gitVisuals,this.animationQueue)},this);var r=JSON.parse(unescape(e));u.each(r.branches,function(e,t){var n=e.target,r=this.makeBranch("o/"+t,this.getCommitFromRef(n));r.set("remote",!0)},this)},y.prototype.getOrMakeRecursive=function(e,t,n){if(t[n])return t[n];var r=function(e,t){if(e.commits[t])return"commit";if(e.branches[t])return"branch";if(t=="HEAD")return"HEAD";throw new Error("bad type for "+t)},i=r(e,n);if(i=="HEAD"){var s=e.HEAD,o=new b(u.extend(e.HEAD,{target:this.getOrMakeRecursive(e,t,s.target)}));return t[n]=o,o}if(i=="branch"){var a=e.branches[n],f=new w(u.extend(e.branches[n],{target:this.getOrMakeRecursive(e,t,a.target)}));return t[n]=f,f}if(i=="commit"){var l=e.commits[n],c=[];u.each(l.parents,function(n){c.push(this.getOrMakeRecursive(e,t,n))},this);var h=new E(u.extend(l,{parents:c,gitVisuals:this.gitVisuals}));return t[n]=h,h}throw new Error("ruh rho!! unsupported type for "+n)},y.prototype.tearDown=function(){this.eventBaton.releaseBaton("processGitCommand",this.dispatch,this),this.removeAll()},y.prototype.reloadGraphics=function(){this.gitVisuals.rootCommit=this.refs.C0,this.gitVisuals.initHeadBranch(),this.gitVisuals.drawTreeFromReload(),this.gitVisuals.refreshTreeHarsh()},y.prototype.removeAll=function(){this.branchCollection.reset(),this.commitCollection.reset(),this.refs={},this.HEAD=null,this.rootCommit=null,this.origin&&(this.origin.gitVisuals.getVisualization().tearDown(),delete this.origin,this.gitVisuals.getVisualization().clearOrigin()),this.gitVisuals.resetAll()},y.prototype.getDetachedHead=function(){var e=this.HEAD.get("target"),t=e.get("type");return t!=="branch"},y.prototype.validateBranchName=function(e){e=e.replace(/\s/g,"");if(!/^[a-zA-Z0-9]+$/.test(e))throw new v({msg:l.str("bad-branch-name",{branch:e})});if(/[hH][eE][aA][dD]/.test(e))throw new v({msg:l.str("bad-branch-name",{branch:e})});return e.length>9&&(e=e.slice(0,9),this.command.addWarning(l.str("branch-name-short",{branch:e}))),e},y.prototype.validateAndMakeBranch=function(e,t){e=this.validateBranchName(e);if(this.refs[e])throw new v({msg:l.str("bad-branch-name",{branch:name})});this.makeBranch(e,t)},y.prototype.makeBranch=function(e,t){var n=new w({target:t,id:e});return this.branchCollection.add(n),this.refs[n.get("id")]=n,n},y.prototype.getHead=function(){return u.clone(this.HEAD)},y.prototype.getBranches=function(){var e=[];return this.branchCollection.each(function(t){e.push({id:t.get("id"),selected:this.HEAD.get("target")===t,target:t.get("target"),remote:t.getIsRemote(),obj:t})},this),e},y.prototype.getRemoteBranches=function(){var e=this.getBranches();return u.filter(e,function(e){return e.remote===!0})},y.prototype.getLocalBranches=function(){var e=this.getBranches();return u.filter(e,function(e){return e.remote===!1})},y.prototype.printBranchesWithout=function(e){var t=this.getUpstreamBranchSet(),n=this.getCommitFromRef(e).get("id"),r=[];u.each(t[n],function(e){e.selected=this.HEAD.get("target").get("id")==e.id,r.push(e)},this),this.printBranches(r)},y.prototype.printBranches=function(e){var t="";throw u.each(e,function(e){t+=(e.selected?"* ":"")+e.id+"\n"}),new m({msg:t})},y.prototype.getUniqueID=function(){var e=this.uniqueId("C"),t=u.bind(function(e){return this.refs[e]?!0:this.origin&&this.origin.refs[e]?!0:!1},this);while(t(e))e=this.uniqueId("C");return e},y.prototype.makeCommit=function(e,t,n){t||(t=this.getUniqueID());var r=new E(u.extend({parents:e,id:t,gitVisuals:this.gitVisuals},n||{}));return this.refs[r.get("id")]=r,this.commitCollection.add(r),r},y.prototype.acceptNoGeneralArgs=function(){if(this.generalArgs.length)throw new v({msg:l.str("git-error-no-general-args")})},y.prototype.validateArgBounds=function(e,t,n,r){var i=r===undefined?"git "+this.command.get("method"):this.command.get("method")+" "+r+" ";i="with "+i;if(e.lengthn)throw new v({msg:l.str("git-error-args-many",{upper:String(n),what:i})})},y.prototype.oneArgImpliedHead=function(e,t){this.validateArgBounds(e,0,1,t),e.length===0&&e.push("HEAD")},y.prototype.twoArgsImpliedHead=function(e,t){this.validateArgBounds(e,1,2,t),e.length==1&&e.push("HEAD")},y.prototype.revertStarter=function(){this.validateArgBounds(this.generalArgs,1,NaN),this.revert(this.generalArgs)},y.prototype.revert=function(e){var t=u.map(e,function(e){return this.getCommitFromRef(e)},this),n=f.defer(),r=n.promise,i=this.resolveID("HEAD");r=c.highlightEachWithPromise(r,t,i);var s=this.getCommitFromRef("HEAD"),o=u.bind(function(e){var t=this.rebaseAltID(e.get("id")),n=l.str("git-revert-msg",{oldCommit:this.resolveName(e),oldMsg:e.get("commitMessage")}),r=this.makeCommit([s],t,{commitMessage:n});return s=r,c.playCommitBirthPromiseAnimation(r,this.gitVisuals)},this);u.each(t,function(e){r=r.then(function(){return o(e)})},this),r=r.then(u.bind(function(){return this.setTargetLocation("HEAD",s),c.playRefreshAnimation(this.gitVisuals)},this)),this.animationQueue.thenFinish(r,n)},y.prototype.resetStarter=function(){if(this.commandOptions["--soft"])throw new v({msg:l.str("git-error-staging")});this.commandOptions["--hard"]&&(this.command.addWarning(l.str("git-warning-hard")),this.generalArgs=this.generalArgs.concat(this.commandOptions["--hard"])),this.validateArgBounds(this.generalArgs,1,1);if(this.getDetachedHead())throw new v({msg:l.str("git-error-reset-detached")});this.reset(this.generalArgs[0])},y.prototype.reset=function(e){this.setTargetLocation("HEAD",this.getCommitFromRef(e))},y.prototype.cherrypickStarter=function(){this.validateArgBounds(this.generalArgs,1,Number.MAX_VALUE);var e=this.getUpstreamSet("HEAD"),t=u.map(this.generalArgs,function(t){var n=this.getCommitFromRef(t);if(e[n.get("id")])throw new v({msg:l.str("git-error-already-exists",{commit:n.get("id")})});return n},this),n=f.defer(),r=n.promise,i=this.resolveID("HEAD");r=c.highlightEachWithPromise(r,t,i);var s=u.bind(function(e){var t=this.cherrypick(e);return c.playCommitBirthPromiseAnimation(t,this.gitVisuals)},this);u.each(t,function(e){r=r.then(function(){return s(e)})},this),this.animationQueue.thenFinish(r,n)},y.prototype.checkUpstreamOfSource=function(e,t,n,r,i){var s=t.getUpstreamSet(r),o=e.getCommitFromRef(n).get("id");if(!s[o])throw new v({msg:i||l.str("git-error-origin-fetch-no-ff")})},y.prototype.getTargetGraphDifference=function(e,t,n,r,i){i=i||{},r=t.resolveID(r);var s=e.getUpstreamSet(n),o=t.getCommitFromRef(r),a=t.exportTree(),f=a.commits[o.get("id")];if(e.refs[f.id]){if(i.dontThrowOnNoFetch)return[];throw new v({msg:l.str("git-error-origin-fetch-uptodate")})}f.depth=0;var c=[],h=[f],p=function(e){if(s[e])return;var t=a.commits[e];t.depth=d.depth+1,h.push(t)};while(h.length){var d=h.pop();c.push(d),u.each(d.parents,p)}var m={},g=[];return u.forEach(c,function(e){if(m[e.id])return;m[e.id]=!0,g.push(e)}),g.sort(function(e,t){return t.depth-e.depth})},y.prototype.pushStarter=function(e){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.push()},y.prototype.push=function(e){e=e||{};var t=this.refs.master,n=this.origin.refs.master;this.checkUpstreamOfSource(this,this.origin,n,t,l.str("git-error-origin-push-no-ff"));var r=this.getTargetGraphDifference(this.origin,this,n,t),i=u.bind(function(e,t){var n=u.map(t,function(e){return this.origin.refs[e]},this);return this.origin.makeCommit(n,e)},this),s=u.bind(function(e,t){var n=i(e,t);return c.playCommitBirthPromiseAnimation(n,this.origin.gitVisuals)},this),o=f.defer(),a=o.promise;u.each(r,function(e){a=a.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.refs[e.id],n)},this)),a=a.then(function(){return s(e.id,e.parents)})},this),a=a.then(u.bind(function(){var e=t.get("target").get("id"),r=this.origin.refs[e];return this.origin.setTargetLocation(n,r),c.playRefreshAnimation(this.gitVisuals),c.playRefreshAnimation(this.origin.gitVisuals)},this)),a=a.then(u.bind(function(){var e=this.getCommitFromRef(t),n=t.getRemoteBranchIDFromTracking();return this.setTargetLocation(this.refs[n],e),c.playRefreshAnimation(this.gitVisuals)},this)),e.dontResolvePromise||this.animationQueue.thenFinish(a,o)},y.prototype.fetchStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.fetch()},y.prototype.fetch=function(e){e=e||{};var t=this.refs["o/master"],n=this.origin.refs.master;this.checkUpstreamOfSource(this,this.origin,t,n);var r=this.getTargetGraphDifference(this,this.origin,t,n,e);if(r.length===0){this.command.addWarning(l.str("git-error-origin-fetch-uptodate"));var i=f.defer();return{deferred:i,chain:i.promise}}var s=u.bind(function(e,t){var n=u.map(t,function(e){return this.refs[e]},this);return this.makeCommit(n,e)},this),o=u.bind(function(e,t){var n=s(e,t);return c.playCommitBirthPromiseAnimation(n,this.gitVisuals)},this),a=f.defer(),h=a.promise;return u.each(r,function(e){h=h.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.origin.refs[e.id],t)},this)),h=h.then(function(){return o(e.id,e.parents)})},this),h=h.then(u.bind(function(){var e=n.get("target").get("id"),r=this.refs[e];return this.setTargetLocation(t,r),c.playRefreshAnimation(this.origin.gitVisuals),c.playRefreshAnimation(this.gitVisuals)},this)),e.dontResolvePromise||this.animationQueue.thenFinish(h,a),{chain:h,deferred:a}},y.prototype.pullStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.pull()},y.prototype.pull=function(){var e=this.refs.master,t=this.refs["o/master"],n=this.fetch({dontResolvePromise:!0,dontThrowOnNoFetch:!0});this.commandOptions["--rebase"]?this.pullFinishWithRebase(n,e,t):this.pullFinishWithMerge(n,e,t)},y.prototype.pullFinishWithRebase=function(e,t,n){var r=e.chain,i=e.deferred;r=r.then(function(){return c.getDelayedPromise(300)}),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(n),t)},this)),r=r.then(u.bind(function(){return e.dontResolvePromise=!0,this.rebase(n,t,e)},this)),this.animationQueue.thenFinish(r,i)},y.prototype.pullFinishWithMerge=function(e,t,n){var r=e.chain,i=e.deferred;r=r.then(function(){return c.getDelayedPromise(300)}),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(n),t)},this)),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(t),n)},this)),r=r.then(function(){return c.getDelayedPromise(700)}),r=r.then(u.bind(function(){var e=this.merge("o/master");return e?c.playCommitBirthPromiseAnimation(e,this.gitVisuals):c.playRefreshAnimation(this.gitVisuals)},this)),this.animationQueue.thenFinish(r,i)},y.prototype.cloneStarter=function(){this.acceptNoGeneralArgs(),this.makeOrigin(this.printTree())},y.prototype.fakeTeamworkStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.validateArgBounds(this.generalArgs,0,2);var e=this.generalArgs[0]||"master",t=this.generalArgs[1]||1,n=this.origin.resolveID(e);if(n.get("type")!=="branch")throw new v({msg:l.str("git-error-options")});this.fakeTeamwork(t,e)},y.prototype.fakeTeamwork=function(e,t){var n=u.bind(function(){var e=this.getUniqueID();return this.origin.receiveTeamwork(e,t,this.animationQueue)},this),r=u.bind(function(){var e=n();return c.playCommitBirthPromiseAnimation(e,this.origin.gitVisuals)},this),i=function(){return r()},s=f.defer(),o=s.promise;u.each(u.range(e),function(e){o=o.then(function(){return r()})}),this.animationQueue.thenFinish(o,s)},y.prototype.receiveTeamwork=function(e,t,n){this.checkout(this.resolveID(t));var r=this.makeCommit([this.getCommitFromRef("HEAD")],e);return this.setTargetLocation(this.HEAD,r),r},y.prototype.cherrypick=function(e){var t=this.rebaseAltID(e.get("id")),n=this.makeCommit([this.getCommitFromRef("HEAD")],t);return this.setTargetLocation(this.HEAD,n),n},y.prototype.commitStarter=function(){this.acceptNoGeneralArgs();if(this.commandOptions["-am"]&&(this.commandOptions["-a"]||this.commandOptions["-m"]))throw new v({msg:l.str("git-error-options")});var e=null,t=null;this.commandOptions["-a"]&&this.command.addWarning(l.str("git-warning-add")),this.commandOptions["-am"]&&(t=this.commandOptions["-am"],this.validateArgBounds(t,1,1,"-am"),e=t[0]),this.commandOptions["-m"]&&(t=this.commandOptions["-m"],this.validateArgBounds(t,1,1,"-m"),e=t[0]);var n=this.commit();e&&(e=e.replace(/"/g,'"').replace(/^"/g,"").replace(/"$/g,""),n.set("commitMessage",e));var r=c.playCommitBirthPromiseAnimation(n,this.gitVisuals);this.animationQueue.thenFinish(r)},y.prototype.commit=function(){var e=this.getCommitFromRef(this.HEAD),t=null;this.commandOptions["--amend"]&&(e=this.resolveID("HEAD~1"),t=this.rebaseAltID(this.getCommitFromRef("HEAD").get("id")));var n=this.makeCommit([e],t);return this.getDetachedHead()&&this.command.addWarning(l.str("git-warning-detached")),this.setTargetLocation(this.HEAD,n),n},y.prototype.resolveName=function(e){var t=this.resolveID(e);return t.get("type")=="commit"?"commit "+t.get("id"):t.get("type")=="branch"?'branch "'+t.get("id")+'"':this.resolveName(t.get("target"))},y.prototype.resolveID=function(e){if(e===null||e===undefined)throw new Error("Dont call this with null / undefined");return typeof e!="string"?e:this.resolveStringRef(e)},y.prototype.resolveRelativeRef=function(e,t){var n=/([~\^])(\d*)/g,r;while(r=n.exec(t)){var i=e,s=r[2]?parseInt(r[2],10):1;if(r[1]=="^")i=e.getParent(s-1);else while(i&&s--)i=i.getParent(0);if(!i){var o=l.str("git-error-relative-ref",{commit:e.id,match:r[0]});throw new v({msg:o})}e=i}return e},y.prototype.resolveStringRef=function(e){e=this.crappyUnescape(e);if(this.refs[e])return this.refs[e];var t=null,n=null,r=/^([a-zA-Z0-9]+)(([~\^]\d*)*)/,i=r.exec(e);if(!i)throw new v({msg:l.str("git-error-exist",{ref:e})});t=i[1],n=i[2];if(!this.refs[t])throw new v({msg:l.str("git-error-exist",{ref:e})});var s=this.getCommitFromRef(t);return n&&(s=this.resolveRelativeRef(s,n)),s},y.prototype.getCommitFromRef=function(e){var t=this.resolveID(e);while(t.get("type")!=="commit")t=t.get("target");return t},y.prototype.getType=function(e){return this.resolveID(e).get("type")},y.prototype.setTargetLocation=function(e,t){if(this.getType(e)=="commit")return;e=this.getOneBeforeCommit(e),e.set("target",t)},y.prototype.getUpstreamBranchSet=function(){var e={},t=function(e,t){var n=!1;return u.each(e,function(e){e.id==t&&(n=!0)}),n},n=function(e){var t=[],n=[e];while(n.length){var r=n.pop();t.push(r.get("id")),r.get("parents")&&r.get("parents").length&&(n=n.concat(r.get("parents")))}return t};return this.branchCollection.each(function(r){var i=n(r.get("target"));u.each(i,function(n){e[n]=e[n]||[],t(e[n],r.get("id"))||e[n].push({obj:r,id:r.get("id")})})}),e},y.prototype.getUpstreamHeadSet=function(){var e=this.getUpstreamSet("HEAD"),t=this.getCommitFromRef("HEAD").get("id");return e[t]=!0,e},y.prototype.getOneBeforeCommit=function(e){var t=this.resolveID(e);return t===this.HEAD&&!this.getDetachedHead()&&(t=t.get("target")),t},y.prototype.scrapeBaseID=function(e){var t=/^C(\d+)/.exec(e);if(!t)throw new Error("regex failed on "+e);return"C"+t[1]},y.prototype.rebaseAltID=function(e){var t=[[/^C(\d+)[']{0,2}$/,function(e){return e[0]+"'"}],[/^C(\d+)[']{3}$/,function(e){return e[0].slice(0,-3)+"'^4"}],[/^C(\d+)['][\^](\d+)$/,function(e){return"C"+String(e[1])+"'^"+String(Number(e[2])+1)}]];for(var n=0;n",this.get("commitMessage"),"
","Commit: "+this.get("id")].join("\n")+"\n"},getShowEntry:function(){return[this.getLogEntry(),"diff --git a/bigGameResults.html b/bigGameResults.html","--- bigGameResults.html","+++ bigGameResults.html","@@ 13,27 @@ Winner, Score","- Stanfurd, 14-7","+ Cal, 21-14"].join("\n")+"\n"},validateAtInit:function(){if(!this.get("id"))throw new Error("Need ID!!");this.get("createTime")||this.set("createTime",(new Date).toString()),this.get("commitMessage")||this.set("commitMessage",l.str("git-dummy-msg")),this.set("children",[]);if(!this.get("rootCommit"))if(!this.get("parents")||!this.get("parents").length)throw new Error("needs parents")},addNodeToVisuals:function(){var e=this.get("gitVisuals").addNode(this.get("id"),this);this.set("visNode",e)},addEdgeToVisuals:function(e){this.get("gitVisuals").addEdge(this.get("id"),e.get("id"))},getParent:function(e){return this&&this.attributes&&this.attributes.parents?this.attributes.parents[e]:null},isMainParent:function(e){var t=this.get("parents").indexOf(e);return t===0},initialize:function(e){this.validateAtInit(),this.addNodeToVisuals(),u.each(this.get("parents"),function(e){e.get("children").push(this),this.addEdgeToVisuals(e)},this)}});n.GitEngine=y,n.Commit=E,n.Branch=w,n.Ref=b}),e.define("/src/js/visuals/animation/animationFactory.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("./index").Animation,c=e("./index").PromiseAnimation,h=e("../../util/constants").GRAPHICS,p={},d=function(e,t){var n=h.defaultAnimationTime*1,r=n*2,i=function(){e.refreshTree(n),t.setBirth(),t.parentInFront(),e.visBranchesFront(),t.animateUpdatedPosition(r,"bounce"),t.animateOutgoingEdges(n)};return{animation:i,duration:Math.max(n,r)}},v=function(e,t){var n=h.defaultAnimationTime*.66,r=n*2;return{animation:function(){e.highlightTo(t,r,"easeInOut")},duration:r*1.5}};p.genCommitBirthAnimation=function(e,t,n){if(!e)throw new Error("Need animation queue to add closure to!");var r=t.get("visNode"),i=d(n,r);e.add(new l({closure:i.animation,duration:i.duration}))},p.genCommitBirthPromiseAnimation=function(e,t){var n=e.get("visNode");return new c(d(t,n))},p.highlightEachWithPromise=function(e,t,n){return u.each(t,function(t){e=e.then(u.bind(function(){return this.playHighlightPromiseAnimation(t,n)},this))},this),e},p.playCommitBirthPromiseAnimation=function(e,t){var n=this.genCommitBirthPromiseAnimation(e,t);return n.play(),n.getPromise()},p.playRefreshAnimationAndFinish=function(e,t){var n=new c({closure:function(){e.refreshTree()}});n.play(),t.thenFinish(n.getPromise())},p.playRefreshAnimation=function(e){var t=new c({closure:function(){e.refreshTree()}});return t.play(),t.getPromise()},p.refreshTree=function(e,t){e.add(new l({closure:function(){t.refreshTree()}}))},p.genHighlightPromiseAnimation=function(e,t){var n=t.get("visBranch")||t.get("visNode"),r=e.get("visNode");return new c(v(r,n))},p.playHighlightPromiseAnimation=function(e,t){var n=this.genHighlightPromiseAnimation(e,t);return n.play(),n.getPromise()},p.getDelayedPromise=function(e){var t=f.defer();return setTimeout(t.resolve,e||1e3),t.promise},p.delay=function(e,t){t=t||h.defaultAnimationTime,e.add(new l({closure:function(){},duration:t}))},n.AnimationFactory=p}),e.define("/src/js/visuals/animation/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("backbone"),l=e("../../util/constants").GLOBAL,c=f.Model.extend({defaults:{duration:300,closure:null},validateAtInit:function(){if(!this.get("closure"))throw new Error("give me a closure!")},initialize:function(e){this.validateAtInit()},run:function(){this.get("closure")()}}),h=f.Model.extend({defaults:{animations:null,index:0,callback:null,defer:!1,promiseBased:!1},initialize:function(e){this.set("animations",[]),e.callback||console.warn("no callback")},thenFinish:function(e,t){e.then(u.bind(function(){this.finish()},this)),this.set("promiseBased",!0),t&&t.resolve()},add:function(e){if(!e instanceof c)throw new Error("Need animation not something else");this.get("animations").push(e)},start:function(){this.set("index",0),l.isAnimating=!0,this.next()},finish:function(){l.isAnimating=!1,this.get("callback")()},next:function(){var e=this.get("animations"),t=this.get("index");if(t>=e.length){this.finish();return}var n=e[t],r=n.get("duration");n.run(),this.set("index",t+1),setTimeout(u.bind(function(){this.next()},this),r)}}),p=f.Model.extend({defaults:{deferred:null,closure:null,duration:300},initialize:function(e){if(!e.closure&&!e.animation)throw new Error("need closure or animation");this.set("closure",e.closure||e.animation),this.set("deferred",e.deferred||a.defer())},getPromise:function(){return this.get("deferred").promise},play:function(){this.get("closure")(),setTimeout(u.bind(function(){this.get("deferred").resolve()},this),this.get("duration"))},then:function(e){return this.get("deferred").promise.then(e)}});p.fromAnimation=function(e){return new p({closure:e.get("closure"),duration:e.get("duration")})},n.Animation=c,n.PromiseAnimation=p,n.AnimationQueue=h}),e.define("/src/js/git/treeCompare.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a={};a.dispatchFromLevel=function(e,t){var n=e.goalTreeString;return a.dispatch(e,n,t)},a.dispatch=function(e,t,n){var r=!0;switch(r){case!!e.compareOnlyMaster:return a.compareBranchWithinTrees(n,t,"master");case!!e.compareOnlyBranches:return a.compareAllBranchesWithinTrees(n,t);case!!e.compareAllBranchesHashAgnostic:return a.compareAllBranchesWithinTreesHashAgnostic(n,t);case!!e.compareOnlyMasterHashAgnostic:return a.compareBranchesWithinTreesHashAgnostic(n,t,["master"]);case!!e.compareOnlyMasterHashAgnosticWithAsserts:return a.compareBranchesWithinTreesHashAgnostic(n,t,["master"])&&a.evalAsserts(n,e.goalAsserts);default:return a.compareAllBranchesWithinTreesAndHEAD(n,t)}},a.compareAllBranchesWithinTreesAndHEAD=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t);debugger;return e.HEAD.target==t.HEAD.target&&this.compareAllBranchesWithinTrees(e,t)},a.compareAllBranchesWithinTrees=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t);var n=u.extend({},e.branches,t.branches),r=!0;return u.uniq(n,function(n,i){r=r&&this.compareBranchWithinTrees(e,t,i)},this),r},a.compareBranchesWithinTrees=function(e,t,n){var r=!0;return u.each(n,function(n){r=r&&this.compareBranchWithinTrees(e,t,n)},this),r},a.compareBranchWithinTrees=function(e,t,n){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var r=this.getRecurseCompare(e,t),i=e.branches[n],s=t.branches[n];return u.isEqual(i,s)&&r(e.commits[i.target],t.commits[s.target])},a.compareAllBranchesWithinTreesHashAgnostic=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var n=u.extend({},e.branches,t.branches),r=[];return u.each(n,function(e,t){r.push(t)}),this.compareBranchesWithinTreesHashAgnostic(e,t,r)},a.compareBranchesWithinTreesHashAgnostic=function(e,t,n){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var r=u.bind(function(e,t){return!e||!t?!1:(e=u.clone(e),t=u.clone(t),e.target=this.getBaseRef(e.target),t.target=this.getBaseRef(t.target),u.isEqual(e,t))},this),i=this.getRecurseCompareHashAgnostic(e,t),s=!0;return u.each(n,function(n){var o=e.branches[n],u=t.branches[n];s=s&&r(o,u)&&i(e.commits[o.target],t.commits[u.target])},this),s},a.evalAsserts=function(e,t){var n=!0;return u.each(t,function(t,r){n=n&&this.evalAssertsOnBranch(e,r,t)},this),n},a.evalAssertsOnBranch=function(e,t,n){e=this.convertTreeSafe(e);if(!e.branches[t])return!1;var r=e.branches[t],i=[r.target],s={};while(i.length){var o=i.pop();s[this.getBaseRef(o)]=this.getNumHashes(o),i=i.concat(e.commits[o].parents)}var a=!0;return u.each(n,function(e){try{a=a&&e(s)}catch(t){console.warn("error during assert",t),console.log(t),a=!1}}),a},a.getNumHashes=function(e){var t=[[/^C(\d+)([']{0,3})$/,function(e){return e[2]?e[2].length:0}],[/^C(\d+)['][\^](\d+)$/,function(e){return Number(e[2])}]];for(var n=0;np.VIEWPORT.minWidth&&e.h>p.VIEWPORT.minHeight&&this.finish()}}),O=L.extend({initialize:function(e){if(!e||!e.level)throw new Error("need level");this.eventBatonName="zoomChange",this.markdowns=["## That zoom level of "+e.level+" is not supported :-/","Please zoom back to a supported zoom level with Ctrl + and Ctrl -","","(and of course, pull requests to fix this are appreciated :D)"],O.__super__.initialize.apply(this,[e])},batonFired:function(e){e<=p.VIEWPORT.maxZoom&&e>=p.VIEWPORT.minZoom&&this.finish()}}),M=m.extend({tagName:"div",className:"levelToolbarHolder",template:u.template($("#level-toolbar-template").html()),initialize:function(e){e=e||{},this.JSON={name:e.name||"Some level! (unknown name)"},this.beforeDestination=$($("#commandLineHistory div.toolbar")[0]),this.render(),e.wait||s.nextTick(u.bind(this.show,this))},getAnimationTime:function(){return 700},render:function(){var e=this.template(this.JSON);this.$el.html(e),this.beforeDestination.after(this.el)},die:function(){this.hide(),setTimeout(u.bind(function(){this.tearDown()},this),this.getAnimationTime())},hide:function(){this.$("div.toolbar").toggleClass("hidden",!0)},show:function(){this.$("div.toolbar").toggleClass("hidden",!1)}}),_=m.extend({tagName:"div",className:"helperBar transitionAll",template:u.template($("#helper-bar-template").html()),events:{"click a":"onClick"},onClick:function(e){var t=e.target,n=$(t).attr("data-id"),r="on"+n[0].toUpperCase()+n.slice(1)+"Click";this[r].call(this)},show:function(){this.$el.toggleClass("show",!0)},hide:function(){this.$el.toggleClass("show",!1),this.deferred&&this.deferred.resolve()},getItems:function(){return[]},setupChildren:function(){},fireCommand:function(e){l.getEventBaton().trigger("commandSubmitted",e)},showDeferMe:function(e){this.hide();var t=a.defer();e.deferred=t,t.promise.then(u.bind(function(){this.show()},this)),e.show()},onExitClick:function(){this.hide()},initialize:function(e){e=e||{},this.destination=$("body"),this.JSON={items:this.getItems()},this.render(),this.setupChildren(),e.wait||this.show()}}),D=_.extend({getItems:function(){return[{text:"Git Branching",id:"english"},{text:"日本語版リポジトリ",id:"japanese"},{text:"Git 브랜치 배우기",id:"korean"},{text:"学习Git分支",id:"chinese"},{text:"français",id:"french"},{icon:"signout",id:"exit"}]},fireCommand:function(){h.viewInteracted("intlSelect"),_.prototype.fireCommand.apply(this,arguments)},onJapaneseClick:function(){this.fireCommand("locale ja; levels"),this.hide()},onEnglishClick:function(){this.fireCommand("locale en_US; levels"),this.hide()},onKoreanClick:function(){this.fireCommand("locale ko; levels"),this.hide()},onFrenchClick:function(){this.fireCommand("locale fr_FR; levels"),this.hide()},onChineseClick:function(){this.fireCommand("locale zh_CN; levels"),this.hide()}}),P=_.extend({getItems:function(){return[{text:"Levels",id:"levels"},{text:"Reset",id:"reset"},{text:"Undo",id:"undo"},{text:"Objective",id:"objectve"},{text:"Help",id:"help"},{icon:"signout",id:"exit"}]},fireCommand:function(){h.viewInteracted("helperBar"),_.prototype.fireCommand.apply(this,arguments)},onObjectiveClick:function(){this.fireCommand("objective")},onLevelsClick:function(){this.fireCommand("levels")},onResetClick:function(){this.fireCommand("reset")},onUndoClick:function(){this.fireCommand("undo")},onHelpClick:function(){this.fireCommand("help general; git help")}}),H=_.extend({getItems:function(){return[{icon:"question-sign",id:"commands"},{icon:"globe",id:"intl"}]},onIntlClick:function(){this.showDeferMe(this.intlHelper),h.viewInteracted("openIntlBar")},onCommandsClick:function(){this.showDeferMe(this.commandsHelper),h.viewInteracted("openCommandsBar")},setupChildren:function(){this.commandsHelper=new P({wait:!0}),this.intlHelper=new D({wait:!0})}}),B=m.extend({tagName:"div",className:"canvasTerminalHolder box flex1",template:u.template($("#terminal-window-bare-template").html()),events:{"click div.wrapper":"onClick"},initialize:function(e){e=e||{},this.destination=$("body"),this.JSON={title:e.title||c.str("goal-to-reach"),text:e.text||c.str("hide-goal")},this.render(),this.inDom=!0,e.additionalClass&&this.$el.addClass(e.additionalClass)},getAnimationTime:function(){return 700},onClick:function(){this.die()},die:function(){this.slideOut(),this.inDom=!1,setTimeout(u.bind(function(){this.tearDown()},this),this.getAnimationTime())},slideOut:function(){this.slideToggle(!0)},slideIn:function(){this.slideToggle(!1)},slideToggle:function(e){this.$("div.terminal-window-holder").toggleClass("slideOut",e)},getCanvasLocation:function(){return this.$("div.inside")[0]}});n.BaseView=m,n.GeneralButton=w,n.ModalView=x,n.ModalTerminal=T,n.ModalAlert=N,n.ContainedBase=b,n.ConfirmCancelView=E,n.LeftRightView=S,n.ZoomAlertWindow=O,n.ConfirmCancelTerminal=C,n.WindowSizeAlertWindow=A,n.MainHelperBar=H,n.CanvasTerminalHolder=B,n.LevelToolbar=M,n.NextLevelConfirm=k}),e.define("/src/js/util/keyboard.js",function(e,t,n,r,i,s,o){function c(e){this.events=e.events||u.clone(a.Events),this.aliasMap=e.aliasMap||{},e.wait||this.listen()}var u=e("underscore"),a=e("backbone"),f=e("../app"),l=function(e){var t={37:"left",38:"up",39:"right",40:"down",27:"esc",13:"enter"};return t[e]};c.prototype.listen=function(){if(this.listening)return;this.listening=!0,f.getEventBaton().stealBaton("docKeydown",this.keydown,this)},c.prototype.mute=function(){this.listening=!1,f.getEventBaton().releaseBaton("docKeydown",this.keydown,this)},c.prototype.keydown=function(e){var t=e.which||e.keyCode,n=l(t);if(n===undefined)return;this.fireEvent(n,e)},c.prototype.fireEvent=function(e,t){e=this.aliasMap[e]||e,this.events.trigger(e,t)},c.prototype.passEventBack=function(e){f.getEventBaton().passBatonBackSoft("docKeydown",this.keydown,this,[e])},n.KeyboardListener=c,n.mapKeycodeToKey=l}),e.define("/node_modules/markdown/package.json",function(e,t,n,r,i,s,o){t.exports={main:"./lib/index.js"}}),e.define("/node_modules/markdown/lib/index.js",function(e,t,n,r,i,s,o){n.markdown=e("./markdown"),n.parse=n.markdown.toHTML}),e.define("/node_modules/markdown/lib/markdown.js",function(e,t,n,r,i,s,o){(function(t){function r(){return"Markdown.mk_block( "+uneval(this.toString())+", "+uneval(this.trailing)+", "+uneval(this.lineNumber)+" )"}function i(){var t=e("util");return"Markdown.mk_block( "+t.inspect(this.toString())+", "+t.inspect(this.trailing)+", "+t.inspect(this.lineNumber)+" )"}function o(e){var t=0,n=-1;while((n=e.indexOf("\n",n+1))!==-1)t++;return t}function u(e,t){function i(e){this.len_after=e,this.name="close_"+t}var n=e+"_state",r=e=="strong"?"em_state":"strong_state";return function(s,o){if(this[n][0]==t)return this[n].shift(),[s.length,new i(s.length-t.length)];var u=this[r].slice(),a=this[n].slice();this[n].unshift(t);var f=this.processInline(s.substr(t.length)),l=f[f.length-1],c=this[n].shift();if(l instanceof i){f.pop();var h=s.length-l.len_after;return[h,[e].concat(f)]}return this[r]=u,this[n]=a,[t.length,t]}}function f(e){var t=e.split(""),n=[""],r=!1;while(t.length){var i=t.shift();switch(i){case" ":r?n[n.length-1]+=i:n.push("");break;case"'":case'"':r=!r;break;case"\\":i=t.shift();default:n[n.length-1]+=i}}return n}function h(e){return l(e)&&e.length>1&&typeof e[1]=="object"&&!l(e[1])?e[1]:undefined}function d(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function v(e){if(typeof e=="string")return d(e);var t=e.shift(),n={},r=[];e.length&&typeof e[0]=="object"&&!(e[0]instanceof Array)&&(n=e.shift());while(e.length)r.push(arguments.callee(e.shift()));var i="";for(var s in n)i+=" "+s+'="'+d(n[s])+'"';return t=="img"||t=="br"||t=="hr"?"<"+t+i+"/>":"<"+t+i+">"+r.join("")+""}function m(e,t,n){var r;n=n||{};var i=e.slice(0);typeof n.preprocessTreeNode=="function"&&(i=n.preprocessTreeNode(i,t));var s=h(i);if(s){i[1]={};for(r in s)i[1][r]=s[r];s=i[1]}if(typeof i=="string")return i;switch(i[0]){case"header":i[0]="h"+i[1].level,delete i[1].level;break;case"bulletlist":i[0]="ul";break;case"numberlist":i[0]="ol";break;case"listitem":i[0]="li";break;case"para":i[0]="p";break;case"markdown":i[0]="html",s&&delete s.references;break;case"code_block":i[0]="pre",r=s?2:1;var o=["code"];o.push.apply(o,i.splice(r)),i[r]=o;break;case"inlinecode":i[0]="code";break;case"img":i[1].src=i[1].href,delete i[1].href;break;case"linebreak":i[0]="br";break;case"link":i[0]="a";break;case"link_ref":i[0]="a";var u=t[s.ref];if(!u)return s.original;delete s.ref,s.href=u.href,u.title&&(s.title=u.title),delete s.original;break;case"img_ref":i[0]="img";var u=t[s.ref];if(!u)return s.original;delete s.ref,s.src=u.href,u.title&&(s.title=u.title),delete s.original}r=1;if(s){for(var a in i[1])r=2;r===1&&i.splice(r,1)}for(;r0&&!l(o[0]))&&this.debug(i[s],"didn't return a proper array"),o}return[]},n.prototype.processInline=function(t){return this.dialect.inline.__call__.call(this,String(t))},n.prototype.toTree=function(t,n){var r=t instanceof Array?t:this.split_blocks(t),i=this.tree;try{this.tree=n||this.tree||["markdown"];e:while(r.length){var s=this.processBlock(r.shift(),r);if(!s.length)continue e;this.tree.push.apply(this.tree,s)}return this.tree}finally{n&&(this.tree=i)}},n.prototype.debug=function(){var e=Array.prototype.slice.call(arguments);e.unshift(this.debug_indent),typeof print!="undefined"&&print.apply(print,e),typeof console!="undefined"&&typeof console.log!="undefined"&&console.log.apply(null,e)},n.prototype.loop_re_over_block=function(e,t,n){var r,i=t.valueOf();while(i.length&&(r=e.exec(i))!=null)i=i.substr(r[0].length),n.call(this,r);return i},n.dialects={},n.dialects.Gruber={block:{atxHeader:function(t,n){var r=t.match(/^(#{1,6})\s*(.*?)\s*#*\s*(?:\n|$)/);if(!r)return undefined;var i=["header",{level:r[1].length}];return Array.prototype.push.apply(i,this.processInline(r[2])),r[0].length1&&n.unshift(r);for(var s=0;s1&&typeof i[i.length-1]=="string"?i[i.length-1]+=o:i.push(o)}}function f(e,t){var n=new RegExp("^("+i+"{"+e+"}.*?\\n?)*$"),r=new RegExp("^"+i+"{"+e+"}","gm"),o=[];while(t.length>0){if(n.exec(t[0])){var u=t.shift(),a=u.replace(r,"");o.push(s(a,u.trailing,u.lineNumber))}break}return o}function l(e,t,n){var r=e.list,i=r[r.length-1];if(i[1]instanceof Array&&i[1][0]=="para")return;if(t+1==n.length)i.push(["para"].concat(i.splice(1)));else{var s=i.pop();i.push(["para"].concat(i.splice(1)),s)}}var e="[*+-]|\\d+\\.",t=/[*+-]/,n=/\d+\./,r=new RegExp("^( {0,3})("+e+")[ ]+"),i="(?: {0,3}\\t| {4})";return function(e,n){function s(e){var n=t.exec(e[2])?["bulletlist"]:["numberlist"];return h.push({list:n,indent:e[1]}),n}var i=e.match(r);if(!i)return undefined;var h=[],p=s(i),d,v=!1,m=[h[0].list],g;e:for(;;){var y=e.split(/(?=\n)/),b="";for(var w=0;wh.length)p=s(i),d.push(p),d=p[1]=["listitem"];else{var N=!1;for(g=0;gi[0].length&&(b+=E+S.substr(i[0].length))}b.length&&(a(d,v,this.processInline(b),E),v=!1,b="");var C=f(h.length,n);C.length>0&&(c(h,l,this),d.push.apply(d,this.toTree(C,[])));var k=n[0]&&n[0].valueOf()||"";if(k.match(r)||k.match(/^ /)){e=n.shift();var L=this.dialect.block.horizRule(e,n);if(L){m.push.apply(m,L);break}c(h,l,this),v=!0;continue e}break}return m}}(),blockquote:function(t,n){if(!t.match(/^>/m))return undefined;var r=[];if(t[0]!=">"){var i=t.split(/\n/),s=[];while(i.length&&i[0][0]!=">")s.push(i.shift());t=i.join("\n"),r.push.apply(r,this.processBlock(s.join("\n"),[]))}while(n.length&&n[0][0]==">"){var o=n.shift();t=new String(t+t.trailing+o),t.trailing=o.trailing}var u=t.replace(/^> ?/gm,""),a=this.tree;return r.push(this.toTree(u,["blockquote"])),r},referenceDefn:function(t,n){var r=/^\s*\[(.*?)\]:\s*(\S+)(?:\s+(?:(['"])(.*?)\3|\((.*?)\)))?\n?/;if(!t.match(r))return undefined;h(this.tree)||this.tree.splice(1,0,{});var i=h(this.tree);i.references===undefined&&(i.references={});var o=this.loop_re_over_block(r,t,function(e){e[2]&&e[2][0]=="<"&&e[2][e[2].length-1]==">"&&(e[2]=e[2].substring(1,e[2].length-1));var t=i.references[e[1].toLowerCase()]={href:e[2]};e[4]!==undefined?t.title=e[4]:e[5]!==undefined&&(t.title=e[5])});return o.length&&n.unshift(s(o,t.trailing)),[]},para:function(t,n){return[["para"].concat(this.processInline(t))]}}},n.dialects.Gruber.inline={__oneElement__:function(t,n,r){var i,s,o=0;n=n||this.dialect.inline.__patterns__;var u=new RegExp("([\\s\\S]*?)("+(n.source||n)+")");i=u.exec(t);if(!i)return[t.length,t];if(i[1])return[i[1].length,i[1]];var s;return i[2]in this.dialect.inline&&(s=this.dialect.inline[i[2]].call(this,t.substr(i.index),i,r||[])),s=s||[i[2].length,i[2]],s},__call__:function(t,n){function s(e){typeof e=="string"&&typeof r[r.length-1]=="string"?r[r.length-1]+=e:r.push(e)}var r=[],i;while(t.length>0)i=this.dialect.inline.__oneElement__.call(this,t,n,r),t=t.substr(i.shift()),c(i,s);return r},"]":function(){},"}":function(){},"\\":function(t){return t.match(/^\\[\\`\*_{}\[\]()#\+.!\-]/)?[2,t[1]]:[1,"\\"]},"![":function(t){var n=t.match(/^!\[(.*?)\][ \t]*\([ \t]*(\S*)(?:[ \t]+(["'])(.*?)\3)?[ \t]*\)/);if(n){n[2]&&n[2][0]=="<"&&n[2][n[2].length-1]==">"&&(n[2]=n[2].substring(1,n[2].length-1)),n[2]=this.dialect.inline.__call__.call(this,n[2],/\\/)[0];var r={alt:n[1],href:n[2]||""};return n[4]!==undefined&&(r.title=n[4]),[n[0].length,["img",r]]}return n=t.match(/^!\[(.*?)\][ \t]*\[(.*?)\]/),n?[n[0].length,["img_ref",{alt:n[1],ref:n[2].toLowerCase(),original:n[0]}]]:[2,"!["]},"[":function b(e){var t=String(e),r=n.DialectHelpers.inline_until_char.call(this,e.substr(1),"]");if(!r)return[1,"["];var i=1+r[0],s=r[1],b,o;e=e.substr(i);var u=e.match(/^\s*\([ \t]*(\S+)(?:[ \t]+(["'])(.*?)\2)?[ \t]*\)/);if(u){var a=u[1];i+=u[0].length,a&&a[0]=="<"&&a[a.length-1]==">"&&(a=a.substring(1,a.length-1));if(!u[3]){var f=1;for(var l=0;l]+)|(.*?@.*?\.[a-zA-Z]+))>/))!=null?n[3]?[n[0].length,["link",{href:"mailto:"+n[3]},n[3]]]:n[2]=="mailto"?[n[0].length,["link",{href:n[1]},n[1].substr("mailto:".length)]]:[n[0].length,["link",{href:n[1]},n[1]]]:[1,"<"]},"`":function(t){var n=t.match(/(`+)(([\s\S]*?)\1)/);return n&&n[2]?[n[1].length+n[2].length,["inlinecode",n[3]]]:[1,"`"]}," \n":function(t){return[3,["linebreak"]]}},n.dialects.Gruber.inline["**"]=u("strong","**"),n.dialects.Gruber.inline.__=u("strong","__"),n.dialects.Gruber.inline["*"]=u("em","*"),n.dialects.Gruber.inline._=u("em","_"),n.buildBlockOrder=function(e){var t=[];for(var n in e){if(n=="__order__"||n=="__call__")continue;t.push(n)}e.__order__=t},n.buildInlinePatterns=function(e){var t=[];for(var n in e){if(n.match(/^__.*__$/))continue;var r=n.replace(/([\\.*+?|()\[\]{}])/g,"\\$1").replace(/\n/,"\\n");t.push(n.length==1?r:"(?:"+r+")")}t=t.join("|"),e.__patterns__=t;var i=e.__call__;e.__call__=function(e,n){return n!=undefined?i.call(this,e,n):i.call(this,e,t)}},n.DialectHelpers={},n.DialectHelpers.inline_until_char=function(e,t){var n=0,r=[];for(;;){if(e[n]==t)return n++,[n,r];if(n>=e.length)return null;res=this.dialect.inline.__oneElement__.call(this,e.substr(n)),n+=res[0],r.push.apply(r,res.slice(1))}},n.subclassDialect=function(e){function t(){}function n(){}return t.prototype=e.block,n.prototype=e.inline,{block:new t,inline:new n}},n.buildBlockOrder(n.dialects.Gruber.block),n.buildInlinePatterns(n.dialects.Gruber.inline),n.dialects.Maruku=n.subclassDialect(n.dialects.Gruber),n.dialects.Maruku.processMetaHash=function(t){var n=f(t),r={};for(var i=0;i1)return undefined;if(!t.match(/^(?:\w+:.*\n)*\w+:.*$/))return undefined;h(this.tree)||this.tree.splice(1,0,{});var r=t.split(/\n/);for(p in r){var i=r[p].match(/(\w+):\s*(.*)$/),s=i[1].toLowerCase(),o=i[2];this.tree[1][s]=o}return[]},n.dialects.Maruku.block.block_meta=function(t,n){var r=t.match(/(^|\n) {0,3}\{:\s*((?:\\\}|[^\}])*)\s*\}$/);if(!r)return undefined;var i=this.dialect.processMetaHash(r[2]),s;if(r[1]===""){var o=this.tree[this.tree.length-1];s=h(o);if(typeof o=="string")return undefined;s||(s={},o.splice(1,0,s));for(a in i)s[a]=i[a];return[]}var u=t.replace(/\n.*$/,""),f=this.processBlock(u,[]);s=h(f[0]),s||(s={},f[0].splice(1,0,s));for(a in i)s[a]=i[a];return f},n.dialects.Maruku.block.definition_list=function(t,n){var r=/^((?:[^\s:].*\n)+):\s+([\s\S]+)$/,i=["dl"],s;if(!(a=t.match(r)))return undefined;var o=[t];while(n.length&&r.exec(n[0]))o.push(n.shift());for(var u=0;u-1&&(a(e)?i=i.split("\n").map(function(e){return" "+e}).join("\n").substr(2):i="\n"+i.split("\n").map(function(e){return" "+e}).join("\n"))):i=o("[Circular]","special"));if(typeof n=="undefined"){if(g==="Array"&&t.match(/^\d+$/))return i;n=JSON.stringify(""+t),n.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(n=n.substr(1,n.length-2),n=o(n,"name")):(n=n.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),n=o(n,"string"))}return n+": "+i});s.pop();var E=0,S=w.reduce(function(e,t){return E++,t.indexOf("\n")>=0&&E++,e+t.length+1},0);return S>50?w=y[0]+(m===""?"":m+"\n ")+" "+w.join(",\n ")+" "+y[1]:w=y[0]+m+" "+w.join(", ")+" "+y[1],w}var s=[],o=function(e,t){var n={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},r={special:"cyan",number:"blue","boolean":"yellow","undefined":"grey","null":"bold",string:"green",date:"magenta",regexp:"red"}[t];return r?"["+n[r][0]+"m"+e+"["+n[r][1]+"m":e};return i||(o=function(e,t){return e}),u(e,typeof r=="undefined"?2:r)};var h=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];n.log=function(e){},n.pump=null;var d=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t},v=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.hasOwnProperty.call(e,n)&&t.push(n);return t},m=Object.create||function(e,t){var n;if(e===null)n={__proto__:null};else{if(typeof e!="object")throw new TypeError("typeof prototype["+typeof e+"] != 'object'");var r=function(){};r.prototype=e,n=new r,n.__proto__=e}return typeof t!="undefined"&&Object.defineProperties&&Object.defineProperties(n,t),n};n.inherits=function(e,t){e.super_=t,e.prototype=m(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})};var g=/%[sdj%]/g;n.format=function(e){if(typeof e!="string"){var t=[];for(var r=0;r=s)return e;switch(e){case"%s":return String(i[r++]);case"%d":return Number(i[r++]);case"%j":return JSON.stringify(i[r++]);default:return e}});for(var u=i[r];r0&&this._events[e].length>n&&(this._events[e].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[e].length),console.trace())}this._events[e].push(t)}else this._events[e]=[this._events[e],t];return this},u.prototype.on=u.prototype.addListener,u.prototype.once=function(e,t){var n=this;return n.on(e,function r(){n.removeListener(e,r),t.apply(this,arguments)}),this},u.prototype.removeListener=function(e,t){if("function"!=typeof t)throw new Error("removeListener only takes instances of Function");if(!this._events||!this._events[e])return this;var n=this._events[e];if(a(n)){var r=f(n,t);if(r<0)return this;n.splice(r,1),n.length==0&&delete this._events[e]}else this._events[e]===t&&delete this._events[e];return this},u.prototype.removeAllListeners=function(e){return e&&this._events&&this._events[e]&&(this._events[e]=null),this},u.prototype.listeners=function(e){return this._events||(this._events={}),this._events[e]||(this._events[e]=[]),a(this._events[e])||(this._events[e]=[this._events[e]]),this._events[e]}}),e.define("/src/js/dialogs/nextLevel.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Great Job!!","","You solved the level in *{numCommands}* command(s); ","our solution uses {best}."]}}],ja:[{type:"ModalAlert",options:{markdowns:["## 完成!","","あなたは*{numCommands}*回のコマンドでこの課題をクリアしました; ","模範解答では{best}回です。"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 碉堡了!","","你用 *{numCommands}* 条命令搞定了这一关;我们的答案要用 {best}。"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Beau Travail!!","","Vous avez résolu le niveau en *{numCommands}* commande(s); ","notre solution le fait en {best}."]}}]}}),e.define("/src/js/models/commandModel.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../util/errors"),l=e("../git/commands"),c=l.GitOptionParser,h=e("../level/parseWaterfall").ParseWaterfall,p=f.CommandProcessError,d=f.GitError,v=f.Warning,m=f.CommandResult,g=a.Model.extend({defaults:{status:"inqueue",rawStr:null,result:"",createTime:null,error:null,warnings:null,parseWaterfall:new h,generalArgs:null,supportedMap:null,options:null,method:null},initialize:function(e){this.initDefaults(),this.validateAtInit(),this.on("change:error",this.errorChanged,this),this.get("error")&&this.errorChanged(),this.parseOrCatch()},initDefaults:function(){this.set("generalArgs",[]),this.set("supportedMap",{}),this.set("warnings",[])},validateAtInit:function(){if(this.get("rawStr")===null)throw new Error("Give me a string!");this.get("createTime")||this.set("createTime",(new Date).toString())},setResult:function(e){this.set("result",e)},finishWith:function(e){this.set("status","finished"),e.resolve()},addWarning:function(e){this.get("warnings").push(e),this.set("numWarnings",this.get("numWarnings")?this.get("numWarnings")+1:1)},getFormattedWarnings:function(){if(!this.get("warnings").length)return"";var e='';return"

"+e+this.get("warnings").join("

"+e)+"

"},parseOrCatch:function(){this.expandShortcuts(this.get("rawStr"));try{this.processInstants()}catch(e){f.filterError(e),this.set("error",e);return}if(this.parseAll())return;this.set("error",new p({msg:'The command "'+this.get("rawStr")+"\" isn't supported, sorry!"}))},errorChanged:function(){var e=this.get("error");e instanceof p||e instanceof d?this.set("status","error"):e instanceof m?this.set("status","finished"):e instanceof v&&this.set("status","warning"),this.formatError()},formatError:function(){this.set("result",this.get("error").toResult())},expandShortcuts:function(e){e=this.get("parseWaterfall").expandAllShortcuts(e),this.set("rawStr",e)},processInstants:function(){var e=this.get("rawStr");if(!e.length)throw new m({msg:""});this.get("parseWaterfall").processAllInstants(e)},parseAll:function(){var e=this.get("rawStr"),t=this.get("parseWaterfall").parseAll(e);return t?(u.each(t.toSet,function(e,t){this.set(t,e)},this),!0):!1}}),y=a.Model.extend({defaults:{text:""}});n.CommandEntry=y,n.Command=g}),e.define("/src/js/git/commands.js",function(e,t,n,r,i,s,o){function y(e,t){this.method=e,this.rawOptions=t,this.supportedMap=this.getMasterOptionMap()[e];if(this.supportedMap===undefined)throw new Error("No option map for "+e);this.generalArgs=[],this.explodeAndSet()}var u=e("underscore"),a=e("../intl"),f=e("../util/errors"),l=f.CommandProcessError,c=f.GitError,h=f.Warning,p=f.CommandResult,d={"git commit":/^(gc|git ci)($|\s)/,"git add":/^ga($|\s)/,"git checkout":/^(go|git co)($|\s)/,"git rebase":/^gr($|\s)/,"git branch":/^(gb|git br)($|\s)/,"git status":/^(gst|gs|git st)($|\s)/,"git help":/^git$/},v=[[/^git help($|\s)/,function(){var e=[a.str("git-version"),"
",a.str("git-usage"),u.escape(a.str("git-usage-command")),"
",a.str("git-supported-commands"),"
"],t=y.prototype.getMasterOptionMap();u.each(t,function(t,n){e.push("git "+n),u.each(t,function(t,n){e.push(" "+n)},this)},this);var n=e.join("\n");throw n=n.replace(/\t/g,"   "),new p({msg:n})}]],m={"git commit":/^git +commit($|\s)/,"git add":/^git +add($|\s)/,"git checkout":/^git +checkout($|\s)/,"git rebase":/^git +rebase($|\s)/,"git reset":/^git +reset($|\s)/,"git branch":/^git +branch($|\s)/,"git revert":/^git +revert($|\s)/,"git log":/^git +log($|\s)/,"git merge":/^git +merge($|\s)/,"git show":/^git +show($|\s)/,"git status":/^git +status($|\s)/,"git cherry-pick":/^git +cherry-pick($|\s)/,"git fakeTeamwork":/^git +fakeTeamwork($|\s)/,"git fetch":/^git +fetch *?$/,"git pull":/^git +pull($|\s)/,"git push":/^git +push($|\s)/,"git clone":/^git +clone *?$/},g=function(e){var t,n;u.each(m,function(r,i){r.exec(e)&&(n=e.slice(i.length+1),t=i.slice("git ".length))});if(!t)return!1;var r=new y(t,n);return{toSet:{generalArgs:r.generalArgs,supportedMap:r.supportedMap,method:t,options:n,eventName:"processGitCommand"}}};y.prototype.getMasterOptionMap=function(){return{commit:{"--amend":!1,"-a":!1,"-am":!1,"-m":!1},status:{},log:{},add:{},"cherry-pick":{},branch:{"-d":!1,"-D":!1,"-f":!1,"-a":!1,"-r":!1,"--contains":!1},checkout:{"-b":!1,"-B":!1,"-":!1},reset:{"--hard":!1,"--soft":!1},merge:{},rebase:{"-i":!1},revert:{},show:{},clone:{},fetch:{},pull:{"--rebase":!1},push:{},fakeTeamwork:{}}},y.prototype.explodeAndSet=function(){var e=this.rawOptions.match(/('.*?'|".*?"|\S+)/g)||[];for(var t=0;t","show commands","show solution","show goal"];throw new v({msg:t.join("\n")})}],[/^locale (\w+)$/,function(t){f.GLOBAL.locale=t[1];var n=e("../app").getEvents().trigger("localeChanged");throw new v({msg:l.str("locale-command",{locale:t[1]})})}],[/^refresh$/,function(){var t=e("../app").getEvents();throw t.trigger("refreshTree"),new v({msg:l.str("refresh-tree-command")})}],[/^rollup (\d+)$/,function(t){var n=e("../app").getEvents();throw n.trigger("rollupCommands",t[1]),new v({msg:"Commands combined!"})}],[/^echo "(.*?)"$|^echo (.*?)$/,function(e){var t=e[1]||e[2];throw new v({msg:t})}],[/^show +commands$/,function(e){var t=y(),n=[l.str("show-all-commands"),"
"];throw u.each(t,function(e,t){n.push(t)}),new v({msg:n.join("\n")})}]],g={"reset solved":/^reset solved($|\s)/,help:/^help( +general)?$|^\?$/,reset:/^reset( +--forSolution)?$/,delay:/^delay (\d+)$/,clear:/^clear($|\s)/,"exit level":/^exit level($|\s)/,sandbox:/^sandbox($|\s)/,level:/^level\s?([a-zA-Z0-9]*)/,levels:/^levels($|\s)/,mobileAlert:/^mobile alert($|\s)/,"build level":/^build +level($|\s)/,"export tree":/^export +tree$/,"import tree":/^import +tree$/,"import level":/^import +level$/,undo:/^undo($|\s)/},y=function(){var t=["mobileAlert"],n=u.extend({},e("../git/commands").regexMap,e("../level").regexMap,g);return u.each(t,function(e){delete n[e]}),n};n.instantCommands=m,n.parse=a.genParseCommand(g,"processSandboxCommand"),n.getOptimisticLevelParse=function(){return a.genParseCommand(e("../level").regexMap,"processLevelCommand")},n.getOptimisticLevelBuilderParse=function(){return a.genParseCommand(e("../level/builder").regexMap,"processLevelBuilderCommand")}}),e.define("/src/js/level/builder.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("../util"),c=e("../app"),h=e("../intl"),p=e("../util/errors"),d=e("../visuals/visualization").Visualization,v=e("../level/parseWaterfall").ParseWaterfall,m=e("../level").Level,g=e("../models/commandModel").Command,y=e("../git/gitShim").GitShim,b=e("../views/multiView").MultiView,w=e("../views").CanvasTerminalHolder,E=e("../views").ConfirmCancelTerminal,S=e("../views").NextLevelConfirm,x=e("../views").LevelToolbar,T=e("../views/builderViews").MarkdownPresenter,N=e("../views/builderViews").MultiViewBuilder,C=e("../views/builderViews").MarkdownGrabber,k={"define goal":/^define goal$/,"define name":/^define name$/,"help builder":/^help builder$/,"define start":/^define start$/,"edit dialog":/^edit dialog$/,"show start":/^show start$/,"hide start":/^hide start$/,"define hint":/^define hint$/,finish:/^finish$/},L=l.genParseCommand(k,"processLevelBuilderCommand"),A=m.extend({initialize:function(t){t=t||{},t.level=t.level||{};var n=h.getLocale();t.level.startDialog={},t.level.startDialog[n]={childViews:h.getDialog(e("../dialogs/levelBuilder"))},A.__super__.initialize.apply(this,[t]),this.startDialogObj=undefined,this.definedGoal=!1,delete this.treeCompare,delete this.solved},initName:function(){this.levelToolbar=new x({name:h.str("level-builder")})},initGoalData:function(){this.level.goalTreeString='{"branches":{"master":{"target":"C1","id":"master"},"makeLevel":{"target":"C2","id":"makeLevel"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"}},"HEAD":{"target":"makeLevel","id":"HEAD"}}',this.level.solutionCommand="git checkout -b makeLevel; git commit",A.__super__.initGoalData.apply(this,arguments)},initStartVisualization:function(){return this.startCanvasHolder=new w({additionalClass:"startTree",text:h.str("hide-start")}),this.startVis=new d({el:this.startCanvasHolder.getCanvasLocation(),containerElement:this.startCanvasHolder.getCanvasLocation(),treeString:this.level.startTree,noKeyboardInput:!0,smallCanvas:!0,noClick:!0}),this.startCanvasHolder},startOffCommand:function(){c.getEventBaton().trigger("commandSubmitted","echo :D")},objectiveDialog:function(e,t){var n=[e,t,this.startDialogObj===undefined?null:{startDialog:{en_US:this.startDialogObj}}];A.__super__.objectiveDialog.apply(this,n)},initParseWaterfall:function(e){A.__super__.initParseWaterfall.apply(this,[e]),this.parseWaterfall.addFirst("parseWaterfall",L),this.parseWaterfall.addFirst("instantWaterfall",this.getInstantCommands())},buildLevel:function(e,t){this.exitLevel(),setTimeout(function(){c.getSandbox().buildLevel(e,t)},this.getAnimationTime()*1.5)},getInstantCommands:function(){return[[/^help$|^\?$/,function(){throw new p.CommandResult({msg:h.str("help-vague-builder")})}]]},takeControl:function(){c.getEventBaton().stealBaton("processLevelBuilderCommand",this.processLevelBuilderCommand,this),A.__super__.takeControl.apply(this)},releaseControl:function(){c.getEventBaton().releaseBaton("processLevelBuilderCommand",this.processLevelBuilderCommand,this),A.__super__.releaseControl.apply(this)},showGoal:function(){this.hideStart(),A.__super__.showGoal.apply(this,arguments)},showStart:function(e,t){this.hideGoal(),this.showSideVis(e,t,this.startCanvasHolder,this.initStartVisualization)},resetSolution:function(){this.gitCommandsIssued=[],this.level.solutionCommand=undefined},hideStart:function(e,t){this.hideSideVis(e,t,this.startCanvasHolder)},defineStart:function(e,t){this.hideStart(),e.addWarning(h.str("define-start-warning")),this.resetSolution(),this.level.startTree=this.mainVis.gitEngine.printTree(),this.mainVis.resetFromThisTreeNow(this.level.startTree),this.showStart(e,t)},defineGoal:function(e,t){this.hideGoal();if(!this.gitCommandsIssued.length){e.set("error",new p.GitError({msg:h.str("solution-empty")})),t.resolve();return}this.definedGoal=!0,this.level.solutionCommand=this.gitCommandsIssued.join(";"),this.level.goalTreeString=this.mainVis.gitEngine.printTree(),this.initGoalVisualization(),this.showGoal(e,t)},defineName:function(e,t){this.level.name={en_US:prompt(h.str("prompt-name"))},e&&e.finishWith(t)},defineHint:function(e,t){this.level.hint={en_US:prompt(h.str("prompt-hint"))},e&&e.finishWith(t)},editDialog:function(e,t){var n=f.defer();this.currentBuilder=new N({multiViewJSON:this.startDialogObj,deferred:n}),n.promise.then(u.bind(function(e){this.startDialogObj=e},this)).fail(function(){}).done(function(){e?e.finishWith(t):t.resolve()})},finish:function(e,t){if(!this.gitCommandsIssued.length||!this.definedGoal){e.set("error",new p.GitError({msg:h.str("solution-empty")})),t.resolve();return}while(!this.level.name)this.defineName();var n=f.defer(),r=n.promise;if(this.level.hint===undefined){var i=f.defer();r=r.then(function(){return i.promise});var s=new E({markdowns:[h.str("want-hint")]});s.getPromise().then(u.bind(this.defineHint,this)).fail(u.bind(function(){this.level.hint={en_US:""}},this)).done(function(){i.resolve()})}if(this.startDialogObj===undefined){var o=f.defer();r=r.then(function(){return o.promise});var a=new E({markdowns:[h.str("want-start-dialog")]});a.getPromise().then(u.bind(function(){var e=f.defer();return this.editDialog(undefined,e),e.promise},this)).fail(function(){}).done(function(){o.resolve()})}r=r.done(u.bind(function(){new T({fillerText:JSON.stringify(this.getExportObj(),null,2),previewText:h.str("share-json")}),e.finishWith(t)},this)),n.resolve()},getExportObj:function(){var e=u.extend({},this.level);return delete e.startDialog,this.startDialogObj&&(e.startDialog={en_US:this.startDialogObj}),e},processLevelBuilderCommand:function(e,t){var n={"define goal":this.defineGoal,"define start":this.defineStart,"show start":this.showStart,"hide start":this.hideStart,finish:this.finish,"define hint":this.defineHint,"define name":this.defineName,"edit dialog":this.editDialog,"help builder":A.__super__.startDialog};if(!n[e.get("method")])throw new Error("woah we dont support that method yet");n[e.get("method")].apply(this,arguments)},afterCommandDefer:function(e,t){e.resolve()},die:function(){this.hideStart(),A.__super__.die.apply(this,arguments),delete this.startVis,delete this.startCanvasHolder}});n.LevelBuilder=A,n.regexMap=k}),e.define("/src/js/git/gitShim.js",function(e,t,n,r,i,s,o){function c(e){e=e||{},this.beforeCB=e.beforeCB||function(){},this.afterCB=e.afterCB||function(){};var t=function(e){e.resolve()};this.beforeDeferHandler=e.beforeDeferHandler||t,this.afterDeferHandler=e.afterDeferHandler||t,this.eventBaton=e.eventBaton||f.getEventBaton()}var u=e("underscore"),a=e("q"),f=e("../app"),l=e("../views/multiView").MultiView;c.prototype.insertShim=function(){this.eventBaton.stealBaton("processGitCommand",this.processGitCommand,this)},c.prototype.removeShim=function(){this.eventBaton.releaseBaton("processGitCommand",this.processGitCommand,this)},c.prototype.processGitCommand=function(e,t){this.beforeCB(e);var n=a.defer();n.promise.then(u.bind(function(){this.afterGitCommandProcessed(e,t)},this)).done();var r=u.bind(function(){this.eventBaton.passBatonBack("processGitCommand",this.processGitCommand,this,[e,n])},this),i=a.defer();i.promise.then(r).done(),this.beforeDeferHandler(i,e)},c.prototype.afterGitCommandProcessed=function(e,t){this.afterCB(e);var n=a.defer();n.promise.then(function(){t.resolve()}).done(),this.afterDeferHandler(n,e)},n.GitShim=c}),e.define("/src/js/views/multiView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../views").ModalTerminal,c=e("../views").ContainedBase,h=e("../views").ConfirmCancelView,p=e("../views").LeftRightView,d=e("../views").ModalAlert,v=e("../views/gitDemonstrationView").GitDemonstrationView,m=e("../views/builderViews"),g=m.MarkdownPresenter,y=e("../util/keyboard").KeyboardListener,b=e("../util/errors").GitError,w=f.View.extend({tagName:"div",className:"multiView",navEventDebounce:550,deathTime:700,typeToConstructor:{ModalAlert:d,GitDemonstrationView:v,MarkdownPresenter:g},initialize:function(e){e=e||{},this.childViewJSONs=e.childViews||[{type:"ModalAlert",options:{markdown:"Woah wtf!!"}},{type:"GitDemonstrationView",options:{command:"git checkout -b side; git commit; git commit"}},{type:"ModalAlert",options:{markdown:"Im second"}}],this.deferred=e.deferred||a.defer(),this.childViews=[],this.currentIndex=0,this.navEvents=u.clone(f.Events),this.navEvents.on("negative",this.getNegFunc(),this),this.navEvents.on("positive",this.getPosFunc(),this),this.navEvents.on("quit",this.finish,this),this.navEvents.on("exit",this.finish,this),this.keyboardListener=new y({events:this.navEvents,aliasMap:{left:"negative",right:"positive",enter:"positive",esc:"quit"}}),this.render(),e.wait||this.start()},onWindowFocus:function(){},getAnimationTime:function(){return 700},getPromise:function(){return this.deferred.promise},getPosFunc:function(){return u.debounce(u.bind(function(){this.navForward()},this),this.navEventDebounce,!0)},getNegFunc:function(){return u.debounce(u.bind(function(){this.navBackward()},this),this.navEventDebounce,!0)},lock:function(){this.locked=!0},unlock:function(){this.locked=!1},navForward:function(){if(this.locked)return;if(this.currentIndex===this.childViews.length-1){this.hideViewIndex(this.currentIndex),this.finish();return}this.navIndexChange(1)},navBackward:function(){if(this.currentIndex===0)return;this.navIndexChange(-1)},navIndexChange:function(e){this.hideViewIndex(this.currentIndex),this.currentIndex+=e,this.showViewIndex(this.currentIndex)},hideViewIndex:function(e){this.childViews[e].hide()},showViewIndex:function(e){this.childViews[e].show()},finish:function(){this.keyboardListener.mute(),u.each(this.childViews,function(e){e.die()}),this.deferred.resolve()},start:function(){this.showViewIndex(this.currentIndex)},createChildView:function(e){var t=e.type;if(!this.typeToConstructor[t])throw new Error('no constructor for type "'+t+'"');var n=new this.typeToConstructor[t](u.extend({},e.options,{wait:!0}));return n},addNavToView:function(e,t){var n=new p({events:this.navEvents,destination:e.getDestination(),showLeft:t!==0,lastNav:t===this.childViewJSONs.length-1});e.receiveMetaNav&&e.receiveMetaNav(n,this)},render:function(){u.each(this.childViewJSONs,function(e,t){var n=this.createChildView(e);this.childViews.push(n),this.addNavToView(n,t)},this)}});n.MultiView=w}),e.define("/src/js/views/gitDemonstrationView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../util/keyboard").KeyboardListener,h=e("../models/commandModel").Command,p=e("../views").ModalTerminal,d=e("../views").ContainedBase,v=e("../visuals/visualization").Visualization,m=d.extend({tagName:"div",className:"gitDemonstrationView box horizontal",template:u.template($("#git-demonstration-view").html()),events:{"click div.command > p.uiButton":"positive"},initialize:function(t){t=t||{},this.options=t,this.JSON=u.extend({beforeMarkdowns:["## Git Commits","","Awesome!"],command:"git commit",afterMarkdowns:["Now you have seen it in action","","Go ahead and try the level!"]},t);var n=function(t){return e("markdown").markdown.toHTML(t.join("\n"))};this.JSON.beforeHTML=n(this.JSON.beforeMarkdowns),this.JSON.afterHTML=n(this.JSON.afterMarkdowns),this.container=new p({title:t.title||"Git Demonstration"}),this.render(),this.checkScroll(),this.navEvents=u.clone(f.Events),this.navEvents.on("positive",this.positive,this),this.navEvents.on("negative",this.negative,this),this.keyboardListener=new c({events:this.navEvents,aliasMap:{enter:"positive",right:"positive",left:"negative"},wait:!0}),this.visFinished=!1,this.initVis(),t.wait||this.show()},receiveMetaNav:function(e,t){var n=this;e.navEvents.on("positive",this.positive,this),this.metaContainerView=t},checkScroll:function(){var e=this.$("div.demonstrationText").children(),t=u.map(e,function(e){return e.clientHeight}),n=u.reduce(t,function(e,t){return e+t});n15&&console.warn("graphics are degrading from too many layers");var t=this.getDepthIncrement(e);u.each(this.visNodeMap,function(e){e.setDepthBasedOn(t,this.getHeaderOffset())},this)},w.prototype.animateNodePositions=function(e){u.each(this.visNodeMap,function(t){t.animateUpdatedPosition(e)},this)},w.prototype.addBranchFromEvent=function(e,t,n){var r=u.bind(function(){this.addBranch(e)},this);!this.gitEngine||!this.gitReady?this.defer(r):r()},w.prototype.addBranch=function(e){var t=new m({branch:e,gitVisuals:this,gitEngine:this.gitEngine});this.visBranchCollection.add(t),this.gitReady?t.genGraphics(this.paper):this.defer(u.bind(function(){t.genGraphics(this.paper)},this))},w.prototype.removeVisBranch=function(e){this.visBranchCollection.remove(e)},w.prototype.removeVisNode=function(e){this.visNodeMap[e.getID()]=undefined},w.prototype.removeVisEdge=function(e){this.visEdgeCollection.remove(e)},w.prototype.animateRefs=function(e){this.visBranchCollection.each(function(t){t.animateUpdatedPos(e)},this)},w.prototype.animateEdges=function(e){this.visEdgeCollection.each(function(t){t.animateUpdatedPath(e)},this)},w.prototype.getMinLayers=function(){return this.options.smallCanvas?2:7},w.prototype.getDepthIncrement=function(e){e=Math.max(e,this.getMinLayers());var t=1-this.getHeaderOffset(),n=t/e;return n},w.prototype.shouldHaveHeader=function(){return this.gitEngine.isOrigin()||this.gitEngine.hasOrigin()},w.prototype.getHeaderOffset=function(){return this.shouldHaveHeader()?.05:0},w.prototype.calcDepthRecursive=function(e,t){e.get("visNode").setDepth(t);var n=e.get("children"),r=t;return u.each(n,function(e){var n=this.calcDepthRecursive(e,t+1);r=Math.max(n,r)},this),r},w.prototype.canvasResize=function(e,t){this.resizeFunc||this.genResizeFunc(),this.resizeFunc(e,t)},w.prototype.genResizeFunc=function(){this.resizeFunc=u.debounce(u.bind(function(t,n){this.refreshTree()},this),200,!0)},w.prototype.addNode=function(e,t){this.commitMap[e]=t,t.get("rootCommit")&&(this.rootCommit=t);var n=new v({id:e,commit:t,gitVisuals:this,gitEngine:this.gitEngine});return this.visNodeMap[e]=n,this.gitReady&&n.genGraphics(this.paper),n},w.prototype.addEdge=function(e,t){var n=this.visNodeMap[e],r=this.visNodeMap[t];if(!n||!r)throw new Error("one of the ids in ("+e+", "+t+") does not exist");var i=new y({tail:n,head:r,gitVisuals:this,gitEngine:this.gitEngine});this.visEdgeCollection.add(i),this.gitReady&&i.genGraphics(this.paper)},w.prototype.zIndexReflow=function(){this.visNodesFront(),this.visBranchesFront()},w.prototype.visNodesFront=function(){u.each(this.visNodeMap,function(e){e.toFront()})},w.prototype.visBranchesFront=function(){this.visBranchCollection.each(function(e){e.nonTextToFront(),e.textToFront()}),this.visBranchCollection.each(function(e){e.textToFrontIfInStack()})},w.prototype.drawTreeFromReload=function(){this.gitReady=!0,this.deferFlush(),this.calcTreeCoords()},w.prototype.drawTreeFirstTime=function(){this.gitReady=!0,this.calcTreeCoords(),u.each(this.visNodeMap,function(e){e.genGraphics(this.paper)},this),this.visEdgeCollection.each(function(e){e.genGraphics(this.paper)},this),this.visBranchCollection.each(function(e){e.genGraphics(this.paper)},this),this.zIndexReflow()},n.GitVisuals=w}),e.define("/src/js/visuals/visNode.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=l.extend({defaults:{depth:undefined,maxWidth:null,outgoingEdges:null,circle:null,text:null,id:null,pos:null,radius:null,commit:null,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing,fill:f.defaultNodeFill,"stroke-width":f.defaultNodeStrokeWidth,stroke:f.defaultNodeStroke},getID:function(){return this.get("id")},validateAtInit:function(){if(!this.get("id"))throw new Error("need id for mapping");if(!this.get("commit"))throw new Error("need commit for linking");this.get("pos")||this.set("pos",{x:Math.random(),y:Math.random()})},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine"),this.set("outgoingEdges",[])},setDepth:function(e){this.set("depth",Math.max(this.get("depth")||0,e))},setDepthBasedOn:function(e,t){if(this.get("depth")===undefined)throw new Error("no depth yet!");var n=this.get("pos");n.y=this.get("depth")*e+t},getMaxWidthScaled:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("commit")),t={branch:1,head:.3,none:.1};if(t[e]===undefined)throw new Error("bad stat");return t[e]*this.get("maxWidth")},toFront:function(){this.get("circle").toFront(),this.get("text").toFront()},getOpacity:function(){var e={branch:1,head:f.upstreamHeadOpacity,none:f.upstreamNoneOpacity},t=this.gitVisuals.getCommitUpstreamStatus(this.get("commit"));if(e[t]===undefined)throw new Error("invalid status");return e[t]},getTextScreenCoords:function(){return this.getScreenCoords()},getAttributes:function(){var e=this.getScreenCoords(),t=this.getTextScreenCoords(),n=this.getOpacity(),r=this.getIsInOrigin()?f.originDash:"";return{circle:{cx:e.x,cy:e.y,opacity:n,r:this.getRadius(),fill:this.getFill(),"stroke-width":this.get("stroke-width"),"stroke-dasharray":r,stroke:this.get("stroke")},text:{x:t.x,y:t.y,opacity:n}}},highlightTo:function(e,t,n){var r=e.get("fill"),i={circle:{fill:r,stroke:r,"stroke-dasharray":"","stroke-width":this.get("stroke-width")*5},text:{}};this.animateToAttr(i,t,n)},animateUpdatedPosition:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},animateToSnapshot:function(e,t,n){if(!e[this.getID()])return;this.animateToAttr(e[this.getID()],t,n)},setAttr:function(e,t,n,r){var i=["text","circle"];this.setAttrBase(i,e,t,n,r)},animateToAttr:function(e,t,n){l.prototype.animateToAttr.apply(this,arguments);var r=t!==undefined?t:this.get("animationSpeed"),i=n||this.get("animationEasing");n=="bounce"&&e.circle&&e.circle.cx!==undefined&&e.text&&e.text.x!==undefined&&(this.get("circle").animate(e.circle.cx,r,"easeInOut"),this.get("text").animate(e.text.x,r,"easeInOut"))},getScreenCoords:function(){var e=this.get("pos");return this.gitVisuals.toScreenCoords(e)},getRadius:function(){return this.get("radius")||f.nodeRadius},getParentScreenCoords:function(){return this.get("commit").get("parents")[0].get("visNode").getScreenCoords()},setBirthPosition:function(){var e=this.getParentScreenCoords();this.get("circle").attr({cx:e.x,cy:e.y,opacity:0,r:0}),this.get("text").attr({x:e.x,y:e.y,opacity:0})},setBirthFromSnapshot:function(e){var t=this.get("commit").get("parents")[0].get("visNode").getID(),n=e[t];this.get("circle").attr({opacity:0,r:0,cx:n.circle.cx,cy:n.circle.cy}),this.get("text").attr({opacity:0,x:n.text.x,y:n.text.y});var r={x:n.circle.cx,y:n.circle.cy};this.setOutgoingEdgesBirthPosition(r)},setBirth:function(){this.setBirthPosition(),this.setOutgoingEdgesBirthPosition(this.getParentScreenCoords())},setOutgoingEdgesOpacity:function(e){u.each(this.get("outgoingEdges"),function(t){t.setOpacity(e)})},animateOutgoingEdgesToAttr:function(e,t,n){u.each(this.get("outgoingEdges"),function(t){var n=e[t.getID()];t.animateToAttr(n)},this)},animateOutgoingEdges:function(e,t){u.each(this.get("outgoingEdges"),function(n){n.animateUpdatedPath(e,t)},this)},animateOutgoingEdgesFromSnapshot:function(e,t,n){u.each(this.get("outgoingEdges"),function(r){var i=e[r.getID()];r.animateToAttr(i,t,n)},this)},setOutgoingEdgesBirthPosition:function(e){u.each(this.get("outgoingEdges"),function(t){var n=t.get("head").getScreenCoords(),r=t.genSmoothBezierPathStringFromCoords(e,n);t.get("path").stop(),t.get("path").attr({path:r,opacity:0})},this)},parentInFront:function(){this.get("commit").get("parents")[0].get("visNode").toFront()},getFontSize:function(e){return e.length<3?12:e.length<5?10:8},getFill:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("commit"));return e=="head"?f.headRectFill:e=="none"?f.orphanNodeFill:this.gitVisuals.getBlendedHuesForCommit(this.get("commit"))},attachClickHandlers:function(){if(this.get("gitVisuals").options.noClick)return;var t="git checkout "+this.get("commit").get("id"),n=e("../app");u.each([this.get("circle"),this.get("text")],function(e){e.click(function(){n.getEventBaton().trigger("commandSubmitted",t)}),$(e.node).css("cursor","pointer")})},setOpacity:function(e){e=e===undefined?1:e;var t=["circle","text"];u.each(t,function(t){this.get(t).attr({opacity:e})},this)},remove:function(){this.removeKeys(["circle"],["text"]);var e=this.get("text");e&&e.remove(),this.gitVisuals.removeVisNode(this)},removeAll:function(){this.remove(),u.each(this.get("outgoingEdges"),function(e){e.remove()},this)},getExplodeStepFunc:function(){var e=this.get("circle"),t=20,n=Math.PI+Math.random()*1*Math.PI,r=.2,i=.01,s=t*Math.cos(n),o=t*Math.sin(n),u=e.attr("cx"),a=e.attr("cy"),f=this.gitVisuals.paper.width,l=this.gitVisuals.paper.height,c=.8,h=1,p=function(){o+=r*h-i*o,s-=i*s,u+=s*h,a+=o*h;if(u<0||u>f)s=c*-s,u=u<0?0:f;if(a<0||a>l)o=c*-o,a=a<0?0:l;return e.attr({cx:u,cy:a}),s*s+o*o<.01&&Math.abs(a-l)===0?!1:!0};return p},genGraphics:function(){var e=this.gitVisuals.paper,t=this.getScreenCoords(),n=this.getTextScreenCoords(),r=e.circle(t.x,t.y,this.getRadius()).attr(this.getAttributes().circle),i=e.text(n.x,n.y,String(this.get("id")));i.attr({"font-size":this.getFontSize(this.get("id")),"font-weight":"bold","font-family":"Monaco, Courier, font-monospace",opacity:this.getOpacity()}),this.set("circle",r),this.set("text",i),this.attachClickHandlers()}});n.VisNode=c}),e.define("/src/js/visuals/visBase.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({removeKeys:function(e){u.each(e,function(e){this.get(e)&&this.get(e).remove()},this)},getNonAnimateKeys:function(){return["stroke-dasharray"]},getIsInOrigin:function(){return this.get("gitEngine")?this.get("gitEngine").isOrigin():!1},animateToAttr:function(e,t,n){if(t===0){this.setAttr(e,!0);return}var r=t!==undefined?t:this.get("animationSpeed"),i=n||this.get("animationEasing");this.setAttr(e,!1,r,i)},setAttrBase:function(e,t,n,r,i){u.each(e,function(e){n?this.get(e).attr(t[e]):(this.get(e).stop(),this.get(e).animate(t[e],r,i),u.forEach(this.getNonAnimateKeys(),function(n){t[e]&&t[e][n]!==undefined&&this.get(e).attr(n,t[e][n])},this)),t.css&&$(this.get(e).node).css(t.css)},this)},animateAttrKeys:function(e,t,n,r){e=u.extend({},{include:["circle","arrow","rect","path","text"],exclude:[]},e||{});var i=this.getAttributes();u.each(e.include,function(e){i[e]=u.extend({},i[e],t)}),u.each(e.exclude,function(e){delete i[e]}),this.animateToAttr(i,n,r)}});n.VisBase=f}),e.define("/src/js/visuals/visBranch.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=function(){var e=Math.random(),t="hsb("+String(e)+",0.7,1)";return t},h=l.extend({defaults:{pos:null,text:null,rect:null,arrow:null,isHead:!1,flip:1,fill:f.rectFill,stroke:f.rectStroke,"stroke-width":f.rectStrokeWidth,offsetX:f.nodeRadius*4.75,offsetY:0,arrowHeight:14,arrowInnerSkew:0,arrowEdgeHeight:6,arrowLength:14,arrowOffsetFromCircleX:10,vPad:5,hPad:5,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing},validateAtInit:function(){if(!this.get("branch"))throw new Error("need a branch!")},getID:function(){return this.get("branch").get("id")},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine");if(!this.gitEngine)throw new Error("asd wtf");this.get("branch").set("visBranch",this);var e=this.get("branch").get("id");e=="HEAD"?(this.set("isHead",!0),this.set("flip",-1),this.refreshOffset(),this.set("fill",f.headRectFill)):e!=="master"&&this.set("fill",c())},getCommitPosition:function(){var e=this.gitEngine.getCommitFromRef(this.get("branch")),t=e.get("visNode");return this.set("flip",this.getFlipValue(e,t)),this.refreshOffset(),t.getScreenCoords()},getFlipValue:function(e,t){var n=this.get("gitVisuals").getFlipPos(),r=t.get("pos").x>n;return e.get("id")==="C0"?-1:this.get("isHead")?r?this.isBranchStackEmpty()?-1:1:this.isBranchStackEmpty()?1:-1:r?-1:1},refreshOffset:function(){var e=f.nodeRadius*4.75,t=33,n=10;this.get("flip")===1?(this.set("offsetY",-t),this.set("offsetX",e-n)):(this.set("offsetY",t),this.set("offsetX",e-n))},getArrowTransform:function(){return this.get("flip")===1?"t-2,-20R-35":"t2,20R-35"},getBranchStackIndex:function(){if(this.get("isHead"))return 0;var e=this.getBranchStackArray(),t=-1;return u.each(e,function(e,n){e.obj==this.get("branch")&&(t=n)},this),t},getBranchStackLength:function(){return this.get("isHead")?1:this.getBranchStackArray().length},isBranchStackEmpty:function(){var e=this.gitVisuals.branchStackMap[this.getCommitID()];return e?e.length===0:!0},getCommitID:function(){var e=this.get("branch").get("target");return e.get("type")==="branch"&&(e=e.get("target")),e.get("id")},getBranchStackArray:function(){var e=this.gitVisuals.branchStackMap[this.getCommitID()];return e===undefined?(this.gitVisuals.calcBranchStacks(),this.getBranchStackArray()):e},getTextPosition:function(){var e=this.getCommitPosition(),t=this.getBranchStackIndex();return{x:e.x+this.get("flip")*this.get("offsetX"),y:e.y+t*f.multiBranchY+this.get("offsetY")}},getRectPosition:function(){var e=this.getTextPosition(),t=this.get("flip"),n=this.getTextSize();return{x:e.x-.5*n.w-this.get("hPad"),y:e.y-.5*n.h-this.get("vPad")}},getArrowPath:function(){var e=function(e,t,n){return{x:e.x+t,y:e.y+n}},t=function(e){return String(Math.round(e.x))+","+String(Math.round(e.y))},n=this.get("flip"),r=e(this.getCommitPosition(),n*this.get("arrowOffsetFromCircleX"),0),i=e(r,n*this.get("arrowLength"),-this.get("arrowHeight")),s=e(r,n*this.get("arrowLength"),this.get("arrowHeight")),o=e(i,n*this.get("arrowInnerSkew"),this.get("arrowEdgeHeight")),a=e(s,n*this.get("arrowInnerSkew"),-this.get("arrowEdgeHeight")),f=49,l=e(o,n*f,0),c=e(a,n*f,0),h="";h+="M"+t(l)+" ";var p=[o,i,r,s,a,c];return u.each(p,function(e){h+="L"+t(e)+" "},this),h+="z",h},getTextSize:function(){var e=function(e){var t=e.get("text")?e.get("text").node:null;return t===null?0:t.clientWidth},t=function(e){return e.w||(e.w=75),e.h||(e.h=20),e},n=this.get("text").node;if(this.get("isHead"))return t({w:n.clientWidth,h:n.clientHeight});var r=0;return u.each(this.getBranchStackArray(),function(t){r=Math.max(r,e(t.obj.get("visBranch")))}),t({w:r,h:n.clientHeight})},getSingleRectSize:function(){var e=this.getTextSize(),t=this.get("vPad"),n=this.get("hPad");return{w:e.w+t*2,h:e.h+n*2}},getRectSize:function(){var e=this.getTextSize(),t=this.get("vPad"),n=this.get("hPad"),r=this.getBranchStackLength();return{w:e.w+t*2,h:e.h*r*1.1+n*2}},getIsRemote:function(){return this.get("branch").getIsRemote()},getName:function(){var e=this.get("branch").getName(),t=this.get("branch")===this.gitEngine.HEAD.get("target"),n=this.getIsRemote(),r=t&&!this.getIsInOrigin()&&!n?"*":"";return e+r},nonTextToFront:function(){this.get("arrow").toFront(),this.get("rect").toFront()},textToFront:function(){this.get("text").toFront()},textToFrontIfInStack:function(){this.getBranchStackIndex()!==0&&this.get("text").toFront()},getFill:function(){return this.get("isHead")||this.getBranchStackLength()==1||this.getBranchStackIndex()!==0?this.get("fill"):this.gitVisuals.blendHuesFromBranchStack(this.getBranchStackArray())},remove:function(){this.removeKeys(["text","arrow","rect"]),this.gitVisuals.removeVisBranch(this)},genGraphics:function(e){var t=this.getTextPosition(),n=this.getName(),r;r=e.text(t.x,t.y,String(n)),r.attr({"font-size":14,"font-family":"Monaco, Courier, font-monospace",opacity:this.getTextOpacity()}),this.set("text",r);var i=this.getAttributes(),s=this.getRectPosition(),o=this.getRectSize(),a=e.rect(s.x,s.y,o.w,o.h,8).attr(i.rect);this.set("rect",a);var f=this.getArrowPath(),l=e.path(f).attr(i.arrow);this.set("arrow",l);var c=["text","rect","arrow"];u.each(c,function(e){$(this.get(e).node).css(i.css)},this),this.attachClickHandlers(),a.toFront(),r.toFront()},attachClickHandlers:function(){if(this.get("gitVisuals").options.noClick)return;var e=[this.get("rect"),this.get("text"),this.get("arrow")];u.each(e,function(e){e.click(u.bind(this.onClick,this))},this)},shouldDisableClick:function(){return this.get("isHead")&&!this.gitEngine.getDetachedHead()},onClick:function(){if(this.shouldDisableClick())return;var t="git checkout "+this.get("branch").get("id"),n=e("../app");n.getEventBaton().trigger("commandSubmitted",t)},updateName:function(){this.get("text").attr({text:this.getName()})},getNonTextOpacity:function(){return this.get("isHead")?this.gitEngine.getDetachedHead()?1:0:this.getBranchStackIndex()===0?1:0},getTextOpacity:function(){return this.get("isHead")?this.gitEngine.getDetachedHead()?1:0:1},getAttributes:function(){var e=this.getNonTextOpacity(),t=this.getTextOpacity();this.updateName();var n=this.getTextPosition(),r=this.getRectPosition(),i=this.getRectSize(),s=this.getArrowPath(),o=this.getIsInOrigin()?f.originDash:"",u=this.shouldDisableClick()?"auto":"pointer";return{css:{cursor:u},text:{x:n.x,y:n.y,opacity:t},rect:{x:r.x,y:r.y,width:i.w,height:i.h,opacity:e,fill:this.getFill(),stroke:this.get("stroke"),"stroke-width":this.get("stroke-width")},arrow:{path:s,opacity:e,fill:this.getFill(),stroke:this.get("stroke"),transform:this.getArrowTransform(),"stroke-width":this.get("stroke-width")}}},animateUpdatedPos:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},setAttr:function(e,t,n,r){var i=["text","rect","arrow"];this.setAttrBase(i,e,t,n,r)}}),p=a.Collection.extend({model:h});n.VisBranchCollection=p,n.VisBranch=h,n.randomHueString=c}),e.define("/src/js/visuals/visEdge.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=l.extend({defaults:{tail:null,head:null,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing},validateAtInit:function(){var e=["tail","head"];u.each(e,function(e){if(!this.get(e))throw new Error(e+" is required!")},this)},getID:function(){return this.get("tail").get("id")+"."+this.get("head").get("id")},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine"),this.get("tail").get("outgoingEdges").push(this)},remove:function(){this.removeKeys(["path"]),this.gitVisuals.removeVisEdge(this)},genSmoothBezierPathString:function(e,t){var n=e.getScreenCoords(),r=t.getScreenCoords();return this.genSmoothBezierPathStringFromCoords(n,r)},genSmoothBezierPathStringFromCoords:function(e,t){var n=function(e){return String(Math.round(e.x))+","+String(Math.round(e.y))},r=function(e,t,n){return n=n||f.curveControlPointOffset,{x:e.x,y:e.y+n*t}},i=function(e,t,n){return{x:e.x+t,y:e.y+n}};e=r(e,-1,this.get("tail").getRadius()),t=r(t,1,this.get("head").getRadius());var s="";s+="M"+n(e)+" ",s+="C",s+=n(r(e,-1))+" ",s+=n(r(t,1))+" ",s+=n(t);var o=f.arrowHeadSize||10;return s+=" L"+n(i(t,-o,o)),s+=" L"+n(i(t,o,o)),s+=" L"+n(t),s+="C",s+=n(r(t,1))+" ",s+=n(r(e,-1))+" ",s+=n(e),s},getBezierCurve:function(){return this.genSmoothBezierPathString(this.get("tail"),this.get("head"))},getStrokeColor:function(){return f.visBranchStrokeColorNone},setOpacity:function(e){e=e===undefined?1:e,this.get("path").attr({opacity:e})},genGraphics:function(e){var t=this.getBezierCurve(),n=e.path(t).attr({"stroke-width":f.visBranchStrokeWidth,stroke:this.getStrokeColor(),"stroke-linecap":"round","stroke-linejoin":"round",fill:this.getStrokeColor()});n.toBack(),this.set("path",n)},getOpacity:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("tail")),t={branch:1,head:f.edgeUpstreamHeadOpacity,none:f.edgeUpstreamNoneOpacity};if(t[e]===undefined)throw new Error("bad stat");return t[e]},getAttributes:function(){var e=this.getBezierCurve(),t=this.getOpacity();return{path:{path:e,opacity:t}}},animateUpdatedPath:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},animateToAttr:function(e,t,n){if(t===0){this.get("path").attr(e.path);return}this.get("path").toBack(),this.get("path").stop(),this.get("path").animate(e.path,t!==undefined?t:this.get("animationSpeed"),n||this.get("animationEasing"))}}),h=a.Collection.extend({model:c});n.VisEdgeCollection=h,n.VisEdge=c}),e.define("/src/js/level/disabledMap.js",function(e,t,n,r,i,s,o){function h(e){e=e||{},this.disabledMap=e.disabledMap||{"git cherry-pick":!0,"git rebase":!0}}var u=e("underscore"),a=e("../intl"),f=e("../git/commands"),l=e("../util/errors"),c=l.GitError;h.prototype.getInstantCommands=function(){var e=[],t=function(){throw new c({msg:a.str("command-disabled")})};return u.each(this.disabledMap,function(n,r){var i=f.regexMap[r];if(!i)throw new Error("wuttttt this disbaled command"+r+" has no regex matching");e.push([i,t])}),e},n.DisabledMap=h}),e.define("/src/js/dialogs/confirmShowSolution.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Are you sure you want to see the solution?","","I believe in you! You can do it"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 确定要看答案吗?","","哥相信你!你可以的"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Êtes-vous sûr de vouloir voir la solution ?","","Je crois en vous ! Vous pouvez le faire"]}}]}}),e.define("/src/js/level/arbiter.js",function(e,t,n,r,i,s,o){function h(){this.levelMap={},this.levelSequences=f,this.sequences=[],this.init();var e;try{e=JSON.parse(localStorage.getItem("solvedMap")||"{}")}catch(t){console.warn("local storage failed",t)}this.solvedMap=e||{},c.getEvents().on("levelSolved",this.levelSolved,this)}var u=e("underscore"),a=e("backbone"),f=e("../../levels").levelSequences,l=e("../../levels").sequenceInfo,c=e("../app");h.prototype.init=function(){var e;u.each(this.levelSequences,function(e,t){this.sequences.push(t);if(!e||!e.length)throw new Error("no empty sequences allowed");u.each(e,function(e,n){this.validateLevel(e);var r=t+String(n+1),i=u.extend({},e,{index:n,id:r,sequenceName:t});this.levelMap[r]=i,this.levelSequences[t][n]=i},this)},this)},h.prototype.isLevelSolved=function(e){if(!this.levelMap[e])throw new Error("that level doesnt exist!");return Boolean(this.solvedMap[e])},h.prototype.levelSolved=function(e){if(!e)return;this.solvedMap[e]=!0,this.syncToStorage()},h.prototype.resetSolvedMap=function(){this.solvedMap={},this.syncToStorage(),c.getEvents().trigger("levelSolved")},h.prototype.syncToStorage=function(){try{localStorage.setItem("solvedMap",JSON.stringify(this.solvedMap))}catch(e){console.warn("local storage fialed on set",e)}},h.prototype.validateLevel=function(e){e=e||{};var t=["name","goalTreeString","solutionCommand"],n=["hint","disabledMap","startTree"];u.each(t,function(t){if(e[t]===undefined)throw console.log(e),new Error("I need this field for a level: "+t)})},h.prototype.getSequenceToLevels=function(){return this.levelSequences},h.prototype.getSequences=function(){return u.keys(this.levelSequences)},h.prototype.getLevelsInSequence=function(e){if(!this.levelSequences[e])throw new Error("that sequecne name "+e+"does not exist");return this.levelSequences[e]},h.prototype.getSequenceInfo=function(e){return l[e]},h.prototype.getLevel=function(e){return this.levelMap[e]},h.prototype.getNextLevel=function(e){if(!this.levelMap[e])return console.warn("that level doesnt exist!!!"),null;var t=this.levelMap[e],n=t.sequenceName,r=this.levelSequences[n],i=t.index+1;if(i master -> C1",""],afterMarkdowns:["And now it's","","HEAD -> C1"],command:"git checkout C1",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["To complete this level, let's detach HEAD from `bugFix` and attach it to the commit instead.","","Specify this commit by its hash. The hash for each commit is displayed on the circle that represents the commit."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 在Git中前后移动","","在接触Git的更多高级主题之前,我们先学习用不同的方法在代表你的项目的提交记录树上前后移动。","","一旦能够熟练地在Git中前进后退,你使用其他git命令的威力也会被放大!","","","","",""]}},{type:"ModalAlert",options:{markdowns:["## HEAD","",'我们首先看一下"HEAD". HEAD是当前提交记录的符号名称 -- 其实就是你正在其基础进行工作的提交记录。',"","HEAD总是指向最近一次提交记录,表现为当前工作树。大多数修改工作树的git命令都开始于改变HEAD指向。","","HEAD通常指向分支名(比如bugFix)。你提交时,改变了bugFix的状态,这一变化通过HEAD变得可见。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["在实例中看一下。我们将会观察提交前后HEAD的位置。"],afterMarkdowns:["看! HEAD一直藏在`master`分支后面。"],command:"git checkout C1; git checkout master; git commit; git checkout C2",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["### 分离 HEAD","","分离HEAD就是让其指向一个提交记录而不是分支名。这是命令执行之前的样子: ","","HEAD -> master -> C1",""],afterMarkdowns:["现在变成了","","HEAD -> C1"],command:"git checkout C1",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["想完成此关,从`bugFix`分离出HEAD并让其指向一个提交记录。","","通过hash值指定提交记录。每个提交记录的hash值显示在代表提交记录的圆圈中。"]}}]}}}}),e.define("/levels/rampup/relativeRefs.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"C3","id":"HEAD"}}',solutionCommand:"git checkout bugFix^",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Relative Refs (^)",zh_CN:"相对引用(^)"},hint:{en_US:"Remember the Caret (^) operator!",zh_CN:"记住插入(^)操作符!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Relative Refs","","Moving around in Git by specifying commit hashes can get a bit tedious. In the real world you won't have a nice commit tree visualization next to your terminal, so you'll have to use `git log` to see hashes.","","Furthermore, hashes are usually a lot longer in the real Git world as well. For instance, the hash of the commit that introduced the previous level is `fed2da64c0efc5293610bdd892f82a58e8cbc5d8`. Doesn't exactly roll off the tongue...","","The upside is that Git is smart about hashes. It only requires you to specify enough characters of the hash until it uniquely identifies the commit. So I can type `fed2` instead of the long string above."]}},{type:"ModalAlert",options:{markdowns:["Like I said, specifying commits by their hash isn't the most convenient thing ever, which is why Git has relative refs. They are awesome!","","With relative refs, you can start somewhere memorable (like the branch `bugFix` or `HEAD`) and work from there.","","Relative commits are powerful, but we will introduce two simple ones here:","","* Moving upwards one commit at a time with `^`","* Moving upwards a number of times with `~`"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's look at the Caret (^) operator first. Each time you append that to a ref name, you are telling Git to find the parent of the specified commit.","",'So saying `master^` is equivalent to "the first parent of `master`".',"","`master^^` is the grandparent (second-generation ancestor) of `master`","","Let's check out the commit above master here"],afterMarkdowns:["Boom! Done. Way easier than typing the commit hash"],command:"git checkout master^",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["You can also reference `HEAD` as a relative ref. Let's use that a couple of times to move upwards in the commit tree"],afterMarkdowns:["Easy! We can travel backwards in time with `HEAD^`"],command:"git checkout C3; git checkout HEAD^; git checkout HEAD^; git checkout HEAD^",beforeCommand:"git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["To complete this level, check out the parent commit of `bugFix`. This will detach `HEAD`.","","You can specify the hash if you want, but try using relative refs instead!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 相对引用","","用指定提交记录hash值的方式在Git中移动会变得比较乏味。在现实中,你不会有漂亮的可视化的提交记录树放在终端旁边,所以你不得不用`git log`来查看hasn值。","","另外,hash值在真实的Git环境中也会更长。举个例子,前一关的介绍中的提交记录的hash值是`fed2da64c0efc5293610bdd892f82a58e8cbc5d8`。不要把舌头闪了...","","好的一面是,Git对hash的处理很智能。你只需要提供能够唯一标识提交记录的前几个字符即可。所以,我可以仅输入`fed2`而不是上面的一长串字符。"]}},{type:"ModalAlert",options:{markdowns:["我说过,通过hash指定提交记录不是很方便,所以Git引入了相对引用。这个就很牛掰了!","","使用相对引用,你可以从一个易于记忆的地方(比如分支名`bugFix`或`HEAD`)开始工作。","","相对引用非常给力,这里我介绍两个简单的用法:","","* 使用`^`向上移动1个提交记录","* 使用`~`向上移动多个提交记录"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["首先看看插入(^)操作符。把插入符跟在引用名后面,表示让Git寻找指定提交记录的父提交。","",'所以`master^`相当于"`master`的父提交"。',"","`master^^`是`master`的父父提交(上上代祖先)","","切换到master的父提交"],afterMarkdowns:["唰!搞定。这种方式比输入提交记录的hash值简单多了!"],command:"git checkout master^",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["你也可以`HEAD`把用作相对引用。以下命令使用`HEAD`在提交树中向上移动几次。"],afterMarkdowns:["简单!我们可以一直使用`HEAD^`向上移动。"],command:"git checkout C3; git checkout HEAD^; git checkout HEAD^; git checkout HEAD^",beforeCommand:"git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["要完成此关,切换到`bugFix`的父提交。这会分离出`HEAD`.","","如果你愿意的话,使用hash值也可以过关,但为何不试试使用相对引用呢?"]}}]}}}}),e.define("/levels/rampup/relativeRefs2.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C6","id":"master"},"bugFix":{"target":"C0","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C5":{"parents":["C3"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"C1","id":"HEAD"}}',solutionCommand:"git branch -f master C6;git checkout HEAD~1;git branch -f bugFix HEAD~1",startTree:'{"branches":{"master":{"target":"C4","id":"master"},"bugFix":{"target":"C5","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C5":{"parents":["C3"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"C2","id":"HEAD"}}',hint:{en_US:"You'll need to use at least one direct reference (hash) to complete this level",zh_CN:"这一关至少要用到一次直接引用(hash)"},name:{en_US:"Relative Refs #2 (~)",zh_CN:"相对引用2(~)"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:['### The "~" operator',"","Say you want to move a lot of levels up in the commit tree. It might be tedious to type `^` several times, so Git also has the tilde (~) operator.","","","The tilde operator (optionally) takes in a trailing number that specifies the number of parents you would like to ascend. Let's see it in action"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's specify a number of commits back with `~`."],afterMarkdowns:["Boom! So concise -- relative refs are great."],command:"git checkout HEAD~4",beforeCommand:"git commit; git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["### Branch forcing","","You're an expert on relative refs now, so let's actually *use* them for something.","","One of the most common ways I use relative refs is to move branches around. You can directly reassign a branch to a commit with the `-f` option. So something like:","","`git branch -f master HEAD~3`","","Moves (by force) the master branch to three parents behind HEAD."]}},{type:"ModalAlert",options:{markdowns:["To complete this level, move `HEAD`, `master`, and `bugFix` to their goal destinations shown."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:['### The "~" operator',"","假设需要在提交树中向上移动很多步。使用多个`^`非常无聊,所以Git也引入了波浪(~)操作符。","","","波浪操作符后面可以(可选地)跟一个数字,指定向上移动多少次。看个例子"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用`~`一次后退多步."],afterMarkdowns:["唰!如此简洁--相对引用就是好啊!"],command:"git checkout HEAD~4",beforeCommand:"git commit; git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["### Branch forcing","","你现在是相对引用的高手了,现在*用*他来实际做点事情。","","我使用相对引用最多的就是移动分支。你可以使用`-f`选项把直接让分支指向另一个提交。举个例子:","","`git branch -f master HEAD~3`","","(强制)移动master指向HEAD的第3级父提交。"]}},{type:"ModalAlert",options:{markdowns:["要完成此关,移动`HEAD`,`master`和`bugFix`到目标所示的位置。"]}}]}}}}),e.define("/levels/rampup/reversingChanges.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22master%22%7D%2C%22pushed%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22pushed%22%7D%2C%22local%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22local%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C2%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22pushed%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git reset HEAD~1;git checkout pushed;git revert HEAD",compareOnlyBranches:!0,startTree:'{"branches":{"master":{"target":"C1","id":"master"},"pushed":{"target":"C2","id":"pushed"},"local":{"target":"C3","id":"local"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"}},"HEAD":{"target":"local","id":"HEAD"}}',name:{en_US:"Reversing Changes in Git",ja:"変更を元に戻す",fr_FR:"Annuler des changements avec Git",ko:"Git에서 작업 되돌리기",zh_CN:"在Git中撤销更改"},hint:{en_US:"Notice that revert and reset take different arguments.",fr_FR:"",zh_CN:"注意revert和reset使用不同的参数。",ko:"",ja:""},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Reversing Changes in Git","","There are many ways to reverse changes in Git. And just like committing, reversing changes in Git has both a low-level component (staging individual files or chunks) and a high-level component (how the changes are actually reversed). Our application will focus on the latter.","","There are two primary ways to undo changes in Git -- one is using `git reset` and the other is using `git revert`. We will look at each of these in the next dialog",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","",'`git reset` reverts changes by moving a branch reference backwards in time to an older commit. In this sense you can think of it as "rewriting history;" `git reset` will move a branch backwards as if the commit had never been made in the first place.',"","Let's see what that looks like:"],afterMarkdowns:["Nice! Git simply moved the master branch reference back to `C1`; now our local repository is in a state as if `C2` had never happened"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","",'While reseting works great for local branches on your own machine, its method of "rewriting history" doesn\'t work for remote branches that others are using.',"","In order to reverse changes and *share* those reversed changes with others, we need to use `git revert`. Let's see it in action"],afterMarkdowns:["Weird, a new commit plopped down below the commit we wanted to reverse. That's because this new commit `C2'` introduces *changes* -- it just happens to introduce changes that exactly reverses the commit of `C2`.","","With reverting, you can push out your changes to share with others."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["To complete this level, reverse the two most recent commits on both `local` and `pushed`.","","Keep in mind that `pushed` is a remote branch and `local` is a local branch -- that should help you choose your methods."]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## 変更を元に戻す","","Gitでは変更を元に戻す方法がたくさんあります。コミットと同じように、低レベルな動作(ファイル別だったりファイルの中の一部だったり)も高レベルな動作(変更のまとまりのキャンセル)もできます。このアプリケーションでは後者の方法について紹介します。","","基本的なアンドゥの方法が2つあります - 一つは`git reset`を使う方法で、もう1つは`git revert`を使う方法です。次のダイアログで一つ一つを見ていきます。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","","`git reset`はブランチのポインタを後方に移動することで変更のキャンセルを実現します。履歴を上書きするような動作だと思うと良いでしょうか:`git reset`はそもそも前のコミットなんかなかったかのように、ブランチのポインタを元に戻してくれます。","","どういう感じか見てみましょう。"],afterMarkdowns:["いいですね!Gitは単純にmasterブランチへのポインタを`C1`へ戻しました。これでこのローカルリポジトリにはまるで`C2`なんて無かったかのように変更をキャンセルできました。"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","自分のマシン上のブランチではさっきの`git reset`でうまくいきましたが、この「履歴を上書きする」手段は、他の人も使っているリモートにあるリポジトリに対しては使うことができません。","","変更を巻き戻して他の人とそれを共有するためには、`git revert`を使う必要があります。今度はこれを見てみましょう。"],afterMarkdowns:["あれ、おかしいな。巻き戻したいと思ってたコミットの下に新しいコミットが出来上がってしまったみたいです。なぜか。これは、この新しい`C2'`コミットは`C2`へ戻すのに必要な内容を確かに変更して巻き戻していたのです。","","こんな風にして、巻き戻した内容を他人と共有するためにはrevertを使います。"],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["この章の仕上げに、`local`と`pushed`の両方の直近のコミットを巻き戻してみましょう。","","`pushed`はリモートのブランチで、`local`はローカルであることに注意。正しくコマンドを使い分けましょう。"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Annuler des changements avec Git","","Il y a de nombreuses façons d'annuler des changement avec Git. De même que pour les commits, annuler des changements avec Git a à la fois un aspect bas-niveau (gestion dans le 'staging' des fichiers et morceaux de fichiers) et un aspect de plus haut niveau 9comment les changements sont effectivement annulés). Nous allons nous intéresser à ce dernier point.","","Il y a principalement deux façons d'annuler des changements avec Git -- l'une est `git reset` et l'autre est `git revert`. Nous allons maintenant voir chacune de ces façons",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","","`git reset` annule des changements en déplaçant la référence en arrière dans le temps sur un commit plus ancien. En ce sens, on peut considérer cela comme une façon de \"réécrire l'histoire\"; `git reset` fait remonter une branche en arrière comme si le(s) commit(s) n'avait jamais eu lieu.","","Regardons à quoi cela ressemble :"],afterMarkdowns:["Bravo ! Git a simplement déplacé la référence de la branche master en la faisant revenir sur `C1`; désormais notre dépôt est dans le même état que si `C2` n'avait jamais eu lieu"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","Bien que le reset marche parfaitement pour les branches locales sur notre propre machine, cette façon de \"réécrire l'histoire\" ne marche pas avec les banches distantes (remote) que d'autres personnes utilisent.","","Pour pouvoir annuler des changements et *partager* ces annulations avec d'autres, nous devons utiliser `git revert`. Regardons comment cela fonctionne"],afterMarkdowns:["Étrangement, un nouveau commit est appaaru en bas sous le commit que nous voulions annuler. C'est parce que ce nouveau commit `C2'` introduit des *modifications* -- celles qui correspondent justement à l'annulation de celles du commit `C2`.","","Avec revert, vous pouvez diffuser (push) vos modifications et les partager avec tout le monde."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["Pour accomplir ce niveau, annulez les deux derniers commits à la fois sur `local` et sur `pushed`.","","Ayez à l'esprit que `pushed` est une branche distante et `local` est une branche locale -- cela devrait vous guider dans le choix de la méthode à employer."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 撤销 Git 里面的变动","","在 Git 里撤销修改的方法很多。和 commit 一样,在 Git 里撤销变动同时具有底层部分(暂存一些独立的文件或者片段)和高层部分(具体到变动是究竟怎么被撤销的)。我们这个应用主要关注后者。","","在 Git 里主要用两种方法来撤销变动 —— 一种是 `git reset`,另外一种是 `git revert`。让我们在下一个窗口逐一了解它们。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","",'`git reset`把分支记录回退到上一个提交记录来实现撤销改动。你可以认为这是在"重写历史"。`git reset`往回移动分支,原来指向的提交记录好像重来没有提交过一样。',"","让我们看看具体的操作:"],command:"git reset HEAD~1",afterMarkdowns:["Nice!Git把master分支的指向简单地移回到`C1`;现在我们的本地代码库处于没有提交过`C2`的状态了。"],beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","虽然在你的本地分支中使用`git reset`很方便,但是这种“改写历史”的方法对别人的远端分支是无效的哦!","","为了撤销更改并*传播*给别人,我们需要使用`git revert`。举个例子"],command:"git revert HEAD",afterMarkdowns:["怪哉!在我们要撤销的提交记录后面居然多了一个新提交!这是因为新提交记录`C2'`引入了*更改*——刚好是用来撤销 `C2` 这个提交的。","","借助 revert,现在可以把你的更改传递给别人啦。"],beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["要完成此关,分别撤销`local`分支和`pushed`分支上的最近一次提交。","","记住 `pushed` 是一个远程分支,`local` 是一个本地分支 —— 有了这么明显的提示应该知道用哪种方法了吧?"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git에서 작업 되돌리기","","Git에는 작업한 것을 되돌리는 여러가지 방법이 있습니다. 변경내역을 되돌리는 것도 커밋과 마찬가지로 낮은 수준의 일(개별 파일이나 묶음을 스테이징 하는 것)과 높은 수준의 일(실제 변경이 복구되는 방법)이 있는데요, 여기서는 후자에 집중해 알려드릴게요.","","Git에서 변경한 내용을 되돌리는 방법은 크게 두가지가 있습니다 -- 하나는 `git reset`을 쓰는거고, 다른 하나는 `git revert`를 사용하는 것입니다. 다음 화면에서 하나씩 알아보겠습니다.",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git 리셋(reset)","",'`git reset`은 브랜치로 하여금 예전의 커밋을 가리키도록 이동시키는 방식으로 변경 내용을 되돌립니다. 이런 관점에서 "히스토리를 고쳐쓴다"라고 말할 수 있습니다. 즉, `git reset`은 마치 애초에 커밋하지 않은 것처럼 예전 커밋으로 브랜치를 옮기는 것입니다.',"","어떤 그림인지 한번 보죠:"],afterMarkdowns:["그림에서처럼 master 브랜치가 가리키던 커밋을 `C1`로 다시 옮겼습니다; 이러면 로컬 저장소에는 마치 `C2`커밋이 아예 없었던 것과 마찬가지 상태가 됩니다."],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git 리버트(revert)","",'각자의 컴퓨터에서 작업하는 로컬 브랜치의 경우 리셋(reset)을 잘 쓸 수 있습니다만, "히스토리를 고쳐쓴다"는 점 때문에 다른 사람이 작업하는 리모트 브랜치에는 쓸 수 없습니다.',"","변경분을 되돌리고, 이 되돌린 내용을 다른 사람들과 *공유하기* 위해서는, `git revert`를 써야합니다. 예제로 살펴볼게요."],afterMarkdowns:["어색하게도, 우리가 되돌리려고한 커밋의 아래에 새로운 커밋이 생겼습니다. `C2`라는 새로운 커밋에 *변경내용*이 기록되는데요, 이 변경내역이 정확히 `C2` 커밋 내용의 반대되는 내용입니다.","","리버트를 하면 다른 사람들에게도 변경 내역을 밀어(push) 보낼 수 있습니다."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["이 레벨을 통과하려면, `local` 브랜치와 `pushed` 브랜치에 있는 최근 두 번의 커밋을 되돌려 보세요.","","`pushed`는 리모트 브랜치이고, `local`은 로컬 브랜치임을 신경쓰셔서 작업하세요 -- 어떤 방법을 선택하실지 떠오르시죠?"]}}]}}}}),e.define("/levels/rebase/manyRebases.js",function(e,t,n,r,i,s,o){n.level={compareOnlyMasterHashAgnostic:!0,disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22master%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22bugFix%22%7D%2C%22side%22%3A%7B%22target%22%3A%22C6%27%22%2C%22id%22%3A%22side%22%7D%2C%22another%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22another%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C6%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C6%22%7D%2C%22C7%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C7%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C6%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C6%27%22%7D%2C%22C7%27%22%3A%7B%22parents%22%3A%5B%22C6%27%22%5D%2C%22id%22%3A%22C7%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout bugFix;git rebase master;git checkout side;git rebase bugFix;git checkout another;git rebase side;git rebase another master",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C3","id":"bugFix"},"side":{"target":"C6","id":"side"},"another":{"target":"C7","id":"another"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C0"],"id":"C4"},"C5":{"parents":["C4"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"},"C7":{"parents":["C5"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Rebasing over 9000 times",ko:"9천번이 넘는 리베이스",ja:"Rebasing over 9000 times",zh_CN:"N次Rebase"},hint:{en_US:"Remember, the most efficient way might be to only update master at the end...",ja:"最も効率的なやり方はmasterを最後に更新するだけかもしれない・・・",ko:"아마도 master를 마지막에 업데이트하는 것이 가장 효율적인 방법일 것입니다...",zh_CN:"记住,最后更新master分支可能是最高效的方法。"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["### Rebasing Multiple Branches","","Man, we have a lot of branches going on here! Let's rebase all the work from these branches onto master.","","Upper management is making this a bit trickier though -- they want the commits to all be in sequential order. So this means that our final tree should have `C7'` at the bottom, `C6'` above that, etc etc, etc all in order.","","If you mess up along the way, feel free to use `reset` to start over again. Be sure to check out our solution and see if you can do it in fewer commands!"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["### 複数のブランチをリベースする","","さあ、いくつものブランチが出てきます。このブランチたち全てをmasterブランチにリベースしましょう。","","おエライさん方が今回の仕事を少しトリッキーにしてくれました ― コミットはすべて一列のシーケンシャルな状態にしてほしいそうです。つまり私たちが作るリポジトリの最終的なツリーの状態は、`C7'`が最後に来て、`C6'`がその一つ上に来て、、と順に積み重なるイメージです。","","試行錯誤してツリーが汚くなってきたら、`reset`コマンドを使ってツリーの状態を初期化してください。模範解答をチェックして、それよりも簡単なコマンドで済ませられるかどうか、を考えるのも忘れずに!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["### 多分支衍合","","呐,现在我们有很多分支啦!让我们rebase这些分支的工作到 master 分支上吧。","","但是你的头头找了点麻烦 —— 他们希望得到有序的提交历史,也就是我们最终的结果是 `C7'` 在最底部,`C6'` 在它上面,以此类推。","","假如你搞砸了,没所谓的(虽然我不会告诉你用 `reset` 可以重新开始)。记得看看我们提供的答案,看你能否使用更少的命令完成任务!"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["### 여러 브랜치를 리베이스(rebase)하기 ","","음, 여기 꽤 여러개의 브랜치가 있습니다! 이 브랜치들의 모든 작업내역을 master에 리베이스 해볼까요?","","윗선에서 일을 복잡하게 만드네요 -- 그 분들이 이 모든 커밋들을 순서에 맞게 정렬하라고 합니다. 그럼 결국 우리의 최종 목표 트리는 제일 아래에 `C7'` 커밋, 그 위에 `C6'` 커밋, 또 그 위에 순서대로 보여합니다.","","만일 작업중에 내용이 꼬인다면, `reset`이라고 쳐서 처음부터 다시 시작할 수 있습니다. 모범 답안을 확인해 보시고, 혹시 더 적은 수의 커맨드로 해결할 수 있는지 알아보세요!"]}}]}}}}),e.define("/levels/mixed/grabbingOneCommit.js",function(e,t,n,r,i,s,o){n.level={compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C4>e.C1}]},disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22master%22%7D%2C%22debug%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22debug%22%7D%2C%22printf%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22printf%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22bugFix%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout master;git cherry-pick C4",startTree:'{"branches":{"master":{"target":"C1","id":"master"},"debug":{"target":"C2","id":"debug"},"printf":{"target":"C3","id":"printf"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"bugFix","id":"HEAD"}}',name:{ko:"딱 한개의 커밋만 가져오기",en_US:"Grabbing Just 1 Commit",ja:"Grabbing Just 1 Commit",zh_CN:"只取一个提交"},hint:{en_US:"Remember, interactive rebase or cherry-pick is your friend here",ja:"このレベルではインタラクティブモードのrebaseやcherry-pickがクリアのカギです",ko:"대화식 리베이스(rebase -i)나 or 체리픽(cherry-pick)을 사용하세요",zh_CN:"记住,交互式 rebase 或者 cherry-pick 会很有帮助"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Locally stacked commits","","Here's a development situation that often happens: I'm trying to track down a bug but it is quite elusive. In order to aid in my detective work, I put in a few debug commands and a few print statements.","","All of these debugging / print statements are in their own branches. Finally I track down the bug, fix it, and rejoice!","","Only problem is that I now need to get my `bugFix` back into the `master` branch! I could simply fast-forward `master`, but then `master` would get all my debug statements."]}},{type:"ModalAlert",options:{markdowns:["This is where the magic of Git comes in. There are a few ways to do this, but the two most straightforward ways are:","","* `git rebase -i`","* `git cherry-pick`","","Interactive (the `-i`) rebasing allows you to choose which commits you want to keep or discard. It also allows you to reorder commits. This can be helpful if you want to toss out some work.","","Cherry-picking allows you to pick individual commits and plop them down on top of `HEAD`"]}},{type:"ModalAlert",options:{markdowns:["This is a later level so we will leave it up to you to decide, but in order to complete the level, make sure `master` receives the commit that `bugFix` references."]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ローカルに積み上がったコミット","","実際の開発ではこういうケースがよくあります:「バグの原因調査を試みているがバグの再現性がかなり低い。調査の補助のために、いくつかのデバッグ用の命令やprint文を差し込んでいる。」","","これらのデバッグ用のコードはバグ修正用のブランチにコミットされています。そしてついにバグの原因を突き止めて、修正した!やった!","","あとは`bugFix`ブランチを`master`ブランチに統合できればOK。そこで単純に`master`をfast-forwardすればよいかというと、それでは`master`ブランチの中にデバッグ用のコードも混入してしまいます。"]}},{type:"ModalAlert",options:{markdowns:["ここでGitの魔法が力を発揮します。解決のためにはいくつかの方法がありますが、最も素直な解決方法は2つあって:","","* `git rebase -i`","* `git cherry-pick`","","インタラクティブモードの(`-i`オプションつきの)rebaseによって、保持したいコミットと破棄したいコミットを選り分けることができます。コミットの順序を変更することも可能です。この方法は、一部の変更をどこかへやってしまいたい時に便利です。","","もう一方のcherry-pickを使うと、持っていきたいコミットを選んで`HEAD`の先にストンと落とすことができます。"]}},{type:"ModalAlert",options:{markdowns:["後半の章ですのでどう解決するかをもう自分で考えることができると思います。このレベルをクリアするためには、`bugFix`が持っているコミットを`master`ブランチが受け取る必要がある点には注意してください。"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 本地栈式提交 (Locally stacked commits)","","设想一下一个经常发生的场景:我在追踪一个有点棘手的 bug,为了更好地排查,我添加了一些调试命令和打印语句。","","所有的这些调试和打印语句都只在它们自己的分支里。最终我终于找到这个 bug,揪出来 fix 掉,然后撒花庆祝!","","现在唯一的问题就是要把我在 `bugFix` 分支里的工作合并回 `master` 分支。我可以简单地把 `master` 分支快进(fast-forward),但这样的话 `master` 分支就会包含我这些调试语句了。"]}},{type:"ModalAlert",options:{markdowns:["现在就是 Git 大显神通的时候啦。解决这个问题的方法不止一个,但最直接的两个方法是:","","* `git rebase -i`","* `git cherry-pick`","","交互(`-i`)衍合允许你选择哪些提交是要被保留,哪些要被舍弃。它允许你将提交重新排序。假如你要舍弃一些工作,这个会帮上很大的忙。","","Cherry-picking 能让你选择单独一个提交并且把它放到 `HEAD` 的最前端。"]}},{type:"ModalAlert",options:{markdowns:["本关是可选关卡,玩不玩随便你。但是如果你坚持要刷,确保 `master` 分支能拿到 `bugFix` 分支的相关提交(references)。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 로컬에 쌓인 커밋들","","개발중에 종종 이런 상황이 생깁니다: 잘 띄지 않는 버그를 찾아서 해결하려고, 어떤 부분의 문제인지를 찾기 위해 디버그용 코드와 화면에 정보를 프린트하는 코드 몇 줄 넣습니다. ","","디버깅용 코드나 프린트 명령은 그 브랜치에 들어있습니다. 마침내 버그를 찾아서 고쳤고, 원래 작업하는 브랜치에 합치면 됩니다!","","이제 `bugFix`브랜치의 내용을 `master`에 합쳐 넣으려 하지만, 한 가지 문제가 있습니다. 그냥 간단히 `master`브랜치를 최신 커밋으로 이동시킨다면(fast-forward) 그 불필요한 디버그용 코드들도 함께 들어가 버린다는 문제죠."]}},{type:"ModalAlert",options:{markdowns:["여기에서 Git의 마법이 드러납니다. 이 문제를 해결하는 여러가지 방법이 있습니다만, 가장 간단한 두가지 방법 아래와 같습니다:","","* `git rebase -i`","* `git cherry-pick`","","대화형 (-i 옵션) 리베이스(rebase)로는 어떤 커밋을 취하거나 버릴지를 선택할 수 있습니다. 또 커밋의 순서를 바꿀 수도 있습니다. 이 커맨드로 어떤 작업의 일부만 골라내기에 유용합니다.","","체리픽(cherry-pick)은 개별 커밋을 골라서 `HEAD`위에 떨어뜨릴 수 있습니다."]}},{type:"ModalAlert",options:{markdowns:["이번 레벨을 통과하기 위해 어떤 방법을 쓰시든 자유입니다만, `master`브랜치가 `bugFix` 브랜치의 커밋을 일부 가져오게 해주세요."]}}]}}}}),e.define("/levels/mixed/jugglingCommits.js",function(e,t,n,r,i,s,o){n.level={disabledMap:{"git cherry-pick":!0,"git revert":!0},compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C2>e.C3},function(e){return e.C2>e.C1}]},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%27%27%22%2C%22id%22%3A%22master%22%7D%2C%22newImage%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22newImage%22%7D%2C%22caption%22%3A%7B%22target%22%3A%22C3%27%27%22%2C%22id%22%3A%22caption%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%2C%22C2%27%27%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%27%27%22%7D%2C%22C3%27%27%22%3A%7B%22parents%22%3A%5B%22C2%27%27%27%22%5D%2C%22id%22%3A%22C3%27%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git rebase -i HEAD~2;git commit --amend;git rebase -i HEAD~2;git rebase caption master",startTree:'{"branches":{"master":{"target":"C1","id":"master"},"newImage":{"target":"C2","id":"newImage"},"caption":{"target":"C3","id":"caption"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"caption","id":"HEAD"}}',name:{ko:"커밋들 갖고 놀기",en_US:"Juggling Commits",ja:"Juggling Commits",zh_CN:"提交变换戏法"},hint:{en_US:"The first command is git rebase -i HEAD~2",ja:"最初に打つコマンドはgit rebase -i HEAD~2",ko:"첫번째 명령은 git rebase -i HEAD~2 입니다",zh_CN:"第一个命令是 'git rebase -i HEAD~2'"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Juggling Commits","","Here's another situation that happens quite commonly. You have some changes (`newImage`) and another set of changes (`caption`) that are related, so they are stacked on top of each other in your repository (aka one after another).","","The tricky thing is that sometimes you need to make a small modification to an earlier commit. In this case, design wants us to change the dimensions of `newImage` slightly, even though that commit is way back in our history!!"]}},{type:"ModalAlert",options:{markdowns:["We will overcome this difficulty by doing the following:","","* We will re-order the commits so the one we want to change is on top with `git rebase -i`","* We will `commit --amend` to make the slight modification","* Then we will re-order the commits back to how they were previously with `git rebase -i`","* Finally, we will move master to this updated part of the tree to finish the level (via the method of your choosing)","","There are many ways to accomplish this overall goal (I see you eye-ing cherry-pick), and we will see more of them later, but for now let's focus on this technique."]}},{type:"ModalAlert",options:{markdowns:["Lastly, pay attention to the goal state here -- since we move the commits twice, they both get an apostrophe appended. One more apostrophe is added for the commit we amend, which gives us the final form of the tree ","","That being said, I can compare levels now based on structure and relative apostrophe differences. As long as your tree's `master` branch has the same structure and relative apostrophe differences, I'll give full credit"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Commitsをやりくりする","","開発中に頻繁に起こるケースをもう1つ考えます。ある変更(`newImage`)とまた別の変更(`caption`)があって、それらに依存関係があるとします。この一連の変更が一列に積み重なっているとします。","","ここでトリッキーなのは、以前のコミットに対して微修正をかけなければならないケースがあるということです。今回の教材でも、過去のコミットであるにも関わらず`newImage`ブランチに僅かな修正を加えるような設計の修正が入ったとしましょう。"]}},{type:"ModalAlert",options:{markdowns:["この困難な状況を、以下の手順で克服することを考えます:","","* `git rebase -i`を使って順番を変更する。これで、変更をかけたいコミットを一番先頭に持ってくる。","* `commit --amend`コマンドで僅かな変更を行う","* `git rebase -i`コマンドを再度使って、先頭に持ってきていたコミットを元に戻す","* 最後に、レベルクリアのためにmasterブランチを先頭に持ってくる","","クリアのための方法はいくつもありますが(cherry-pickを使うこともできます)、別の回答はまた後程の章で見ることにんして、今回は上記の方法でやってみることにしましょう。"]}},{type:"ModalAlert",options:{markdowns:["最後に、ゴール時点での状態に気を付けてください。今回2回ほどコミットを動かしますから、コミットへのポインタにはアポストロフィ(')が追加されます。commit --amendコマンドの実行でできたコミットには更にもう1つのアポストロフィが追加されます。 "]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 提交变换戏法","","下面这种情况也是经常出现的。例如你之前已经在 `newImage` 分支上做了一些提交,然后又在 `caption` 分支上做了一些相关的提交,因此它们看起来是一个连一个的(stacked on top of each other in your repository)。","","有点棘手的就是有时候你又想往先前的提交里做些小改动。呐,现在就是设计师想要我们去轻微改变下 `newImage` 的内容(change the dimensions slightly),尽管那个提交是很久很久以前的了。"]}},{type:"ModalAlert",options:{markdowns:["为了实现他的愿望,我们可以按照下面的方法来做:","","* 先用 `git rebase -i` 将提交重新排序,然后把我们想要修改的提交挪到最前","* 然后用 `commit --amend` 来进行一些小修改","* 接着再用 `git rebase -i` 来将他们按最开始的顺序重新排好","* 最后我们把 master 移到修改的最前端(用你自己喜欢的方法),就大功告成啦!","","当然还有许多方法可以完成这个任务(我知道你在看 cherry-pick 啦),之后我们会多点关注这些技巧啦,但现在暂时只专注上面这种方法。"]}},{type:"ModalAlert",options:{markdowns:["啊最后还要提醒你一下最终的形式 —— 因为我们把这个提交移动了两次,所以会分别产生一个省略提交(both get an apostrophe appended)。还有一个省略提交是因为我们为了实现最终效果去修改提交而添加的。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 커밋들 갖고 놀기","","이번에도 꽤 자주 발생하는 상황입니다. `newImage`와 `caption` 브랜치에 각각의 변경내역이 있고 서로 약간 관련이 있어서, 저장소에 차례로 쌓여있는 상황입니다.","","때로는 이전 커밋의 내용을 살짝 바꿔야하는 골치아픈 상황에 빠지게 됩니다. 이번에는 디자인 쪽에서 우리의 작업이력(history)에서는 이미 한참 전의 커밋 내용에 있는 `newImage`의 크기를 살짝 바꿔달라는 요청이 들어왔습니다."]}},{type:"ModalAlert",options:{markdowns:["이 문제를 다음과 같이 풀어봅시다:","","* `git rebase -i` 명령으로 우리가 바꿀 커밋을 가장 최근 순서로 바꾸어 놓습니다","* `commit --amend` 명령으로 커밋 내용을 정정합니다","* 다시 `git rebase -i` 명령으로 이 전의 커밋 순서대로 되돌려 놓습니다","* 마지막으로, master를 지금 트리가 변경된 부분으로 이동합니다. (편하신 방법으로 하세요)","","이 목표를 달성하기 위해서는 많은 방법이 있는데요(체리픽을 고민중이시죠?), 체리픽은 나중에 더 살펴보기로 하고, 우선은 위의 방법으로 해결해보세요."]}},{type:"ModalAlert",options:{markdowns:["최종적으로, 목표 결과를 눈여겨 보세요 -- 우리가 커밋을 두 번 옮겼기 때문에, 두 커밋 모두 따옴표 표시가 붙어있습니다. 정정한(amend) 커밋은 따옴표가 추가로 하나 더 붙어있습니다."]}}]}}}}),e.define("/levels/mixed/jugglingCommits2.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22master%22%7D%2C%22newImage%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22newImage%22%7D%2C%22caption%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22caption%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%27%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout master;git cherry-pick C2;git commit --amend;git cherry-pick C3",disabledMap:{"git revert":!0},startTree:'{"branches":{"master":{"target":"C1","id":"master"},"newImage":{"target":"C2","id":"newImage"},"caption":{"target":"C3","id":"caption"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"caption","id":"HEAD"}}',compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C2>e.C3},function(e){return e.C2>e.C1}]},name:{ko:"커밋 갖고 놀기 #2",en_US:"Juggling Commits #2",ja:"コミットをやりくりする その2",zh_CN:"提交交换戏法 #2"},hint:{en_US:"Don't forget to forward master to the updated changes!",ja:"masterのポインタを先に進めることを忘れずに!",ko:"master를 변경 완료한 커밋으로 이동(forward)시키는 것을 잊지 마세요!",zh_CN:"别忘记了将 master 快进到最新的更新上!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Juggling Commits #2","","*If you haven't completed Juggling Commits #1 (the previous level), please do so before continuing*","","As you saw in the last level, we used `rebase -i` to reorder the commits. Once the commit we wanted to change was on top, we could easily --amend it and re-order back to our preferred order.","","The only issue here is that there is a lot of reordering going on, which can introduce rebase conflicts. Let's look at another method with `git cherry-pick`"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Remember that git cherry-pick will plop down a commit from anywhere in the tree onto HEAD (as long as that commit isn't upstream).","","Here's a small refresher demo:"],afterMarkdowns:["Nice! Let's move on"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["So in this level, let's accomplish the same objective of amending `C2` once but avoid using `rebase -i`. I'll leave it up to you to figure it out! :D","","Remember, the exact number of apostrophe's (') on the commit are not important, only the relative differences. For example, I will give credit to a tree that matches the goal tree but has one extra apostrophe everywhere"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## コミットをやりくりする その2","","*注意 この一つ前のレベル「コミットをやりくりする」をクリアしていない人は、まずそちらの問題をクリアしてきてください*","","前回見てきたように、コミット順序の変更のために、私たちは`rebase -i`コマンドを利用しました。ツリーの先頭に変更対象のコミットがあれば、--amendオプションを使うことで容易に変更を書きかえて、元の順序に戻すことができます。","","この場合に心配なことが一つだけあって、それは複数回の順序の変更が行われるので、rebaseのコンフリクト(衝突)が起こりうることです。こういうケースへの対策として、`git cherry-pick`を使った別の解決法について考えてみましょう。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["git cherry-pickを使うと、ツリーの中から複数のコミットを選んで、HEADの下に新しく作ることができましたね。","","簡単なデモを見てみましょう:"],afterMarkdowns:["できました!次へ進みましょう"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["このレベルでは、`C2`をamendすることで前回と同じ目的を達成しましょう。但し`rebase -i`は使わずにクリアしてください。どんな方法で進めるかはあなたにおまかせします!:D"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 提交变换戏法 #2","","*假如你还没有完成提交变换戏法 #1(前一关),这关不让玩哦!*","","如你在上一关所见,我们使用 `rebase -i` 来重排那些提交。只要把我们想要的提交挪到最顶端,我们就可以很容易地改变它,然后把它们重新排成我们想要的顺序。","","但唯一的问题就是这样做就要排很多次,有可能造成衍合冲突(rebase conflicts)。下面就看看用另外一种方法 `git cherry-pick` 是怎么做的吧。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["要在心理牢记 cherry-pick 可以从提交树的任何地方拿一个提交来放在 HEAD 上(尽管那个提交不在上游)。","","下面是一个小小的演示:"],command:"git cherry-pick C2",afterMarkdowns:["好滴咧,我们继续"],beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["那么这关呢,和上一关一样要改变提交 `C2`,但你要避免使用 `rebase -i`。自己想想要怎么解决吧,骚年! :D"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 커밋 갖고 놀기 #2","","*만약 이전 레벨의 커밋 갖고 놀기 #1을 풀지 않으셨다면, 계속하기에 앞서서 꼭 풀어보세요*","","이전 레벨에서 보셨듯이 `rebase -i` 명령으로 커밋의 순서를 바꿀 수 있습니다. 정정할 커밋이 바로 직전(top)에 있으면 간단히 --amend로 수정할 수 있고, 그리고 나서 다시 원하는 순서로 되돌려 놓으면 됩니다.","","이번에 한가지 문제는 순서를 꽤 많이 바꿔야한다는 점인데요, 그러다가 리베이스중에 충돌이 날 수 있습니다. 이번에는 다른 방법인 `git cherry-pick`으로 해결해 봅시다."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["git cherry-pick으로 HEAD에다 어떤 커밋이든 떨어 뜨려 놓을 수 있다고 알려드린것 기억나세요? (단, 그 커밋이 현재 가리키고 있는 커밋이 아니어야합니다)","","간단한 데모로 다시 알려드리겠습니다:"],afterMarkdowns:["좋아요! 계속할게요"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["그럼 이번 레벨에서는 아까와 마찬가지로 `C2` 커밋의 내용을 정정하되, `rebase -i`를 쓰지 말고 해보세요. ^.~"]}}]}}}}),e.define("/levels/advanced/multipleParents.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C7","id":"master"},"bugWork":{"target":"C2","id":"bugWork"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C2"],"id":"C5"},"C6":{"parents":["C4","C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',solutionCommand:"git branch bugWork master^^2^",startTree:'{"branches":{"master":{"target":"C7","id":"master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C2"],"id":"C5"},"C6":{"parents":["C4","C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Multiple parents",zh_CN:"多个父提交记录"},hint:{en_US:"Use `git branch bugWork` with a target commit to create the missing reference.",zh_CN:"使用`git branch bugWork`加上一个目标提交记录来创建消失的引用。"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["### Specifying Parents","","Like the `~` modifier, the `^` modifier also accepts an optional number after it.","","Rather than specifying the number of generations to go back (what `~` takes), the modifier on `^` specifies which parent reference to follow from a merge commit. Remember that merge commits have multiple parents, so the path to choose is ambiguous.","",'Git will normally follow the "first" parent upwards from a merge commit, but specifying a number with `^` changes this default behavior.',"","Enough talking, let's see it in action.",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have a merge commit. If we checkout `master^` without the modifier, we will follow the first parent after the merge commit. ","","(*In our visuals, the first parent is positioned directly above the merge commit.*)"],afterMarkdowns:["Easy -- this is what we are all used to."],command:"git checkout master^",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Now let's try specifying the second parent instead..."],afterMarkdowns:["See? We followed the other parent upwards."],command:"git checkout master^2",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["The `^` and `~` modifiers can make moving around a commit tree very powerful:"],afterMarkdowns:["Lightning fast!"],command:"git checkout HEAD~; git checkout HEAD^2; git checkout HEAD~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Even crazier, these modifiers can be chained together! Check this out:"],afterMarkdowns:["The same movement as before, but all in one command."],command:"git checkout HEAD~^2~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"ModalAlert",options:{markdowns:["### Put it to practice","","To complete this level, create a new branch at the specified destination.","","Obviously it would be easy to specify the commit directly (with something like `C6`), but I challenge you to use the modifiers we talked about instead!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["### 选择父提交","","和`~`修改符一样,`^`修改符之后也可以跟一个(可选的)数字。","","这不是用来指定向上返回几代(`~`的作用),`^`后的数字指定跟随合并提交记录的哪一个父提交。还记得一个合并提交有多个父提交吧,所有选择哪条路径不是那么清晰。","",'Git默认选择跟随合并提交的"第一个"父提交,使用`^`后跟一个数字来改变这一默认行为。',"","废话不多说,举个例子。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["这里有一个合并提交。如果不加数字修改符直接切换到`master^`,会回到第一个父提交。","","(*在我们的图示中,第一个父提交是指合并提交正上方的那个父提交。*)"],afterMarkdowns:["OK--这恰好是我们想要的。"],command:"git checkout master^",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["现在来试试选择第二个父提交……"],afterMarkdowns:["看见了吧?我们回到了第二个父提交。"],command:"git checkout master^2",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用`^`和`~`可以自由在在提交树中移动:"],afterMarkdowns:["快若闪电!"],command:"git checkout HEAD~; git checkout HEAD^2; git checkout HEAD~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["再疯狂点,这些修改符支持链式操作!试一下这个:"],afterMarkdowns:["和前面的结果一样,但只用了一条命令。"],command:"git checkout HEAD~^2~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"ModalAlert",options:{markdowns:["### 实践一下","","要完成此关,在指定的目标位置创建一个新的分支。","","很明显可以简单的直接使用提交记录的hash值(比如`C6`),但我要求你使用刚刚讲到的相对引用修饰符!"]}}]}}}}),e.define("/levels/rebase/selectiveRebase.js",function(e,t,n,r,i,s,o){n.level={compareAllBranchesHashAgnostic:!0,disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C5%22%2C%22id%22%3A%22master%22%7D%2C%22one%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22one%22%7D%2C%22two%22%3A%7B%22target%22%3A%22C2%27%27%22%2C%22id%22%3A%22two%22%7D%2C%22three%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22three%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C4%27%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C4%27%27%22%7D%2C%22C3%27%27%22%3A%7B%22parents%22%3A%5B%22C4%27%27%22%5D%2C%22id%22%3A%22C3%27%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C3%27%27%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22two%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout one; git cherry-pick C4 C3 C2; git checkout two; git cherry-pick C5 C4 C3 C2; git branch -f three C2",startTree:'{"branches":{"master":{"target":"C5","id":"master"},"one":{"target":"C1","id":"one"},"two":{"target":"C1","id":"two"},"three":{"target":"C1","id":"three"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C4"],"id":"C5"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{ko:"브랜치 스파게티",en_US:"Branch Spaghetti",ja:"ブランチスパゲッティ",zh_CN:"分支浆糊"},hint:{en_US:"Make sure to do everything in the proper order! Branch one first, then two, then three",ja:"全て正しい順番で処理すること!oneが最初で、次がtwo、最後にthreeを片付ける。",ko:"이 문제를 해결하는 방법은 여러가지가 있습니다! 체리픽(cherry-pick)이 가장 쉽지만 오래걸리는 방법이고, 리베이스(rebase -i)가 빠른 방법입니다",zh_CN:"确保你是按照正确的顺序来操作!先操作分支 `one`, 然后 `two`, 最后才是 `three`"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branch Spaghetti","","WOAHHHhhh Nelly! We have quite the goal to reach in this level.","","Here we have `master` that is a few commits ahead of branches `one` `two` and `three`. For whatever reason, we need to update these three other branches with modified versions of the last few commits on master.","","Branch `one` needs a re-ordering and a deletion of `C5`. `two` needs pure reordering, and `three` only needs one commit!","","We will let you figure out how to solve this one -- make sure to check out our solution afterwards with `show solution`. "]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ブランチスパゲッティ","","なんということでしょう。今回のレベルクリアのために、やることがたくさんあります。","","いま`master`が指しているコミットの数個前のコミットに、ブランチ`one`、`two`それから`three`があります。何か事情があって、これらの3つのブランチをmasterが指している最新の状態に更新したいケースを考えます。","","ブランチ`one`に対しては、順序の変更と`C5`の削除が必要です。`two`では順序の変更のみ、`three`に対しては1回だけコミットすればOKです。","","`show solution`コマンドで模範解答を確認できますから、こちらも利用してください。 "]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branch Spaghetti","","哇塞大神!这关我们要来点不同的!","","现在我们的 `master` 分支是比 `one` `two` 和 `three` 要多几个提交。出于某种原因,我们需要把其他三个分支更新到 master 分支上新近的几个不同提交上。(update these three other brances with modified versions of the last few commits on master)","","分支 `one` 需要重新排序和撤销, `two` 需要完全重排,而 `three` 只需要提交一次。","","慢慢摸索会找到答案的 —— 你完事记得用 `show solution` 看看我们的答案哦。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 브랜치 스파게티","","음, 이번에는 만만치 않습니다!","","여기 `master` 브랜치의 몇 번 이전 커밋에 `one`, `two`,`three` 총 3개의 브랜치가 있습니다. 어떤 이유인지는 몰라도, master의 최근 커밋 몇 개를 나머지 세 개의 브랜치에 반영하려고 합니다.","","`one` 브랜치는 순서를 바꾸고 `C5`커밋을 삭제하고, `two`브랜치는 순서만 바꾸며, `three`브랜치는 하나의 커밋만 가져옵시다!","","자유롭게 이 문제를 풀어보시고 나서 `show solution`명령어로 모범 답안을 확인해보세요."]}}]}}}}),e.define("/src/js/views/levelDropdownView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../intl"),h=e("../log"),p=e("../util/keyboard").KeyboardListener,d=e("../app"),v=e("../views").ModalTerminal,m=e("../views").ContainedBase,g=e("../views").BaseView,y=m.extend({tagName:"div",className:"levelDropdownView box vertical",template:u.template($("#level-dropdown-view").html()),initialize:function(e){e=e||{},this.JSON={},this.navEvents=u.clone(f.Events),this.navEvents.on("clickedID",u.debounce(u.bind(this.loadLevelID,this),300,!0)),this.navEvents.on("negative",this.negative,this),this.navEvents.on("positive",this.positive,this),this.navEvents.on("left",this.left,this),this.navEvents.on("right",this.right,this),this.navEvents.on("up",this.up,this),this.navEvents.on("down",this.down,this),this.keyboardListener=new p({events:this.navEvents,aliasMap:{esc:"negative",enter:"positive"},wait:!0}),this.sequences=d.getLevelArbiter().getSequences(),this.sequenceToLevels=d.getLevelArbiter().getSequenceToLevels(),this.container=new v({title:c.str("select-a-level")}),this.render(),d.getEvents().on("resetMapSolved",this.render,this),d.getEvents().on("localeChanged",this.render,this),e.wait||this.show()},render:function(){y.__super__.render.apply(this,arguments),this.buildSequences()},positive:function(){if(!this.selectedID)return;this.loadLevelID(this.selectedID)},left:function(){if(this.turnOnKeyboardSelection())return;this.leftOrRight(-1)},leftOrRight:function(e){this.deselectIconByID(this.selectedID),this.selectedIndex=this.wrapIndex(this.selectedIndex+e,this.getCurrentSequence()),this.selectedID=this.getSelectedID(),this.selectIconByID(this.selectedID)},right:function(){if(this.turnOnKeyboardSelection())return;this.leftOrRight(1)},up:function(){if(this.turnOnKeyboardSelection())return;this.selectedSequence=this.getPreviousSequence(),this.downOrUp()},down:function(){if(this.turnOnKeyboardSelection())return;this.selectedSequence=this.getNextSequence(),this.downOrUp()},downOrUp:function(){this.selectedIndex=this.boundIndex(this.selectedIndex,this.getCurrentSequence()),this.deselectIconByID(this.selectedID),this.selectedID=this.getSelectedID(),this.selectIconByID(this.selectedID)},turnOnKeyboardSelection:function(){return this.selectedID?!1:(this.selectFirst(),!0)},turnOffKeyboardSelection:function(){if(!this.selectedID)return;this.deselectIconByID(this.selectedID),this.selectedID=undefined,this.selectedIndex=undefined,this.selectedSequence=undefined},wrapIndex:function(e,t){return e=e>=t.length?0:e,e=e<0?t.length-1:e,e},boundIndex:function(e,t){return e=e>=t.length?t.length-1:e,e=e<0?0:e,e},getNextSequence:function(){var e=this.getSequenceIndex(this.selectedSequence),t=this.wrapIndex(e+1,this.sequences);return this.sequences[t]},getPreviousSequence:function(){var e=this.getSequenceIndex(this.selectedSequence),t=this.wrapIndex(e-1,this.sequences);return this.sequences[t]},getSequenceIndex:function(e){var t=this.sequences.indexOf(e);if(t<0)throw new Error("didnt find");return t},getIndexForID:function(e){return d.getLevelArbiter().getLevel(e).index},selectFirst:function(){var e=this.sequenceToLevels[this.sequences[0]][0].id;this.selectIconByID(e),this.selectedIndex=0,this.selectedSequence=this.sequences[0]},getCurrentSequence:function(){return this.sequenceToLevels[this.selectedSequence]},getSelectedID:function(){return this.sequenceToLevels[this.selectedSequence][this.selectedIndex].id},selectIconByID:function(e){this.toggleIconSelect(e,!0)},deselectIconByID:function(e){this.toggleIconSelect(e,!1)},toggleIconSelect:function(e,t){this.selectedID=e;var n="#levelIcon-"+e;$(n).toggleClass("selected",t)},negative:function(){this.hide()},testOption:function(e){return this.currentCommand&&(new RegExp("--"+e)).test(this.currentCommand.get("rawStr"))},show:function(e,t){this.currentCommand=t,this.updateSolvedStatus(),this.showDeferred=e,this.keyboardListener.listen(),y.__super__.show.apply(this)},hide:function(){this.showDeferred&&this.showDeferred.resolve(),this.showDeferred=undefined,this.keyboardListener.mute(),this.turnOffKeyboardSelection(),y.__super__.hide.apply(this)},loadLevelID:function(e){if(!this.testOption("noOutput")){d.getEventBaton().trigger("commandSubmitted","level "+e);var t=d.getLevelArbiter().getLevel(e),n=t.name.en_US;h.levelSelected(n)}this.hide()},updateSolvedStatus:function(){u.each(this.seriesViews,function(e){e.updateSolvedStatus()},this)},buildSequences:function(){this.seriesViews=[],u.each(this.sequences,function(e){this.seriesViews.push(new b({destination:this.$el,name:e,navEvents:this.navEvents}))},this)}}),b=g.extend({tagName:"div",className:"seriesView box flex1 vertical",template:u.template($("#series-view").html()),events:{"click div.levelIcon":"click","mouseenter div.levelIcon":"enterIcon","mouseleave div.levelIcon":"leaveIcon"},initialize:function(e){this.name=e.name||"intro",this.navEvents=e.navEvents,this.info=d.getLevelArbiter().getSequenceInfo(this.name),this.levels=d.getLevelArbiter().getLevelsInSequence(this.name),this.levelIDs=[],u.each(this.levels,function(e){this.levelIDs.push(e.id)},this),this.destination=e.destination,this.JSON={displayName:c.getIntlKey(this.info,"displayName"),about:c.getIntlKey(this.info,"about")||" ",ids:this.levelIDs},this.render(),this.updateSolvedStatus()},updateSolvedStatus:function(){var e=this.$("div.levelIcon").each(function(e,t){var n=$(t).attr("data-id");$(t).toggleClass("solved",d.getLevelArbiter().isLevelSolved(n))})},getEventID:function(e){var t=e.target;return $(t).attr("data-id")},resetAbout:function(){this.$("p.about").text(c.getIntlKey(this.info,"about")).css("font-style","inherit")},setAbout:function(e){this.$("p.about").text(e).css("font-style","italic")},enterIcon:function(e){var t=this.getEventID(e),n=d.getLevelArbiter().getLevel(t);this.setAbout(c.getName(n))},leaveIcon:function(){this.resetAbout()},click:function(e){var t=this.getEventID(e);this.navEvents.trigger("clickedID",t)}});n.LevelDropdownView=y}),e.define("/src/js/views/commandViews.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../models/collections").CommandEntryCollection,l=e("../app"),c=e("../models/commandModel").Command,h=e("../models/commandModel").CommandEntry,p=e("../util/errors"),d=p.Warning,v=e("../util"),m=e("../log"),g=e("../util/keyboard"),y=a.View.extend({initialize:function(e){l.getEvents().on("commandSubmittedPassive",this.addToCommandHistory,this),this.commands=new f,this.commands.fetch({success:u.bind(function(){var e=[];this.commands.each(function(t){e.push(t)}),e.reverse(),this.commands.reset(),u.each(e,function(e){this.commands.add(e)},this)},this)}),this.index=-1,this.commandParagraph=this.$("#prompt p.command")[0],this.commandCursor=this.$("#prompt span.cursor")[0],this.focus(),l.getEvents().on("rollupCommands",this.rollupCommands,this),l.getEventBaton().stealBaton("keydown",this.onKeyDown,this),l.getEventBaton().stealBaton("keyup",this.onKeyUp,this)},events:{"blur #commandTextField":"hideCursor","focus #commandTextField":"showCursor"},blur:function(){this.hideCursor()},focus:function(){this.$("#commandTextField").focus(),this.showCursor()},hideCursor:function(){this.toggleCursor(!1)},showCursor:function(){this.toggleCursor(!0)},toggleCursor:function(e){$(this.commandCursor).toggleClass("shown",e)},onKeyDown:function(e){var t=e.target;this.updatePrompt(t)},onKeyUp:function(e){this.onKeyDown(e);var t={enter:u.bind(function(){this.submit()},this),up:u.bind(function(){this.commandSelectChange(1)},this),down:u.bind(function(){this.commandSelectChange(-1)},this)},n=g.mapKeycodeToKey(e.which||e.keyCode);t[n]!==undefined&&(e.preventDefault(),t[n](),this.onKeyDown(e))},badHtmlEncode:function(e){return e.replace(/&/g,"&").replace(/=this.commands.length||this.index<0){this.clear(),this.index=-1;return}var t=this.commands.toArray()[this.index].get("text");this.setTextField(t)},clearLocalStorage:function(){this.commands.each(function(e){a.sync("delete",e,function(){})},this)},setTextField:function(e){this.$("#commandTextField").val(e)},clear:function(){this.setTextField("")},submit:function(){var e=this.$("#commandTextField").val().replace("\n","");this.clear(),this.submitCommand(e),this.index=-1},rollupCommands:function(e){var t=this.commands.toArray().slice(1,Number(e)+1);t.reverse();var n="";u.each(t,function(e){n+=e.get("text")+";"},this);var r=new h({text:n});this.commands.unshift(r),a.sync("create",r,function(){})},addToCommandHistory:function(e){var t=e.length&&this.index===-1||e.length&&this.index!==-1&&this.commands.toArray()[this.index].get("text")!==e;if(!t)return;var n=new h({text:e});this.commands.unshift(n),a.sync("create",n,function(){}),this.commands.length>100&&this.clearLocalStorage(),m.commandEntered(e)},submitCommand:function(e){l.getEventBaton().trigger("commandSubmitted",e)}}),b=a.View.extend({tagName:"div",model:c,template:u.template($("#command-template").html()),events:{click:"clicked"},clicked:function(e){},initialize:function(){this.model.bind("change",this.wasChanged,this),this.model.bind("destroy",this.remove,this)},wasChanged:function(e,t){var n=t.changes,r=u.keys(n);u.difference(r,["status"]).length===0?this.updateStatus():this.render()},updateStatus:function(){var e=["inqueue","processing","finished"],t={};u.each(e,function(e){t[e]=!1}),t[this.model.get("status")]=!0;var n=this.$("p.commandLine");u.each(t,function(e,t){n.toggleClass(t,e)})},render:function(){var e=u.extend({resultType:"",result:"",formattedWarnings:this.model.getFormattedWarnings()},this.model.toJSON());return this.$el.html(this.template(e)),this},remove:function(){$(this.el).hide()}}),w=a.View.extend({initialize:function(e){this.collection=e.collection,this.collection.on("add",this.addOne,this),this.collection.on("reset",this.addAll,this),this.collection.on("all",this.render,this),this.collection.on("change",this.scrollDown,this),l.getEvents().on("commandScrollDown",this.scrollDown,this),l.getEvents().on("clearOldCommands",this.clearOldCommands,this)},addWarning:function(e){var t=new d({msg:e}),n=new c({error:t,rawStr:"Warning:"});this.collection.add(n)},clearOldCommands:function(){var e=[];this.collection.each(function(t){t.get("status")!=="inqueue"&&t.get("status")!=="processing"&&e.push(t)},this),u.each(e,function(e){e.destroy()},this),this.scrollDown()},scrollDown:function(){var e=$("#commandDisplay")[0],t=$("#terminal")[0],n=e.clientHeight>t.clientHeight||$(window).height()"]}},{type:"ModalAlert",options:{markdowns:["## Git 명령어","","연습 모드에서 쓸 수 있는 다양한 git명령어는 다음과 같습니다",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## 공유해주세요!","","`export tree` 와 `import tree`로 여러분의 친구들에게 트리를 공유해주세요","","훌륭한 학습 자료가 있으신가요? `build level`로 레벨을 만들어 보시거나, 친구의 레벨을 `import level`로 가져와서 실험해보세요","","이제 레슨을 시작해봅시다..."]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Bienvenue sur LearnGitBranching!","","Cette application a été conçue pour aider les débutants à saisir ","les puissants concepts derrière les branches en travaillant ","avec git. Nous espérons que vous apprécierez cette application et ","que vous apprendrez peut-être quelque chose d'intéressant !","","# Démo !","","Si vous n'avez pas vu la démo, vous pouvez le faire là :","","[http://pcottle.github.io/learnGitBranching/?demo](http://pcottle.github.io/learnGitBranching/?demo)","","Agacé par ce dialogue ? Ajoutez `?NODEMO` à l'URL pour le supprimer, en lien ci-dessous pour votre commodité :","","[http://pcottle.github.io/learnGitBranching/?NODEMO](?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## Commandes Git","","Il existe une large variété de commandes git disponibles dans le mode bac à sable. Sont inclues",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## Partager, c'est se soucier!","","Partagez des arbres avec vous amis via `export tree` et `import tree`","","Vous avez une grande leçon à partager ? Essayez de construire un niveau avec `build level` ou essayez le niveau d'un ami avec `import level`","","Pour voir la gamme complète des commandes, tapez `show commands`. Il y a quelques perles telles que `undo` et `reset`","","Mais tout de suite commencez sur les `levels`…"]}}]}}),e.define("/src/js/util/mock.js",function(e,t,n,r,i,s,o){n.mock=function(e){var t={},n=function(){};for(var r in e.prototype)t[r]=n;return t}}),e.define("sys",function(e,t,n,r,i,s,o){t.exports=e("util")}),e.define("child_process",function(e,t,n,r,i,s,o){n.spawn=function(){},n.exec=function(){}}),e.define("/src/js/visuals/tree.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({removeKeys:function(e){u.each(e,function(e){this.get(e)&&this.get(e).remove()},this)},animateAttrKeys:function(e,t,n,r){e=u.extend({},{include:["circle","arrow","rect","path","text"],exclude:[]},e||{});var i=this.getAttributes();u.each(e.include,function(e){i[e]=u.extend({},i[e],t)}),u.each(e.exclude,function(e){delete i[e]}),this.animateToAttr(i,n,r)}});n.VisBase=f}),e.define("/src/js/git/headless.js",function(e,t,n,r,i,s,o){function E(){var e={},t=function(){return f.defer().promise};for(var n in c)e[n]=t;return e.playRefreshAnimationAndFinish=function(e,t){console.log("trying to finish"),t.thenFinish(f.defer().promise)},e}var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("../git").GitEngine,c=e("../visuals/animation/animationFactory").AnimationFactory,h=e("../visuals").GitVisuals,p=e("../git/treeCompare").TreeCompare,d=e("../util/eventBaton").EventBaton,v=e("../models/collections"),m=v.CommitCollection,g=v.BranchCollection,y=e("../models/commandModel").Command,b=e("../util/mock").mock,w=e("../util"),S=function(){this.init()};S.prototype.init=function(){this.commitCollection=new m,this.branchCollection=new g;var e=E(),t=b(h);this.gitEngine=new l({collection:this.commitCollection,branches:this.branchCollection,gitVisuals:t,animationFactory:e,eventBaton:new d}),this.gitEngine.init()},S.prototype.sendCommand=function(e){w.splitTextCommand(e,function(e){var t=new y({rawStr:e});this.gitEngine.dispatch(t,f.defer())},this)},n.HeadlessGit=S}),e.define("/src/js/app/index.js",function(e,t,n,r,i,s,o){function E(){var t=e("../views"),n=e("../models/collections"),r=e("../views/commandViews"),i=new t.MainHelperBar;this.commandCollection=new n.CommandCollection,this.commandBuffer=new n.CommandBuffer({collection:this.commandCollection}),this.commandPromptView=new r.CommandPromptView({el:$("#commandLineBar")}),this.commandLineHistoryView=new r.CommandLineHistoryView({el:$("#commandLineHistory"),collection:this.commandCollection})}var u=e("underscore"),a=e("backbone"),f=e("../util/constants"),l=e("../util"),c=u.clone(a.Events),h,p,d,v,m,g=function(){var t=e("../level/sandbox").Sandbox,n=e("../level").Level,r=e("../util/eventBaton").EventBaton,i=e("../level/arbiter").LevelArbiter,s=e("../views/levelDropdownView").LevelDropdownView;d=new r,h=new E,p=new t,v=new i,m=new s({wait:!0}),c.on("localeChanged",y),b(d),w(p)},y=function(){if(!window.$)return;$("span.intl-aware").each(function(t,n){var r=e("../intl"),i=$(n).attr("data-intl");$(n).text(r.str(i).toUpperCase())})},b=function(e){var t=function(){$("#commandTextField").focus()};t(),$(window).focus(function(t){e.trigger("windowFocus",t)}),$(document).click(function(t){e.trigger("documentClick",t)}),$(document).bind("keydown",function(t){e.trigger("docKeydown",t)}),$(document).bind("keyup",function(t){e.trigger("docKeyup",t)}),$(window).on("resize",function(e){c.trigger("resize",e)}),e.stealBaton("docKeydown",function(){}),e.stealBaton("docKeyup",function(){}),e.stealBaton("windowFocus",t),e.stealBaton("documentClick",t);var n=function(t){return function(){var n=[t];u.each(arguments,function(e){n.push(e)}),e.trigger.apply(e,n)}};$("#commandTextField").on("keydown",n("keydown")),$("#commandTextField").on("keyup",n("keyup")),$(window).trigger("resize")},w=function(e){var t=l.parseQueryString(window.location.href);t.hasOwnProperty("demo")?e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",["git commit; git checkout -b bugFix C1; git commit; git merge master; git checkout master; git commit; git rebase bugFix;","delay 1000; reset;","level rebase1 --noFinishDialog --noStartCommand --noIntroDialog;","delay 2000; show goal; delay 1000; hide goal;","git checkout bugFix; git rebase master; git checkout side; git rebase bugFix;","git checkout another; git rebase side; git rebase another master;","help; levels"].join(""))}):t.hasOwnProperty("NODEMO")||e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",["git help;","delay 1000;","help;","levels"].join(""))}),t.locale!==undefined&&t.locale.length&&(f.GLOBAL.locale=t.locale,c.trigger("localeChanged"));if(t.command){var n=unescape(t.command);e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted",n)})}(/(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent)||/android/i.test(navigator.userAgent))&&e.mainVis.customEvents.on("gitEngineReady",function(){d.trigger("commandSubmitted","mobile alert")})};e("../util").isBrowser()&&$(document).ready(g),n.getEvents=function(){return c},n.getSandbox=function(){return p},n.getEventBaton=function(){return d},n.getCommandUI=function(){return h},n.getLevelArbiter=function(){return v},n.getLevelDropdown=function(){return m},n.init=g}),e("/src/js/app/index.js"),e.define("/src/js/dialogs/confirmShowSolution.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Are you sure you want to see the solution?","","I believe in you! You can do it"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 确定要看答案吗?","","哥相信你!你可以的"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Êtes-vous sûr de vouloir voir la solution ?","","Je crois en vous ! Vous pouvez le faire"]}}]}}),e("/src/js/dialogs/confirmShowSolution.js"),e.define("/src/js/dialogs/levelBuilder.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Welcome to the level builder!","","Here are the main steps:",""," * Set up the initial environment with git commands"," * Define the starting tree with ```define start```"," * Enter the series of git commands that compose the (optimal) solution"," * Define the goal tree with ```define goal```. Defining the goal also defines the solution"," * Optionally define a hint with ```define hint```"," * Edit the name with ```define name```"," * Optionally define a nice start dialog with ```edit dialog```"," * Enter the command ```finish``` to output your level JSON!"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 欢迎使用关卡生成器!","","主要步骤如下:",""," * 使用 git 命令布置好初始环境"," * 使用 ```define start``` 命令定义起始树"," * 输入一系列 git 命令,编好答案"," * 使用 ```define goal``` 命令定义目标树。定义目标的同时定义答案"," * 还可以用 ```define hint``` 命令定义一个提示"," * 用 ```define name``` 修改名称"," * 还可以用 ```edit dialog``` 定义一个漂亮的开始对话框"," * 输入 ```finish``` 就可以输出你的关卡数据(JSON)了!"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Bienvenue dans l'éditeur niveaux !","","Voici les étapes principales :",""," * Mettez en place l'environnement initial avec des commandes git"," * Définissez l'arbre de départ avec ```define start```"," * Saisissez la série de commandes git qui composent la solution (optimale)"," * Définissez l'arbre cible avec ```define goal```. Cela définit aussi la solution"," * Optionnellement, définissez un indice avec ```define hint```"," * Changez le nom avec ```define name```"," * Optionellement, definissez un joli dialogue de départ avec ```edit dialog```"," * Entrez la commande ```finish``` pour délivrer votre niveau JSON!"]}}]}}),e("/src/js/dialogs/levelBuilder.js"),e.define("/src/js/dialogs/nextLevel.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Great Job!!","","You solved the level in *{numCommands}* command(s); ","our solution uses {best}."]}}],ja:[{type:"ModalAlert",options:{markdowns:["## 完成!","","あなたは*{numCommands}*回のコマンドでこの課題をクリアしました; ","模範解答では{best}回です。"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 碉堡了!","","你用 *{numCommands}* 条命令搞定了这一关;我们的答案要用 {best}。"]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Beau Travail!!","","Vous avez résolu le niveau en *{numCommands}* commande(s); ","notre solution le fait en {best}."]}}]}}),e("/src/js/dialogs/nextLevel.js"),e.define("/src/js/dialogs/sandbox.js",function(e,t,n,r,i,s,o){n.dialog={en_US:[{type:"ModalAlert",options:{markdowns:["## Welcome to LearnGitBranching!","","This application is designed to help beginners grasp ","the powerful concepts behind branching when working ","with git. We hope you enjoy this application and maybe ","even learn something!","","# Demo!","","If you have not seen the demo, please check it out here:","","[http://pcottle.github.io/learnGitBranching/?demo](http://pcottle.github.io/learnGitBranching/?demo)","","Annoyed at this dialog? Append `?NODEMO` to the url to get rid of it, linked below for convenience:","","[http://pcottle.github.io/learnGitBranching/?NODEMO](?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## Git commands","","You have a large variety of git commands available in sandbox mode. These include",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## Sharing is caring!","","Share trees with your friends via `export tree` and `import tree`","","Have a great lesson to share? Try building a level with `build level` or try out a friend's level with `import level`","","To see the full range of commands, try `show commands`. There are some gems like `undo` and `reset`","","For now let's get you started on the `levels`..."]}}],ja:[{type:"ModalAlert",options:{markdowns:["## LearnGitBranchingへようこそ","","gitのパワフルなブランチ機能のコンセプトが ","学びやすくなるようにこのアプリケーションを作りました。 ","このアプリケーションを楽しんで使って頂いて、 ","何かを学習して頂けたなら嬉しいです。","","# とりあえず触ってみたい方へ:","","簡単なデモを用意してあるので、もしよければこちらもご覧ください:","","[http://remore.github.io/learnGitBranching-ja/?demo](http://remore.github.io/learnGitBranching-ja/?demo)","","このダイアログ自体を省略するには、以下のようにURLの末尾にクエリストリング`?NODEMO`を付加してアクセスしてください。","","[http://remore.github.io/learnGitBranching-ja/?NODEMO](http://remore.github.io/learnGitBranching-ja/?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## ここで学べるGitのオペレーション","","ここでは、下記の種類のgitコマンドを学ぶことができます。",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## 学習した内容を共有できます","","画面左のコマンドプロンプトから`export tree`や`import tree`とタイプすることで、gitのツリー構造を友達に送ることができます","","何か教材になるようなケースはご存知ないでしょうか。`build level`で課題を作成したり、`import level`で他の人の課題に挑戦してみてください。","","それでは教材の選択画面に進んでみることにします。"]}}],zh_CN:[{type:"ModalAlert",options:{markdowns:["## 欢迎光临 LearnGitBranching!","","本应用旨在帮助初学者领会 git 分支背后的强大概念。","希望你能喜欢这个应用,并学到知识!","","# 演示!","","如果你还没看过演示,请到此查看:","","[http://pcottle.github.io/learnGitBranching/?demo](http://pcottle.github.io/learnGitBranching/?demo)","","厌烦这个对话框? 在 URL 后头加上 `?NODEMO` 就看不到它了,也可以直接点下边这个链接:","","[http://pcottle.github.io/learnGitBranching/?NODEMO](http://pcottle.github.io/learnGitBranching/?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## Git 命令","","在沙盒模式里,你有好多命令可用。 包括:",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## 分享即关怀","","使用 `export tree` 和 `import tree` 与朋友分享 Git 树","","有个好课程可以分享?试试用 `build level` 创建一个关卡,或者 `import level` 试试朋友的。","","言归正传,让我们先从 `levels` 开始……"]}}],ko:[{type:"ModalAlert",options:{markdowns:["## Git 브랜치 배우기를 시작합니다!","","이 애플리케이션은 git을 쓸 때 필요한 브랜치에 대한 개념을","탄탄히 잡게끔 도와드리기 위해 만들었습니다. 재밌게 사용해주시기를","바라며, 무언가를 배워가신다면 더 기쁘겠습니다!","","이 애플리케이션은 [Peter Cottle](https://github.io/pcottle)님의 [LearnGitBranching](http://pcottle.github.io/learnGitBranching/)를 번역한 것입니다.","아래 데모를 먼저 보셔도 좋습니다.","",""]}},{type:"ModalAlert",options:{markdowns:["## Git 명령어","","연습 모드에서 쓸 수 있는 다양한 git명령어는 다음과 같습니다",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## 공유해주세요!","","`export tree` 와 `import tree`로 여러분의 친구들에게 트리를 공유해주세요","","훌륭한 학습 자료가 있으신가요? `build level`로 레벨을 만들어 보시거나, 친구의 레벨을 `import level`로 가져와서 실험해보세요","","이제 레슨을 시작해봅시다..."]}}],fr_FR:[{type:"ModalAlert",options:{markdowns:["## Bienvenue sur LearnGitBranching!","","Cette application a été conçue pour aider les débutants à saisir ","les puissants concepts derrière les branches en travaillant ","avec git. Nous espérons que vous apprécierez cette application et ","que vous apprendrez peut-être quelque chose d'intéressant !","","# Démo !","","Si vous n'avez pas vu la démo, vous pouvez le faire là :","","[http://pcottle.github.io/learnGitBranching/?demo](http://pcottle.github.io/learnGitBranching/?demo)","","Agacé par ce dialogue ? Ajoutez `?NODEMO` à l'URL pour le supprimer, en lien ci-dessous pour votre commodité :","","[http://pcottle.github.io/learnGitBranching/?NODEMO](?NODEMO)"]}},{type:"ModalAlert",options:{markdowns:["## Commandes Git","","Il existe une large variété de commandes git disponibles dans le mode bac à sable. Sont inclues",""," * commit"," * branch"," * checkout"," * cherry-pick"," * reset"," * revert"," * rebase"," * merge"]}},{type:"ModalAlert",options:{markdowns:["## Partager, c'est se soucier!","","Partagez des arbres avec vous amis via `export tree` et `import tree`","","Vous avez une grande leçon à partager ? Essayez de construire un niveau avec `build level` ou essayez le niveau d'un ami avec `import level`","","Pour voir la gamme complète des commandes, tapez `show commands`. Il y a quelques perles telles que `undo` et `reset`","","Mais tout de suite commencez sur les `levels`…"]}}]}}),e("/src/js/dialogs/sandbox.js"),e.define("/src/js/git/commands.js",function(e,t,n,r,i,s,o){function y(e,t){this.method=e,this.rawOptions=t,this.supportedMap=this.getMasterOptionMap()[e];if(this.supportedMap===undefined)throw new Error("No option map for "+e);this.generalArgs=[],this.explodeAndSet()}var u=e("underscore"),a=e("../intl"),f=e("../util/errors"),l=f.CommandProcessError,c=f.GitError,h=f.Warning,p=f.CommandResult,d={"git commit":/^(gc|git ci)($|\s)/,"git add":/^ga($|\s)/,"git checkout":/^(go|git co)($|\s)/,"git rebase":/^gr($|\s)/,"git branch":/^(gb|git br)($|\s)/,"git status":/^(gst|gs|git st)($|\s)/,"git help":/^git$/},v=[[/^git help($|\s)/,function(){var e=[a.str("git-version"),"
",a.str("git-usage"),u.escape(a.str("git-usage-command")),"
",a.str("git-supported-commands"),"
"],t=y.prototype.getMasterOptionMap();u.each(t,function(t,n){e.push("git "+n),u.each(t,function(t,n){e.push(" "+n)},this)},this);var n=e.join("\n");throw n=n.replace(/\t/g,"   "),new p({msg:n})}]],m={"git commit":/^git +commit($|\s)/,"git add":/^git +add($|\s)/,"git checkout":/^git +checkout($|\s)/,"git rebase":/^git +rebase($|\s)/,"git reset":/^git +reset($|\s)/,"git branch":/^git +branch($|\s)/,"git revert":/^git +revert($|\s)/,"git log":/^git +log($|\s)/,"git merge":/^git +merge($|\s)/,"git show":/^git +show($|\s)/,"git status":/^git +status($|\s)/,"git cherry-pick":/^git +cherry-pick($|\s)/,"git fakeTeamwork":/^git +fakeTeamwork($|\s)/,"git fetch":/^git +fetch *?$/,"git pull":/^git +pull($|\s)/,"git push":/^git +push($|\s)/,"git clone":/^git +clone *?$/},g=function(e){var t,n;u.each(m,function(r,i){r.exec(e)&&(n=e.slice(i.length+1),t=i.slice("git ".length))});if(!t)return!1;var r=new y(t,n);return{toSet:{generalArgs:r.generalArgs,supportedMap:r.supportedMap,method:t,options:n,eventName:"processGitCommand"}}};y.prototype.getMasterOptionMap=function(){return{commit:{"--amend":!1,"-a":!1,"-am":!1,"-m":!1},status:{},log:{},add:{},"cherry-pick":{},branch:{"-d":!1,"-D":!1,"-f":!1,"-a":!1,"-r":!1,"--contains":!1},checkout:{"-b":!1,"-B":!1,"-":!1},reset:{"--hard":!1,"--soft":!1},merge:{},rebase:{"-i":!1},revert:{},show:{},clone:{},fetch:{},pull:{"--rebase":!1},push:{},fakeTeamwork:{}}},y.prototype.explodeAndSet=function(){var e=this.rawOptions.match(/('.*?'|".*?"|\S+)/g)||[];for(var t=0;t9&&(e=e.slice(0,9),this.command.addWarning(l.str("branch-name-short",{branch:e}))),e},y.prototype.validateAndMakeBranch=function(e,t){e=this.validateBranchName(e);if(this.refs[e])throw new v({msg:l.str("bad-branch-name",{branch:name})});this.makeBranch(e,t)},y.prototype.makeBranch=function(e,t){var n=new w({target:t,id:e});return this.branchCollection.add(n),this.refs[n.get("id")]=n,n},y.prototype.getHead=function(){return u.clone(this.HEAD)},y.prototype.getBranches=function(){var e=[];return this.branchCollection.each(function(t){e.push({id:t.get("id"),selected:this.HEAD.get("target")===t,target:t.get("target"),remote:t.getIsRemote(),obj:t})},this),e},y.prototype.getRemoteBranches=function(){var e=this.getBranches();return u.filter(e,function(e){return e.remote===!0})},y.prototype.getLocalBranches=function(){var e=this.getBranches();return u.filter(e,function(e){return e.remote===!1})},y.prototype.printBranchesWithout=function(e){var t=this.getUpstreamBranchSet(),n=this.getCommitFromRef(e).get("id"),r=[];u.each(t[n],function(e){e.selected=this.HEAD.get("target").get("id")==e.id,r.push(e)},this),this.printBranches(r)},y.prototype.printBranches=function(e){var t="";throw u.each(e,function(e){t+=(e.selected?"* ":"")+e.id+"\n"}),new m({msg:t})},y.prototype.getUniqueID=function(){var e=this.uniqueId("C"),t=u.bind(function(e){return this.refs[e]?!0:this.origin&&this.origin.refs[e]?!0:!1},this);while(t(e))e=this.uniqueId("C");return e},y.prototype.makeCommit=function(e,t,n){t||(t=this.getUniqueID());var r=new E(u.extend({parents:e,id:t,gitVisuals:this.gitVisuals},n||{}));return this.refs[r.get("id")]=r,this.commitCollection.add(r),r},y.prototype.acceptNoGeneralArgs=function(){if(this.generalArgs.length)throw new v({msg:l.str("git-error-no-general-args")})},y.prototype.validateArgBounds=function(e,t,n,r){var i=r===undefined?"git "+this.command.get("method"):this.command.get("method")+" "+r+" ";i="with "+i;if(e.lengthn)throw new v({msg:l.str("git-error-args-many",{upper:String(n),what:i})})},y.prototype.oneArgImpliedHead=function(e,t){this.validateArgBounds(e,0,1,t),e.length===0&&e.push("HEAD")},y.prototype.twoArgsImpliedHead=function(e,t){this.validateArgBounds(e,1,2,t),e.length==1&&e.push("HEAD")},y.prototype.revertStarter=function(){this.validateArgBounds(this.generalArgs,1,NaN),this.revert(this.generalArgs)},y.prototype.revert=function(e){var t=u.map(e,function(e){return this.getCommitFromRef(e)},this),n=f.defer(),r=n.promise,i=this.resolveID("HEAD");r=c.highlightEachWithPromise(r,t,i);var s=this.getCommitFromRef("HEAD"),o=u.bind(function(e){var t=this.rebaseAltID(e.get("id")),n=l.str("git-revert-msg",{oldCommit:this.resolveName(e),oldMsg:e.get("commitMessage")}),r=this.makeCommit([s],t,{commitMessage:n});return s=r,c.playCommitBirthPromiseAnimation(r,this.gitVisuals)},this);u.each(t,function(e){r=r.then(function(){return o(e)})},this),r=r.then(u.bind(function(){return this.setTargetLocation("HEAD",s),c.playRefreshAnimation(this.gitVisuals)},this)),this.animationQueue.thenFinish(r,n)},y.prototype.resetStarter=function(){if(this.commandOptions["--soft"])throw new v({msg:l.str("git-error-staging")});this.commandOptions["--hard"]&&(this.command.addWarning(l.str("git-warning-hard")),this.generalArgs=this.generalArgs.concat(this.commandOptions["--hard"])),this.validateArgBounds(this.generalArgs,1,1);if(this.getDetachedHead())throw new v({msg:l.str("git-error-reset-detached")});this.reset(this.generalArgs[0])},y.prototype.reset=function(e){this.setTargetLocation("HEAD",this.getCommitFromRef(e))},y.prototype.cherrypickStarter=function(){this.validateArgBounds(this.generalArgs,1,Number.MAX_VALUE);var e=this.getUpstreamSet("HEAD"),t=u.map(this.generalArgs,function(t){var n=this.getCommitFromRef(t);if(e[n.get("id")])throw new v({msg:l.str("git-error-already-exists",{commit:n.get("id")})});return n},this),n=f.defer(),r=n.promise,i=this.resolveID("HEAD");r=c.highlightEachWithPromise(r,t,i);var s=u.bind(function(e){var t=this.cherrypick(e);return c.playCommitBirthPromiseAnimation(t,this.gitVisuals)},this);u.each(t,function(e){r=r.then(function(){return s(e)})},this),this.animationQueue.thenFinish(r,n)},y.prototype.checkUpstreamOfSource=function(e,t,n,r,i){var s=t.getUpstreamSet(r),o=e.getCommitFromRef(n).get("id");if(!s[o])throw new v({msg:i||l.str("git-error-origin-fetch-no-ff")})},y.prototype.getTargetGraphDifference=function(e,t,n,r,i){i=i||{},r=t.resolveID(r);var s=e.getUpstreamSet(n),o=t.getCommitFromRef(r),a=t.exportTree(),f=a.commits[o.get("id")];if(e.refs[f.id]){if(i.dontThrowOnNoFetch)return[];throw new v({msg:l.str("git-error-origin-fetch-uptodate")})}f.depth=0;var c=[],h=[f],p=function(e){if(s[e])return;var t=a.commits[e];t.depth=d.depth+1,h.push(t)};while(h.length){var d=h.pop();c.push(d),u.each(d.parents,p)}var m={},g=[];return u.forEach(c,function(e){if(m[e.id])return;m[e.id]=!0,g.push(e)}),g.sort(function(e,t){return t.depth-e.depth})},y.prototype.pushStarter=function(e){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.push()},y.prototype.push=function(e){e=e||{};var t=this.refs.master,n=this.origin.refs.master;this.checkUpstreamOfSource(this,this.origin,n,t,l.str("git-error-origin-push-no-ff"));var r=this.getTargetGraphDifference(this.origin,this,n,t),i=u.bind(function(e,t){var n=u.map(t,function(e){return this.origin.refs[e]},this);return this.origin.makeCommit(n,e)},this),s=u.bind(function(e,t){var n=i(e,t);return c.playCommitBirthPromiseAnimation(n,this.origin.gitVisuals)},this),o=f.defer(),a=o.promise;u.each(r,function(e){a=a.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.refs[e.id],n)},this)),a=a.then(function(){return s(e.id,e.parents)})},this),a=a.then(u.bind(function(){var e=t.get("target").get("id"),r=this.origin.refs[e];return this.origin.setTargetLocation(n,r),c.playRefreshAnimation(this.gitVisuals),c.playRefreshAnimation(this.origin.gitVisuals)},this)),a=a.then(u.bind(function(){var e=this.getCommitFromRef(t),n=t.getRemoteBranchIDFromTracking();return this.setTargetLocation(this.refs[n],e),c.playRefreshAnimation(this.gitVisuals)},this)),e.dontResolvePromise||this.animationQueue.thenFinish(a,o)},y.prototype.fetchStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.fetch()},y.prototype.fetch=function(e){e=e||{};var t=this.refs["o/master"],n=this.origin.refs.master;this.checkUpstreamOfSource(this,this.origin,t,n);var r=this.getTargetGraphDifference(this,this.origin,t,n,e);if(r.length===0){this.command.addWarning(l.str("git-error-origin-fetch-uptodate"));var i=f.defer();return{deferred:i,chain:i.promise}}var s=u.bind(function(e,t){var n=u.map(t,function(e){return this.refs[e]},this);return this.makeCommit(n,e)},this),o=u.bind(function(e,t){var n=s(e,t);return c.playCommitBirthPromiseAnimation(n,this.gitVisuals)},this),a=f.defer(),h=a.promise;return u.each(r,function(e){h=h.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.origin.refs[e.id],t)},this)),h=h.then(function(){return o(e.id,e.parents)})},this),h=h.then(u.bind(function(){var e=n.get("target").get("id"),r=this.refs[e];return this.setTargetLocation(t,r),c.playRefreshAnimation(this.origin.gitVisuals),c.playRefreshAnimation(this.gitVisuals)},this)),e.dontResolvePromise||this.animationQueue.thenFinish(h,a),{chain:h,deferred:a}},y.prototype.pullStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.acceptNoGeneralArgs(),this.pull()},y.prototype.pull=function(){var e=this.refs.master,t=this.refs["o/master"],n=this.fetch({dontResolvePromise:!0,dontThrowOnNoFetch:!0});this.commandOptions["--rebase"]?this.pullFinishWithRebase(n,e,t):this.pullFinishWithMerge(n,e,t)},y.prototype.pullFinishWithRebase=function(e,t,n){var r=e.chain,i=e.deferred;r=r.then(function(){return c.getDelayedPromise(300)}),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(n),t)},this)),r=r.then(u.bind(function(){return e.dontResolvePromise=!0,this.rebase(n,t,e)},this)),this.animationQueue.thenFinish(r,i)},y.prototype.pullFinishWithMerge=function(e,t,n){var r=e.chain,i=e.deferred;r=r.then(function(){return c.getDelayedPromise(300)}),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(n),t)},this)),r=r.then(u.bind(function(){return c.playHighlightPromiseAnimation(this.getCommitFromRef(t),n)},this)),r=r.then(function(){return c.getDelayedPromise(700)}),r=r.then(u.bind(function(){var e=this.merge("o/master");return e?c.playCommitBirthPromiseAnimation(e,this.gitVisuals):c.playRefreshAnimation(this.gitVisuals)},this)),this.animationQueue.thenFinish(r,i)},y.prototype.cloneStarter=function(){this.acceptNoGeneralArgs(),this.makeOrigin(this.printTree())},y.prototype.fakeTeamworkStarter=function(){if(!this.hasOrigin())throw new v({msg:l.str("git-error-origin-required")});this.validateArgBounds(this.generalArgs,0,2);var e=this.generalArgs[0]||"master",t=this.generalArgs[1]||1,n=this.origin.resolveID(e);if(n.get("type")!=="branch")throw new v({msg:l.str("git-error-options")});this.fakeTeamwork(t,e)},y.prototype.fakeTeamwork=function(e,t){var n=u.bind(function(){var e=this.getUniqueID();return this.origin.receiveTeamwork(e,t,this.animationQueue)},this),r=u.bind(function(){var e=n();return c.playCommitBirthPromiseAnimation(e,this.origin.gitVisuals)},this),i=function(){return r()},s=f.defer(),o=s.promise;u.each(u.range(e),function(e){o=o.then(function(){return r()})}),this.animationQueue.thenFinish(o,s)},y.prototype.receiveTeamwork=function(e,t,n){this.checkout(this.resolveID(t));var r=this.makeCommit([this.getCommitFromRef("HEAD")],e);return this.setTargetLocation(this.HEAD,r),r},y.prototype.cherrypick=function(e){var t=this.rebaseAltID(e.get("id")),n=this.makeCommit([this.getCommitFromRef("HEAD")],t);return this.setTargetLocation(this.HEAD,n),n},y.prototype.commitStarter=function(){this.acceptNoGeneralArgs();if(this.commandOptions["-am"]&&(this.commandOptions["-a"]||this.commandOptions["-m"]))throw new v({msg:l.str("git-error-options")});var e=null,t=null;this.commandOptions["-a"]&&this.command.addWarning(l.str("git-warning-add")),this.commandOptions["-am"]&&(t=this.commandOptions["-am"],this.validateArgBounds(t,1,1,"-am"),e=t[0]),this.commandOptions["-m"]&&(t=this.commandOptions["-m"],this.validateArgBounds(t,1,1,"-m"),e=t[0]);var n=this.commit();e&&(e=e.replace(/"/g,'"').replace(/^"/g,"").replace(/"$/g,""),n.set("commitMessage",e));var r=c.playCommitBirthPromiseAnimation(n,this.gitVisuals);this.animationQueue.thenFinish(r)},y.prototype.commit=function(){var e=this.getCommitFromRef(this.HEAD),t=null;this.commandOptions["--amend"]&&(e=this.resolveID("HEAD~1"),t=this.rebaseAltID(this.getCommitFromRef("HEAD").get("id")));var n=this.makeCommit([e],t);return this.getDetachedHead()&&this.command.addWarning(l.str("git-warning-detached")),this.setTargetLocation(this.HEAD,n),n},y.prototype.resolveName=function(e){var t=this.resolveID(e);return t.get("type")=="commit"?"commit "+t.get("id"):t.get("type")=="branch"?'branch "'+t.get("id")+'"':this.resolveName(t.get("target"))},y.prototype.resolveID=function(e){if(e===null||e===undefined)throw new Error("Dont call this with null / undefined");return typeof e!="string"?e:this.resolveStringRef(e)},y.prototype.resolveRelativeRef=function(e,t){var n=/([~\^])(\d*)/g,r;while(r=n.exec(t)){var i=e,s=r[2]?parseInt(r[2],10):1;if(r[1]=="^")i=e.getParent(s-1);else while(i&&s--)i=i.getParent(0);if(!i){var o=l.str("git-error-relative-ref",{commit:e.id,match:r[0]});throw new v({msg:o})}e=i}return e},y.prototype.resolveStringRef=function(e){e=this.crappyUnescape(e);if(this.refs[e])return this.refs[e];var t=null,n=null,r=/^([a-zA-Z0-9]+)(([~\^]\d*)*)/,i=r.exec(e);if(!i)throw new v({msg:l.str("git-error-exist",{ref:e})});t=i[1],n=i[2];if(!this.refs[t])throw new v({msg:l.str("git-error-exist",{ref:e})});var s=this.getCommitFromRef(t);return n&&(s=this.resolveRelativeRef(s,n)),s},y.prototype.getCommitFromRef=function(e){var t=this.resolveID(e);while(t.get("type")!=="commit")t=t.get("target");return t},y.prototype.getType=function(e){return this.resolveID(e).get("type")},y.prototype.setTargetLocation=function(e,t){if(this.getType(e)=="commit")return;e=this.getOneBeforeCommit(e),e.set("target",t)},y.prototype.getUpstreamBranchSet=function(){var e={},t=function(e,t){var n=!1;return u.each(e,function(e){e.id==t&&(n=!0)}),n},n=function(e){var t=[],n=[e];while(n.length){var r=n.pop();t.push(r.get("id")),r.get("parents")&&r.get("parents").length&&(n=n.concat(r.get("parents")))}return t};return this.branchCollection.each(function(r){var i=n(r.get("target"));u.each(i,function(n){e[n]=e[n]||[],t(e[n],r.get("id"))||e[n].push({obj:r,id:r.get("id")})})}),e},y.prototype.getUpstreamHeadSet=function(){var e=this.getUpstreamSet("HEAD"),t=this.getCommitFromRef("HEAD").get("id");return e[t]=!0,e},y.prototype.getOneBeforeCommit=function(e){var t=this.resolveID(e);return t===this.HEAD&&!this.getDetachedHead()&&(t=t.get("target")),t},y.prototype.scrapeBaseID=function(e){var t=/^C(\d+)/.exec(e);if(!t)throw new Error("regex failed on "+e);return"C"+t[1]},y.prototype.rebaseAltID=function(e){var t=[[/^C(\d+)[']{0,2}$/,function(e){return e[0]+"'"}],[/^C(\d+)[']{3}$/,function(e){return e[0].slice(0,-3)+"'^4"}],[/^C(\d+)['][\^](\d+)$/,function(e){return"C"+String(e[1])+"'^"+String(Number(e[2])+1)}]];for(var n=0;n",this.get("commitMessage"),"
","Commit: "+this.get("id")].join("\n")+"\n"},getShowEntry:function(){return[this.getLogEntry(),"diff --git a/bigGameResults.html b/bigGameResults.html","--- bigGameResults.html","+++ bigGameResults.html","@@ 13,27 @@ Winner, Score","- Stanfurd, 14-7","+ Cal, 21-14"].join("\n")+"\n"},validateAtInit:function(){if(!this.get("id"))throw new Error("Need ID!!");this.get("createTime")||this.set("createTime",(new Date).toString()),this.get("commitMessage")||this.set("commitMessage",l.str("git-dummy-msg")),this.set("children",[]);if(!this.get("rootCommit"))if(!this.get("parents")||!this.get("parents").length)throw new Error("needs parents")},addNodeToVisuals:function(){var e=this.get("gitVisuals").addNode(this.get("id"),this);this.set("visNode",e)},addEdgeToVisuals:function(e){this.get("gitVisuals").addEdge(this.get("id"),e.get("id"))},getParent:function(e){return this&&this.attributes&&this.attributes.parents?this.attributes.parents[e]:null},isMainParent:function(e){var t=this.get("parents").indexOf(e);return t===0},initialize:function(e){this.validateAtInit(),this.addNodeToVisuals(),u.each(this.get("parents"),function(e){e.get("children").push(this),this.addEdgeToVisuals(e)},this)}});n.GitEngine=y,n.Commit=E,n.Branch=w,n.Ref=b}),e("/src/js/git/index.js"),e.define("/src/js/git/treeCompare.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a={};a.dispatchFromLevel=function(e,t){var n=e.goalTreeString;return a.dispatch(e,n,t)},a.dispatch=function(e,t,n){var r=!0;switch(r){case!!e.compareOnlyMaster:return a.compareBranchWithinTrees(n,t,"master");case!!e.compareOnlyBranches:return a.compareAllBranchesWithinTrees(n,t);case!!e.compareAllBranchesHashAgnostic:return a.compareAllBranchesWithinTreesHashAgnostic(n,t);case!!e.compareOnlyMasterHashAgnostic:return a.compareBranchesWithinTreesHashAgnostic(n,t,["master"]);case!!e.compareOnlyMasterHashAgnosticWithAsserts:return a.compareBranchesWithinTreesHashAgnostic(n,t,["master"])&&a.evalAsserts(n,e.goalAsserts);default:return a.compareAllBranchesWithinTreesAndHEAD(n,t)}},a.compareAllBranchesWithinTreesAndHEAD=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t);debugger;return e.HEAD.target==t.HEAD.target&&this.compareAllBranchesWithinTrees(e,t)},a.compareAllBranchesWithinTrees=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t);var n=u.extend({},e.branches,t.branches),r=!0;return u.uniq(n,function(n,i){r=r&&this.compareBranchWithinTrees(e,t,i)},this),r},a.compareBranchesWithinTrees=function(e,t,n){var r=!0;return u.each(n,function(n){r=r&&this.compareBranchWithinTrees(e,t,n)},this),r},a.compareBranchWithinTrees=function(e,t,n){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var r=this.getRecurseCompare(e,t),i=e.branches[n],s=t.branches[n];return u.isEqual(i,s)&&r(e.commits[i.target],t.commits[s.target])},a.compareAllBranchesWithinTreesHashAgnostic=function(e,t){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var n=u.extend({},e.branches,t.branches),r=[];return u.each(n,function(e,t){r.push(t)}),this.compareBranchesWithinTreesHashAgnostic(e,t,r)},a.compareBranchesWithinTreesHashAgnostic=function(e,t,n){e=this.convertTreeSafe(e),t=this.convertTreeSafe(t),this.reduceTreeFields([e,t]);var r=u.bind(function(e,t){return!e||!t?!1:(e=u.clone(e),t=u.clone(t),e.target=this.getBaseRef(e.target),t.target=this.getBaseRef(t.target),u.isEqual(e,t))},this),i=this.getRecurseCompareHashAgnostic(e,t),s=!0;return u.each(n,function(n){var o=e.branches[n],u=t.branches[n];s=s&&r(o,u)&&i(e.commits[o.target],t.commits[u.target])},this),s},a.evalAsserts=function(e,t){var n=!0;return u.each(t,function(t,r){n=n&&this.evalAssertsOnBranch(e,r,t)},this),n},a.evalAssertsOnBranch=function(e,t,n){e=this.convertTreeSafe(e);if(!e.branches[t])return!1;var r=e.branches[t],i=[r.target],s={};while(i.length){var o=i.pop();s[this.getBaseRef(o)]=this.getNumHashes(o),i=i.concat(e.commits[o].parents)}var a=!0;return u.each(n,function(e){try{a=a&&e(s)}catch(t){console.warn("error during assert",t),console.log(t),a=!1}}),a},a.getNumHashes=function(e){var t=[[/^C(\d+)([']{0,3})$/,function(e){return e[2]?e[2].length:0}],[/^C(\d+)['][\^](\d+)$/,function(e){return Number(e[2])}]];for(var n=0;n []",zh_CN:"git <命令> [<参数>]",fr_FR:"git []"},"git-supported-commands":{__desc__:"In the git help command, the header above the supported commands",en_US:"Supported commands:",zh_CN:"支持的命令有:",fr_FR:"Commandes supportées"},"git-usage":{__desc__:"In the dummy git output, the header before showing all the commands",en_US:"Usage:",zh_CN:"使用:",fr_FR:"Utilisation :"},"git-version":{__desc__:"The git version dummy output, kind of silly. PCOTTLE is my unix name but feel free to put yours instead",en_US:"Git Version PCOTTLE.1.0",zh_CN:"Git 版本 PCOTTLE.1.0",fr_FR:"Git version PCOTTLE.1.0"},"refresh-tree-command":{__desc__:"when the tree is visually refreshed",en_US:"Refreshing tree...",zh_CN:"正在刷新树结构...",fr_FR:"Actualisation de l'arbre…"},"locale-command":{__desc__:"when the locale is set to something",en_US:"Locale set to {locale}",zh_CN:"语言更改为 {locale}",fr_FR:"Langue changée à {locale}"},"locale-reset-command":{__desc__:"when the locale is reset",en_US:"Locale reset to default, which is {locale}",zh_CN:"语言重置为默认的 {locale}",fr_FR:"Langue remise par défaut, qui est {locale}"},"show-command":{__desc__:'command output title from "show"',en_US:"Please use one of the following commands for more info:",fr_FR:"Merci d'utiliser une des commandes suivantes pour obtenir plus d'info"},"show-all-commands":{__desc__:'command output title from "show commands"',en_US:"Here is a list of all the commmands available:",fr_FR:"Ci-dessous est la liste de toutes les commandes disponibles :"},"cd-command":{__desc__:"dummy command output for the command in the key",en_US:'Directory changed to "/directories/dont/matter/in/this/demo"',zh_CN:'目录切换到 "/directories/dont/matter/in/this/demo"',fr_FR:'Répertoire changé à "/directories/dont/matter/in/this/demo" (les répertoires ne servent à rien dans cette démo)'},"ls-command":{__desc__:"Dummy command output for the command in the key",en_US:"DontWorryAboutFilesInThisDemo.txt",zh_CN:"DontWorryAboutFilesInThisDemo.txt (译: 在试验里不用担心文件.txt)",fr_FR:"DontWorryAboutFilesInThisDemo.txt (ne vous préoccupez pas des noms de fichier dans cette démo)"},"mobile-alert":{__desc__:"When someone comes to the site on a mobile device, they can not input commands so this is a nasty alert to tell them",en_US:"Can't bring up the keyboard on mobile / tablet :( try visiting on desktop! :D",zh_CN:"无法在移动设备/平板上调出键盘 :( 请试试桌面版 :D",fr_FR:"Impossible de faire apparaître le clavier sur mobile / tablette :( Essayez de passer sur un ordinateur de bureau :D"},"share-tree":{__desc__:"When you export a tree, we want you to share the tree with friends",en_US:'Share this tree with friends! They can load it with "import tree"',zh_CN:'与你的好友分享提交树!他们可以用 "import tree" 加载它',fr_FR:'Partagez cet arbre avec vos amis ! Ils peuvent le charger avec "import tree"'},"paste-json":{__desc__:"When you are importing a level or tree",en_US:"Paste a JSON blob below!",zh_CN:"在下边粘贴一个JSON串",fr_FR:"Collez un blob JSON ci-dessous !"},"solved-map-reset":{__desc__:"When you reset the solved map to clear your solved history, in case someone else wants to use your browser",en_US:"Solved map was reset, you are starting from a clean slate!",zh_CN:"解决列表已重置,您现在从零开始了",fr_FR:"La carte des niveaux résolus a été effacée, vous repartez de zéro !"},"level-cant-exit":{__desc__:"When the user tries to exit a level when they are not in one",en_US:'You are not in a level! You are in a sandbox, start a level with "levels"',zh_CN:'您没在关卡中!您在沙盒中,要开始关卡请输入 "levels"',fr_FR:'Vous n\'êtes pas dans un niveau ! Vous êtes dans le mode bac à sable, commencez un niveau avec "levels"'},"level-no-id":{__desc__:"When you say an id but that level doesnt exist",en_US:'A level for that id "{id}" was not found! Opening up a level selection view',zh_CN:'没找到id为 "{id}" 的关卡!打开关卡选择框',fr_FR:"Le niveau dont l'identifiant est {id} n'a pas été trouvé ! Ouverture de la vue de sélection des niveaux"},"undo-stack-empty":{__desc__:"The undo command can only undo back until the last time the level was reset or the beginning of the level",en_US:"The undo stack is empty!",zh_CN:"还没有什么可以撤销",fr_FR:"La pile d'annulation est vide !"},"already-solved":{__desc__:"When you play in a level that is already solved",en_US:'You have already solved this level, try other levels with "levels" or go back to sandbox with "sandbox"',zh_CN:'你已经解决了本关,输入 "levels" 尝试其他关卡,或者输入 "sandbox" 回到沙盒中',fr_FR:'Vous avez déjà résolu ce niveau, essayez d\'autres niveaux avec "levels" ou revenez au bac à sable avec "sandbox"'},"command-disabled":{__desc__:"When you try a command that is disabled",en_US:"That git command is disabled for this level!",zh_CN:"该命令在本关不允许使用!",fr_FR:"Cette commande git est désactivée pour ce niveau !"},"share-json":{__desc__:"when you have made the level, prompt to share this",en_US:"Here is the JSON for this level! Share it with somenoe or send it to me on Github",zh_CN:"这是一个关卡定义JSON!您可以分享它或者发到我的GitHub上",fr_FR:"Voici le JSON pour ce niveau ! Partagez-le avec quelqu'un ou envoyez-le moi sur Github"},"want-start-dialog":{__desc__:"prompt to add a start dialog",en_US:"You have not specified a start dialog, would you like to add one?",zh_CN:"您还没有定义一开始的介绍,是否添加一个?",fr_FR:"Vous n'avez pas spécifié de dialogue de départ, voulez-vous en ajouter un ?"},"want-hint":{__desc__:"prompt to add a hint",en_US:"You have not specified a hint, would you like to add one?",zh_CN:"您还没有定义提示,是否添加一个?",fr_FR:"Vous n'avez pas spécifié d'indice, voulez-vous en ajouter un ?"},"prompt-hint":{__desc__:"prompt for hint",en_US:"Enter the hint for this level, or leave this blank if you do not want to include one",zh_CN:"请输入关卡提示,或者故意留空",fr_FR:"Entrez l'indice pour ce niveau, ou laissez-le vide pour ne pas l'inclure"},"prompt-name":{__desc__:"prompt for level name",en_US:"Enter the name for the level",zh_CN:"输入关卡名",fr_FR:"Entrez le nom pour ce niveau"},"solution-empty":{__desc__:"If you define a solution without any commands, aka a level that is solved without doing anything",en_US:"Your solution is empty!! Something is amiss",zh_CN:"你的解法是空的!! 这应该是出错了",fr_FR:"Votre solution est vide !! Quelque chose ne tourne pas rond"},"define-start-warning":{__desc__:"When you define the start point again, it overwrites the solution and goal so we add a warning",en_US:"Defining start point... solution and goal will be overwritten if they were defined earlier",zh_CN:"定义开始点... 解决方法和目标会被新的替代",fr_FR:"Redéfinition du point de départ… la solution et la cible seront écrasés s'ils ont déjà été définis"},"help-vague-level":{__desc__:"When you are in a level and you say help, its vague and you need to specify",en_US:'You are in a level, so multiple forms of help are available. Please select either "help level" to learn more about this lesson, "help general" for using Learn GitBranching, or "objective" to learn about how to solve the level.',zh_CN:'您正在关卡中,这里有多种形式的帮助,请选择 "help level" (关卡帮助)或 "help general" (一般帮助)',fr_FR:'Vous êtes dans un niveau, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help level" pour en apprendre plus sur cette leçon, "help general" pour l\'utilisation de Learn GitBranching, ou "objective" pour apprendre comment résoudre le niveau'},"help-vague-builder":{__desc__:"When you are in a level builder, the help command is vague so you need to specify what you mean",en_US:'You are in a level builder, so multiple forms of help are available. Please select either "help general" or "help builder"',zh_CN:'您正在进行关卡构建中,这里有多种形式的帮助,请选择 "help general" (一般帮助)或 "help builder" (关卡构建帮助)',fr_FR:'Vous êtes dans l\'éditeur de niveaux, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help general" soit "help builder"'},"goal-to-reach":{__desc__:"title of window that shoes the goal tree to reach",en_US:"Goal To Reach",zh_CN:"目标",fr_FR:"Cible à atteindre"},"hide-goal":{__desc__:"the helper message for the window that shows the goal tree",en_US:'You can hide this window with "hide goal"',zh_CN:'你可以通过命令 "hide goal" 关闭这个窗口',fr_FR:'Vous pouvez masquer cette fenêtre avec "hide goal"'},"hide-start":{__desc__:"The helper message for the window that shows the start tree for a level",en_US:'You can hide this window with "hide start"',zh_CN:'你可以通过命令 "hide start" 关闭这个窗口',fr_FR:'Vous pouvez masquer cette fenêtre avec "hide start"'},"level-builder":{__desc__:"The name for the environment where you build levels",en_US:"Level Builder",zh_CN:"关卡生成器",fr_FR:"Éditeur de niveaux"},"no-start-dialog":{__desc__:"when the user tries to open a start dialog for a level that does not have one",en_US:"There is no start dialog to show for this level!",zh_CN:"介绍? 这关真没有!",fr_FR:"Il n'y a aucun dialogue de départ à afficher pour ce niveau !"},"no-hint":{__desc__:"when no hint is available for a level",en_US:"Hmm, there doesn't seem to be a hint for this level :-/",zh_CN:"提示?嗯,这关真没有哎~ :-/",fr_FR:"Hum, il ne semble pas y avoir d'indice pour ce niveau :-/"},"error-untranslated-key":{__desc__:"This error happens when we are trying to translate a specific key and the locale version is mission",en_US:"The translation for {key} does not exist yet :( Please hop on github and offer up a translation!",zh_CN:"还没翻译 {key} :( 请在gitHub上贡献你的翻译!",fr_FR:"La traduction pour {key} n'existe pas encore :( Venez sur Github pour en offrir une !"},"error-untranslated":{__desc__:"The general error when we encounter a dialog that is not translated",en_US:"This dialog or text is not yet translated in your locale :( Hop on github to aid in translation!",zh_CN:"这段对话还没有被翻译成你的语言 :( 欢迎在gitHub上贡献你的翻译!",fr_FR:"Ce message n'a pas encore été traduit dans votre langue :( Venez sur Github aider à la traduction !"}}}),e("/src/js/intl/strings.js"),e.define("/src/js/level/arbiter.js",function(e,t,n,r,i,s,o){function h(){this.levelMap={},this.levelSequences=f,this.sequences=[],this.init();var e;try{e=JSON.parse(localStorage.getItem("solvedMap")||"{}")}catch(t){console.warn("local storage failed",t)}this.solvedMap=e||{},c.getEvents().on("levelSolved",this.levelSolved,this)}var u=e("underscore"),a=e("backbone"),f=e("../../levels").levelSequences,l=e("../../levels").sequenceInfo,c=e("../app");h.prototype.init=function(){var e;u.each(this.levelSequences,function(e,t){this.sequences.push(t);if(!e||!e.length)throw new Error("no empty sequences allowed");u.each(e,function(e,n){this.validateLevel(e);var r=t+String(n+1),i=u.extend({},e,{index:n,id:r,sequenceName:t});this.levelMap[r]=i,this.levelSequences[t][n]=i},this)},this)},h.prototype.isLevelSolved=function(e){if(!this.levelMap[e])throw new Error("that level doesnt exist!");return Boolean(this.solvedMap[e])},h.prototype.levelSolved=function(e){if(!e)return;this.solvedMap[e]=!0,this.syncToStorage()},h.prototype.resetSolvedMap=function(){this.solvedMap={},this.syncToStorage(),c.getEvents().trigger("levelSolved")},h.prototype.syncToStorage=function(){try{localStorage.setItem("solvedMap",JSON.stringify(this.solvedMap))}catch(e){console.warn("local storage fialed on set",e)}},h.prototype.validateLevel=function(e){e=e||{};var t=["name","goalTreeString","solutionCommand"],n=["hint","disabledMap","startTree"];u.each(t,function(t){if(e[t]===undefined)throw console.log(e),new Error("I need this field for a level: "+t)})},h.prototype.getSequenceToLevels=function(){return this.levelSequences},h.prototype.getSequences=function(){return u.keys(this.levelSequences)},h.prototype.getLevelsInSequence=function(e){if(!this.levelSequences[e])throw new Error("that sequecne name "+e+"does not exist");return this.levelSequences[e]},h.prototype.getSequenceInfo=function(e){return l[e]},h.prototype.getLevel=function(e){return this.levelMap[e]},h.prototype.getNextLevel=function(e){if(!this.levelMap[e])return console.warn("that level doesnt exist!!!"),null;var t=this.levelMap[e],n=t.sequenceName,r=this.levelSequences[n],i=t.index+1;if(i","show commands","show solution","show goal"];throw new v({msg:t.join("\n")})}],[/^locale (\w+)$/,function(t){f.GLOBAL.locale=t[1];var n=e("../app").getEvents().trigger("localeChanged");throw new v({msg:l.str("locale-command",{locale:t[1]})})}],[/^refresh$/,function(){var t=e("../app").getEvents();throw t.trigger("refreshTree"),new v({msg:l.str("refresh-tree-command")})}],[/^rollup (\d+)$/,function(t){var n=e("../app").getEvents();throw n.trigger("rollupCommands",t[1]),new v({msg:"Commands combined!"})}],[/^echo "(.*?)"$|^echo (.*?)$/,function(e){var t=e[1]||e[2];throw new v({msg:t})}],[/^show +commands$/,function(e){var t=y(),n=[l.str("show-all-commands"),"
"];throw u.each(t,function(e,t){n.push(t)}),new v({msg:n.join("\n")})}]],g={"reset solved":/^reset solved($|\s)/,help:/^help( +general)?$|^\?$/,reset:/^reset( +--forSolution)?$/,delay:/^delay (\d+)$/,clear:/^clear($|\s)/,"exit level":/^exit level($|\s)/,sandbox:/^sandbox($|\s)/,level:/^level\s?([a-zA-Z0-9]*)/,levels:/^levels($|\s)/,mobileAlert:/^mobile alert($|\s)/,"build level":/^build +level($|\s)/,"export tree":/^export +tree$/,"import tree":/^import +tree$/,"import level":/^import +level$/,undo:/^undo($|\s)/},y=function(){var t=["mobileAlert"],n=u.extend({},e("../git/commands").regexMap,e("../level").regexMap,g);return u.each(t,function(e){delete n[e]}),n};n.instantCommands=m,n.parse=a.genParseCommand(g,"processSandboxCommand"),n.getOptimisticLevelParse=function(){return a.genParseCommand(e("../level").regexMap,"processLevelCommand")},n.getOptimisticLevelBuilderParse=function(){return a.genParseCommand(e("../level/builder").regexMap,"processLevelBuilderCommand")}}),e("/src/js/level/sandboxCommands.js"),e.define("/src/js/log/index.js",function(e,t,n,r,i,s,o){var u=function(e,t,n){window._gaq=window._gaq||[],window._gaq.push(["_trackEvent",e,t,n])};n.viewInteracted=function(e){u("views","interacted",e)},n.showLevelSolution=function(e){u("levels","showedLevelSolution",e)},n.choseNextLevel=function(e){u("levels","nextLevelChosen",e)},n.levelSelected=function(e){u("levels","levelSelected",e)},n.levelSolved=function(e){u("levels","levelSolved",e)},n.commandEntered=function(e){u("commands","commandEntered",e)}}),e("/src/js/log/index.js"),e.define("/src/js/models/collections.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?f=window.Backbone:f=e("backbone"),l=e("../git").Commit,c=e("../git").Branch,h=e("../models/commandModel").Command,p=e("../models/commandModel").CommandEntry,d=e("../util/constants").TIME,v=f.Collection.extend({model:l}),m=f.Collection.extend({model:h}),g=f.Collection.extend({model:c}),y=f.Collection.extend({model:p,localStorage:f.LocalStorage?new f.LocalStorage("CommandEntries"):null}),b=f.Model.extend({defaults:{collection:null},initialize:function(e){e.collection.bind("add",this.addCommand,this),this.buffer=[],this.timeout=null},addCommand:function(e){this.buffer.push(e),this.touchBuffer()},touchBuffer:function(){if(this.timeout)return;this.setTimeout()},setTimeout:function(){this.timeout=setTimeout(u.bind(function(){this.sipFromBuffer()},this),d.betweenCommandsDelay)},popAndProcess:function(){var e=this.buffer.shift(0);while(e.get("error")&&this.buffer.length)e=this.buffer.shift(0);e.get("error")?this.clear():this.processCommand(e)},processCommand:function(t){t.set("status","processing");var n=a.defer();n.promise.then(u.bind(function(){this.setTimeout()},this));var r=t.get("eventName");if(!r)throw new Error("I need an event to trigger when this guy is parsed and ready");var i=e("../app"),s=i.getEventBaton(),o=s.getNumListeners(r);if(!o){var f=e("../util/errors");t.set("error",new f.GitError({msg:"That command is valid, but not supported in this current environment! Try entering a level or level builder to use that command"})),n.resolve();return}i.getEventBaton().trigger(r,t,n)},clear:function(){clearTimeout(this.timeout),this.timeout=null},sipFromBuffer:function(){if(!this.buffer.length){this.clear();return}this.popAndProcess()}});n.CommitCollection=v,n.CommandCollection=m,n.BranchCollection=g,n.CommandEntryCollection=y,n.CommandBuffer=b}),e("/src/js/models/collections.js"),e.define("/src/js/models/commandModel.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../util/errors"),l=e("../git/commands"),c=l.GitOptionParser,h=e("../level/parseWaterfall").ParseWaterfall,p=f.CommandProcessError,d=f.GitError,v=f.Warning,m=f.CommandResult,g=a.Model.extend({defaults:{status:"inqueue",rawStr:null,result:"",createTime:null,error:null,warnings:null,parseWaterfall:new h,generalArgs:null,supportedMap:null,options:null,method:null},initialize:function(e){this.initDefaults(),this.validateAtInit(),this.on("change:error",this.errorChanged,this),this.get("error")&&this.errorChanged(),this.parseOrCatch()},initDefaults:function(){this.set("generalArgs",[]),this.set("supportedMap",{}),this.set("warnings",[])},validateAtInit:function(){if(this.get("rawStr")===null)throw new Error("Give me a string!");this.get("createTime")||this.set("createTime",(new Date).toString())},setResult:function(e){this.set("result",e)},finishWith:function(e){this.set("status","finished"),e.resolve()},addWarning:function(e){this.get("warnings").push(e),this.set("numWarnings",this.get("numWarnings")?this.get("numWarnings")+1:1)},getFormattedWarnings:function(){if(!this.get("warnings").length)return"";var e='';return"

"+e+this.get("warnings").join("

"+e)+"

"},parseOrCatch:function(){this.expandShortcuts(this.get("rawStr"));try{this.processInstants()}catch(e){f.filterError(e),this.set("error",e);return}if(this.parseAll())return;this.set("error",new p({msg:'The command "'+this.get("rawStr")+"\" isn't supported, sorry!"}))},errorChanged:function(){var e=this.get("error");e instanceof p||e instanceof d?this.set("status","error"):e instanceof m?this.set("status","finished"):e instanceof v&&this.set("status","warning"),this.formatError()},formatError:function(){this.set("result",this.get("error").toResult())},expandShortcuts:function(e){e=this.get("parseWaterfall").expandAllShortcuts(e),this.set("rawStr",e)},processInstants:function(){var e=this.get("rawStr");if(!e.length)throw new m({msg:""});this.get("parseWaterfall").processAllInstants(e)},parseAll:function(){var e=this.get("rawStr"),t=this.get("parseWaterfall").parseAll(e);return t?(u.each(t.toSet,function(e,t){this.set(t,e)},this),!0):!1}}),y=a.Model.extend({defaults:{text:""}});n.CommandEntry=y,n.Command=g}),e("/src/js/models/commandModel.js"),e.define("/src/js/util/constants.js",function(e,t,n,r,i,s,o){var u={betweenCommandsDelay:400},a={isAnimating:!1},f={minZoom:.55,maxZoom:1.25,minWidth:600,minHeight:600},l={arrowHeadSize:8,nodeRadius:17,curveControlPointOffset:50,defaultEasing:"easeInOut",defaultAnimationTime:400,rectFill:"hsb(0.8816909813322127,0.7,1)",headRectFill:"#2831FF",rectStroke:"#FFF",rectStrokeWidth:"3",originDash:"- ",multiBranchY:20,upstreamHeadOpacity:.5,upstreamNoneOpacity:.2,edgeUpstreamHeadOpacity:.4,edgeUpstreamNoneOpacity:.15,visBranchStrokeWidth:2,visBranchStrokeColorNone:"#333",defaultNodeFill:"hsba(0.5,0.8,0.7,1)",defaultNodeStrokeWidth:2,defaultNodeStroke:"#FFF",orphanNodeFill:"hsb(0.5,0.8,0.7)"};n.GLOBAL=a,n.TIME=u,n.GRAPHICS=l,n.VIEWPORT=f}),e("/src/js/util/constants.js"),e.define("/src/js/util/debug.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a={Tree:e("../visuals/tree"),Visuals:e("../visuals"),Git:e("../git"),CommandModel:e("../models/commandModel"),Levels:e("../git/treeCompare"),Constants:e("../util/constants"),Collections:e("../models/collections"),Async:e("../visuals/animation"),AnimationFactory:e("../visuals/animation/animationFactory"),Main:e("../app"),HeadLess:e("../git/headless"),Q:{Q:e("q")},RebaseView:e("../views/rebaseView"),Views:e("../views"),MultiView:e("../views/multiView"),ZoomLevel:e("../util/zoomLevel"),VisBranch:e("../visuals/visBranch"),Level:e("../level"),Sandbox:e("../level/sandbox"),GitDemonstrationView:e("../views/gitDemonstrationView"),Markdown:e("markdown"),LevelDropdownView:e("../views/levelDropdownView"),BuilderViews:e("../views/builderViews"),Intl:e("../intl")};u.each(a,function(e){for(var t in e)window["debug_"+t]=e[t]}),$(document).ready(function(){window.events=a.Main.getEvents(),window.eventBaton=a.Main.getEventBaton(),window.sandbox=a.Main.getSandbox(),window.modules=a,window.levelDropdown=a.Main.getLevelDropdown(),window.under=u,window.copyTree=function(){return a.Main.getSandbox().mainVis.gitEngine.printAndCopyTree()}})}),e("/src/js/util/debug.js"),e.define("/src/js/util/errors.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({defaults:{type:"MyError",msg:"Unknown Error"},toString:function(){return this.get("type")+": "+this.get("msg")},getMsg:function(){return this.get("msg")||"Unknown Error"},toResult:function(){return this.get("msg").length?"

"+this.get("msg").replace(/\n/g,"

")+"

":""}}),l=n.CommandProcessError=f.extend({defaults:{type:"Command Process Error"}}),c=n.CommandResult=f.extend({defaults:{type:"Command Result"}}),h=n.Warning=f.extend({defaults:{type:"Warning"}}),p=n.GitError=f.extend({defaults:{type:"Git Error"}}),d=function(e){if(e instanceof l||e instanceof p||e instanceof c||e instanceof h)return;throw e};n.filterError=d}),e("/src/js/util/errors.js"),e.define("/src/js/util/eventBaton.js",function(e,t,n,r,i,s,o){function a(){this.eventMap={}}var u=e("underscore");a.prototype.stealBaton=function(e,t,n){if(!e)throw new Error("need name");if(!t)throw new Error("need func!");var r=this.eventMap[e]||[];r.push({func:t,context:n}),this.eventMap[e]=r},a.prototype.sliceOffArgs=function(e,t){var n=[];for(var r=e;r0&&!e.length)return;t(e)})},n.genParseCommand=function(e,t){return function(n){var r,i;return u.each(e,function(e,t){var s=e.exec(n);s&&(r=t,i=s)}),r?{toSet:{eventName:t,method:r,regexResults:i}}:!1}}}),e("/src/js/util/index.js"),e.define("/src/js/util/keyboard.js",function(e,t,n,r,i,s,o){function c(e){this.events=e.events||u.clone(a.Events),this.aliasMap=e.aliasMap||{},e.wait||this.listen()}var u=e("underscore"),a=e("backbone"),f=e("../app"),l=function(e){var t={37:"left",38:"up",39:"right",40:"down",27:"esc",13:"enter"};return t[e]};c.prototype.listen=function(){if(this.listening)return;this.listening=!0,f.getEventBaton().stealBaton("docKeydown",this.keydown,this)},c.prototype.mute=function(){this.listening=!1,f.getEventBaton().releaseBaton("docKeydown",this.keydown,this)},c.prototype.keydown=function(e){var t=e.which||e.keyCode,n=l(t);if(n===undefined)return;this.fireEvent(n,e)},c.prototype.fireEvent=function(e,t){e=this.aliasMap[e]||e,this.events.trigger(e,t)},c.prototype.passEventBack=function(e){f.getEventBaton().passBatonBackSoft("docKeydown",this.keydown,this,[e])},n.KeyboardListener=c,n.mapKeycodeToKey=l}),e("/src/js/util/keyboard.js"),e.define("/src/js/util/mock.js",function(e,t,n,r,i,s,o){n.mock=function(e){var t={},n=function(){};for(var r in e.prototype)t[r]=n;return t}}),e("/src/js/util/mock.js"),e.define("/src/js/util/zoomLevel.js",function(e,t,n,r,i,s,o){function f(){return!window.outerWidth||!window.innerWidth?(a&&(console.warn("Can't detect zoom level correctly :-/"),a=!1),1):window.outerWidth/window.innerWidth}var u=e("underscore"),a=!0,l=!0,c=function(e,t){var n=0;setInterval(function(){var r=f();if(r!==n){if(l){l=!1;return}n=r,e.apply(t,[r])}else l=!0},500)};n.setupZoomPoll=c,n.detectZoom=f}),e("/src/js/util/zoomLevel.js"),e.define("/src/js/views/builderViews.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../intl"),h=e("../util/keyboard").KeyboardListener,p=e("../views"),d=p.ModalTerminal,v=p.ContainedBase,m=v.extend({tagName:"div",className:"textGrabber box vertical",template:u.template($("#text-grabber").html()),initialize:function(e){e=e||{},this.JSON={helperText:e.helperText||"Enter some text"},this.container=e.container||new d({title:"Enter some text"}),this.render(),e.initialText&&this.setText(e.initialText),e.wait||this.show()},getText:function(){return this.$("textarea").val()},setText:function(e){this.$("textarea").val(e)}}),g=v.extend({tagName:"div",className:"markdownGrabber box horizontal",template:u.template($("#markdown-grabber-view").html()),events:{"keyup textarea":"keyup"},initialize:function(e){e=e||{},this.deferred=e.deferred||a.defer(),e.fromObj&&(e.fillerText=e.fromObj.options.markdowns.join("\n")),this.JSON={previewText:e.previewText||"Preview",fillerText:e.fillerText||"## Enter some markdown!\n\n\n"},this.container=e.container||new d({title:e.title||"Enter some markdown"}),this.render();if(!e.withoutButton){var t=a.defer();t.promise.then(u.bind(this.confirmed,this)).fail(u.bind(this.cancelled,this)).done();var n=new p.ConfirmCancelView({deferred:t,destination:this.getDestination()})}this.updatePreview(),e.wait||this.show()},confirmed:function(){this.die(),this.deferred.resolve(this.getRawText())},cancelled:function(){this.die(),this.deferred.resolve()},keyup:function(){this.throttledPreview||(this.throttledPreview=u.throttle(u.bind(this.updatePreview,this),500)),this.throttledPreview()},getRawText:function(){return this.$("textarea").val()},exportToArray:function(){return this.getRawText().split("\n")},getExportObj:function(){return{markdowns:this.exportToArray()}},updatePreview:function(){var t=this.getRawText(),n=e("markdown").markdown.toHTML(t);this.$("div.insidePreview").html(n)}}),y=v.extend({tagName:"div",className:"markdownPresenter box vertical",template:u.template($("#markdown-presenter").html()),initialize:function(e){e=e||{},this.deferred=e.deferred||a.defer(),this.JSON={previewText:e.previewText||"Here is something for you",fillerText:e.fillerText||"# Yay"},this.container=new d({title:"Check this out..."}),this.render();if(!e.noConfirmCancel){var t=new p.ConfirmCancelView({destination:this.getDestination()});t.deferred.promise.then(u.bind(function(){this.deferred.resolve(this.grabText())},this)).fail(u.bind(function(){this.deferred.reject()},this)).done(u.bind(this.die,this))}this.show()},grabText:function(){return this.$("textarea").val()}}),b=v.extend({tagName:"div",className:"demonstrationBuilder box vertical",template:u.template($("#demonstration-builder").html()),events:{"click div.testButton":"testView"},initialize:function(e){e=e||{},this.deferred=e.deferred||a.defer();if(e.fromObj){var t=e.fromObj.options;e=u.extend({},e,t,{beforeMarkdown:t.beforeMarkdowns.join("\n"),afterMarkdown:t.afterMarkdowns.join("\n")})}this.JSON={},this.container=new d({title:"Demonstration Builder"}),this.render(),this.beforeMarkdownView=new g({container:this,withoutButton:!0,fillerText:e.beforeMarkdown,previewText:"Before demonstration Markdown"}),this.beforeCommandView=new m({container:this,helperText:"The git command(s) to set up the demonstration view (before it is displayed)",initialText:e.beforeCommand||"git checkout -b bugFix"}),this.commandView=new m({container:this,helperText:"The git command(s) to demonstrate to the reader",initialText:e.command||"git commit"}),this.afterMarkdownView=new g({container:this,withoutButton:!0,fillerText:e.afterMarkdown,previewText:"After demonstration Markdown"});var n=a.defer(),r=new p.ConfirmCancelView({deferred:n,destination:this.getDestination()});n.promise.then(u.bind(this.confirmed,this)).fail(u.bind(this.cancelled,this)).done()},testView:function(){var t=e("../views/multiView").MultiView;new t({childViews:[{type:"GitDemonstrationView",options:this.getExportObj()}]})},getExportObj:function(){return{beforeMarkdowns:this.beforeMarkdownView.exportToArray(),afterMarkdowns:this.afterMarkdownView.exportToArray(),command:this.commandView.getText(),beforeCommand:this.beforeCommandView.getText()}},confirmed:function(){this.die(),this.deferred.resolve(this.getExportObj())},cancelled:function(){this.die(),this.deferred.resolve()},getInsideElement:function(){return this.$(".insideBuilder")[0]}}),w=v.extend({tagName:"div",className:"multiViewBuilder box vertical",template:u.template($("#multi-view-builder").html()),typeToConstructor:{ModalAlert:g,GitDemonstrationView:b},events:{"click div.deleteButton":"deleteOneView","click div.testButton":"testOneView","click div.editButton":"editOneView","click div.testEntireView":"testEntireView","click div.addView":"addView","click div.saveView":"saveView","click div.cancelView":"cancel"},initialize:function(e){e=e||{},this.deferred=e.deferred||a.defer(),this.multiViewJSON=e.multiViewJSON||{},this.JSON={views:this.getChildViews(),supportedViews:u.keys(this.typeToConstructor)},this.container=new d({title:"Build a MultiView!"}),this.render(),this.show()},saveView:function(){this.hide(),this.deferred.resolve(this.multiViewJSON)},cancel:function(){this.hide(),this.deferred.resolve()},addView:function(e){var t=e.target,n=$(t).attr("data-type"),r=a.defer(),i=this.typeToConstructor[n],s=new i({deferred:r});r.promise.then(u.bind(function(){var e={type:n,options:s.getExportObj()};this.addChildViewObj(e)},this)).fail(function(){}).done()},testOneView:function(t){var n=t.target,r=$(n).attr("data-index"),i=this.getChildViews()[r],s=e("../views/multiView").MultiView;new s({childViews:[i]})},testEntireView:function(){var t=e("../views/multiView").MultiView;new t({childViews:this.getChildViews()})},editOneView:function(e){var t=e.target,n=$(t).attr("data-index"),r=$(t).attr("data-type"),i=a.defer(),s=new this.typeToConstructor[r]({deferred:i,fromObj:this.getChildViews()[n]});i.promise.then(u.bind(function(){var e={type:r,options:s.getExportObj()},t=this.getChildViews();t[n]=e,this.setChildViews(t)},this)).fail(function(){}).done()},deleteOneView:function(e){var t=e.target,n=$(t).attr("data-index"),r=this.getChildViews(),i=r.slice(0,n).concat(r.slice(n+1));this.setChildViews(i),this.update()},addChildViewObj:function(e,t){var n=this.getChildViews();n.push(e),this.setChildViews(n),this.update()},setChildViews:function(e){this.multiViewJSON.childViews=e},getChildViews:function(){return this.multiViewJSON.childViews||[]},update:function(){this.JSON.views=this.getChildViews(),this.renderAgain()}});n.MarkdownGrabber=g,n.DemonstrationBuilder=b,n.TextGrabber=m,n.MultiViewBuilder=w,n.MarkdownPresenter=y}),e("/src/js/views/builderViews.js"),e.define("/src/js/views/commandViews.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../models/collections").CommandEntryCollection,l=e("../app"),c=e("../models/commandModel").Command,h=e("../models/commandModel").CommandEntry,p=e("../util/errors"),d=p.Warning,v=e("../util"),m=e("../log"),g=e("../util/keyboard"),y=a.View.extend({initialize:function(e){l.getEvents().on("commandSubmittedPassive",this.addToCommandHistory,this),this.commands=new f,this.commands.fetch({success:u.bind(function(){var e=[];this.commands.each(function(t){e.push(t)}),e.reverse(),this.commands.reset(),u.each(e,function(e){this.commands.add(e)},this)},this)}),this.index=-1,this.commandParagraph=this.$("#prompt p.command")[0],this.commandCursor=this.$("#prompt span.cursor")[0],this.focus(),l.getEvents().on("rollupCommands",this.rollupCommands,this),l.getEventBaton().stealBaton("keydown",this.onKeyDown,this),l.getEventBaton().stealBaton("keyup",this.onKeyUp,this)},events:{"blur #commandTextField":"hideCursor","focus #commandTextField":"showCursor"},blur:function(){this.hideCursor()},focus:function(){this.$("#commandTextField").focus(),this.showCursor()},hideCursor:function(){this.toggleCursor(!1)},showCursor:function(){this.toggleCursor(!0)},toggleCursor:function(e){$(this.commandCursor).toggleClass("shown",e)},onKeyDown:function(e){var t=e.target;this.updatePrompt(t)},onKeyUp:function(e){this.onKeyDown(e);var t={enter:u.bind(function(){this.submit()},this),up:u.bind(function(){this.commandSelectChange(1)},this),down:u.bind(function(){this.commandSelectChange(-1)},this)},n=g.mapKeycodeToKey(e.which||e.keyCode);t[n]!==undefined&&(e.preventDefault(),t[n](),this.onKeyDown(e))},badHtmlEncode:function(e){return e.replace(/&/g,"&").replace(/=this.commands.length||this.index<0){this.clear(),this.index=-1;return}var t=this.commands.toArray()[this.index].get("text");this.setTextField(t)},clearLocalStorage:function(){this.commands.each(function(e){a.sync("delete",e,function(){})},this)},setTextField:function(e){this.$("#commandTextField").val(e)},clear:function(){this.setTextField("")},submit:function(){var e=this.$("#commandTextField").val().replace("\n","");this.clear(),this.submitCommand(e),this.index=-1},rollupCommands:function(e){var t=this.commands.toArray().slice(1,Number(e)+1);t.reverse();var n="";u.each(t,function(e){n+=e.get("text")+";"},this);var r=new h({text:n});this.commands.unshift(r),a.sync("create",r,function(){})},addToCommandHistory:function(e){var t=e.length&&this.index===-1||e.length&&this.index!==-1&&this.commands.toArray()[this.index].get("text")!==e;if(!t)return;var n=new h({text:e});this.commands.unshift(n),a.sync("create",n,function(){}),this.commands.length>100&&this.clearLocalStorage(),m.commandEntered(e)},submitCommand:function(e){l.getEventBaton().trigger("commandSubmitted",e)}}),b=a.View.extend({tagName:"div",model:c,template:u.template($("#command-template").html()),events:{click:"clicked"},clicked:function(e){},initialize:function(){this.model.bind("change",this.wasChanged,this),this.model.bind("destroy",this.remove,this)},wasChanged:function(e,t){var n=t.changes,r=u.keys(n);u.difference(r,["status"]).length===0?this.updateStatus():this.render()},updateStatus:function(){var e=["inqueue","processing","finished"],t={};u.each(e,function(e){t[e]=!1}),t[this.model.get("status")]=!0;var n=this.$("p.commandLine");u.each(t,function(e,t){n.toggleClass(t,e)})},render:function(){var e=u.extend({resultType:"",result:"",formattedWarnings:this.model.getFormattedWarnings()},this.model.toJSON());return this.$el.html(this.template(e)),this},remove:function(){$(this.el).hide()}}),w=a.View.extend({initialize:function(e){this.collection=e.collection,this.collection.on("add",this.addOne,this),this.collection.on("reset",this.addAll,this),this.collection.on("all",this.render,this),this.collection.on("change",this.scrollDown,this),l.getEvents().on("commandScrollDown",this.scrollDown,this),l.getEvents().on("clearOldCommands",this.clearOldCommands,this)},addWarning:function(e){var t=new d({msg:e}),n=new c({error:t,rawStr:"Warning:"});this.collection.add(n)},clearOldCommands:function(){var e=[];this.collection.each(function(t){t.get("status")!=="inqueue"&&t.get("status")!=="processing"&&e.push(t)},this),u.each(e,function(e){e.destroy()},this),this.scrollDown()},scrollDown:function(){var e=$("#commandDisplay")[0],t=$("#terminal")[0],n=e.clientHeight>t.clientHeight||$(window).height() p.uiButton":"positive"},initialize:function(t){t=t||{},this.options=t,this.JSON=u.extend({beforeMarkdowns:["## Git Commits","","Awesome!"],command:"git commit",afterMarkdowns:["Now you have seen it in action","","Go ahead and try the level!"]},t);var n=function(t){return e("markdown").markdown.toHTML(t.join("\n"))};this.JSON.beforeHTML=n(this.JSON.beforeMarkdowns),this.JSON.afterHTML=n(this.JSON.afterMarkdowns),this.container=new p({title:t.title||"Git Demonstration"}),this.render(),this.checkScroll(),this.navEvents=u.clone(f.Events),this.navEvents.on("positive",this.positive,this),this.navEvents.on("negative",this.negative,this),this.keyboardListener=new c({events:this.navEvents,aliasMap:{enter:"positive",right:"positive",left:"negative"},wait:!0}),this.visFinished=!1,this.initVis(),t.wait||this.show()},receiveMetaNav:function(e,t){var n=this;e.navEvents.on("positive",this.positive,this),this.metaContainerView=t},checkScroll:function(){var e=this.$("div.demonstrationText").children(),t=u.map(e,function(e){return e.clientHeight}),n=u.reduce(t,function(e,t){return e+t});np.VIEWPORT.minWidth&&e.h>p.VIEWPORT.minHeight&&this.finish()}}),O=L.extend({initialize:function(e){if(!e||!e.level)throw new Error("need level");this.eventBatonName="zoomChange",this.markdowns=["## That zoom level of "+e.level+" is not supported :-/","Please zoom back to a supported zoom level with Ctrl + and Ctrl -","","(and of course, pull requests to fix this are appreciated :D)"],O.__super__.initialize.apply(this,[e])},batonFired:function(e){e<=p.VIEWPORT.maxZoom&&e>=p.VIEWPORT.minZoom&&this.finish()}}),M=m.extend({tagName:"div",className:"levelToolbarHolder",template:u.template($("#level-toolbar-template").html()),initialize:function(e){e=e||{},this.JSON={name:e.name||"Some level! (unknown name)"},this.beforeDestination=$($("#commandLineHistory div.toolbar")[0]),this.render(),e.wait||s.nextTick(u.bind(this.show,this))},getAnimationTime:function(){return 700},render:function(){var e=this.template(this.JSON);this.$el.html(e),this.beforeDestination.after(this.el)},die:function(){this.hide(),setTimeout(u.bind(function(){this.tearDown()},this),this.getAnimationTime())},hide:function(){this.$("div.toolbar").toggleClass("hidden",!0)},show:function(){this.$("div.toolbar").toggleClass("hidden",!1)}}),_=m.extend({tagName:"div",className:"helperBar transitionAll",template:u.template($("#helper-bar-template").html()),events:{"click a":"onClick"},onClick:function(e){var t=e.target,n=$(t).attr("data-id"),r="on"+n[0].toUpperCase()+n.slice(1)+"Click";this[r].call(this)},show:function(){this.$el.toggleClass("show",!0)},hide:function(){this.$el.toggleClass("show",!1),this.deferred&&this.deferred.resolve()},getItems:function(){return[]},setupChildren:function(){},fireCommand:function(e){l.getEventBaton().trigger("commandSubmitted",e)},showDeferMe:function(e){this.hide();var t=a.defer();e.deferred=t,t.promise.then(u.bind(function(){this.show()},this)),e.show()},onExitClick:function(){this.hide()},initialize:function(e){e=e||{},this.destination=$("body"),this.JSON={items:this.getItems()},this.render(),this.setupChildren(),e.wait||this.show()}}),D=_.extend({getItems:function(){return[{text:"Git Branching",id:"english"},{text:"日本語版リポジトリ",id:"japanese"},{text:"Git 브랜치 배우기",id:"korean"},{text:"学习Git分支",id:"chinese"},{text:"français",id:"french"},{icon:"signout",id:"exit"}]},fireCommand:function(){h.viewInteracted("intlSelect"),_.prototype.fireCommand.apply(this,arguments)},onJapaneseClick:function(){this.fireCommand("locale ja; levels"),this.hide()},onEnglishClick:function(){this.fireCommand("locale en_US; levels"),this.hide()},onKoreanClick:function(){this.fireCommand("locale ko; levels"),this.hide()},onFrenchClick:function(){this.fireCommand("locale fr_FR; levels"),this.hide()},onChineseClick:function(){this.fireCommand("locale zh_CN; levels"),this.hide()}}),P=_.extend({getItems:function(){return[{text:"Levels",id:"levels"},{text:"Reset",id:"reset"},{text:"Undo",id:"undo"},{text:"Objective",id:"objectve"},{text:"Help",id:"help"},{icon:"signout",id:"exit"}]},fireCommand:function(){h.viewInteracted("helperBar"),_.prototype.fireCommand.apply(this,arguments)},onObjectiveClick:function(){this.fireCommand("objective")},onLevelsClick:function(){this.fireCommand("levels")},onResetClick:function(){this.fireCommand("reset")},onUndoClick:function(){this.fireCommand("undo")},onHelpClick:function(){this.fireCommand("help general; git help")}}),H=_.extend({getItems:function(){return[{icon:"question-sign",id:"commands"},{icon:"globe",id:"intl"}]},onIntlClick:function(){this.showDeferMe(this.intlHelper),h.viewInteracted("openIntlBar")},onCommandsClick:function(){this.showDeferMe(this.commandsHelper),h.viewInteracted("openCommandsBar")},setupChildren:function(){this.commandsHelper=new P({wait:!0}),this.intlHelper=new D({wait:!0})}}),B=m.extend({tagName:"div",className:"canvasTerminalHolder box flex1",template:u.template($("#terminal-window-bare-template").html()),events:{"click div.wrapper":"onClick"},initialize:function(e){e=e||{},this.destination=$("body"),this.JSON={title:e.title||c.str("goal-to-reach"),text:e.text||c.str("hide-goal")},this.render(),this.inDom=!0,e.additionalClass&&this.$el.addClass(e.additionalClass)},getAnimationTime:function(){return 700},onClick:function(){this.die()},die:function(){this.slideOut(),this.inDom=!1,setTimeout(u.bind(function(){this.tearDown()},this),this.getAnimationTime())},slideOut:function(){this.slideToggle(!0)},slideIn:function(){this.slideToggle(!1)},slideToggle:function(e){this.$("div.terminal-window-holder").toggleClass("slideOut",e)},getCanvasLocation:function(){return this.$("div.inside")[0]}});n.BaseView=m,n.GeneralButton=w,n.ModalView=x,n.ModalTerminal=T,n.ModalAlert=N,n.ContainedBase=b,n.ConfirmCancelView=E,n.LeftRightView=S,n.ZoomAlertWindow=O,n.ConfirmCancelTerminal=C,n.WindowSizeAlertWindow=A,n.MainHelperBar=H,n.CanvasTerminalHolder=B,n.LevelToolbar=M,n.NextLevelConfirm=k}),e("/src/js/views/index.js"),e.define("/src/js/views/levelDropdownView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../util"),c=e("../intl"),h=e("../log"),p=e("../util/keyboard").KeyboardListener,d=e("../app"),v=e("../views").ModalTerminal,m=e("../views").ContainedBase,g=e("../views").BaseView,y=m.extend({tagName:"div",className:"levelDropdownView box vertical",template:u.template($("#level-dropdown-view").html()),initialize:function(e){e=e||{},this.JSON={},this.navEvents=u.clone(f.Events),this.navEvents.on("clickedID",u.debounce(u.bind(this.loadLevelID,this),300,!0)),this.navEvents.on("negative",this.negative,this),this.navEvents.on("positive",this.positive,this),this.navEvents.on("left",this.left,this),this.navEvents.on("right",this.right,this),this.navEvents.on("up",this.up,this),this.navEvents.on("down",this.down,this),this.keyboardListener=new p({events:this.navEvents,aliasMap:{esc:"negative",enter:"positive"},wait:!0}),this.sequences=d.getLevelArbiter().getSequences(),this.sequenceToLevels=d.getLevelArbiter().getSequenceToLevels(),this.container=new v({title:c.str("select-a-level")}),this.render(),d.getEvents().on("resetMapSolved",this.render,this),d.getEvents().on("localeChanged",this.render,this),e.wait||this.show()},render:function(){y.__super__.render.apply(this,arguments),this.buildSequences()},positive:function(){if(!this.selectedID)return;this.loadLevelID(this.selectedID)},left:function(){if(this.turnOnKeyboardSelection())return;this.leftOrRight(-1)},leftOrRight:function(e){this.deselectIconByID(this.selectedID),this.selectedIndex=this.wrapIndex(this.selectedIndex+e,this.getCurrentSequence()),this.selectedID=this.getSelectedID(),this.selectIconByID(this.selectedID)},right:function(){if(this.turnOnKeyboardSelection())return;this.leftOrRight(1)},up:function(){if(this.turnOnKeyboardSelection())return;this.selectedSequence=this.getPreviousSequence(),this.downOrUp()},down:function(){if(this.turnOnKeyboardSelection())return;this.selectedSequence=this.getNextSequence(),this.downOrUp()},downOrUp:function(){this.selectedIndex=this.boundIndex(this.selectedIndex,this.getCurrentSequence()),this.deselectIconByID(this.selectedID),this.selectedID=this.getSelectedID(),this.selectIconByID(this.selectedID)},turnOnKeyboardSelection:function(){return this.selectedID?!1:(this.selectFirst(),!0)},turnOffKeyboardSelection:function(){if(!this.selectedID)return;this.deselectIconByID(this.selectedID),this.selectedID=undefined,this.selectedIndex=undefined,this.selectedSequence=undefined},wrapIndex:function(e,t){return e=e>=t.length?0:e,e=e<0?t.length-1:e,e},boundIndex:function(e,t){return e=e>=t.length?t.length-1:e,e=e<0?0:e,e},getNextSequence:function(){var e=this.getSequenceIndex(this.selectedSequence),t=this.wrapIndex(e+1,this.sequences);return this.sequences[t]},getPreviousSequence:function(){var e=this.getSequenceIndex(this.selectedSequence),t=this.wrapIndex(e-1,this.sequences);return this.sequences[t]},getSequenceIndex:function(e){var t=this.sequences.indexOf(e);if(t<0)throw new Error("didnt find");return t},getIndexForID:function(e){return d.getLevelArbiter().getLevel(e).index},selectFirst:function(){var e=this.sequenceToLevels[this.sequences[0]][0].id;this.selectIconByID(e),this.selectedIndex=0,this.selectedSequence=this.sequences[0]},getCurrentSequence:function(){return this.sequenceToLevels[this.selectedSequence]},getSelectedID:function(){return this.sequenceToLevels[this.selectedSequence][this.selectedIndex].id},selectIconByID:function(e){this.toggleIconSelect(e,!0)},deselectIconByID:function(e){this.toggleIconSelect(e,!1)},toggleIconSelect:function(e,t){this.selectedID=e;var n="#levelIcon-"+e;$(n).toggleClass("selected",t)},negative:function(){this.hide()},testOption:function(e){return this.currentCommand&&(new RegExp("--"+e)).test(this.currentCommand.get("rawStr"))},show:function(e,t){this.currentCommand=t,this.updateSolvedStatus(),this.showDeferred=e,this.keyboardListener.listen(),y.__super__.show.apply(this)},hide:function(){this.showDeferred&&this.showDeferred.resolve(),this.showDeferred=undefined,this.keyboardListener.mute(),this.turnOffKeyboardSelection(),y.__super__.hide.apply(this)},loadLevelID:function(e){if(!this.testOption("noOutput")){d.getEventBaton().trigger("commandSubmitted","level "+e);var t=d.getLevelArbiter().getLevel(e),n=t.name.en_US;h.levelSelected(n)}this.hide()},updateSolvedStatus:function(){u.each(this.seriesViews,function(e){e.updateSolvedStatus()},this)},buildSequences:function(){this.seriesViews=[],u.each(this.sequences,function(e){this.seriesViews.push(new b({destination:this.$el,name:e,navEvents:this.navEvents}))},this)}}),b=g.extend({tagName:"div",className:"seriesView box flex1 vertical",template:u.template($("#series-view").html()),events:{"click div.levelIcon":"click","mouseenter div.levelIcon":"enterIcon","mouseleave div.levelIcon":"leaveIcon"},initialize:function(e){this.name=e.name||"intro",this.navEvents=e.navEvents,this.info=d.getLevelArbiter().getSequenceInfo(this.name),this.levels=d.getLevelArbiter().getLevelsInSequence(this.name),this.levelIDs=[],u.each(this.levels,function(e){this.levelIDs.push(e.id)},this),this.destination=e.destination,this.JSON={displayName:c.getIntlKey(this.info,"displayName"),about:c.getIntlKey(this.info,"about")||" ",ids:this.levelIDs},this.render(),this.updateSolvedStatus()},updateSolvedStatus:function(){var e=this.$("div.levelIcon").each(function(e,t){var n=$(t).attr("data-id");$(t).toggleClass("solved",d.getLevelArbiter().isLevelSolved(n))})},getEventID:function(e){var t=e.target;return $(t).attr("data-id")},resetAbout:function(){this.$("p.about").text(c.getIntlKey(this.info,"about")).css("font-style","inherit")},setAbout:function(e){this.$("p.about").text(e).css("font-style","italic")},enterIcon:function(e){var t=this.getEventID(e),n=d.getLevelArbiter().getLevel(t);this.setAbout(c.getName(n))},leaveIcon:function(){this.resetAbout()},click:function(e){var t=this.getEventID(e);this.navEvents.trigger("clickedID",t)}});n.LevelDropdownView=y}),e("/src/js/views/levelDropdownView.js"),e.define("/src/js/views/multiView.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("../util").isBrowser()?window.Backbone:e("backbone"),l=e("../views").ModalTerminal,c=e("../views").ContainedBase,h=e("../views").ConfirmCancelView,p=e("../views").LeftRightView,d=e("../views").ModalAlert,v=e("../views/gitDemonstrationView").GitDemonstrationView,m=e("../views/builderViews"),g=m.MarkdownPresenter,y=e("../util/keyboard").KeyboardListener,b=e("../util/errors").GitError,w=f.View.extend({tagName:"div",className:"multiView",navEventDebounce:550,deathTime:700,typeToConstructor:{ModalAlert:d,GitDemonstrationView:v,MarkdownPresenter:g},initialize:function(e){e=e||{},this.childViewJSONs=e.childViews||[{type:"ModalAlert",options:{markdown:"Woah wtf!!"}},{type:"GitDemonstrationView",options:{command:"git checkout -b side; git commit; git commit"}},{type:"ModalAlert",options:{markdown:"Im second"}}],this.deferred=e.deferred||a.defer(),this.childViews=[],this.currentIndex=0,this.navEvents=u.clone(f.Events),this.navEvents.on("negative",this.getNegFunc(),this),this.navEvents.on("positive",this.getPosFunc(),this),this.navEvents.on("quit",this.finish,this),this.navEvents.on("exit",this.finish,this),this.keyboardListener=new y({events:this.navEvents,aliasMap:{left:"negative",right:"positive",enter:"positive",esc:"quit"}}),this.render(),e.wait||this.start()},onWindowFocus:function(){},getAnimationTime:function(){return 700},getPromise:function(){return this.deferred.promise},getPosFunc:function(){return u.debounce(u.bind(function(){this.navForward()},this),this.navEventDebounce,!0)},getNegFunc:function(){return u.debounce(u.bind(function(){this.navBackward()},this),this.navEventDebounce,!0)},lock:function(){this.locked=!0},unlock:function(){this.locked=!1},navForward:function(){if(this.locked)return;if(this.currentIndex===this.childViews.length-1){this.hideViewIndex(this.currentIndex),this.finish();return}this.navIndexChange(1)},navBackward:function(){if(this.currentIndex===0)return;this.navIndexChange(-1)},navIndexChange:function(e){this.hideViewIndex(this.currentIndex),this.currentIndex+=e,this.showViewIndex(this.currentIndex)},hideViewIndex:function(e){this.childViews[e].hide()},showViewIndex:function(e){this.childViews[e].show()},finish:function(){this.keyboardListener.mute(),u.each(this.childViews,function(e){e.die()}),this.deferred.resolve()},start:function(){this.showViewIndex(this.currentIndex)},createChildView:function(e){var t=e.type;if(!this.typeToConstructor[t])throw new Error('no constructor for type "'+t+'"');var n=new this.typeToConstructor[t](u.extend({},e.options,{wait:!0}));return n},addNavToView:function(e,t){var n=new p({events:this.navEvents,destination:e.getDestination(),showLeft:t!==0,lastNav:t===this.childViewJSONs.length-1});e.receiveMetaNav&&e.receiveMetaNav(n,this)},render:function(){u.each(this.childViewJSONs,function(e,t){var n=this.createChildView(e);this.childViews.push(n),this.addNavToView(n,t)},this)}});n.MultiView=w}),e("/src/js/views/multiView.js"),e.define("/src/js/views/rebaseView.js",function(e,t,n,r,i,s,o){var u=e("../util/errors").GitError,a=e("underscore"),f=e("q"),l=e("../util").isBrowser()?window.Backbone:e("backbone"),c=e("../views").ModalTerminal,h=e("../views").ContainedBase,p=e("../views").ConfirmCancelView,d=e("../views").LeftRightView,v=h.extend({tagName:"div",template:a.template($("#interactive-rebase-template").html()),initialize:function(e){this.deferred=e.deferred,this.rebaseMap={},this.entryObjMap={},this.rebaseEntries=new g,e.toRebase.reverse(),a.each(e.toRebase,function(e){var t=e.get("id");this.rebaseMap[t]=e,this.entryObjMap[t]=new m({id:t}),this.rebaseEntries.add(this.entryObjMap[t])},this),this.container=new c({title:"Interactive Rebase"}),this.render(),this.show()},confirm:function(){this.die();var e=[];this.$("ul.rebaseEntries li").each(function(t,n){e.push(n.id)});var t=[];a.each(e,function(e){this.entryObjMap[e].get("pick")&&t.unshift(this.rebaseMap[e])},this),t.reverse(),this.deferred.resolve(t),this.$el.html("")},render:function(){var e={num:a.keys(this.rebaseMap).length},t=this.container.getInsideElement();this.$el.html(this.template(e)),$(t).append(this.el);var n=this.$("ul.rebaseEntries");this.rebaseEntries.each(function(e){new y({el:n,model:e})},this),n.sortable({axis:"y",placeholder:"rebaseEntry transitionOpacity ui-state-highlight",appendTo:"parent"}),this.makeButtons()},makeButtons:function(){var e=f.defer();e.promise.then(a.bind(function(){this.confirm()},this)).fail(a.bind(function(){this.hide(),this.deferred.resolve([])},this)).done(),new p({destination:this.$(".confirmCancel"),deferred:e})}}),m=l.Model.extend({defaults:{pick:!0},toggle:function(){this.set("pick",!this.get("pick"))}}),g=l.Collection.extend({model:m}),y=l.View.extend({tagName:"li",template:a.template($("#interactive-rebase-entry-template").html()),toggle:function(){this.model.toggle(),this.listEntry.toggleClass("notPicked",!this.model.get("pick"))},initialize:function(e){this.render()},render:function(){var e=this.model.toJSON();this.$el.append(this.template(this.model.toJSON())),this.listEntry=this.$el.children(":last"),this.listEntry.delegate("#toggleButton","click",a.bind(function(){this.toggle()},this))}});n.InteractiveRebaseView=v}),e("/src/js/views/rebaseView.js"),e.define("/src/js/visuals/animation/animationFactory.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("q"),l=e("./index").Animation,c=e("./index").PromiseAnimation,h=e("../../util/constants").GRAPHICS,p={},d=function(e,t){var n=h.defaultAnimationTime*1,r=n*2,i=function(){e.refreshTree(n),t.setBirth(),t.parentInFront(),e.visBranchesFront(),t.animateUpdatedPosition(r,"bounce"),t.animateOutgoingEdges(n)};return{animation:i,duration:Math.max(n,r)}},v=function(e,t){var n=h.defaultAnimationTime*.66,r=n*2;return{animation:function(){e.highlightTo(t,r,"easeInOut")},duration:r*1.5}};p.genCommitBirthAnimation=function(e,t,n){if(!e)throw new Error("Need animation queue to add closure to!");var r=t.get("visNode"),i=d(n,r);e.add(new l({closure:i.animation,duration:i.duration}))},p.genCommitBirthPromiseAnimation=function(e,t){var n=e.get("visNode");return new c(d(t,n))},p.highlightEachWithPromise=function(e,t,n){return u.each(t,function(t){e=e.then(u.bind(function(){return this.playHighlightPromiseAnimation(t,n)},this))},this),e},p.playCommitBirthPromiseAnimation=function(e,t){var n=this.genCommitBirthPromiseAnimation(e,t);return n.play(),n.getPromise()},p.playRefreshAnimationAndFinish=function(e,t){var n=new c({closure:function(){e.refreshTree()}});n.play(),t.thenFinish(n.getPromise())},p.playRefreshAnimation=function(e){var t=new c({closure:function(){e.refreshTree()}});return t.play(),t.getPromise()},p.refreshTree=function(e,t){e.add(new l({closure:function(){t.refreshTree()}}))},p.genHighlightPromiseAnimation=function(e,t){var n=t.get("visBranch")||t.get("visNode"),r=e.get("visNode");return new c(v(r,n))},p.playHighlightPromiseAnimation=function(e,t){var n=this.genHighlightPromiseAnimation(e,t);return n.play(),n.getPromise()},p.getDelayedPromise=function(e){var t=f.defer();return setTimeout(t.resolve,e||1e3),t.promise},p.delay=function(e,t){t=t||h.defaultAnimationTime,e.add(new l({closure:function(){},duration:t}))},n.AnimationFactory=p}),e("/src/js/visuals/animation/animationFactory.js"),e.define("/src/js/visuals/animation/index.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("q"),f=e("backbone"),l=e("../../util/constants").GLOBAL,c=f.Model.extend({defaults:{duration:300,closure:null},validateAtInit:function(){if(!this.get("closure"))throw new Error("give me a closure!")},initialize:function(e){this.validateAtInit()},run:function(){this.get("closure")()}}),h=f.Model.extend({defaults:{animations:null,index:0,callback:null,defer:!1,promiseBased:!1},initialize:function(e){this.set("animations",[]),e.callback||console.warn("no callback")},thenFinish:function(e,t){e.then(u.bind(function(){this.finish()},this)),this.set("promiseBased",!0),t&&t.resolve()},add:function(e){if(!e instanceof c)throw new Error("Need animation not something else");this.get("animations").push(e)},start:function(){this.set("index",0),l.isAnimating=!0,this.next()},finish:function(){l.isAnimating=!1,this.get("callback")()},next:function(){var e=this.get("animations"),t=this.get("index");if(t>=e.length){this.finish();return}var n=e[t],r=n.get("duration");n.run(),this.set("index",t+1),setTimeout(u.bind(function(){this.next()},this),r)}}),p=f.Model.extend({defaults:{deferred:null,closure:null,duration:300},initialize:function(e){if(!e.closure&&!e.animation)throw new Error("need closure or animation");this.set("closure",e.closure||e.animation),this.set("deferred",e.deferred||a.defer())},getPromise:function(){return this.get("deferred").promise},play:function(){this.get("closure")(),setTimeout(u.bind(function(){this.get("deferred").resolve()},this),this.get("duration"))},then:function(e){return this.get("deferred").promise.then(e)}});p.fromAnimation=function(e){return new p({closure:e.get("closure"),duration:e.get("duration")})},n.Animation=c,n.PromiseAnimation=p,n.AnimationQueue=h}),e("/src/js/visuals/animation/index.js"),e.define("/src/js/visuals/index.js",function(e,t,n,r,i,s,o){function w(t){t=t||{},this.options=t,this.visualization=t.visualization,this.commitCollection=t.commitCollection,this.branchCollection=t.branchCollection,this.visNodeMap={},this.visEdgeCollection=new b,this.visBranchCollection=new g,this.commitMap={},this.rootCommit=null,this.branchStackMap=null,this.upstreamBranchSet=null,this.upstreamHeadSet=null,this.paper=t.paper,this.gitReady=!1,this.branchCollection.on("add",this.addBranchFromEvent,this),this.branchCollection.on("remove",this.removeBranch,this),this.deferred=[],this.flipFraction=.65;var n=e("../app");n.getEvents().on("refreshTree",this.refreshTree,this)}function E(e){var t=0,n=0,r=0,i=0,s=e.length;u.each(e,function(e){var s=e.split("(")[1];s=s.split(")")[0],s=s.split(","),r+=parseFloat(s[1]),i+=parseFloat(s[2]);var o=parseFloat(s[0]),u=o*Math.PI*2;t+=Math.cos(u),n+=Math.sin(u)}),t/=s,n/=s,r/=s,i/=s;var o=Math.atan2(n,t)/(Math.PI*2);return o<0&&(o+=1),"hsb("+String(o)+","+String(r)+","+String(i)+")"}var u=e("underscore"),a=e("q"),f=e("backbone"),l=e("../util/constants").GRAPHICS,c=e("../util/constants").GLOBAL,h=e("../models/collections"),p=h.CommitCollection,d=h.BranchCollection,v=e("../visuals/visNode").VisNode,m=e("../visuals/visBranch").VisBranch,g=e("../visuals/visBranch").VisBranchCollection,y=e("../visuals/visEdge").VisEdge,b=e("../visuals/visEdge").VisEdgeCollection;w.prototype.defer=function(e){this.deferred.push(e)},w.prototype.deferFlush=function(){u.each(this.deferred,function(e){e()},this),this.deferred=[]},w.prototype.resetAll=function(){var e=this.visEdgeCollection.toArray();u.each(e,function(e){e.remove()},this);var t=this.visBranchCollection.toArray();u.each(t,function(e){e.remove()},this),u.each(this.visNodeMap,function(e){e.remove()},this),this.visEdgeCollection.reset(),this.visBranchCollection.reset(),this.visNodeMap={},this.rootCommit=null,this.commitMap={}},w.prototype.tearDown=function(){this.resetAll(),this.paper.remove()},w.prototype.assignGitEngine=function(e){this.gitEngine=e,this.initHeadBranch(),this.deferFlush()},w.prototype.getVisualization=function(){return this.visualization},w.prototype.initHeadBranch=function(){this.addBranchFromEvent(this.gitEngine.HEAD)},w.prototype.getScreenPadding=function(){return{widthPadding:l.nodeRadius*1.5,topHeightPadding:l.nodeRadius*1.5,bottomHeightPadding:l.nodeRadius*5}},w.prototype.getPosBoundaries=function(){return this.gitEngine.hasOrigin()?{min:0,max:.5}:this.gitEngine.isOrigin()?{min:.5,max:1}:{min:0,max:1}},w.prototype.getFlipPos=function(){var e=this.getPosBoundaries(),t=e.min,n=e.max;return this.flipFraction*(n-t)+t},w.prototype.toScreenCoords=function(e){if(!this.paper.width)throw new Error("being called too early for screen coords");var t=this.getScreenPadding(),n=function(e,t,n){return n+e*(t-n*2)},r=function(e,t,n,r){return n+e*(t-r-n)};return{x:n(e.x,this.paper.width,t.widthPadding),y:r(e.y,this.paper.height,t.topHeightPadding,t.bottomHeightPadding)}},w.prototype.animateAllAttrKeys=function(e,t,n,r){var i=a.defer(),s=function(i){i.animateAttrKeys(e,t,n,r)};this.visBranchCollection.each(s),this.visEdgeCollection.each(s),u.each(this.visNodeMap,s);var o=n!==undefined?n:l.defaultAnimationTime;return setTimeout(function(){i.resolve()},o),i.promise},w.prototype.finishAnimation=function(){var e=this,t=a.defer(),n=a.defer(),r=l.defaultAnimationTime,i=l.nodeRadius,s="Solved!!\n:D",o=null,f=u.bind(function(){o=this.paper.text(this.paper.width/2,this.paper.height/2,s),o.attr({opacity:0,"font-weight":500,"font-size":"32pt","font-family":"Monaco, Courier, font-monospace",stroke:"#000","stroke-width":2,fill:"#000"}),o.animate({opacity:1},r)},this);return t.promise.then(u.bind(function(){return this.animateAllAttrKeys({exclude:["circle"]},{opacity:0},r*1.1)},this)).then(u.bind(function(){return this.animateAllAttrKeys({exclude:["arrow","rect","path","text"]},{r:i*2},r*1.5)},this)).then(u.bind(function(){return this.animateAllAttrKeys({exclude:["arrow","rect","path","text"]},{r:i*.75},r*.5)},this)).then(u.bind(function(){return f(),this.explodeNodes()},this)).then(u.bind(function(){return this.explodeNodes()},this)).then(u.bind(function(){return this.animateAllAttrKeys({exclude:["arrow","rect","path","text"]},{},r*1.25)},this)).then(u.bind(function(){return o.animate({opacity:0},r,undefined,undefined,function(){o.remove()}),this.animateAllAttrKeys({},{})},this)).then(function(){n.resolve()}).fail(function(e){console.warn("animation error"+e)}).done(),t.resolve(),n.promise},w.prototype.explodeNodes=function(){var e=a.defer(),t=[];u.each(this.visNodeMap,function(e){t.push(e.getExplodeStepFunc())});var n=setInterval(function(){var r=[];u.each(t,function(e){e()&&r.push(e)});if(!r.length){clearInterval(n),e.resolve();return}t=r},.025);return e.promise},w.prototype.animateAllFromAttrToAttr=function(e,t,n){var r=function(r){var i=r.getID();if(u.include(n,i))return;if(!e[i]||!t[i])return;r.animateFromAttrToAttr(e[i],t[i])};this.visBranchCollection.each(r),this.visEdgeCollection.each(r),u.each(this.visNodeMap,r)},w.prototype.genSnapshot=function(){this.fullCalc();var e={};return u.each(this.visNodeMap,function(t){e[t.get("id")]=t.getAttributes()},this),this.visBranchCollection.each(function(t){e[t.getID()]=t.getAttributes()},this),this.visEdgeCollection.each(function(t){e[t.getID()]=t.getAttributes()},this),e},w.prototype.refreshTree=function(e){if(!this.gitReady||!this.gitEngine.rootCommit)return;this.fullCalc(),this.animateAll(e)},w.prototype.refreshTreeHarsh=function(){this.fullCalc(),this.animateAll(0)},w.prototype.animateAll=function(e){this.zIndexReflow(),this.animateEdges(e),this.animateNodePositions(e),this.animateRefs(e)},w.prototype.fullCalc=function(){this.calcTreeCoords(),this.calcGraphicsCoords()},w.prototype.calcTreeCoords=function(){if(!this.rootCommit)throw new Error("grr, no root commit!");this.calcUpstreamSets(),this.calcBranchStacks(),this.calcDepth(),this.calcWidth()},w.prototype.calcGraphicsCoords=function(){this.visBranchCollection.each(function(e){e.updateName()})},w.prototype.calcUpstreamSets=function(){this.upstreamBranchSet=this.gitEngine.getUpstreamBranchSet(),this.upstreamHeadSet=this.gitEngine.getUpstreamHeadSet()},w.prototype.getCommitUpstreamBranches=function(e){return this.branchStackMap[e.get("id")]},w.prototype.getBlendedHuesForCommit=function(e){var t=this.upstreamBranchSet[e.get("id")];if(!t)throw new Error("that commit doesnt have upstream branches!");return this.blendHuesFromBranchStack(t)},w.prototype.blendHuesFromBranchStack=function(e){var t=[];return u.each(e,function(e){var n=e.obj.get("visBranch").get("fill");if(n.slice(0,3)!=="hsb"){var r=Raphael.color(n);n="hsb("+String(r.h)+","+String(r.l),n=n+","+String(r.s)+")"}t.push(n)}),E(t)},w.prototype.getCommitUpstreamStatus=function(e){if(!this.upstreamBranchSet)throw new Error("Can't calculate this yet!");var t=e.get("id"),n=this.upstreamBranchSet,r=this.upstreamHeadSet;return n[t]?"branch":r[t]?"head":"none"},w.prototype.calcBranchStacks=function(){var e=this.gitEngine.getBranches(),t={};u.each(e,function(e){var n=e.target.get("id");t[n]=t[n]||[],t[n].push(e),t[n].sort(function(e,t){var n=e.obj.get("id"),r=t.obj.get("id");return n=="master"||r=="master"?n=="master"?-1:1:n.localeCompare(r)})}),this.branchStackMap=t},w.prototype.calcWidth=function(){this.maxWidthRecursive(this.rootCommit);var e=this.getPosBoundaries();this.assignBoundsRecursive(this.rootCommit,e.min,e.max)},w.prototype.maxWidthRecursive=function(e){var t=0;u.each(e.get("children"),function(n){if(n.isMainParent(e)){var r=this.maxWidthRecursive(n);t+=r}},this);var n=Math.max(1,t);return e.get("visNode").set("maxWidth",n),n},w.prototype.assignBoundsRecursive=function(e,t,n){var r=(n+t)/2;e.get("visNode").get("pos").x=r;if(e.get("children").length===0)return;var i=n-t,s=0,o=e.get("children");u.each(o,function(t){t.isMainParent(e)&&(s+=t.get("visNode").getMaxWidthScaled())},this);var a=t;u.each(o,function(t,n){if(!t.isMainParent(e))return;var r=t.get("visNode").getMaxWidthScaled(),o=r/s*i,u=a,f=u+o;this.assignBoundsRecursive(t,u,f),a=u+o},this)},w.prototype.calcDepth=function(){var e=this.calcDepthRecursive(this.rootCommit,0);e>15&&console.warn("graphics are degrading from too many layers");var t=this.getDepthIncrement(e);u.each(this.visNodeMap,function(e){e.setDepthBasedOn(t,this.getHeaderOffset())},this)},w.prototype.animateNodePositions=function(e){u.each(this.visNodeMap,function(t){t.animateUpdatedPosition(e)},this)},w.prototype.addBranchFromEvent=function(e,t,n){var r=u.bind(function(){this.addBranch(e)},this);!this.gitEngine||!this.gitReady?this.defer(r):r()},w.prototype.addBranch=function(e){var t=new m({branch:e,gitVisuals:this,gitEngine:this.gitEngine});this.visBranchCollection.add(t),this.gitReady?t.genGraphics(this.paper):this.defer(u.bind(function(){t.genGraphics(this.paper)},this))},w.prototype.removeVisBranch=function(e){this.visBranchCollection.remove(e)},w.prototype.removeVisNode=function(e){this.visNodeMap[e.getID()]=undefined},w.prototype.removeVisEdge=function(e){this.visEdgeCollection.remove(e)},w.prototype.animateRefs=function(e){this.visBranchCollection.each(function(t){t.animateUpdatedPos(e)},this)},w.prototype.animateEdges=function(e){this.visEdgeCollection.each(function(t){t.animateUpdatedPath(e)},this)},w.prototype.getMinLayers=function(){return this.options.smallCanvas?2:7},w.prototype.getDepthIncrement=function(e){e=Math.max(e,this.getMinLayers());var t=1-this.getHeaderOffset(),n=t/e;return n},w.prototype.shouldHaveHeader=function(){return this.gitEngine.isOrigin()||this.gitEngine.hasOrigin()},w.prototype.getHeaderOffset=function(){return this.shouldHaveHeader()?.05:0},w.prototype.calcDepthRecursive=function(e,t){e.get("visNode").setDepth(t);var n=e.get("children"),r=t;return u.each(n,function(e){var n=this.calcDepthRecursive(e,t+1);r=Math.max(n,r)},this),r},w.prototype.canvasResize=function(e,t){this.resizeFunc||this.genResizeFunc(),this.resizeFunc(e,t)},w.prototype.genResizeFunc=function(){this.resizeFunc=u.debounce(u.bind(function(t,n){this.refreshTree()},this),200,!0)},w.prototype.addNode=function(e,t){this.commitMap[e]=t,t.get("rootCommit")&&(this.rootCommit=t);var n=new v({id:e,commit:t,gitVisuals:this,gitEngine:this.gitEngine});return this.visNodeMap[e]=n,this.gitReady&&n.genGraphics(this.paper),n},w.prototype.addEdge=function(e,t){var n=this.visNodeMap[e],r=this.visNodeMap[t];if(!n||!r)throw new Error("one of the ids in ("+e+", "+t+") does not exist");var i=new y({tail:n,head:r,gitVisuals:this,gitEngine:this.gitEngine});this.visEdgeCollection.add(i),this.gitReady&&i.genGraphics(this.paper)},w.prototype.zIndexReflow=function(){this.visNodesFront(),this.visBranchesFront()},w.prototype.visNodesFront=function(){u.each(this.visNodeMap,function(e){e.toFront()})},w.prototype.visBranchesFront=function(){this.visBranchCollection.each(function(e){e.nonTextToFront(),e.textToFront()}),this.visBranchCollection.each(function(e){e.textToFrontIfInStack()})},w.prototype.drawTreeFromReload=function(){this.gitReady=!0,this.deferFlush(),this.calcTreeCoords()},w.prototype.drawTreeFirstTime=function(){this.gitReady=!0,this.calcTreeCoords(),u.each(this.visNodeMap,function(e){e.genGraphics(this.paper)},this),this.visEdgeCollection.each(function(e){e.genGraphics(this.paper)},this),this.visBranchCollection.each(function(e){e.genGraphics(this.paper)},this),this.zIndexReflow()},n.GitVisuals=w}),e("/src/js/visuals/index.js"),e.define("/src/js/visuals/tree.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({removeKeys:function(e){u.each(e,function(e){this.get(e)&&this.get(e).remove()},this)},animateAttrKeys:function(e,t,n,r){e=u.extend({},{include:["circle","arrow","rect","path","text"],exclude:[]},e||{});var i=this.getAttributes();u.each(e.include,function(e){i[e]=u.extend({},i[e],t)}),u.each(e.exclude,function(e){delete i[e]}),this.animateToAttr(i,n,r)}});n.VisBase=f}),e("/src/js/visuals/tree.js"),e.define("/src/js/visuals/visBase.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=a.Model.extend({removeKeys:function(e){u.each(e,function(e){this.get(e)&&this.get(e).remove()},this)},getNonAnimateKeys:function(){return["stroke-dasharray"]},getIsInOrigin:function(){return this.get("gitEngine")?this.get("gitEngine").isOrigin():!1},animateToAttr:function(e,t,n){if(t===0){this.setAttr(e,!0);return}var r=t!==undefined?t:this.get("animationSpeed"),i=n||this.get("animationEasing");this.setAttr(e,!1,r,i)},setAttrBase:function(e,t,n,r,i){u.each(e,function(e){n?this.get(e).attr(t[e]):(this.get(e).stop(),this.get(e).animate(t[e],r,i),u.forEach(this.getNonAnimateKeys(),function(n){t[e]&&t[e][n]!==undefined&&this.get(e).attr(n,t[e][n])},this)),t.css&&$(this.get(e).node).css(t.css)},this)},animateAttrKeys:function(e,t,n,r){e=u.extend({},{include:["circle","arrow","rect","path","text"],exclude:[]},e||{});var i=this.getAttributes();u.each(e.include,function(e){i[e]=u.extend({},i[e],t)}),u.each(e.exclude,function(e){delete i[e]}),this.animateToAttr(i,n,r)}});n.VisBase=f}),e("/src/js/visuals/visBase.js"),e.define("/src/js/visuals/visBranch.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=function(){var e=Math.random(),t="hsb("+String(e)+",0.7,1)";return t},h=l.extend({defaults:{pos:null,text:null,rect:null,arrow:null,isHead:!1,flip:1,fill:f.rectFill,stroke:f.rectStroke,"stroke-width":f.rectStrokeWidth,offsetX:f.nodeRadius*4.75,offsetY:0,arrowHeight:14,arrowInnerSkew:0,arrowEdgeHeight:6,arrowLength:14,arrowOffsetFromCircleX:10,vPad:5,hPad:5,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing},validateAtInit:function(){if(!this.get("branch"))throw new Error("need a branch!")},getID:function(){return this.get("branch").get("id")},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine");if(!this.gitEngine)throw new Error("asd wtf");this.get("branch").set("visBranch",this);var e=this.get("branch").get("id");e=="HEAD"?(this.set("isHead",!0),this.set("flip",-1),this.refreshOffset(),this.set("fill",f.headRectFill)):e!=="master"&&this.set("fill",c())},getCommitPosition:function(){var e=this.gitEngine.getCommitFromRef(this.get("branch")),t=e.get("visNode");return this.set("flip",this.getFlipValue(e,t)),this.refreshOffset(),t.getScreenCoords()},getFlipValue:function(e,t){var n=this.get("gitVisuals").getFlipPos(),r=t.get("pos").x>n;return e.get("id")==="C0"?-1:this.get("isHead")?r?this.isBranchStackEmpty()?-1:1:this.isBranchStackEmpty()?1:-1:r?-1:1},refreshOffset:function(){var e=f.nodeRadius*4.75,t=33,n=10;this.get("flip")===1?(this.set("offsetY",-t),this.set("offsetX",e-n)):(this.set("offsetY",t),this.set("offsetX",e-n))},getArrowTransform:function(){return this.get("flip")===1?"t-2,-20R-35":"t2,20R-35"},getBranchStackIndex:function(){if(this.get("isHead"))return 0;var e=this.getBranchStackArray(),t=-1;return u.each(e,function(e,n){e.obj==this.get("branch")&&(t=n)},this),t},getBranchStackLength:function(){return this.get("isHead")?1:this.getBranchStackArray().length},isBranchStackEmpty:function(){var e=this.gitVisuals.branchStackMap[this.getCommitID()];return e?e.length===0:!0},getCommitID:function(){var e=this.get("branch").get("target");return e.get("type")==="branch"&&(e=e.get("target")),e.get("id")},getBranchStackArray:function(){var e=this.gitVisuals.branchStackMap[this.getCommitID()];return e===undefined?(this.gitVisuals.calcBranchStacks(),this.getBranchStackArray()):e},getTextPosition:function(){var e=this.getCommitPosition(),t=this.getBranchStackIndex();return{x:e.x+this.get("flip")*this.get("offsetX"),y:e.y+t*f.multiBranchY+this.get("offsetY")}},getRectPosition:function(){var e=this.getTextPosition(),t=this.get("flip"),n=this.getTextSize();return{x:e.x-.5*n.w-this.get("hPad"),y:e.y-.5*n.h-this.get("vPad")}},getArrowPath:function(){var e=function(e,t,n){return{x:e.x+t,y:e.y+n}},t=function(e){return String(Math.round(e.x))+","+String(Math.round(e.y))},n=this.get("flip"),r=e(this.getCommitPosition(),n*this.get("arrowOffsetFromCircleX"),0),i=e(r,n*this.get("arrowLength"),-this.get("arrowHeight")),s=e(r,n*this.get("arrowLength"),this.get("arrowHeight")),o=e(i,n*this.get("arrowInnerSkew"),this.get("arrowEdgeHeight")),a=e(s,n*this.get("arrowInnerSkew"),-this.get("arrowEdgeHeight")),f=49,l=e(o,n*f,0),c=e(a,n*f,0),h="";h+="M"+t(l)+" ";var p=[o,i,r,s,a,c];return u.each(p,function(e){h+="L"+t(e)+" "},this),h+="z",h},getTextSize:function(){var e=function(e){var t=e.get("text")?e.get("text").node:null;return t===null?0:t.clientWidth},t=function(e){return e.w||(e.w=75),e.h||(e.h=20),e},n=this.get("text").node;if(this.get("isHead"))return t({w:n.clientWidth,h:n.clientHeight});var r=0;return u.each(this.getBranchStackArray(),function(t){r=Math.max(r,e(t.obj.get("visBranch")))}),t({w:r,h:n.clientHeight})},getSingleRectSize:function(){var e=this.getTextSize(),t=this.get("vPad"),n=this.get("hPad");return{w:e.w+t*2,h:e.h+n*2}},getRectSize:function(){var e=this.getTextSize(),t=this.get("vPad"),n=this.get("hPad"),r=this.getBranchStackLength();return{w:e.w+t*2,h:e.h*r*1.1+n*2}},getIsRemote:function(){return this.get("branch").getIsRemote()},getName:function(){var e=this.get("branch").getName(),t=this.get("branch")===this.gitEngine.HEAD.get("target"),n=this.getIsRemote(),r=t&&!this.getIsInOrigin()&&!n?"*":"";return e+r},nonTextToFront:function(){this.get("arrow").toFront(),this.get("rect").toFront()},textToFront:function(){this.get("text").toFront()},textToFrontIfInStack:function(){this.getBranchStackIndex()!==0&&this.get("text").toFront()},getFill:function(){return this.get("isHead")||this.getBranchStackLength()==1||this.getBranchStackIndex()!==0?this.get("fill"):this.gitVisuals.blendHuesFromBranchStack(this.getBranchStackArray())},remove:function(){this.removeKeys(["text","arrow","rect"]),this.gitVisuals.removeVisBranch(this)},genGraphics:function(e){var t=this.getTextPosition(),n=this.getName(),r;r=e.text(t.x,t.y,String(n)),r.attr({"font-size":14,"font-family":"Monaco, Courier, font-monospace",opacity:this.getTextOpacity()}),this.set("text",r);var i=this.getAttributes(),s=this.getRectPosition(),o=this.getRectSize(),a=e.rect(s.x,s.y,o.w,o.h,8).attr(i.rect);this.set("rect",a);var f=this.getArrowPath(),l=e.path(f).attr(i.arrow);this.set("arrow",l);var c=["text","rect","arrow"];u.each(c,function(e){$(this.get(e).node).css(i.css)},this),this.attachClickHandlers(),a.toFront(),r.toFront()},attachClickHandlers:function(){if(this.get("gitVisuals").options.noClick)return;var e=[this.get("rect"),this.get("text"),this.get("arrow")];u.each(e,function(e){e.click(u.bind(this.onClick,this))},this)},shouldDisableClick:function(){return this.get("isHead")&&!this.gitEngine.getDetachedHead()},onClick:function(){if(this.shouldDisableClick())return;var t="git checkout "+this.get("branch").get("id"),n=e("../app");n.getEventBaton().trigger("commandSubmitted",t)},updateName:function(){this.get("text").attr({text:this.getName()})},getNonTextOpacity:function(){return this.get("isHead")?this.gitEngine.getDetachedHead()?1:0:this.getBranchStackIndex()===0?1:0},getTextOpacity:function(){return this.get("isHead")?this.gitEngine.getDetachedHead()?1:0:1},getAttributes:function(){var e=this.getNonTextOpacity(),t=this.getTextOpacity();this.updateName();var n=this.getTextPosition(),r=this.getRectPosition(),i=this.getRectSize(),s=this.getArrowPath(),o=this.getIsInOrigin()?f.originDash:"",u=this.shouldDisableClick()?"auto":"pointer";return{css:{cursor:u},text:{x:n.x,y:n.y,opacity:t},rect:{x:r.x,y:r.y,width:i.w,height:i.h,opacity:e,fill:this.getFill(),stroke:this.get("stroke"),"stroke-width":this.get("stroke-width")},arrow:{path:s,opacity:e,fill:this.getFill(),stroke:this.get("stroke"),transform:this.getArrowTransform(),"stroke-width":this.get("stroke-width")}}},animateUpdatedPos:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},setAttr:function(e,t,n,r){var i=["text","rect","arrow"];this.setAttrBase(i,e,t,n,r)}}),p=a.Collection.extend({model:h});n.VisBranchCollection=p,n.VisBranch=h,n.randomHueString=c}),e("/src/js/visuals/visBranch.js"),e.define("/src/js/visuals/visEdge.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=l.extend({defaults:{tail:null,head:null,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing},validateAtInit:function(){var e=["tail","head"];u.each(e,function(e){if(!this.get(e))throw new Error(e+" is required!")},this)},getID:function(){return this.get("tail").get("id")+"."+this.get("head").get("id")},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine"),this.get("tail").get("outgoingEdges").push(this)},remove:function(){this.removeKeys(["path"]),this.gitVisuals.removeVisEdge(this)},genSmoothBezierPathString:function(e,t){var n=e.getScreenCoords(),r=t.getScreenCoords();return this.genSmoothBezierPathStringFromCoords(n,r)},genSmoothBezierPathStringFromCoords:function(e,t){var n=function(e){return String(Math.round(e.x))+","+String(Math.round(e.y))},r=function(e,t,n){return n=n||f.curveControlPointOffset,{x:e.x,y:e.y+n*t}},i=function(e,t,n){return{x:e.x+t,y:e.y+n}};e=r(e,-1,this.get("tail").getRadius()),t=r(t,1,this.get("head").getRadius());var s="";s+="M"+n(e)+" ",s+="C",s+=n(r(e,-1))+" ",s+=n(r(t,1))+" ",s+=n(t);var o=f.arrowHeadSize||10;return s+=" L"+n(i(t,-o,o)),s+=" L"+n(i(t,o,o)),s+=" L"+n(t),s+="C",s+=n(r(t,1))+" ",s+=n(r(e,-1))+" ",s+=n(e),s},getBezierCurve:function(){return this.genSmoothBezierPathString(this.get("tail"),this.get("head"))},getStrokeColor:function(){return f.visBranchStrokeColorNone},setOpacity:function(e){e=e===undefined?1:e,this.get("path").attr({opacity:e})},genGraphics:function(e){var t=this.getBezierCurve(),n=e.path(t).attr({"stroke-width":f.visBranchStrokeWidth,stroke:this.getStrokeColor(),"stroke-linecap":"round","stroke-linejoin":"round",fill:this.getStrokeColor()});n.toBack(),this.set("path",n)},getOpacity:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("tail")),t={branch:1,head:f.edgeUpstreamHeadOpacity,none:f.edgeUpstreamNoneOpacity};if(t[e]===undefined)throw new Error("bad stat");return t[e]},getAttributes:function(){var e=this.getBezierCurve(),t=this.getOpacity();return{path:{path:e,opacity:t}}},animateUpdatedPath:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},animateToAttr:function(e,t,n){if(t===0){this.get("path").attr(e.path);return}this.get("path").toBack(),this.get("path").stop(),this.get("path").animate(e.path,t!==undefined?t:this.get("animationSpeed"),n||this.get("animationEasing"))}}),h=a.Collection.extend({model:c});n.VisEdgeCollection=h,n.VisEdge=c}),e("/src/js/visuals/visEdge.js"),e.define("/src/js/visuals/visNode.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("backbone"),f=e("../util/constants").GRAPHICS,l=e("../visuals/visBase").VisBase,c=l.extend({defaults:{depth:undefined,maxWidth:null,outgoingEdges:null,circle:null,text:null,id:null,pos:null,radius:null,commit:null,animationSpeed:f.defaultAnimationTime,animationEasing:f.defaultEasing,fill:f.defaultNodeFill,"stroke-width":f.defaultNodeStrokeWidth,stroke:f.defaultNodeStroke},getID:function(){return this.get("id")},validateAtInit:function(){if(!this.get("id"))throw new Error("need id for mapping");if(!this.get("commit"))throw new Error("need commit for linking");this.get("pos")||this.set("pos",{x:Math.random(),y:Math.random()})},initialize:function(){this.validateAtInit(),this.gitVisuals=this.get("gitVisuals"),this.gitEngine=this.get("gitEngine"),this.set("outgoingEdges",[])},setDepth:function(e){this.set("depth",Math.max(this.get("depth")||0,e))},setDepthBasedOn:function(e,t){if(this.get("depth")===undefined)throw new Error("no depth yet!");var n=this.get("pos");n.y=this.get("depth")*e+t},getMaxWidthScaled:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("commit")),t={branch:1,head:.3,none:.1};if(t[e]===undefined)throw new Error("bad stat");return t[e]*this.get("maxWidth")},toFront:function(){this.get("circle").toFront(),this.get("text").toFront()},getOpacity:function(){var e={branch:1,head:f.upstreamHeadOpacity,none:f.upstreamNoneOpacity},t=this.gitVisuals.getCommitUpstreamStatus(this.get("commit"));if(e[t]===undefined)throw new Error("invalid status");return e[t]},getTextScreenCoords:function(){return this.getScreenCoords()},getAttributes:function(){var e=this.getScreenCoords(),t=this.getTextScreenCoords(),n=this.getOpacity(),r=this.getIsInOrigin()?f.originDash:"";return{circle:{cx:e.x,cy:e.y,opacity:n,r:this.getRadius(),fill:this.getFill(),"stroke-width":this.get("stroke-width"),"stroke-dasharray":r,stroke:this.get("stroke")},text:{x:t.x,y:t.y,opacity:n}}},highlightTo:function(e,t,n){var r=e.get("fill"),i={circle:{fill:r,stroke:r,"stroke-dasharray":"","stroke-width":this.get("stroke-width")*5},text:{}};this.animateToAttr(i,t,n)},animateUpdatedPosition:function(e,t){var n=this.getAttributes();this.animateToAttr(n,e,t)},animateFromAttrToAttr:function(e,t,n,r){this.animateToAttr(e,0),this.animateToAttr(t,n,r)},animateToSnapshot:function(e,t,n){if(!e[this.getID()])return;this.animateToAttr(e[this.getID()],t,n)},setAttr:function(e,t,n,r){var i=["text","circle"];this.setAttrBase(i,e,t,n,r)},animateToAttr:function(e,t,n){l.prototype.animateToAttr.apply(this,arguments);var r=t!==undefined?t:this.get("animationSpeed"),i=n||this.get("animationEasing");n=="bounce"&&e.circle&&e.circle.cx!==undefined&&e.text&&e.text.x!==undefined&&(this.get("circle").animate(e.circle.cx,r,"easeInOut"),this.get("text").animate(e.text.x,r,"easeInOut"))},getScreenCoords:function(){var e=this.get("pos");return this.gitVisuals.toScreenCoords(e)},getRadius:function(){return this.get("radius")||f.nodeRadius},getParentScreenCoords:function(){return this.get("commit").get("parents")[0].get("visNode").getScreenCoords()},setBirthPosition:function(){var e=this.getParentScreenCoords();this.get("circle").attr({cx:e.x,cy:e.y,opacity:0,r:0}),this.get("text").attr({x:e.x,y:e.y,opacity:0})},setBirthFromSnapshot:function(e){var t=this.get("commit").get("parents")[0].get("visNode").getID(),n=e[t];this.get("circle").attr({opacity:0,r:0,cx:n.circle.cx,cy:n.circle.cy}),this.get("text").attr({opacity:0,x:n.text.x,y:n.text.y});var r={x:n.circle.cx,y:n.circle.cy};this.setOutgoingEdgesBirthPosition(r)},setBirth:function(){this.setBirthPosition(),this.setOutgoingEdgesBirthPosition(this.getParentScreenCoords())},setOutgoingEdgesOpacity:function(e){u.each(this.get("outgoingEdges"),function(t){t.setOpacity(e)})},animateOutgoingEdgesToAttr:function(e,t,n){u.each(this.get("outgoingEdges"),function(t){var n=e[t.getID()];t.animateToAttr(n)},this)},animateOutgoingEdges:function(e,t){u.each(this.get("outgoingEdges"),function(n){n.animateUpdatedPath(e,t)},this)},animateOutgoingEdgesFromSnapshot:function(e,t,n){u.each(this.get("outgoingEdges"),function(r){var i=e[r.getID()];r.animateToAttr(i,t,n)},this)},setOutgoingEdgesBirthPosition:function(e){u.each(this.get("outgoingEdges"),function(t){var n=t.get("head").getScreenCoords(),r=t.genSmoothBezierPathStringFromCoords(e,n);t.get("path").stop(),t.get("path").attr({path:r,opacity:0})},this)},parentInFront:function(){this.get("commit").get("parents")[0].get("visNode").toFront()},getFontSize:function(e){return e.length<3?12:e.length<5?10:8},getFill:function(){var e=this.gitVisuals.getCommitUpstreamStatus(this.get("commit"));return e=="head"?f.headRectFill:e=="none"?f.orphanNodeFill:this.gitVisuals.getBlendedHuesForCommit(this.get("commit"))},attachClickHandlers:function(){if(this.get("gitVisuals").options.noClick)return;var t="git checkout "+this.get("commit").get("id"),n=e("../app");u.each([this.get("circle"),this.get("text")],function(e){e.click(function(){n.getEventBaton().trigger("commandSubmitted",t)}),$(e.node).css("cursor","pointer")})},setOpacity:function(e){e=e===undefined?1:e;var t=["circle","text"];u.each(t,function(t){this.get(t).attr({opacity:e})},this)},remove:function(){this.removeKeys(["circle"],["text"]);var e=this.get("text");e&&e.remove(),this.gitVisuals.removeVisNode(this)},removeAll:function(){this.remove(),u.each(this.get("outgoingEdges"),function(e){e.remove()},this)},getExplodeStepFunc:function(){var e=this.get("circle"),t=20,n=Math.PI+Math.random()*1*Math.PI,r=.2,i=.01,s=t*Math.cos(n),o=t*Math.sin(n),u=e.attr("cx"),a=e.attr("cy"),f=this.gitVisuals.paper.width,l=this.gitVisuals.paper.height,c=.8,h=1,p=function(){o+=r*h-i*o,s-=i*s,u+=s*h,a+=o*h;if(u<0||u>f)s=c*-s,u=u<0?0:f;if(a<0||a>l)o=c*-o,a=a<0?0:l;return e.attr({cx:u,cy:a}),s*s+o*o<.01&&Math.abs(a-l)===0?!1:!0};return p},genGraphics:function(){var e=this.gitVisuals.paper,t=this.getScreenCoords(),n=this.getTextScreenCoords(),r=e.circle(t.x,t.y,this.getRadius()).attr(this.getAttributes().circle),i=e.text(n.x,n.y,String(this.get("id")));i.attr({"font-size":this.getFontSize(this.get("id")),"font-weight":"bold","font-family":"Monaco, Courier, font-monospace",opacity:this.getOpacity()}),this.set("circle",r),this.set("text",i),this.attachClickHandlers()}});n.VisNode=c}),e("/src/js/visuals/visNode.js"),e.define("/src/js/visuals/visualization.js",function(e,t,n,r,i,s,o){var u=e("underscore"),a=e("../util").isBrowser()?a=window.Backbone:a=e("backbone"),f=e("../models/collections"),l=f.CommitCollection,c=f.BranchCollection,h=e("../util/eventBaton").EventBaton,p=e("../visuals").GitVisuals,d=a.View.extend({initialize:function(e){e=e||{},this.options=e,this.customEvents=u.clone(a.Events),this.containerElement=e.containerElement;var t=this,n=e.containerElement||$("#canvasHolder")[0];new Raphael(n,200,200,function(){var n=this;s.nextTick(function(){t.paperInitialize(n,e)})})},paperInitialize:function(t,n){this.treeString=n.treeString,this.paper=t;var r=e("../app");this.eventBaton=n.noKeyboardInput?new h:r.getEventBaton(),this.commitCollection=new l,this.branchCollection=new c,this.gitVisuals=new p({commitCollection:this.commitCollection,branchCollection:this.branchCollection,paper:this.paper,noClick:this.options.noClick,smallCanvas:this.options.smallCanvas,visualization:this});var i=e("../git").GitEngine;this.gitEngine=new i({collection:this.commitCollection,branches:this.branchCollection,gitVisuals:this.gitVisuals,eventBaton:this.eventBaton}),this.gitEngine.init(),this.gitVisuals.assignGitEngine(this.gitEngine),this.myResize(),$(window).on("resize",u.bind(function(){this.myResize()},this)),this.gitVisuals.drawTreeFirstTime(),this.treeString&&this.gitEngine.loadTreeFromString(this.treeString),this.options.zIndex&&this.setTreeIndex(this.options.zIndex),this.shown=!1,this.setTreeOpacity(0),s.nextTick(u.bind(this.fadeTreeIn,this)),this.customEvents.trigger("gitEngineReady"),this.customEvents.trigger("paperReady")},clearOrigin:function(){delete this.originVis},makeOrigin:function(e){return this.originVis=new d(u.extend({},this.options,{noKeyboardInput:!0,noClick:!0,treeString:e.treeString})),this.originVis},originToo:function(e,t){if(!this.originVis)return;var n=u.bind(function(){this.originVis[e].apply(this.originVis,t)},this);if(this.originVis.paper){n();return}this.originVis.customEvents.on("paperReady",n)},setTreeIndex:function(e){$(this.paper.canvas).css("z-index",e),this.originToo("setTreeIndex",arguments)},setTreeOpacity:function(e){e===0&&(this.shown=!1),$(this.paper.canvas).css("opacity",e),this.originToo("setTreeOpacity",arguments)},getAnimationTime:function(){return 300},fadeTreeIn:function(){this.shown=!0,$(this.paper.canvas).animate({opacity:1},this.getAnimationTime()),this.originToo("fadeTreeIn",arguments)},fadeTreeOut:function(){this.shown=!1,$(this.paper.canvas).animate({opacity:0},this.getAnimationTime()),this.originToo("fadeTreeOut",arguments)},hide:function(){this.fadeTreeOut(),setTimeout(u.bind(function(){$(this.paper.canvas).css("visibility","hidden")},this),this.getAnimationTime()),this.originToo("hide",arguments)},show:function(){$(this.paper.canvas).css("visibility","visible"),setTimeout(u.bind(this.fadeTreeIn,this),10),this.originToo("show",arguments)},showHarsh:function(){$(this.paper.canvas).css("visibility","visible"),this.setTreeOpacity(1),this.originToo("showHarsh",arguments)},resetFromThisTreeNow:function(e){this.treeString=e;var t=this.getOriginInTreeString(e);if(t){var n=this.gitEngine.printTree(t);this.originToo("resetFromThisThreeNow",[n])}},getOriginInTreeString:function(e){var t=JSON.parse(unescape(e));return t.originTree},reset:function(e){var t=e||this.treeString;this.setTreeOpacity(0),t?this.gitEngine.loadTreeFromString(t):this.gitEngine.defaultInit(),this.fadeTreeIn();if(this.originVis)if(t){var n=this.getOriginInTreeString(t);this.originToo("reset",[JSON.stringify(n)])}else this.originToo("reset",arguments)},tearDown:function(){this.gitEngine.tearDown(),this.gitVisuals.tearDown(),delete this.paper,this.originToo("tearDown",arguments)},die:function(){this.fadeTreeOut(),setTimeout(u.bind(function(){this.shown||this.tearDown()},this),this.getAnimationTime()),this.originToo("die",arguments)},myResize:function(){if(!this.paper)return;var e=1,t=this.el,n=t.clientWidth-e,r=t.clientHeight-e;if(!this.containerElement){var i=t.offsetLeft,s=t.offsetTop;$(this.paper.canvas).css({position:"absolute",left:i+"px",top:s+"px"})}this.paper.setSize(n,r),this.gitVisuals.canvasResize(n,r)}});n.Visualization=d}),e("/src/js/visuals/visualization.js"),e.define("/src/levels/advanced/multipleParents.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C7","id":"master"},"bugWork":{"target":"C2","id":"bugWork"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C2"],"id":"C5"},"C6":{"parents":["C4","C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',solutionCommand:"git branch bugWork master^^2^",startTree:'{"branches":{"master":{"target":"C7","id":"master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C2"],"id":"C5"},"C6":{"parents":["C4","C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Multiple parents",zh_CN:"多个父提交记录"},hint:{en_US:"Use `git branch bugWork` with a target commit to create the missing reference.",zh_CN:"使用`git branch bugWork`加上一个目标提交记录来创建消失的引用。"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["### Specifying Parents","","Like the `~` modifier, the `^` modifier also accepts an optional number after it.","","Rather than specifying the number of generations to go back (what `~` takes), the modifier on `^` specifies which parent reference to follow from a merge commit. Remember that merge commits have multiple parents, so the path to choose is ambiguous.","",'Git will normally follow the "first" parent upwards from a merge commit, but specifying a number with `^` changes this default behavior.',"","Enough talking, let's see it in action.",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have a merge commit. If we checkout `master^` without the modifier, we will follow the first parent after the merge commit. ","","(*In our visuals, the first parent is positioned directly above the merge commit.*)"],afterMarkdowns:["Easy -- this is what we are all used to."],command:"git checkout master^",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Now let's try specifying the second parent instead..."],afterMarkdowns:["See? We followed the other parent upwards."],command:"git checkout master^2",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["The `^` and `~` modifiers can make moving around a commit tree very powerful:"],afterMarkdowns:["Lightning fast!"],command:"git checkout HEAD~; git checkout HEAD^2; git checkout HEAD~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Even crazier, these modifiers can be chained together! Check this out:"],afterMarkdowns:["The same movement as before, but all in one command."],command:"git checkout HEAD~^2~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"ModalAlert",options:{markdowns:["### Put it to practice","","To complete this level, create a new branch at the specified destination.","","Obviously it would be easy to specify the commit directly (with something like `C6`), but I challenge you to use the modifiers we talked about instead!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["### 选择父提交","","和`~`修改符一样,`^`修改符之后也可以跟一个(可选的)数字。","","这不是用来指定向上返回几代(`~`的作用),`^`后的数字指定跟随合并提交记录的哪一个父提交。还记得一个合并提交有多个父提交吧,所有选择哪条路径不是那么清晰。","",'Git默认选择跟随合并提交的"第一个"父提交,使用`^`后跟一个数字来改变这一默认行为。',"","废话不多说,举个例子。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["这里有一个合并提交。如果不加数字修改符直接切换到`master^`,会回到第一个父提交。","","(*在我们的图示中,第一个父提交是指合并提交正上方的那个父提交。*)"],afterMarkdowns:["OK--这恰好是我们想要的。"],command:"git checkout master^",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["现在来试试选择第二个父提交……"],afterMarkdowns:["看见了吧?我们回到了第二个父提交。"],command:"git checkout master^2",beforeCommand:"git checkout HEAD^; git commit; git checkout master; git merge C2"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用`^`和`~`可以自由在在提交树中移动:"],afterMarkdowns:["快若闪电!"],command:"git checkout HEAD~; git checkout HEAD^2; git checkout HEAD~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["再疯狂点,这些修改符支持链式操作!试一下这个:"],afterMarkdowns:["和前面的结果一样,但只用了一条命令。"],command:"git checkout HEAD~^2~2",beforeCommand:"git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"}},{type:"ModalAlert",options:{markdowns:["### 实践一下","","要完成此关,在指定的目标位置创建一个新的分支。","","很明显可以简单的直接使用提交记录的hash值(比如`C6`),但我要求你使用刚刚讲到的相对引用修饰符!"]}}]}}}}),e("/src/levels/advanced/multipleParents.js"),e.define("/src/levels/index.js",function(e,t,n,r,i,s,o){n.levelSequences={intro:[e("../../levels/intro/commits").level,e("../../levels/intro/branching").level,e("../../levels/intro/merging").level,e("../../levels/intro/rebasing").level],rampup:[e("../../levels/rampup/detachedHead").level,e("../../levels/rampup/relativeRefs").level,e("../../levels/rampup/relativeRefs2").level,e("../../levels/rampup/reversingChanges").level],rebase:[e("../../levels/rebase/manyRebases").level],mixed:[e("../../levels/mixed/grabbingOneCommit").level,e("../../levels/mixed/jugglingCommits").level,e("../../levels/mixed/jugglingCommits2").level],advanced:[e("../../levels/advanced/multipleParents").level,e("../../levels/rebase/selectiveRebase").level]},n.sequenceInfo={intro:{displayName:{en_US:"Introduction Sequence",ja:"まずはここから",fr_FR:"Séquence d'introduction",zh_CN:"基础篇",ko:"기본 명령어"},about:{en_US:"A nicely paced introduction to the majority of git commands",ja:"gitの基本的なコマンド群をほどよいペースで学ぶ",fr_FR:"Une introduction en douceur à la majorité des commandes git",zh_CN:"循序渐进介绍git主要命令",ko:"브랜치 관련 주요 git 명령어를 깔끔하게 알려드립니다"}},rampup:{displayName:{en_US:"Ramping Up",ja:"次のレベルに進もう",fr_FR:"Montée en puissance",zh_CN:"进阶篇"},about:{en_US:"The next serving of 100% git awesomes-ness. Hope you're hungry",ja:"更にgitの素晴らしさを堪能しよう",fr_FR:"Le prochain service git 100% excellence. J'espère que vous êtes affamés",zh_CN:"接下来是git的超赞特性。迫不及待了吧!"}},rebase:{displayName:{en_US:"Master the Rebase Luke!",ja:"Rebaseをモノにする",fr_FR:"Maîtrise Rebase, Luke!",zh_CN:"精通Rebase!",ko:"리베이스 완전정복!"},about:{en_US:"What is this whole rebase hotness everyone is talking about? Find out!",ja:"話題のrebaseってどんなものだろう?って人にオススメ",fr_FR:"Qu'est-ce que ce rebase dont tout le monde parle ? Découvrez-le !",ko:"그 좋다고들 말하는 rebase에 대해 알아봅시다!",zh_CN:"大家都在说的rebase究竟是神马?看看吧!"}},mixed:{displayName:{en_US:"A Mixed Bag",ja:"様々なtips",fr_FR:"Un assortiment",ko:"종합선물세트",zh_CN:"大杂烩?"},about:{en_US:"A mixed bag of Git techniques, tricks, and tips",ja:"gitを使う上での様々なtipsやテクニックなど",fr_FR:"Un assortiment de techniques et astuces pour utiliser Git",ko:"Git을 다루는 다양한 팁과 테크닉을 다양하게 알아봅니다",zh_CN:"Git技术,技巧与贴士杂烩"}},advanced:{displayName:{en_US:"Advanced Topics",fr_FR:"Sujets Avancés",zh_CN:"高级主题"},about:{en_US:"For the truly brave!",fr_FR:"Pour les plus courageux !",zh_CN:"只为真正的勇士!"}}}}),e("/src/levels/index.js"),e.define("/src/levels/intro/branching.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C1","id":"master"},"bugFix":{"target":"C1","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"bugFix","id":"HEAD"}}',solutionCommand:"git branch bugFix;git checkout bugFix",name:{en_US:"Branching in Git",ja:"Gitのブランチ",ko:"Git에서 브랜치 쓰기",fr_FR:"Gérer les branches avec Git",zh_CN:"建立Git分支"},hint:{en_US:'Make a new branch with "git branch [name]" and check it out with "git checkout [name]"',ja:'ブランチの作成("git branch [ブランチ名]")と、チェックアウト("git checkout [ブランチ名]")',fr_FR:'Faites une nouvelle branche avec "git branch [nom]" positionnez-vous dans celle-ci avec "git checkout [nom]"',zh_CN:"用 'git branch [分支名]' 来创建分支,用 'git checkout [分支名]' 切换到分支",ko:'"git branch [브랜치명]"으로 새 브랜치를 만들고, "git checkout [브랜치명]"로 그 브랜치로 이동하세요'},disabledMap:{"git revert":!0},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Branches","","Branches in Git are incredibly lightweight as well. They are simply references to a specific commit -- nothing more. This is why many Git enthusiasts chant the mantra:","","```","branch early, and branch often","```","","Because there is no storage / memory overhead with making many branches, it's easier to logically divide up your work than have big beefy branches.","",'When we start mixing branches and commits, we will see how these two features combine. For now though, just remember that a branch essentially says "I want to include the work of this commit and all parent commits."']}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's see what branches look like in practice.","","Here we will create a new branch named `newImage`"],afterMarkdowns:["There, that's all there is to branching! The branch `newImage` now refers to commit `C1`"],command:"git branch newImage",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's try to put some work on this new branch. Hit the button below"],afterMarkdowns:["Oh no! The `master` branch moved but the `newImage` branch didn't! That's because we weren't \"on\" the new branch, which is why the asterisk (*) was on `master`"],command:"git commit",beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's tell git we want to checkout the branch with","","```","git checkout [name]","```","","This will put us on the new branch before committing our changes"],afterMarkdowns:["There we go! Our changes were recorded on the new branch"],command:"git checkout newImage; git commit",beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["Ok! You are all ready to get branching. Once this window closes,","make a new branch named `bugFix` and switch to that branch"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Gitのブランチ","","Gitではコミットだけでなく、ブランチもまた信じられないほど軽量です。ブランチとは単に特定のコミットを指示したポインタにしか過ぎません。Gitの達人は決まってこう言うのは、そのためです:","","```","早めに、かつ頻繁にブランチを切りなさい","```","","どれほど多くのブランチを作ってもストレージやメモリを全然使わないので、ブランチを肥大化させるよりも論理的に分割していく方が簡単なのです。","","ブランチとコミットをあわせて使い始めると、これら2つのフィーチャがどのように連動して機能するかがわかるでしょう。ここではとりあえず、ブランチは基本的には「あるコミットとその親のコミットたちを含めた全てのコミット」のことを呼ぶと覚えておいてください。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["では実際にブランチがどのようなものかを見ていきましょう。","","`newImage`という名前の新しいブランチを切ってみることにします。"],afterMarkdowns:["以上。必要な手順はこれだけです。いま作成された`newImage`ブランチは`C1`コミットを指しています。"],command:"git branch newImage",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["この新しいブランチに何か変更を加えてみましょう。次のボタンを押してください。"],afterMarkdowns:["あれ?`newImage`ではなくて`master`ブランチが移動してしまいました。これは、私たちが`newImage`のブランチ上で作業していなかったためです。どのブランチで作業しているかは、アスタリスク(*)がついてるかどうかで分かります。"],command:"git commit",beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["今度は作業したいブランチ名をgitに伝えてみましょう。","","```","git checkout [ブランチ名]","```","","このようにして、コミットする前に新しいブランチへと作業ブランチを移動することができます。"],afterMarkdowns:["できましたね。今度は新しいブランチに対して変更を記録することができました。"],command:"git checkout newImage; git commit",beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["OK! もうどんなブランチでも切れますね。このウィンドウを閉じて、","`bugFix`という名前のブランチを作成し、そのブランチをチェックアウトしてみましょう。"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branches Git","","Les branches sous Git sont incroyablement légères aussi. Elles sont simplment des références un commit spécifique -- rien de plus. C'est pourquoi beaucoup d'enthousiastes répètent en cœur :","","```","n'attendez pas pour faire des branches, et faites souvent des branches","```","","Parce qu'il n'y a pas de surcoût (stockage/mémoire) associés aux branches, il est facile de diviser son travail en de nombreuses branches plutôt que d'avoir quelques grosses branches.","","Nous verrons comment les banches et les commits interagissent quand nous les utiliserons ensemble. Pour l'instant, souvenez-vous qu'une branche est un moyen d'exprimer \"Je veux inclure le contenu de ce commit et de tous les commits parents.\""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Regardons à quoi ressemblent les branches en pratique.","","Nous allons nous positionner (checkout) dans une nouvelle branche appellée `newImage`"],afterMarkdowns:["Et voilà, c'est tout ! La branche `newImage` se réfère désormais au commit `C1`"],command:"git branch newImage",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Travaillons mainenant dans cette branche. Appuyez sur le bouton ci-dessous."],afterMarkdowns:["Oh non! La branche `master` a bougé mais pas la branche `newImage` ! C'est parce aue nous n'étions pas \"sur\" la nouvelle branche, comme indiqué par l'asterisque (*) sur `master`"],command:"git commit",beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Indiquons à git que nous voulons nous positionner sur la branche avec ","","```","git checkout [nom]","```","","Ceci nous positionne sur la nouvelle branche avant de faire un commit avec nos modifications"],afterMarkdowns:["C'est parti ! Nos modifications ont été enregistrées sur la nouvelle branche"],command:"git checkout newImage; git commit",beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["Ok! Vous êtes fin prêt pour faire des branches. Après la fermeture de cette fenêtre,","faites une nouvelle branche nommée `bugFix` et positionnez-vous sur cette branche"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Branches",""," Git 的分支非常轻量。它们只是简单地指向某个提交纪录——仅此而已。所以许多Git爱好者会念叨:","","```","早点建分支!经常建分支!","```","","创建分支没有储存或内存上的开销,所以按逻辑分解工作比维护单一的代码树要简单。","","同时使用分支和提交时,我们会看到两者如何配合。现在,只要记住使用分支其实就是在说:“我想包含本次提交及所有的父提交记录。”"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["举个例子看看分支究竟是什么。","","这里,我们切换到到名为`newImage`的新分支。"],command:"git branch newImage",afterMarkdowns:["看,这就是建立分支所需的操作啦!`newImage`分支现在指向提交记录`C1`。"],beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["现在让我们修改一下新分支。点击下面的按钮。"],command:"git commit",afterMarkdowns:["啊摔!`master`分支前进了,但`newImage`分支没有哇!这是因为我们没有“在”这个新分支上,这也是为什么星号(*)只在 `master` 上。"],beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用如下命令告诉git我们想要切换到新的分支","","```","git checkout [name]","```","","这可以让我们在提交修改之前切换到新的分支。"],command:"git checkout newImage; git commit",afterMarkdowns:["好的嘞!新的分支已经记录了我们的修改。"],beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["好啦,你已经准备好使用分支了。当前窗口关闭后,","创建一个叫 `bugFix` 的新分支,然后切换过去。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git 브랜치","","깃의 브랜치도 놀랍도록 가볍습니다. 브랜치는 특정 커밋에 대한 참조(reference)에 지나지 않습니다. 이런 사실 때문에 수많은 Git 애찬론자들이 자주 이렇게 말하곤 합니다:","","```","브랜치를 서둘러서, 그리고 자주 만드세요","```","","브랜치를 많이 만들어도 메모리나 디스크 공간에 부담이 되지 않기 때문에, 여러분의 작업을 커다른 브랜치로 만들기 보다, 작은 단위로 잘게 나누는 것이 좋습니다.","",'브랜치와 커밋을 같이 쓸 때, 어떻게 두 기능이 조화를 이루는지 알아보겠습니다. 하지만 우선은, 단순히 브랜치를 "하나의 커밋과 그 부모 커밋들을 포함하는 작업 내역"이라고 기억하시면 됩니다.']}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["브랜치가 어떤 것인지 연습해보죠.","","`newImage`라는 브랜치를 살펴보겠습니다."],afterMarkdowns:["저 그림에 브랜치의 모든 것이 담겨있습니다! 브랜치 `newImage`가 커밋 `C1`를 가리킵니다"],command:"git branch newImage",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["이 새로운 브랜치에 약간의 작업을 더해봅시다. 아래 버튼을 눌러주세요"],afterMarkdowns:["앗! `master` 브랜치가 움직이고, `newImage` 브랜치는 이동하지 않았네요! 그건 우리가 새 브랜치 위에 있지 않았었기 때문입니다. 별표(*)가 `master`에 있었던 것이죠."],command:"git commit",beforeCommand:"git branch newImage"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["아래의 명령으로 새 브랜치로 이동해 봅시다.","","```","git checkout [브랜치명]","```","","이렇게 하면 변경분을 커밋하기 전에 새 브랜치로 이동하게 됩니다."],afterMarkdowns:["이거죠! 이제 우리의 변경이 새 브랜치에 기록되었습니다!"],command:"git checkout newImage; git commit",beforeCommand:"git branch newImage"}},{type:"ModalAlert",options:{markdowns:["좋아요! 이제 직접 브랜치 작업을 연습해봅시다. 이 창을 닫고,","`bugFix`라는 새 브랜치를 만드시고, 그 브랜치로 이동해보세요"]}}]}}}}),e("/src/levels/intro/branching.js"),e.define("/src/levels/intro/commits.js",function(e,t,n,r,i,s,o){n.level={name:{en_US:"Introduction to Git Commits",fr_FR:"Introduction aux commits avec Git",ja:"Gitのコミット",ko:"Git 커밋 소개",zh_CN:"Git Commits简介"},goalTreeString:'{"branches":{"master":{"target":"C3","id":"master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"master","id":"HEAD"}}',solutionCommand:"git commit;git commit",startTree:'{"branches":{"master":{"target":"C1","id":"master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"master","id":"HEAD"}}',hint:{en_US:"Just type in 'git commit' twice to finish!",fr_FR:"Il suffit de saisir 'git commit' deux fois pour réussir !",zh_CN:"敲两次 'git commit' 就好啦!",ja:"'git commit'コマンドを2回打てば完成!",ko:"'git commit'이라고 두 번 치세요!"},disabledMap:{"git revert":!0},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Commits","A commit in a git repository records a snapshot of all the files in your directory. It's like a giant copy and paste, but even better!","","Git wants to keep commits as lightweight as possible though, so it doesn't just copy the entire directory every time you commit. It actually stores each commit as a set of changes, or a \"delta\", from one version of the repository to the next. That's why most commits have a parent commit above them -- you'll see this later in our visualizations.","",'In order to clone a repository, you have to unpack or "resolve" all these deltas. That\'s why you might see the command line output:',"","`resolving deltas`","","when cloning a repo.","","It's a lot to take in, but for now you can think of commits as snapshots of the project. Commits are very light and switching between them is wicked fast!"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's see what this looks like in practice. On the right we have a visualization of a (small) git repository. There are two commits right now -- the first initial commit, `C0`, and one commit after that `C1` that might have some meaningful changes.","","Hit the button below to make a new commit"],afterMarkdowns:["There we go! Awesome. We just made changes to the repository and saved them as a commit. The commit we just made has a parent, `C1`, which references which commit it was based off of."],command:"git commit",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["Go ahead and try it out on your own! After this window closes, make two commits to complete the level"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Gitのコミット","コミットによって、ディレクトリ中の全てのファイルのスナップショットを記録します。巨大なコピー&ペーストのようなものですが、実はそれよりずっと良いものです。","","Gitではコミットを可能な限り軽量に保つために、コミット毎にフォルダ全体をコピーしません。実際にはGitは、コミットを直前のバージョンから一つ先のバージョンへの「変更の固まり」あるいは「差分」として記録します。後で出てきますが、ほとんどのコミットが親を持っているのはそういう理由からです。","","リポジトリをcloneする時には、内部動作としてはコミットの差分をたどって全ての変更を取得しています。cloneした時に以下のような表示が出るのは:","","`resolving deltas`(訳:差分を解決中)","","このためです。","","もっと説明したいところですが、しばらくはコミットをスナップショットのようなものだと考えてください。コミットは非常に軽量であり、コミット間の移動も非常に高速です。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["これがどういうことか、動きを見ていきましょう。図には(小さな)gitリポジトリが描かれています。コミットが2つあります ― `C0`という名前の初回のコミットがあり、`C1`という名前の次のコミットが続きます。これは何か意味のある変更かもしれません。","","下のボタンを押下して新しいコミットを作ってみましょう。"],afterMarkdowns:["できました! 良いですね。いまリポジトリに新しい変更が加えられ、1つのコミットとして保存されました。作成したコミットには親がいて、このコミットの出発点となった`C1`を指しています。"],command:"git commit",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["実際に手を動かしてみましょう。このウィンドウを閉じたら、試しに2回コミットをしてみましょう。"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Commits Git","Un commit dans un dépôt (repository) git enregistre une image (snapshot) de tous les fichiers du repertoire. Comme un Copier-Coller géant, mais en bien mieux !","","Git fait en sorte que les commits soient aussi légers que possible donc il ne recopie pas tous le répertoire à chaque commit. En fait, git n'enregistre que l'ensemble des changments (\"delta\") depuis la version précédante du dépôt. C'est pour cette raison que la plupart des commits ont un commit parent -- ainsi que nous le verrons plus tard.","",'Pour cloner un dépôt, il faut décompresser ("résoudre") tous ces deltas. C\'est la raison pour laquelle la commande écrit :',"","`resolving deltas`","","lorsque l'on clone un dépôt.","","C'est beaucoup à absorber, mais pour l'instant vous pouvez considérer les commits comme des snapshots du projet. Les commits sont très légers et passer de l'un à l'autre est très rapide !"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Voyons à quoi cela ressemble en pratique. Sur la droite, on peut visualiser un (petit) dépôt git. Il y a pour l'instant deux commits -- le premier commit initial, `C0`, et un commit suivant `C1` qui aurait des changements significatifs.","","Appuyez sur le bouton ci-dessous pour faire un nouveau commit"],afterMarkdowns:["C'est parti ! Super. Nous venons de faire des modifications sur le dépôt et de saugevarder celles-ci dans un commit. Ce commit que nous venons de faire a un parent, `C1`, qui référence le commit sur lequel il est basé."],command:"git commit",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["Allez-y et essayez par vous-même ! Après la fermeture de cettefenêtre, faites deux commits pour terminer ce niveau."]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git 커밋","커밋은 Git 저장소에 여러분의 디렉토리에 있는 모든 파일에 대한 스냅샷을 기록하는 것입니다. 디렉토리 전체에 대한 복사해 붙이기와 비슷하지만 훨씬 유용합니다!","",'Git은 커밋을 가능한한 가볍게 유지하고자 해서, 커밋할 때마다 디렉토리 전체를 복사하는 일은 하지 않습니다. 각 커밋은 저장소의 이전 버전과 다음 버전의 변경내역("delta"라고도 함)을 저장합니다. 그래서 대부분의 커밋이 그 커밋 위에 부모 커밋을 가리키고 있게 되는 것입니다. -- 곧 그림으로 된 화면에서 살펴보게 될 것입니다.',"","저장소를 복제(clone)하려면, 그 모든 변경분(delta)를 풀어내야하는데, 그 때문에 명령행 결과로 아래와 같이 보게됩니다. ","","`resolving deltas`","","알아야할 것이 꽤 많습니다만, 일단은 커밋을 프로젝트의 각각의 스냅샷들로 생각하시는 걸로 충분합니다. 커밋은 매우 가볍고 커밋 사이의 전환도 매우 빠르다는 것을 기억해주세요!"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["연습할 때 어떻게 보이는지 확인해보죠. 오른쪽 화면에 git 저장소를 그림으로 표현해 놓았습니다. 현재 두번 커밋한 상태입니다 -- 첫번째 커밋으로 `C0`, 그 다음으로 `C1`이라는 어떤 의미있는 변화가 있는 커밋이 있습니다.","","아래 버튼을 눌러 새로운 커밋을 만들어보세요"],afterMarkdowns:["이렇게 보입니다! 멋지죠. 우리는 방금 저장소 내용을 변경해서 한번의 커밋으로 저장했습니다. 방금 만든 커밋은 부모는 `C1`이고, 어떤 커밋을 기반으로 변경된 것인지를 가리킵니다."],command:"git commit",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["계속해서 직접 한번 해보세요! 이 창을 닫고, 커밋을 두 번 하면 다음 레벨로 넘어갑니다"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Commits","git仓库中的一次提交(commit)记录目录下所有文件的快照。感觉像是大量的复制和粘贴,但 git 做的不只这么简单!","",'Git 希望提交记录尽可能地轻量,所以每次进行提交时,它不会简单地复制整个目录。实际上它把每次提交记录保存为从代码库的一个版本到下一个版本的变化集,或者说一个"增量(delta)"。所以,大部分提交记录都有一个父提交(parent commit)-- 我们会很快演示这一点。',"","克隆(clone)代码库时,需要解包(unpack)或者“解析(resolve)”所有的差异。所以在克隆代码库时,可能会看见如下命令行输出:","","`resolving deltas`","","要学的东西有很多,但现在你可以把提交记录看作是项目的快照。提交记录非常轻量且可以快速切换!"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["在实践中学习commit。右边是一个(小)git代码库的图示。当前有两个提交记录—— 初始提交`C0`和其后可能包含有用修改的提交`C1`。","","点击下面的按钮生成新的提交记录。"],command:"git commit",afterMarkdowns:["看!碉堡吧!我们修改了代码,并保存为一次提交记录。刚刚做的提交`C2`有一个父提交(parent)`C1`,代表此次修改的基础。"],beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["接下来你可以随便测试。当前窗口关闭后,完成两次提交就可以过关!"]}}]}}}}),e("/src/levels/intro/commits.js"),e.define("/src/levels/intro/merging.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C4","id":"master"},"bugFix":{"target":"C2","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3","C2"],"id":"C4"}},"HEAD":{"target":"master","id":"HEAD"}}',solutionCommand:"git checkout -b bugFix;git commit;git checkout master;git commit;git merge bugFix",name:{en_US:"Merging in Git",fr_FR:"Faire des 'merge' (fusions de branches) avec Git",ko:"Git에서 브랜치 합치기(Merge)",ja:"ブランチとマージ",zh_CN:"分支与合并"},hint:{en_US:"Remember to commit in the order specified (bugFix before master)",ja:"指示された順番でコミットすること(masterの前にbugFixで)",fr_FR:"Pensez à faire des commits dans l'ordre indiqué (bugFix avant master)",zh_CN:"记住按指定的顺序提交(bugFix先于master)",ko:"말씀드린 순서대로 커밋해주세요 (bugFix에 먼저 커밋하고 master에 커밋)"},disabledMap:{"git revert":!0},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branches and Merging","","Great! We now know how to commit and branch. Now we need to learn some kind of way of combining the work from two different branches together. This will allow us to branch off, develop a new feature, and then combine it back in.","",'The first method to combine work that we will examine is `git merge`. Merging in Git creates a special commit that has two unique parents. A commit with two parents essentially means "I want to include all the work from this parent over here and this one over here, *and* the set of all their parents."',"","It's easier with visuals, let's check it out in the next view"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have two branches; each has one commit that's unique. This means that neither branch includes the entire set of \"work\" in the repository that we have done. Let's fix that with merge.","","We will `merge` the branch `bugFix` into `master`"],afterMarkdowns:["Woah! See that? First of all, `master` now points to a commit that has two parents. If you follow the arrows upstream from `master`, you will hit every commit along the way to the root. This means that `master` contains all the work in the repository now.","","Also, see how the colors of the commits changed? To help with learning, I have included some color coordination. Each branch has a unique color. Each commit turns a color that is the blended combination of all the branches that contain that commit.","","So here we see that the `master` branch color is blended into all the commits, but the `bugFix` color is not. Let's fix that..."],command:"git merge bugFix",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's merge `master` into `bugFix`:"],afterMarkdowns:["Since `bugFix` was downstream of `master`, git didn't have to do any work; it simply just moved `bugFix` to the same commit `master` was attached to.","","Now all the commits are the same color, which means each branch contains all the work in the repository! Woohoo!"],command:"git checkout bugFix; git merge master",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["To complete this level, do the following steps:","","* Make a new branch called `bugFix`","* Checkout the `bugFix` branch with `git checkout bugFix`","* Commit once","* Go back to `master` with `git checkout`","* Commit another time","* Merge the branch `bugFix` into `master` with `git merge`","",'*Remember, you can always re-display this dialog with "help level"!*']}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ブランチとマージ","","いい調子ですね。これまでにコミットとブランチについて学びました。そろそろ2つのブランチを1つにまとめるやり方について見ていきましょう。これができれば新しいフィーチャの開発のために新しいブランチを切って、開発が終わったら変更を元のブランチへ統合することができるようになります。","","はじめに紹介するのは、`git merge`を使ったマージのやり方です。mergeコマンドによって、2つの独立した親を持つ特別なコミットを作ることができます。2つの親を持つコミットが持つ意味とは、「全く別々の場所にいるこの親とその親(*かつ*、それらの親の祖先全て)が持つ全ての変更を含んでいますよ」ということです。","","見てみた方が早いので、次の画面で確認してみましょう。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["それぞれ別のコミットを指している2つのブランチがあります。変更が別々のブランチに分散していて統合されていないケースです。これをマージで1つにまとめてみましょう。","","`bugFix`ブランチを`master`ブランチにマージしてみます。"],afterMarkdowns:["わあ。見ましたか?まず初めに、`master`ブランチが2つのコミットを親に持つ新しいコミットを指してますね。`master`から親をたどっていくと、最も古いコミットにたどり着くまでに全てのコミットを含んでいる様が確認できます。これで、全ての変更を含む`master`が完成しました。","","色がどう変わったかにも注目して下さい。学習を助けるために、ブランチ毎に色をつけています。それぞれのブランチは自分の色を持っていて、どのブランチから派生して出てくるか次第でコミットごとの色が決まります。","","今回のコミットには`master`ブランチの色が使われました。しかし`bugFix`ブランチの色がまだ変わってないようなので、これを変えてみましょう。"],command:"git merge bugFix",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["`master`ブランチを`bugFix`ブランチにマージしてみます。"],afterMarkdowns:["`bugFix`ブランチは`master`ブランチの派生元だったので、gitは実際大したことはしていません:`bugFix`ブランチを指していたポインタを`master`が指していたコミットへと移動させただけです。","","これで全てのコミットが同じ色になりました。つまり、リポジトリの中の全ての変更をそれぞれのブランチが持ったことになります。やったね!"],command:"git checkout bugFix; git merge master",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["以下の作業で理解度の確認をしてみましょう。 steps:","","* `bugFix`という名前で新しいブランチを切る","* `git checkout bugFix`コマンドで`bugFix`ブランチをチェックアウトする","* 一回だけコミット","* `git checkout`で`master`へ戻る","* もう1回コミットする","* `git merge`コマンドを使って、`bugFix`ブランチを`master`ブランチへとマージする","",'*注:"help level"コマンドでこのヘルプにいつでも戻ってこれます*']}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branches et Merges","","Super! Nous savons désormais comment faire des commits et de branches. Maintenant nous devons apprendre comment combiner ensemble les contenus de deux branches différentes. Ceci nous permettra de créer une nouvelle branche, développer une nouvelle fonctionnalité sur cette dernière, puis intégrer cette fonctionnalité en combinant le contenu de cette branche de développement à la branche d'origine(master par exemple).","","La première méthode que nous alons voir pour combiner le conenu de deux branches est `git merge`. Faire un 'merge' en git Git crée un commit spécial qui a deux parents. Un commit avec deux parents indique en susbtance \"Je veux inclure le contenu de ce parent et le conenu de cet autre parent, *et* l'ensemble de leurs parents.\"","","C'est plus facile en visualisant, regardons dans la vue suivante"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have two branches; each has one commit that's unique. This means that neither branch includes the entire set of \"work\" in the repository that we have done. Let's fix that with merge.","","We will `merge` the branch `bugFix` into `master`"],afterMarkdowns:["Woah! See that? First of all, `master` now points to a commit that has two parents. If you follow the arrows upstream from `master`, you will hit every commit along the way to the root. This means that `master` contains all the work in the repository now.","","Also, see how the colors of the commits changed? To help with learning, I have included some color coordination. Each branch has a unique color. Each commit turns a color that is the blended combination of all the branches that contain that commit.","","So here we see that the `master` branch color is blended into all the commits, but the `bugFix` color is not. Let's fix that..."],command:"git merge bugFix",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Faisons un merge de `master` dans `bugFix`:"],afterMarkdowns:["Puisque `bugFix` était un descendant de `master`, git n'avait aucun travail à effectuer; il a simplement déplacé `bugFix` au même commit auquel `master` est attaché.","","Maintenant tous les commits sont de la même couleur, ce qui indique que chaque branche contient tout le contenu du dépôt ! Woohoo!"],command:"git checkout bugFix; git merge master",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["Pour accomplir ce niveau, effectuez les opérations suivantes :","","* Faites une nouvelle branche appelée `bugFix`","* Positionnez-vous sur la branche `bugFix` avec `git checkout bugFix`","* Faites un commit","* Retournez sur la branche `master` (commande `git checkout`)","* Faites un nouveau commit","* Fusionnez la branche `bugFix` dans `master` avec `git merge`","",'*Rappelez-vous que vous pouvez à tout moment réafficher ces indications avec "help level"!*']}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branches and Merging","","Great! 我们已经知道怎么提交和使用分支了。接下来要学的一招是如何合并两个不同分支的工作。这让我们可以新建一个分支,在其上开发新功能,然后合并回主线。","","`git merge`是我们要学习的合并工作的第一个方法。合并产生一个特殊的提交记录,它包含两个唯一父提交。有两个父提交的提交记录本质上是:“我想把这两个父提交本身及它们的父提交集合都包含进来。”","","有图有真相,看看下面的图示就明白了。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["当前有两个分支:各有一个唯一的提交。这意味着没有一个分支包含我们对代码库的所有修改。让我们合并这两个分支来解决这个问题。","","我们要把 `bugFix` 合并到 `master` "],command:"git merge bugFix",afterMarkdowns:["哇!看见木有?首先,`master` 现在指向一个拥有两个父提交的提交记录。假如从 `master` 开始沿着箭头向上游走,在到达起点的路上会经过所有的提交记录。这说明有 `master` 包含了对代码库的所有修改。","","还有,看见各个提交记录的颜色变化了吗?为了帮助学习,我使用了颜色混合。每个分支都有特定的颜色。每个提交记录都变成了含有此提交的所有分支的混合色。","","所以,`master` 分支的颜色被混入到所有的提交记录,但 `bugFix` 没有。接下来就改一下这里吧。"],beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["让我们把 `master` 分支合并到 `bugFix` 吧。"],command:"git checkout bugFix; git merge master",afterMarkdowns:["因为 `bugFix` 分支在 `master` 分支的下游,git什么都不用做,只是简单地把`bugfix`分支移动到`master`指向的提交记录。","","现在所有的提交记录的颜色都是一样的啦,这表明每一个分支都包含了代码库的所有修改!走起!"],beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["想完成此关,执行收下操作:","","* 创建新分支 `bugFix` ","* 用 `git checkout bugFix` 切换到 `bugFix`分支","* 提交一次","* 用 `git checkout` 切换回 `master` ","* 再提交一次","* 用 `git merge` 合并 `bugFix`分支进 `master`","",'*记住,总是可以用 "help level" 命令来重新显示这个对话框!*']}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 브랜치와 합치기(Merge)","","좋습니다! 지금까지 커밋하고 브랜치를 만드는 방법을 알아봤습니다. 이제 두 별도의 브랜치를 합치는 몇가지 방법을 알아볼 차례입니다. 이제부터 배우는 방법으로 브랜치를 따고, 새 기능을 개발 한 다음 합칠 수 있게 될 것입니다.","",'처음으로 살펴볼 방법은 `git merge`입니다. Git의 합치기(merge)는 두 개의 부모(parent)를 가리키는 특별한 커밋을 만들어 냅니다. 두개의 부모가 있는 커밋이라는 것은 "한 부모의 모든 작업내역과 나머지 부모의 모든 작업, *그리고* 그 두 부모의 모든 부모들의 작업내역을 포함한다"라는 의미가 있습니다. ',"","그림으로 보는게 이해하기 쉬워요. 다음 화면을 봅시다."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["여기에 브랜치가 두 개 있습니다. 각 브랜치에 독립된 커밋이 하나씩 있구요. 그 말은 이 저장소에 지금까지 작업한 내역이 나뉘어 담겨 있다는 얘기입니다. 두 브랜치를 합쳐서(merge) 이 문제를 해결해 볼까요?","","`bugFix` 브랜치를 `master` 브랜치에 합쳐(merge) 보겠습니다."],afterMarkdowns:["보셨어요? 우선, `master`가 두 부모가 있는 커밋을 가리키고 있습니다. ","","또, 커밋들의 색이 바뀐 것을 눈치 채셨나요? 이해를 돕기위해 색상으로 구분해 표현했습니다. 각 브랜치는 그 브랜치만의 색상으로 그렸습니다. 브랜치가 합쳐지는 커밋의 경우에는, 그 브랜치들의 색을 조합한 색상으로 표시 했습니다.","","그런식으로 여기에 `bugFix`브랜치 쪽을 제외한 나머지 커밋만 `master` 브랜치의 색으로 칠해져 있습니다. 이걸 고쳐보죠..."],command:"git merge bugFix",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["이제 `master` 브랜치에 `bugFix`를 합쳐(merge) 봅시다:"],afterMarkdowns:["`bugFix`가 `master`의 부모쪽에 있었기 때문에, git이 별다른 일을 할 필요가 없었습니다; 간단히 `bugFix`를 `master`가 붙어 있는 커밋으로 이동시켰을 뿐입니다.","","짜잔! 이제 모든 커밋의 색이 같아졌고, 이는 두 브랜치가 모두 저장소의 모든 작업 내역을 포함하고 있다는 뜻입니다."],command:"git checkout bugFix; git merge master",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"}},{type:"ModalAlert",options:{markdowns:["아래 작업을 해서 이 레벨을 통과하세요:","","* `bugFix`라는 새 브랜치를 만듭니다","* `git checkout bugFix`를 입력해 `bugFix` 브랜치로 이동(checkout)합니다.","* 커밋 한 번 하세요","* `git checkout` 명령어를 이용해 `master`브랜치로 돌아갑니다","* 커밋 또 하세요","* `git merge` 명령어로 `bugFix`브랜치를 `master`에 합쳐 넣습니다.","",'*아 그리고, "help level" 명령어로 이 안내창을 다시 볼 수 있다는 것을 기억해 두세요!*']}}]}}}}),e("/src/levels/intro/merging.js"),e.define("/src/levels/intro/rebasing.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22master%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22bugFix%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C2%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22bugFix%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout -b bugFix;git commit;git checkout master;git commit;git checkout bugFix;git rebase master",name:{en_US:"Rebase Introduction",ja:"Rebaseの解説",fr_FR:"Introduction à rebase",ko:"리베이스(rebase)의 기본",zh_CN:"Rebase简介"},hint:{en_US:"Make sure you commit from bugFix first",ja:"初めにbugFixを指した状態でコミットする",fr_FR:"Assurez-vous de bien faire votre en premier votre commit sur bugFix",ko:"bugFix 브랜치에서 먼저 커밋하세요",zh_CN:"确保你先在 bugFix 分支进行提交"},disabledMap:{"git revert":!0},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Rebase","",'The second way of combining work between branches is *rebasing.* Rebasing essentially takes a set of commits, "copies" them, and plops them down somewhere else.',"","While this sounds confusing, the advantage of rebasing is that it can be used to make a nice linear sequence of commits. The commit log / history of the repository will be a lot cleaner if only rebasing is allowed.","","Let's see it in action..."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Here we have two branches yet again; note that the bugFix branch is currently selected (note the asterisk)","","We would like to move our work from bugFix directly onto the work from master. That way it would look like these two features were developed sequentially, when in reality they were developed in parallel.","","Let's do that with the `git rebase` command"],afterMarkdowns:["Awesome! Now the work from our bugFix branch is right on top of master and we have a nice linear sequence of commits.","",'Note that the commit C3 still exists somewhere (it has a faded appearance in the tree), and C3\' is the "copy" that we rebased onto master.',"","The only problem is that master hasn't been updated either, let's do that now..."],command:"git rebase master",beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Now we are checked out on the `master` branch. Let's go ahead and rebase onto `bugFix`..."],afterMarkdowns:["There! Since `master` was downstream of `bugFix`, git simply moved the `master` branch reference forward in history."],command:"git rebase bugFix",beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["To complete this level, do the following","","* Checkout a new branch named `bugFix`","* Commit once","* Go back to master and commit again","* Check out bugFix again and rebase onto master","","Good luck!"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Rebase","","ブランチを一つにまとめる方法として前回はマージを紹介しましたが、今回紹介するリベースを使うこともできます。リベースの動作は、マージするコミットのコピーをとって、どこかにストンと落とすというイメージです。","","ピンと来ないかもしれませんが、リベースのメリットは一本の連続したシーケンシャルなコミットに整形できることです。リベースだけ使っていると、コミットのログや履歴が非常にクリーンな状態に保たれます。","","早速実際にどう動くのかを見てみましょう。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["前回と同様の2つのブランチを考えます:仮にいまbugFixブランチをチェックアウトしているとします。(アスタリスクつきのもの)","","bugFixに入ってる作業内容をそのまま直接masterブランチ上の内容に移動したいとします。こうすることで、実際には並行して開発された2つの別々のブランチ上のフィーチャを、あたかも1本のブランチ上でシーケンシャルに開発されていたかのように見せることができます。","","`git rebase`コマンドでそれをやってみましょう。"],afterMarkdowns:["できた!これでbugFixブランチの作業内容はmasterブランチのすぐ先に移動したので、見た目が一本になってスッキリしました。","","気を付けてほしいのは、C3コミットはどこかに残ってるということ(ツリーの中で半透明にしてあります)、そしてC3'は(C3との接続が切れているC3の)コピーがmasterブランチ上に作られているということです。","","一つ問題が残ってて、masterブランチがまだ最新化されていませんね。ちょっと直してみましょう。。"],command:"git rebase master",beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["masterブランチはチェックアウトしてあります。この状態からmasterブランチを`bugFix`へとリベースしてみましょう。"],afterMarkdowns:["できた!`master`は`bugFix`の直前のコミットだったので、gitは単純に`master`ブランチのポインタを前に進めただけでした。"],command:"git rebase bugFix",beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["以下の作業で理解度の確認をしてみましょう。","","* `bugFix`という名前の新しいブランチをチェックアウトする","* 一回だけコミット","* masterブランチに戻ってもう1回コミット","* bugFixをもう1回チェックアウトして、master上にリベース","","幸運を祈る!"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Rebase","",'La seconde façon de combiner les contenus de deux branches est *rebase*. Rebase prend un enselble de commits, les "recopie", et les ajoute en bout de chaine à un autre endroit.',"","Bien que cela puisse sembler compliqué, l'avantage de rebase est de permettre d'obtenir une simple séquence linéeire de commits. Les logs/l'historique du dépôt seront bien plus propres si seul rebase est autorisé (plutôt que merge).","","Voyons rebase en action…"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Ici nous avons encore une fois deux branches; notez que nous sommes sur la branche bugFix (cf. l'asterisque)","","Nous voudrions transferer notre travail sur la branche 'bugFix' directement sur le travail dans 'master'. Ainsi on aurait l'impression que ces deux travaux ont été développés séquentiellement alors qu'en réalité ils ont été réalisés en parallèle.","","Faisons cela avec la commande `git rebase`"],afterMarkdowns:["Super! Désormais, le travail de la branche 'bugFix' est juste en haut de la branche 'master' et non avons une belle séquence linéaire de commits.","","Notez que le commit C3 existe toujours quelquepart (il est en grisé sur l'arbre), et C3' est la \"copie\" que nous avons créée sur master avec rebase.","","Le seul problème est que master n'a pas été mis à jour, faisons cela maintenant…"],command:"git rebase master",beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Nous sommes désormais positionnés sur la branche `master`. Continuons en faisant le rebase sur `bugFix`…","Et voilà ! Puisque `master` était un ascendant de `bugFix`, git a simplement déplacé la référence de la branche `master` en avant dans le temps."],command:"git rebase bugFix",beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["Pour acomplir ce niveau, faites les opérations suivantes","","* Positionnez-vous (checkout) sur une nouvelle branche nommée `bugFix`","* Faites un commit","* Retournez sur master et faites un nouveau commit","* Positionnez-vous à nouveau sur bugFix et faites un rebase sur master","","Bonne chance !"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git Rebase","",'*rebasing*是在分支之间合并工作的第二种方法。Rebasing就是取出一系列的提交记录,"复制"它们,然后把在别的某个地方放下来。',"","虽然听上去难以理解,rebasing 的优势是可以创造更线性的提交历史。假如只允许使用rebasing,代码库的提交日志/历史会更好看。","","让我们亲身体会下……"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["这里,还是有两个分支;注意当前分支是 bugFix(看那颗星)","","我们想要把 bugfix 里面的工作直接移到 master 分支上。使用这个方法,两个分支的功能看起来像是按顺序开发,实际上它们是平行开发的。","","用 `git rebase`实现此目标"],command:"git rebase master",afterMarkdowns:["碉堡吧,现在 bugFix 分支上的工作在 master 的最前端,同时我们也得到了一个更线性的提交序列。","","注意,提交记录 C3 仍然存在(阴影的那货就是你了,还看什么看),而我们已经将 C3 复制到了master。","","现在唯一的问题是 master 分支还没有更新……下面就来更新它吧"],beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["现在,切换到 `master` 分支。接下来就把它 rebase 到 `bugFix` 吧……"],command:"git rebase bugFix",afterMarkdowns:["完成!因为 `master` 是 `bugFix` 的下游,所以 git 只把 `master` 分支的记录前移到 `bugFix` 上。"],beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["想完成此关,执行以下操作:","","* 新建`bugFix`分支","* 提交一次","* 切换回 master 分支再提交一次","* 再次切换到 bugFix 分支,rebase 到 master 上","","祝你好运啦!"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git 리베이스(Rebase)","","브랜치끼리의 작업을 접목하는 두번째 방법은 *리베이스(rebase)*입니다. 리베이스는 기본적으로 커밋들을 모아서 복사한 뒤, 다른 곳에 떨궈 놓는 것입니다.","","조금 어려게 느껴질 수 있지만, 리베이스를 하면 커밋들의 흐름을 보기 좋게 한 줄로 만들 수 있다는 장점이 있습니다. 리베이스를 쓰면 저장소의 커밋 로그와 이력이 한결 깨끗해집니다.","","어떻게 동작하는지 살펴볼까요..."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["여기 또 브랜치 두 개가 있습니다; bugFix브랜치가 현재 선택됐다는 점 눈여겨 보세요 (별표 표시)","","bugFix 브랜치에서의 작업을 master 브랜치 위로 직접 옮겨 놓으려고 합니다. 그렇게 하면, 실제로는 두 기능을 따로따로 개발했지만, 마치 순서대로 개발한 것처럼 보이게 됩니다.","","`git rebase` 명령어로 함께 해보죠."],afterMarkdowns:["오! 이제 bugFix 브랜치의 작업 내용이 master의 바로 위에 깔끔한 한 줄의 커밋으로 보이게 됐습니다.","","C3 커밋은 어딘가에 아직 남아있고(그림에서 흐려짐), C3'는 master 위에 올려 놓은 복사본입니다.","","master가 아직 그대로라는 문제가 남아있는데요, 바로 해결해보죠..."],command:"git rebase master",beforeCommand:"git commit; git checkout -b bugFix C1; git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["우리는 지금 `master` 브랜치를 선택한 상태입니다. `bugFix` 브랜치쪽으로 리베이스 해보겠습니다..."],afterMarkdowns:["보세요! `master`가 `bugFix`의 부모쪽에 있었기 때문에, 단순히 그 브랜치를 더 앞쪽의 커밋을 가리키게 이동하는 것이 전부입니다."],command:"git rebase bugFix",beforeCommand:"git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"}},{type:"ModalAlert",options:{markdowns:["이하 작업을 하면 이번 레벨을 통과합니다","","* `bugFix`라는 새 브랜치를 만들어 선택하세요","* 커밋 한 번 합니다","* master로 돌아가서 또 커밋합니다","* bugFix를 다시 선택하고 master에 리베이스 하세요","","화이팅!"]}}]}}}}),e("/src/levels/intro/rebasing.js"),e.define("/src/levels/mixed/grabbingOneCommit.js",function(e,t,n,r,i,s,o){n.level={compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C4>e.C1}]},disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22master%22%7D%2C%22debug%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22debug%22%7D%2C%22printf%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22printf%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22bugFix%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout master;git cherry-pick C4",startTree:'{"branches":{"master":{"target":"C1","id":"master"},"debug":{"target":"C2","id":"debug"},"printf":{"target":"C3","id":"printf"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"bugFix","id":"HEAD"}}',name:{ko:"딱 한개의 커밋만 가져오기",en_US:"Grabbing Just 1 Commit",ja:"Grabbing Just 1 Commit",zh_CN:"只取一个提交"},hint:{en_US:"Remember, interactive rebase or cherry-pick is your friend here",ja:"このレベルではインタラクティブモードのrebaseやcherry-pickがクリアのカギです",ko:"대화식 리베이스(rebase -i)나 or 체리픽(cherry-pick)을 사용하세요",zh_CN:"记住,交互式 rebase 或者 cherry-pick 会很有帮助"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Locally stacked commits","","Here's a development situation that often happens: I'm trying to track down a bug but it is quite elusive. In order to aid in my detective work, I put in a few debug commands and a few print statements.","","All of these debugging / print statements are in their own branches. Finally I track down the bug, fix it, and rejoice!","","Only problem is that I now need to get my `bugFix` back into the `master` branch! I could simply fast-forward `master`, but then `master` would get all my debug statements."]}},{type:"ModalAlert",options:{markdowns:["This is where the magic of Git comes in. There are a few ways to do this, but the two most straightforward ways are:","","* `git rebase -i`","* `git cherry-pick`","","Interactive (the `-i`) rebasing allows you to choose which commits you want to keep or discard. It also allows you to reorder commits. This can be helpful if you want to toss out some work.","","Cherry-picking allows you to pick individual commits and plop them down on top of `HEAD`"]}},{type:"ModalAlert",options:{markdowns:["This is a later level so we will leave it up to you to decide, but in order to complete the level, make sure `master` receives the commit that `bugFix` references."]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ローカルに積み上がったコミット","","実際の開発ではこういうケースがよくあります:「バグの原因調査を試みているがバグの再現性がかなり低い。調査の補助のために、いくつかのデバッグ用の命令やprint文を差し込んでいる。」","","これらのデバッグ用のコードはバグ修正用のブランチにコミットされています。そしてついにバグの原因を突き止めて、修正した!やった!","","あとは`bugFix`ブランチを`master`ブランチに統合できればOK。そこで単純に`master`をfast-forwardすればよいかというと、それでは`master`ブランチの中にデバッグ用のコードも混入してしまいます。"]}},{type:"ModalAlert",options:{markdowns:["ここでGitの魔法が力を発揮します。解決のためにはいくつかの方法がありますが、最も素直な解決方法は2つあって:","","* `git rebase -i`","* `git cherry-pick`","","インタラクティブモードの(`-i`オプションつきの)rebaseによって、保持したいコミットと破棄したいコミットを選り分けることができます。コミットの順序を変更することも可能です。この方法は、一部の変更をどこかへやってしまいたい時に便利です。","","もう一方のcherry-pickを使うと、持っていきたいコミットを選んで`HEAD`の先にストンと落とすことができます。"]}},{type:"ModalAlert",options:{markdowns:["後半の章ですのでどう解決するかをもう自分で考えることができると思います。このレベルをクリアするためには、`bugFix`が持っているコミットを`master`ブランチが受け取る必要がある点には注意してください。"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 本地栈式提交 (Locally stacked commits)","","设想一下一个经常发生的场景:我在追踪一个有点棘手的 bug,为了更好地排查,我添加了一些调试命令和打印语句。","","所有的这些调试和打印语句都只在它们自己的分支里。最终我终于找到这个 bug,揪出来 fix 掉,然后撒花庆祝!","","现在唯一的问题就是要把我在 `bugFix` 分支里的工作合并回 `master` 分支。我可以简单地把 `master` 分支快进(fast-forward),但这样的话 `master` 分支就会包含我这些调试语句了。"]}},{type:"ModalAlert",options:{markdowns:["现在就是 Git 大显神通的时候啦。解决这个问题的方法不止一个,但最直接的两个方法是:","","* `git rebase -i`","* `git cherry-pick`","","交互(`-i`)衍合允许你选择哪些提交是要被保留,哪些要被舍弃。它允许你将提交重新排序。假如你要舍弃一些工作,这个会帮上很大的忙。","","Cherry-picking 能让你选择单独一个提交并且把它放到 `HEAD` 的最前端。"]}},{type:"ModalAlert",options:{markdowns:["本关是可选关卡,玩不玩随便你。但是如果你坚持要刷,确保 `master` 分支能拿到 `bugFix` 分支的相关提交(references)。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 로컬에 쌓인 커밋들","","개발중에 종종 이런 상황이 생깁니다: 잘 띄지 않는 버그를 찾아서 해결하려고, 어떤 부분의 문제인지를 찾기 위해 디버그용 코드와 화면에 정보를 프린트하는 코드 몇 줄 넣습니다. ","","디버깅용 코드나 프린트 명령은 그 브랜치에 들어있습니다. 마침내 버그를 찾아서 고쳤고, 원래 작업하는 브랜치에 합치면 됩니다!","","이제 `bugFix`브랜치의 내용을 `master`에 합쳐 넣으려 하지만, 한 가지 문제가 있습니다. 그냥 간단히 `master`브랜치를 최신 커밋으로 이동시킨다면(fast-forward) 그 불필요한 디버그용 코드들도 함께 들어가 버린다는 문제죠."]}},{type:"ModalAlert",options:{markdowns:["여기에서 Git의 마법이 드러납니다. 이 문제를 해결하는 여러가지 방법이 있습니다만, 가장 간단한 두가지 방법 아래와 같습니다:","","* `git rebase -i`","* `git cherry-pick`","","대화형 (-i 옵션) 리베이스(rebase)로는 어떤 커밋을 취하거나 버릴지를 선택할 수 있습니다. 또 커밋의 순서를 바꿀 수도 있습니다. 이 커맨드로 어떤 작업의 일부만 골라내기에 유용합니다.","","체리픽(cherry-pick)은 개별 커밋을 골라서 `HEAD`위에 떨어뜨릴 수 있습니다."]}},{type:"ModalAlert",options:{markdowns:["이번 레벨을 통과하기 위해 어떤 방법을 쓰시든 자유입니다만, `master`브랜치가 `bugFix` 브랜치의 커밋을 일부 가져오게 해주세요."]}}]}}}}),e("/src/levels/mixed/grabbingOneCommit.js"),e.define("/src/levels/mixed/jugglingCommits.js",function(e,t,n,r,i,s,o){n.level={disabledMap:{"git cherry-pick":!0,"git revert":!0},compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C2>e.C3},function(e){return e.C2>e.C1}]},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%27%27%22%2C%22id%22%3A%22master%22%7D%2C%22newImage%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22newImage%22%7D%2C%22caption%22%3A%7B%22target%22%3A%22C3%27%27%22%2C%22id%22%3A%22caption%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%2C%22C2%27%27%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%27%27%22%7D%2C%22C3%27%27%22%3A%7B%22parents%22%3A%5B%22C2%27%27%27%22%5D%2C%22id%22%3A%22C3%27%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git rebase -i HEAD~2;git commit --amend;git rebase -i HEAD~2;git rebase caption master",startTree:'{"branches":{"master":{"target":"C1","id":"master"},"newImage":{"target":"C2","id":"newImage"},"caption":{"target":"C3","id":"caption"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"caption","id":"HEAD"}}',name:{ko:"커밋들 갖고 놀기",en_US:"Juggling Commits",ja:"Juggling Commits",zh_CN:"提交变换戏法"},hint:{en_US:"The first command is git rebase -i HEAD~2",ja:"最初に打つコマンドはgit rebase -i HEAD~2",ko:"첫번째 명령은 git rebase -i HEAD~2 입니다",zh_CN:"第一个命令是 'git rebase -i HEAD~2'"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Juggling Commits","","Here's another situation that happens quite commonly. You have some changes (`newImage`) and another set of changes (`caption`) that are related, so they are stacked on top of each other in your repository (aka one after another).","","The tricky thing is that sometimes you need to make a small modification to an earlier commit. In this case, design wants us to change the dimensions of `newImage` slightly, even though that commit is way back in our history!!"]}},{type:"ModalAlert",options:{markdowns:["We will overcome this difficulty by doing the following:","","* We will re-order the commits so the one we want to change is on top with `git rebase -i`","* We will `commit --amend` to make the slight modification","* Then we will re-order the commits back to how they were previously with `git rebase -i`","* Finally, we will move master to this updated part of the tree to finish the level (via the method of your choosing)","","There are many ways to accomplish this overall goal (I see you eye-ing cherry-pick), and we will see more of them later, but for now let's focus on this technique."]}},{type:"ModalAlert",options:{markdowns:["Lastly, pay attention to the goal state here -- since we move the commits twice, they both get an apostrophe appended. One more apostrophe is added for the commit we amend, which gives us the final form of the tree ","","That being said, I can compare levels now based on structure and relative apostrophe differences. As long as your tree's `master` branch has the same structure and relative apostrophe differences, I'll give full credit"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## Commitsをやりくりする","","開発中に頻繁に起こるケースをもう1つ考えます。ある変更(`newImage`)とまた別の変更(`caption`)があって、それらに依存関係があるとします。この一連の変更が一列に積み重なっているとします。","","ここでトリッキーなのは、以前のコミットに対して微修正をかけなければならないケースがあるということです。今回の教材でも、過去のコミットであるにも関わらず`newImage`ブランチに僅かな修正を加えるような設計の修正が入ったとしましょう。"]}},{type:"ModalAlert",options:{markdowns:["この困難な状況を、以下の手順で克服することを考えます:","","* `git rebase -i`を使って順番を変更する。これで、変更をかけたいコミットを一番先頭に持ってくる。","* `commit --amend`コマンドで僅かな変更を行う","* `git rebase -i`コマンドを再度使って、先頭に持ってきていたコミットを元に戻す","* 最後に、レベルクリアのためにmasterブランチを先頭に持ってくる","","クリアのための方法はいくつもありますが(cherry-pickを使うこともできます)、別の回答はまた後程の章で見ることにんして、今回は上記の方法でやってみることにしましょう。"]}},{type:"ModalAlert",options:{markdowns:["最後に、ゴール時点での状態に気を付けてください。今回2回ほどコミットを動かしますから、コミットへのポインタにはアポストロフィ(')が追加されます。commit --amendコマンドの実行でできたコミットには更にもう1つのアポストロフィが追加されます。 "]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 提交变换戏法","","下面这种情况也是经常出现的。例如你之前已经在 `newImage` 分支上做了一些提交,然后又在 `caption` 分支上做了一些相关的提交,因此它们看起来是一个连一个的(stacked on top of each other in your repository)。","","有点棘手的就是有时候你又想往先前的提交里做些小改动。呐,现在就是设计师想要我们去轻微改变下 `newImage` 的内容(change the dimensions slightly),尽管那个提交是很久很久以前的了。"]}},{type:"ModalAlert",options:{markdowns:["为了实现他的愿望,我们可以按照下面的方法来做:","","* 先用 `git rebase -i` 将提交重新排序,然后把我们想要修改的提交挪到最前","* 然后用 `commit --amend` 来进行一些小修改","* 接着再用 `git rebase -i` 来将他们按最开始的顺序重新排好","* 最后我们把 master 移到修改的最前端(用你自己喜欢的方法),就大功告成啦!","","当然还有许多方法可以完成这个任务(我知道你在看 cherry-pick 啦),之后我们会多点关注这些技巧啦,但现在暂时只专注上面这种方法。"]}},{type:"ModalAlert",options:{markdowns:["啊最后还要提醒你一下最终的形式 —— 因为我们把这个提交移动了两次,所以会分别产生一个省略提交(both get an apostrophe appended)。还有一个省略提交是因为我们为了实现最终效果去修改提交而添加的。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 커밋들 갖고 놀기","","이번에도 꽤 자주 발생하는 상황입니다. `newImage`와 `caption` 브랜치에 각각의 변경내역이 있고 서로 약간 관련이 있어서, 저장소에 차례로 쌓여있는 상황입니다.","","때로는 이전 커밋의 내용을 살짝 바꿔야하는 골치아픈 상황에 빠지게 됩니다. 이번에는 디자인 쪽에서 우리의 작업이력(history)에서는 이미 한참 전의 커밋 내용에 있는 `newImage`의 크기를 살짝 바꿔달라는 요청이 들어왔습니다."]}},{type:"ModalAlert",options:{markdowns:["이 문제를 다음과 같이 풀어봅시다:","","* `git rebase -i` 명령으로 우리가 바꿀 커밋을 가장 최근 순서로 바꾸어 놓습니다","* `commit --amend` 명령으로 커밋 내용을 정정합니다","* 다시 `git rebase -i` 명령으로 이 전의 커밋 순서대로 되돌려 놓습니다","* 마지막으로, master를 지금 트리가 변경된 부분으로 이동합니다. (편하신 방법으로 하세요)","","이 목표를 달성하기 위해서는 많은 방법이 있는데요(체리픽을 고민중이시죠?), 체리픽은 나중에 더 살펴보기로 하고, 우선은 위의 방법으로 해결해보세요."]}},{type:"ModalAlert",options:{markdowns:["최종적으로, 목표 결과를 눈여겨 보세요 -- 우리가 커밋을 두 번 옮겼기 때문에, 두 커밋 모두 따옴표 표시가 붙어있습니다. 정정한(amend) 커밋은 따옴표가 추가로 하나 더 붙어있습니다."]}}]}}}}),e("/src/levels/mixed/jugglingCommits.js"),e.define("/src/levels/mixed/jugglingCommits2.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22master%22%7D%2C%22newImage%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22newImage%22%7D%2C%22caption%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22caption%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%27%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout master;git cherry-pick C2;git commit --amend;git cherry-pick C3",disabledMap:{"git revert":!0},startTree:'{"branches":{"master":{"target":"C1","id":"master"},"newImage":{"target":"C2","id":"newImage"},"caption":{"target":"C3","id":"caption"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"caption","id":"HEAD"}}',compareOnlyMasterHashAgnosticWithAsserts:!0,goalAsserts:{master:[function(e){return e.C2>e.C3},function(e){return e.C2>e.C1}]},name:{ko:"커밋 갖고 놀기 #2",en_US:"Juggling Commits #2",ja:"コミットをやりくりする その2",zh_CN:"提交交换戏法 #2"},hint:{en_US:"Don't forget to forward master to the updated changes!",ja:"masterのポインタを先に進めることを忘れずに!",ko:"master를 변경 완료한 커밋으로 이동(forward)시키는 것을 잊지 마세요!",zh_CN:"别忘记了将 master 快进到最新的更新上!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Juggling Commits #2","","*If you haven't completed Juggling Commits #1 (the previous level), please do so before continuing*","","As you saw in the last level, we used `rebase -i` to reorder the commits. Once the commit we wanted to change was on top, we could easily --amend it and re-order back to our preferred order.","","The only issue here is that there is a lot of reordering going on, which can introduce rebase conflicts. Let's look at another method with `git cherry-pick`"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Remember that git cherry-pick will plop down a commit from anywhere in the tree onto HEAD (as long as that commit isn't upstream).","","Here's a small refresher demo:"],afterMarkdowns:["Nice! Let's move on"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["So in this level, let's accomplish the same objective of amending `C2` once but avoid using `rebase -i`. I'll leave it up to you to figure it out! :D","","Remember, the exact number of apostrophe's (') on the commit are not important, only the relative differences. For example, I will give credit to a tree that matches the goal tree but has one extra apostrophe everywhere"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## コミットをやりくりする その2","","*注意 この一つ前のレベル「コミットをやりくりする」をクリアしていない人は、まずそちらの問題をクリアしてきてください*","","前回見てきたように、コミット順序の変更のために、私たちは`rebase -i`コマンドを利用しました。ツリーの先頭に変更対象のコミットがあれば、--amendオプションを使うことで容易に変更を書きかえて、元の順序に戻すことができます。","","この場合に心配なことが一つだけあって、それは複数回の順序の変更が行われるので、rebaseのコンフリクト(衝突)が起こりうることです。こういうケースへの対策として、`git cherry-pick`を使った別の解決法について考えてみましょう。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["git cherry-pickを使うと、ツリーの中から複数のコミットを選んで、HEADの下に新しく作ることができましたね。","","簡単なデモを見てみましょう:"],afterMarkdowns:["できました!次へ進みましょう"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["このレベルでは、`C2`をamendすることで前回と同じ目的を達成しましょう。但し`rebase -i`は使わずにクリアしてください。どんな方法で進めるかはあなたにおまかせします!:D"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 提交变换戏法 #2","","*假如你还没有完成提交变换戏法 #1(前一关),这关不让玩哦!*","","如你在上一关所见,我们使用 `rebase -i` 来重排那些提交。只要把我们想要的提交挪到最顶端,我们就可以很容易地改变它,然后把它们重新排成我们想要的顺序。","","但唯一的问题就是这样做就要排很多次,有可能造成衍合冲突(rebase conflicts)。下面就看看用另外一种方法 `git cherry-pick` 是怎么做的吧。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["要在心理牢记 cherry-pick 可以从提交树的任何地方拿一个提交来放在 HEAD 上(尽管那个提交不在上游)。","","下面是一个小小的演示:"],command:"git cherry-pick C2",afterMarkdowns:["好滴咧,我们继续"],beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["那么这关呢,和上一关一样要改变提交 `C2`,但你要避免使用 `rebase -i`。自己想想要怎么解决吧,骚年! :D"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 커밋 갖고 놀기 #2","","*만약 이전 레벨의 커밋 갖고 놀기 #1을 풀지 않으셨다면, 계속하기에 앞서서 꼭 풀어보세요*","","이전 레벨에서 보셨듯이 `rebase -i` 명령으로 커밋의 순서를 바꿀 수 있습니다. 정정할 커밋이 바로 직전(top)에 있으면 간단히 --amend로 수정할 수 있고, 그리고 나서 다시 원하는 순서로 되돌려 놓으면 됩니다.","","이번에 한가지 문제는 순서를 꽤 많이 바꿔야한다는 점인데요, 그러다가 리베이스중에 충돌이 날 수 있습니다. 이번에는 다른 방법인 `git cherry-pick`으로 해결해 봅시다."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["git cherry-pick으로 HEAD에다 어떤 커밋이든 떨어 뜨려 놓을 수 있다고 알려드린것 기억나세요? (단, 그 커밋이 현재 가리키고 있는 커밋이 아니어야합니다)","","간단한 데모로 다시 알려드리겠습니다:"],afterMarkdowns:["좋아요! 계속할게요"],command:"git cherry-pick C2",beforeCommand:"git checkout -b bugFix; git commit; git checkout master; git commit"}},{type:"ModalAlert",options:{markdowns:["그럼 이번 레벨에서는 아까와 마찬가지로 `C2` 커밋의 내용을 정정하되, `rebase -i`를 쓰지 말고 해보세요. ^.~"]}}]}}}}),e("/src/levels/mixed/jugglingCommits2.js"),e.define("/src/levels/rampup/detachedHead.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"C4","id":"HEAD"}}',solutionCommand:"git checkout C4",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Detach yo' HEAD",zh_CN:"分离HEAD"},hint:{en_US:"Use the label (hash) on the commit for help!",zh_CN:"使用提交记录上的标签(hash)来求助!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Moving around in Git","","Before we get to some of the more advanced features of Git, it's important to understand different ways to move through the commit tree that represents your project.","","Once you're comfortable moving around, your powers with other git commands will be amplified!","","","","",""]}},{type:"ModalAlert",options:{markdowns:["## HEAD","","First we have to talk about \"HEAD\". HEAD is the symbolic name for the currently checked out commit -- it's essentially what commit you're working on top of.","","HEAD always points to the most recent commit which is reflected in the working tree. Most git commands which make changes to the working tree will start by changing HEAD.","","Normally HEAD points to a branch name (like bugFix). When you commit, the status of bugFix is altered and this change is visible through HEAD."]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's see this in action. Here we will reveal HEAD before and after a commit."],afterMarkdowns:["See! HEAD was hiding underneath our `master` branch all along."],command:"git checkout C1; git checkout master; git commit; git checkout C2",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["### Detaching HEAD","","Detaching HEAD just means attaching it to a commit instead of a branch. This is what it looks like beforehand:","","HEAD -> master -> C1",""],afterMarkdowns:["And now it's","","HEAD -> C1"],command:"git checkout C1",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["To complete this level, let's detach HEAD from `bugFix` and attach it to the commit instead.","","Specify this commit by its hash. The hash for each commit is displayed on the circle that represents the commit."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 在Git中前后移动","","在接触Git的更多高级主题之前,我们先学习用不同的方法在代表你的项目的提交记录树上前后移动。","","一旦能够熟练地在Git中前进后退,你使用其他git命令的威力也会被放大!","","","","",""]}},{type:"ModalAlert",options:{markdowns:["## HEAD","",'我们首先看一下"HEAD". HEAD是当前提交记录的符号名称 -- 其实就是你正在其基础进行工作的提交记录。',"","HEAD总是指向最近一次提交记录,表现为当前工作树。大多数修改工作树的git命令都开始于改变HEAD指向。","","HEAD通常指向分支名(比如bugFix)。你提交时,改变了bugFix的状态,这一变化通过HEAD变得可见。"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["在实例中看一下。我们将会观察提交前后HEAD的位置。"],afterMarkdowns:["看! HEAD一直藏在`master`分支后面。"],command:"git checkout C1; git checkout master; git commit; git checkout C2",beforeCommand:""}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["### 分离 HEAD","","分离HEAD就是让其指向一个提交记录而不是分支名。这是命令执行之前的样子: ","","HEAD -> master -> C1",""],afterMarkdowns:["现在变成了","","HEAD -> C1"],command:"git checkout C1",beforeCommand:""}},{type:"ModalAlert",options:{markdowns:["想完成此关,从`bugFix`分离出HEAD并让其指向一个提交记录。","","通过hash值指定提交记录。每个提交记录的hash值显示在代表提交记录的圆圈中。"]}}]}}}}),e("/src/levels/rampup/detachedHead.js"),e.define("/src/levels/rampup/relativeRefs.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"C3","id":"HEAD"}}',solutionCommand:"git checkout bugFix^",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Relative Refs (^)",zh_CN:"相对引用(^)"},hint:{en_US:"Remember the Caret (^) operator!",zh_CN:"记住插入(^)操作符!"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Relative Refs","","Moving around in Git by specifying commit hashes can get a bit tedious. In the real world you won't have a nice commit tree visualization next to your terminal, so you'll have to use `git log` to see hashes.","","Furthermore, hashes are usually a lot longer in the real Git world as well. For instance, the hash of the commit that introduced the previous level is `fed2da64c0efc5293610bdd892f82a58e8cbc5d8`. Doesn't exactly roll off the tongue...","","The upside is that Git is smart about hashes. It only requires you to specify enough characters of the hash until it uniquely identifies the commit. So I can type `fed2` instead of the long string above."]}},{type:"ModalAlert",options:{markdowns:["Like I said, specifying commits by their hash isn't the most convenient thing ever, which is why Git has relative refs. They are awesome!","","With relative refs, you can start somewhere memorable (like the branch `bugFix` or `HEAD`) and work from there.","","Relative commits are powerful, but we will introduce two simple ones here:","","* Moving upwards one commit at a time with `^`","* Moving upwards a number of times with `~`"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's look at the Caret (^) operator first. Each time you append that to a ref name, you are telling Git to find the parent of the specified commit.","",'So saying `master^` is equivalent to "the first parent of `master`".',"","`master^^` is the grandparent (second-generation ancestor) of `master`","","Let's check out the commit above master here"],afterMarkdowns:["Boom! Done. Way easier than typing the commit hash"],command:"git checkout master^",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["You can also reference `HEAD` as a relative ref. Let's use that a couple of times to move upwards in the commit tree"],afterMarkdowns:["Easy! We can travel backwards in time with `HEAD^`"],command:"git checkout C3; git checkout HEAD^; git checkout HEAD^; git checkout HEAD^",beforeCommand:"git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["To complete this level, check out the parent commit of `bugFix`. This will detach `HEAD`.","","You can specify the hash if you want, but try using relative refs instead!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 相对引用","","用指定提交记录hash值的方式在Git中移动会变得比较乏味。在现实中,你不会有漂亮的可视化的提交记录树放在终端旁边,所以你不得不用`git log`来查看hasn值。","","另外,hash值在真实的Git环境中也会更长。举个例子,前一关的介绍中的提交记录的hash值是`fed2da64c0efc5293610bdd892f82a58e8cbc5d8`。不要把舌头闪了...","","好的一面是,Git对hash的处理很智能。你只需要提供能够唯一标识提交记录的前几个字符即可。所以,我可以仅输入`fed2`而不是上面的一长串字符。"]}},{type:"ModalAlert",options:{markdowns:["我说过,通过hash指定提交记录不是很方便,所以Git引入了相对引用。这个就很牛掰了!","","使用相对引用,你可以从一个易于记忆的地方(比如分支名`bugFix`或`HEAD`)开始工作。","","相对引用非常给力,这里我介绍两个简单的用法:","","* 使用`^`向上移动1个提交记录","* 使用`~`向上移动多个提交记录"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["首先看看插入(^)操作符。把插入符跟在引用名后面,表示让Git寻找指定提交记录的父提交。","",'所以`master^`相当于"`master`的父提交"。',"","`master^^`是`master`的父父提交(上上代祖先)","","切换到master的父提交"],afterMarkdowns:["唰!搞定。这种方式比输入提交记录的hash值简单多了!"],command:"git checkout master^",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["你也可以`HEAD`把用作相对引用。以下命令使用`HEAD`在提交树中向上移动几次。"],afterMarkdowns:["简单!我们可以一直使用`HEAD^`向上移动。"],command:"git checkout C3; git checkout HEAD^; git checkout HEAD^; git checkout HEAD^",beforeCommand:"git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["要完成此关,切换到`bugFix`的父提交。这会分离出`HEAD`.","","如果你愿意的话,使用hash值也可以过关,但为何不试试使用相对引用呢?"]}}]}}}}),e("/src/levels/rampup/relativeRefs.js"),e.define("/src/levels/rampup/relativeRefs2.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:'{"branches":{"master":{"target":"C6","id":"master"},"bugFix":{"target":"C0","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C5":{"parents":["C3"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"C1","id":"HEAD"}}',solutionCommand:"git branch -f master C6;git checkout HEAD~1;git branch -f bugFix HEAD~1",startTree:'{"branches":{"master":{"target":"C4","id":"master"},"bugFix":{"target":"C5","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C5":{"parents":["C3"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"C2","id":"HEAD"}}',hint:{en_US:"You'll need to use at least one direct reference (hash) to complete this level",zh_CN:"这一关至少要用到一次直接引用(hash)"},name:{en_US:"Relative Refs #2 (~)",zh_CN:"相对引用2(~)"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:['### The "~" operator',"","Say you want to move a lot of levels up in the commit tree. It might be tedious to type `^` several times, so Git also has the tilde (~) operator.","","","The tilde operator (optionally) takes in a trailing number that specifies the number of parents you would like to ascend. Let's see it in action"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["Let's specify a number of commits back with `~`."],afterMarkdowns:["Boom! So concise -- relative refs are great."],command:"git checkout HEAD~4",beforeCommand:"git commit; git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["### Branch forcing","","You're an expert on relative refs now, so let's actually *use* them for something.","","One of the most common ways I use relative refs is to move branches around. You can directly reassign a branch to a commit with the `-f` option. So something like:","","`git branch -f master HEAD~3`","","Moves (by force) the master branch to three parents behind HEAD."]}},{type:"ModalAlert",options:{markdowns:["To complete this level, move `HEAD`, `master`, and `bugFix` to their goal destinations shown."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:['### The "~" operator',"","假设需要在提交树中向上移动很多步。使用多个`^`非常无聊,所以Git也引入了波浪(~)操作符。","","","波浪操作符后面可以(可选地)跟一个数字,指定向上移动多少次。看个例子"]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["使用`~`一次后退多步."],afterMarkdowns:["唰!如此简洁--相对引用就是好啊!"],command:"git checkout HEAD~4",beforeCommand:"git commit; git commit; git commit"}},{type:"ModalAlert",options:{markdowns:["### Branch forcing","","你现在是相对引用的高手了,现在*用*他来实际做点事情。","","我使用相对引用最多的就是移动分支。你可以使用`-f`选项把直接让分支指向另一个提交。举个例子:","","`git branch -f master HEAD~3`","","(强制)移动master指向HEAD的第3级父提交。"]}},{type:"ModalAlert",options:{markdowns:["要完成此关,移动`HEAD`,`master`和`bugFix`到目标所示的位置。"]}}]}}}}),e("/src/levels/rampup/relativeRefs2.js"),e.define("/src/levels/rampup/reversingChanges.js",function(e,t,n,r,i,s,o){n.level={goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22master%22%7D%2C%22pushed%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22pushed%22%7D%2C%22local%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22local%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C2%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22pushed%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git reset HEAD~1;git checkout pushed;git revert HEAD",compareOnlyBranches:!0,startTree:'{"branches":{"master":{"target":"C1","id":"master"},"pushed":{"target":"C2","id":"pushed"},"local":{"target":"C3","id":"local"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"}},"HEAD":{"target":"local","id":"HEAD"}}',name:{en_US:"Reversing Changes in Git",ja:"変更を元に戻す",fr_FR:"Annuler des changements avec Git",ko:"Git에서 작업 되돌리기",zh_CN:"在Git中撤销更改"},hint:{en_US:"Notice that revert and reset take different arguments.",fr_FR:"",zh_CN:"注意revert和reset使用不同的参数。",ko:"",ja:""},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Reversing Changes in Git","","There are many ways to reverse changes in Git. And just like committing, reversing changes in Git has both a low-level component (staging individual files or chunks) and a high-level component (how the changes are actually reversed). Our application will focus on the latter.","","There are two primary ways to undo changes in Git -- one is using `git reset` and the other is using `git revert`. We will look at each of these in the next dialog",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","",'`git reset` reverts changes by moving a branch reference backwards in time to an older commit. In this sense you can think of it as "rewriting history;" `git reset` will move a branch backwards as if the commit had never been made in the first place.',"","Let's see what that looks like:"],afterMarkdowns:["Nice! Git simply moved the master branch reference back to `C1`; now our local repository is in a state as if `C2` had never happened"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","",'While reseting works great for local branches on your own machine, its method of "rewriting history" doesn\'t work for remote branches that others are using.',"","In order to reverse changes and *share* those reversed changes with others, we need to use `git revert`. Let's see it in action"],afterMarkdowns:["Weird, a new commit plopped down below the commit we wanted to reverse. That's because this new commit `C2'` introduces *changes* -- it just happens to introduce changes that exactly reverses the commit of `C2`.","","With reverting, you can push out your changes to share with others."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["To complete this level, reverse the two most recent commits on both `local` and `pushed`.","","Keep in mind that `pushed` is a remote branch and `local` is a local branch -- that should help you choose your methods."]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## 変更を元に戻す","","Gitでは変更を元に戻す方法がたくさんあります。コミットと同じように、低レベルな動作(ファイル別だったりファイルの中の一部だったり)も高レベルな動作(変更のまとまりのキャンセル)もできます。このアプリケーションでは後者の方法について紹介します。","","基本的なアンドゥの方法が2つあります - 一つは`git reset`を使う方法で、もう1つは`git revert`を使う方法です。次のダイアログで一つ一つを見ていきます。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","","`git reset`はブランチのポインタを後方に移動することで変更のキャンセルを実現します。履歴を上書きするような動作だと思うと良いでしょうか:`git reset`はそもそも前のコミットなんかなかったかのように、ブランチのポインタを元に戻してくれます。","","どういう感じか見てみましょう。"],afterMarkdowns:["いいですね!Gitは単純にmasterブランチへのポインタを`C1`へ戻しました。これでこのローカルリポジトリにはまるで`C2`なんて無かったかのように変更をキャンセルできました。"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","自分のマシン上のブランチではさっきの`git reset`でうまくいきましたが、この「履歴を上書きする」手段は、他の人も使っているリモートにあるリポジトリに対しては使うことができません。","","変更を巻き戻して他の人とそれを共有するためには、`git revert`を使う必要があります。今度はこれを見てみましょう。"],afterMarkdowns:["あれ、おかしいな。巻き戻したいと思ってたコミットの下に新しいコミットが出来上がってしまったみたいです。なぜか。これは、この新しい`C2'`コミットは`C2`へ戻すのに必要な内容を確かに変更して巻き戻していたのです。","","こんな風にして、巻き戻した内容を他人と共有するためにはrevertを使います。"],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["この章の仕上げに、`local`と`pushed`の両方の直近のコミットを巻き戻してみましょう。","","`pushed`はリモートのブランチで、`local`はローカルであることに注意。正しくコマンドを使い分けましょう。"]}}]},fr_FR:{childViews:[{type:"ModalAlert",options:{markdowns:["## Annuler des changements avec Git","","Il y a de nombreuses façons d'annuler des changement avec Git. De même que pour les commits, annuler des changements avec Git a à la fois un aspect bas-niveau (gestion dans le 'staging' des fichiers et morceaux de fichiers) et un aspect de plus haut niveau 9comment les changements sont effectivement annulés). Nous allons nous intéresser à ce dernier point.","","Il y a principalement deux façons d'annuler des changements avec Git -- l'une est `git reset` et l'autre est `git revert`. Nous allons maintenant voir chacune de ces façons",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","","`git reset` annule des changements en déplaçant la référence en arrière dans le temps sur un commit plus ancien. En ce sens, on peut considérer cela comme une façon de \"réécrire l'histoire\"; `git reset` fait remonter une branche en arrière comme si le(s) commit(s) n'avait jamais eu lieu.","","Regardons à quoi cela ressemble :"],afterMarkdowns:["Bravo ! Git a simplement déplacé la référence de la branche master en la faisant revenir sur `C1`; désormais notre dépôt est dans le même état que si `C2` n'avait jamais eu lieu"],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","Bien que le reset marche parfaitement pour les branches locales sur notre propre machine, cette façon de \"réécrire l'histoire\" ne marche pas avec les banches distantes (remote) que d'autres personnes utilisent.","","Pour pouvoir annuler des changements et *partager* ces annulations avec d'autres, nous devons utiliser `git revert`. Regardons comment cela fonctionne"],afterMarkdowns:["Étrangement, un nouveau commit est appaaru en bas sous le commit que nous voulions annuler. C'est parce que ce nouveau commit `C2'` introduit des *modifications* -- celles qui correspondent justement à l'annulation de celles du commit `C2`.","","Avec revert, vous pouvez diffuser (push) vos modifications et les partager avec tout le monde."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["Pour accomplir ce niveau, annulez les deux derniers commits à la fois sur `local` et sur `pushed`.","","Ayez à l'esprit que `pushed` est une branche distante et `local` est une branche locale -- cela devrait vous guider dans le choix de la méthode à employer."]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## 撤销 Git 里面的变动","","在 Git 里撤销修改的方法很多。和 commit 一样,在 Git 里撤销变动同时具有底层部分(暂存一些独立的文件或者片段)和高层部分(具体到变动是究竟怎么被撤销的)。我们这个应用主要关注后者。","","在 Git 里主要用两种方法来撤销变动 —— 一种是 `git reset`,另外一种是 `git revert`。让我们在下一个窗口逐一了解它们。",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Reset","",'`git reset`把分支记录回退到上一个提交记录来实现撤销改动。你可以认为这是在"重写历史"。`git reset`往回移动分支,原来指向的提交记录好像重来没有提交过一样。',"","让我们看看具体的操作:"],command:"git reset HEAD~1",afterMarkdowns:["Nice!Git把master分支的指向简单地移回到`C1`;现在我们的本地代码库处于没有提交过`C2`的状态了。"],beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git Revert","","虽然在你的本地分支中使用`git reset`很方便,但是这种“改写历史”的方法对别人的远端分支是无效的哦!","","为了撤销更改并*传播*给别人,我们需要使用`git revert`。举个例子"],command:"git revert HEAD",afterMarkdowns:["怪哉!在我们要撤销的提交记录后面居然多了一个新提交!这是因为新提交记录`C2'`引入了*更改*——刚好是用来撤销 `C2` 这个提交的。","","借助 revert,现在可以把你的更改传递给别人啦。"],beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["要完成此关,分别撤销`local`分支和`pushed`分支上的最近一次提交。","","记住 `pushed` 是一个远程分支,`local` 是一个本地分支 —— 有了这么明显的提示应该知道用哪种方法了吧?"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## Git에서 작업 되돌리기","","Git에는 작업한 것을 되돌리는 여러가지 방법이 있습니다. 변경내역을 되돌리는 것도 커밋과 마찬가지로 낮은 수준의 일(개별 파일이나 묶음을 스테이징 하는 것)과 높은 수준의 일(실제 변경이 복구되는 방법)이 있는데요, 여기서는 후자에 집중해 알려드릴게요.","","Git에서 변경한 내용을 되돌리는 방법은 크게 두가지가 있습니다 -- 하나는 `git reset`을 쓰는거고, 다른 하나는 `git revert`를 사용하는 것입니다. 다음 화면에서 하나씩 알아보겠습니다.",""]}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git 리셋(reset)","",'`git reset`은 브랜치로 하여금 예전의 커밋을 가리키도록 이동시키는 방식으로 변경 내용을 되돌립니다. 이런 관점에서 "히스토리를 고쳐쓴다"라고 말할 수 있습니다. 즉, `git reset`은 마치 애초에 커밋하지 않은 것처럼 예전 커밋으로 브랜치를 옮기는 것입니다.',"","어떤 그림인지 한번 보죠:"],afterMarkdowns:["그림에서처럼 master 브랜치가 가리키던 커밋을 `C1`로 다시 옮겼습니다; 이러면 로컬 저장소에는 마치 `C2`커밋이 아예 없었던 것과 마찬가지 상태가 됩니다."],command:"git reset HEAD~1",beforeCommand:"git commit"}},{type:"GitDemonstrationView",options:{beforeMarkdowns:["## Git 리버트(revert)","",'각자의 컴퓨터에서 작업하는 로컬 브랜치의 경우 리셋(reset)을 잘 쓸 수 있습니다만, "히스토리를 고쳐쓴다"는 점 때문에 다른 사람이 작업하는 리모트 브랜치에는 쓸 수 없습니다.',"","변경분을 되돌리고, 이 되돌린 내용을 다른 사람들과 *공유하기* 위해서는, `git revert`를 써야합니다. 예제로 살펴볼게요."],afterMarkdowns:["어색하게도, 우리가 되돌리려고한 커밋의 아래에 새로운 커밋이 생겼습니다. `C2`라는 새로운 커밋에 *변경내용*이 기록되는데요, 이 변경내역이 정확히 `C2` 커밋 내용의 반대되는 내용입니다.","","리버트를 하면 다른 사람들에게도 변경 내역을 밀어(push) 보낼 수 있습니다."],command:"git revert HEAD",beforeCommand:"git commit"}},{type:"ModalAlert",options:{markdowns:["이 레벨을 통과하려면, `local` 브랜치와 `pushed` 브랜치에 있는 최근 두 번의 커밋을 되돌려 보세요.","","`pushed`는 리모트 브랜치이고, `local`은 로컬 브랜치임을 신경쓰셔서 작업하세요 -- 어떤 방법을 선택하실지 떠오르시죠?"]}}]}}}}),e("/src/levels/rampup/reversingChanges.js"),e.define("/src/levels/rebase/manyRebases.js",function(e,t,n,r,i,s,o){n.level={compareOnlyMasterHashAgnostic:!0,disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22master%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22bugFix%22%7D%2C%22side%22%3A%7B%22target%22%3A%22C6%27%22%2C%22id%22%3A%22side%22%7D%2C%22another%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22another%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C6%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C6%22%7D%2C%22C7%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C7%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C6%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C6%27%22%7D%2C%22C7%27%22%3A%7B%22parents%22%3A%5B%22C6%27%22%5D%2C%22id%22%3A%22C7%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout bugFix;git rebase master;git checkout side;git rebase bugFix;git checkout another;git rebase side;git rebase another master",startTree:'{"branches":{"master":{"target":"C2","id":"master"},"bugFix":{"target":"C3","id":"bugFix"},"side":{"target":"C6","id":"side"},"another":{"target":"C7","id":"another"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C0"],"id":"C4"},"C5":{"parents":["C4"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"},"C7":{"parents":["C5"],"id":"C7"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{en_US:"Rebasing over 9000 times",ko:"9천번이 넘는 리베이스",ja:"Rebasing over 9000 times",zh_CN:"N次Rebase"},hint:{en_US:"Remember, the most efficient way might be to only update master at the end...",ja:"最も効率的なやり方はmasterを最後に更新するだけかもしれない・・・",ko:"아마도 master를 마지막에 업데이트하는 것이 가장 효율적인 방법일 것입니다...",zh_CN:"记住,最后更新master分支可能是最高效的方法。"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["### Rebasing Multiple Branches","","Man, we have a lot of branches going on here! Let's rebase all the work from these branches onto master.","","Upper management is making this a bit trickier though -- they want the commits to all be in sequential order. So this means that our final tree should have `C7'` at the bottom, `C6'` above that, etc etc, etc all in order.","","If you mess up along the way, feel free to use `reset` to start over again. Be sure to check out our solution and see if you can do it in fewer commands!"]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["### 複数のブランチをリベースする","","さあ、いくつものブランチが出てきます。このブランチたち全てをmasterブランチにリベースしましょう。","","おエライさん方が今回の仕事を少しトリッキーにしてくれました ― コミットはすべて一列のシーケンシャルな状態にしてほしいそうです。つまり私たちが作るリポジトリの最終的なツリーの状態は、`C7'`が最後に来て、`C6'`がその一つ上に来て、、と順に積み重なるイメージです。","","試行錯誤してツリーが汚くなってきたら、`reset`コマンドを使ってツリーの状態を初期化してください。模範解答をチェックして、それよりも簡単なコマンドで済ませられるかどうか、を考えるのも忘れずに!"]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["### 多分支衍合","","呐,现在我们有很多分支啦!让我们rebase这些分支的工作到 master 分支上吧。","","但是你的头头找了点麻烦 —— 他们希望得到有序的提交历史,也就是我们最终的结果是 `C7'` 在最底部,`C6'` 在它上面,以此类推。","","假如你搞砸了,没所谓的(虽然我不会告诉你用 `reset` 可以重新开始)。记得看看我们提供的答案,看你能否使用更少的命令完成任务!"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["### 여러 브랜치를 리베이스(rebase)하기 ","","음, 여기 꽤 여러개의 브랜치가 있습니다! 이 브랜치들의 모든 작업내역을 master에 리베이스 해볼까요?","","윗선에서 일을 복잡하게 만드네요 -- 그 분들이 이 모든 커밋들을 순서에 맞게 정렬하라고 합니다. 그럼 결국 우리의 최종 목표 트리는 제일 아래에 `C7'` 커밋, 그 위에 `C6'` 커밋, 또 그 위에 순서대로 보여합니다.","","만일 작업중에 내용이 꼬인다면, `reset`이라고 쳐서 처음부터 다시 시작할 수 있습니다. 모범 답안을 확인해 보시고, 혹시 더 적은 수의 커맨드로 해결할 수 있는지 알아보세요!"]}}]}}}}),e("/src/levels/rebase/manyRebases.js"),e.define("/src/levels/rebase/selectiveRebase.js",function(e,t,n,r,i,s,o){n.level={compareAllBranchesHashAgnostic:!0,disabledMap:{"git revert":!0},goalTreeString:"%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C5%22%2C%22id%22%3A%22master%22%7D%2C%22one%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22one%22%7D%2C%22two%22%3A%7B%22target%22%3A%22C2%27%27%22%2C%22id%22%3A%22two%22%7D%2C%22three%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22three%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C4%27%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C4%27%27%22%7D%2C%22C3%27%27%22%3A%7B%22parents%22%3A%5B%22C4%27%27%22%5D%2C%22id%22%3A%22C3%27%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C3%27%27%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22two%22%2C%22id%22%3A%22HEAD%22%7D%7D",solutionCommand:"git checkout one; git cherry-pick C4 C3 C2; git checkout two; git cherry-pick C5 C4 C3 C2; git branch -f three C2",startTree:'{"branches":{"master":{"target":"C5","id":"master"},"one":{"target":"C1","id":"one"},"two":{"target":"C1","id":"two"},"three":{"target":"C1","id":"three"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C4"],"id":"C5"}},"HEAD":{"target":"master","id":"HEAD"}}',name:{ko:"브랜치 스파게티",en_US:"Branch Spaghetti",ja:"ブランチスパゲッティ",zh_CN:"分支浆糊"},hint:{en_US:"Make sure to do everything in the proper order! Branch one first, then two, then three",ja:"全て正しい順番で処理すること!oneが最初で、次がtwo、最後にthreeを片付ける。",ko:"이 문제를 해결하는 방법은 여러가지가 있습니다! 체리픽(cherry-pick)이 가장 쉽지만 오래걸리는 방법이고, 리베이스(rebase -i)가 빠른 방법입니다",zh_CN:"确保你是按照正确的顺序来操作!先操作分支 `one`, 然后 `two`, 最后才是 `three`"},startDialog:{en_US:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branch Spaghetti","","WOAHHHhhh Nelly! We have quite the goal to reach in this level.","","Here we have `master` that is a few commits ahead of branches `one` `two` and `three`. For whatever reason, we need to update these three other branches with modified versions of the last few commits on master.","","Branch `one` needs a re-ordering and a deletion of `C5`. `two` needs pure reordering, and `three` only needs one commit!","","We will let you figure out how to solve this one -- make sure to check out our solution afterwards with `show solution`. "]}}]},ja:{childViews:[{type:"ModalAlert",options:{markdowns:["## ブランチスパゲッティ","","なんということでしょう。今回のレベルクリアのために、やることがたくさんあります。","","いま`master`が指しているコミットの数個前のコミットに、ブランチ`one`、`two`それから`three`があります。何か事情があって、これらの3つのブランチをmasterが指している最新の状態に更新したいケースを考えます。","","ブランチ`one`に対しては、順序の変更と`C5`の削除が必要です。`two`では順序の変更のみ、`three`に対しては1回だけコミットすればOKです。","","`show solution`コマンドで模範解答を確認できますから、こちらも利用してください。 "]}}]},zh_CN:{childViews:[{type:"ModalAlert",options:{markdowns:["## Branch Spaghetti","","哇塞大神!这关我们要来点不同的!","","现在我们的 `master` 分支是比 `one` `two` 和 `three` 要多几个提交。出于某种原因,我们需要把其他三个分支更新到 master 分支上新近的几个不同提交上。(update these three other brances with modified versions of the last few commits on master)","","分支 `one` 需要重新排序和撤销, `two` 需要完全重排,而 `three` 只需要提交一次。","","慢慢摸索会找到答案的 —— 你完事记得用 `show solution` 看看我们的答案哦。"]}}]},ko:{childViews:[{type:"ModalAlert",options:{markdowns:["## 브랜치 스파게티","","음, 이번에는 만만치 않습니다!","","여기 `master` 브랜치의 몇 번 이전 커밋에 `one`, `two`,`three` 총 3개의 브랜치가 있습니다. 어떤 이유인지는 몰라도, master의 최근 커밋 몇 개를 나머지 세 개의 브랜치에 반영하려고 합니다.","","`one` 브랜치는 순서를 바꾸고 `C5`커밋을 삭제하고, `two`브랜치는 순서만 바꾸며, `three`브랜치는 하나의 커밋만 가져옵시다!","","자유롭게 이 문제를 풀어보시고 나서 `show solution`명령어로 모범 답안을 확인해보세요."]}}]}}}}),e("/src/levels/rebase/selectiveRebase.js")})(); \ No newline at end of file diff --git a/index.html b/index.html index 43c1b54f..0dd4a100 100644 --- a/index.html +++ b/index.html @@ -434,7 +434,7 @@ For a much easier time perusing the source, see the individual files at: https://github.com/pcottle/learnGitBranching --> - +