pull master

This commit is contained in:
mosuzi 2023-07-18 02:08:39 +08:00
commit e6457c4e4e
25 changed files with 930 additions and 447 deletions

View file

@ -93,7 +93,9 @@ function overviewBurgs() {
data-type="${type}"
>
<span data-tip="Click to zoom into view" class="icon-dot-circled pointer"></span>
<input data-tip="Burg name. Click and type to change" class="burgName" value="${b.name}" autocorrect="off" spellcheck="false" />
<input data-tip="Burg name. Click and type to change" class="burgName" value="${
b.name
}" autocorrect="off" spellcheck="false" />
<input data-tip="Burg province" class="burgState" value="${province}" disabled />
<input data-tip="Burg state" class="burgState" value="${state}" disabled />
<select data-tip="Dominant culture. Click to change burg culture (to change cell culture use Cultures Editor)" class="stateCulture">
@ -106,10 +108,14 @@ function overviewBurgs() {
data-tip="${b.capital ? " This burg is a state capital" : "Click to assign a capital status"}"
class="icon-star-empty${b.capital ? "" : " inactive pointer"}"
></span>
<span data-tip="Click to toggle port status" class="icon-anchor pointer${b.port ? "" : " inactive"}" style="font-size:.9em"></span>
<span data-tip="Click to toggle port status" class="icon-anchor pointer${
b.port ? "" : " inactive"
}" style="font-size:.9em"></span>
</div>
<span data-tip="Edit burg" class="icon-pencil"></span>
<span class="locks pointer ${b.lock ? "icon-lock" : "icon-lock-open inactive"}" onmouseover="showElementLockTip(event)"></span>
<span class="locks pointer ${
b.lock ? "icon-lock" : "icon-lock-open inactive"
}" onmouseover="showElementLockTip(event)"></span>
<span data-tip="Remove burg" class="icon-trash-empty"></span>
</div>`;
}
@ -125,8 +131,12 @@ function overviewBurgs() {
body.querySelectorAll("div > input.burgName").forEach(el => el.addEventListener("input", changeBurgName));
body.querySelectorAll("div > span.icon-dot-circled").forEach(el => el.addEventListener("click", zoomIntoBurg));
body.querySelectorAll("div > select.stateCulture").forEach(el => el.addEventListener("change", changeBurgCulture));
body.querySelectorAll("div > input.burgPopulation").forEach(el => el.addEventListener("change", changeBurgPopulation));
body.querySelectorAll("div > span.icon-star-empty").forEach(el => el.addEventListener("click", toggleCapitalStatus));
body
.querySelectorAll("div > input.burgPopulation")
.forEach(el => el.addEventListener("change", changeBurgPopulation));
body
.querySelectorAll("div > span.icon-star-empty")
.forEach(el => el.addEventListener("click", toggleCapitalStatus));
body.querySelectorAll("div > span.icon-anchor").forEach(el => el.addEventListener("click", togglePortStatus));
body.querySelectorAll("div > span.locks").forEach(el => el.addEventListener("click", toggleBurgLockStatus));
body.querySelectorAll("div > span.icon-pencil").forEach(el => el.addEventListener("click", openBurgEditor));
@ -137,7 +147,9 @@ function overviewBurgs() {
function getCultureOptions(culture) {
let options = "";
pack.cultures.filter(c => !c.removed).forEach(c => (options += `<option ${c.i === culture ? "selected" : ""} value="${c.i}">${c.name}</option>`));
pack.cultures
.filter(c => !c.removed)
.forEach(c => (options += `<option ${c.i === culture ? "selected" : ""} value="${c.i}">${c.name}</option>`));
return options;
}
@ -228,7 +240,8 @@ function overviewBurgs() {
function triggerBurgRemove() {
const burg = +this.parentNode.dataset.id;
if (pack.burgs[burg].capital) return tip("You cannot remove the capital. Please change the capital first", false, "error");
if (pack.burgs[burg].capital)
return tip("You cannot remove the capital. Please change the capital first", false, "error");
confirmationDialog({
title: "Remove burg",
@ -266,8 +279,10 @@ function overviewBurgs() {
function addBurgOnClick() {
const point = d3.mouse(this);
const cell = findCell(point[0], point[1]);
if (pack.cells.h[cell] < 20) return tip("You cannot place state into the water. Please click on a land cell", false, "error");
if (pack.cells.burg[cell]) return tip("There is already a burg in this cell. Please select a free cell", false, "error");
if (pack.cells.h[cell] < 20)
return tip("You cannot place state into the water. Please click on a land cell", false, "error");
if (pack.cells.burg[cell])
return tip("There is already a burg in this cell. Please select a free cell", false, "error");
addBurg(point); // add new burg
@ -301,7 +316,19 @@ function overviewBurgs() {
const capital = b.capital;
const province = pack.cells.province[b.cell];
const parent = province ? province + states.length - 1 : b.state;
return {id, i: b.i, state: b.state, culture: b.culture, province, parent, name: b.name, population, capital, x: b.x, y: b.y};
return {
id,
i: b.i,
state: b.state,
culture: b.culture,
province,
parent,
name: b.name,
population,
capital,
x: b.x,
y: b.y
};
});
const data = states.concat(burgs);
if (data.length < 2) return tip("No burgs to show", false, "error");
@ -452,7 +479,7 @@ function overviewBurgs() {
}
function downloadBurgsData() {
let data = `Id,Burg,Province,Province Full Name,State,State Full Name,Culture,Religion,Population,Latitude,Longitude,Elevation (${heightUnit.value}),Capital,Port,Citadel,Walls,Plaza,Temple,Shanty Town`; // headers
let data = `Id,Burg,Province,Province Full Name,State,State Full Name,Culture,Religion,Population,X,Y,Latitude,Longitude,Elevation (${heightUnit.value}),Capital,Port,Citadel,Walls,Plaza,Temple,Shanty Town`; // headers
if (options.showMFCGMap) data += `,City Generator Link`;
data += "\n";
@ -471,6 +498,8 @@ function overviewBurgs() {
data += rn(b.population * populationRate * urbanization) + ",";
// add geography data
data += b.x + ",";
data += b.y + ",";
data += getLatitude(b.y, 2) + ",";
data += getLongitude(b.x, 2) + ",";
data += parseInt(getHeight(pack.cells.h[b.cell])) + ",";

View file

@ -44,7 +44,12 @@ function editEmblem(type, id, el) {
function defineEmblemData(e) {
const parent = e.target.parentNode;
const [g, t] = parent.id === "burgEmblems" ? [pack.burgs, "burg"] : parent.id === "provinceEmblems" ? [pack.provinces, "province"] : [pack.states, "state"];
const [g, t] =
parent.id === "burgEmblems"
? [pack.burgs, "burg"]
: parent.id === "provinceEmblems"
? [pack.provinces, "province"]
: [pack.states, "state"];
const i = +e.target.dataset.i;
type = t;
id = type + "COA" + i;
@ -88,8 +93,12 @@ function editEmblem(type, id, el) {
emblemBurgs.options.length = 0;
emblemBurgs.options.add(new Option("", 0, false, !burg));
const burgList = validBurgs.filter(burg => (province ? pack.cells.province[burg.cell] === province : burg.state === state));
burgList.forEach(b => emblemBurgs.options.add(new Option(b.capital ? "👑 " + b.name : b.name, b.i, false, b.i === burg)));
const burgList = validBurgs.filter(burg =>
province ? pack.cells.province[burg.cell] === province : burg.state === state
);
burgList.forEach(b =>
emblemBurgs.options.add(new Option(b.capital ? "👑 " + b.name : b.name, b.i, false, b.i === burg))
);
emblemBurgs.options[0].disabled = true;
COArenderer.trigger(id, el.coa);
@ -224,12 +233,15 @@ function editEmblem(type, id, el) {
}
function upload(type) {
const input = type === "image" ? document.getElementById("emblemImageToLoad") : document.getElementById("emblemSVGToLoad");
const input =
type === "image" ? document.getElementById("emblemImageToLoad") : document.getElementById("emblemSVGToLoad");
const file = input.files[0];
input.value = "";
if (file.size > 500000) {
tip(`File is too big, please optimize file size up to 500kB and re-upload. Recommended size is 200x200 px and up to 100kB`, true, "error", 5000);
const message =
"File is too big, please optimize file size up to 500kB and re-upload. Recommended size is 200x200 px and up to 100kB";
tip(message, true, "error", 5000);
return;
}
@ -238,36 +250,37 @@ function editEmblem(type, id, el) {
reader.onload = function (readerEvent) {
const result = readerEvent.target.result;
const defs = document.getElementById("defs-emblems");
const coa = document.getElementById(id); // old emblem
const oldEmblem = document.getElementById(id);
if (type === "image") {
const svg = `<svg id="${id}" xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200"><image x="0" y="0" width="200" height="200" href="${result}"/></svg>`;
defs.insertAdjacentHTML("beforeend", svg);
} else {
let href = result; // raster images
if (type === "svg") {
const el = document.createElement("html");
el.innerHTML = result;
// remove sodipodi and inkscape attributes
el.querySelectorAll("*").forEach(el => {
const attributes = el.getAttributeNames();
attributes.forEach(attr => {
if (el.id === "adobe_illustrator_pgf") el.remove(); // remove Adobe Illustrator inner data
el.getAttributeNames().forEach(attr => {
// remove sodipodi and inkscape attributes
if (attr.includes("inkscape") || attr.includes("sodipodi")) el.removeAttribute(attr);
});
});
const svg = el.querySelector("svg");
if (!svg) {
tip("The file should be prepated for load to FMG. Please use Armoria or other relevant tools", false, "error");
const message = "The file is not a valid SVG. Please use Armoria or other relevant tools";
tip(message, false, "error");
return;
}
const newEmblem = defs.appendChild(svg);
newEmblem.id = id;
newEmblem.setAttribute("width", 200);
newEmblem.setAttribute("height", 200);
const serialized = new XMLSerializer().serializeToString(svg);
href = "data:image/svg+xml;base64," + window.btoa(serialized);
}
if (coa) coa.remove(); // remove old emblem
const svg = `<svg id="${id}" viewBox="0 0 200 200"><image width="200" height="200" href="${href}"/></svg>`;
defs.insertAdjacentHTML("beforeend", svg);
if (oldEmblem) oldEmblem.remove();
el.coa = "custom";
emblemShapeSelector.disabled = true;
};
@ -351,7 +364,9 @@ function editEmblem(type, id, el) {
validStates
.map(state => {
const el = document.getElementById("stateCOA" + state.i);
return `<figure id="state_${state.i}"><a href="#provinces_${state.i}"><figcaption>${state.fullName}</figcaption>${getSVG(el, 200)}</a></figure>`;
return `<figure id="state_${state.i}"><a href="#provinces_${state.i}"><figcaption>${
state.fullName
}</figcaption>${getSVG(el, 200)}</a></figure>`;
})
.join("") +
`</div>`;
@ -362,13 +377,14 @@ function editEmblem(type, id, el) {
const figures = stateProvinces
.map(province => {
const el = document.getElementById("provinceCOA" + province.i);
return `<figure id="province_${province.i}"><a href="#burgs_${province.i}"><figcaption>${province.fullName}</figcaption>${getSVG(
el,
200
)}</a></figure>`;
return `<figure id="province_${province.i}"><a href="#burgs_${province.i}"><figcaption>${
province.fullName
}</figcaption>${getSVG(el, 200)}</a></figure>`;
})
.join("");
return stateProvinces.length ? `<div id="provinces_${state.i}">${back}<h2>${state.fullName} provinces</h2>${figures}</div>` : "";
return stateProvinces.length
? `<div id="provinces_${state.i}">${back}<h2>${state.fullName} provinces</h2>${figures}</div>`
: "";
})
.join("");
@ -385,7 +401,9 @@ function editEmblem(type, id, el) {
return `<figure id="burg_${burg.i}"><figcaption>${burg.name}</figcaption>${getSVG(el, 200)}</figure>`;
})
.join("");
return provinceBurgs.length ? `<div id="burgs_${province.i}">${back}<h2>${province.fullName} burgs</h2>${provinceBurgFigures}</div>` : "";
return provinceBurgs.length
? `<div id="burgs_${province.i}">${back}<h2>${province.fullName} burgs</h2>${provinceBurgFigures}</div>`
: "";
})
.join("");
@ -464,7 +482,7 @@ function editEmblem(type, id, el) {
}
div > a {
float: right;
font-family: monospace;
font-family: var(--monospace);
margin-top: 0.8em;
}
</style>

