mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 01:41:22 +01:00
v1.0
This commit is contained in:
parent
5f9cab4f84
commit
cab429a346
58 changed files with 6413 additions and 1489 deletions
521
modules/ui/provinces-editor.js
Normal file
521
modules/ui/provinces-editor.js
Normal file
|
|
@ -0,0 +1,521 @@
|
|||
"use strict";
|
||||
function editProvinces() {
|
||||
if (customization) return;
|
||||
closeDialogs("#provincesEditor, .stable");
|
||||
if (!layerIsOn("toggleProvinces")) toggleProvinces();
|
||||
if (!layerIsOn("toggleBorders")) toggleBorders();
|
||||
if (layerIsOn("toggleStates")) toggleStates();
|
||||
if (layerIsOn("toggleCultures")) toggleCultures();
|
||||
|
||||
const body = document.getElementById("provincesBodySection");
|
||||
refreshProvincesEditor();
|
||||
|
||||
if (modules.editProvinces) return;
|
||||
modules.editProvinces = true;
|
||||
|
||||
$("#provincesEditor").dialog({
|
||||
title: "Provinces Editor", resizable: false, width: fitContent(), close: closeProvincesEditor,
|
||||
position: {my: "right top", at: "right-10 top+10", of: "svg", collision: "fit"}
|
||||
});
|
||||
|
||||
// add listeners
|
||||
document.getElementById("provincesEditorRefresh").addEventListener("click", refreshProvincesEditor);
|
||||
document.getElementById("provincesFilterState").addEventListener("change", provincesEditorAddLines);
|
||||
document.getElementById("provincesPercentage").addEventListener("click", togglePercentageMode);
|
||||
document.getElementById("provincesToggleLabels").addEventListener("click", toggleLabels);
|
||||
document.getElementById("provincesExport").addEventListener("click", downloadProvincesData);
|
||||
document.getElementById("provincesRemoveAll").addEventListener("click", removeAllProvinces);
|
||||
document.getElementById("provincesManually").addEventListener("click", enterProvincesManualAssignent);
|
||||
document.getElementById("provincesManuallyApply").addEventListener("click", applyProvincesManualAssignent);
|
||||
document.getElementById("provincesManuallyCancel").addEventListener("click", () => exitProvincesManualAssignment());
|
||||
document.getElementById("provincesAdd").addEventListener("click", enterAddProvinceMode);
|
||||
|
||||
body.addEventListener("click", function(ev) {
|
||||
if (customization) return;
|
||||
const el = ev.target, cl = el.classList, line = el.parentNode, p = +line.dataset.id;
|
||||
if (cl.contains("zoneFill")) changeFill(el); else
|
||||
if (cl.contains("icon-fleur")) provinceOpenCOA(p); else
|
||||
if (cl.contains("icon-star-empty")) capitalZoomIn(p); else
|
||||
if (cl.contains("icon-pin")) focusOn(p, cl); else
|
||||
if (cl.contains("icon-trash-empty")) removeProvince(p);
|
||||
if (cl.contains("hoverButton") && cl.contains("stateName")) regenerateName(p, line); else
|
||||
if (cl.contains("hoverButton") && cl.contains("stateForm")) regenerateForm(p, line);
|
||||
});
|
||||
|
||||
body.addEventListener("input", function(ev) {
|
||||
const el = ev.target, cl = el.classList, line = el.parentNode, p = +line.dataset.id;
|
||||
if (cl.contains("stateName")) changeName(p, line, el.value); else
|
||||
if (cl.contains("stateForm")) changeForm(p, line, el.value); else
|
||||
if (cl.contains("cultureBase")) changeCapital(p, line, el.value);
|
||||
});
|
||||
|
||||
function refreshProvincesEditor() {
|
||||
collectStatistics();
|
||||
updateFilter();
|
||||
provincesEditorAddLines();
|
||||
}
|
||||
|
||||
function collectStatistics() {
|
||||
const cells = pack.cells, provinces = pack.provinces;
|
||||
provinces.forEach(p => {
|
||||
if (!p.i) return;
|
||||
p.area = p.rural = p.urban = 0;
|
||||
p.burgs = [];
|
||||
});
|
||||
|
||||
for (const i of cells.i) {
|
||||
const p = cells.province[i];
|
||||
if (!p) continue;
|
||||
|
||||
provinces[p].area += cells.area[i];
|
||||
provinces[p].rural += cells.pop[i];
|
||||
if (!cells.burg[i]) continue;
|
||||
provinces[p].urban += pack.burgs[cells.burg[i]].population;
|
||||
provinces[p].burgs.push(cells.burg[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function updateFilter() {
|
||||
const stateFilter = document.getElementById("provincesFilterState");
|
||||
const selectedState = stateFilter.value || 1;
|
||||
stateFilter.options.length = 0; // remove all options
|
||||
stateFilter.options.add(new Option(`all`, -1, false, selectedState == -1));
|
||||
const statesSorted = pack.states.filter(s => s.i && !s.removed).sort((a, b) => (a.name > b.name) ? 1 : -1);
|
||||
statesSorted.forEach(s => stateFilter.options.add(new Option(s.name, s.i, false, s.i == selectedState)));
|
||||
}
|
||||
|
||||
// add line for each state
|
||||
function provincesEditorAddLines() {
|
||||
const unit = areaUnit.value === "square" ? " " + distanceUnitInput.value + "²" : " " + areaUnit.value;
|
||||
const selectedState = +document.getElementById("provincesFilterState").value;
|
||||
let filtered = pack.provinces.filter(p => p.i && !p.removed); // all valid burgs
|
||||
if (selectedState != -1) filtered = filtered.filter(p => p.state === selectedState); // filtered by state
|
||||
body.innerHTML = "";
|
||||
let lines = "", totalArea = 0, totalPopulation = 0;
|
||||
|
||||
for (const p of filtered) {
|
||||
const area = p.area * (distanceScaleInput.value ** 2);
|
||||
totalArea += area;
|
||||
const rural = p.rural * populationRate.value;
|
||||
const urban = p.urban * populationRate.value * urbanization.value;
|
||||
const population = rn(rural + urban);
|
||||
const populationTip = `Total population: ${si(population)}; Rural population: ${si(rural)}; Urban population: ${si(urban)}`;
|
||||
totalPopulation += population;
|
||||
|
||||
const stateName = pack.states[p.state].name;
|
||||
const capital = p.burg ? pack.burgs[p.burg].name : '';
|
||||
const focused = defs.select("#fog #focusProvince"+p.i).size();
|
||||
lines += `<div class="states" data-id=${p.i} data-name=${p.name} data-form=${p.formName} data-color="${p.color}" data-capital="${capital}" data-state="${stateName}" data-area=${area} data-population=${population}>
|
||||
<svg data-tip="Province fill style. Click to change" width="9" height="9" style="margin-bottom:-1px"><rect x="0" y="0" width="9" height="9" fill="${p.color}" class="zoneFill"></svg>
|
||||
<input data-tip="Province name. Click and type to change" class="stateName" value="${p.name}" autocorrect="off" spellcheck="false">
|
||||
<span data-tip="Click to re-generate province name" class="icon-arrows-cw stateName hoverButton placeholder"></span>
|
||||
<span data-tip="Click to open province COA in the Iron Arachne Heraldry Generator" class="icon-fleur pointer hide"></span>
|
||||
<input data-tip="Province form name. Click and type to change" class="stateForm" value="${p.formName}" autocorrect="off" spellcheck="false">
|
||||
<span data-tip="Click to re-generate form name" class="icon-arrows-cw stateForm hoverButton placeholder"></span>
|
||||
<span data-tip="Province capital. Click to zoom into view" class="icon-star-empty pointer hide ${p.burg?'':'placeholder'}"></span>
|
||||
<select data-tip="Province capital. Click to select from burgs within the state. No capital means the province is governed from the state capital" class="cultureBase hide ${p.burgs.length?'':'placeholder'}">${p.burgs.length ? getCapitalOptions(p.burgs, p.burg) : ''}</select>
|
||||
<input data-tip="Province owner" class="provinceOwner" value="${stateName}" disabled hide">
|
||||
<span data-tip="Province area" style="padding-right: 4px" class="icon-map-o hide"></span>
|
||||
<div data-tip="Province area" class="biomeArea hide">${si(area) + unit}</div>
|
||||
<span data-tip="${populationTip}" class="icon-male hide"></span>
|
||||
<div data-tip="${populationTip}" class="culturePopulation hide">${si(population)}</div>
|
||||
<span data-tip="Toggle province focus" class="icon-pin ${focused?'':' inactive'} hide"></span>
|
||||
<span data-tip="Remove the province" class="icon-trash-empty hide"></span>
|
||||
</div>`;
|
||||
}
|
||||
body.innerHTML = lines;
|
||||
|
||||
// update footer
|
||||
provincesFooterNumber.innerHTML = filtered.length;
|
||||
provincesFooterArea.innerHTML = filtered.length ? si(totalArea / filtered.length) + unit : 0 + unit;
|
||||
provincesFooterPopulation.innerHTML = filtered.length ? si(totalPopulation / filtered.length) : 0;
|
||||
provincesFooterArea.dataset.area = totalArea;
|
||||
provincesFooterPopulation.dataset.population = totalPopulation;
|
||||
|
||||
body.querySelectorAll("div.states").forEach(el => {
|
||||
el.addEventListener("click", selectProvinceOnLineClick);
|
||||
el.addEventListener("mouseenter", ev => provinceHighlightOn(ev));
|
||||
el.addEventListener("mouseleave", ev => provinceHighlightOff(ev));
|
||||
});
|
||||
|
||||
if (body.dataset.type === "percentage") {body.dataset.type = "absolute"; togglePercentageMode();}
|
||||
applySorting(provincesHeader);
|
||||
$("#provincesEditor").dialog({width: fitContent()});
|
||||
}
|
||||
|
||||
function getCapitalOptions(burgs, capital) {
|
||||
let options = "";
|
||||
burgs.forEach(b => options += `<option ${b === capital ? "selected" : ""} value="${b}">${pack.burgs[b].name}</option>`);
|
||||
return options;
|
||||
}
|
||||
|
||||
function provinceHighlightOn(event) {
|
||||
if (!customization) event.target.querySelectorAll(".hoverButton").forEach(el => el.classList.remove("placeholder"));
|
||||
if (!layerIsOn("toggleProvinces")) return;
|
||||
if (customization) return;
|
||||
const province = +event.target.dataset.id;
|
||||
const animate = d3.transition().duration(2000).ease(d3.easeSinIn);
|
||||
provs.select("#province"+province).raise().transition(animate).attr("stroke-width", 2.5).attr("stroke", "#d0240f");
|
||||
}
|
||||
|
||||
function provinceHighlightOff(event) {
|
||||
if (!customization) event.target.querySelectorAll(".hoverButton").forEach(el => el.classList.add("placeholder"));
|
||||
if (!layerIsOn("toggleProvinces")) return;
|
||||
const province = +event.target.dataset.id;
|
||||
provs.select("#province"+province).transition().attr("stroke-width", null).attr("stroke", null);
|
||||
}
|
||||
|
||||
function changeFill(el) {
|
||||
const currentFill = el.getAttribute("fill");
|
||||
const p = +el.parentNode.parentNode.dataset.id;
|
||||
|
||||
const callback = function(fill) {
|
||||
el.setAttribute("fill", fill);
|
||||
pack.provinces[p].color = fill;
|
||||
const g = provs.select("#provincesBody");
|
||||
g.select("#province"+p).attr("fill", fill);
|
||||
g.select("#province-gap"+p).attr("stroke", fill);
|
||||
}
|
||||
|
||||
openPicker(currentFill, callback);
|
||||
}
|
||||
|
||||
function provinceOpenCOA(p) {
|
||||
const url = `https://ironarachne.com/heraldry/${seed}-p${p}`;
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
|
||||
function capitalZoomIn(p) {
|
||||
const capital = pack.provinces[p].burg;
|
||||
const l = burgLabels.select("[data-id='" + capital + "']");
|
||||
const x = +l.attr("x"), y = +l.attr("y");
|
||||
zoomTo(x, y, 8, 2000);
|
||||
}
|
||||
|
||||
function focusOn(p, cl) {
|
||||
const inactive = cl.contains("inactive");
|
||||
cl.toggle("inactive");
|
||||
|
||||
if (inactive) {
|
||||
if (defs.select("#fog #focusProvince"+p).size()) return;
|
||||
fogging.attr("display", "block");
|
||||
const path = provs.select("#province"+p).attr("d");
|
||||
defs.select("#fog").append("path").attr("d", path).attr("fill", "black").attr("id", "focusProvince"+p);
|
||||
fogging.append("path").attr("d", path).attr("id", "focusProvinceHalo"+p)
|
||||
.attr("fill", "none").attr("stroke", pack.provinces[p].color).attr("filter", "url(#blur5)");
|
||||
} else unfocus(p);
|
||||
}
|
||||
|
||||
function unfocus(p) {
|
||||
defs.select("#focusProvince"+p).remove();
|
||||
fogging.select("#focusProvinceHalo"+p).remove();
|
||||
if (!defs.selectAll("#fog path").size()) fogging.attr("display", "none"); // all items are de-focused
|
||||
}
|
||||
|
||||
function removeProvince(p) {
|
||||
pack.cells.province.forEach((province, i) => {if(province === p) pack.cells.province[i] = 0;});
|
||||
const state = pack.provinces[p].state;
|
||||
if (pack.states[state].provinces.includes(p)) pack.states[state].provinces.splice(pack.states[state].provinces.indexOf(p), 1);
|
||||
pack.provinces[p].removed = true;
|
||||
unfocus(p);
|
||||
|
||||
const g = provs.select("#provincesBody");
|
||||
g.select("#province"+p).remove();
|
||||
g.select("#province-gap"+p).remove();
|
||||
if (!layerIsOn("toggleBorders")) toggleBorders(); else drawBorders();
|
||||
refreshProvincesEditor();
|
||||
}
|
||||
|
||||
function changeName(p, line, value) {
|
||||
pack.provinces[p].name = line.querySelector(".stateName").value = line.dataset.name = value;
|
||||
pack.provinces[p].fullName = value + " " + pack.provinces[p].formName;
|
||||
provs.select("#provinceLabel"+p).text(value);
|
||||
}
|
||||
|
||||
function regenerateName(p, line) {
|
||||
const c = pack.cells.culture[pack.provinces[p].center];
|
||||
const name = Names.getState(Names.getCultureShort(c), c);
|
||||
changeName(p, line, name);
|
||||
}
|
||||
|
||||
function changeForm(p, line, value) {
|
||||
pack.provinces[p].formName = line.querySelector(".stateForm").value = line.dataset.form = value;
|
||||
pack.provinces[p].fullName = pack.provinces[p].name + " " + value;
|
||||
}
|
||||
|
||||
function regenerateForm(p, line) {
|
||||
const forms = ["County", "Earldom", "Shire", "Landgrave", 'Margrave', "Barony", "Province",
|
||||
"Department", "Governorate", "State", "Canton", "Prefecture", "Parish", "Deanery",
|
||||
"Council", "District", "Republic", "Territory", "Land", "Region"];
|
||||
changeForm(p, line, ra(forms));
|
||||
}
|
||||
|
||||
function changeCapital(p, line, value) {
|
||||
line.dataset.capital = pack.burgs[+value].name;
|
||||
pack.provinces[p].center = pack.burgs[+value].cell;
|
||||
pack.provinces[p].burg = +value;
|
||||
}
|
||||
|
||||
function togglePercentageMode() {
|
||||
if (body.dataset.type === "absolute") {
|
||||
body.dataset.type = "percentage";
|
||||
const totalArea = +provincesFooterArea.dataset.area;
|
||||
const totalPopulation = +provincesFooterPopulation.dataset.population;
|
||||
|
||||
body.querySelectorAll(":scope > div").forEach(function(el) {
|
||||
el.querySelector(".biomeArea").innerHTML = rn(+el.dataset.area / totalArea * 100) + "%";
|
||||
el.querySelector(".culturePopulation").innerHTML = rn(+el.dataset.population / totalPopulation * 100) + "%";
|
||||
});
|
||||
} else {
|
||||
body.dataset.type = "absolute";
|
||||
provincesEditorAddLines();
|
||||
}
|
||||
}
|
||||
|
||||
function toggleLabels() {
|
||||
const hidden = provs.select("#provinceLabels").style("display") === "none";
|
||||
provs.select("#provinceLabels").style("display", `${hidden ? "block" : "none"}`);
|
||||
provs.attr("data-labels", +hidden);
|
||||
}
|
||||
|
||||
function enterProvincesManualAssignent() {
|
||||
if (!layerIsOn("toggleProvinces")) toggleProvinces();
|
||||
if (!layerIsOn("toggleBorders")) toggleBorders();
|
||||
|
||||
customization = 11;
|
||||
provs.select("g#provincesBody").append("g").attr("id", "temp");
|
||||
provs.select("g#provincesBody").append("g").attr("id", "centers")
|
||||
.attr("fill", "none").attr("stroke", "#ff0000").attr("stroke-width", 1);
|
||||
|
||||
document.querySelectorAll("#provincesBottom > *").forEach(el => el.style.display = "none");
|
||||
document.getElementById("provincesManuallyButtons").style.display = "inline-block";
|
||||
|
||||
provincesEditor.querySelectorAll(".hide").forEach(el => el.classList.add("hidden"));
|
||||
provincesFooter.style.display = "none";
|
||||
body.querySelectorAll("div > input, select, span, svg").forEach(e => e.style.pointerEvents = "none");
|
||||
$("#provincesEditor").dialog({position: {my: "right top", at: "right-10 top+10", of: "svg", collision: "fit"}});
|
||||
|
||||
tip("Click on a province to select, drag the circle to change province", true);
|
||||
viewbox.style("cursor", "crosshair")
|
||||
.on("click", selectProvinceOnMapClick)
|
||||
.call(d3.drag().on("start", dragBrush))
|
||||
.on("touchmove mousemove", moveBrush);
|
||||
|
||||
body.querySelector("div").classList.add("selected");
|
||||
}
|
||||
|
||||
function selectProvinceOnLineClick() {
|
||||
if (customization !== 11) return;
|
||||
if (this.parentNode.id !== "provincesBodySection") return;
|
||||
body.querySelector("div.selected").classList.remove("selected");
|
||||
this.classList.add("selected");
|
||||
}
|
||||
|
||||
function selectProvinceOnMapClick() {
|
||||
const point = d3.mouse(this);
|
||||
const i = findCell(point[0], point[1]);
|
||||
if (pack.cells.h[i] < 20 || !pack.cells.state[i]) return;
|
||||
|
||||
const assigned = provs.select("g#temp").select("polygon[data-cell='"+i+"']");
|
||||
const province = assigned.size() ? +assigned.attr("data-province") : pack.cells.province[i];
|
||||
|
||||
const editorLine = body.querySelector("div[data-id='"+province+"']");
|
||||
if (!editorLine) {tip("You cannot select a province if it is not in the Editor list", false, "error"); return;}
|
||||
|
||||
body.querySelector("div.selected").classList.remove("selected");
|
||||
editorLine.classList.add("selected");
|
||||
}
|
||||
|
||||
function dragBrush() {
|
||||
const r = +provincesManuallyBrush.value;
|
||||
|
||||
d3.event.on("drag", () => {
|
||||
if (!d3.event.dx && !d3.event.dy) return;
|
||||
const p = d3.mouse(this);
|
||||
moveCircle(p[0], p[1], r);
|
||||
|
||||
const found = r > 5 ? findAll(p[0], p[1], r) : [findCell(p[0], p[1], r)];
|
||||
const selection = found.filter(isLand);
|
||||
if (selection) changeForSelection(selection);
|
||||
});
|
||||
}
|
||||
|
||||
// change province within selection
|
||||
function changeForSelection(selection) {
|
||||
const temp = provs.select("#temp"), centers = provs.select("#centers");
|
||||
const selected = body.querySelector("div.selected");
|
||||
|
||||
const provinceNew = +selected.dataset.id;
|
||||
const state = pack.provinces[provinceNew].state;
|
||||
const fill = pack.provinces[provinceNew].color || "#ffffff";
|
||||
const stroke = d3.color(fill).darker(.2).hex();
|
||||
|
||||
selection.forEach(i => {
|
||||
if (!pack.cells.state[i] || pack.cells.state[i] !== state) return;
|
||||
const exists = temp.select("polygon[data-cell='"+i+"']");
|
||||
const provinceOld = exists.size() ? +exists.attr("data-province") : pack.cells.province[i];
|
||||
if (provinceNew === provinceOld) return;
|
||||
if (i === pack.provinces[provinceOld].center) {
|
||||
const center = centers.select("polygon[data-center='"+i+"']");
|
||||
if (!center.size()) centers.append("polygon").attr("data-center", i).attr("points", getPackPolygon(i));
|
||||
tip("Province center cannot be assigned to a different region. Please remove the province first", false, "error");
|
||||
return;
|
||||
}
|
||||
|
||||
// change of append new element
|
||||
if (exists.size()) exists.attr("data-province", provinceNew).attr("fill", fill).attr("stroke", stroke);
|
||||
else temp.append("polygon").attr("points", getPackPolygon(i))
|
||||
.attr("data-cell", i).attr("data-province", provinceNew)
|
||||
.attr("fill", fill).attr("stroke", stroke);
|
||||
});
|
||||
}
|
||||
|
||||
function moveBrush() {
|
||||
showMainTip();
|
||||
const point = d3.mouse(this);
|
||||
const radius = +provincesManuallyBrush.value;
|
||||
moveCircle(point[0], point[1], radius);
|
||||
}
|
||||
|
||||
function applyProvincesManualAssignent() {
|
||||
provs.select("#temp").selectAll("polygon").each(function() {
|
||||
const i = +this.dataset.cell;
|
||||
pack.cells.province[i] = +this.dataset.province;;
|
||||
});
|
||||
|
||||
if (!layerIsOn("toggleBorders")) toggleBorders(); else drawBorders();
|
||||
if (!layerIsOn("toggleProvinces")) toggleProvinces(); else drawProvinces();
|
||||
exitProvincesManualAssignment();
|
||||
refreshProvincesEditor();
|
||||
}
|
||||
|
||||
function exitProvincesManualAssignment(close) {
|
||||
customization = 0;
|
||||
provs.select("#temp").remove();
|
||||
provs.select("#centers").remove();
|
||||
removeCircle();
|
||||
|
||||
document.querySelectorAll("#provincesBottom > *").forEach(el => el.style.display = "inline-block");
|
||||
document.getElementById("provincesManuallyButtons").style.display = "none";
|
||||
|
||||
provincesEditor.querySelectorAll(".hide:not(.show)").forEach(el => el.classList.remove("hidden"));
|
||||
provincesFooter.style.display = "block";
|
||||
body.querySelectorAll("div > input, select, span, svg").forEach(e => e.style.pointerEvents = "all");
|
||||
if(!close) $("#provincesEditor").dialog({position: {my: "right top", at: "right-10 top+10", of: "svg", collision: "fit"}});
|
||||
|
||||
restoreDefaultEvents();
|
||||
clearMainTip();
|
||||
const selected = body.querySelector("div.selected");
|
||||
if (selected) selected.classList.remove("selected");
|
||||
}
|
||||
|
||||
function enterAddProvinceMode() {
|
||||
if (this.classList.contains("pressed")) {exitAddProvinceMode(); return;};
|
||||
customization = 12;
|
||||
this.classList.add("pressed");
|
||||
tip("Click on the map to place a new province center", true);
|
||||
viewbox.style("cursor", "crosshair").on("click", addProvince);
|
||||
body.querySelectorAll("div > input, select, span, svg").forEach(e => e.style.pointerEvents = "none");
|
||||
}
|
||||
|
||||
function addProvince() {
|
||||
const cells = pack.cells, provinces = pack.provinces;
|
||||
const point = d3.mouse(this);
|
||||
const center = findCell(point[0], point[1]);
|
||||
if (cells.h[center] < 20) {tip("You cannot place province into the water. Please click on a land cell", false, "error"); return;}
|
||||
const oldProvince = cells.province[center];
|
||||
if (oldProvince && provinces[oldProvince].center === center) {tip("The cell is already a center of a different province. Select other cell", false, "error"); return;}
|
||||
const state = cells.state[center];
|
||||
if (!state) {tip("You cannot create a province in neutral lands> Please assign this land to a state first", false, "error"); return;}
|
||||
|
||||
if (d3.event.shiftKey === false) exitAddProvinceMode();
|
||||
|
||||
const province = provinces.length;
|
||||
pack.states[state].provinces.push(province);
|
||||
const burg = cells.burg[center];
|
||||
const c = cells.culture[center];
|
||||
const name = burg ? pack.burgs[burg].name : Names.getState(Names.getCultureShort(c), c);
|
||||
const formName = oldProvince ? provinces[oldProvince].formName : "Province";
|
||||
const fullName = name + " " + formName;
|
||||
const stateColor = pack.states[state].color, rndColor = getRandomColor();
|
||||
const color = stateColor[0] === "#" ? d3.color(d3.interpolate(stateColor, rndColor)(.2)).hex() : rndColor;
|
||||
provinces.push({i:province, state, center, burg, name, formName, fullName, color});
|
||||
|
||||
cells.province[center] = province;
|
||||
cells.c[center].forEach(c => {
|
||||
if (cells.h[c] < 20 || cells.state[c] !== state) return;
|
||||
if (provinces.find(p => !p.removed && p.center === c)) return;
|
||||
cells.province[c] = province;
|
||||
});
|
||||
|
||||
if (!layerIsOn("toggleBorders")) toggleBorders(); else drawBorders();
|
||||
if (!layerIsOn("toggleProvinces")) toggleProvinces(); else drawProvinces();
|
||||
collectStatistics();
|
||||
document.getElementById("provincesFilterState").value = state;
|
||||
provincesEditorAddLines();
|
||||
}
|
||||
|
||||
function exitAddProvinceMode() {
|
||||
customization = 0;
|
||||
restoreDefaultEvents();
|
||||
clearMainTip();
|
||||
body.querySelectorAll("div > input, select, span, svg").forEach(e => e.style.pointerEvents = "all");
|
||||
if (provincesAdd.classList.contains("pressed")) provincesAdd.classList.remove("pressed");
|
||||
}
|
||||
|
||||
function downloadProvincesData() {
|
||||
const unit = areaUnit.value === "square" ? distanceUnitInput.value + "2" : areaUnit.value;
|
||||
let data = "Id,Province,Form,State,Color,Capital,Area "+unit+",Population\n"; // headers
|
||||
|
||||
body.querySelectorAll(":scope > div").forEach(function(el) {
|
||||
data += el.dataset.id + ",";
|
||||
data += el.dataset.name + ",";
|
||||
data += el.dataset.form + ",";
|
||||
data += el.dataset.state + ",";
|
||||
data += el.dataset.color + ",";
|
||||
data += el.dataset.capital + ",";
|
||||
data += el.dataset.area + ",";
|
||||
data += el.dataset.population + "\n";
|
||||
});
|
||||
|
||||
const dataBlob = new Blob([data], {type: "text/plain"});
|
||||
const url = window.URL.createObjectURL(dataBlob);
|
||||
const link = document.createElement("a");
|
||||
document.body.appendChild(link);
|
||||
link.download = "provinces_data" + Date.now() + ".csv";
|
||||
link.href = url;
|
||||
link.click();
|
||||
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);
|
||||
}
|
||||
|
||||
function removeAllProvinces() {
|
||||
alertMessage.innerHTML = `Are you sure you want to remove all provinces?`;
|
||||
$("#alert").dialog({resizable: false, title: "Remove all provinces",
|
||||
buttons: {
|
||||
Remove: function() {
|
||||
$(this).dialog("close");
|
||||
pack.provinces.filter(p => p.i).forEach(p => {
|
||||
p.removed = true;
|
||||
unfocus(p.i);
|
||||
});
|
||||
pack.cells.i.forEach(i => pack.cells.province[i] = 0);
|
||||
pack.states.filter(s => s.i && !s.removed).forEach(s => s.provinces = []);
|
||||
|
||||
if (!layerIsOn("toggleBorders")) toggleBorders(); else drawBorders();
|
||||
provs.select("#provincesBody").remove();
|
||||
turnButtonOff("toggleProvinces");
|
||||
|
||||
provincesEditorAddLines();
|
||||
},
|
||||
Cancel: function() {$(this).dialog("close");}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function closeProvincesEditor() {
|
||||
if (customization === 11) exitProvincesManualAssignment("close");
|
||||
if (customization === 12) exitAddStateMode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue