I am a student in Germany, more specifically in Bavaria, and here we use to have a so-called "Kirwa", an event for celebrating the establishment of the local church - technically that's the reason. Today it is more about drinking, but that's off-topic. It is common to sell "Bratwürste" or sausages on these events. Since I am a student and I need the money, I often help with the sale.
Normal cashiers calculate the price and the return money in their head, but since I am neither good nor fast with Math, I decided to open a python interpreter I had installed on my mobile and made this program. The main aim is to be able to calculate the price fast and have all of the necessary information displayed.
For review: I come from a java/c#/c++ background and I know I can't really treat python the same way, but with the limited knowledge of python I had, I tried my best. If there are little features in the language I can use or there is a best practice, tell me about it. I would mainly like to hear about the clarity, documentation, and implementation of my code, especially for the calc_money_sizes
function.
The code may be a bit "over-engineered" this is due to some long periods where I had nothing to do and got bored. But still don't hold back on criticism I can take it :)
__author__ = "Patrick Hollweck"
import collections
class Money:
""" A class handling Interaction with money """
SIZES = [0.01, 0.020, 0.050, 0.10, 0.20, 0.5, 1.0, 2.0, 5.0, 10.0, 20.0, 50.0, 100.0, 200.0, 500.0]
def calc_money_sizes(money):
result = collections.OrderedDict()
if money < 0:
return result
for size in reversed(Money.SIZES):
while True:
outcome = money - size
if outcome > -0.001:
if size in result:
result[size] += 1
else:
result[size] = 1
money = outcome
else:
break
return result
class PriceCalculator:
""" Class to calculate all sort of bratwurst Stuff! """
SAUSAGE_PRICE = 1.10
BREAD_PRICE = 0.30
def calc_price(sausage_count, bread_count):
sausage_price = sausage_count * PriceCalculator.SAUSAGE_PRICE
bread_price = bread_count * PriceCalculator.BREAD_PRICE
return sausage_price + bread_price
def calc_return_money(price, given):
return given - price
class Console:
""" Console helpers """
class input:
""" Input helpers """
def safe_int(message, allowNoInput = False):
return Console.input.__safe_base(message, allowNoInput, int)
def safe_float(message, allowNoInput = False):
return Console.input.__safe_base(message, allowNoInput, float)
def __safe_base(message, allowNoInput, typefunc):
while True:
try:
result = input(message)
if result == "" and allowNoInput:
return None
elif result == "clear":
Console.Out.clear()
continue
else:
return typefunc(result)
except Exception:
print("Invalid input! (" + str(typefunc) + ") expected")
continue
class format:
""" Formating functions for the console """
def float(number):
return "{0:.2f}".format(number)
def str_normalize_lenght(string, longest):
if len(string) < longest:
missing_chars = longest - len(string)
return string + " " * abs(missing_chars)
else:
return string
class pretty_print:
""" Use this class for pretty printing commons types """
def float(number):
print(Console.format.float(number))
def dict(dictionary):
if len(dictionary) is 0:
print("NOT POSSIBLE")
return
for key in dictionary.keys():
print(str(Console.format.str_normalize_lenght(Console.format.float(key), 6)) + " -> " + str(dictionary[key]))
class output:
""" Output helpers """
def header(text):
print("\n--- " + text + " ---\n")
def clear():
print("\n" * 50)
if __name__ == "__main__":
Console.output.clear()
while True:
# print header
print("Bratwurst price Calculator!\n")
# Get input
sausage_count = Console.input.safe_int("Sausages Count: ")
bread_count = Console.input.safe_int("Bread Count: ")
# Calculate total price and output
price = PriceCalculator.calc_price(sausage_count, bread_count)
Console.output.header("TOTAL PRICE")
Console.pretty_print.float(price)
# Calculate return money
given = Console.input.safe_float("\nGiven money: ", allowNoInput = True)
# Optional skip return money calculation when reqested
if given == None:
Console.output.clear()
continue
return_money = PriceCalculator.calc_return_money(price, given)
Console.output.header("RETURN MONEY")
# Return money amount
if return_money < 0:
print("WARNING: Not enought money!")
Console.pretty_print.float(return_money)
# Return money format
Console.output.header("RETURN MONEY FORMAT")
Console.pretty_print.dict(Money.calc_money_sizes(return_money))
# Cleanup
input("\n... Continue ...")
Console.output.clear();