Posts Tagged ‘java’

Toodledo API (simple java version)

Sunday, June 5th, 2011

Wanted to get a list of all the bugs for my Star Trek game, that I have registered at Toodledo and have them listed on the Trekwar wiki.

Toodledo offers a nicely done API, but there was no java implementation, there were a couple of unofficial ones, but I decided to write my own very simple basic program for connecting to Toodledo and getting all the tasks as XML, and parsing them into a simple Java object. So if you’re doing something similar, this program might be a nice place to start. To keep it as short as possible, comments and exception handling is pretty much not there :)

download the file: Toodledo2html.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
 
class Task {
    String id;
    String title;
    String modified;
    String completed;
 
    String folder;
    String context;
    String tag;
    String status;
    String priority;
    String length;
    String note;
}
 
public class Toodledoo2html {
    // TODO you must get the 4 values below from Toodledo
    private static String appID = "x";
    private static String userID = "x";
    private static String userPW = "x";
    private static String applicationToken = "x";
 
    private static String fields = "folder,context,tag,status,priority,length,note"; // get these fields when downloading tasks
 
    private static String sessionToken;
    private static String key;
 
    private static String toodledoTokenURL = "https://api.toodledo.com/2/account/token.php";
    private static String toodledoGetTaskURL = "https://api.toodledo.com/2/tasks/get.php";
 
    public static void main(String[] args) {
        sessionToken = getSessionToken(md5(userID+applicationToken));
        key = md5(md5(userPW)+applicationToken+sessionToken);
        ArrayList<Task> tasks = getTasks();
        // do whatever to tasks
    }
 
    private static ArrayList<Task> getTasks() {
        try {
            String data = "?key=" + key + ";fields=" + fields + ";f=xml";
 
            System.out.println("Getting tasks: " + toodledoGetTaskURL + data);
 
            URL url = new URL(toodledoGetTaskURL + data);
            URLConnection connection = url.openConnection();
            connection.setDoOutput(true);
 
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            StringBuilder xml = new StringBuilder();
            String line = in.readLine();
            while( line != null) {
                System.out.println(line);
                xml.append(line);
                line = in.readLine();
            }
            in.close();
 
            ArrayList<Task> tasks = xmlToTasks(xml.toString());
 
            for(Task t : tasks) {
                System.out.println(t.id + " " + t.title);
            }
            return tasks;
 
        } catch (MalformedURLException ex) {
            System.out.println(ex);
        } catch (IOException ioe) {
            System.out.println(ioe);
        }
        return null;
    }
 
    private static ArrayList<Task> xmlToTasks(String xml) {
        ArrayList<Task> taskList = new ArrayList<Task>();
 
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(new InputSource(new StringReader(xml)));
 
            Element root = doc.getDocumentElement();
 
            NodeList tasks = root.getElementsByTagName("task");
            for (int i = 0; i < tasks.getLength(); i++) {
                Element task = (Element) tasks.item(i);
 
                Task t = new Task();
                t.id = getDomTextValue(task, "id");
                t.title = getDomTextValue(task, "title");
                t.modified = getDomTextValue(task, "modified");
                t.completed = getDomTextValue(task, "completed");
 
                t.folder = getDomTextValue(task, "folder");
                t.context = getDomTextValue(task, "context");
                t.tag = getDomTextValue(task, "tag");
                t.status = getDomTextValue(task, "status");
                t.priority = getDomTextValue(task, "priority");
                t.length = getDomTextValue(task, "length");
                t.note = getDomTextValue(task, "note");
                taskList.add(t);
            }
 
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(Toodledoo2html.class.getName()).log(Level.SEVERE, null, ex);
        }
        catch(SAXException se) {
 
        }
        catch(IOException ioe) {
 
        }
 
