The Experience Generator

For my project, I wanted to process my user’s interactions into actual control of their desktop. I utilize the arduino’s serial connections and java’s ability to control your keyboard and mouse to turn a big red button and a sliber bar into an “Interactive Reddit Experience Generator.” By Translating the slider movement to be a scaled value from “Mundane and Probably SFW” to “Different and Probably NSFW” I allow the user to dictate the browsing experience of the current session with the click of a button. The Decisions on what is “Different” or “Mundane” is currently up to my personal taste but I would like to write an algorithm which automatically does this for me.

Here are a few stills of what the experience generator can throw out.

Snap 2014-10-29 at 18.15.37

Snap 2014-10-29 at 18.16.16

Snap 2014-10-29 at 18.16.56

Here is my Arduino and Processing Code (The Arduino code is about the same as the example code, while the processing code uses quite a few java libraries.”

Special thanks to Alvin Alexander at alvinalexander.com for a well documented java typing example!

// This Processing program reads serial data for two sensors,
// presumably digitized by and transmitted from an Arduino. 
// It displays two rectangles whose widths are proportional
// to the values 0-1023 received from the Arduino.
 
// Import the Serial library and create a Serial port handler
import processing.serial.*;
import java.awt.Desktop;
import java.net.URI;
Serial myPort;   

import java.awt.Robot;
import java.awt.AWTException;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

Robot rob;

boolean run = false;
int timeHit = 0;

ArrayList<Tuple> rankings;

int listLength;
 
// Hey you! Use these variables to do something interesting. 
// If you captured them with analog sensors on the arduino, 
// They're probably in the range from 0 ... 1023:
int valueA;  // Sensor Value A
int valueB;  // Sensor Value B
 
//------------------------------------
void setup() { 
  size(50,50);
  rankings = new ArrayList<Tuple>();
  initList();
  
  //Set up Bot to move mouse
  try {
  rob = new Robot();
  }
  catch (AWTException e) {
    e.printStackTrace();
  }
 
  // List my available serial ports
  int nPorts = Serial.list().length; 
  for (int i=0; i < nPorts; i++) {
    println("Port " + i + ": " + Serial.list()[i]);
  } 
 
  // Choose which serial port to fetch data from. 
  // IMPORTANT: This depends on your computer!!!
  // Read the list of ports printed by the code above,
  // and try choosing the one like /dev/cu.usbmodem1411
  // On my laptop, I'm using port #4, but yours may differ.
  String portName = Serial.list()[0]; 
  myPort = new Serial(this, portName, 9600);
  serialChars = new ArrayList();
  rob.delay(300); 
}
 
//------------------------------------
void draw() {
 
  // Process the serial data. This acquires freshest values. 
  processSerial();

  if ((valueB > 0) && (!run) && (millis() - timeHit > 50)) {
      run = true;
      timeHit = millis();
      runWindow();
      delay(300);
  }
  if ((run) && valueB > 0) {
      findSub();
      rect(0,0,width,height);
  }
}
 
ArrayList serialChars;      // Temporary storage for received serial data
int whichValueToAccum = 0;  // Which piece of data am I currently collecting? 
boolean bJustBuilt = false; // Did I just finish collecting a datum?
 
void processSerial() {
 
  while (myPort.available () > 0) {
    char aChar = (char) myPort.read();
 
    // You'll need to add a block like one of these 
    // if you want to add a 3rd sensor:
    if (aChar == 'A') {
      bJustBuilt = false;
      whichValueToAccum = 0;
    } else if (aChar == 'B') {
      bJustBuilt = false;
      whichValueToAccum = 1;
    } else if (((aChar == 13) || (aChar == 10)) && (!bJustBuilt)) {
      // If we just received a return or newline character, build the number: 
      int accum = 0; 
      int nChars = serialChars.size(); 
      for (int i=0; i < nChars; i++) { 
        int n = (nChars - i) - 1; 
        int aDigit = ((Integer)(serialChars.get(i))).intValue(); 
        accum += aDigit * (int)(pow(10, n));
      }
 
      // Set the global variable to the number we captured.
      // You'll need to add another block like one of these 
      // if you want to add a 3rd sensor:
      if (whichValueToAccum == 0) {
        valueA = accum;
        // println ("A = " + valueA);
      } else if (whichValueToAccum == 1) {
        valueB = accum;
        // println ("B = " + valueB);
      }
 
      // Now clear the accumulator
      serialChars.clear();
      bJustBuilt = true;
 
    } else if ((aChar >= 48) && (aChar <= 57)) {
      // If the char is between '0' and '9', save it.
      int aDigit = (int)(aChar - '0'); 
      serialChars.add(aDigit);
    }
  }
}

void runWindow() {
    if(Desktop.isDesktopSupported()) {
      try {
          Desktop.getDesktop().browse(new URI("http://www.google.com"));
      } catch (Exception e) {
        println("Oh no");
      }
   }
}

void initList() {
  //Initialize List (Yes it's ugly but it was a 
//quick conversion from python)
rankings.add(new Tuple("pics", -1));
rankings.add(new Tuple("funny", 0));
rankings.add(new Tuple("aww", 0));
rankings.add(new Tuple("cats", 0));
rankings.add(new Tuple("dIY", 0));
rankings.add(new Tuple("todayilearned", 1));
rankings.add(new Tuple("videos", 1));
rankings.add(new Tuple("gaming", 1));
rankings.add(new Tuple("politics", 1));
rankings.add(new Tuple("technology", 1));
rankings.add(new Tuple("space", 1));
rankings.add(new Tuple("bitcoin", 1));
rankings.add(new Tuple("art", 1));
rankings.add(new Tuple("foodporn", 1));
rankings.add(new Tuple("blep", 1));
rankings.add(new Tuple("askreddit", 2));
rankings.add(new Tuple("atheism", 2));
rankings.add(new Tuple("imgoingtohellforthis", 2));
rankings.add(new Tuple("gentlemanboners", 2));
rankings.add(new Tuple("tattoos", 2));
rankings.add(new Tuple("nosleep", 2));
rankings.add(new Tuple("malefashionadvice", 2));
rankings.add(new Tuple("woodworking", 2));
rankings.add(new Tuple("christianity", 2));
rankings.add(new Tuple("nononono", 2));
rankings.add(new Tuple("gaybros", 2.3));
rankings.add(new Tuple("tinder", 2.5));
rankings.add(new Tuple("microgrowery", 2.7));
rankings.add(new Tuple("trees", 3));
rankings.add(new Tuple("relationships", 3));
rankings.add(new Tuple("shittynosleep", 3));
rankings.add(new Tuple("lifehacks", 3));
rankings.add(new Tuple("girlsinyogapants", 3));
rankings.add(new Tuple("politota", 3));
rankings.add(new Tuple("forwardsfromgrandma", 3.2));
rankings.add(new Tuple("ebola", 3.5));
rankings.add(new Tuple("WTF", 4));
rankings.add(new Tuple("nsfw", 4));
rankings.add(new Tuple("realgirls", 4));
rankings.add(new Tuple("ladyboners", 4));
rankings.add(new Tuple("exmormon", 4));
rankings.add(new Tuple("odd", 4));
rankings.add(new Tuple("nofap", 4));
rankings.add(new Tuple("swoleacceptance", 4));
rankings.add(new Tuple("colanders", 4));
rankings.add(new Tuple("4chan", 5));
rankings.add(new Tuple("nsfw_gif", 5));
rankings.add(new Tuple("ass", 5));
rankings.add(new Tuple("youtubehaiku", 5));
rankings.add(new Tuple("asstastic", 5));
rankings.add(new Tuple("humanporn", 5));
rankings.add(new Tuple("classic4chan", 5));
rankings.add(new Tuple("milf", 6));
rankings.add(new Tuple("creepypms", 6));
rankings.add(new Tuple("mensrights", 6));
rankings.add(new Tuple("translucent_porn", 6));
rankings.add(new Tuple("fiftyfifty", 7));
rankings.add(new Tuple("futanari", 7));
rankings.add(new Tuple("watchpeopledie", 9));
rankings.add(new Tuple("spacedicks", 10));

listLength = rankings.size();
}

void leftClick() {
    rob.mousePress(InputEvent.BUTTON1_MASK);
    rob.delay(200);
    rob.mouseRelease(InputEvent.BUTTON1_MASK);
    rob.delay(200);
    }

void type( String s) {
  rob.keyPress(KeyEvent.VK_CONTROL);
  rob.keyPress(KeyEvent.VK_L);
  
  rob.keyRelease(KeyEvent.VK_CONTROL);
  rob.keyRelease(KeyEvent.VK_L);
  byte[] bytes = s.getBytes();
  for (byte b : bytes)
  {
    int code = b;
    if (code > 96 && code < 123){
      code = code - 32;
      rob.delay(100);
      rob.keyPress(code);
      rob.keyRelease(code);
    }
    else if (code == 46) {
      rob.keyPress(KeyEvent.VK_PERIOD);
      rob.keyRelease(KeyEvent.VK_PERIOD);
    }
    else if (code == 47) {
      rob.keyPress(KeyEvent.VK_SLASH);
      rob.keyRelease(KeyEvent.VK_SLASH);
    }
    else if (code == 95) {

    }
      
   
  }
  rob.keyPress(KeyEvent.VK_ENTER);
  rob.keyRelease(KeyEvent.VK_ENTER);
}

class Tuple {
  public String value;
  public float rating;
  public Tuple(String v, float r) {
    value = v;
    rating = r;
  }
}

void findSub() {
  delay(100);
  int i = (int)map(valueA, 0, 1000, 0, listLength-2) ;
  String sub = rankings.get(i).value;
  String url = String.format("reddit.com/r/%s",sub);
  type(url);
}

Here’s the Arduino code

int sensorValue0 = 0;  // variable to store the value coming from the sensor
int sensorValue1 = 0;  // variable to store the value coming from the other sensor
 
void setup() {
  Serial.begin(9600);  // initialize serial communications    
}
 
void loop() {
 
  // Read the value from the sensor(s):
  sensorValue0 = analogRead (A0);  // reads value from Analog input 0
  sensorValue1 = analogRead (A1);  // reads value from Analog input 1    
 
  Serial.print ("A"); 
  Serial.println (sensorValue0); 
  Serial.print ("B"); 
  Serial.println (sensorValue1);  
 
  delay (50);   // wait a fraction of a second, to be polite
}

Here’s a fritzing diagram of the circuit I used.

ExperienceGenerator

Comments are closed.