Implementing xkcd.com/1031 for Twitter live Stream

If you don’t regularly read xkcd, please start now.

telnet www.sagaoftherealms.net 2211

The above command will log you into a server I am running. It is running a filter of Twitter looking for posts containing “keyboard” and replacing that word with “leopard”. (See www.xkcd.com/1031 if you don’t get the joke) This was surprisingly easy to write using the twitter4j library and Java 7′s new Asynchronous Socket Channels. It was also fast enough to handle at least 100 concurrent listeners when I was doing local testing.

For purposes of this post I will focus only on the Twitter4j integration.

Twitter4j uses StatusListener objects to consume StatusStreams. This is where I break up the message and replace my words.


StatusListener listener = new StatusListener() {

@Override
public void onStatus(Status status) {
String tweet = status.getText();
tweet = tweet.toLowerCase();
int index = tweet.indexOf("keyboard");
tweet = status.getText();
tweet = tweet.subSequence(0, index) + "leopard" + tweet.subSequence(index + 8, tweet.length());

queue.transfer("@" + status.getUser().getScreenName() + " - " + tweet);

}

public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {
System.out.println("Got a status deletion notice id:" + statusDeletionNotice.getStatusId());
}

public void onTrackLimitationNotice(int numberOfLimitedStatuses) {
System.out.println("Got track limitation notice:" + numberOfLimitedStatuses);
}

public void onScrubGeo(long userId, long upToStatusId) {
System.out.println("Got scrub_geo event userId:" + userId + " upToStatusId:" + upToStatusId);
}

public void onException(Exception ex) {
ex.printStackTrace();
}
};

Now we configure Twitter4j to consume the stream.


ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true).setUser("username").setPassword("password");

long[] ids = {};
String[] tags = {"keyboard"};

FilterQuery query = new FilterQuery(0, ids, tags);

TwitterStream twitterStream = new TwitterStreamFactory(cb.build()).getInstance();

twitterStream.addListener(listener);
StatusStream stream = twitterStream.getFilterStream(query);

while (true) {
stream.next(listener);
}

The code should be rather self explanatory. FilterQuery creates a query which is submitted by Twitter4J to instruct Twitter to stream back tweets containing “keyboard”. I create a stream using my credentials and then loop to process each event. None of these are particularly exciting, and this code should be called in a main function or some background thread because it will block as written.

Presentation from Ajug

Tonight I presented at the Atlanta Java User’s Group on Augmented Reality with Android and Qualcomm’s AR Toolkit. Here is the announcement and useful links

Download (PDF, 461.93KB)

Augmented Reality with Android

February, 21 2012

This month Summers Pittman is going to present on how to use computer vision technologies in Android. He will be presenting an Android application using the Qualcomm AR toolkit to control a Java game using Augmented Reality Tags.

About the speaker

Summers is a Java developer at Engauge in midtown Atlanta. He has a degree in Human Computer Interaction from Georgia Tech and serves as the AJUG Web Chair.

Creating a “Simple” MongoDB + Groovy + Maven Project

Currently, I am experimenting with writing a MOO (Programmable text based game). To facilitate the dynamic behavior I want to encourage, I decided to write it using Groovy and MongoDB with Maven[1] doing the actual building. However, the “real world” documentation of this combination has been rather lacking and thus, this post.

First let’s tackle Maven and Groovy. There are currently two Maven plugins for Groovy: GMaven and groovy-eclipse-compiler. GMaven generates .java stub files and tends to have a little bit better integration with Java. However, this leads to having lots of “weird”[2] errors which require a clean and build to fix. groovy-eclipse-compiler doesn’t generate stubs and works a little bit more smoothly in a mostly Groovy project, and that is the plugin I chose to use.

With that out of the way, let’s create the maven project.

mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes

For this example, I used “net.saga.blog” as my groupId and “GroovyMongoBlogPost” as my artifactId. If you choose to use different ones, make sure to update your package names accordingly.

Now let’s update the pom to include the groovy builders. First we have to add Groovy to our dependencies:

<dependency>
     <groupId>org.codehaus.groovy</groupId>
     <artifactId>groovy-all</artifactId>
     <version>1.8.5</version>
</dependency>

Next, let’s add the groovy-eclipse-compiler and our groovy source directories to our builders. Create a directory named “groovy” in both the src/main and src/test directories. Then add the following to your pom:

<plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <version>1.5</version>
                <executions>
                    <execution>
                        <id>add-source</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>src/main/groovy</source>
                            </sources>
                        </configuration>
                    </execution>
                    <execution>
                        <id>add-test-source</id>
                        <phase>generate-test-sources</phase>
                        <goals>
                            <goal>add-test-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>src/test/groovy</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <compilerId>groovy-eclipse-compiler</compilerId>
                    <verbose>true</verbose>
                    <source>1.7</source>
                    <target>1.7</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.codehaus.groovy</groupId>
                        <artifactId>groovy-eclipse-compiler</artifactId>
                        <version>2.6.0-01</version>
                    </dependency>
                </dependencies>
            </plugin>

Perform a quick build and make sure everything is set up correctly so far, I’ll wait.

Now let’s add in our first test. Create in “src/test/groovy” a file:SimpleGroovyTest.groovy.

package net.saga.blog.groovy
/**
 *
 * @author summers
 */
class SimpleGroovyTest extends GroovyTestCase {

    void testPass() {
        assert false
    }

}

Now perform a build and ensure that the build fails. Once you have a failing build, change false to true and rebuild for the green bar. We now have a fully functional Groovy project being built with Maven.

One of the things I ran into was that JUnit Suites and Groovy don’t behave as much as I would like. Also, a lot of libraries for Java still work “better” in a Java source file. To get around this, I overrode Maven’s default and used JUnit 4.10 and create a class to setup my database and then run the Groovy tests.

First, we replace the JUnit dependency with the following:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.10</version>
    <scope>test</scope>
</dependency>

Then we change our test class:

package net.saga.blog.groovymongoblogpost
import org.junit.Test
import com.gmongo.GMongo

/**
 *
 * @author summers
 */
class SimpleGroovyTest extends GroovyTestCase {

    @Test
    void testPass() {
        assert true
    }
}

Now we create a Java class in src/test/java/net/saga/blog/groovymongoblogpost directory.

package net.saga.blog.groovymongoblogpost;
import junit.framework.TestSuite;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
/**
 * Unit test for simple App.
 */
@RunWith(value = org.junit.runners.Suite.class)
@Suite.SuiteClasses({net.saga.blog.groovymongoblogpost.SimpleGroovyTest.class})
public class AppTestSuite
    extends TestSuite
{
    /**
     * Create the test case
     *
     * @param testName name of the test case
     */
    public AppTest( String testName )
    {
        super( testName );
    }
}

