Adding base system for routes testing + start refractor for bd changing & incomming ORM

This commit is contained in:
jeffcheasey88 2024-02-28 22:32:24 +01:00
parent 8041ddb470
commit e0773afa0f
44 changed files with 285 additions and 1661 deletions

View file

@ -2,5 +2,6 @@ eclipse.preferences.version=1
org.eclipse.jdt.apt.aptEnabled=true org.eclipse.jdt.apt.aptEnabled=true
org.eclipse.jdt.apt.genSrcDir=.apt_generated org.eclipse.jdt.apt.genSrcDir=.apt_generated
org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests 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.processorOptions/treasure.source=%sourcepath%
org.eclipse.jdt.apt.reconcileEnabled=true org.eclipse.jdt.apt.reconcileEnabled=true

Binary file not shown.

View file

@ -7,7 +7,9 @@ import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.lang.reflect.Field; 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 { public class Configuration {
@ -57,18 +59,21 @@ public class Configuration {
return this; return this;
} }
public void load() throws Exception{ public Configuration load() throws Exception{
if(!this._file.exists()) return; if(!this._file.exists()) return this;
BufferedReader reader = new BufferedReader(new FileReader(this._file)); BufferedReader reader = new BufferedReader(new FileReader(this._file));
String line; String line;
while((line = reader.readLine()) != null){ while((line = reader.readLine()) != null){
String[] split = line.split("="); int index = line.indexOf('=');
Field field = getClass().getDeclaredField(split[0]); String key = line.substring(0, index);
String value = line.substring(index+1);
Field field = getClass().getDeclaredField(key);
if(field == null) continue; if(field == null) continue;
field.setAccessible(true); field.setAccessible(true);
injectValue(field, split[1]); injectValue(field, value);
} }
reader.close(); reader.close();
return this;
} }
private void injectValue(Field field, String value) throws IllegalAccessException { private void injectValue(Field field, String value) throws IllegalAccessException {
@ -131,25 +136,9 @@ public class Configuration {
public boolean isProduction(){ public boolean isProduction(){
return this.prod; return this.prod;
} }
public String getDbHost() { public Compass getCompass(){
return this.db_host; return new MySQLCompass(db_host, db_port, db_database, db_user, db_password);
}
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 String getSslKeystore() { public String getSslKeystore() {

View file

@ -6,33 +6,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; 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.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.Context;
import dev.peerat.framework.HttpReader; import dev.peerat.framework.HttpReader;
import dev.peerat.framework.HttpWriter; import dev.peerat.framework.HttpWriter;
@ -41,17 +15,19 @@ import dev.peerat.framework.RequestType;
import dev.peerat.framework.Response; import dev.peerat.framework.Response;
import dev.peerat.framework.Route; import dev.peerat.framework.Route;
import dev.peerat.framework.Router; 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; import dev.peerat.framework.Locker.Key;
public class Main{ public class Main{
public static void main(String[] args) throws Exception{ public static void main(String[] args) throws Exception{
Configuration config = new Configuration("config.txt") Configuration config = new Configuration("config.txt")
.addDefaultValue("users_files", "/tmp/users_files"); .addDefaultValue("users_files", "/tmp/users_files")
config.load(); .load();
Class.forName("com.mysql.cj.jdbc.Driver"); Ship ship = new Ship("mysql", config.getCompass(), new MySQLMap());
DatabaseRepository repo = new DatabaseRepository(config);
Router<PeerAtUser> router = new Router<PeerAtUser>() Router<PeerAtUser> router = new Router<PeerAtUser>()
.configureJwt( .configureJwt(
(builder) -> builder.setExpectedIssuer(config.getTokenIssuer()), (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 { public void exec(Matcher matcher, Context context, HttpReader reader, HttpWriter writer) throws Exception {
context.response(200); context.response(200);
} }
}); });
initRoutes(router, repo, config); initRoutes(router, config);
new Thread(new Runnable(){ new Thread(new Runnable(){
public void run(){ public void run(){
@ -95,7 +70,7 @@ public class Main{
locker.lock(key); locker.lock(key);
Context instance = locker.getValue(key); Context instance = locker.getValue(key);
if(instance == null) continue; if(instance == null) continue;
System.out.println("["+((instance.isLogged()) ? repo.getPlayer(instance.<PeerAtUser>getUser().getId()).getPseudo() : "?")+"] "+instance.getType()+" "+instance.getPath()+" -> "+instance.getResponseCode()); System.out.println("["+((instance.isLogged()) ? instance.<PeerAtUser>getUser().getPseudo() : "?")+"] "+instance.getType()+" "+instance.getPath()+" -> "+instance.getResponseCode());
} }
}catch(Exception e){ }catch(Exception e){
e.printStackTrace(); e.printStackTrace();
@ -108,43 +83,12 @@ public class Main{
router.listen(config.getTcpPort(), config.useSsl()); router.listen(config.getTcpPort(), config.useSsl());
} }
private static void initRoutes(Router<PeerAtUser> router, DatabaseRepository repo, Configuration config) throws Exception{ private static void initRoutes(Router<PeerAtUser> router, Configuration config) throws Exception{
Map<String, Integer> playersWaiting = new HashMap<>(); Map<String, Integer> playersWaiting = new HashMap<>();
Mail mail = config.getMail(); Mail mail = config.getMail();
Locker<Group> groupLock = new Locker<>(); Locker<Group> groupLock = new Locker<>();
Locker<Completion> leaderboard = new Locker<>(); Locker<Completion> 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 bot = new Bot(config, repo, groupLock);
// bot.start(); // bot.start();
} }

View file

@ -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;
}
}

View file

@ -1,66 +1,26 @@
package dev.peerat.backend.model; package dev.peerat.backend.model;
import java.sql.Timestamp;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
import dev.peerat.mapping.Treasure;
@Treasure
public class Chapter { public class Chapter {
private int id; private int participantCount;
private String name; private LocalDateTime start;
private List<Puzzle> puzzles; private LocalDateTime end;
private Timestamp startDate;
private Timestamp endDate; public int getParticipantCount(){
return this.participantCount;
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<Puzzle> getPuzzles() {
return puzzles;
}
public void setPuzzles(List<Puzzle> puzzles) {
this.puzzles = puzzles;
} }
public boolean hasStarted(){ public LocalDateTime getStartTime(){
LocalDateTime now = LocalDateTime.now(); return this.start;
boolean show = true;
if(startDate != null) show &= now.isAfter(startDate.toLocalDateTime());
return show;
} }
public Timestamp getStartDate() { public LocalDateTime getEndTime(){
return startDate; return this.end;
}
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;
} }
} }

View file

@ -1,103 +1,51 @@
package dev.peerat.backend.model; package dev.peerat.backend.model;
import java.util.Arrays; import dev.peerat.mapping.Treasure;
@Treasure
public class Completion{ public class Completion{
private int puzzleId;
private int playerId; private PeerAtUser player;
private int tries; private int tries;
private String fileName; private String file;
private byte[] code;
private int score; 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){ public Completion(){}
this(playerId, puzzleId, tries, score, fileName, null, null, null, null);
} public Completion(PeerAtUser player, String file){
public Completion(int playerId, int puzzleId, int tries, String fileName, int score, String puzzleName) { this.player = player;
this(playerId, puzzleId, tries, score, fileName, null, null, null, puzzleName); this.tries = 1;
} this.file = file;
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(int initTries, int initScore){ public PeerAtUser getPlayer(){
// For group leaderboard return this.player;
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 void updatePlayer(int playerId){ public int getTries(){
this.playerId = playerId; return this.tries;
}
public String getFileName() {
return fileName;
} }
public String getPuzzleName() { public String getFileName(){
return puzzleName; return this.file;
} }
public byte[] getCode() { public int getScore(){
return code; return this.score;
} }
public int getScore() { public int getScoreTime(){
return score; return this.scoreTime;
}
public int getScoreRespect(){
return this.scoreRespect;
}
public Solution getSolution(){
return this.solution;
} }
} }

View file

@ -1,152 +1,32 @@
package dev.peerat.backend.model; package dev.peerat.backend.model;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import org.jose4j.json.internal.json_simple.JSONArray; import dev.peerat.mapping.Treasure;
import org.jose4j.json.internal.json_simple.JSONObject;
import be.jeffcheasey88.peeratcode.mapping.SeaBottle; @Treasure
import dev.peerat.framework.utils.json.JsonMap; public class Group {
public class Group implements Comparable<Group> {
private String name; private String name;
private Integer linkToChapter; private List<PeerAtUser> players;
// private Integer linkToPuzzle; private Puzzle puzzle;
private List<Player> players; private Chapter chapter;
@Override public Group(){}
public String toString(){
return "Group[name="+name+", chapter="+linkToChapter+"]"; public String getName(){
} return this.name;
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;
} }
@SeaBottle public List<PeerAtUser> getPlayers(){
public static Group getGroup(int player){ return this.players;
return null;
} }
public void addPlayer(Player newPlayer) { public Puzzle getPuzzle(){
if (newPlayer != null) { return this.puzzle;
if (players == null)
players = new ArrayList<Player>();
int pPosition = players.indexOf(newPlayer);
if (pPosition < 0) {
players.add(newPlayer);
} else {
players.get(pPosition).addCompletion(new Completion(newPlayer.getTotalTries(), newPlayer.getTotalScore()));
}
}
} }
public int getScore() { public Chapter getChapter(){
int score = 0; return this.chapter;
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);
} }
} }

View file

@ -2,9 +2,17 @@ package dev.peerat.backend.model;
import org.jose4j.jwt.JwtClaims; 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 int id;
private String pseudo;
private String email;
private String fistName;
private String lastName;
private School school;
public PeerAtUser(int id){ public PeerAtUser(int id){
this.id = id; this.id = id;
@ -23,6 +31,23 @@ public class PeerAtUser extends dev.peerat.framework.User{
return this.id; 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;
}
} }

View file

@ -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<Player> {
private String pseudo;
private String email;
private String firstname;
private String lastname;
private String description;
private Set<Group> groups;
private Set<Completion> completions = new HashSet<Completion>();
private byte[] avatar;
private int rank;
private Set<Badge> 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<Group> 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<Group>();
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<Badge> 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<Badge>();
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);
}
}

View file

@ -1,109 +1,30 @@
package dev.peerat.backend.model; package dev.peerat.backend.model;
import java.sql.Timestamp;
import java.time.LocalDateTime; 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.mapping.Treasure;
import dev.peerat.framework.utils.json.JsonMap;
public class Puzzle { @Treasure
public class Puzzle{
private int id; private int participantCount;
private String name; private LocalDateTime start;
private String content; private LocalDateTime end;
private byte[] soluce; private Chapter chapter;
private String verify;
private int scoreMax; public int getParticipantCount(){
private Set<String> tags; return this.participantCount;
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<String> 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<String>(Arrays.asList(tags.split(",")));
}
public int getDepend() {
return this.depend;
} }
public boolean hasStarted(){ public LocalDateTime getStartTime(){
LocalDateTime now = LocalDateTime.now(); return this.start;
boolean show = true;
if(startDate != null) show &= now.isAfter(startDate.toLocalDateTime());
return show;
} }
@Override public LocalDateTime getEndTime(){
public boolean equals(Object object) { return this.end;
if (this == object)
return true;
if (!(object instanceof Puzzle))
return false;
return this.id == (((Puzzle) object).id);
} }
@Override public Chapter getChapter(){
public int hashCode() { return this.chapter;
return id;
} }
} }

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
*
*/

View file

@ -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<Puzzle> getPuzzlesInChapter(int id) throws SQLException {
List<Puzzle> 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<Player> getAllPlayerForLeaderboard() {
try {
ensureConnection();
PreparedStatement playersStmt = DatabaseQuery.ALL_PLAYERS_FOR_LEADERBOARD.prepare(this.con);
ResultSet result = playersStmt.executeQuery();
ArrayList<Player> players = new ArrayList<Player>();
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<Player>(players);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
public SortedSet<Group> getAllGroupForChapterLeaderboard(int chapterId){
try{
ensureConnection();
PreparedStatement groupsStmt = DatabaseQuery.ALL_GROUP_FOR_CHAPTER_LEADERBOARD.prepare(this.con);
groupsStmt.setInt(1, chapterId);
ResultSet result = groupsStmt.executeQuery();
List<Group> groups = new ArrayList<Group>();
Group tmpGroup;
while (result.next()) {
tmpGroup = makeGroup(result);
if (tmpGroup != null) {
int gPosition = groups.indexOf(tmpGroup);
if (gPosition < 0) {
tmpGroup.addPlayer(makeGroupPlayer(result));
groups.add(tmpGroup);
} else {
groups.get(gPosition).addPlayer(makeGroupPlayer(result));
}
}
}
return new TreeSet<Group>(groups);
}catch(SQLException e){
e.printStackTrace();
}
return null;
}
public Badge getBadge(int badgeId) {
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<Puzzle> 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<Puzzle> 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<Chapter> getAllChapters() {
try {
List<Chapter> 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<Group> getAllGroups() {
try {
ensureConnection();
List<Group> 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();
}
}

View file

@ -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<File> 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<String> headers;
private String payload;
private int responseCode;
private List<String> 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();
}
}
}