mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
Dev csv (#761)
* import cultures feature * remove debug messages * code cleanup
This commit is contained in:
parent
1384daf6f9
commit
af62ff915c
3 changed files with 110 additions and 32 deletions
|
|
@ -1426,7 +1426,7 @@
|
|||
<p>
|
||||
Join our <a href='https://discordapp.com/invite/X7E84HU' target='_blank'>Discord server</a> and <a href="https://www.reddit.com/r/FantasyMapGenerator/" target="_blank">Reddit community</a> to ask questions, get help and share maps.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
The project is under active development. Creator and main maintainer: Azgaar. To track the development progress see the <a href="https://trello.com/b/7x832DG4/fantasy-map-generator" target="_blank">devboard</a>.
|
||||
For older versions see the <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Changelog" target="_blank">changelog</a>. Please report bugs <a href="https://github.com/Azgaar/Fantasy-Map-Generator/issues" target="_blank">here</a>. You can also contact me directly via <a href="mailto:azgaar.fmg@yandex.by" target="_blank">email</a>.
|
||||
|
|
@ -2610,7 +2610,7 @@
|
|||
<option value="Sultanate">Sultanate</option>
|
||||
<option value="Tsardom">Tsardom</option>
|
||||
<option value="Ulus">Ulus</option>
|
||||
<option value="Viceroyalty">Viceroyalty</option>
|
||||
<option value="Viceroyalty">Viceroyalty</option>
|
||||
</optgroup>
|
||||
<optgroup label="Republic">
|
||||
<option value="Chancellery">Chancellery</option>
|
||||
|
|
@ -2852,6 +2852,7 @@
|
|||
<button id="culturesEditNamesBase" data-tip="Edit a database used for names generation" class="icon-font"></button>
|
||||
<button id="culturesAdd" data-tip="Add a new culture. Hold Shift to add multiple" class="icon-plus"></button>
|
||||
<button id="culturesExport" data-tip="Download cultures-related data" class="icon-download"></button>
|
||||
<button id="culturesImport" data-tip="Upload cultures-related data" class="icon-upload"></button>
|
||||
<button id="culturesRecalculate" data-tip="Recalculate cultures based on current values of growth-related attributes" class="icon-retweet"></button>
|
||||
<span data-tip="Allow culture centers, expansion and type changes to take an immediate effect">
|
||||
<input id="culturesAutoChange" class="checkbox" type="checkbox">
|
||||
|
|
@ -3692,6 +3693,7 @@
|
|||
<input type="file" accept=".txt" id="templateToLoad">
|
||||
<input type="file" accept=".txt" id="namesbaseToLoad">
|
||||
<input type="file" accept=".json" id="styleToLoad">
|
||||
<input type="file" accept=".csv" id="culturesCSVToLoad">
|
||||
</div>
|
||||
|
||||
<!-- svg elements not required for map display -->
|
||||
|
|
@ -4341,7 +4343,7 @@
|
|||
<path d="M 43.4,0 36.2,12.5 43.4,25 M 21.7,12.5 H 36.2 Z M 0,0 H 14.5 L 21.7,12.5 14.5,25 H 0"/>
|
||||
</pattern>
|
||||
</g>
|
||||
|
||||
|
||||
<g id="defs-hatching">
|
||||
<pattern id="hatch0" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:2"/>
|
||||
|
|
@ -4583,6 +4585,7 @@
|
|||
<script defer src="modules/io/cloud.js"></script>
|
||||
<script defer src="modules/io/export.js"></script>
|
||||
<script defer src="modules/io/export-json.js"></script>
|
||||
<script defer src="modules/io/formats.js"></script>
|
||||
|
||||
<!-- Web Components -->
|
||||
<script defer src="components/fill-box.js"></script>
|
||||
|
|
|
|||
19
modules/io/formats.js
Normal file
19
modules/io/formats.js
Normal file
|
|
@ -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};
|
||||
})();
|
||||
|
|
@ -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 += `<option ${type === t ? "selected" : ""} value="${t}">${t}</option>`));
|
||||
cultureTypes.forEach(t => (options += `<option ${type === t ? "selected" : ""} value="${t}">${t}</option>`));
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue