Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiplayer bugs fixing (don't accept) #214

Closed
wants to merge 41 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
391f82f
frontEnd for multiplayer
uo288061 Apr 9, 2024
152e216
init backEnd for multiplayer
uo288061 Apr 9, 2024
3eb53d9
more backEnd for multiplayer
uo288061 Apr 9, 2024
06f209d
fixing backEnd for multiplayer (It is not yet implemented) done about…
uo288061 Apr 10, 2024
15c35d5
starting multiplayer lobby
uo288061 Apr 10, 2024
7c197e8
done multiplayer lobby, now the list of players updates automatically
uo288061 Apr 10, 2024
989fee5
fix some problems
uo288061 Apr 10, 2024
c1a4d4e
create and join buttons working correctly
uo288061 Apr 11, 2024
acd0e36
players can can play multiplayer games
uo288061 Apr 11, 2024
c46e273
The multiplayer mode is done but some bugs need to be fixed
uo288061 Apr 13, 2024
81accd1
Players with same multiplayerCode, have same questions
uo288061 Apr 14, 2024
4968265
Update multiplayerGame.html style
RicardoDiNu Apr 15, 2024
863dc8f
Update lobby.html style
RicardoDiNu Apr 15, 2024
db833af
Fix small bug of code validation (only numbers are permited)
RicardoDiNu Apr 15, 2024
586805e
Change multiFinished.html style
RicardoDiNu Apr 15, 2024
b32fa20
FinishGame bug fixed
RicardoDiNu Apr 16, 2024
33111ed
Duplicate multiFinished window bug fixed
RicardoDiNu Apr 16, 2024
db70848
multiFinished style update
RicardoDiNu Apr 16, 2024
b4b0d1d
Some endMultiGame logic added
RicardoDiNu Apr 16, 2024
01543f7
new entity on the dataBase (MultiplayerSession)
uo288061 Apr 23, 2024
f9ea290
Error fixed - new entity on the dataBase (MultiplayerSession)
uo288061 Apr 23, 2024
59e24bc
more changes
uo288061 Apr 23, 2024
fcb1a15
logic for MultiplayerSession done
uo288061 Apr 23, 2024
2773302
some problems fixed
uo288061 Apr 23, 2024
cdca207
frontend for multiplayerRanking.html done
uo288061 Apr 23, 2024
c1793ba
some important changes for multiplayer logic
uo288061 Apr 23, 2024
2b58429
all problems fixed (I think)
uo288061 Apr 24, 2024
147bb7d
small changes
uo288061 Apr 24, 2024
c85ee32
All multiplayerGame correct
uo288061 Apr 25, 2024
af999eb
cleaning code
uo288061 Apr 25, 2024
0a8e957
Merge remote-tracking branch 'origin/develop' into multiplayer-bugs-f…
uo288061 Apr 25, 2024
f92a7b1
problems solved
uo288061 Apr 25, 2024
4ea0663
unit tests for MultiplayerSession
uo288061 Apr 26, 2024
ccc1a72
unit tests for MultiplayerSession (fixed)
uo288061 Apr 26, 2024
704843a
MultiplayerSession Unit Tests - Entities
RicardoDiNu Apr 26, 2024
ba731ef
MultiplayerSession Unit Tests - GameService
RicardoDiNu Apr 26, 2024
e0f6fd7
MultiplayerSession Unit Tests - QuestionService
RicardoDiNu Apr 26, 2024
dfd89ec
MultiplayerSession Unit Tests - PlayerService(users)
RicardoDiNu Apr 26, 2024
05e25ee
MultiplayerSession Unit Tests - PlayerService(score)
RicardoDiNu Apr 26, 2024
183e050
MultiplayerSession Unit Tests - PlayerService(session and code)
RicardoDiNu Apr 26, 2024
025fecd
Merge branch 'develop' into multiplayer-bugs-fixing
RicardoDiNu Apr 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/main/java/com/uniovi/configuration/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.requestMatchers("/signup/**").permitAll()
.requestMatchers("/api/**").permitAll()
.requestMatchers("/game/**").authenticated()
.requestMatchers("/multiplayerGame/**").authenticated()
.requestMatchers("/lobby/**").authenticated()
.requestMatchers("/ranking/playerRanking").authenticated()
.requestMatchers("/player/admin/**").hasAuthority("ROLE_ADMIN")
.requestMatchers("/**").permitAll()
Expand Down
137 changes: 132 additions & 5 deletions src/main/java/com/uniovi/controllers/GameController.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package com.uniovi.controllers;

import com.uniovi.entities.GameSession;
import com.uniovi.entities.MultiplayerSession;
import com.uniovi.entities.Player;
import com.uniovi.entities.Question;
import com.uniovi.services.GameSessionService;
import com.uniovi.services.MultiplayerSessionService;
import com.uniovi.services.PlayerService;
import com.uniovi.services.QuestionService;
import jakarta.servlet.http.HttpSession;
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.web.bind.annotation.GetMapping;
Expand All @@ -16,19 +20,24 @@
import java.security.Principal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Optional;
import java.util.*;

@Controller
public class GameController {
private final QuestionService questionService;
private final GameSessionService gameSessionService;
private final PlayerService playerService;

private final MultiplayerSessionService multiplayerSessionService;

private boolean isMultiPlayer;

public GameController(QuestionService questionService, GameSessionService gameSessionService,
PlayerService playerService) {
PlayerService playerService, MultiplayerSessionService multiplayerSessionService) {
this.questionService = questionService;
this.gameSessionService = gameSessionService;
this.playerService = playerService;
this.multiplayerSessionService = multiplayerSessionService;
}


Expand All @@ -46,14 +55,116 @@ public String getGame(HttpSession session, Model model, Principal principal) {
}
} else {
gameSession = gameSessionService.startNewGame(getLoggedInPlayer(principal));
playerService.deleteMultiplayerCode(gameSession.getPlayer().getId());
session.setAttribute("gameSession", gameSession);

}

model.addAttribute("question", gameSession.getCurrentQuestion());
model.addAttribute("questionDuration", getRemainingTime(gameSession));
return "game/basicGame";
}

