Processing: New York Times Article Search API

Processing: New York Time Article Search API - First view when the program starts
Processing: New York Time Article Search API – Video of the program

Processing: New York Times Article Search API

Task:

Use the New York Times Article Search API and combine it with one of the examples of the Book „Generative Gestaltung“ to create an interactive display which can be used at an airport.

Description of the solution:

This interactive display uses some code of the example P_4_3_2_01 from the book „Generative Gestaltung“ and articles from the New York Times Article Search API by searching for the search term „Germany“ within two days before today and four days before today and order these articles by the newest. From these articles the program needs three things: the headline, the snippet (which is the first line of text of the article) and the image of the article.

The text (headline and snipped) is displayed with rotating and overlapping characters in the colours of the pixels of the image. These characters are rotating each randomly to create motion, which is used to attract the users attention. Moreover, the articles are changing by time.

If the user gets closer to the display (for now: press left arrow key), the suddenly rotation stops and the characters jump all to a position without overlapping each other any more so the text gets readable. Then the image cannot be recognized so well instead. If the user‘ goes away (for now: press right arrow key) it goes back to the overlapping and rotating characters again.

This can be nice and interesting for people who are waiting at an airport to overcome the waiting time for example on the gate.

Processing: New York Time Article Search API - First view when the program starts
Processing: New York Time Article Search API – First view when the program starts
Possible improvements:

As this is a first version of the idea, there are still some things that have to be rethought to improve the design of this program.

Now, when the user gets closer to the display, the characters are directly jumping to their new position without any transition. This was meant as a surprise. But the user might does not understand that the image before is made from the characters of the article and that it is an image from the article, because the change is too fast. Therefore, an improvement might be to add at least a little transition. This transition can be to first stop the rotation and bring their rotation back in their original angel as one step. The second step can then make the characters jump into the right position. That maybe makes it more obvious that the image is made with the characters of the article.

Another problem is the readability when a user is closer to the display. Sometimes it is hard to read because some parts of the images, where the colour of the characters comes from, have less contrast or the same colour as the background. To avoid this it might be necessary to change the colour of all letters to one colour instead of the images colours. That can be a third step of the transformation.

Processing-Code: New York Times Article Search API
// P_4_3_2_01.pde
// 
// Generative Gestaltung, ISBN: 978-3-87439-759-9
// First Edition, Hermann Schmidt, Mainz, 2009
// Hartmut Bohnacker, Benedikt Gross, Julia Laub, Claudius Lazzeroni
// Copyright 2009 Hartmut Bohnacker, Benedikt Gross, Julia Laub, Claudius Lazzeroni
//
// http://www.generative-gestaltung.de
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * pixel mapping. each pixel is translated into a new element (letter)
 * 
 * KEYS
 * arrow right/left  : near/close
 */

import processing.pdf.*;
import java.util.Calendar;
import http.requests.*;

String q, url, begin_date, end_date, sort, api_key;
String textLines, headline, snippet, image_path;

boolean savePDF = false;

float fontSizeMax = 20;
float fontSizeMin = 15;
float spacing = 6; // line height 12
float kerning = -3; // between letters 0.5

boolean fontSizeStatic = false;
boolean blackAndWhite = false;
boolean closeTo = false;

int seconds = second();
int articleNumber = 0;
int secoundCounter = 1;
int end_day;
int end_month;
int end_year;
int begin_day;
int begin_month;
int begin_year;

PFont normal;
PFont bold;
PImage img;

JSONObject response;

void setup() {

  size(1200, 800);
  smooth();

  normal = createFont("Arial", 10);
  bold = createFont("Arial Black", 10);

  // Specify Parameters
  api_key = "YOUR KEY"; //key
  url = "https://api.nytimes.com/svc/search/v2/articlesearch.json";
  String today = timestamp();
  end_day = /*31;*/ int(today.substring(4, 6))-2;
  end_month = /*10;*/ int(today.substring(2, 4));
  end_year = /*2018;*/ int("20" + today.substring(0, 2));
  if ((end_day - 2) <= 0) {
    if ((end_month - 1) <= 0) {
      begin_day = 29;
      begin_month = 12;
      begin_year = end_year - 1;
    } else {
      begin_day = 29;
      begin_month = end_month-1;
      begin_year = end_year;
    }
  } else {
    begin_day = end_day-2;
    begin_month = end_month;
    begin_year = end_year;
  }
  //begin_date = Integer.toString(begin_year) + Integer.toString(begin_month) + Integer.toString(begin_day); //eg. "20181001";
  begin_date = Integer.toString(begin_year) + String.format("%02d", begin_month) + String.format("%02d", begin_day); //eg. "20181001";
  println(begin_date);
  //end_date = Integer.toString(end_year) + Integer.toString(end_month) + Integer.toString(end_day); //eg. "20181031";
  end_date = Integer.toString(end_year) + String.format("%02d", end_month) + String.format("%02d", end_day); //eg. "20181031";
  println(end_date);
  sort = "newest";
  q = "Germany";

  // Specify HTTP-Request
  //GetRequest get = new GetRequest(url + "?" + "q=" + q + "&begin_date=" + begin_date + "&end_date=" + end_date + "&sort=" + sort);
  GetRequest get = new GetRequest(url + "?" + "q=" + q + "&begin_date=" + begin_date + "&end_date=" + end_date + "&sort=" + sort + "&api-key=" + api_key);
  //get.addHeader("api-key", api_key);
  // Send Request
  get.send();

  // Save response in JSON Object
  response = parseJSONObject(get.getContent());
  saveJSONObject(response, "nyt-test.json");

  // Get interesting informations
  headline = response.getJSONObject("response").getJSONArray("docs").getJSONObject(0).getJSONObject("headline").getString("main");
  snippet = response.getJSONObject("response").getJSONArray("docs").getJSONObject(0).getString("snippet");
  textLines = (headline + ": " + snippet);
  println(textLines);

  image_path = response.getJSONObject("response").getJSONArray("docs").getJSONObject(0).getJSONArray("multimedia").getJSONObject(0).getString("url");
  img = loadImage("https://www.nytimes.com/" + image_path);

  println(img.width+" x "+img.height);
}

