'use strict';
+const Fs = require('fs');
+const Path = require('path');
-var fs = require('fs');
-
-var Promise = require('bluebird');
-require('neon');
-
-var Conjugator = require('./Conjugator');
-
-var InsultGenerator = Class({}, "InsultGenerator")({
- prototype : {
- file : null,
- verbs: null,
- nouns: null,
-
- _maxTries: 10,
- _loaded: false,
- _verbRe: /^[0-9]+\-v\s+?lemma\s+?([^ ]+)/,
- _nounRe: /^[0-9]+\-n\s+?lemma\s+?([^ ]+)/,
- _conjugator: null,
-
- init : function init(config) {
- config = config || {};
-
- Object.keys(config).forEach(function (property) {
- this[property] = config[property];
- }, this);
-
- this._conjugator = new Conjugator();
- },
-
- generate : function generate(config) {
- var selectedVerb;
- return this._load()
- .then(function () {
- return this._getVerb();
- }.bind(this)).then(function (verb) {
- return this._conjugateVerb(verb);
- }.bind(this)).then(function (conjugatedVerb) {
- selectedVerb = conjugatedVerb;
- return this._getNoun();
- }.bind(this)).then(function (noun) {
- return this._generateInsult(selectedVerb, noun);
- }.bind(this));
- },
-
- _load : function _load() {
- return this._loadFile()
- .then(function () {
- return this._loadVerbs();
- }.bind(this)).then(function () {
- return this._loadNouns();
- }.bind(this));
- },
-
- _loadFile : function _loadFile() {
- return new Promise(function (resolve, reject) {
- if (this._loaded) {
- return resolve();
- }
+const Conjugator = require('./Conjugator');
- fs.readFile(this.file, {encoding: 'utf8'}, function (err, contents) {
- if (err) {
- return reject(err);
- }
+const internals = {
+ kMaxAttempts: 10,
+ kVowels: ['a', 'e', 'i', 'o', 'u'],
+ kWordFile: Path.resolve(__dirname, '../ext/words.tab'),
+ kWordRe: /^[0-9]+\-(n|v)\s+?lemma\s+?([^ ]+)/,
- this._contents = contents;
- this._loaded = true;
- resolve();
- }.bind(this));
- }.bind(this));
- },
-
- _loadVerbs : function _loadVerbs() {
- return new Promise(function (resolve, reject) {
- if (this.verbs) {
- return resolve();
- }
+ wordList: null,
- this.verbs = [];
- this._contents.split('\n').forEach(function (line) {
- var matches;
- matches = line.match(this._verbRe);
+ // Gets the list of words, key can be either nouns or verbs
- if (matches) {
- if (this.verbs.indexOf(matches[1]) === -1) {
- this.verbs.push(matches[1])
- }
- }
- }, this);
+ async getWordList(key) {
+
+ internals.wordList = internals.wordList || await internals.readWordFile();
+ return internals.wordList[key];
+ },
+
+ // Read the list of words and returns it
+
+ readWordFile() {
- resolve();
- }.bind(this));
- },
+ return new Promise(function (resolve, reject) {
- _loadNouns : function _loadNouns() {
- return new Promise(function (resolve, reject) {
- if (this.nouns) {
- return resolve();
+ console.debug('Reading word file');
+ Fs.readFile(internals.kWordFile, {encoding: 'utf8'}, function (err, contents) {
+
+ if (err) {
+ return reject(err);
}
- this.nouns = [];
- this._contents.split('\n').forEach(function (line) {
- var matches;
- matches = line.match(this._nounRe);
+ const verbs = new Set();
+ const nouns = new Set();
+ const words = contents.split('\n');
+
+ console.debug(`Found ${words.length} words, categorizing`);
+
+ words.forEach(function (line) {
+
+ const matches = line.match(internals.kWordRe);
if (matches) {
- if (this.nouns.indexOf(matches[1]) === -1) {
- this.nouns.push(matches[1])
+ if (matches[1] === 'v') {
+ return verbs.add(matches[2]);
}
+
+ nouns.add(matches[2]);
}
- }, this);
-
- resolve();
- }.bind(this));
- },
-
- _getVerb : function _getVerb() {
- var index;
- index = Math.floor(Math.random()*this.verbs.length);
- return Promise.resolve(this.verbs[index]);
- },
-
- _conjugateVerb : function _conjugateVerb(verb) {
- return new Promise(function (resolve, reject) {
- var tries;
-
- tries = 0;
-
- var attemptConjugation = function attemptConjugation(verb, tries) {
- if (tries > this._maxTries) {
- return reject(new Error("Couldn't find a proper verb"));
- };
-
- this._conjugator.conjugate(verb)
- .then(function (conjugatedVerb) {
- resolve(conjugatedVerb);
- })
- .catch(function (err) {
- this._getVerb().then(function (verb) {
- attemptConjugation.bind(this)(verb, tries + 1);
- }.bind(this))
- }.bind(this));
- };
-
- setTimeout(attemptConjugation.bind(this, verb, 0), 0);
- }.bind(this));
- },
-
- _getNoun : function _getNoun() {
- var index, noun;
- index = Math.floor(Math.random()*this.nouns.length);
- return Promise.resolve(this.nouns[index].toLowerCase());
- },
-
- _generateInsult : function _generateInsult(verb, noun) {
- return Promise.resolve(verb + this._pluralize(noun));
- },
-
- // Super dumb pluralizer
- _pluralize : function _pluralize(noun) {
- var lastLetter;
-
- lastLetter = noun[noun.length - 1];
-
- if (lastLetter === "s") {
- return noun;
- }
-
- if (["a","e","i","o","u"].indexOf(lastLetter) >= 0) {
- return noun + "s"
- }
-
- return noun + "es";
+ });
+
+ console.debug(`Nouns: ${nouns.size}, Verbs: ${verbs.size}`);
+
+ resolve({
+ verbs: [...verbs],
+ nouns: [...nouns]
+ });
+ });
+ });
+ },
+
+ // Gets a conjugated verb
+
+ async getVerb() {
+
+ const verbs = await internals.getWordList('verbs');
+ const verb = verbs[Math.floor(Math.random()*verbs.length)];
+ return await Conjugator.conjugate(verb);
+ },
+
+ // Gets a pluralized noun
+
+ async getNoun() {
+
+ const nouns = await internals.getWordList('nouns');
+ const noun = nouns[Math.floor(Math.random()*nouns.length)];
+ return internals.pluralize(noun);
+ },
+
+ // Pluralizes a word
+
+ pluralize(noun) {
+
+ const lastLetter = noun[noun.length - 1];
+
+ if (lastLetter === 's') {
+ return noun;
}
+
+ if (internals.kVowels.indexOf(lastLetter) >= 0) {
+ return noun + 's'
+ }
+
+ return noun + 'es';
}
-});
+};
+
+module.exports = {
-module.exports = InsultGenerator;
+ // Generates an insult.
+
+ async generate() {
+
+ const verb = await internals.getVerb();
+ const noun = await internals.getNoun();
+
+ return (verb + noun).toLowerCase();
+ }
+};