From 2d6b5c9005ce8819947f8109197899f86d268e4d Mon Sep 17 00:00:00 2001 From: Francois G Date: Sun, 19 Mar 2023 15:16:05 +0100 Subject: [PATCH 1/2] Fix leaderboard calculation and add a ranking to player in details and leaderboard --- .../peeratcode/model/Player.java | 17 +++++++++ .../repository/DatabaseRepository.java | 38 +++++++++---------- .../peeratcode/routes/Leaderboard.java | 3 +- .../peeratcode/routes/PlayerDetails.java | 3 +- 4 files changed, 39 insertions(+), 22 deletions(-) diff --git a/src/be/jeffcheasey88/peeratcode/model/Player.java b/src/be/jeffcheasey88/peeratcode/model/Player.java index a543ac2..9a5bb22 100644 --- a/src/be/jeffcheasey88/peeratcode/model/Player.java +++ b/src/be/jeffcheasey88/peeratcode/model/Player.java @@ -21,12 +21,17 @@ public class Player implements Comparable { private LinkedHashSet groups; private byte[] avatar; + private int rank; private int totalScore; private int totalCompletion; private int totalTries; private String badges; // To change to a set of model + public Player(String pseudo, String email, String firstname, String lastname, String description) { + this(pseudo, email, firstname, lastname, description, null, null); + } + public Player(String pseudo, String email, String firstname, String lastname, String description, String groups) { this(pseudo, email, firstname, lastname, description, groups, null); } @@ -103,10 +108,22 @@ public class Player implements Comparable { return this.avatar; } + public void setAvatar(byte[] newAvatar) { + avatar = newAvatar; + } + public String getPathToSourceCode() { return String.format(PATH_TO_CODE, pseudo); } + public int getRank() { + return rank; + } + + public void setRank(int newRank) { + rank = newRank; + } + public int getTotalScore() { return totalScore; } diff --git a/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java b/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java index 11b199d..56a7b62 100644 --- a/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java +++ b/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java @@ -33,21 +33,13 @@ public class DatabaseRepository { private static final String CHECK_PASSWORD = "SELECT id_player, passwd FROM players WHERE pseudo=?"; private static final String SCORE = "SELECT score FROM completions WHERE fk_player = ? AND fk_puzzle = ?"; private static final String GET_COMPLETION = "SELECT id_completion, tries, fileName, score FROM completions WHERE fk_puzzle = ? AND fk_player = ?"; - private static final String PART_GET_PLAYER_GROUP = " LEFT JOIN containsGroups cg ON p.id_player = cg.fk_player LEFT JOIN groups g ON cg.fk_group = g.id_group "; - private static final String GET_PLAYER = "SELECT p.*, GROUP_CONCAT(g.name ORDER BY g.fk_chapter, g.fk_puzzle) FROM players p WHERE "; - private static final String GET_PLAYER_BY_ID = GET_PLAYER + "id_player = ?" + PART_GET_PLAYER_GROUP; - private static final String GET_PLAYER_BY_PSEUDO = GET_PLAYER + "pseudo = ?" + PART_GET_PLAYER_GROUP;; - private static final String GET_PLAYER_DETAILS = "SELECT p.pseudo, p.email, p.firstname, p.lastname, p.description, p.avatar, GROUP_CONCAT(DISTINCT g.name ORDER BY g.fk_chapter, g.fk_puzzle) AS sgroup,\n" - + " SUM(c.score) AS playerScore, COUNT(c.id_completion) AS playerCompletions, SUM(c.tries) AS playerTries,\n" - + " GROUP_CONCAT(DISTINCT b.name ORDER BY b.name ASC) AS badges FROM players p\n" - + "LEFT JOIN completions c ON p.id_player = c.fk_player\n" - + "LEFT JOIN containsBadges cb ON p.id_player = cb.fk_player\n" - + "LEFT JOIN badges b ON cb.fk_badge = b.id_badge\n" + PART_GET_PLAYER_GROUP; + private static final String GET_PLAYER_SIMPLE = "SELECT pseudo, email, firstname, lastname, description FROM players WHERE id_player = ?"; + private static final String GET_PLAYER_DETAILS = "SELECT p.*, scores.score, scores.completions, scores.tries, scores.rank, GROUP_CONCAT(DISTINCT b.name ORDER BY b.name ASC) AS badges, GROUP_CONCAT(DISTINCT g.name ORDER BY g.fk_chapter, g.fk_puzzle) AS sgroup 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 containsBadges cb ON scores.fk_player = cb.fk_player LEFT JOIN badges b ON cb.fk_badge = b.id_badge 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 AND "; private static final String GET_PLAYER_DETAILS_BY_ID = GET_PLAYER_DETAILS - + " WHERE p.id_player = ? GROUP BY p.id_player;"; + + " p.id_player = ? GROUP BY p.id_player;"; private static final String GET_PLAYER_DETAILS_BY_PSEUDO = GET_PLAYER_DETAILS - + " WHERE p.pseudo = ? GROUP BY p.pseudo;"; - private static final String ALL_PLAYERS_FOR_LEADERBOARD = "SELECT p.*, GROUP_CONCAT(DISTINCT g.name ORDER BY g.fk_chapter, g.fk_puzzle) AS sgroup, sum(c.score) AS playerScore, count(c.id_completion) AS playerCompletions, sum(c.tries) AS playerTries FROM players p " + PART_GET_PLAYER_GROUP + "LEFT JOIN completions c ON c.fk_player = p.id_player GROUP BY p.id_player ORDER BY playerScore DESC"; + + "p.pseudo = ? GROUP BY p.pseudo;"; + private static final String ALL_PLAYERS_FOR_LEADERBOARD = "select DISTINCT p.*, scores.* 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 WHERE p.id_player = scores.fk_player"; private static final String GET_BADGE = "SELECT * FROM badges WHERE id_badge = ?"; private static final String INSERT_COMPLETION = "INSERT INTO completions (fk_puzzle, fk_player, tries, code, fileName, score) values (?, ?, ?, ?, ?, ?)"; private static final String UPDATE_COMPLETION = "UPDATE completions SET tries = ?, filename = ?, score = ? WHERE fk_puzzle = ? AND fk_player = ?"; @@ -86,12 +78,18 @@ public class DatabaseRepository { private Player makePlayer(ResultSet playerResult) throws SQLException { Player p = new Player(playerResult.getString("pseudo"), playerResult.getString("email"), playerResult.getString("firstName"), playerResult.getString("LastName"), - playerResult.getString("description"), playerResult.getString("sgroup"), - playerResult.getBytes("avatar")); - if (hasColumn(playerResult, "playerScore")) { - p.setTotalScore(playerResult.getInt("playerScore")); - p.setTotalCompletion(playerResult.getInt("playerCompletions")); - p.setTotalTries(playerResult.getInt("playerTries")); + playerResult.getString("description")); + if (hasColumn(playerResult, "avatar")) { + p.setAvatar(playerResult.getBytes("avatar")); + } + if (hasColumn(playerResult, "sgroup")) { + p.setGroups(playerResult.getString("sgroup")); + } + if (hasColumn(playerResult, "score")) { + p.setRank(playerResult.getInt("rank")); + p.setTotalScore(playerResult.getInt("score")); + p.setTotalCompletion(playerResult.getInt("completions")); + p.setTotalTries(playerResult.getInt("tries")); } if (hasColumn(playerResult, "badges")) { p.setBadges(playerResult.getString("badges")); @@ -181,7 +179,7 @@ public class DatabaseRepository { public Player getPlayer(int idPlayer) { try { - PreparedStatement completionsStmt = con.prepareStatement(GET_PLAYER); + PreparedStatement completionsStmt = con.prepareStatement(GET_PLAYER_SIMPLE); completionsStmt.setInt(1, idPlayer); ResultSet result = completionsStmt.executeQuery(); if (result.next()) { diff --git a/src/be/jeffcheasey88/peeratcode/routes/Leaderboard.java b/src/be/jeffcheasey88/peeratcode/routes/Leaderboard.java index 6f30ef1..83b0531 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/Leaderboard.java +++ b/src/be/jeffcheasey88/peeratcode/routes/Leaderboard.java @@ -35,7 +35,8 @@ public class Leaderboard implements Response { JSONObject playerJSON = new JSONObject(); playerJSON.put("pseudo", player.getPseudo()); if (player.getGroups() != null) playerJSON.put("groups", player.getJsonGroups()); - if(player.getAvatar() != null) playerJSON.put("avatar", Base64.getEncoder().encodeToString(player.getAvatar())); + //if(player.getAvatar() != null) playerJSON.put("avatar", Base64.getEncoder().encodeToString(player.getAvatar())); + playerJSON.put("rank", player.getRank()); playerJSON.put("score", player.getTotalScore()); playerJSON.put("completions", player.getTotalCompletion()); playerJSON.put("tries", player.getTotalTries()); diff --git a/src/be/jeffcheasey88/peeratcode/routes/PlayerDetails.java b/src/be/jeffcheasey88/peeratcode/routes/PlayerDetails.java index 153a746..7aa3c69 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/PlayerDetails.java +++ b/src/be/jeffcheasey88/peeratcode/routes/PlayerDetails.java @@ -40,11 +40,12 @@ public class PlayerDetails implements Response { playerJSON.put("lastname", player.getLastname()); playerJSON.put("description", player.getDescription()); if (player.getGroups() != null) playerJSON.put("groups", player.getJsonGroups()); + playerJSON.put("rank", player.getRank()); playerJSON.put("score", player.getTotalScore()); playerJSON.put("completions", player.getTotalCompletion()); playerJSON.put("tries", player.getTotalTries()); playerJSON.put("badges", player.getBadges()); - if(player.getAvatar() != null) playerJSON.put("avatar", Base64.getEncoder().encodeToString(player.getAvatar())); + //if(player.getAvatar() != null) playerJSON.put("avatar", Base64.getEncoder().encodeToString(player.getAvatar())); writer.write(playerJSON.toJSONString().replace("\\", "")); } else { HttpUtil.responseHeaders(writer, 400, "Access-Control-Allow-Origin: *"); From 71c7e4e02cbf83af06f0216ede52c586296c52b4 Mon Sep 17 00:00:00 2001 From: Francois G Date: Sun, 19 Mar 2023 20:19:36 +0100 Subject: [PATCH 2/2] Return all badge info in player details route --- .../jeffcheasey88/peeratcode/model/Badge.java | 10 +++-- .../peeratcode/model/Player.java | 41 ++++++++++++++--- .../repository/DatabaseRepository.java | 44 ++++++++++--------- .../peeratcode/routes/Leaderboard.java | 2 +- .../peeratcode/routes/PlayerDetails.java | 2 +- .../peeratcode/webserver/Client.java | 4 +- 6 files changed, 69 insertions(+), 34 deletions(-) diff --git a/src/be/jeffcheasey88/peeratcode/model/Badge.java b/src/be/jeffcheasey88/peeratcode/model/Badge.java index a79945b..55f6834 100644 --- a/src/be/jeffcheasey88/peeratcode/model/Badge.java +++ b/src/be/jeffcheasey88/peeratcode/model/Badge.java @@ -4,9 +4,12 @@ public class Badge { private String name; private byte[] logo; private int level; - + + public Badge(String name, int level) { + this(name, null, level); + } + public Badge(String name, byte[] logo, int level) { - super(); this.name = name; this.logo = logo; this.level = level; @@ -35,6 +38,5 @@ public class Badge { public void setLevel(int level) { this.level = level; } - - + } diff --git a/src/be/jeffcheasey88/peeratcode/model/Player.java b/src/be/jeffcheasey88/peeratcode/model/Player.java index 9a5bb22..e3da650 100644 --- a/src/be/jeffcheasey88/peeratcode/model/Player.java +++ b/src/be/jeffcheasey88/peeratcode/model/Player.java @@ -1,11 +1,14 @@ package be.jeffcheasey88.peeratcode.model; import java.util.Arrays; +import java.util.Base64; import java.util.HashSet; import java.util.LinkedHashSet; 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; @@ -26,7 +29,7 @@ public class Player implements Comparable { private int totalCompletion; private int totalTries; - private String badges; // To change to a set of model + private Set badges; public Player(String pseudo, String email, String firstname, String lastname, String description) { this(pseudo, email, firstname, lastname, description, null, null); @@ -41,7 +44,7 @@ public class Player implements Comparable { this(pseudo, email, firstname, lastname, description, groups, avatar, null); } public Player(String pseudo, String email, String firstname, String lastname, String description, String groups, - byte[] avatar, String badges) { + byte[] avatar, Set badges) { this.pseudo = pseudo; this.email = email; this.firstname = firstname; @@ -54,7 +57,10 @@ public class Player implements Comparable { totalCompletion = 0; totalTries = 0; - this.badges = null; + if (badges != null) + this.badges = new HashSet(badges); + else + this.badges = new HashSet(); } public String getPseudo() { @@ -99,7 +105,7 @@ public class Player implements Comparable { public void setGroups(String groups) { if (groups == null || groups.isEmpty()) - groups = null; + this.groups = null; else this.groups = new LinkedHashSet(Arrays.asList(groups.split(","))); } @@ -148,11 +154,28 @@ public class Player implements Comparable { this.totalTries = totalTries; } - public String getBadges() { + public Set getBadges() { return badges; } - public void setBadges(String initBadges) { - badges = initBadges; + + /** + * SEE SET_TAGS IN PUZZLE + * @return DEATH + */ + public JSONArray getJsonBadges() { + if (badges == null) + return null; + JSONArray badgesJSON = new JSONArray(); + for (Badge badge: badges) { + JSONObject badgeJSON = new JSONObject(); + badgeJSON.put("name", badge.getName()); + byte[] logo = badge.getLogo(); + if (logo != null) + badgeJSON.put("logo", Base64.getEncoder().encodeToString(logo)); + badgeJSON.put("level", badge.getLevel()); + badgesJSON.add(badgeJSON); + } + return badgesJSON; } @Override @@ -172,4 +195,8 @@ public class Player implements Comparable { return compare; } + + public void addBadge(Badge newBadge) { + badges.add(newBadge); + } } diff --git a/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java b/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java index 56a7b62..bad66b0 100644 --- a/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java +++ b/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java @@ -34,13 +34,14 @@ public class DatabaseRepository { private static final String SCORE = "SELECT score FROM completions WHERE fk_player = ? AND fk_puzzle = ?"; private static final String GET_COMPLETION = "SELECT id_completion, tries, fileName, score FROM completions WHERE fk_puzzle = ? AND fk_player = ?"; private static final String GET_PLAYER_SIMPLE = "SELECT pseudo, email, firstname, lastname, description FROM players WHERE id_player = ?"; - private static final String GET_PLAYER_DETAILS = "SELECT p.*, scores.score, scores.completions, scores.tries, scores.rank, GROUP_CONCAT(DISTINCT b.name ORDER BY b.name ASC) AS badges, GROUP_CONCAT(DISTINCT g.name ORDER BY g.fk_chapter, g.fk_puzzle) AS sgroup 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 containsBadges cb ON scores.fk_player = cb.fk_player LEFT JOIN badges b ON cb.fk_badge = b.id_badge 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 AND "; + private static final String GET_PLAYER_DETAILS = "SELECT p.*, scores.score, scores.completions, scores.tries, scores.rank, GROUP_CONCAT(DISTINCT g.name ORDER BY g.fk_chapter, g.fk_puzzle) AS sgroup 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 AND "; private static final String GET_PLAYER_DETAILS_BY_ID = GET_PLAYER_DETAILS + " p.id_player = ? GROUP BY p.id_player;"; private static final String GET_PLAYER_DETAILS_BY_PSEUDO = GET_PLAYER_DETAILS + "p.pseudo = ? GROUP BY p.pseudo;"; private static final String ALL_PLAYERS_FOR_LEADERBOARD = "select DISTINCT p.*, scores.* 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 WHERE p.id_player = scores.fk_player"; private static final String GET_BADGE = "SELECT * FROM badges WHERE id_badge = ?"; + private static final String GET_BADGES_OF_PLAYER = "SELECT * FROM badges b LEFT JOIN containsBadges cb ON cb.fk_badge = b.id_badge WHERE cb.fk_player = ?"; private static final String INSERT_COMPLETION = "INSERT INTO completions (fk_puzzle, fk_player, tries, code, fileName, score) values (?, ?, ?, ?, ?, ?)"; private static final String UPDATE_COMPLETION = "UPDATE completions SET tries = ?, filename = ?, score = ? WHERE fk_puzzle = ? AND fk_player = ?"; @@ -77,7 +78,7 @@ public class DatabaseRepository { private Player makePlayer(ResultSet playerResult) throws SQLException { Player p = new Player(playerResult.getString("pseudo"), playerResult.getString("email"), - playerResult.getString("firstName"), playerResult.getString("LastName"), + playerResult.getString("firstName"), playerResult.getString("lastName"), playerResult.getString("description")); if (hasColumn(playerResult, "avatar")) { p.setAvatar(playerResult.getBytes("avatar")); @@ -91,9 +92,6 @@ public class DatabaseRepository { p.setTotalCompletion(playerResult.getInt("completions")); p.setTotalTries(playerResult.getInt("tries")); } - if (hasColumn(playerResult, "badges")) { - p.setBadges(playerResult.getString("badges")); - } return p; } @@ -192,28 +190,34 @@ public class DatabaseRepository { } public Player getPlayerDetails(int idPlayer) { - try { - ensureConnection(); - PreparedStatement completionsStmt = con.prepareStatement(GET_PLAYER_DETAILS_BY_ID); - completionsStmt.setInt(1, idPlayer); - ResultSet result = completionsStmt.executeQuery(); - if (result.next()) { - return makePlayer(result); - } - } catch (SQLException e) { - e.printStackTrace(); - } - return null; + return getPlayerDetails(idPlayer, null); } public Player getPlayerDetails(String pseudoPlayer) { + return getPlayerDetails(-1, pseudoPlayer); + } + + private Player getPlayerDetails(int id, String pseudo) { try { ensureConnection(); - PreparedStatement completionsStmt = con.prepareStatement(GET_PLAYER_DETAILS_BY_PSEUDO); - completionsStmt.setString(1, pseudoPlayer); + PreparedStatement completionsStmt; + if (pseudo != null) { + completionsStmt = con.prepareStatement(GET_PLAYER_DETAILS_BY_PSEUDO); + completionsStmt.setString(1, pseudo); + } else { + completionsStmt = con.prepareStatement(GET_PLAYER_DETAILS_BY_ID); + completionsStmt.setInt(1, id); + } ResultSet result = completionsStmt.executeQuery(); if (result.next()) { - return makePlayer(result); + Player player = makePlayer(result); + completionsStmt = con.prepareStatement(GET_BADGES_OF_PLAYER); + completionsStmt.setInt(1, result.getInt("id_player")); + ResultSet resultBadges = completionsStmt.executeQuery(); + while (resultBadges.next()) { + player.addBadge(makeBadge(resultBadges)); + } + return player; } } catch (SQLException e) { e.printStackTrace(); diff --git a/src/be/jeffcheasey88/peeratcode/routes/Leaderboard.java b/src/be/jeffcheasey88/peeratcode/routes/Leaderboard.java index 83b0531..0230787 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/Leaderboard.java +++ b/src/be/jeffcheasey88/peeratcode/routes/Leaderboard.java @@ -35,7 +35,7 @@ public class Leaderboard implements Response { JSONObject playerJSON = new JSONObject(); playerJSON.put("pseudo", player.getPseudo()); if (player.getGroups() != null) playerJSON.put("groups", player.getJsonGroups()); - //if(player.getAvatar() != null) playerJSON.put("avatar", Base64.getEncoder().encodeToString(player.getAvatar())); + if(player.getAvatar() != null) playerJSON.put("avatar", Base64.getEncoder().encodeToString(player.getAvatar())); playerJSON.put("rank", player.getRank()); playerJSON.put("score", player.getTotalScore()); playerJSON.put("completions", player.getTotalCompletion()); diff --git a/src/be/jeffcheasey88/peeratcode/routes/PlayerDetails.java b/src/be/jeffcheasey88/peeratcode/routes/PlayerDetails.java index 7aa3c69..0f2fdb4 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/PlayerDetails.java +++ b/src/be/jeffcheasey88/peeratcode/routes/PlayerDetails.java @@ -44,7 +44,7 @@ public class PlayerDetails implements Response { playerJSON.put("score", player.getTotalScore()); playerJSON.put("completions", player.getTotalCompletion()); playerJSON.put("tries", player.getTotalTries()); - playerJSON.put("badges", player.getBadges()); + if (player.getBadges().size() > 0) playerJSON.put("badges", player.getJsonBadges()); //if(player.getAvatar() != null) playerJSON.put("avatar", Base64.getEncoder().encodeToString(player.getAvatar())); writer.write(playerJSON.toJSONString().replace("\\", "")); } else { diff --git a/src/be/jeffcheasey88/peeratcode/webserver/Client.java b/src/be/jeffcheasey88/peeratcode/webserver/Client.java index ec4f321..692fa58 100644 --- a/src/be/jeffcheasey88/peeratcode/webserver/Client.java +++ b/src/be/jeffcheasey88/peeratcode/webserver/Client.java @@ -34,7 +34,9 @@ public class Client extends Thread{ router.exec(headers[0], headers[1], isLogin(reader), reader, writer); writer.flush(); writer.close(); - } catch (Exception e){} + } catch (Exception e){ + e.printStackTrace(); + } } private User isLogin(HttpReader reader) throws Exception{