Fantasy-Map-Generator/modules/ui/namesbase-editor.js
2021-05-16 18:51:34 +03:00

240 lines
9.1 KiB
JavaScript

'use strict';
function editNamesbase() {
if (customization) return;
closeDialogs('#namesbaseEditor, .stable');
$('#namesbaseEditor').dialog();
if (modules.editNamesbase) return;
modules.editNamesbase = true;
// add listeners
document.getElementById('namesbaseSelect').addEventListener('change', updateInputs);
document.getElementById('namesbaseTextarea').addEventListener('change', updateNamesData);
document.getElementById('namesbaseUpdateExamples').addEventListener('click', updateExamples);
document.getElementById('namesbaseExamples').addEventListener('click', updateExamples);
document.getElementById('namesbaseName').addEventListener('input', updateBaseName);
document.getElementById('namesbaseMin').addEventListener('input', updateBaseMin);
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('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('namesbaseSpeak').addEventListener('click', () => speak(namesbaseExamples.textContent));
createBasesList();
updateInputs();
$('#namesbaseEditor').dialog({
title: 'Namesbase Editor',
width: '42.5em',
position: {my: 'center', at: 'center', of: 'svg'}
});
function createBasesList() {
const select = document.getElementById('namesbaseSelect');
select.innerHTML = '';
nameBases.forEach((b, i) => select.options.add(new Option(b.name, i)));
}
function updateInputs() {
const base = +document.getElementById('namesbaseSelect').value;
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;
document.getElementById('namesbaseMax').value = nameBases[base].max;
document.getElementById('namesbaseDouble').value = nameBases[base].d;
updateExamples();
}
function updateExamples() {
const base = +document.getElementById('namesbaseSelect').value;
let examples = '';
for (let i = 0; i < 10; i++) {
const example = Names.getBase(base);
if (example === undefined) {
examples = 'Cannot generate examples. Please verify the data';
break;
}
if (i) examples += ', ';
examples += example;
}
document.getElementById('namesbaseExamples').innerHTML = examples;
}
function updateNamesData() {
const base = +document.getElementById('namesbaseSelect').value;
const b = document.getElementById('namesbaseTextarea').value;
if (b.split(',').length < 3) {
tip('The names data provided is too short of incorrect', false, 'error');
return;
}
nameBases[base].b = b;
Names.updateChain(base);
}
function updateBaseName() {
const base = +document.getElementById('namesbaseSelect').value;
const select = document.getElementById('namesbaseSelect');
select.options[namesbaseSelect.selectedIndex].innerHTML = this.value;
nameBases[base].name = this.value;
}
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;
}
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;
}
nameBases[base].max = +this.value;
}
function updateBaseDublication() {
const base = +document.getElementById('namesbaseSelect').value;
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;
}
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
? "<span style='color:red'>[not enough]</span>"
: l < 150
? "<span style='color:darkred'>[low]</span>"
: l < 150
? "<span style='color:orange'>[low]</span>"
: l < 400
? "<span style='color:green'>[good]</span>"
: l < 600
? "<span style='color:orange'>[overmuch]</span>"
: "<span style='color:darkred'>[overmuch]</span>";
const rangeStat =
l < 10
? "<span style='color:red'>[low]</span>"
: l < 15
? "<span style='color:darkred'>[low]</span>"
: l < 20
? "<span style='color:orange'>[low]</span>"
: "<span style='color:green'>[good]</span>";
const depthStat =
l < 15
? "<span style='color:red'>[low]</span>"
: l < 20
? "<span style='color:darkred'>[low]</span>"
: l < 25
? "<span style='color:orange'>[low]</span>"
: "<span style='color:green'>[good]</span>";
alertMessage.innerHTML = `<div style="line-height: 1.6em; max-width: 20em">
<div>Namesbase length: ${l} ${lengthStat}</div>
<div>Namesbase range: ${Object.keys(chain).length - 1} ${rangeStat}</div>
<div>Namesbase depth: ${depth} ${depthStat}</div>
<div>Non-basic chars: ${nonLatin}</div>
<hr>
<div>Min name length: ${d3.min(wordsLength)}</div>
<div>Max name length: ${d3.max(wordsLength)}</div>
<div>Mean name length: ${rn(d3.mean(wordsLength), 1)}</div>
<div>Median name length: ${d3.median(wordsLength)}</div>
<div>Doubled chars: ${doubled}</div>
<div>Multi-word names: ${multi}%</div>
</div>`;
$('#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';
nameBases.push({name: 'Base' + base, min: 5, max: 12, d: '', m: 0, b});
document.getElementById('namesbaseSelect').add(new Option('Base' + base, base));
document.getElementById('namesbaseSelect').value = base;
document.getElementById('namesbaseTextarea').value = b;
document.getElementById('namesbaseName').value = 'Base' + base;
document.getElementById('namesbaseMin').value = 5;
document.getElementById('namesbaseMax').value = 12;
document.getElementById('namesbaseDouble').value = '';
document.getElementById('namesbaseExamples').innerHTML = 'Please provide names data';
}
function namesbaseRestoreDefault() {
const message = 'Are you sure you want to restore default namesbase? <br>This action cannot be reverted';
const onConfirm = () => {
Names.clearChains();
nameBases = Names.getNameBases();
createBasesList();
updateInputs();
};
confirmationDialog({title: 'Restore default data', message, confirm: 'Restore', onConfirm});
}
function namesbaseDownload() {
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;
}
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]});
});
createBasesList();
updateInputs();
}
}