        System.out.println("xmlToTasks got " + taskList.size() + " tasks");
        return taskList;
    }
 
    private static String getSessionToken(String signature) {
        try {
            String data = "?userid=" + userID + ";appid=" + appID + ";sig=" + signature + ";f=xml";
 
            System.out.println("Getting session token: " + toodledoTokenURL+data);
 
            URL url = new URL(toodledoTokenURL + data);
            URLConnection connection = url.openConnection();
            connection.setDoOutput(true);
 
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String xml = in.readLine();
            in.close();
            String token = xml.substring(xml.indexOf("<token>")+7, xml.indexOf("</token>"));
            return token;
        } catch (MalformedURLException ex) {
            System.out.println(ex);
        }
        catch(IOException ioe) {
            System.out.println(ioe);
        }
        return "";
    }
 
    private static String md5(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(input.getBytes());
 
            byte byteData[] = md.digest();
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < byteData.length; i++) {
                sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException nse) {
            System.err.println("ERROR. MD5 ALGORITHM NOT FOUND");
            return "";
        }
    }
 
    public static String getDomTextValue(Element element, String tag) {
        if (element != null) {
            NodeList nl = element.getElementsByTagName(tag);
            if (nl != null && nl.getLength() > 0) {
                Element el = (Element) nl.item(0);
                if(el != null && el.getFirstChild() != null) {
                    return el.getFirstChild().getNodeValue();
                }
            }
        }
        return "";
    }
}

Note: This program was made to run once per hour.. running this program many times in a row will cause Toodledo to ban you for about 1 hour. When that happens there will be a IndexOutOfBoundsException -7 from the method that gets the session token. This can be fixed by saving the token you get between requests, and not asking for a new one each time (which is what causes the short ban).

Increasing earthquakes?

Saturday, May 14th, 2011

Are earthquakes increasing in strength or frequency?

Just found myself in a debate where the opposition claims earthquakes is on the rise (judgement day, wrath of god, etc..), being a skeptic I of course needed evidence, and where better to get it than to analyse it for myself from raw data?

How many earthquakes are there?
I went to the United States Geological Survey for the raw data, they have a pretty big list of “selected earthquakes of general historic interest” (6.0+) earthquakes recorded (ordered by magnitude, strongest quake first)
http://earthquake.usgs.gov/earthquakes/world/historical_mag_big.php

I then made a little computer program to parse the text, and output it in csv format:
java program: Test.java
data text file: quakes.txt (program input)
csv result file: quakes.csv (program output)

The output from the data was opened in a spreadsheet for further analysis. There are 722 quakes in the input data file. I used the data from the period 1900 to 2010 in the statistics below (660 of the 722 total data entries).

The data in table form

6+ 7+ 8+
1900 9 5 1
1905 14 12 5
1910 14 9 1
1915 9 6 0
1920 10 8 3
1925 15 10 0
1930 20 13 4
1935 12 7 2
1940 16 15 4
1945 21 18 5
1950 21 11 3
1955 20 18 3
1960 12 10 3
1965 34 18 3
1970 21 13 2
1975 18 12 0
1980 15 4 0
1985 17 6 1
1990 17 11 1
1995 31 21 1
2000 110 50 5
2005 194 67 8

The first column is the date of the quakes, the next 3 are number of earthquakes with a magnitude of at least 6, 7 and 8 respectively.
Data is grouped into 5 years.. so the first row with year 1900, is data from 1900 to 1904, followed by 1905 to 1909, etc..

Graph
Earhquake frequency last 110 years

Click for larger version

Conclusion
This graph makes it look like earthquakes are running rampant, and you might have seen a very similar graph on the Internet (YouTube and other places), used by conspiracy cranks as an argument that earthquakes are increasing. But fortunately this graph is very misleading.

The data used to make it is complete rubbish, to quote the page they are collected from: “selected earthquakes of general historic interest”.. These quakes have been hand picked as the most interesting ones, and the data has a HUGE bias towards newer earthquakes, so you can’t make any meaningful statistics out of it (except if you are making statistics of which years the guy who compiled the data finds “interesting”).

Maybe we should try and remake the graphs using some good solid data..

== Real Data ==

A scientist at the USGS was kind enough to send me a datafile with all the 7.0+ earthquakes from 1900 to 2010 (all the registered quakes, not filtered in any way).