Finally, we reconfigure surefire in build/plugins in the pom to only run app suites.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.11</version>
    <configuration>
        <includes>
            <include>**/*TestSuite.java</include>
        </includes>
    </configuration>
</plugin>

Now rebuild your application and make sure your test is run. Once you get that, let’s move on to actually using MongoDB.

Installing MongoDB is beyond the scope of this tutorial (sorry if you were waiting this long for that), but it is rather trivial on a majority of systems. Ubuntu users, for instance, can sudo apt-get install mongodb. Your mileage may vary, but there are plenty of resources. What IS important is that you have Mongo running on your box (at 127.0.0.1) on the default port (27017).

For my project, I have chosen GMongo as my Groovy Mongo driver. It wraps the Java driver and makes is slightly Groovy-er. You will notice the code you write looks much like the Javascript code in your Mongo shell.

Now, add GMongo to your dependencies in your POM:

<dependency>
    <groupId>com.gmongo</groupId>
    <artifactId>gmongo</artifactId>
    <version>0.9.3</version>
</dependency>

Now let’s write some Mongo code. We will create a file that will populate some seed data in our database. This file will be called from the java test suite class. In the groovy test directory (src/test/groovy) create the file TestSetup.groovy.

import com.gmongo.GMongo
assert System.properties.database_address
//assert System.properties.database_user
assert System.properties.database_name
//assert System.properties.database_password
def port = System.properties.database_port?:27017
def address = System.properties.database_address
//def userName = System.properties.database_user
def databaseName = System.properties.database_name
//def password = System.properties.database_password
def mongo = new GMongo(address, port)
assert mongo
// Get a db reference in the old fashion way
def db = mongo.getDB(databaseName)
db.users.insert([name:'jesse', password:'scherer']);
db.users.insert([name:'kim', password:'berly']);
assert db.users.find([name:'jesse', password:'scherer'])[0] != null

And now we need to call it from AppTestSuite

Add some imports:

import groovy.lang.Binding;
import groovy.util.GroovyScriptEngine;
import java.io.IOException;
import junit.framework.TestSuite;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;

Some static code:

private final static String[] roots = new String[]{"src/test/groovy/net/saga/blog/groovymongoblogpost"};
    private final static GroovyScriptEngine gse;

    static {
        System.setProperty("database_address", "127.0.0.1");
        System.setProperty("database_name", "Testing");
        try {
            gse = new GroovyScriptEngine(roots);
        } catch (IOException ex) {
            throw new RuntimeException("failed to start tests", ex);
        }
    }

And actually call the file:

    @BeforeClass
    public static void setUpSuite() throws Exception {
        Binding binding = new Binding();
        gse.run("TestSetup.groovy", binding);
    }

Now we can add a test to our SimpleTestCase file

    @Test
    void testSimpleMongoFetch() {
        def port = System.properties.database_port?:27017
        def address = System.properties.database_address
        def databaseName = System.properties.database_name

        def mongo = new GMongo(address, port)
        def db = mongo.getDB("Testing")

        def userResult = db.users.find([name:'jesse', password:'password'])[0]

        assertNotNull( userResult )
        assertEquals ('jesse', userResult.name)
    }

Now if we build out app we should see that we have records in out database AND that groovy can query them.

Asides/Footnotes:
[1]: I understand Gradle may be a better technology (lord knows it can’t be worse), but Maven works much better in Netbeans and that has some pretty powerful side effects.
[2]: Basically if you update your groovy code, the linking will fail and trying to run your tests using the IDE will get a error until you clean and build.

Using an XBOX 360 Controller on Android

I’ve been working on a few Android games in my spare time. With the rollout of Honeycomb to my Logitech Revue, I’ve been able to finally test these games on it. One of the things I noticed was that the Revue has USB Host support and (wired) Xbox 360 controllers are simply plug and play. Using them is quite simple as well; the button presses are mostly mapped to the key event. The left and right triggers, right directional stick, and analog inputs are not mapped through this method however. The left analog stick and directional pads have their inputs mapped to direction buttons.

@Override
public  boolean onKeyDown(int keyCode, KeyEvent event) {
     switch(keyCode) {
          case KeyEvent.KEYCODE_BUTTON_L1:
          case KeyEvent.KEYCODE_BUTTON_R1:
          case KeyEvent.KEYCODE_BUTTON_THUMBR:
          case KeyEvent.KEYCODE_BUTTON_THUMBL:
          case KeyEvent.KEYCODE_DPAD_LEFT:
          case KeyEvent.KEYCODE_DPAD_RIGHT:
          case KeyEvent.KEYCODE_DPAD_UP:
          case KeyEvent.KEYCODE_DPAD_DOWN:
          case KeyEvent.KEYCODE_BUTTON_START:
          case KeyEvent.KEYCODE_BUTTON_MODE://Big button in the middle
          case KeyEvent.KEYCODE_BUTTON_B:
          case KeyEvent.KEYCODE_BUTTON_A:
          case KeyEvent.KEYCODE_BUTTON_X:
          case KeyEvent.KEYCODE_BUTTON_Y:
          default:
          return super.onKeyDown(keyCode, keyEvent);
     }
}

Of special note, KeyEvent.KEYCODE_BUTTON_B goes back and KeyEvent.KEYCODE_BUTTON_START pulls up home bar in the default implementation. Also, the “A” button has special behaviors which I don’t fully understand.

For the analog controls however, we must override the method onGenericMotionEvent as follows:

@Override
public boolean onGenericMotionEvent(MotionEvent event) {

	Log.d("Right Trigger Value", event.getAxisValue(MotionEvent.AXIS_RTRIGGER) + "");
	Log.d("Left Trigger Value", event.getAxisValue(MotionEvent.AXIS_LTRIGGER) + "");

    Log.d("Left Stick X", event.getX() + "");
	Log.d("Left Stick Y", event.getY() + "");

	Log.d("Right Stick Y", event.getAxisValue(MotionEvent.AXIS_RZ) + "");
	Log.d("Right Stick X", event.getAxisValue(MotionEvent.AXIS_Z) + ""); 

	return super.onGenericMotionEvent(event);
}