View file

@ -54,8 +54,12 @@ function overviewMarkers() {
<div data-tip="Marker icon and type" style="width:12em">${icon} ${type}</div>
<span style="padding-right:.1em" data-tip="Edit marker" class="icon-pencil"></span>
<span style="padding-right:.1em" data-tip="Focus on marker position" class="icon-dot-circled pointer"></span>
<span style="padding-right:.1em" data-tip="Pin marker (display only pinned markers)" class="icon-pin ${pinned ? "" : "inactive"}" pointer"></span>
<span style="padding-right:.1em" class="locks pointer ${lock ? "icon-lock" : "icon-lock-open inactive"}" onmouseover="showElementLockTip(event)"></span>
<span style="padding-right:.1em" data-tip="Pin marker (display only pinned markers)" class="icon-pin ${
pinned ? "" : "inactive"
}" pointer"></span>
<span style="padding-right:.1em" class="locks pointer ${
lock ? "icon-lock" : "icon-lock-open inactive"
}" onmouseover="showElementLockTip(event)"></span>
<span data-tip="Remove marker" class="icon-trash-empty"></span>
</div>`;
})
@ -170,16 +174,20 @@ function overviewMarkers() {
}
function exportMarkers() {
const headers = "Id,Type,Icon,Name,Note,X,Y\n";
const headers = "Id,Type,Icon,Name,Note,X,Y,Latitude,Longitude\n";
const quote = s => '"' + s.replaceAll('"', '""') + '"';
const body = pack.markers.map(marker => {
const {i, type, icon, x, y} = marker;
const id = `marker${i}`;
const note = notes.find(note => note.id === id);
const name = note ? quote(note.name) : 'Unknown';
const legend = note ? quote(note.legend) : '';
return [id, type, icon, name, legend, x, y].join(",");
const name = note ? quote(note.name) : "Unknown";
const legend = note ? quote(note.legend) : "";
const lat = getLatitude(y, 2);
const lon = getLongitude(x, 2);
return [id, type, icon, name, legend, x, y, lat, lon].join(",");
});
const data = headers + body.join("\n");

View file

@ -23,23 +23,11 @@ function editNamesbase() {
const uploader = document.getElementById("namesbaseToLoad");
document.getElementById("namesbaseUpload").addEventListener("click", () => {
uploader.addEventListener(
"change",
function (event) {
uploadFile(event.target, d => namesbaseUpload(d, true));
},
{once: true}
);
uploader.addEventListener("change", e => uploadFile(e.target, d => namesbaseUpload(d, true)), {once: true});
uploader.click();
});
document.getElementById("namesbaseUploadExtend").addEventListener("click", () => {
uploader.addEventListener(
"change",
function (event) {
uploadFile(event.target, d => namesbaseUpload(d, false));
},
{once: true}
);
uploader.addEventListener("change", e => uploadFile(e.target, d => namesbaseUpload(d, false)), {once: true});
uploader.click();
});
@ -92,11 +80,13 @@ function editNamesbase() {
function updateNamesData() {
const base = +document.getElementById("namesbaseSelect").value;
const rawInput = document.getElementById("namesbaseTextarea").value;
if (rawInput.split(",").length < 3) return tip("The names data provided is too short of incorrect", false, "error");
const input = document.getElementById("namesbaseTextarea");
if (input.value.split(",").length < 3)
return tip("The names data provided is too short of incorrect", false, "error");
const namesData = rawInput.replace(/[/|]/g, "");
nameBases[base].b = namesData;
const securedNamesData = input.value.replace(/[/|]/g, "");
nameBases[base].b = securedNamesData;
input.value = securedNamesData;
Names.updateChain(base);
}
@ -113,19 +103,13 @@ function editNamesbase() {
function updateBaseMin() {
const base = +document.getElementById("namesbaseSelect").value;
if (+this.value > nameBases[base].max) {
tip("Minimal length cannot be greater than maximal", false, "error");
return;
}
if (+this.value > nameBases[base].max) return tip("Minimal length cannot be greater than maximal", false, "error");
nameBases[base].min = +this.value;
}
function updateBaseMax() {
const base = +document.getElementById("namesbaseSelect").value;
if (+this.value < nameBases[base].min) {
tip("Maximal length should be greater than minimal", false, "error");
return;
}
if (+this.value < nameBases[base].min) return tip("Maximal length should be greater than minimal", false, "error");
nameBases[base].max = +this.value;
}
@ -256,16 +240,15 @@ function editNamesbase() {
function namesbaseUpload(dataLoaded, override = true) {
const data = dataLoaded.split("\r\n");
if (!data || !data[0]) {
tip("Cannot load a namesbase. Please check the data format", false, "error");
return;
}
if (!data || !data[0]) return tip("Cannot load a namesbase. Please check the data format", false, "error");
Names.clearChains();
if (override) nameBases = [];
data.forEach(d => {
const e = d.split("|");
nameBases.push({name: e[0], min: e[1], max: e[2], d: e[3], m: e[4], b: e[5]});
data.forEach(base => {
const [name, min, max, d, m, names] = base.split("|");
const secureNames = names.replace(/[/|]/g, "");
nameBases.push({name, min, max, d, m, b: secureNames});
});
createBasesList();

View file

@ -76,7 +76,7 @@ document
// show popup with a list of Patreon supportes (updated manually)
async function showSupporters() {
const {supporters} = await import("../dynamic/supporters.js?v=19062022");
const {supporters} = await import("../dynamic/supporters.js?v=1.89.15");
const list = supporters.split("\n").sort();
const columns = window.innerWidth < 800 ? 2 : 5;
@ -157,6 +157,8 @@ optionsContent.addEventListener("click", function (event) {
else if (id === "translateExtent") toggleTranslateExtent(event.target);
else if (id === "speakerTest") testSpeaker();
else if (id === "themeColorRestore") restoreDefaultThemeColor();
else if (id === "loadGoogleTranslateButton") loadGoogleTranslate();
else if (id === "resetLanguage") resetLanguage();
});
function mapSizeInputChange() {
@ -474,6 +476,44 @@ function changeDialogsTheme(themeColor, transparency) {
});
}
function loadGoogleTranslate() {
const script = document.createElement("script");
script.src = "https://translate.google.com/translate_a/element.js?cb=initGoogleTranslate";
script.onload = () => {
document.getElementById("loadGoogleTranslateButton")?.remove();
// replace mapLayers underline <u> with bare text to avoid translation issue
document
.getElementById("mapLayers")
.querySelectorAll("li")
.forEach(el => {
const text = el.innerHTML.replace(/<u>(.+)<\/u>/g, "$1");
el.innerHTML = text;
});
};
document.head.appendChild(script);
}
function initGoogleTranslate() {
new google.translate.TranslateElement(
{pageLanguage: "en", layout: google.translate.TranslateElement.InlineLayout.VERTICAL},
"google_translate_element"
);
}
function resetLanguage() {
const languageSelect = document.querySelector("#google_translate_element select");
if (!languageSelect.value) return;
languageSelect.value = "en";
languageSelect.dispatchEvent(new Event("change"));
// do once again to actually reset the language
languageSelect.value = "en";
languageSelect.dispatchEvent(new Event("change"));
}
function changeZoomExtent(value) {
if (+zoomExtentMin.value > +zoomExtentMax.value) {
[zoomExtentMin.value, zoomExtentMax.value] = [zoomExtentMax.value, zoomExtentMin.value];

View file

@ -37,7 +37,9 @@ function overviewRegiments(state) {
const insert = html => document.getElementById("regimentsTotal").insertAdjacentHTML("beforebegin", html);
for (const u of options.military) {
const label = capitalize(u.name.replace(/_/g, " "));
insert(`<div data-tip="Regiment ${u.name} units number. Click to sort" class="sortable removable" data-sortby="${u.name}">${label}&nbsp;</div>`);
insert(
`<div data-tip="Regiment ${u.name} units number. Click to sort" class="sortable removable" data-sortby="${u.name}">${label}&nbsp;</div>`
);
}
header.querySelectorAll(".removable").forEach(function (e) {
e.addEventListener("click", function () {
@ -60,10 +62,12 @@ function overviewRegiments(state) {
for (const r of s.military) {
const sortData = options.military.map(u => `data-${u.name}=${r.u[u.name] || 0}`).join(" ");
const lineData = options.military
.map(u => `<div data-type="${u.name}" data-tip="${capitalize(u.name)} units number">${r.u[u.name] || 0}</div>`)
.map(
u => `<div data-type="${u.name}" data-tip="${capitalize(u.name)} units number">${r.u[u.name] || 0}</div>`
)
.join(" ");
lines += /* html */ `<div class="states" data-id=${r.i} data-s="${s.i}" data-state="${s.name}" data-name="${r.name}" ${sortData} data-total="${r.a}">
lines += /* html */ `<div class="states" data-id="${r.i}" data-s="${s.i}" data-state="${s.name}" data-name="${r.name}" ${sortData} data-total="${r.a}">
<fill-box data-tip="${s.fullName}" fill="${s.color}" disabled></fill-box>
<input data-tip="${s.fullName}" style="width:6em" value="${s.name}" readonly />
<span data-tip="Regiment's emblem" style="width:1em">${r.icon}</span>
@ -79,7 +83,9 @@ function overviewRegiments(state) {
lines += /* html */ `<div id="regimentsTotalLine" class="totalLine" data-tip="Total of all displayed regiments">
<div style="width: 21em; margin-left: 1em">Regiments: ${regiments.length}</div>
${options.military.map(u => `<div style="width:5em">${si(d3.sum(regiments.map(r => r.u[u.name] || 0)))}</div>`).join(" ")}
${options.military
.map(u => `<div style="width:5em">${si(d3.sum(regiments.map(r => r.u[u.name] || 0)))}</div>`)
.join(" ")}
<div style="width:5em">${si(d3.sum(regiments.map(r => r.a)))}</div>
</div>`;
@ -92,7 +98,9 @@ function overviewRegiments(state) {
// add listeners
body.querySelectorAll("div.states").forEach(el => el.addEventListener("mouseenter", ev => regimentHighlightOn(ev)));
body.querySelectorAll("div.states").forEach(el => el.addEventListener("mouseleave", ev => regimentHighlightOff(ev)));
body
.querySelectorAll("div.states")
.forEach(el => el.addEventListener("mouseleave", ev => regimentHighlightOff(ev)));
}
function updateFilter(state) {
@ -158,10 +166,7 @@ function overviewRegiments(state) {
function addRegimentOnClick() {
const state = +regimentsFilter.value;
if (state === -1) {
tip("Please select state from the list", false, "error");
return;
}
if (state === -1) return tip("Please select state from the list", false, "error");
const point = d3.mouse(this);
const cell = findCell(point[0], point[1]);
@ -180,15 +185,32 @@ function overviewRegiments(state) {
function downloadRegimentsData() {
const units = options.military.map(u => u.name);
let data = "State,Id,Name," + units.map(u => capitalize(u)).join(",") + ",Total\n"; // headers
let data =
"State,Id,Icon,Name," +
units.map(u => capitalize(u)).join(",") +
",X,Y,Latitude,Longitude,Base X,Base Y,Base Latitude,Base Longitude\n"; // headers
body.querySelectorAll(":scope > div:not(.totalLine)").forEach(function (el) {
data += el.dataset.state + ",";
data += el.dataset.id + ",";
data += el.dataset.name + ",";
data += units.map(u => el.dataset[u]).join(",") + ",";
data += el.dataset.total + "\n";
});
for (const s of pack.states) {
if (!s.i || s.removed || !s.military.length) continue;
for (const r of s.military) {
data += s.name + ",";
data += r.i + ",";
data += r.icon + ",";
data += r.name + ",";
data += units.map(unit => r.u[unit]).join(",") + ",";
data += r.x + ",";
data += r.y + ",";
data += getLatitude(r.y, 2) + ",";
data += getLongitude(r.x, 2) + ",";
data += r.bx + ",";
data += r.by + ",";
data += getLatitude(r.by, 2) + ",";
data += getLongitude(r.bx, 2) + "\n";
}
}
const name = getFileName("Regiments") + ".csv";
downloadFile(data, name);

View file

@ -137,7 +137,10 @@ function recalculatePopulation() {
}
function regenerateStates() {
recreateStates();
const newStates = recreateStates();
if (!newStates) return;
pack.states = newStates;
BurgsAndStates.expandStates();
BurgsAndStates.normalizeStates();
BurgsAndStates.collectStatistics();
@ -165,21 +168,32 @@ function recreateStates() {
Math.random = aleaPRNG(localSeed);
const statesCount = +regionsOutput.value;
if (!statesCount) {
tip(`<i>States Number</i> option value is zero. No counties are generated`, false, "error");
return null;
}
const validBurgs = pack.burgs.filter(b => b.i && !b.removed);
if (!validBurgs.length) {
tip("There are no any burgs to generate states. Please create burgs first", false, "error");
return null;
}
if (!validBurgs.length)
return tip("There are no any burgs to generate states. Please create burgs first", false, "error");
if (validBurgs.length < statesCount)
tip(
`Not enough burgs to generate ${statesCount} states. Will generate only ${validBurgs.length} states`,
false,
"warn"
);
if (validBurgs.length < statesCount) {
const message = `Not enough burgs to generate ${statesCount} states. Will generate only ${validBurgs.length} states`;
tip(message, false, "warn");
}
const lockedStates = pack.states.filter(s => s.i && !s.removed && s.lock);
const validStates = pack.states.filter(s => s.i && !s.removed);
const lockedStates = validStates.filter(s => s.lock);
const lockedStatesIds = lockedStates.map(s => s.i);
const lockedStatesCapitals = lockedStates.map(s => s.capital);
if (lockedStates.length === validStates.length) {
tip("Unable to regenerate as all states are locked", false, "error");
return null;
}
// turn all old capitals into towns, except for the capitals of locked states
for (const burg of validBurgs) {
if (!burg.capital) continue;
@ -229,7 +243,7 @@ function recreateStates() {
// restore locked states
lockedStates.forEach(state => {
const newId = newStates.length;
const {x, y} = validBurgs[state.capital];
const {x, y} = pack.burgs[state.capital];
capitalsTree.add([x, y]);
// update label id reference
@ -300,9 +314,7 @@ function recreateStates() {
newStates.push({i, name, type, capital: capital.i, center: capital.cell, culture, expansionism, coa});
}
if (!statesCount) tip(`<i>States Number</i> option is set to zero. No counties are generated`, false, "warn");
pack.states = newStates;
return newStates;
}
function regenerateProvinces() {
@ -920,6 +932,6 @@ function viewCellDetails() {
}
async function overviewCharts() {
const Overview = await import("../dynamic/overview/charts-overview.js?v=1.87.03");
const Overview = await import("../dynamic/overview/charts-overview.js?v=1.89.24");
Overview.open();
}