@GetMapping("/multiplayerGame")
public String getMultiplayerGame() {
return "game/multiplayerGame";
}

@GetMapping("/multiplayerGame/{code}")
public String joinMultiplayerGame(@PathVariable String code, HttpSession session, Principal principal, Model model) {
Optional<Player> player = playerService.getUserByUsername(principal.getName());
Player p = player.orElse(null);
isMultiPlayer=true;
if(playerService.changeMultiplayerCode(p.getId(),code)){
multiplayerSessionService.addToLobby(code,p.getId());
model.addAttribute("multiplayerGameCode",code);
session.setAttribute("multiplayerCode",code);
return "redirect:/game/lobby";
} else {
return "redirect:/multiplayerGame";
}
}

@GetMapping("/multiplayerGame/createGame")
public String createMultiplayerGame(HttpSession session, Principal principal, Model model) {
Optional<Player> player = playerService.getUserByUsername(principal.getName());
Player p = player.orElse(null);
String code=""+playerService.createMultiplayerGame(p.getId());
multiplayerSessionService.multiCreate(code,p.getId());
session.setAttribute("multiplayerCode",code);
isMultiPlayer=true;
return "redirect:/game/lobby";
}

@GetMapping("/startMultiplayerGame")
public String startMultiplayerGame(HttpSession session, Model model, Principal principal) {
GameSession gameSession = (GameSession) session.getAttribute("gameSession");
if(! isMultiPlayer){
return "index";
}
if (gameSession != null) {
if (checkUpdateGameSession(gameSession, session)) {
return "game/fragments/gameFinished";
}
} else {
gameSession = gameSessionService.startNewMultiplayerGame(getLoggedInPlayer(principal),
playerService.getUserByUsername(principal.getName()).get().getMultiplayerCode());
session.setAttribute("gameSession", gameSession);

}

model.addAttribute("question", gameSession.getCurrentQuestion());
model.addAttribute("questionDuration", getRemainingTime(gameSession));
return "game/basicGame";
}

@GetMapping("/multiplayerGame/endGame/{code}")
public String endMultiplayerGame(Model model,@PathVariable String code) {
model.addAttribute("code",code);
return "ranking/multiplayerRanking";
}
@GetMapping("/endGameList/{code}")
@ResponseBody
public Map<String, String> endMultiplayerGameTable(@PathVariable String code) {
Map<Player, Integer> playerScores = multiplayerSessionService.getPlayersWithScores(Integer.parseInt(code));
Map<String, String> playersNameWithScore=new HashMap<>();
for (Map.Entry<Player, Integer> player : playerScores.entrySet()) {
String playerName = player.getKey().getUsername();
String playerScoreValue;
if(player.getValue()==-1){
playerScoreValue="N/A";
}else{
playerScoreValue=""+player.getValue();
}
playersNameWithScore.put(playerName, playerScoreValue);
}
return playersNameWithScore;
}

@GetMapping("/game/lobby/{code}")
@ResponseBody
public List<String> updatePlayerList(@PathVariable String code) {
Map<Player,Integer> players= multiplayerSessionService.getPlayersWithScores(Integer.parseInt(code));
List<String> playerNames = new ArrayList<>();
for (Map.Entry<Player, Integer> player : players.entrySet()) {
playerNames.add(player.getKey().getUsername());
}
Collections.sort(playerNames);
return playerNames;
}
@GetMapping("/game/lobby")
public String createLobby( HttpSession session, Model model) {
int code = Integer.parseInt((String)session.getAttribute("multiplayerCode"));
List<Player> players=playerService.getUsersByMultiplayerCode(code);
model.addAttribute("players",players);
model.addAttribute("code",session.getAttribute("multiplayerCode"));
return "/game/lobby";
}

@GetMapping("/game/startMultiplayerGame")
public String startMultiplayerGame( HttpSession session, Model model) {
return "/game/lobby";
}

