diff --git a/src/main/java/com/uniovi/configuration/CustomConfiguration.java b/src/main/java/com/uniovi/configuration/CustomConfiguration.java index 9f82b231..86bc6ad0 100644 --- a/src/main/java/com/uniovi/configuration/CustomConfiguration.java +++ b/src/main/java/com/uniovi/configuration/CustomConfiguration.java @@ -2,6 +2,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.web.PageableHandlerMethodArgumentResolver; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; @@ -9,6 +12,7 @@ import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; import org.springframework.web.servlet.i18n.SessionLocaleResolver; +import java.util.List; import java.util.Locale; @Configuration @@ -31,4 +35,13 @@ public LocaleChangeInterceptor localeChangeInterceptor() { public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(localeChangeInterceptor()); } + + @Override + public void addArgumentResolvers(List argumentResolvers) { + int page = 0; + int size = 5; + PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver(); + resolver.setFallbackPageable(PageRequest.of(page, size)); + argumentResolvers.add(resolver); + } } diff --git a/src/main/java/com/uniovi/controllers/PlayersController.java b/src/main/java/com/uniovi/controllers/PlayersController.java index dbbcca5b..a998b69d 100644 --- a/src/main/java/com/uniovi/controllers/PlayersController.java +++ b/src/main/java/com/uniovi/controllers/PlayersController.java @@ -1,19 +1,17 @@ package com.uniovi.controllers; import com.uniovi.configuration.SecurityConfig; +import com.uniovi.entities.GameSession; import com.uniovi.entities.Player; +import com.uniovi.services.GameSessionService; import com.uniovi.services.PlayerService; import com.uniovi.validators.SignUpValidator; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; -import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.web.authentication.WebAuthenticationDetails; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; @@ -25,17 +23,19 @@ import org.springframework.web.bind.annotation.RequestParam; import java.security.Principal; -import java.util.Optional; @Controller public class PlayersController { private final PlayerService playerService; private final SignUpValidator signUpValidator; + private final GameSessionService gameSessionService; + @Autowired - public PlayersController(PlayerService playerService, SignUpValidator signUpValidator) { + public PlayersController(PlayerService playerService, SignUpValidator signUpValidator, GameSessionService gameSessionService) { this.playerService = playerService; this.signUpValidator = signUpValidator; + this.gameSessionService = gameSessionService; } @GetMapping("/signup") @@ -92,4 +92,27 @@ public String showLoginForm(Model model, @RequestParam(value = "error", required public String home(Model model, Principal principal) { return "player/home"; } + + + @GetMapping("/ranking/globalRanking") + public String showGlobalRanking(Pageable pageable, Model model) { + Page ranking = gameSessionService.getGlobalRanking(pageable); + + model.addAttribute("ranking", ranking.getContent()); + model.addAttribute("page", ranking); + + return "/ranking/globalRanking"; + } + + @GetMapping("/ranking/playerRanking") + public String showPlayerRanking(Pageable pageable, Model model, Principal principal) { + Player player = playerService.getUserByUsername(principal.getName()).get(); + Page ranking = gameSessionService.getPlayerRanking(pageable, player); + + model.addAttribute("ranking", ranking.getContent()); + model.addAttribute("page", ranking); + + return "/ranking/playerRanking"; + } + } diff --git a/src/main/java/com/uniovi/entities/GameSession.java b/src/main/java/com/uniovi/entities/GameSession.java index 4928b0e3..05bee1dd 100644 --- a/src/main/java/com/uniovi/entities/GameSession.java +++ b/src/main/java/com/uniovi/entities/GameSession.java @@ -34,6 +34,8 @@ public class GameSession implements JsonEntity { private int score; + private int score; + public void addQuestion(boolean correct) { if(correct) correctQuestions++; diff --git a/src/main/java/com/uniovi/repositories/GameSessionRepository.java b/src/main/java/com/uniovi/repositories/GameSessionRepository.java index fd33f135..e3c40519 100644 --- a/src/main/java/com/uniovi/repositories/GameSessionRepository.java +++ b/src/main/java/com/uniovi/repositories/GameSessionRepository.java @@ -1,7 +1,25 @@ package com.uniovi.repositories; +import com.uniovi.entities.Answer; import com.uniovi.entities.GameSession; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; +import com.uniovi.entities.Player; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + + +import java.util.List; + public interface GameSessionRepository extends CrudRepository { + + List findAll(); + + List findAllByPlayer(Player player); + + + @Query("SELECT gs.player, SUM(gs.score) FROM GameSession gs GROUP BY gs.player ORDER BY SUM(gs.score) DESC") + Page findTotalScoresByPlayer(Pageable pageable); + Page findAllByPlayerOrderByScoreDesc(Pageable pageable, Player player); } diff --git a/src/main/java/com/uniovi/services/GameSessionService.java b/src/main/java/com/uniovi/services/GameSessionService.java new file mode 100644 index 00000000..1f032301 --- /dev/null +++ b/src/main/java/com/uniovi/services/GameSessionService.java @@ -0,0 +1,34 @@ +package com.uniovi.services; + +import com.uniovi.entities.GameSession; +import com.uniovi.entities.Player; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +@Service +public interface GameSessionService { + + /** + * Return the list of GameSessions + * + * @return the list of GameSessions + */ + List getGameSessions(); + +// /** +// * Return the list of GameSessions by player +// * +// * @return the list of GameSessions by player +// */ +// List getGameSessionsByPlayer(Player player); +// +// HashMap getSortedPlayersScores(); + + + public Page getGlobalRanking(Pageable pageable); + public Page getPlayerRanking(Pageable pageable, Player player); + +} diff --git a/src/main/java/com/uniovi/services/impl/GameSessionImpl.java b/src/main/java/com/uniovi/services/impl/GameSessionImpl.java new file mode 100644 index 00000000..caf18492 --- /dev/null +++ b/src/main/java/com/uniovi/services/impl/GameSessionImpl.java @@ -0,0 +1,81 @@ +package com.uniovi.services.impl; + +import com.uniovi.entities.Player; +import com.uniovi.repositories.GameSessionRepository; +import com.uniovi.entities.GameSession; +import com.uniovi.services.GameSessionService; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import java.util.*; + +@Service +public class GameSessionImpl implements GameSessionService { + + private final GameSessionRepository gameSessionRepository; + + public GameSessionImpl(GameSessionRepository gameSessionRepository) { + this.gameSessionRepository = gameSessionRepository; + } + + @Override + public List getGameSessions() { + return gameSessionRepository.findAll(); + } + +// @Override +// public List getGameSessionsByPlayer(Player player) { +// return gameSessionRepository.findAllByPlayer(player); +// } +// +// @Override +// public HashMap getSortedPlayersScores() { +// List gameSessions = gameSessionRepository.findAll(); +// HashMap ranking = getRanking(gameSessions); +// // Ordenar las entradas del ranking por puntuación +// List> sortedEntries = new ArrayList<>(ranking.entrySet()); +// sortedEntries.sort(Map.Entry.comparingByValue(Comparator.reverseOrder())); +// +// // Crear un LinkedHashMap para mantener el orden de inserción +// LinkedHashMap sortedRanking = new LinkedHashMap<>(); +// for (Map.Entry entry : sortedEntries) { +// sortedRanking.put(entry.getKey(), entry.getValue()); +// } +// +// return sortedRanking; +// } +// +// private static HashMap getRanking(List gameSessions) { +// HashMap ranking = new HashMap<>(); +// +// // Iterar a través de las sesiones de juego +// for (GameSession gameSession : gameSessions) { +// Player player = gameSession.getPlayer(); +// int score = gameSession.getScore(); +// +// // Si el jugador ya está en el ranking, sumar la puntuación, de lo contrario, agregarlo al ranking +// if (ranking.containsKey(player)) { +// int currentScore = ranking.get(player) + score; +// ranking.put(player, currentScore); +// } else { +// ranking.put(player, score); +// } +// } +// return ranking; +// } + + + @Override + public Page getGlobalRanking(Pageable pageable) { + return gameSessionRepository.findTotalScoresByPlayer(pageable); + } + + @Override + public Page getPlayerRanking(Pageable pageable, Player player) { + return gameSessionRepository.findAllByPlayerOrderByScoreDesc(pageable, player); + } + + +} diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 642af222..2c624ffb 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -5,6 +5,9 @@ navbar.play=Jugar navbar.game1=Juego 1 navbar.game2=Juego 2 navbar.history=Historial +navbar.ranking=Ranking +navbar.ranking.global=Ranking global +navbar.ranking.player=Tu ranking personal navbar.changeLanguage=Idioma navbar.toEnglish=Inglés navbar.toSpanish=Español @@ -59,6 +62,13 @@ signup.passwordConfirm.placeholder=Repita la contraseña signup.submit=Registrarse signup.title=Regístrate +# -------------------Statements for the playerRanking.html and GlobalRanking.html file--------------------- +ranking.title=Ranking +ranking.position=Posición +ranking.score=Puntuación +ranking.date=Fecha +ranking.player=Player + # -------------------Statements for the apiHome.html file--------------------- api.doc.title=Documentación de la API api.doc.description=Esta es la documentación de la API de WIQ. Aquí puedes encontrar información sobre los recursos disponibles, los parámetros que aceptan y los ejemplos de uso. diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties index 5d0941a0..e3c3842e 100644 --- a/src/main/resources/messages_en.properties +++ b/src/main/resources/messages_en.properties @@ -5,6 +5,10 @@ navbar.play=Play navbar.game1=Game 1 navbar.game2=Game 2 navbar.history=History +navbar.ranking=Ranking +navbar.ranking.global=Global ranking +navbar.ranking.player=Your personal ranking +navbar.changeLanguage=Idiom navbar.changeLanguage=Language navbar.toEnglish=English navbar.toSpanish=Spanish @@ -58,6 +62,13 @@ signup.passwordConfirm.placeholder=Confirm your password signup.submit=Sign up signup.title=Sign up +# -------------------Statements for the playerRanking.html and GlobalRanking.html file--------------------- +ranking.title=Ranking +ranking.position=Position +ranking.score=Score +ranking.date=Date +ranking.player=Player + # -------------------Statements for the apiHome.html file--------------------- api.doc.title=API Documentation api.doc.description=This document describes the REST API endpoints. @@ -80,9 +91,4 @@ api.doc.player.emails=Emails, comma separated (optional) api.doc.question.category=Category (optional). Category ID or name. api.doc.question.id=Question ID in the system (optional) -api.doc.question.statement=Statement (optional). Text to search in the question statement. - - - - - +api.doc.question.statement=Statement (optional). Text to search in the question statement. \ No newline at end of file diff --git a/src/main/resources/messages_es.properties b/src/main/resources/messages_es.properties index 6a1b638c..a3a71bd6 100644 --- a/src/main/resources/messages_es.properties +++ b/src/main/resources/messages_es.properties @@ -5,6 +5,9 @@ navbar.play=Jugar navbar.game1=Juego 1 navbar.game2=Juego 2 navbar.history=Historial +navbar.ranking=Ranking +navbar.ranking.global=Ranking global +navbar.ranking.player=Tu ranking personal navbar.changeLanguage=Idioma navbar.toEnglish=Inglés navbar.toSpanish=Español @@ -59,6 +62,13 @@ signup.passwordConfirm.placeholder=Repita la contraseña signup.submit=Registrarse signup.title=Regístrate +# -------------------Statements for the playerRanking.html and GlobalRanking.html file--------------------- +ranking.title=Ranking +ranking.position=Posición +ranking.score=Puntuación +ranking.date=Fecha +ranking.player=Jugador + # -------------------Statements for the apiHome.html file--------------------- api.doc.title=Documentación de la API api.doc.description=Esta es la documentación de la API de WIQ. Aquí puedes encontrar información sobre los recursos disponibles, los parámetros que aceptan y los ejemplos de uso. diff --git a/src/main/resources/templates/fragments/nav.html b/src/main/resources/templates/fragments/nav.html index e7c5deae..fb935b31 100644 --- a/src/main/resources/templates/fragments/nav.html +++ b/src/main/resources/templates/fragments/nav.html @@ -28,6 +28,16 @@ +