Python Forum
Help on a program to help with distributing food to the needy
Thread Rating:
  • 3 Vote(s) - 2.33 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help on a program to help with distributing food to the needy
#21
I have an update on my program. I am going to make a function be the main menu. My current code is like this:
#! /usr/bin/env python3
#for use in the total() function
from fractions import Fraction
#to use in time and date stamps in the file written by the total() function
import time

def food_items():
    #This is the dictionary that will store our items and their respective amounts
    items = {}
    #This loop defines the user adding the items
    while True:
        #requests name and amount, amount in integer form
        while True:
            item_name = input("Type the name of your food item here: ")
            item_units = input("Type the number of units of your item, just the number, here: ")
            try:
                value = int(item_units)
                break
            except ValueError:
                print('The number of units you entered: ', item_units, ' is not a normal number, please try entering it again.')
                continue
        #writes the name and amount as the key and value in our dictionary
        items[item_name] = item_units
        #from here the user can enter a new item or go on to the registration step
        next_step_option = input("Type 'a' to do another item, type 'n' to go to the next step': ")
        if next_step_option == 'a':
            print('Adding another food item')
        elif next_step_option == 'n':
            main()
        else:
            print('......An incorrect or blank character has been entered, try the last entry again.')

#just a repepitive line
def show_sizes(large, small):
    print ('Large families: ', large, ' small families: ', small)
  
#this function defines the first input data and how to store that data
def one_or_two():
    # instruction for quitting
    print("Press 'm' to go back to the main function. Your data will be saved.")
    #declareing the necessary variables
    large = 0
    small = 0
    while True:
        letter = input("Is it a large family or small? Type l for large family, s for small: ").lower()
        if letter in ('s', 'small'):
            #adding to the value of small families 
            small = small + 1
            show_sizes(large, small)
        elif letter in ('l', 'large'):
            #adding to the value of large families
            large = large + 1
            show_sizes(large, small)
        elif letter in ('m', 'main'):
            break
        else:
            print('......An incorrect or blank character has been entered, try the last entry again.')
        print()
    return large, small
    main()
  
#this function gives a tally with information when the program is exited and also writes it to a file.
def total(large, small):
    #we set local_time to equal the current time and date.
    timestr = time.strftime("%Y%m%d-%H%M")
    final_total = large + small
    #the following four lines print out a simple block of data.
    print('\n***There is a final total of ',final_total, ' families***')
    show_sizes(large, small)
    if small != 0:
        print('The ratio of large families to small families is: ' ,Fraction(large, small), ' large/small')
    else:
        print('The ratio of large families to small families is: ', large, '/0 large/small')
    print('{:.1%} of the families were large.'.format(large / final_total))
    #the next six lines make a file name that is time and date stamped and add the same data to it as was printed above.
    filename = 'food drive log'
    with open(filename + timestr + '.txt', 'a') as file_object:
        file_object.write('***There is a final total of ' + str(final_total) + ' families***\n')
        if small != 0:
            file_object.write('The ratio of large families to small families is: ' + str(Fraction(large, small)) + ' large/small\n')
        else:
            file_object.write('The ratio of large families to small families is: ' + str(large) + '/0 large/small\n')
        file_object.write('{:.1%} of the families were large.\n'.format(large / final_total))
        file_object.write('Large families: ' + str(large) + ' Small families: ' + str(small) + '\n')

def main():
    userin = input("Type 'i' to enter new items, 'r' to begin registering new families, or 't' to get currnet total and stats, e is to exit: ")
    while userin != 'e':
        if userin == 'i':
            food_items()
        elif userin == 'r':
            one_or_two()
        elif userin == 't':
            large, small = one_or_two()
            total(large, small)
        elif userin == 'e':
            large, small = one_or_two()
            total(large, small)
            break
        else:
            print('An unknown option: ', userin, ' has been entered. Please try the last entry again.')
      
main()
My problem is this: how can i return to the main menu while saving the data already in the functions? I need to be able to switch between registering and items, just in case, so i need to make a function that can go back and forth between them. obviously this code doesnt work, or i wouldnt be asking for more help. 
here:
#this function defines the first input data and how to store that data
def one_or_two():
    # instruction for quitting
    print("Press 'm' to go back to the main function. Your data will be saved.")
    #declareing the necessary variables
    large = 0
    small = 0
    while True:
        letter = input("Is it a large family or small? Type l for large family, s for small: ").lower()
        if letter in ('s', 'small'):
            #adding to the value of small families 
            small = small + 1
            show_sizes(large, small)
        elif letter in ('l', 'large'):
            #adding to the value of large families
            large = large + 1
            show_sizes(large, small)
        elif letter in ('m', 'main'):
            break
        else:
            print('......An incorrect or blank character has been entered, try the last entry again.')
        print()
    return large, small
    main()
