mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-22 12:01:23 +01:00
pull master
This commit is contained in:
commit
e6457c4e4e
25 changed files with 930 additions and 447 deletions
|
|
@ -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])) + ",";
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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} </div>`);
|
||||
insert(
|
||||
`<div data-tip="Regiment ${u.name} units number. Click to sort" class="sortable removable" data-sortby="${u.name}">${label} </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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue