update = () => {
if (!updating) return;
let pos, idx;
let next = { display: "", buffer: "" };
let word = { display: "", buffer: "" };
let wordsLength = wordsDisplay.length;
if (state.outgoing) {
let r = Math.floor(Math.random() * wordsLength);
for (let i = r; i < wordsLength + r; i++) {
idx = DEBUG
? RiTa.evaluate(`(${i % wordsLength} [20] | 8)`)
: i % wordsLength;
word.display = wordsDisplay[idx].toLowerCase();
word.buffer = wordsBuffer[idx].toLowerCase();
if (!replaceableWord(word.display) || !replaceableWord(word.buffer))
continue;
// if (reject) continue;
pos = partsOfSpeech[idx];
// we are going to create histories for both words and wordsOfTarget
// regardless of where we are actually rambling out from
// find related words
let similar = { display: [], buffer: [] };
for (let prop in next) {
let rhymes = RiTa.rhymes(word[prop], { pos });
let sounds = RiTa.soundsLike(word[prop], { pos });
let spells = RiTa.spellsLike(word[prop], { pos });
let theseSimilars = [...rhymes, ...sounds, ...spells];
similar[prop] = theseSimilars;
}
let reject = false;
for (let prop in similar) {
// only words with 2 or more similars
if (similar[prop].length < 2) reject = true;
}
if (reject) continue;
// pick random similars
for (let prop in next) {
next[prop] = RiTa.random(similar[prop]);
}
reject = false;
for (let prop in next) {
if (next[prop].length < 3) reject = true; // skip if not >= 3 letters long
if (next[prop].includes(word[prop]) || word[prop].includes(next[prop]))
reject = true; // skip substrings
if (ignores.includes(next[prop])) reject = true;
}
if (reject) continue;
for (let prop in next) {
if (/[A-Z]/.test(wordsDisplay[idx][0]))
next[prop] = RiTa.capitalize(next[prop]); // keep capitals
if (/[A-Z]/.test(wordsBuffer[idx][0]))
next[prop] = RiTa.capitalize(next[prop]); // keep capitals
}
// word = state.domain == "origin" ? originWords[idx] : targetWords[idx];
wordsDisplay[idx] = next.display;
wordsBuffer[idx] = next.buffer;
for (let prop in next) {
state.histories[prop][idx].push(next[prop]);
}
// originWords[idx] = nexts[0]; // do replacement
// targetWords[idx] = nexts[1]; // do replacement in target
// state.history[idx].push(nexts[0]); // add to history
// state.historyOfTarget[idx].push(nexts[1]); // add to historyOfTarget
// next = state.domain == "origin" ? nexts[0] : nexts[1];
next = next.display;
word = word.display;
mutable replacementCount++;
break; // done
}
} else {
// ramble back
let data = restore();
if (!data) {
// also means that replacements() <= 0
return;
}
mutable replacementCount--;
[next, idx, pos, word] = Object.values(data);
}
updateDOM(next, idx);
// DOM updated, here's the report ...
let numDisplay = wordsDisplay.reduce(
(acc, w, i) => (acc += state.histories.display[i].length - 1),
0
);
let numBuffer = wordsBuffer.reduce(
(acc, w, i) => (acc += state.histories.buffer[i].length - 1),
0
);
console.log(
`${numDisplay}) @${idx} ${word} -> ${next} [${pos}] numBuffer: ${numBuffer} replacementCount: ${mutable replacementCount}`
);
// ... now update state
updateState();
}