// AmyTron4000 // Gerenator for text // Main object var amytron = {} // Discrete distribution // The distribution object defines a discrete distribution amytron.Distribution = function () { this.total = 0 // Total number of elements in the distribution this.items = new Map() // Map of item -> number of elements } // Add 'occur' number of 'elem' elements into the distribution amytron.Distribution.prototype.addTo = function (elem, occur) { this.total += occur if (this.items.has(elem)) { this.items.set(elem, occur + this.items.get(elem)) } else { this.items.set(elem, occur) } } // Pick a random element from the distribution amytron.Distribution.prototype.pickFrom = function () { var idx = Math.floor(Math.random() * this.total) var acc = 0 var pick = undefined for (var [elem, occur] of this.items) { acc += occur pick = elem if (acc > idx) { break } } return pick } // Rule generator // This generator makes an array of elements from rules describing how to generate the array // Each rule is associated to a distribution of patterns indicating how to replace a rule identifier amytron.RuleGenerator = function () { this.rules = new Map() } // Populate the rules table from a description amytron.RuleGenerator.prototype.initializeFromDescription = function (description) { for (var rule of description) { var dist = new amytron.Distribution() for (var pat of rule.distribution) { dist.addTo(pat.pattern, pat.occurences) } this.rules.set(rule.id, dist) } } // Generate an array of elements amytron.RuleGenerator.prototype.generate = function () { var replacePattern = function (rules, input) { var output = new Array() for (var i of input) { if (rules.has(i)) { output = output.concat(replacePattern(rules, rules.get(i).pickFrom())) } else { output.push(i) } } return output } return replacePattern(this.rules, this.rules.get('@output@').pickFrom()) } // Model of the amytron generator amytron.model = {} amytron.model.generators = new Map() // Generate text from the generator id amytron.generateText = function () { var selector = document.getElementById('generator-selector') var generatorId = selector.options[selector.selectedIndex].value var generator = amytron.model.generators.get(generatorId) document.getElementById('generated-text').innerHTML = generator.generate() } // Transform a list of strings to a formatted strings amytron.formatText = function (input, isSentence) { // Construct the output string from the list of strings. var text = "" if (isSentence) { var first = true for (var s of input) { if (first) { text += s.charAt(0).toUpperCase() + s.slice(1) first = false } else if (s.charAt(0).match(/\p{General_Category=Punctuation}/gu) != null) { // No space before a punctuation text += s } else { text += " " + s } } text = text.trim() + "." } else { for (var s of input) { text += s } } // Construct the HTML content return "

" + text + "

" } // Make a rule generator amytron.makeRuleBasedGenerator = function (rules, isSentence) { var ruleGenerator = new amytron.RuleGenerator() ruleGenerator.initializeFromDescription(rules) return function () { var output = ruleGenerator.generate() return amytron.formatText(output, isSentence) } } // Parse a raw generator description amytron.parseGenerator = function (gen) { var generator = {} generator.name = gen.name generator.description = gen.description generator.moredescription = gen.moredescription generator.generate = amytron.makeRuleBasedGenerator(gen.rules, gen.issentence) return generator } // Draw the amytron div amytron.drawDiv = function (model) { var contents = '' contents += '' contents += '' contents += '
' contents += '

' contents += '

' document.getElementById('amytron').innerHTML = contents // Update the description amytron.updateDescription() } // Draw the description amytron.updateDescription = function () { var selector = document.getElementById('generator-selector') var generatorId = selector.options[selector.selectedIndex].value var generator = amytron.model.generators.get(generatorId) document.getElementById('generator-description').innerHTML = generator.description + "
" + generator.moredescription } // Load the model amytron.loadModel = function (gen) { // Parse the raw model amytron.model.generators.set(gen.id, amytron.parseGenerator(gen)) // Draw the amytron
amytron.drawDiv(amytron.model) } // Loading function for Phonagen-htmljs amytron.load = function (jsonFile) { fetch(jsonFile) .then(function(response) { return response.json() }) .then(amytron.loadModel) } // Load several files amytron.loadAll = function (jsonFiles) { for (file of jsonFiles) { amytron.load(file) } } // Export info //module.exports = amytron