Wednesday 29 July 2015

Electronic Point of Sale


Since I was getting bored with strings and the basics. I decided to take a fun little project. The challenge is to write a program that works like an electronic point of sale. In simpler terms a cash register.

The code gets a little messy because I was getting tired and frustrated and I'm not a programmer of any level of skill. Although I have Python 3.4 installed on my PC. Python 2.7 is used by default. Which it turns out is terrible at handling unicode characters. All I wanted it to print was the £ sign in a raw_input() prompt. The answer was to explicitly use Python 3.x.

With the unicode problem sorted and the program re-factored for Python 3.x I decided to call it a day with what I have for now. Back to basics again I think.


  • The program assumes a terminal with of 80 columns. Which used to be the norm.
  • The database of goods is a simple dictionary. Which actually works quite well for this application.
  • To select an item from the inventory simply type it in.
  • Only one item can be selected at a time. But you can allow the program to loop several times to build up a list of items.
  • An item can appear more than once in your list.
  • When you select "P" to pay. The program will ask how much you are paying and then calculate your change. If you don't give enough, you'll be told to come back when you can pay.
  • The program will pause for a few seconds to allow you to read the receipt. And then it moves on to the next customer.
  • Press "Q" to quit.


#!/usr/bin/env python3

# Project       : Electronic Point of Sale
# Author        : Kevin Lynch
# Created      : 29.07.2015

# Brief: Create a program that will hold a database of goods matched against
#        their prices which can then be used to tally up the cost of a shoppers
#        order.

# Function definitions.
def wait(t):
        for i in range(0,t):
                i = i + 0
                
def orderScreen(s): # Show goods for sale with prices.
        welcome = " Welcome to Python General Stores "
        instruct = "[P = Pay] [Q = Quit] | Please select an item."
        print("{:*^80}".format(welcome))
        
        for key in s.keys():
                print(u"{: >39} \xA3{: <39.2f}".format(key,s[key]))
                
        print("{:*^80}".format(""))
        print("{: ^80}".format(instruct))
        print("{:*^80}".format(""))

def acceptPayment(o,s):
        import time
        header = " Sale "
        prompt = u"{: >40}\xA3".format("Amount Given: ")
        total = 0.00
        given = 0.00
        change = 0.00
        
        for i in range(0,len(o)): # Calculate total due.
                for key in s.keys():
                        if o[i] == key:
                                total = total + s[key]
        
        print("{:*^80}".format(header)) # Print order and amount due.
        
        for i in range(0,len(o)):
                print(u"{: >39} \xA3{: <39.2f}".format(o[i],s[o[i]]))
                
        print(u"{: >40}\xA3{: <39.2f}".format("Amount Due: ",total))
        given = float(input(prompt)) # Amount given.
        if given >= total: # Calculate change due.
                change = given - total
                print(u"{: >40}\xA3{: <39.2f}".format("Change Due: ",change))
        else:
                print("{: ^80}".format("Please come back when you can pay."))
        time.sleep(3)

def takeOrder(s): # Get the customers order.
        kbd = ""
        order = []
        while str.upper(kbd) != "P": # Loop until customer decides to pay.
                if str.upper(kbd) == "Q": # Break loop to quit.
                        break 
                orderScreen(stock)
                kbd = input("::")

                for key in s.keys():
                        if key == str.capitalize(kbd):
                                order.append(str.capitalize(kbd))
                        
        if str.upper(kbd) == "P":
                acceptPayment(order,stock) # Call acceptPayment
                
        return kbd # Return to main program.

# Global variables.
stock = {"Apple":0.50,"Banana":0.50,"Milk":1.00,"Bread":1.50,"Bacon":5.60}

# Main Program
kbd = ""
while str.upper(kbd) != "Q":
        kbd = takeOrder(stock)

Tuesday 28 July 2015

Arithmetic Operators

#!/usr/bin/env python

# Like most languages Python supports some basic arethmetic operators.
# + Addition
# - Subtration
# * Multiplication
# / Division
# // Explicite "floor/integer division"

# % Calculates the remainder of a division.
# ** Calculates powers
# () Brackets are also supported for grouping. Think BODMAS theory.

number = 0 # Set number to 0.
print number

number = number + 10 # number is now 10.
print number

number = number - 3 # number is now 7.
print number

number = number * 3 # number is now 21.
print number

number = number / 7 # number is now 3.
print number

number = number // 2 # number is now 1.
print number

number = number % 2 # number is now 1.
print number