Making some graphs from those data yields results consistent with what the experts on earthquakes are saying.. They are totally random and unpredictable, and there has been no increase of earthquakes since we started recording them:

Frequency of earthquakes from 1900 to 2010. Click for bigger version:
Earthquake frequency, 1900 to 2010

Distribution of earthquakes by month:
Earthquakes by month

Distribution of earthquakes by day of month, (day 31 omitted for obvious reasons):
Earthquakes by day of  month

Distribution of earthquakes by hour of day:
Earthquakes by hour of day

Coloring stuff

Wednesday, August 18th, 2010

Seeing that I got nothing better to do, I finished up a half done project of mine the other day.

I wrote this program mostly just because I was messing around with different pathing/filling algorithms and the Java PixelGrabber class.

The program lets you color different motives (animals, people, vehicles, etc..) and I’ve probably spent more time coloring dogs and bunnies than actual programming :)

Kolor with Kribsy

Download Kolor with Kribsy

Kribsy BTW is a poorly drawn imaginary bunny with self esteem issues and a knack for painting stuff :)

Lady Java (Javazone song)

Friday, August 13th, 2010

Check out this awesome music video for JavaZone

I guess we CAN make cool music that’s not Black Metal. Haven’t felt such a surge of patriotism since the good old days.

The song says what I’ve been saying for years (except I’m usually not as polite): “Some people prefer other languages, and that’s OK if you’re retarded I guess”

Oups

Monday, March 15th, 2010

While cleaning up in the core classes of Trekwar yesterday (documenting functions, formatting/structuring code, minor improvements) I also saw lots of equals(Object o) methods. And in my infinite wisdom I decided to use generics since it is used pretty extensively throughout the code anyway, so I changed basically all the equals methods.

example:

public boolean equals(Object o) {
        if(o instanceof Structure)
            return equals((Structure)o);
        return false;
    }

was changed to:

public boolean equals(Structure s2) {
        return name.equals(s2.getName());
    }

Now this is not a problem when writing code, as you pretty much always compare objects of the same type. However, the code also uses the Java Collections contains() method a few places, and it always uses the equals(Object) version. So when my classes no longer provided this method, the default one inherited from java.lang.Object was used instead. This caused a strange array of bugs to appear (star systems on the map not shown with faction color/icon except for the Cardassians for some strange reason, users not having any technologies, unable to build any structures, generally erratic behavior, etc..). Luckily I discovered the cause pretty quickly and only wasted about an hour or so on this :)

I guess the lesson is that objects that needs to be compared, directly or indirectly by contains() or other methods, should always define an equals(Object) method that just passes the call along to the equals method written with generics.

public boolean equals(Object o) {
        if(o instanceof Structure) {
            return equals((Structure)o);
        }
        return false;
    }

And perhaps that you should not mess around with your code for hours on end without stopping to test if you broke it once in a while :)

Debug poem

Thursday, March 11th, 2010

Today I wasted two hours locating and fixing a trivial bug:

“Spent hours debugging my code, fixing hacks
but somehow mistook Math.min() for Math.max()”

Today I wasted 5 minutes trying to think of something that rhymes with “Math.max()”

Trekwar cargo system

Sunday, March 7th, 2010

Today I mostly finished the Trekwar Cargo system, so now it’s possible to collect resources and bring them back to your starsystems.

Also included 4 images from the design and implementation of the UI:

Read full devblog post at trekwar.org

I love VPS.net!

Monday, March 1st, 2010

I recently moved all my php sites to a new server, about a month ago, and had previously used VPS.net for my jsp/svn/etc.. server for quite a few months.

Running tomcat and sql + a few other things have used up almost all the memory on my java server, so I was thrilled to find a mail from vps.net in my inbox today, stating that they will upgrade all nodes from 256 mb ram to 375, and add 200 mhz cpu :D

