Skip to content

Commit

Permalink
Merge pull request #288 from Arquisoft/develop
Browse files Browse the repository at this point in the history
bug fixes
  • Loading branch information
Toto-hitori authored Apr 25, 2024
2 parents faceb13 + e9dbf86 commit 678d505
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 36 deletions.
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,4 @@ jobs:
echo "SSL_PASSWORD=${{ secrets.SSL_PASSWORD }}" >> .env
docker compose --profile prod down
docker compose --profile prod up -d --pull always
docker image prune
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ public static List<QuestionCategory> getQuestionCategoriesForGamemode(GameMode g
gamemode = KIWI_QUEST;
}
return switch (gamemode) {
case KIWI_QUEST -> List.of(QuestionCategory.ART, QuestionCategory.MUSIC, QuestionCategory.GEOGRAPHY);
case KIWI_QUEST -> List.of(QuestionCategory.ART,/* QuestionCategory.MUSIC, */ QuestionCategory.GEOGRAPHY);
case FOOTBALL_SHOWDOWN -> List.of(QuestionCategory.SPORTS);
case GEO_GENIUS -> List.of(QuestionCategory.GEOGRAPHY);
case VIDEOGAME_ADVENTURE -> List.of(QuestionCategory.VIDEOGAMES);
case ANCIENT_ODYSSEY -> List.of(QuestionCategory.MUSIC,QuestionCategory.ART);
case ANCIENT_ODYSSEY -> List.of(/*QuestionCategory.MUSIC,*/QuestionCategory.ART);
case RANDOM -> List.of(QuestionCategory.values());
case CUSTOM -> questionCategoriesForCustom;
};
Expand Down Expand Up @@ -70,11 +70,12 @@ private static List<QuestionCategoryDto> getQuestionCategoriesEn(){
.description("Are you an art expert? Prove it!")
.internalRepresentation(QuestionCategory.ART)
.build(),
/*
QuestionCategoryDto.builder()
.name("Music")
.description("Are you a music lover? Prove it!")
.internalRepresentation(QuestionCategory.MUSIC)
.build(),
.build(),*/
QuestionCategoryDto.builder()
.name("Geography")
.description("Are you a geography expert? Prove it!")
Expand All @@ -100,11 +101,12 @@ private static List<QuestionCategoryDto> getQuestionCategoriesEs(){
.description("¿Eres un experto en arte? ¡Demuéstralo!")
.internalRepresentation(QuestionCategory.ART)
.build(),
/*
QuestionCategoryDto.builder()
.name("Música")
.description("¿Eres un melómano? ¡Demuéstralo!")
.internalRepresentation(QuestionCategory.MUSIC)
.build(),
.build(),*/
QuestionCategoryDto.builder()
.name("Geografía")
.description("¿Eres un experto en geografía? ¡Demuéstralo!")
Expand Down
16 changes: 14 additions & 2 deletions api/src/main/java/lab/en2b/quizapi/game/GameService.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package lab.en2b.quizapi.game;

import lab.en2b.quizapi.commons.exceptions.InternalApiErrorException;
import lab.en2b.quizapi.commons.user.UserService;
import lab.en2b.quizapi.commons.utils.GameModeUtils;
import lab.en2b.quizapi.game.dtos.*;
import lab.en2b.quizapi.game.mappers.GameResponseDtoMapper;
import lab.en2b.quizapi.questions.question.Question;
import lab.en2b.quizapi.questions.question.QuestionService;
import lab.en2b.quizapi.questions.question.dtos.QuestionCategoryDto;
import lab.en2b.quizapi.questions.question.dtos.QuestionResponseDto;
Expand Down Expand Up @@ -55,18 +57,28 @@ public GameResponseDto newGame(String lang, GameMode gamemode, CustomGameDto new
* @param authentication the authentication of the user
* @return the game with the new round started
*/
@Transactional
public GameResponseDto startRound(Long id, Authentication authentication) {
// Get the game by id and user
Game game = gameRepository.findByIdForUser(id, userService.getUserByAuthentication(authentication).getId()).orElseThrow();
// Check if the game should be over
wasGameMeantToBeOver(game);
// Start a new round
game.newRound(questionService.findRandomQuestion(game.getLanguage(),game.getQuestionCategoriesForGamemode()));

game.newRound(generateQuestionForGame(game));
return gameResponseDtoMapper.apply(gameRepository.save(game));
}

private Question generateQuestionForGame(Game game){
Optional<Question> question = questionService.findRandomQuestion(game.getLanguage(),game.getQuestionCategoriesForGamemode());
if(question.isPresent()){
return question.get();
} else {
game.isGameOver();
gameRepository.save(game);
throw new InternalApiErrorException("Could not find a question for the game");
}
}

/**
* Gets the current question for the game
* @param id the id of the game to get the question for
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@

public enum QuestionCategory {
//HISTORY, GEOGRAPHY, SCIENCE, MATH, LITERATURE, ART, SPORTS, MUSIC, MOVIES, TV, POLITICS, OTHER
GEOGRAPHY, SPORTS, MUSIC, ART, VIDEOGAMES
GEOGRAPHY, SPORTS, //MUSIC,
ART, VIDEOGAMES
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
import org.springframework.data.jpa.repository.Query;

import java.util.List;
import java.util.Optional;

public interface QuestionRepository extends JpaRepository<Question,Long> {
@Query(value = "SELECT q.* FROM questions q INNER JOIN answers a ON q.correct_answer_id=a.id WHERE a.language = ?1 " +
"AND q.question_category IN ?2 " +
" ORDER BY RANDOM() LIMIT 1 ", nativeQuery = true)
Question findRandomQuestion(String lang, List<String> questionCategories);
Optional<Question> findRandomQuestion(String lang, List<String> questionCategories);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

@Service
@RequiredArgsConstructor
Expand Down Expand Up @@ -42,7 +43,10 @@ else if(question.getAnswers().stream().noneMatch(i -> i.getId().equals(answerDto
}

public QuestionResponseDto getRandomQuestion(String lang) {
return questionResponseDtoMapper.apply(findRandomQuestion(lang, List.of(QuestionCategory.values())));
Optional<Question> q = findRandomQuestion(lang, List.of(QuestionCategory.values()));
if(q.isEmpty())
throw new InternalApiErrorException("No questions found");
return questionResponseDtoMapper.apply(q.get());
}

/**
Expand All @@ -51,15 +55,13 @@ public QuestionResponseDto getRandomQuestion(String lang) {
* @return The random question
*/

public Question findRandomQuestion(String language, List<QuestionCategory> questionCategoriesForCustom) {
public Optional<Question> findRandomQuestion(String language, List<QuestionCategory> questionCategoriesForCustom) {
if (language==null || language.isBlank()) {
language = "en";
}
Question q = questionRepository.findRandomQuestion(language,questionCategoriesForCustom.stream().map(Enum::toString).toList());
if(q==null) {
throw new InternalApiErrorException("No questions found for the specified language!");
}
loadAnswers(q);
Optional<Question> q = questionRepository.findRandomQuestion(language,questionCategoriesForCustom.stream().map(Enum::toString).toList());
q.ifPresent(this::loadAnswers);

return q;
}

Expand Down
39 changes: 25 additions & 14 deletions api/src/test/java/lab/en2b/quizapi/game/GameServiceTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package lab.en2b.quizapi.game;

import ch.qos.logback.core.util.TimeUtil;
import lab.en2b.quizapi.commons.exceptions.InternalApiErrorException;
import lab.en2b.quizapi.commons.user.User;
import lab.en2b.quizapi.commons.user.dtos.UserResponseDto;
import lab.en2b.quizapi.commons.user.UserService;
Expand Down Expand Up @@ -253,7 +254,7 @@ public void isGameActiveNoActiveGame(){
public void startRound(){
when(gameRepository.findByIdForUser(any(), any())).thenReturn(Optional.of(defaultGame));
when(gameRepository.save(any())).thenAnswer(invocation -> invocation.getArgument(0));
when(questionService.findRandomQuestion(any(),any())).thenReturn(defaultQuestion);
when(questionService.findRandomQuestion(any(),any())).thenReturn(Optional.of(defaultQuestion));
when(userService.getUserByAuthentication(authentication)).thenReturn(defaultUser);
GameResponseDto gameDto = gameService.startRound(1L, authentication);
GameResponseDto result = defaultGameResponseDto;
Expand All @@ -262,11 +263,18 @@ public void startRound(){
result.setRoundStartTime(Instant.ofEpochMilli(defaultGame.getRoundStartTime()).toString());
assertEquals(result, gameDto);
}

@Test
public void startRoundNoQuestionCouldBeGenerated(){
when(gameRepository.findByIdForUser(any(), any())).thenReturn(Optional.of(defaultGame));
when(gameRepository.save(any())).thenAnswer(invocation -> invocation.getArgument(0));
when(userService.getUserByAuthentication(authentication)).thenReturn(defaultUser);
when(questionService.findRandomQuestion(any(),any())).thenReturn(Optional.empty());
assertThrows(InternalApiErrorException.class, () -> gameService.startRound(1L, authentication));
}
@Test
public void startRoundGameOver(){
when(gameRepository.findByIdForUser(any(), any())).thenReturn(Optional.of(defaultGame));
when(questionService.findRandomQuestion(any(),any())).thenReturn(defaultQuestion);
when(questionService.findRandomQuestion(any(),any())).thenReturn(Optional.of(defaultQuestion));
when(userService.getUserByAuthentication(authentication)).thenReturn(defaultUser);
defaultGame.setActualRound(10L);
assertThrows(IllegalStateException.class, () -> gameService.startRound(1L,authentication));
Expand All @@ -276,7 +284,7 @@ public void startRoundGameOver(){
public void startRoundWhenRoundNotFinished(){
when(gameRepository.findByIdForUser(any(), any())).thenReturn(Optional.of(defaultGame));
when(gameRepository.save(any())).thenAnswer(invocation -> invocation.getArgument(0));
when(questionService.findRandomQuestion(any(),any())).thenReturn(defaultQuestion);
when(questionService.findRandomQuestion(any(),any())).thenReturn(Optional.of(defaultQuestion));
when(userService.getUserByAuthentication(authentication)).thenReturn(defaultUser);
gameService.startRound(1L,authentication);
assertThrows(IllegalStateException.class, () -> gameService.startRound(1L,authentication));
Expand All @@ -286,7 +294,7 @@ public void startRoundWhenRoundNotFinished(){
public void getCurrentQuestion() {
when(gameRepository.findByIdForUser(any(), any())).thenReturn(Optional.of(defaultGame));
when(gameRepository.save(any())).thenAnswer(invocation -> invocation.getArgument(0));
when(questionService.findRandomQuestion(any(),any())).thenReturn(defaultQuestion);
when(questionService.findRandomQuestion(any(),any())).thenReturn(Optional.of(defaultQuestion));
when(userService.getUserByAuthentication(authentication)).thenReturn(defaultUser);
gameService.startRound(1L,authentication);
QuestionResponseDto questionDto = gameService.getCurrentQuestion(1L,authentication);
Expand All @@ -312,7 +320,7 @@ public void getCurrentQuestionRoundNotStarted() {
public void getCurrentQuestionRoundFinished() {
when(gameRepository.findByIdForUser(any(), any())).thenReturn(Optional.of(defaultGame));
when(gameRepository.save(any())).thenAnswer(invocation -> invocation.getArgument(0));
when(questionService.findRandomQuestion(any(),any())).thenReturn(defaultQuestion);
when(questionService.findRandomQuestion(any(),any())).thenReturn(Optional.of(defaultQuestion));
when(userService.getUserByAuthentication(authentication)).thenReturn(defaultUser);
gameService.startRound(1L,authentication);
defaultGame.setRoundStartTime(Instant.now().minusSeconds(100).toEpochMilli());
Expand All @@ -324,7 +332,7 @@ public void getCurrentQuestionGameFinished() {
when(gameRepository.findByIdForUser(any(), any())).thenReturn(Optional.of(defaultGame));
when(userService.getUserByAuthentication(authentication)).thenReturn(defaultUser);
when(gameRepository.save(any())).thenAnswer(invocation -> invocation.getArgument(0));
when(questionService.findRandomQuestion(any(),any())).thenReturn(defaultQuestion);
when(questionService.findRandomQuestion(any(),any())).thenReturn(Optional.of(defaultQuestion));
gameService.startRound(1L,authentication);
defaultGame.setGameOver(true);
defaultGame.setActualRound(10L);
Expand All @@ -336,7 +344,7 @@ public void answerQuestionCorrectly(){
when(gameRepository.findByIdForUser(any(), any())).thenReturn(Optional.of(defaultGame));
when(gameRepository.save(any())).thenAnswer(invocation -> invocation.getArgument(0));
when(userService.getUserByAuthentication(authentication)).thenReturn(defaultUser);
when(questionService.findRandomQuestion(any(),any())).thenReturn(defaultQuestion);
when(questionService.findRandomQuestion(any(),any())).thenReturn(Optional.of(defaultQuestion));
gameService.newGame(null,null,null,authentication);
gameService.startRound(1L, authentication);
gameService.answerQuestion(1L, new GameAnswerDto(1L), authentication);
Expand All @@ -350,7 +358,7 @@ public void answerQuestionIncorrectly(){
when(gameRepository.findByIdForUser(any(), any())).thenReturn(Optional.of(defaultGame));
when(gameRepository.save(any())).thenAnswer(invocation -> invocation.getArgument(0));
when(userService.getUserByAuthentication(authentication)).thenReturn(defaultUser);
when(questionService.findRandomQuestion(any(),any())).thenReturn(defaultQuestion);
when(questionService.findRandomQuestion(any(),any())).thenReturn(Optional.of(defaultQuestion));
gameService.newGame(null,null,null,authentication);
gameService.startRound(1L, authentication);
gameService.answerQuestion(1L, new GameAnswerDto(2L), authentication);
Expand All @@ -364,7 +372,7 @@ public void answerQuestionWhenGameHasFinished(){
when(gameRepository.findByIdForUser(any(), any())).thenReturn(Optional.of(defaultGame));
when(gameRepository.save(any())).thenAnswer(invocation -> invocation.getArgument(0));
when(userService.getUserByAuthentication(authentication)).thenReturn(defaultUser);
when(questionService.findRandomQuestion(any(),any())).thenReturn(defaultQuestion);
when(questionService.findRandomQuestion(any(),any())).thenReturn(Optional.of(defaultQuestion));
gameService.newGame(null,null,null,authentication);
gameService.startRound(1L, authentication);
defaultGame.setGameOver(true);
Expand All @@ -377,7 +385,7 @@ public void answerQuestionLastRound(){
when(gameRepository.findByIdForUser(any(), any())).thenReturn(Optional.of(defaultGame));
when(gameRepository.save(any())).thenAnswer(invocation -> invocation.getArgument(0));
when(userService.getUserByAuthentication(authentication)).thenReturn(defaultUser);
when(questionService.findRandomQuestion(any(),any())).thenReturn(defaultQuestion);
when(questionService.findRandomQuestion(any(),any())).thenReturn(Optional.of(defaultQuestion));
gameService.newGame(null,null,null,authentication);
defaultGame.setActualRound(8L);
gameService.startRound(1L, authentication);
Expand All @@ -390,7 +398,7 @@ public void answerQuestionWhenRoundHasFinished(){
when(gameRepository.findByIdForUser(any(), any())).thenReturn(Optional.of(defaultGame));
when(gameRepository.save(any())).thenAnswer(invocation -> invocation.getArgument(0));
when(userService.getUserByAuthentication(authentication)).thenReturn(defaultUser);
when(questionService.findRandomQuestion(any(),any())).thenReturn(defaultQuestion);
when(questionService.findRandomQuestion(any(),any())).thenReturn(Optional.of(defaultQuestion));
gameService.newGame(null,null,null,authentication);
gameService.startRound(1L, authentication);
defaultGame.setRoundStartTime(Instant.now().minusSeconds(100).toEpochMilli());
Expand All @@ -402,7 +410,7 @@ public void answerQuestionInvalidId(){
when(gameRepository.findByIdForUser(any(), any())).thenReturn(Optional.of(defaultGame));
when(gameRepository.save(any())).thenAnswer(invocation -> invocation.getArgument(0));
when(userService.getUserByAuthentication(authentication)).thenReturn(defaultUser);
when(questionService.findRandomQuestion(any(),any())).thenReturn(defaultQuestion);
when(questionService.findRandomQuestion(any(),any())).thenReturn(Optional.of(defaultQuestion));
gameService.newGame(null,null,null,authentication);
gameService.startRound(1L, authentication);
assertThrows(IllegalArgumentException.class, () -> gameService.answerQuestion(1L, new GameAnswerDto(3L), authentication));
Expand All @@ -413,6 +421,7 @@ public void changeLanguage(){
when(gameRepository.findByIdForUser(any(), any())).thenReturn(Optional.of(defaultGame));
when(gameRepository.save(any())).thenAnswer(invocation -> invocation.getArgument(0));
when(userService.getUserByAuthentication(authentication)).thenReturn(defaultUser);
when(questionService.findRandomQuestion(any(),any())).thenReturn(Optional.of(defaultQuestion));
gameService.newGame(null,null,null,authentication);
gameService.startRound(1L, authentication);
gameService.changeLanguage(1L, "es", authentication);
Expand All @@ -424,6 +433,7 @@ public void changeLanguage(){
public void changeLanguageGameOver(){
when(gameRepository.findByIdForUser(any(), any())).thenReturn(Optional.of(defaultGame));
when(gameRepository.save(any())).thenAnswer(invocation -> invocation.getArgument(0));
when(questionService.findRandomQuestion(any(),any())).thenReturn(Optional.of(defaultQuestion));
when(userService.getUserByAuthentication(authentication)).thenReturn(defaultUser);

gameService.newGame(null,null,null,authentication);
Expand All @@ -448,7 +458,7 @@ public void getGameDetails(){
when(gameRepository.findByIdForUser(any(), any())).thenReturn(Optional.of(defaultGame));
when(userService.getUserByAuthentication(authentication)).thenReturn(defaultUser);
when(gameRepository.save(any())).thenAnswer(invocation -> invocation.getArgument(0));

when(questionService.findRandomQuestion(any(),any())).thenReturn(Optional.of(defaultQuestion));
GameResponseDto gameDto = gameService.newGame(null,null,null,authentication);
gameService.startRound(1L, authentication);
gameService.getGameDetails(1L, authentication);
Expand All @@ -461,6 +471,7 @@ public void getGameDetailsInvalidId(){
when(gameRepository.findByIdForUser(1L, 1L)).thenReturn(Optional.of(defaultGame));
when(userService.getUserByAuthentication(authentication)).thenReturn(defaultUser);
when(gameRepository.save(any())).thenAnswer(invocation -> invocation.getArgument(0));
when(questionService.findRandomQuestion(any(),any())).thenReturn(Optional.of(defaultQuestion));
gameService.newGame(null,null,null,authentication);
gameService.startRound(1L, authentication);
assertThrows(NoSuchElementException.class, () -> gameService.getGameDetails(2L, authentication));
Expand Down
Loading

0 comments on commit 678d505

Please sign in to comment.