diff --git a/modules/names-generator.js b/modules/names-generator.js
index 84b3a860..8a950260 100644
--- a/modules/names-generator.js
+++ b/modules/names-generator.js
@@ -7,9 +7,9 @@
let chains = [];
// calculate Markov chain for a namesbase
- const calculateChain = function(b) {
+ const calculateChain = function(string) {
const chain = [];
- const d = nameBases[b].b.toLowerCase().replace(/,/g, " ");
+ const d = string.toLowerCase().replace(/,/g, " ");
for (let i = -1, str = ""; i < d.length - 2; i += str.length, str = "") {
let v = 0, f = " ";
@@ -33,7 +33,7 @@
}
// update chain for specific base
- const updateChain = (i) => chains[i] = nameBases[i] || nameBases[i].b ? calculateChain(i) : null;
+ const updateChain = (i) => chains[i] = nameBases[i] || nameBases[i].b ? calculateChain(nameBases[i].b) : null;
// update chains for all used bases
const clearChains = () => chains = [];
@@ -67,7 +67,7 @@
cur = "";
v = data[" "];
} else {
- v = data[cur.slice(-1)];
+ v = data[cur.slice(-1)] || data[" "];
}
}
@@ -255,5 +255,5 @@
];
}
- return {getBase, getCulture, getCultureShort, getBaseShort, getState, updateChain, clearChains, getNameBases, getMapName};
+ return {getBase, getCulture, getCultureShort, getBaseShort, getState, updateChain, clearChains, getNameBases, getMapName, calculateChain};
})));
diff --git a/modules/ui/namesbase-editor.js b/modules/ui/namesbase-editor.js
index cae0e687..9531b9cf 100644
--- a/modules/ui/namesbase-editor.js
+++ b/modules/ui/namesbase-editor.js
@@ -18,6 +18,7 @@ function editNamesbase() {
document.getElementById("namesbaseDouble").addEventListener("input", updateBaseDublication);
document.getElementById("namesbaseMulti").addEventListener("input", updateBaseMiltiwordRate);
document.getElementById("namesbaseAdd").addEventListener("click", namesbaseAdd);
+ document.getElementById("namesbaseAnalize").addEventListener("click", analizeNamesbase);
document.getElementById("namesbaseDefault").addEventListener("click", namesbaseRestoreDefault);
document.getElementById("namesbaseDownload").addEventListener("click", namesbaseDownload);
document.getElementById("namesbaseUpload").addEventListener("click", () => namesbaseToLoad.click());
@@ -105,7 +106,63 @@ function editNamesbase() {
const base = +document.getElementById("namesbaseSelect").value;
nameBases[base].m = +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;}
+
+ 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 lengthStat =
+ l < 30 ? "
[not enough]" :
+ l < 150 ? "
[low]" :
+ l < 150 ? "
[low]" :
+ l < 400 ? "
[good]" :
+ l < 600 ? "
[overmuch]" :
+ "
[overmuch]";
+
+ const rangeStat =
+ l < 10 ? "
[low]" :
+ l < 15 ? "
[low]" :
+ l < 20 ? "
[low]" :
+ "
[good]";
+
+ const depthStat =
+ l < 15 ? "
[low]" :
+ l < 20 ? "
[low]" :
+ l < 25 ? "
[low]" :
+ "
[good]";
+
+ alertMessage.innerHTML = `
+
Namesnase length: ${l} ${lengthStat}
+
Namesbase range: ${Object.keys(chain).length-1} ${rangeStat}
+
Namesbase depth: ${depth} ${depthStat}
+
Non-basic chars: ${nonLatin}
+
+
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}%
+
`;
+ $("#alert").dialog({
+ resizable: false, title: "Data Analysis",
+ position: {my: "left top-30", at: "right+10 top", of: "#namesbaseEditor"},
+ buttons: {OK: function() {$(this).dialog("close");}}
+ });
+ }
+
function namesbaseAdd() {
const base = nameBases.length;
const b = "This,is,an,example,of,name,base,showing,correct,format,It,should,have,at,least,one,hundred,names,separated,with,comma";
diff --git a/modules/utils.js b/modules/utils.js
index 89452149..89acad24 100644
--- a/modules/utils.js
+++ b/modules/utils.js
@@ -470,34 +470,6 @@ function getNumberInRange(r) {
return count;
}
-// helper function non-used for the generation
-function analizeNamesbase() {
- const result = [];
- nameBases.forEach((b,i) => {
- const string = nameBases[i].b;
- const d = string.split(",");
- const size = d.length;
- const ar = d.map(n => n.length);
- const min = d3.min(ar);
- const max = d3.max(ar);
- const mean = rn(d3.mean(ar), 1);
- const median = d3.median(ar);
- const lengths = new Uint8Array(max);
- ar.forEach(l => lengths[l]++);
- const common = d3.scan(lengths, (a,b) => b-a);
- const doubleArray = [];
- let double = "";
- for (let i=0; i
size/35) double += l;}
- const multi = rn(d3.mean(d.map(n => (n.match(/ /g)||[]).length-1)),2);
- result.push({name:b.name, size, min, max, mean, median, common, double, multi});
- });
- console.table(result);
-}
-
// helper function non-used for the generation
function drawCellsValue(data) {
debug.selectAll("text").remove();