Skip to content

Update bowling canonical-data #391

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

Merged
merged 5 commits into from
Oct 16, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 78 additions & 77 deletions exercises/bowling/canonical-data.json
Original file line number Diff line number Diff line change
@@ -1,117 +1,118 @@
{
"#": [
"Bowling is game where players roll a heavy ball to knock down pins",
"arranged in a triangle. Write code to keep track of the score of a",
"game of bowling."
"Students should implement roll and score methods.",
"Roll should accept a single integer.",
"Score should return the game's final score, when possible",
"For brevity the tests display all the rolls in an array;",
"each element of the rolls array should be passed to the roll method",
"The final tests define situations where the score can not be returned",
"The expection for these tests is -1, indicating an error",
"In these cases you should expect an error as is idiomatic for your language",
"When to error is also left up to your implementation. There are two options",
" - Error as soon as an invalid roll is made",
" - Error when scoring a game with an invalid roll",
"You can also error in both cases."
],
"methods": {
"description": [
"Check the public API is correct."
],
"cases": [{
"description": "must be able to roll with a number of pins",
"method": "roll",
"arity": 1
}, {
"description": "must have a score",
"method": "score",
"arity": 0
}]
},
"score": {
"description": [
"Check game can be scored correctly."
"Returns the final score of a bowling game"
],
"cases": [{
"description": "should be able to score open frame",
"rolls": [3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"expected": 7
}, {
"description": "should be able to score multiple frames",
"rolls": [3, 4, 2, 3, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"expected": 19
}, {
"description": "should be able to score a game with all gutterballs",
"description": "should be able to score a game with all zeros",
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"expected": 0
}, {
"description": "should be able to score a game with all single pin rolls",
"rolls": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
"expected": 20
}, {
"description": "should be able to score a game with all open frames",
"description": "should be able to score a game with no strikes or spares",
"rolls": [3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6],
"expected": 90
}, {
"description": "should be able to score a strike not in the last frame",
"description": "a spare followed by zeros is worth ten points",
"rolls": [6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"expected": 10
}, {
"description": "points scored in the roll after a spare are counted twice",
"rolls": [6, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"expected": 16
}, {
"description": "consecutive spares each get a one roll bonus",
"rolls": [5, 5, 3, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"expected": 31
}, {
"description": "a spare in the last frame gets a one roll bonus that is counted once",
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 7],
"expected": 17
}, {
"description": "a strike earns ten points in frame with a single roll",
"rolls": [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"expected": 10
}, {
"description": "points scored in the two rolls after a strike are counted twice as a bonus",
"rolls": [10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"expected": 26
}, {
"description": "should be able to score a spare not in the last frame",
"rolls": [5, 5, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"expected": 20
}, {
"description": "should be able to score multiple strikes in a row",
"description": "consecutive strikes each get the two roll bonus",
"rolls": [10, 10, 10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"expected": 81
}, {
"description": "should be able to score multiple spares in a row",
"rolls": [5, 5, 3, 7, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"expected": 32
}, {
"description": "should allow fill balls when the last frame is a strike",
"description": "a strike in the last frame gets a two roll bonus that is counted once",
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 1],
"expected": 18
}, {
"description": "should allow fill ball when the last frame is a spare",
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 1, 7],
"expected": 17
"description": "rolling a spare with the two roll bonus does not get a bonus roll",
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 3],
"expected": 20
}, {
"description": "should allow fill balls to be a strike",
"description": "strikes with the two roll bonus do not get bonus rolls",
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10],
"expected": 30
}, {
"description": "should be able to score a perfect game",
"description": "a strike with the one roll bonus after a spare in the last frame does not get a bonus",
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 10],
"expected": 20
}, {
"description": "all strikes is a perfect game",
"rolls": [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
"expected": 300
}]
},
"validations": {
"description": [
"Check game rules."
],
"cases": [{
"description": "should not allow rolls with negative pins",
"rolls": [-1],
"expected": "Pins must have a value from 0 to 10"
}, {
"description": "should not allow rolls better than strike",
"rolls": [11],
"expected": "Pins must have a value from 0 to 10"
"description": "Rolls can not score negative points",
"rolls": [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"expected": -1
}, {
"description": "should not allow two normal rolls better than strike",
"rolls": [5, 6],
"expected": "Pin count exceeds pins on the lane"
"description": "A roll can not score more than 10 points",
"rolls": [11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"expected": -1
}, {
"description": "should not allow two normal rolls better than strike in last frame",
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6],
"expected": "Pin count exceeds pins on the lane"
"description": "Two rolls in a frame can not score more than 10 points",
"rolls": [5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"expected": -1
}, {
"description": "should not allow to take score at the beginning of the game",
"description": "Two bonus rolls after a strike in the last frame can not score more than 10 points",
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 5, 6],
"expected": -1
}, {
"description": "An unstarted game can not be scored",
"rolls": [],
"expected": "Score cannot be taken until the end of the game"
"expected": -1
}, {
"description": "should not allow to take score before the game has ended",
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"expected": "Score cannot be taken until the end of the game"
"description": "An incomplete game can not be scored",
Copy link
Member

Choose a reason for hiding this comment

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

any value in keeping these? it did catch an oversight in my code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If these tests caught an edge case, then they should be kept. Thanks.

Copy link
Member

Choose a reason for hiding this comment

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

I was indeed treating the bonus rolls in a separate place from the normal ten frames, so I do say it is worth keeping.

"rolls": [0, 0],
"expected": -1
}, {
"description": "should not allow rolls after the tenth frame",
"description": "A game with more than ten frames can not be scored",
Copy link
Member

@petertseng petertseng Oct 8, 2016

Choose a reason for hiding this comment

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

The change in the description seems to change the implication of where the error should occur.

Before, to me this sounds like: The roll should be rejected before there is any attempt to take the score.

After, it sounds like: The roll should be accepted, and only when taking the score do we realize there is a failure.

And I definitely think the roll should be rejected as soon as possible.

But this is a difficult proposition when the only expectation this test file expresses is the score at the end, instead of noting where the error should occur. That's a difficult concept to express though. The first idea that comes to mind (and the idea may be crazy) is:

"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"roll_should_fail": 0,

If the idea is accepted, it can also be used for the [5, 6] roll.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For those of you who aren't Peter, we've been talking about this in the Rust PR as well.

exercism/rust#213

For Rust, at least, we're going to have the roll method fail if the roll is invalid.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can update the description to talk about this decision. I think the json file can mention it, but leave it up to the implementation.

Copy link
Member

@petertseng petertseng Oct 12, 2016

Choose a reason for hiding this comment

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

I can update the description to talk about this decision. I think the json file can mention it, but leave it up to the implementation.

Seems good.

"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"expected": "Should not be able to roll after game is over"
"expected": -1
}, {
"description": "bonus rolls for a strike in the last frame must be rolled before score can be calculated",
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
"expected": -1
}, {
"description": "both bonus rolls for a strike in the last frame must be rolled before score can be calculated",
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10],
"expected": -1
}, {
"description": "should not calculate score before fill balls have been played",
"rolls": [10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
"expected": "Score cannot be taken until the end of the game"
"description": "bonus roll for a spare in the last frame must be rolled before score can be calculated",
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3],
"expected": -1
}]
}
}