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;
|
package be.jeffcheasey88.peeratcode.model;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import org.json.simple.JSONArray;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
public class Group {
|
public class Group implements Comparable<Group> {
|
||||||
private String name;
|
private String name;
|
||||||
private int linkToChapter;
|
private int linkToChapter;
|
||||||
private int linkToPuzzle;
|
private int linkToPuzzle;
|
||||||
|
private List<Player> players;
|
||||||
|
private Timestamp endDate;
|
||||||
|
|
||||||
public Group(JSONObject json){
|
public Group(JSONObject json){
|
||||||
this.name = (String)json.get("name");
|
this.name = (String)json.get("name");
|
||||||
|
@ -14,11 +20,55 @@ public class Group {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Group(String name, int initChap, int initPuzz) {
|
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.name = name;
|
||||||
this.linkToChapter = initChap;
|
this.linkToChapter = initChap;
|
||||||
this.linkToPuzzle = initPuzz;
|
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() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
@ -44,10 +94,61 @@ public class Group {
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject toJson() {
|
public JSONObject toJson() {
|
||||||
|
return this.toJson(null);
|
||||||
|
}
|
||||||
|
public JSONObject toJson(Integer rank) {
|
||||||
JSONObject groupJSON = new JSONObject();
|
JSONObject groupJSON = new JSONObject();
|
||||||
groupJSON.put("name", name);
|
groupJSON.put("name", name);
|
||||||
if (linkToChapter > 0) groupJSON.put("chapter", linkToChapter);
|
if (rank != null) groupJSON.put("rank", rank);
|
||||||
if (linkToPuzzle > 0) groupJSON.put("puzzle", linkToPuzzle);
|
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;
|
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;
|
package be.jeffcheasey88.peeratcode.model;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
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.JSONArray;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
@ -43,6 +36,18 @@ public class Player implements Comparable<Player> {
|
||||||
totalTries = 0;
|
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() {
|
public String getPseudo() {
|
||||||
return this.pseudo;
|
return this.pseudo;
|
||||||
}
|
}
|
||||||
|
@ -115,6 +120,12 @@ public class Player implements Comparable<Player> {
|
||||||
this.totalScore = totalScore;
|
this.totalScore = totalScore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addScore(int addScore, int tries) {
|
||||||
|
totalScore = totalScore + addScore;
|
||||||
|
totalTries = totalTries + tries;
|
||||||
|
totalCompletion++;
|
||||||
|
}
|
||||||
|
|
||||||
public int getTotalCompletion() {
|
public int getTotalCompletion() {
|
||||||
return totalCompletion;
|
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"),
|
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_CHAPTERS_QUERY("SELECT * FROM chapters WHERE id_chapter > 0"),
|
||||||
ALL_GROUPS("SELCT * FROM groups"),
|
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_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_PSEUDO_AVAILABLE_QUERY("SELECT * FROM players WHERE pseudo = ?"),
|
||||||
CHECK_EMAIL_AVAILABLE_QUERY("SELECT * FROM players WHERE email = ?"),
|
CHECK_EMAIL_AVAILABLE_QUERY("SELECT * FROM players WHERE email = ?"),
|
||||||
REGISTER_QUERY("INSERT INTO players (pseudo, email, passwd, firstname, lastname, description, avatar) VALUES (?, ?, ?, ?, ?, ?, ?)"),
|
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 {
|
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 {
|
private Badge makeBadge(ResultSet rs) throws SQLException {
|
||||||
|
@ -91,8 +97,9 @@ public class DatabaseRepository {
|
||||||
// Found on StackOverflow
|
// Found on StackOverflow
|
||||||
ResultSetMetaData rsmd = rs.getMetaData();
|
ResultSetMetaData rsmd = rs.getMetaData();
|
||||||
int columns = rsmd.getColumnCount();
|
int columns = rsmd.getColumnCount();
|
||||||
for(int x = 1; x <= columns; x++){
|
for (int x = 1; x <= columns; x++) {
|
||||||
if(columnName.equals(rsmd.getColumnName(x))) return true;
|
if (columnName.equals(rsmd.getColumnName(x)))
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -238,6 +245,33 @@ public class DatabaseRepository {
|
||||||
return null;
|
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) {
|
public Badge getBadge(int badgeId) {
|
||||||
try {
|
try {
|
||||||
ensureConnection();
|
ensureConnection();
|
||||||
|
@ -380,7 +414,8 @@ public class DatabaseRepository {
|
||||||
ResultSet inserted = playerStatement.getGeneratedKeys();
|
ResultSet inserted = playerStatement.getGeneratedKeys();
|
||||||
if (inserted.next()) {
|
if (inserted.next()) {
|
||||||
int newPlayerId = inserted.getInt(1);
|
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.setInt(1, newPlayerId);
|
||||||
containsGroupsStatement.setString(2, sgroup);
|
containsGroupsStatement.setString(2, sgroup);
|
||||||
containsGroupsStatement.executeUpdate();
|
containsGroupsStatement.executeUpdate();
|
||||||
|
@ -390,10 +425,9 @@ public class DatabaseRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} catch (SQLException e) {
|
||||||
catch (SQLException e) {
|
con.rollback();
|
||||||
con.rollback();
|
con.setAutoCommit(true);
|
||||||
con.setAutoCommit(true);
|
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -453,8 +487,8 @@ public class DatabaseRepository {
|
||||||
statement.setInt(6, newCompletion.getScore());
|
statement.setInt(6, newCompletion.getScore());
|
||||||
statement.executeUpdate();
|
statement.executeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean insertGroup(Group group){
|
public boolean insertGroup(Group group) {
|
||||||
try {
|
try {
|
||||||
ensureConnection();
|
ensureConnection();
|
||||||
PreparedStatement statement = DatabaseQuery.INSERT_GROUP.prepare(this.con);
|
PreparedStatement statement = DatabaseQuery.INSERT_GROUP.prepare(this.con);
|
||||||
|
@ -462,7 +496,8 @@ public class DatabaseRepository {
|
||||||
statement.setInt(2, group.getLinkToChapter());
|
statement.setInt(2, group.getLinkToChapter());
|
||||||
statement.setInt(3, group.getLinkToPuzzle());
|
statement.setInt(3, group.getLinkToPuzzle());
|
||||||
return statement.executeUpdate() >= 0;
|
return statement.executeUpdate() >= 0;
|
||||||
}catch(Exception e){}
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package be.jeffcheasey88.peeratcode.routes;
|
package be.jeffcheasey88.peeratcode.routes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
@ -7,6 +8,7 @@ import java.util.regex.Matcher;
|
||||||
import org.json.simple.JSONArray;
|
import org.json.simple.JSONArray;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
import be.jeffcheasey88.peeratcode.model.Group;
|
||||||
import be.jeffcheasey88.peeratcode.model.Player;
|
import be.jeffcheasey88.peeratcode.model.Player;
|
||||||
import be.jeffcheasey88.peeratcode.repository.DatabaseRepository;
|
import be.jeffcheasey88.peeratcode.repository.DatabaseRepository;
|
||||||
import be.jeffcheasey88.peeratcode.webserver.HttpReader;
|
import be.jeffcheasey88.peeratcode.webserver.HttpReader;
|
||||||
|
@ -24,10 +26,41 @@ public class Leaderboard implements Response {
|
||||||
this.databaseRepo = databaseRepo;
|
this.databaseRepo = databaseRepo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Route(path = "^\\/leaderboard$")
|
@Route(path = "^\\/leaderboard\\/?(\\d+)?$")
|
||||||
@Override
|
@Override
|
||||||
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception {
|
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception {
|
||||||
HttpUtil.responseHeaders(writer, 200, "Access-Control-Allow-Origin: *");
|
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();
|
SortedSet<Player> allPlayers = databaseRepo.getAllPlayerForLeaderboard();
|
||||||
JSONArray playersJSON = new JSONArray();
|
JSONArray playersJSON = new JSONArray();
|
||||||
if (allPlayers != null) {
|
if (allPlayers != null) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue