harsh-Book

Title: Make Limericks Not Hate
Description: A collection of Limericks made out of the President's tweets.

link

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:

  1. Collect a JSON with tweets with certain keywords from : http://www.trumptwitterarchive.com/
  2. 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".
  3. Key Words: [fake news, wall, bad, winning, loser, stupid]
  4. 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
  5. 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
  6. Program a particle system using twitter icon in Basil.js - this would serve as background for the chapter
  7. Randomly mix and match limericks and place into the document in Basil.
  8. 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();