├── .gitignore ├── jasmine-1.1.0 ├── jasmine_favicon.png ├── MIT.LICENSE ├── jasmine.css └── jasmine-html.js ├── test ├── test_page.js ├── test_storage.js ├── test_tools.js ├── test_viewmodel.js ├── test_iterator.js ├── test_simulate.js └── test_stats.js ├── js ├── page.js ├── storage.js ├── tools.js ├── viewmodel.js ├── simulation.js ├── mc.js ├── enchantments.js └── knockout.js ├── make.ps1 ├── README.md ├── test.html ├── index.html └── css └── bootstrap.min.css /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | -------------------------------------------------------------------------------- /jasmine-1.1.0/jasmine_favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zazcallabah/mce/HEAD/jasmine-1.1.0/jasmine_favicon.png -------------------------------------------------------------------------------- /test/test_page.js: -------------------------------------------------------------------------------- 1 | var _tools = makePage(); 2 | describe('enchantments', function(){ 3 | 4 | it('all have unique ids', function(){ 5 | for( var i = 0; i<_enchantments.length; i++ ) 6 | for( var j = i +1; j<_enchantments.length; j++ ) 7 | expect( _enchantments[i].id ).not.toBe( _enchantments[j].id ); 8 | }); 9 | }); -------------------------------------------------------------------------------- /test/test_storage.js: -------------------------------------------------------------------------------- 1 | var _storage = makeStorage(); 2 | describe('storage', function(){ 3 | 4 | it('can retrieve data to model', function(){ 5 | 6 | var model = makeViewModel(); 7 | model.mode( "aoeu"); 8 | 9 | 10 | _storage.getData(model); 11 | 12 | expect( model.mode() ).not.toBe( "aoeu" ); 13 | }); 14 | }); -------------------------------------------------------------------------------- /test/test_tools.js: -------------------------------------------------------------------------------- 1 | describe('tools', function(){ 2 | describe('when foreaching over a collection object', function(){ 3 | it('calls properties in order',function(){ 4 | var t = makeTools(); 5 | var c = makeCollection(t); 6 | 7 | c.report(1); 8 | c.report(3); 9 | c.report(2); 10 | 11 | c.report(3); 12 | c.report(3); 13 | c.report(2); 14 | 15 | var count = 0; 16 | c.foreach( function(item,label) 17 | { 18 | expect(label).toBe(''+(count+1)); 19 | expect(item.x).toBe((count+1)); 20 | count++; 21 | } 22 | ); 23 | 24 | }); 25 | }); 26 | }); -------------------------------------------------------------------------------- /test/test_viewmodel.js: -------------------------------------------------------------------------------- 1 | describe('a viewmodel', function(){ 2 | var tools = makeTools(); 3 | describe('with attached simulation',function(){ 4 | it('runs sim when updating material', function(){ 5 | var vm = makeViewModel(); 6 | vm.material("aoeu"); 7 | var hitcount = 0; 8 | vm.setOnChanged(function(){hitcount++;}); 9 | vm.material("other"); 10 | expect(hitcount).toBe(1); 11 | }); 12 | }); 13 | describe( 'stores item ids', function(){ 14 | var vm = makeViewModel(); 15 | 16 | it('supports bow',function(){ 17 | var item = tools.where( vm.availableItems(),function(i){return i.name==="Bow"})[0]; 18 | expect(item.value).toBe(8); 19 | }); 20 | }); 21 | 22 | }); 23 | -------------------------------------------------------------------------------- /test/test_iterator.js: -------------------------------------------------------------------------------- 1 | describe('iterator', function(){ 2 | var action = undefined; 3 | var callback = undefined; 4 | var iterator = makeIterator( 5 | function( data ) { if( action !== undefined ) return action( data ); }, 6 | function( result ) { if( callback !== undefined ) callback( result ); } 7 | ); 8 | 9 | it('runs times times', function(){ 10 | var count = 0; 11 | action = function(){ count++; }; 12 | 13 | iterator.run( 5 ); 14 | 15 | expect( count ).toBe( 5 ); 16 | }); 17 | 18 | it('calls action with parameter data', function(){ 19 | var obj = { aoeu: "aoeu" }; 20 | action = function( o ) { expect( o.aoeu ).toBe( "aoeu" ); }; 21 | iterator.run( 1, obj ); 22 | }); 23 | 24 | it('calls callback with result from action', function(){ 25 | action = function() { return { lol: "test2" }; }; 26 | callback = function( o ) { expect( o.lol ).toBe( "test2" ); }; 27 | 28 | iterator.run( 1 ); 29 | }); 30 | }); -------------------------------------------------------------------------------- /js/page.js: -------------------------------------------------------------------------------- 1 | var makePage = function( storage, tools, model ) { return { 2 | 3 | /* 4 | * Writes data to the info box. 5 | */ 6 | write: function( str ) 7 | { 8 | if(str === undefined ) 9 | str = " "; 10 | window.document.getElementById("output").innerHTML += str + "\n"; 11 | }, 12 | 13 | /* 14 | * Clears the info box of all components. 15 | */ 16 | clear: function() 17 | { 18 | model.clear(); 19 | this.clearAll("textholder"); 20 | }, 21 | 22 | clearAll: function( identifier ) 23 | { 24 | var elems = window.document.getElementsByClassName(identifier) 25 | for(var i = 0; i 30 ) // new level cap in 1.3 40 | model.level( 30 ); 41 | } 42 | else 43 | { 44 | if( level > 50 ) 45 | model.level(50); 46 | } 47 | if( isNaN( level ) ) 48 | model.level( 30 ); 49 | } 50 | }; }; 51 | -------------------------------------------------------------------------------- /jasmine-1.1.0/MIT.LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2011 Pivotal Labs 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /make.ps1: -------------------------------------------------------------------------------- 1 | function MakePattern( $name ) 2 | { 3 | [String]::Format("", $name) 4 | } 5 | 6 | function MakeCss( $name ) 7 | { 8 | [String]::Format("", $name ); 9 | } 10 | 11 | function ReplaceWithFile( $str, $name ) { 12 | $pattern = MakePattern $name 13 | $filecontents = gc $name 14 | $replacementdata = [String]::Format("" , [String]::Join("`n",$filecontents)) 15 | $str.Replace( $pattern, $replacementdata ); 16 | } 17 | 18 | function ReplaceWithCss( $str, $name ) { 19 | $pattern = MakeCss $name 20 | $filec = gc $name 21 | $repl = [String]::Format("", [String]::Join("`n",$filec)) 22 | $str.Replace( $pattern, $repl ); 23 | } 24 | rm mce.html 25 | gc index.html | Foreach-Object{ 26 | $one = ReplaceWithFile $_ "js/knockout.js" 27 | $two = ReplaceWithFile $one "js/storage.js" 28 | $three = ReplaceWithFile $two "js/tools.js" 29 | $four = ReplaceWithFile $three "js/enchantments.js" 30 | $five = ReplaceWithFile $four "js/viewmodel.js" 31 | $six = ReplaceWithFile $five "js/page.js" 32 | $seven = ReplaceWithFile $six "js/mc.js" 33 | $nine = ReplaceWithFile $seven "js/simulation.js" 34 | $ten = ReplaceWithCss $nine "css/bootstrap.min.css" 35 | add-content mce.html $ten 36 | } 37 | -------------------------------------------------------------------------------- /test/test_simulate.js: -------------------------------------------------------------------------------- 1 | var _page = makePage(); 2 | var _mc = makeMC("test"); 3 | describe('enchantmentlist',function(){ 4 | it('when striped removes self',function(){ 5 | 6 | var enchantmentlist = _mc.getEnchantments( 0, 0, 30 ); 7 | var enchantment = enchantmentlist[0]; 8 | enchantmentlist = _mc.stripeIncompatibleEnchantments( enchantment, enchantmentlist ); 9 | expect(enchantmentlist).not.toContain(enchantment); 10 | }); 11 | }); 12 | 13 | describe('enchantmentlist', function(){ 14 | it('when striped based on efficienty', function(){ 15 | var e1 = { 16 | enchantment: _enchantments[14], 17 | enchantmentLevel: 1 18 | }; 19 | var e2 = { 20 | enchantment: _enchantments[14], 21 | enchantmentLevel: 2 22 | }; 23 | var enchantmentlist = [e1,e2]; 24 | 25 | enchantmentlist = _mc.stripeIncompatibleEnchantments(enchantmentlist[0],enchantmentlist); 26 | expect( enchantmentlist ).not.toContain( e1 ); 27 | expect( enchantmentlist ).not.toContain( e2 ); 28 | }); 29 | }); 30 | 31 | describe('enchantmentlist', function(){ 32 | it('when created only holds one enchantment of each type', function(){ 33 | var enchantmentList = _mc.getEnchantments( 0, 0, 35 ); 34 | for( var i = 0; i 2 | 3 | 4 | Jasmine Spec Runner 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /js/tools.js: -------------------------------------------------------------------------------- 1 | var makeTools = function () { return { 2 | 3 | foreach: function( list, callback, order ) 4 | { 5 | function keys(obj) 6 | { 7 | var keys = []; 8 | for(var key in obj) 9 | { 10 | keys.push(key); 11 | } 12 | return keys; 13 | } 14 | 15 | var sortedproperties = keys(list).sort(); 16 | for( var i = 0; i 0 ) 72 | model.displayedCharts.pop(); 73 | }; 74 | 75 | var changeLevel = function( l ) 76 | { 77 | var level = parseInt(model.level(),10); 78 | model.level( level + l); 79 | }; 80 | 81 | model.addLevel = function(){changeLevel(1);}; 82 | model.removeLevel=function(){changeLevel(-1);}; 83 | 84 | model.setOnChanged = function( action ){ 85 | model.level.subscribe(action); 86 | model.stdev.subscribe(action); 87 | model.material.subscribe(action); 88 | model.item.subscribe(action); 89 | model.simulations.subscribe(action); 90 | model.iterations.subscribe(action); 91 | model.levelSimulations.subscribe(action); 92 | model.levelIterations.subscribe(action); 93 | model.mode.subscribe(action); 94 | model.power.subscribe(action); 95 | model.enchantment.subscribe(action); 96 | model.version.subscribe(action); 97 | }; 98 | model.run = function(){}; 99 | model.reset = function(){}; 100 | return model; 101 | }; 102 | 103 | /* 104 | Viewmodel object constructor function for one statistics-bar in a chart. 105 | */ 106 | var makeBar = function(color,message,label,upper,mean,lower,stdev,distanceleft,detailed,width) 107 | { 108 | var bar = {}; 109 | bar.color = ko.observable(color); 110 | bar.detailmessage=ko.observable(message); 111 | bar.label = ko.observable(label); 112 | bar.pixelheight = ko.observable( Math.round(mean) + "px"); 113 | bar.stdev = ko.observable(stdev); 114 | bar.upperstdev = ko.observable(Math.round(upper)+"px"); 115 | bar.lowerstdev = ko.observable(Math.round(lower)+"px"); 116 | bar.distanceleft = ko.observable(distanceleft+"px"); 117 | bar.showstdev = ko.observable(detailed); 118 | bar.mainopacity = ko.observable(detailed ? 0.7 : 1.0); 119 | bar.width = ko.observable( (width || 20) + "px" ); 120 | return bar; 121 | }; 122 | 123 | /* 124 | Viewmodel object constructor function for one chart. A chart holds a bunch of bars. 125 | */ 126 | var makeChart = function(title){ 127 | var chart={}; 128 | chart.bars = ko.observableArray([]); 129 | chart.title = ko.observable(title); 130 | chart.addBar= function( bar ){ 131 | chart.bars.push( bar ); 132 | }; 133 | return chart; 134 | }; 135 | 136 | -------------------------------------------------------------------------------- /js/simulation.js: -------------------------------------------------------------------------------- 1 | var makeSim = function(page,tools,model){ 2 | 3 | var simulate = function(gc,c,level,mc) 4 | { 5 | var iterations = model.iterations(); 6 | var simulations = model.simulations(); 7 | 8 | if( model.mode() === "level" ) 9 | { 10 | iterations = model.levelIterations(); 11 | simulations = model.levelSimulations(); 12 | } 13 | 14 | var total=0,misses=0; 15 | var collecthelper = function( result ) 16 | { 17 | gc.report( result.enchantment.id, result.enchantmentLevel ); 18 | }; 19 | 20 | var collectStats = function( result ) 21 | { 22 | total += result.length; 23 | if( result.length === 0 ) 24 | misses++; 25 | if( c!== undefined ) 26 | c.report(result.length); 27 | tools.foreach( result, collecthelper ) 28 | }; 29 | var calculateStdDev = function() 30 | { 31 | if(c!==undefined) 32 | c.updateSum(); 33 | gc.updateSum(); 34 | }; 35 | var it = makeIterator( mc.simulateEnchantments, collectStats, level || model.level() ); 36 | 37 | var iterate = function() 38 | { 39 | it.run( iterations, model ); 40 | }; 41 | var sim = makeIterator( iterate, calculateStdDev ); 42 | sim.run( simulations, model ); 43 | return {total:total,misses:misses}; 44 | }; 45 | 46 | var byEnchantment = function(mc) 47 | { 48 | var statsSimulateEnchantment = makeGroupedCollection( tools ); 49 | var statsEnchantmentCount = makeCollection( tools ); 50 | var itemname,materialname; 51 | tools.foreach( model.availableItems(), function(item){if( item.value === model.item() ) itemname = item.name; }); 52 | tools.foreach( model.availableMaterials(), function(mat){if( mat.value === model.material() ) materialname = mat.name; }); 53 | 54 | page.write( "Simulating enchanting " 55 | + materialname + " " 56 | + itemname + " " 57 | + model.iterations() + " times over " 58 | + model.simulations() +" series." ); 59 | 60 | var sim_result = simulate(statsSimulateEnchantment,statsEnchantmentCount,undefined,mc); 61 | 62 | page.write( "Done, presenting data..." ); 63 | if(sim_result.misses > 0 ) 64 | page.write ("Missed enchanting " + sim_result.misses + " times."); 65 | 66 | page.write( "Enchantment count saturation: " + sim_result.total / (model.iterations()*model.simulations()) ); 67 | 68 | var writeNInfo = function( p,s,label ) 69 | { 70 | return label + " enchantments: " + tools.wrapPercent(p,s); 71 | }; 72 | 73 | var writeCInfo = function(enchantment,p,s,level) 74 | { 75 | return enchantment.name + " " + level + ": " + _tools.wrapPercent( p, s ); 76 | }; 77 | var eChart = makeChart("Probability that enchantment will be included"); 78 | model.addChart(eChart); 79 | var drawController = makeDrawController( 240, 23, writeCInfo, model.iterations(), model.stdev(), page, 80 | function( enchantment, p ) 81 | { 82 | page.write("Total prob. for " + enchantment.name + ": " + Math.floor(p*1000)/10+ "%" ); 83 | }, 84 | eChart); 85 | 86 | statsSimulateEnchantment.foreach( drawController ); 87 | page.write(); 88 | var nChart = makeChart("Probability to get N enchantments"); 89 | model.addChart(nChart); 90 | var nWriter = makeBarGroup( 240, 23, "white", writeNInfo, model.iterations(), model.stdev(), page, nChart ); 91 | statsEnchantmentCount.foreach( nWriter.drawNext ); 92 | }; 93 | 94 | var byLevel = function(from,to,mc){ 95 | var ench = _enchantments[model.enchantment()]; 96 | var chart = makeChart("Probability by level"); 97 | model.addChart(chart); 98 | var writer = makeBarGroup( 240,16,ench.color,function(p,s,l){ 99 | if(isNaN(p))return "";return l+": "+tools.wrapPercent(p,s)},model.levelIterations(),model.stdev(),page,chart,1 ); 100 | for(var l = from; l<= to;l++) 101 | { 102 | var collection = makeGroupedCollection(tools); 103 | simulate(collection,undefined,l,mc); 104 | 105 | var data = collection.find(model.enchantment(),model.power()); 106 | writer.drawNext(data,l); 107 | } 108 | }; 109 | 110 | return function(){ 111 | var mc = makeMC(model.version()); 112 | 113 | page.clear(); 114 | page.validateFields(); 115 | _storage.saveData(model); 116 | var baseLevel = mc.getBaseEnchantmentLevel( model.item(), model.material() ); 117 | 118 | page.write(""); 119 | page.write( "Base enchantment level for tool: " + baseLevel ); 120 | 121 | if( baseLevel <= 0 ) 122 | { 123 | page.write( "Not enchantable!" ); 124 | model.addChart(makeChart()); 125 | return; 126 | } 127 | 128 | if( model.mode() === "level" ) 129 | { 130 | if( model.version() === "1.3.1" ) 131 | { 132 | byLevel( 1,30,mc); // new level cap 133 | } 134 | else 135 | { 136 | byLevel(1,25,mc); 137 | byLevel(26,50,mc); 138 | } 139 | } 140 | else 141 | { 142 | byEnchantment(mc); 143 | } 144 | }; 145 | }; 146 | 147 | var makeBarGroup = function( height, width, color, makeInfo, iterations, detailed, page, chart, existingcolumns ) 148 | { 149 | var columncount = existingcolumns || 0; 150 | var bargroup = { 151 | drawNext: function( statEntry, label ) 152 | { 153 | var percent = statEntry.mean / iterations; 154 | var stdev = Math.sqrt( statEntry.variance ) / iterations; 155 | 156 | var info = makeInfo( percent, stdev, label ); 157 | var upper = height * (percent + stdev ); 158 | var mean = height * percent; 159 | var lower = height * (percent - stdev ); 160 | chart.addBar( makeBar(color,info,label,upper,mean,lower,stdev, width*columncount + 1,detailed,width-3)); 161 | if( info !== "" ) 162 | page.write( info); 163 | columncount += 1; 164 | }, 165 | 166 | currentColumnCount: function() 167 | { 168 | return columncount; 169 | } 170 | }; 171 | return bargroup; 172 | }; 173 | var makeDrawController = function( height, width, makeInfo, iterations, detailed, page, reportBack, chart ) 174 | { 175 | var currentEnchantment = undefined; 176 | var probabilitySum = 0; 177 | 178 | var maker = { currentColumnCount: function() { return 0; } }; 179 | 180 | return { 181 | before: function( position ) 182 | { 183 | currentEnchantment = _enchantments[position]; 184 | probabilitySum = 0; 185 | maker = makeBarGroup( 186 | height, 187 | width, 188 | currentEnchantment.color, 189 | function(p,s,label) 190 | { 191 | probabilitySum += p; 192 | return makeInfo(currentEnchantment,p,s,label); 193 | }, 194 | iterations, 195 | detailed, 196 | page, 197 | chart, 198 | maker.currentColumnCount() 199 | ); 200 | }, 201 | callback: function( stats, label ){ maker.drawNext(stats,label); }, 202 | after: function() { reportBack( currentEnchantment, probabilitySum ); } 203 | }; 204 | }; 205 | -------------------------------------------------------------------------------- /js/mc.js: -------------------------------------------------------------------------------- 1 | var makeMC = function(version) 2 | { 3 | /**/ 4 | var N = function N() 5 | { 6 | return Math.random(); 7 | }; 8 | 9 | /**/ 10 | var X = function X( base ) 11 | { 12 | return Math.floor( Math.random() * ( base/2 + 1 ) ); 13 | }; 14 | 15 | /* 16 | j = 1 + random.nextInt((j >> 1) + 1) + random.nextInt((j >> 1) + 1); 17 | int k = j + i; 18 | float f = ((random.nextFloat() + random.nextFloat()) - 1.0F) * 0.25F; 19 | int l = (int)((float)k * (1.0F + f) + 0.5F); 20 | */ 21 | var simulateDistr = function simulateDistr( base, level ) 22 | { 23 | 24 | var j = Math.round(base); 25 | var i = Math.round(level); 26 | 27 | var j2 = 1 + X(j) + X(j); 28 | 29 | var k = j2 + i; 30 | var f = ((N() + N()) - 1.0) * 0.25; 31 | return Math.floor(k * (1.0 + f) + 0.5); 32 | }; 33 | 34 | /* 35 | Item item = par1ItemStack.getItem(); 36 | int i = item.getItemEnchantability(); 37 | 38 | if (i <= 0) 39 | { 40 | return null; 41 | } 42 | 43 | j /= 2; 44 | j2 = 1 + par0Random.nextInt((j >> 1) + 1) + par0Random.nextInt((j >> 1) + 1); 45 | int k = j2 + i; 46 | float f = ((par0Random.nextFloat() + par0Random.nextFloat()) - 1.0F) * 0.15F; 47 | int rrr = (int)((float)k* (1.0F + f) + 0.5F); 48 | 49 | if (rrr < 1) 50 | { 51 | rrr = 1; 52 | }*/ 53 | var simulateDistr13 = function( base, level ) 54 | { 55 | 56 | var j = Math.round(base) / 2; 57 | var i = Math.round(level); 58 | 59 | var j2 = 1 + X(j) + X(j); 60 | 61 | var k = j2 + i; 62 | var f = ((N() + N()) - 1.0) * 0.15; 63 | return Math.floor(k * (1.0 + f) + 0.5); 64 | }; 65 | 66 | /**/ 67 | var foreachValidEnchantment = function( materialId, itemId, callback ) { 68 | for( var i =0;i<_enchantments.length;i++) 69 | { 70 | if( _enchantments[i].canEnchant( materialId, itemId ) ) 71 | for( var v= _enchantments[i].minlevel; v<=_enchantments[i].maxlevel; v++) 72 | callback( _enchantments[i], v ); 73 | } 74 | }; 75 | 76 | /**/ 77 | var getEnchantments = function getEnchantments( matId, itemId, level ) 78 | { 79 | var map = {}; 80 | foreachValidEnchantment( matId, itemId, function( ench, enchlevel ) 81 | { 82 | if( ench.minEnchant(enchlevel) <= level && ench.maxEnchant(enchlevel) >= level ) 83 | map[ench.name] = { enchantment: ench, enchantmentLevel: enchlevel }; 84 | }); 85 | 86 | var list = []; 87 | for( var name in map ) 88 | { 89 | list[list.length] = map[name]; 90 | } 91 | return list; 92 | }; 93 | 94 | var stripeIncompatibleEnchantments = function stripeIncompatibleEnchantments( enchantment, list ) 95 | { 96 | var arr = []; 97 | for( var i =0;i 0; i = Math.floor(i / 2) ) 119 | { 120 | enchantmentlist = stripeIncompatibleEnchantmentsCallback( enchantment, enchantmentlist ); 121 | if( enchantmentlist.length > 0 ) 122 | { 123 | enchantment = selectWeightedCallback( enchantmentlist ); 124 | applied_enchantments[applied_enchantments.length] = enchantment; 125 | } 126 | } 127 | 128 | return applied_enchantments; 129 | }; 130 | 131 | 132 | /**/ 133 | var selectWeighted = function selectWeighted( validEnchantments ) 134 | { 135 | var totalweight = 0; 136 | for( var i = 0; i 2 | 3 | 4 | Minecraft Enchantment Simulator 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 35 | 36 | 37 | 38 | 39 | 49 |
50 |
51 |
52 |
53 |
54 |
55 | Select input 56 |
57 | 58 |
59 | 60 |
61 |
62 |
63 | 64 |
65 | 66 |
67 |
68 |
69 | 70 |
71 | 72 |
73 |
74 |
75 |
76 |
80 | 84 |
85 |
86 |
87 | 88 |
89 | 90 |
91 |
92 |
93 | 94 |
95 | 96 |
97 |
98 |
99 | 100 |
101 | 102 | 103 | 104 |
105 |
106 |
107 | 108 |
109 | 110 | 111 |
112 |
113 |
114 | 115 |
116 | 117 | 118 |
119 |
120 |
121 |
122 | 126 |
127 |
128 |
129 | 130 | 131 |
132 |
133 |
134 |
135 |
136 |

137 | 			
138 |
139 |
140 |
141 |
142 |
143 | 144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 | 162 |
163 | 180 | 181 | -------------------------------------------------------------------------------- /jasmine-1.1.0/jasmine-html.js: -------------------------------------------------------------------------------- 1 | jasmine.TrivialReporter = function(doc) { 2 | this.document = doc || document; 3 | this.suiteDivs = {}; 4 | this.logRunningSpecs = false; 5 | }; 6 | 7 | jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { 8 | var el = document.createElement(type); 9 | 10 | for (var i = 2; i < arguments.length; i++) { 11 | var child = arguments[i]; 12 | 13 | if (typeof child === 'string') { 14 | el.appendChild(document.createTextNode(child)); 15 | } else { 16 | if (child) { el.appendChild(child); } 17 | } 18 | } 19 | 20 | for (var attr in attrs) { 21 | if (attr == "className") { 22 | el[attr] = attrs[attr]; 23 | } else { 24 | el.setAttribute(attr, attrs[attr]); 25 | } 26 | } 27 | 28 | return el; 29 | }; 30 | 31 | jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) { 32 | var showPassed, showSkipped; 33 | 34 | this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' }, 35 | this.createDom('div', { className: 'banner' }, 36 | this.createDom('div', { className: 'logo' }, 37 | this.createDom('span', { className: 'title' }, "Jasmine"), 38 | this.createDom('span', { className: 'version' }, runner.env.versionString())), 39 | this.createDom('div', { className: 'options' }, 40 | "Show ", 41 | showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }), 42 | this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "), 43 | showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }), 44 | this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped") 45 | ) 46 | ), 47 | 48 | this.runnerDiv = this.createDom('div', { className: 'runner running' }, 49 | this.createDom('a', { className: 'run_spec', href: '?' }, "run all"), 50 | this.runnerMessageSpan = this.createDom('span', {}, "Running..."), 51 | this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, "")) 52 | ); 53 | 54 | this.document.body.appendChild(this.outerDiv); 55 | 56 | var suites = runner.suites(); 57 | for (var i = 0; i < suites.length; i++) { 58 | var suite = suites[i]; 59 | var suiteDiv = this.createDom('div', { className: 'suite' }, 60 | this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"), 61 | this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description)); 62 | this.suiteDivs[suite.id] = suiteDiv; 63 | var parentDiv = this.outerDiv; 64 | if (suite.parentSuite) { 65 | parentDiv = this.suiteDivs[suite.parentSuite.id]; 66 | } 67 | parentDiv.appendChild(suiteDiv); 68 | } 69 | 70 | this.startedAt = new Date(); 71 | 72 | var self = this; 73 | showPassed.onclick = function(evt) { 74 | if (showPassed.checked) { 75 | self.outerDiv.className += ' show-passed'; 76 | } else { 77 | self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, ''); 78 | } 79 | }; 80 | 81 | showSkipped.onclick = function(evt) { 82 | if (showSkipped.checked) { 83 | self.outerDiv.className += ' show-skipped'; 84 | } else { 85 | self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, ''); 86 | } 87 | }; 88 | }; 89 | 90 | jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { 91 | var results = runner.results(); 92 | var className = (results.failedCount > 0) ? "runner failed" : "runner passed"; 93 | this.runnerDiv.setAttribute("class", className); 94 | //do it twice for IE 95 | this.runnerDiv.setAttribute("className", className); 96 | var specs = runner.specs(); 97 | var specCount = 0; 98 | for (var i = 0; i < specs.length; i++) { 99 | if (this.specFilter(specs[i])) { 100 | specCount++; 101 | } 102 | } 103 | var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s"); 104 | message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"; 105 | this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild); 106 | 107 | this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString())); 108 | }; 109 | 110 | jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { 111 | var results = suite.results(); 112 | var status = results.passed() ? 'passed' : 'failed'; 113 | if (results.totalCount === 0) { // todo: change this to check results.skipped 114 | status = 'skipped'; 115 | } 116 | this.suiteDivs[suite.id].className += " " + status; 117 | }; 118 | 119 | jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) { 120 | if (this.logRunningSpecs) { 121 | this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); 122 | } 123 | }; 124 | 125 | jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { 126 | var results = spec.results(); 127 | var status = results.passed() ? 'passed' : 'failed'; 128 | if (results.skipped) { 129 | status = 'skipped'; 130 | } 131 | var specDiv = this.createDom('div', { className: 'spec ' + status }, 132 | this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"), 133 | this.createDom('a', { 134 | className: 'description', 135 | href: '?spec=' + encodeURIComponent(spec.getFullName()), 136 | title: spec.getFullName() 137 | }, spec.description)); 138 | 139 | 140 | var resultItems = results.getItems(); 141 | var messagesDiv = this.createDom('div', { className: 'messages' }); 142 | for (var i = 0; i < resultItems.length; i++) { 143 | var result = resultItems[i]; 144 | 145 | if (result.type == 'log') { 146 | messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); 147 | } else if (result.type == 'expect' && result.passed && !result.passed()) { 148 | messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); 149 | 150 | if (result.trace.stack) { 151 | messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); 152 | } 153 | } 154 | } 155 | 156 | if (messagesDiv.childNodes.length > 0) { 157 | specDiv.appendChild(messagesDiv); 158 | } 159 | 160 | this.suiteDivs[spec.suite.id].appendChild(specDiv); 161 | }; 162 | 163 | jasmine.TrivialReporter.prototype.log = function() { 164 | var console = jasmine.getGlobal().console; 165 | if (console && console.log) { 166 | if (console.log.apply) { 167 | console.log.apply(console, arguments); 168 | } else { 169 | console.log(arguments); // ie fix: console.log.apply doesn't exist on ie 170 | } 171 | } 172 | }; 173 | 174 | jasmine.TrivialReporter.prototype.getLocation = function() { 175 | return this.document.location; 176 | }; 177 | 178 | jasmine.TrivialReporter.prototype.specFilter = function(spec) { 179 | var paramMap = {}; 180 | var params = this.getLocation().search.substring(1).split('&'); 181 | for (var i = 0; i < params.length; i++) { 182 | var p = params[i].split('='); 183 | paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); 184 | } 185 | 186 | if (!paramMap.spec) { 187 | return true; 188 | } 189 | return spec.getFullName().indexOf(paramMap.spec) === 0; 190 | }; 191 | -------------------------------------------------------------------------------- /js/enchantments.js: -------------------------------------------------------------------------------- 1 | /* 2 | * The extracted data for each enchantment type. Source: Minecraft source, deobfuscated using the Minecraft Coder Pack 3 | */ 4 | var _enchantments = [ 5 | 6 | { 7 | name: "fortune", 8 | weight: 2, 9 | minlevel: 1, 10 | maxlevel: 3, 11 | maxEnchant: function( i ){ return this.minEnchant(i) + 50;}, 12 | minEnchant: function( i ){ return 15+(i-1)*9;}, 13 | canEnchant: function(mId,iId) { return iId === 0 || iId === 2 || iId === 3; }, 14 | applies: function( other ) { return !( other === "fortune" || other === "silktouch" ) }, 15 | id: 0, 16 | color: "white" 17 | }, 18 | { 19 | name: "protection", 20 | weight: 10, 21 | minlevel: 1, 22 | maxlevel: 4, 23 | maxEnchant: function( i ){ return this.minEnchant(i) + 20;}, 24 | minEnchant: function( i ){ return 1+(i-1)*11; }, 25 | canEnchant: function(mId,iId) { return iId >= 4 && iId < 8; }, 26 | applies: function( other ) { return !( other === "protection" || other === "fireprotection" || other === "blastprotection" ||other === "projectileprotection" ) }, 27 | id: 1, 28 | color: "blue" 29 | }, 30 | { 31 | name: "fireprotection", 32 | weight: 5, 33 | minlevel: 1, 34 | maxlevel: 4, 35 | maxEnchant: function( i ){ return this.minEnchant(i) + 12;}, 36 | minEnchant: function( i ){ return 10+(i-1)*8;}, 37 | canEnchant: function(mId,iId) { return iId >= 4 && iId < 8; }, 38 | applies: function( other ) { return !( other === "protection" || other === "fireprotection" || other === "blastprotection" ||other === "projectileprotection" ) }, 39 | id: 2, 40 | color: "red" 41 | }, 42 | { 43 | name: "featherfall", 44 | weight: 5, 45 | minlevel: 1, 46 | maxlevel: 4, 47 | maxEnchant: function( i ){ return this.minEnchant(i) + 10;}, 48 | minEnchant: function( i ){ return 5+(i-1)*6;}, 49 | canEnchant: function(mId,iId) { return iId === 7 }, 50 | applies: function( other ) { return other !== "featherfall" }, 51 | id: 3, 52 | color: "grey" 53 | }, 54 | { 55 | name: "blastprotection", 56 | weight: 2, 57 | minlevel: 1, 58 | maxlevel: 4, 59 | maxEnchant: function( i ){ return this.minEnchant(i) + 12;}, 60 | minEnchant: function( i ){ return 5+(i-1)*8;}, 61 | canEnchant: function(mId,iId) { return iId >= 4 && iId < 8; }, 62 | applies: function( other ) { return !( other === "protection" || other === "fireprotection" || other === "blastprotection" ||other === "projectileprotection" ) }, 63 | id: 4, 64 | color: "black" 65 | }, 66 | { 67 | name: "projectileprotection", 68 | weight: 5, 69 | minlevel: 1, 70 | maxlevel: 4, 71 | maxEnchant: function( i ){ return this.minEnchant(i) + 15;}, 72 | minEnchant: function( i ){ return 3+(i-1)*6;}, 73 | canEnchant: function(mId,iId) { return iId >= 4 && iId < 8; }, 74 | applies: function( other ) { return !( other === "protection" || other === "fireprotection" || other === "blastprotection" ||other === "projectileprotection" ) }, 75 | id: 5, 76 | color: "green" 77 | }, 78 | { 79 | name: "respiration", 80 | weight: 2, 81 | minlevel: 1, 82 | maxlevel: 3, 83 | maxEnchant: function( i ){ return this.minEnchant(i) + 30;}, 84 | minEnchant: function( i ){ return i*10;}, 85 | canEnchant: function(mId,iId) { return iId === 4 }, 86 | applies: function( other ) { return other !== "respiration" }, 87 | id: 6, 88 | color: "lime" 89 | }, 90 | { 91 | name: "aquaaffinity", 92 | weight: 2, 93 | minlevel: 1, 94 | maxlevel: 1, 95 | maxEnchant: function(){ return 41 }, 96 | minEnchant: function(){ return 1}, 97 | canEnchant: function(mId,iId) { return iId === 4; }, 98 | applies: function( other ) { return other !== "aquaaffinity" }, 99 | id: 7, 100 | color: "teal" 101 | }, 102 | { 103 | name: "sharpness", 104 | weight: 10, 105 | minlevel: 1, 106 | maxlevel: 5, 107 | maxEnchant: function( i ){ return this.minEnchant(i) + 20;}, 108 | minEnchant: function( i ){ return 1+(i-1)*11;}, 109 | canEnchant: function(mId,iId) { return iId === 1 ; }, 110 | applies: function( other ) { return !( other === "baneofarthropods" || other === "smite" || other === "sharpness" ) }, 111 | id: 8, 112 | color: "yellow" }, 113 | { 114 | name: "smite", 115 | weight: 5, 116 | minlevel: 1, 117 | maxlevel: 5, 118 | maxEnchant: function( i ){ return this.minEnchant(i) + 20;}, 119 | minEnchant: function( i ){ return 5+(i-1)*8;}, 120 | canEnchant: function(mId,iId) { return iId === 1; }, 121 | applies: function( other ) { return !(other === "baneofarthropods" || other === "smite" || other === "sharpness") }, 122 | id: 9, 123 | color: "sienna" 124 | }, 125 | { 126 | name: "baneofarthropods", 127 | weight: 5, 128 | minlevel: 1, 129 | maxlevel: 5, 130 | maxEnchant: function( i ){ return this.minEnchant(i) + 20;}, 131 | minEnchant: function( i ){ return 5+(i-1)*8;}, 132 | canEnchant: function(mId,iId) { return iId === 1; }, 133 | applies: function( other ) { return !( other === "baneofarthropods" || other === "smite" || other === "sharpness" ) }, 134 | id: 10, 135 | color: "olive" 136 | }, 137 | { 138 | name: "knockback", 139 | weight: 5, 140 | minlevel: 1, 141 | maxlevel: 2, 142 | maxEnchant: function( i ){ return this.minEnchant(i) + 50;}, 143 | minEnchant: function( i ){ return 5+(i-1)*20;}, 144 | canEnchant: function(mId,iId) { return iId === 1; }, 145 | applies: function( other ) { return other !== "knockback" }, 146 | id: 11, 147 | color: "lightblue" 148 | }, 149 | { 150 | name: "fireaspect", 151 | weight: 2, 152 | minlevel: 1, 153 | maxlevel: 2, 154 | maxEnchant: function( i ){ return this.minEnchant(i) + 50;}, 155 | minEnchant: function( i ){ return 10+(i-1)*20;}, 156 | canEnchant: function(mId,iId) { return iId === 1; }, 157 | applies: function( other ) { return other !== "fireaspect" }, 158 | id: 12, 159 | color: "orange" 160 | }, 161 | { 162 | name: "looting", 163 | weight: 2, 164 | minlevel: 1, 165 | maxlevel: 3, 166 | maxEnchant: function( i ){ return this.minEnchant(i) + 50;}, 167 | minEnchant: function( i ){ return 20+(i-1)*12;}, 168 | canEnchant: function(mId,iId) { return iId === 1; }, 169 | applies: function( other ) { return other !== "looting" }, 170 | id: 13, 171 | color: "navy" 172 | }, 173 | { 174 | name: "efficiency", 175 | weight: 10, 176 | minlevel: 1, 177 | maxlevel: 5, 178 | maxEnchant: function( i ){ return this.minEnchant(i) + 50;}, 179 | minEnchant: function( i ){ return 1+(i-1)*10;}, 180 | canEnchant: function(mId,iId) { return iId === 0 || iId === 2 || iId === 3; }, 181 | applies: function( other ) { return !( other === "efficiency" ) }, 182 | id: 14, 183 | color: "orchid" 184 | }, 185 | { 186 | name: "silktouch", 187 | weight: 1, 188 | minlevel: 1, 189 | maxlevel: 1, 190 | maxEnchant: function( i ){ return this.minEnchant(i) + 50;}, 191 | minEnchant: function(){ return 15;}, 192 | canEnchant: function(mId,iId) { return iId === 0 || iId === 2 || iId === 3; }, 193 | applies: function( other ) { return !( other === "fortune" || other === "silktouch" ) }, 194 | id: 15, 195 | color: "darkviolet" 196 | }, 197 | { 198 | name: "unbreaking", 199 | weight: 5, 200 | minlevel: 1, 201 | maxlevel: 3, 202 | maxEnchant: function( i ){ return this.minEnchant(i) + 50;}, 203 | minEnchant: function( i ){ return 5+(i-1)*8;}, 204 | canEnchant: function(mId,iId) { return iId === 0 || iId === 2 || iId === 3; }, 205 | applies: function( other ) { return other !== "unbreaking" }, 206 | id: 16, 207 | color: "turquoise" 208 | }, 209 | { 210 | name: "power", 211 | weight: 10, 212 | minlevel: 1, 213 | maxlevel: 5, 214 | maxEnchant: function( i ){ return this.minEnchant(i) + 15;}, 215 | minEnchant: function( i ){ return 1+(i-1)*10;}, 216 | canEnchant: function(mId,iId) { return iId === 8; }, 217 | applies: function( other ) { return other !== "power" }, 218 | id: 17, 219 | color: "yellow" 220 | }, 221 | { 222 | name: "flame", 223 | weight: 2, 224 | minlevel: 1, 225 | maxlevel: 1, 226 | maxEnchant: function( i ){ return 50;}, 227 | minEnchant: function( i ){ return 20;}, 228 | canEnchant: function(mId,iId) { return iId === 8; }, 229 | applies: function( other ) { return other !== "flame" }, 230 | id: 18, 231 | color: "orange" 232 | }, 233 | { 234 | name: "punch", 235 | weight: 2, 236 | minlevel: 1, 237 | maxlevel: 2, 238 | maxEnchant: function( i ){ return this.minEnchant(i) + 25;}, 239 | minEnchant: function( i ){ return 12+(i-1)*20;}, 240 | canEnchant: function(mId,iId) { return iId === 8; }, 241 | applies: function( other ) { return other !== "punch" }, 242 | id: 19, 243 | color: "lightblue" 244 | }, 245 | { 246 | name: "infinity", 247 | weight: 1, 248 | minlevel: 1, 249 | maxlevel: 1, 250 | maxEnchant: function( i ){ return 50;}, 251 | minEnchant: function( i ){ return 20;}, 252 | canEnchant: function(mId,iId) { return iId === 8; }, 253 | applies: function( other ) { return other !== "infinity" }, 254 | id: 20, 255 | color: "pink" 256 | } 257 | ]; 258 | -------------------------------------------------------------------------------- /js/knockout.js: -------------------------------------------------------------------------------- 1 | // Knockout JavaScript library v2.0.0 2 | // (c) Steven Sanderson - http://knockoutjs.com/ 3 | // License: MIT (http://www.opensource.org/licenses/mit-license.php) 4 | 5 | (function(window,undefined){ 6 | function c(a){throw a;}var l=void 0,m=!0,o=null,p=!1,r=window.ko={};r.b=function(a,b){for(var d=a.split("."),e=window,f=0;f",b[0];);return 4r.a.k(e,a[b])&&e.push(a[b]);return e},ba:function(a,e){for(var a=a||[],b=[],f=0,d=a.length;fa.length?p:a.substring(0,e.length)===e},hb:function(a){for(var e=Array.prototype.slice.call(arguments,1),b="return ("+a+")",f=0;f",""]||!d.indexOf("",""]||(!d.indexOf("",""]||[0,"",""];a="ignored
"+ 25 | d[1]+a+d[2]+"
";for("function"==typeof window.innerShiv?b.appendChild(window.innerShiv(a)):b.innerHTML=a;d[0]--;)b=b.lastChild;b=r.a.X(b.lastChild.childNodes)}return b};r.a.Z=function(a,b){r.a.U(a);if(b!==o&&b!==l)if("string"!=typeof b&&(b=b.toString()),"undefined"!=typeof jQuery)jQuery(a).html(b);else for(var d=r.a.ma(b),e=0;e"},Ra:function(a,b){var h=d[a];h===l&&c(Error("Couldn't find any memo with ID "+ 27 | a+". Perhaps it's already been unmemoized."));try{return h.apply(o,b||[]),m}finally{delete d[a]}},Sa:function(a,f){var d=[];b(a,d);for(var g=0,i=d.length;gb;b++)a=a();return a})};r.toJSON=function(a){a=r.Pa(a);return r.a.qa(a)}})();r.b("ko.toJS",r.Pa);r.b("ko.toJSON",r.toJSON); 43 | r.h={q:function(a){return"OPTION"==a.tagName?a.__ko__hasDomDataOptionValue__===m?r.a.e.get(a,r.c.options.la):a.getAttribute("value"):"SELECT"==a.tagName?0<=a.selectedIndex?r.h.q(a.options[a.selectedIndex]):l:a.value},S:function(a,b){if("OPTION"==a.tagName)switch(typeof b){case "string":r.a.e.set(a,r.c.options.la,l);"__ko__hasDomDataOptionValue__"in a&&delete a.__ko__hasDomDataOptionValue__;a.value=b;break;default:r.a.e.set(a,r.c.options.la,b),a.__ko__hasDomDataOptionValue__=m,a.value="number"===typeof b? 44 | b:""}else if("SELECT"==a.tagName)for(var d=a.options.length-1;0<=d;d--){if(r.h.q(a.options[d])==b){a.selectedIndex=d;break}}else{if(b===o||b===l)b="";a.value=b}}};r.b("ko.selectExtensions",r.h);r.b("ko.selectExtensions.readValue",r.h.q);r.b("ko.selectExtensions.writeValue",r.h.S); 45 | r.j=function(){function a(a,e){for(var d=o;a!=d;)d=a,a=a.replace(b,function(a,b){return e[b]});return a}var b=/\@ko_token_(\d+)\@/g,d=/^[\_$a-z][\_$a-z0-9]*(\[.*?\])*(\.[\_$a-z][\_$a-z0-9]*(\[.*?\])*)*$/i,e=["true","false"];return{D:[],Y:function(b){var e=r.a.z(b);if(3>e.length)return[];"{"===e.charAt(0)&&(e=e.substring(1,e.length-1));for(var b=[],d=o,i,j=0;j$/: 50 | /^\s*ko\s+(.*\:.*)\s*$/,g=f?/^<\!--\s*\/ko\s*--\>$/:/^\s*\/ko\s*$/,i={ul:m,ol:m};r.f={C:{},childNodes:function(b){return a(b)?d(b):b.childNodes},ha:function(b){if(a(b))for(var b=r.f.childNodes(b),e=0,d=b.length;e"),p)}};r.c.uniqueName.Za=0; 70 | r.c.checked={init:function(a,b,d){r.a.s(a,"click",function(){var e;if("checkbox"==a.type)e=a.checked;else if("radio"==a.type&&a.checked)e=a.value;else return;var f=b();"checkbox"==a.type&&r.a.d(f)instanceof Array?(e=r.a.k(r.a.d(f),a.value),a.checked&&0>e?f.push(a.value):!a.checked&&0<=e&&f.splice(e,1)):r.P(f)?f()!==e&&f(e):(f=d(),f._ko_property_writers&&f._ko_property_writers.checked&&f._ko_property_writers.checked(e))});"radio"==a.type&&!a.name&&r.c.uniqueName.init(a,function(){return m})},update:function(a, 71 | b){var d=r.a.d(b());if("checkbox"==a.type)a.checked=d instanceof Array?0<=r.a.k(d,a.value):d;else if("radio"==a.type)a.checked=a.value==d}};r.c.attr={update:function(a,b){var d=r.a.d(b())||{},e;for(e in d)if("string"==typeof e){var f=r.a.d(d[e]);f===p||f===o||f===l?a.removeAttribute(e):a.setAttribute(e,f.toString())}}}; 72 | r.c.hasfocus={init:function(a,b,d){function e(a){var e=b();a!=r.a.d(e)&&(r.P(e)?e(a):(e=d(),e._ko_property_writers&&e._ko_property_writers.hasfocus&&e._ko_property_writers.hasfocus(a)))}r.a.s(a,"focus",function(){e(m)});r.a.s(a,"focusin",function(){e(m)});r.a.s(a,"blur",function(){e(p)});r.a.s(a,"focusout",function(){e(p)})},update:function(a,b){var d=r.a.d(b());d?a.focus():a.blur();r.a.sa(a,d?"focusin":"focusout")}}; 73 | r.c["with"]={o:function(a){return function(){var b=a();return{"if":b,data:b,templateEngine:r.p.M}}},init:function(a,b){return r.c.template.init(a,r.c["with"].o(b))},update:function(a,b,d,e,f){return r.c.template.update(a,r.c["with"].o(b),d,e,f)}};r.j.D["with"]=p;r.f.C["with"]=m;r.c["if"]={o:function(a){return function(){return{"if":a(),templateEngine:r.p.M}}},init:function(a,b){return r.c.template.init(a,r.c["if"].o(b))},update:function(a,b,d,e,f){return r.c.template.update(a,r.c["if"].o(b),d,e,f)}}; 74 | r.j.D["if"]=p;r.f.C["if"]=m;r.c.ifnot={o:function(a){return function(){return{ifnot:a(),templateEngine:r.p.M}}},init:function(a,b){return r.c.template.init(a,r.c.ifnot.o(b))},update:function(a,b,d,e,f){return r.c.template.update(a,r.c.ifnot.o(b),d,e,f)}};r.j.D.ifnot=p;r.f.C.ifnot=m; 75 | r.c.foreach={o:function(a){return function(){var b=r.a.d(a());return!b||"number"==typeof b.length?{foreach:b,templateEngine:r.p.M}:{foreach:b.data,includeDestroyed:b.includeDestroyed,afterAdd:b.afterAdd,beforeRemove:b.beforeRemove,afterRender:b.afterRender,templateEngine:r.p.M}}},init:function(a,b){return r.c.template.init(a,r.c.foreach.o(b))},update:function(a,b,d,e,f){return r.c.template.update(a,r.c.foreach.o(b),d,e,f)}};r.j.D.foreach=p;r.f.C.foreach=m;r.b("ko.allowedVirtualElementBindings",r.f.C); 76 | r.t=function(){};r.t.prototype.renderTemplateSource=function(){c("Override renderTemplateSource")};r.t.prototype.createJavaScriptEvaluatorBlock=function(){c("Override createJavaScriptEvaluatorBlock")};r.t.prototype.makeTemplateSource=function(a){if("string"==typeof a){var b=document.getElementById(a);b||c(Error("Cannot find template with ID "+a));return new r.m.g(b)}if(1==a.nodeType||8==a.nodeType)return new r.m.I(a);c(Error("Unknown template type: "+a))}; 77 | r.t.prototype.renderTemplate=function(a,b,d){return this.renderTemplateSource(this.makeTemplateSource(a),b,d)};r.t.prototype.isTemplateRewritten=function(a){return this.allowTemplateRewriting===p?m:this.W&&this.W[a]?m:this.makeTemplateSource(a).data("isRewritten")};r.t.prototype.rewriteTemplate=function(a,b){var d=this.makeTemplateSource(a),e=b(d.text());d.text(e);d.data("isRewritten",m);if("string"==typeof a)this.W=this.W||{},this.W[a]=m};r.b("ko.templateEngine",r.t); 78 | r.$=function(){function a(a,b,d){for(var a=r.j.Y(a),g=r.j.D,i=0;i/g;return{gb:function(a,b){b.isTemplateRewritten(a)||b.rewriteTemplate(a,function(a){return r.$.ub(a,b)})},ub:function(e,f){return e.replace(b,function(b,e,d,j,k,n,t){return a(t,e,f)}).replace(d,function(b,e){return a(e,"<\!-- ko --\>",f)})},Ua:function(a){return r.r.ka(function(b,d){b.nextSibling&&r.xa(b.nextSibling,a,d)})}}}();r.b("ko.templateRewriting",r.$);r.b("ko.templateRewriting.applyMemoizedBindingsToNextSibling",r.$.Ua);r.m={};r.m.g=function(a){this.g=a}; 80 | r.m.g.prototype.text=function(){if(0==arguments.length)return"script"==this.g.tagName.toLowerCase()?this.g.text:this.g.innerHTML;var a=arguments[0];"script"==this.g.tagName.toLowerCase()?this.g.text=a:r.a.Z(this.g,a)};r.m.g.prototype.data=function(a){if(1===arguments.length)return r.a.e.get(this.g,"templateSourceData_"+a);r.a.e.set(this.g,"templateSourceData_"+a,arguments[1])};r.m.I=function(a){this.g=a};r.m.I.prototype=new r.m.g; 81 | r.m.I.prototype.text=function(){if(0==arguments.length)return r.a.e.get(this.g,"__ko_anon_template__");r.a.e.set(this.g,"__ko_anon_template__",arguments[0])};r.b("ko.templateSources",r.m);r.b("ko.templateSources.domElement",r.m.g);r.b("ko.templateSources.anonymousTemplate",r.m.I); 82 | (function(){function a(a,b,d){for(var g=0;node=a[g];g++)node.parentNode===b&&(1===node.nodeType||8===node.nodeType)&&d(node)}function b(a,b,h,g,i){var i=i||{},j=i.templateEngine||d;r.$.gb(h,j);h=j.renderTemplate(h,g,i);("number"!=typeof h.length||0a&&c(Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later."));var h=d.data("precompiled");h||(h=d.text()||"",h=jQuery.template(o,"{{ko_with $item.koBindingContext}}"+h+"{{/ko_with}}"),d.data("precompiled",h)); 95 | d=[e.$data];e=jQuery.extend({koBindingContext:e},f.templateOptions);e=jQuery.tmpl(h,d,e);e.appendTo(document.createElement("div"));jQuery.fragments={};return e};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+a+" })()) }}"};this.addTemplate=function(a,b){document.write("