It simply restarts the current function, losing the data that was previously entered. I need it to finish the function, return or store the values somehow, then return to the main menu. I need the food_items(), total(), and one_or_two() functions to be able to use this solution. Thanks again to the fantastic people who have helped me on this project, i am learning quite a bit about making larger projects with python.
Reply
#22
Use large, small defined in your main function and update it with your one_or_two.
def main():
    #declareing the necessary variables
    large, small = 0, 0
    while True:
        userin = input("Type 'i' to enter new items, 'r' to begin registering new families, or 't' to get currnet total and stats, e is to exit: ")
        if userin == 'i':
            food_items()
        elif userin == 'r':
            large, small = one_or_two(large, small)
        elif userin == 't':
            total(large, small)
        elif userin == 'e':
            total(large, small)
            break
        else:
            print('An unknown option: ', userin, ' has been entered. Please try the last entry again.')
def one_or_two(large, small):
    # instruction for quitting
    print("Press 'm' to go back to the main function. Your data will be saved.")
    while True:
And remove calls for main() from your other functions.
Reply
#23
Thank you, i will try it. what about being able to return to the main menu?

Also, could you put that python code in [  python][  /python] tags? I cant really see any of it, it is all displayed on two lines.
Reply
#24
(Apr-07-2017, 11:44 AM)teenspirit Wrote: it's just that no one has ever really figured our average for 1's to 2's, or the average number of people who attend. ... We already have a registration table where people sign in to get their card, so implementation should not be much of an issue.

What are you doing with the sign in sheets? That seems to be the perfect place to get historical data. Analyzing that data should be the first step before you design your prediction program.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#25
After i get a little bit of a working front end to show Scott why i need the data, I will ask. I live in a rural area and should see him sunday, so i wont drive the thirty five minutes one way just to talk to him about it. I dont have contact info for him unfortunately. Its hard to get people to take a teenager serious on anything that involves anything complex or affects the way something is managed.
Reply
#26
Quote:Its hard to get people to take a teenager serious on anything that involves anything complex or affects the way something is managed.
Same thing happens when you turn 70!
Reply
#27
This is now my progress on the program:
#! /usr/bin/env python3

#For use in the total() function.
from fractions import Fraction
#To use in time and date stamps in the file written by the total() function.
import time

def get_item_info(items):
    #Requests name and amount, amount in integer form.
    while True:
        item_name = input("Type the name of your food item here: ")
        item_units = input("Type the number of units of your item, just the number, here: ")
        #The next six lines makes sure that the user has enterred an integer in 
        try:
            value = int(item_units)
            break
        except ValueError:
            print('The number of units you entered: ', item_units, ' is not a normal number, please try entering it again.')
            continue
    #Writes the name and amount as the key and value in our dictionary.
    items[item_name] = int(item_units)
    #This prints the current list of items to the screen.
    for item, amount in items.items():
        print(item + ' ..... ' + str(amount))


#This function defines the process of adding new food items to the items dictionary.
def food_items(items):
    #This loop defines the user adding the items.
    while True:
        get_item_info(items)
        #After running the get_item_info function, this code will determine what the user will do next.
        next_step_option = input("Type 'a' to do another item, type 'm' to go to the main menu': ")
        #This statement says that if the input is 'a', it goes back to the top of our loop and recalls get_item_info(items)
        if next_step_option == 'a':
                print('Adding another food item')
        #This line exits to the main menu by breaking the loop, finishing the function call.
        elif next_step_option == 'm':
            break
        else:
            print('......An incorrect or blank character has been entered, try the last entry again.')

#Just a repepitive line that it isn't practical to keep writing over and over.
def show_sizes(large, small):
    print ('Large families: ', large, ' small families: ', small)
  
#This function defines the first input data and how to store that data.
def one_or_two(large, small):
    # instruction for quitting
    print("Press 'm' to go back to the main menu. Your data will be saved.")
    while True:
        letter = input("Is it a large family or small? Type l for large family, s for small: ").lower()
        if letter in ('s', 'small'):
            #adding to the value of small families 
            small = small + 1
            show_sizes(large, small)
        elif letter in ('l', 'large'):
            #adding to the value of large families
            large = large + 1
            show_sizes(large, small)
        #This exits back to the main menu by breaking the loop, finishing the function call.
        elif letter in ('m', 'main'):
            break
        else:
            print('......An incorrect or blank character has been entered, try the last entry again.')
        print()
    return large, small
  
#This function gives a tally with information when called and also writes it to a file.
def total(large, small):
    #We set local_time to equal the current time and date.
    timestr = time.strftime("%Y%m%d-%H%M")
    final_total = large + small
    #The following four lines print out a simple block of data.
    print('\n***There is a final total of ',final_total, ' families***')
    show_sizes(large, small)
    if small != 0:
        print('The ratio of large families to small families is: ' ,Fraction(large, small), ' large/small')
    else:
        print('The ratio of large families to small families is: ', large, '/0 large/small')
    print('{:.1%} of the families were large.'.format(large / final_total))

    
