/// <summary> /// Private method that fully creates a game, called after two players enter a game. /// </summary> /// <param name="timeLimit">TimeLimit of second user</param> /// <param name="gameID">ID of game to be created</param> private void setupGame(string timeLimit, string gameID) { BoggleBoard board = new BoggleBoard(); int time1; int time2; int.TryParse(AllGames[gameID].TimeLimit, out time1); int.TryParse(timeLimit, out time2); if (time1 < time2) { time2 = ((time2 - time1) / 2); } else { time1 = ((time1 - time2) / 2); } AllGames[gameID].TimeLimit = (time1 + time2).ToString(); AllGames[gameID].TimeLeft = AllGames[gameID].TimeLimit; AllGames[gameID].GameState = "active"; AllGames[gameID].RelevantBoard = board; AllGames[gameID].Board = AllGames[gameID].RelevantBoard.ToString(); AllGames[gameID].StartGameTime = DateTime.Now; }
/// <summary> /// Helper to check score for a given word /// </summary> private int CheckScore(string word, BoggleBoard board) { if (word.Length < 3) { return(0); } // Illegal word if (!validwords.Contains(word) || !board.CanBeFormed(word)) { return(-1); } else if (word.Length > 7) { return(11); } else if (word.Length == 7) { return(5); } else if (word.Length == 6) { return(3); } else if (word.Length == 5) { return(2); } // word length 3 or 4 else { return(1); } }
/// <summary> /// Helper method that gets all the words that a player has played in a given game /// </summary> /// <param name="UserToken"></param> /// <returns></returns> private List <Words> GetWordsPlayed(string UserToken, string GameID, BoggleBoard board) { lock (sync) { List <Words> wordList = new List <Words>(); using (SqlConnection conn = new SqlConnection(BoggleDB)) { conn.Open(); using (SqlTransaction trans = conn.BeginTransaction()) { using (SqlCommand command = new SqlCommand("SELECT * FROM Words WHERE GameID = " + GameID + "AND Player = \'" + UserToken + "\'", conn, trans)) { SqlDataReader reader = command.ExecuteReaderAsync().Result; while (reader.Read()) { try { Words word = new Words(); word.Word = reader.GetFieldValue <string>(1); word.Score = reader.GetFieldValue <int>(4); wordList.Add(word); } catch { // Intentionally empty } } reader.Close(); trans.Commit(); } } } return(wordList); } }
/// <summary> /// Helper method finds valid words, given a game board /// </summary> /// <param name="board"></param> /// <returns></returns> public Dictionary <int, LinkedList <string> > GetValidWords(BoggleBoard board, int desiredNumWords) { Dictionary <int, LinkedList <string> > validWords = new Dictionary <int, LinkedList <string> >(); int timesChecked = 0; using (StreamReader reader = new StreamReader("dictionary.txt")) { string line; while ((line = reader.ReadLine()) != null && timesChecked < desiredNumWords) { if (board.CanBeFormed(line)) { if (!validWords.ContainsKey(line.Length)) { validWords.Add(line.Length, new LinkedList <string>()); } validWords[line.Length].AddLast(line); desiredNumWords++; } } } return(validWords); }
public void PlayWord14() { Dictionary <string, string> gameInfo = simulateGame(30); string[] words = File.ReadAllLines("dictionary.txt"); Response gameRequest = client.DoGetAsync("games/{0}?Brief={1}", gameInfo["gameId"], "asdf").Result; dynamic game = gameRequest.Data; BoggleBoard board = new BoggleBoard(game.Board.ToString()); dynamic play = new ExpandoObject(); play.UserToken = gameInfo["userToken"]; play.Word = "jkashdjkhfakfhad"; Response r = client.DoPutAsync(play, "games/" + gameInfo["gameId"]).Result; Assert.AreEqual(OK, r.Status); dynamic result = r.Data; int score; Assert.IsTrue(Int32.TryParse(result.Score.ToString(), out score)); Assert.AreEqual(-1, score); }
public BoggleResult(BoggleBoard board, Dictionary <string, int> wordPointDict, int points, TimeSpan duration) { Board = board; WordPointDict = wordPointDict; Points = points; Duration = duration; }
private BoggleTracker CreateTracker(IBogglePlayer player, BoggleBoard board) { BoggleTracker tracker = new BoggleTracker(player.Id, board); Trackers.Add(tracker); return(tracker); }
/// <summary> /// Takes a valid game ID and process Boggle game logic and returns a score based on word evaluation. /// </summary> /// <param name="games"></param> /// <param name="GameID"></param> /// <returns></returns> public PlayResponse PlayWord(PlayRequest games, string GamedID, out HttpStatusCode status) { string word = games.Word; string trimmed; // Various types of condition checks for request object, played word and game ID if (word == null || (trimmed = word.Trim()).Length == 0 || games.UserToken == null) { status = Forbidden; return(null); } if (!Int32.TryParse(GamedID, out int id)) { status = Forbidden; return(null); } PlayResponse response = new PlayResponse(); using (SqlConnection conn = new SqlConnection(BoggleDB)) { conn.Open(); using (SqlTransaction trans = conn.BeginTransaction()) { if (!IsUserTokenValid(games.UserToken, conn, trans) || id < 1 || id > GetRecentGameID(conn, trans) || !IsPlayerInGame(games.UserToken, conn, trans, id)) { status = Forbidden; return(null); } if (ComputeTimeLeft(id, conn, trans) < 1) { status = Conflict; return(null); } // If everything is fine at this point, insert the played word into DB using (SqlCommand comm = new SqlCommand("INSERT INTO Words (Word, Player, GameID, Score) VALUES (@Word, @Player, @GameID, @Score)", conn, trans)) { BoggleBoard board = FetchBoard(id, conn, trans); List <WordsPlayed> playedList = FetchWords(games.UserToken, id, conn, trans); // Compute score with gameboard and played word list int score = ComputeScore(trimmed, board, playedList); comm.Parameters.AddWithValue("@Word", trimmed); comm.Parameters.AddWithValue("@Player", games.UserToken); comm.Parameters.AddWithValue("@GameID", id); comm.Parameters.AddWithValue("@Score", score); // Compose response message response.Score = score; comm.ExecuteNonQuery(); } trans.Commit(); } } status = OK; return(response); }
public void BasicTests() { //Create users -- throws exception if unsuccessful string usertoken1 = CreateUser("Boggler"); string usertoken2 = CreateUser("Boggled"); //Join game 1 -- throws exception if unsuccessful string gameid1 = JoinGame(usertoken1, 15); dynamic token = GameStatus(gameid1); //Test that game is pending string status = token.GameState; Assert.AreEqual("pending", status); //Join game 2 string gameid2 = JoinGame(usertoken2, 15); //Test that gameid1 and gameid2 are same Assert.AreEqual(gameid1, gameid2); //Test that game is now active token = GameStatus(gameid1); status = token.GameState; Assert.AreEqual("active", status); //Test play word player 1 string score = PlayWord(usertoken1, "ABUDABUDABBADABBA", gameid1); Assert.AreEqual("-1", score); //Test the game status token = GameStatus(gameid1); score = token.Player1.Score; Assert.AreEqual("-1", score); //Test play word player 2 score = PlayWord(usertoken2, "ZXquekoi03jd@", gameid1); Assert.AreEqual("-1", score); //Test the game status token = GameStatus(gameid1); score = token.Player2.Score; Assert.AreEqual("-1", score); //Test stream generation Response r = client.DoGetAsync("/games/" + gameid1).Result; Assert.AreEqual(r.Status, OK); BoggleBoard bb = new BoggleBoard("AAAAAAAAAAAAAAAA"); }
/// Play a word in a game. /// If Word is null or empty or longer than 30 characters when trimmed, or if GameID or UserToken is invalid, or if UserToken is not a player in the /// game identified by GameID, responds with response code 403 (Forbidden). /// Otherwise, if the game state is anything other than "active", responds with response code 409 (Conflict). /// Otherwise, records the trimmed Word as being played by UserToken in the game identified by GameID. Returns the score for Word in the context of the /// game (e.g. if Word has been played before the score is zero). Responds with status 200 (OK). Note: The word is not case sensitive. public WordScore PlayWord(WordToPlay w, string gameID) { lock (sync) { if (w.Word == null || w.Word.Trim().Length > 30 || w.UserToken == null || !players.ContainsKey(w.UserToken) || gameID == null || !(games.TryGetValue(gameID, out GameStatus temp) || (temp.Player1.UserToken != w.UserToken || temp.Player2.UserToken != w.UserToken))) { SetStatus(Forbidden); return(null); } else { games.TryGetValue(gameID, out GameStatus g); if (!g.GameState.Equals("active")) { SetStatus(Conflict); return(null); } else { updateTime(gameID); Words wordPlay = new Words(); wordPlay.Word = w.Word; // Generate boggle board board = new BoggleBoard(g.Board); players.TryGetValue(w.UserToken, out Player p); // Score 0 if the word is less than 3 characters or -1 if it doesn't exist in dic. wordPlay.Score = board.CanBeFormed(wordPlay.Word) ? GetScore(wordPlay.Word) : -1; if (wordPlay.Word.Length < 3) { wordPlay.Score = 0; } else { foreach (Words word in p.WordsPlayed) { if (word.Word.ToUpper().Equals(wordPlay.Word.ToUpper())) { wordPlay.Score = 0; } } } // Set the appropriate score for each word WordScore scoreWord = new WordScore(); scoreWord.Score = wordPlay.Score; // Update the players' scores p.Score += wordPlay.Score; p.WordsPlayed.Add(wordPlay); SetStatus(OK); return(scoreWord); } } } }
public BoggleTracker(Guid playerId, BoggleBoard board) { PlayerId = playerId; Board = board; WordPointDict = new Dictionary <string, int>(); Points = 0; Stopwatch = new Stopwatch(); }
public GameInfo(int Gameid) { GameState = "pending"; GameID = Gameid.ToString(); //Player1.Score = 0; // Player2.Score = 0; GameBoard = new BoggleBoard(); Board = GameBoard.ToString(); }
/// Play a word in a game. /// If Word is null or empty or longer than 30 characters when trimmed, or if GameID or UserToken is invalid, or if UserToken is not a player in the /// game identified by GameID, responds with response code 403 (Forbidden). /// Otherwise, if the game state is anything other than "active", responds with response code 409 (Conflict). /// Otherwise, records the trimmed Word as being played by UserToken in the game identified by GameID. Returns the score for Word in the context of the /// game (e.g. if Word has been played before the score is zero). Responds with status 200 (OK). Note: The word is not case sensitive. public WordScore PlayWord(WordToPlay w, string gameID) { int timeLeft; if (w.Word == null || w.Word.Equals("") || w.Word.Trim().Length > 30 || w.UserToken == null || !tryGetPlayer(w.UserToken, out Player p) || gameID == null || !int.TryParse(gameID, out int GameID) || !((timeLeft = getTimeLeft(GameID)) is int) || !tryGetGame(GameID, out GameStatus g) || (!w.UserToken.Equals(g.Player1.UserToken) && !w.UserToken.Equals(g.Player2.UserToken))) { SetStatus(Forbidden); return(null); } else { if (!g.GameState.Equals("active")) { SetStatus(Conflict); return(null); } else { Words wordPlay = new Words(); wordPlay.Word = w.Word; // Generate boggle board BoggleBoard board = new BoggleBoard(g.Board); // Score 0 if the word is less than 3 characters or -1 if it doesn't exist in dic. wordPlay.Score = board.CanBeFormed(wordPlay.Word) ? GetScore(wordPlay.Word) : -1; if (wordPlay.Word.Length < 3) { wordPlay.Score = 0; } else { foreach (Words word in getWordsPlayed(w.UserToken, GameID)) { if (word.Word.ToUpper().Equals(wordPlay.Word.ToUpper())) { wordPlay.Score = 0; } } } // Set the appropriate score for each word WordScore scoreWord = new WordScore(); scoreWord.Score = wordPlay.Score; // Update the players' played words addWordToList(w, GameID, scoreWord.Score); SetStatus(OK); return(scoreWord); } } }
public BoggleGame(string player1, string player2, ISet<string> dictionary, int timeLimit) { this.dictionary = dictionary; this.Player1 = player1; this.Player2 = player2; Words1 = new List<WordAndScore>(); Words2 = new List<WordAndScore>(); TimeLimit = timeLimit; startTime = DateTime.Now; board = new BoggleBoard(); }
public void PlayWordCoverage() { dynamic data = new ExpandoObject(); data.Nickname = "p1"; Response r = client.DoPostAsync("users", data).Result; Assert.AreEqual(Created, r.Status); string p1token = (string)r.Data.UserToken; data = new ExpandoObject(); data.Nickname = "p2"; r = client.DoPostAsync("users", data).Result; Assert.AreEqual(Created, r.Status); string p2token = (string)r.Data.UserToken; data = new ExpandoObject(); data.Nickname = "p3"; r = client.DoPostAsync("users", data).Result; Assert.AreEqual(Created, r.Status); string p3token = (string)r.Data.UserToken; data = new ExpandoObject(); data.UserToken = p1token; data.TimeLimit = 10; r = client.DoPostAsync("games", data).Result; Assert.AreEqual(Accepted, r.Status); string gid = (string)r.Data.GameID; data = new ExpandoObject(); data.UserToken = p2token; data.TimeLimit = 10; r = client.DoPostAsync("games", data).Result; Assert.AreEqual(Created, r.Status); Assert.AreEqual(gid, (string)r.Data.GameID); r = client.DoGetAsync("games/" + gid).Result; Assert.AreEqual(OK, r.Status); BoggleBoard board = new BoggleBoard((string)r.Data.Board); Dictionary <int, LinkedList <string> > validWords = GetValidWords(board, 1); foreach (int key in validWords.Keys) { data = new ExpandoObject(); data.UserToken = p3token; data.Word = validWords[key].First.Value; r = client.DoPutAsync("games/" + gid, data).Result; Assert.AreEqual(Forbidden, r.Status); } }
/// <summary> /// overload for user specified board with preset dice results. /// </summary> /// <param name="_p1Sock"> player one's socket (ss)</param> /// <param name="_p2Sock">player two's socket (ss)</param> /// <param name="_time">the game time</param> /// <param name="boardLetters">the optional string params for the console running emacs stuff</param> public game(BoggleServer _parent, Tuple <StringSocket, string> _p1Sock, Tuple <StringSocket, string> _p2Sock, int _time, string boardLetters) { parent = _parent; player1 = new player(_p1Sock.Item1, _p1Sock.Item2); player2 = new player(_p2Sock.Item1, _p2Sock.Item2); time = _time; board = new BoggleBoard(boardLetters); secondsTimer = new Timer(1000); common = new HashSet <string>(); processingKey = new object(); StartGame(); }
/// <summary> /// Given a board configuration, returns all the valid words. /// </summary> private static List <string> AllValidWords(string board) { BoggleBoard bb = new BoggleBoard(board); List <string> validWords = new List <string>(); foreach (string word in dictionary) { if (word.Length > 2 && bb.CanBeFormed(word)) { validWords.Add(word); } } return(validWords); }
public static int WordValue(string word, string board, ISet <string> dictionary) { if (word == null) { return(-2); } else if (word.Length < 3) { return(0); } else if (!dictionary.Contains(word.ToUpper())) { return(-1); } else if (BoggleBoard.CanBeFormed(word, board)) { if (word.Length <= 4) { return(1); } else if (word.Length == 5) { return(2); } else if (word.Length == 6) { return(3); } else if (word.Length == 7) { return(5); } else { return(11); } } else { return(-1); } }
private int calculateScore(BoggleBoard boggleBoard, string word) { if (word == null || boggleBoard == null) { return(-2); } //here you need to add the word to the database, //if the word is already there set the score to zero. return((boggleBoard.CanBeFormed(word) && bigDict.Contains(word)) ? word.Length < 3 ? 0 : word.Length < 5 ? 1 : word.Length < 6 ? 2 : word.Length < 7 ? 3 : word.Length < 8 ? 5 : 11 : -1); }
public void PlayWord13() { Dictionary <string, string> gameInfo = simulateGame(30); string[] words = File.ReadAllLines("dictionary.txt"); Response gameRequest = client.DoGetAsync("games/{0}?Brief={1}", gameInfo["gameId"], "asdf").Result; dynamic game = gameRequest.Data; BoggleBoard board = new BoggleBoard(game.Board.ToString()); string word = ""; foreach (string s in words) { if (s.Length == 5 && board.CanBeFormed(s)) { // Found a valid word word = s; break; } } // Repeat the test with new boards until a word with 5 letters can be formed. if (word != "") { dynamic play = new ExpandoObject(); play.UserToken = gameInfo["userToken"]; play.Word = word; Response r = client.DoPutAsync(play, "games/" + gameInfo["gameId"]).Result; Assert.AreEqual(OK, r.Status); dynamic result = r.Data; int score; Assert.IsTrue(Int32.TryParse(result.Score.ToString(), out score)); Assert.AreEqual(2, score); } else { PlayWord13(); } }
private int calculateScore(string word, List <Words> words, BoggleBoard board) { if (word.Length < 3) { return(0); } if (words != null && words.Count > 0) { foreach (Words wordThing in words) { if (wordThing.Word.Equals(word)) { return(0); } } } if (!board.CanBeFormed(word)) { return(-1); } switch (word.Length) { case 3: case 4: return(1); case 5: return(2); case 6: return(3); case 7: return(5); default: return(11); } }
/// <summary> /// This private helper evaluate player's word input and returns a valid score. /// </summary> /// <param name="trimmed"></param> /// <param name="board"></param> /// <returns></returns> private int ComputeScore(string trimmed, BoggleBoard board, List <WordsPlayed> words) { int wordCount = trimmed.Length; WordsPlayed PlayedWord = new WordsPlayed(); PlayedWord.Word = trimmed; // If word is less than 3 words, no point. Same goes for duplicated inputs. if (wordCount < 3 || words.Contains(PlayedWord)) { return(0); } // If word is not present in the dictionary.txt if (!board.CanBeFormed(trimmed) || !dictionary.Contains(trimmed)) { return(-1); } // Assign score based on the length of word input if (wordCount == 3 || wordCount == 4) { return(1); } else if (wordCount == 5) { return(2); } else if (wordCount == 6) { return(3); } else if (wordCount == 7) { return(5); } // word inputs > 7 gets 11 points return(11); }
public BoggleResult Play(IBogglePlayer player, int randomSeed = 0, int boardSize = BoggleRules.BoardSizeDefault) { BoggleBoard board = Rules.GenerateBoard(randomSeed, boardSize); BoggleTracker tracker = CreateTracker(player, board); tracker.Start(); try { player.Solve(board); tracker.Stop(); } catch (Exception) { tracker.Stop(); tracker.Update(string.Empty, BoggleRules.CatastrophicScore); throw; } BoggleResult result = CreateResult(tracker); DeleteTracker(player.Id, board.Id); return(result); }
public ScoreReturn PlayWord(WordInfo InputObject, string GameID) { lock (sync) { Game CurrentGame; ScoreReturn Score = new ScoreReturn(); Score.Score = 0; int internalscore = 0; //All the failure cases for bad input. if (InputObject.Word == null || InputObject.Word.Trim().Length == 0) { SetStatus(Forbidden); return(Score); } // Playing a word in a pending game. if ((GameList.Keys.Count + 1).ToString() == GameID) { SetStatus(Conflict); return(Score); } // Invalid GameID if (!GameList.TryGetValue(Int32.Parse(GameID), out CurrentGame) || !UserIDs.ContainsKey(InputObject.UserToken)) { SetStatus(Forbidden); return(Score); } else if (CurrentGame.Player1Token != InputObject.UserToken && CurrentGame.Player2Token != InputObject.UserToken) { SetStatus(Forbidden); return(Score); } else if (CurrentGame.GameState != "active") { SetStatus(Conflict); return(Score); } else { CurrentGame = new Game(); GameList.TryGetValue(Int32.Parse(GameID), out CurrentGame); string word = InputObject.Word.Trim(); BoggleBoard Board = new BoggleBoard(CurrentGame.Board); // If its player 1 playing the word. if (CurrentGame.Player1Token == InputObject.UserToken) { if (word.Length < 3) { internalscore = 0; // repeated code across branches, can be cleaned up later. this is to fix branching issues, will need to be done with player 2 as well WordScore CurrentPair = new WordScore(); CurrentPair.Score = internalscore; CurrentPair.Word = word; CurrentGame.Player1.WordsPlayed.Add(CurrentPair); } else if (Board.CanBeFormed(word)) { foreach (WordScore obj in CurrentGame.Player1.WordsPlayed) { if (obj.Word == word) { internalscore = 0; break; } } if (word.Length == 3 || word.Length == 4) { internalscore = 1; } else if (word.Length == 5) { internalscore = 2; } else if (word.Length == 6) { internalscore = 3; } else if (word.Length == 7) { internalscore = 5; } else if (word.Length > 7) { internalscore = 11; } WordScore CurrentPair = new WordScore(); CurrentPair.Score = internalscore; CurrentPair.Word = word; CurrentGame.Player1.WordsPlayed.Add(CurrentPair); CurrentGame.Player1.Score += internalscore; } else { internalscore = -1; WordScore CurrentPair = new WordScore(); CurrentPair.Score = internalscore; CurrentPair.Word = word; CurrentGame.Player1.WordsPlayed.Add(CurrentPair); CurrentGame.Player1.Score += internalscore; } GameList[Int32.Parse(GameID)] = CurrentGame; } //If its player 2 playing the word. if (CurrentGame.Player2Token == InputObject.UserToken) { if (word.Length < 3) { internalscore = 0; // repeated code across branches, can be cleaned up later. this is to fix branching issues, will need to be done with player 2 as well WordScore CurrentPair = new WordScore(); CurrentPair.Score = internalscore; CurrentPair.Word = word; CurrentGame.Player2.WordsPlayed.Add(CurrentPair); } else if (Board.CanBeFormed(word)) { foreach (WordScore obj in CurrentGame.Player1.WordsPlayed) { if (obj.Word == word) { internalscore = 0; break; } } if (word.Length == 3 || word.Length == 4) { internalscore = 1; } else if (word.Length == 5) { internalscore = 2; } else if (word.Length == 6) { internalscore = 3; } else if (word.Length == 7) { internalscore = 5; } else if (word.Length > 7) { internalscore = 11; } WordScore CurrentPair = new WordScore(); CurrentPair.Score = internalscore; CurrentPair.Word = word; CurrentGame.Player2.WordsPlayed.Add(CurrentPair); CurrentGame.Player2.Score += internalscore; } else { internalscore = -1; WordScore CurrentPair = new WordScore(); CurrentPair.Score = internalscore; CurrentPair.Word = word; CurrentGame.Player2.WordsPlayed.Add(CurrentPair); CurrentGame.Player2.Score += internalscore; } GameList[Int32.Parse(GameID)] = CurrentGame; } } // Records the word as being played. SetStatus(OK); Score.Score = internalscore; return(Score); } }
public string joinGame(string UserToken, int TimeLimit) { if (UserToken == null || TimeLimit < 5 || TimeLimit > 120) { SetStatus(Forbidden); return null; } if (players.p1_ID != UserToken || players.p1_ID != UserToken) { SetStatus(Forbidden); return null; } //Otherwise, if UserToken is already a player in the pending game, responds with status 409 (Conflict). if (UserToken == players.p1_ID) { playersToGame.Add(players, GameObject); // if this updates after player 2 is added, good, otherwise move it down GameObject.GameState = "pending"; SetStatus(Accepted); tempGameID++; return tempGameID.ToString(); } if (UserToken == players.p2_ID) { GameObject.GameState = "active"; SetStatus(Created); ActivePlayer player1 = new ActivePlayer(); ActivePlayer player2 = new ActivePlayer(); BoggleBoard board = new BoggleBoard(); player1.UserToken = players.p1_ID; player2.UserToken = players.p2_ID; player1.GameID = tempGameID.ToString(); player2.GameID = tempGameID.ToString(); player1.GameState = GameObject.GameState; player2.GameState = GameObject.GameState; player1.board = board; player2.board = board; p1holder = player1; p2holder = player2; return tempGameID.ToString(); } //if(UserToken == "affjda")//second player //{ // BoggleData data1 = new BoggleData(); // Player p2 = new Player(); // SetStatus(Accepted); // return data1.GameID; //} string GameID = Guid.NewGuid().ToString(); BoggleData data = new BoggleData(); Player p1 = new Player(); data.GameID = GameID; SetStatus(Accepted); return data.ToString(); }
public void TestGetStatus() { dynamic data = new ExpandoObject(); data.Nickname = "p1"; Response r = client.DoPostAsync("users", data).Result; Assert.AreEqual(Created, r.Status); string p1token = (string)r.Data.UserToken; data = new ExpandoObject(); data.Nickname = "p2"; r = client.DoPostAsync("users", data).Result; Assert.AreEqual(Created, r.Status); string p2token = (string)r.Data.UserToken; //add p1 data = new ExpandoObject(); data.UserToken = p1token; data.TimeLimit = 15; r = client.DoPostAsync("games", data).Result; Assert.AreEqual(Accepted, r.Status); string gid = (string)r.Data.GameID; //pending get status r = client.DoGetAsync("games/{0}?Brief=no", gid).Result; Assert.AreEqual(OK, r.Status); Assert.AreEqual("pending", (string)r.Data.GameState); //add p2 data = new ExpandoObject(); data.UserToken = p2token; data.TimeLimit = 15; r = client.DoPostAsync("games", data).Result; Assert.AreEqual(Created, r.Status); Assert.AreEqual(gid, (string)r.Data.GameID); //Get the board to form words r = client.DoGetAsync("games/" + gid).Result; Assert.AreEqual(OK, r.Status); BoggleBoard board = new BoggleBoard((string)r.Data.Board); Dictionary <int, LinkedList <string> > validWords = GetValidWords(board, 1000); int totalScore = 0; IList <string> wordsadded = new List <string>(); IList <int> scores = new List <int>(); //test each scoring method foreach (KeyValuePair <int, LinkedList <string> > pair in validWords) { int length = pair.Key; LinkedList <string> words = pair.Value; data = new ExpandoObject(); data.UserToken = p1token; data.Word = words.First.Value; r = client.DoPutAsync("games/" + gid, data).Result; Assert.AreEqual(OK, r.Status); wordsadded.Add(validWords[length].First.Value); if (length == 3 || length == 4) { totalScore++; scores.Add(1); } else if (length == 5 || length == 6) { totalScore += length - 3; scores.Add(length - 3); } else if (length == 7) { totalScore += 5; scores.Add(5); } else if (length > 7) { totalScore += 11; scores.Add(11); } else { scores.Add(0); } } //Test an -1 score word data = new ExpandoObject(); data.UserToken = p1token; data.Word = "invalidword0"; r = client.DoPutAsync("games/" + gid, data).Result; Assert.AreEqual(OK, r.Status); Assert.AreEqual(-1, (int)r.Data.Score); totalScore--; wordsadded.Add("invalidword0"); scores.Add(-1); //testing a full status when active and brief=yes r = client.DoGetAsync("games/" + gid + "?Brief=yes").Result; Assert.AreEqual(OK, r.Status); Assert.AreEqual("active", (string)r.Data.GameState); Assert.AreEqual(totalScore, (int)r.Data.Player1.Score); Assert.AreEqual(0, (int)r.Data.Player2.Score); //testing a full status when active and brief=no r = client.DoGetAsync("games/" + gid).Result; Assert.AreEqual(OK, r.Status); Assert.AreEqual("active", (string)r.Data.GameState); Assert.AreEqual(15, (int)r.Data.TimeLimit); Assert.AreEqual(totalScore, (int)r.Data.Player1.Score); Assert.AreEqual(0, (int)r.Data.Player2.Score); Assert.AreEqual("p1", (string)r.Data.Player1.Nickname); Assert.AreEqual("p2", (string)r.Data.Player2.Nickname); Thread.Sleep(15000); //testing a full status when comppleted and brief=yes r = client.DoGetAsync("games/" + gid + "?Brief=yes").Result; Assert.AreEqual(OK, r.Status); Assert.AreEqual("completed", (string)r.Data.GameState); Assert.AreEqual(totalScore, (int)r.Data.Player1.Score); Assert.AreEqual(0, (int)r.Data.Player2.Score); //testing a full status when completed and brief=no r = client.DoGetAsync("games/" + gid).Result; Assert.AreEqual(OK, r.Status); Assert.AreEqual("completed", (string)r.Data.GameState); Assert.AreNotEqual(0, (int)r.Data.Player1.Score); }
public void PlayWordValid() { dynamic data = new ExpandoObject(); data.Nickname = "p1"; Response r = client.DoPostAsync("users", data).Result; Assert.AreEqual(Created, r.Status); string p1token = (string)r.Data.UserToken; data = new ExpandoObject(); data.Nickname = "p2"; r = client.DoPostAsync("users", data).Result; Assert.AreEqual(Created, r.Status); string p2token = (string)r.Data.UserToken; //add p1 data = new ExpandoObject(); data.UserToken = p1token; data.TimeLimit = 15; r = client.DoPostAsync("games", data).Result; Assert.AreEqual(Accepted, r.Status); string gid = (string)r.Data.GameID; //add p2 data = new ExpandoObject(); data.UserToken = p2token; data.TimeLimit = 15; r = client.DoPostAsync("games", data).Result; Assert.AreEqual(Created, r.Status); Assert.AreEqual(gid, (string)r.Data.GameID); //Get the board to form words r = client.DoGetAsync("games/" + gid).Result; Assert.AreEqual(OK, r.Status); BoggleBoard board = new BoggleBoard((string)r.Data.Board); Dictionary <int, LinkedList <string> > validWords = GetValidWords(board, 100); //test each scoring method foreach (int key in validWords.Keys) { data = new ExpandoObject(); data.UserToken = p1token; data.Word = validWords[key].First.Value; r = client.DoPutAsync("games/" + gid, data).Result; Assert.AreEqual(OK, r.Status); if (key < 3) { Assert.AreEqual(0, (int)r.Data.Score); } else if (key == 3 || key == 4) { Assert.AreEqual(1, (int)r.Data.Score); } else if (key == 5 || key == 6) { Assert.AreEqual(key - 3, (int)r.Data.Score); } else if (key == 7) { Assert.AreEqual(5, (int)r.Data.Score); } else if (key > 7) { Assert.AreEqual(11, (int)r.Data.Score); } } //Test an -1 score word data = new ExpandoObject(); data.UserToken = p1token; data.Word = "invalidword0"; r = client.DoPutAsync("games/" + gid, data).Result; Assert.AreEqual(OK, r.Status); Assert.AreEqual(-1, (int)r.Data.Score); }
/// <summary> /// Play a word in a game /// /// If Word is null or empty when trimmed, or if GameID or /// UserToken is missing or invalid, or if UserToken is not a /// player in the game identified by GameID, responds with response /// code 403 (Forbidden). /// /// Otherwise, if the game state is anything other than "active", /// responds with response code 409 (Conflict). /// /// Otherwise, records the trimmed Word as being played by UserToken /// in the game identified by GameID. Returns the score for Word in the /// context of the game (e.g. if Word has been played before the score is zero). /// Responds with status 200 (OK). Note: The word is not case sensitive. /// </summary> /// <param name="gameID"></param> /// <param name="UserToken"></param> /// <param name="Word"></param> /// <returns></returns> public WordScore PlayWord(string gameID, WordCheck info) { try { string word = info.Word.Trim(); string userToken = info.UserToken; BoggleBoard PlayBoard; string status1; int score = 0; bool canPlay; DateTime time; int TimeLimit; if (word.Length == 0 || userToken == null || gameID == null) { SetStatus(Forbidden); return(null); } if (!(new Regex(@"\d+").IsMatch(gameID))) { SetStatus(Forbidden); return(null); } //Creates a sql connection using (SqlConnection conn = new SqlConnection(BoggleDB)) { //open connection conn.Open(); using (SqlTransaction trans = conn.BeginTransaction()) { using (SqlCommand command = new SqlCommand("select GameStatus, StartTime, TimeLimit from Games where GameID = @GameID", conn, trans)) { command.Parameters.AddWithValue("@GameID", gameID); using (SqlDataReader reader = command.ExecuteReader()) { //added check to make sure game was in table if (!reader.HasRows) { SetStatus(Forbidden); return(null); } reader.Read(); status1 = reader.GetString(0); // else we get the time the game started and the calculated time limit from the 2 players. time = reader.GetDateTime(1); TimeLimit = (int)reader.GetValue(2); double elapsedTime = Math.Round((DateTime.Now.TimeOfDay.TotalSeconds - time.TimeOfDay.TotalSeconds), 0); // If the elapsed time is greater than or equal to the time limit, the game is marked as completed so no // Actions can be made to the game. if (elapsedTime >= (double)TimeLimit) { SetStatus(Conflict); status1 = "completed"; } } } } using (SqlTransaction trans = conn.BeginTransaction()) { // Gets thge players and board based on the given GameID. using (SqlCommand command = new SqlCommand("select Player1, Player2, Board, GameStatus from Games where GameID = @GameID", conn, trans)) { string P1; string P2; string status; command.Parameters.AddWithValue("@GameID", gameID); using (SqlDataReader reader = command.ExecuteReader()) { if (!reader.HasRows) { SetStatus(Forbidden); return(null); } reader.Read(); P1 = reader.GetString(0); P2 = reader.GetString(1); status = reader.GetString(3); if (!P1.Equals(userToken) && !P2.Equals(userToken)) { SetStatus(Forbidden); return(null); } if (status1 != "active") { SetStatus(Conflict); return(null); } PlayBoard = new BoggleBoard(reader.GetString(2)); // Checks to make sure P1 and P2 are in the game. if (P1 == null || P2 == null) { SetStatus(Forbidden); return(null); } // If game status is Active, sets a bool that allows up to play a word. If it is anything but Active, // we can't play a word. if (status == "active") { canPlay = true; } else { canPlay = false; SetStatus(Conflict); } } } // If we can play a word, we go in to the if statement. If not, we set the status to 409 - Conflict and return null if (canPlay) { // Checks to make sure the word can be formed on the game board. if (PlayBoard.CanBeFormed(word)) { string scoreString; // Sets the score initially to the word score from the dictionary. Can be changed below if the word has already been played by // the player. if (dictionary.TryGetValue(word.ToUpper(), out scoreString)) { int.TryParse(scoreString, out score); // Gets all the words played by a player in a game. using (SqlCommand command2 = new SqlCommand("select Word from Words where GameID = @GameID and Player = @Player", conn, trans)) { command2.Parameters.AddWithValue("@GameID", gameID); command2.Parameters.AddWithValue("@Player", userToken); using (SqlDataReader reader1 = command2.ExecuteReader()) { // Reads each row/word that a player has played for a game. while (reader1.Read()) { // If the word has been played, score is updated to 0. if (reader1.GetString(0) == word) { score = 0; break; } } } } } } // If the word can't be formed on the board or is an invalid word, score is set to -1. else { score = -1; } // Inserts the word into the Words table. The word is accociated with a GameID, Player, and score. using (SqlCommand command3 = new SqlCommand("Insert into Words (Word, GameID, Player, Score) values (@Word, @GameID, @Player, @Score)", conn, trans)) { command3.Parameters.AddWithValue("@Word", word); command3.Parameters.AddWithValue("@GameID", gameID); command3.Parameters.AddWithValue("@Player", userToken); command3.Parameters.AddWithValue("@Score", score); if (command3.ExecuteNonQuery() != 1) { SetStatus(BadRequest); return(null); } } SetStatus(OK); //comit transaction and return the usertoken trans.Commit(); // Returns a WordScore object that reflect the score of the word a player just played. return(new WordScore { Score = score.ToString() }); } // Only gets done when the game status is anything other than Active. { SetStatus(Conflict); return(null); } } } } catch (Exception) { SetStatus(Conflict); return(null); } }
public GameInfo JoinGame(UserInfo user, out HttpStatusCode status) { status = OK; lock (sync) { if (user.UserToken == null || user.UserToken.Length == 0 || user.TimeLimit < 5 || user.TimeLimit > 120) { status = Forbidden; return(null); } string gameID = ""; using (SqlConnection conn = new SqlConnection(BoggleDB)) { conn.Open(); using (SqlTransaction trans = conn.BeginTransaction()) { //check if the user is in the user table. //if not set the status to forbidden and return null. using (SqlCommand command = new SqlCommand("select UserID from Users where UserID = @UserID", conn, trans)) { command.Parameters.AddWithValue("@UserID", user.UserToken); using (SqlDataReader reader = command.ExecuteReader()) { //if the user is not registered, forbidden if (!reader.HasRows) { reader.Close(); status = Forbidden; trans.Commit(); return(null); } } } // create a pending game with no player if needed using (SqlCommand command = new SqlCommand("select GameID from Games", conn, trans)) { using (SqlDataReader reader = command.ExecuteReader()) { //if there is no games, add a new pending game. if (!reader.HasRows) { reader.Close(); using (SqlCommand command4 = new SqlCommand("insert into Games (GameState) values (@GameState)", conn, trans)) { command4.Parameters.AddWithValue("@GameState", "pending"); command4.ExecuteNonQuery(); } } } } // check if user is already a player in a pending game using (SqlCommand command = new SqlCommand("select Player1, Player2 " + "from Games where Player1 = @Player1 and Player2 is NULL", conn, trans)) { command.Parameters.AddWithValue("@Player1", user.UserToken); //command.Parameters.AddWithValue("@Player2", null); using (SqlDataReader reader = command.ExecuteReader()) { //if user is already Player1 in pending game if (reader.HasRows) { reader.Close(); status = Conflict; trans.Commit(); return(null); } } } // get pending gameID using (SqlCommand command = new SqlCommand("select GameID from Games where " + "Player2 is NULL", conn, trans)) { //command.Parameters.AddWithValue("@Player2", null); using (SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { gameID = reader["GameID"].ToString(); } } } // determine if Player1 of the pending game is null using (SqlCommand command = new SqlCommand("select Player1 from Games where " + "GameID = @GameID", conn, trans)) { command.Parameters.AddWithValue("@GameID", gameID); using (SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { if (reader.IsDBNull(0)) //)//|| { reader.Close(); //add user as player1 to pending game using (SqlCommand command2 = new SqlCommand("update Games set Player1 = @Player1, TimeLimit = @TimeLimit, GameState = @GameState where GameID = @GameID", conn, trans)) { command2.Parameters.AddWithValue("@GameID", gameID); command2.Parameters.AddWithValue("@Player1", user.UserToken); command2.Parameters.AddWithValue("@TimeLimit", user.TimeLimit); command2.Parameters.AddWithValue("@GameState", "pending"); command2.ExecuteNonQuery(); status = Accepted; GameInfo temp = new GameInfo(); temp.GameID = gameID; trans.Commit(); return(temp); } } else { reader.Close(); //otherwise, add user as player2 to pending game and make gamestate active using (SqlCommand command3 = new SqlCommand("update Games set Player2 = @Player2, " + "Board = @Board, TimeLimit = (TimeLimit + @TimeLimit) / 2, " + "StartTime = @StartTime, GameState = @GameState where GameID = @GameID", conn, trans)) { command3.Parameters.AddWithValue("@GameID", gameID); command3.Parameters.AddWithValue("@Player2", user.UserToken); command3.Parameters.AddWithValue("@TimeLimit", user.TimeLimit); command3.Parameters.AddWithValue("@GameState", "active"); BoggleBoard board = new BoggleBoard(); command3.Parameters.AddWithValue("@Board", board.ToString()); command3.Parameters.AddWithValue("@StartTime", DateTime.UtcNow); command3.ExecuteNonQuery(); status = Created; } //adding a new pending game without any players using (SqlCommand command4 = new SqlCommand("insert into Games (GameState) values (@GameState)", conn, trans)) { command4.Parameters.AddWithValue("@GameState", "pending"); command4.ExecuteNonQuery(); GameInfo temp = new GameInfo(); temp.GameID = gameID; trans.Commit(); return(temp); } } } return(null); } } } } } }
public WordPlayed PlayWord(UserInfo user, string GameID, out HttpStatusCode status) { lock (sync) { string trimmedWord = user.Word.Trim().ToUpper(); int scoreOfWord = 0; string boardString = ""; if (!(Int32.TryParse(GameID, out int result))) { status = Forbidden; return(null); } if (user.UserToken == null || user.UserToken.Length == 0 || user.Word == null || user.Word.Length == 0 || user.Word.Trim().Length > 30) { status = Forbidden; return(null); } using (SqlConnection conn = new SqlConnection(BoggleDB)) { conn.Open(); using (SqlTransaction trans = conn.BeginTransaction()) { // determine whether GameID is valid (exists in Games table) using (SqlCommand command = new SqlCommand("select GameID, Player1, Player2, Board from Games where Games.GameID = @GameID", conn, trans)) { command.Parameters.AddWithValue("@GameID", GameID); using (SqlDataReader reader = command.ExecuteReader()) { // if GameID does not exist in games if (!reader.HasRows) { status = Forbidden; reader.Close(); trans.Commit(); return(null); } // determine whether user has valid userToken (Player1 or Player2 has user.UserToken) while (reader.Read()) { string player1Token = reader["Player1"].ToString(); string player2Token = reader["Player2"].ToString(); boardString = reader["Board"].ToString(); // if neither player1 nor player2 has user.UserToken if ((player1Token != user.UserToken) && (player2Token != user.UserToken)) { status = Forbidden; reader.Close(); trans.Commit(); return(null); } } reader.Close(); // determine whether game state is not active string gameState = ""; HttpStatusCode a = OK; GameStatus("asd", GameID, out a); using (SqlCommand cmd = new SqlCommand("select GameState from Games where Games.GameID = @GameID2", conn, trans)) { cmd.Parameters.AddWithValue("@GameID2", GameID); using (SqlDataReader reader2 = cmd.ExecuteReader()) { while (reader2.Read()) { gameState = reader2["GameState"].ToString(); } reader2.Close(); } } if (gameState != "active") { status = Conflict; trans.Commit(); return(null); } if (trimmedWord.Length < 3) { scoreOfWord = 0; } else { BoggleBoard board = new BoggleBoard(boardString); if (board.CanBeFormed(trimmedWord) && IsInDictionary(trimmedWord)) { if (trimmedWord.Length < 5) { scoreOfWord = 1; } else if (trimmedWord.Length == 5) { scoreOfWord = 2; } else if (trimmedWord.Length == 6) { scoreOfWord = 3; } else if (trimmedWord.Length == 7) { scoreOfWord = 5; } else { scoreOfWord = 11; } } else { scoreOfWord = -1; } } } } // check if this word has already been played by this player in this game using (SqlCommand command = new SqlCommand("select Word from Words where Words.GameID = @GameID and Words.Word = @Word and Words.Player = @Player", conn, trans)) { command.Parameters.AddWithValue("@Word", trimmedWord); command.Parameters.AddWithValue("@GameID", GameID); command.Parameters.AddWithValue("@Player", user.UserToken); using (SqlDataReader reader = command.ExecuteReader()) { // if this word has already been played by this player in this game if (reader.HasRows) { scoreOfWord = 0; } reader.Close(); } } //update Word table using (SqlCommand command = new SqlCommand("insert into Words(Word, GameID, Player, Score) values(@Word, @GameID, @Player, @Score)", conn, trans)) { command.Parameters.AddWithValue("@GameID", GameID); command.Parameters.AddWithValue("@Word", trimmedWord); command.Parameters.AddWithValue("@Player", user.UserToken); command.Parameters.AddWithValue("@Score", scoreOfWord); command.ExecuteNonQuery(); status = OK; trans.Commit(); WordPlayed word = new WordPlayed(); word.Score = scoreOfWord; return(word); } } } } }
/// <summary> /// Invokes a user token to join the game /// </summary> public GameIDReturn JoinGame(GameInfo Info) { lock (sync) { GameIDReturn ReturnInfo = new GameIDReturn(); //string ReturnInfo = string.Empty; string nickname; //!UserIDs.ContainsKey(Info.UserToken) || if (Info.TimeLimit < 5 || Info.TimeLimit > 120) { SetStatus(Forbidden); return(ReturnInfo); } else if (!UserIDs.TryGetValue(Info.UserToken, out nickname)) { SetStatus(Forbidden); return(ReturnInfo); } //If the same player tries to join the pending game against himself. else if (CurrentPendingGame.Player1Token == Info.UserToken) { SetStatus(Conflict); return(ReturnInfo); } //If the pending game has a player 1 waiting. else if (CurrentPendingGame.Player1Token != null) { Game NewGame = new Game(); NewGame.Player1 = new Player(); NewGame.Player2 = new Player(); string P1Nickname; UserIDs.TryGetValue(CurrentPendingGame.Player1Token, out P1Nickname); //Game NewPendingGame = new Game(); BoggleBoard Board = new BoggleBoard(); string PendingGameID = GameList.Keys.Count.ToString(); //Start new active game. NewGame.GameState = "active"; NewGame.Board = Board.ToString(); NewGame.Player1Token = CurrentPendingGame.Player1Token; NewGame.Player2Token = Info.UserToken; NewGame.TimeLimit = (Info.TimeLimit + CurrentPendingGame.TimeLimit) / 2; NewGame.TimeLeft = NewGame.TimeLimit; NewGame.Player1.Nickname = P1Nickname; NewGame.Player1.Score = 0; NewGame.Player1.WordsPlayed = new List <WordScore>(); NewGame.Player2.Nickname = UserIDs[Info.UserToken]; NewGame.Player2.Score = 0; NewGame.Player2.WordsPlayed = new List <WordScore>(); //Add an empty pending game. CurrentPendingGame.Player1Token = null; CurrentPendingGame.TimeLimit = 0; //Send back information to client. GameList.Add(GameList.Keys.Count + 1, NewGame); //GameList.Add(GameList.Keys.Count + 1, NewPendingGame); //ReturnInfo.GameID = (GameList.Keys.Count - 1).ToString(); ReturnInfo.GameID = (GameList.Keys.Count).ToString(); SetStatus(Created); return(ReturnInfo); } //If the pending game is empty. else if (CurrentPendingGame.Player1Token == null) { //Inputs user data into the pending game. CurrentPendingGame.GameState = "pending"; CurrentPendingGame.Player1Token = Info.UserToken; CurrentPendingGame.TimeLimit = Info.TimeLimit; //Returns info back to the user. //ReturnInfo.GameID = GameList.Keys.Count.ToString(); ReturnInfo.GameID = (GameList.Keys.Count + 1).ToString(); SetStatus(Accepted); return(ReturnInfo); } return(ReturnInfo); } }