3
\$\begingroup\$

Everything currently works exactly as requested by the instructor, I've included as much possible commented documentation as I can think of to make it easier for people to see what the required criteria is for the project! Let me know what you guys think, I would really appreciated it!

The program is disjointed as it is a culmination of almost everything we've learned this semester.

The program is going to define a main function with at least 3 other embedded functions(any other functions will be extra credit). It must create a list of usernames, using a while loop to gather info from the user until they decide to stop, include a random number between the user's age and 99 (inclusively), add all the generated names to a list and display the names in lower case. It will then allow the user to test if a name is contained within the list, until they decide to stop. Write the user names to an empty text file titled 'username.txt'. Then it must calculate an average based on entered number of test scores and classify the average to a letter grade.

import random
uNameList = []
 
def start():          #create the greeting function
    """Present user with a greeting and program introduction"""
    print("""=======================================================================
Welcome to my Username generator and test-score-average-classifier.  
This program will allow you to create a set of user names by entering a user's 
first name, last name, and their age. You will then be able to check to see if 
a Username that you enter is currently in use. Finally, you will be able to enter 
in a number of test scores, get the average and return an equivalent letter
grade. 
======================================================================\n\n""")
 
def end():           #create the farewell function
    """Offers farewell and thanks to the user"""
    print("""\n\n======================================================================
You have reached the end of the Username generator and the
test-score-average-classifier.  Your Usernames will appear in a
text file after you close out the program.  Thank you for your
time and have a wonderful day!
 
Goodbye!
======================================================================""")
 
#my attempt at an extra credit function
def lWriter(listName):
    """This should be a simple call to create the text file"""
    f = open("username.txt", 'w')
    for names in listName:
        f.write(names+"\n")
    f.close()

def grader(tAverage):
    """A function to classify they test averages into a letter grade"""
    if tAverage >= 90:
            return "A"
    elif tAverage >= 80 and tAverage < 90:
        return "B"
    elif tAverage >= 70 and tAverage < 80:
        return "C"
    elif tAverage >= 60 and tAverage < 70:
        return "D"
    else:
        return "F"
        
#create the averaging function
def average(scoreTotal, tests):       
    """Returns an average based on number of tests ,and total score"""
    return scoreTotal/tests
 
    #create the main function
def main():
    start()    #call the start function
    """The main function will contain all additional functions"""
    print("Why don't we generate some Usernames first?\n")
 
    #time to gather user info and compile names into a list
    fname = input("What is the user's first name? ")
 
    while fname != "":
        lname = input("What is the user's last name? ")
        age = int(input("What is the user's age? "))
 
        rNum = random.randint(age,100)
 
        uName = fname[-1]+lname[0:4]+str(rNum)
        uName = uName.lower()
 
        uNameList.append(uName)
 
        #give the user a chance to continue, or exit and move onto the next task
        fname = input("""\nIf there is another user, please enter their first name.
If not, simply press <Enter> to continue: """)
 
    print ("\nYour available Username choices are displayed below:")
    print()
    print (uNameList)
    print()
    
        
 
    #the user enters a new loop to test whether or not certain names are contained in the list
    uNameChoice = input("Enter a Username to check if it is contained in the list: ")
 
    while uNameChoice != "":
        if uNameChoice in uNameList:
            print ("Yes, that user name is contained in the list.")
            print()
        else:
            print ("No that user name is not contained in the list.")
            print()
 
        uNameChoice = input("""Would you like to check another user name?
If not, simply press <Enter> to continue: """)
    print()
 
    #time to generate a test score average for the user
    print("Now we can move on to calculating the average of your tests!")
    print()
    tests = int(input("How many test grades would you like to enter?"))
    
    #I'm turning this into a loop as well, in case the user wants to check multiple sets of grades
    while tests != 0:
        scoreTotal = 0
 
        for scores in range(tests):
            score = int(input("Please enter one of the grades: "))
 
            scoreTotal += score
        print()
        tAverage = average(scoreTotal,tests)

        print("The test score average is",round(tAverage,2),"and the letter grade is:",grader(tAverage),end=".")
        print("\n\n")

        tests = int(input("""If you'd like to check a new set of tests, please tell me how many there are.
If not, then please simply type a '0' to end the program. """))
 
         
    lWriter(uNameList)      #write all the usernames to the textfile before the program closes out
    
    print()
 
 
    end()
#make sure to call main at the end of the program to ensure it will start automatically
if __name__=="__main__":
    main()
\$\endgroup\$
6
  • 3
    \$\begingroup\$ The current question title, which states your concerns about the code, applies to too many questions on this site to be useful. The site standard is for the title to simply state the task accomplished by the code. Please see How to Ask for examples, and revise the title accordingly. \$\endgroup\$
    – Mast
    Dec 3 '21 at 21:15
  • 2
    \$\begingroup\$ This question is incomplete. To help reviewers give you better answers, please add sufficient context to your question. The more you tell us about what your code does and what the purpose of doing that is, the easier it will be for reviewers to help you. Questions should include a description of what the code does. What are the exact requirements for this program? \$\endgroup\$
    – Mast
    Dec 3 '21 at 21:16
  • \$\begingroup\$ Sorry, I included what the program was supposed to do in the actual docstring in the coding. Let me reword my program setup \$\endgroup\$
    – SnazzyJoe
    Dec 3 '21 at 21:42
  • \$\begingroup\$ I'm still really new to the site, so I appreciate the help getting things posted correctly \$\endgroup\$
    – SnazzyJoe
    Dec 3 '21 at 21:50
  • 1
    \$\begingroup\$ For what Python version did you write this? \$\endgroup\$
    – Mast
    Dec 4 '21 at 10:03