def final_total(large, small):
    total(large, small)

    #The next six lines make a filename that is time/date stamped and adds the specified information
    filename = 'food drive log'
    with open(filename + timestr + '.txt', 'a') as file_object:
        file_object.write('***There is a final total of ' + str(final_total) + ' families***\n')
        if small != 0:
            file_object.write('The ratio of large families to small families is: ' + str(Fraction(large, small)) + ' large/small\n')
        else:
            file_object.write('The ratio of large families to small families is: ' + str(large) + '/0 large/small\n')
        file_object.write('{:.1%} of the families were large.\n'.format(large / final_total))
        file_object.write('Large families: ' + str(large) + ' Small families: ' + str(small) + '\n')

#This function is the main menu and controller of the other functions we have defined.
def main():
    #Declaring the necessary variables and dictionary.
    large, small = 0, 0
    items = {}
    while True:
        #The following is our main menu that the user will see.
        userin = input("Type 'i' to enter new items, 'r' to begin registering new families, or 't' to get currnet total and stats, e is to exit: ")
        if userin == 'i':
            food_items(items)
        elif userin == 'r':
            large, small = one_or_two(large, small)
        elif userin == 't':
            total(large, small)
        elif userin == 'e':
            final_total(large, small)
            break
        else:
            print('An unknown option: ', userin, ' has been entered. Please try the last entry again.')

#Calling our main function to start running the primary protions of our program.
main()
As you can see i split the food_items(items) function into two seperate functions, so that it would properly exit to the main menu. 
I also made a new total(large, small) function removing the file writing from that function, adding that functionality to the new final_total(large, small) function. I followed some of the advice for minor changes that has been given to me, and cleaned up the commenting a little bit. If anyone has any further suggestions or would like to help with development, please, just let me know. I am going to add writing the contents of our items dictionary to the onscreen total function and to the final_total function to add to the data given and stored with those functions.
Reply
#28
Why items[item_name] = int(item_units) and not items[item_name] = value?
The exception force the user to input the item_name again.
item_name = input("Type the name of your food item here: ")
while True:
    try:
        item_units = int(input("Type the number of units of your item, just the number, here: "))
    except ValueError:
        print("Incorrect entry!")
Printing the items after each input could be annoying and if the dictionary is big, it will fly across the screen and you'll see nothing.
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#29
I would start simpler. You say you have a bunch of people sign up before you start handing out food. Take that as the ratio of ones to twos for the evening, and use it to estimate the total number of families. Don't ignore Scott here. The first rule of data analysis is to listen to the subject matter experts. Write a program to calculate what to hand out based on what you get and what your estimates are.

Collect and store the data. If the sign in sheets have the time the family showed up, great. If not, get them marked marked with the time every 15 to 30 minutes. Now, collect some data from several weeks of handing out food. And by collect, I mean type it into the computer. I expect this project will be more about data and less about programming. Start to look at the error rate on your estimate, especially it's bias and variance. You'll want to adjust to the bias, to get the best estimate. You'll want to look to the variance. This is trickier. What is your goal? To get rid of all the food or to make sure everybody gets some food. If the former, high ball your estimate by one standard deviation; if the latter, low ball your estimate by one standard deviation.

Next, look for patterns in the data that could justify a real time analysis. Do some simulations using sampled data to see if any real time adjustment strategies improve performance against your targets. Present this to Scott. Then implement the programs to do the real time analysis and adjustments.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#30
First, your latest revision. Somewhere along the line you lost the definition of 'timestr'.
    with open(filename + timestr + '.txt', 'a') as file_object:
Second, before you get more invested in the program, you really, truly need to incorporate a database.  Be it sqlite3, Postgre, or some other database.  When it comes to data manipulation, text files are, to say the least, cumbersome and inefficient.  As you have it, at the end of a year, you will have at least 365 files.  To gather your data, you will need to access each one. Also, you really need to listen to the advice by ichabod801.  If you are going to pitch this Scott, you have to show proof of concept...that your program can deliver what he wants.  Something to remember, bosses like reports, even better, they like tables, but what really gets their attention is graphs. They really loves their graphs, especially if they are colorful.  Even if you start small, as ichabod801 says, at least you can go to Scott and say "Here is what I can give you, just based on the sign-in sheets for the past month, I would be interested in what you would like to see in addition to this....by the way, I have a graph." (Scott now very happy and offers to buy you a car.)


Finally, and this is just my opinion, but why the use of 'Fraction'?  It really adds nothing to the overall script and just adds to the complexity.
If it ain't broke, I just haven't gotten to it yet.
OS: Windows 10, openSuse 42.3, freeBSD 11, Raspian "Stretch"
Python 3.6.5, IDE: PyCharm 2018 Community Edition
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Optimization problem ( food menu ) Truman 3 3,567 Apr-01-2019, 09:28 PM
Last Post: Truman
  Packaging and Distributing App for Python 3.6 solaikannan 1 2,658 Aug-21-2017, 09:36 AM
Last Post: snippsat

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020