/z now lists all games opened and closed

also fixed two bugs in VoteHandler (Array out of Bound in GhostNPC and in ClientVoteData)
This commit is contained in:
Seraina 2022-04-15 18:47:05 +02:00
parent 1ba30663be
commit 7c70b276cd
12 changed files with 105 additions and 48 deletions

View File

@ -23,8 +23,9 @@ Votes are held in the night for the ghosts to decide who will be next and during
* /w _username$message_ - sends a message to the specified user only. * /w _username$message_ - sends a message to the specified user only.
* /g - create (&join) a new lobby. * /g - create (&join) a new lobby.
* /j _1_ - join lobby 1. To join lobby 2, use /j _2_, etc. * /j _1_ - join lobby 1. To join lobby 2, use /j _2_, etc.
* /l - list all connected clients and all lobbies * /l - list all connected clients and all lobbies and their status
* /p - list all players in your lobby. * /p - list all players in your lobby.
* /z - list all games on the server and their status
* /e - exit your lobby * /e - exit your lobby
* /n _name_ - changes player name. If unavailable, it adds a fun and quirky suffix * /n _name_ - changes player name. If unavailable, it adds a fun and quirky suffix
* /q - quit * /q - quit

View File

@ -1,6 +1,9 @@
package ch.unibas.dmi.dbis.cs108.gamelogic; package ch.unibas.dmi.dbis.cs108.gamelogic;
import ch.unibas.dmi.dbis.cs108.BudaLogConfig;
import java.util.Arrays; import java.util.Arrays;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/** /**
* Data structure that is used to store clientVotes in an array, where the index correponds to the * Data structure that is used to store clientVotes in an array, where the index correponds to the
@ -8,6 +11,8 @@ import java.util.Arrays;
*/ */
public class ClientVoteData { public class ClientVoteData {
public static final Logger LOGGER = LogManager.getLogger();
public static final BudaLogConfig l = new BudaLogConfig(LOGGER);
private int[] vote; //saves vote of clientHandler for later transmission to passenger, by default MAX_VALUE, index corresponds to Passenger position private int[] vote; //saves vote of clientHandler for later transmission to passenger, by default MAX_VALUE, index corresponds to Passenger position
private boolean[] hasVoted; //saves hasVoted status of clientHandler for later transmission to passenger, by default false, index corresponds to Passenger position private boolean[] hasVoted; //saves hasVoted status of clientHandler for later transmission to passenger, by default false, index corresponds to Passenger position
@ -33,7 +38,14 @@ public class ClientVoteData {
* @param vote the vote value * @param vote the vote value
*/ */
public void setVote(int position, int vote) { public void setVote(int position, int vote) {
if (vote == Integer.MAX_VALUE) {
setHasVoted(position, false);
}
try {
this.vote[position] = vote; this.vote[position] = vote;
} catch (IndexOutOfBoundsException e) {
LOGGER.info("Position is: " + position);
}
} }
/** /**

View File

@ -19,9 +19,7 @@ public class Game implements Runnable {
/** /**
* Can be extended for optional Game-settings * Can be extended for optional Game-settings
**/ **/
protected final int nrOfPlayers; //sets the length of the train
protected final int nrOfGhosts; // sets how many Ghosts we start witch
protected int nrOfUsers; // safes how many clients are active in this Game
protected GameState gameState; protected GameState gameState;
protected boolean isDay = false; //false means it is night, it is night by default protected boolean isDay = false; //false means it is night, it is night by default
protected VoteHandler voteHandler = new VoteHandler(); protected VoteHandler voteHandler = new VoteHandler();
@ -38,36 +36,23 @@ public class Game implements Runnable {
*/ */
public Game(int nrOfPlayers, int nrOfGhosts, int nrOfUsers, Lobby lobby) public Game(int nrOfPlayers, int nrOfGhosts, int nrOfUsers, Lobby lobby)
throws TrainOverflow { //ToDo: Who handles Exception how and where throws TrainOverflow { //ToDo: Who handles Exception how and where
this.nrOfPlayers = nrOfPlayers;
this.nrOfGhosts = nrOfGhosts;
this.nrOfUsers = nrOfUsers;
this.gameState = new GameState(nrOfPlayers, nrOfGhosts, nrOfUsers); this.gameState = new GameState(nrOfPlayers, nrOfGhosts, nrOfUsers);
this.lobby = lobby; this.lobby = lobby;
nameCounter++; nameCounter++;
this.name = "Game-" + nameCounter; this.name = "Game" + nameCounter;
} }
public GameState getGameState() { public GameState getGameState() {
return gameState; return gameState;
} }
public int getNrOfGhosts() {
return nrOfGhosts;
}
public int getNrOfPlayers() {
return nrOfPlayers;
}
public int getNrOfUsers() {
return nrOfUsers;
}
public Lobby getLobby() { public Lobby getLobby() {
return lobby; return lobby;
} }
public boolean getIsDay() {return isDay;} public boolean getIsDay() {return isDay; }
public String getName() {return name; }
public void setDay(boolean day) { public void setDay(boolean day) {
isDay = day; isDay = day;

View File

@ -76,6 +76,18 @@ public class GameState {
return train; return train;
} }
public int getNrOfUsers() {
return nrOfUsers;
}
public int getNrOfPlayers() {
return nrOfPlayers;
}
public int getNrOfGhosts() {
return nrOfGhosts;
}
/** /**
* *
* *

View File

@ -11,7 +11,7 @@ import org.apache.logging.log4j.Logger;
* vote / ghost vote) and handles votes accordingly. - Sends voting request to passengers that need * vote / ghost vote) and handles votes accordingly. - Sends voting request to passengers that need
* to be concerned - collects voting results - calculates who was voted for - decides consequence of * to be concerned - collects voting results - calculates who was voted for - decides consequence of
* vote: - Is it OG ghost: humans win - Is it last human: ghosts win - Is it just a human: message * vote: - Is it OG ghost: humans win - Is it last human: ghosts win - Is it just a human: message
* "x is a human" - Is it a peasant ghost -> kickoff * "x is a human" - Is it a peasant ghost - kickoff
* *
* <p>(All messages going to Clients are handled via ServerGameInfoHandler) * <p>(All messages going to Clients are handled via ServerGameInfoHandler)
* *
@ -44,7 +44,7 @@ public class VoteHandler {
* @param passengers: passengers on the train * @param passengers: passengers on the train
*/ */
public void ghostVote(Passenger[] passengers, Game game) { public String ghostVote(Passenger[] passengers, Game game) {
LOGGER.debug("ghostVote has been called"); LOGGER.debug("ghostVote has been called");
LOGGER.info(game.getGameState().toString()); LOGGER.info(game.getGameState().toString());
@ -106,12 +106,23 @@ public class VoteHandler {
n.noiseNotifier(passengers, passengers[i], g, game); n.noiseNotifier(passengers, passengers[i], g, game);
} }
} }
int humanCounter = 0;
for(Passenger passenger : passengers) {
if(!passenger.getIsGhost()) { //if it is a human
humanCounter++;
}
}
if (humanCounter == 0) {
return ClientGameInfoHandler.gameOverGhostsWin;
}
LOGGER.info(game.getGameState().toString()); LOGGER.info(game.getGameState().toString());
// set hasVoted to false for all passengers for future votings // set hasVoted to false for all passengers for future votings
for (Passenger passenger : passengers) { for (Passenger passenger : passengers) {
passenger.setHasVoted(false); passenger.setHasVoted(false);
} }
return "";
} }
/** /**

View File

@ -43,15 +43,19 @@ public class GhostNPC extends Ghost {
* but only for positions where there aren't any ghosts and sets hasVoted to true * but only for positions where there aren't any ghosts and sets hasVoted to true
* TODO: Make NPC smarter * TODO: Make NPC smarter
*/ */
public void vote(Game game){ public void vote(Game game) {
int ghostCounter = 0; int ghostCounter = 0;
Passenger[] train = game.getGameState().getPassengerTrain(); Passenger[] train = game.getGameState().getPassengerTrain();
for(Passenger passenger : train) { for (Passenger passenger : train) {
if(passenger.isGhost) { if (passenger.isGhost) {
ghostCounter++; ghostCounter++;
} }
} }
int[] humanPositions = new int[game.getNrOfPlayers() - ghostCounter ]; int[] humanPositions = new int[game.getGameState().getNrOfPlayers() - ghostCounter];
if (humanPositions.length == 0) {
vote = Integer.MAX_VALUE;
} else {
int j = 0; int j = 0;
for (int i = 0; i < train.length; i++) { for (int i = 0; i < train.length; i++) {
if (!train[i].isGhost) { //is human if (!train[i].isGhost) { //is human
@ -59,11 +63,12 @@ public class GhostNPC extends Ghost {
j++; j++;
} }
} }
int randomPosition = (int) (Math.random()*humanPositions.length); int randomPosition = (int) (Math.random() * humanPositions.length);
vote = humanPositions[randomPosition]; vote = humanPositions[randomPosition];
hasVoted = true; hasVoted = true;
LOGGER.info("GhostNPC at Position: " + this.getPosition() + " has voted for: " + vote); LOGGER.info("GhostNPC at Position: " + this.getPosition() + " has voted for: " + vote);
} }
}
/** /**
* Decides what to do when a noise ist heard, currently just always broadcasts it * Decides what to do when a noise ist heard, currently just always broadcasts it

View File

@ -53,7 +53,7 @@ public class GhostPlayer extends Ghost {
public void getVoteFromGameState(ClientVoteData clientVoteData, Game game) { public void getVoteFromGameState(ClientVoteData clientVoteData, Game game) {
vote = clientVoteData.getVote()[position]; vote = clientVoteData.getVote()[position];
hasVoted = clientVoteData.getHasVoted()[position]; hasVoted = clientVoteData.getHasVoted()[position];
clientVoteData.setVote(position,Integer.MAX_VALUE); clientVoteData.setVote(position, Integer.MAX_VALUE);
clientVoteData.setHasVoted(position,false); clientVoteData.setHasVoted(position,false);
LOGGER.info("Ghost at Pos: " + position + " has voted for: " + vote); LOGGER.info("Ghost at Pos: " + position + " has voted for: " + vote);
/* /*

View File

@ -65,6 +65,9 @@ public class MessageFormatter {
case "/p": case "/p":
stringBuilder.append(Protocol.listPlayersInLobby); stringBuilder.append(Protocol.listPlayersInLobby);
break; break;
case "/z":
stringBuilder.append(Protocol.listGames);
break;
case "/j": case "/j":
stringBuilder.append(Protocol.joinLobby + "$"); stringBuilder.append(Protocol.joinLobby + "$");
try { try {
@ -93,7 +96,6 @@ public class MessageFormatter {
break; break;
case "/s": case "/s":
stringBuilder.append(Protocol.startANewGame); stringBuilder.append(Protocol.startANewGame);
break; break;
default: default:
s = msg; s = msg;

View File

@ -122,10 +122,17 @@ public class Protocol {
/** /**
* A Client decides to start the game. * A Client decides to start the game. The game is started in the lobby the message came from.
* Only one game can be started per lobby at a time.
*/ */
public static final String startANewGame = "STGAM"; public static final String startANewGame = "STGAM";
/**
* Client request to see a list of all games, ongoing and finished.
*/
public static final String listGames = "LISTG";
/** /**
* Client informs server that they have voted and delivers this vote in the form of "CVOTE$position$vote" * Client informs server that they have voted and delivers this vote in the form of "CVOTE$position$vote"
*/ */

View File

@ -423,7 +423,7 @@ public class ClientHandler implements Runnable {
*/ */
public void listLobbies() { public void listLobbies() {
if (Lobby.lobbies.isEmpty()) { if (Lobby.lobbies.isEmpty()) {
sendAnnouncementToClient("No open Lobbies."); sendAnnouncementToClient("No Lobbies.");
} else { } else {
for (Lobby l : Lobby.lobbies) { for (Lobby l : Lobby.lobbies) {
String lobbyStatus = "closed"; String lobbyStatus = "closed";
@ -475,6 +475,32 @@ public class ClientHandler implements Runnable {
} }
} }
/**
* Lists all Games currenty running and already finished and displays it to the client handled by this
*/
public void listGames() {
if (Lobby.runningGames.isEmpty() && Lobby.finishedGames.isEmpty()) {
sendAnnouncementToClient("No Games");
} else {
sendAnnouncementToClient("Running Games:");
try {
for (Game runningGame : Lobby.runningGames) {
sendAnnouncementToClient(" - " + runningGame.getName() + ", Lobby" + runningGame.getLobby().getLobbyID());
}
} catch (Exception e) {
sendAnnouncementToClient(" - No running Games");
}
sendAnnouncementToClient("Finished Games");
try {
for (Game finishedGame : Lobby.finishedGames) {
sendAnnouncementToClient(" - " + finishedGame.getName() + ", Lobby" + finishedGame.getLobby().getLobbyID());
}
} catch (Exception e) {
sendAnnouncementToClient(" - No finished Games");
}
}
}
/** /**
* Closes the client's socket, in, and out. and removes from global list of clients. * Closes the client's socket, in, and out. and removes from global list of clients.
*/ */

View File

@ -111,6 +111,9 @@ public class JServerProtocolParser {
case Protocol.startANewGame: case Protocol.startANewGame:
h.startNewGame(); h.startNewGame();
break; break;
case Protocol.listGames:
h.listGames();
break;
default: default:
System.out.println("Received unknown command"); System.out.println("Received unknown command");
} }

View File

@ -108,13 +108,6 @@ public class Lobby {
return null; return null;
} }
public static HashSet<Game> getFinishedGames() {
return finishedGames;
}
public static HashSet<Game> getRunningGames() {
return runningGames;
}
/** /**
* Returns the game that the clients in this lobby are in * Returns the game that the clients in this lobby are in