4
\$\begingroup\$

I will first say, broadly: I understand that you're constrained by the demands of the assignment, but the assignment doesn't make any sense. It isn't your fault, but like - some of the features are pointless. Allowing the user to check whether a username exists in the list is pointless. There are ways to construct a semi-realistic scenario that exercise the same skills, for example splitting the program into two - an admin interface that makes the user list, and a user interface that has the user log in, where the list membership check would take place. Anyway.

Congratulations on getting everything working!

  • Avoid keeping uNameList in the global namespace
  • Start introducing PEP484 type hints to make your code more self-documenting and amenable to static analysis
  • In your start(), rather than writing \n\n it's probably better to just write literal newlines
  • Rather than lWriter, prefer write_list - it's an "action phrase", and it's in lower_snake_case.
  • It's good that you're using functions, but you haven't always captured the right things in them. average shouldn't exist at all since there's already a statistics.mean; and conversely the big chunks on the inside of main should be broken into subroutines.
  • randint's upper limit is inclusive, so you actually want to pass 99 instead of 100.
  • Consider using an interpolated f-string for making your uName (which should be called something like name or user_name).
  • Your grader would benefit from the use of a binary search via bisect.
  • Don't explicitly close your file; put it in a with where the close is both implied and guaranteed.

Suggested

from bisect import bisect
from numbers import Real
from random import randint
from statistics import mean
from typing import List, Iterator, Collection


BANNER = '='*71


def start() -> None:
    """Present user with a greeting and program introduction"""
    print(
f"""{BANNER}
Welcome to my Username generator and test-score-average-classifier.  
This program will allow you to create a set of user names by entering a user's 
first name, last name, and their age. You will then be able to check to see if 
a Username that you enter is currently in use. Finally, you will be able to enter 
in a number of test scores, get the average and return an equivalent letter
grade. 
{BANNER}
"""
    )


def end() -> None:
    """Offers farewell and thanks to the user"""
    print(
f"""{BANNER}
You have reached the end of the Username generator and the
test-score-average-classifier. Your Usernames will appear in a
text file after you close out the program.  Thank you for your
time and have a wonderful day!

Goodbye!
{BANNER}
"""
    )


def write_list(names: List[str]) -> None:
    with open("username.txt", 'w') as f:
        for name in names:
            f.write(name + "\n")


def grader(average: Real) -> str:
    """A function to classify they test averages into a letter grade"""
    thresholds = (60, 70, 80, 90)
    letters = 'FDCBA'
    return letters[bisect(thresholds, average)]


def get_names() -> Iterator[str]:
    print("Why don't we generate some Usernames first?\n")

    # time to gather user info and compile names into a list

    while True:
        # give the user a chance to continue, or exit and move onto the next task
        fname = input(
            "If there is another user, please enter their first name.\n"
            "If not, simply press <Enter> to continue: "
        )
        if fname == '':
            break

        lname = input("What is the user's last name? ")
        age = int(input("What is the user's age? "))
        suffix = randint(age, 99)
        name = f'{fname[-1]}{lname[:4]}{suffix}'.lower()

        yield name


def check_name(names: Collection[str]) -> None:
    # the user enters a new loop to test whether or not certain names are contained in the list
    while True:
        choice = input(
            "Enter a Username to check if it is contained in the list, "
            "or press <Enter> to continue: "
        )
        if choice == '':
            break

        if choice in names:
            print("Yes, that user name is contained in the list.\n")
        else:
            print("No that user name is not contained in the list.\n")

    print()


def get_scores(n: int) -> Iterator[float]:
    for _ in range(n):
        yield float(input("Please enter one of the grades: "))


def score_loop() -> None:
    # time to generate a test score average for the user
    # I'm turning this into a loop as well, in case the user wants to check multiple sets of grades
    print("Now we can move on to calculating the average of your tests!")
    print()

    while True:
        tests = input(
            "If you'd like to check a set of tests, please tell me how many there are. "
            "If not, then please simply press <Enter>."
        )
        if tests == '':
            break

        average = mean(get_scores(n=int(tests)))

        print(
            f"The test score average is {average:.2f} "
            f"and the letter grade is {grader(average)}."
            "\n\n"
        )


def main() -> None:
    start()

    names = list(get_names())

    print("\nYour available Username choices are displayed below:\n")
    print('\n'.join(names))
    print()

    check_name(names)

    score_loop()
    
    # write all the usernames to the textfile before the program closes out
    write_list(names)  
    
    end()


# make sure to call main at the end of the program to ensure it will start automatically
if __name__ == "__main__":
    main()
\$\endgroup\$
1
  • 1
    \$\begingroup\$ There's a lot in this we haven't actually learned yet, so it's cool to see some of the other available functions and stuff! I really appreciate the input. And yes, I understand that the program makes no sense. It's less a well designed program, and more of a..."Let's see how many concepts we can chuck into a single project to make sure they understand." I'll be modifying my program just a little bit after going through your suggestions! \$\endgroup\$
    – SnazzyJoe
    Dec 6 '21 at 15:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.