diff --git a/13_Bounce/python/bounce.py b/13_Bounce/python/bounce.py index fc11c204..f36acc94 100644 --- a/13_Bounce/python/bounce.py +++ b/13_Bounce/python/bounce.py @@ -6,7 +6,7 @@ A physics simulation Ported by Dave LeCompte """ -from typing import Tuple +from typing import Tuple, List PAGE_WIDTH = 64 @@ -51,8 +51,8 @@ def print_at_tab(line: str, tab: int, s: str) -> str: return line -def run_simulation(delta_t, v0, coeff_rest) -> None: - bounce_time = [0] * 20 # time of each bounce +def run_simulation(delta_t: float, v0: float, coeff_rest: float) -> None: + bounce_time: List[float] = [0] * 20 # time of each bounce print("FEET") print() @@ -67,7 +67,7 @@ def run_simulation(delta_t, v0, coeff_rest) -> None: line = "" if int(h) == h: line += str(int(h)) - total_time = 0 + total_time: float = 0 for i in range(1, sim_dur + 1): tm: float = 0 while tm <= bounce_time[i]: diff --git a/13_Bounce/python/test_bounce.py b/13_Bounce/python/test_bounce.py new file mode 100644 index 00000000..2960919d --- /dev/null +++ b/13_Bounce/python/test_bounce.py @@ -0,0 +1,72 @@ +import io + +from _pytest.monkeypatch import MonkeyPatch +from _pytest.capture import CaptureFixture + +from bounce import main + + +def test_bounce(monkeypatch: MonkeyPatch, capsys: CaptureFixture[str]) -> None: + time_increment = 0.1 + velocity = 30 + coefficient = 1 + monkeypatch.setattr( + "sys.stdin", + io.StringIO(f"{time_increment:0.1f}\n{velocity}\n{coefficient}\n"), + ) + main() + actual = capsys.readouterr().out + expected = """ BOUNCE + CREATIVE COMPUTING MORRISTOWN, NEW JERSEY + + + +THIS SIMULATION LETS YOU SPECIFY THE INITIAL VELOCITY +OF A BALL THROWN STRAIGHT UP, AND THE COEFFICIENT OF +ELASTICITY OF THE BALL. PLEASE USE A DECIMAL FRACTION +COEFFICIENCY (LESS THAN 1). + +YOU ALSO SPECIFY THE TIME INCREMENT TO BE USED IN +'STROBING' THE BALL'S FLIGHT (TRY .1 INITIALLY). + +TIME INCREMENT (SEC)? +VELOCITY (FPS)? +COEFFICIENT? +FEET + +14 000 000 000 + 0 0 0 +13 0 0 0 0 0 0 + +12 0 0 0 0 0 0 + +11 0 0 0 + 0 0 0 +10 + 0 0 0 +9 0 0 0 + +8 + 0 0 0 +7 0 0 0 + +6 + 0 0 0 +5 0 0 0 + +4 + +3 0 0 0 + +2 0 0 0 + +1 + +00 0 0 +................................................................... + 0 1 2 3 4 5 6 + + SECONDS + +""" # noqa: W291 + assert actual.split("\n") == expected.split("\n") diff --git a/14_Bowling/python/bowling.py b/14_Bowling/python/bowling.py index d4e66ab4..f4a566aa 100644 --- a/14_Bowling/python/bowling.py +++ b/14_Bowling/python/bowling.py @@ -1,14 +1,15 @@ import random +from typing import List -def simulate_roll(pins) -> None: +def simulate_roll(pins: List[int]) -> None: for _ in range(20): x = random.randint(0, 14) if x < len(pins): pins[x] = 1 -def calculate_score(rolls) -> int: +def calculate_score(rolls: List[int]) -> int: score = 0 frame = 1 b = 1 @@ -32,11 +33,11 @@ def calculate_score(rolls) -> int: class Player: - def __init__(self, name): + def __init__(self, name: str): self.name = name - self.rolls = [] + self.rolls: List[int] = [] - def play_frame(self, frame): + def play_frame(self, frame: int) -> None: extra = 0 prev_score = 0 pins = [0] * 10 # reset the pins @@ -73,10 +74,10 @@ class Player: score = sum(pins) self.rolls.append(score) - def __str__(self): + def __str__(self) -> str: return f"{self.name}: {self.rolls}, total:{calculate_score(self.rolls)}" - def show(self, pins): + def show(self, pins: List[int]) -> None: pins_iter = iter(pins) print() for row in range(4): @@ -87,14 +88,14 @@ class Player: print() -def centreText(text, width): +def centre_text(text: str, width: int) -> str: t = len(text) return (" " * ((width - t) // 2)) + text def main() -> None: - print(centreText("Bowl", 80)) - print(centreText("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY", 80)) + print(centre_text("Bowl", 80)) + print(centre_text("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY", 80)) print() print("WELCOME TO THE ALLEY.") print("BRING YOUR FRIENDS.") diff --git a/14_Bowling/python/test_bowling.py b/14_Bowling/python/test_bowling.py new file mode 100644 index 00000000..04bb7cf6 --- /dev/null +++ b/14_Bowling/python/test_bowling.py @@ -0,0 +1,273 @@ +import io +from typing import List + +from _pytest.capture import CaptureFixture +from _pytest.monkeypatch import MonkeyPatch + +from bowling import main + + +def test_bowling_strikes(monkeypatch: MonkeyPatch, capsys: CaptureFixture[str]) -> None: + def perfect_roll(pins: List[int]) -> None: + for i in range(20): + x = i + if x < len(pins): + pins[x] = 1 + + monkeypatch.setattr("bowling.simulate_roll", perfect_roll) + + instructions1 = "Y" + players1 = 1 + name1 = "Martin" + another_game1 = "Y" + + instructions2 = "N" + players2 = 2 + name21 = "Anna" + name22 = "Bob" + another_game2 = "N" + monkeypatch.setattr( + "sys.stdin", + io.StringIO( + f"{instructions1}\n{players1}\n{name1}\n{another_game1}\n" + f"{instructions2}\n{players2}\n{name21}\n{name22}\n{another_game2}" + ), + ) + main() + actual = capsys.readouterr().out + expected = """ Bowl + CREATIVE COMPUTING MORRISTOWN, NEW JERSEY + +WELCOME TO THE ALLEY. +BRING YOUR FRIENDS. +OKAY LET'S FIRST GET ACQUAINTED. + +THE INSTRUCTIONS (Y/N)? THE GAME OF BOWLING TAKES MIND AND SKILL. DURING THE GAME +THE COMPUTER WILL KEEP SCORE. YOU MAY COMPETE WITH +OTHER PLAYERS[UP TO FOUR]. YOU WILL BE PLAYING TEN FRAMES. +ON THE PIN DIAGRAM 'O' MEANS THE PIN IS DOWN...'+' MEANS THE +PIN IS STANDING. AFTER THE GAME THE COMPUTER WILL SHOW YOUR +SCORES. +FIRST OF ALL...HOW MANY ARE PLAYING? +VERY GOOD... +Enter name for player 1: +O O O O + O O O + O O + O +10 for Martin +STRIKE!!! + +O O O O + O O O + O O + O +10 for Martin +STRIKE!!! + +O O O O + O O O + O O + O +10 for Martin +STRIKE!!! + +O O O O + O O O + O O + O +10 for Martin +STRIKE!!! + +O O O O + O O O + O O + O +10 for Martin +STRIKE!!! + +O O O O + O O O + O O + O +10 for Martin +STRIKE!!! + +O O O O + O O O + O O + O +10 for Martin +STRIKE!!! + +O O O O + O O O + O O + O +10 for Martin +STRIKE!!! + +O O O O + O O O + O O + O +10 for Martin +STRIKE!!! + +O O O O + O O O + O O + O +10 for Martin +STRIKE!!! +Extra rolls for Martin +Martin: [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10], total:300 +DO YOU WANT ANOTHER GAME? +THE INSTRUCTIONS (Y/N)? FIRST OF ALL...HOW MANY ARE PLAYING? +VERY GOOD... +Enter name for player 1: Enter name for player 2: +O O O O + O O O + O O + O +10 for Anna +STRIKE!!! + +O O O O + O O O + O O + O +10 for Bob +STRIKE!!! + +O O O O + O O O + O O + O +10 for Anna +STRIKE!!! + +O O O O + O O O + O O + O +10 for Bob +STRIKE!!! + +O O O O + O O O + O O + O +10 for Anna +STRIKE!!! + +O O O O + O O O + O O + O +10 for Bob +STRIKE!!! + +O O O O + O O O + O O + O +10 for Anna +STRIKE!!! + +O O O O + O O O + O O + O +10 for Bob +STRIKE!!! + +O O O O + O O O + O O + O +10 for Anna +STRIKE!!! + +O O O O + O O O + O O + O +10 for Bob +STRIKE!!! + +O O O O + O O O + O O + O +10 for Anna +STRIKE!!! + +O O O O + O O O + O O + O +10 for Bob +STRIKE!!! + +O O O O + O O O + O O + O +10 for Anna +STRIKE!!! + +O O O O + O O O + O O + O +10 for Bob +STRIKE!!! + +O O O O + O O O + O O + O +10 for Anna +STRIKE!!! + +O O O O + O O O + O O + O +10 for Bob +STRIKE!!! + +O O O O + O O O + O O + O +10 for Anna +STRIKE!!! + +O O O O + O O O + O O + O +10 for Bob +STRIKE!!! + +O O O O + O O O + O O + O +10 for Anna +STRIKE!!! +Extra rolls for Anna + +O O O O + O O O + O O + O +10 for Bob +STRIKE!!! +Extra rolls for Bob +Anna: [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10], total:300 +Bob: [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10], total:300 +DO YOU WANT ANOTHER GAME? """ # noqa: W291 + assert actual.split("\n") == expected.split("\n")