From e0773afa0fb3990a0c7b7053c435b203bdcb8aa3 Mon Sep 17 00:00:00 2001 From: jeffcheasey88 Date: Wed, 28 Feb 2024 22:32:24 +0100 Subject: [PATCH] Adding base system for routes testing + start refractor for bd changing & incomming ORM --- .../peeratcode/model/Badge.class | Bin 218 -> 0 bytes .settings/org.eclipse.jdt.apt.core.prefs | 1 + Treasure.jar | Bin 7831 -> 146377 bytes src/dev/peerat/backend/Configuration.java | 39 +- src/dev/peerat/backend/Main.java | 74 +- .../{bonus => last_bonus}/discord/Bot.java | 0 .../extract/RouteDoc.java | 0 .../extract/RouteDocs.java | 0 .../extract/RouteExtracter.java | 0 .../{routes => last_routes}/BadgeDetails.java | 0 .../ChapterElement.java | 0 .../{routes => last_routes}/ChapterList.java | 0 .../DynamicLeaderboard.java | 0 .../{routes => last_routes}/Leaderboard.java | 0 .../PlayerDetails.java | 0 .../PuzzleElement.java | 0 .../PuzzleResponse.java | 0 .../{routes => last_routes}/Result.java | 0 .../{routes => last_routes}/Swagger.java | 0 .../admins/DynamicLogs.java | 0 .../groups/GroupCreate.java | 0 .../groups/GroupJoin.java | 0 .../groups/GroupList.java | 0 .../groups/GroupQuit.java | 0 .../users/ChangePassword.java | 0 .../users/ForgotPassword.java | 0 .../{routes => last_routes}/users/Login.java | 0 .../users/MailConfirmation.java | 0 .../users/ProfileSettings.java | 0 .../users/Register.java | 0 .../{utils => last_utils}/FormResponse.java | 0 .../backend/{utils => last_utils}/Mail.java | 0 src/dev/peerat/backend/model/Badge.java | 26 - src/dev/peerat/backend/model/Chapter.java | 70 +- src/dev/peerat/backend/model/Completion.java | 120 +-- src/dev/peerat/backend/model/Group.java | 156 +--- src/dev/peerat/backend/model/PeerAtUser.java | 29 +- src/dev/peerat/backend/model/Player.java | 207 ------ src/dev/peerat/backend/model/Puzzle.java | 115 +-- src/dev/peerat/backend/model/School.java | 17 + src/dev/peerat/backend/model/Solution.java | 39 + .../backend/repository/DatabaseQuery.java | 265 ------- .../repository/DatabaseRepository.java | 695 ------------------ .../peerat/backend/routes/StateTestCase.java | 93 +++ 44 files changed, 285 insertions(+), 1661 deletions(-) delete mode 100644 .generated/be/jeffcheasey88/peeratcode/model/Badge.class rename src/dev/peerat/backend/{bonus => last_bonus}/discord/Bot.java (100%) rename src/dev/peerat/backend/{bonus => last_bonus}/extract/RouteDoc.java (100%) rename src/dev/peerat/backend/{bonus => last_bonus}/extract/RouteDocs.java (100%) rename src/dev/peerat/backend/{bonus => last_bonus}/extract/RouteExtracter.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/BadgeDetails.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/ChapterElement.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/ChapterList.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/DynamicLeaderboard.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/Leaderboard.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/PlayerDetails.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/PuzzleElement.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/PuzzleResponse.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/Result.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/Swagger.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/admins/DynamicLogs.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/groups/GroupCreate.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/groups/GroupJoin.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/groups/GroupList.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/groups/GroupQuit.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/users/ChangePassword.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/users/ForgotPassword.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/users/Login.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/users/MailConfirmation.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/users/ProfileSettings.java (100%) rename src/dev/peerat/backend/{routes => last_routes}/users/Register.java (100%) rename src/dev/peerat/backend/{utils => last_utils}/FormResponse.java (100%) rename src/dev/peerat/backend/{utils => last_utils}/Mail.java (100%) delete mode 100644 src/dev/peerat/backend/model/Badge.java delete mode 100644 src/dev/peerat/backend/model/Player.java create mode 100644 src/dev/peerat/backend/model/School.java create mode 100644 src/dev/peerat/backend/model/Solution.java delete mode 100644 src/dev/peerat/backend/repository/DatabaseQuery.java delete mode 100644 src/dev/peerat/backend/repository/DatabaseRepository.java create mode 100644 test/dev/peerat/backend/routes/StateTestCase.java diff --git a/.generated/be/jeffcheasey88/peeratcode/model/Badge.class b/.generated/be/jeffcheasey88/peeratcode/model/Badge.class deleted file mode 100644 index 735a8711f73fde25ce1192d584c1ecfcf32ae7ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 218 zcmW-bJr06E5QX0YiXuiYU}5D?;kFjULK7>ag~omt27~|_L=%r?Wn$q0Jd|-@CV7)@ z-X!zBzxM}#hpqzyrVYzQ15JT`qV7tjDv#t&C*+p`O)t*lav@-jCr2ACfsrPeP#F3r zQdfG+=kh{SsM0?NBr}#&E>#ebfVE;0=xyShwzo`EaZoztjk7=B3ZK?-4fXY`dW|7$ gPE?iP=1i<@ra{d>WBP)4*0#f1*?`5`;c3AA1GW1shX4Qo diff --git a/.settings/org.eclipse.jdt.apt.core.prefs b/.settings/org.eclipse.jdt.apt.core.prefs index 4dfc072..cb6c1ce 100644 --- a/.settings/org.eclipse.jdt.apt.core.prefs +++ b/.settings/org.eclipse.jdt.apt.core.prefs @@ -2,5 +2,6 @@ eclipse.preferences.version=1 org.eclipse.jdt.apt.aptEnabled=true org.eclipse.jdt.apt.genSrcDir=.apt_generated org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests +org.eclipse.jdt.apt.processorOptions/treasure.providers=dev.peerat.mapping.providers.mysql.MySQLProvider org.eclipse.jdt.apt.processorOptions/treasure.source=%sourcepath% org.eclipse.jdt.apt.reconcileEnabled=true diff --git a/Treasure.jar b/Treasure.jar index 1b2293a83f38ac77cdfd22f474421fd2839d83b8..9342460189d7e7d39a470bec7c3ebdef3f847cc5 100644 GIT binary patch literal 146377 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

&<@9^w$n zn(V_Xag96LvM0Jq67ZHy5 zmv!-%T1x7UZ%QPgCQZ@GOu2c=JB+1@5pWzpWu*CCi|)p2G=q`2u+!vCB+MC#bX?z3 z;5!?_#afux1V9spIIR_?YlM-ur{W&gnhHuZ&9Fr?1TrHjLoG>hcb=|`g+|fnX9kJ2 z3yK&kbef?h3tc#u7PQdbuaPjOFk1N;QRj>fBb6&bR4j+21IRZJcKb_TJ_x*B{^{vh zvsM7K1@{ikhuO85@B_?FLnyJ>pv4dKP^Zu)xdepHsWG&uHk7Ct#wr%t6dap;?@8UG zv=M}N7w_r=BSpyu-A+4eH%;{&IC4eKA!cLl<48LWhEPaL`ofwT^@?FcXDDltWvZdT z^|KpI01NAQ*h|VdjL+#yHHYmcq2o=<$&FXO+X%O1^9{sL8f{t=HK&N^iWBfdHStTh z9}$%_^IB*F-wd&J+Ip^?on=ReK{hP1Y%F=U^4K%R`l6wy^}5BZlqjW%6(y=wn%Y{) zKD>1d5qp9muKM>BAiq2~1LbHMmx@8aVP>4Jvh+C?(+NB)V=%Ur{!!F8du*)2eO%UW zzlZi1Es8Et8JaiReYm4_irTp_J*iBI`}UzYb;NBV7AlJJ>TRwNhK&1>SVg!rHr~%H^uHW_-&&nb6`&5vkjQ8Fb)=Y)b zr9^JWaHz94=L|VDEGZ5Jh3I7AQs9gEc=hq&Bf0K0Chti~+oJg@5?-(N`~=jv??P>4 zPsdP4o_`F{Swkit;+o3-heV97 zKX-7|aKX@Z!a5=k&y&*sM)00&veQXZnDia~)^POlfB1R_;7Gpk-#fOmv28oqBr~yX z+qS*2ZES37W81c^jlFsE``=sjqUya>r@Bvf iCIo(TfpPnf44zp$X4XL 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

