From 67f6d48b85a6236ce1ba881e6af858b4b6aa3fdd Mon Sep 17 00:00:00 2001 From: Francois G Date: Thu, 23 Feb 2023 15:53:55 +0100 Subject: [PATCH] Add route for puzzle response and beta puzzle score in response --- src/be/jeffcheasey88/peeratcode/Main.java | 4 +- .../repository/DatabaseRepository.java | 93 +++++++++++++++++++ .../peeratcode/routes/PuzzleResponse.java | 79 ++++++++++++++++ .../peeratcode/webserver/HttpReader.java | 8 ++ 4 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 src/be/jeffcheasey88/peeratcode/routes/PuzzleResponse.java diff --git a/src/be/jeffcheasey88/peeratcode/Main.java b/src/be/jeffcheasey88/peeratcode/Main.java index 1e08e06..832dddc 100644 --- a/src/be/jeffcheasey88/peeratcode/Main.java +++ b/src/be/jeffcheasey88/peeratcode/Main.java @@ -8,13 +8,13 @@ import java.util.regex.Pattern; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; -import javax.net.ssl.SSLSocket; import be.jeffcheasey88.peeratcode.repository.DatabaseRepository; import be.jeffcheasey88.peeratcode.routes.ChapterElement; import be.jeffcheasey88.peeratcode.routes.ChapterList; import be.jeffcheasey88.peeratcode.routes.Login; import be.jeffcheasey88.peeratcode.routes.PuzzleElement; +import be.jeffcheasey88.peeratcode.routes.PuzzleResponse; import be.jeffcheasey88.peeratcode.routes.Register; import be.jeffcheasey88.peeratcode.webserver.Client; import be.jeffcheasey88.peeratcode.webserver.HttpReader; @@ -24,7 +24,6 @@ import be.jeffcheasey88.peeratcode.webserver.Response; import be.jeffcheasey88.peeratcode.webserver.Router; public class Main { - // Define SSL Protocol parameters public static void main(String[] args) throws Exception { Configuration config = new Configuration("config.txt"); config.load(); @@ -59,6 +58,7 @@ public class Main { router.register(new PuzzleElement(repo)); router.register(new Register(repo)); router.register(new Login(repo)); + router.register(new PuzzleResponse(repo)); } private static void startWebServer(Configuration config, Router router) throws IOException { diff --git a/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java b/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java index 7f6a9c5..b50b888 100644 --- a/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java +++ b/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java @@ -23,6 +23,12 @@ public class DatabaseRepository { private static final String CHECK_EMAIL_AVAILABLE_QUERY = "SELECT * FROM players WHERE email = ?"; private static final String REGISTER_QUERY = "INSERT INTO players (pseudo, email, passwd, firstname, lastname, description, sgroup, avatar) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; private static final String CHECK_PASSWORD = "SELECT passwd FROM players WHERE pseudo=?"; + private static final String GET_PUZZLE_SOLUTION = "SELECT soluce FROM puzzles WHERE id_puzzle=?"; + private static final String GET_PUZZLE_SCORE_MAX = "SELECT score_max FROM puzzles WHERE id_puzzle=?"; + private static final String GET_PLAYER_ID_BY_PSEUDO = "SELECT id_player FROM players WHERE pseudo=?"; + private static final String GET_PUZZLE_NB_TRIES_AND_SCORE_BY_PLAYER = "SELECT tries, score FROM completions WHERE fk_puzzle = ? AND 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 = ?, code = ?, filename = ?, score = ?"; private Connection con; private Configuration config; @@ -213,4 +219,91 @@ public class DatabaseRepository { } return false; } + + public byte[] getPuzzleSolution(int puzzleId) { + try { + PreparedStatement puzzleStmt = con.prepareStatement(GET_PUZZLE_SOLUTION); + puzzleStmt.setInt(1, puzzleId); + ResultSet result = puzzleStmt.executeQuery(); + if (result.next()) { + return result.getBytes("soluce"); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + public int insertOrUpdatePuzzleResponse(int puzzleId, String pseudo, String fileName, byte[] code) { + try { + ensureConnection(); + int[] triesAndScore = getPuzzleNbTriesAndScore(puzzleId, pseudo); + int playerId = getPlayerIdByPseudo(pseudo); + int puzzleScoreMax = getPuzzleScoreMax(puzzleId); + if (triesAndScore[0] < 0) { + // Insert completions + PreparedStatement statement = con.prepareStatement(INSERT_COMPLETION); + statement.setInt(1, puzzleId); + statement.setInt(2, playerId); + statement.setInt(3, 0); + statement.setBytes(4, code); + statement.setString(5, fileName); + statement.setInt(6, puzzleScoreMax); + return puzzleScoreMax; + } else { + // Update completions + int score = puzzleScoreMax * (((triesAndScore[0]-1)*10)/100); + PreparedStatement statement = con.prepareStatement(UPDATE_COMPLETION); + statement.setInt(1, triesAndScore[0]+1); + statement.setBytes(2, code); + statement.setString(3, fileName); + statement.setInt(4, score); + return score; + } + } catch (SQLException e) { + e.printStackTrace(); + } + return -1; + } + public int getPuzzleScoreMax(int puzzleId) { + try { + PreparedStatement puzzleStmt = con.prepareStatement(GET_PUZZLE_SCORE_MAX); + puzzleStmt.setInt(1, puzzleId); + ResultSet result = puzzleStmt.executeQuery(); + if (result.next()) { + return result.getInt("score_max"); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return -1; + } + public int[] getPuzzleNbTriesAndScore(int puzzleId, String pseudo) { + try { + PreparedStatement puzzleStmt = con.prepareStatement(GET_PUZZLE_NB_TRIES_AND_SCORE_BY_PLAYER); + puzzleStmt.setInt(1, puzzleId); + ResultSet result = puzzleStmt.executeQuery(); + int[] res = new int[2]; + if (result.next()) { + res[0] = result.getInt("tries"); + res[1] = result.getInt("score"); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + private int getPlayerIdByPseudo(String pseudo) { + try { + PreparedStatement puzzleStmt = con.prepareStatement(GET_PLAYER_ID_BY_PSEUDO); + puzzleStmt.setString(1, pseudo); + ResultSet result = puzzleStmt.executeQuery(); + if (result.next()) { + return result.getInt("id_player"); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return -1; + } } \ No newline at end of file diff --git a/src/be/jeffcheasey88/peeratcode/routes/PuzzleResponse.java b/src/be/jeffcheasey88/peeratcode/routes/PuzzleResponse.java new file mode 100644 index 0000000..4742433 --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/routes/PuzzleResponse.java @@ -0,0 +1,79 @@ +package be.jeffcheasey88.peeratcode.routes; + +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.json.simple.JSONObject; + +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; + +public class PuzzleResponse implements Response { + private final DatabaseRepository databaseRepo; + + public PuzzleResponse(DatabaseRepository databaseRepo) { + this.databaseRepo = databaseRepo; + } + + @Override + public void exec(Matcher matcher, HttpReader reader, HttpWriter writer) throws Exception { + HttpUtil.skipHeaders(reader); + + int puzzleId = Integer.parseInt(matcher.group(1)); + byte[] response; + byte[] fileName; + byte[] sourceCode; + + // Response + int hSize = reader.readInt(); + response = new byte[hSize]; + if (hSize == reader.read(response)) { + // File Name + hSize = reader.readInt(); + fileName = new byte[hSize]; + if (hSize == reader.read(fileName)) { + // Source Code + hSize = reader.readInt(); + sourceCode = new byte[hSize]; + if (hSize == reader.read(sourceCode)) { + int score = databaseRepo.insertOrUpdatePuzzleResponse(puzzleId, "Pseudo", fileName.toString(), sourceCode); + if (Arrays.equals(response, databaseRepo.getPuzzleSolution(puzzleId))) { + HttpUtil.responseHeaders(writer, 200, + "Access-Control-Allow-Origin: *", + "Content-Type: application/json"); + JSONObject responseJSON = new JSONObject(); + responseJSON.put("id", puzzleId); + responseJSON.put("score", score); + writer.write(responseJSON.toJSONString()); + writer.flush(); + writer.close(); + } else { + HttpUtil.responseHeaders(writer, 406, "Access-Control-Allow-Origin: *"); + } + } + else { + HttpUtil.responseHeaders(writer, 400, "Access-Control-Allow-Origin: *"); + } + } + else { + HttpUtil.responseHeaders(writer, 400, "Access-Control-Allow-Origin: *"); + } + + } + HttpUtil.responseHeaders(writer, 403, "Access-Control-Allow-Origin: *"); + } + + @Override + public Pattern getPattern() { + return Pattern.compile("^\\/puzzleResponse\\/([0-9]+)$"); + } + + @Override + public String getType() { + return "POST"; + } +} diff --git a/src/be/jeffcheasey88/peeratcode/webserver/HttpReader.java b/src/be/jeffcheasey88/peeratcode/webserver/HttpReader.java index b124d2f..031b9ee 100644 --- a/src/be/jeffcheasey88/peeratcode/webserver/HttpReader.java +++ b/src/be/jeffcheasey88/peeratcode/webserver/HttpReader.java @@ -38,4 +38,12 @@ public class HttpReader { return this.reader.ready(); } + public int readInt() throws Exception{ + int result = 0; + result+=this.in.read() << 24; + result+=this.in.read() << 16; + result+=this.in.read() << 8; + result+=this.in.read(); + return result; + } } \ No newline at end of file