/**
* This method is used to check the answer for a specific question
Expand All @@ -65,7 +176,7 @@ public String getGame(HttpSession session, Model model, Principal principal) {
* shown or the timeOutFailure view is shown.
*/
@GetMapping("/game/{idQuestion}/{idAnswer}")
public String getCheckResult(@PathVariable Long idQuestion, @PathVariable Long idAnswer, Model model, HttpSession session) {
public String getCheckResult(@PathVariable Long idQuestion, @PathVariable Long idAnswer, Model model, HttpSession session,Principal principal) {
GameSession gameSession = (GameSession) session.getAttribute("gameSession");
if (gameSession == null) {
return "redirect:/game";
Expand Down Expand Up @@ -95,14 +206,30 @@ else if(questionService.checkAnswer(idQuestion, idAnswer)) {

session.setAttribute("hasJustAnswered", true);
gameSession.getNextQuestion();

return updateGame(model, session);
}

@GetMapping("/game/update")
public String updateGame(Model model, HttpSession session) {
public String updateGame(Model model, HttpSession session, Principal principal) {
GameSession gameSession = (GameSession) session.getAttribute("gameSession");
Question nextQuestion = gameSession.getCurrentQuestion();
if(nextQuestion == null && isMultiPlayer/*gameSession.getPlayer().getMultiplayerCode()!=null session.getAttribute("multiplayerCode") !=null*/){
gameSessionService.endGame(gameSession);

int code = Integer.parseInt((String)session.getAttribute("multiplayerCode"));
List<Player> players=playerService.getUsersByMultiplayerCode(code);
model.addAttribute("players",players);
model.addAttribute("code",session.getAttribute("multiplayerCode"));
session.removeAttribute("gameSession");

Optional<Player> player = playerService.getUserByUsername(principal.getName());
Player p = player.orElse(null);
playerService.setScoreMultiplayerCode(p.getId(),""+gameSession.getScore());
multiplayerSessionService.changeScore(p.getMultiplayerCode()+"",p.getId(),gameSession.getScore());
isMultiPlayer=false;
return "game/multiFinished";
}
if (nextQuestion == null) {
gameSessionService.endGame(gameSession);
session.removeAttribute("gameSession");
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/uniovi/dto/PlayerDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ public class PlayerDto {
@Schema(hidden = true)
private String passwordConfirm;

//@Schema(description = "code of group of the player", example = "5565")
//private Integer multiplayerCode;

@Schema(description = "Roles of the player", example = "[\"ROLE_USER\"]")
private String[] roles;
}
38 changes: 38 additions & 0 deletions src/main/java/com/uniovi/entities/MultiplayerSession.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.uniovi.entities;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

@Getter // getters para todas las propiedades
@Setter // setters para todas las propiedades
@Entity
public class MultiplayerSession {
@Id
@GeneratedValue
private Long id;
@Column
private String multiplayerCode;

@ElementCollection
@Column
private Map<Player, Integer> playerScores = new HashMap<>();

public MultiplayerSession() {}

public MultiplayerSession(String code, Player p) {
this.multiplayerCode=code;
playerScores.put(p,-1);

}

public void addPlayer(Player p){
playerScores.put(p,-1);
}
}
9 changes: 9 additions & 0 deletions src/main/java/com/uniovi/entities/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ public class Player implements JsonEntity {
@NotEmpty
private String password;

@Column
private Integer multiplayerCode;

@Column
private String scoreMultiplayerCode;


@ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
private Set<Role> roles = new HashSet<>();

Expand All @@ -42,6 +49,8 @@ public class Player implements JsonEntity {
@OneToOne(cascade = CascadeType.ALL, mappedBy = "player")
private ApiKey apiKey;



// Transient: no se almacena en la base de datos
@Transient
private String passwordConfirm;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.uniovi.repositories;

import com.uniovi.entities.GameSession;
import com.uniovi.entities.MultiplayerSession;
import com.uniovi.entities.Player;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;

import java.util.List;

public interface MultiplayerSessionRepository extends CrudRepository<MultiplayerSession, Long> {
MultiplayerSession findByMultiplayerCode(String code);
}

4 changes: 3 additions & 1 deletion src/main/java/com/uniovi/repositories/PlayerRepository.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package com.uniovi.repositories;

import com.uniovi.entities.Player;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.CrudRepository;

public interface PlayerRepository extends CrudRepository<Player, Long> {
Player findByEmail(String email);
Player findByUsername(String nickname);

@Query("SELECT player FROM Player player WHERE player.multiplayerCode=:multiplayerCode")
Iterable<Player> findAllByMultiplayerCode(int multiplayerCode);
Page<Player> findAll(Pageable pageable);
}
3 changes: 3 additions & 0 deletions src/main/java/com/uniovi/services/GameSessionService.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,8 @@ public interface GameSessionService {
Page<GameSession> getPlayerRanking(Pageable pageable, Player player);

GameSession startNewGame(Player player);

GameSession startNewMultiplayerGame(Player player, int code);

void endGame(GameSession gameSession);
}
22 changes: 22 additions & 0 deletions src/main/java/com/uniovi/services/MultiplayerSessionService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.uniovi.services;

import com.uniovi.entities.GameSession;
import com.uniovi.entities.MultiplayerSession;
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.List;
import java.util.Map;

@Service
public interface MultiplayerSessionService {

Map<Player, Integer> getPlayersWithScores(int multiplayerCode);
void multiCreate(String code, Long id);

void addToLobby(String code, Long id);

void changeScore(String code,Long id,int score);
}
22 changes: 22 additions & 0 deletions src/main/java/com/uniovi/services/PlayerService.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ public interface PlayerService {
*/
List<Player> getUsers();


/**
* Get all the players in the database with same multiplayerCode
* @return A list with the players
*/
List<Player> getUsersByMultiplayerCode(int multiplayerCode);

/**
* Get a player by its id
* @param id The id of the player
Expand Down Expand Up @@ -69,6 +76,21 @@ public interface PlayerService {
*/
void updatePlayer(Long id, PlayerDto playerDto);

/**
* Update the multiplayerCode of a player
* @param id The id of the player to update
* @param code The new multiplayerCode of the player
*/
boolean changeMultiplayerCode(Long id, String code);

String getScoreMultiplayerCode(Long id);

void setScoreMultiplayerCode(Long id, String score);

int createMultiplayerGame(Long id);

void deleteMultiplayerCode(Long id);

/**
* Delete a player from the database
* @param id The id of the player to delete
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/uniovi/services/QuestionService.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ public interface QuestionService {
*/
List<Question> getRandomQuestions(int num);

List<Question> getRandomMultiplayerQuestions(int num, int code);

/**
* Check if the answer is correct
* @param idquestion The id of the question
Expand Down
Loading
Loading