Y2ANzQ4^3$yKys~*3%}@r4N6?%5E2uHOff^S zJCtSqBN_#GigT>3NRkkLMD%5o2{$9j&{a=kP$J&a)i&a2%{X1np_yA_eq5z3&b>>U%X@|hzjLgYWJ9j5)<0V z6G_%$ZXIa;DtaO(ie!J9w&(XT3Gy$r+DuiD^GiL(SPOE z70cSgK?3P-7gJ3;@_&4YH&9{%r5IV7bkIL|!1rJ46S45$$)vF94}U?e$VAY+kX5e` z=WC8o^|>Gyklq9VMI*P2Q#$$#+8DEzwnpt4ioPKN;fB^qH6Ej3-%npoJ&DFhYw}pI zD7KYGPM-{~idjf`hj?zZjrE^7z}KF4-vSH-L>>|Zg#F*-01;<1Bb$GwfRs&nG-347 zkJ1!|YBicqLrCbKn&}5bc2n)FZB+`2=HVnAy0X$hCDJ#i-DPfndR%hveL-XN1tFa9 zH1D9Z1DES&Y8m&NME(QrW&ENHNz℘%a8ti$ytb@7rC( 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 diff --git a/src/dev/peerat/backend/Configuration.java b/src/dev/peerat/backend/Configuration.java index c466bc5..c03cb1c 100644 --- a/src/dev/peerat/backend/Configuration.java +++ b/src/dev/peerat/backend/Configuration.java @@ -7,7 +7,9 @@ import java.io.FileReader; import java.io.FileWriter; import java.lang.reflect.Field; -import dev.peerat.backend.utils.Mail; +import dev.peerat.backend.last_utils.Mail; +import dev.peerat.mapping.providers.Compass; +import dev.peerat.mapping.providers.mysql.MySQLCompass; public class Configuration { @@ -57,18 +59,21 @@ public class Configuration { return this; } - public void load() throws Exception{ - if(!this._file.exists()) return; + public Configuration load() throws Exception{ + if(!this._file.exists()) return this; BufferedReader reader = new BufferedReader(new FileReader(this._file)); String line; while((line = reader.readLine()) != null){ - String[] split = line.split("="); - Field field = getClass().getDeclaredField(split[0]); + int index = line.indexOf('='); + String key = line.substring(0, index); + String value = line.substring(index+1); + Field field = getClass().getDeclaredField(key); if(field == null) continue; field.setAccessible(true); - injectValue(field, split[1]); + injectValue(field, value); } reader.close(); + return this; } private void injectValue(Field field, String value) throws IllegalAccessException { @@ -131,25 +136,9 @@ public class Configuration { public boolean isProduction(){ return this.prod; } - - public String getDbHost() { - return this.db_host; - } - - public int getDbPort() { - return this.db_port; - } - - public String getDbUser() { - return this.db_user; - } - - public String getDbDatabase() { - return this.db_database; - } - - public String getDbPassword() { - return this.db_password; + + public Compass getCompass(){ + return new MySQLCompass(db_host, db_port, db_database, db_user, db_password); } public String getSslKeystore() { diff --git a/src/dev/peerat/backend/Main.java b/src/dev/peerat/backend/Main.java index e78982c..e3d7ade 100644 --- a/src/dev/peerat/backend/Main.java +++ b/src/dev/peerat/backend/Main.java @@ -6,33 +6,7 @@ import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; -import dev.peerat.backend.bonus.extract.RouteExtracter; -import dev.peerat.backend.model.Completion; -import dev.peerat.backend.model.Group; import dev.peerat.backend.model.PeerAtUser; -import dev.peerat.backend.repository.DatabaseRepository; -import dev.peerat.backend.routes.BadgeDetails; -import dev.peerat.backend.routes.ChapterElement; -import dev.peerat.backend.routes.ChapterList; -import dev.peerat.backend.routes.DynamicLeaderboard; -import dev.peerat.backend.routes.Leaderboard; -import dev.peerat.backend.routes.PlayerDetails; -import dev.peerat.backend.routes.PuzzleElement; -import dev.peerat.backend.routes.PuzzleResponse; -import dev.peerat.backend.routes.Result; -import dev.peerat.backend.routes.Swagger; -import dev.peerat.backend.routes.admins.DynamicLogs; -import dev.peerat.backend.routes.groups.GroupCreate; -import dev.peerat.backend.routes.groups.GroupJoin; -import dev.peerat.backend.routes.groups.GroupList; -import dev.peerat.backend.routes.groups.GroupQuit; -import dev.peerat.backend.routes.users.ChangePassword; -import dev.peerat.backend.routes.users.ForgotPassword; -import dev.peerat.backend.routes.users.Login; -import dev.peerat.backend.routes.users.MailConfirmation; -import dev.peerat.backend.routes.users.ProfileSettings; -import dev.peerat.backend.routes.users.Register; -import dev.peerat.backend.utils.Mail; import dev.peerat.framework.Context; import dev.peerat.framework.HttpReader; import dev.peerat.framework.HttpWriter; @@ -41,17 +15,19 @@ import dev.peerat.framework.RequestType; import dev.peerat.framework.Response; import dev.peerat.framework.Route; import dev.peerat.framework.Router; +import dev.peerat.mapping.Ship; +import dev.peerat.mapping.providers.mysql.MySQLCompass; +import dev.peerat.mapping.providers.mysql.MySQLMap; import dev.peerat.framework.Locker.Key; public class Main{ public static void main(String[] args) throws Exception{ Configuration config = new Configuration("config.txt") - .addDefaultValue("users_files", "/tmp/users_files"); - config.load(); + .addDefaultValue("users_files", "/tmp/users_files") + .load(); - Class.forName("com.mysql.cj.jdbc.Driver"); + Ship ship = new Ship("mysql", config.getCompass(), new MySQLMap()); - DatabaseRepository repo = new DatabaseRepository(config); Router router = new Router() .configureJwt( (builder) -> builder.setExpectedIssuer(config.getTokenIssuer()), @@ -78,10 +54,9 @@ public class Main{ public void exec(Matcher matcher, Context context, HttpReader reader, HttpWriter writer) throws Exception { context.response(200); } - }); - initRoutes(router, repo, config); + initRoutes(router, config); new Thread(new Runnable(){ public void run(){ @@ -95,7 +70,7 @@ public class Main{ locker.lock(key); Context instance = locker.getValue(key); if(instance == null) continue; - System.out.println("["+((instance.isLogged()) ? repo.getPlayer(instance.getUser().getId()).getPseudo() : "?")+"] "+instance.getType()+" "+instance.getPath()+" -> "+instance.getResponseCode()); + System.out.println("["+((instance.isLogged()) ? instance.getUser().getPseudo() : "?")+"] "+instance.getType()+" "+instance.getPath()+" -> "+instance.getResponseCode()); } }catch(Exception e){ e.printStackTrace(); @@ -108,43 +83,12 @@ public class Main{ router.listen(config.getTcpPort(), config.useSsl()); } - private static void initRoutes(Router router, DatabaseRepository repo, Configuration config) throws Exception{ + private static void initRoutes(Router router, Configuration config) throws Exception{ Map playersWaiting = new HashMap<>(); Mail mail = config.getMail(); Locker groupLock = new Locker<>(); Locker leaderboard = new Locker<>(); - if(config.isProduction()) - router. - register(new Register(repo, playersWaiting, mail)). - register(new MailConfirmation(repo, router, config.getUsersFiles(), config.getGitToken(), playersWaiting, mail)); - - router. - register(new Login(repo, router)). - register(new ProfileSettings(repo)). - register(new ChangePassword(repo)). - register(new ForgotPassword(router, repo, mail)). - - register(new DynamicLogs(router.getLogger(), repo)). - - register(new ChapterElement(repo)). - register(new ChapterList(repo)). - register(new PuzzleElement(repo)). - register(new Result(repo)). - register(new Leaderboard(repo)). - register(new PlayerDetails(repo)). - register(new BadgeDetails(repo)). - - register(new DynamicLeaderboard(repo, leaderboard)). - register(new PuzzleResponse(repo, config.getUsersFiles(), leaderboard)). - - register(new GroupCreate(repo, groupLock, config.getGroupJoinMinutes())). - register(new GroupList(repo)). - register(new GroupJoin(repo, config.getGroupJoinMinutes(), config.getGroupQuitMinutes(), leaderboard)). - register(new GroupQuit(repo, config.getGroupJoinMinutes(), leaderboard)) - - .register(new Swagger(new RouteExtracter(router),config.getTokenIssuer())); - // Bot bot = new Bot(config, repo, groupLock); // bot.start(); } diff --git a/src/dev/peerat/backend/bonus/discord/Bot.java b/src/dev/peerat/backend/last_bonus/discord/Bot.java similarity index 100% rename from src/dev/peerat/backend/bonus/discord/Bot.java rename to src/dev/peerat/backend/last_bonus/discord/Bot.java diff --git a/src/dev/peerat/backend/bonus/extract/RouteDoc.java b/src/dev/peerat/backend/last_bonus/extract/RouteDoc.java similarity index 100% rename from src/dev/peerat/backend/bonus/extract/RouteDoc.java rename to src/dev/peerat/backend/last_bonus/extract/RouteDoc.java diff --git a/src/dev/peerat/backend/bonus/extract/RouteDocs.java b/src/dev/peerat/backend/last_bonus/extract/RouteDocs.java similarity index 100% rename from src/dev/peerat/backend/bonus/extract/RouteDocs.java rename to src/dev/peerat/backend/last_bonus/extract/RouteDocs.java diff --git a/src/dev/peerat/backend/bonus/extract/RouteExtracter.java b/src/dev/peerat/backend/last_bonus/extract/RouteExtracter.java similarity index 100% rename from src/dev/peerat/backend/bonus/extract/RouteExtracter.java rename to src/dev/peerat/backend/last_bonus/extract/RouteExtracter.java diff --git a/src/dev/peerat/backend/routes/BadgeDetails.java b/src/dev/peerat/backend/last_routes/BadgeDetails.java similarity index 100% rename from src/dev/peerat/backend/routes/BadgeDetails.java rename to src/dev/peerat/backend/last_routes/BadgeDetails.java diff --git a/src/dev/peerat/backend/routes/ChapterElement.java b/src/dev/peerat/backend/last_routes/ChapterElement.java similarity index 100% rename from src/dev/peerat/backend/routes/ChapterElement.java rename to src/dev/peerat/backend/last_routes/ChapterElement.java diff --git a/src/dev/peerat/backend/routes/ChapterList.java b/src/dev/peerat/backend/last_routes/ChapterList.java similarity index 100% rename from src/dev/peerat/backend/routes/ChapterList.java rename to src/dev/peerat/backend/last_routes/ChapterList.java diff --git a/src/dev/peerat/backend/routes/DynamicLeaderboard.java b/src/dev/peerat/backend/last_routes/DynamicLeaderboard.java similarity index 100% rename from src/dev/peerat/backend/routes/DynamicLeaderboard.java rename to src/dev/peerat/backend/last_routes/DynamicLeaderboard.java diff --git a/src/dev/peerat/backend/routes/Leaderboard.java b/src/dev/peerat/backend/last_routes/Leaderboard.java similarity index 100% rename from src/dev/peerat/backend/routes/Leaderboard.java rename to src/dev/peerat/backend/last_routes/Leaderboard.java diff --git a/src/dev/peerat/backend/routes/PlayerDetails.java b/src/dev/peerat/backend/last_routes/PlayerDetails.java similarity index 100% rename from src/dev/peerat/backend/routes/PlayerDetails.java rename to src/dev/peerat/backend/last_routes/PlayerDetails.java diff --git a/src/dev/peerat/backend/routes/PuzzleElement.java b/src/dev/peerat/backend/last_routes/PuzzleElement.java similarity index 100% rename from src/dev/peerat/backend/routes/PuzzleElement.java rename to src/dev/peerat/backend/last_routes/PuzzleElement.java diff --git a/src/dev/peerat/backend/routes/PuzzleResponse.java b/src/dev/peerat/backend/last_routes/PuzzleResponse.java similarity index 100% rename from src/dev/peerat/backend/routes/PuzzleResponse.java rename to src/dev/peerat/backend/last_routes/PuzzleResponse.java diff --git a/src/dev/peerat/backend/routes/Result.java b/src/dev/peerat/backend/last_routes/Result.java similarity index 100% rename from src/dev/peerat/backend/routes/Result.java rename to src/dev/peerat/backend/last_routes/Result.java diff --git a/src/dev/peerat/backend/routes/Swagger.java b/src/dev/peerat/backend/last_routes/Swagger.java similarity index 100% rename from src/dev/peerat/backend/routes/Swagger.java rename to src/dev/peerat/backend/last_routes/Swagger.java diff --git a/src/dev/peerat/backend/routes/admins/DynamicLogs.java b/src/dev/peerat/backend/last_routes/admins/DynamicLogs.java similarity index 100% rename from src/dev/peerat/backend/routes/admins/DynamicLogs.java rename to src/dev/peerat/backend/last_routes/admins/DynamicLogs.java diff --git a/src/dev/peerat/backend/routes/groups/GroupCreate.java b/src/dev/peerat/backend/last_routes/groups/GroupCreate.java similarity index 100% rename from src/dev/peerat/backend/routes/groups/GroupCreate.java rename to src/dev/peerat/backend/last_routes/groups/GroupCreate.java diff --git a/src/dev/peerat/backend/routes/groups/GroupJoin.java b/src/dev/peerat/backend/last_routes/groups/GroupJoin.java similarity index 100% rename from src/dev/peerat/backend/routes/groups/GroupJoin.java rename to src/dev/peerat/backend/last_routes/groups/GroupJoin.java diff --git a/src/dev/peerat/backend/routes/groups/GroupList.java b/src/dev/peerat/backend/last_routes/groups/GroupList.java similarity index 100% rename from src/dev/peerat/backend/routes/groups/GroupList.java rename to src/dev/peerat/backend/last_routes/groups/GroupList.java diff --git a/src/dev/peerat/backend/routes/groups/GroupQuit.java b/src/dev/peerat/backend/last_routes/groups/GroupQuit.java similarity index 100% rename from src/dev/peerat/backend/routes/groups/GroupQuit.java rename to src/dev/peerat/backend/last_routes/groups/GroupQuit.java diff --git a/src/dev/peerat/backend/routes/users/ChangePassword.java b/src/dev/peerat/backend/last_routes/users/ChangePassword.java similarity index 100% rename from src/dev/peerat/backend/routes/users/ChangePassword.java rename to src/dev/peerat/backend/last_routes/users/ChangePassword.java diff --git a/src/dev/peerat/backend/routes/users/ForgotPassword.java b/src/dev/peerat/backend/last_routes/users/ForgotPassword.java similarity index 100% rename from src/dev/peerat/backend/routes/users/ForgotPassword.java rename to src/dev/peerat/backend/last_routes/users/ForgotPassword.java diff --git a/src/dev/peerat/backend/routes/users/Login.java b/src/dev/peerat/backend/last_routes/users/Login.java similarity index 100% rename from src/dev/peerat/backend/routes/users/Login.java rename to src/dev/peerat/backend/last_routes/users/Login.java diff --git a/src/dev/peerat/backend/routes/users/MailConfirmation.java b/src/dev/peerat/backend/last_routes/users/MailConfirmation.java similarity index 100% rename from src/dev/peerat/backend/routes/users/MailConfirmation.java rename to src/dev/peerat/backend/last_routes/users/MailConfirmation.java diff --git a/src/dev/peerat/backend/routes/users/ProfileSettings.java b/src/dev/peerat/backend/last_routes/users/ProfileSettings.java similarity index 100% rename from src/dev/peerat/backend/routes/users/ProfileSettings.java rename to src/dev/peerat/backend/last_routes/users/ProfileSettings.java diff --git a/src/dev/peerat/backend/routes/users/Register.java b/src/dev/peerat/backend/last_routes/users/Register.java similarity index 100% rename from src/dev/peerat/backend/routes/users/Register.java rename to src/dev/peerat/backend/last_routes/users/Register.java diff --git a/src/dev/peerat/backend/utils/FormResponse.java b/src/dev/peerat/backend/last_utils/FormResponse.java similarity index 100% rename from src/dev/peerat/backend/utils/FormResponse.java rename to src/dev/peerat/backend/last_utils/FormResponse.java diff --git a/src/dev/peerat/backend/utils/Mail.java b/src/dev/peerat/backend/last_utils/Mail.java similarity index 100% rename from src/dev/peerat/backend/utils/Mail.java rename to src/dev/peerat/backend/last_utils/Mail.java diff --git a/src/dev/peerat/backend/model/Badge.java b/src/dev/peerat/backend/model/Badge.java deleted file mode 100644 index e9ce799..0000000 --- a/src/dev/peerat/backend/model/Badge.java +++ /dev/null @@ -1,26 +0,0 @@ -package dev.peerat.backend.model; - -public class Badge { - - private String name; - private byte[] logo; - private int level; - - public Badge(String name, byte[] logo, int level) { - this.name = name; - this.logo = logo; - this.level = level; - } - - public String getName(){ - return name; - } - - public byte[] getLogo() { - return logo; - } - - public int getLevel() { - return level; - } -} diff --git a/src/dev/peerat/backend/model/Chapter.java b/src/dev/peerat/backend/model/Chapter.java index 312fde4..d533b33 100644 --- a/src/dev/peerat/backend/model/Chapter.java +++ b/src/dev/peerat/backend/model/Chapter.java @@ -1,66 +1,26 @@ package dev.peerat.backend.model; -import java.sql.Timestamp; import java.time.LocalDateTime; -import java.util.List; +import dev.peerat.mapping.Treasure; + +@Treasure public class Chapter { - private int id; - private String name; - private List puzzles; - private Timestamp startDate; - private Timestamp endDate; - - public Chapter(int id, String name, Timestamp startDate, Timestamp endDate) { - this.id = id; - this.name = name; - this.startDate = startDate; - this.endDate = endDate; - } - - public int getId() { - return id; - } - - public String getName() { - return name; - } - - public List getPuzzles() { - return puzzles; - } - - public void setPuzzles(List puzzles) { - this.puzzles = puzzles; + private int participantCount; + private LocalDateTime start; + private LocalDateTime end; + + public int getParticipantCount(){ + return this.participantCount; } - public boolean hasStarted(){ - LocalDateTime now = LocalDateTime.now(); - boolean show = true; - if(startDate != null) show &= now.isAfter(startDate.toLocalDateTime()); - return show; + public LocalDateTime getStartTime(){ + return this.start; } - - public Timestamp getStartDate() { - return startDate; - } - - public Timestamp getEndDate() { - return endDate; - } - - @Override - public boolean equals(Object object) { - if (this == object) - return true; - if (!(object instanceof Chapter)) - return false; - return this.id == (((Chapter) object).id); - } - - @Override - public int hashCode() { - return id; + + public LocalDateTime getEndTime(){ + return this.end; } + } diff --git a/src/dev/peerat/backend/model/Completion.java b/src/dev/peerat/backend/model/Completion.java index 2967308..064088e 100644 --- a/src/dev/peerat/backend/model/Completion.java +++ b/src/dev/peerat/backend/model/Completion.java @@ -1,103 +1,51 @@ package dev.peerat.backend.model; -import java.util.Arrays; +import dev.peerat.mapping.Treasure; +@Treasure public class Completion{ - private int puzzleId; - private int playerId; + + private PeerAtUser player; private int tries; - private String fileName; - private byte[] code; + private String file; private int score; - private String puzzleName; + private int scoreTime; + private int scoreRespect; + private Solution solution; - public Completion(int playerId, int puzzleId, int tries, String fileName, int score){ - this(playerId, puzzleId, tries, score, fileName, null, null, null, null); - } - public Completion(int playerId, int puzzleId, int tries, String fileName, int score, String puzzleName) { - this(playerId, puzzleId, tries, score, fileName, null, null, null, puzzleName); - } - - public Completion(int playerId, int puzzleId, String fileName, byte[] file, byte[] response, Puzzle currentPuzzle) { - this(playerId, puzzleId, 0, 0, fileName, file, response, currentPuzzle, null); + public Completion(){} + + public Completion(PeerAtUser player, String file){ + this.player = player; + this.tries = 1; + this.file = file; } - public Completion(int initTries, int initScore){ - // For group leaderboard - this(-1, -1, initTries, initScore, null, null, null, null, null); - } - - public Completion(int playerId, int puzzleId, int tries, int score, String fileName, byte[] file, byte[] response, - Puzzle currentPuzzle, String initPuzzleName){ - this.playerId = playerId; - this.puzzleId = puzzleId; - this.fileName = fileName; - if (code != null) - this.code = Arrays.copyOf(file, file.length); - - // Updated with addTry - this.tries = tries; - this.score = score; - - if (currentPuzzle != null) - addTry(currentPuzzle, response, 0); - - puzzleName = initPuzzleName; - } - - @Override - public String toString(){ - return "Completion[puzzleId="+puzzleId+", userId="+playerId+",tries="+tries+",score="+score+"]"; - } - - public int getPuzzleId() { - return puzzleId; - } - - public int getPlayerId() { - return playerId; - } - - public int getTries() { - return tries; - } - - public void addTry(Puzzle currentPuzzle, byte[] response, int chapter){ - if (score <= 0){ - tries++; - if (response != null && Arrays.equals(currentPuzzle.getSoluce(), response)){ - if (tries > 1) { // Loose 5% each try with a minimum of 1 for score - if(chapter < 4){ - score = currentPuzzle.getScoreMax(); - }else{ - score = (int) Math.ceil(currentPuzzle.getScoreMax() * (1 - ((tries - 1) / 20.))); - } -// score = currentPuzzle.getScoreMax(); - if (score < 1) - score = 1; - } else - score = currentPuzzle.getScoreMax(); - } - } + public PeerAtUser getPlayer(){ + return this.player; } - public void updatePlayer(int playerId){ - this.playerId = playerId; - } - - public String getFileName() { - return fileName; + public int getTries(){ + return this.tries; } - public String getPuzzleName() { - return puzzleName; + public String getFileName(){ + return this.file; } - - public byte[] getCode() { - return code; + + public int getScore(){ + return this.score; } - - public int getScore() { - return score; + + public int getScoreTime(){ + return this.scoreTime; + } + + public int getScoreRespect(){ + return this.scoreRespect; + } + + public Solution getSolution(){ + return this.solution; } } diff --git a/src/dev/peerat/backend/model/Group.java b/src/dev/peerat/backend/model/Group.java index 6d8b8d7..e9e567e 100644 --- a/src/dev/peerat/backend/model/Group.java +++ b/src/dev/peerat/backend/model/Group.java @@ -1,152 +1,32 @@ package dev.peerat.backend.model; -import java.util.ArrayList; import java.util.List; -import java.util.Objects; -import org.jose4j.json.internal.json_simple.JSONArray; -import org.jose4j.json.internal.json_simple.JSONObject; +import dev.peerat.mapping.Treasure; -import be.jeffcheasey88.peeratcode.mapping.SeaBottle; -import dev.peerat.framework.utils.json.JsonMap; +@Treasure +public class Group { -public class Group implements Comparable { private String name; - private Integer linkToChapter; -// private Integer linkToPuzzle; - private List players; + private List players; + private Puzzle puzzle; + private Chapter chapter; - @Override - public String toString(){ - return "Group[name="+name+", chapter="+linkToChapter+"]"; - } - - public Group(JsonMap json){ - this.name = (String) json.get("name"); - if (json.has("chapter")) - this.linkToChapter = ((Number) json.get("chapter")).intValue(); -// if (json.has("puzzle")) -// this.linkToPuzzle = ((Number) json.get("puzzle")).intValue(); - } - - public Group(String name, Integer initChap, Integer initPuzz) { - this.name = name; - this.linkToChapter = initChap; -// this.linkToPuzzle = initPuzz; + public Group(){} + + public String getName(){ + return this.name; } - @SeaBottle - public static Group getGroup(int player){ - return null; + public List getPlayers(){ + return this.players; } - - public void addPlayer(Player newPlayer) { - if (newPlayer != null) { - if (players == null) - players = new ArrayList(); - - int pPosition = players.indexOf(newPlayer); - if (pPosition < 0) { - players.add(newPlayer); - } else { - players.get(pPosition).addCompletion(new Completion(newPlayer.getTotalTries(), newPlayer.getTotalScore())); - } - } + + public Puzzle getPuzzle(){ + return this.puzzle; } - - 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; - } - - public Integer getLinkToChapter() { - return linkToChapter; - } - -// public Integer getLinkToPuzzle() { -// return linkToPuzzle; -// } - - public JSONObject toJson() { - return this.toJson(null); - } - - public JSONObject toJson(Integer rank) { - JSONObject groupJSON = new JSONObject(); - groupJSON.put("name", name); - if (rank != null) - groupJSON.put("rank", rank); - else if (linkToChapter != null) - groupJSON.put("chapter", linkToChapter); -// else if (linkToPuzzle != null) -// groupJSON.put("puzzle", linkToPuzzle); - 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(obj == this) return true; - if(obj == null) return false; - if(!(obj instanceof Group)) return false; - Group other = (Group) obj; - return this.name.equals(other.name) && integerEquals(this.linkToChapter, other.linkToChapter); // && integerEquals(this.linkToPuzzle, other.linkToPuzzle); - } - - private boolean integerEquals(Integer a, Integer b){ - if(a == null) return b == null; - return a.equals(b); + + public Chapter getChapter(){ + return this.chapter; } } diff --git a/src/dev/peerat/backend/model/PeerAtUser.java b/src/dev/peerat/backend/model/PeerAtUser.java index 28d9642..61a8a33 100644 --- a/src/dev/peerat/backend/model/PeerAtUser.java +++ b/src/dev/peerat/backend/model/PeerAtUser.java @@ -2,9 +2,17 @@ package dev.peerat.backend.model; import org.jose4j.jwt.JwtClaims; -public class PeerAtUser extends dev.peerat.framework.User{ +import dev.peerat.mapping.Treasure; +@Treasure +public class PeerAtUser extends dev.peerat.framework.User{ + private int id; + private String pseudo; + private String email; + private String fistName; + private String lastName; + private School school; public PeerAtUser(int id){ this.id = id; @@ -23,6 +31,23 @@ public class PeerAtUser extends dev.peerat.framework.User{ return this.id; } + public String getPseudo(){ + return this.pseudo; + } - + public String getEmail(){ + return this.email; + } + + public String getFirstName(){ + return this.fistName; + } + + public String getLastName(){ + return this.lastName; + } + + public School getSchool(){ + return this.school; + } } diff --git a/src/dev/peerat/backend/model/Player.java b/src/dev/peerat/backend/model/Player.java deleted file mode 100644 index 540b30b..0000000 --- a/src/dev/peerat/backend/model/Player.java +++ /dev/null @@ -1,207 +0,0 @@ -package dev.peerat.backend.model; - -import java.util.Base64; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -import dev.peerat.framework.utils.json.JsonArray; -import dev.peerat.framework.utils.json.JsonMap; - -public class Player implements Comparable { - private String pseudo; - private String email; - private String firstname; - private String lastname; - private String description; - private Set groups; - private Set completions = new HashSet(); - private byte[] avatar; - - private int rank; - - private Set badges; - - public Player(String pseudo, String email, String firstname, String lastname) { - this.pseudo = pseudo; - this.email = email; - this.firstname = firstname; - this.lastname = lastname; - this.description = ""; - } - - public Player(String pseudo, int score, int tries) { - // For groups leaderboard - this.pseudo = pseudo; - this.completions.add(new Completion(tries, score)); - email = ""; // TO make compareTo and equals works as usual - } - - public Player(String email) { - // For player find in Map during register process - this.email = email; - } - - public void setPseudo(String pseudo){ - this.pseudo = pseudo; - } - - public String getPseudo() { - return this.pseudo; - } - - public String getEmail() { - return this.email; - } - - public String getFirstname() { - return this.firstname; - } - - public String getLastname() { - return this.lastname; - } - - public String getDescription() { - return this.description; - } - - public Set getGroups() { - return groups; - } - - public JsonArray getJsonGroups() { - if (groups != null) { - JsonArray groupsJSON = new JsonArray(); - for (Group group : groups) { - groupsJSON.add(group.toJson()); - } - return groupsJSON; - } - return null; - } - - public void addGroup(Group newGroup) { - if (newGroup != null) { - if (this.groups == null) - this.groups = new HashSet(); - this.groups.add(newGroup); - } - } - - public byte[] getAvatar() { - return this.avatar; - } - - public void setAvatar(byte[] newAvatar) { - avatar = newAvatar; - } - - public int getRank() { - return rank; - } - - public void setRank(int newRank) { - rank = newRank; - } - - public void addCompletion(Completion makeCompletion) { - completions.add(makeCompletion); - } - - public int getTotalScore() { - int totalScore = 0; - for (Completion c: completions) { - totalScore = totalScore + c.getScore(); - } - return totalScore; - } - - public int getTotalCompletion() { - return completions.size(); - } - - public JsonArray getJsonCompletions() { - JsonArray completionsJSON = new JsonArray(); - for (Completion completion : completions) { - JsonMap completionJSON = new JsonMap(); - completionJSON.set("puzzleName", completion.getPuzzleName()); - completionJSON.set("tries", completion.getTries()); - completionJSON.set("score", completion.getScore()); - completionsJSON.add(completionJSON); - } - return completionsJSON; - } - - public int getTotalTries() { - int totalTries = 0; - for (Completion c: completions) { - totalTries = totalTries + c.getTries(); - } - return totalTries; - } - - public Set getBadges() { - return badges; - } - - public JsonArray getJsonBadges() { - if (badges == null) - return null; - JsonArray badgesJSON = new JsonArray(); - for (Badge badge : badges) { - JsonMap badgeJSON = new JsonMap(); - badgeJSON.set("name", badge.getName()); - byte[] logo = badge.getLogo(); - if (logo != null) - badgeJSON.set("logo", Base64.getEncoder().encodeToString(logo)); - badgeJSON.set("level", badge.getLevel()); - badgesJSON.add(badgeJSON); - } - return badgesJSON; - } - - public void addBadge(Badge newBadge) { - if (newBadge != null) { - if (badges == null) - badges = new HashSet(); - badges.add(newBadge); - } - } - - @Override - public int compareTo(Player other) { - if (this == other) - return 0; - if (other == null) - return -1; - int compare = Integer.compare(other.getTotalScore(), getTotalScore()); - if (compare == 0) { - compare = Integer.compare(other.getTotalCompletion(), getTotalCompletion()); - if (compare == 0) { - compare = Integer.compare(getTotalTries(), other.getTotalTries()); - if (compare == 0) - compare = other.getPseudo().compareTo(pseudo); - } - } - - return compare; - } - - @Override - public int hashCode(){ - return Objects.hash(email, pseudo); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Player other = (Player) obj; - return Objects.equals(email, other.email) && Objects.equals(pseudo, other.pseudo); - } -} diff --git a/src/dev/peerat/backend/model/Puzzle.java b/src/dev/peerat/backend/model/Puzzle.java index 453a18f..7a1a6ef 100644 --- a/src/dev/peerat/backend/model/Puzzle.java +++ b/src/dev/peerat/backend/model/Puzzle.java @@ -1,109 +1,30 @@ package dev.peerat.backend.model; -import java.sql.Timestamp; import java.time.LocalDateTime; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import dev.peerat.framework.utils.json.JsonArray; -import dev.peerat.framework.utils.json.JsonMap; +import dev.peerat.mapping.Treasure; -public class Puzzle { +@Treasure +public class Puzzle{ - private int id; - private String name; - private String content; - private byte[] soluce; - private String verify; - private int scoreMax; - private Set tags; - private int depend; - private Timestamp startDate; - - public Puzzle(int id, String name, String content, byte[] soluce, String verify, int scoreMax, String tags, - int depend, Timestamp startDate) { - this.id = id; - this.name = name; - this.content = content; - this.soluce = soluce; - this.verify = verify; - this.scoreMax = scoreMax; - setTags(tags); - this.depend = depend; - this.startDate = startDate; - } - - public int getId() { - return id; - } - - public String getName() { - return name; - } - - public String getContent() { - return content; - } - - public byte[] getSoluce() { - return this.soluce; - } - - public int getScoreMax() { - return this.scoreMax; - } - - public Set getTags() { - return this.tags; - } - - /** - * DO NOT EVER EVER SHOW TO MISTER LUDWIG XD - * - * @return DEATH - */ - public JsonArray getJsonTags() { - if (tags == null) - return null; - JsonArray tagsJSON = new JsonArray(); - for (String tag : tags) { - JsonMap tagJSON = new JsonMap(); - tagJSON.set("name", tag); - tagsJSON.add(tagJSON); - } - return tagsJSON; - } - - public void setTags(String tags) { - if (tags == null || tags.isEmpty()) - this.tags = null; - else - this.tags = new HashSet(Arrays.asList(tags.split(","))); - } - - public int getDepend() { - return this.depend; + private int participantCount; + private LocalDateTime start; + private LocalDateTime end; + private Chapter chapter; + + public int getParticipantCount(){ + return this.participantCount; } - public boolean hasStarted(){ - LocalDateTime now = LocalDateTime.now(); - boolean show = true; - if(startDate != null) show &= now.isAfter(startDate.toLocalDateTime()); - return show; + public LocalDateTime getStartTime(){ + return this.start; } - - @Override - public boolean equals(Object object) { - if (this == object) - return true; - if (!(object instanceof Puzzle)) - return false; - return this.id == (((Puzzle) object).id); + + public LocalDateTime getEndTime(){ + return this.end; } - - @Override - public int hashCode() { - return id; + + public Chapter getChapter(){ + return this.chapter; } } diff --git a/src/dev/peerat/backend/model/School.java b/src/dev/peerat/backend/model/School.java new file mode 100644 index 0000000..4868255 --- /dev/null +++ b/src/dev/peerat/backend/model/School.java @@ -0,0 +1,17 @@ +package dev.peerat.backend.model; + +import dev.peerat.mapping.Treasure; + +@Treasure +public class School{ + + private String name; + + public School(String name){ + this.name = name; + } + + public String getName(){ + return this.name; + } +} diff --git a/src/dev/peerat/backend/model/Solution.java b/src/dev/peerat/backend/model/Solution.java new file mode 100644 index 0000000..abede76 --- /dev/null +++ b/src/dev/peerat/backend/model/Solution.java @@ -0,0 +1,39 @@ +package dev.peerat.backend.model; + +import dev.peerat.mapping.Treasure; + +@Treasure +public class Solution{ + + private Puzzle puzzle; + private byte[] answer; + private String verify; + private int scoreMax; + private int scoreMaxTime; + private int ScoreMaxRespect; + + public Puzzle getPuzzle(){ + return this.puzzle; + } + + public byte[] getAnswer(){ + return answer; + } + + public String getVerify(){ + return verify; + } + + public int getScoreMax(){ + return scoreMax; + } + + public int getScoreMaxTime(){ + return scoreMaxTime; + } + + public int getScoreMaxRespect(){ + return ScoreMaxRespect; + } + +} diff --git a/src/dev/peerat/backend/repository/DatabaseQuery.java b/src/dev/peerat/backend/repository/DatabaseQuery.java deleted file mode 100644 index 9448907..0000000 --- a/src/dev/peerat/backend/repository/DatabaseQuery.java +++ /dev/null @@ -1,265 +0,0 @@ -package dev.peerat.backend.repository; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; - -public enum DatabaseQuery { - // PUZZLES - SPECIFIC_PUZZLE_QUERY( - "SELECT p.*, np.origin, GROUP_CONCAT(t.name) AS tags FROM puzzles p LEFT JOIN nextPart np ON p.id_puzzle = np.next LEFT JOIN containsTags ct ON ct.fk_puzzle = p.id_puzzle LEFT JOIN tags t ON t.id_tag = ct.fk_tag WHERE p.id_puzzle = ? 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"), - - // CHAPTERS - SPECIFIC_CHAPTER_QUERY("SELECT * FROM chapters WHERE id_chapter = ?"), - CHAPTER_FROM_PUZZLE("SELECT c.*\r\n" - + "FROM chapters c\r\n" - + "JOIN puzzles p ON p.fk_chapter = c.id_chapter\r\n" - + "WHERE p.id_puzzle = ?"), - ALL_CHAPTERS_QUERY("SELECT * FROM chapters WHERE id_chapter > 0"), - - // GROUPS - ALL_GROUPS("SELECT * FROM groups"), - GET_GROUP_FOR_PLAYER("SELECT g.* FROM groups g JOIN containsGroups cg ON cg.fk_group = g.id_group WHERE cg.fk_player = ? AND g.fk_chapter = ?"), // AND g.fk_puzzle = ? - GET_GROUP_ID_BY_DATA("SELECT id_group FROM groups WHERE name = ? AND (fk_chapter = ?)"), // OR fk_puzzle = ? - INSERT_GROUP("INSERT INTO groups (name, fk_chapter) VALUES (?,?)"), - INSERT_PLAYER_IN_GROUP("INSERT INTO containsGroups (fk_player, fk_group) VALUES (?,?)"), - LEAVE_GROUP("DELETE FROM containsGroups WHERE fk_player = ? AND fk_group = ?"), - - // LEADERBOARD - 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 LEFT JOIN puzzles puzz on puzz.id_puzzle = c.fk_puzzle LEFT JOIN chapters chap on chap.id_chapter = puzz.fk_chapter WHERE chap.id_chapter > 1 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"), - ALL_GROUP_FOR_CHAPTER_LEADERBOARD( - "SELECT g.*, pl.pseudo, co.score, co.tries 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 WHERE cg.fk_player IS NOT NULL AND 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);"), - - // REGISTER - 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 (?, ?, ?, ?, ?, ?, ?)"), - REGISTER_PLAYER_IN_EXISTING_GROUP( - "INSERT INTO containsGroups (fk_player, fk_group) VALUES (?, (SELECT id_group FROM groups WHERE name = ?));"), - - // LOGIN - CHECK_PASSWORD("SELECT id_player, passwd FROM players WHERE pseudo=?"), - - // COMPLETIONS - GET_COMPLETION( - "SELECT * FROM completions WHERE fk_puzzle = ? AND fk_player = ?"), - GET_COMPLETION_GROUP("SELECT c.*\r\n" - + "FROM completions c\r\n" - + "JOIN containsGroups cG on c.fk_player = cG.fk_player\r\n" - + "JOIN containsGroups cGs on cGs.fk_group = cG.fk_group\r\n" - + "JOIN groups g on cG.fk_group = g.id_group\r\n" - + "JOIN puzzles p on p.id_puzzle = c.fk_puzzle\r\n" - + "JOIN chapters ch on ch.id_chapter = p.fk_chapter\r\n" - + "WHERE ch.id_chapter < 2 AND cGs.fk_player = ? AND p.id_puzzle = ?"), - INSERT_COMPLETION( - "INSERT INTO completions (fk_puzzle, fk_player, tries, code, fileName, score) values (?, ?, ?, ?, ?, ?)"), - UPDATE_COMPLETION( - "UPDATE completions SET tries = ?, score = ?, fk_player = ? WHERE fk_puzzle = ? AND fk_player = ?"), - SCORE("SELECT score FROM completions WHERE fk_player = ? AND fk_puzzle = ?"), - SCORE_GROUP("SELECT c.score\r\n" - + "FROM completions c\r\n" - + "JOIN containsGroups cG on c.fk_player = cG.fk_player\r\n" - + "JOIN containsGroups cGs on cGs.fk_group = cG.fk_group\r\n" - + "JOIN groups g on cG.fk_group = g.id_group\r\n" - + "JOIN puzzles p on p.id_puzzle = c.fk_puzzle\r\n" - + "JOIN chapters ch on ch.id_chapter = p.fk_chapter\r\n" - + "WHERE ch.id_chapter < 2 AND cGs.fk_player = ? AND p.id_puzzle = ?"), - - // PLAYERS - GET_PLAYER_SIMPLE("SELECT pseudo, email, firstname, lastname, description FROM players WHERE id_player = ?"), - GET_PLAYER_EMAIL("SELECT id_player FROM players WHERE email = ?"), - GET_PLAYER_PSEUDO("SELECT * FROM players WHERE pseudo = ?"), - GET_PLAYER_DETAILS("SELECT p.*, g.*\r\n" - + "FROM players p\r\n" - + "LEFT OUTER JOIN containsGroups cg ON p.id_player = cg.fk_player\r\n" - + "LEFT OUTER JOIN groups g ON cg.fk_group = g.id_group\r\n" - + "LEFT OUTER JOIN completions c on p.id_player = c.fk_player\r\n" - + "WHERE "), - GET_PLAYER_DETAILS_BY_ID(GET_PLAYER_DETAILS, " p.id_player = ? GROUP BY g.name ORDER BY g.fk_chapter, g.fk_puzzle;"), - GET_PLAYER_DETAILS_BY_PSEUDO(GET_PLAYER_DETAILS, "p.pseudo = ? GROUP BY g.name ORDER BY g.fk_chapter, g.fk_puzzle;"), - GET_PLAYER_COMPLETIONS("select c.*, p.name from completions c left join puzzles p on c.fk_puzzle = p.id_puzzle where fk_player = ?;"), - GET_PLAYER_RANK("SELECT * FROM (SELECT fk_player, RANK() OVER(ORDER BY SUM(score) DESC) rank FROM completions c LEFT JOIN puzzles puzz on puzz.id_puzzle = c.fk_puzzle LEFT JOIN chapters chap on chap.id_chapter = puzz.fk_chapter LEFT JOIN players p ON p.id_player = c.fk_player WHERE chap.id_chapter > 1 GROUP BY fk_player ORDER BY rank) AS ranks WHERE ranks.fk_player = ?;"), - UPDATE_PLAYER_INFO("UPDATE players SET pseudo = ?, email = ?, firstname = ?, lastname = ? WHERE id_player = ?"), - UPDATE_PLAYER_PASSWORD("UPDATE players SET passwd = ? WHERE id_player = ?"), - - // BADGES - GET_BADGE("SELECT * FROM badges WHERE id_badge = ?"), GET_BADGES_OF_PLAYER( - "SELECT * FROM badges b LEFT JOIN containsBadges cb ON cb.fk_badge = b.id_badge WHERE cb.fk_player = ?"), - - //TRIGGER - FIRST_TRY("CREATE OR REPLACE TRIGGER FirstTry\r\n" - + "AFTER INSERT\r\n" - + " ON completions FOR EACH ROW\r\n" - + "BEGIN\r\n" - + " DECLARE badge INT;\r\n" - + " DECLARE contain INT;\r\n" - + " \r\n" - + " SELECT id_badge\r\n" - + " INTO @badge\r\n" - + " FROM badges\r\n" - + " WHERE name = 'FirstTry';\r\n" - + " \r\n" - + " IF @badge is not null THEN\r\n" - + " \r\n" - + " SELECT count(*)\r\n" - + " INTO @contain\r\n" - + " FROM containsBadges\r\n" - + " WHERE fk_badge = @badge AND fk_player = NEW.fk_player;\r\n" - + " \r\n" - + " IF (@contain = 0) THEN\r\n" - + " INSERT INTO containsBadges(fk_player, fk_badge) VALUES (NEW.fk_player, @badge);\r\n" - + " END IF;\r\n" - + " END IF;\r\n" - + "END;"), - EventParticipation("CREATE OR REPLACE TRIGGER EventParticipation\r\n" - + "AFTER INSERT\r\n" - + " ON completions FOR EACH ROW\r\n" - + "BEGIN\r\n" - + " DECLARE badge INT;\r\n" - + " DECLARE endDate datetime;\r\n" - + " DECLARE player INT;\r\n" - + " DECLARE contain INT;\r\n" - + "\r\n" - + " SELECT id_badge\r\n" - + " INTO badge\r\n" - + " FROM badges\r\n" - + " WHERE name = 'EventParticipation';\r\n" - + "\r\n" - + " IF @badge is not null THEN\r\n" - + "\r\n" - + " SELECT c.end_date, i.fk_player\r\n" - + " INTO endDate, player\r\n" - + " FROM inserted i\r\n" - + " JOIN puzzles p ON i.fk_puzzle = p.id_puzzle\r\n" - + " JOIN chapters c on p.fk_chapter = c.id_chapter;\r\n" - + "\r\n" - + " IF @endDate is not null THEN\r\n" - + "\r\n" - + " SELECT count(*)\r\n" - + " INTO contain\r\n" - + " FROM containsBadges\r\n" - + " WHERE fk_badge = badge AND fk_player = player;\r\n" - + "\r\n" - + " IF (@contain = 0) THEN\r\n" - + " INSERT INTO containsBadges(fk_player, fk_badge) VALUES (@player, @badge);\r\n" - + " END IF;\r\n" - + " END IF;\r\n" - + " END IF;\r\n" - + "END;"); - - private String request; - - DatabaseQuery(DatabaseQuery parent, String request) { - this.request = parent.request + request; - } - - DatabaseQuery(String request) { - this.request = request; - } - - public PreparedStatement prepare(Connection con) throws SQLException { - return con.prepareStatement(this.request); - } - - @Override - public String toString() { - return this.request; - } -} - - -/* - * - - SELECT p.*, scores.score, scores.completions, scores.tries, scores.rank, 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 OUTER JOIN containsGroups cg ON scores.fk_player = cg.fk_player - LEFT OUTER JOIN groups g ON cg.fk_group = g.id_group - WHERE p.id_player = scores.fk_player AND "), - - - * - */ - -/* TRIGGER PLACE - * - -CREATE OR REPLACE TRIGGER FirstTry -AFTER INSERT - ON completions FOR EACH ROW -BEGIN - DECLARE badge INT; - DECLARE contain INT; - - SELECT id_badge - INTO @badge - FROM badges - WHERE name = 'FirstTry'; - - IF @badge is not null THEN - - SELECT count(*) - INTO @contain - FROM containsBadges - WHERE fk_badge = @badge AND fk_player = NEW.fk_player; - - IF (@contain = 0) THEN - - IF (NEW.score >= 0 AND NEW.tries < 2) THEN - INSERT INTO containsBadges(fk_player, fk_badge) VALUES (NEW.fk_player, @badge); - END IF; - END IF; - END IF; -END; - - - -CREATE OR REPLACE TRIGGER EventParticipation -AFTER INSERT - ON completions FOR EACH ROW -BEGIN - DECLARE badge INT; - DECLARE endDate datetime; - DECLARE player INT; - DECLARE contain INT; - - SELECT id_badge - INTO badge - FROM badges - WHERE name = 'EventParticipation'; - - IF @badge is not null THEN - - SELECT c.end_date, i.fk_player - INTO endDate, player - FROM inserted i - JOIN puzzles p ON i.fk_puzzle = p.id_puzzle - JOIN chapters c on p.fk_chapter = c.id_chapter; - - IF @endDate is not null THEN - - SELECT count(*) - INTO contain - FROM containsBadges - WHERE fk_badge = badge AND fk_player = player; - - IF (@contain = 0) THEN - INSERT INTO containsBadges(fk_player, fk_badge) VALUES (@player, @badge); - END IF; - END IF; - END IF; -END; - - - * - */ \ No newline at end of file diff --git a/src/dev/peerat/backend/repository/DatabaseRepository.java b/src/dev/peerat/backend/repository/DatabaseRepository.java deleted file mode 100644 index 595c980..0000000 --- a/src/dev/peerat/backend/repository/DatabaseRepository.java +++ /dev/null @@ -1,695 +0,0 @@ -package dev.peerat.backend.repository; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -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.Password; - -import dev.peerat.backend.Configuration; -import dev.peerat.backend.model.Badge; -import dev.peerat.backend.model.Chapter; -import dev.peerat.backend.model.Completion; -import dev.peerat.backend.model.Group; -import dev.peerat.backend.model.PeerAtUser; -import dev.peerat.backend.model.Player; -import dev.peerat.backend.model.Puzzle; - -public class DatabaseRepository { - - private Connection con; - private Configuration config; - - public DatabaseRepository(Configuration config) { - this.config = config; - } - - private void ensureConnection() throws SQLException { - if (con == null || (!con.isValid(5))) { - this.con = DriverManager.getConnection( - "jdbc:mysql://" + config.getDbHost() + ":" + config.getDbPort() + "/" + config.getDbDatabase() + "", - config.getDbUser(), config.getDbPassword()); - } - } - - private Puzzle makePuzzle(ResultSet puzzleResult) throws SQLException { - return new Puzzle(puzzleResult.getInt("id_puzzle"), puzzleResult.getString("name"), - puzzleResult.getString("content"), puzzleResult.getBytes("soluce"), puzzleResult.getString("verify"), - puzzleResult.getInt("score_max"), puzzleResult.getString("tags"), - hasColumn(puzzleResult, "origin") ? puzzleResult.getInt("origin") : -1, - puzzleResult.getTimestamp("start_date")); - } - - private Chapter makeChapter(ResultSet chapterResult) throws SQLException { - return new Chapter(chapterResult.getInt("id_chapter"), chapterResult.getString("name"), - chapterResult.getTimestamp("start_date"), chapterResult.getTimestamp("end_date")); - } - - private Completion makeCompletion(ResultSet completionResult) throws SQLException { - String fileName = null; - if (hasColumn(completionResult, "fileName")) - fileName = completionResult.getString("fileName"); - String puzzleName = null; - if (hasColumn(completionResult, "name")) - puzzleName = completionResult.getString("name"); - - return new Completion(completionResult.getInt("fk_player"), completionResult.getInt("fk_puzzle"), completionResult.getInt("tries"), - fileName, completionResult.getInt("score"), puzzleName); - } - - private Player makePlayer(ResultSet playerResult, int id) throws SQLException { - Player p = new Player(playerResult.getString("pseudo"), playerResult.getString("email"), - playerResult.getString("firstName"), playerResult.getString("lastName")); - if (hasColumn(playerResult, "avatar")) { - p.setAvatar(playerResult.getBytes("avatar")); - } - if (hasColumn(playerResult, "score")) { - p.addCompletion(new Completion(playerResult.getInt("tries"), playerResult.getInt("score"))); - for (int ct = 1; ct < playerResult.getInt("completions"); ct++) - { // TODO refactor for V3 - p.addCompletion(new Completion(0, 0)); - } - } - if (hasColumn(playerResult, "name")) { - // Manage groups - String groupName = playerResult.getString("name"); - if (groupName != null) { - p.addGroup(makeGroup(playerResult)); - } - } - - // ADD rank - PreparedStatement completionsStmt = DatabaseQuery.GET_PLAYER_RANK.prepare(con); - completionsStmt.setInt(1, id); - ResultSet result = completionsStmt.executeQuery(); - while (result.next()) { - p.setRank(result.getInt("rank")); - } - return p; - } - - private Group makeGroup(ResultSet result) throws SQLException { - 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 { - return new Badge(rs.getString("name"), rs.getBytes("logo"), rs.getInt("level")); - } - - private boolean hasColumn(ResultSet rs, String columnName) throws SQLException { - // 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; - } - return false; - } - - private List getPuzzlesInChapter(int id) throws SQLException { - List puzzles = new ArrayList<>(); - ensureConnection(); - PreparedStatement puzzleStmt = DatabaseQuery.PUZZLES_IN_CHAPTER_QUERY.prepare(this.con); - puzzleStmt.setInt(1, id); - ResultSet puzzleResult = puzzleStmt.executeQuery(); - while (puzzleResult.next()) { - puzzles.add(makePuzzle(puzzleResult)); - } - return puzzles; - } - - /** - * Get a specific puzzle - * - * @param id The id of the puzzle - * @return The puzzle or null if an error occurred - */ - public Puzzle getPuzzle(int id) { - try { - ensureConnection(); - PreparedStatement puzzleStmt = DatabaseQuery.SPECIFIC_PUZZLE_QUERY.prepare(this.con); - puzzleStmt.setInt(1, id); - ResultSet puzzleResult = puzzleStmt.executeQuery(); - if (puzzleResult.next()) { - return makePuzzle(puzzleResult); - } - } catch (SQLException e) { - e.printStackTrace(); - } - return null; - } - - public int getScore(int user, int puzzle) { - try { - ensureConnection(); - PreparedStatement stmt = DatabaseQuery.SCORE_GROUP.prepare(this.con); - stmt.setInt(1, user); - stmt.setInt(2, puzzle); - ResultSet result = stmt.executeQuery(); - if (result.next()) - return result.getInt("score"); - - stmt = DatabaseQuery.SCORE.prepare(this.con); - stmt.setInt(1, user); - stmt.setInt(2, puzzle); - - result = stmt.executeQuery(); - if (result.next()) - return result.getInt("score"); - } catch (Exception e) { - e.printStackTrace(); - } - return -1; - } - - public Completion getCompletionGroup(int user, int puzzle) { - try { - PreparedStatement stmt = DatabaseQuery.GET_COMPLETION_GROUP.prepare(this.con); - stmt.setInt(1, user); - stmt.setInt(2, puzzle); - ResultSet result = stmt.executeQuery(); - if (result.next()) - return makeCompletion(result); - } catch (SQLException e) { - e.printStackTrace(); - } - return getCompletion(user, puzzle); - } - - public Completion getCompletion(int playerId, int puzzleId) { - try { - PreparedStatement completionsStmt = DatabaseQuery.GET_COMPLETION.prepare(this.con); - completionsStmt.setInt(1, puzzleId); - completionsStmt.setInt(2, playerId); - ResultSet result = completionsStmt.executeQuery(); - if (result.next()) { - return makeCompletion(result); - } - } catch (SQLException e) { - e.printStackTrace(); - } - return null; - } - - public Player getPlayer(int idPlayer) { - try { - PreparedStatement completionsStmt = DatabaseQuery.GET_PLAYER_SIMPLE.prepare(this.con); - completionsStmt.setInt(1, idPlayer); - ResultSet result = completionsStmt.executeQuery(); - if (result.next()) { - return makePlayer(result, idPlayer); - } - } catch (SQLException e) { - e.printStackTrace(); - } - return null; - } - - public int getPlayerId(String email){ - try { - PreparedStatement completionsStmt = DatabaseQuery.GET_PLAYER_EMAIL.prepare(this.con); - completionsStmt.setString(1, email); - ResultSet result = completionsStmt.executeQuery(); - if (result.next()) { - return result.getInt("id_player"); - } - } catch (SQLException e) { - e.printStackTrace(); - } - return -1; - } - - public boolean updatePseudo(int id, Player player, String pseudo){ - try{ - PreparedStatement statment = DatabaseQuery.GET_PLAYER_PSEUDO.prepare(this.con); - statment.setString(1, pseudo); - ResultSet result = statment.executeQuery(); - if(result.next()) return false; - statment = DatabaseQuery.UPDATE_PLAYER_INFO.prepare(this.con); - statment.setString(1, pseudo); - statment.setString(2, player.getEmail()); - statment.setString(3, player.getFirstname()); - statment.setString(4, player.getLastname()); - statment.setInt(5, id); - return statment.executeUpdate() > 0; - }catch(Exception e){ - e.printStackTrace(); - } - return false; - } - - public void updateProfile(int id, Player player, String lastname, String firstname){ - try{ - PreparedStatement statment = DatabaseQuery.UPDATE_PLAYER_INFO.prepare(this.con); - statment.setString(1, player.getPseudo()); - statment.setString(2, player.getEmail()); - statment.setString(3, firstname); - statment.setString(4, lastname); - statment.setInt(5, id); - statment.executeUpdate(); - }catch(Exception e){ - e.printStackTrace(); - } - } - - public void updatePassword(int id, String password){ - try{ - PreparedStatement statment = DatabaseQuery.UPDATE_PLAYER_PASSWORD.prepare(this.con); - statment.setString(1, Password.hash(password).withArgon2().getResult()); - statment.setInt(2, id); - statment.executeUpdate(); - }catch(Exception e){ - e.printStackTrace(); - } - } - - public Player getPlayerDetails(int idPlayer) { - return getPlayerDetails(idPlayer, null); - } - - public Player getPlayerDetails(String pseudoPlayer) { - return getPlayerDetails(-1, pseudoPlayer); - } - - private Player getPlayerDetails(int id, String pseudo) { - try { - ensureConnection(); - PreparedStatement completionsStmt; - if (pseudo != null) { - completionsStmt = DatabaseQuery.GET_PLAYER_DETAILS_BY_PSEUDO.prepare(this.con); - completionsStmt.setString(1, pseudo); - } else { - completionsStmt = DatabaseQuery.GET_PLAYER_DETAILS_BY_ID.prepare(this.con); - completionsStmt.setInt(1, id); - } - ResultSet result = completionsStmt.executeQuery(); - Player player = null; - while (result.next()) { - if (player == null) { - id = result.getInt("id_player"); - player = makePlayer(result, id); - completionsStmt = DatabaseQuery.GET_BADGES_OF_PLAYER.prepare(this.con); - completionsStmt.setInt(1, id); - ResultSet resultBadges = completionsStmt.executeQuery(); - while (resultBadges.next()) { - player.addBadge(makeBadge(resultBadges)); - } - } else { - player.addGroup(makeGroup(result)); - } - } - // ADD completions - completionsStmt = DatabaseQuery.GET_PLAYER_COMPLETIONS.prepare(con); - completionsStmt.setInt(1, id); - result = completionsStmt.executeQuery(); - while (result.next()) { - player.addCompletion(makeCompletion(result)); - } - - return player; - } catch (SQLException e) { - e.printStackTrace(); - } - return null; - } - - public SortedSet getAllPlayerForLeaderboard() { - try { - ensureConnection(); - PreparedStatement playersStmt = DatabaseQuery.ALL_PLAYERS_FOR_LEADERBOARD.prepare(this.con); - ResultSet result = playersStmt.executeQuery(); - ArrayList players = new ArrayList(); - Player tmpPlayer; - while (result.next()) { - tmpPlayer = makePlayer(result, result.getInt("id_player")); - if (!players.contains(tmpPlayer)) { - players.add(tmpPlayer); - } else { - players.get(players.indexOf(tmpPlayer)).addGroup(makeGroup(result)); - } - } - return new TreeSet(players); - } catch (SQLException e) { - e.printStackTrace(); - } - return null; - } - - public SortedSet 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 groups = new ArrayList(); - 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(groups); - }catch(SQLException e){ - e.printStackTrace(); - } - return null; - } - - public Badge getBadge(int badgeId) { - try { - ensureConnection(); - PreparedStatement completionsStmt = DatabaseQuery.GET_BADGE.prepare(this.con); - completionsStmt.setInt(1, badgeId); - ResultSet result = completionsStmt.executeQuery(); - if (result.next()) { - return makeBadge(result); - } - } catch (SQLException e) { - e.printStackTrace(); - } - return null; - } - - /** - * Get a specific chapter - * - * @param id The id of the chapter - * @return The chapter or null if an error occurred - */ - public Chapter getChapter(int id) { - try { - ensureConnection(); - PreparedStatement chapterStmt = DatabaseQuery.SPECIFIC_CHAPTER_QUERY.prepare(this.con); - chapterStmt.setInt(1, id); - ResultSet chapterResult = chapterStmt.executeQuery(); - if (chapterResult.next()) { - Chapter chapter = makeChapter(chapterResult); - List puzzles = getPuzzlesInChapter(id); - chapter.setPuzzles(puzzles); - return chapter; - } - } catch (SQLException e) { - e.printStackTrace(); - } - return null; - } - - public Chapter getChapter(Puzzle puzzle){ - try { - ensureConnection(); - PreparedStatement chapterStmt = DatabaseQuery.CHAPTER_FROM_PUZZLE.prepare(this.con); - chapterStmt.setInt(1, puzzle.getId()); - ResultSet chapterResult = chapterStmt.executeQuery(); - if (chapterResult.next()) { - Chapter chapter = makeChapter(chapterResult); - List puzzles = getPuzzlesInChapter(chapter.getId()); - chapter.setPuzzles(puzzles); - return chapter; - } - } catch (SQLException e) { - e.printStackTrace(); - } - return null; - } - - /** - * Get all chapters in the database - * - * @return List of all chapters or null if an error occurred - */ - public List getAllChapters() { - try { - List chapterList = new ArrayList<>(); - ensureConnection(); - PreparedStatement chapterStmt = DatabaseQuery.ALL_CHAPTERS_QUERY.prepare(this.con); - ResultSet chapterResult = chapterStmt.executeQuery(); - while (chapterResult.next()) { - Chapter chapter = makeChapter(chapterResult); - chapter.setPuzzles(getPuzzlesInChapter(chapter.getId())); - chapterList.add(chapter); - } - return chapterList; - } catch (SQLException e) { - e.printStackTrace(); - } - return null; - } - - public List getAllGroups() { - try { - ensureConnection(); - List list = new ArrayList<>(); - PreparedStatement stmt = DatabaseQuery.ALL_GROUPS.prepare(this.con); - ResultSet groupResult = stmt.executeQuery(); - while (groupResult.next()) - list.add(makeGroup(groupResult)); - return list; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - /** - * Check if a pseudo is available - * - * @param pseudo The pseudo to check - * @return True if the pseudo is available, false if it's already taken - */ - public boolean checkPseudoAvailability(String pseudo) { - return checkAvailability(pseudo, DatabaseQuery.CHECK_PSEUDO_AVAILABLE_QUERY.toString()); - } - - /** - * Check if an email is available - * - * @param email The email to check - * @return True if the email is available, false if it's already taken - */ - public boolean checkEmailAvailability(String email) { - return checkAvailability(email, DatabaseQuery.CHECK_EMAIL_AVAILABLE_QUERY.toString()); - } - - private boolean checkAvailability(String queriedString, String correspondingQuery) { - try { - ensureConnection(); - PreparedStatement statement = con.prepareStatement(correspondingQuery); - statement.setString(1, queriedString); - ResultSet result = statement.executeQuery(); - return !result.next(); - } catch (SQLException e) { - e.printStackTrace(); - } - return false; - } - - /** - * Register a new user - * - * @param pseudo The pseudo of the user - * @param email The email of the user - * @param password The password of the user - * @param firstname The firstname of the user - * @param lastname The lastname of the user - * @param description The description of the user - * @param sgroup The group of the user - * @param avatar The avatar of the user - * @return True if the user was registered, false if an error occurred - */ - public int register(String pseudo, String email, String password, String firstname, String lastname, - String description, String sgroup, String avatar) { - try { - ensureConnection(); - con.setAutoCommit(false); - try (PreparedStatement playerStatement = con.prepareStatement(DatabaseQuery.REGISTER_QUERY.toString(), - Statement.RETURN_GENERATED_KEYS)) { - playerStatement.setString(1, pseudo); - playerStatement.setString(2, email); - playerStatement.setString(3, Password.hash(password).withArgon2().getResult()); - playerStatement.setString(4, firstname); - playerStatement.setString(5, lastname); - playerStatement.setString(6, description); - playerStatement.setString(7, avatar); - if (playerStatement.executeUpdate() == 1) { - ResultSet inserted = playerStatement.getGeneratedKeys(); - if (inserted.next()) { - int newPlayerId = inserted.getInt(1); - if (!sgroup.isEmpty()) { - try (PreparedStatement containsGroupsStatement = con - .prepareStatement(DatabaseQuery.REGISTER_PLAYER_IN_EXISTING_GROUP.toString())) { - containsGroupsStatement.setInt(1, newPlayerId); - containsGroupsStatement.setString(2, sgroup); - containsGroupsStatement.executeUpdate(); - } - } - con.commit(); - con.setAutoCommit(true); - return newPlayerId; - } - } - } catch (SQLException e) { - con.rollback(); - con.setAutoCommit(true); - e.printStackTrace(); - } - } catch (SQLException e) { - e.printStackTrace(); - } - return -1; - } - - /** - * Login a user - * - * @param username The username of the user - * @param password The password of the user - * @return id the id of the user, -1 if not login successefuly - */ - public int login(String username, String password) { - try { - ensureConnection(); - PreparedStatement statement = con.prepareStatement(DatabaseQuery.CHECK_PASSWORD.toString()); - DatabaseQuery.PUZZLES_IN_CHAPTER_QUERY.prepare(this.con); - statement.setString(1, username); - ResultSet result = statement.executeQuery(); - if (result.next()) { - String hashedPassword = result.getString("passwd"); - if (Password.check(password, hashedPassword).withArgon2()) - return result.getInt("id_player"); - } - } catch (SQLException e) { - } - return -1; - } - - public Completion insertOrUpdatePuzzleResponse(int puzzleId, int userId, String fileName, byte[] code, - byte[] response, Puzzle currentPuzzle){ - try { - ensureConnection(); - Completion completion = getCompletionGroup(userId, puzzleId); - if (completion == null){ - System.out.println("Completion is null"); - completion = new Completion(userId, puzzleId, fileName, code, response, currentPuzzle); - insertCompletion(completion); - } else { - System.out.println(completion); - completion.addTry(currentPuzzle, response, getChapter(currentPuzzle).getId()); - int lastUserId = completion.getPlayerId(); - completion.updatePlayer(userId); - updateCompletion(completion, lastUserId); - } - return completion; - } catch (SQLException e) { - e.printStackTrace(); - } - return null; - } - - private void insertCompletion(Completion newCompletion) throws SQLException { - PreparedStatement statement = DatabaseQuery.INSERT_COMPLETION.prepare(this.con); - statement.setInt(1, newCompletion.getPuzzleId()); - statement.setInt(2, newCompletion.getPlayerId()); - statement.setInt(3, newCompletion.getTries()); - statement.setBytes(4, newCompletion.getCode()); - statement.setString(5, newCompletion.getFileName()); - statement.setInt(6, newCompletion.getScore()); - statement.executeUpdate(); - } - - public boolean insertGroup(Group group, PeerAtUser creator) throws SQLException { - Integer groupId = getGroupId(group); - if (groupId == null) - ensureConnection(); - PreparedStatement statement = DatabaseQuery.INSERT_GROUP.prepare(this.con); - statement.setString(1, group.getName()); - statement.setObject(2, group.getLinkToChapter()); -// statement.setObject(3, group.getLinkToPuzzle()); - if (statement.executeUpdate() >= 0) - return insertUserInGroup(group, creator); - return false; - } - - public Group getPlayerGroup(int user, Integer chapter) throws SQLException { - ensureConnection(); - PreparedStatement stmt = DatabaseQuery.GET_GROUP_FOR_PLAYER.prepare(this.con); - stmt.setInt(1, user); - stmt.setObject(2, chapter); -// stmt.setObject(3, puzzle); - - ResultSet result = stmt.executeQuery(); - if (result.next()) - return makeGroup(result); - return null; - } - - public Integer getGroupId(Group group) throws SQLException { - ensureConnection(); - PreparedStatement stmt = DatabaseQuery.GET_GROUP_ID_BY_DATA.prepare(this.con); - stmt.setString(1, group.getName()); - stmt.setObject(2, group.getLinkToChapter()); -// stmt.setObject(3, group.getLinkToPuzzle()); - - ResultSet result = stmt.executeQuery(); - if (result.next()) - return result.getInt("id_group"); - return null; - } - - public boolean insertUserInGroup(Group group, PeerAtUser user) throws SQLException { - Integer id = getGroupId(group); - Group alreadyInGroup = getPlayerGroup(user.getId(), group.getLinkToChapter()); - if (id != null && alreadyInGroup == null) { - PreparedStatement stmt = DatabaseQuery.INSERT_PLAYER_IN_GROUP.prepare(this.con); - - stmt.setInt(1, user.getId()); - stmt.setInt(2, id); - - return stmt.executeUpdate() >= 0; - } - return false; - } - - public boolean leaveGroup(Group group, PeerAtUser user) throws SQLException { - Integer id = getGroupId(group); - if (id != null) { - PreparedStatement stmt = DatabaseQuery.LEAVE_GROUP.prepare(this.con); - - stmt.setInt(1, user.getId()); - stmt.setInt(2, id); - - return stmt.executeUpdate() >= 0; - } - return false; - } - - private void updateCompletion(Completion completionToUpdate, int user) throws SQLException{ - System.out.println("update "+completionToUpdate); - PreparedStatement statement = DatabaseQuery.UPDATE_COMPLETION.prepare(this.con); - statement.setInt(1, completionToUpdate.getTries()); - statement.setInt(2, completionToUpdate.getScore()); - statement.setInt(3, completionToUpdate.getPlayerId()); - statement.setInt(4, completionToUpdate.getPuzzleId()); - statement.setInt(5, user); - statement.executeUpdate(); - } -} \ No newline at end of file diff --git a/test/dev/peerat/backend/routes/StateTestCase.java b/test/dev/peerat/backend/routes/StateTestCase.java new file mode 100644 index 0000000..f983d8d --- /dev/null +++ b/test/dev/peerat/backend/routes/StateTestCase.java @@ -0,0 +1,93 @@ +package dev.peerat.backend.routes; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import dev.peerat.framework.RequestType; + +public class StateTestCase{ + + @Test + void main() throws Exception{ + String host = "127.0.0.1"; + int port = 80; + + File dir = new File("./route-test/"); + for(File cases : dir.listFiles()){ + if(!cases.isDirectory()) continue; + List responses = new ArrayList<>(); + File dbsetup = null; + for(File file : cases.listFiles()){ + if(file.getName().endsWith(".class")) dbsetup = file; else responses.add(file); + } +// Class clazz = new URLClassLoader(new URL[]{cases.toURI().toURL()}).loadClass(dbsetup.getAbsolutePath().substring(cases.getAbsolutePath().length()+1).replace("/", ".").replace("\\", ".").replace(".class", "")); + //setup database with clazz + for(File file : responses){ + StateCase state = new StateCase(file); + state.execute(host, port); + } + } + } + + public static class StateCase{ + + private String path; + private RequestType type; + private List headers; + private String payload; + + private int responseCode; + private List responseHeaders; + private String responsePayload; + + public StateCase(File file) throws Exception{ + BufferedReader reader = new BufferedReader(new FileReader(file)); + String line; + String payloadBuffer; + this.headers = new ArrayList<>(); + this.responseHeaders = new ArrayList<>(); + + this.path = reader.readLine(); + this.type = RequestType.valueOf(reader.readLine()); + + while(((line = reader.readLine() )!= null) && (!line.isEmpty())) headers.add(line); + + payloadBuffer = ""; + while(((line = reader.readLine() )!= null) && (!line.isEmpty())) payloadBuffer+=line; + this.payload = payloadBuffer; + + this.responseCode = Integer.parseInt(reader.readLine()); + while(((line = reader.readLine() )!= null) && (!line.isEmpty())) responseHeaders.add(line); + + payloadBuffer = ""; + while(((line = reader.readLine() )!= null) && (!line.isEmpty())) payloadBuffer+=line; + this.responsePayload = payloadBuffer; + } + + public void execute(String host, int port) throws Exception{ + Socket socket = new Socket(host, port); + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); + writer.write(this.type.toString()+" "+path+" HTTP/1.1\n"); + for(String header : headers) writer.write(header+"\n"); + writer.write("\n"); + if(payload != null) writer.write(payload+"\n"); + writer.flush(); + + BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); + String line; + while((line = reader.readLine()) != null) System.out.println(line); + + socket.close(); + } + } + +}