OnlineMultiplayerScreenProvider.java
package com.github.quizclash.application.screen.provider;
import com.github.quizclash.application.QuizGame;
import com.github.quizclash.application.TerminationException;
import com.github.quizclash.application.room.*;
import com.github.quizclash.application.screen.*;
import com.github.quizclash.application.screen.menu.MenuCreator;
import com.github.quizclash.application.screen.menu.OnlineMultiplayerMenuEnum;
import com.github.quizclash.domain.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
public class OnlineMultiplayerScreenProvider implements ScreenProvider, GameRoomListener {
private final Repository repository;
private final ScreenFactory screenFactory;
private final GameRoomManager gameRoomManager;
private final User playingUser;
private GameRoom gameRoom;
private QuizGame onlineQuizGame;
public OnlineMultiplayerScreenProvider(Repository repository,
ScreenFactory screenFactory,
GameRoomManager gameRoomManager) {
this.repository = repository;
this.screenFactory = screenFactory;
this.gameRoomManager = gameRoomManager;
this.playingUser = repository.getUserRepository().getUsers().get(0);
}
@Override
public void execute() {
String menuTitle = "What do you want to do?";
MenuCreator menuCreator = new MenuCreator(menuTitle, OnlineMultiplayerMenuEnum.values(),
screenFactory);
int selection = menuCreator.displayAndGetSelection();
try {
if (selection == 1) {
this.createNewRoom();
} else {
this.joinRoom();
}
gameRoom.addListener(this);
gameRoom.waitForGameToFinish();
List<String> lines = new ArrayList<>();
Player[] players = onlineQuizGame.getPlayers();
for (Player player : players) {
lines.add(String.format("%s - %d points", player.getPlayerName(),
player.getCurrentScore().getIntScore()));
}
screenFactory.createInformationScreen("Result", lines).render();
} catch (GameRoomCreationException e) {
List<String> exceptionMessage = List.of("Room creation was not possible");
screenFactory.createInformationScreen("Operation failed", exceptionMessage).render();
} catch (GameRoomJoinException e) {
List<String> exceptionMessage = List.of("Joining the room was not possible");
screenFactory.createInformationScreen("Operation failed", exceptionMessage).render();
}
}
@Override
public ScreenProviderType getNextScreenProviderType() {
return ScreenProviderType.MENU;
}
private void createNewRoom() throws GameRoomCreationException, GameRoomJoinException {
TextInputScreen createRoomScreen = screenFactory.createTextInputScreen(
"Create a new room by giving it a name", "Enter name for new room");
createRoomScreen.render();
String roomName = createRoomScreen.getTextInput().getActionValue();
NumberInputScreen amountOfPlayersScreen = screenFactory.createNumberInputScreen(
"Define with how many players you want to play", "Amount of players");
amountOfPlayersScreen.render();
int amountOfPlayers = amountOfPlayersScreen.getNumberInput().getActionValue();
gameRoom = gameRoomManager.createRoom(playingUser, roomName, amountOfPlayers);
}
private void joinRoom() throws GameRoomJoinException {
TextInputScreen joinRoomScreen = screenFactory.createTextInputScreen(
"Join a room by entering the game code of the desired room", "Enter room code");
joinRoomScreen.render();
String roomCode = joinRoomScreen.getTextInput().getActionValue();
gameRoom = gameRoomManager.joinRoom(playingUser, roomCode);
}
private void displayCategorySelection(boolean isLocalTurn) {
String playerName = onlineQuizGame.getCurrentPlayer().getPlayerName();
Screen categoryScreen;
List<? extends Displayable> remainingCategories = onlineQuizGame.getRemainingGameCategories();
if (isLocalTurn) {
String screenName = playerName + ", select category";
categoryScreen = screenFactory.createOptionScreen(screenName, remainingCategories);
} else {
String screenName = playerName + " is selecting category";
List<String> categoryLines = IntStream
.range(0, remainingCategories.size())
.mapToObj(i -> (i + 1) + ") " + remainingCategories.get(i).getDisplayName())
.toList();
categoryScreen = screenFactory.createInformationScreen(screenName, categoryLines, false);
}
categoryScreen.render();
if (isLocalTurn) {
int action = ((OptionScreen) categoryScreen).getOptionInput().getActionValue();
onlineQuizGame.setCurrentCategory(action - 1);
gameRoom.sendSelectedCategoryId(onlineQuizGame.getCurrentCategory().getId());
}
}
@Override
public void onJoinedRoom() {
String roomName = gameRoom.getRoomName();
String roomCode = gameRoom.getCode();
List<String> displayText = List.of("Your room with the name " + roomName + " is ready",
"Invite other players by giving them the code " + roomCode);
screenFactory.createInformationScreen("Room ready!", displayText, false).render();
}
@Override
public void onUpdatePlayers() {
String roomName = gameRoom.getRoomName();
String roomCode = gameRoom.getCode();
List<User> users = gameRoom.getPlayers();
List<String> userText = users.stream().map(User::getName).toList();
screenFactory
.createInformationScreen("Room: " + roomName + " (" + roomCode + ")", userText, false)
.render();
}
@Override
public void onGameStart() {
CategoryRepository categoryRepository = gameRoom.getRoomCategoryRepository();
List<User> usersToPlay = gameRoom.getPlayers();
Player[] players = usersToPlay
.stream()
.map(user -> new Player(user.getName()))
.toArray(Player[]::new);
onlineQuizGame = new QuizGame(categoryRepository, 4 * players.length, players);
}
@Override
public void onGameTurnAction() {
this.displayCategorySelection(true);
Question currentQuestion = onlineQuizGame.getCurrentQuestion();
OptionScreen optionScreen = screenFactory.createOptionScreen(
"Question: " + currentQuestion.getQuestion(),
List.of(currentQuestion.getQuestionOptions()));
optionScreen.render();
int action = optionScreen.getOptionInput().getActionValue();
onlineQuizGame.submitQuestionAnswer(action - 1);
gameRoom.sendSelectedQuestionOptionIndex(action - 1);
}
@Override
public void onGameTurnListen() {
this.displayCategorySelection(false);
}
@Override
public void onGameTurnListenCategorySubmission(int selectedCategoryId) {
onlineQuizGame.setCurrentCategoryById(selectedCategoryId);
String playerName = onlineQuizGame.getCurrentPlayer().getPlayerName();
String categoryName = onlineQuizGame.getCurrentCategory().getCategoryName();
screenFactory
.createInformationScreen("Category selection",
List.of("Player " + playerName + " selected category " + categoryName), false)
.render();
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
throw new TerminationException("QuizClash was interrupted");
}
Question currentQuestion = onlineQuizGame.getCurrentQuestion();
QuestionOption[] currentQuestionOptions = currentQuestion.getQuestionOptions();
List<String> questionOptionLines = IntStream
.range(0, currentQuestionOptions.length)
.mapToObj(i -> (i + 1) + ") " + currentQuestionOptions[i].getDisplayName())
.toList();
screenFactory
.createInformationScreen("Question: " + currentQuestion.getQuestion(), questionOptionLines,
false)
.render();
}
@Override
public void onGameTurnListenQuestionOptionSubmission(int selectedQuestionOptionIndex) {
onlineQuizGame.submitQuestionAnswer(selectedQuestionOptionIndex);
}
}