diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..cc67606f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "python.linting.pylintEnabled": true, + "python.linting.enabled": true +} \ No newline at end of file diff --git a/Tests/__init__.py b/Tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Tests/__pycache__/__init__.cpython-39.pyc b/Tests/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 00000000..aa2521f1 Binary files /dev/null and b/Tests/__pycache__/__init__.cpython-39.pyc differ diff --git a/Tests/__pycache__/test_cash_register.cpython-39-pytest-6.2.4.pyc b/Tests/__pycache__/test_cash_register.cpython-39-pytest-6.2.4.pyc new file mode 100644 index 00000000..bf38d538 Binary files /dev/null and b/Tests/__pycache__/test_cash_register.cpython-39-pytest-6.2.4.pyc differ diff --git a/Tests/test_cash_register.py b/Tests/test_cash_register.py new file mode 100644 index 00000000..7a1ab993 --- /dev/null +++ b/Tests/test_cash_register.py @@ -0,0 +1,47 @@ +from cash_register import ChangeCalculator +import pytest + +change = ChangeCalculator() + +#----- INITIAL TESTS FOR STRING CONVERSION TO TUPLE-----# +def test_accepts_input_00(): + money = change.convert_to_float("2.12,3.00") + assert money == (2.12, 3.00) + +def test_accepts_input_01(): + money = change.convert_to_float("1.97,2.00") + assert money == (1.97, 2.00) + +def test_accepts_input_02(): + money = change.convert_to_float("3.33,5.00") + assert money == (3.33, 5.00) + +#------BASIC CALCULATIONS-------------------------------# +def test_amt_less_than_total(): + assert change.change_calculate(4.00, 2.00) == False + +def test_subtraction(): + assert change.change_calculate(2.13, 3.00) == "3 quarters, 1 dime, 2 pennies" + +@pytest.mark.skip(reason="This test will fail due to random value") +def test_dollar_amt(): + money = change.change_calculate(2.00, 5.00) + assert money == "3 dollars, " + +#------TEST FOR ACCURATE DENOMINATION AMOUNTS-----------# +def test_quarter_amt(): + money_back = change.change_calculate(2.25, 3.00) + assert money_back == "3 quarters, " + +def test_coins_amt_00(): + money_back = change.change_calculate(2.13, 3.00) + assert money_back == "3 quarters, 1 dime, 2 pennies" + +def test_coins_amt_01(): + money_back = change.change_calculate(1.97, 2.00) + assert money_back == "3 pennies" + +@pytest.mark.skip(reason="This test will fail due to random value") +def test_coins_amt_02(): + money_back = change.change_calculate(3.33, 5.00) + assert money_back == "1 dollar, 2 quarters, 1 dime, 1 nickel, 2 pennies" \ No newline at end of file diff --git a/__pycache__/cash_register.cpython-39.pyc b/__pycache__/cash_register.cpython-39.pyc new file mode 100644 index 00000000..2094dfd1 Binary files /dev/null and b/__pycache__/cash_register.cpython-39.pyc differ diff --git a/cash_reg_ex.py b/cash_reg_ex.py new file mode 100644 index 00000000..e9355373 --- /dev/null +++ b/cash_reg_ex.py @@ -0,0 +1,8 @@ +from cash_register import ChangeCalculator + +c = ChangeCalculator() + +print("Please enter total and amount given") + +total, amt_given = c.convert_to_float(input()) +calc = c.change_calculate(total, amt_given) diff --git a/cash_register.py b/cash_register.py new file mode 100644 index 00000000..4fd1ad39 --- /dev/null +++ b/cash_register.py @@ -0,0 +1,225 @@ +class ChangeCalculator(): + + # converting a str flat file into a list + def convert_to_float(self, currency): + + new_curr = currency.split(",") + total = float(new_curr[0]) + amt_given = float(new_curr[1]) + + return total, amt_given + + def change_calculate(self, total_01, amt_given_01): + + # ***UPDATE*** + # Actually accessing convert_to_float() and returning + # its value to perform operations in this function + + total_01 = int(total_01 * 100) # multiply both by 100 to avoid + amt_given_01 = int(amt_given_01 * 100) # floating point arithmetic + + # returns last to digits to check for divisibility + total_div_3 = self.get_last_digits(total_01) + + if amt_given_01 < total_01: + return False + elif total_div_3 % 3 == 0: + # runs random function + total_change = amt_given_01 - total_01 + change = self.random_denominations(total_change / 100) + return change + else: + # runs regular conversion function + total_change = amt_given_01 - total_01 + change = self.change_denominations(total_change / 100) + return change + + + + def get_last_digits(self, num): + # indexes the last two digits of a cast sting then cast again as an integer + total_coins = int(str(num)[-2:]) + # **NOTES** total_coins = abs(num) % 100 does not work for random + return total_coins + + def change_denominations(self, total_change): + + # mulitplied by 100 again for float arithmetic + total_change = total_change * 100 + + # this dictionary stores the amount of each denomination + denom_dict = { + "dollar_amt": 0, + "quarter_amt": 0, + "dime_amt": 0, + "nickel_amt": 0, + "penny_amt": 0 + } + + # accessing each dict key and updated total change per function call + denom_dict["dollar_amt"], total_change = self.denom_conversion(total_change, 100) + denom_dict["quarter_amt"], total_change = self.denom_conversion(total_change, 25) + denom_dict["dime_amt"], total_change = self.denom_conversion(total_change, 10) + denom_dict["nickel_amt"], total_change = self.denom_conversion(total_change, 5) + denom_dict["penny_amt"], total_change = self.denom_conversion(total_change, 1) + + # variables to access value of dictionary + dollar_amt = denom_dict["dollar_amt"] + quarter_amt = denom_dict["quarter_amt"] + dime_amt = denom_dict["dime_amt"] + nickel_amt = denom_dict["nickel_amt"] + penny_amt = denom_dict["penny_amt"] + + denoms = "" + + # conditional statements establishing plurality + if dollar_amt < 1: + pass + elif dollar_amt > 1: + denoms += f"{dollar_amt} dollars, " + else: + denoms += f"{dollar_amt} dollar, " + + if quarter_amt < 1: + pass + elif quarter_amt > 1: + denoms += f"{quarter_amt} quarters, " + else: + denoms += f"{quarter_amt} quarter, " + + if dime_amt < 1: + pass + elif dime_amt > 1: + denoms += f"{dime_amt} dimes, " + else: + denoms += f"{dime_amt} dime, " + + if nickel_amt < 1: + pass + elif nickel_amt > 1: + denoms += f"{nickel_amt} nickels, " + else: + denoms += f"{nickel_amt} nickel, " + + if penny_amt < 1: + pass + elif penny_amt > 1: + denoms += f"{penny_amt} pennies" + else: + denoms += f"{penny_amt} penny" + + print(denoms) + return denoms + + + def denom_conversion(self, total_change, change): + + # looping thru each denomination returning the denom amount and updated total + # where total_change is the remaining change value and change is an int for + # each denomination value (i.e., if change = 100, that's a dollar) + denom_amt = 0 + while total_change >= change: + if total_change >= change: + total_change -= change + denom_amt += 1 + + return denom_amt, total_change + + def rand_denom_conversion(self, total_change, change, denom_amt): + + # similar to denom_conversion() function but instead of + # looping thru to get maximum amount of each denom, it + # only returns one at a time. + # denom_amt value is updated and returned with each call + if total_change >= change: + total_change -= change + denom_amt += 1 + + return denom_amt, total_change + + def random_denominations(self, total_change): + import random + + # similar to denom_conversion() + # mult for FP arithmetic + total_change = total_change * 100 + + # dictionary initialized + DENOMS = { + "dollar_amt": 0, + "quarter_amt": 0, + "dime_amt": 0, + "nickel_amt": 0, + "penny_amt": 0 + } + + + # elements in rand_list reference which function to call + # similar to a dice roll. each call returns denom amount + # and updated total same as denom_conversion() + rand_list = [1, 2, 3, 4, 5] + + while total_change > 0: + random_choice = random.choice(rand_list) + if random_choice == 1: + DENOMS["dollar_amt"], total_change = self.rand_denom_conversion(total_change, 100, DENOMS["dollar_amt"]) + + if random_choice == 2: + DENOMS["quarter_amt"], total_change = self.rand_denom_conversion(total_change, 25, DENOMS["quarter_amt"]) + + if random_choice == 3: + DENOMS["dime_amt"], total_change = self.rand_denom_conversion(total_change, 10, DENOMS["dime_amt"]) + + if random_choice == 4: + DENOMS["nickel_amt"], total_change = self.rand_denom_conversion(total_change, 5, DENOMS["nickel_amt"]) + + if random_choice == 5: + DENOMS["penny_amt"], total_change = self.rand_denom_conversion(total_change, 1, DENOMS["penny_amt"]) + + # same setup as in denom_conversions() function + dollar_amt = DENOMS["dollar_amt"] + quarter_amt = DENOMS["quarter_amt"] + dime_amt = DENOMS["dime_amt"] + nickel_amt = DENOMS["nickel_amt"] + penny_amt = DENOMS["penny_amt"] + + + denoms = "" + # establishing plurality + if dollar_amt < 1: + pass + elif dollar_amt > 1: + denoms += f"{dollar_amt} dollars, " + else: + denoms += f"{dollar_amt} dollar, " + + if quarter_amt < 1: + pass + elif quarter_amt > 1: + denoms += f"{quarter_amt} quarters, " + else: + denoms += f"{quarter_amt} quarter, " + + if dime_amt < 1: + pass + elif dime_amt > 1: + denoms += f"{dime_amt} dimes, " + else: + denoms += f"{dime_amt} dime, " + + if nickel_amt < 1: + pass + elif nickel_amt > 1: + denoms += f"{nickel_amt} nickels, " + else: + denoms += f"{nickel_amt} nickel, " + + if penny_amt < 1: + pass + elif penny_amt > 1: + denoms += f"{penny_amt} pennies" + else: + denoms += f"{penny_amt} penny" + + print(denoms) + return denoms \ No newline at end of file