From 28edcc96ba7fdcccb91a6fa000b279447dd976f9 Mon Sep 17 00:00:00 2001 From: marie3003 <marie.viktoria.becker@gmail.com> Date: Thu, 12 Dec 2024 15:24:39 +0100 Subject: [PATCH 01/16] work on leaveGame button --- src/client/GameController.cpp | 11 +++++------ src/client/GameController.h | 2 +- src/client/panels/MainGamePanelWizard.cpp | 21 +++++++++++++++++++++ src/client/panels/MainGamePanelWizard.h | 1 + 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/client/GameController.cpp b/src/client/GameController.cpp index d732d59..bbacad9 100644 --- a/src/client/GameController.cpp +++ b/src/client/GameController.cpp @@ -147,6 +147,11 @@ void GameController::startGame() { ClientNetworkManager::sendRequest(request); } +void GameController::leaveGame() { + leave_game_request request = leave_game_request(GameController::_currentGameState->get_id(), GameController::_me->get_id(), _me->get_player_name()); + ClientNetworkManager::sendRequest(request); +} + void GameController::estimateTricks(int nof_tricks) { estimate_tricks_request request = estimate_tricks_request(GameController::_currentGameState->get_id(), GameController::_me->get_id(), nof_tricks); ClientNetworkManager::sendRequest(request); @@ -157,12 +162,6 @@ void GameController::playCard(card* cardToPlay) { ClientNetworkManager::sendRequest(request); } -void GameController::leaveGame() -{ - leave_game_request request = leave_game_request(GameController::_me->get_id(), GameController::_me->get_player_name()); - ClientNetworkManager::sendRequest(request); -} - // TODO: estimate trick request, here message box with entry void GameController::estimateTrick() { diff --git a/src/client/GameController.h b/src/client/GameController.h index 43c81bf..b5613b5 100644 --- a/src/client/GameController.h +++ b/src/client/GameController.h @@ -18,8 +18,8 @@ public: static void connectToServer(); static void updateGameState(game_state* newGameState); static void startGame(); - static void estimateTricks(int nof_cards); static void leaveGame(); + static void estimateTricks(int nof_cards); static void playCard(card* cardToPlay); static void estimateTrick(); diff --git a/src/client/panels/MainGamePanelWizard.cpp b/src/client/panels/MainGamePanelWizard.cpp index 672ba92..c74f980 100644 --- a/src/client/panels/MainGamePanelWizard.cpp +++ b/src/client/panels/MainGamePanelWizard.cpp @@ -144,6 +144,9 @@ void MainGamePanelWizard::buildGameState(game_state* gameState, player* me) // show button to display score board this->buildScoreBoardButton(sizer, gameState); + // show button to leave game + this->buildLeaveGameButton(sizer, gameState, me); + // update Layout this->Layout(); } @@ -167,6 +170,24 @@ void MainGamePanelWizard::buildScoreBoardButton(wxGridBagSizer *sizer, game_stat } +void MainGamePanelWizard::buildLeaveGameButton(wxGridBagSizer *sizer, game_state* gameState, player* me) { + wxGBSizerItem* item = sizer->FindItemAtPosition(wxGBPosition(3,4)); + wxPanel* panel = dynamic_cast<wxPanel*>(item->GetWindow()); + + if (gameState->is_started()) { + wxBoxSizer *sizer_vert = new wxBoxSizer(wxVERTICAL); + panel->SetSizer(sizer_vert); + + wxButton *leaveGameButton = new wxButton(panel, wxID_ANY, "Leave Game"); + sizer_vert->Add(leaveGameButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5); + + leaveGameButton->Bind(wxEVT_BUTTON, [gameState](wxCommandEvent &event) { + GameController::leaveGame(); + }); + } + +} + void MainGamePanelWizard::buildOtherPlayers(wxGridBagSizer* sizer, game_state* gameState, player* me, int myPosition) { std::vector<player*> players = gameState->get_players(); diff --git a/src/client/panels/MainGamePanelWizard.h b/src/client/panels/MainGamePanelWizard.h index cd1e7cf..4febe89 100644 --- a/src/client/panels/MainGamePanelWizard.h +++ b/src/client/panels/MainGamePanelWizard.h @@ -21,6 +21,7 @@ private: void buildTrumpCard(wxGridBagSizer* sizer, game_state* gameState); void buildScoreBoardButton(wxGridBagSizer* sizer, game_state* gameState); + void buildLeaveGameButton(wxGridBagSizer *sizer, game_state* gameState, player* me); wxSize const panelSize = wxSize(960, 680); // also set in the constructor implementation wxSize const cardSize = wxSize(70, 108); -- GitLab From 4b607dcb503caa013a08d21edc5d995212c0069e Mon Sep 17 00:00:00 2001 From: marie3003 <marie.viktoria.becker@gmail.com> Date: Thu, 12 Dec 2024 15:28:24 +0100 Subject: [PATCH 02/16] fixed error that happened during merge with two many constructors in trick --- src/common/game_state/cards/trick.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/common/game_state/cards/trick.h b/src/common/game_state/cards/trick.h index 93766b7..710b275 100644 --- a/src/common/game_state/cards/trick.h +++ b/src/common/game_state/cards/trick.h @@ -38,17 +38,11 @@ public: * @brief Constructs a new trick object. */ trick(); - explicit trick(std::string id); - trick(std::string id, - std::vector<std::pair<card*, player*>> &cards, - serializable_value<int>* trick_color, - serializable_value<int>* trump_color); /** * @brief Constructs a new trick object as a deep copy of another trick object. * @param other The trick it is copied from. */ - trick(const trick &other); /** -- GitLab From b82eafab170c28ad7f6df0848922de82ae93ece1 Mon Sep 17 00:00:00 2001 From: marie3003 <marie.viktoria.becker@gmail.com> Date: Thu, 12 Dec 2024 16:02:30 +0100 Subject: [PATCH 03/16] add work on leave game button --- src/client/panels/MainGamePanelWizard.cpp | 2 +- src/client/panels/MainGamePanelWizard.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/panels/MainGamePanelWizard.cpp b/src/client/panels/MainGamePanelWizard.cpp index c74f980..3afc394 100644 --- a/src/client/panels/MainGamePanelWizard.cpp +++ b/src/client/panels/MainGamePanelWizard.cpp @@ -170,7 +170,7 @@ void MainGamePanelWizard::buildScoreBoardButton(wxGridBagSizer *sizer, game_stat } -void MainGamePanelWizard::buildLeaveGameButton(wxGridBagSizer *sizer, game_state* gameState, player* me) { +void MainGamePanelWizard::buildLeaveGameButton(wxGridBagSizer *sizer, game_state* gameState) { wxGBSizerItem* item = sizer->FindItemAtPosition(wxGBPosition(3,4)); wxPanel* panel = dynamic_cast<wxPanel*>(item->GetWindow()); diff --git a/src/client/panels/MainGamePanelWizard.h b/src/client/panels/MainGamePanelWizard.h index 4febe89..2950112 100644 --- a/src/client/panels/MainGamePanelWizard.h +++ b/src/client/panels/MainGamePanelWizard.h @@ -21,7 +21,7 @@ private: void buildTrumpCard(wxGridBagSizer* sizer, game_state* gameState); void buildScoreBoardButton(wxGridBagSizer* sizer, game_state* gameState); - void buildLeaveGameButton(wxGridBagSizer *sizer, game_state* gameState, player* me); + void buildLeaveGameButton(wxGridBagSizer *sizer, game_state* gameState); wxSize const panelSize = wxSize(960, 680); // also set in the constructor implementation wxSize const cardSize = wxSize(70, 108); -- GitLab From 753d332d6b7f8b5eebd954b9be7e8103b16bb9b8 Mon Sep 17 00:00:00 2001 From: marie3003 <marie.viktoria.becker@gmail.com> Date: Thu, 12 Dec 2024 16:14:10 +0100 Subject: [PATCH 04/16] todo: adapt request handler leave game --- src/server/request_handler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/server/request_handler.cpp b/src/server/request_handler.cpp index 2056ca2..91ad458 100644 --- a/src/server/request_handler.cpp +++ b/src/server/request_handler.cpp @@ -140,6 +140,7 @@ request_response* request_handler::handle_request(const client_request* const re return new request_response(game_instance_ptr->get_id(), req_id, true, game_instance_ptr->get_game_state()->to_json(), err); } + // TODO: I think this logic makes no sense, if the player is not in the game this should be outside the if cond it is in // Case 2: player is already in player_LUT of player_manager but not yet in a game player_manager::remove_player(player_id, player); -- GitLab From cc617a07db9f26cb8530caef5d70c7d7673cf898 Mon Sep 17 00:00:00 2001 From: marie3003 <marie.viktoria.becker@gmail.com> Date: Fri, 13 Dec 2024 13:12:30 +0100 Subject: [PATCH 05/16] leave game handling in request handler corrected --- src/server/request_handler.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/server/request_handler.cpp b/src/server/request_handler.cpp index 91ad458..751773a 100644 --- a/src/server/request_handler.cpp +++ b/src/server/request_handler.cpp @@ -133,21 +133,20 @@ request_response* request_handler::handle_request(const client_request* const re std::string player_name = ((leave_game_request *) req)->get_player_name(); // Case 1: player is in a game //remove player from game via game instance manager -> game instance -> game state - if (game_instance_manager::try_remove_player(player, game_id, err)) - { + if (game_instance_manager::try_remove_player(player, game_id, err)) { //remove player from list of active players (delete from LUT table) if (player_manager::remove_player(player_id, player)){ return new request_response(game_instance_ptr->get_id(), req_id, true, game_instance_ptr->get_game_state()->to_json(), err); } - // TODO: I think this logic makes no sense, if the player is not in the game this should be outside the if cond it is in - // Case 2: player is already in player_LUT of player_manager but not yet in a game - player_manager::remove_player(player_id, player); - - //Case 3: player either couldn't be removed from game or player LUT + } + // player not in game instance yet but already in LUT + else if (player_manager::remove_player(player_id, player)) { + return new request_response("", req_id, true, nullptr, err); + } + else { + err = "Player was found neither in any game nor in lookup table."; return new request_response("", req_id, false, nullptr, err); - - } } // ##################### UNKNOWN REQUEST ##################### // -- GitLab From 78465f7fa02818ac7d29b2a2f5115cf1bec89ebe Mon Sep 17 00:00:00 2001 From: marie3003 <marie.viktoria.becker@gmail.com> Date: Fri, 13 Dec 2024 16:02:21 +0100 Subject: [PATCH 06/16] error correcrted in leave game request --- src/client/panels/MainGamePanelWizard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/panels/MainGamePanelWizard.cpp b/src/client/panels/MainGamePanelWizard.cpp index 3afc394..1e20c66 100644 --- a/src/client/panels/MainGamePanelWizard.cpp +++ b/src/client/panels/MainGamePanelWizard.cpp @@ -145,7 +145,7 @@ void MainGamePanelWizard::buildGameState(game_state* gameState, player* me) this->buildScoreBoardButton(sizer, gameState); // show button to leave game - this->buildLeaveGameButton(sizer, gameState, me); + this->buildLeaveGameButton(sizer, gameState); // update Layout this->Layout(); -- GitLab From 8629aa29aad5105298a6bde00682e84a3280e6c5 Mon Sep 17 00:00:00 2001 From: hwinter <hwinter@student.ethz.ch> Date: Fri, 13 Dec 2024 17:03:15 +0100 Subject: [PATCH 07/16] buttons --- src/client/panels/MainGamePanelWizard.cpp | 37 ++++++++++++++++------ src/client/panels/MainGamePanelWizard.h | 3 +- src/client/panels/TrickEstimationPanel.cpp | 25 +++++++++++++-- src/client/panels/TrickEstimationPanel.h | 2 +- 4 files changed, 52 insertions(+), 15 deletions(-) diff --git a/src/client/panels/MainGamePanelWizard.cpp b/src/client/panels/MainGamePanelWizard.cpp index 1e20c66..ced27ad 100644 --- a/src/client/panels/MainGamePanelWizard.cpp +++ b/src/client/panels/MainGamePanelWizard.cpp @@ -142,44 +142,63 @@ void MainGamePanelWizard::buildGameState(game_state* gameState, player* me) this->buildOtherPlayers(sizer, gameState, me, myPosition); // show button to display score board - this->buildScoreBoardButton(sizer, gameState); + this->buildScoreLeaveButtons(sizer, gameState); // show button to leave game - this->buildLeaveGameButton(sizer, gameState); + // this->buildLeaveGameButton(sizer, gameState); // update Layout this->Layout(); } -void MainGamePanelWizard::buildScoreBoardButton(wxGridBagSizer *sizer, game_state* gameState) { +void MainGamePanelWizard::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_state* gameState) { wxGBSizerItem* item = sizer->FindItemAtPosition(wxGBPosition(3,3)); wxPanel* panel = dynamic_cast<wxPanel*>(item->GetWindow()); if (gameState->is_started()) { wxBoxSizer *sizer_vert = new wxBoxSizer(wxVERTICAL); panel->SetSizer(sizer_vert); + auto sizer_hor = new wxBoxSizer(wxHORIZONTAL); + sizer_vert->Add(sizer_hor, 1, wxALIGN_LEFT); wxButton *scoreBoardButton = new wxButton(panel, wxID_ANY, "ScoreBoard"); - sizer_vert->Add(scoreBoardButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5); + scoreBoardButton->SetMinSize(wxSize(90, 35)); + sizer_hor->Add(scoreBoardButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 3); + + scoreBoardButton->SetBackgroundColour(wxColour(50,0,51)); // Set background color to blue + scoreBoardButton->SetForegroundColour(*wxWHITE); scoreBoardButton->Bind(wxEVT_BUTTON, [gameState](wxCommandEvent &event) { ScoreBoardDialog scoreBoard(nullptr, "ScoreBoard", "Here will be the scoreboard", gameState); scoreBoard.ShowModal(); }); + + wxButton *leaveGameButton = new wxButton(panel, wxID_ANY, "Leave Game"); + leaveGameButton->SetMinSize(wxSize(90, 35)); + sizer_hor->Add(leaveGameButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 3); + + leaveGameButton->SetBackgroundColour(wxColour(50,0,51)); // Set background color to blue + leaveGameButton->SetForegroundColour(*wxWHITE); + + leaveGameButton->Bind(wxEVT_BUTTON, [gameState](wxCommandEvent &event) { + GameController::leaveGame(); + }); } } +/* void MainGamePanelWizard::buildLeaveGameButton(wxGridBagSizer *sizer, game_state* gameState) { - wxGBSizerItem* item = sizer->FindItemAtPosition(wxGBPosition(3,4)); + wxGBSizerItem* item = sizer->FindItemAtPosition(wxGBPosition(3,3)); wxPanel* panel = dynamic_cast<wxPanel*>(item->GetWindow()); if (gameState->is_started()) { - wxBoxSizer *sizer_vert = new wxBoxSizer(wxVERTICAL); - panel->SetSizer(sizer_vert); + wxSizer* sizer_vert = panel->GetSizer(); + // wxBoxSizer *sizer_vert = new wxBoxSizer(wxVERTICAL); + // panel->SetSizer(sizer_vert); wxButton *leaveGameButton = new wxButton(panel, wxID_ANY, "Leave Game"); - sizer_vert->Add(leaveGameButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5); + sizer_vert->Add(leaveGameButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 1); leaveGameButton->Bind(wxEVT_BUTTON, [gameState](wxCommandEvent &event) { GameController::leaveGame(); @@ -187,7 +206,7 @@ void MainGamePanelWizard::buildLeaveGameButton(wxGridBagSizer *sizer, game_state } } - +*/ void MainGamePanelWizard::buildOtherPlayers(wxGridBagSizer* sizer, game_state* gameState, player* me, int myPosition) { std::vector<player*> players = gameState->get_players(); diff --git a/src/client/panels/MainGamePanelWizard.h b/src/client/panels/MainGamePanelWizard.h index 2950112..01831b0 100644 --- a/src/client/panels/MainGamePanelWizard.h +++ b/src/client/panels/MainGamePanelWizard.h @@ -20,8 +20,7 @@ private: void buildTrickPile(wxGridBagSizer* sizer, game_state* gameState, player *me); void buildTrumpCard(wxGridBagSizer* sizer, game_state* gameState); - void buildScoreBoardButton(wxGridBagSizer* sizer, game_state* gameState); - void buildLeaveGameButton(wxGridBagSizer *sizer, game_state* gameState); + void buildScoreLeaveButtons(wxGridBagSizer* sizer, game_state* gameState); wxSize const panelSize = wxSize(960, 680); // also set in the constructor implementation wxSize const cardSize = wxSize(70, 108); diff --git a/src/client/panels/TrickEstimationPanel.cpp b/src/client/panels/TrickEstimationPanel.cpp index 34cb20d..277d4d2 100644 --- a/src/client/panels/TrickEstimationPanel.cpp +++ b/src/client/panels/TrickEstimationPanel.cpp @@ -100,27 +100,46 @@ void TrickEstimationPanel::buildGameState(game_state* gameState, player* me) this->buildTrumpColor(sizer, gameState); - this->buildScoreBoardButton(sizer, gameState); + this->buildScoreLeaveButtons(sizer, gameState); this->Layout(); } -void TrickEstimationPanel::buildScoreBoardButton(wxGridBagSizer *sizer, game_state* gameState) { +void TrickEstimationPanel::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_state* gameState) { wxGBSizerItem* item = sizer->FindItemAtPosition(wxGBPosition(2,2)); wxPanel* panel = dynamic_cast<wxPanel*>(item->GetWindow()); wxBoxSizer* sizer_vert = new wxBoxSizer(wxVERTICAL); panel->SetSizer(sizer_vert); + auto sizer_hor = new wxBoxSizer(wxHORIZONTAL); + sizer_vert->Add(sizer_hor, 1, wxALIGN_CENTER); wxButton* scoreBoardButton = new wxButton(panel, wxID_ANY, "ScoreBoard"); - sizer_vert->Add(scoreBoardButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5); + scoreBoardButton->SetMinSize(wxSize(90, 35)); + + scoreBoardButton->SetBackgroundColour(wxColour(50,0,51)); // Set background color to blue + scoreBoardButton->SetForegroundColour(*wxWHITE); + + + sizer_hor->Add(scoreBoardButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 3); scoreBoardButton->Bind(wxEVT_BUTTON, [gameState](wxCommandEvent& event) { ScoreBoardDialog scoreBoard(nullptr, "ScoreBoard", "Here will be the scoreboard", gameState); scoreBoard.ShowModal(); }); + wxButton *leaveGameButton = new wxButton(panel, wxID_ANY, "Leave Game"); + leaveGameButton->SetMinSize(wxSize(90, 35)); + sizer_hor->Add(leaveGameButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 3); + + leaveGameButton->SetBackgroundColour(wxColour(50,0,51)); // Set background color to blue + leaveGameButton->SetForegroundColour(*wxWHITE); + + leaveGameButton->Bind(wxEVT_BUTTON, [gameState](wxCommandEvent &event) { + GameController::leaveGame(); + }); + } diff --git a/src/client/panels/TrickEstimationPanel.h b/src/client/panels/TrickEstimationPanel.h index f8d9ef6..bd42b4f 100644 --- a/src/client/panels/TrickEstimationPanel.h +++ b/src/client/panels/TrickEstimationPanel.h @@ -27,7 +27,7 @@ private: void buildThisPlayer(wxGridBagSizer* sizer, game_state* gameState, player* me); void buildOtherPlayers(wxGridBagSizer* sizer, game_state* gameState, int myPosition); - void buildScoreBoardButton(wxGridBagSizer* sizer, game_state* gameState); + void buildScoreLeaveButtons(wxGridBagSizer* sizer, game_state* gameState); InputField* _trickEstimateField; }; -- GitLab From 26e70b1e03592002275df073bd0b209d8e313e5f Mon Sep 17 00:00:00 2001 From: marie3003 <marie.viktoria.becker@gmail.com> Date: Sat, 14 Dec 2024 12:29:27 +0100 Subject: [PATCH 08/16] adapt button size --- src/client/panels/MainGamePanelWizard.cpp | 2 +- src/client/panels/TrickEstimationPanel.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/panels/MainGamePanelWizard.cpp b/src/client/panels/MainGamePanelWizard.cpp index 64b1fb6..726b090 100644 --- a/src/client/panels/MainGamePanelWizard.cpp +++ b/src/client/panels/MainGamePanelWizard.cpp @@ -190,7 +190,7 @@ void MainGamePanelWizard::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_sta }); wxButton *leaveGameButton = new wxButton(panel, wxID_ANY, "Leave Game"); - leaveGameButton->SetMinSize(wxSize(90, 35)); + leaveGameButton->SetMinSize(wxSize(110, 43)); sizer_hor->Add(leaveGameButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 3); leaveGameButton->SetFont(magicalFont); diff --git a/src/client/panels/TrickEstimationPanel.cpp b/src/client/panels/TrickEstimationPanel.cpp index 14bb384..e661ccf 100644 --- a/src/client/panels/TrickEstimationPanel.cpp +++ b/src/client/panels/TrickEstimationPanel.cpp @@ -132,7 +132,7 @@ void TrickEstimationPanel::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_st }); wxButton *leaveGameButton = new wxButton(panel, wxID_ANY, "Leave Game"); - leaveGameButton->SetMinSize(wxSize(90, 35)); + leaveGameButton->SetMinSize(wxSize(110, 43)); sizer_hor->Add(leaveGameButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 3); leaveGameButton->SetFont(magicalFontTrick); -- GitLab From 9babca05c51fc1fd17bee5286efa5caf5220b140 Mon Sep 17 00:00:00 2001 From: marie3003 <marie.viktoria.becker@gmail.com> Date: Sat, 14 Dec 2024 18:15:30 +0100 Subject: [PATCH 09/16] work in progress: leave game request. I have no idea why request response leads to an error. --- src/client/GameController.cpp | 1 - src/client/network/ResponseListenerThread.cpp | 1 + src/client/panels/MainGamePanelWizard.cpp | 4 +- src/client/panels/TrickEstimationPanel.cpp | 4 +- src/common/game_state/game_state.cpp | 40 ++++++++++++------- src/server/game_instance.cpp | 13 ++++-- src/server/request_handler.cpp | 21 +++++----- 7 files changed, 53 insertions(+), 31 deletions(-) diff --git a/src/client/GameController.cpp b/src/client/GameController.cpp index 1b481b6..40522af 100644 --- a/src/client/GameController.cpp +++ b/src/client/GameController.cpp @@ -290,7 +290,6 @@ void GameController::showGameOverMessage() { std::string message = "Final score:\n"; std::string buttonLabel = "Close Game"; - // TODO: change logic to determine winner because now we have vector of scores // sort players by score std::vector<player*> players = GameController::_currentGameState->get_players(); std::sort(players.begin(), players.end(), [](const player* a, const player* b) -> bool { diff --git a/src/client/network/ResponseListenerThread.cpp b/src/client/network/ResponseListenerThread.cpp index 6614d6d..95f5565 100644 --- a/src/client/network/ResponseListenerThread.cpp +++ b/src/client/network/ResponseListenerThread.cpp @@ -65,6 +65,7 @@ wxThread::ExitCode ResponseListenerThread::Entry() { } } + // took out check to not have this error at the end of the game when one player leaves if (count <= 0) { this->outputError("Network error", "Read error [" + std::to_string(this->_connection->last_error()) + "]: " + this->_connection->last_error_str()); } diff --git a/src/client/panels/MainGamePanelWizard.cpp b/src/client/panels/MainGamePanelWizard.cpp index 726b090..39f2d4f 100644 --- a/src/client/panels/MainGamePanelWizard.cpp +++ b/src/client/panels/MainGamePanelWizard.cpp @@ -178,7 +178,7 @@ void MainGamePanelWizard::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_sta wxButton *scoreBoardButton = new wxButton(panel, wxID_ANY, "ScoreBoard"); scoreBoardButton->SetMinSize(wxSize(110, 43)); //90 , 35 - sizer_hor->Add(scoreBoardButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 3); + sizer_hor->Add(scoreBoardButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3); scoreBoardButton->SetFont(magicalFont); scoreBoardButton->SetForegroundColour(wxColour(225, 225, 225)); // Set button text color @@ -191,7 +191,7 @@ void MainGamePanelWizard::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_sta wxButton *leaveGameButton = new wxButton(panel, wxID_ANY, "Leave Game"); leaveGameButton->SetMinSize(wxSize(110, 43)); - sizer_hor->Add(leaveGameButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 3); + sizer_hor->Add(leaveGameButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3); leaveGameButton->SetFont(magicalFont); leaveGameButton->SetBackgroundColour(wxColour(50,0,51)); // Set background color to blue diff --git a/src/client/panels/TrickEstimationPanel.cpp b/src/client/panels/TrickEstimationPanel.cpp index e661ccf..79e7092 100644 --- a/src/client/panels/TrickEstimationPanel.cpp +++ b/src/client/panels/TrickEstimationPanel.cpp @@ -121,7 +121,7 @@ void TrickEstimationPanel::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_st wxButton* scoreBoardButton = new wxButton(panel, wxID_ANY, "ScoreBoard"); scoreBoardButton->SetMinSize(wxSize(110, 43)); //90 35 - sizer_hor->Add(scoreBoardButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 3); + sizer_hor->Add(scoreBoardButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3); scoreBoardButton->SetFont(magicalFontTrick); scoreBoardButton->SetForegroundColour(wxColour(225, 225, 225)); // Set button text color scoreBoardButton->SetBackgroundColour(wxColour(50, 0, 51)); //make button same purple as estimation panel once clickable @@ -133,7 +133,7 @@ void TrickEstimationPanel::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_st wxButton *leaveGameButton = new wxButton(panel, wxID_ANY, "Leave Game"); leaveGameButton->SetMinSize(wxSize(110, 43)); - sizer_hor->Add(leaveGameButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 3); + sizer_hor->Add(leaveGameButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3); leaveGameButton->SetFont(magicalFontTrick); leaveGameButton->SetBackgroundColour(wxColour(50,0,51)); // Set background color to blue diff --git a/src/common/game_state/game_state.cpp b/src/common/game_state/game_state.cpp index dbadead..458294a 100644 --- a/src/common/game_state/game_state.cpp +++ b/src/common/game_state/game_state.cpp @@ -208,6 +208,7 @@ int game_state::get_trick_estimate_sum() const unsigned int game_state::get_max_round_number() const { + //return 1; return 60 / _players.size(); } @@ -452,23 +453,35 @@ bool game_state::play_card(player* player, const std::string& card_id, std::stri bool game_state::remove_player(player *player_ptr, std::string &err) { - if (const int idx = get_player_index(player_ptr); idx != -1) { - if (_is_started->get_value() == false) { - if (idx < _current_player_idx->get_value()) { - // reduce current_player_idx if the player who left had a lower index - _current_player_idx->set_value(_current_player_idx->get_value() - 1); - } - _players.erase(_players.begin() + idx); - return true; - } else { - finish_game(err); - return true; + // only called when game hasn't been started yet + // get pointer of leaving player by id + if(player_ptr == nullptr) + { + std::cout << "Player does not exist." << std::endl; + } + std::cout << "Player" << player_ptr->get_id() << std::endl; + player* leaving_player = nullptr; + std::cout << "Loop started" << std::endl; + for (player* p : _players){ + if (player_ptr->get_player_name() == p->get_player_name()) { + leaving_player = p; } - } else { + } + std::cout << "Loop ended" << std::endl; + + if (leaving_player == nullptr) { err = "Could not leave game, as the requested player was not found in that game."; return false; } - return false; + + const int idx = get_player_index(leaving_player); + + if (idx < _current_player_idx->get_value()) { + // reduce current_player_idx if the player who left had a lower index + _current_player_idx->set_value(_current_player_idx->get_value() - 1); + } + _players.erase(_players.begin() + idx); + return true; } bool game_state::add_player(player* player, std::string& err) @@ -497,7 +510,6 @@ bool game_state::add_player(player* player, std::string& err) bool game_state::finish_game(std::string &err) const { _is_finished->set_value(true); - // TODO: part to determine winner of the game, it is done in game controller right now and could stay there. return true; } #endif diff --git a/src/server/game_instance.cpp b/src/server/game_instance.cpp index bcae145..9c844c0 100644 --- a/src/server/game_instance.cpp +++ b/src/server/game_instance.cpp @@ -75,14 +75,21 @@ bool game_instance::start_game(player* player, std::string &err) { bool game_instance::try_remove_player(player *player, std::string &err) { modification_lock.lock(); - if (_game_state->remove_player(player, err)) { - player->set_game_id(""); + if (_game_state->is_started()) { // send state update to all other players + _game_state->finish_game(err); full_state_response state_update_msg = full_state_response(this->get_id(), *_game_state); server_network_manager::broadcast_message(state_update_msg, _game_state->get_players(), player); modification_lock.unlock(); return true; - } + }// else if (_game_state->remove_player(player, err)){ + // player->set_game_id(""); + // send state update to all other players + // full_state_response state_update_msg = full_state_response(this->get_id(), *_game_state); + //server_network_manager::broadcast_message(state_update_msg, _game_state->get_players(), player); + //modification_lock.unlock(); + //return true; + //} modification_lock.unlock(); return false; } diff --git a/src/server/request_handler.cpp b/src/server/request_handler.cpp index 751773a..c28844c 100644 --- a/src/server/request_handler.cpp +++ b/src/server/request_handler.cpp @@ -129,21 +129,24 @@ request_response* request_handler::handle_request(const client_request* const re // ##################### LEAVE GAME ##################### // case RequestType::leave_game: { - //get player name - std::string player_name = ((leave_game_request *) req)->get_player_name(); + + // Case 1: player is in a game //remove player from game via game instance manager -> game instance -> game state + std::cout << "Leave game request reached request handler." << std::endl; if (game_instance_manager::try_remove_player(player, game_id, err)) { - //remove player from list of active players (delete from LUT table) - if (player_manager::remove_player(player_id, player)){ - return new request_response(game_instance_ptr->get_id(), req_id, true, + std::cout << "Player successfully removed from the game " << std::endl; + return new request_response(game_instance_ptr->get_id(), req_id, true, game_instance_ptr->get_game_state()->to_json(), err); - } + + //remove player from list of active players (delete from LUT table) + //if (player_manager::remove_player(player_id, player)){ + //} } // player not in game instance yet but already in LUT - else if (player_manager::remove_player(player_id, player)) { - return new request_response("", req_id, true, nullptr, err); - } + //else if (player_manager::remove_player(player_id, player)) { + // return new request_response("", req_id, true, nullptr, err); + //} else { err = "Player was found neither in any game nor in lookup table."; return new request_response("", req_id, false, nullptr, err); -- GitLab From da7c7fb6354f7bc8f2cb18b4874fcd7f63c1a419 Mon Sep 17 00:00:00 2001 From: marie3003 <marie.viktoria.becker@gmail.com> Date: Sun, 15 Dec 2024 00:32:24 +0100 Subject: [PATCH 10/16] leave game early works now --- src/common/game_state/game_state.cpp | 37 +++++++++------------------- src/server/game_instance.cpp | 12 ++++++++- src/server/request_handler.cpp | 31 +++++++++++------------ 3 files changed, 37 insertions(+), 43 deletions(-) diff --git a/src/common/game_state/game_state.cpp b/src/common/game_state/game_state.cpp index 458294a..78a0dd9 100644 --- a/src/common/game_state/game_state.cpp +++ b/src/common/game_state/game_state.cpp @@ -453,35 +453,22 @@ bool game_state::play_card(player* player, const std::string& card_id, std::stri bool game_state::remove_player(player *player_ptr, std::string &err) { - // only called when game hasn't been started yet - // get pointer of leaving player by id - if(player_ptr == nullptr) - { - std::cout << "Player does not exist." << std::endl; - } - std::cout << "Player" << player_ptr->get_id() << std::endl; - player* leaving_player = nullptr; - std::cout << "Loop started" << std::endl; - for (player* p : _players){ - if (player_ptr->get_player_name() == p->get_player_name()) { - leaving_player = p; + if (const int idx = get_player_index(player_ptr); idx != -1) { + // Case 1: Game has not been started yet. + if (_is_started->get_value() == false) { + if (idx < _current_player_idx->get_value()) { + // reduce current_player_idx if the player who left had a lower index + _current_player_idx->set_value(_current_player_idx->get_value() - 1); + } + _players.erase(_players.begin() + idx); + return true; + } else { + return finish_game(err); } - } - std::cout << "Loop ended" << std::endl; - - if (leaving_player == nullptr) { + } else { err = "Could not leave game, as the requested player was not found in that game."; return false; } - - const int idx = get_player_index(leaving_player); - - if (idx < _current_player_idx->get_value()) { - // reduce current_player_idx if the player who left had a lower index - _current_player_idx->set_value(_current_player_idx->get_value() - 1); - } - _players.erase(_players.begin() + idx); - return true; } bool game_state::add_player(player* player, std::string& err) diff --git a/src/server/game_instance.cpp b/src/server/game_instance.cpp index 9c844c0..38d1ad6 100644 --- a/src/server/game_instance.cpp +++ b/src/server/game_instance.cpp @@ -75,6 +75,15 @@ bool game_instance::start_game(player* player, std::string &err) { bool game_instance::try_remove_player(player *player, std::string &err) { modification_lock.lock(); + if(_game_state->remove_player(player, err)) + { + // player->set_game_id(""); + full_state_response state_update_msg = full_state_response(this->get_id(), *_game_state); + server_network_manager::broadcast_message(state_update_msg, _game_state->get_players(), player); + modification_lock.unlock(); + return true; + } + /* if (_game_state->is_started()) { // send state update to all other players _game_state->finish_game(err); @@ -82,7 +91,8 @@ bool game_instance::try_remove_player(player *player, std::string &err) { server_network_manager::broadcast_message(state_update_msg, _game_state->get_players(), player); modification_lock.unlock(); return true; - }// else if (_game_state->remove_player(player, err)){ + */ + //}// else if (_game_state->remove_player(player, err)){ // player->set_game_id(""); // send state update to all other players // full_state_response state_update_msg = full_state_response(this->get_id(), *_game_state); diff --git a/src/server/request_handler.cpp b/src/server/request_handler.cpp index c28844c..081e78c 100644 --- a/src/server/request_handler.cpp +++ b/src/server/request_handler.cpp @@ -129,26 +129,23 @@ request_response* request_handler::handle_request(const client_request* const re // ##################### LEAVE GAME ##################### // case RequestType::leave_game: { - - // Case 1: player is in a game //remove player from game via game instance manager -> game instance -> game state - std::cout << "Leave game request reached request handler." << std::endl; - if (game_instance_manager::try_remove_player(player, game_id, err)) { - std::cout << "Player successfully removed from the game " << std::endl; - return new request_response(game_instance_ptr->get_id(), req_id, true, - game_instance_ptr->get_game_state()->to_json(), err); + if (game_instance_manager::try_get_player_and_game_instance(player_id, player, game_instance_ptr, err)) { + if (game_instance_manager::try_remove_player(player, game_id, err)) { + std::cout << "Player successfully removed from the game " << std::endl; + if (player_manager::remove_player(player_id, player)){ + return new request_response(game_instance_ptr->get_id(), req_id, true, + game_instance_ptr->get_game_state()->to_json(), err); + } - //remove player from list of active players (delete from LUT table) - //if (player_manager::remove_player(player_id, player)){ - //} - } - // player not in game instance yet but already in LUT - //else if (player_manager::remove_player(player_id, player)) { - // return new request_response("", req_id, true, nullptr, err); - //} - else { - err = "Player was found neither in any game nor in lookup table."; + } + } // Case 2: player not in game yet but already in LUT + else if(player_manager::remove_player(player_id, player)) { + return new request_response(game_instance_ptr->get_id(), req_id, true, + game_instance_ptr->get_game_state()->to_json(), err); + } else { + err = "Player or game instance were not found."; return new request_response("", req_id, false, nullptr, err); } } -- GitLab From 67dee97c3af5709c56916c8d775459d72f0e997b Mon Sep 17 00:00:00 2001 From: hwinter <hwinter@student.ethz.ch> Date: Sun, 15 Dec 2024 10:16:43 +0100 Subject: [PATCH 11/16] leave game in lobby --- src/client/panels/MainGamePanelWizard.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/client/panels/MainGamePanelWizard.cpp b/src/client/panels/MainGamePanelWizard.cpp index 39f2d4f..f17e836 100644 --- a/src/client/panels/MainGamePanelWizard.cpp +++ b/src/client/panels/MainGamePanelWizard.cpp @@ -159,9 +159,6 @@ void MainGamePanelWizard::buildGameState(game_state* gameState, player* me) // show button to display score board this->buildScoreLeaveButtons(sizer, gameState); - // show button to leave game - // this->buildLeaveGameButton(sizer, gameState); - // update Layout this->Layout(); } @@ -170,12 +167,13 @@ void MainGamePanelWizard::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_sta wxGBSizerItem* item = sizer->FindItemAtPosition(wxGBPosition(3,3)); wxPanel* panel = dynamic_cast<wxPanel*>(item->GetWindow()); - if (gameState->is_started()) { - wxBoxSizer *sizer_vert = new wxBoxSizer(wxVERTICAL); - panel->SetSizer(sizer_vert); - auto sizer_hor = new wxBoxSizer(wxHORIZONTAL); - sizer_vert->Add(sizer_hor, 1, wxALIGN_LEFT); + wxBoxSizer *sizer_vert = new wxBoxSizer(wxVERTICAL); + panel->SetSizer(sizer_vert); + auto sizer_hor = new wxBoxSizer(wxHORIZONTAL); + sizer_vert->Add(sizer_hor, 1, wxALIGN_LEFT); + if (gameState->is_started()) + { wxButton *scoreBoardButton = new wxButton(panel, wxID_ANY, "ScoreBoard"); scoreBoardButton->SetMinSize(wxSize(110, 43)); //90 , 35 sizer_hor->Add(scoreBoardButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3); @@ -188,7 +186,7 @@ void MainGamePanelWizard::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_sta ScoreBoardDialog scoreBoard(nullptr, "ScoreBoard", "Here will be the scoreboard", gameState); scoreBoard.ShowModal(); }); - + } wxButton *leaveGameButton = new wxButton(panel, wxID_ANY, "Leave Game"); leaveGameButton->SetMinSize(wxSize(110, 43)); sizer_hor->Add(leaveGameButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3); @@ -200,8 +198,6 @@ void MainGamePanelWizard::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_sta leaveGameButton->Bind(wxEVT_BUTTON, [gameState](wxCommandEvent &event) { GameController::leaveGame(); }); - } - } /* -- GitLab From a56889d124d38ecbb15a257478ad09155b519cd6 Mon Sep 17 00:00:00 2001 From: hwinter <hwinter@student.ethz.ch> Date: Sun, 15 Dec 2024 10:25:09 +0100 Subject: [PATCH 12/16] buttons adjusted --- src/client/panels/MainGamePanelWizard.cpp | 4 ++-- src/client/panels/TrickEstimationPanel.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/client/panels/MainGamePanelWizard.cpp b/src/client/panels/MainGamePanelWizard.cpp index f17e836..9d8f3b1 100644 --- a/src/client/panels/MainGamePanelWizard.cpp +++ b/src/client/panels/MainGamePanelWizard.cpp @@ -176,7 +176,7 @@ void MainGamePanelWizard::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_sta { wxButton *scoreBoardButton = new wxButton(panel, wxID_ANY, "ScoreBoard"); scoreBoardButton->SetMinSize(wxSize(110, 43)); //90 , 35 - sizer_hor->Add(scoreBoardButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3); + sizer_vert->Add(scoreBoardButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3); scoreBoardButton->SetFont(magicalFont); scoreBoardButton->SetForegroundColour(wxColour(225, 225, 225)); // Set button text color @@ -189,7 +189,7 @@ void MainGamePanelWizard::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_sta } wxButton *leaveGameButton = new wxButton(panel, wxID_ANY, "Leave Game"); leaveGameButton->SetMinSize(wxSize(110, 43)); - sizer_hor->Add(leaveGameButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3); + sizer_vert->Add(leaveGameButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3); leaveGameButton->SetFont(magicalFont); leaveGameButton->SetBackgroundColour(wxColour(50,0,51)); // Set background color to blue diff --git a/src/client/panels/TrickEstimationPanel.cpp b/src/client/panels/TrickEstimationPanel.cpp index 79e7092..a29ca2b 100644 --- a/src/client/panels/TrickEstimationPanel.cpp +++ b/src/client/panels/TrickEstimationPanel.cpp @@ -121,7 +121,7 @@ void TrickEstimationPanel::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_st wxButton* scoreBoardButton = new wxButton(panel, wxID_ANY, "ScoreBoard"); scoreBoardButton->SetMinSize(wxSize(110, 43)); //90 35 - sizer_hor->Add(scoreBoardButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3); + sizer_vert->Add(scoreBoardButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3); scoreBoardButton->SetFont(magicalFontTrick); scoreBoardButton->SetForegroundColour(wxColour(225, 225, 225)); // Set button text color scoreBoardButton->SetBackgroundColour(wxColour(50, 0, 51)); //make button same purple as estimation panel once clickable @@ -133,7 +133,7 @@ void TrickEstimationPanel::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_st wxButton *leaveGameButton = new wxButton(panel, wxID_ANY, "Leave Game"); leaveGameButton->SetMinSize(wxSize(110, 43)); - sizer_hor->Add(leaveGameButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3); + sizer_vert->Add(leaveGameButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3); leaveGameButton->SetFont(magicalFontTrick); leaveGameButton->SetBackgroundColour(wxColour(50,0,51)); // Set background color to blue -- GitLab From 6811d6bcb70b784808799909837d5c5665336af7 Mon Sep 17 00:00:00 2001 From: marie3003 <marie.viktoria.becker@gmail.com> Date: Sun, 15 Dec 2024 12:45:36 +0100 Subject: [PATCH 13/16] game can now also be left when game has not started yet --- src/client/GameController.cpp | 7 ++++++- src/client/GameController.h | 1 + src/client/panels/MainGamePanelWizard.cpp | 14 ++++++++++--- src/common/game_state/game_state.cpp | 1 + src/common/game_state/player/player.cpp | 25 +++++++++++++++++++++-- src/common/game_state/player/player.h | 16 +++++++++++++++ 6 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/client/GameController.cpp b/src/client/GameController.cpp index 40522af..d040d52 100644 --- a/src/client/GameController.cpp +++ b/src/client/GameController.cpp @@ -171,6 +171,7 @@ void GameController::startGame() { } void GameController::leaveGame() { + _me->set_has_left_game(true); leave_game_request request = leave_game_request(GameController::_currentGameState->get_id(), GameController::_me->get_id(), _me->get_player_name()); ClientNetworkManager::sendRequest(request); } @@ -284,7 +285,6 @@ void GameController::showTrickOverMessage(const player* winner) dialog->ShowModal(); } - void GameController::showGameOverMessage() { std::string title = "Game Over!"; std::string message = "Final score:\n"; @@ -327,3 +327,8 @@ void GameController::showGameOverMessage() { GameController::_gameWindow->Close(); } } + +void GameController::closeGameWindow() +{ + GameController::_gameWindow->Close(); +} diff --git a/src/client/GameController.h b/src/client/GameController.h index 90310f6..4494b48 100644 --- a/src/client/GameController.h +++ b/src/client/GameController.h @@ -29,6 +29,7 @@ public: static void showNewRoundMessage(game_state* oldGameState, game_state* newGameState); static void showTrickOverMessage(const player* winner); static void showGameOverMessage(); + static void closeGameWindow(); private: static GameWindow* _gameWindow; diff --git a/src/client/panels/MainGamePanelWizard.cpp b/src/client/panels/MainGamePanelWizard.cpp index 03c6006..f9b2eac 100644 --- a/src/client/panels/MainGamePanelWizard.cpp +++ b/src/client/panels/MainGamePanelWizard.cpp @@ -98,10 +98,18 @@ void MainGamePanelWizard::buildGameState(game_state* gameState, player* me) std::vector<player*>::iterator it = std::find_if(players.begin(), players.end(), [me](const player* x) { return x->get_id() == me->get_id(); }); + std::cout << me->has_left_game() << std::endl; if (it < players.end()) { me = *it; myPosition = it - players.begin(); - } else { + } + else if (me->has_left_game() == true) + { + //GameController::showError("Left Game", "You have left the game."); + GameController::closeGameWindow(); + return; + } + else { GameController::showError("Game state error", "Could not find this player among players of server game."); return; } @@ -176,7 +184,7 @@ void MainGamePanelWizard::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_sta { wxButton *scoreBoardButton = new wxButton(panel, wxID_ANY, "ScoreBoard"); scoreBoardButton->SetMinSize(wxSize(110, 43)); //90 , 35 - sizer_vert->Add(scoreBoardButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3); + sizer_vert->Add(scoreBoardButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 3); scoreBoardButton->SetFont(magicalFont); scoreBoardButton->SetForegroundColour(wxColour(225, 225, 225)); // Set button text color @@ -189,7 +197,7 @@ void MainGamePanelWizard::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_sta } wxButton *leaveGameButton = new wxButton(panel, wxID_ANY, "Leave Game"); leaveGameButton->SetMinSize(wxSize(110, 43)); - sizer_vert->Add(leaveGameButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3); + sizer_vert->Add(leaveGameButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 3); leaveGameButton->SetFont(magicalFont); leaveGameButton->SetBackgroundColour(wxColour(50,0,51)); // Set background color to blue diff --git a/src/common/game_state/game_state.cpp b/src/common/game_state/game_state.cpp index 845f157..e2295a1 100644 --- a/src/common/game_state/game_state.cpp +++ b/src/common/game_state/game_state.cpp @@ -451,6 +451,7 @@ bool game_state::remove_player(player *player_ptr, std::string &err) // reduce current_player_idx if the player who left had a lower index _current_player_idx->set_value(_current_player_idx->get_value() - 1); } + player_ptr->set_has_left_game(true); _players.erase(_players.begin() + idx); return true; } else { diff --git a/src/common/game_state/player/player.cpp b/src/common/game_state/player/player.cpp index 2efef60..c33546f 100644 --- a/src/common/game_state/player/player.cpp +++ b/src/common/game_state/player/player.cpp @@ -8,20 +8,22 @@ player::player(const std::string& name) : unique_serializable() { this->_nof_predicted = new serializable_value<int>(-1); this->_nof_tricks = new serializable_value<int>(0); this->_scores = std::vector<serializable_value<int>*>(0); + this->_has_left_game = new serializable_value<bool>(false); this->_hand = new hand(); - } // deserialization constructor player::player(const std::string& id, serializable_value<std::string>* name, serializable_value<int>* nof_tricks, serializable_value<int>* nof_predicted, - const std::vector<serializable_value<int>*>& scores, hand *hand) : + const std::vector<serializable_value<int>*>& scores, + serializable_value<bool>* player_has_left_game, hand *hand) : unique_serializable(id), _player_name(name), _nof_tricks(nof_tricks), _nof_predicted(nof_predicted), _scores(scores), + _has_left_game(player_has_left_game), _hand(hand) { } @@ -32,11 +34,13 @@ player::~player() { delete _player_name; delete _nof_predicted; delete _nof_tricks; + delete _has_left_game; _hand = nullptr; _player_name = nullptr; _nof_predicted = nullptr; _nof_tricks = nullptr; + _has_left_game = nullptr; } } @@ -50,6 +54,7 @@ player::player(const std::string& id, const std::string& name) : this->_hand = new hand(); this->_nof_predicted = new serializable_value<int>(-1); this->_nof_tricks = new serializable_value<int>(0); + this->_has_left_game = new serializable_value<bool>(false); } // server accessors @@ -87,6 +92,16 @@ void player::set_nof_tricks(const int nof_tricks) const _nof_tricks->set_value(nof_tricks); } +bool player::has_left_game() const +{ + return _has_left_game->get_value(); +} + +void player::set_has_left_game(bool has_left_game) +{ + _has_left_game->set_value(has_left_game); +} + // getter and setter for number of predicted tricks int player::get_nof_predicted() const noexcept @@ -175,6 +190,10 @@ void player::write_into_json(rapidjson::Value& json, rapidjson::Document::Alloca json.AddMember("scores", vector_utils::serialize_vector(_scores, allocator), allocator); + rapidjson::Value has_left_game_val(rapidjson::kObjectType); + _has_left_game->write_into_json(has_left_game_val, allocator); + json.AddMember("has_left_game", has_left_game_val, allocator); + rapidjson::Value hand_val(rapidjson::kObjectType); _hand->write_into_json(hand_val, allocator); json.AddMember("hand", hand_val, allocator); @@ -186,6 +205,7 @@ player* player::from_json(const rapidjson::Value &json) { && json.HasMember("nof_tricks") && json.HasMember("player_name") && json.HasMember("scores") + && json.HasMember("has_left_game") && json.HasMember("hand")) { std::vector<serializable_value<int>*> deserialized_scores; @@ -198,6 +218,7 @@ player* player::from_json(const rapidjson::Value &json) { serializable_value<int>::from_json(json["nof_tricks"].GetObject()), serializable_value<int>::from_json(json["nof_predicted"].GetObject()), deserialized_scores, + serializable_value<bool>::from_json(json["has_left_game"].GetObject()), hand::from_json(json["hand"].GetObject())); } else { throw WizardException("Failed to deserialize player from json. Required json entries were missing."); diff --git a/src/common/game_state/player/player.h b/src/common/game_state/player/player.h index 1eb41bd..3a1f159 100644 --- a/src/common/game_state/player/player.h +++ b/src/common/game_state/player/player.h @@ -22,6 +22,7 @@ private: serializable_value<int>* _nof_tricks; ///< The number of tricks won in the current round. serializable_value<int>* _nof_predicted; ///< The number of predicted tricks in the current round. std::vector<serializable_value<int>*> _scores; ///< The scores of the player (total game score, current and past ones). + serializable_value<bool>* _has_left_game; ///< Boolean whether player has left the game. hand* _hand; ///< The player's hand holding the player's cards. #ifdef WIZARD_SERVER @@ -35,6 +36,7 @@ private: * @param nof_tricks The number of tricks won by the player in the current round. * @param nof_predicted The number of tricks predicted to be won by the player in the current round. * @param scores The player's scores. + * @param has_left_game Boolean whether player has left the game. * @param hand The player's hand. */ player(const std::string& id, @@ -42,6 +44,7 @@ private: serializable_value<int>* nof_tricks, serializable_value<int>* nof_predicted, const std::vector<serializable_value<int>*>& scores, + serializable_value<bool>* has_left_game, hand* hand); public: @@ -106,6 +109,18 @@ public: */ void set_nof_tricks(int nof_tricks) const; + /** + * @brief State whether player has left the game. + * @return Boolean stating whether player has left the game. + */ + [[nodiscard]] bool has_left_game() const; + + /** + * @brief Sets the players game to left when he leaves the game + * @param has_left_game Boolean whether player has left game + */ + void set_has_left_game(bool has_left_game); + /** * @brief Gets the number of tricks predicted to be won by the player in the current round. * @return The number of tricks predicted to be won by the player in the current round. @@ -127,6 +142,7 @@ public: */ [[nodiscard]] unsigned int get_nof_cards() const noexcept; + /** * @brief Gets the player's hand. * @return The player's hand. -- GitLab From 70469c2854abc65a64e43a98e15caad3996dd073 Mon Sep 17 00:00:00 2001 From: marie3003 <marie.viktoria.becker@gmail.com> Date: Sun, 15 Dec 2024 12:52:03 +0100 Subject: [PATCH 14/16] fixed wxwidget error with vertical sizers --- src/client/panels/TrickEstimationPanel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/panels/TrickEstimationPanel.cpp b/src/client/panels/TrickEstimationPanel.cpp index 581df62..102d2de 100644 --- a/src/client/panels/TrickEstimationPanel.cpp +++ b/src/client/panels/TrickEstimationPanel.cpp @@ -121,7 +121,7 @@ void TrickEstimationPanel::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_st wxButton* scoreBoardButton = new wxButton(panel, wxID_ANY, "ScoreBoard"); scoreBoardButton->SetMinSize(wxSize(110, 43)); //90 35 - sizer_vert->Add(scoreBoardButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3); + sizer_vert->Add(scoreBoardButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 3); scoreBoardButton->SetFont(magicalFontTrick); scoreBoardButton->SetForegroundColour(wxColour(225, 225, 225)); // Set button text color scoreBoardButton->SetBackgroundColour(wxColour(50, 0, 51)); //make button same purple as estimation panel once clickable @@ -133,7 +133,7 @@ void TrickEstimationPanel::buildScoreLeaveButtons(wxGridBagSizer *sizer, game_st wxButton *leaveGameButton = new wxButton(panel, wxID_ANY, "Leave Game"); leaveGameButton->SetMinSize(wxSize(110, 43)); - sizer_vert->Add(leaveGameButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3); + sizer_vert->Add(leaveGameButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 3); leaveGameButton->SetFont(magicalFontTrick); leaveGameButton->SetBackgroundColour(wxColour(50,0,51)); // Set background color to blue -- GitLab From a1c548d8602c1b3c9229eb44d18e775c9ca5609c Mon Sep 17 00:00:00 2001 From: marie3003 <marie.viktoria.becker@gmail.com> Date: Sun, 15 Dec 2024 13:32:44 +0100 Subject: [PATCH 15/16] adapt game state test to make sure it still runs even though new object was added to game state --- src/common/game_state/game_state.cpp | 6 +++--- unit-tests/game_state.cpp | 26 +++++++++++++++++++------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/common/game_state/game_state.cpp b/src/common/game_state/game_state.cpp index e2295a1..625c5f8 100644 --- a/src/common/game_state/game_state.cpp +++ b/src/common/game_state/game_state.cpp @@ -579,7 +579,7 @@ void game_state::write_into_json(rapidjson::Value &json, rapidjson::Value trick_estimate_sum_val(rapidjson::kObjectType); _trick_estimate_sum->write_into_json(trick_estimate_sum_val, allocator); - json.AddMember("trick_estimate_sum_val", trick_estimate_sum_val, allocator); + json.AddMember("trick_estimate_sum", trick_estimate_sum_val, allocator); } @@ -601,7 +601,7 @@ game_state* game_state::from_json(const rapidjson::Value &json) { && json.HasMember("current_player_idx") && json.HasMember("trump_color") && json.HasMember("trump_card_value") - && json.HasMember("trick_estimate_sum_val")) + && json.HasMember("trick_estimate_sum")) { std::vector<player*> deserialized_players; for (auto &serialized_player : json["players"].GetArray()) { @@ -624,7 +624,7 @@ game_state* game_state::from_json(const rapidjson::Value &json) { serializable_value<int>::from_json(json["current_player_idx"].GetObject()), serializable_value<int>::from_json(json["trump_color"].GetObject()), serializable_value<int>::from_json(json["trump_card_value"].GetObject()), - serializable_value<int>::from_json(json["trick_estimate_sum_val"].GetObject())); + serializable_value<int>::from_json(json["trick_estimate_sum"].GetObject())); } throw WizardException("Failed to deserialize game_state. Required entries were missing."); } \ No newline at end of file diff --git a/unit-tests/game_state.cpp b/unit-tests/game_state.cpp index 6954e44..c5032b8 100644 --- a/unit-tests/game_state.cpp +++ b/unit-tests/game_state.cpp @@ -320,7 +320,8 @@ void create_json(rapidjson::Value &json, rapidjson::MemoryPoolAllocator<rapidjso serializable_value<bool>* test_is_estimation_phase, serializable_value<int>* test_round_number, serializable_value<int>* test_trick_number, serializable_value<int>* test_starting_player_idx, serializable_value<int>* test_trick_starting_player_idx, serializable_value<int>* test_current_player_idx, - serializable_value<int>* test_trump_color, serializable_value<int>* test_trick_estimate_sum) + serializable_value<int>* test_trump_color, serializable_value<int>* test_trump_card_value, + serializable_value<int>* test_trick_estimate_sum) { // id json.AddMember("id", "4f38hvid20dj", allocator); @@ -388,10 +389,15 @@ void create_json(rapidjson::Value &json, rapidjson::MemoryPoolAllocator<rapidjso test_trump_color->write_into_json(trump_color_val, allocator); json.AddMember("trump_color", trump_color_val, allocator); + // trump card value + rapidjson::Value trump_card_value_val(rapidjson::kObjectType); + test_trump_card_value->write_into_json(trump_card_value_val, allocator); + json.AddMember("trump_card_value", trump_card_value_val, allocator); + // trick estimate sum rapidjson::Value trick_estimate_sum_val(rapidjson::kObjectType); test_trick_estimate_sum->write_into_json(trick_estimate_sum_val, allocator); - json.AddMember("trick_estimate_sum_val", trick_estimate_sum_val, allocator); + json.AddMember("trick_estimate_sum", trick_estimate_sum_val, allocator); } @@ -410,13 +416,15 @@ TEST(GameStateJson, CreateJson) const auto test_trick_starting_player_idx = new serializable_value<int>(0); const auto test_current_player_idx = new serializable_value<int>(0); const auto test_trump_color = new serializable_value<int>(0); + const auto test_trump_card_value = new serializable_value<int>(0); const auto test_trick_estimate_sum = new serializable_value<int>(0); auto* json = new rapidjson::Document(); json->SetObject(); create_json(*json, json->GetAllocator(), test_players, test_deck, test_trick, test_last_trick, test_is_finished, test_is_started, test_is_estimation_phase, test_round_number, test_trick_number, test_starting_player_idx, - test_trick_starting_player_idx, test_current_player_idx, test_trump_color, test_trick_estimate_sum); + test_trick_starting_player_idx, test_current_player_idx, test_trump_color, test_trump_card_value, + test_trick_estimate_sum); const std::string message = json_utils::to_string(json); delete json; @@ -449,6 +457,7 @@ TEST(GameStateUpdateCurrentPlayerTest, UpatePLayerEstimation) const auto test_trick_starting_player_idx = new serializable_value<int>(2); // depends on who won last trick const auto test_current_player_idx = new serializable_value<int>(2); // first one to estimate const auto test_trump_color = new serializable_value<int>(2); + const auto test_trump_card_value = new serializable_value<int>(2); const auto test_trick_estimate_sum = new serializable_value<int>(0); auto* json = new rapidjson::Document(); @@ -456,7 +465,7 @@ TEST(GameStateUpdateCurrentPlayerTest, UpatePLayerEstimation) create_json(*json, json->GetAllocator(), test_players, test_deck, test_trick, test_last_trick, test_is_finished, test_is_started, test_is_estimation_phase, test_round_number, test_trick_number, test_starting_player_idx, test_trick_starting_player_idx, test_current_player_idx, test_trump_color, - test_trick_estimate_sum); + test_trump_card_value, test_trick_estimate_sum); const std::string message = json_utils::to_string(json); delete json; @@ -491,6 +500,7 @@ TEST(GameStateUpdateCurrentPlayerTest, UpatePLayerEstimationToPlaying) const auto test_trick_starting_player_idx = new serializable_value<int>(0); // round starter starts const auto test_current_player_idx = new serializable_value<int>(3); // last one to estimate const auto test_trump_color = new serializable_value<int>(2); + const auto test_trump_card_value = new serializable_value<int>(2); const auto test_trick_estimate_sum = new serializable_value<int>(4); auto* json = new rapidjson::Document(); @@ -498,7 +508,7 @@ TEST(GameStateUpdateCurrentPlayerTest, UpatePLayerEstimationToPlaying) create_json(*json, json->GetAllocator(), test_players, test_deck, test_trick, test_last_trick, test_is_finished, test_is_started, test_is_estimation_phase, test_round_number, test_trick_number, test_starting_player_idx, test_trick_starting_player_idx, test_current_player_idx, test_trump_color, - test_trick_estimate_sum); + test_trump_card_value, test_trick_estimate_sum); const std::string message = json_utils::to_string(json); delete json; @@ -534,6 +544,7 @@ TEST(GameStateUpdateCurrentPlayerTest, UpatePLayerPlayingToNextRound) const auto test_trick_starting_player_idx = new serializable_value<int>(2); // depends on last trick const auto test_current_player_idx = new serializable_value<int>(1); // last one to play const auto test_trump_color = new serializable_value<int>(2); + const auto test_trump_card_value = new serializable_value<int>(2); const auto test_trick_estimate_sum = new serializable_value<int>(4); auto* json = new rapidjson::Document(); @@ -541,7 +552,7 @@ TEST(GameStateUpdateCurrentPlayerTest, UpatePLayerPlayingToNextRound) create_json(*json, json->GetAllocator(), test_players, test_deck, test_trick, test_last_trick, test_is_finished, test_is_started, test_is_estimation_phase, test_round_number, test_trick_number, test_starting_player_idx, test_trick_starting_player_idx, test_current_player_idx, test_trump_color, - test_trick_estimate_sum); + test_trump_card_value, test_trick_estimate_sum); const std::string message = json_utils::to_string(json); delete json; @@ -604,6 +615,7 @@ TEST(GameStateFinishGameTest, FinishGame) const auto test_trick_starting_player_idx = new serializable_value<int>(2); // depends on last trick const auto test_current_player_idx = new serializable_value<int>(1); // last one to play const auto test_trump_color = new serializable_value<int>(2); + const auto test_trump_card_value = new serializable_value<int>(2); const auto test_trick_estimate_sum = new serializable_value<int>(12); auto* json = new rapidjson::Document(); @@ -611,7 +623,7 @@ TEST(GameStateFinishGameTest, FinishGame) create_json(*json, json->GetAllocator(), test_players, test_deck, test_trick, test_last_trick, test_is_finished, test_is_started, test_is_estimation_phase, test_round_number, test_trick_number, test_starting_player_idx, test_trick_starting_player_idx, test_current_player_idx, test_trump_color, - test_trick_estimate_sum); + test_trump_card_value, test_trick_estimate_sum); const std::string message = json_utils::to_string(json); delete json; -- GitLab From 33d797ab64c52d3126a7552cd7c9d31a721d1294 Mon Sep 17 00:00:00 2001 From: marie3003 <marie.viktoria.becker@gmail.com> Date: Sun, 15 Dec 2024 13:35:26 +0100 Subject: [PATCH 16/16] remove prints --- src/client/panels/MainGamePanelWizard.cpp | 3 --- src/client/panels/TrickEstimationPanel.cpp | 1 - 2 files changed, 4 deletions(-) diff --git a/src/client/panels/MainGamePanelWizard.cpp b/src/client/panels/MainGamePanelWizard.cpp index f9b2eac..8aa0f92 100644 --- a/src/client/panels/MainGamePanelWizard.cpp +++ b/src/client/panels/MainGamePanelWizard.cpp @@ -98,14 +98,12 @@ void MainGamePanelWizard::buildGameState(game_state* gameState, player* me) std::vector<player*>::iterator it = std::find_if(players.begin(), players.end(), [me](const player* x) { return x->get_id() == me->get_id(); }); - std::cout << me->has_left_game() << std::endl; if (it < players.end()) { me = *it; myPosition = it - players.begin(); } else if (me->has_left_game() == true) { - //GameController::showError("Left Game", "You have left the game."); GameController::closeGameWindow(); return; } @@ -316,7 +314,6 @@ void MainGamePanelWizard::buildTrumpCard(wxGridBagSizer* sizer, game_state* game int trumpCardValue = gameState->get_trump_card_value(); std::string cardImage = "assets/card_" + std::to_string(trumpCardValue) + "_" + std::to_string(trumpColor)+".png"; - std::cout << cardImage << std::endl; ImagePanel* cardPanel = new ImagePanel(trumpPanel, cardImage, wxBITMAP_TYPE_ANY, wxDefaultPosition, MainGamePanelWizard::cardSize); diff --git a/src/client/panels/TrickEstimationPanel.cpp b/src/client/panels/TrickEstimationPanel.cpp index 102d2de..c5c88ea 100644 --- a/src/client/panels/TrickEstimationPanel.cpp +++ b/src/client/panels/TrickEstimationPanel.cpp @@ -160,7 +160,6 @@ void TrickEstimationPanel::buildTrumpColor(wxGridBagSizer *sizer, game_state *ga int trumpCardValue = gameState->get_trump_card_value(); std::string cardImage = "assets/card_" + std::to_string(trumpCardValue) + "_" + std::to_string(trumpColor)+".png"; - std::cout << cardImage << std::endl; ImagePanel* cardPanel = new ImagePanel(trumpPanel, cardImage, wxBITMAP_TYPE_ANY, wxDefaultPosition, TrickEstimationPanel::cardSize); -- GitLab