Title: Make Limericks Not Hate
Description: A collection of Limericks made out of the President's tweets.
Narrative
Needless to say, this project was super fun to work on (though frustrating at times). Here's a short description of the steps I took to make it:
- Collect a JSON with tweets with certain keywords from : http://www.trumptwitterarchive.com/
- Parse those keywords with Rita.js and break the sentences down into 8-ish syllable long strings with the keyword at the end, eg "bad" or "fake news".
- Key Words: [fake news, wall, bad, winning, loser, stupid]
- Come up with the starting lines for the limericks, because a limerick has the structure of AABBA, I chose to come up with some defaults for the first A, first B and last A, and then inject the parsed sentences into the other remaining A and B, so there would be some continuity and narrative in the limericks
- Program in Rita to construct the limerick and export as a JSON with individual limericks, I essentially mixed and matched my keywords between the A's and B's - so you could find 'news' as A and 'bad' as B and vice versa
- Program a particle system using twitter icon in Basil.js - this would serve as background for the chapter
- Randomly mix and match limericks and place into the document in Basil.
- Huzzah!
Overall, I'm happy with the results I got - in another iteration of this project I'd focus on parsing the tweets in a smarter manner, possibly using sentiment analysis or something else to understand the meaning in the tweet.
Code - Rita.js
var wall; var stupid; var sad; var bad; var news ; var loser; var news_st_end = ['There was once a man who was known to accuse', 'It just seemed like he was confused']; var news_end = ["Often he'd overuse"]; var bad_st_end = ["There was once a man who was very mad","But now we know he was just a fad"]; var bad_end = ["He was often mad"]; var wall_st_end = ["There was once a man who would often bawl","But to be fair, he wasn't very tall"]; var wall_end = ["He would often call"]; var loser_st_end = ["There was once an old schmoozer","He came to be known as quite the abuser"]; var loser_end = ["He'd often doozer"]; var stupid_st_end = ["There was once a man who wasn't exactly lucid","All of his claims were later disputed"]; var stupid_end = ["He concluded"]; var winning_st_end = ["There was once a man who'd keep singing","Yeah, he was crazy from the beginning"]; var winning_end = ["He'd be grinning"]; var list = ['news', 'bad', 'wall', 'loser', 'stupid', 'winning']; var stList = [news_st_end, bad_st_end, wall_st_end, loser_st_end, stupid_st_end, winning_st_end]; var endList = [news_end, bad_end, wall_end, loser_end, stupid_end, winning_end]; function preload(){ winning = loadStrings('trump_winning.txt'); wall = loadStrings('trump_wall.txt'); stupid = loadStrings('trump_stupid.txt'); sad = loadStrings('trump_sad.txt'); bad = loadStrings('trump_bad.txt'); news = loadStrings('trump_fake_news.txt'); loser = loadStrings('trump_loser.txt'); } function setup() { var strings = [news, bad, wall, loser, stupid, winning]; createCanvas(300, 300); background(255); fill(255); var json = {}; var temp; for(var i=0; i<list.length; i++){ for(var j=0; j<list.length; j++){ if(i==j){continue;} temp = make_limerick(strings[i], strings[j], stList[i], endList[j], list[i]+'+'+list[j]); json[list[i]+'+'+list[j]] = temp; } } saveJSON(json, 'master'); } function draw(){ } function make_limerick(A, B, A_st_end, B_end,name){ var lower = Math.min(A.length, B.length); result = []; for(var i=0; i<lower; i++){ var temp = A_st_end[0] + "," + "\n"; temp += "He'd say, " + '"' + cap_first(A[i].trim()) + '"' + "," + "\n"; temp += B_end[0] + "," + "\n"; temp += '"' + cap_first(B[i].trim()) + '"'; temp += "," + "\n"; temp += A_st_end[1] + "." console.log(temp); result.push(temp); } var txt = parse('%s.json', name); return result; } function cap_first(string) { return string.charAt(0).toUpperCase() + string.slice(1); } function parse(str) { var args = [].slice.call(arguments, 1), i = 0; return str.replace(/%s/g, function() { return args[i++]; }); } function clean_up (stuff){ var master = ''; var expression1 = /[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/; var expression2 = /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9]\.[^\s]{2,})/; var expression3 = /(@[A-Za-z0-9]+)|([^0-9A-Za-z \t])|(\w+:\/\/\S+)/; var expression4 = /^[ \t]+|[ \t]+$/; var expression5 = /a@(foo|bar|baz)\b/; var regex1 = new RegExp(expression1); var regex2 = new RegExp(expression2); var regex3 = new RegExp(expression3); var regex4 = new RegExp(expression4); var regex5 = new RegExp(expression5); for(var i=0; i < 100; i++){ var cur_text = stuff[i].text; var rs = new RiString(cur_text); rs.replaceAll(regex1, " "); rs.replaceAll(regex2, " "); rs.replaceAll(regex3, " "); rs.replaceAll(regex4, ""); rs.toLowerCase(); if(rs._text.search("stupid") != -1 ){ var tokens = RiTa.tokenize(rs._text); var badIndex = tokens.indexOf("stupid"); if(badIndex > 5){ tokens = tokens.slice(badIndex-10, badIndex+1); var token_string = '' for(var j=0; j<tokens.length; j++){ token_string += tokens[j]; token_string += ' '; } master+=token_string; master+= '\n' } } } return master; } |
Code - Basil.js
#include "../../bundle/basil.js"; // Version for basil.js v.1.1.0 // Load a data file containing your book's content. This is expected // to be located in the "data" folder adjacent to your .indd and .jsx. // In this example (an alphabet book), our data file looks like: // [ // { // "title": "A", // "image": "a.jpg", // "caption": "Ant" // } // ] var jsonString; var jsonData; //-------------------------------------------------------- function setup() { // Load the jsonString. jsonString = b.loadString("master.json"); // Clear the document at the very start. b.clear (b.doc()); var offset = 0; for(var f=0; f<25; f++){ // Make a title page. var pageNum = 0; b.addPage(); var birds = generateBirds(); b.fill(0,0,0); b.textSize(30); b.textFont("Helvetica","Bold"); b.textAlign(Justification.LEFT_ALIGN); b.text("Build Limericks Not Walls", 100,390,450,36); var obj = b.JSON.decode(jsonString); var list = ['news', 'bad', 'wall', 'loser', 'stupid', 'winning']; for(var i=0; i<6; i++){ b.textFont("Helvetica","Regular"); b.textSize(16); var curBroadTopic = list[i]; for(var j=0; j<4; j++){ var rand = Math.floor(Math.random() * 6); while(rand == i){ rand = Math.floor(Math.random() * 6); } var curSpecificTopic = curBroadTopic + "+" + list[rand]; var curValList = obj[curSpecificTopic]; var randomVal = Math.floor(Math.random() * curValList.length-1); curVal = curValList[randomVal]; if(j%2 == 0){ b.addPage(); pageNum += 1; moveBirds(birds,pageNum); b.textFont("Helvetica","Bold"); var curTopicSplit = curSpecificTopic.split('+'); b.textSize(16); b.text(curTopicSplit[0].toUpperCase(),60,60,400,100); b.textSize(16); b.textFont("Helvetica","Regular"); while(curVal === undefined){ var randVal = Math.floor(Math.random() * curValList.length-1); curVal = curValList[randVal]; } b.text(curVal,60,150,500,200); } else{ while(curVal === undefined){ var randVal = Math.floor (Math.random() * curValList.length-1); curVal = curValList[randVal]; } b.text(curVal,60,400,500,200); } } offset+= 1; // b.savePDF(f.toString()); // for(var i=0; i<13; i++){ // b.removePage(); // } } } }; function randomN(seed) { var x = Math.sin(seed++) * 10000; return x - Math.floor(x); } function generateBirds(){ var birds = []; var posx; var posy; for(var i=0; i<7; i++){ posx = Math.floor(randomN(i) * 436); posy = Math.floor(randomN(1000-i) * 300); birds.push([posx, posy]); var angle = Math.atan((648-posy)/(432-posx)); b.pushMatrix(); b.noStroke(); b.rotate(angle); var anImage = b.image("twit.png", posx, posy, 15, 15); anImage.fit(FitOptions.PROPORTIONALLY); b.opacity(anImage, 50); b.popMatrix(); } return birds; } function moveBirds(birds,pageNum){ for(var i=0; i<birds.length; i++){ var curBird = birds[i]; var posx = curBird[0]+(30*pageNum); var posy = curBird[1]+(50*pageNum); var angle = Math.atan((576-posy)/(400-posx)); b.pushMatrix(); b.noStroke(); b.rotate(angle); var anImage = b.image('twit.png', posx, posy, 15, 15); anImage.fit(FitOptions.PROPORTIONALLY); b.opacity(anImage, 50); b.popMatrix(); } } // This makes it all happen: b.go(); |