Difference between revisions of "MediaWiki:SCalScript.js"

From Istaria Lexica

m (Too large code import)
Line 3: Line 3:
 
  * Elteria Shadowhand
 
  * Elteria Shadowhand
 
  */
 
  */
$(document).ready(function(){
+
$(document).ready(function() {
   if(document.getElementById('SCalMain')) {
+
   if (document.getElementById('SCalMain')) {
     let SCalBaseResources = [];
+
     let baseResources; // Collection of the needed base resources. To be filled.
     let initialCount = 10;
+
    let initialKeyCount = 1;
 +
    let maxKeyCount = 5000;
 +
    let maxSkillCount = 2000;
 +
     let skills = new Map();// a list of all skills needed.
  
     SCalPrintHeader();
+
     // let's add some relevant information.
 +
    // needed amounts default to optimum skills
 +
    let products = new Map();
 +
    products.set('Skeleton Key', { subs: new Map(), skill:'Tinkering', minCount: 1, maxCount: 1, minSkill: 1100, maxSkill: 1425, type: 'Product' });
 +
    products.get('Skeleton Key').subs
 +
      .set('Enchanted Adamantium-Mithril Bar', { subs: new Map(), skill:'Tinkering', minCount: 3, maxCount: 6, minSkill: 1100, maxSkill: 1425, type: 'Product' });
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .set('Gozar\'s Blessing', { subs: new Map(), skill:'Scribing', minCount: 2, maxCount: 4, minSkill: 1100, maxSkill: 1425, type: 'Product' });
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .set('Meltanis\' Prayer', { subs: new Map(), skill:'Spellcraft', minCount: 1, maxCount: 3, minSkill: 1100, maxSkill: 1425, type: 'Product' });
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Meltanis\' Prayer').subs
 +
            .set('Travertine Spell Shard', { subs: new Map(), skill:'Spellcraft', minCount: 1, maxCount: 5, minSkill: 1100, maxSkill: 1425, type: 'RefinedResource' });
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Meltanis\' Prayer').subs
 +
            .get('Travertine Spell Shard').subs
 +
              .set('Travertine Brick', { subs: new Map(), skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325, type: 'RefinedResource' });
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Meltanis\' Prayer').subs
 +
            .get('Travertine Spell Shard').subs
 +
              .get('Travertine Brick').subs
 +
                .set('Travertine Slab', { skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325 });
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Meltanis\' Prayer').subs
 +
            .set('Radiant Essence Orb', { subs: new Map(), skill:'Essence Shaping', minCount: 4, maxCount: 10, minSkill: 1000, maxSkill: 1325, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Meltanis\' Prayer').subs
 +
            .get('Radiant Essence Orb').subs
 +
              .set('Radiant Essence', { skill:'Essence Shaping', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .set('Primal Burst III', { subs: new Map(), skill:'Spellcraft', minCount: 1, maxCount: 3, minSkill: 930, maxSkill: 1130, type: 'Product'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Primal Burst III').subs
 +
            .set('Marble Spell Shard', { subs: new Map(), skill:'Spellcraft', minCount: 5, maxCount: 5, minSkill: 930, maxSkill: 1130, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Primal Burst III').subs
 +
            .get('Marble Spell Shard').subs
 +
              .set('Marble Brick', { subs: new Map(), skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Primal Burst III').subs
 +
            .get('Marble Spell Shard').subs
 +
              .get('Marble Brick').subs
 +
                .set('Marble Slab', { skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Primal Burst III').subs
 +
            .set('Shining Essence Orb', { subs: new Map(), skill:'Essence Shaping', minCount: 9, maxCount: 18, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Primal Burst III').subs
 +
            .get('Shining Essence Orb').subs
 +
              .set('Shining Essence', { skill:'Essence Shaping', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .set('Energy Strike V', { subs: new Map(), skill:'Spellcraft', minCount: 1, maxCount: 3, minSkill: 850, maxSkill: 1050, type: 'Product'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Energy Strike V').subs
 +
            .set('Marble Spell Shard', { subs: new Map(), skill:'Spellcraft', minCount: 4, maxCount: 4, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Energy Strike V').subs
 +
            .get('Marble Spell Shard').subs
 +
              .set('Marble Brick', { subs: new Map(), skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Energy Strike V').subs
 +
            .get('Marble Spell Shard').subs
 +
              .get('Marble Brick').subs
 +
                .set('Marble Slab', { skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Energy Strike V').subs
 +
            .set('Shining Essence Orb', { subs: new Map(), skill:'Essence Shaping', minCount: 7, maxCount: 14, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Energy Strike V').subs
 +
            .get('Shining Essence Orb').subs
 +
              .set('Shining Essence', { skill:'Essence Shaping', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .set('Ice Bomb V', { subs: new Map(), skill:'Spellcraft', minCount: 1, maxCount: 3, minSkill: 920, maxSkill: 1120, type: 'Product'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Ice Bomb V').subs
 +
            .set('Marble Spell Shard', { subs: new Map(), skill:'Spellcraft', minCount: 5, maxCount: 5, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Ice Bomb V').subs
 +
            .get('Marble Spell Shard').subs
 +
              .set('Marble Brick', { subs: new Map(), skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Ice Bomb V').subs
 +
            .get('Marble Spell Shard').subs
 +
              .get('Marble Brick').subs
 +
                .set('Marble Slab', { skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Ice Bomb V').subs
 +
            .set('Shining Essence Orb', { subs: new Map(), skill:'Essence Shaping', minCount: 9, maxCount: 18, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Ice Bomb V').subs
 +
            .get('Shining Essence Orb').subs
 +
              .set('Shining Essence', { skill:'Essence Shaping', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .set('Fiery Strike V', { subs: new Map(), skill:'Spellcraft', minCount: 1, maxCount: 3, minSkill: 980, maxSkill: 1180, type: 'Product'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Fiery Strike V').subs
 +
            .set('Marble Spell Shard', { subs: new Map(), skill:'Spellcraft', minCount: 6, maxCount: 6, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Fiery Strike V').subs
 +
            .get('Marble Spell Shard').subs
 +
              .set('Marble Brick', { subs: new Map(), skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Fiery Strike V').subs
 +
            .get('Marble Spell Shard').subs
 +
              .get('Marble Brick').subs
 +
                .set('Marble Slab', { skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Fiery Strike V').subs
 +
            .set('Shining Essence Orb', { subs: new Map(), skill:'Essence Shaping', minCount: 11, maxCount: 22, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Fiery Strike V').subs
 +
            .get('Shining Essence Orb').subs
 +
              .set('Shining Essence', { skill:'Essence Shaping', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .set('Gold Papyrus Sheet', { subs: new Map(), skill:'Papermaking', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Gozar\'s Blessing').subs
 +
          .get('Gold Papyrus Sheet').subs
 +
            .set('Gold Papyrus Stem', { skill:'Papermaking', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .set('Hardened Adamantium-Mithril Bar', { subs: new Map(), skill:'Tinkering', minCount: 2, maxCount: 5, minSkill: 1100, maxSkill: 1425, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Hardened Adamantium-Mithril Bar').subs
 +
          .set('Solution of Majorita', { subs: new Map(), skill:'Alchemy', minCount: 2, maxCount: 5, minSkill: 1100, maxSkill: 1425, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Hardened Adamantium-Mithril Bar').subs
 +
          .get('Solution of Majorita').subs
 +
            .set('Thornwood Bowl', { subs: new Map(), skill:'Alchemy', minCount: 1, maxCount: 3, minSkill: 1100, maxSkill: 1425, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Hardened Adamantium-Mithril Bar').subs
 +
          .get('Solution of Majorita').subs
 +
            .get('Thornwood Bowl').subs
 +
              .set('Thornwood Sap', { skill:'Papermaking', minCount: 3, maxCount: 6, minSkill: 1100, maxSkill: 1425});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Hardened Adamantium-Mithril Bar').subs
 +
          .get('Solution of Majorita').subs
 +
            .get('Thornwood Bowl').subs
 +
              .set('Thornwood Board', { subs: new Map(), skill:'Lumbering', minCount: 5, maxCount: 10, minSkill: 1000, maxSkill: 1325, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Hardened Adamantium-Mithril Bar').subs
 +
          .get('Solution of Majorita').subs
 +
            .get('Thornwood Bowl').subs
 +
              .get('Thornwood Board').subs
 +
                .set('Thornwood Log', { skill:'Lumbering', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Hardened Adamantium-Mithril Bar').subs
 +
          .get('Solution of Majorita').subs
 +
            .set('Crystallized Travertine Brick', { subs: new Map(), skill:'Stoneworking', minCount: 5, maxCount: 10, minSkill: 1000, maxSkill: 1325, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Hardened Adamantium-Mithril Bar').subs
 +
          .get('Solution of Majorita').subs
 +
            .get('Crystallized Travertine Brick').subs
 +
              .set('Unfocused Violet Azulyte Crystal', { skill:'Stoneworking', minCount: 1, maxCount: 5, minSkill: 1000, maxSkill: 1325});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Hardened Adamantium-Mithril Bar').subs
 +
          .get('Solution of Majorita').subs
 +
            .get('Crystallized Travertine Brick').subs
 +
              .set('Travertine Slab', { skill:'Stoneworking', minCount: 1, maxCount: 5, minSkill: 1000, maxSkill: 1325});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Hardened Adamantium-Mithril Bar').subs
 +
          .get('Solution of Majorita').subs
 +
            .set('Purified Radiant Essence Orb', { subs: new Map(), skill:'Enchanting', minCount: 1, maxCount: 4, minSkill: 1100, maxSkill: 1325, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Hardened Adamantium-Mithril Bar').subs
 +
          .get('Solution of Majorita').subs
 +
            .get('Purified Radiant Essence Orb').subs
 +
              .set('Radiant Essence Orb', { subs: new Map(), skill:'Essence Shaping', minCount: 1, maxCount: 4, minSkill: 1100, maxSkill: 1325, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Hardened Adamantium-Mithril Bar').subs
 +
          .get('Solution of Majorita').subs
 +
            .get('Purified Radiant Essence Orb').subs
 +
              .get('Radiant Essence Orb').subs
 +
                .set('Radiant Essence', { skill:'Essence Shaping', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Hardened Adamantium-Mithril Bar').subs
 +
          .get('Solution of Majorita').subs
 +
            .set('Water', { skill:'Alchemy', minCount: 15, maxCount: 30, minSkill: 1100, maxSkill: 1425});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Hardened Adamantium-Mithril Bar').subs
 +
          .set('Adamantium-Mithril Bar', { subs: new Map(), skill:'Smelting', minCount: 1, maxCount: 1, minSkill: 1100, maxSkill: 1425, type: 'RefinedResource'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Hardened Adamantium-Mithril Bar').subs
 +
          .get('Adamantium-Mithril Bar').subs
 +
            .set('Mithril Ore', { skill:'Smelting', minCount: 3, maxCount: 6, minSkill: 1100, maxSkill: 1425});
 +
    products.get('Skeleton Key').subs
 +
      .get('Enchanted Adamantium-Mithril Bar').subs
 +
        .get('Hardened Adamantium-Mithril Bar').subs
 +
          .get('Adamantium-Mithril Bar').subs
 +
            .set('Adamantium Ore', { skill:'Smelting', minCount: 3, maxCount: 6, minSkill: 1100, maxSkill: 1425});
 +
    products.get('Skeleton Key').subs
 +
      .set('Skeleton Key Mold', { subs: new Map(), skill:'Earthencraft', minCount: 1, maxCount: 1, minSkill: 1100, maxSkill: 1425, type: 'Product'});
 +
    products.get('Skeleton Key').subs
 +
      .get('Skeleton Key Mold').subs
 +
        .set('Skeleton Key Pattern', { skill:'Earthencraft', minCount: 1, maxCount: 1, minSkill: 1100, maxSkill: 1425});
 +
    products.get('Skeleton Key').subs
 +
      .get('Skeleton Key Mold').subs
 +
        .set('Porcelain Clay Chunk', { skill:'Earthencraft', minCount: 2, maxCount: 5, minSkill: 1100, maxSkill: 1425});
 +
 
 +
    printHeader();
  
 
     $('#SCalMain').append('<center><table>'
 
     $('#SCalMain').append('<center><table>'
        + '<tr valign="top">'
+
      + '<tr valign="top">'
          + '<td id="SCalResourcesrow1"></td>'
+
      + '<td id="SCalResourcesrow1"></td>'
          + '<td id="SCalResourcesrow2"></td>'
+
      + '<td id="SCalResourcesrow2"></td>'
        + '</tr>'
+
      + '</tr>'
 
       + '</table></center>'
 
       + '</table></center>'
 
     );
 
     );
  
 
     $('#SCalResourcesrow1').append('<div id="SCalResources"></div>');
 
     $('#SCalResourcesrow1').append('<div id="SCalResources"></div>');
   
 
    SCalCalculateNow();
 
    SCalPrintBaseResources();
 
   
 
    $('#SCalCountBtn').click(function(){
 
      SCalCalculateNow();
 
      SCalPrintBaseResources();
 
    });
 
   
 
    $('#SCalCountInput').keypress(function(event) {
 
      if(event.key === "Enter") {
 
        SCalCalculateNow();
 
        SCalPrintBaseResources();
 
      }
 
    });
 
  
     mw.loader.using( 'jquery.tablesorter', function() {
+
    printLists();
       $('table.sortable').tablesorter( {sortList: [ { 0: 'asc'} ]} )
+
 
 +
     mw.loader.using('jquery.tablesorter', function() {
 +
       $('table.sortable').tablesorter({ sortList: [{ 0: 'asc' }] })
 
     });
 
     });
   
 
    function SCalCalculateNow() {
 
      SCalValidate();
 
      var keyCount = $('#SCalCountInput').val();
 
      SCalBaseResources = [];
 
      $('#SCalResources').html('');
 
      $('#SCalResources').append('<h2><span id="mw-headline">Tree of needed products</span></h2>');
 
      $('#SCalResources').append('<ul>'
 
        + '<li>' + SCalPrintResource('Enchanted Adamantium-Mithril Bar',keyCount*3,false,'SCalMainResource')
 
          + '<ul>'
 
            + '<li>' + SCalPrintResource('Gozar\'s Blessing',keyCount*6,false,'SCalSubResource')
 
              + '<ul>'
 
                + '<li>' + SCalPrintResource('Meltanis\' Prayer',keyCount*6,false,'SCalSubResource')
 
                  + '<ul>'
 
                    + '<li>' + SCalPrintResource('Travertine Spell Shard',keyCount*6,false,'SCalBaseResource')
 
                      + '<ul>'
 
                        + '<li>' + SCalPrintResource('Travertine Brick',keyCount*12,false,'SCalBaseResource')
 
                          + '<ul>'
 
                            + '<li>' + SCalPrintResource('Travertine Slab',keyCount*24,true,'SCalBaseResource') + '</li>'
 
                          + '</ul>'
 
                        + '</li>'
 
                      + '</ul>'
 
                    + '</li>'
 
                    + '<li>' + SCalPrintResource('Radiant Essence Orb',keyCount*24,false,'SCalBaseResource')
 
                      + '<ul>'
 
                        + '<li>' + SCalPrintResource('Radiant Essence',keyCount*48,true,'SCalBaseResource') + '</li>'
 
                      + '</ul>'
 
                    + '</li>'
 
                  + '</ul>'
 
                + '</li>'
 
                + '<li>' + SCalPrintResource('Primal Burst III',keyCount*6,false,'SCalSubResource')
 
                  + '<ul>'
 
                    + '<li>' + SCalPrintResource('Marble Spell Shard',keyCount*30,false,'SCalBaseResource')
 
                      + '<ul>'
 
                        + '<li>' + SCalPrintResource('Marble Brick',keyCount*60,false,'SCalBaseResource')
 
                          + '<ul>'
 
                            + '<li>' + SCalPrintResource('Marble Slab',keyCount*120,true,'SCalBaseResource') + '</li>'
 
                          + '</ul>'
 
                        + '</li>'
 
                      + '</ul>'
 
                    + '</li>'
 
                    + '<li>' + SCalPrintResource('Shining Essence Orb',keyCount*54,false,'SCalBaseResource')
 
                      + '<ul>'
 
                        + '<li>' + SCalPrintResource('Shining Essence',keyCount*108,true,'SCalBaseResource') + '</li>'
 
                      + '</ul>'
 
                    + '</li>'
 
                  + '</ul>'
 
                + '</li>'
 
                + '<li>' + SCalPrintResource('Gold Papyrus Sheet',keyCount*12,false,'SCalSubResource')
 
                  + '<ul>'
 
                    + '<li>' + SCalPrintResource('Gold Papyrus Stem',keyCount*24,true,'SCalBaseResource') + '</li>'
 
                  + '</ul>'
 
                + '</li>'
 
                + '<li>' + SCalPrintResource('Energy Strike V',keyCount*6,false,'SCalSubResource')
 
                  + '<ul>'
 
                    + '<li>' + SCalPrintResource('Marble Spell Shard',keyCount*24,false,'SCalBaseResource')
 
                      + '<ul>'
 
                        + '<li>' + SCalPrintResource('Marble Brick',keyCount*48,false,'SCalBaseResource')
 
                          + '<ul>'
 
                            + '<li>' + SCalPrintResource('Marble Slab',keyCount*96,true,'SCalBaseResource') + '</li>'
 
                          + '</ul>'
 
                        + '</li>'
 
                      + '</ul>'
 
                    + '</li>'
 
                    + '<li>' + SCalPrintResource('Shining Essence Orb',keyCount*42,false,'SCalBaseResource')
 
                      + '<ul>'
 
                        + '<li>' + SCalPrintResource('Shining Essence',keyCount*84,true,'SCalBaseResource') + '</li>'
 
                      + '</ul>'
 
                    + '</li>'
 
                  + '</ul>'
 
                + '</li>'
 
                + '<li>' + SCalPrintResource('Ice Bomb V',keyCount*6,false,'SCalSubResource')
 
                  + '<ul>'
 
                    + '<li>' + SCalPrintResource('Marble Spell Shard',keyCount*30,false,'SCalBaseResource')
 
                      + '<ul>'
 
                        + '<li>' + SCalPrintResource('Marble Brick',keyCount*60,false,'SCalBaseResource')
 
                          + '<ul>'
 
                            + '<li>' + SCalPrintResource('Marble Slab',keyCount*120,true,'SCalBaseResource') + '</li>'
 
                          + '</ul>'
 
                        + '</li>'
 
                      + '</ul>'
 
                    + '</li>'
 
                    + '<li>' + SCalPrintResource('Shining Essence Orb',keyCount*64,false,'SCalBaseResource')
 
                      + '<ul>'
 
                        + '<li>' + SCalPrintResource('Shining Essence',keyCount*108,true,'SCalBaseResource') + '</li>'
 
                      + '</ul>'
 
                    + '</li>'
 
                  + '</ul>'
 
                + '</li>'
 
                + '<li>' + SCalPrintResource('Fiery Strike V',keyCount*6,false,'SCalSubResource')
 
                  + '<ul>'
 
                    + '<li>' + SCalPrintResource('Marble Spell Shard',keyCount*36,false,'SCalBaseResource')
 
                      + '<ul>'
 
                        + '<li>' + SCalPrintResource('Marble Brick',keyCount*72,false,'SCalBaseResource')
 
                          + '<ul>'
 
                            + '<li>' + SCalPrintResource('Marble Slab',keyCount*144,true,'SCalBaseResource') + '</li>'
 
                          + '</ul>'
 
                        + '</li>'
 
                      + '</ul>'
 
                    + '</li>'
 
                    + '<li>' + SCalPrintResource('Shining Essence Orb',keyCount*66,false,'SCalBaseResource')
 
                      + '<ul>'
 
                        + '<li>' + SCalPrintResource('Shining Essence',keyCount*132,true,'SCalBaseResource') + '</li>'
 
                      + '</ul>'
 
                    + '</li>'
 
                  + '</ul>'
 
                + '</li>'
 
              + '</ul>'
 
            + '</li>'
 
            + '<li>' + SCalPrintResource('Hardened Adamantium-Mithril Bar',keyCount*6,false,'SCalSubResource')
 
              + '<ul>'
 
                + '<li>' + SCalPrintResource('Solution of Majorita',keyCount*12,false,'SCalSubResource')
 
                  + '<ul>'
 
                    + '<li>' + SCalPrintResource('Thornwood Bowl',keyCount*12,false,'SCalBaseResource')
 
                      + '<ul>'
 
                        + '<li>' + SCalPrintResource('Thornwood Sap',keyCount*36,true,'SCalBaseResource')
 
                        + '<li>' + SCalPrintResource('Thornwood Board',keyCount*60,false,'SCalBaseResource')
 
                          + '<ul>'
 
                            + '<li>' + SCalPrintResource('Thornwood Log',keyCount*120,true,'SCalBaseResource') + '</li>'
 
                          + '</ul>'
 
                        + '</li>'
 
                      + '</ul>'
 
                    + '</li>'
 
                    + '<li>' + SCalPrintResource('Crystallized Travertine Brick',keyCount*60,false,'SCalBaseResource')
 
                      + '<ul>'
 
                        + '<li>' + SCalPrintResource('Unfocused Violet Azulyte Crystal',keyCount*60,true,'SCalBaseResource') + '</li>'
 
                        + '<li>' + SCalPrintResource('Travertine Slab',keyCount*60,true,'SCalBaseResource') + '</li>'
 
                      + '</ul>'
 
                    + '<li>' + SCalPrintResource('Purified Radiant Essence Orb',keyCount*12, false,'SCalBaseResource')
 
                      + '<ul>'
 
                        + '<li>' + SCalPrintResource('Radiant Essence Orb',keyCount*12, false,'SCalBaseResource')
 
                          + '<ul>'
 
                            + '<li>' + SCalPrintResource('Radiant Essence',keyCount*24, true,'SCalBaseResource') + '</li>'
 
                          + '</ul>'
 
                        + '</li>'
 
                      + '</ul>'
 
                    + '<li>' + SCalPrintResource('Water',keyCount*180, true) + '</li>'
 
                  + '</ul>'
 
                + '<li>' + SCalPrintResource('Adamantium-Mithril Bar',keyCount*6, false,'SCalBaseResource')
 
                  + '<ul>'
 
                    + '<li>' + SCalPrintResource('Mithril Ore',keyCount*18, true,'SCalBaseResource') + '</li>'
 
                    + '<li>' + SCalPrintResource('Adamantium Ore',keyCount*18, true,'SCalBaseResource') + '</li>'
 
                  + '</ul>'
 
                + '</li>'
 
              + '</ul>'
 
            + '</li>'
 
          + '</ul>'
 
        + '</li>'
 
        + '<li>' + SCalPrintResource('Skeleton Key Mold',keyCount*1,false,'SCalMainResource')
 
          + '<ul>'
 
            + '<li>' + SCalPrintResource('Skeleton Key Pattern',keyCount*1, true,'SCalBaseResource') + '</li>'
 
            + '<li>' + SCalPrintResource('Porcelain Clay Chunk',keyCount*2, true,'SCalBaseResource') + '</li>'
 
          + '</ul>'
 
        + '</li>'
 
      + '</ul>');
 
    }
 
  
     function SCalPrintHeader(){
+
    //FUNCTIONS:
 +
     function printHeader() {
 
       $('#SCalMain').append('<h1 id="SCalH1">The Calculator</h1>');
 
       $('#SCalMain').append('<h1 id="SCalH1">The Calculator</h1>');
 
       $('#SCalMain').append('<center><label for="SCalCountInput" id="SCalCountInputLbl">How much Skeleton Keys would you want to create?</label></center>');
 
       $('#SCalMain').append('<center><label for="SCalCountInput" id="SCalCountInputLbl">How much Skeleton Keys would you want to create?</label></center>');
       $('#SCalMain').append('<center><input type="number" id="SCalCountInput" name="SCalCountInput" value="' + initialCount + '" size="6"><input type="button" id="SCalCountBtn" value="Calculate now!"></center>');
+
       $('#SCalMain').append('<center><input type="number" id="SCalCountInput" name="SCalCountInput" value="' + initialKeyCount + '" size="6"></center>');
 +
      $('#SCalMain').append('<br />');
 +
      $('#SCalMain').append('<hr />');
 +
      $('#SCalMain').append('<center>Please enter your current skills in the fields below. Defaults to optimal skills.</center>');
 +
      $('#SCalMain').append('<center><input type="button" id="SCalMaxSkillsBtn" value="Reset to optimal skills"></center>');
 +
      $('#SCalMain').append('<center><input type="button" id="SCalMinSkillsBtn" value="Reset to minimal skills"></center>');
 +
      $('#SCalMain').append('<center><div id="SCalSkills" style="column-count:3; width:fit-content; text-align:left"></div></center>');
 +
      $('#SCalMain').append('<br />');
 +
      $('#SCalMain').append('<center><input type="button" id="SCalCountBtn" value="Calculate now!"></center>');
 
       $('#SCalMain').append('<div id="SCalErrorText"></div>');
 
       $('#SCalMain').append('<div id="SCalErrorText"></div>');
       $('#SCalMain').append('<br />');
+
       $('#SCalMain').append('<hr />');
       $('#SCalMain').append('<br /></center>');
+
 
     };
+
      $('#SCalMaxSkillsBtn').click(function() {
 +
        for (var v of skills.values()) {
 +
          $('#SCalSkill' + v + 'Input').val(maxSkillCount);
 +
        };
 +
      });
 +
 
 +
      $('#SCalCountBtn').click(function() {
 +
        printLists();
 +
      });
 +
 
 +
      $('#SCalCountInput').keypress(function(event) {
 +
        if (event.key === 'Enter') printLists();
 +
      });
 +
 
 +
      printSkillInputs();
 +
    }
 +
 
 +
    function printLists() {
 +
      baseResources = new Map();
 +
     
 +
      if(validateInputs()) { // check if the input fields contain valid entries
 +
        
 +
        $('#SCalResources').html('');
 +
        $('#SCalResources').append('<h2>Tree of needed products</h2>');
 +
        products = recursiveCalculateNeedEffectives(products, parseInt($('#SCalCountInput').val()));
 +
        var html = recursivePrintTreeProduct(products);
 +
        $('#SCalResources').append(html);
 +
 
 +
        printBaseResources();
 +
      }
 +
    }
 +
 
 +
    function printSkillInputs() {
 +
      recursiveDetermineSkills(products);
 +
      for (var [key, value] of skills.entries()) {
 +
        $('#SCalSkills').append('<input type="number" id="SCalSkill' + value + 'Input" name="SCalSkill' + value + '" value="' + maxSkillCount + '" size="6"><label for="SCalSkill' + value + '">&nbsp;&nbsp;' + key + '</label><br />');
 +
        $('#SCalSkill' + value + 'Input').keypress(function(event) {
 +
          if (event.key === 'Enter') printLists();
 +
        });
 +
      }
 +
     }
 +
 
 +
    function recursiveDetermineSkills(product) {
 +
      product.forEach((obj) => {
 +
        if(typeof obj.skill != 'undefined') {
 +
          skills.set(obj.skill, obj.skill.replace(/\s/, ''));
 +
        }
 +
       
 +
        if(obj.subs instanceof Map) {
 +
          recursiveDetermineSkills(obj.subs);
 +
        }
 +
      });
 +
    }
 
      
 
      
     function SCalPrintResource(name, count, isbaseresource, cssclass){
+
     function recursivePrintTreeProduct(product) {
       if(isbaseresource) {
+
       var html = '';
         objIndex = SCalBaseResources.findIndex((obj => obj.name == name));
+
      product.forEach((obj, value) => {
         if(objIndex == -1) {
+
         html += '<ul>';
           SCalBaseResources.push({
+
        html += '<li>';
            'name' : name,
+
        html += value + ': ' + obj.neededCount;
            'count' : count
+
        if(obj.subs instanceof Map) {
          });
+
          html += recursivePrintTreeProduct(obj.subs);
 +
        }
 +
        html += '</ul>';
 +
        html += '</li>'
 +
      });
 +
      return html;
 +
    }
 +
 
 +
    function recursiveCalculateNeedEffectives(product, previousCount) {
 +
      product.forEach((value,key) => {
 +
        var currentSkill;
 +
         if(typeof value.skill != 'undefined') { // if we found a skill, use the value of the input field
 +
           currentSkill = $('#SCalSkill' + skills.get(value.skill) + 'Input').val();
 
         } else {
 
         } else {
           SCalBaseResources[objIndex].count += count;
+
           currentSkill = maxSkillCount;
 
         }
 
         }
      }
+
        var percent = (currentSkill - value.minSkill) / (value.maxSkill - value.minSkill);
      return '<span class="' + cssclass + '"><a href="' + mw.util.getUrl(name) + '">' + name + '</a>: ' + count + '</span>';
+
        var needEffective = value.maxCount - ((value.maxCount - value.minCount) * percent);
     };
+
        needEffective = Math.ceil(needEffective);
 +
 
 +
        if (needEffective < value.minCount) needEffective = value.minCount;
 +
        if (needEffective > value.maxCount) needEffective = value.maxCount;
 +
       
 +
        value.neededCount = needEffective * previousCount;
 +
 
 +
        if(!(value.subs instanceof Map)) { // we assume that a product without subs is a base resource
 +
          if(baseResources.has(key)) {
 +
            baseResources.set(key, value.neededCount + baseResources.get(key));
 +
          } else {
 +
            baseResources.set(key, value.neededCount);
 +
          }
 +
        }
 +
 
 +
        if(value.subs instanceof Map) {
 +
          recursiveCalculateNeedEffectives(value.subs, value.neededCount);
 +
        }
 +
      });
 +
 
 +
      return product;
 +
     }
 +
 
 +
    function printBaseResources() {
 +
      baseResources = new Map([...baseResources.entries()].sort());
  
    function SCalPrintBaseResources() {
 
      SCalBaseResources.sort(SCalCompare('name'))
 
 
       $('#SCalResourcesrow2').html('');
 
       $('#SCalResourcesrow2').html('');
 
       $('#SCalResourcesrow2').append('<h2><span id="mw-headline">Overview of base resources</span></h2>');
 
       $('#SCalResourcesrow2').append('<h2><span id="mw-headline">Overview of base resources</span></h2>');
 
       $('#SCalResourcesrow2').append('<table id="SCalBaseResourceTable" class="wikitable sortable"><thead>'
 
       $('#SCalResourcesrow2').append('<table id="SCalBaseResourceTable" class="wikitable sortable"><thead>'
 
         + '<tr>'
 
         + '<tr>'
          + '<th align="left">Resource</th>'
+
        + '<th align="left">Resource</th>'
          + '<th align="left">Need</th>'
+
        + '<th align="left">Need</th>'
 
         + '</tr></thead>'
 
         + '</tr></thead>'
 
       );
 
       );
     
+
 
 
       var tablecontent = '<tbody>';
 
       var tablecontent = '<tbody>';
  
       for(var index in SCalBaseResources) {
+
       baseResources.forEach(function(value, key) {
 
         tablecontent += '<tr>'
 
         tablecontent += '<tr>'
            + '<td><a href="' + mw.util.getUrl(SCalBaseResources[index].name) + '">' + SCalBaseResources[index].name + '</a></td>'
+
          + '<td><a href="' + mw.util.getUrl(key) + '">' + key + '</a></td>'
            + '<td>' + SCalBaseResources[index].count + '</td>'
+
          + '<td>' + value + '</td>'
            + '</tr>';
+
          + '</tr>';
       }
+
       });
  
 
       tablecontent += '</tbody)';
 
       tablecontent += '</tbody)';
Line 244: Line 450:
 
     }
 
     }
  
     function SCalCompare(prop) {  
+
     function validateInputs() {
        return function(a, b) {   
+
      var ready = true;
            if (a[prop] > b[prop]) {   
+
      //reset the error textfield
                return 1;   
+
      $('#SCalErrorText').html('');
            } else if (a[prop] < b[prop]) {   
+
 
                return -1;  
+
      // check the keycounter value
            }
+
      $('#SCalCountInput').removeClass('SCalErroreousInput');
            return 0;   
 
        }   
 
    }
 
   
 
    function SCalValidate() {
 
 
       var value = $('#SCalCountInput').val();
 
       var value = $('#SCalCountInput').val();
      $('#SCalErrorText').html('&nbsp;');
+
       if (!(!isNaN(value) &&
       if(!(!isNaN(value) &&  
+
        parseInt(Number(value)) == value &&
            parseInt(Number(value)) == value &&  
+
        !isNaN(parseInt(value, 10)))) {
            !isNaN(parseInt(value, 10)))) {
+
         $('#SCalErrorText').append('<center>Amount of keys: this was not a number!</center>');
         $('#SCalErrorText').html('<center>This was not a number! I\'ve reset the counter to ' + initialCount + ' for you.</center>');
+
         $('#SCalCountInput').addClass('SCalErroreousInput');
         $('#SCalCountInput').val(initialCount);
+
        ready = false;
 
       } else {
 
       } else {
         if(value < 1 || value > 5000) {
+
         if (value < 1 || value > maxKeyCount) {
           $('#SCalErrorText').html('<center>Please provide a number between 1 and 5000</center>');
+
           $('#SCalErrorText').append('<center>Amount of keys: please provide a number between 1 and ' + maxKeyCount + '</center>');
           $('#SCalCountInput').val(initialCount);
+
           $('#SCalCountInput').addClass('SCalErroreousInput');
 +
          ready = false;
 +
        }
 +
      }
 +
 
 +
      //check the skills counters
 +
      for (var [skill, id] of skills) {
 +
        $('#SCalSkill' + id + 'Input').removeClass('SCalErroreousInput');
 +
        number = $('#SCalSkill' + id + 'Input').val();
 +
 
 +
        if (!(!isNaN(number) &&
 +
          parseInt(Number(number)) == number &&
 +
          !isNaN(parseInt(number, 10)))) {
 +
          $('#SCalErrorText').append('<center>' + skill + ': this was not a number!</center>');
 +
          $('#SCalSkill' + id + 'Input').addClass('SCalErroreousInput');
 +
          ready = false;
 +
        } else {
 +
          if (number < 1 || number > maxSkillCount) {
 +
            $('#SCalErrorText').append('<center>' + skill + ': please provide a number between 1 and ' + maxSkillCount + '</center>');
 +
            $('#SCalSkill' + id + 'Input').addClass('SCalErroreousInput');
 +
            ready = false;
 +
          }
 
         }
 
         }
 
       }
 
       }
 +
      return ready;
 
     }
 
     }
 
   }
 
   }
 
});
 
});

Revision as of 03:15, 19 June 2022

/**
 * Skeleton Key Calculator V 0.1
 * Elteria Shadowhand
 */
$(document).ready(function() {
  if (document.getElementById('SCalMain')) {
    let baseResources; // Collection of the needed base resources. To be filled.
    let initialKeyCount = 1;
    let maxKeyCount = 5000;
    let maxSkillCount = 2000;
    let skills = new Map();// a list of all skills needed.

    // let's add some relevant information.
    // needed amounts default to optimum skills
    let products = new Map(); 
    products.set('Skeleton Key', { subs: new Map(), skill:'Tinkering', minCount: 1, maxCount: 1, minSkill: 1100, maxSkill: 1425, type: 'Product' });
    products.get('Skeleton Key').subs
      .set('Enchanted Adamantium-Mithril Bar', { subs: new Map(), skill:'Tinkering', minCount: 3, maxCount: 6, minSkill: 1100, maxSkill: 1425, type: 'Product' });
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .set('Gozar\'s Blessing', { subs: new Map(), skill:'Scribing', minCount: 2, maxCount: 4, minSkill: 1100, maxSkill: 1425, type: 'Product' });
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .set('Meltanis\' Prayer', { subs: new Map(), skill:'Spellcraft', minCount: 1, maxCount: 3, minSkill: 1100, maxSkill: 1425, type: 'Product' });
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Meltanis\' Prayer').subs
            .set('Travertine Spell Shard', { subs: new Map(), skill:'Spellcraft', minCount: 1, maxCount: 5, minSkill: 1100, maxSkill: 1425, type: 'RefinedResource' });
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Meltanis\' Prayer').subs
            .get('Travertine Spell Shard').subs
              .set('Travertine Brick', { subs: new Map(), skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325, type: 'RefinedResource' });
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Meltanis\' Prayer').subs
            .get('Travertine Spell Shard').subs
              .get('Travertine Brick').subs
                .set('Travertine Slab', { skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325 });
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Meltanis\' Prayer').subs
            .set('Radiant Essence Orb', { subs: new Map(), skill:'Essence Shaping', minCount: 4, maxCount: 10, minSkill: 1000, maxSkill: 1325, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Meltanis\' Prayer').subs
            .get('Radiant Essence Orb').subs
              .set('Radiant Essence', { skill:'Essence Shaping', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .set('Primal Burst III', { subs: new Map(), skill:'Spellcraft', minCount: 1, maxCount: 3, minSkill: 930, maxSkill: 1130, type: 'Product'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Primal Burst III').subs
            .set('Marble Spell Shard', { subs: new Map(), skill:'Spellcraft', minCount: 5, maxCount: 5, minSkill: 930, maxSkill: 1130, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Primal Burst III').subs
            .get('Marble Spell Shard').subs
              .set('Marble Brick', { subs: new Map(), skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Primal Burst III').subs
            .get('Marble Spell Shard').subs
              .get('Marble Brick').subs
                .set('Marble Slab', { skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Primal Burst III').subs
            .set('Shining Essence Orb', { subs: new Map(), skill:'Essence Shaping', minCount: 9, maxCount: 18, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Primal Burst III').subs
            .get('Shining Essence Orb').subs
              .set('Shining Essence', { skill:'Essence Shaping', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .set('Energy Strike V', { subs: new Map(), skill:'Spellcraft', minCount: 1, maxCount: 3, minSkill: 850, maxSkill: 1050, type: 'Product'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Energy Strike V').subs
            .set('Marble Spell Shard', { subs: new Map(), skill:'Spellcraft', minCount: 4, maxCount: 4, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Energy Strike V').subs
            .get('Marble Spell Shard').subs
              .set('Marble Brick', { subs: new Map(), skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Energy Strike V').subs
            .get('Marble Spell Shard').subs
              .get('Marble Brick').subs
                .set('Marble Slab', { skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Energy Strike V').subs
            .set('Shining Essence Orb', { subs: new Map(), skill:'Essence Shaping', minCount: 7, maxCount: 14, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Energy Strike V').subs
            .get('Shining Essence Orb').subs
              .set('Shining Essence', { skill:'Essence Shaping', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .set('Ice Bomb V', { subs: new Map(), skill:'Spellcraft', minCount: 1, maxCount: 3, minSkill: 920, maxSkill: 1120, type: 'Product'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Ice Bomb V').subs
            .set('Marble Spell Shard', { subs: new Map(), skill:'Spellcraft', minCount: 5, maxCount: 5, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Ice Bomb V').subs
            .get('Marble Spell Shard').subs
              .set('Marble Brick', { subs: new Map(), skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Ice Bomb V').subs
            .get('Marble Spell Shard').subs
              .get('Marble Brick').subs
                .set('Marble Slab', { skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Ice Bomb V').subs
            .set('Shining Essence Orb', { subs: new Map(), skill:'Essence Shaping', minCount: 9, maxCount: 18, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Ice Bomb V').subs
            .get('Shining Essence Orb').subs
              .set('Shining Essence', { skill:'Essence Shaping', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .set('Fiery Strike V', { subs: new Map(), skill:'Spellcraft', minCount: 1, maxCount: 3, minSkill: 980, maxSkill: 1180, type: 'Product'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Fiery Strike V').subs
            .set('Marble Spell Shard', { subs: new Map(), skill:'Spellcraft', minCount: 6, maxCount: 6, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Fiery Strike V').subs
            .get('Marble Spell Shard').subs
              .set('Marble Brick', { subs: new Map(), skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Fiery Strike V').subs
            .get('Marble Spell Shard').subs
              .get('Marble Brick').subs
                .set('Marble Slab', { skill:'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Fiery Strike V').subs
            .set('Shining Essence Orb', { subs: new Map(), skill:'Essence Shaping', minCount: 11, maxCount: 22, minSkill: 800, maxSkill: 1100, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Fiery Strike V').subs
            .get('Shining Essence Orb').subs
              .set('Shining Essence', { skill:'Essence Shaping', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .set('Gold Papyrus Sheet', { subs: new Map(), skill:'Papermaking', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Gozar\'s Blessing').subs
          .get('Gold Papyrus Sheet').subs
            .set('Gold Papyrus Stem', { skill:'Papermaking', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .set('Hardened Adamantium-Mithril Bar', { subs: new Map(), skill:'Tinkering', minCount: 2, maxCount: 5, minSkill: 1100, maxSkill: 1425, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Hardened Adamantium-Mithril Bar').subs
          .set('Solution of Majorita', { subs: new Map(), skill:'Alchemy', minCount: 2, maxCount: 5, minSkill: 1100, maxSkill: 1425, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Hardened Adamantium-Mithril Bar').subs
          .get('Solution of Majorita').subs
            .set('Thornwood Bowl', { subs: new Map(), skill:'Alchemy', minCount: 1, maxCount: 3, minSkill: 1100, maxSkill: 1425, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Hardened Adamantium-Mithril Bar').subs
          .get('Solution of Majorita').subs
            .get('Thornwood Bowl').subs
              .set('Thornwood Sap', { skill:'Papermaking', minCount: 3, maxCount: 6, minSkill: 1100, maxSkill: 1425});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Hardened Adamantium-Mithril Bar').subs
          .get('Solution of Majorita').subs
            .get('Thornwood Bowl').subs
              .set('Thornwood Board', { subs: new Map(), skill:'Lumbering', minCount: 5, maxCount: 10, minSkill: 1000, maxSkill: 1325, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Hardened Adamantium-Mithril Bar').subs
          .get('Solution of Majorita').subs
            .get('Thornwood Bowl').subs
              .get('Thornwood Board').subs
                .set('Thornwood Log', { skill:'Lumbering', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Hardened Adamantium-Mithril Bar').subs
          .get('Solution of Majorita').subs
            .set('Crystallized Travertine Brick', { subs: new Map(), skill:'Stoneworking', minCount: 5, maxCount: 10, minSkill: 1000, maxSkill: 1325, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Hardened Adamantium-Mithril Bar').subs
          .get('Solution of Majorita').subs
            .get('Crystallized Travertine Brick').subs
              .set('Unfocused Violet Azulyte Crystal', { skill:'Stoneworking', minCount: 1, maxCount: 5, minSkill: 1000, maxSkill: 1325});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Hardened Adamantium-Mithril Bar').subs
          .get('Solution of Majorita').subs
            .get('Crystallized Travertine Brick').subs
              .set('Travertine Slab', { skill:'Stoneworking', minCount: 1, maxCount: 5, minSkill: 1000, maxSkill: 1325});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Hardened Adamantium-Mithril Bar').subs
          .get('Solution of Majorita').subs
            .set('Purified Radiant Essence Orb', { subs: new Map(), skill:'Enchanting', minCount: 1, maxCount: 4, minSkill: 1100, maxSkill: 1325, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Hardened Adamantium-Mithril Bar').subs
          .get('Solution of Majorita').subs
            .get('Purified Radiant Essence Orb').subs
              .set('Radiant Essence Orb', { subs: new Map(), skill:'Essence Shaping', minCount: 1, maxCount: 4, minSkill: 1100, maxSkill: 1325, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Hardened Adamantium-Mithril Bar').subs
          .get('Solution of Majorita').subs
            .get('Purified Radiant Essence Orb').subs
              .get('Radiant Essence Orb').subs
                .set('Radiant Essence', { skill:'Essence Shaping', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Hardened Adamantium-Mithril Bar').subs
          .get('Solution of Majorita').subs
            .set('Water', { skill:'Alchemy', minCount: 15, maxCount: 30, minSkill: 1100, maxSkill: 1425});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Hardened Adamantium-Mithril Bar').subs
          .set('Adamantium-Mithril Bar', { subs: new Map(), skill:'Smelting', minCount: 1, maxCount: 1, minSkill: 1100, maxSkill: 1425, type: 'RefinedResource'});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Hardened Adamantium-Mithril Bar').subs
          .get('Adamantium-Mithril Bar').subs
            .set('Mithril Ore', { skill:'Smelting', minCount: 3, maxCount: 6, minSkill: 1100, maxSkill: 1425});
    products.get('Skeleton Key').subs
      .get('Enchanted Adamantium-Mithril Bar').subs
        .get('Hardened Adamantium-Mithril Bar').subs
          .get('Adamantium-Mithril Bar').subs
            .set('Adamantium Ore', { skill:'Smelting', minCount: 3, maxCount: 6, minSkill: 1100, maxSkill: 1425});
    products.get('Skeleton Key').subs
      .set('Skeleton Key Mold', { subs: new Map(), skill:'Earthencraft', minCount: 1, maxCount: 1, minSkill: 1100, maxSkill: 1425, type: 'Product'});
    products.get('Skeleton Key').subs
      .get('Skeleton Key Mold').subs
        .set('Skeleton Key Pattern', { skill:'Earthencraft', minCount: 1, maxCount: 1, minSkill: 1100, maxSkill: 1425});
    products.get('Skeleton Key').subs
      .get('Skeleton Key Mold').subs
        .set('Porcelain Clay Chunk', { skill:'Earthencraft', minCount: 2, maxCount: 5, minSkill: 1100, maxSkill: 1425});

    printHeader();

    $('#SCalMain').append('<center><table>'
      + '<tr valign="top">'
      + '<td id="SCalResourcesrow1"></td>'
      + '<td id="SCalResourcesrow2"></td>'
      + '</tr>'
      + '</table></center>'
    );

    $('#SCalResourcesrow1').append('<div id="SCalResources"></div>');

    printLists();

    mw.loader.using('jquery.tablesorter', function() {
      $('table.sortable').tablesorter({ sortList: [{ 0: 'asc' }] })
    });

    //FUNCTIONS:
    function printHeader() {
      $('#SCalMain').append('<h1 id="SCalH1">The Calculator</h1>');
      $('#SCalMain').append('<center><label for="SCalCountInput" id="SCalCountInputLbl">How much Skeleton Keys would you want to create?</label></center>');
      $('#SCalMain').append('<center><input type="number" id="SCalCountInput" name="SCalCountInput" value="' + initialKeyCount + '" size="6"></center>');
      $('#SCalMain').append('<br />');
      $('#SCalMain').append('<hr />');
      $('#SCalMain').append('<center>Please enter your current skills in the fields below. Defaults to optimal skills.</center>');
      $('#SCalMain').append('<center><input type="button" id="SCalMaxSkillsBtn" value="Reset to optimal skills"></center>');
      $('#SCalMain').append('<center><input type="button" id="SCalMinSkillsBtn" value="Reset to minimal skills"></center>');
      $('#SCalMain').append('<center><div id="SCalSkills" style="column-count:3; width:fit-content; text-align:left"></div></center>');
      $('#SCalMain').append('<br />');
      $('#SCalMain').append('<center><input type="button" id="SCalCountBtn" value="Calculate now!"></center>');
      $('#SCalMain').append('<div id="SCalErrorText"></div>');
      $('#SCalMain').append('<hr />');

      $('#SCalMaxSkillsBtn').click(function() {
        for (var v of skills.values()) {
          $('#SCalSkill' + v + 'Input').val(maxSkillCount);
        };
      });

      $('#SCalCountBtn').click(function() {
        printLists();
      });

      $('#SCalCountInput').keypress(function(event) {
        if (event.key === 'Enter') printLists();
      });

      printSkillInputs();
    }

    function printLists() {
      baseResources = new Map();
      
      if(validateInputs()) { // check if the input fields contain valid entries
      
        $('#SCalResources').html('');
        $('#SCalResources').append('<h2>Tree of needed products</h2>');
        products = recursiveCalculateNeedEffectives(products, parseInt($('#SCalCountInput').val()));
        var html = recursivePrintTreeProduct(products);
        $('#SCalResources').append(html);
  
        printBaseResources();
      }
    }

    function printSkillInputs() {
      recursiveDetermineSkills(products);
      for (var [key, value] of skills.entries()) {
        $('#SCalSkills').append('<input type="number" id="SCalSkill' + value + 'Input" name="SCalSkill' + value + '" value="' + maxSkillCount + '" size="6"><label for="SCalSkill' + value + '">&nbsp;&nbsp;' + key + '</label><br />');
        $('#SCalSkill' + value + 'Input').keypress(function(event) {
          if (event.key === 'Enter') printLists();
        });
      }
    }

    function recursiveDetermineSkills(product) {
      product.forEach((obj) => {
        if(typeof obj.skill != 'undefined') {
          skills.set(obj.skill, obj.skill.replace(/\s/, ''));
        }
        
        if(obj.subs instanceof Map) {
          recursiveDetermineSkills(obj.subs);
        }
      }); 
    }
    
    function recursivePrintTreeProduct(product) {
      var html = '';
      product.forEach((obj, value) => {
        html += '<ul>';
        html += '<li>';
        html += value + ': ' + obj.neededCount;
        if(obj.subs instanceof Map) {
          html += recursivePrintTreeProduct(obj.subs);
        }
        html += '</ul>';
        html += '</li>'
      });
      return html;
    }

    function recursiveCalculateNeedEffectives(product, previousCount) {
      product.forEach((value,key) => {
        var currentSkill;
        if(typeof value.skill != 'undefined') { // if we found a skill, use the value of the input field
          currentSkill = $('#SCalSkill' + skills.get(value.skill) + 'Input').val();
        } else {
          currentSkill = maxSkillCount;
        }
        var percent = (currentSkill - value.minSkill) / (value.maxSkill - value.minSkill);
        var needEffective = value.maxCount - ((value.maxCount - value.minCount) * percent);
        needEffective = Math.ceil(needEffective);
  
        if (needEffective < value.minCount) needEffective = value.minCount;
        if (needEffective > value.maxCount) needEffective = value.maxCount;
        
        value.neededCount = needEffective * previousCount;

        if(!(value.subs instanceof Map)) { // we assume that a product without subs is a base resource
          if(baseResources.has(key)) {
            baseResources.set(key, value.neededCount + baseResources.get(key));
          } else {
            baseResources.set(key, value.neededCount);
          }
        }

        if(value.subs instanceof Map) {
          recursiveCalculateNeedEffectives(value.subs, value.neededCount);
        }
      });

      return product;
    }

    function printBaseResources() {
      baseResources = new Map([...baseResources.entries()].sort());

      $('#SCalResourcesrow2').html('');
      $('#SCalResourcesrow2').append('<h2><span id="mw-headline">Overview of base resources</span></h2>');
      $('#SCalResourcesrow2').append('<table id="SCalBaseResourceTable" class="wikitable sortable"><thead>'
        + '<tr>'
        + '<th align="left">Resource</th>'
        + '<th align="left">Need</th>'
        + '</tr></thead>'
      );

      var tablecontent = '<tbody>';

      baseResources.forEach(function(value, key) {
        tablecontent += '<tr>'
          + '<td><a href="' + mw.util.getUrl(key) + '">' + key + '</a></td>'
          + '<td>' + value + '</td>'
          + '</tr>';
      });

      tablecontent += '</tbody)';
      $('#SCalBaseResourceTable').append(tablecontent);
      $('#SCalResources').append('</table>');
    }

    function validateInputs() {
      var ready = true;
      //reset the error textfield
      $('#SCalErrorText').html('');

      // check the keycounter value
      $('#SCalCountInput').removeClass('SCalErroreousInput');
      var value = $('#SCalCountInput').val();
      if (!(!isNaN(value) &&
        parseInt(Number(value)) == value &&
        !isNaN(parseInt(value, 10)))) {
        $('#SCalErrorText').append('<center>Amount of keys: this was not a number!</center>');
        $('#SCalCountInput').addClass('SCalErroreousInput');
        ready = false;
      } else {
        if (value < 1 || value > maxKeyCount) {
          $('#SCalErrorText').append('<center>Amount of keys: please provide a number between 1 and ' + maxKeyCount + '</center>');
          $('#SCalCountInput').addClass('SCalErroreousInput');
          ready = false;
        }
      }

      //check the skills counters
      for (var [skill, id] of skills) {
        $('#SCalSkill' + id + 'Input').removeClass('SCalErroreousInput');
        number = $('#SCalSkill' + id + 'Input').val();

        if (!(!isNaN(number) &&
          parseInt(Number(number)) == number &&
          !isNaN(parseInt(number, 10)))) {
          $('#SCalErrorText').append('<center>' + skill + ': this was not a number!</center>');
          $('#SCalSkill' + id + 'Input').addClass('SCalErroreousInput');
          ready = false;
        } else {
          if (number < 1 || number > maxSkillCount) {
            $('#SCalErrorText').append('<center>' + skill + ': please provide a number between 1 and ' + maxSkillCount + '</center>');
            $('#SCalSkill' + id + 'Input').addClass('SCalErroreousInput');
            ready = false;
          }
        }
      }
      return ready;
    }
  }
});