Add route for groups leaderboard
This commit is contained in:
parent
e5794f382d
commit
14905a489a
5 changed files with 206 additions and 23 deletions
|
@ -1,11 +1,17 @@
|
|||
package be.jeffcheasey88.peeratcode.model;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.*;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class Group {
|
||||
public class Group implements Comparable<Group> {
|
||||
private String name;
|
||||
private int linkToChapter;
|
||||
private int linkToPuzzle;
|
||||
private List<Player> players;
|
||||
private Timestamp endDate;
|
||||
|
||||
public Group(JSONObject json){
|
||||
this.name = (String)json.get("name");
|
||||
|
@ -14,11 +20,55 @@ public class Group {
|
|||
}
|
||||
|
||||
public Group(String name, int initChap, int initPuzz) {
|
||||
this(name, initChap, initPuzz, null);
|
||||
}
|
||||
public Group(String name, int initChap, int initPuzz, Timestamp initEnd) {
|
||||
this.name = name;
|
||||
this.linkToChapter = initChap;
|
||||
this.linkToPuzzle = initPuzz;
|
||||
this.endDate = initEnd;
|
||||
}
|
||||
|
||||
|
||||
public void addPlayer(Player newPlayer) {
|
||||
if (newPlayer != null) {
|
||||
if (players == null)
|
||||
players = new ArrayList<Player>();
|
||||
|
||||
int pPosition = players.indexOf(newPlayer);
|
||||
if (pPosition < 0) {
|
||||
players.add(newPlayer);
|
||||
}
|
||||
else {
|
||||
players.get(pPosition).addScore(newPlayer.getTotalScore(), newPlayer.getTotalTries());
|
||||
}
|
||||
}
|
||||
}
|
||||
public SortedSet<Player> getPlayers() {
|
||||
return new TreeSet<Player>(players);
|
||||
}
|
||||
|
||||
public int getScore() {
|
||||
int score = 0;
|
||||
|
||||
if (players != null) {
|
||||
for (Player p: players) {
|
||||
score = score + p.getTotalScore();
|
||||
}
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
public int getTries() {
|
||||
int tries = 0;
|
||||
|
||||
if (players != null) {
|
||||
for (Player p: players) {
|
||||
tries = tries + p.getTotalTries();
|
||||
}
|
||||
}
|
||||
return tries;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
@ -44,10 +94,61 @@ public class Group {
|
|||
}
|
||||
|
||||
public JSONObject toJson() {
|
||||
return this.toJson(null);
|
||||
}
|
||||
public JSONObject toJson(Integer rank) {
|
||||
JSONObject groupJSON = new JSONObject();
|
||||
groupJSON.put("name", name);
|
||||
if (linkToChapter > 0) groupJSON.put("chapter", linkToChapter);
|
||||
if (linkToPuzzle > 0) groupJSON.put("puzzle", linkToPuzzle);
|
||||
if (rank != null) groupJSON.put("rank", rank);
|
||||
else if (linkToChapter > 0) groupJSON.put("chapter", linkToChapter);
|
||||
else if (linkToPuzzle > 0) groupJSON.put("puzzle", linkToPuzzle);
|
||||
if (endDate != null) groupJSON.put("end_date", endDate.toString());
|
||||
if (players != null) {
|
||||
JSONArray groupsPlayerJSON = new JSONArray();
|
||||
for (Player p:players) {
|
||||
JSONObject playerJSON = new JSONObject();
|
||||
playerJSON.put("pseudo", p.getPseudo());
|
||||
playerJSON.put("score", p.getTotalScore());
|
||||
playerJSON.put("completion", p.getTotalCompletion());
|
||||
playerJSON.put("tries", p.getTotalTries());
|
||||
groupsPlayerJSON.add(playerJSON);
|
||||
}
|
||||
groupJSON.put("players", groupsPlayerJSON);
|
||||
}
|
||||
return groupJSON;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Group arg0) {
|
||||
int comparo = arg0.getScore() - getScore();
|
||||
if (comparo == 0) {
|
||||
comparo = players.size() - arg0.players.size();
|
||||
if (comparo == 0) {
|
||||
comparo = getTries() - arg0.getTries();
|
||||
if (comparo == 0) {
|
||||
comparo = name.compareTo(arg0.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return comparo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Group other = (Group) obj;
|
||||
return Objects.equals(name, other.name);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,16 +1,9 @@
|
|||
package be.jeffcheasey88.peeratcode.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
@ -43,6 +36,18 @@ public class Player implements Comparable<Player> {
|
|||
totalTries = 0;
|
||||
}
|
||||
|
||||
public Player(String pseudo, int score, int tries) {
|
||||
// For groups leaderboard
|
||||
this.pseudo = pseudo;
|
||||
totalScore = score;
|
||||
totalTries = tries;
|
||||
if (totalTries > 0)
|
||||
totalCompletion = totalTries;
|
||||
else
|
||||
totalCompletion = 0;
|
||||
email = ""; // TO make compareTo and equals works as usual
|
||||
}
|
||||
|
||||
public String getPseudo() {
|
||||
return this.pseudo;
|
||||
}
|
||||
|
@ -115,6 +120,12 @@ public class Player implements Comparable<Player> {
|
|||
this.totalScore = totalScore;
|
||||
}
|
||||
|
||||
public void addScore(int addScore, int tries) {
|
||||
totalScore = totalScore + addScore;
|
||||
totalTries = totalTries + tries;
|
||||
totalCompletion++;
|
||||
}
|
||||
|
||||
public int getTotalCompletion() {
|
||||
return totalCompletion;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,10 @@ public enum DatabaseQuery {
|
|||
PUZZLES_IN_CHAPTER_QUERY("SELECT p.*, GROUP_CONCAT(t.name) AS tags FROM puzzles p LEFT JOIN containsTags ct ON ct.fk_puzzle = p.id_puzzle LEFT JOIN tags t ON t.id_tag = ct.fk_tag WHERE fk_chapter = ? GROUP BY p.id_puzzle"),
|
||||
ALL_CHAPTERS_QUERY("SELECT * FROM chapters WHERE id_chapter > 0"),
|
||||
ALL_GROUPS("SELCT * FROM groups"),
|
||||
|
||||
ALL_PLAYERS_FOR_LEADERBOARD("select p.*, scores.*, g.* from players p ,(SELECT fk_player, SUM(c.score) AS score, COUNT(c.id_completion) AS completions, SUM(c.tries) AS tries, rank() over(ORDER BY score DESC) AS rank FROM completions c GROUP BY c.fk_player) AS scores LEFT JOIN containsGroups cg ON scores.fk_player = cg.fk_player LEFT JOIN groups g ON cg.fk_group = g.id_group WHERE p.id_player = scores.fk_player ORDER BY g.fk_chapter, g.fk_puzzle"),
|
||||
ALL_GROUP_FOR_CHAPTER_LEADERBOARD("SELECT g.*, pl.pseudo, co.score, co.tries, ch.end_date FROM groups g LEFT JOIN containsGroups cg ON g.id_group = cg.fk_group LEFT JOIN players pl ON cg.fk_player = pl.id_player LEFT JOIN completions co ON pl.id_player = co.fk_player LEFT JOIN chapters ch ON g.fk_chapter = ch.id_chapter WHERE fk_chapter = ? AND (co.fk_puzzle IN (SELECT id_puzzle FROM puzzles puz WHERE puz.fk_chapter = g.fk_chapter) OR co.score IS NULL);"),
|
||||
|
||||
CHECK_PSEUDO_AVAILABLE_QUERY("SELECT * FROM players WHERE pseudo = ?"),
|
||||
CHECK_EMAIL_AVAILABLE_QUERY("SELECT * FROM players WHERE email = ?"),
|
||||
REGISTER_QUERY("INSERT INTO players (pseudo, email, passwd, firstname, lastname, description, avatar) VALUES (?, ?, ?, ?, ?, ?, ?)"),
|
||||
|
|
|
@ -80,7 +80,13 @@ public class DatabaseRepository {
|
|||
}
|
||||
|
||||
private Group makeGroup(ResultSet result) throws SQLException {
|
||||
return new Group(result.getString("name"), result.getInt("fk_chapter"), result.getInt("fk_puzzle"));
|
||||
if (hasColumn(result, "end_date"))
|
||||
return new Group(result.getString("name"), result.getInt("fk_chapter"), result.getInt("fk_puzzle"), result.getTimestamp("end_date"));
|
||||
else
|
||||
return new Group(result.getString("name"), result.getInt("fk_chapter"), result.getInt("fk_puzzle"));
|
||||
}
|
||||
private Player makeGroupPlayer(ResultSet result) throws SQLException {
|
||||
return new Player(result.getString("pseudo"), result.getInt("score"), result.getInt("tries"));
|
||||
}
|
||||
|
||||
private Badge makeBadge(ResultSet rs) throws SQLException {
|
||||
|
@ -91,8 +97,9 @@ public class DatabaseRepository {
|
|||
// Found on StackOverflow
|
||||
ResultSetMetaData rsmd = rs.getMetaData();
|
||||
int columns = rsmd.getColumnCount();
|
||||
for(int x = 1; x <= columns; x++){
|
||||
if(columnName.equals(rsmd.getColumnName(x))) return true;
|
||||
for (int x = 1; x <= columns; x++) {
|
||||
if (columnName.equals(rsmd.getColumnName(x)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -238,6 +245,33 @@ public class DatabaseRepository {
|
|||
return null;
|
||||
}
|
||||
|
||||
public SortedSet<Group> getAllGroupForChapterLeaderboard(int chapterId) {
|
||||
try {
|
||||
ensureConnection();
|
||||
PreparedStatement groupsStmt = DatabaseQuery.ALL_GROUP_FOR_CHAPTER_LEADERBOARD.prepare(this.con);
|
||||
groupsStmt.setInt(1, chapterId);
|
||||
ResultSet result = groupsStmt.executeQuery();
|
||||
List<Group> groups = new ArrayList<Group>();
|
||||
Group tmpGroup;
|
||||
while (result.next()) {
|
||||
tmpGroup = makeGroup(result);
|
||||
if (tmpGroup != null) {
|
||||
int gPosition = groups.indexOf(tmpGroup);
|
||||
if (gPosition < 0) {
|
||||
tmpGroup.addPlayer(makeGroupPlayer(result));
|
||||
groups.add(tmpGroup);
|
||||
} else {
|
||||
groups.get(gPosition).addPlayer(makeGroupPlayer(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
return new TreeSet<Group>(groups);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Badge getBadge(int badgeId) {
|
||||
try {
|
||||
ensureConnection();
|
||||
|
@ -380,7 +414,8 @@ public class DatabaseRepository {
|
|||
ResultSet inserted = playerStatement.getGeneratedKeys();
|
||||
if (inserted.next()) {
|
||||
int newPlayerId = inserted.getInt(1);
|
||||
try (PreparedStatement containsGroupsStatement = con.prepareStatement(DatabaseQuery.REGISTER_PLAYER_IN_EXISTING_GROUP.toString())) {
|
||||
try (PreparedStatement containsGroupsStatement = con
|
||||
.prepareStatement(DatabaseQuery.REGISTER_PLAYER_IN_EXISTING_GROUP.toString())) {
|
||||
containsGroupsStatement.setInt(1, newPlayerId);
|
||||
containsGroupsStatement.setString(2, sgroup);
|
||||
containsGroupsStatement.executeUpdate();
|
||||
|
@ -390,10 +425,9 @@ public class DatabaseRepository {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SQLException e) {
|
||||
con.rollback();
|
||||
con.setAutoCommit(true);
|
||||
} catch (SQLException e) {
|
||||
con.rollback();
|
||||
con.setAutoCommit(true);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
|
@ -453,8 +487,8 @@ public class DatabaseRepository {
|
|||
statement.setInt(6, newCompletion.getScore());
|
||||
statement.executeUpdate();
|
||||
}
|
||||
|
||||
public boolean insertGroup(Group group){
|
||||
|
||||
public boolean insertGroup(Group group) {
|
||||
try {
|
||||
ensureConnection();
|
||||
PreparedStatement statement = DatabaseQuery.INSERT_GROUP.prepare(this.con);
|
||||
|
@ -462,7 +496,8 @@ public class DatabaseRepository {
|
|||
statement.setInt(2, group.getLinkToChapter());
|
||||
statement.setInt(3, group.getLinkToPuzzle());
|
||||
return statement.executeUpdate() >= 0;
|
||||
}catch(Exception e){}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package be.jeffcheasey88.peeratcode.routes;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Base64;
|
||||
import java.util.SortedSet;
|
||||
import java.util.regex.Matcher;
|
||||
|
@ -7,6 +8,7 @@ import java.util.regex.Matcher;
|
|||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import be.jeffcheasey88.peeratcode.model.Group;
|
||||
import be.jeffcheasey88.peeratcode.model.Player;
|
||||
import be.jeffcheasey88.peeratcode.repository.DatabaseRepository;
|
||||
import be.jeffcheasey88.peeratcode.webserver.HttpReader;
|
||||
|
@ -24,10 +26,41 @@ public class Leaderboard implements Response {
|
|||
this.databaseRepo = databaseRepo;
|
||||
}
|
||||
|
||||
@Route(path = "^\\/leaderboard$")
|
||||
@Route(path = "^\\/leaderboard\\/?(\\d+)?$")
|
||||
@Override
|
||||
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception {
|
||||
HttpUtil.responseHeaders(writer, 200, "Access-Control-Allow-Origin: *");
|
||||
if (matcher.group(1) != null){
|
||||
groupsLeaderboard(Integer.parseInt(matcher.group(1)), writer);
|
||||
} else {
|
||||
playersLeaderboard(writer);
|
||||
}
|
||||
}
|
||||
|
||||
private void groupsLeaderboard(int chapterId, HttpWriter writer) throws IOException {
|
||||
SortedSet<Group> allGroupsForChapter = databaseRepo.getAllGroupForChapterLeaderboard(chapterId);
|
||||
JSONArray groupsJSON = new JSONArray();
|
||||
if (allGroupsForChapter != null) {
|
||||
int rank = 1;
|
||||
int sameRankCount = 1;
|
||||
Group previousGroup = null;
|
||||
for (Group g: allGroupsForChapter) {
|
||||
if (previousGroup != null) {
|
||||
if (g.compareTo(previousGroup) == 0) {
|
||||
sameRankCount++;
|
||||
} else {
|
||||
rank = rank + sameRankCount;
|
||||
sameRankCount = 1;
|
||||
}
|
||||
}
|
||||
groupsJSON.add(g.toJson(rank));
|
||||
previousGroup = g;
|
||||
}
|
||||
}
|
||||
writer.write(groupsJSON.toJSONString().replace("\\", ""));
|
||||
}
|
||||
|
||||
private void playersLeaderboard(HttpWriter writer) throws IOException {
|
||||
SortedSet<Player> allPlayers = databaseRepo.getAllPlayerForLeaderboard();
|
||||
JSONArray playersJSON = new JSONArray();
|
||||
if (allPlayers != null) {
|
||||
|
|
Loading…
Add table
Reference in a new issue