As you have seen from my previous posts, I have been using Scrumwise to help me facilitate Scrum in my projects. The think which I am missing but is on the wish-list is reporting. As teamlead I had to report to projectmanagers about progress, hours burned etc… All these things I can get from Scrumwise through its API. See https://www.scrumwise.com/api.html .
To get this done I wrote a simple Java program to get the a nice up-to-date printout of the stats. The first thing is you need to generate an API key in Scrumwise and get the code from there. Is this next bit I will show you how to connect to Scrumwise. It looks like this:
/**
* Connect to Scrumwise and get all the scrumwise details in a JSONObject
*
* @return JSONObject the result of the call
* @throws Exception
*/
private static JSONObject callScrumwise() throws Exception {
JSONObject result = null;
// Setup proxy if needed
//Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(
// PROXY_IP, PROXY_PORT));
// Setup connection
URL url = new URL("https://api.scrumwise.com/service/api/v1/getData");
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
// setup credentials
String loginPassword = "USERNAME:API-KEY";
// Overwrite the setting or else it will cut of the encoded password
String encoded = new sun.misc.BASE64Encoder() {
@Override
protected int bytesPerLine() {
return 9999;
}
}.encode(loginPassword.getBytes());
connection.setRequestProperty("Authorization", "Basic " + encoded);
// setup POST parameters
String urlParameters = "projectIDs=null&includeProperties=Project.backlogItems,BacklogItem.timeEntries, BacklogItem.tasks, Task.timeEntries, Data.persons";
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = connection.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + urlParameters);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// proces result
result = (JSONObject) JSONSerializer.toJSON(response.toString());
return result;
}
After that I loop through the items and pick out the backlogitems I need per project. I named the backlog items following the next convention: <project-code> <project-name>.
//project MyProject private static String MyProject = "131206 MyProject: "; //project MyProject backlog items private static ListmyprojectBacklogItems = new ArrayList (Arrays.asList("Design", "Develop", "Test", "Coordinate"));
After this I call my generic method which prints me all the backlogitems with their hours and status. This looks something like this:
/**
* Print time per user
* @param aJson
* @param aName
*/
private static void printUsedTimePerUser(JSONObject aJson, String aName){
Map result = new HashMap();
JSONArray projects = (JSONArray) aJson.getJSONObject("result").getJSONArray("projects");
//loop through all projects
for (int i = 0; i < projects.size(); i++) {
JSONObject project = projects.getJSONObject(i);
JSONArray backlogitems = project.getJSONArray("backlogItems");
//loop through all backlogitems
for (int j = 0; j < backlogitems.size(); j++) {
JSONObject backlogItem = backlogitems.getJSONObject(j);
//filter only the mosaic backlogitems
if (backlogItem.getString("name").startsWith(aName)) {
//System.out.printf("\n=====================================================================================================================================\n");
// get hours under backlogitem
JSONArray timeEntries = backlogItem.getJSONArray("timeEntries");
for (int k = 0; k < timeEntries.size(); k++) {
JSONObject timeEntry = timeEntries.getJSONObject(k);
int backlogTimeEntry = timeEntry.getInt("usedTime");
String person = timeEntry.getString("personID");
Integer usedTime = result.get(person);
if(usedTime == null){
result.put(person, new Integer(backlogTimeEntry));
}
else{
result.put(person, usedTime + backlogTimeEntry);
}
}
// get tasks under backlogitem
JSONArray tasks = backlogItem.getJSONArray("tasks");
for (int l = 0; l < tasks.size(); l++) {
JSONObject task = tasks.getJSONObject(l);
Iterator taskTimeIter = task.getJSONArray("timeEntries").iterator();
while (taskTimeIter.hasNext()) {
JSONObject timeEntry = taskTimeIter.next();
String person = timeEntry.getString("personID");
int taskTimeEntry = timeEntry.getInt("usedTime");
//System.out.println("Person " + person + " wrote " + taskTimeEntry + " hours on " + task.getString("name"));
Integer usedTime = result.get(person);
if(usedTime == null){
result.put(person, new Integer(taskTimeEntry));
}
else{
result.put(person, usedTime + taskTimeEntry);
}
}
}
}
}
}
System.out.println(result.toString());
}
In the end….when you run all this you will get a simple output of the all the items which will look something like this:
Sending ‘POST’ request to URL : https://api.scrumwise.com/service/api/v1/getData
Post parameters : projectIDs=null&includeProperties=Project.backlogItems,BacklogItem.timeEntries, BacklogItem.tasks, Task.timeEntries, Data.persons
Response Code : 200
MyProject: hours per item
================================================================================================================================= Subject | 131206 MyProject: Design = 99 uur | Sprint completed Task | Design Database = 99 uur | Done ================================================================================================================================= Subject | 31206 MyProject: Develop = 31 uur | In progress Task | Create proxy service = 11 uur | Done Task | Create business service = 4 uur | Done Task | Create xquery = 4 uur | In progress Task | Import WSDL's = 6 uur | Done Task | Junit test = 6 uur | In progress
…….etc
As you can see I haven’t really spend a lot of time optimizing code etc as i needed something quick and dirty and this does the job. Still work in progress but it will give you an idea of what is possible.
