Created
January 15, 2012 02:02
-
-
Save maxcountryman/1613894 to your computer and use it in GitHub Desktop.
A "point of price" terminal simulator (expects Python 2.7.x)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
terminal | |
-------- | |
A simple checkout simulator. | |
''' | |
class Terminal(object): | |
'''A "point of sale" terminal object.''' | |
def __init__(self): | |
self.total = '$0.00' | |
self.scanned_items = {} | |
def setPricing(self, pricing_table): | |
'''Sets the pricing table on the object. | |
:param pricing_table: A dictionary containing item, pricing pairs. | |
Price values should be lists where the 0th element is the base price | |
and other elements are the discount price. | |
''' | |
self.pricing_table = pricing_table | |
def scan(self, item): | |
'''This function is used to calculate the total of a given set of | |
items, adjusting price for quantitative discounts. | |
Here we "scan" an item by adding it to a dictionary of such items | |
containing the item name and its quantity. If the item key is not | |
found, we create it and intialize it to 1. Otherwise we increment the | |
item count, i.e. the value. | |
Next we loop over the aforementioned dictionary, extracting the key | |
and its respective value. The key is mapped against a pricing table | |
which gives us a list of prices; either the base price only or base | |
price and discount price. | |
Using this table we are then able to increment our running total. In | |
the case of an item which only has a base price we increment by the | |
product of the price and the quantity. | |
If the item also has a discount price then we can apply this by | |
incrementing the running total by dividing quantity by the required | |
qualifying discount quantity and then mulitplying the result by the | |
discount price. | |
To complete the application we must also determine the remainder of | |
the above division and then multiply that remainder by the price. This | |
gives us the correct adjusted price. | |
Finally we update `total`, formatting it as a string and prefixing it | |
with the dollar sign. | |
:param item: A string representing the key to be matched in the | |
pricing table as set by :class:`setPricing`. | |
''' | |
item_quantity = self.scanned_items.get(item) | |
if not item_quantity: | |
self.scanned_items[item] = 1 | |
else: | |
self.scanned_items[item] += 1 | |
running_total = 0.0 | |
for scanned_item, quantity in self.scanned_items.iteritems(): | |
item_pricing = self.pricing_table[scanned_item] | |
price = item_pricing[0] | |
# if the product has discount or bulk pricing, use it otherwise | |
# simply apply the base price to the running total | |
if len(item_pricing) != 1: | |
discount_quantity = item_pricing[1][0] | |
discount_price = item_pricing[1][1] | |
running_total += (quantity / discount_quantity) * discount_price | |
running_total += (quantity % discount_quantity) * price | |
else: | |
running_total += price * quantity | |
self.total = '${0:.2f}'.format(running_total) | |
def reset(self): | |
'''Resets the terminal for a fresh round.''' | |
self.total = '$0.00' | |
self.scanned_items = {} | |
if __name__ == '__main__': | |
terminal = Terminal() | |
terminal.setPricing({'A': [2.0, (4, 7.0)], | |
'B': [12.0], | |
'C': [1.25, (6, 6.0)], | |
'D': [.15]}) | |
# test the first set | |
lane_one = ['A', 'B', 'C', 'D', 'A', 'B', 'A', 'A'] | |
map(terminal.scan, lane_one) | |
print terminal.total | |
assert terminal.total == '$32.40' | |
# test the second set | |
terminal.reset() | |
lane_two = ['C', 'C', 'C', 'C', 'C', 'C', 'C'] | |
map(terminal.scan, lane_two) | |
print terminal.total | |
assert terminal.total == '$7.25' | |
# test the third set | |
terminal.reset() | |
lane_three = ['A', 'B', 'C', 'D'] | |
map(terminal.scan, lane_three) | |
print terminal.total | |
assert terminal.total == '$15.40' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment