I am doing a GCSE NEA project for practice.

Customer Loyalty Scheme

The managers of Crawdale Hotel Group have decided to update their customer loyalty scheme. Customers joining the scheme become silver members. Customers are upgraded to gold members when they have booked 30 nights’ accommodation and to platinum once they reach 100 nights.

Silver members receive 2500 loyalty points per night booked, gold members receive 3000 points and platinum members 4000 points. The data is stored as a text file.

The data in this table is provided in the SampleData2017.txt file.

| MemberID |  Surname  | YearJoined | MembershipStatus | NightsBooked | PointsBalance |
| Gri33415 | Griffiths |    2015    |       Gold       |      35      |     40000     |
| Smi22316 |   Smith   |    2016    |      Silver      |       3      |      7500     |
| Mia56213 |    Miah   |    2013    |     Platinum     |      140     |     165000    |
| All78915 |   Allen   |    2015    |     Platinum     |      120     |     145000    |
| Hug91714 |  Huggett  |    2014    |     Platinum     |      150     |     50000     |
| Sel77617 |   Selby   |    2017    |       Gold       |      40      |     45000     |
| San55614 |   Santus  |    2014    |      Silver      |      12      |     30000     |
| Lee44213 |   Leewah  |    2013    |      Silver      |      15      |     37500     |

The loyalty points can be redeemed for nights at the hotels. A night costs 25000 points.


The managers want a computer program to help them operate the scheme efficiently. The program must allow hotel staff to add new members to the scheme, record nights booked and points redeemed. It must also update a member’s points balance each time they book nights or redeem points, upgrade their membership status when appropriate and allow the number and status of the members to be monitored.

The number of nights in a single booking must be limited to a maximum of 14.

The program must allocate a unique ID to each new member consisting of the first three letters of their surname, plus a three-digit number, followed by the last two digits of the current year.

Your task is to analyse these requirements and to design, implement, test and evaluate a solution. You will need to make some assumptions and decisions of your own.

Below is my code. Can you please tell me if I need any improvements or anything?

while True:
    import random
    import time

    select = input("=============================\n\nA - Add new user \nB - Book a night \nC - Check everyones account information \nR - Redeem a night \nQ - Quit System \nChoose an option: ")

    if select == 'A':
        hotelfile = open("SampleData2017.txt", "a+")
        membersname = input("What is your surname? ")
        eighteen = ("18")
        username = membersname[0:3] + str(random.randint(100, 999)) + eighteen
        print("Your username is ", username)
        comma = (",")
        hotelfile.write (username)
        hotelfile.write (comma)
        hotelfile.write (membersname)
        hotelfile.write (comma)
        hotelfile.write ("2018")
        hotelfile.write (comma)
        hotelfile.write ("Silver")
        hotelfile.write (comma)
        hotelfile.write ("0")
        hotelfile.write (comma)
        hotelfile.write ("0")
        hotelfile.write ("\n")

    elif select ==  'B':

    elif select == 'C':
        hotelfile = open("SampleData2017.txt", "r+")
        for line in hotelfile:
            print (line)

    elif select == 'Q':



  • \$\begingroup\$ Are you allowed to import csv? This would make the exercise very easy (avoids the necessity of you writing the file input/output handling). \$\endgroup\$ – C. Harley Sep 25 '18 at 5:57

Move imports outside of loops

Whether or not Python optimizes this away, it is better to move import statements to the top of the file rather than scattered among the rest of the code.

Use nouns for variable names, verbs for functions

Instead of the variable select, give it a noun as name, such as selection or choice.

Don't give magic constants useless names

While it is often a good idea to define a variable holding a magic constant once, and then using it, you must give it a good name. The following is bad:

eighteen = ("18")

Instead, give the variable a more meaningful name, that describes its purpose. Also, sometimes a constant speaks for itself, and does not need to be put into a variable, like:

comma = (",")

Just use "," directly in the code. There is also no need to put parentheses around them.

Use format strings for formatting your output

Writing lines word by word is inefficient, and results in longer, convoluted code. It is better to use a format string to write a line at a time. For example:

hotelfile.write("{},{},{},{},{},{}\n".format(username, membersname, year, status, nightsbooked, pointsbalance))

Move big actions into functions

Your code will grow over time, and having everything in one big function will cause you to lose overview. Try to split of the actions you perform on the list of bookings into separate functions. So your code should get the following structure:

def addUser(...):
    # code to add a new user

def bookNight(...):
    # code to book a night


choice = input(...)
if choice == 'A':
elif choice == 'B':
elif ...

When your code grows even more, you will probably have to think about adding classes that represent users, booking and so on. It is good to think a little bit ahead and add some more structure to your code early on (but you don't have to overdo it).

Ensure usernames are really unique

You are generating usernames by taking the first three characters of the surname, then adding a random number between 100 and 999, and then add the magic "18". This means that if a new user is added, and his or her surname starts with the same three characters as an existing user, that there is at least a 1 in 900 chance that you generate the same username. You blindly add the username to the file without checking for a possible collision. This will cause real problems! Fix it in one of these ways:

  • Use a global counter that increments each time a user is added to the system, and make the complete value of that counter part of the username.

  • Check if any users are in the system that have the same three starting characters, if so check what the highest number associated with them is, and give the new user a number which is at least one higher than that.

  • Generate a truly random number that is at least 128 bits long, so that the average time before you have any real chance of having a collision is longer than the age of the universe. Python has a uuid library for exactly this sort of thing.

  • \$\begingroup\$ @g-sliepen The requirements state the format of the User ID; first three letters of their surname, plus a three-digit number, followed by the last two digits of the current year. There's no need to run off generating UUIDs, just maintain a dict, do a has_key() check and increment (don't randomize, there's no need) until the has_key() function returns false (typically only against the 3-digit number, as the rest of them will obviously have collisions which is perfectly fine) to get your unique User ID. \$\endgroup\$ – C. Harley Sep 25 '18 at 5:51
  • \$\begingroup\$ Requirements can be wrong too. This limits the hotel chain to accepting only 900 Smiths each year, not a wise business decision if you ask me. Either the requirement should be fixed, or the system should somehow deal with the 901th Smith. \$\endgroup\$ – G. Sliepen Sep 25 '18 at 17:16
  • \$\begingroup\$ Sure, it's not a real-life booking system, I don't think they're going to be throwing 999+1 Smiths against it in testing to validate a failure of their own GCSE NEA requirements. \$\endgroup\$ – C. Harley Sep 27 '18 at 0:29

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.