From af62ff915c1d85ad66e75554c7c2241dfc8d7c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Anna=20Veronika?= <39062493+annapanni@users.noreply.github.com> Date: Sat, 2 Apr 2022 22:42:54 +0200 Subject: [PATCH] Dev csv (#761) * import cultures feature * remove debug messages * code cleanup --- index.html | 9 ++- modules/io/formats.js | 19 ++++++ modules/ui/cultures-editor.js | 114 +++++++++++++++++++++++++--------- 3 files changed, 110 insertions(+), 32 deletions(-) create mode 100644 modules/io/formats.js diff --git a/index.html b/index.html index a5733917..20930605 100644 --- a/index.html +++ b/index.html @@ -1426,7 +1426,7 @@

Join our Discord server and Reddit community to ask questions, get help and share maps.

- +

The project is under active development. Creator and main maintainer: Azgaar. To track the development progress see the devboard. For older versions see the changelog. Please report bugs here. You can also contact me directly via email. @@ -2610,7 +2610,7 @@ - + @@ -2852,6 +2852,7 @@ + @@ -3692,6 +3693,7 @@ + @@ -4341,7 +4343,7 @@ - + @@ -4583,6 +4585,7 @@ + diff --git a/modules/io/formats.js b/modules/io/formats.js new file mode 100644 index 00000000..329d85db --- /dev/null +++ b/modules/io/formats.js @@ -0,0 +1,19 @@ +"use strict" + +window.Formats = (function () { + async function csvParser (file, separator=",") { + const txt = await file.text(); + const rows = txt.split("\n"); + const headers = rows.shift().split(separator).map(x => x.toLowerCase()); + const data = rows.filter(a => a.trim()!=="").map(r=>r.split(separator)); + return { + headers, + data, + iterator: function* (sortf){ + const dataset = sortf? this.data.sort(sortf):this.data; + for (const d of dataset) + yield Object.fromEntries(d.map((a, i) => [this.headers[i], a])); + }}; + } + return {csvParser}; +})(); diff --git a/modules/ui/cultures-editor.js b/modules/ui/cultures-editor.js index 50b5bc63..65d5fd38 100644 --- a/modules/ui/cultures-editor.js +++ b/modules/ui/cultures-editor.js @@ -1,5 +1,6 @@ "use strict"; function editCultures() { + const cultureTypes = ["Generic", "River", "Lake", "Naval", "Nomadic", "Hunting", "Highland"]; if (customization) return; closeDialogs("#culturesEditor, .stable"); if (!layerIsOn("toggleCultures")) toggleCultures(); @@ -37,6 +38,9 @@ function editCultures() { document.getElementById("culturesEditNamesBase").addEventListener("click", editNamesbase); document.getElementById("culturesAdd").addEventListener("click", enterAddCulturesMode); document.getElementById("culturesExport").addEventListener("click", downloadCulturesData); + document.getElementById("culturesImport").addEventListener("click", () => document.getElementById("culturesCSVToLoad").click()); + + document.getElementById("culturesCSVToLoad").addEventListener("change", uploadCulturesData); function refreshCulturesEditor() { culturesCollectStatistics(); @@ -169,8 +173,7 @@ function editCultures() { function getTypeOptions(type) { let options = ""; - const types = ["Generic", "River", "Lake", "Naval", "Nomadic", "Hunting", "Highland"]; - types.forEach(t => (options += ``)); + cultureTypes.forEach(t => (options += ``)); return options; } @@ -366,7 +369,7 @@ function editCultures() { width: "24em", buttons: { Apply: function () { - applyPopulationChange(); + applyPopulationChange(rural, urban, ruralPop.value, urbanPop.value, culture); $(this).dialog("close"); }, Cancel: function () { @@ -375,32 +378,33 @@ function editCultures() { }, position: {my: "center", at: "center", of: "svg"} }); + } - function applyPopulationChange() { - const ruralChange = ruralPop.value / rural; - if (isFinite(ruralChange) && ruralChange !== 1) { - const cells = pack.cells.i.filter(i => pack.cells.culture[i] === culture); - cells.forEach(i => (pack.cells.pop[i] *= ruralChange)); - } - if (!isFinite(ruralChange) && +ruralPop.value > 0) { - const points = ruralPop.value / populationRate; - const cells = pack.cells.i.filter(i => pack.cells.culture[i] === culture); - const pop = rn(points / cells.length); - cells.forEach(i => (pack.cells.pop[i] = pop)); - } - - const urbanChange = urbanPop.value / urban; - if (isFinite(urbanChange) && urbanChange !== 1) { - burgs.forEach(b => (b.population = rn(b.population * urbanChange, 4))); - } - if (!isFinite(urbanChange) && +urbanPop.value > 0) { - const points = urbanPop.value / populationRate / urbanization; - const population = rn(points / burgs.length, 4); - burgs.forEach(b => (b.population = population)); - } - - refreshCulturesEditor(); + function applyPopulationChange(oldRural, oldUrban, newRural, newUrban, culture) { + const ruralChange = newRural / oldRural; + if (isFinite(ruralChange) && ruralChange !== 1) { + const cells = pack.cells.i.filter(i => pack.cells.culture[i] === culture); + cells.forEach(i => (pack.cells.pop[i] *= ruralChange)); } + if (!isFinite(ruralChange) && +newRural > 0) { + const points = newRural / populationRate; + const cells = pack.cells.i.filter(i => pack.cells.culture[i] === culture); + const pop = rn(points / cells.length); + cells.forEach(i => (pack.cells.pop[i] = pop)); + } + + const burgs = pack.burgs.filter(b => !b.removed && b.culture === culture); + const urbanChange = newUrban / oldUrban; + if (isFinite(urbanChange) && urbanChange !== 1) { + burgs.forEach(b => (b.population = rn(b.population * urbanChange, 4))); + } + if (!isFinite(urbanChange) && +newUrban > 0) { + const points = newUrban / populationRate / urbanization; + const population = rn(points / burgs.length, 4); + burgs.forEach(b => (b.population = population)); + } + + refreshCulturesEditor(); } function cultureRegenerateBurgs() { @@ -856,7 +860,7 @@ function editCultures() { function downloadCulturesData() { const unit = areaUnit.value === "square" ? distanceUnitInput.value + "2" : areaUnit.value; - let data = "Id,Culture,Color,Cells,Expansionism,Type,Area " + unit + ",Population,Namesbase,Emblems Shape\n"; // headers + let data = "Id,Culture,Color,Cells,Expansionism,Type,Area " + unit + ",Population,Namesbase,Emblems Shape,Origin\n"; // headers body.querySelectorAll(":scope > div").forEach(function (el) { data += el.dataset.id + ","; @@ -869,7 +873,8 @@ function editCultures() { data += el.dataset.population + ","; const base = +el.dataset.base; data += nameBases[base].name + ","; - data += el.dataset.emblems + "\n"; + data += el.dataset.emblems + ","; + data += pack.cultures[+el.dataset.id].origin + "\n"; }); const name = getFileName("Cultures") + ".csv"; @@ -881,4 +886,55 @@ function editCultures() { exitCulturesManualAssignment("close"); exitAddCultureMode(); } + async function uploadCulturesData() { + const csv = await Formats.csvParser(this.files[0]); + this.value = ""; + const cultures = pack.cultures; + const shapes = Object.keys(COA.shields.types) + .map(type => Object.keys(COA.shields[type])) + .flat(); + const populated = pack.cells.pop.map((c, i) => c? i: null).filter(c => c); + cultures.forEach((item) => {if (item.i) item.removed = true}); + for (const c of csv.iterator((a, b) => +a[0] > +b[0])) { + let current; + if (+c.id < cultures.length) { + current = cultures[c.id]; + const ratio = current.urban / (current.rural + current.urban); + applyPopulationChange(current.rural, current.urban, c.population*(1 - ratio), c.population*ratio, +c.id); + } else { + current = { + i: cultures.length, + center: ra(populated), + area: 0, + cells: 0, + origin: 0, + rural: 0, + urban: 0, + } + cultures.push(current) + } + current.name = c.culture; + current.code = abbreviate(current.name, cultures.map(c => c.code)); + current.color = c.color; + current.expansionism = +c.expansionism; + current.origin = +c.origin; + if (cultureTypes.includes(c.type)) + current.type = c.type; + else + current.type = "Generic"; + current.removed = false; + const shieldShape = c["emblems shape"].toLowerCase(); + if (shapes.includes(shieldShape)) + current.shield = shieldShape + else + current.shield = "heater"; + + const nbi = nameBases.findIndex(n => n.name==c.namesbase); + current.base = nbi==-1? 0: nbi; + } + const validId = cultures.filter(c => !c.removed).map(c => c.i); + cultures.forEach(item => item.origin = validId.includes(item.origin)? item.origin:0); + cultures[0].origin = null; + refreshCulturesEditor(); + } }