'use strict'; function editResources() { if (customization) return; closeDialogs('#resourcesEditor, .stable'); if (!layerIsOn('toggleResources')) toggleResources(); const body = document.getElementById('resourcesBody'); resourcesEditorAddLines(); if (modules.editResources) return; modules.editResources = true; $('#resourcesEditor').dialog({ title: 'Resources Editor', resizable: false, width: fitContent(), close: closeResourcesEditor, position: {my: 'right top', at: 'right-10 top+10', of: 'svg'} }); // add listeners document.getElementById('resourcesEditorRefresh').addEventListener('click', resourcesEditorAddLines); document.getElementById('resourcesRegenerate').addEventListener('click', regenerateResources); document.getElementById('resourcesLegend').addEventListener('click', toggleLegend); document.getElementById('resourcesPercentage').addEventListener('click', togglePercentageMode); document.getElementById('resourcesExport').addEventListener('click', downloadResourcesData); body.addEventListener('click', function (ev) { const el = ev.target, cl = el.classList, line = el.parentNode, i = +line.dataset.id; const resource = Resources.get(+line.dataset.id); if (cl.contains('resourceCategory')) return changeCategory(resource, line, el); if (cl.contains('resourceModel')) return changeModel(resource, line, el); if (cl.contains('resourceBonus')) return changeBonus(resource, line, el); }); body.addEventListener('change', function (ev) { const el = ev.target, cl = el.classList, line = el.parentNode; const resource = Resources.get(+line.dataset.id); if (cl.contains('resourceName')) return changeName(resource, el.value, line); if (cl.contains('resourceValue')) return changeValue(resource, el.value, line); if (cl.contains('resourceChance')) return changeChance(resource, el.value, line); }); function getBonusIcon(bonus) { if (bonus === 'fleet') return ``; if (bonus === 'defence') return ``; if (bonus === 'prestige') return ``; if (bonus === 'artillery') return ``; if (bonus === 'infantry') return ``; if (bonus === 'population') return ``; if (bonus === 'archers') return ``; if (bonus === 'cavalry') return ``; } // add line for each resource function resourcesEditorAddLines() { const addTitle = (string, max) => (string.length < max ? '' : `title="${string}"`); let lines = ''; for (const r of pack.resources) { const stroke = Resources.getStroke(r.color); const model = r.model.replaceAll('_', ' '); const bonusArray = Object.entries(r.bonus).map(e => Array(e[1]).fill(e[0])).flat(); //prettier-ignore const bonusHTML = bonusArray.map((bonus) => getBonusIcon(bonus)).join(''); const bonusString = Object.entries(r.bonus).map((e) => e.join(': ')).join('; '); //prettier-ignore lines += `
${r.category}
${model}
${r.cells}
${bonusHTML}
`; } body.innerHTML = lines; // update footer document.getElementById('resourcesNumber').innerHTML = pack.resources.length; // add listeners // body.querySelectorAll("div.resources").forEach(el => el.addEventListener("mouseenter", ev => resourceHighlightOn(ev))); // body.querySelectorAll("div.resources").forEach(el => el.addEventListener("mouseleave", ev => resourceHighlightOff(ev))); // body.querySelectorAll("div.states").forEach(el => el.addEventListener("click", selectResourceOnLineClick)); body.querySelectorAll('svg.icon').forEach((el) => el.addEventListener('click', resourceChangeColor)); if (body.dataset.type === 'percentage') { body.dataset.type = 'absolute'; togglePercentageMode(); } applySorting(resourcesHeader); $('#resourcesEditor').dialog({width: fitContent()}); } function changeCategory(resource, line, el) { const categories = [...new Set(pack.resources.map((r) => r.category))].sort(); const categoryOptions = (category) => categories.map((c) => ``).join(''); alertMessage.innerHTML = `
Select category:
Custom category:
`; $('#alert').dialog({ resizable: false, title: 'Change category', buttons: { Cancel: function () { $(this).dialog('close'); }, Apply: function () { applyChanges(); $(this).dialog('close'); } } }); function applyChanges() { const custom = document.getElementById('resouceCategoryAdd').value; const select = document.getElementById('resouceCategorySelect').value; const category = custom ? capitalize(custom) : select; resource.category = line.dataset.category = el.innerHTML = category; } } function changeModel(resource, line, el) { const defaultModels = Resources.defaultModels; const model = line.dataset.model; const modelOptions = Object.keys(defaultModels) .sort() .map((m) => ``) .join(''); const wikiURL = 'https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Resources:-spread-functions'; const onSelect = "resouceModelFunction.innerHTML = Resources.defaultModels[this.value] || ' '; resouceModelCustomName.value = ''; resouceModelCustomFunction.value = ''"; alertMessage.innerHTML = `
Predefined models
Name:
Function:
${defaultModels[model] || ' '}
Custom model
Name:
Function:
`; $('#alert').dialog({ resizable: false, title: 'Change spread model', buttons: { Help: () => openURL(wikiURL), Cancel: function () { $(this).dialog('close'); }, Apply: function () { applyChanges(this); } } }); function applyChanges(dialog) { const customName = document.getElementById('resouceModelCustomName').value; const customFn = document.getElementById('resouceModelCustomFunction').value; const message = document.getElementById('resourceModelMessage'); if (customName && !customFn) return (message.innerHTML = 'Error. Custom model function is required'); if (!customName && customFn) return (message.innerHTML = 'Error. Custom model name is required'); message.innerHTML = ''; if (customName && customFn) { try { const allMethods = '{' + Object.keys(Resources.methods).join(', ') + '}'; const fn = new Function(allMethods, 'return ' + customFn); fn({...Resources.methods}); } catch (err) { message.innerHTML = 'Error. ' + err.message || err; return; } resource.model = line.dataset.model = el.innerHTML = customName; el.setAttribute('title', customName.length > 7 ? customName : ''); resource.custom = customFn; $(dialog).dialog('close'); return; } const model = document.getElementById('resouceModelSelect').value; if (!model) return (message.innerHTML = 'Error. Model is not set'); resource.model = line.dataset.model = el.innerHTML = model; el.setAttribute('title', model.length > 7 ? model : ''); $(dialog).dialog('close'); } } function changeBonus(resource, line, el) { const bonuses = [...new Set(pack.resources.map((r) => Object.keys(r.bonus)).flat())].sort(); const inputs = bonuses.map( (bonus) => `
${getBonusIcon(bonus)}
${capitalize(bonus)}
` ); alertMessage.innerHTML = inputs.join(''); $('#alert').dialog({ resizable: false, title: 'Change bonus', buttons: { Cancel: function () { $(this).dialog('close'); }, Apply: function () { applyChanges(); $(this).dialog('close'); } } }); function applyChanges() { const bonusObj = {}; bonuses.forEach((bonus) => { const el = document.getElementById('resourceBonus_' + bonus); const value = parseInt(el.value); if (isNaN(value) || !value) return; bonusObj[bonus] = value; }); const bonusArray = Object.entries(bonusObj).map(e => Array(e[1]).fill(e[0])).flat(); //prettier-ignore const bonusHTML = bonusArray.map((bonus) => getBonusIcon(bonus)).join(''); const bonusString = Object.entries(bonusObj).map((e) => e.join(': ')).join('; '); //prettier-ignore resource.bonus = bonusObj; el.innerHTML = bonusHTML; line.dataset.bonus = bonusString; el.setAttribute('title', bonusString); } } function changeName(resource, name, line) { resource.name = line.dataset.name = name; } function changeValue(resource, value, line) { resource.value = line.dataset.value = +value; } function changeChance(resource, chance, line) { resource.chance = line.dataset.chance = +chance; } function resourceChangeColor() { const circle = this.querySelector('circle'); const resource = Resources.get(+this.parentNode.dataset.id); const callback = function (fill) { const stroke = Resources.getStroke(fill); circle.setAttribute('fill', fill); circle.setAttribute('stroke', stroke); resource.color = fill; resource.stroke = stroke; goods.selectAll(`circle[data-i='${resource.i}']`).attr('fill', fill).attr('stroke', stroke); }; openPicker(resource.color, callback, {allowHatching: false}); } function toggleLegend() { if (legend.selectAll('*').size()) { clearLegend(); return; } const data = pack.resources .filter((r) => r.i && r.cells) .sort((a, b) => b.cells - a.cells) .map((r) => [r.i, r.color, r.name]); drawLegend('Resources', data); } function togglePercentageMode() { if (body.dataset.type === 'absolute') { body.dataset.type = 'percentage'; const totalCells = pack.cells.resource.filter((r) => r !== 0).length; body.querySelectorAll(':scope > div').forEach(function (el) { el.querySelector('.cells').innerHTML = rn((+el.dataset.cells / totalCells) * 100) + '%'; }); } else { body.dataset.type = 'absolute'; resourcesEditorAddLines(); } } function downloadResourcesData() { let data = 'Id,Resource,Color,Category,Value,Bonus,Chance,Model,Cells\n'; // headers body.querySelectorAll(':scope > div').forEach(function (el) { data += el.dataset.id + ','; data += el.dataset.name + ','; data += el.dataset.color + ','; data += el.dataset.category + ','; data += el.dataset.value + ','; data += el.dataset.bonus + ','; data += el.dataset.chance + ','; data += el.dataset.model + ','; data += el.dataset.cells + '\n'; }); const name = getFileName('Resources') + '.csv'; downloadFile(data, name); } function closeResourcesEditor() {} }