brogue
Version:
A Grammar based generative text library based on Tracery.
88 lines (87 loc) • 2.96 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Markov = void 0;
const END_SYMBOL = "_END_";
class Markov {
constructor(sentences, settings) {
this.sentences = [];
this.sentences = sentences;
this.settings = settings ?? Markov.DefaultSettings;
}
static get DefaultSettings() {
return {
minCharacters: 0,
maxCharacters: 100000,
maxTries: 100,
order: 2,
uniqueOutput: true,
};
}
setSentences(sentences) {
this.sentences = sentences;
}
train() {
this.trainingData = new Map();
const order = this.settings.order;
this.sentences.forEach((sentence) => {
// Split the sentence into tokens, removing empty entries
const tokens = sentence
.split(/\s+/)
.filter((x) => x);
// Add end tokens to know how to end sentences
tokens.push(END_SYMBOL);
// Build frquency map
for (let i = -order; i < tokens.length - order; ++i) {
const start = i;
const end = i + order;
let keyTokens = tokens.slice(Math.max(start, 0), end);
if (start < 0) {
keyTokens = Array(Math.abs(start))
.fill('')
.concat(keyTokens);
}
const key = keyTokens.join(' ');
const next = tokens[end];
if (!this.trainingData.has(key)) {
this.trainingData.set(key, []);
}
this.trainingData.get(key).push(next);
}
});
}
generate(context) {
if (!this.trainingData) {
throw new Error("Markov is not trained. Call `train()` before generating.");
}
const order = this.settings.order;
const words = [];
const keyTokens = Array(order).fill('');
let numCharacters = 0;
while (true) {
const key = keyTokens.join(' ');
keyTokens.shift();
const next = this._randomElementForKey(key, context);
if (next === END_SYMBOL) {
break;
}
keyTokens.push(next);
words.push(next);
numCharacters += next.length;
if (numCharacters >= this.settings.maxCharacters) {
return undefined;
}
}
return words.join(' ');
}
_randomElementForKey(key, context) {
if (!this.trainingData) {
throw new Error("Markov is not trained. Call `train()` before generating.");
}
const set = this.trainingData.get(key);
if (!set) {
throw new Error(`No training data for key ${key}`);
}
return set[context.grammar.random.range(set.length)];
}
}
exports.Markov = Markov;