""" atm.py Implements an ATM simulation with data stored in a "list of dictionaries", an example of a python data structure. Accounts are dictionaries with keys (person, password, checking, savings). The bank is a list of accounts. bank = [ {'person': 'Jack', 'password': 'jackpass', # account 0 'checking': 100.00, 'savings': 500.00 }, # {'person': 'Jill', 'password': 'janepass', # account 1 'checking': 243.56, 'savings': 876.54 } # ] The initial data for the bank is read from a CSV (comma separated value) file that looks like this: -- atm_data.txt -- person,password,checking,savings Jack,jackpass,100.00,500.00 Jill,jillpass,243.56,876.54 Notice that * the only global variable is a constant which sets the name of the data file, * all the functions have docstrings which describes their arguments and return value, and * the main() function is short and sweet. There is a built-in library in python for reading and writing to CSV files, but here that file is processed explicitly instead. TODO : * Write the modified data back out to the file, so that repeated execution remembers the transactions. * Rewrite this wholel thing using classes for Person, Account, Bank rather than a data structure. (Just as a learning exercise.) * For a really good time, implement more realistic passwords : * Add counter to login attempts & quit if too many. * Use the python getpass library. (Alternative input without display.) * Hide the passwords in the data file with hashlib library. * Add a "salt" to the stored password so that duplicate passwords don't have the same hash. Jim Mahoney | Nov 2016 | MIT License """ datafilename = 'data_atm.csv' def get_bank_from_file(filename = datafilename): """ Return a 'bank' data structure as described at the top of the file, by reading its data from a CSV file """ # Yet another function that follows the "accumulator pattern". bank = [] # Start with an empty bank. datafile = open(filename, 'r') firstline = datafile.readline() # Read & do nothing with first line. while True: # Loop over remaing lines in file. line = datafile.readline() if line == '': # At end of file, readline() returns '' return bank # ... so the bank is filled with accounts. else: (person, password, checking, savings) = line.split(',') bank.append( {'person': person, # Make a new dict 'password': password, # account, and put 'checking': float(checking), # it in the bank. 'savings': float(savings) } # ) def login(bank): """ Prompt the user to login to a bank account. If succesful, return id = index of account in bank list. If user types 'QUIT', return 'QUIT'. """ while True: # Allow repeated login attempts. # print "DEBUG: {}:format(bank)" print who = raw_input('Login with your name (or QUIT to exit): ') if who == 'QUIT': print 'Bye.' return 'QUIT' password = raw_input('Password? ') for id in range(len(bank)): # search accounts for user,passwd account = bank[id] #print "DEBUG: id={} account={}".format(id, account) #print "DEBUG: passwd='{}'".format(password) #print "DEBUG: who='{}'".format(who) #print "DEBUG: person match? ", account['person'] == who #print "DEBUG: passwd match? ", account['password'] == password if account['person'] == who and account['password'] == password: return id print " OOPS: name or password is wrong - try again. " def transaction(account): """ Prompt user for transactions to apply to given account, which is a dictionary with keys ('person', 'password', 'checking', 'savings') Return the modified account. """ while True: # show account status print " status: {} has {} in checking, {} in savings.".format( account['person'], account['checking'], account['savings']) # do one transaction what = raw_input(' transaction (deposit, withdraw, transfer, end) ? ') if what[0] == 'e': # end return account elif what[0] == 'w': # withdraw which = raw_input(' account (checking, savings) ? ') amount = float(raw_input(' amount (xxx.xx) ? ')) account[which] = account[which] - amount elif what[0] == 'd': # deposit which = raw_input(' account (checking, savings) ? ') amount = float(raw_input(' amount (xxx.xx) ? ')) account[which] = account[which] + amount elif what[0] == 't': # transfer which = raw_input(' 1 (check to save) or 2 (save -> check) ? ') amount = float(raw_input(' amount (xxx.xx) ? ')) if which == '1': account['checking'] = account['checking'] - amount account['savings'] = account['savings'] + amount if which == '2': account['checking'] = account['checking'] + amount account['savings'] = account['savings'] - amount def main(): print "-- ATM simulation --" bank = get_bank_from_file() while True: id = login(bank) if id == 'QUIT': return else: bank[id] = transaction( bank[id] ) if __name__ == '__main__': main()