Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Octos Maja Brenda Scrabble #16

Open
wants to merge 35 commits into
base: master
Choose a base branch
from
Open

Octos Maja Brenda Scrabble #16

wants to merge 35 commits into from

Conversation

mgraonic
Copy link

@mgraonic mgraonic commented Feb 24, 2018

Scrabble

Congratulations! You're submitting your assignment.

Comprehension Questions

Feature Feedback
What are the advantages of using git when collaboratively working on one code base? By using git both persons can collaborate and work at the same time.
Why do you think we chose to make the score method in the Scoring class a class method instead of an instance method? We made the Score method a Class method because it does not have to do anything with a particular instance so we didn't require an instance method.
Describe an example of a test you wrote for a nominal case. When we tested a valid word and got the score for it.
Describe an example of a test you wrote for an edge case. When we tested a letter of more than 7 letters.
Does your code use any methods from the Enumerable mixin? If so, where and why was it helpful? Yes, in the self.highest_score_from method in the file Scoring we used the method min to get break a tie when two letters get the same score so with min we were able to compare the words and choose the one with less letters.

Also, we used the delete_if method in the draw_tiles method in the Tilebag file to delete the letter if its quantity was 0. They were very useful to complete and meet the requirements.
What was one method you and your pair used to debug code? We used several times the pry gem to find out the problem and debug. We also debugged by hardcoding values to better see where things were going wrong.
Is there a specific piece of code you'd like feedback on? The self.highest_score_from method. Are there places where we could have used fewer extra data structures? Or made the code shorter?
What are two discussion points that you and your pair discussed when giving/receiving feedback from each other that you would be willing to share? About how useful is to talk to each other about our ideas, and that thinking out loud can also be very useful.

@droberts-sea
Copy link

Scrabble

What We're Looking For

Feature Feedback
General
Answered comprehension questions yes
Both Teammates contributed to the codebase yes
Regular Commits with meaningful commit messages yes
Scoring class
score method yes
Uses appropriate data structure to store the letter score yes
Appropriately handles edge cases yes
highest_score_from method yes
Appropriately handles edge cases yes
Test implementations for highest_score_from yes
Player class
Uses an array to keep track of words played yes
Uses existing code to create highest_scoring_word and highest_word_score yes
Returns true or false from won? method yes
Tests edge cases on the play(word) some missing - see inline
TileBag class
Uses a data structure to keep the set of default tiles in the bag see inline
draw_tiles method uses the parameter to draw a set of random tiles big bug - see inline
tiles_remaining method returns a count yes
Tests draw_tiles edge cases some missing - see inline

Good job overall! The big learning goals I'm looking to see demonstrated on this project are:

  • Building complex logic (tie-breaking logic in highest_score_from)
  • Test coverage
  • Object composition (interaction between Player and TileBag)

I feel that you've done a good job of demonstrating the first and the third of these. Your test coverage could use some work - several of your methods are missing tests entirely, or are missing interesting cases. I've left some inline comments for you to review, please do so, and keep up the hard work!

@letters = {
"A"=>1,
"B"=>3,
"C"=>3,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this choice of data structure. Since it's not going to change during one run of the program, this is the sort of thing that would be great as a constant.

else
array_of_words.length.times do
@words_scores = {}
array_of_words.each do |word|

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You loop over the list of words twice here! I think the outer loop (line 63) could be removed entirely, since you unconditionally return at the end of it (line 86), so it will never run more than once.

elsif array_of_words.length == 1
return array_of_words[0]
else
array_of_words.length.times do

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally this check should be unnecessary, and your loop code should do the right thing if there's only one word.

if word.length == 7
winner = word
else
winner = tied_words.min{|word1,word2| word1.length <=> word2.length}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On line 83 you're computing the min across all the tied words within the loop of all the tied words. This is probably not what you want - it means you're looking at all the words each time you look at one of the words, an O(n^2) operation. We could rewrite this tiebreaker section as follows:

winner = tied_words.find{ |word| word.length == 7 }
if winner.nil?
  # min by length, equivalent to your line 83 but a little more concise
  winner = tied_words.min_by{ |word| word.length }
end

if @won == true
return false
else
@plays << word

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the if clause returns from the method, you can leave out the else:

if @won
  return false
end
@plays << word
# ...

describe 'won method' do
it 'returns true if score is > 100' do
john = Scrabble::Player.new("John")
john.play("squeeze")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to see more precision around the "edge" between winning and not winning. What happens if the player has:

  • 99 points
  • 100 points
  • 101 points

it 'returns the highest word if there are two words' do
it 'returns the highest value word if there are two words' do
words2 = ["cookie", "cake"]
Scrabble::Scoring.highest_score_from(words2).must_equal "cookie"
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like we discussed in class, it would probably be wise to check multiple orderings of these words, that is, both ['dog', 'fish'] and ['fish', 'dog']. You'd be surprised how often this sort of thing turns up a bug.

end

it 'if tied, prefer a word with 7 letters' do
words3 = ["qqqqqx", "aeiould"]

Scrabble::Scoring.highest_score_from(words3).must_equal "aeiould"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work on this test.

it 'returns a collection of random tiles' do
tile_bag = Scrabble::TileBag.new
tile_bag.draw_tiles(4).must_be_instance_of Array
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should check more than that it gives back an array here. For example:

  • Is the array the correct length?
  • Are all the members letters?
  • Are the letters that were returned the same as the ones that were removed from the bag (how would you test this?)

Expanding your tests in this way would have caught that bug with draw_tiles.

tile_bag = Scrabble::TileBag.new
tile_bag.draw_tiles(7)
tile_bag.default_tiles.values.sum.must_equal 91
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also like to see tests for draw_tiles that answer the following questions:

  • Am I able to draw the last tile from the bag?
  • What happens if I try to draw more tiles than are currently in the bag?
  • What if I try to draw 0 or -3 tiles?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants