diff --git a/src/main/java/delta/codecharacter/server/config/CorsFilter.java b/src/main/java/delta/codecharacter/server/config/CorsFilter.java index 1fd2155e..2340d18a 100644 --- a/src/main/java/delta/codecharacter/server/config/CorsFilter.java +++ b/src/main/java/delta/codecharacter/server/config/CorsFilter.java @@ -14,7 +14,7 @@ @Order(Ordered.HIGHEST_PRECEDENCE) public class CorsFilter implements Filter { - @Value("${client.request.origin}") + @Value("${client.request.cors.origin}") private String origin; @Override diff --git a/src/main/java/delta/codecharacter/server/config/WebSecurityConfig.java b/src/main/java/delta/codecharacter/server/config/WebSecurityConfig.java index 9f38dd77..3dabaa00 100644 --- a/src/main/java/delta/codecharacter/server/config/WebSecurityConfig.java +++ b/src/main/java/delta/codecharacter/server/config/WebSecurityConfig.java @@ -40,7 +40,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { private final Logger LOG = Logger.getLogger(WebSecurityConfig.class.getName()); //routes which do not require authentication - String[] ignoringAntMatchers = {"/", "/login/**", "/error/**", "/logout", "/user", "/user/**", "/match/top/**", "/match", "/socket/**"}; + String[] ignoringAntMatchers = {"/", "/login/**", "/error/**", "/logout", "/user", "/user/**", "/match/top/**", "/match", "/socket/**", "/code/lock"}; @Autowired private BCryptPasswordEncoder bCryptPasswordEncoder; diff --git a/src/main/java/delta/codecharacter/server/controller/api/CodeVersionController.java b/src/main/java/delta/codecharacter/server/controller/api/CodeVersionController.java index 66ff9af6..d4e1a55f 100644 --- a/src/main/java/delta/codecharacter/server/controller/api/CodeVersionController.java +++ b/src/main/java/delta/codecharacter/server/controller/api/CodeVersionController.java @@ -1,20 +1,25 @@ package delta.codecharacter.server.controller.api; import delta.codecharacter.server.controller.request.Codeversion.CommitResponse; +import delta.codecharacter.server.controller.request.LockCodeRequest; import delta.codecharacter.server.model.User; import delta.codecharacter.server.service.UserService; import delta.codecharacter.server.service.VersionControlService; import lombok.SneakyThrows; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.util.List; import java.util.logging.Logger; +@Controller @RestController @RequestMapping(value = "/code") public class CodeVersionController { @@ -26,6 +31,9 @@ public class CodeVersionController { @Autowired UserService userService; + @Value("${compilebox.secret-key}") + private String secretKey; + @GetMapping(value = "/latest") @SneakyThrows public ResponseEntity getLatestCode(Authentication authentication) { @@ -38,7 +46,6 @@ public ResponseEntity getLatestCode(Authentication authentication) { } @PutMapping(value = "") - @SneakyThrows public ResponseEntity saveCode(@RequestBody @Valid String code, Authentication authentication) { String email = userService.getEmailFromAuthentication(authentication); User user = userService.getUserByEmail(email); @@ -48,17 +55,6 @@ public ResponseEntity saveCode(@RequestBody @Valid String code, Authenti return new ResponseEntity<>("Saved Code", HttpStatus.OK); } - @PutMapping(value = "/submit") - @SneakyThrows - public ResponseEntity setLockedCode(Authentication authentication) { - String email = userService.getEmailFromAuthentication(authentication); - User user = userService.getUserByEmail(email); - if (user == null) return new ResponseEntity<>("User not found", HttpStatus.UNAUTHORIZED); - if (!versionControlService.setLockedCode(user.getUserId())) - return new ResponseEntity<>("Code repository not created", HttpStatus.FORBIDDEN); - return new ResponseEntity<>("Code Submitted", HttpStatus.OK); - } - @PostMapping(value = "/commit") @SneakyThrows public ResponseEntity commit(@RequestBody @Valid String commitMessage, Authentication authentication) { @@ -112,4 +108,18 @@ public ResponseEntity forkCommitByHash(@PathVariable String commitHash, return new ResponseEntity<>("Code repository not created", HttpStatus.FORBIDDEN); return new ResponseEntity<>("Forked successfully", HttpStatus.OK); } + + @MessageMapping("/code/submit") + public void submitCode(Authentication authentication) { + String email = userService.getEmailFromAuthentication(authentication); + User user = userService.getUserByEmail(email); + versionControlService.submitCode(user.getUserId()); + } + + @PostMapping(value = "/lock") + public void lockCode(@RequestBody LockCodeRequest lockCodeRequest) { + if (!lockCodeRequest.getSecretKey().equals(secretKey)) + return; + versionControlService.lockCode(lockCodeRequest); + } } diff --git a/src/main/java/delta/codecharacter/server/controller/api/GameController.java b/src/main/java/delta/codecharacter/server/controller/api/GameController.java index 119bdec8..0c11041e 100644 --- a/src/main/java/delta/codecharacter/server/controller/api/GameController.java +++ b/src/main/java/delta/codecharacter/server/controller/api/GameController.java @@ -2,23 +2,28 @@ import delta.codecharacter.server.controller.response.GameLogs; import delta.codecharacter.server.service.GameService; +import delta.codecharacter.server.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.*; -@RequestMapping(value = "/game") @RestController +@CrossOrigin("*") +@RequestMapping("/game") public class GameController { @Autowired private GameService gameService; + @Autowired + private UserService userService; + @GetMapping(value = "/log/{gameId}") - public ResponseEntity getGameLog(@PathVariable Integer gameId) { - return new ResponseEntity<>(gameService.getGameLog(gameId), HttpStatus.OK); + public ResponseEntity getGameLog(@PathVariable Integer gameId, Authentication authentication) { + String email = userService.getEmailFromAuthentication(authentication); + var user = userService.getUserByEmail(email); + return new ResponseEntity<>(gameService.getGameLog(gameId, user.getUserId()), HttpStatus.OK); } } diff --git a/src/main/java/delta/codecharacter/server/controller/api/MatchController.java b/src/main/java/delta/codecharacter/server/controller/api/MatchController.java index d4a8babf..ea9349e1 100644 --- a/src/main/java/delta/codecharacter/server/controller/api/MatchController.java +++ b/src/main/java/delta/codecharacter/server/controller/api/MatchController.java @@ -36,5 +36,4 @@ public void updateMatch(@RequestBody @Valid UpdateMatchRequest updateMatchReques return; matchService.updateMatch(updateMatchRequest); } - } diff --git a/src/main/java/delta/codecharacter/server/controller/api/UserController.java b/src/main/java/delta/codecharacter/server/controller/api/UserController.java index c402652f..a1156f73 100644 --- a/src/main/java/delta/codecharacter/server/controller/api/UserController.java +++ b/src/main/java/delta/codecharacter/server/controller/api/UserController.java @@ -2,7 +2,7 @@ import delta.codecharacter.server.controller.request.User.*; import delta.codecharacter.server.controller.response.Match.DetailedMatchStatsResponse; -import delta.codecharacter.server.controller.response.Match.PrivateMatchResponse; +import delta.codecharacter.server.controller.response.Match.MatchResponse; import delta.codecharacter.server.controller.response.User.PrivateUserResponse; import delta.codecharacter.server.controller.response.User.PublicUserResponse; import delta.codecharacter.server.controller.response.UserRatingsResponse; @@ -158,7 +158,7 @@ public ResponseEntity> getUserRatings(@PathVariable St } @GetMapping(value = "/match/{pageNo}/{pageSize}") - public ResponseEntity> getManualAndAutoExecutedMatches(@PathVariable Integer pageNo, @PathVariable Integer pageSize, Authentication authentication) { + public ResponseEntity> getManualAndAutoExecutedMatches(@PathVariable Integer pageNo, @PathVariable Integer pageSize, Authentication authentication) { String email = userService.getEmailFromAuthentication(authentication); User user = userService.getUserByEmail(email); Pageable pageable = PageRequest.of(pageNo - 1, pageSize); diff --git a/src/main/java/delta/codecharacter/server/controller/request/LockCodeRequest.java b/src/main/java/delta/codecharacter/server/controller/request/LockCodeRequest.java new file mode 100644 index 00000000..09279f53 --- /dev/null +++ b/src/main/java/delta/codecharacter/server/controller/request/LockCodeRequest.java @@ -0,0 +1,22 @@ +package delta.codecharacter.server.controller.request; + +import lombok.Data; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; + +import java.util.List; + +@Data +@JsonIgnoreProperties(value = "true") +public class LockCodeRequest { + private String secretKey; + + private Integer userId; + + private Boolean success; + + private List playerDLLs; + + private String errorType; + + private String error; +} diff --git a/src/main/java/delta/codecharacter/server/controller/request/Simulation/CompileCodeRequest.java b/src/main/java/delta/codecharacter/server/controller/request/Simulation/CompileCodeRequest.java new file mode 100644 index 00000000..4a2940f6 --- /dev/null +++ b/src/main/java/delta/codecharacter/server/controller/request/Simulation/CompileCodeRequest.java @@ -0,0 +1,16 @@ +package delta.codecharacter.server.controller.request.Simulation; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class CompileCodeRequest { + private String jobType; + + private Integer userId; + + private String secretKey; + + private String code; +} diff --git a/src/main/java/delta/codecharacter/server/controller/request/UpdateGameDetails.java b/src/main/java/delta/codecharacter/server/controller/request/UpdateGameDetails.java index dd1a3483..a9e1f26d 100644 --- a/src/main/java/delta/codecharacter/server/controller/request/UpdateGameDetails.java +++ b/src/main/java/delta/codecharacter/server/controller/request/UpdateGameDetails.java @@ -15,6 +15,8 @@ public class UpdateGameDetails { private Verdict verdict; + private String winType; + private Integer matchId; private Integer points1; @@ -24,5 +26,7 @@ public class UpdateGameDetails { private String player1LogCompressed; private String player2LogCompressed; + + private String errorType; } diff --git a/src/main/java/delta/codecharacter/server/controller/response/Match/MatchResponse.java b/src/main/java/delta/codecharacter/server/controller/response/Match/MatchResponse.java index 1135dfda..60368908 100644 --- a/src/main/java/delta/codecharacter/server/controller/response/Match/MatchResponse.java +++ b/src/main/java/delta/codecharacter/server/controller/response/Match/MatchResponse.java @@ -17,9 +17,9 @@ public class MatchResponse { private String username2; - private Integer avatarId1; + private Integer avatar1; - private Integer avatarId2; + private Integer avatar2; private Integer score1; diff --git a/src/main/java/delta/codecharacter/server/controller/response/Match/PrivateMatchResponse.java b/src/main/java/delta/codecharacter/server/controller/response/Match/PrivateMatchResponse.java deleted file mode 100644 index 369e574e..00000000 --- a/src/main/java/delta/codecharacter/server/controller/response/Match/PrivateMatchResponse.java +++ /dev/null @@ -1,37 +0,0 @@ -package delta.codecharacter.server.controller.response.Match; - -import delta.codecharacter.server.model.Game; -import delta.codecharacter.server.util.enums.MatchMode; -import delta.codecharacter.server.util.enums.Verdict; -import lombok.Builder; -import lombok.Data; -import org.springframework.data.mongodb.core.mapping.Field; - -import java.util.Date; -import java.util.List; - -@Data -@Builder -public class PrivateMatchResponse { - private String username1; - - private String username2; - - private Integer avatar1; - - private Integer avatar2; - - private Integer score1; - - private Integer score2; - - private Verdict verdict; - - @Field("match_mode") - private MatchMode matchMode; - - @Field("played_at") - private Date playedAt; - - private List games; -} diff --git a/src/main/java/delta/codecharacter/server/model/Game.java b/src/main/java/delta/codecharacter/server/model/Game.java index 4ab990b7..a4015f17 100644 --- a/src/main/java/delta/codecharacter/server/model/Game.java +++ b/src/main/java/delta/codecharacter/server/model/Game.java @@ -32,6 +32,10 @@ public class Game { @Builder.Default private Verdict verdict = Verdict.TIE; + private String winType; + + private String errorType; + @Field("points_1") @Builder.Default private Integer points1 = 0; diff --git a/src/main/java/delta/codecharacter/server/service/GameService.java b/src/main/java/delta/codecharacter/server/service/GameService.java index 2e13aa7b..d7bdc631 100644 --- a/src/main/java/delta/codecharacter/server/service/GameService.java +++ b/src/main/java/delta/codecharacter/server/service/GameService.java @@ -6,6 +6,7 @@ import delta.codecharacter.server.repository.MatchRepository; import delta.codecharacter.server.util.LogUtil; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.util.List; @@ -19,6 +20,12 @@ public class GameService { @Autowired private MatchRepository matchRepository; + @Autowired + private SocketService socketService; + + @Value("/socket/response/alert/") + private String socketAlertMessageDest; + /** * Create a new game for the given matchId * @@ -45,12 +52,16 @@ public Game createGame(Integer matchId, Integer mapId) { * @param gameId Game Id of the game * @return game log, player1 log and player2 log of the game */ - public GameLogs getGameLog(Integer gameId) { + public GameLogs getGameLog(Integer gameId, Integer userId) { + var game = gameRepository.findFirstById(gameId); + if (!game.getWinType().equals("SCORE")) { + socketService.sendMessage(socketAlertMessageDest + userId, game.getVerdict() + " won by " + game.getWinType()); + return null; + } var gameLogs = LogUtil.getLogs(gameId); if (gameLogs == null) return null; - var game = gameRepository.findFirstById(gameId); var match = matchRepository.findFirstById(game.getMatchId()); gameLogs.setPlayerId1(match.getPlayerId1()); diff --git a/src/main/java/delta/codecharacter/server/service/MatchService.java b/src/main/java/delta/codecharacter/server/service/MatchService.java index 66762ad8..e1a87a72 100644 --- a/src/main/java/delta/codecharacter/server/service/MatchService.java +++ b/src/main/java/delta/codecharacter/server/service/MatchService.java @@ -1,5 +1,7 @@ package delta.codecharacter.server.service; + + import delta.codecharacter.server.controller.api.UserController; import delta.codecharacter.server.controller.request.Notification.CreateNotificationRequest; import delta.codecharacter.server.controller.request.UpdateGameDetails; @@ -7,7 +9,6 @@ import delta.codecharacter.server.controller.response.GameLogs; import delta.codecharacter.server.controller.response.Match.DetailedMatchStatsResponse; import delta.codecharacter.server.controller.response.Match.MatchResponse; -import delta.codecharacter.server.controller.response.Match.PrivateMatchResponse; import delta.codecharacter.server.model.Match; import delta.codecharacter.server.model.User; import delta.codecharacter.server.repository.*; @@ -118,8 +119,10 @@ public List getTopMatches(Integer PageNumber, Integer PageSize) { MatchResponse matchResponse = MatchResponse.builder() .username1(user1.getUsername()) .username2(user2.getUsername()) - .avatarId1(user1.getAvatarId()) - .avatarId2(user2.getAvatarId()) + .avatar1(user1.getAvatarId()) + .avatar2(user2.getAvatarId()) + .score1(match.getScore1()) + .score2(match.getScore2()) .verdict(match.getVerdict()) .matchMode(match.getMatchMode()) .games(gameService.getAllGamesByMatchId(match.getId())) @@ -137,15 +140,15 @@ public List getTopMatches(Integer PageNumber, Integer PageSize) { * @param userId UserId of the player * @return List of paginated manual and auto matches */ - public List getManualAndAutoExecutedMatchesPaginated(Integer userId, Pageable pageable) { + public List getManualAndAutoExecutedMatchesPaginated(Integer userId, Pageable pageable) { Aggregation aggregation = newAggregation( match( - new Criteria().andOperator( new Criteria().andOperator( - new Criteria().orOperator(Criteria.where("player_id_1").is(userId), Criteria.where("player_id_2").is(userId)), - new Criteria().orOperator(Criteria.where("match_mode").is(MatchMode.MANUAL), Criteria.where("match_mode").is(MatchMode.AUTO)) - ), Criteria.where("status").is("EXECUTED") - ) + new Criteria().andOperator( + new Criteria().orOperator(Criteria.where("player_id_1").is(userId), Criteria.where("player_id_2").is(userId)), + new Criteria().orOperator(Criteria.where("match_mode").is(MatchMode.MANUAL), Criteria.where("match_mode").is(MatchMode.AUTO)) + ), Criteria.where("status").is("EXECUTED") + ) ), sort(Sort.by("createdAt").descending()), skip((long) pageable.getPageNumber() * pageable.getPageSize()), @@ -155,26 +158,28 @@ public List getManualAndAutoExecutedMatchesPaginated(Integ var groupResults = mongoTemplate.aggregate(aggregation, Match.class, Match.class); List matches = groupResults.getMappedResults(); - List privateMatchResponse = new ArrayList<>(); + List matchResponseList = new ArrayList<>(); for (var match : matches) { User user1 = userRepository.findByUserId(match.getPlayerId1()); User user2 = userRepository.findByUserId(match.getPlayerId2()); - var matchResponse = PrivateMatchResponse.builder() + var matchResponse = MatchResponse.builder() .username1(user1.getUsername()) .username2(user2.getUsername()) .avatar1(user1.getAvatarId()) .avatar2(user2.getAvatarId()) + .score1(match.getScore1()) + .score2(match.getScore2()) .verdict(match.getVerdict()) .playedAt(match.getCreatedAt()) .matchMode(match.getMatchMode()) .games(gameService.getAllGamesByMatchId(match.getId())) .build(); - privateMatchResponse.add(matchResponse); + matchResponseList.add(matchResponse); } - return privateMatchResponse; + return matchResponseList; } /** @@ -390,15 +395,17 @@ public void updateMatch(UpdateMatchRequest updateMatchRequest) { if (!success) { match.setStatus(Status.EXECUTE_ERROR); matchRepository.save(match); - - socketService.sendMessage(socketMatchResultDest + match.getPlayerId1(), "Error: " + updateMatchRequest.getError()); - socketService.sendMessage(socketAlertMessageDest + match.getPlayerId1(), "Execute Error"); + socketService.sendMessage(socketAlertMessageDest + match.getPlayerId1(), "Error: " + + getErrorNotificationMessage(updateMatchRequest.getErrorType())); return; } + Verdict matchVerdict = deduceMatchVerdict(updateMatchRequest.getGameResults()); + String errorType = null; List gameLogsList = new ArrayList<>(); var gameResults = updateMatchRequest.getGameResults(); + if (match.getMatchMode() != MatchMode.AUTO && match.getMatchMode() != MatchMode.MANUAL) { for (var game : gameResults) { var gameLogs = GameLogs.builder() @@ -408,13 +415,20 @@ public void updateMatch(UpdateMatchRequest updateMatchRequest) { .player2Log(game.getPlayer2LogCompressed()) .build(); gameLogsList.add(gameLogs); + errorType = game.getErrorType(); } + } - Integer playerId = match.getPlayerId1(); - socketService.sendMessage(socketMatchResultDest + playerId, gameLogsList.toString()); - String matchMessage = getMatchResultByVerdict(matchId, matchVerdict, playerId); - socketService.sendMessage(socketAlertMessageDest + playerId, matchMessage); - createMatchNotification(playerId, matchMessage); + Integer socketListenerId = match.getPlayerId1(); + LOG.info("Message sent to "+ socketMatchResultDest+socketListenerId); + socketService.sendMessage(socketMatchResultDest + socketListenerId, gameLogsList.toString()); + String matchMessage = getMatchResultByVerdict(matchId, matchVerdict, socketListenerId); + if (errorType != null && (errorType.equals(String.valueOf(ErrorType.TIMEOUT)) || errorType.equals(String.valueOf(ErrorType.PLAYER_RUNTIME_ERROR)))) { + socketService.sendMessage(socketAlertMessageDest + socketListenerId, matchMessage + " by " + errorType); + createMatchNotification(socketListenerId, matchMessage, errorType, Type.ERROR); + } else { + socketService.sendMessage(socketAlertMessageDest + socketListenerId, matchMessage); + createMatchNotification(socketListenerId, "Match Result", matchMessage, Type.INFO); } if (match.getMatchMode() == MatchMode.MANUAL) { @@ -426,9 +440,9 @@ public void updateMatch(UpdateMatchRequest updateMatchRequest) { // If match mode is manual, create a notification for player 2 also. Integer playerId = match.getPlayerId2(); - String matchMessage = getMatchResultByVerdict(matchId, matchVerdict, playerId); + matchMessage = getMatchResultByVerdict(matchId, matchVerdict, playerId); socketService.sendMessage(socketAlertMessageDest + playerId, matchMessage); - createMatchNotification(playerId, matchMessage); + createMatchNotification(playerId, matchMessage, errorType, Type.INFO); // Add an entry to User rating table // NOTE: CalculateMatchRatings will add an entry in User Rating and update Leaderboard @@ -444,16 +458,20 @@ public void updateMatch(UpdateMatchRequest updateMatchRequest) { game.setPoints1(gameResult.getPoints1()); game.setPoints2(gameResult.getPoints2()); game.setVerdict(gameResult.getVerdict()); + game.setErrorType(gameResult.getErrorType()); + game.setWinType(gameResult.getWinType()); gameRepository.save(game); Integer gameId = gameResult.getId(); - LogUtil.createLogRepository(gameId); - var gameLogs = GameLogs.builder() - .gameLog(gameResult.getLog()) - .player1Log(gameResult.getPlayer1LogCompressed()) - .player2Log(gameResult.getPlayer2LogCompressed()) - .build(); - LogUtil.setLogs(gameId, gameLogs); + if (match.getMatchMode() == MatchMode.AUTO || match.getMatchMode() == MatchMode.MANUAL) { + LogUtil.createLogRepository(gameId); + var gameLogs = GameLogs.builder() + .gameLog(gameResult.getLog()) + .player1Log(gameResult.getPlayer1LogCompressed()) + .player2Log(gameResult.getPlayer2LogCompressed()) + .build(); + LogUtil.setLogs(gameId, gameLogs); + } } match.setStatus(Status.EXECUTED); @@ -462,6 +480,21 @@ public void updateMatch(UpdateMatchRequest updateMatchRequest) { matchRepository.save(match); } + private String getErrorNotificationMessage(String errorType) { + switch (errorType) { + case "COMPILER_ERROR": + return "Compilation Error"; + case "EXECUTE_PROCESS_ERROR": + return "Execution Error"; + case "UNKNOWN_EXECUTE_ERROR": + return "Something went wrong!"; + case "PLAYER_RUNTIME_ERROR": + return "Runtime Error"; + default: + return errorType; + } + } + private void updateMatchScore(Match match, List gameDetails) { Integer player1Wins = 0, player2Wins = 0; for (var game : gameDetails) { @@ -514,12 +547,12 @@ private String getMatchResultByVerdict(Integer matchId, Verdict verdict, Integer * @param playerId userId of the player * @param notificationContent Content of the notification */ - private void createMatchNotification(Integer playerId, String notificationContent) { + private void createMatchNotification(Integer playerId, String notificationTitle, String notificationContent, Type notificationType) { CreateNotificationRequest createNotificationRequest = CreateNotificationRequest.builder() .userId(playerId) - .title("Match Result") + .title(notificationTitle) .content(notificationContent) - .type(Type.INFO) + .type(notificationType) .build(); notificationService.createNotification(createNotificationRequest); } diff --git a/src/main/java/delta/codecharacter/server/service/VersionControlService.java b/src/main/java/delta/codecharacter/server/service/VersionControlService.java index 1c6449d7..ba9fe857 100644 --- a/src/main/java/delta/codecharacter/server/service/VersionControlService.java +++ b/src/main/java/delta/codecharacter/server/service/VersionControlService.java @@ -1,6 +1,10 @@ package delta.codecharacter.server.service; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import delta.codecharacter.server.controller.request.Codeversion.CommitResponse; +import delta.codecharacter.server.controller.request.LockCodeRequest; +import delta.codecharacter.server.controller.request.Simulation.CompileCodeRequest; import delta.codecharacter.server.model.CodeStatus; import delta.codecharacter.server.repository.CodeStatusRepository; import delta.codecharacter.server.util.DllUtil; @@ -30,6 +34,13 @@ public class VersionControlService { private static final Logger LOG = Logger.getLogger(VersionControlService.class.getName()); + Gson gson = new GsonBuilder().disableHtmlEscaping().serializeNulls().create(); + + @Value("${compilebox.secret-key}") + private String secretKey; + + @Value("/socket/response/alert/") + private String socketAlertMessageDest; @Value("${storage.playercode.dir}") private String codeStoragePath; @@ -46,12 +57,18 @@ public class VersionControlService { @Value("${storage.playerLockedCode.filename}") private String lockedCodeFileName; + @Autowired + private RabbitMqService rabbitMqService; + @Autowired private CodeStatusService codeStatusService; @Autowired private CodeStatusRepository codeStatusRepository; + @Autowired + private SocketService socketService; + /** * Commit the saved code * @@ -403,7 +420,7 @@ public String getLockedCode(Integer userId) { * @param userId UserId of user */ @SneakyThrows - public boolean setLockedCode(Integer userId) { + public void submitCode(Integer userId) { if (!checkLockedCodeRepositoryExists(userId)) throw new Exception("No repository found"); @@ -411,15 +428,38 @@ public boolean setLockedCode(Integer userId) { DllUtil.deleteDllFile(userId, DllId.DLL_1); DllUtil.deleteDllFile(userId, DllId.DLL_2); - String lockedCodeFileUri = getLockedCodeFileUri(userId); String code = getCode(userId); - FileHandler.writeFileContents(lockedCodeFileUri, code); + + var compileCodeRequest = CompileCodeRequest.builder() + .jobType("COMPILE") + .userId(userId) + .secretKey(secretKey) + .code(code) + .build(); + + rabbitMqService.sendMessageToQueue(gson.toJson(compileCodeRequest)); + socketService.sendMessage(socketAlertMessageDest + userId, "Code Compiling"); + } + + public void lockCode(LockCodeRequest lockCodeRequest) { + Integer userId = lockCodeRequest.getUserId(); + Boolean success = lockCodeRequest.getSuccess(); + if (!success) { + socketService.sendMessage(socketAlertMessageDest + userId, "Failed to Submit!"); + socketService.sendMessage(socketAlertMessageDest + userId, "Error: " + lockCodeRequest.getErrorType()); + return; + } //set isLocked to true in codeStatus table CodeStatus codeStatus = codeStatusService.getCodeStatusByUserId(userId); - codeStatus.setLocked(true); - codeStatusRepository.save(codeStatus); + if (!codeStatus.isLocked()) { + codeStatus.setLocked(true); + codeStatusRepository.save(codeStatus); + } - return true; + DllUtil.setDll(userId, DllId.DLL_1, lockCodeRequest.getPlayerDLLs().get(0)); + DllUtil.setDll(userId, DllId.DLL_2, lockCodeRequest.getPlayerDLLs().get(1)); + + socketService.sendMessage(socketAlertMessageDest + userId, "Code Submitted Successfully"); } } diff --git a/src/main/java/delta/codecharacter/server/util/enums/ErrorType.java b/src/main/java/delta/codecharacter/server/util/enums/ErrorType.java new file mode 100644 index 00000000..61f862cd --- /dev/null +++ b/src/main/java/delta/codecharacter/server/util/enums/ErrorType.java @@ -0,0 +1,5 @@ +package delta.codecharacter.server.util.enums; + +public enum ErrorType { + TIMEOUT, PLAYER_RUNTIME_ERROR +}