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){ Mapresult = 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.