number = 0
number = (((((number + 10) - 3) * 3) / 7) // 2) % 2 # number is now 1.
print number

number = 0
number = number + 10 - 3 * 3 / 7 // 2 % 2 # number is now 10.
print number

number = number ** 2 # number is now 100.
print number

Functions

#!/usr/bin/env python

# Functions allow us to include code in our programs that will only run when
# explicitly called and can be reused.

# Simple function example.
def allStars(n):
        for i in range(0,n):
                print "*"

# Main Program
run = True              
while run:
        x = raw_input("How many stars should I print? ")
        if str.isdigit(x):
                allStars(int(x))
                x = raw_input("Do you want another go? Press Y or N")
                if str.upper(x) == "N":
                        run = False
        else:
                print "%s is not a number." % x

Flow Control 2: while, while-else

#!/usr/bin/env python

# Simple while loop example.
i = 0
while i != 10:
        i = i + 1
        print i
       
# while-else
while i != 10:
        i = i +1
        print i
else:
        print "We're all done here!"

Flow Control 1: for, for-else

#!/usr/bin/env python

# Simple for loop example.
for i in range(0,11):
        print "The value of i is %d." % i

# for-else example.
# This is taken directly from the Python documentation. The else statement
# looks as though it's in the wrong place. It's not. Python for loops can have
# else statements.
for n in range(2, 10):
        for x in range(2, n):
                if n % x == 0:
                        print n, 'equals', x, '*', n/x
                        break
        else:
                # loop fell through without finding a factor
                print n, 'is a prime number'

Strings 2

#!/usr/bin/env python

# Python has an unhealthy string obsession. There are many ways of converting
# and formatting strings.

A = "hello world"

# More formatting.
# https://docs.python.org/2.7/library/string.html#string-formatting
print "The first character of A is %s." % A[0] # Old method.
print "The first character of A is {!s}.".format(A[0]) # New method, Python 3.

# Some useful built in string methods.
# https://docs.python.org/2.7/library/stdtypes.html#string-methods

# Check and convert a string to all caps.
print(str.upper(A))

if str.isupper(A):
        print(A)
else:
        print(str.upper(A) + " : Converted with str.upper().")
        print(str.swapcase(A) + " : Converted with str.swapcase().")
        print(A + " : Original remains intact. Strings are immutable!")

# Check and convert a string to all lower case.
B = "HELLO WORLD"
print(str.lower(B))

if str.islower(B):
        print(B)
else:
        print(str.upper(B) + " : Converted with str.lower().")
        print(str.swapcase(B) + " : Converted with str.swapcase().")
        print(B + " : Original remains intact. Strings are immutable!")

# Be careful with str.swapcase()
print(str.swapcase("str.swapcase Literally swAps eACH CHARACTER'S case."))

# Capitalise the first letter only.
print(str.capitalize(A))
print(str.capitalize(B))

# Find a substring within a string.
stringToFind = "lo"
i = A.find(stringToFind)
print(A[i:i + len(stringToFind)] + " found at position %d") % i

# The last example uses a technique called slicing with the print statment.
# This is used to print a sub string and can infact be used on most list
# style objects with indices. The axample below is a bit simpler.

print(A[0:5])

# The first value in the square brackets is the index position to begin at.
# The second value is the number of positions we want to include in the slice.
# It is NOT an index value.

# So if we imagine our string "Hello World" is a row of boxes. What we're
# telling Python to do is start at index 0 and print only the next 5 boxes.
# The index value for the "o" in "Hello" will of course be 4 and not 5. This is
# because the indices in lists and strings begin at 0 and not 1.

Strings 1

#!/usr/bin/env python

# The first thing to note about strings is that they are basically lists of
# characters. This means all elements of a string can be accessed directly
# using their indices.

# Python strings effectively have two indices. The first starts at 0 for the
# first character on wards. The second starts at -1 from the last character.

A = "Hello World"
print "The first character of A is \"%s\"." % A[0]
print "The last charachter of A is \"%s\"." % A[-1]

# The code above looks very simple. And it is. However a number of thing are
# happening that would normally require a lot more code in Java or C.

# 1. A is declaired and it's value set as the string "Hello World".
# 2. Python is told to print the first and last characters.
# 3. ASCII escape characters are used to enclose the first and last characters
#    in double quotes. Getting to grips with these will save a lot of code.
# 4. We perform a substitution instead of concatinating multiple strings.

# Concatinated version.
print ('The first character of A is ' + '"' + A[0] + '".')
print ('The first character of A is ' + '"' + A[-1] + '".')

# Slightly more complex examples.
B = ["first","second","third","fourth","last","second last"]
print ("The %s character of A is \"%s\".") % (B[0],A[0])
print ("The %s character of A is \"%s\".") % (B[1],A[1])
print ("The %s character of A is \"%s\".") % (B[4],A[-1])
print ("The %s character of A is \"%s\".") % (B[5],A[-2])

print ('The ' + B[0] + ' character of A is ' + '"' + A[0] + '".')
print ('The ' + B[1] + ' character of A is ' + '"' + A[1] + '".')
print ('The ' + B[4] + ' character of A is ' + '"' + A[-1] + '".')
print ('The ' + B[5] + ' character of A is ' + '"' + A[-2] + '".')

# Integer substition example.
print ("The %s character of A is \"%s\". A is %d characters long.") % (B[4],
        A[-2],len(A))
       
print ('The ' + B[4] + ' character of A is ' + '"' + A[-1] + '". A is '
        + str(len(A)) + ' characters long.')

# Note that to substitute in an integer %d is used instead of %s. Conversion of
# the integer happens automatically. However in the concatination version the
# conversion must be done manually. Which isn't a problem in this example. But
# it would make larger programs harder to read and maintain.

# More information on string formatting can be found here,
# https://docs.python.org/2/library/stdtypes.html#string-formatting-operations

Monday 27 July 2015

Making Decisions: if-elif-else

#!/usr/bin/env python

# Programs normally execute one line after the other from top to bottom.
# But sometimes we need to make a decision while the program is running.
# Some of these decisions will send the program down one path or the other.

# To do this in Python we use the if-elif-else statements.

# The first thing to note is Python uses indentation to define code blocks
# rather than the {} notation found in C or Java. This means in Python
# indentation of code blocks is manditory. We also don't actually
# type "then" as in "if condition is true then do somemthing". Instead we use
# a colon ":". Because why not?

# Basic if statement.
A = 0 # Integer.
if A == 0: print A

# A more complex example with indentation defining a code block.

A = [1,2,3,4,5] # List of integers.
if A[0] != 0:
        print ("A at index 0 is equal to %d.") % A[0]
        print ("A at index 0 is equal to %d.") % A[1]
        print ("A at index 0 is equal to %d.") % A[2]
        print ("A at index 0 is equal to %d.") % A[3]
        print ("A at index 0 is equal to %d.") % A[4]      

# Both the examples above will only print the value of A if the condition is
# met. But often we need alternative actions to be taken when the condition
# has not been met. For this we add the else statement.

A = 1
if A == 0:
        print A
else:
        print ("A is not 0.")
       
# By adding additional if statements we can test for multiple possibilities.
# We do this in Python by using elif.

A = 2
if A == 0:
        print A
elif A == 1:
        print A
elif A == 2:
        print A
elif A == 3:
        print A
else:
        print ("The value of A does not match the test.")

Variables and Data Types

#!/usr/bin/env python

# Python Variables and Data Types
# The first thing to know about a variable is that it is just a place in the
# computer's memory where data is held. Think of them as boxes.

# Variables have names to make them easier to work with. In most programming
# languages variable names can be made up of numbers and letters. And they
# normally must start with a letter or underscore character "_". Python in this
# respect is like any other programming language. A variable name is called an
# "identifier". Identifiers are case sensitive. Python keywords cannot be used
# as identifiers.

# Python variables are loosely typed. The interpreter assumes the variable type
# based on the content of the variable. Variables can be integers, long integers
# octal literals (base 8), hexadecimal literals (base 16), floating-point
# numbers and complex numbers.

# Python also supports some complex data structures. These are strings, lists,
# tupels, dictionaries and sets. A list is like an array in Java or C. Except a
# list in Python can consist of mixed types. Tupels, dictionaries and sets are
# similar to lists. But they have different uses, attributes and methods of
# access.

# Examples of numbers.
a = 1 # Integer.
b = 42000000000000000000L # Long integer.
c = 010 # Octal literal.
d = 0xA1F # Hexadecimal literal.
e = 0XA1F # Hexadecimal literal.
f = 45.33 # Floating-point number.
g = 9.5541e-10 # Floating-point number.
h = 4 + 4j # Complex number.

print a
print b
print c
print d
print e
print f
print g
print h

# Examples of strings.
i = "Hello World" # String with double quotes "
j = 'Hello World' # String with single quotes '

k = '''Hello World can extend over multiple lines
and contain 'single quotes' and "double quotes"
 which is crazy.''' # String with triple quotes '''

l = '\"Hello World\"' # String with single quotes, printing double quotes.
m = "\'Hello World\'" # String with double quotes, printing single quotes.

print i
print j
print k
print l
print m

# Example of a list.
n = ["H","e","l","l","0"] # A simple list.
o = [["W","o","r","l","d"],2,3.45,0xA1F] # A list composed of multiple types.

print n
print o
print n[0]
print n[1]
print n[2]
print n[3]
print n[4]
print o[0][0]
print o[0][1]
print o[0][2]
print o[0][3]
print o[0][4]
print o[1]
print o[2]
print o[3]

# Example of a tuple.
p = ("Tuples","are","immutable","lists")
print p
print p[0]
print p[1]
print p[2]
print p[3]

# Example of a dictionary.
q = {"Name" : "Bob","Age" : 20}
print q
print q["Name"]
print q["Age"]

# Example of a set.
r = set(("Hello World",i))
s = {"Hello World",i}
print r
print s
# Why doesn't "Hello World" print twice for each set as we would expect?
# Sets contain non-repeating data only. Since "Hello World" and "i" are the same,
# one is discarded.