-1

I'm creating a simple shell program that accepts commands from the user for a restaurant. But I'm very confused on how to accept multiple inputs from the user so that the shell can read it and then interpret it to follow with the called function.

iinventory = {
    "apple": 0,
    "beets": 0,
    "carrots": 0}

total=20

def handle_commands():
    keep_going=True
    while keep_going:
        command=input("$ ").split()
        var1=input()
        var2=input()
        if command == var1 + var2:
            var1="loadrecipefile"
            var2=recipe_file
            loadrecipefile(recipe_file)
        elif command == "printrecipes":
            printrecipes()
        elif command == "printiinventory":
            printiinventory()
        elif command == "printmoney":
            printmoney()
        elif command == "preparedish ":
            command=input().split(" ")
            preparedish(recipe_name)
        elif command == "buyingredient ":
            command=input().split(" ")
            buyingredient(name, number)
        elif command == "quit":
            keep_going=False
            break
        else:
            print("Sorry that is not an acceptable command")
    return 

def loadrecipefile (recipe_file):
    infile=open(recipe_file)
    Linelist=infile.readlines()
    for line in Linelist:
        wordList=line.split()
        r1={'apple':int(wordList[1]),'beets':int(wordList[2]),'carrots':int(wordList[3])}
        cookbook={wordList[0]:r1}

def printrecipes():
    for name,ingred in cookbook.items():
        print(name + " " + str(ingred['apple']) + " " + str(ingred['beets']) + " " + str(ingred['carrots']))

def buyingredient(name, number:int):
    global total
    total_spent=0
    if number + total_spent > total:
        print("Not enough cash!")
    iinventory[name] += number
    total -= number

def printiinventory():
    print(iinventory['apple'],iinventory['beets'],iinventory['carrots'])

def printmoney():
    print(total)

def CanPrepareDish(recipe_name):
    recipe = cookbook[recipe_name]
    for ingred in recipe:
        if ingred not in iinventory:
            return False
        if iinventory[ingred] < recipe[ingred]:
            return False
    return True

def preparedish(recipe_name):
    if not CanPrepareDish(recipe_name):
        print("Not enough ingredients")
    else:
        recipe = cookbook[recipe_name]
        for ingred in recipe:
            iinventory[ingred] -= recipe[ingred]
        if recipe_name in iinventory:
            iinventory[recipe_name] +=1
        else:
            iinventory[recipe_name] = 1
            print("Dish prepared")

handle_commands()

For example, if the user was to execute:

$ buyingredient apple 5

The program should be able to accept all 3 of the different inputs then split the inputs by the spaces and then execute the function, buyingredient. I don't know how to accept the multiple inputs in one line of command.

AND, for the printrecipes() function, I want it to print the cookbook that is created in the loadrecipefile function but it says that the cookbook is not defined so how do I use the cookbook from the loadrecipefile function for the printrecipes(). The cookbook is a dictionary and I've tried making the cookbook={} outside of the function but printrecipes() just prints it as blank rather than printing the cookbook that was created in loadrecipe file

def loadrecipefile (recipe_file):
    infile=open(recipe_file)
    Linelist=infile.readlines()
    for line in Linelist:
        wordList=line.split()
        r1={'apple':int(wordList[1]),'beets':int(wordList[2]),'carrots':int(wordList[3])}
        cookbook={wordList[0]:r1}
        print(cookbook)

So for example, using the above code, it would print the cookbook:

loadrecipefile("recipe_file.txt")
{'Recipe1': {'apple': 1, 'beets': 4, 'carrots': 3}}
{'Recipe2': {'apple': 0, 'beets': 2, 'carrots': 4}}
{'Recipe3': {'apple': 3, 'beets': 0, 'carrots': 1}}
{'Recipe4': {'apple': 2, 'beets': 1, 'carrots': 0}}

and with printrecipes() it should print

Recipe1 1 4 3
Recipe2 0 2 4
Recipe3 3 0 1
Recipe4 2 1 0

Any help would be appreciated.

khelwood
  • 55,782
  • 14
  • 81
  • 108
Taitmi Lee
  • 17
  • 1

1 Answers1

0

This

command=input("$ ").split()
var1=input()
var2=input()

asks for 3 user inputs. The first one is split like you seem to want to.

if command == var1 + var2:
    var1="loadrecipefile"
    var2=recipe_file
    loadrecipefile(recipe_file)

is never going to happen, as command is a list (due to splitting) and var1 and var2 are strings.


You can create a mapping from input command to funciton call as a dict, check for enough parameters and proceed:

Create some function stubbs that do what need to be done (just printing here):

def buySomething(what, howMany):
    print(what,howMany) 

def listThem(ingredient):
    print("Listing: ", ingredient)

def searchRecepie(receipt):
    print("Searching for:", receipt)

def error(line):
    print ("An error occured, try again", line)

def qexit():
    exit(0)

Create parsing and mapping:

# create mapping what input maps to what function call        
mapping = {"buy":buySomething, 
           "list":listThem,
           "search":searchRecepie,
           "q":qexit}

# create mapping how many params are needed for each function
numParams = {"buy":2, "list":1,"search":1, "q":0}

while True:

    # split the input, extract the command
    choices = input("$ ").strip().lower().split()

    command = choices[0]

    # see if the command is mapped, if not, default to use error function
    callMe = mapping.get(command,error)

    if callMe != error:
        # check if exactly enough params given, if not, use error function
        if len(choices)-1 != numParams.get(command,-1): # cant have -2, this 
            error(choices)
            continue # back to start of 'while True:' scope

        # call the function with params, unpack list without the command
        callMe(*choices[1:])
    else:
        callMe(choices) # this is the error function with the params given

Output:

$ buy apple 5
apple 5
$ list 9
Listing:  9
$ search popsickle
Searching for: popsickle
$ buy nothing
An error occured, try again ['buy', 'nothing'] # wrong amount of params error
$ cook me
An error occured, try again ['cook', 'me'] # unmapped command error 
$ q 

You should probably create different (better suited) error function for "not in list of commands" and "not enough / too much params provided"


Read about user input validation in this great Q/A: Asking the user for input until they give a valid response

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