From dbe84ea0151bb00f8c6182a1d12717751d8ad2e9 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Sat, 15 Jan 2022 17:19:55 +0300 Subject: [PATCH] improved namesbase analysis --- index.css | 5 +- index.html | 15 ++-- modules/ui/namesbase-editor.js | 147 ++++++++++++++++++++------------- 3 files changed, 100 insertions(+), 67 deletions(-) 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 @@
Select base: + Names data:
-
- Names data:
- -
+
+ +
Name: Length: - Double: + Doubled:
+
Generated examples:
@@ -2898,12 +2899,12 @@
- - + +
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();