'From Squeakland 3.8-05 of 7 September 2005 [latest update: #527] on 23 November 2006 at 9:29:04 am'! LinkedList subclass: #BowlingScore instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'BowlingScore-LinkedList'! Link subclass: #BowlingScoreFrame instanceVariableNames: 'throws' classVariableNames: '' poolDictionaries: '' category: 'BowlingScore-LinkedList'! BowlingScoreFrame subclass: #BowlingScoreFinalFrame instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'BowlingScore-LinkedList'! TestCase subclass: #BowlingScoreTest instanceVariableNames: 'game' classVariableNames: '' poolDictionaries: '' category: 'BowlingScore-LinkedList-Test'! !BowlingScore methodsFor: 'adding' stamp: 'sumim 11/23/2006 09:27'! add: nPins (self isEmpty or: [self lastFrame isOver]) ifTrue: [ self size = 10 ifTrue: [^ self "error: 'the game is already over!!'"]. super add: (self size < 9 ifTrue: [BowlingScoreFrame] ifFalse: [BowlingScoreFinalFrame]) new]. ^ self lastFrame add: nPins! ! !BowlingScore methodsFor: 'accessing' stamp: 'sumim 11/23/2006 00:45'! frameScoreAt: n ^ (self first: n) inject: 0 into: [:score :frame | score + (frame points ifNil: [^ nil])]! ! !BowlingScore methodsFor: 'accessing' stamp: 'sumim 11/23/2006 09:24'! lastFrame ^ lastLink! ! !BowlingScore methodsFor: 'accessing' stamp: 'sumim 11/23/2006 00:45'! score ^ self inject: 0 into: [:score :frame | score + (frame points ifNil: [^ score])]! ! !BowlingScoreFrame methodsFor: 'accessing' stamp: 'sumim 11/23/2006 09:26'! nextFrame ^ nextLink! ! !BowlingScoreFrame methodsFor: 'accessing' stamp: 'sumim 11/22/2006 23:53'! throws ^ throws! ! !BowlingScoreFrame methodsFor: 'adding' stamp: 'sumim 11/22/2006 23:55'! add: nPins throws add: nPins! ! !BowlingScoreFrame methodsFor: 'initializing' stamp: 'sumim 11/22/2006 23:56'! initialize throws _ OrderedCollection new! ! !BowlingScoreFrame methodsFor: 'printing' stamp: 'sumim 11/23/2006 00:07'! printOn: stream stream nextPut: $(. throws do: [:each | stream nextPutAll: each asString] separatedBy: [stream space]. stream nextPut: $)! ! !BowlingScoreFrame methodsFor: 'testing' stamp: 'sumim 11/23/2006 00:39'! isEmptyOrNil ^ throws isEmpty! ! !BowlingScoreFrame methodsFor: 'testing' stamp: 'sumim 11/22/2006 23:50'! isOver ^ self isStrike or: [throws size = 2]! ! !BowlingScoreFrame methodsFor: 'testing' stamp: 'sumim 11/23/2006 00:35'! isSpare ^ throws size = 2 and: [throws sum = 10]! ! !BowlingScoreFrame methodsFor: 'testing' stamp: 'sumim 11/22/2006 23:57'! isStrike ^ throws notEmpty and: [throws first = 10]! ! !BowlingScoreFrame methodsFor: 'private' stamp: 'sumim 11/23/2006 00:28'! points throws isEmpty ifTrue: [^ nil]. self isStrike ifTrue: [^ self pointsWithNextTwoThrows]. self isSpare ifTrue: [^ self pointsWithNextThrow]. ^ throws sum! ! !BowlingScoreFrame methodsFor: 'private' stamp: 'sumim 11/23/2006 09:27'! pointsWithNextThrow self nextFrame isEmptyOrNil ifTrue: [^ nil]. ^ self nextFrame throws first + 10! ! !BowlingScoreFrame methodsFor: 'private' stamp: 'sumim 11/23/2006 09:27'! pointsWithNextTwoThrows self nextFrame isEmptyOrNil ifTrue: [^ nil]. self nextFrame throws size = 1 ifTrue: [^ self nextFrame pointsWithNextThrow ifNotNilDo: [:pt | pt + 10]]. ^ (self nextFrame throws first: 2) sum + 10! ! !BowlingScoreFinalFrame methodsFor: 'testing' stamp: 'sumim 11/22/2006 23:52'! isOver ^ throws size = 3 or: [throws size = 2 and: [throws sum < 10]]! ! !BowlingScoreFinalFrame methodsFor: 'private' stamp: 'sumim 11/23/2006 00:56'! pointsWithNextThrow throws size < 3 ifTrue: [^ nil]. ^ throws sum! ! !BowlingScoreFinalFrame methodsFor: 'private' stamp: 'sumim 11/23/2006 00:54'! pointsWithNextTwoThrows throws size < 3 ifTrue: [^ nil]. ^ throws sum! ! !BowlingScoreTest methodsFor: 'tests' stamp: 'sumim 11/23/2006 00:25'! test01 game add: 3. self assert: game last throws asArray = #(3). game add: 3. self assert: game last throws asArray = #(3 3). game add: 3. self assert: game size = 2. self assert: game last throws asArray = #(3). game add: 3. game add: 10. game add: 3. self assert: game size = 4. self assert: game last throws asArray = #(3). 13 timesRepeat: [game add: 3]. self assert: game size = 10. self assert: (game last isKindOf: BowlingScoreFinalFrame). self assert: game last throws asArray = #(3 3)! ! !BowlingScoreTest methodsFor: 'tests' stamp: 'sumim 11/23/2006 00:46'! test02 game add: 3; add: 3. self assert: (game frameScoreAt: 1) = 6. game add: 3; add: 7. self assert: (game frameScoreAt: 2) isNil. game add: 3. self assert: (game frameScoreAt: 2) = 19. game add: 3. self assert: game score = 25! ! !BowlingScoreTest methodsFor: 'tests' stamp: 'sumim 11/23/2006 00:52'! test03 game addAll: #(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0). self assert: game score = 0! ! !BowlingScoreTest methodsFor: 'tests' stamp: 'sumim 11/23/2006 00:52'! test04 12 timesRepeat: [game add: 10]. self assert: game score = 300! ! !BowlingScoreTest methodsFor: 'tests' stamp: 'sumim 11/23/2006 00:51'! test05 game addAll: #(10 5 5 0 0). self assert: game score = 30! ! !BowlingScoreTest methodsFor: 'tests' stamp: 'sumim 11/23/2006 01:04'! test06 20 timesRepeat: [game add: 3]. self assert: game score = 60! ! !BowlingScoreTest methodsFor: 'tests' stamp: 'sumim 11/23/2006 01:04'! test07 game addAll: #(0 0 10 8 2 10 10 10 5 3 8 2 10 10 10 10). self assert: game score = 201! ! !BowlingScoreTest methodsFor: 'tests' stamp: 'sumim 11/23/2006 01:06'! test08 game addAll: #(1 4 4 5 6 4 5 5 10 0 1 7 3 6 4 10 2 8 6). self assert: game score = 133. #(5 14 29 49 60 61 77 97 117) doWithIndex: [:score :idx | self assert: (game frameScoreAt: idx) = score]! ! !BowlingScoreTest methodsFor: 'running' stamp: 'sumim 11/22/2006 23:28'! setUp game _ BowlingScore new! !