February 17, 2019
Anapest Generator: a JavaScript Poem Maker
My JavaScript iambic pentameter generator is among the most popular articles on this blog. If you liked that, you’re gonna love today’s article. I decided to make an anapest generator with a rhyme! It’s a JavaScript poetry generator using an anapest, that is, a poem with anapestic meter.
An anapest, or anapestic meter, is a metrical foot consisting of two unstressed syllables followed by a stressed one. Perhaps the most famous example of an anapestic poem (also mentioned in my article on poetry) is Lord Byron’s βThe Destruction of Sennacheribβ.
The Assyrian came down like the wolf on the fold,
And his cohorts were gleaming in purple and gold;
And the sheen of their spears was like stars on the sea,
When the blue wave rolls nightly on deep Galilee.Like the leaves of the forest when Summer is green,
That host with their banners at sunset were seen:
Like the leaves of the forest when Autumn hath blown,
That host on the morrow lay withered and strown.
A Simple Anapest Generator in Javascript
Without further delay, here’s what I came up with:
Click to run the program
Perceptive observers will notice that the anapest generator is running in an iframe. It links to raw.githack. This means that, as a free service, 100% uptime cannot be guaranteed.
Looking for the code? Here it is, you’re welcome: π
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script src="https://cdnjs.cloudflare.com/ajax/libs/rita/1.3.11/rita-full.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body style="background-color:black;color:silver">
<input type="button" style="margin-bottom:5px;padding:5px" value="Generate New" onclick="window.location.reload();">
<br>
<div id="out1" style="color:white;font-family:Verdana"></div><br>
</body>
<script>
let rhymedWord, rhymedWord2, preRhyme, preRhymeB, advS, advSB;
let det = " they ";
//creating rhymes
let w1 = wordChoice("vbn", 2);
let w1b = wordChoice("vb", 2);
let w2, w2b;
//
fetchTheWord('https://api.datamuse.com/words?rel_rhy='+w1).then(function(obj){
w2 = obj[Math.floor(Math.random()*obj.length)].word;
fetchTheWord('https://api.datamuse.com/words?rel_rhy='+w1b).then(function(obj){
w2b = obj[Math.floor(Math.random()*obj.length)].word;
var syllNum = new_count(w2);
var syllNumB = new_count(w2b);
// first & second lines
if (w2 != undefined) {
rhymedWord = w2;
if (syllNum == 1) {
advS = 3;
det = " some ";
preRhyme = wordChoice("nns", advS)
}
else if (syllNum == 2) {
advS = 2;
preRhyme = RiTa.randomWord("rb", advS)
}
else if (syllNum == 3) {
advS = 1;
preRhyme = RiTa.randomWord("rb", advS);
}
else if (syllNum == 4) {
preRhyme = "";
}
else {
advS = 1;
preRhyme = RiTa.randomWord("rb", advS);
}
}
else {
rhymedWord = wordChoice("vb", 3);
advS = 1;
preRhyme = RiTa.randomWord("rb", advS);
}
// third and fourth lines
if (w2b != undefined) {
rhymedWord2 = w2b;
if (syllNumB == 1) {
advSB = 2;
preRhymeB = wordChoice("rb", advSB)
}
else if (syllNumB == 2) {
advSB = 1;
preRhymeB = RiTa.randomWord("md", advSB)
}
else if (syllNumB == 3) {
advSB = 1;
preRhymeB = "";
}
else {
advSB = 1;
preRhymeB = RiTa.randomWord("md", advSB);
}
}
else {
rhymedWord2 = wordChoice("vb", 2);
advSB = 1;
preRhymeB = RiTa.randomWord("md",advSB);
}
// structuring lines
var line1 = capitalizeFirstLetter(RiTa.randomWord("prp$",1)) + " " + wordChoice("jj",2) + " " + wordChoice("nn",3) + " " + retConjunction() + " " + wordChoice("nns",2) + " has " + w1 + ",";
var line2 = RiTa.randomWord("jj",1) + " " + wordChoice2("jj",3) + " " + wordChoice("nns",2) + " " + retConjunction2() + det + preRhyme + " " + rhymedWord + ".";
var line3 = capitalizeFirstLetter(wordChoice("jj",3)) + " " + RiTa.randomWord("jj",1) + " " + wordChoice("nn",2) + " " + retConjunction() + " " + wordChoice("nns",2) + " " + RiTa.randomWord ("md", 1) + " " + w1b + ",";
var line4 = RiTa.randomWord("prp$",1) + " " + wordChoice("jj",2) + " " + RiTa.randomWord("jj", 1) + " " + wordChoice("nn",2) + " " + retConjunction2() + " " + wordChoice("nns",2) + " " + preRhymeB + " " + rhymedWord2 + ".";
$('#out1').append(line1+"<br/>"+line2+"<br/>"+line3+"<br/>"+line4+"<br/>"+"<br/>");
});
});
// word picking functions for stress detection
function wordChoice(pos, syl) {
var word = RiTa.randomWord(pos, syl);
if ((RiTa.getStresses(word) == "0/1") || (RiTa.getStresses(word) == "0/0/1")) {
return (word);
}
else {
return (wordChoice(pos, syl));
}
}
function wordChoice2(pos, syl) {
var word = RiTa.randomWord(pos, syl);
if (RiTa.getStresses(word) == "0/1/0") {
return (word);
}
else {
return (wordChoice2(pos, syl));
}
}
function wordChoice3(pos, syl) {
var word = RiTa.randomWord(pos, syl);
if (RiTa.getStresses(word) == "1/0/0") {
return (word);
}
else {
return (wordChoice3(pos, syl));
}
}
//capitalize first letter
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
// counts syllables
function new_count(word) {
word = word.toLowerCase();
if(word.length <= 3) { return 1; }
word = word.replace(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '');
word = word.replace(/^y/, '');
return word.match(/[aeiouy]{1,2}/g).length;
}
function retConjunction() {
var conjs = ["with", "near", "for"];
var ind = Math.floor(Math.random() * (2 - 0 + 1) ) + 0;
return conjs[ind];
}
function retConjunction2() {
var conjs = ["as", "while", "soon", "then", "which", "how"];
var ind = Math.floor(Math.random() * (5 - 0 + 1) ) + 0;
return conjs[ind];
}
function fetchTheWord(url) {
return new Promise(function (resolve) {
resolve($.get(url));
});
}
</script>
</html>
You will need the RiTa library for this to work. It also implements the Datamuse API (which means, if the Datamuse server is slow, this page will be slow as well; it’s out of my control).
Anapestic Poetry Generator: Next Steps
As with my iambic pentameter maker, this is really, really “alpha”. I’d like to work on it some more, if I only find the time. My main focus would be an attempt to improve semantic coherence.
I’ve also noticed that sometimes the generator draws a blank (not verse!). If that happens, pressing “Generate New” should resolve the issue.
There’s also the same issue as with the iambic pentameter generator, namely, that the library Iβm using to detect syllable stress isnβt 100% correct. If you came up with an improved version, feel free to share it!
Interested in haikus? Take a look at my haiku generator with user input!