package service.rest;
import gamification.Player;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import persistency.entities.Comment;
import persistency.entities.LoggedUser;
import persistency.entities.Session;
import persistency.entities.gamification.PointsCategory;
import persistency.exposed.LoggedUserExposed;
import persistency.exposed.PointsCategoryExposed;
import persistency.exposed.SessionExposedBasic;
import service.rest.wrappers.CommentBasic;
import com.google.gson.Gson;
@Path("stats")
@Produces({ MediaType.APPLICATION_JSON })
public class StatsResource {
private static final int MIN_RATES = 9;
@GET
@Path("game")
public Response getGamificationStats(@Context HttpServletRequest request){
LoggedUserExposed lue = new LoggedUserExposed();
Data d = new Data();
List<LoggedUser> allPersons = lue.getAllPersons();
d.allPlayers = allPersons.size();
List<Comment> allComments = new ArrayList<Comment>();
PointsCategoryExposed pce = new PointsCategoryExposed();
PointsCategory category = pce.findCategoryByShortName("share");
d.allShares = category.getInstancesOfThisType().size();
for (LoggedUser loggedUser : allPersons) {
Player player = loggedUser.getPlayer();
d.totalScore += player.getPoints();
d.totalLikes += loggedUser.getLikedComments().size();
d.totalComments += loggedUser.getComments().size();
allComments.addAll(loggedUser.getComments());
d.totalRates += loggedUser.getSessionRatings().size()+loggedUser.getSpeakerRatings().size();
}
Collections.sort(allComments);
int howManyTopComments = 3;
for (Comment comment : allComments) {
if (howManyTopComments <= 0){
break;
}
d.topComments.add(new CommentBasic(comment, false));
howManyTopComments--;
}
return Response.ok().entity((new Gson()).toJson(d)).build();
}
public class Data {
private int allPlayers;
private int allShares;
private int totalScore;
private int totalLikes;
private int totalComments;
private int totalRates;
private List<CommentBasic> topComments = new ArrayList<CommentBasic>();
}
@GET
@Path("session")
public Response getSessionRanking( @QueryParam("min_votes") int min_votes, @QueryParam("max_votes") int max_votes){
if(min_votes == 0){
min_votes = MIN_RATES;
}
if(max_votes == 0){
max_votes = -1;
}
LoggedUserExposed lue = new LoggedUserExposed();
List<LoggedUser> allPersons = lue.getAllPersons();
List<RatedObject> result = new ArrayList<StatsResource.RatedObject>();
SessionExposedBasic seb = new SessionExposedBasic();
for (LoggedUser loggedUser : allPersons) {
Map<Integer, Integer> sessionRatings = loggedUser.getSessionRatings();
processRatings(result, seb, sessionRatings);
}
result = clearLowRatingSessions(result, min_votes, max_votes);
return Response.ok().entity((new Gson()).toJson(result)).build();
}
private void processRatings(List<RatedObject> result, SessionExposedBasic seb,
Map<Integer, Integer> sessionRatings) {
Set<Integer> keySet = sessionRatings.keySet();
for (Integer integer : keySet) {
RatedObject rated = new RatedObject();
rated.id = integer;
int indexOf = result.indexOf(rated);
if(indexOf != -1){
result.get(indexOf).totalRating+= sessionRatings.get(integer);
result.get(indexOf).timesRated++;
} else {
Session findSessionById = seb.findSessionById(integer+"");
rated.name = findSessionById.getName();
findSessionById.getSpeakers().size();
rated.speakers = findSessionById.getSpeakers().toString();
rated.totalRating = sessionRatings.get(integer);
result.add(rated);
}
}
}
private List<RatedObject> clearLowRatingSessions(List<RatedObject> preResult, int min_votes, int max_votes) {
List<RatedObject> forRemove = new ArrayList<StatsResource.RatedObject>();
for (RatedObject ratedObject : preResult) {
if(ratedObject.timesRated < min_votes || (max_votes > -1 && ratedObject.timesRated > max_votes)){
forRemove.add(ratedObject);
} else {
ratedObject.computeRating();
}
}
for (RatedObject ratedObject : forRemove) {
preResult.remove(ratedObject);
}
Collections.sort(preResult);
List<RatedObject> result = new ArrayList<StatsResource.RatedObject>(5);
int pos = 0;
double lastRating = 6;
for (RatedObject ratedObject : preResult) {
if(lastRating > ratedObject.rating){
lastRating = ratedObject.rating;
pos++;
}
ratedObject.pos = pos;
result.add(ratedObject);
}
return result;
}
private class RatedObject implements Comparable<RatedObject>{
private int id;
private String name;
private String speakers;
private double rating = 0;
private double totalRating = 0;
private int timesRated = 1;
private int pos = 1;
@Override
public boolean equals(Object obj) {
if(RatedObject.class.isInstance(obj)){
return ((RatedObject) obj).id == id;
}
return super.equals(obj);
}
public void computeRating() {
double d = (double)totalRating/timesRated;
d = Math.round(d*100)/100.0d;
rating = d;
}
@Override
public int compareTo(RatedObject o) {
double diff = o.rating - rating;
if(diff>0){
return 1;
} else if(diff <0){
return -1;
}
return 0;
}
}
@GET
@Path("speaker")
public Response getSpeakerRanking(@QueryParam("min_votes") int min_votes, @QueryParam("max_votes") int max_votes){
if(min_votes == 0){
min_votes = MIN_RATES;
}
if(max_votes == 0){
max_votes = -1;
}
LoggedUserExposed lue = new LoggedUserExposed();
List<LoggedUser> allPersons = lue.getAllPersons();
List<RatedObject> result = new ArrayList<StatsResource.RatedObject>();
SessionExposedBasic seb = new SessionExposedBasic();
for (LoggedUser loggedUser : allPersons) {
Map<Integer, Integer> sessionRatings = loggedUser.getSpeakerRatings();
processRatings(result, seb, sessionRatings);
}
result = clearLowRatingSessions(result, min_votes, max_votes);
return Response.ok().entity((new Gson()).toJson(result)).build();
}
}