void draw() {
  if (!closeTo) {
    if (int(frameCount/frameRate)%seconds==secoundCounter) {
    secoundCounter ++;
    if (articleNumber < (response.getJSONObject("response").getJSONArray("docs").size())-1) {
      articleNumber++;
    } else {
      articleNumber = 0;
    }
    if (response.getJSONObject("response").getJSONArray("docs").getJSONObject(articleNumber).getJSONArray("multimedia").size() > 0) {
      headline = response.getJSONObject("response").getJSONArray("docs").getJSONObject(articleNumber).getJSONObject("headline").getString("main");
      snippet = response.getJSONObject("response").getJSONArray("docs").getJSONObject(articleNumber).getString("snippet");
      textLines = (headline + ": " + snippet);
      image_path = response.getJSONObject("response").getJSONArray("docs").getJSONObject(articleNumber).getJSONArray("multimedia").getJSONObject(0).getString("url");
      img = loadImage("https://www.nytimes.com/" + image_path);
    } else {
      if (articleNumber < response.getJSONObject("response").getJSONArray("docs").size()-1) {
        articleNumber++;
      } else {
        articleNumber = 0;
      }
    }
  } 
  }

  if (!closeTo) {
    background(80);
  } else {
    background(255);
  }
  textAlign(LEFT);

  float x = 0, y = 10;
  int counter = 0;

  while (y < height) {
    // translate position (display) to position (image)
    int imgX = (int) map(x, 0, width, 0, img.width);
    int imgY = (int) map(y, 0, height, 0, img.height);
    // get current color
    color c = img.pixels[imgY*img.width+imgX];
    int greyscale = round(red(c)*0.222 + green(c)*0.707 + blue(c)*0.071);

    pushMatrix();
    translate(x, y);
    if (!closeTo) {
      rotate(PI/random(0, 10));
    }

    if (fontSizeStatic) {
      textFont(normal, fontSizeMax);
      if (blackAndWhite) fill(greyscale);
      else fill(c);
    } else {
      // greyscale to fontsize
      float fontSize = map(greyscale, 0, 255, fontSizeMax, fontSizeMin);
      fontSize = max(fontSize, 1);
      textFont(normal, fontSize);
      if (blackAndWhite) fill(0);
      else fill(c);
    } 

    char letter = textLines.charAt(counter);
    text(letter, 1, 0);
    float letterWidth = textWidth(letter)+ kerning;
    // for the next letter ... x + letter width
    x = x + letterWidth+1; // update x-coordinate
    popMatrix();

    // linebreaks
    if (x+letterWidth >= width) {
      x = 0;
      y = y + spacing; // add line height
    }

    counter++;
    if (counter > textLines.length()-1) counter = 0;
  }
  textFont(bold, 30);
  fill(255);
  rect(0, height-45, width, 45);
  fill(0);
  textAlign(CENTER);
  text(headline, width/2, height-10);

  if (savePDF) {
    savePDF = false;
    endRecord();
  }
}


void keyReleased() {
  
}

void keyPressed() {
  if (keyCode == LEFT) {
    spacing = fontSizeMax; // line height 12
    kerning = 0.5; // between letters 0.5
    closeTo = true;
  }

  if (keyCode == RIGHT) {
    spacing = 6; // line height 12
    kerning = -3; // between letters 0.5
    closeTo = false;
    seconds = second();
    secoundCounter = 1;
  }
}

// timestamp
String timestamp() {
  Calendar now = Calendar.getInstance();
  return String.format("%1$ty%1$tm%1$td_%1$tH%1$tM%1$tS", now);
}

Here you can download a ZIP-Folder with the complete program:

NYT_ArticleSearch – Processing-Program