From d9578996e71661954a873e9437d326185ecaa77f Mon Sep 17 00:00:00 2001 From: Sarah Kim Date: Thu, 16 Mar 2023 14:35:31 -0700 Subject: [PATCH 01/11] added my name to the readme --- README_sarah.md | 255 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 README_sarah.md diff --git a/README_sarah.md b/README_sarah.md new file mode 100644 index 00000000..cfaa5310 --- /dev/null +++ b/README_sarah.md @@ -0,0 +1,255 @@ +# AdaGrams + +## Skills Assessed + +- Following directions and reading comprehension +- Reading tests +- Using git to maintain code +- Manipulating and processing data in lists and strings + +## Goal + +An [anagram](https://en.wikipedia.org/wiki/Anagram) is a word or phrase formed by rearranging the letters of a different word or phrase. In this project you will be creating _Adagrams_, a game in which a player is given a random set of letters and must make an anagram using those letters. Each submitted word will score points. + +While working on _Adagrams_, it may help to think of a physical metaphor for this game, such as other common word games like _Scrabble_ or _Bananagrams_. These games all feature a _pool_ of letter _tiles_ that the player _draws_ from. + +In this version of _Adagrams_, we will only be working with the English alphabet. + +![an image of a pile of letter tiles](images/letter-tiles.jpeg) + +## One-Time Project Setup + +Follow these directions once, at the beginning of your project: + + +1. Navigate to your projects folder named `projects`. + +If you followed Ada's recommended file system structure from the Intro to Dev Environment lesson in Learn, you can navigate to your projects folder with the following command: + +```bash +$ cd ~/Developer/projects +``` + +2. In Github click on the "Fork" button in github and fork the repository to your Github account. This will make a copy of the project in your github account. + +![Fork Button](images/fork.png) + +3. "Clone" (download a copy of this project) into your projects folder. This command makes a new folder called `adagrams-py`, and then puts the project into this new folder. Make sure you are cloning from your copy of the project and not the class version (ada-cX). + +```bash +$ git clone ... +``` + +Use `ls` to confirm there's a new project folder + +4. Move your location into this project folder + +```bash +$ cd adagrams-py +``` + +5. Create a virtual environment named `venv` for this project: + +```bash +$ python3 -m venv venv +``` + +6. Activate this environment: + +```bash +$ source venv/bin/activate +``` + +Verify that you're in a python3 virtual environment by running: + +- `$ python --version` should output a Python 3 version +- `$ pip --version` should output that it is working with Python 3 + +7. Install dependencies once at the beginning of this project with + +```bash +# Must be in activated virtual environment +$ pip install -r requirements.txt +``` + +Summary of one-time project setup: +- [ ] Fork the project respository +- [ ] `cd` into your `projects` folder +- [ ] Clone the project onto your machine +- [ ] `cd` into the `adagrams-py` folder +- [ ] Create the virtual environment `venv` +- [ ] Activate the virtual environment `venv` +- [ ] Install the dependencies with `pip` + +## Project Development Workflow + +1. When you want to begin work on this project, ensure that your virtual environment is activated: + +```bash +$ source venv/bin/activate +``` + +2. Run the game and play test your current wave. Replace the word `wave` below with the wave number (ie, 1, 2, 3 or 4): + +```bash +# Must be in activated virtual environment +$ python main.py wave +``` + +3. Use play-testing to guide your development. + +4. Use tests to verify your functions after thoroughly play-testing. See instructions for running tests in the section below. *A complete set of unit tests is provided for this project.* + +5. Use git to commit your work regularly! Commit between each wave. + +```bash +# Add your current work +$ git add . +$ git commit -m "meaningful message explaining your commit" +``` + +6. Move on to the next wave! + +7. When you are finished working for the day, deactivate your environment with deactivate or closing the Terminal tab/window + +```bash +$ deactivate +``` + +## Details About How to Run Tests + +1. Find the test file that contains the test you want to run. + + - Check the `tests` folder, and find the test file you want to run + - In that test file, read through each test case + + +2. Run the tests for your specific wave + +```bash +# Must be in activated virtual environment +$ pytest tests/test_wave_01.py +``` + +3. Run all tests that exist in this project with: + +```bash +# Must be in activated virtual environment +$ pytest +``` + +4. If you want to see any `print` statements print to the console, add `-s` to the end of any `pytest` command: + +```bash +# Must be in activated virtual environment +$ pytest -s +``` + +## Project Write-Up: How to Complete and Submit + + +The goal of this project is to write code in `game.py` so each of the functions meet the requirements outlined in the Project Directions below. + +Go through the waves one-by-one and build the features of this game. + +You will use play-testing and unit tests to drive your development. + +At submission time, no matter where you are, submit the project via Learn. + +This will let us give feedback on what you've finished so that you can be better prepared for the next project. + +## Project Directions + +### Get Familiar + +Take time to read through the Wave 1 implementation requirements and the tests for Wave 1. Write down your questions, and spend some time going through your understanding of the requirements and tests. Make sure you can run `$ pytest` and see the tests fail. + +If, after you have taken some time to think through the problem and would like direction for how to dissect the problem, or if you need clarity on the terms/vocabulary we used in this project, you can check out [a small hint we've provided](./project_docs/hints.md). + +### Wave 1: draw_letters + +Your first task is to build a hand of 10 letters for the user. To do so, implement the function `draw_letters` in `game.py`. This method should have the following properties: + +- No parameters +- Returns an array of ten strings + - Each string should contain exactly one letter + - These represent the hand of letters that the player has drawn +- The letters should be randomly drawn from a pool of letters + - This letter pool should reflect the distribution of letters as described in the table below + - There are only 2 available `C` letters, so `draw_letters` cannot ever return more than 2 `C`s + - Since there are 12 `E`s but only 1 `Z`, it should be 12 times as likely for the user to draw an `E` as a `Z` +- Invoking this function should **not** change the pool of letters + - Imagine that the user returns their hand to the pool before drawing new letters + +#### Distribution of Letters + +| Letter : Qty. | Letter : Qty. | +|:------:|:-----:| +| A : 9 | N : 6 | +| B : 2 | O : 8 | +| C : 2 | P : 2 | +| D : 4 | Q : 1 | +| E : 12 | R : 6 | +| F : 2 | S : 4 | +| G : 3 | T : 6 | +| H : 2 | U : 4 | +| I : 9 | V : 2 | +| J : 1 | W : 2 | +| K : 1 | X : 1 | +| L : 4 | Y : 2 | +| M : 2 | Z : 1 | + +**Note:** Making sure that the drawn letters match the rules of the letter pool can be straightforward or very difficult, depending on how you build the data structure for the letter pool. It is worth spending some time to think carefully about this. + + +### Wave 2: use_available_letters + +Next, you need a way to check if an input word (a word a player submits) only uses characters that are contained within a collection (or hand) of drawn letters. Essentially, you need a way to check if the word is an anagram of some or all of the given letters in the hand. + +To do so, implement the function called `uses_available_letters` in `game.py`. This function should have the following properties: + +- Has two parameters: + - `word`, the first parameter, describes some input word, and is a string + - `letter_bank`, the second parameter, describes an array of drawn letters in a hand. You can expect this to be an array of ten strings, with each string representing a letter +- Returns either `True` or `False` +- Returns `True` if every letter in the `input` word is available (in the right quantities) in the `letter_bank` +- Returns `False` if not; if there is a letter in `input` that is not present in the `letter_bank` or has too much of compared to the `letter_bank` + +### Wave 3: score_word + +Now you need a function returns the score of a given word as defined by the Adagrams game. + +Implement the function `score_word` in `game.py`. This method should have the following properties: + +- Has one parameter: `word`, which is a string of characters +- Returns an integer representing the number of points +- Each letter within `word` has a point value. The number of points of each letter is summed up to represent the total score of `word` +- Each letter's point value is described in the table below +- If the length of the word is 7, 8, 9, or 10, then the word gets an additional 8 points + +#### Score chart + +|Letter | Value| +|:----------------------------:|:----:| +|A, E, I, O, U, L, N, R, S, T | 1 | +|D, G | 2 | +|B, C, M, P | 3 | +|F, H, V, W, Y | 4 | +|K | 5 | +|J, X | 8 | +|Q, Z | 10 | + +### Wave 4: get_highest_word_score + +After several hands have been drawn, words have been submitted, checked, scored, and played, you need a way to find the highest scoring word. This function looks at the list of `word_list` and calculates which of these words has the highest score, applies any tie-breaking logic, and returns the winning word in a special data structure. + +Implement a function called `get_highest_word_score` in `game.py`. This method should have the following properties: + +- Has one parameter: `word_list`, which is a list of strings +- Returns a tuple that represents the data of a winning word and it's score. The tuple must contain the following elements: + - index 0 ([0]): a string of a word + - index 1 ([1]): the score of that word +- In the case of tie in scores, use these tie-breaking rules: + - prefer the word with the fewest letters... + - ...unless one word has 10 letters. If the top score is tied between multiple words and one is 10 letters long, choose the one with 10 letters over the one with fewer tiles + - If the there are multiple words that are the same score and the same length, pick the first one in the supplied list From 6d53b37dbd829881ba4c867569474c0798035d2b Mon Sep 17 00:00:00 2001 From: Sarah Kim Date: Fri, 17 Mar 2023 15:06:16 -0700 Subject: [PATCH 02/11] test 1 and 2 of test_wave_01 passed --- adagrams/game.py | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/adagrams/game.py b/adagrams/game.py index 5fb37b11..87319898 100644 --- a/adagrams/game.py +++ b/adagrams/game.py @@ -1,5 +1,40 @@ +import random def draw_letters(): - pass + list_of_letters = [] + LETTER_POOL = { + 'A': 9, + 'B': 2, + 'C': 2, + 'D': 4, + 'E': 12, + 'F': 2, + 'G': 3, + 'H': 2, + 'I': 9, + 'J': 1, + 'K': 1, + 'L': 4, + 'M': 2, + 'N': 6, + 'O': 8, + 'P': 2, + 'Q': 1, + 'R': 6, + 'S': 4, + 'T': 6, + 'U': 4, + 'V': 2, + 'W': 2, + 'X': 1, + 'Y': 2, + 'Z': 1 + } + for i in LETTER_POOL: + while len(list_of_letters) < 10: + list_of_letters.append(i) + return list_of_letters + + def uses_available_letters(word, letter_bank): pass From d0d1dd08b4d22930e7143d62e70bf8220db8656c Mon Sep 17 00:00:00 2001 From: Sarah Kim Date: Sat, 18 Mar 2023 13:41:08 -0700 Subject: [PATCH 03/11] function draw_letters returns a list of random letters according to the distribution --- adagrams/game.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/adagrams/game.py b/adagrams/game.py index 87319898..a6ae9a3e 100644 --- a/adagrams/game.py +++ b/adagrams/game.py @@ -31,11 +31,14 @@ def draw_letters(): } for i in LETTER_POOL: while len(list_of_letters) < 10: - list_of_letters.append(i) + letter_chosen = random.choice(list(LETTER_POOL)) + LETTER_POOL[letter_chosen] -= 1 + if LETTER_POOL[letter_chosen] > 0: + list_of_letters.append(letter_chosen) + else: + continue return list_of_letters - - def uses_available_letters(word, letter_bank): pass From de82185c7133cdf5a76d863a0a429e4d71cc9dd4 Mon Sep 17 00:00:00 2001 From: Sarah Kim Date: Sat, 18 Mar 2023 14:05:10 -0700 Subject: [PATCH 04/11] refined the draw_letters function, ommitted redundant lines of code --- adagrams/game.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/adagrams/game.py b/adagrams/game.py index a6ae9a3e..37e54e5e 100644 --- a/adagrams/game.py +++ b/adagrams/game.py @@ -29,15 +29,14 @@ def draw_letters(): 'Y': 2, 'Z': 1 } - for i in LETTER_POOL: - while len(list_of_letters) < 10: - letter_chosen = random.choice(list(LETTER_POOL)) + + while len(list_of_letters) < 10: + letter_chosen = random.choice(list(LETTER_POOL)) + if LETTER_POOL[letter_chosen] > 0: + list_of_letters.append(letter_chosen) LETTER_POOL[letter_chosen] -= 1 - if LETTER_POOL[letter_chosen] > 0: - list_of_letters.append(letter_chosen) - else: - continue - return list_of_letters + + return list_of_letters def uses_available_letters(word, letter_bank): pass From 2ffffc735e405c7d1c07ec694223bab84faafafb Mon Sep 17 00:00:00 2001 From: Sarah Kim Date: Sat, 18 Mar 2023 15:46:13 -0700 Subject: [PATCH 05/11] added functionality for uses_available_letters checking to see if the guessed word is within the list of letter --- adagrams/game.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/adagrams/game.py b/adagrams/game.py index 37e54e5e..e4e43821 100644 --- a/adagrams/game.py +++ b/adagrams/game.py @@ -39,7 +39,14 @@ def draw_letters(): return list_of_letters def uses_available_letters(word, letter_bank): - pass + ## word is a string + ## letter bank is list of letters + #compare the word to letter bank + for elem in word: + if elem not in letter_bank: + return False + return True + def score_word(word): pass From ad525c374691fa033afb7261c01ac01aebac2148 Mon Sep 17 00:00:00 2001 From: Sarah Kim Date: Sat, 18 Mar 2023 21:48:24 -0700 Subject: [PATCH 06/11] added all functionality to uses_available_letters --- adagrams/game.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/adagrams/game.py b/adagrams/game.py index e4e43821..0e97360e 100644 --- a/adagrams/game.py +++ b/adagrams/game.py @@ -41,9 +41,25 @@ def draw_letters(): def uses_available_letters(word, letter_bank): ## word is a string ## letter bank is list of letters - #compare the word to letter bank - for elem in word: - if elem not in letter_bank: + + + #always make string 'word' be uppercase + word = word.upper() + #generating a dictionary to keep track of how many each letter occurs in letter bank + letter_frequency = {} + for letter in letter_bank: + if letter in letter_frequency: + letter_frequency[letter] += 1 + else: + letter_frequency[letter] = 1 + #compare each letter in word to the key in letter frequency dictionary + for elem in word: # loop through each letter in the word + if elem in letter_frequency.keys(): + if letter_frequency[elem] > 0: + letter_frequency[elem] -= 1 + else: + return False + else: return False return True From 6a830b757219d35a09f51cf69ad616045891a7f9 Mon Sep 17 00:00:00 2001 From: Sarah Kim Date: Mon, 20 Mar 2023 18:05:58 -0700 Subject: [PATCH 07/11] added functionality to letter_score where each letter will be scored and the total score of a word is returned --- adagrams/game.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/adagrams/game.py b/adagrams/game.py index 0e97360e..c0b419c5 100644 --- a/adagrams/game.py +++ b/adagrams/game.py @@ -66,6 +66,52 @@ def uses_available_letters(word, letter_bank): def score_word(word): pass + #returns an integer representing the number of points + #each letter has a point value and sum up the total score + #if length of word is >7 then word gets additional 8 points + # does not care about upper or lower case + letter_score = { + "A" : 1, + "E" : 1, + "I" : 1, + "O" : 1, + "U" : 1, + "L" : 1, + "N" : 1, + "R" : 1, + "S" : 1, + "T" : 1, + "D" : 2, + "G" : 2, + "B" : 3, + "C" : 3, + "M" : 3, + "P" : 3, + "F" : 4, + "H" : 4, + "V" : 4, + "W" : 4, + "Y" : 4, + "K" : 5, + "J" : 8, + "X" : 8, + "Q" : 10, + "Z" : 10 + } + + #turn every letter in the word to upper case + word = word.upper() + total_score = 0 + # loop through each letter in the string "word" + for letter in word: + # compare each letter to letters in the table + # add the value of the letter to a variable called total_score + total_score += letter_score[letter] + # check if the word length is >=7 and if it is then add 8 to the total_score + if len(word) >= 7: + total_score += 8 + # return the score + return total_score def get_highest_word_score(word_list): pass \ No newline at end of file From 0e87f4aad137734b8160096e41ba66c83e6b6fdd Mon Sep 17 00:00:00 2001 From: Sarah Kim Date: Tue, 21 Mar 2023 17:31:07 -0700 Subject: [PATCH 08/11] added functionality to get_highest_word_score to return the highest scoring word and highest score --- adagrams/game.py | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/adagrams/game.py b/adagrams/game.py index c0b419c5..0e8a0947 100644 --- a/adagrams/game.py +++ b/adagrams/game.py @@ -65,7 +65,6 @@ def uses_available_letters(word, letter_bank): def score_word(word): - pass #returns an integer representing the number of points #each letter has a point value and sum up the total score #if length of word is >7 then word gets additional 8 points @@ -113,5 +112,40 @@ def score_word(word): total_score += 8 # return the score return total_score + def get_highest_word_score(word_list): - pass \ No newline at end of file + # returns a tuple (a string of a word, the score of that word) + highest_scoring_word = "" + highest_score = 0 + for word in word_list: + # find each score for word in the word_list + score_for_one_word =score_word(word) + # if len(word) == 10: + # highest_score = score_for_one_word + # highest_scoring_word = word + if score_for_one_word == highest_score: + if len(word) == 10: + if len(highest_scoring_word) == 10: + continue + highest_score = score_for_one_word + highest_scoring_word = word + elif len(highest_scoring_word) > len(word): + if len(highest_scoring_word) == 10: + continue + highest_scoring_word = word + + elif score_for_one_word > highest_score: + highest_score = score_for_one_word + highest_scoring_word = word + + + + # elif score_for_one_word == highest_score: + # length_word = len(word) + # length_highest_scoring_word = len(highest_scoring_word) + + return highest_scoring_word, highest_score + + +words = ["JQ", "FHQ", "AAAAAAAAAA", "BBBBBB", "TTTTTTTTTT"] +get_highest_word_score(words) \ No newline at end of file From 335d4e9947b13362d94d7c7b1180e2ed41cc34d7 Mon Sep 17 00:00:00 2001 From: Sarah Kim Date: Wed, 22 Mar 2023 21:13:03 -0700 Subject: [PATCH 09/11] refactored and added comments to the get_highest_word_score function --- adagrams/game.py | 51 ++++++++++++------------------------------------ 1 file changed, 12 insertions(+), 39 deletions(-) diff --git a/adagrams/game.py b/adagrams/game.py index 0e8a0947..49022c86 100644 --- a/adagrams/game.py +++ b/adagrams/game.py @@ -39,10 +39,6 @@ def draw_letters(): return list_of_letters def uses_available_letters(word, letter_bank): - ## word is a string - ## letter bank is list of letters - - #always make string 'word' be uppercase word = word.upper() #generating a dictionary to keep track of how many each letter occurs in letter bank @@ -65,11 +61,6 @@ def uses_available_letters(word, letter_bank): def score_word(word): - #returns an integer representing the number of points - #each letter has a point value and sum up the total score - #if length of word is >7 then word gets additional 8 points - # does not care about upper or lower case - letter_score = { "A" : 1, "E" : 1, @@ -98,13 +89,11 @@ def score_word(word): "Q" : 10, "Z" : 10 } - + total_score = 0 #turn every letter in the word to upper case word = word.upper() - total_score = 0 # loop through each letter in the string "word" for letter in word: - # compare each letter to letters in the table # add the value of the letter to a variable called total_score total_score += letter_score[letter] # check if the word length is >=7 and if it is then add 8 to the total_score @@ -114,38 +103,22 @@ def score_word(word): return total_score def get_highest_word_score(word_list): - # returns a tuple (a string of a word, the score of that word) highest_scoring_word = "" highest_score = 0 - for word in word_list: + for new_word in word_list: # find each score for word in the word_list - score_for_one_word =score_word(word) - # if len(word) == 10: - # highest_score = score_for_one_word - # highest_scoring_word = word + score_for_one_word = score_word(new_word) + #decide on tie breaker first if score_for_one_word == highest_score: - if len(word) == 10: - if len(highest_scoring_word) == 10: - continue - highest_score = score_for_one_word - highest_scoring_word = word - elif len(highest_scoring_word) > len(word): - if len(highest_scoring_word) == 10: - continue - highest_scoring_word = word - + # length of 10 letters trumps any word that is shorter + if len(new_word) == 10 and len(highest_scoring_word)!= 10: + highest_scoring_word = new_word + # having fewer letters is a tie breaker as long as the current stored word's length is not 10 + elif len(highest_scoring_word) > len(new_word) and len(highest_scoring_word) != 10: + highest_scoring_word = new_word + #Look for word with highest score elif score_for_one_word > highest_score: highest_score = score_for_one_word - highest_scoring_word = word + highest_scoring_word = new_word - - - # elif score_for_one_word == highest_score: - # length_word = len(word) - # length_highest_scoring_word = len(highest_scoring_word) - return highest_scoring_word, highest_score - - -words = ["JQ", "FHQ", "AAAAAAAAAA", "BBBBBB", "TTTTTTTTTT"] -get_highest_word_score(words) \ No newline at end of file From 05e63f1bdb75f30c6ea3580c6dcea57977ccda8d Mon Sep 17 00:00:00 2001 From: Sarah Kim Date: Wed, 22 Mar 2023 21:18:09 -0700 Subject: [PATCH 10/11] refactored and added comments to get_highest_word_score function --- adagrams/game.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/adagrams/game.py b/adagrams/game.py index 49022c86..2422ee24 100644 --- a/adagrams/game.py +++ b/adagrams/game.py @@ -99,7 +99,6 @@ def score_word(word): # check if the word length is >=7 and if it is then add 8 to the total_score if len(word) >= 7: total_score += 8 - # return the score return total_score def get_highest_word_score(word_list): @@ -119,6 +118,5 @@ def get_highest_word_score(word_list): #Look for word with highest score elif score_for_one_word > highest_score: highest_score = score_for_one_word - highest_scoring_word = new_word - + highest_scoring_word = new_word return highest_scoring_word, highest_score From c971784a864380f7c9696bd8c9542ce42ba48c29 Mon Sep 17 00:00:00 2001 From: Sarah Kim Date: Wed, 22 Mar 2023 21:21:43 -0700 Subject: [PATCH 11/11] final version of Adagrams --- README.md | 255 ------------------------------------------------------ 1 file changed, 255 deletions(-) delete mode 100644 README.md diff --git a/README.md b/README.md deleted file mode 100644 index cfaa5310..00000000 --- a/README.md +++ /dev/null @@ -1,255 +0,0 @@ -# AdaGrams - -## Skills Assessed - -- Following directions and reading comprehension -- Reading tests -- Using git to maintain code -- Manipulating and processing data in lists and strings - -## Goal - -An [anagram](https://en.wikipedia.org/wiki/Anagram) is a word or phrase formed by rearranging the letters of a different word or phrase. In this project you will be creating _Adagrams_, a game in which a player is given a random set of letters and must make an anagram using those letters. Each submitted word will score points. - -While working on _Adagrams_, it may help to think of a physical metaphor for this game, such as other common word games like _Scrabble_ or _Bananagrams_. These games all feature a _pool_ of letter _tiles_ that the player _draws_ from. - -In this version of _Adagrams_, we will only be working with the English alphabet. - -![an image of a pile of letter tiles](images/letter-tiles.jpeg) - -## One-Time Project Setup - -Follow these directions once, at the beginning of your project: - - -1. Navigate to your projects folder named `projects`. - -If you followed Ada's recommended file system structure from the Intro to Dev Environment lesson in Learn, you can navigate to your projects folder with the following command: - -```bash -$ cd ~/Developer/projects -``` - -2. In Github click on the "Fork" button in github and fork the repository to your Github account. This will make a copy of the project in your github account. - -![Fork Button](images/fork.png) - -3. "Clone" (download a copy of this project) into your projects folder. This command makes a new folder called `adagrams-py`, and then puts the project into this new folder. Make sure you are cloning from your copy of the project and not the class version (ada-cX). - -```bash -$ git clone ... -``` - -Use `ls` to confirm there's a new project folder - -4. Move your location into this project folder - -```bash -$ cd adagrams-py -``` - -5. Create a virtual environment named `venv` for this project: - -```bash -$ python3 -m venv venv -``` - -6. Activate this environment: - -```bash -$ source venv/bin/activate -``` - -Verify that you're in a python3 virtual environment by running: - -- `$ python --version` should output a Python 3 version -- `$ pip --version` should output that it is working with Python 3 - -7. Install dependencies once at the beginning of this project with - -```bash -# Must be in activated virtual environment -$ pip install -r requirements.txt -``` - -Summary of one-time project setup: -- [ ] Fork the project respository -- [ ] `cd` into your `projects` folder -- [ ] Clone the project onto your machine -- [ ] `cd` into the `adagrams-py` folder -- [ ] Create the virtual environment `venv` -- [ ] Activate the virtual environment `venv` -- [ ] Install the dependencies with `pip` - -## Project Development Workflow - -1. When you want to begin work on this project, ensure that your virtual environment is activated: - -```bash -$ source venv/bin/activate -``` - -2. Run the game and play test your current wave. Replace the word `wave` below with the wave number (ie, 1, 2, 3 or 4): - -```bash -# Must be in activated virtual environment -$ python main.py wave -``` - -3. Use play-testing to guide your development. - -4. Use tests to verify your functions after thoroughly play-testing. See instructions for running tests in the section below. *A complete set of unit tests is provided for this project.* - -5. Use git to commit your work regularly! Commit between each wave. - -```bash -# Add your current work -$ git add . -$ git commit -m "meaningful message explaining your commit" -``` - -6. Move on to the next wave! - -7. When you are finished working for the day, deactivate your environment with deactivate or closing the Terminal tab/window - -```bash -$ deactivate -``` - -## Details About How to Run Tests - -1. Find the test file that contains the test you want to run. - - - Check the `tests` folder, and find the test file you want to run - - In that test file, read through each test case - - -2. Run the tests for your specific wave - -```bash -# Must be in activated virtual environment -$ pytest tests/test_wave_01.py -``` - -3. Run all tests that exist in this project with: - -```bash -# Must be in activated virtual environment -$ pytest -``` - -4. If you want to see any `print` statements print to the console, add `-s` to the end of any `pytest` command: - -```bash -# Must be in activated virtual environment -$ pytest -s -``` - -## Project Write-Up: How to Complete and Submit - - -The goal of this project is to write code in `game.py` so each of the functions meet the requirements outlined in the Project Directions below. - -Go through the waves one-by-one and build the features of this game. - -You will use play-testing and unit tests to drive your development. - -At submission time, no matter where you are, submit the project via Learn. - -This will let us give feedback on what you've finished so that you can be better prepared for the next project. - -## Project Directions - -### Get Familiar - -Take time to read through the Wave 1 implementation requirements and the tests for Wave 1. Write down your questions, and spend some time going through your understanding of the requirements and tests. Make sure you can run `$ pytest` and see the tests fail. - -If, after you have taken some time to think through the problem and would like direction for how to dissect the problem, or if you need clarity on the terms/vocabulary we used in this project, you can check out [a small hint we've provided](./project_docs/hints.md). - -### Wave 1: draw_letters - -Your first task is to build a hand of 10 letters for the user. To do so, implement the function `draw_letters` in `game.py`. This method should have the following properties: - -- No parameters -- Returns an array of ten strings - - Each string should contain exactly one letter - - These represent the hand of letters that the player has drawn -- The letters should be randomly drawn from a pool of letters - - This letter pool should reflect the distribution of letters as described in the table below - - There are only 2 available `C` letters, so `draw_letters` cannot ever return more than 2 `C`s - - Since there are 12 `E`s but only 1 `Z`, it should be 12 times as likely for the user to draw an `E` as a `Z` -- Invoking this function should **not** change the pool of letters - - Imagine that the user returns their hand to the pool before drawing new letters - -#### Distribution of Letters - -| Letter : Qty. | Letter : Qty. | -|:------:|:-----:| -| A : 9 | N : 6 | -| B : 2 | O : 8 | -| C : 2 | P : 2 | -| D : 4 | Q : 1 | -| E : 12 | R : 6 | -| F : 2 | S : 4 | -| G : 3 | T : 6 | -| H : 2 | U : 4 | -| I : 9 | V : 2 | -| J : 1 | W : 2 | -| K : 1 | X : 1 | -| L : 4 | Y : 2 | -| M : 2 | Z : 1 | - -**Note:** Making sure that the drawn letters match the rules of the letter pool can be straightforward or very difficult, depending on how you build the data structure for the letter pool. It is worth spending some time to think carefully about this. - - -### Wave 2: use_available_letters - -Next, you need a way to check if an input word (a word a player submits) only uses characters that are contained within a collection (or hand) of drawn letters. Essentially, you need a way to check if the word is an anagram of some or all of the given letters in the hand. - -To do so, implement the function called `uses_available_letters` in `game.py`. This function should have the following properties: - -- Has two parameters: - - `word`, the first parameter, describes some input word, and is a string - - `letter_bank`, the second parameter, describes an array of drawn letters in a hand. You can expect this to be an array of ten strings, with each string representing a letter -- Returns either `True` or `False` -- Returns `True` if every letter in the `input` word is available (in the right quantities) in the `letter_bank` -- Returns `False` if not; if there is a letter in `input` that is not present in the `letter_bank` or has too much of compared to the `letter_bank` - -### Wave 3: score_word - -Now you need a function returns the score of a given word as defined by the Adagrams game. - -Implement the function `score_word` in `game.py`. This method should have the following properties: - -- Has one parameter: `word`, which is a string of characters -- Returns an integer representing the number of points -- Each letter within `word` has a point value. The number of points of each letter is summed up to represent the total score of `word` -- Each letter's point value is described in the table below -- If the length of the word is 7, 8, 9, or 10, then the word gets an additional 8 points - -#### Score chart - -|Letter | Value| -|:----------------------------:|:----:| -|A, E, I, O, U, L, N, R, S, T | 1 | -|D, G | 2 | -|B, C, M, P | 3 | -|F, H, V, W, Y | 4 | -|K | 5 | -|J, X | 8 | -|Q, Z | 10 | - -### Wave 4: get_highest_word_score - -After several hands have been drawn, words have been submitted, checked, scored, and played, you need a way to find the highest scoring word. This function looks at the list of `word_list` and calculates which of these words has the highest score, applies any tie-breaking logic, and returns the winning word in a special data structure. - -Implement a function called `get_highest_word_score` in `game.py`. This method should have the following properties: - -- Has one parameter: `word_list`, which is a list of strings -- Returns a tuple that represents the data of a winning word and it's score. The tuple must contain the following elements: - - index 0 ([0]): a string of a word - - index 1 ([1]): the score of that word -- In the case of tie in scores, use these tie-breaking rules: - - prefer the word with the fewest letters... - - ...unless one word has 10 letters. If the top score is tied between multiple words and one is 10 letters long, choose the one with 10 letters over the one with fewer tiles - - If the there are multiple words that are the same score and the same length, pick the first one in the supplied list