From 42640f489aa0f1c86719cf4106c3e5a48de4a02d Mon Sep 17 00:00:00 2001 From: Adam Lerer Date: Wed, 9 Nov 2022 09:49:35 -0800 Subject: [PATCH 1/5] Fix backend for create game --- .vscode/settings.json | 13 - api.php | 318 +++++++++--------- .../src/components/ui/new/CreateGameForm.tsx | 2 +- beta-src/src/state/game/game-api-slice.ts | 3 + 4 files changed, 157 insertions(+), 179 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index a882c2019..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "cSpell.words": [ - "colourblind", - "gameplay", - "passwordcheck", - "Protanope", - "rulebook", - "tritanope", - "xsss", - "themer", - "tritanope" - ] -} diff --git a/api.php b/api.php index 0187c0440..c878ed64e 100644 --- a/api.php +++ b/api.php @@ -1405,7 +1405,7 @@ public function __construct() { } public function run($userID, $permissionIsExplicit) { - global $DB, $MC, $Misc; + global $DB, $MC, $Misc, $Game; $User = new User($userID); $args = $this->getArgs(); @@ -1440,191 +1440,179 @@ public function run($userID, $permissionIsExplicit) { // $input['botFill'] = 'Yes'; // } - try { - if ($Misc->Panic) { - throw new Exception(l_t("Game creation has been temporarily disabled while we take care of an unexpected problem. Please try again later, sorry for the inconvenience")); - } + if ($Misc->Panic) { + throw new Exception(l_t("Game creation has been temporarily disabled while we take care of an unexpected problem. Please try again later, sorry for the inconvenience")); + } - $variantID = (int)$variantID; - if (!isset(Config::$variants[$variantID])) { - throw new Exception(l_t("Variant ID given (%s) doesn't represent a real variant.", $variantID)); - } + $variantID = (int)$variantID; + if (!isset(Config::$variants[$variantID])) { + throw new Exception(l_t("Variant ID given (%s) doesn't represent a real variant.", $variantID)); + } - // If the name isn't unique or is too long the database will stop it - $name = $DB->escape($name); - if ( !$name ) { throw new Exception(l_t("No name entered.")); } + // If the name isn't unique or is too long the database will stop it + $name = $DB->escape($name); + if ( !$name ) { throw new Exception(l_t("No name entered.")); } - // This is hashed, so doesn't need validation - if ( $inviteCode != $inviteCodeConfirmation ) { - throw new Exception(l_t("The two invite codes entered don't match.")); - } + // This is hashed, so doesn't need validation + if ( $inviteCode != $inviteCodeConfirmation ) { + throw new Exception(l_t("The two invite codes entered don't match.")); + } - $bet = (int)$bet; - if ($bet < 5 or $bet > $User->points){ - throw new Exception(l_t("%s is an invalid bet size.",(string)$bet)); - } + $bet = (int)$bet; + if ($bet < 5 or $bet > $User->points){ + throw new Exception(l_t("%s is an invalid bet size.",(string)$bet)); + } - if ($potType != 'Winner-takes-all' and $potType != 'Points-per-supply-center' and $potType != 'Unranked' and $potType != 'Sum-of-squares') { - throw new Exception(l_t('Invalid potType input given.')); - } + if ($potType != 'Winner-takes-all' and $potType != 'Points-per-supply-center' and $potType != 'Unranked' and $potType != 'Sum-of-squares') { + throw new Exception(l_t('Invalid potType input given.')); + } - $phaseMinutes = (int)$phaseMinutes; - if ($phaseMinutes < 5 or $phaseMinutes > 1440*10) { - throw new Exception(l_t("The phase value is too large or small; it must be between 5 minutes and 10 days.")); - } - $phaseMinutesRB = (int)$phaseMinutesRB; - if ($phaseMinutesRB != -1 && ($phaseMinutesRB < 1 or $phaseMinutesRB > 1440*10)) { - throw new Exception(l_t("The phase value for retreats and builds is too large or small; it must be between 1 minute and 10 days.")); - } - if ($phaseMinutesRB != -1 && ($phaseMinutesRB > $phaseMinutes || $phaseMinutesRB < $phaseMinutes / 10)) { - throw new Exception(l_t("The phase length for retreats and builds must be within 10% and 100% of the regular phase length.")); - } + $phaseMinutes = (int)$phaseMinutes; + if ($phaseMinutes < 5 or $phaseMinutes > 1440*10) { + throw new Exception(l_t("The phase value is too large or small; it must be between 5 minutes and 10 days.")); + } + $phaseMinutesRB = (int)$phaseMinutesRB; + if ($phaseMinutesRB != -1 && ($phaseMinutesRB < 1 or $phaseMinutesRB > 1440*10)) { + throw new Exception(l_t("The phase value for retreats and builds is too large or small; it must be between 1 minute and 10 days.")); + } + if ($phaseMinutesRB != -1 && ($phaseMinutesRB > $phaseMinutes || $phaseMinutesRB < $phaseMinutes / 10)) { + throw new Exception(l_t("The phase length for retreats and builds must be within 10% and 100% of the regular phase length.")); + } - $nextPhaseMinutes = (int)$nextPhaseMinutes; - $phaseSwitchPeriod = (int)$phaseSwitchPeriod; + $nextPhaseMinutes = (int)$nextPhaseMinutes; + $phaseSwitchPeriod = (int)$phaseSwitchPeriod; - // If a game is not live, set the next phase minutes to match the phase. - if ($phaseMinutes > 60) { - $nextPhaseMinutes = $phaseMinutes; - $phaseSwitchPeriod = -1; + // If a game is not live, set the next phase minutes to match the phase. + if ($phaseMinutes > 60) { + $nextPhaseMinutes = $phaseMinutes; + $phaseSwitchPeriod = -1; + } + + if ($phaseMinutes < 61 and $phaseSwitchPeriod != -1) { + // If the next phase minutes is less than 1 day or more than 10 because someone is messing around with the console, default to 2 days if the game is live. + if (($nextPhaseMinutes < 1440 or $nextPhaseMinutes > 1440*10)) { + $nextPhaseMinutes = 2880; } - - if ($phaseMinutes < 61 and $phaseSwitchPeriod != -1) { - // If the next phase minutes is less than 1 day or more than 10 because someone is messing around with the console, default to 2 days if the game is live. - if (($nextPhaseMinutes < 1440 or $nextPhaseMinutes > 1440*10)) { - $nextPhaseMinutes = 2880; - } - // If the phase Switch period is outside the allowed range default it to 3 hours. - if (($phaseSwitchPeriod > 360 or $phaseSwitchPeriod < $phaseMinutes)) { - $phaseSwitchPeriod = 180; - } + // If the phase Switch period is outside the allowed range default it to 3 hours. + if (($phaseSwitchPeriod > 360 or $phaseSwitchPeriod < $phaseMinutes)) { + $phaseSwitchPeriod = 180; } + } - $joinPeriod = (int)$joinPeriod; - if ($joinPeriod < 5 or $joinPeriod > 1440*14) { - throw new Exception(l_t("Joining period value out of range.")); - } - - $anon = ((strtolower($anon) == 'yes') ? 'Yes' : 'No'); - - // Force 1 vs 1 variants to be unranked to prevent point farming. - if ($variantID == 15 or $variantID == 23 or $variantID == 91) { - $bet = 5; - $potType = 'Unranked'; - } + $joinPeriod = (int)$joinPeriod; + if ($joinPeriod < 5 or $joinPeriod > 1440*14) { + throw new Exception(l_t("Joining period value out of range.")); + } + + $anon = ((strtolower($anon) == 'yes') ? 'Yes' : 'No'); + + // Force 1 vs 1 variants to be unranked to prevent point farming. + if ($variantID == 15 or $variantID == 23 or $variantID == 91) { + $bet = 5; + $potType = 'Unranked'; + } - // Only classic, no press can support fill with bots. - if (($variantID != 1) || ($pressType != 'NoPress')) { - $botFill = 'No'; - } + // Only classic, no press can support fill with bots. + if (($variantID != 1) || ($pressType != 'NoPress')) { + $botFill = 'No'; + } - // If no press is selected, force the game to anon to prevent cheating via out of game messaging. - switch($pressType) { - case 'PublicPressOnly': - $pressType = 'PublicPressOnly'; - break; - case 'NoPress': - $pressType = 'NoPress'; - $anon = 'Yes'; - break; - case 'RulebookPress': - $pressType = 'RulebookPress'; - break; - case 'Regular': // Regular is the default - default: - $pressType = 'Regular'; - } - - // Force bot games to be no press and unranked. - if($botFill == 'Yes') { + // If no press is selected, force the game to anon to prevent cheating via out of game messaging. + switch($pressType) { + case 'PublicPressOnly': + $pressType = 'PublicPressOnly'; + break; + case 'NoPress': $pressType = 'NoPress'; - $potType = 'Unranked'; - $bet = 5; - $playerTypes = 'Mixed'; - } - - switch($missingPlayerPolicy) { - case 'Wait': - $missingPlayerPolicy = 'Wait'; - break; - default: - $missingPlayerPolicy = 'Normal'; - } switch($drawType) { - case 'draw-votes-hidden': - $drawType = 'draw-votes-hidden'; - break; - default: - $drawType = 'draw-votes-public'; - break; - } + $anon = 'Yes'; + break; + case 'RulebookPress': + $pressType = 'RulebookPress'; + break; + case 'Regular': // Regular is the default + default: + $pressType = 'Regular'; + } + + // Force bot games to be no press and unranked. + if($botFill == 'Yes') { + $pressType = 'NoPress'; + $potType = 'Unranked'; + $bet = 5; + $playerTypes = 'Mixed'; + } - $minimumReliabilityRating = (int)$minimumReliabilityRating; - if ($minimumReliabilityRating < 0 or $minimumReliabilityRating > 100) { - throw new RequestException(l_t("The reliability rating threshold must range from 0-100")); - } + switch($missingPlayerPolicy) { + case 'Wait': + $missingPlayerPolicy = 'Wait'; + break; + default: + $missingPlayerPolicy = 'Normal'; + } switch($drawType) { + case 'draw-votes-hidden': + $drawType = 'draw-votes-hidden'; + break; + default: + $drawType = 'draw-votes-public'; + break; + } - if ($minimumReliabilityRating > $User->reliabilityRating) { - throw new Exception(l_t("Your reliability rating is %s%%, so you can't create a game which requires players to have a RR of %s%% or greater.",$User->reliabilityRating, $minimumReliabilityRating)); - } + $minimumReliabilityRating = (int)$minimumReliabilityRating; + if ($minimumReliabilityRating < 0 or $minimumReliabilityRating > 100) { + throw new RequestException(l_t("The reliability rating threshold must range from 0-100")); + } - $excusedMissedTurns = (int)$excusedMissedTurns; - if ($excusedMissedTurns < 0 || $excusedMissedTurns > 4) { - throw new Exception(l_t("The excused missed turn number is too large or small; it must be between 0 and 4.")); - } + // if ($minimumReliabilityRating > $User->reliabilityRating) { + // throw new Exception(l_t("Your reliability rating is %s%%, so you can't create a game which requires players to have a RR of %s%% or greater.",$User->reliabilityRating, $minimumReliabilityRating)); + // } - // Prevent temp banned players from making new games. - if ($User->userIsTempBanned()) { - throw new Exception(l_t("You are blocked from creating new games.', 'You are blocked from creating new games.")); - } + $excusedMissedTurns = (int)$excusedMissedTurns; + if ($excusedMissedTurns < 0 || $excusedMissedTurns > 4) { + throw new Exception(l_t("The excused missed turn number is too large or small; it must be between 0 and 4.")); + } - // Create Game record & object - // require_once(l_r('gamemaster/game.php')); - // $Game = processGame::create( - // $variantID, - // $name, - // $inviteCode, - // $bet, - // $potType, - // $phaseMinutes, - // $phaseMinutesRB, - // $nextPhaseMinutes, - // $phaseSwitchPeriod, - // $joinPeriod, - // $anon, - // $pressType, - // $missingPlayerPolicy, - // $drawType, - // $minimumReliabilityRating, - // $excusedMissedTurns, - // $playerTypes); - - // file_put_contents('php://stdout', 'Enter here'); - // file_put_contents('php://stdout', $User->id); - // // Create first Member record & object - // processMember::create($User->id, $bet); - // $Game->Members->joinedRedirect(); - - // $responseStr = $game ? 'Game successfully created.' : 'Game was not created'; - $responseStr = ""; - - return $this->JSONResponse( - $responseStr, - '', - true, - $payload - ); - } catch(Exception $e) { - // return $this->JSONResponse( - // $e->getMessage(), - // '', - // false, - // $payload - // ); - throw new RequestException( - $this->JSONResponse('A gameID is required.', '', false, []) - ); + // Prevent temp banned players from making new games. + if ($User->userIsTempBanned()) { + throw new Exception(l_t("You are blocked from creating new games.', 'You are blocked from creating new games.")); } + + // Create Game record & object + require_once(l_r('gamemaster/game.php')); + $Game = processGame::create( + $variantID, + $name, + $inviteCode, + $bet, + $potType, + $phaseMinutes, + $phaseMinutesRB, + $nextPhaseMinutes, + $phaseSwitchPeriod, + $joinPeriod, + $anon, + $pressType, + $missingPlayerPolicy, + $drawType, + $minimumReliabilityRating, + $excusedMissedTurns, + $playerTypes); + + file_put_contents('php://stdout', 'Enter here'); + file_put_contents('php://stdout', $User->id); + // Create first Member record & object + processMember::create($User->id, $bet); + // $Game->Members->joinedRedirect(); + + // $responseStr = $game ? 'Game successfully created.' : 'Game was not created'; + return $this->JSONResponse( + 'Successfully created game.', + '', + true, + [ + 'gameID' => $Game->id + ] + ); } } // return json_encode([ diff --git a/beta-src/src/components/ui/new/CreateGameForm.tsx b/beta-src/src/components/ui/new/CreateGameForm.tsx index 8882ca71f..c33848e6d 100644 --- a/beta-src/src/components/ui/new/CreateGameForm.tsx +++ b/beta-src/src/components/ui/new/CreateGameForm.tsx @@ -65,7 +65,7 @@ const CreateGameForm: FunctionComponent = function ({ validationSchema, onSubmit: async (values) => { console.log("values", values); - // dispatch(createGame(values)); + dispatch(createGame(values)); showSuccess({ title: "Game created", description: "The game was successfully created", diff --git a/beta-src/src/state/game/game-api-slice.ts b/beta-src/src/state/game/game-api-slice.ts index 0853a44f0..bd0421fb5 100644 --- a/beta-src/src/state/game/game-api-slice.ts +++ b/beta-src/src/state/game/game-api-slice.ts @@ -437,6 +437,8 @@ const gameApiSlice = createSlice({ if (action.payload) { handlePostSucceeded(state); console.log({ action }); + const { gameID } = action.payload; + // redirect to gameID // const { messages } = action.payload; // const allMessages = mergeMessageArrays( @@ -452,6 +454,7 @@ const gameApiSlice = createSlice({ } }) .addCase(createGame.rejected, (state, action) => { + console.log({ state, action }); handlePostFailed( state, "Error sending message, network connection issue", From d123a3069539321af82db93f2f11bbe8e6545fd6 Mon Sep 17 00:00:00 2001 From: Adam Lerer Date: Wed, 9 Nov 2022 14:38:20 -0800 Subject: [PATCH 2/5] Write the backend for listing games --- api.php | 22 +++++++- api/responses/list_games.php | 100 +++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 api/responses/list_games.php diff --git a/api.php b/api.php index c878ed64e..55562853d 100644 --- a/api.php +++ b/api.php @@ -32,6 +32,7 @@ require_once('api/responses/members_in_cd.php'); require_once('api/responses/unordered_countries.php'); require_once('api/responses/active_games.php'); +require_once('api/responses/list_games.php'); require_once('api/responses/game_state.php'); require_once('objects/game.php'); require_once('objects/user.php'); @@ -342,15 +343,32 @@ public function run($userID, $permissionIsExplicit) { } } +/** + * API entry players/list_games + * + * List all games. + */ +class ListGames extends ApiEntry { + public function __construct() { + parent::__construct('players/list_games', 'GET', '', array(), false); + } + public function run($userID, $permissionIsExplicit) { + $gameList = new \webdiplomacy_api\ListGames($userID, ); + + return $gameList->toJson(); + } +} + /** * API entry players/active_games */ class ListActiveGamesForUser extends ApiEntry { public function __construct() { - parent::__construct('players/active_games', 'GET', '', array(), false); + parent::__construct('players/active_games', 'GET', '', array('queryType'), false); } public function run($userID, $permissionIsExplicit) { - $activeGames = new \webdiplomacy_api\ActiveGames($userID); + $queryType = $args['queryType']; + $activeGames = new \webdiplomacy_api\ActiveGames($userID, $queryType); return $activeGames->toJson(); } } diff --git a/api/responses/list_games.php b/api/responses/list_games.php new file mode 100644 index 000000000..99d58672c --- /dev/null +++ b/api/responses/list_games.php @@ -0,0 +1,100 @@ +. + */ +namespace webdiplomacy_api; + +defined('IN_CODE') or die('This script can not be run by itself.'); + +require_once ('config.php'); +require_once ('game_country.php'); + +/** + * List all games for a certain query + * + * Note: copied with modification from gamelistings.php + * + * @package webdiplomacy_api + */ +class ListGames { + /** + * List of (gameID, countryID) + * @var array + */ + public $value = array(); + + /** + * Load the countries with missing orders for a given user; + */ + function load($userID, $queryType) + { + global $DB; + + // Filter allowed variantIDs + $apiVariants = implode(', ', \Config::$apiConfig['variantIDs']); + + // Filter allowed gameIDs + $filterGameClause = ''; + if (!empty(\Config::$apiConfig['restrictToGameIDs'])) { + $filterGameIDs = implode(', ', \Config::$apiConfig['restrictToGameIDs']); + $filterGameClause = "AND g.id IN ($filterGameIDs)"; + } + + // for now, lets just have a fixed set of query types + if ($queryType == 'new') { + $filterGameClause = "$filterGameClause AND g.phase = 'Pre-game' AND playerTypes <> 'MemberVsBots' "; + } + elseif ($queryType == 'active') { + $filterGameClause = "$filterGameClause AND g.phase <> 'Pre-game' AND g.phase <> 'Finished' AND playerTypes <> 'MemberVsBots' "; + } else { + throw new RequestException("Unknown query type: $queryType"); + } + + $tabl = $DB->sql_tabl("SELECT g.id, g.turn, g.phase, g.name, g.processTime, g.phaseMinutes, g.pressType, g.variantID + FROM wD_Games AS g + WHERE $filterGameClause + ORDER BY g.processTime ASC;"); + + while( $row = $DB->tabl_hash($tabl) ) + { + array_push($this->value, [ + 'gameID' => intval($row['id']), + 'pressType' => $row['pressType'], + 'turn' => intval($row['turn']), + 'phase' => $row['phase'], + 'processTime' => intval($row['processTime']), + 'phaseMinutes' => intval($row['phaseMinutes']), + 'variantID' => intval($row['variantID']), + ]); + } + } + + function toJson() + { + return json_encode(['games' => $this->value]); + } + + /** + * Finds games where the user is playing and orders have not been submitted yet. + */ + function __construct($userID) + { + $this->load($userID); + } + +} From 232440dd705466ecd95b50d91e8d5a7635eee9f8 Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 10 Nov 2022 19:14:56 -0500 Subject: [PATCH 3/5] add DB commit --- api.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api.php b/api.php index 55562853d..219813260 100644 --- a/api.php +++ b/api.php @@ -1623,6 +1623,8 @@ public function run($userID, $permissionIsExplicit) { // $Game->Members->joinedRedirect(); // $responseStr = $game ? 'Game successfully created.' : 'Game was not created'; + $DB->sql_put("COMMIT"); + return $this->JSONResponse( 'Successfully created game.', '', From 0dbc0cac71331271444b2570a26f970b7e09740f Mon Sep 17 00:00:00 2001 From: Adam Lerer Date: Thu, 17 Nov 2022 07:54:14 -0800 Subject: [PATCH 4/5] fix --- api.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/api.php b/api.php index 219813260..4a1eff82e 100644 --- a/api.php +++ b/api.php @@ -350,11 +350,11 @@ public function run($userID, $permissionIsExplicit) { */ class ListGames extends ApiEntry { public function __construct() { - parent::__construct('players/list_games', 'GET', '', array(), false); + parent::__construct('players/list_games', 'GET', '', array('queryType'), false); } public function run($userID, $permissionIsExplicit) { - $gameList = new \webdiplomacy_api\ListGames($userID, ); - + $queryType = $args['queryType']; + $gameList = new \webdiplomacy_api\ListGames($userID, $queryType); return $gameList->toJson(); } } @@ -364,11 +364,10 @@ public function run($userID, $permissionIsExplicit) { */ class ListActiveGamesForUser extends ApiEntry { public function __construct() { - parent::__construct('players/active_games', 'GET', '', array('queryType'), false); + parent::__construct('players/active_games', 'GET', '', array(), false); } public function run($userID, $permissionIsExplicit) { - $queryType = $args['queryType']; - $activeGames = new \webdiplomacy_api\ActiveGames($userID, $queryType); + $activeGames = new \webdiplomacy_api\ActiveGames($userID); return $activeGames->toJson(); } } From eb192607d2b90b3394429a325259f3865b016fc4 Mon Sep 17 00:00:00 2001 From: Cesar Gutierrez Date: Thu, 17 Nov 2022 19:22:58 -0500 Subject: [PATCH 5/5] add list games --- api.php | 1 + 1 file changed, 1 insertion(+) diff --git a/api.php b/api.php index 4a1eff82e..bc6605d30 100644 --- a/api.php +++ b/api.php @@ -1916,6 +1916,7 @@ public function run() { $api->load(new GetMessages()); $api->load(new GetAllGames()); $api->load(new CreateGame()); + $api->load(new ListGames()); $api->load(new MessagesSeen()); $api->load(new MarkBackFromLeft());