UNPKG

brogue

Version:

A Grammar based generative text library based on Tracery.

88 lines (87 loc) 2.96 kB
"use strict"; 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;