Skip to content

Instantly share code, notes, and snippets.

@maxcountryman
Created January 15, 2012 02:02
Show Gist options
  • Save maxcountryman/1613894 to your computer and use it in GitHub Desktop.
Save maxcountryman/1613894 to your computer and use it in GitHub Desktop.
A "point of price" terminal simulator (expects Python 2.7.x)
'''
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