From b5db4328f224b936a1bb16d725381b08d77bb7cf Mon Sep 17 00:00:00 2001 From: Francois G Date: Sat, 25 Feb 2023 21:19:58 +0100 Subject: [PATCH] Add leaderboard route --- src/be/jeffcheasey88/peeratcode/Main.java | 2 + .../peeratcode/model/Player.java | 64 ++++++++++++++++++- .../repository/DatabaseRepository.java | 27 +++++++- .../peeratcode/routes/Leaderboard.java | 52 +++++++++++++++ .../peeratcode/routes/PuzzleResponse.java | 2 - 5 files changed, 143 insertions(+), 4 deletions(-) create mode 100644 src/be/jeffcheasey88/peeratcode/routes/Leaderboard.java diff --git a/src/be/jeffcheasey88/peeratcode/Main.java b/src/be/jeffcheasey88/peeratcode/Main.java index 36cfb90..9be49b9 100644 --- a/src/be/jeffcheasey88/peeratcode/Main.java +++ b/src/be/jeffcheasey88/peeratcode/Main.java @@ -28,6 +28,7 @@ import org.jose4j.lang.JoseException; import be.jeffcheasey88.peeratcode.repository.DatabaseRepository; import be.jeffcheasey88.peeratcode.routes.ChapterElement; import be.jeffcheasey88.peeratcode.routes.ChapterList; +import be.jeffcheasey88.peeratcode.routes.Leaderboard; import be.jeffcheasey88.peeratcode.routes.Login; import be.jeffcheasey88.peeratcode.routes.PuzzleElement; import be.jeffcheasey88.peeratcode.routes.PuzzleResponse; @@ -79,6 +80,7 @@ public class Main { router.register(new Login(router.getDataBase(), router)); router.register(new Result(router.getDataBase())); router.register(new PuzzleResponse(router.getDataBase())); + router.register(new Leaderboard(router.getDataBase())); } private static void startWebServer(Configuration config, Router router) throws IOException { diff --git a/src/be/jeffcheasey88/peeratcode/model/Player.java b/src/be/jeffcheasey88/peeratcode/model/Player.java index 2eb0ada..fe63524 100644 --- a/src/be/jeffcheasey88/peeratcode/model/Player.java +++ b/src/be/jeffcheasey88/peeratcode/model/Player.java @@ -1,6 +1,8 @@ package be.jeffcheasey88.peeratcode.model; -public class Player { +import java.util.Objects; + +public class Player implements Comparable { public static final String PATH_TO_CODE = "/home/%s/peer-at-source/"; private String pseudo; @@ -9,14 +11,29 @@ public class Player { private String lastname; private String description; private String sgroup; + private byte[] avatar; + + private int totalScore; + private int totalCompletion; + private int totalTries; public Player(String pseudo, String email, String firstname, String lastname, String description, String sgroup) { + this(pseudo, email, firstname, lastname, description, sgroup, null); + } + + public Player(String pseudo, String email, String firstname, String lastname, String description, String sgroup, + byte[] avatar) { this.pseudo = pseudo; this.email = email; this.firstname = firstname; this.lastname = lastname; this.description = description; this.sgroup = sgroup; + this.avatar = avatar; + + totalScore = 0; + totalCompletion = 0; + totalTries = 0; } public String getPseudo() { @@ -43,7 +60,52 @@ public class Player { return this.sgroup; } + public byte[] getAvatar() { + return this.avatar; + } + public String getPathToSourceCode() { return String.format(PATH_TO_CODE, pseudo); } + + public int getTotalScore() { + return totalScore; + } + + public void setTotalScore(int totalScore) { + this.totalScore = totalScore; + } + + public int getTotalCompletion() { + return totalCompletion; + } + + public void setTotalCompletion(int totalCompletion) { + this.totalCompletion = totalCompletion; + } + + public int getTotalTries() { + return totalTries; + } + + public void setTotalTries(int totalTries) { + this.totalTries = totalTries; + } + + @Override + public int compareTo(Player arg0) { + if (this == arg0) + return 0; + if (arg0 == null) + return -1; + int compare = Integer.compare(arg0.getTotalScore(), totalScore); + if (compare == 0) { + compare = Integer.compare(arg0.getTotalCompletion(), totalCompletion); + if (compare == 0) { + compare = Integer.compare(totalTries, arg0.getTotalTries()); + } + } + + return compare; + } } diff --git a/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java b/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java index d70c3d7..20840c1 100644 --- a/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java +++ b/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java @@ -8,6 +8,8 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; import com.password4j.Hash; import com.password4j.Password; @@ -30,6 +32,7 @@ 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 = "SELECT * FROM players WHERE id_player = ?"; + private static final String ALL_PLAYERS_FOR_LEADERBOARD = "SELECT p.*, sum(c.score) AS playerScore, count(c.id_completion) AS playerCompletions, sum(c.tries) AS playerTries FROM players p LEFT JOIN completions c ON c.fk_player = p.id_player GROUP BY p.id_player ORDER BY playerScore DESC"; 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 = ?"; @@ -66,7 +69,8 @@ public class DatabaseRepository { private Player makePlayer(ResultSet playerResult) throws SQLException { return new Player(playerResult.getString("pseudo"), playerResult.getString("email"), playerResult.getString("firstName"), playerResult.getString("LastName"), - playerResult.getString("description"), playerResult.getString("sgroup")); + playerResult.getString("description"), playerResult.getString("sgroup"), + playerResult.getBytes("avatar")); } private List getPuzzlesInChapter(int id) throws SQLException { @@ -147,6 +151,27 @@ public class DatabaseRepository { return null; } + public SortedSet getAllPlayerForLeaderboard() { + try { + ensureConnection(); + PreparedStatement playersStmt = con.prepareStatement(ALL_PLAYERS_FOR_LEADERBOARD); + ResultSet result = playersStmt.executeQuery(); + SortedSet players = new TreeSet(); + Player tmpPlayer; + while (result.next()) { + tmpPlayer = makePlayer(result); + tmpPlayer.setTotalScore(result.getInt("playerScore")); + tmpPlayer.setTotalCompletion(result.getInt("playerCompletions")); + tmpPlayer.setTotalTries(result.getInt("playerTries")); + players.add(tmpPlayer); + } + return players; + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + /** * Get a specific chapter * diff --git a/src/be/jeffcheasey88/peeratcode/routes/Leaderboard.java b/src/be/jeffcheasey88/peeratcode/routes/Leaderboard.java new file mode 100644 index 0000000..457dc58 --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/routes/Leaderboard.java @@ -0,0 +1,52 @@ +package be.jeffcheasey88.peeratcode.routes; + +import be.jeffcheasey88.peeratcode.model.Player; +import be.jeffcheasey88.peeratcode.repository.DatabaseRepository; +import be.jeffcheasey88.peeratcode.webserver.HttpReader; +import be.jeffcheasey88.peeratcode.webserver.HttpUtil; +import be.jeffcheasey88.peeratcode.webserver.HttpWriter; +import be.jeffcheasey88.peeratcode.webserver.Response; +import be.jeffcheasey88.peeratcode.webserver.User; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import java.util.SortedSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Leaderboard implements Response { + + private final DatabaseRepository databaseRepo; + + public Leaderboard(DatabaseRepository databaseRepo) { + this.databaseRepo = databaseRepo; + } + + @Override + public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { + HttpUtil.responseHeaders(writer, 200, "Access-Control-Allow-Origin: *"); + SortedSet allPlayers = databaseRepo.getAllPlayerForLeaderboard(); + if (allPlayers != null) { + JSONArray playersJSON = new JSONArray(); + for (Player player : allPlayers) { + JSONObject playerJSON = new JSONObject(); + playerJSON.put("pseudo", player.getPseudo()); + playerJSON.put("group", player.getGroup()); + // chapterJSON.put("avatar", player.); + playerJSON.put("score", player.getTotalScore()); + playerJSON.put("completions", player.getTotalCompletion()); + playerJSON.put("tries", player.getTotalTries()); + playersJSON.add(playerJSON); + } + writer.write(playersJSON.toJSONString()); + } + writer.flush(); + writer.close(); + } + + @Override + public Pattern getPattern() { + return Pattern.compile("^\\/leaderboard$"); + } +} diff --git a/src/be/jeffcheasey88/peeratcode/routes/PuzzleResponse.java b/src/be/jeffcheasey88/peeratcode/routes/PuzzleResponse.java index d613efb..67caac0 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/PuzzleResponse.java +++ b/src/be/jeffcheasey88/peeratcode/routes/PuzzleResponse.java @@ -1,11 +1,9 @@ package be.jeffcheasey88.peeratcode.routes; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; import java.util.Arrays; import java.util.regex.Matcher; import java.util.regex.Pattern;