brogue
Version:
A Grammar based generative text library based on Tracery.
203 lines (202 loc) • 6.41 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getBuiltInModifier = void 0;
/* eslint-disable no-unused-vars */
const compromise_1 = __importDefault(require("compromise"));
const articles_1 = __importDefault(require("articles"));
const num_words_1 = __importDefault(require("num-words"));
const expand_1 = require("./expand");
function _isVowel(s) {
return s === 'a' || s === 'e' || s === 'i' || s === 'o' || s === 'u' || s === 'y' || s === 'A' || s === 'E' || s === 'I' || s === 'O' || s === 'U' || s === 'Y';
}
function _isConsonant(s) {
return !_isVowel(s);
}
function _funcCapitalize(s, _) {
return s.charAt(0).toUpperCase() + s.slice(1);
}
function _funcCapitalizeAll(s, _) {
return s.replace(/(?:^|\s)\S/g, (a) => {
return a.toUpperCase();
});
}
function _funcQuotes(s, _) {
return `"${s}"`;
}
function _funcTimes(s, _, n) {
if (n === undefined || Number.isNaN(n) || typeof n !== 'number') {
throw new Error('Expected number parameter. Ex: times(3)');
}
return Array(n).fill(s).join(' ');
}
function _funcArtical(s, _) {
return articles_1.default.articlize(s);
}
function _funcPluralize(s, _) {
return compromise_1.default(s).tag("#Noun").nouns()
.toPlural()
.text();
}
function _funcSingularize(s, _) {
return compromise_1.default(s).tag("#Noun").nouns()
.toSingular()
.text();
}
function _funcPossessive(s, _) {
return compromise_1.default(s).tag("#Noun").nouns()
.toPossessive()
.text();
}
function _funcPastTense(s, _) {
return compromise_1.default(s).tag("#Verb").verbs()
.toPastTense()
.text();
}
function _funcPresentTense(s, _) {
return compromise_1.default(s).tag("#Verb").verbs()
.toPresentTense()
.text();
}
function _funcFutureTense(s, _) {
return compromise_1.default(s).tag("#Verb").verbs()
.toFutureTense()
.text();
}
function _funcGerund(s, _) {
return compromise_1.default(s).tag("#Verb").verbs()
.toGerund()
.text();
}
function _funcInfinitive(s, _) {
return compromise_1.default(s).tag("#Verb").verbs()
.toInfinitive()
.text();
}
function _funcPositive(s, _) {
return compromise_1.default(s).tag("#Verb").verbs()
.toPositive()
.text();
}
function _funcNegative(s, _) {
return compromise_1.default(s).tag("#Verb").verbs()
.toNegative()
.text();
}
function _funcNounify(s, context) {
const infinitive = _funcInfinitive(s, context);
const lastChar = infinitive.charAt(infinitive.length - 1);
if (lastChar === 'e') {
return `${infinitive}r`;
}
let vowelCount = 0;
for (let i = 0; i < s.length; ++i) {
vowelCount += _isVowel(s[i]) ? 1 : 0;
}
// Double final consonant if:
// word is 1 syllable
// has 1 vowel
// and has a consonant that follows the vowel
if (_isConsonant(lastChar) &&
lastChar !== 'x' &&
vowelCount === 1 &&
_isVowel(infinitive.charAt(infinitive.length - 2)) &&
infinitive.length < 5) {
return `${infinitive.slice(0, -1) + lastChar + lastChar}er`;
}
return `${infinitive}er`;
}
function _funcRandomNumber(_, context, minString = '0', maxString = '99') {
const min = parseInt(minString, 10);
const max = parseInt(maxString, 10);
return context.grammar.random.intBetween(min, max).toString();
}
function _funcRoll(_, context, rollString) {
if (!rollString) {
throw new Error(`Tried to invoke roll() without argument`);
}
const matches = rollString.match(/(?<num>\d+)d(?<sides>\d+)(?:(?:\s?\+\s?(?<plus>\d+))|(?:\s?-\s?(?<minus>\d+)))?/);
if (!matches || !matches.groups?.num || !matches.groups?.sides) {
throw new Error(`Failed to parse die roll string: ${rollString}`);
}
const num = parseInt(matches.groups.num, 10);
const sides = parseInt(matches.groups.sides, 10);
let val = 0;
for (let i = 0; i < num; ++i) {
val += context.grammar.random.intBetween(1, sides);
}
if (matches.groups.plus) {
val += parseInt(matches.groups.plus, 10);
}
if (matches.groups.minus) {
val -= parseInt(matches.groups.minus, 10);
}
return val.toString();
}
function _funcUniques(_, context, ruleName, num, separator = " ") {
const rule = context.grammar.rules.get(ruleName);
if (!rule) {
throw new Error(`Failed to call modifier 'uniques'. Rule {ruleName} not found in loaded grammar.`);
}
const picks = [];
context.pushUniqueTracker();
const maxTries = 10;
let tries = 0;
while (picks.length < num && tries++ < maxTries) {
const lexeme = expand_1.pickLexeme(rule, context);
if (!lexeme) {
break;
}
const expanded = expand_1.expandLexeme(lexeme, context, true);
if (expanded === undefined) {
continue;
}
if (!picks.includes(expanded)) {
picks.push(expanded);
}
}
context.popUniqueTracker();
return picks.join(separator);
}
function _funcNumberToWords(s, _) {
const parsed = parseInt(s, 10);
if (isNaN(parsed)) {
return s;
}
return num_words_1.default(parsed);
}
function _funcChoose(_, context, ...args) {
const string = args[context.grammar.random.range(args.length)].toString();
return expand_1.expand(context.grammar, string);
}
const builtInModifiers = new Map(Object.entries({
// Lexical
capitalize: _funcCapitalize,
capitalizeall: _funcCapitalizeAll,
quotes: _funcQuotes,
times: _funcTimes,
a: _funcArtical,
s: _funcPluralize,
singular: _funcSingularize,
past: _funcPastTense,
present: _funcPresentTense,
future: _funcFutureTense,
ing: _funcGerund,
infinitive: _funcInfinitive,
nounify: _funcNounify,
possessive: _funcPossessive,
positive: _funcPositive,
negative: _funcNegative,
numberToWords: _funcNumberToWords,
// Genrative
randomNumber: _funcRandomNumber,
roll: _funcRoll,
uniques: _funcUniques,
choose: _funcChoose,
}));
function getBuiltInModifier(name) {
return builtInModifiers.get(name);
}
exports.getBuiltInModifier = getBuiltInModifier;