Difference between revisions of "MediaWiki:SCalScript.js"
From Istaria Lexica
(Undo revision 137348 by Maintenance script (talk)) Tag: Undo |
(Big file import) |
||
Line 6: | Line 6: | ||
if (document.getElementById('SCalMain')) { | if (document.getElementById('SCalMain')) { | ||
'use strict'; | 'use strict'; | ||
+ | mw.loader.load( mw.util.getUrl('MediaWiki:SCalScript.css') + "&action=raw&ctype=text/css", "text/css" ); | ||
let baseResources; // Collection of the needed base resources. To be filled. | let baseResources; // Collection of the needed base resources. To be filled. | ||
let refinedResources; // Collection of the needed refined resources. To be filled. | let refinedResources; // Collection of the needed refined resources. To be filled. | ||
let productsSkills = {}; // A list of all product's skills needed, containing their names and their min/opt values. | let productsSkills = {}; // A list of all product's skills needed, containing their names and their min/opt values. | ||
let skillsOverview; // A list of all needed skills, their min/opt stats and an id | let skillsOverview; // A list of all needed skills, their min/opt stats and an id | ||
+ | let resourcesTree = {}; // A tree of resources and needed counts. to be filled. | ||
let initialKeyCount = 10; | let initialKeyCount = 10; | ||
let maxKeyCount = 5000; | let maxKeyCount = 5000; | ||
Line 183: | Line 185: | ||
printSkillInputs(); | printSkillInputs(); | ||
+ | $('#SCalMain').append('<div id="SCalExportEverything" style="text-align: center"></div>'); | ||
+ | |||
+ | // Details of the crafting | ||
$('#SCalMain').append('<center><table>' | $('#SCalMain').append('<center><table>' | ||
+ '<tr valign="top">' | + '<tr valign="top">' | ||
Line 197: | Line 202: | ||
printLists(); | printLists(); | ||
} | } | ||
+ | |||
+ | // The 'print everything' feature | ||
+ | resourcesTree = recursiveGenerateTree(products); | ||
+ | printPrintEverythingLinks(); | ||
//FUNCTIONS: | //FUNCTIONS: | ||
Line 208: | Line 217: | ||
$('#SCalMain').append('<hr />'); | $('#SCalMain').append('<hr />'); | ||
$('#SCalMain').append('<center>Please enter your current skills in the fields below. Defaults to optimal skills.</center>'); | $('#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" class="SCal" id="SCalMaxSkillsBtn" value="Reset to optimal skills"></center>'); |
$('#SCalMain').append('<center><div id="SCalSkills" style="column-count:3; width:fit-content; text-align:left"></div></center>'); | $('#SCalMain').append('<center><div id="SCalSkills" style="column-count:3; width:fit-content; text-align:left"></div></center>'); | ||
$('#SCalMain').append('<br /><center>A <font style="color: red"><b>red</b></font> box means there is an error.</center>'); | $('#SCalMain').append('<br /><center>A <font style="color: red"><b>red</b></font> box means there is an error.</center>'); | ||
$('#SCalMain').append('<center>A <font style="color: green"><b>green</b></font> box means you\'re optimal for creating the items.</center>'); | $('#SCalMain').append('<center>A <font style="color: green"><b>green</b></font> box means you\'re optimal for creating the items.</center>'); | ||
+ | $('#SCalMain').append('<div id="SCalErrorText"></div>'); | ||
$('#SCalMain').append('<br />'); | $('#SCalMain').append('<br />'); | ||
− | $('#SCalMain').append('<center><input type="button" id="SCalCountBtn" value="Calculate now!"></center | + | $('#SCalMain').append('<center><input type="button" class="SCal" id="SCalCountBtn" value="Calculate now!"></center>'); |
− | |||
$('#SCalMain').append('<hr />'); | $('#SCalMain').append('<hr />'); | ||
Line 247: | Line 256: | ||
}); | }); | ||
} | } | ||
+ | |||
+ | function printPrintEverythingLinks() { | ||
+ | $('#SCalExportEverything').append('<a id="SCalExportEverythingAsJSONA"></a>'); | ||
+ | $('#SCalExportEverythingAsJSONA').append('<input class="SCal" id="SCalExportEverythingAsJSON" name="SCalExportEverythingAsJSON" type="button" value="Export everything as JSON">'); | ||
+ | $('#SCalExportEverythingAsJSON').click(function() { | ||
+ | var JSONeverything = { | ||
+ | 'Product Tree': resourcesTree, | ||
+ | 'Base Resources': baseResources, | ||
+ | 'Refined Resources': refinedResources, | ||
+ | 'Skills': generateSkillsAsJSON() | ||
+ | }; | ||
+ | |||
+ | var url = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(JSONeverything)); | ||
+ | $('#SCalExportEverythingAsJSONA').attr('href', url); | ||
+ | $('#SCalExportEverythingAsJSONA').attr('download', 'Skeleton Key - All.json'); | ||
+ | }); | ||
+ | $('#SCalExportEverything').append('<a id="SCalExportEverythingAsTEXTA"></a>'); | ||
+ | $('#SCalExportEverythingAsTEXTA').append('<input class="SCal" id="SCalExportEverythingAsTEXT" name="SCalExportEverythingAsTEXT" type="button" value="Export everything as TEXT">'); | ||
+ | $('#SCalExportEverythingAsTEXT').click(function() { | ||
+ | var text = '--- Tree of needed Resources ---\n\n'; | ||
+ | text += recursiveGenerateTreeAsTEXT(resourcesTree, 0); | ||
+ | text += '\n\n'; | ||
+ | text += '--- Needed Base Resources ---\n\n'; | ||
+ | text += generateResourcesAsTEXT(baseResources); | ||
+ | text += '\n\n'; | ||
+ | text += '--- Needed Refined Resources ---\n\n'; | ||
+ | text += generateResourcesAsTEXT(refinedResources); | ||
+ | text += '\n\n'; | ||
+ | text += '--- Needed Skills ---\n\n'; | ||
+ | text += generateSkillsAsTEXT([9,7]); | ||
+ | |||
+ | var url = 'data:text/plain;charset=utf-8,' + encodeURIComponent(text); | ||
+ | $('#SCalExportEverythingAsTEXTA').attr('href', url); | ||
+ | $('#SCalExportEverythingAsTEXTA').attr('download', 'Skeleton Key - All.txt'); | ||
+ | }); | ||
+ | $('#SCalExportEverything').append('<a id="SCalExportEverythingAsXMLA"></a>'); | ||
+ | $('#SCalExportEverythingAsXMLA').append('<input class="SCal" id="SCalExportEverythingAsXML" name="SCalExportEverythingAsXML" type="button" value="Export everything as XML">'); | ||
+ | $('#SCalExportEverythingAsXML').click(function() { | ||
+ | var text = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\n'; | ||
+ | text += '<ResourcesTree>\n'; | ||
+ | text += recursiveGenerateTreeAsXML(resourcesTree, 2); | ||
+ | text += '</ResourcesTree>\n'; | ||
+ | text += generateResourcesAsXML(baseResources,'BaseResources', 0); | ||
+ | text += generateResourcesAsXML(refinedResources,'RefinedResources', 0); | ||
+ | text += generateSkillsAsXML(0); | ||
+ | var url = 'data:application/xml;charset=utf-8,' + encodeURIComponent(text); | ||
+ | |||
+ | $('#SCalExportEverythingAsXMLA').attr('href', url); | ||
+ | $('#SCalExportEverythingAsXMLA').attr('download', 'Skeleton Key - All.xml'); | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | function generateSkillsAsJSON() { | ||
+ | var json = {}; | ||
+ | for(var [key, values] of Object.entries(skillsOverview).sort()) { | ||
+ | json[key] = { | ||
+ | minimal: values.min, | ||
+ | optimal: values.max | ||
+ | } | ||
+ | } | ||
+ | return json; | ||
+ | } | ||
+ | |||
+ | function recursiveGenerateTree(product) { | ||
+ | var tree = {}; | ||
+ | for(var [key, value] of Object.entries(product)) { | ||
+ | tree[key] = { needed: value.needed }; | ||
+ | |||
+ | if(value.hasOwnProperty('subs')) { | ||
+ | tree[key].subs = recursiveGenerateTree(value.subs); | ||
+ | } | ||
+ | } | ||
+ | return tree; | ||
+ | } | ||
+ | |||
+ | function recursiveGenerateTreeAsTEXT(tree, indent) { | ||
+ | var text = ''; | ||
+ | for(var [key, value] of Object.entries(tree)) { | ||
+ | for(var i=0; i<indent; i++) { | ||
+ | text += ' '; | ||
+ | } | ||
+ | |||
+ | text += '|- '; | ||
+ | text += key + ' '; | ||
+ | text += value.needed; | ||
+ | text += '\n'; | ||
+ | |||
+ | if(value.hasOwnProperty('subs')) { | ||
+ | text += recursiveGenerateTreeAsTEXT(value.subs, indent+2); | ||
+ | } | ||
+ | } | ||
+ | return text; | ||
+ | } | ||
+ | |||
+ | function recursiveGenerateTreeAsXML(tree, indent) { | ||
+ | var xml = ''; | ||
+ | for(var [key, value] of Object.entries(tree)) { | ||
+ | for(var i=0; i<indent; i++) { | ||
+ | xml += ' '; | ||
+ | } | ||
+ | |||
+ | xml += '<item name="' + key +'" needed="' + value.needed + '">\n'; | ||
+ | |||
+ | if(value.hasOwnProperty('subs')) { | ||
+ | xml += recursiveGenerateTreeAsXML(value.subs, indent+2); | ||
+ | } | ||
+ | |||
+ | for(var i=0; i<indent; i++) { | ||
+ | xml += ' '; | ||
+ | } | ||
+ | |||
+ | xml +='</item>\n'; | ||
+ | } | ||
+ | return xml; | ||
+ | } | ||
+ | |||
+ | function determineNeededDigitlength(resources, length) { | ||
+ | for(var value of Object.values(resources)) { | ||
+ | if(value.toString().length > length) length = value.toString().length; | ||
+ | } | ||
+ | return length; | ||
+ | } | ||
+ | |||
+ | function determineNeededDigitlengthSkills(length) { | ||
+ | for(var key of Object.keys(skillsOverview)) { | ||
+ | if(skillsOverview[key].min.toString().length > length) length[0] = skillsOverview[key].min.toString().length; | ||
+ | if(skillsOverview[key].max.toString().length > length) length[1] = skillsOverview[key].max.toString().length; | ||
+ | } | ||
+ | return length; | ||
+ | } | ||
+ | |||
function printLists() { | function printLists() { | ||
Line 255: | Line 395: | ||
recursiveCalculateNeededResources(products, parseInt($('#SCalCountInput').val())); | recursiveCalculateNeededResources(products, parseInt($('#SCalCountInput').val())); | ||
$('#SCalResources').html(''); | $('#SCalResources').html(''); | ||
+ | |||
+ | |||
$('#SCalResources').append('<h2>Tree of needed products</h2>'); | $('#SCalResources').append('<h2>Tree of needed products</h2>'); | ||
+ | $('#SCalResources').append('<a id="SCalExportTreeAsJSONA"></a>'); | ||
+ | $('#SCalExportTreeAsJSONA').append('<input class="SCal" id="SCalExportTreeAsJSON" name="SCalExportTreeAsJSON" type="button" value="Export as JSON">'); | ||
+ | $('#SCalExportTreeAsJSON').click(function() { | ||
+ | var url = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(resourcesTree)); | ||
+ | $('#SCalExportTreeAsJSONA').attr('href', url); | ||
+ | $('#SCalExportTreeAsJSONA').attr('download', 'Skeleton Key - Tree.json'); | ||
+ | }); | ||
+ | $('#SCalResources').append('<a id="SCalExportTreeAsTEXTA"></a>'); | ||
+ | $('#SCalExportTreeAsTEXTA').append('<input class="SCal" id="SCalExportTreeAsTEXT" name="SCalExportTreeAsTEXT" type="button" value="Export as TEXT">'); | ||
+ | $('#SCalExportTreeAsTEXT').click(function() { | ||
+ | var url = 'data:text/plain;charset=utf-8,' + encodeURIComponent(recursiveGenerateTreeAsTEXT(resourcesTree, 0)); | ||
+ | $('#SCalExportTreeAsTEXTA').attr('href', url); | ||
+ | $('#SCalExportTreeAsTEXTA').attr('download', 'Skeleton Key - Tree.txt'); | ||
+ | }); | ||
+ | $('#SCalResources').append('<a id="SCalExportTreeAsXMLA"></a>'); | ||
+ | $('#SCalExportTreeAsXMLA').append('<input class="SCal" id="SCalExportTreeAsXML" name="SCalExportTreeAsXML" type="button" value="Export as XML">'); | ||
+ | $('#SCalExportTreeAsXML').click(function() { | ||
+ | var url = 'data:application/xml;charset=utf-8,' + encodeURIComponent( | ||
+ | '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\n' | ||
+ | + recursiveGenerateTreeAsXML(resourcesTree, 0)); | ||
+ | $('#SCalExportTreeAsXMLA').attr('href', url); | ||
+ | $('#SCalExportTreeAsXMLA').attr('download', 'Skeleton Key - Tree.xml'); | ||
+ | }); | ||
+ | |||
var html = recursivePrintTreeProduct(products); | var html = recursivePrintTreeProduct(products); | ||
$('#SCalResources').append(html); | $('#SCalResources').append(html); | ||
Line 266: | Line 432: | ||
$('table.sortable').tablesorter({ sortList: [{ 0: 'asc' }] }) | $('table.sortable').tablesorter({ sortList: [{ 0: 'asc' }] }) | ||
}); | }); | ||
+ | } | ||
+ | |||
+ | function generateExportSkills() { | ||
+ | var skills = {}; | ||
+ | for(var [key, value] of Object.entries(skillsOverview).sort()) { | ||
+ | skills[key] = { | ||
+ | 'minimal skill': value.min, | ||
+ | 'optimal skill': value.max | ||
+ | } | ||
+ | } | ||
+ | return skills; | ||
} | } | ||
function printNeededSkills() { | function printNeededSkills() { | ||
$('#SCalResourcesrow2').append('<h2>Required skills</h2>'); | $('#SCalResourcesrow2').append('<h2>Required skills</h2>'); | ||
+ | |||
+ | $('#SCalResourcesrow2').append('<a id="SCalExportSkillsAsJSONA"></a>'); | ||
+ | $('#SCalExportSkillsAsJSONA').append('<input class="SCal" id="SCalExportSkillsAsJSON" name="SCalExportSkillsAsJSON" type="button" value="Export as JSON">'); | ||
+ | $('#SCalExportSkillsAsJSON').click(function() { | ||
+ | var url = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(generateExportSkills())); | ||
+ | $('#SCalExportSkillsAsJSONA').attr('href', url); | ||
+ | $('#SCalExportSkillsAsJSONA').attr('download', 'Skeleton Key - Skills.json'); | ||
+ | }); | ||
+ | |||
+ | $('#SCalResourcesrow2').append('<a id="SCalExportSkillsAsTEXTA"></a>'); | ||
+ | $('#SCalExportSkillsAsTEXTA').append('<input class="SCal" id="SCalExportSkillsAsTEXT" name="SCalExportSkillsAsTEXT" type="button" value="Export as TEXT">'); | ||
+ | $('#SCalExportSkillsAsTEXT').click(function() { | ||
+ | var text = generateSkillsAsTEXT(determineNeededDigitlengthSkills([9,7])); | ||
+ | var url = 'data:text/plain;charset=utf-8,' + encodeURIComponent(text); | ||
+ | $('#SCalExportSkillsAsTEXTA').attr('href', url); | ||
+ | $('#SCalExportSkillsAsTEXTA').attr('download', 'Skeleton Key - Skills.txt'); | ||
+ | }); | ||
+ | |||
+ | $('#SCalResourcesrow2').append('<a id="SCalExportSkillsAsXMLA"></a>'); | ||
+ | $('#SCalExportSkillsAsXMLA').append('<input class="SCal" id="SCalExportSkillsAsXML" name="SCalExportSkillsAsXML" type="button" value="Export as XML">'); | ||
+ | $('#SCalExportSkillsAsXML').click(function() { | ||
+ | var text = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\n' | ||
+ | + generateSkillsAsXML(0); | ||
+ | var url = 'data:application/xml;charset=utf-8,' + encodeURIComponent(text); | ||
+ | $('#SCalExportSkillsAsXMLA').attr('href', url); | ||
+ | $('#SCalExportSkillsAsXMLA').attr('download', 'Skeleton Key - Skills.xml'); | ||
+ | }); | ||
+ | |||
+ | |||
$('#SCalResourcesrow2').append('<table id="SCalNeededSkillsTable" class="wikitable sortable"><thead>' | $('#SCalResourcesrow2').append('<table id="SCalNeededSkillsTable" class="wikitable sortable"><thead>' | ||
+ '<tr>' | + '<tr>' | ||
Line 372: | Line 578: | ||
// Adds needed resources to the dataset and counts up the base and refined resources | // Adds needed resources to the dataset and counts up the base and refined resources | ||
− | function recursiveCalculateNeededResources( | + | function recursiveCalculateNeededResources(product, previousCount) { |
− | for(var [key, values] of Object.entries( | + | for(var [key, values] of Object.entries(product)) { |
var currentSkill = $('#' + skillsOverview[values.skill].id).val(); | var currentSkill = $('#' + skillsOverview[values.skill].id).val(); | ||
Line 405: | Line 611: | ||
values.needed = needEffective; | values.needed = needEffective; | ||
− | + | product[key] = values; | |
if(values.hasOwnProperty('subs')) { | if(values.hasOwnProperty('subs')) { | ||
Line 411: | Line 617: | ||
} | } | ||
} | } | ||
− | return | + | return product; |
} | } | ||
function printRefinedResources() { | function printRefinedResources() { | ||
$('#SCalResourcesrow2').append('<h2>Overview of refined resources</h2>'); | $('#SCalResourcesrow2').append('<h2>Overview of refined resources</h2>'); | ||
+ | |||
+ | $('#SCalResourcesrow2').append('<a id="SCalExportRefinedresourcesAsJSONA"></a>'); | ||
+ | $('#SCalExportRefinedresourcesAsJSONA').append('<input class="SCal" id="SCalExportRefinedresourceAsJSON" name="SCalExportRefinedresourceAsJSON" type="button" value="Export as JSON">'); | ||
+ | $('#SCalExportRefinedresourceAsJSON').click(function() { | ||
+ | var url = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(Object.fromEntries(Object.entries(refinedResources).sort()))); | ||
+ | $('#SCalExportRefinedresourcesAsJSONA').attr('href', url); | ||
+ | $('#SCalExportRefinedresourcesAsJSONA').attr('download', 'Skeleton Key - Refined Resources.json'); | ||
+ | }); | ||
+ | |||
+ | $('#SCalResourcesrow2').append('<a id="SCalExportRefinedresourcesAsTEXTA"></a>'); | ||
+ | $('#SCalExportRefinedresourcesAsTEXTA').append('<input class="SCal" id="SCalExportRefinedresourceAsTEXT" name="SCalExportRefinedresourceAsTEXT" type="button" value="Export as TEXT">'); | ||
+ | $('#SCalExportRefinedresourceAsTEXT').click(function() { | ||
+ | var url = 'data:application/xml;charset=utf-8,' + encodeURIComponent(generateResourcesAsTEXT(baseResources)); | ||
+ | $('#SCalExportRefinedresourcesAsTEXTA').attr('href', url); | ||
+ | $('#SCalExportRefinedresourcesAsTEXTA').attr('download', 'Skeleton Key - Refined Resouces.txt'); | ||
+ | }); | ||
+ | |||
+ | $('#SCalResourcesrow2').append('<a id="SCalExportRefinedresourcesAsXMLA"></a>'); | ||
+ | $('#SCalExportRefinedresourcesAsXMLA').append('<input class="SCal" id="SCalExportRefinedresourceAsXML" name="SCalExportRefinedresourceAsXML" type="button" value="Export as XML">'); | ||
+ | $('#SCalExportRefinedresourceAsXML').click(function() { | ||
+ | var url = 'data:application/xml;charset=utf-8,' + encodeURIComponent( | ||
+ | '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\n' | ||
+ | + generateResourcesAsXML(refinedResources,'RefinedResources', 0)); | ||
+ | $('#SCalExportRefinedresourcesAsXMLA').attr('href', url); | ||
+ | $('#SCalExportRefinedresourcesAsXMLA').attr('download', 'Skeleton Key - Refined Resources.xml'); | ||
+ | }); | ||
+ | |||
$('#SCalResourcesrow2').append('<table id="SCalRefinedResourceTable" class="wikitable sortable"><thead>' | $('#SCalResourcesrow2').append('<table id="SCalRefinedResourceTable" class="wikitable sortable"><thead>' | ||
+ '<tr>' | + '<tr>' | ||
Line 440: | Line 673: | ||
$('#SCalResourcesrow2').html(''); | $('#SCalResourcesrow2').html(''); | ||
$('#SCalResourcesrow2').append('<h2>Overview of base resources</h2>'); | $('#SCalResourcesrow2').append('<h2>Overview of base resources</h2>'); | ||
+ | |||
+ | $('#SCalResourcesrow2').append('<a id="SCalExportBaseresourcesAsJSONA"></a>'); | ||
+ | $('#SCalExportBaseresourcesAsJSONA').append('<input class="SCal" id="SCalExportBaseresourceAsJSON" name="SCalExportBaseresourceAsJSON" type="button" value="Export as JSON">'); | ||
+ | $('#SCalExportBaseresourceAsJSON').click(function() { | ||
+ | var url = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(Object.fromEntries(Object.entries(baseResources).sort()))); | ||
+ | $('#SCalExportBaseresourcesAsJSONA').attr('href', url); | ||
+ | $('#SCalExportBaseresourcesAsJSONA').attr('download', 'Skeleton Key - Base Resources.json'); | ||
+ | }); | ||
+ | |||
+ | $('#SCalResourcesrow2').append('<a id="SCalExportBaseresourcesAsTEXTA"></a>'); | ||
+ | $('#SCalExportBaseresourcesAsTEXTA').append('<input class="SCal" id="SCalExportBaseresourceAsTEXT" name="SCalExportBaseresourceAsTEXT" type="button" value="Export as TEXT">'); | ||
+ | $('#SCalExportBaseresourceAsTEXT').click(function() { | ||
+ | var url = 'data:application/xml;charset=utf-8,' + encodeURIComponent(generateResourcesAsTEXT(baseResources)); | ||
+ | $('#SCalExportBaseresourcesAsTEXTA').attr('href', url); | ||
+ | $('#SCalExportBaseresourcesAsTEXTA').attr('download', 'Skeleton Key - Base Resouces.txt'); | ||
+ | }); | ||
+ | |||
+ | $('#SCalResourcesrow2').append('<a id="SCalExportBaseresourcesAsXMLA"></a>'); | ||
+ | $('#SCalExportBaseresourcesAsXMLA').append('<input class="SCal" id="SCalExportBaseresourceAsXML" name="SCalExportBaseresourceAsXML" type="button" value="Export as XML">'); | ||
+ | $('#SCalExportBaseresourceAsXML').click(function() { | ||
+ | var url = 'data:application/xml;charset=utf-8,' + encodeURIComponent( | ||
+ | '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\n' | ||
+ | + generateResourcesAsXML(baseResources,'BaseResources', 0)); | ||
+ | $('#SCalExportBaseresourcesAsXMLA').attr('href', url); | ||
+ | $('#SCalExportBaseresourcesAsXMLA').attr('download', 'Skeleton Key - Base Resources.xml'); | ||
+ | }); | ||
+ | |||
$('#SCalResourcesrow2').append('<table id="SCalBaseResourceTable" class="wikitable sortable"><thead>' | $('#SCalResourcesrow2').append('<table id="SCalBaseResourceTable" class="wikitable sortable"><thead>' | ||
+ '<tr>' | + '<tr>' | ||
Line 460: | Line 720: | ||
$('#SCalBaseResourceTable').append(tablecontent); | $('#SCalBaseResourceTable').append(tablecontent); | ||
+ | } | ||
+ | |||
+ | function generateResourcesAsTEXT(resources) { | ||
+ | var text = ''; | ||
+ | var length = determineNeededDigitlength(resources, 0); | ||
+ | for(var [key, count] of Object.entries(resources).sort()) { | ||
+ | var indent = ''; | ||
+ | for(var i = 0;i < length - count.toString().length; i++) { | ||
+ | indent += ' '; | ||
+ | } | ||
+ | |||
+ | text += count + indent + ' ' + key + '\n'; | ||
+ | } | ||
+ | return text; | ||
+ | } | ||
+ | |||
+ | function generateSkillsAsXML(indent) { | ||
+ | indentation = ''; | ||
+ | for(var i = 0; i < indent; i++) { | ||
+ | indentation += ' '; | ||
+ | } | ||
+ | |||
+ | var xml = indentation + '<Skills>\n'; | ||
+ | for(var [key, values] of Object.entries(skillsOverview).sort()) { | ||
+ | xml += indentation + ' <skill minimal="' + values.min + '" optimal="' + values.max + '">' + key + '</item>\n'; | ||
+ | } | ||
+ | xml += indentation + '</Skills>' | ||
+ | return xml; | ||
+ | } | ||
+ | |||
+ | function generateSkillsAsTEXT(lengths) { | ||
+ | var text = 'Minimal Optimal Skillname\n'; | ||
+ | text += '--------------------------------------------------------\n'; | ||
+ | |||
+ | for(var [key, values] of Object.entries(skillsOverview).sort()) { | ||
+ | var needIndent = ''; | ||
+ | var optIndent = ''; | ||
+ | for(var i = 0;i < lengths[0] - values.min.toString().length; i++) { | ||
+ | needIndent += ' '; | ||
+ | } | ||
+ | |||
+ | for(var i = 0;i < lengths[1] - values.max.toString().length; i++) { | ||
+ | optIndent += ' '; | ||
+ | } | ||
+ | |||
+ | text += values.min + needIndent + values.max + optIndent + ' ' + key + '\n'; | ||
+ | } | ||
+ | return text; | ||
+ | } | ||
+ | |||
+ | function generateResourcesAsXML(resources, tag, indent) { | ||
+ | var indentation = ''; | ||
+ | for(var i = 0; i < indent; i++) { | ||
+ | indentation += ' '; | ||
+ | } | ||
+ | var xml = indentation + '<' + tag + '>\n'; | ||
+ | |||
+ | for(var [key, count] of Object.entries(resources).sort()) { | ||
+ | xml += indentation + ' <item needed="' + count + '">' + key + '</item>\n'; | ||
+ | } | ||
+ | xml += '</' + tag + '>\n'; | ||
+ | return xml; | ||
} | } | ||
Revision as of 16:10, 22 June 2022
/** * Skeleton Key Calculator V 0.5 * Elteria Shadowhand */ $(document).ready(function() { if (document.getElementById('SCalMain')) { 'use strict'; mw.loader.load( mw.util.getUrl('MediaWiki:SCalScript.css') + "&action=raw&ctype=text/css", "text/css" ); let baseResources; // Collection of the needed base resources. To be filled. let refinedResources; // Collection of the needed refined resources. To be filled. let productsSkills = {}; // A list of all product's skills needed, containing their names and their min/opt values. let skillsOverview; // A list of all needed skills, their min/opt stats and an id let resourcesTree = {}; // A tree of resources and needed counts. to be filled. let initialKeyCount = 10; let maxKeyCount = 5000; let maxSkillCount = 2000; // the dataset // Note that the skill is NOT the actual skill you need to create the product. // It is the skill you need to create it's parent product. So if you created a Spell Shard which needs Spellcraft, // the subcomponent (i.e. a Stone Brick, which would be Stoneworking) of it would be Spellcraft. The minXXX and maxXXX // parameters behave the same. // the REAL needed skills are documented in the skillsOverview variable. let products = { 'Skeleton Key': { skill: 'Tinkering', minCount: 1, maxCount: 1, minSkill: 1100, maxSkill: 1425, type: 'SCalProduct', subs: { 'Enchanted Adamantium-Mithril Bar': { skill: 'Tinkering', minCount: 3, maxCount: 6, minSkill: 1100, maxSkill: 1425, type: 'SCalProduct', subs: { 'Gozar\'s Blessing': { skill: 'Tinkering', minCount: 2, maxCount: 4, minSkill: 1100, maxSkill: 1425, type: 'SCalProduct', subs: { 'Meltanis\' Prayer': { skill: 'Scribing', minCount: 1, maxCount: 3, minSkill: 1100, maxSkill: 1425, type: 'SCalProduct', subs: { 'Travertine Spell Shard': { skill: 'Spellcraft', minCount: 1, maxCount: 5, minSkill: 1100, maxSkill: 1425, type: 'SCalRefinedResource', subs: { 'Travertine Brick': { skill: 'Stoneworking', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325, type: 'SCalRefinedResource', subs: { 'Travertine Slab': { skill: 'Stoneworking', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325 } } } } }, 'Radiant Essence Orb': { skill: 'Spellcraft', minCount: 4, maxCount: 10, minSkill: 1100, maxSkill: 1425, type: 'SCalRefinedResource', subs: { 'Radiant Essence': { skill: 'Essence Shaping', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325 } } } } }, 'Primal Burst III': { skill: 'Spellcraft', minCount: 1, maxCount: 3,minSkill: 930, maxSkill: 1130, type: 'SCalProduct', subs: { 'Marble Spell Shard': { skill: 'Spellcraft', minCount: 5, maxCount: 5, minSkill: 930, maxSkill: 1130, type: 'SCalRefinedResource', subs: { 'Marble Brick': { skill: 'Spellcraft', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100, type: 'SCalRefinedResource', subs: { 'Marble Slab': { skill: 'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100 } } } } }, 'Shining Essence Orb': { skill: 'Spellcraft', minCount: 9, maxCount: 18, minSkill: 930, maxSkill: 1130, type: 'SCalRefinedResource', subs: { 'Shining Essence': { skill: 'Essence Shaping', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100 } } } } }, 'Energy Strike V': { skill: 'Spellcraft', minCount: 1, maxCount: 3, minSkill: 850, maxSkill: 1050, type: 'SCalProduct', subs: { 'Marble Spell Shard': { skill: 'Spellcraft', minCount: 4, maxCount: 4, minSkill: 850, maxSkill: 1050, type: 'SCalRefinedResource', subs: { 'Marble Brick': { skill: 'Spellcraft', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100, type: 'SCalRefinedResource', subs: { 'Marble Slab': { skill: 'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100 } } } } }, 'Shining Essence Orb': { skill: 'Spellcraft', minCount: 7, maxCount: 14, minSkill: 800, maxSkill: 1100, type: 'SCalRefinedResource', subs: { 'Shining Essence': { skill: 'Essence Shaping', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100 } } } } }, 'Ice Bomb V': { skill: 'Spellcraft', minCount: 1, maxCount: 3, minSkill: 920, maxSkill: 1120, type: 'SCalProduct', subs: { 'Marble Spell Shard': { skill: 'Spellcraft', minCount: 5, maxCount: 5, minSkill: 800, maxSkill: 1100, type: 'SCalRefinedResource', subs: { 'Marble Brick': { skill: 'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100, type: 'SCalRefinedResource', subs: { 'Marble Slab': { skill: 'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100 } } } } }, 'Shining Essence Orb': { skill: 'Spellcraft', minCount: 9, maxCount: 18, minSkill: 920, maxSkill: 1120, type: 'SCalRefinedResource', subs: { 'Shining Essence': { skill: 'Essence Shaping', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100 } } } } }, 'Fiery Strike V': { skill: 'Spellcraft', minCount: 1, maxCount: 3, minSkill: 980, maxSkill: 1180, type: 'SCalProduct', subs: { 'Marble Spell Shard': { skill: 'Spellcraft', minCount: 6, maxCount: 6, minSkill: 800, maxSkill: 1100, type: 'SCalRefinedResource', subs: { 'Marble Brick': { skill: 'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100, type: 'SCalRefinedResource', subs: { 'Marble Slab': { skill: 'Stoneworking', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100 } } } } }, 'Shining Essence Orb': { skill: 'Spellcraft', minCount: 11, maxCount: 22, minSkill: 980, maxSkill: 1180, type: 'SCalRefinedResource', subs: { 'Shining Essence': { skill: 'Essence Shaping', minCount: 2, maxCount: 5, minSkill: 800, maxSkill: 1100 } } } } }, 'Gold Papyrus Sheet': { skill: 'Scribing', minCount: 2, maxCount: 5, minSkill: 1100, maxSkill: 1425, type: 'SCalRefinedResource', subs: { 'Gold Papyrus Stem': { skill: 'Papermaking', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325 } } } } }, 'Hardened Adamantium-Mithril Bar': { skill: 'Tinkering', minCount: 2, maxCount: 5, minSkill: 1100, maxSkill: 1425, type: 'SCalRefinedResource', subs: { 'Solution of Majorita': { skill: 'Tinkering', minCount: 2, maxCount: 5, minSkill: 1100, maxSkill: 1425, type: 'SCalRefinedResource', subs: { 'Thornwood Bowl': { skill: 'Alchemy', minCount: 1, maxCount: 3, minSkill: 1100, maxSkill: 1425, type: 'SCalRefinedResource', subs: { 'Thornwood Sap': { skill: 'Fletching', minCount: 3, maxCount: 6, minSkill: 1100, maxSkill: 1425 } , 'Thornwood Board': { skill: 'Fletching', minCount: 5, maxCount: 10, minSkill: 1100, maxSkill: 1425, type: 'SCalRefinedResource', subs: { 'Thornwood Log': { skill: 'Lumbering', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325 } } } } }, 'Crystallized Travertine Brick': { skill: 'Alchemy', minCount: 5, maxCount: 10, minSkill: 1000, maxSkill: 1325, type: 'SCalRefinedResource', subs: { 'Unfocused Violet Azulyte Crystal': { skill: 'Stoneworking', minCount: 1, maxCount: 5, minSkill: 1000, maxSkill: 1325 } , 'Travertine Slab': { skill: 'Stoneworking', minCount: 1, maxCount: 5, minSkill: 1000, maxSkill: 1325 } } }, 'Purified Radiant Essence Orb': { skill: 'Alchemy', minCount: 1, maxCount: 4, minSkill: 1100, maxSkill: 1425, type: 'SCalRefinedResource', subs: { 'Radiant Essence Orb': { skill: 'Alchemy', minCount: 1, maxCount: 4, minSkill: 1100, maxSkill: 1325, type: 'SCalRefinedResource', subs: { 'Radiant Essence': { skill: 'Essence Shaping', minCount: 2, maxCount: 5, minSkill: 1000, maxSkill: 1325 } } } } }, 'Water': { skill: 'Alchemy', minCount: 15, maxCount: 30, minSkill: 1100, maxSkill: 1425 } } }, 'Adamantium-Mithril Bar': { skill: 'Tinkering', minCount: 1, maxCount: 1, minSkill: 1100, maxSkill: 1425, type: 'SCalRefinedResource', subs: { 'Mithril Ore': { skill: 'Smelting', minCount: 3, maxCount: 6, minSkill: 1100, maxSkill: 1425 } , 'Adamantium Ore': { skill: 'Smelting', minCount: 3, maxCount: 6, minSkill: 1100, maxSkill: 1425 } } } } } } }, 'Skeleton Key Mold': { skill: 'Tinkering', minCount: 1, maxCount: 1, minSkill: 1100, maxSkill: 1425, type: 'SCalProduct', subs: { 'Skeleton Key Pattern': { skill: 'Earthencraft', minCount: 1, maxCount: 1, minSkill: 1100, maxSkill: 1425 } , 'Porcelain Clay Chunk': { skill: 'Earthencraft', minCount: 2, maxCount: 5, minSkill: 1100, maxSkill: 1425 } } } } } }; // List of the skills you need to have for crafting everything, only used for the input fields skillsOverview = { 'Tinkering': { min: 1100, max: 1425 }, 'Scribing': { min: 1100, max: 1425 }, 'Spellcraft': { min: 1100, max: 1425 }, 'Essence Shaping': { min: 1000, max: 1325 }, 'Papermaking': { min: 1000, max: 1325 }, 'Alchemy': { min: 1100, max: 1425 }, 'Fletching': { min: 1100, max: 1425 }, 'Enchanting': { min: 1100, max: 1425 }, 'Stoneworking': { min: 1000, max: 1325 }, 'Lumbering': { min: 1000, max: 1325 }, 'Smelting': { min: 1100, max: 1425 }, 'Earthencraft': { min: 1100, max: 1425 }, }; for(var [key, values] of Object.entries(skillsOverview)) { values.id = 'SCal' + key.replace(/\s/, '') + 'Input'; } printHeader(); printSkillInputs(); $('#SCalMain').append('<div id="SCalExportEverything" style="text-align: center"></div>'); // Details of the crafting $('#SCalMain').append('<center><table>' + '<tr valign="top">' + '<td id="SCalResourcesrow1"></td>' + '<td id="SCalResourcesrow2"></td>' + '</tr>' + '</table></center>' ); $('#SCalResourcesrow1').append('<div id="SCalResources"></div>'); recursiveDetermineProductsSkills(products); if(validateInputs()) { printLists(); } // The 'print everything' feature resourcesTree = recursiveGenerateTree(products); printPrintEverythingLinks(); //FUNCTIONS: function printHeader() { var keyCount = getCookie('SCalCountInput'); if(!isRealInteger(keyCount)) keyCount = initialKeyCount; $('#SCalMain').append('<h1 id="SCalH1">The Calculator</h1>'); $('#SCalMain').append('<center><label for="SCalCountInput" id="SCalCountInputLbl">How many Skeleton Keys would you want to create?</label></center>'); $('#SCalMain').append('<center><input type="number" id="SCalCountInput" name="SCalCountInput" value="' + keyCount + '" 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" class="SCal" id="SCalMaxSkillsBtn" value="Reset to optimal skills"></center>'); $('#SCalMain').append('<center><div id="SCalSkills" style="column-count:3; width:fit-content; text-align:left"></div></center>'); $('#SCalMain').append('<br /><center>A <font style="color: red"><b>red</b></font> box means there is an error.</center>'); $('#SCalMain').append('<center>A <font style="color: green"><b>green</b></font> box means you\'re optimal for creating the items.</center>'); $('#SCalMain').append('<div id="SCalErrorText"></div>'); $('#SCalMain').append('<br />'); $('#SCalMain').append('<center><input type="button" class="SCal" id="SCalCountBtn" value="Calculate now!"></center>'); $('#SCalMain').append('<hr />'); $('#SCalMaxSkillsBtn').click(function() { if(confirm('This will reset all of the skills! Are you really sure? ')) { for (var v of Object.values(skillsOverview)) { $('#' + v.id).val(v.max); $('#' + v.id).change(); }; } }); $('#SCalCountBtn').click(function(event) { if(validateInputs()) { printLists(); checkIntegerAndSetCookieById(event.target.id); } }); $('#SCalCountInput').keypress(function(event) { if (event.key === 'Enter' && validateInputs()) { printLists(); checkIntegerAndSetCookieById(event.target.id); } }); $('#SCalCountInput').change(function(event) { if(validateInputs()) { printLists(); checkIntegerAndSetCookieById(event.target.id); } }); } function printPrintEverythingLinks() { $('#SCalExportEverything').append('<a id="SCalExportEverythingAsJSONA"></a>'); $('#SCalExportEverythingAsJSONA').append('<input class="SCal" id="SCalExportEverythingAsJSON" name="SCalExportEverythingAsJSON" type="button" value="Export everything as JSON">'); $('#SCalExportEverythingAsJSON').click(function() { var JSONeverything = { 'Product Tree': resourcesTree, 'Base Resources': baseResources, 'Refined Resources': refinedResources, 'Skills': generateSkillsAsJSON() }; var url = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(JSONeverything)); $('#SCalExportEverythingAsJSONA').attr('href', url); $('#SCalExportEverythingAsJSONA').attr('download', 'Skeleton Key - All.json'); }); $('#SCalExportEverything').append('<a id="SCalExportEverythingAsTEXTA"></a>'); $('#SCalExportEverythingAsTEXTA').append('<input class="SCal" id="SCalExportEverythingAsTEXT" name="SCalExportEverythingAsTEXT" type="button" value="Export everything as TEXT">'); $('#SCalExportEverythingAsTEXT').click(function() { var text = '--- Tree of needed Resources ---\n\n'; text += recursiveGenerateTreeAsTEXT(resourcesTree, 0); text += '\n\n'; text += '--- Needed Base Resources ---\n\n'; text += generateResourcesAsTEXT(baseResources); text += '\n\n'; text += '--- Needed Refined Resources ---\n\n'; text += generateResourcesAsTEXT(refinedResources); text += '\n\n'; text += '--- Needed Skills ---\n\n'; text += generateSkillsAsTEXT([9,7]); var url = 'data:text/plain;charset=utf-8,' + encodeURIComponent(text); $('#SCalExportEverythingAsTEXTA').attr('href', url); $('#SCalExportEverythingAsTEXTA').attr('download', 'Skeleton Key - All.txt'); }); $('#SCalExportEverything').append('<a id="SCalExportEverythingAsXMLA"></a>'); $('#SCalExportEverythingAsXMLA').append('<input class="SCal" id="SCalExportEverythingAsXML" name="SCalExportEverythingAsXML" type="button" value="Export everything as XML">'); $('#SCalExportEverythingAsXML').click(function() { var text = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\n'; text += '<ResourcesTree>\n'; text += recursiveGenerateTreeAsXML(resourcesTree, 2); text += '</ResourcesTree>\n'; text += generateResourcesAsXML(baseResources,'BaseResources', 0); text += generateResourcesAsXML(refinedResources,'RefinedResources', 0); text += generateSkillsAsXML(0); var url = 'data:application/xml;charset=utf-8,' + encodeURIComponent(text); $('#SCalExportEverythingAsXMLA').attr('href', url); $('#SCalExportEverythingAsXMLA').attr('download', 'Skeleton Key - All.xml'); }); } function generateSkillsAsJSON() { var json = {}; for(var [key, values] of Object.entries(skillsOverview).sort()) { json[key] = { minimal: values.min, optimal: values.max } } return json; } function recursiveGenerateTree(product) { var tree = {}; for(var [key, value] of Object.entries(product)) { tree[key] = { needed: value.needed }; if(value.hasOwnProperty('subs')) { tree[key].subs = recursiveGenerateTree(value.subs); } } return tree; } function recursiveGenerateTreeAsTEXT(tree, indent) { var text = ''; for(var [key, value] of Object.entries(tree)) { for(var i=0; i<indent; i++) { text += ' '; } text += '|- '; text += key + ' '; text += value.needed; text += '\n'; if(value.hasOwnProperty('subs')) { text += recursiveGenerateTreeAsTEXT(value.subs, indent+2); } } return text; } function recursiveGenerateTreeAsXML(tree, indent) { var xml = ''; for(var [key, value] of Object.entries(tree)) { for(var i=0; i<indent; i++) { xml += ' '; } xml += '<item name="' + key +'" needed="' + value.needed + '">\n'; if(value.hasOwnProperty('subs')) { xml += recursiveGenerateTreeAsXML(value.subs, indent+2); } for(var i=0; i<indent; i++) { xml += ' '; } xml +='</item>\n'; } return xml; } function determineNeededDigitlength(resources, length) { for(var value of Object.values(resources)) { if(value.toString().length > length) length = value.toString().length; } return length; } function determineNeededDigitlengthSkills(length) { for(var key of Object.keys(skillsOverview)) { if(skillsOverview[key].min.toString().length > length) length[0] = skillsOverview[key].min.toString().length; if(skillsOverview[key].max.toString().length > length) length[1] = skillsOverview[key].max.toString().length; } return length; } function printLists() { // (re-)initialize to be updated lists baseResources = {}; refinedResources = {}; recursiveCalculateNeededResources(products, parseInt($('#SCalCountInput').val())); $('#SCalResources').html(''); $('#SCalResources').append('<h2>Tree of needed products</h2>'); $('#SCalResources').append('<a id="SCalExportTreeAsJSONA"></a>'); $('#SCalExportTreeAsJSONA').append('<input class="SCal" id="SCalExportTreeAsJSON" name="SCalExportTreeAsJSON" type="button" value="Export as JSON">'); $('#SCalExportTreeAsJSON').click(function() { var url = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(resourcesTree)); $('#SCalExportTreeAsJSONA').attr('href', url); $('#SCalExportTreeAsJSONA').attr('download', 'Skeleton Key - Tree.json'); }); $('#SCalResources').append('<a id="SCalExportTreeAsTEXTA"></a>'); $('#SCalExportTreeAsTEXTA').append('<input class="SCal" id="SCalExportTreeAsTEXT" name="SCalExportTreeAsTEXT" type="button" value="Export as TEXT">'); $('#SCalExportTreeAsTEXT').click(function() { var url = 'data:text/plain;charset=utf-8,' + encodeURIComponent(recursiveGenerateTreeAsTEXT(resourcesTree, 0)); $('#SCalExportTreeAsTEXTA').attr('href', url); $('#SCalExportTreeAsTEXTA').attr('download', 'Skeleton Key - Tree.txt'); }); $('#SCalResources').append('<a id="SCalExportTreeAsXMLA"></a>'); $('#SCalExportTreeAsXMLA').append('<input class="SCal" id="SCalExportTreeAsXML" name="SCalExportTreeAsXML" type="button" value="Export as XML">'); $('#SCalExportTreeAsXML').click(function() { var url = 'data:application/xml;charset=utf-8,' + encodeURIComponent( '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\n' + recursiveGenerateTreeAsXML(resourcesTree, 0)); $('#SCalExportTreeAsXMLA').attr('href', url); $('#SCalExportTreeAsXMLA').attr('download', 'Skeleton Key - Tree.xml'); }); var html = recursivePrintTreeProduct(products); $('#SCalResources').append(html); printBaseResources(); printRefinedResources(); printNeededSkills(); mw.loader.using('jquery.tablesorter', function() { $('table.sortable').tablesorter({ sortList: [{ 0: 'asc' }] }) }); } function generateExportSkills() { var skills = {}; for(var [key, value] of Object.entries(skillsOverview).sort()) { skills[key] = { 'minimal skill': value.min, 'optimal skill': value.max } } return skills; } function printNeededSkills() { $('#SCalResourcesrow2').append('<h2>Required skills</h2>'); $('#SCalResourcesrow2').append('<a id="SCalExportSkillsAsJSONA"></a>'); $('#SCalExportSkillsAsJSONA').append('<input class="SCal" id="SCalExportSkillsAsJSON" name="SCalExportSkillsAsJSON" type="button" value="Export as JSON">'); $('#SCalExportSkillsAsJSON').click(function() { var url = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(generateExportSkills())); $('#SCalExportSkillsAsJSONA').attr('href', url); $('#SCalExportSkillsAsJSONA').attr('download', 'Skeleton Key - Skills.json'); }); $('#SCalResourcesrow2').append('<a id="SCalExportSkillsAsTEXTA"></a>'); $('#SCalExportSkillsAsTEXTA').append('<input class="SCal" id="SCalExportSkillsAsTEXT" name="SCalExportSkillsAsTEXT" type="button" value="Export as TEXT">'); $('#SCalExportSkillsAsTEXT').click(function() { var text = generateSkillsAsTEXT(determineNeededDigitlengthSkills([9,7])); var url = 'data:text/plain;charset=utf-8,' + encodeURIComponent(text); $('#SCalExportSkillsAsTEXTA').attr('href', url); $('#SCalExportSkillsAsTEXTA').attr('download', 'Skeleton Key - Skills.txt'); }); $('#SCalResourcesrow2').append('<a id="SCalExportSkillsAsXMLA"></a>'); $('#SCalExportSkillsAsXMLA').append('<input class="SCal" id="SCalExportSkillsAsXML" name="SCalExportSkillsAsXML" type="button" value="Export as XML">'); $('#SCalExportSkillsAsXML').click(function() { var text = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\n' + generateSkillsAsXML(0); var url = 'data:application/xml;charset=utf-8,' + encodeURIComponent(text); $('#SCalExportSkillsAsXMLA').attr('href', url); $('#SCalExportSkillsAsXMLA').attr('download', 'Skeleton Key - Skills.xml'); }); $('#SCalResourcesrow2').append('<table id="SCalNeededSkillsTable" class="wikitable sortable"><thead>' + '<tr>' + '<th align="left">Skill</th>' + '<th align="left">Minimal</th>' + '<th align="left">Optimal</th>' + '</tr></thead>' ); var tablecontent = '<tbody>'; for(var [key, value] of Object.entries(skillsOverview).sort()) { tablecontent += '<tr>' + '<td><a href="' + mw.util.getUrl(key) + '">' + key + '</a></td>' + '<td>' + value.min + '</td>' + '<td>' + value.max + '</td>' + '</tr>'; } tablecontent += '</tbody>'; tablecontent += '</table>'; $('#SCalNeededSkillsTable').append(tablecontent); } function printSkillInputs() { for (var [key, value] of Object.entries(skillsOverview)) { var id = value.id; var skill = getCookie(id); if(!isRealInteger(skill)) { // default to max value if cookie not correctly set skill = value.max; } $('#SCalSkills').append('<input type="number" id="' + id + '" name="' + id + '" size="6"><label for="' + id + '"> ' + key + '</label><br />'); $('#' + id).keypress(function(event) { if (event.key === 'Enter' && validateInputs()) { printLists(); checkIntegerAndSetCookieById(event.target.id); } }); $('#' + id).change(function(event) { if(validateInputs()) { printLists(); checkIntegerAndSetCookieById(event.target.id); } }); $('#' + id).val(skill); } } // Tests if the provided input field has a valid integer and sets a cookie for it function checkIntegerAndSetCookieById(id) { hashedId = '#' + id; if(isRealInteger($(hashedId).val())) setCookie(id, $(hashedId).val(), new Date(3030,1,4)); } // Adds skillnames, ids, minskill and maxskill to a skills list function recursiveDetermineProductsSkills(currentproducts) { for (var product of Object.values(currentproducts)) { var skillName = product.skill; var newSkills = {}; // compare min and max skills and set accordingly newSkills.minSkill = product.minSkill; newSkills.maxSkill = product.maxSkill; if(productsSkills.hasOwnProperty(skillName)) { if(productsSkills[skillName].minSkill < newSkills.minSkill) { newSkills.minSkill = productsSkills[skillName].minSkill; } if(productsSkills[skillName].maxSkill > newSkills.maxSkill) { newSkills.maxSkill = productsSkills[skillName].maxSkill; } } productsSkills[skillName] = newSkills; if(product.hasOwnProperty('subs')) { recursiveDetermineProductsSkills(product.subs); } } } function recursivePrintTreeProduct(product) { var html = ''; for(var [key, value] of Object.entries(product)) { html += '<ul>'; html += '<li>'; html += '<span class="' + value.type + '"><a href="' + mw.util.getUrl(key) + '">' + key + '</a>: ' + value.needed + '</span>'; if(value.hasOwnProperty('subs')) { html += recursivePrintTreeProduct(value.subs); } html += '</ul>'; html += '</li>' } return html; } // Adds needed resources to the dataset and counts up the base and refined resources function recursiveCalculateNeededResources(product, previousCount) { for(var [key, values] of Object.entries(product)) { var currentSkill = $('#' + skillsOverview[values.skill].id).val(); var percent = (currentSkill - values.minSkill) / (values.maxSkill - values.minSkill); var needEffective = values.maxCount - ((values.maxCount - values.minCount) * percent); needEffective = Math.ceil(needEffective); if (needEffective < values.minCount) needEffective = values.minCount; if (needEffective > values.maxCount) needEffective = values.maxCount; needEffective *= previousCount; // Process base resources // we assume that a product without subs is a base resource if(!values.hasOwnProperty('subs')) { if(baseResources.hasOwnProperty(key)) { baseResources[key] = needEffective + baseResources[key]; } else { baseResources[key] = needEffective; } } // Process refined resources if(values.type == 'SCalRefinedResource') { if(refinedResources.hasOwnProperty(key)) { refinedResources[key] = needEffective + refinedResources[key]; } else { refinedResources[key] = needEffective; } } values.needed = needEffective; product[key] = values; if(values.hasOwnProperty('subs')) { values.subs = recursiveCalculateNeededResources(values.subs, needEffective); } } return product; } function printRefinedResources() { $('#SCalResourcesrow2').append('<h2>Overview of refined resources</h2>'); $('#SCalResourcesrow2').append('<a id="SCalExportRefinedresourcesAsJSONA"></a>'); $('#SCalExportRefinedresourcesAsJSONA').append('<input class="SCal" id="SCalExportRefinedresourceAsJSON" name="SCalExportRefinedresourceAsJSON" type="button" value="Export as JSON">'); $('#SCalExportRefinedresourceAsJSON').click(function() { var url = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(Object.fromEntries(Object.entries(refinedResources).sort()))); $('#SCalExportRefinedresourcesAsJSONA').attr('href', url); $('#SCalExportRefinedresourcesAsJSONA').attr('download', 'Skeleton Key - Refined Resources.json'); }); $('#SCalResourcesrow2').append('<a id="SCalExportRefinedresourcesAsTEXTA"></a>'); $('#SCalExportRefinedresourcesAsTEXTA').append('<input class="SCal" id="SCalExportRefinedresourceAsTEXT" name="SCalExportRefinedresourceAsTEXT" type="button" value="Export as TEXT">'); $('#SCalExportRefinedresourceAsTEXT').click(function() { var url = 'data:application/xml;charset=utf-8,' + encodeURIComponent(generateResourcesAsTEXT(baseResources)); $('#SCalExportRefinedresourcesAsTEXTA').attr('href', url); $('#SCalExportRefinedresourcesAsTEXTA').attr('download', 'Skeleton Key - Refined Resouces.txt'); }); $('#SCalResourcesrow2').append('<a id="SCalExportRefinedresourcesAsXMLA"></a>'); $('#SCalExportRefinedresourcesAsXMLA').append('<input class="SCal" id="SCalExportRefinedresourceAsXML" name="SCalExportRefinedresourceAsXML" type="button" value="Export as XML">'); $('#SCalExportRefinedresourceAsXML').click(function() { var url = 'data:application/xml;charset=utf-8,' + encodeURIComponent( '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\n' + generateResourcesAsXML(refinedResources,'RefinedResources', 0)); $('#SCalExportRefinedresourcesAsXMLA').attr('href', url); $('#SCalExportRefinedresourcesAsXMLA').attr('download', 'Skeleton Key - Refined Resources.xml'); }); $('#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>'; for(var [key, value] of Object.entries(refinedResources).sort()) { 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() { $('#SCalResourcesrow2').html(''); $('#SCalResourcesrow2').append('<h2>Overview of base resources</h2>'); $('#SCalResourcesrow2').append('<a id="SCalExportBaseresourcesAsJSONA"></a>'); $('#SCalExportBaseresourcesAsJSONA').append('<input class="SCal" id="SCalExportBaseresourceAsJSON" name="SCalExportBaseresourceAsJSON" type="button" value="Export as JSON">'); $('#SCalExportBaseresourceAsJSON').click(function() { var url = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(Object.fromEntries(Object.entries(baseResources).sort()))); $('#SCalExportBaseresourcesAsJSONA').attr('href', url); $('#SCalExportBaseresourcesAsJSONA').attr('download', 'Skeleton Key - Base Resources.json'); }); $('#SCalResourcesrow2').append('<a id="SCalExportBaseresourcesAsTEXTA"></a>'); $('#SCalExportBaseresourcesAsTEXTA').append('<input class="SCal" id="SCalExportBaseresourceAsTEXT" name="SCalExportBaseresourceAsTEXT" type="button" value="Export as TEXT">'); $('#SCalExportBaseresourceAsTEXT').click(function() { var url = 'data:application/xml;charset=utf-8,' + encodeURIComponent(generateResourcesAsTEXT(baseResources)); $('#SCalExportBaseresourcesAsTEXTA').attr('href', url); $('#SCalExportBaseresourcesAsTEXTA').attr('download', 'Skeleton Key - Base Resouces.txt'); }); $('#SCalResourcesrow2').append('<a id="SCalExportBaseresourcesAsXMLA"></a>'); $('#SCalExportBaseresourcesAsXMLA').append('<input class="SCal" id="SCalExportBaseresourceAsXML" name="SCalExportBaseresourceAsXML" type="button" value="Export as XML">'); $('#SCalExportBaseresourceAsXML').click(function() { var url = 'data:application/xml;charset=utf-8,' + encodeURIComponent( '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\n' + generateResourcesAsXML(baseResources,'BaseResources', 0)); $('#SCalExportBaseresourcesAsXMLA').attr('href', url); $('#SCalExportBaseresourcesAsXMLA').attr('download', 'Skeleton Key - Base Resources.xml'); }); $('#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>'; for (var [key, value] of Object.entries(baseResources).sort()) { tablecontent += '<tr>' + '<td><a href="' + mw.util.getUrl(key) + '">' + key + '</a></td>' + '<td>' + value + '</td>' + '</tr>'; } tablecontent += '</tbody>'; tablecontent += '</table>'; $('#SCalBaseResourceTable').append(tablecontent); } function generateResourcesAsTEXT(resources) { var text = ''; var length = determineNeededDigitlength(resources, 0); for(var [key, count] of Object.entries(resources).sort()) { var indent = ''; for(var i = 0;i < length - count.toString().length; i++) { indent += ' '; } text += count + indent + ' ' + key + '\n'; } return text; } function generateSkillsAsXML(indent) { indentation = ''; for(var i = 0; i < indent; i++) { indentation += ' '; } var xml = indentation + '<Skills>\n'; for(var [key, values] of Object.entries(skillsOverview).sort()) { xml += indentation + ' <skill minimal="' + values.min + '" optimal="' + values.max + '">' + key + '</item>\n'; } xml += indentation + '</Skills>' return xml; } function generateSkillsAsTEXT(lengths) { var text = 'Minimal Optimal Skillname\n'; text += '--------------------------------------------------------\n'; for(var [key, values] of Object.entries(skillsOverview).sort()) { var needIndent = ''; var optIndent = ''; for(var i = 0;i < lengths[0] - values.min.toString().length; i++) { needIndent += ' '; } for(var i = 0;i < lengths[1] - values.max.toString().length; i++) { optIndent += ' '; } text += values.min + needIndent + values.max + optIndent + ' ' + key + '\n'; } return text; } function generateResourcesAsXML(resources, tag, indent) { var indentation = ''; for(var i = 0; i < indent; i++) { indentation += ' '; } var xml = indentation + '<' + tag + '>\n'; for(var [key, count] of Object.entries(resources).sort()) { xml += indentation + ' <item needed="' + count + '">' + key + '</item>\n'; } xml += '</' + tag + '>\n'; return xml; } function isRealInteger(number) { return (!isNaN(number) && parseInt(Number(number)) == number && !isNaN(parseInt(number, 10))); } // check if the input fields contain valid entries 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, values] of Object.entries(skillsOverview)) { var inputObj = $('#' + values.id); inputObj.removeClass('SCalErroreousInput'); inputObj.removeClass('SCalOptimalInput'); number = inputObj.val(); if (!isRealInteger(number)) { $('#SCalErrorText').append('<center>' + skill + ': this was not a number!</center>'); inputObj.addClass('SCalErroreousInput'); ready = false; } else { if (number < 1 || number > maxSkillCount) { // exceeds the number range $('#SCalErrorText').append('<center>' + skill + ': please provide a number between 1 and ' + maxSkillCount + '</center>'); inputObj.addClass('SCalErroreousInput'); ready = false; } if(number < values.min) { $('#SCalErrorText').append('<center>Skill ' + skill + ' is too low (have:' + number + ', need: ' + values.min + ')</center>'); inputObj.addClass('SCalErroreousInput'); } if(!inputObj.hasClass('SCalErroreousInput')) { if(number >= values.max) inputObj.addClass('SCalOptimalInput'); } } } return ready; } function setCookie(name, value, date) { var expires = '; expires=' + date.toGMTString(); var cookie = name + '=' + value + expires + '; path=/; SameSite=Strict'; 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; } } });