Difference between revisions of "MediaWiki:SCalScript.js"

From Istaria Lexica

(Undo revision 137319 by Maintenance script (talk))
Tag: Undo
m (Importing a too big article!)
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 refinedResources; // Collection of the needed refined resources. To be filled.
 +
    let initialKeyCount = 10;
 +
    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: 'SCalProduct' });
 +
    products.get('Skeleton Key').subs
 +
      .set('Enchanted Adamantium-Mithril Bar', { subs: new Map(), skill:'Tinkering', minCount: 3, maxCount: 6, minSkill: 1100, maxSkill: 1425, type: 'SCalProduct' });
 +
    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: 'SCalProduct' });
 +
    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: 'SCalProduct' });
 +
    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: 'SCalRefinedResource' });
 +
    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: 'SCalRefinedResource' });
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalProduct'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalProduct'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalProduct'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalProduct'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalRefinedResource'});
 +
    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: 'SCalProduct'});
 +
    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});
  
     SCalPrintHeader();
+
     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() {
 +
        if(confirm('This will reset all of the skills! Are you really sure? ')) {
 +
          for (var v of skills.values()) {
 +
            $('#SCalSkill' + v + 'Input').val(maxSkillCount);
 +
            $('#SCalSkill' + v + 'Input').change();
 +
          };
 +
        }
 +
      });
 +
 
 +
      $('#SCalMinSkillsBtn').click(function() { //TODO: delete me
 +
        for (var v of skills.values()) {
 +
          $('#SCalSkill' + v + 'Input').val(1);
 +
          $('#SCalSkill' + v + 'Input').change();
 +
        };
 +
      });
 +
 
 +
      $('#SCalCountBtn').click(function() {
 +
        printLists();
 +
      });
 +
 
 +
      $('#SCalCountInput').keypress(function(event) {
 +
        if (event.key === 'Enter') printLists();
 +
      });
 +
 
 +
      printSkillInputs();
 +
    }
 +
 
 +
    function printLists() {
 +
      baseResources = new Map();
 +
      refinedResources = 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();
 +
        printRefinedResources();
 +
      }
 +
    }
 +
 
 +
    function printSkillInputs() {
 +
      recursiveDetermineSkills(products);
 +
      for (var [key, value] of skills.entries()) {
 +
        var id = 'SCalSkill' + value;
 +
        var skill = getCookie(id + 'Input');
 +
        console.log(id + ': skill is: ' + skill);
 +
        if(!isRealInteger(skill)) {
 +
          skill = maxSkillCount;
 +
        }
 +
 
 +
        $('#SCalSkills').append('<input type="number" id="' + id + 'Input" name="' + id + '" size="6"><label for="' + id + '">&nbsp;&nbsp;' + key + '</label><br />');
 +
        $('#' + id + 'Input').keypress(function(event) {
 +
          if (event.key === 'Enter') {
 +
            printLists();
 +
            setCookie(id, skill, new Date(3030,1,4));
 +
          }
 +
        });
 +
        $('#' + id + 'Input').change(function(event) {
 +
          console.log(event.target.id);
 +
          setCookie(event.target.id, $('#' + event.target.id).val(), new Date(3030,1,4));
 +
        });
 +
        $('#SCalSkill' + value + 'Input').val(skill);
 +
      }
 +
     }
 +
 
 +
    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 += '<span class="' + obj.type + '"><a href="' + mw.util.getUrl(value) + '">' + value + '</a>: ' + obj.neededCount + '</span>';
            '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);
 +
        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);
 +
          }
 
         }
 
         }
      }
 
      return '<span class="' + cssclass + '"><a href="' + mw.util.getUrl(name) + '">' + name + '</a>: ' + count + '</span>';
 
    };
 
  
     function SCalPrintBaseResources() {
+
        if(value.type == 'SCalRefinedResource') {
       SCalBaseResources.sort(SCalCompare('name'))
+
          if(refinedResources.has(key)) {
 +
            refinedResources.set(key, value.neededCount + refinedResources.get(key));
 +
          } else {
 +
            refinedResources.set(key, value.neededCount);
 +
          }
 +
        }
 +
 
 +
        if(value.subs instanceof Map) {
 +
          recursiveCalculateNeedEffectives(value.subs, value.neededCount);
 +
        }
 +
      });
 +
 
 +
      return product;
 +
    }
 +
 
 +
     function printRefinedResources() {
 +
       refinedResources = new Map([...refinedResources.entries()].sort());
 +
 
 +
      $('#SCalResourcesrow2').append('<h2>Overview of refined resources</h2>');
 +
      $('#SCalResourcesrow2').append('<table id="SCalRefinedResourceTable" class="wikitable sortable"><thead>'
 +
        + '<tr>'
 +
        + '<th align="left">Resource</th>'
 +
        + '<th align="left">Need</th>'
 +
        + '</tr></thead>'
 +
      );
 +
 
 +
      var tablecontent = '<tbody>';
 +
 
 +
      refinedResources.forEach(function(value, key) {
 +
        tablecontent += '<tr>'
 +
          + '<td><a href="' + mw.util.getUrl(key) + '">' + key + '</a></td>'
 +
          + '<td>' + value + '</td>'
 +
          + '</tr>';
 +
      });
 +
 
 +
      tablecontent += '</tbody>';
 +
      tablecontent += '</table>';
 +
      $('#SCalRefinedResourceTable').append(tablecontent);
 +
    }
 +
 
 +
    function printBaseResources() {
 +
      baseResources = new Map([...baseResources.entries()].sort());
 +
 
 
       $('#SCalResourcesrow2').html('');
 
       $('#SCalResourcesrow2').html('');
       $('#SCalResourcesrow2').append('<h2><span id="mw-headline">Overview of base resources</span></h2>');
+
       $('#SCalResourcesrow2').append('<h2>Overview of base resources</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 += '</table>';
  
      tablecontent += '</tbody)';
 
 
       $('#SCalBaseResourceTable').append(tablecontent);
 
       $('#SCalBaseResourceTable').append(tablecontent);
      $('#SCalResources').append('</table>');
 
 
     }
 
     }
  
     function SCalCompare(prop) {  
+
     function isRealInteger(number) {
        return function(a, b) {   
+
      return (!isNaN(number) && parseInt(Number(number)) == number && !isNaN(parseInt(number, 10)));
            if (a[prop] > b[prop]) {   
 
                return 1;   
 
            } else if (a[prop] < b[prop]) {   
 
                return -1;  
 
            }
 
            return 0;   
 
        }   
 
 
     }
 
     }
 
      
 
      
     function SCalValidate() {
+
     function validateInputs() {
       var value = $('#SCalCountInput').val();
+
       var ready = true;
       $('#SCalErrorText').html('&nbsp;');
+
      //reset the error textfield
       if(!(!isNaN(value) &&
+
      $('#SCalErrorText').html('');
            parseInt(Number(value)) == value &&
+
 
            !isNaN(parseInt(value, 10)))) {
+
      // check the keycounter value
         $('#SCalErrorText').html('<center>This was not a number! I\'ve reset the counter to ' + initialCount + ' for you.</center>');
+
       $('#SCalCountInput').removeClass('SCalErroreousInput');
         $('#SCalCountInput').val(initialCount);
+
       var number = $('#SCalCountInput').val();
 +
      if (!isRealInteger(number)) {
 +
         $('#SCalErrorText').append('<center>Amount of keys: this was not a number!</center>');
 +
         $('#SCalCountInput').addClass('SCalErroreousInput');
 +
        ready = false;
 
       } else {
 
       } else {
         if(value < 1 || value > 5000) {
+
         if (number < 1 || number > 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 (!isRealInteger(number)) {
 +
          $('#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;
 +
    }
 +
   
 +
    function setCookie(name, value, date) {
 +
      var expires = '; expires=' + date.toGMTString();
 +
      var cookie = name + '=' + value + expires + '; path=/; SameSite=Strict';
 +
      console.log(cookie);
 +
      document.cookie = cookie;
 +
    }
 +
 +
    function getCookie(name) {
 +
      var nameEQ = name + '=';
 +
      var ca = document.cookie.split(';');
 +
      for(var i=0;i < ca.length;i++) {
 +
        var c = ca[i];
 +
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
 +
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
 +
      }
 +
      return null;
 
     }
 
     }
 
   }
 
   }
 
});
 
});

