diff --git a/index.css b/index.css
index 89d33e82..c2297f96 100644
--- a/index.css
+++ b/index.css
@@ -35,8 +35,7 @@ input[type="radio"] {
}
textarea {
- padding: 2px;
- text-indent: 1px;
+ padding: 3px;
box-sizing: border-box;
width: 100%;
}
@@ -2012,7 +2011,7 @@ div.textual fieldset {
div.textual span,
.textual legend {
- font-size: 0.8em;
+ font-size: 0.9em;
font-weight: bold;
}
diff --git a/index.html b/index.html
index 369cddf7..4a084eb0 100644
--- a/index.html
+++ b/index.html
@@ -2875,21 +2875,22 @@
-
Names data:
-
-
+
diff --git a/modules/ui/namesbase-editor.js b/modules/ui/namesbase-editor.js
index 03149a13..d347c498 100644
--- a/modules/ui/namesbase-editor.js
+++ b/modules/ui/namesbase-editor.js
@@ -17,18 +17,24 @@ function editNamesbase() {
document.getElementById("namesbaseMax").addEventListener("input", updateBaseMax);
document.getElementById("namesbaseDouble").addEventListener("input", updateBaseDublication);
document.getElementById("namesbaseAdd").addEventListener("click", namesbaseAdd);
- document.getElementById("namesbaseAnalize").addEventListener("click", analizeNamesbase);
+ document.getElementById("namesbaseAnalyze").addEventListener("click", analyzeNamesbase);
document.getElementById("namesbaseDefault").addEventListener("click", namesbaseRestoreDefault);
document.getElementById("namesbaseDownload").addEventListener("click", namesbaseDownload);
- document.getElementById("namesbaseUpload").addEventListener("click", () => namesbaseToLoad.click());
- document.getElementById("namesbaseToLoad").addEventListener("change", function() {uploadFile(this, namesbaseUpload)});
+ document.getElementById("namesbaseUpload").addEventListener("click", () => document.getElementById("namesbaseToLoad").click());
+ document.getElementById("namesbaseToLoad").addEventListener("change", function () {
+ uploadFile(this, namesbaseUpload);
+ });
+ document.getElementById("namesbaseCA").addEventListener("click", () => {
+ openURL("https://cartographyassets.com/asset-category/specific-assets/azgaars-generator/namebases/");
+ });
document.getElementById("namesbaseSpeak").addEventListener("click", () => speak(namesbaseExamples.textContent));
createBasesList();
updateInputs();
$("#namesbaseEditor").dialog({
- title: "Namesbase Editor", width: "42.5em",
+ title: "Namesbase Editor",
+ width: "auto",
position: {my: "center", at: "center", of: "svg"}
});
@@ -40,7 +46,10 @@ function editNamesbase() {
function updateInputs() {
const base = +document.getElementById("namesbaseSelect").value;
- if (!nameBases[base]) {tip(`Namesbase ${base} is not defined`, false, "error"); return;}
+ if (!nameBases[base]) {
+ tip(`Namesbase ${base} is not defined`, false, "error");
+ return;
+ }
document.getElementById("namesbaseTextarea").value = nameBases[base].b;
document.getElementById("namesbaseName").value = nameBases[base].name;
document.getElementById("namesbaseMin").value = nameBases[base].min;
@@ -52,7 +61,7 @@ function editNamesbase() {
function updateExamples() {
const base = +document.getElementById("namesbaseSelect").value;
let examples = "";
- for (let i=0; i < 10; i++) {
+ for (let i = 0; i < 10; i++) {
const example = Names.getBase(base);
if (example === undefined) {
examples = "Cannot generate examples. Please verify the data";
@@ -84,13 +93,19 @@ 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) {
+ tip("Minimal length cannot be greater than maximal", false, "error");
+ return;
+ }
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) {
+ tip("Maximal length should be greater than minimal", false, "error");
+ return;
+ }
nameBases[base].max = +this.value;
}
@@ -99,59 +114,70 @@ function editNamesbase() {
nameBases[base].d = this.value;
}
- function analizeNamesbase() {
- const string = document.getElementById("namesbaseTextarea").value;
- if (!string) {tip("Names data field should not be empty", false, "error"); return;}
- const base = string.toLowerCase();
- const array = base.split(",");
- const l = array.length;
- if (!l) {tip("Names data should not be empty", false, "error"); return;}
+ function analyzeNamesbase() {
+ const namesSourceString = document.getElementById("namesbaseTextarea").value;
+ const namesArray = namesSourceString.toLowerCase().split(",");
+ const length = namesArray.length;
+ if (!namesSourceString || !length) return tip("Names data should not be empty", false, "error");
- const wordsLength = array.map(n => n.length);
- const multi = rn(d3.mean(array.map(n => (n.match(/ /i)||[]).length)) * 100, 2);
- const geminate = array.map(name => name.match(/[^\w\s]|(.)(?=\1)/g)||[]).flat();
- const doubled = ([...new Set(geminate)].filter(l => geminate.filter(d => d === l).length > 3)||["none"]).join("");
- const chain = Names.calculateChain(string);
- const depth = rn(d3.mean(Object.keys(chain).map(key => chain[key].filter(c => c !== " ").length)));
- const nonLatin = (string.match(/[^\u0000-\u007f]/g)||["none"]).join("");
+ const chain = Names.calculateChain(namesSourceString);
+ const variety = rn(d3.mean(Object.values(chain).map(keyValue => keyValue.length)));
- const lengthStat =
- l < 30 ? "
[not enough]" :
- l < 150 ? "
[low]" :
- l < 150 ? "
[low]" :
- l < 400 ? "
[good]" :
- l < 600 ? "
[overmuch]" :
- "
[overmuch]";
+ const wordsLength = namesArray.map(n => n.length);
- const rangeStat =
- l < 10 ? "
[low]" :
- l < 15 ? "
[low]" :
- l < 20 ? "
[low]" :
- "
[good]";
+ const nonLatin = namesSourceString.match(/[^\u0000-\u007f]/g);
+ const nonBasicLatinChars = nonLatin
+ ? unique(
+ namesSourceString
+ .match(/[^\u0000-\u007f]/g)
+ .join("")
+ .toLowerCase()
+ ).join("")
+ : "none";
- const depthStat =
- l < 15 ? "
[low]" :
- l < 20 ? "
[low]" :
- l < 25 ? "
[low]" :
- "
[good]";
+ const geminate = namesArray.map(name => name.match(/[^\w\s]|(.)(?=\1)/g) || []).flat();
+ const doubled = unique(geminate).filter(char => geminate.filter(doudledChar => doudledChar === char).length > 3) || ["none"];
+
+ const duplicates = unique(namesArray.filter((e, i, a) => a.indexOf(e) !== i)).join(", ") || "none";
+ const multiwordRate = d3.mean(namesArray.map(n => +n.includes(" ")));
+
+ const getLengthQuality = () => {
+ if (length < 30) return "
[not enough]";
+ if (length < 100) return "
[low]";
+ if (length <= 400) return "
[good]";
+ return "
[overmuch]";
+ };
+
+ const getVarietyLevel = () => {
+ if (variety < 15) return "
[low]";
+ if (variety < 30) return "
[mean]";
+ return "
[good]";
+ };
alertMessage.innerHTML = `
-
Namesbase length: ${l} ${lengthStat}
-
Namesbase range: ${Object.keys(chain).length-1} ${rangeStat}
-
Namesbase depth: ${depth} ${depthStat}
-
Non-basic chars: ${nonLatin}
+
Namesbase length: ${length} ${getLengthQuality()}
+
Namesbase variety: ${variety} ${getVarietyLevel()}
-
Min name length: ${d3.min(wordsLength)}
-
Max name length: ${d3.max(wordsLength)}
-
Mean name length: ${rn(d3.mean(wordsLength), 1)}
-
Median name length: ${d3.median(wordsLength)}
-
Doubled chars: ${doubled}
-
Multi-word names: ${multi}%
+
Min name length: ${d3.min(wordsLength)}
+
Max name length: ${d3.max(wordsLength)}
+
Mean name length: ${rn(d3.mean(wordsLength), 1)}
+
Median name length: ${d3.median(wordsLength)}
+
+
Non-basic chars: ${nonBasicLatinChars}
+
Doubled chars: ${doubled.join("")}
+
Duplicates: ${duplicates}
+
Multi-word names: ${rn(multiwordRate * 100, 2)}%
`;
+
$("#alert").dialog({
- resizable: false, title: "Data Analysis",
+ resizable: false,
+ title: "Data Analysis",
position: {my: "left top-30", at: "right+10 top", of: "#namesbaseEditor"},
- buttons: {OK: function() {$(this).dialog("close");}}
+ buttons: {
+ OK: function () {
+ $(this).dialog("close");
+ }
+ }
});
}
@@ -171,35 +197,42 @@ function editNamesbase() {
function namesbaseRestoreDefault() {
alertMessage.innerHTML = `Are you sure you want to restore default namesbase?`;
- $("#alert").dialog({resizable: false, title: "Restore default data",
+ $("#alert").dialog({
+ resizable: false,
+ title: "Restore default data",
buttons: {
- Restore: function() {
+ Restore: function () {
$(this).dialog("close");
Names.clearChains();
nameBases = Names.getNameBases();
createBasesList();
updateInputs();
},
- Cancel: function() {$(this).dialog("close");}
+ Cancel: function () {
+ $(this).dialog("close");
+ }
}
});
}
function namesbaseDownload() {
- const data = nameBases.map((b,i) => `${b.name}|${b.min}|${b.max}|${b.d}|${b.m}|${b.b}`).join("\r\n");
+ const data = nameBases.map((b, i) => `${b.name}|${b.min}|${b.max}|${b.d}|${b.m}|${b.b}`).join("\r\n");
const name = getFileName("Namesbase") + ".txt";
downloadFile(data, name);
}
function namesbaseUpload(dataLoaded) {
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]) {
+ tip("Cannot load a namesbase. Please check the data format", false, "error");
+ return;
+ }
Names.clearChains();
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]});
+ nameBases.push({name: e[0], min: e[1], max: e[2], d: e[3], m: e[4], b: e[5]});
});
createBasesList();