aggixx

Untitled

May 21st, 2017
251
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // name, lvl, modifiers, weights
  2. var rawData = `MapAtlasMapsHave20PercentQuality 1   "Maps have 20% Quality
  3. Unique Bosses deal 20% increased Damage"    default 1,000
  4. MapAtlasContainsAdditionalRandomBoss    1   Areas are inhabited by an additional Invasion Boss  "hall_of_grandmasters 0
  5. default 1,000"
  6. MapAtlasClustersOfBloodwormBarrels  1   Areas contain 30 additional Clusters of Mysterious Barrels  default 850
  7. MapAtlasPhysicalDamageAndPacks_ 1   "Areas contain additional Monsters that deal Physical Damage
  8. Players and Monsters take 10% increased Physical Damage"    "no_monster_packs 0
  9. default 1,000"
  10. MapAtlasHighValueEnemiesOnOwnTeam   1   Areas contain hunted traitors   "no_monster_packs 0
  11. default 100"
  12. MapAtlasMagicAndRareMapsHaveAdditionalPacks 1   "Magic Maps contain additional Magic Monsters
  13. Rare Maps contain additional Rare Monsters
  14. Normal Maps contain additional Normal Monsters" "unique_map 0
  15. no_monster_packs 0
  16. default 1,000"
  17. MapAtlasMoveAttackCastSpeed 1   "20% increased Player and Monster Movement Speed
  18. 20% increased Monster Attack Speed
  19. 20% increased Monster Cast Speed"   default 1,000
  20. MapAtlasMontersThatConvertOnDeath__ 1   Areas contain additional Monsters that Convert when Killed  "no_monster_packs 0
  21. default 1,000"
  22. MapAtlasUnIDedMapsGrantQuantity 1   "30% increased Quantity of Items found in Unidentified Maps
  23. Found Items drop Identified in Identified Maps
  24. 15% increased Pack Size in Unidentified Maps"   default 1,000
  25. MapAtlasReducedReflectedDamageTakenMirroredRares    1   "Players cannot take Reflected Damage
  26. Areas contain additional Packs with Mirrored Rare Monsters" default 1,000
  27. MapAtlasPlayersDamageDealtAndTakenWhileStationary_  1   "Players deal 100% increased Damage while stationary
  28. Players take 10% increased Damage while stationary" "vaults_of_atziri 0
  29. default 1,000"
  30. MapAtlasFireDamageAndPacks  1   "Areas contain additional Monsters that deal Fire Damage
  31. Players and Monsters take 10% increased Fire Damage"    "no_monster_packs 0
  32. default 1,000"
  33. MapAtlasGroundHaste 1   Areas contain Slipstreams   default 1,000
  34. MapAtlasInstantFlasksAndHealingMonsters 1   "Life and Mana Recovery from Flasks are instant
  35. Areas contain additional Monsters that Heal"    default 1,000
  36. MapAtlasOnslaughtWhenHitAndOnslaughtEffect  1   "Players and Monsters have Onslaught if they have been Hit Recently
  37. 100% increased effect of Onslaught on Players and Monsters" "vaults_of_atziri 0
  38. default 1,000"
  39. MapAtlasColdDamageAndPacks  1   "Areas contain additional Monsters that deal Cold Damage
  40. Players and Monsters take 10% increased Cold Damage"    "no_monster_packs 0
  41. default 1,000"
  42. MapAtlasStrongboxMonstersEnrageAndDrops 1   "Strongbox Monsters have 500% increased Item Quantity
  43. Strongbox Monsters are Enraged
  44. Areas contain an extra Strongbox"   "hall_of_grandmasters 0
  45. no_strongboxes 0
  46. default 1,000"
  47. MapAtlasMagicPackSize   1   30% increased Magic Pack Size   "no_monster_packs 0
  48. default 1,000"
  49. MapAtlasBodyguardsAndBossMapDrops   1   "Unique Bosses are accompanied by Bodyguards
  50. An additional Map drops on Completing Areas"    "no_boss 0
  51. default 1,000"
  52. MapAtlasLightningDamageAndPacks 1   "Areas contain additional Monsters that deal Lightning Damage
  53. Players and Monsters take 10% increased Lightning Damage"   "no_monster_packs 0
  54. default 1,000"
  55. MapAtlasPoisonEffectsAndParasites   1   "Players deal 10% increased Damage for each Poison on them
  56. Players have 5% increased Movement Speed for each Poison on them
  57. Areas contain additional Poisonous Monsters"    default 1,000
  58. MapAtlasRogueExilesDamageAndDropAdditionalJewels    1   "Rogue Exiles deal 20% increased Damage
  59. Rogue Exiles have 20% increased Maximum Life
  60. Rogue Exiles drop 2 additional Jewels
  61. Areas are inhabited by 1 additional Rogue Exile"    "no_monster_packs 0
  62. default 1,000"
  63. MapAtlasCurseEffectOnPlayersAndMonsters 73  "20% reduced Effect of Curses on Monsters
  64. 60% reduced Effect of Curses on Players"    "vaults_of_atziri 0
  65. default 1,000"
  66. MapAtlasContainsZanaMission 73  Areas contain Zana  "unique_map 0
  67. default 200"
  68. MapAtlasMapQualityBonusAlsoAppliesToRarity  73  "Quality bonus of Maps also applies to Rarity of Items found
  69. Unique Bosses have 20% increased Life"  default 1,000
  70. MapAtlasStrongboxesAreCorruptedAndUnided    73  "Strongboxes in Areas are Corrupted
  71. Areas contain an extra Strongbox
  72. Strongboxes in Areas are at least Rare Rarity"  "no_strongboxes 0
  73. default 200"
  74. MapAtlasChaosDamageAndPacks_    73  "Areas contain additional Monsters that deal Chaos Damage
  75. Players and Monsters take 10% increased Chaos Damage"   "no_monster_packs 0
  76. default 1,000"
  77. MapAtlasUniqueMonstersDropCorruptedItems    73  Unique Monsters drop Corrupted Items    "vaults_of_atziri 0
  78. hall_of_grandmasters 0
  79. default 200"
  80. MapAtlasCorruptedMapBossesDropAdditionalVaalItems   78  "Unique Bosses of Corrupted Maps drop an additional Vaal Item
  81. Found Items have a 5% chance to drop Corrupted in Areas"    default 1,000
  82. MapAtlasBloodlinesDropAdditionalCurrency    78  Nemesis Monsters drop 3 additional Currency Items   "no_monster_packs 0
  83. default 200"
  84. MapAtlasFishy   78  Areas are Alluring  default 10`;
  85.  
  86. // tier "enum"
  87. var tier = {
  88.     WHITE: 1,
  89.   YELLOW: 73,
  90.   RED: 78,
  91. };
  92.  
  93. function getSextantCost(tier) {
  94.     switch ( tier ) {
  95.     case 1:
  96.         return 2.0; // 4 chaos
  97.     case 73:
  98.         return 4.0; // 5 chaos
  99.     case 78:
  100.         return 8.0; // 6 chaos
  101.   }
  102. }
  103.  
  104. var maxIterations = 500000;
  105.  
  106. var mapData = {
  107.     "Shaped Primordial Pool": {
  108.     tier: tier.YELLOW,
  109.     adjacent: [
  110.         "Cavern",
  111.       "Waste Pool",
  112.       "Phantasmagoria",
  113.       "Burial Chambers",
  114.     ]
  115.   },
  116.     "Canyon": {
  117.     tier: tier.YELLOW,
  118.     adjacent: [
  119.       "Waste Pool",
  120.     ]
  121.   },
  122.     "Vaal City": {
  123.     tier: tier.YELLOW,
  124.     adjacent: [
  125.         "Burial Chambers",
  126.         "Vaults of Atziri",
  127.         "Arachnid Tomb",
  128.         "Olmec's Sanctum",
  129.         "Shore",
  130.         "Catacombs",
  131.     ]
  132.   },
  133.     "Arachnid Tomb": {
  134.     tier: tier.YELLOW,
  135.     adjacent: [
  136.         "Vaults of Atziri",
  137.         "Shore",
  138.       "Vaal City",
  139.       "Vaal Pyramid",
  140.     ]
  141.   },
  142.     "Shore": {
  143.     tier: tier.YELLOW,
  144.     adjacent: [
  145.         "Arachnid Tomb",
  146.       "Vaal City",
  147.       "Catacombs",
  148.       "Olmec's Sanctum",
  149.     ]
  150.   },
  151.     "Catacombs": {
  152.     tier: tier.YELLOW,
  153.     adjacent: [
  154.       "Vaal City",
  155.       "Shore",
  156.       "Olmec's Sanctum",
  157.     ]
  158.   },
  159.     "Olmec's Sanctum": {
  160.     tier: tier.YELLOW,
  161.     adjacent: [
  162.       "Vaal City",
  163.       "Shore",
  164.       "Catacombs",
  165.     ]
  166.   },
  167.     "Vaal Pyramid": {
  168.     tier: tier.WHITE,
  169.     adjacent: [
  170.       "Phantasmagoria",
  171.       "Burial Chambers",
  172.       "Marshes",
  173.       "Vaults of Atziri",
  174.       "Arachnid Tomb",
  175.     ]
  176.   },
  177.     "Marshes": {
  178.     tier: tier.WHITE,
  179.     adjacent: [
  180.       "Phantasmagoria",
  181.       "Vaal Pyramid",
  182.     ]
  183.   },
  184.     "Phantasmagoria": {
  185.     tier: tier.WHITE,
  186.     adjacent: [
  187.       "Shaped Primordial Pool",
  188.       "Vaal Pyramid",
  189.       "Marshes",
  190.     ]
  191.   },
  192.     "Burial Chambers": {
  193.     tier: tier.WHITE,
  194.     adjacent: [
  195.       "Shaped Primordial Pool",
  196.       "Vaal Pyramid",
  197.       "Vaults of Atziri",
  198.       "Vaal City",
  199.     ]
  200.   },
  201.     "Cavern": {
  202.     tier: tier.WHITE,
  203.     adjacent: [
  204.       "Shaped Primordial Pool",
  205.       "Waste Pool",
  206.     ]
  207.   },
  208.     "Waste Pool": {
  209.     tier: tier.WHITE,
  210.     adjacent: [
  211.       "Shaped Primordial Pool",
  212.       "Cavern",
  213.       "Canyon",
  214.       "Channel",
  215.     ]
  216.   },
  217.     "Channel": {
  218.     tier: tier.WHITE,
  219.     adjacent: [
  220.       "Waste Pool",
  221.       "Acid Lakes",
  222.       "Mesa",
  223.       "Factory",
  224.     ]
  225.   },
  226.     "Vaults of Atziri": {
  227.     tier: tier.WHITE,
  228.     adjacent: [
  229.       "Burial Chambers",
  230.       "Vaal City",
  231.       "Arachnid Tomb",
  232.       "Vaal Pyramid",
  233.     ]
  234.   },
  235.     "Acid Lakes": {
  236.     tier: tier.WHITE,
  237.     adjacent: [
  238.       "Channel",
  239.       "Factory",
  240.     ]
  241.   },
  242.     "Mesa": {
  243.     tier: tier.WHITE,
  244.     adjacent: [
  245.       "Channel",
  246.     ]
  247.   },
  248.     "Factory": {
  249.     tier: tier.WHITE,
  250.     adjacent: [
  251.       "Channel",
  252.       "Acid Lakes",
  253.     ]
  254.   },
  255. };
  256.  
  257. var goodMods = {
  258.   "MapAtlasFireDamageAndPacks": true,
  259.   "MapAtlasColdDamageAndPacks": true,
  260.   "MapAtlasLightningDamageAndPacks": true,
  261.   "MapAtlasPhysicalDamageAndPacks_": true,
  262.   "MapAtlasChaosDamageAndPacks_": true,
  263.   "MapAtlasMontersThatConvertOnDeath__": true,
  264.   "MapAtlasInstantFlasksAndHealingMonsters": true,
  265.   "MapAtlasMagicAndRareMapsHaveAdditionalPacks": true,
  266.   "MapAtlasHighValueEnemiesOnOwnTeam": true,
  267.   "MapAtlasPoisonEffectsAndParasites": true,
  268.     "MapAtlasClustersOfBloodwormBarrels": true,
  269.   "MapAtlasClustersOfParasiteBarrels": true,
  270.   "MapAtlasClustersOfWealthyBarrels": true,
  271.   "MapAtlasClustersOfBeaconBarrels": true,
  272.   "MapAtlasClustersOfVolatileBarrels": true,
  273.   "MapAtlasMagicPackSize": true,
  274.   "MapAtlasUniqueMonstersDropCorruptedItems": true,
  275.   "MapAtlasBloodlinesDropAdditionalCurrency": true,
  276.   "MapAtlasReducedReflectedDamageTakenMirroredRares": true,
  277.   "MapAtlasStrongboxesAreCorruptedAndUnided": true,
  278.   "MapAtlasStrongboxMonstersEnrageAndDrops": true,
  279. }
  280.  
  281. var parsed = rawData.match( /.+\t.+\t[^\t]+\t[^\t]+\n/g );
  282.  
  283. for ( var i = 0; i < parsed.length; i++ ) {
  284.     var str = parsed[i];
  285.  
  286.   str = str.match( /[^\t]+/g );
  287.  
  288.   parsed[i] = {
  289.     name: str[0],
  290.     level: parseInt(str[1]),
  291.     mods: str[2].match( /[^\n"]+/g ),
  292.     weights: str[3].match( /[^\n"]+/g ),
  293.   }
  294.  
  295.   var weightsObj = {};
  296.  
  297.   for ( var j = 0; j < parsed[i].weights.length; j++ ) {
  298.     var r = parsed[i].weights[j].split( /\s/ );
  299.     weightsObj[r[0]] = parseInt( r[1].replace(",", "") );
  300.   }
  301.  
  302.   parsed[i].weights = weightsObj;
  303. }
  304.  
  305. var maps = {};
  306.  
  307. // Map prototype -------------------------------------------------
  308.  
  309. // constructor
  310.  
  311. function Map(name, tier, adj, activeMod) {
  312.     this.name = name;
  313.   this.tier = tier;
  314.   this.sextantCost = getSextantCost( this.tier );
  315.   //console.log( this.name + " sextant cost is " + this.sextantCost + "c.");
  316.   if ( activeMod ) {
  317.     for ( var mod in parsed ) {
  318.         if ( mod.name == activeMod ) {
  319.         this.mod = mod;
  320.         break;
  321.       }
  322.     }
  323.   }
  324.   this.adjacent = adj;
  325.  
  326.   maps[this.name] = this;
  327. }
  328.  
  329. Map.prototype.getBlockedMods = function( log ) {
  330.     if ( log ) { console.log("Blocked mods for " + this.name + ":"); }
  331.     var blocked = {};
  332.     for ( var i in this.adjacent ) {
  333.     if ( this.adjacent[i].mod ) {
  334.         if ( log ) { console.log(this.adjacent[i].name + " blocks " + this.adjacent[i].mod.name); }
  335.         blocked[this.adjacent[i].mod.name] = true;
  336.     }
  337.    
  338.     for ( var j in this.adjacent[i].adjacent ) {
  339.         if ( this.adjacent[i].adjacent[j].mod ) {
  340.             if ( log ) { console.log(this.adjacent[i].adjacent[j].name + " blocks " + this.adjacent[i].adjacent[j].mod.name); }
  341.             blocked[this.adjacent[i].adjacent[j].mod.name] = true;
  342.       }
  343.     }
  344.   }
  345.   return blocked;
  346. }
  347.  
  348. Map.prototype.getFilteredModList = function() {
  349.     var blocked = this.getBlockedMods();
  350.  
  351.     return parsed.filter( function(mod) {
  352.     if ( this.tier < mod.level || blocked[mod.name] || mod == this.mod ) {
  353.         return false;
  354.     }
  355.     return true;
  356.   } );
  357. }
  358.  
  359. Map.prototype.roll = function() {
  360.     var mods = this.getFilteredModList();
  361.    
  362.   var totalWeight = mods.reduce( function( acc, val ) {
  363.     return acc + val.weights.default;
  364.   }, 0);
  365.     var roll = Math.random() * totalWeight;
  366.   var sum = 0;
  367.  
  368.   for ( var mod in mods ) {
  369.     sum += mods[mod].weights.default;
  370.     if ( roll < sum ) {
  371.         this.mod = mods[mod];
  372.       //console.log("Applied '" + this.mod.name + "' to " + this.name + ".");
  373.       return this.sextantCost;
  374.     }
  375.   }
  376. }
  377.  
  378. Map.prototype.isAdjacentTo = function( name ) {
  379.   return Boolean( this.adjacent.find( map => map.name === name ) );
  380. }
  381.  
  382. // END Map prototype -------------------------------------------
  383.  
  384. // START atlas prototype ---------------------------------------
  385.  
  386. function Atlas( maps ) {
  387.     this.maps = maps;
  388.     this.savedMods = {};
  389.  
  390.     for ( var map in this.maps ) {
  391.     this.savedMods[this.maps[map].name] = this.maps[map].mod;
  392.   }
  393.  
  394.   //console.log(this.savedMods);
  395. }
  396.  
  397. Atlas.prototype.reset = function() {
  398.     for ( var map in this.savedMods ) {
  399.     this.maps[map].mod = this.savedMods[map];
  400.   }
  401. };
  402.  
  403. // END atlas prototype -----------------------------------------
  404.  
  405. // create map objects
  406.  
  407. for ( var map in mapData ) {
  408.     new Map( map, mapData[map].tier, mapData[map].adjacent, mapData[map].mod );
  409. }
  410.  
  411. // objectify adjacent arrays
  412.  
  413. for ( var k in maps ) {
  414.     var map = maps[k];
  415.  
  416.   map.adjacent = map.adjacent.map( function( element ) {
  417.     if ( ! maps[element] ) {
  418.         throw new Error( "Could not convert '" + element + "' to object" );
  419.     }
  420.     return maps[element];
  421.   } );
  422. }
  423.  
  424. // sanity check adjacents
  425.  
  426. for ( var k in maps ) {
  427.     var map = maps[k];
  428.  
  429.   map.adjacent.forEach( function( a ) {
  430.     if ( ! a.isAdjacentTo( map.name ) ) {
  431.         throw new Error( "1 sided adjacent relation: " + map.name + ", " + a.name );
  432.     }
  433.   } )
  434. }
  435.  
  436. // block mods
  437.  
  438. function applyBlockMod( originMap, currentMap ) {
  439.         if ( currentMap.name == "Shaped Primordial Pool" || currentMap.isAdjacentTo( "Shaped Primordial Pool" ) ) {
  440.         return;
  441.     }
  442.     if ( currentMap.mod ) {
  443.         return;
  444.     }
  445.  
  446.     // filter out good mods
  447.     // filter non-white mods
  448.     var mods = originMap.getFilteredModList().filter( function( mod ) {
  449.       return ! goodMods[ mod.name ];
  450.     }).filter( function( mod ) {
  451.       return mod.level == tier.WHITE;
  452.     });
  453.    
  454.     // sort by weight, descending
  455.     mods.sort( function(a, b) {
  456.       return b.weights.default - a.weights.default;
  457.     });
  458.    
  459.     currentMap.mod = mods[0];
  460.     console.log("Applied '" + currentMap.mod.name + "' to " + currentMap.name + ".");
  461. }
  462.  
  463. // First, apply sextants to maps 2 degrees away from Pool.
  464.  
  465. var m = maps["Shaped Primordial Pool"];
  466.  
  467. m.adjacent.forEach( function( map ) {
  468.     map.adjacent.forEach( function( map2 ) {
  469.     applyBlockMod( m, map2 );
  470.   });
  471. });
  472.  
  473. // Second, block sextants on Burial Chambers.
  474.  
  475. m = maps["Burial Chambers"];
  476.  
  477. m.adjacent.forEach( function( map ) {
  478.     map.adjacent.forEach( function( map2 ) {
  479.     applyBlockMod( m, map2 );
  480.   });
  481. });
  482.  
  483. for ( var m in maps ) {
  484.     var m = maps[m];
  485.  
  486.   if ( ! m.isAdjacentTo( "Shaped Primordial Pool" ) ) {
  487.     continue;
  488.   }
  489.  
  490.   // apply to adjacent maps
  491.  
  492.   for ( var i = 0; i < m.adjacent.length; i++ ) {
  493.     var c = m.adjacent[i];
  494.     applyBlockMod( m, c );
  495.   }
  496.  
  497.   // apply to 2nd degree adjacent maps
  498.  
  499.   for ( var i = 0; i < m.adjacent.length; i++ ) {
  500.     var proxy = m.adjacent[i];
  501.    
  502.     if ( proxy.name == "Shaped Primordial Pool" ) { continue; }
  503.    
  504.     for ( var j = 0; j < proxy.adjacent.length; j++ ) {
  505.       var c = proxy.adjacent[j];
  506.       applyBlockMod( m, c );
  507.     }
  508.   }
  509. }
  510.  
  511. // create atlas object and snapshot blocked mods
  512. var atl = new Atlas( maps );
  513.  
  514. // heaps permute --------------------------------------------
  515.  
  516. var swap = function (array, pos1, pos2) {
  517.   var temp = array[pos1];
  518.   array[pos1] = array[pos2];
  519.   array[pos2] = temp;
  520. };
  521.  
  522. var heapsPermute = function (array, output, n) {
  523.   n = n || array.length; // set n default to array.length
  524.   if (n === 1) {
  525.     output(array);
  526.   } else {
  527.     for (var i = 1; i <= n; i += 1) {
  528.       heapsPermute(array, output, n - 1);
  529.       if (n % 2) {
  530.         var j = 1;
  531.       } else {
  532.         var j = i;
  533.       }
  534.       swap(array, j - 1, n - 1); // -1 to account for javascript zero-indexing
  535.     }
  536.   }
  537. };
  538.  
  539. // END heaps permute -------------------------------------------
  540.  
  541. // START result prototype --------------------------------------
  542.  
  543. function result( order ) {
  544.     this.order = order;
  545.   this.sum_x = 0;
  546.   this.sum_x2 = 0;
  547.   this.n = 0;
  548. }
  549.  
  550. result.prototype.mean = function() {
  551.     return this.sum_x / this.n;
  552. }
  553.  
  554. result.prototype.stdDev = function() {
  555.     var mean = this.mean();
  556.     return Math.sqrt( this.sum_x2 / this.n - mean * mean );
  557. }
  558.  
  559. result.prototype.generateSamples = function( n ) {
  560.     // Apply sextants to maps
  561.   for ( var iter = 0; iter < n; iter++ ) {
  562.     atl.reset();
  563.     var cost = 0;
  564.    
  565.     // First, roll any mod on each map in order.
  566.     this.order.forEach( function( m ) {
  567.       if ( ! maps[m].mod ) {
  568.         cost += maps[m].roll();
  569.       }
  570.     } );
  571.    
  572.         // Second, finish rolling each map to a good mod, again respecting the order.
  573.     this.order.forEach( function( m ) {
  574.       // While no/bad sextant, keep rolling
  575.       while ( ! ( maps[m].mod && goodMods[maps[m].mod.name] ) ) {
  576.         cost += maps[m].roll();
  577.       }
  578.     } );
  579.    
  580.     this.sum_x += cost;
  581.     this.sum_x2 += cost * cost;
  582.     this.n++;
  583.   }
  584. }
  585.  
  586. result.prototype.confidenceInterval = function() {
  587.     return 1.645 * ( this.stdDev() / Math.sqrt( this.n ) );
  588. }
  589.  
  590. // END result prototype ------------------------------------------
  591.  
  592. function countKeys(a) {
  593.     var n = 0;
  594.     for ( var k in a ) {
  595.     n++;
  596.   }
  597.   return n;
  598. }
  599.  
  600. var results = [];
  601.  
  602. var mapsToRoll = [];
  603. for ( var map in maps ) {
  604.     if ( map == "Shaped Primordial Pool" || maps[map].isAdjacentTo( "Shaped Primordial Pool" ) ) {
  605.     console.log( map + " blocks " + countKeys(maps[map].getBlockedMods()) + " mods");
  606.     mapsToRoll.push(map);
  607.   }
  608. }
  609.  
  610. // create a result entry for every permutation
  611. heapsPermute(mapsToRoll, function( order ) {
  612.     /*if ( order[0] !== "Shaped Primordial Pool" ) {
  613.     return;
  614.   }*/
  615.  
  616.     results.push( new result( order.slice( 0 ) ) );
  617. } );
  618.  
  619. while ( true ) {
  620.     var results_b = results.filter( function( r ) {
  621.     if ( r == results[0] || results[0].n == 0 ) {
  622.         return true;
  623.     }
  624.     return r.mean() - r.confidenceInterval() <= results[0].mean() + results[0].confidenceInterval();
  625.   } );
  626.  
  627.   if ( results_b.length <= 1 || results_b[0].n >= maxIterations ) {
  628.     break;
  629.   }
  630.    
  631.   console.log( results[0].n + " iterations (" + results_b.length + " remaining permutations)" );
  632.  
  633.   var iterTarget = results[0].n + 5000 / Math.sqrt( results_b.length );
  634.  
  635.   results_b.forEach( function( r ) {
  636.     r.generateSamples( iterTarget - r.n );
  637.   } );
  638.  
  639.   results.sort( function( a, b ) {
  640.     return a.mean() - b.mean();
  641.   } );
  642. }
  643.  
  644. console.log( "Results (up to " + maxIterations + " iterations):" );
  645.  
  646. for ( var i = 0; i < results.length; i++ ) {
  647.   var str = "" + results[i].mean().toFixed(3) + " ± " + results[i].confidenceInterval().toFixed(3) + "c";
  648.  
  649.   for ( var j = 0; j < results[i].order.length; j++ ) {
  650.     if ( j > 0 ) { str += "," };
  651.     str += " " + results[i].order[j];
  652.   }
  653.  
  654.   console.log(str);
  655. }
Advertisement
Add Comment
Please, Sign In to add comment