on VPS.net you create your own virtual server which is made up of 1-18 nodes (1 node = 256 mb ram, 400 mhz cpu, 10 gb disk). So it’s very easy to make new machines, or upgrade an existing one by adding more nodes (then just restart the virtual server).

The server has been extremely stable, fast (the site your on now runs on a single node) and only restarted once, the website it runs is being monitored and have not had any downtime. This is by FAR the best virtual (or even dedicated!) server solution I’ve ever tried, and I would absolutely recommend it for anyone who needs a virtual or dedicated server. 1 node is just 20$ per month, there are no sign up fees and you can cancel at any time (1 node will be able to host a good amount of http/php/mysql content).

And if anyone wonders, no I’m not getting paid by VPS to advertise for them :) They’re just so awesome that I HAD to mention it, there are so many crappy hosting / virtual server companies but these guys really are awesome :)

Using WeakReference to confirm/find memory leaks in Java

Friday, September 4th, 2009

I recently had a memory leak in my Trekwar game, and to find it (or at least confirm it’s there) I used the WeakReference object in Java..

This is how I proceeded in locating the memory leak, this method could easily be adapted to other programs.

Trekwar is turn based, so each turn the client downloads a Galaxy object from the server. There are many references to this objects inside action listeners, threads, etc..

WeakReference
To make a long story short, a weak reference is like a normal reference, except it will not prevent the object it points to from being garbage collected.

This means that is you  have a normal and a weak reference to object A, the weak reference will be null if you remove the “hard” reference.

1) In the client main executable (the class that holds the method that updates the map from the server). Import, declare and make a list of weak references

import java.lang.ref.WeakReference;
private ArrayList<WeakReference<Galaxy>> weakRefs;
 
weakRefs = new ArrayList<WeakReference<Galaxy>>();

2) Find the place in your program where a new object is being added, in my place this is the localGalaxy object. Create a weak reference to this object, and list all your weak references.

localGalaxy = (Galaxy) objStream.readObject();
weakRefs.add(new WeakReference(localGalaxy));
for(int i = 0; i < weakRefs.size(); i++) {
System.out.print("ref # " + i + " = ");
try {
Galaxy testG = (Galaxy)weakRefs.get(i).get();
System.out.println(testG + ", tick = " + testG.currentTick);
}
catch(NullPointerException npe) {
System.out.println("null");
}
}

And you’re done!

Now when you run the program, you should see something like this each time the method is called

ref # 0 = org.aakretech.trekwar2.common.Galaxy@11ed166, tick = 37
ref # 1 = org.aakretech.trekwar2.common.Galaxy@9801f4, tick = 37
ref # 2 = org.aakretech.trekwar2.common.Galaxy@1c5d81c, tick = 38
ref # 3 = org.aakretech.trekwar2.common.Galaxy@101f8f4, tick = 39
ref # 4 = org.aakretech.trekwar2.common.Galaxy@1ed1e7e, tick = 40
ref # 5 = org.aakretech.trekwar2.common.Galaxy@e0a7ea, tick = 41

Unless you want to wait until your GC decides it’s time to go, use a tool like VisualVM to force the Garbage Collector to run.

After the GC has run, the output should look like this:

ref # 0 = null
ref # 1 = null
ref # 2 = null
ref # 3 = null
ref # 4 = null
ref # 5 = null
ref # 6 = org.aakretech.trekwar2.common.Galaxy@2b3c91, tick = 42

Now, this means that the object IS being garbage collected, and there is no memory leak.. If you run this and the object you are monitoring (in this example the localGalaxy object) is not GC’ed because of stray references, you can tell because none of the references will point to null.

JavaEaster

Friday, April 10th, 2009

Easter is almost over, and I used most of the time to complete the Trekwar shipdesigner, and set up lots of hulls for it.. I also created a chat system for the game.

ShipDesigner:
trekwar_shipdesigner_boomship

Faction Hulls:
xtrekwar_hulls_easter09

Chat:
trekwar_chat

I was planning to implement the ship actions, like colonization and ship combat this easter. But I think I’ll work on the Starsystem management system instead, as I redesigned it heavily this easter.