Revision as of 07:34, 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 refinedResources; // Collection of the needed refined resources. To be filled.
    let initialKeyCount = 10;
    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: 'SCalProduct' });
    products.get('Skeleton Key').subs
      .set('Enchanted Adamantium-Mithril Bar', { subs: new Map(), skill:'Tinkering', minCount: 3, maxCount: 6, minSkill: 1100, maxSkill: 1425, type: 'SCalProduct' });
    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: 'SCalProduct' });
    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: 'SCalProduct' });
    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: 'SCalRefinedResource' });
    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: 'SCalRefinedResource' });
    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: 'SCalRefinedResource'});
    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: 'SCalProduct'});
    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: 'SCalRefinedResource'});
    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: 'SCalRefinedResource'});
    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: 'SCalRefinedResource'});
    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: 'SCalProduct'});
    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: 'SCalRefinedResource'});
    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: 'SCalRefinedResource'});
    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: 'SCalRefinedResource'});
    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: 'SCalProduct'});
    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: 'SCalRefinedResource'});
    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: 'SCalRefinedResource'});
    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: 'SCalRefinedResource'});
    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: 'SCalProduct'});
    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: 'SCalRefinedResource'});
    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: 'SCalRefinedResource'});
    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: 'SCalRefinedResource'});
    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: 'SCalRefinedResource'});
    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: 'SCalRefinedResource'});
    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: 'SCalRefinedResource'});
    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: 'SCalRefinedResource'});
    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: 'SCalRefinedResource'});
    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: 'SCalRefinedResource'});
    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: 'SCalRefinedResource'});
    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: 'SCalRefinedResource'});
    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: 'SCalRefinedResource'});
    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: 'SCalProduct'});
    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() {
        if(confirm('This will reset all of the skills! Are you really sure? ')) {
          for (var v of skills.values()) {
            $('#SCalSkill' + v + 'Input').val(maxSkillCount);
            $('#SCalSkill' + v + 'Input').change();
          };
        }
      });

      $('#SCalMinSkillsBtn').click(function() { //TODO: delete me
        for (var v of skills.values()) {
          $('#SCalSkill' + v + 'Input').val(1);
          $('#SCalSkill' + v + 'Input').change();
        };
      });

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

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

      printSkillInputs();
    }

    function printLists() {
      baseResources = new Map();
      refinedResources = 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();
        printRefinedResources();
      }
    }

    function printSkillInputs() {
      recursiveDetermineSkills(products);
      for (var [key, value] of skills.entries()) {
        var id = 'SCalSkill' + value;
        var skill = getCookie(id + 'Input');
        console.log(id + ': skill is: ' + skill);
        if(!isRealInteger(skill)) {
          skill = maxSkillCount;
        } 

        $('#SCalSkills').append('<input type="number" id="' + id + 'Input" name="' + id + '" size="6"><label for="' + id + '">&nbsp;&nbsp;' + key + '</label><br />');
        $('#' + id + 'Input').keypress(function(event) {
          if (event.key === 'Enter') {
            printLists();
            setCookie(id, skill, new Date(3030,1,4));
          }
        });
        $('#' + id + 'Input').change(function(event) {
          console.log(event.target.id);
          setCookie(event.target.id, $('#' + event.target.id).val(), new Date(3030,1,4));
        });
        $('#SCalSkill' + value + 'Input').val(skill);
      }
    }

    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 += '<span class="' + obj.type + '"><a href="' + mw.util.getUrl(value) + '">' + value + '</a>: ' + obj.neededCount + '</span>';
        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.type == 'SCalRefinedResource') { 
          if(refinedResources.has(key)) {
            refinedResources.set(key, value.neededCount + refinedResources.get(key));
          } else {
            refinedResources.set(key, value.neededCount);
          }
        }

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

      return product;
    }

    function printRefinedResources() {
      refinedResources = new Map([...refinedResources.entries()].sort());

      $('#SCalResourcesrow2').append('<h2>Overview of refined resources</h2>');
      $('#SCalResourcesrow2').append('<table id="SCalRefinedResourceTable" class="wikitable sortable"><thead>'
        + '<tr>'
        + '<th align="left">Resource</th>'
        + '<th align="left">Need</th>'
        + '</tr></thead>'
      );

      var tablecontent = '<tbody>';

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

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

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

      $('#SCalResourcesrow2').html('');
      $('#SCalResourcesrow2').append('<h2>Overview of base resources</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>';
      tablecontent += '</table>';

      $('#SCalBaseResourceTable').append(tablecontent);
    }

    function isRealInteger(number) {
      return (!isNaN(number) && parseInt(Number(number)) == number && !isNaN(parseInt(number, 10)));
    }
    
    function validateInputs() {
      var ready = true;
      //reset the error textfield
      $('#SCalErrorText').html('');

      // check the keycounter value
      $('#SCalCountInput').removeClass('SCalErroreousInput');
      var number = $('#SCalCountInput').val();
      if (!isRealInteger(number)) {
        $('#SCalErrorText').append('<center>Amount of keys: this was not a number!</center>');
        $('#SCalCountInput').addClass('SCalErroreousInput');
        ready = false;
      } else {
        if (number < 1 || number > 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 (!isRealInteger(number)) {
          $('#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;
    }
    
    function setCookie(name, value, date) {
      var expires = '; expires=' + date.toGMTString();
      var cookie = name + '=' + value + expires + '; path=/; SameSite=Strict';
      console.log(cookie);
      document.cookie = cookie;
    }

    function getCookie(name) {
      var nameEQ = name + '=';
      var ca = document.cookie.split(';');
      for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
      }
      return null;
    }
  }
});