0

Newbie to programming and having issues with one of my assignments. I'm trying to get one of my functions to read data from a txt file and calculate the amount owed, but I'm defiantly not doing it right. I've gotten the other functions correct, but can't figure this one out.

I'm sorry if it seems like I'm asking you guys to do my homework for me, but I'm not. I'm just very confused on what I'm supposed to do here to make it work.

Here's the code (I'm stuck on line 12 "calcData")

import csv
def readData():
    fields = ("name", "city", "miles", "gallons")
    f = open("travel.txt", "r")
    travels = []
    dReader = csv.DictReader(f, fieldnames=fields, delimiter="\t")
    for row in dReader:
        travels.append(row)
    f.close()
    return travels

def calcData(trips):
    user = input("Enter user: ")
    record = {'name' : user, 'miles': mi, 'gallons': gal}
    mpg = mi/gal
    owed = mi*.75
    print(user,  "is owed:" , owed)
    print(user, " had an mpg of: ", mpg)
    return trips

def displayData(trips):
    fs = "%-8s %-16s %7s %s"
    print(fs % ("Name", "City", "Miles", "Gallons"))
    for t in trips:
        fs = "%-8s %-16s %6s %5s"
        print(fs % (t['name'], t['city'], t['miles'], t['gallons']))

def addTrip(trips):
    nom = input("Enter your first name: ")
    city = input("Enter the destination city: ")
    mi = input("Enter the miles traveled: ")
    gal = input("Enter the gallons used: ")
    record = {'name' : nom, 'city': city, 'miles': mi, 'gallons': gal}
    trips.append(record)
    return trips

def storeData(trips):
    fields = ("name", "city", "miles", "gallons")
    f = open("travel.txt", "w")
    dWriter = csv.DictWriter(f, fieldnames=fields, delimiter="\t",lineterminator="\n")
    dWriter.writerows(trips)

    f.close()

def main():

    travel_log = readData()

    while True:
        print("""
        Menu options. Choose 1, 2, or 3
            1. Display all trip data
            2. Calculate user expense
            3. Add a trip
            4. Save and exit

        """)

        opt = input("   Enter your choise, 1, 2, or 3: ")

        if opt == "1":
            print()
            displayData(travel_log)
        elif opt == "2":
            print()
            travel_log = calcData(travel_log)
        elif opt == "3":
            travel_log = addTrip(travel_log)
        elif opt == "4":
            storeData(travel_log)
            print("Goodbye")
            print()
            break
main()

Here is the text I'm trying to make it read from :

alice   chicago 663 20.7
bob indianapolis    226 8.7
alice   nashville   409 16.4
carl    indianapolis    243 8.4
diane   st. louis   581 16.4
bob st. louis   560 18.1
bob cincinnati  237 6.6
alice   chicago 681 17.9
alice   nashville   422 14.6
diane   chicago 676 22.5
carl    indianapolis    243 6.4
diane   indianapolis    276 7.7
diane   indianapolis    241 9.4

here is the error I'm getting

Edit:

Traceback (most recent call last):
  File "..." 
  in <module>
    main()
   File ".."
, in main
    travel_log = calcData(travel_log)
  File ".."
, in calcData
    record = {'name' : user, 'miles': mi, 'gallon' : gal }
NameError: name 'mi' is not defined

Here is what it is suppoesed to look like according to my professor

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
  • It looks like that you know how to format code, good. I think the input should be formatted as code, too. – user202729 Mar 25 '18 at 15:59
  • [Read this](https://stackoverflow.com/questions/39682842/is-it-possible-to-access-a-local-variable-in-another-function). – user202729 Mar 25 '18 at 16:00
  • Also --- on [so], we expect people to post only a [mcve] -- for example, prompting for user input is redundant. – user202729 Mar 25 '18 at 16:01
  • Take a look at the traceback. You have not defined `mi` (or `gal` for that matter). You need to fetch this data from your text prior to using it to assign a `dict` value. Though, I'm not sure that assigning it to a `dict` value is actually the way you want to go. Easier to just use the name as a reference to pull the data from the CSV file. – Mr. Kelsey Mar 25 '18 at 16:22

1 Answers1

0

You need to search all trips for "alice" and only calculate "her" expenses like so (and use string formatting for bonus points):

import csv

def calcData(trips):
    user = input("Enter user: ")
    mi = 0
    gal = 0

    for t in trips:
        if t["name"] != user:
            continue  # next one, not alice
        mi  += float(t["miles"])     # add up all hers
        gal += float(t["gallons"])   # same

    mpg = mi / gal
    owed = mi * .75
    print('{} is owed: {:8.2f}'.format(user,owed)) # format float as you like
    print('{}  had an mpg of: {:8.2f}'.format(user, mpg))
    return trips

Additionally I would change your reading/writing:

def readData():
    fields = ("name", "city", "miles", "gallons")
    travels = []
    # f = open("travel.txt", "r")
    with open("travel.txt", "r") as f: # more robust regarding errors and autocloses
        dReader = csv.DictReader(f, fieldnames=fields, delimiter="\t")
        for row in dReader: 
            travels.append(row)
    return travels


def storeData(trips):
    fields = ("name", "city", "miles", "gallons")
    with open("travel.txt", "w", newline="") as f:  # this recreates the file all the time
        dWriter = csv.DictWriter(f, fieldnames=fields, delimiter="\t",lineterminator="\n")
        dWriter.writerows(trips)

To make it more robust against exception and avoid unnnessecary newlines.

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69