trackler 1.0.4.0 → 1.0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/common/CONTRIBUTING.md +17 -2
- data/common/exercises/anagram/canonical-data.json +0 -14
- data/common/exercises/pig-latin/canonical-data.json +6 -1
- data/common/exercises/raindrops/description.md +4 -4
- data/common/exercises/raindrops/metadata.yml +1 -1
- data/common/exercises/roman-numerals/metadata.yml +1 -1
- data/lib/trackler/version.rb +1 -1
- data/tracks/c/config.json +12 -1
- data/tracks/c/exercises/roman-numerals/makefile +16 -0
- data/tracks/c/exercises/roman-numerals/src/example.c +43 -0
- data/tracks/c/exercises/roman-numerals/src/example.h +6 -0
- data/tracks/c/exercises/roman-numerals/test/test_roman_numerals.c +126 -0
- data/tracks/c/exercises/roman-numerals/test/vendor/unity.c +1300 -0
- data/tracks/c/exercises/roman-numerals/test/vendor/unity.h +274 -0
- data/tracks/c/exercises/roman-numerals/test/vendor/unity_internals.h +701 -0
- data/tracks/clojure/exercises/flatten-array/project.clj +4 -0
- data/tracks/csharp/exercises/protein-translation/ProteinTranslationTest.cs +1 -1
- data/tracks/elixir/exercises/bowling/bowling_test.exs +157 -62
- data/tracks/elixir/exercises/bowling/example.exs +33 -4
- data/tracks/erlang/config.json +176 -36
- data/tracks/go/.travis.yml +7 -1
- data/tracks/go/bin/test-without-stubs +29 -0
- data/tracks/go/exercises/robot-simulator/defs.go +1 -1
- data/tracks/go/exercises/variable-length-quantity/variable_length_quantity_test.go +31 -25
- data/tracks/haskell/.travis.yml +9 -5
- data/tracks/haskell/config.json +127 -121
- data/tracks/haskell/exercises/leap/src/LeapYear.hs +1 -1
- data/tracks/haskell/exercises/space-age/HINTS.md +14 -2
- data/tracks/haskell/exercises/space-age/{src/Example.hs → examples/success-double/SpaceAge.hs} +0 -0
- data/tracks/haskell/exercises/space-age/examples/success-double/package.yaml +19 -0
- data/tracks/haskell/exercises/space-age/examples/success-rational/SpaceAge.hs +24 -0
- data/tracks/haskell/exercises/space-age/examples/success-rational/package.yaml +19 -0
- data/tracks/haskell/exercises/space-age/src/SpaceAge.hs +4 -1
- data/tracks/haskell/exercises/space-age/test/Tests.hs +12 -5
- data/tracks/haskell/exercises/word-count/HINTS.md +21 -0
- data/tracks/haskell/exercises/word-count/examples/success-newtype/WordCount.hs +31 -0
- data/tracks/haskell/exercises/word-count/examples/success-newtype/package.yaml +21 -0
- data/tracks/haskell/exercises/word-count/examples/success-simple/WordCount.hs +13 -0
- data/tracks/haskell/exercises/word-count/examples/success-simple/package.yaml +20 -0
- data/tracks/haskell/exercises/word-count/package.yaml +0 -2
- data/tracks/haskell/exercises/word-count/src/WordCount.hs +2 -1
- data/tracks/haskell/exercises/word-count/test/Tests.hs +15 -6
- data/tracks/haskell/exercises/zebra-puzzle/package.yaml +19 -0
- data/tracks/haskell/exercises/zebra-puzzle/src/Example.hs +113 -0
- data/tracks/haskell/exercises/zebra-puzzle/src/ZebraPuzzle.hs +12 -0
- data/tracks/haskell/exercises/zebra-puzzle/stack.yaml +1 -0
- data/tracks/haskell/exercises/zebra-puzzle/test/Tests.hs +13 -0
- data/tracks/javascript/exercises/beer-song/beer-song.spec.js +5 -0
- data/tracks/lisp/config.json +147 -0
- data/tracks/ocaml/config.json +12 -0
- data/tracks/ocaml/exercises/atbash-cipher/.merlin +5 -0
- data/tracks/ocaml/exercises/atbash-cipher/HINTS.md +17 -0
- data/tracks/ocaml/exercises/atbash-cipher/Makefile +11 -0
- data/tracks/ocaml/exercises/atbash-cipher/atbash_cipher.mli +5 -0
- data/tracks/ocaml/exercises/atbash-cipher/example.ml +47 -0
- data/tracks/ocaml/exercises/atbash-cipher/test.ml +37 -0
- data/tracks/ocaml/exercises/meetup/.merlin +5 -0
- data/tracks/ocaml/exercises/meetup/Makefile +11 -0
- data/tracks/ocaml/exercises/meetup/example.ml +63 -0
- data/tracks/ocaml/exercises/meetup/meetup.mli +7 -0
- data/tracks/ocaml/exercises/meetup/test.ml +786 -0
- data/tracks/php/exercises/bowling/bowling_test.php +233 -10
- data/tracks/php/exercises/bowling/example.php +49 -6
- data/tracks/python/.travis.yml +5 -0
- data/tracks/python/config.json +33 -1
- data/tracks/python/exercises/flatten-array/example.py +18 -0
- data/tracks/python/exercises/flatten-array/flatten_array_test.py +40 -0
- data/tracks/python/exercises/robot-name/robot_name_test.py +8 -2
- data/tracks/r/config.json +32 -8
- data/tracks/ruby/bin/enable-executable +9 -5
- data/tracks/ruby/bin/executable-tests-check +7 -3
- data/tracks/ruby/bin/local-status-check +4 -4
- data/tracks/ruby/config.json +8 -1
- data/tracks/ruby/exercises/acronym/acronym_test.rb +0 -1
- data/tracks/ruby/exercises/anagram/.version +1 -0
- data/tracks/ruby/exercises/anagram/anagram_test.rb +101 -31
- data/tracks/ruby/exercises/anagram/example.rb +4 -0
- data/tracks/ruby/exercises/anagram/example.tt +19 -0
- data/tracks/ruby/exercises/gigasecond/.version +1 -1
- data/tracks/ruby/exercises/gigasecond/example.rb +1 -1
- data/tracks/ruby/exercises/gigasecond/gigasecond_test.rb +2 -2
- data/tracks/ruby/exercises/isogram/.version +1 -0
- data/tracks/ruby/exercises/isogram/example.rb +10 -0
- data/tracks/ruby/exercises/isogram/example.tt +20 -0
- data/tracks/ruby/exercises/isogram/isogram_test.rb +90 -0
- data/tracks/ruby/exercises/poker/example.rb +97 -39
- data/tracks/ruby/exercises/poker/poker_test.rb +67 -36
- data/tracks/ruby/exercises/sieve/.version +1 -0
- data/tracks/ruby/exercises/sieve/example.rb +4 -0
- data/tracks/ruby/exercises/sieve/example.tt +21 -0
- data/tracks/ruby/exercises/sieve/sieve_test.rb +36 -13
- data/tracks/ruby/exercises/word-count/example.tt +4 -3
- data/tracks/ruby/exercises/word-count/word_count_test.rb +38 -48
- data/tracks/ruby/lib/anagram_cases.rb +42 -0
- data/tracks/ruby/lib/isogram_cases.rb +24 -0
- data/tracks/ruby/lib/sieve_cases.rb +33 -0
- data/tracks/ruby/lib/word_count_cases.rb +19 -0
- data/tracks/scala/config.json +21 -0
- data/tracks/scala/docs/RESOURCES.md +1 -0
- data/tracks/scala/exercises/bracket-push/build.sbt +4 -0
- data/tracks/scala/exercises/bracket-push/example.scala +23 -0
- data/tracks/scala/exercises/bracket-push/src/main/scala/.keep +0 -0
- data/tracks/scala/exercises/bracket-push/src/test/scala/BracketsTest.scala +68 -0
- data/tracks/scala/exercises/change/src/test/scala/ChangeTest.scala +7 -0
- data/tracks/scala/exercises/sgf-parsing/build.sbt +7 -0
- data/tracks/scala/exercises/sgf-parsing/example.scala +66 -0
- data/tracks/scala/exercises/sgf-parsing/src/main/scala/.keep +0 -0
- data/tracks/scala/exercises/sgf-parsing/src/main/scala/Sgf.scala +17 -0
- data/tracks/scala/exercises/sgf-parsing/src/test/scala/SgfTest.scala +66 -0
- data/tracks/scala/exercises/zebra-puzzle/build.sbt +3 -0
- data/tracks/scala/exercises/zebra-puzzle/example.scala +152 -0
- data/tracks/scala/exercises/zebra-puzzle/src/main/scala/.keep +0 -0
- data/tracks/scala/exercises/zebra-puzzle/src/main/scala/ZebraPuzzle.scala +14 -0
- data/tracks/scala/exercises/zebra-puzzle/src/test/scala/ZebraPuzzleTest.scala +11 -0
- data/tracks/scala/testgen/src/main/scala/BracketPushTestGenerator.scala +44 -0
- metadata +63 -3
- data/tracks/haskell/exercises/word-count/src/Example.hs +0 -8
|
@@ -16,43 +16,163 @@ class GameTest extends \PHPUnit_Framework_TestCase
|
|
|
16
16
|
$this->game = new Game();
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
public function
|
|
19
|
+
public function testShouldBeAbleToScoreAGameWithAllZeros()
|
|
20
20
|
{
|
|
21
21
|
$this->rollMany(20, 0);
|
|
22
22
|
|
|
23
23
|
$this->assertEquals(0, $this->game->score());
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
public function
|
|
26
|
+
public function testShouldBeAbleToScoreAGameWithNoStrikesOrSpares()
|
|
27
27
|
{
|
|
28
28
|
$this->markTestSkipped();
|
|
29
|
-
$this->
|
|
29
|
+
$this->game->roll(3);
|
|
30
|
+
$this->game->roll(6);
|
|
31
|
+
$this->game->roll(3);
|
|
32
|
+
$this->game->roll(6);
|
|
33
|
+
$this->game->roll(3);
|
|
34
|
+
$this->game->roll(6);
|
|
35
|
+
$this->game->roll(3);
|
|
36
|
+
$this->game->roll(6);
|
|
37
|
+
$this->game->roll(3);
|
|
38
|
+
$this->game->roll(6);
|
|
39
|
+
$this->game->roll(3);
|
|
40
|
+
$this->game->roll(6);
|
|
41
|
+
$this->game->roll(3);
|
|
42
|
+
$this->game->roll(6);
|
|
43
|
+
$this->game->roll(3);
|
|
44
|
+
$this->game->roll(6);
|
|
45
|
+
$this->game->roll(3);
|
|
46
|
+
$this->game->roll(6);
|
|
47
|
+
$this->game->roll(3);
|
|
48
|
+
$this->game->roll(6);
|
|
30
49
|
|
|
31
|
-
$this->assertEquals(
|
|
50
|
+
$this->assertEquals(90, $this->game->score());
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public function testASpareFollowedByZerosIsWorthTenPoints()
|
|
54
|
+
{
|
|
55
|
+
$this->markTestSkipped();
|
|
56
|
+
$this->game->roll(6);
|
|
57
|
+
$this->game->roll(4);
|
|
58
|
+
$this->rollMany(18, 0);
|
|
59
|
+
|
|
60
|
+
$this->assertEquals(10, $this->game->score());
|
|
32
61
|
}
|
|
33
62
|
|
|
34
|
-
public function
|
|
63
|
+
public function testPointsScoredInTheRollAfterASpareAreCountedTwice()
|
|
35
64
|
{
|
|
36
65
|
$this->markTestSkipped();
|
|
37
|
-
$this->
|
|
66
|
+
$this->game->roll(6);
|
|
67
|
+
$this->game->roll(4);
|
|
38
68
|
$this->game->roll(3);
|
|
39
69
|
$this->rollMany(17, 0);
|
|
40
70
|
|
|
41
71
|
$this->assertEquals(16, $this->game->score());
|
|
42
72
|
}
|
|
43
73
|
|
|
44
|
-
public function
|
|
74
|
+
public function testConsecutiveSparesEachGetAOneRollBonus()
|
|
45
75
|
{
|
|
46
76
|
$this->markTestSkipped();
|
|
47
|
-
$this->
|
|
77
|
+
$this->game->roll(5);
|
|
78
|
+
$this->game->roll(5);
|
|
48
79
|
$this->game->roll(3);
|
|
80
|
+
$this->game->roll(7);
|
|
49
81
|
$this->game->roll(4);
|
|
82
|
+
$this->rollMany(15, 0);
|
|
83
|
+
|
|
84
|
+
$this->assertEquals(31, $this->game->score());
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public function testASpareInTheLastFrameGetsAOneRollBonusThatIsCountedOnce()
|
|
88
|
+
{
|
|
89
|
+
$this->markTestSkipped();
|
|
90
|
+
$this->rollMany(18, 0);
|
|
91
|
+
$this->game->roll(7);
|
|
92
|
+
$this->game->roll(3);
|
|
93
|
+
$this->game->roll(7);
|
|
94
|
+
|
|
95
|
+
$this->assertEquals(17, $this->game->score());
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public function testAStrikeEarnsTenPointsInFrameWithASingleRoll()
|
|
99
|
+
{
|
|
100
|
+
$this->markTestSkipped();
|
|
101
|
+
$this->game->roll(10);
|
|
102
|
+
$this->rollMany(18, 0);
|
|
103
|
+
|
|
104
|
+
$this->assertEquals(10, $this->game->score());
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public function testPointsScoredInTheTwoRollsAfterAStrikeAreCountedTwiceAsABonus()
|
|
108
|
+
{
|
|
109
|
+
$this->markTestSkipped();
|
|
110
|
+
$this->game->roll(10);
|
|
111
|
+
$this->game->roll(5);
|
|
112
|
+
$this->game->roll(3);
|
|
50
113
|
$this->rollMany(16, 0);
|
|
51
114
|
|
|
52
|
-
$this->assertEquals(
|
|
115
|
+
$this->assertEquals(26, $this->game->score());
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
public function testConsecutiveStrikesEachGetTheTwoRollBonus()
|
|
119
|
+
{
|
|
120
|
+
$this->markTestSkipped();
|
|
121
|
+
$this->game->roll(10);
|
|
122
|
+
$this->game->roll(10);
|
|
123
|
+
$this->game->roll(10);
|
|
124
|
+
$this->game->roll(5);
|
|
125
|
+
$this->game->roll(3);
|
|
126
|
+
$this->rollMany(12, 0);
|
|
127
|
+
|
|
128
|
+
$this->assertEquals(81, $this->game->score());
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
public function testAStrikeInTheLastFrameGetsATwoRollBonusThatIsCountedOnce()
|
|
132
|
+
{
|
|
133
|
+
$this->markTestSkipped();
|
|
134
|
+
$this->rollMany(18, 0);
|
|
135
|
+
$this->game->roll(10);
|
|
136
|
+
$this->game->roll(7);
|
|
137
|
+
$this->game->roll(1);
|
|
138
|
+
|
|
139
|
+
$this->assertEquals(18, $this->game->score());
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
public function testRollingASpareWithTheTwoRollBonusDoesNotGetABonusRoll()
|
|
143
|
+
{
|
|
144
|
+
$this->markTestSkipped();
|
|
145
|
+
$this->rollMany(18, 0);
|
|
146
|
+
$this->game->roll(10);
|
|
147
|
+
$this->game->roll(10);
|
|
148
|
+
$this->game->roll(10);
|
|
149
|
+
|
|
150
|
+
$this->assertEquals(30, $this->game->score());
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
public function testAStrikeWithTheOneRollBonusAfterASpareInTheLastFrameDoesNotGetABonus()
|
|
154
|
+
{
|
|
155
|
+
$this->markTestSkipped();
|
|
156
|
+
$this->rollMany(18, 0);
|
|
157
|
+
$this->game->roll(7);
|
|
158
|
+
$this->game->roll(3);
|
|
159
|
+
$this->game->roll(10);
|
|
160
|
+
|
|
161
|
+
$this->assertEquals(20, $this->game->score());
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
public function testStrikesWithTheTwoRollBonusDoNotGetBonusRolls()
|
|
165
|
+
{
|
|
166
|
+
$this->markTestSkipped();
|
|
167
|
+
$this->rollMany(18, 0);
|
|
168
|
+
$this->game->roll(10);
|
|
169
|
+
$this->game->roll(7);
|
|
170
|
+
$this->game->roll(3);
|
|
171
|
+
|
|
172
|
+
$this->assertEquals(20, $this->game->score());
|
|
53
173
|
}
|
|
54
174
|
|
|
55
|
-
public function
|
|
175
|
+
public function testAllStrikesIsAPerfectGame()
|
|
56
176
|
{
|
|
57
177
|
$this->markTestSkipped();
|
|
58
178
|
$this->rollMany(12, 10);
|
|
@@ -60,6 +180,109 @@ class GameTest extends \PHPUnit_Framework_TestCase
|
|
|
60
180
|
$this->assertEquals(300, $this->game->score());
|
|
61
181
|
}
|
|
62
182
|
|
|
183
|
+
public function testRollsCanNotScoreNegativePoints()
|
|
184
|
+
{
|
|
185
|
+
$this->markTestSkipped();
|
|
186
|
+
$this->expectException(Exception::class);
|
|
187
|
+
|
|
188
|
+
$this->game->roll(-1);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
public function testARollCanNotScoreMoreThan10Points()
|
|
192
|
+
{
|
|
193
|
+
$this->markTestSkipped();
|
|
194
|
+
$this->expectException(Exception::class);
|
|
195
|
+
$this->game->roll(11);
|
|
196
|
+
$this->rollMany(19, 0);
|
|
197
|
+
|
|
198
|
+
$this->game->score();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
public function testTwoRollsInAFrameCanNotScoreMoreThan10Points()
|
|
202
|
+
{
|
|
203
|
+
$this->markTestSkipped();
|
|
204
|
+
|
|
205
|
+
$this->expectException(Exception::class);
|
|
206
|
+
$this->game->roll(5);
|
|
207
|
+
$this->game->roll(6);
|
|
208
|
+
$this->rollMany(18, 0);
|
|
209
|
+
|
|
210
|
+
$this->game->score();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
public function testTwoBonusRollsAfterAStrikeInTheLastFrameCanNotScoreMoreThan10Points()
|
|
214
|
+
{
|
|
215
|
+
$this->markTestSkipped();
|
|
216
|
+
$this->expectException(Exception::class);
|
|
217
|
+
|
|
218
|
+
$this->rollMany(18, 0);
|
|
219
|
+
$this->game->roll(10);
|
|
220
|
+
$this->game->roll(5);
|
|
221
|
+
$this->game->roll(6);
|
|
222
|
+
|
|
223
|
+
$this->game->score();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
public function testAnUnstartedGameCanNotBeScored()
|
|
227
|
+
{
|
|
228
|
+
$this->markTestSkipped();
|
|
229
|
+
|
|
230
|
+
$this->expectException(Exception::class);
|
|
231
|
+
|
|
232
|
+
$this->game->score();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
public function testAnIncompleteGameCanNotBeScored()
|
|
236
|
+
{
|
|
237
|
+
$this->markTestSkipped();
|
|
238
|
+
$this->expectException(Exception::class);
|
|
239
|
+
$this->game->roll(0);
|
|
240
|
+
$this->game->roll(0);
|
|
241
|
+
|
|
242
|
+
$this->game->score();
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
public function testAGameWithMoreThanTenFramesCanNotBeScored()
|
|
246
|
+
{
|
|
247
|
+
$this->markTestSkipped();
|
|
248
|
+
$this->expectException(Exception::class);
|
|
249
|
+
$this->rollMany(21, 0);
|
|
250
|
+
|
|
251
|
+
$this->game->score();
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
public function testBonusRollsForAStrikeInTheLastFrameMustBeRolledBeforeScoreCanBeCalculated()
|
|
255
|
+
{
|
|
256
|
+
$this->markTestSkipped();
|
|
257
|
+
$this->expectException(Exception::class);
|
|
258
|
+
$this->rollMany(18, 0);
|
|
259
|
+
$this->game->roll(10);
|
|
260
|
+
|
|
261
|
+
$this->game->score();
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
public function testBothBonusRollsForAStrikeInTheLastFrameMustBeRolledBeforeScoreCanBeCalculated()
|
|
265
|
+
{
|
|
266
|
+
$this->markTestSkipped();
|
|
267
|
+
$this->expectException(Exception::class);
|
|
268
|
+
$this->rollMany(18, 0);
|
|
269
|
+
$this->game->roll(10);
|
|
270
|
+
$this->game->roll(10);
|
|
271
|
+
|
|
272
|
+
$this->game->score();
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
public function testBonusRollForASpareInTheLastFrameMustBeRolledBeforeScoreCanBeCalculated()
|
|
276
|
+
{
|
|
277
|
+
$this->markTestSkipped();
|
|
278
|
+
$this->expectException(Exception::class);
|
|
279
|
+
$this->rollMany(18, 0);
|
|
280
|
+
$this->game->roll(7);
|
|
281
|
+
$this->game->roll(3);
|
|
282
|
+
|
|
283
|
+
$this->game->score();
|
|
284
|
+
}
|
|
285
|
+
|
|
63
286
|
private function rollStrike()
|
|
64
287
|
{
|
|
65
288
|
$this->game->roll(10);
|
|
@@ -6,19 +6,22 @@
|
|
|
6
6
|
*/
|
|
7
7
|
class Game
|
|
8
8
|
{
|
|
9
|
-
private $rolls =
|
|
10
|
-
private $currentRoll = 0;
|
|
9
|
+
private $rolls = [];
|
|
11
10
|
|
|
12
11
|
public function roll($pins)
|
|
13
12
|
{
|
|
14
|
-
$
|
|
13
|
+
if ($pins < 0 || $pins > 10) {
|
|
14
|
+
throw new Exception('Pins must be between 0 and 10');
|
|
15
|
+
}
|
|
16
|
+
$this->rolls[] = $pins;
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
public function score()
|
|
18
20
|
{
|
|
19
21
|
$score = 0;
|
|
20
22
|
$frameIndex = 0;
|
|
21
|
-
|
|
23
|
+
foreach (range(1, 10) as $frame) {
|
|
24
|
+
$this->guardAgainstIncompleteGame($frameIndex);
|
|
22
25
|
if ($this->isStrike($frameIndex)) {
|
|
23
26
|
$score += 10 + $this->strikeBonus($frameIndex);
|
|
24
27
|
$frameIndex++;
|
|
@@ -30,6 +33,7 @@ class Game
|
|
|
30
33
|
$frameIndex += 2;
|
|
31
34
|
}
|
|
32
35
|
}
|
|
36
|
+
$this->guardAgainstTooManyFrames($frameIndex);
|
|
33
37
|
|
|
34
38
|
return $score;
|
|
35
39
|
}
|
|
@@ -41,7 +45,16 @@ class Game
|
|
|
41
45
|
|
|
42
46
|
private function strikeBonus($frameIndex)
|
|
43
47
|
{
|
|
44
|
-
|
|
48
|
+
if (!isset($this->rolls[$frameIndex + 1]) || !isset($this->rolls[$frameIndex + 2])) {
|
|
49
|
+
throw new Exception('Incomplete game');
|
|
50
|
+
}
|
|
51
|
+
$bonus1 = $this->rolls[$frameIndex + 1];
|
|
52
|
+
$bonus2 = $this->rolls[$frameIndex + 2];
|
|
53
|
+
$sum = $bonus1 + $bonus2;
|
|
54
|
+
if ($sum > 10 && $frameIndex = 10 && $bonus1 != 10) {
|
|
55
|
+
throw new Exception('Cannot score more than 10');
|
|
56
|
+
}
|
|
57
|
+
return $sum;
|
|
45
58
|
}
|
|
46
59
|
|
|
47
60
|
private function isSpare($frameIndex)
|
|
@@ -51,11 +64,41 @@ class Game
|
|
|
51
64
|
|
|
52
65
|
private function spareBonus($frameIndex)
|
|
53
66
|
{
|
|
67
|
+
if (!isset($this->rolls[$frameIndex + 2])) {
|
|
68
|
+
throw new Exception('Incomplete game');
|
|
69
|
+
}
|
|
54
70
|
return $this->rolls[$frameIndex + 2];
|
|
55
71
|
}
|
|
56
72
|
|
|
57
73
|
private function sumOfBallsInFrame($frameIndex)
|
|
58
74
|
{
|
|
59
|
-
|
|
75
|
+
$sum = $this->rolls[$frameIndex] + $this->rolls[$frameIndex + 1];
|
|
76
|
+
if ($sum > 10) {
|
|
77
|
+
throw new Exception('Cannot score more than ten in single frame');
|
|
78
|
+
}
|
|
79
|
+
return $sum;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private function guardAgainstIncompleteGame($frameIndex)
|
|
83
|
+
{
|
|
84
|
+
if (!isset($this->rolls[$frameIndex])) {
|
|
85
|
+
throw new Exception('Incomplete game');
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private function guardAgainstTooManyFrames($frameIndex)
|
|
90
|
+
{
|
|
91
|
+
$rollsCount = count($this->rolls);
|
|
92
|
+
if ($this->isStrike($frameIndex - 1)) {
|
|
93
|
+
if ($rollsCount > $frameIndex + 2) {
|
|
94
|
+
throw new Exception('Too many frames in game');
|
|
95
|
+
}
|
|
96
|
+
} elseif ($this->isSpare($frameIndex - 2)) {
|
|
97
|
+
if ($rollsCount > $frameIndex + 1) {
|
|
98
|
+
throw new Exception('Too many frames in game');
|
|
99
|
+
}
|
|
100
|
+
} elseif ($rollsCount > $frameIndex) {
|
|
101
|
+
throw new Exception('Too many frames in game');
|
|
102
|
+
}
|
|
60
103
|
}
|
|
61
104
|
}
|
data/tracks/python/.travis.yml
CHANGED
data/tracks/python/config.json
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"largest-series-product",
|
|
29
29
|
"kindergarten-garden",
|
|
30
30
|
"grade-school",
|
|
31
|
+
"flatten-array",
|
|
31
32
|
"roman-numerals",
|
|
32
33
|
"space-age",
|
|
33
34
|
"grains",
|
|
@@ -100,24 +101,49 @@
|
|
|
100
101
|
"slug": "pangram",
|
|
101
102
|
"difficulty": 1,
|
|
102
103
|
"topics": [
|
|
104
|
+
"control-flow (loops)",
|
|
105
|
+
"control-flow (if-else statements)",
|
|
106
|
+
"strings",
|
|
107
|
+
"algorithms",
|
|
108
|
+
"filtering",
|
|
109
|
+
"logic"
|
|
103
110
|
]
|
|
104
111
|
},
|
|
105
112
|
{
|
|
106
113
|
"slug": "rna-transcription",
|
|
107
114
|
"difficulty": 1,
|
|
108
115
|
"topics": [
|
|
116
|
+
"control-flow (if-else statements)",
|
|
117
|
+
"control-flow (loops)",
|
|
118
|
+
"maps",
|
|
119
|
+
"strings",
|
|
120
|
+
"logic",
|
|
121
|
+
"transforming"
|
|
109
122
|
]
|
|
110
123
|
},
|
|
111
124
|
{
|
|
112
125
|
"slug": "hamming",
|
|
113
126
|
"difficulty": 1,
|
|
114
127
|
"topics": [
|
|
128
|
+
"control-flow (if-else statements)",
|
|
129
|
+
"control-flow (loops)",
|
|
130
|
+
"sequences",
|
|
131
|
+
"sets",
|
|
132
|
+
"strings",
|
|
133
|
+
"algorithms",
|
|
134
|
+
"filtering",
|
|
135
|
+
"logic"
|
|
115
136
|
]
|
|
116
137
|
},
|
|
117
138
|
{
|
|
118
139
|
"slug": "word-count",
|
|
119
|
-
"difficulty":
|
|
140
|
+
"difficulty": 3,
|
|
120
141
|
"topics": [
|
|
142
|
+
"strings",
|
|
143
|
+
"algorithms",
|
|
144
|
+
"logic",
|
|
145
|
+
"pattern recognition",
|
|
146
|
+
"text formatting"
|
|
121
147
|
]
|
|
122
148
|
},
|
|
123
149
|
{
|
|
@@ -222,6 +248,12 @@
|
|
|
222
248
|
"topics": [
|
|
223
249
|
]
|
|
224
250
|
},
|
|
251
|
+
{
|
|
252
|
+
"slug": "flatten-array",
|
|
253
|
+
"difficulty": 1,
|
|
254
|
+
"topics": [
|
|
255
|
+
]
|
|
256
|
+
},
|
|
225
257
|
{
|
|
226
258
|
"slug": "roman-numerals",
|
|
227
259
|
"difficulty": 1,
|