/// <summary> /// Scores the passed word in the passed boggle board. It assumes the word has not been played before. /// /// Case insensitive. /// </summary> private int ScoreWord(string boardString, string word) { //If the word is too small if (word.Length < 3) { return(0); } //Valid word scoring else if (StaticBoard.CanBeFormed(boardString, word) && Dict.Contains(word.ToLower())) { int leng = word.Length; if (leng == 3 || leng == 4) { return(1); } else if (leng == 5 || leng == 6) { return(leng - 3); } else if (leng == 7) { return(5); } else { return(11); } } //Invalid word that is longer is length 3 else { return(-1); } }
/// <summary> /// Attempts to join a game with user userToken and timeLimit /// /// If UserToken is invalid, TimeLimit is less than 5, or TimeLimit is over 120, responds /// with status 403 (Forbidden). /// /// Otherwise, if UserToken is already a player in the pending game, responds with status /// 409 (Conflict). /// /// Otherwise, if there is already one player in the pending game, adds UserToken as the /// second player. The pending game becomes active. The active game's time limit is the integer /// average of the time limits requested by the two players. Returns the new active game's /// GameID (which should be the same as the old pending game's GameID). Responds with /// status 201 (Created). /// /// Otherwise, adds UserToken as the first player of a new pending game, and the TimeLimit as /// the pending game's requested time limit. Returns the pending game's GameID. Responds with /// status 202 (Accepted). /// </summary> public GameIDResponse JoinGame(JoinRequest request, out HttpStatusCode status) { int timeLimit = request.TimeLimit; // make sure TimeLimit is within the expected bounds if (!(timeLimit >= 5 && timeLimit <= 120)) { status = Forbidden; return(null); } //null checks if (request is null || request.UserToken is null) { status = Forbidden; return(null); } // the UserID that'll be used throughout this method string userID = request.UserToken.Trim(); // make sure UserToken is within the expected bounds if (userID == null || userID.Length == 0 || userID.Length > 36) { status = Forbidden; return(null); } // open connection to database using (SqlConnection connection = new SqlConnection(BoggleDB)) { connection.Open(); // execute all commands within a single transaction using (SqlTransaction transaction = connection.BeginTransaction()) { // todo: make sure GameID starts at 1, not 0 // (otherwise, this should be changed, because this might actually end up as 0 when creating a game) int gameID = -1; // find out whether there's a pending game using (SqlCommand command = new SqlCommand("select GameID, Player1, TimeLimit from Games where Player2 is null", connection, transaction)) { // the reader that will determine whether there's a pending game, and if so, what its gameID is using (SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { gameID = (int)reader["GameID"]; string player1 = (string)reader["Player1"]; // averages the time between player1's requested time and this user's requested time int player1RequestedTime = (int)reader["TimeLimit"]; timeLimit = (timeLimit + player1RequestedTime) / 2; // player is already searching for a game if (player1 == userID) { status = Conflict; reader.Close(); transaction.Commit(); return(null); } } } } if (gameID == -1) { using (SqlCommand command = new SqlCommand("insert into Games (Player1, TimeLimit) output inserted.GameID values(@Player1, @TimeLimit)", connection, transaction)) { command.Parameters.AddWithValue("@Player1", userID); command.Parameters.AddWithValue("@TimeLimit", timeLimit); SqlParameter outputparam = new SqlParameter("@GameID", SqlDbType.Int) { Direction = ParameterDirection.Output }; command.Parameters.Add(outputparam); // execute command, and get back the primary key (GameID) try { gameID = (int)command.ExecuteScalar(); } //If an exception was thrown, a foreign key pair was violated catch (SqlException) { status = Forbidden; transaction.Commit(); return(null); } status = Accepted; } } else { using (SqlCommand command = new SqlCommand("update Games set Player2 = @Player2, Board = @Board, TimeLimit = @TimeLimit, StartTime = @StartTime where GameID = @GameID", connection, transaction)) { command.Parameters.AddWithValue("@Player2", userID); command.Parameters.AddWithValue("@Board", StaticBoard.GenerateBoggleBoard()); command.Parameters.AddWithValue("@TimeLimit", timeLimit); command.Parameters.AddWithValue("@StartTime", DateTime.UtcNow); command.Parameters.AddWithValue("@GameID", gameID); try { if (command.ExecuteNonQuery() != 1) { throw new Exception("SQL query failed"); } } //If Player2 is not a registered user catch (SqlException) { status = Forbidden; transaction.Commit(); return(null); } status = Created; } } transaction.Commit(); return(new GameIDResponse { GameID = gameID }); } } }