diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 48d1bde..e1ba390 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -30,10 +30,11 @@ jobs: if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Test with pytest run: | - pytest --continue-on-collection-errors + git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/* + git diff origin/main HEAD --name-only -- practice | xargs dirname | sort | uniq | xargs pytest - name: Lint with flake8 run: | # stop the build if there are Python syntax errors or undefined names flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics \ No newline at end of file diff --git a/practice/bowling/bowling.py b/practice/bowling/bowling.py index de2dbb0..c038cd5 100644 --- a/practice/bowling/bowling.py +++ b/practice/bowling/bowling.py @@ -1,9 +1,50 @@ class BowlingGame: + def __init__(self): - pass + self.rolls = [] + self.current_roll = 0 def roll(self, pins): - pass + if pins < 0 or pins > 10: + raise ValueError('Invalid roll') + + if self.current_roll > 20 or (self.current_roll == 20 and not self.is_last_frame_strike_or_spare()): + raise Exception('Game already has 10 frames') + + self.rolls.append(pins) + self.current_roll += 1 def score(self): + score = 0 + roll_index = 0 + + for frame in range(10): + if self.is_strike(roll_index): + score += 10 + self.strike_bonus(roll_index) + roll_index += 1 + elif self.is_spare(roll_index): + score += 10 + self.spare_bonus(roll_index) + roll_index += 2 + else: + score += self.rolls[roll_index] + self.rolls[roll_index + 1] + roll_index += 2 + + return score + + def is_strike(self, roll_index): + return self.rolls[roll_index] == 10 + + def is_spare(self, roll_index): + return self.rolls[roll_index] + self.rolls[roll_index + 1] == 10 + + def strike_bonus(self, roll_index): + return self.rolls[roll_index + 1] + self.rolls[roll_index + 2] + + def spare_bonus(self, roll_index): + return self.rolls[roll_index + 2] + + def is_last_frame_strike_or_spare(self): + return self.is_strike(18) or self.is_spare(18) + + pass