package de.tud.kom.socom.web.server.database.statistics; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashSet; import java.util.Set; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import de.tud.kom.socom.web.server.database.HSQLAccess; import de.tud.kom.socom.web.server.util.Logger; import de.tud.kom.socom.web.server.util.LoggerFactory; public class HSQLStatisticDatabase implements StatisticDatabase { private static StatisticDatabase instance = new HSQLStatisticDatabase(); private Logger logger = LoggerFactory.getLogger(); private static HSQLAccess db; private HSQLStatisticDatabase() { db = HSQLAccess.getInstance(); } public static StatisticDatabase getInstance() { return instance; } @Override public JSONObject getGameGraphJSON(long instanceid) throws SQLException, JSONException { PreparedStatement statement = db.getPreparedStatement("SELECT * FROM gameinstances WHERE id = ?;"); statement.setLong(1, instanceid); ResultSet rs = statement.executeQuery(); if(!rs.next()){ // instance doesnt exist logger.Debug("Instance " + instanceid + " not found, abort."); return null; } JSONObject json = new JSONObject(); json.put("instanceid", instanceid); JSONArray contextarray = new JSONArray(); statement = db.getPreparedStatement("SELECT " + "gamecontexts.name, " + "gamecontexts.externalid, " + "gamecontexts.autogenerated, " + "gamecontexts.id, " + "COUNT(DISTINCT gamecontent.id) AS contentcount, " + "SUM(DISTINCT gamecontent.hits) AS contenthitstotal, " + "COUNT(DISTINCT influence.id) AS influencecount, " + "COUNT(DISTINCT userprogress.uid) AS usersseen, " + "SUM(userprogress.playtime) AS timespenttotal " + "FROM " + "((gamecontexts LEFT JOIN gamecontent ON gamecontent.contextid = gamecontexts.id) " + "LEFT JOIN influence ON influence.contextid = gamecontexts.id) " + "LEFT JOIN userprogress ON userprogress.scnid = gamecontexts.id " + "WHERE " + "gamecontexts.gameinstid = ? " + "GROUP BY " + "name, " + "externalid," + "autogenerated, " + "id;"); statement.setLong(1, instanceid); rs = statement.executeQuery(); JSONArray endNodes = new JSONArray(); long startNode = -1; Set<Long> gotRelations = new HashSet<Long>(); Set<Long> nodes = new HashSet<Long>(); long timeSpentAvgMin = Long.MAX_VALUE, timeSpentAvgMax = 0; while(rs.next()) { long id = rs.getLong("id"); nodes.add(id); boolean autogenerated = rs.getBoolean("autogenerated"); String name = rs.getString("name"); String externalid = rs.getString("externalid"); long timeSpentTotal = rs.getLong("timespenttotal"); long usersSeen = rs.getLong("usersseen"); long timeSpentAvg = usersSeen > 0 ? timeSpentTotal / usersSeen : 0; if(timeSpentAvg > timeSpentAvgMax) timeSpentAvgMax = timeSpentAvg; if(timeSpentAvg < timeSpentAvgMin) timeSpentAvgMin = timeSpentAvg; long contentCount = rs.getLong("contentcount"); long influenceCount = rs.getLong("influenceCount"); long contentHits = rs.getLong("contenthitstotal"); JSONArray relations = getRelations(id, gotRelations); contextarray.put(new JSONObject().put("id", id).put("data", new JSONObject().put("id", id).put("autogenerated", autogenerated) .put("name", name).put("timeSpentTotal", timeSpentTotal).put("timeSpentAvg", timeSpentAvg).put("externalid",externalid) .put("usersSeen", usersSeen).put("contentCount", contentCount).put("influenceCount", influenceCount) .put("contentHits", contentHits).put("relationsTo", relations))); if(relations.length() == 0) // no relations anywhere -> endnodes.. (dead-end) endNodes.put(id); } for(long node : nodes){ if(!gotRelations.contains(node)) startNode = node; } if(startNode == -1) { startNode = findStartNodeFromFromStartingTimes(instanceid); } json.put("contexts", contextarray); json.put("timeSpentAvgMin", timeSpentAvgMin); json.put("timeSpentAvgMax", timeSpentAvgMax); json.put("startnode", startNode); json.put("endnodes", endNodes); return json; } private long findStartNodeFromFromStartingTimes(long instanceid) throws SQLException { PreparedStatement statement = db.getPreparedStatement("SELECT COUNT(uid), scnid " + "FROM (userprogress " + "LEFT JOIN " + "(SELECT uid AS newuid, MIN(time) AS mintime FROM userprogress GROUP BY uid) AS t1 " + "ON userprogress.uid = t1.newuid) " + "LEFT JOIN gamecontexts ON gamecontexts.id = userprogress.scnid " + "WHERE time = mintime AND gameinstid = ? " + "GROUP BY scnid " + "LIMIT 1"); statement.setLong(1, instanceid); ResultSet rs = statement.executeQuery(); long startId = -1; if(rs.next()) startId = rs.getLong("scnid"); return startId; } private JSONArray getRelations(long contextid, Set<Long> gotRelations) throws SQLException, JSONException { JSONArray array = new JSONArray(); PreparedStatement statement = db.getPreparedStatement("SELECT * FROM gamecontextrelations WHERE parentid = ?;"); statement.setLong(1, contextid); ResultSet rs = statement.executeQuery(); while(rs.next()) { long source = contextid; long dest = rs.getLong("childid"); long timesUsed = rs.getLong("timesused"); boolean autogenerated = rs.getBoolean("autogenerated"); array.put(new JSONObject().put("destination", dest).put("source", source).put("timesUsed", timesUsed) .put("autogenerated", autogenerated)); gotRelations.add(dest); } return array; } }