Cinema Seat Booking Assignment
Detail of the task(s)
Here is the layout of the cinema:
A, B, C & D = Standard E & F = Deluxe
The seats in the cinema have been represented in a data model using a list of lists. Each inner list is a row. Each seat in a row is marked as being either available, using integer 0 (zero), or booked, using integer 1.
In this version of the data structure, seat ‘A4’ is marked as being booked and all the other seats are marked as available.
Task 1: BASIC SELECTION, REPETITION, and USER I/O
You Have to develop two functions and basic user interaction to book a cinema ticket:
FUNCTION: displaySeats()
This function is required to iterate over the ‘cinema’ list of lists and display whether a seat is booked, using the letter ‘X’ or available, using the letter ‘O’; NOT zero. It should display the seats in a tabulated format as close to the following example as possible:
O = Available. X = Booked.
Rows A, B, C & D = Standard Seats Rows E & F = Deluxe Seats
In this example of the output from the displaySeats() function, the seat at ‘A4’ has been booked. This function does not return a value. NOTE: List indexes start at 0 (zero).
FUNCTION: bookASeat(seatID)
This function assumes the user has entered a valid seat I.D. in the format: Letter (A through F) directly followed by either a single digit or two digits (1 -> 9, or 01 -> 12). The function needs to transpose the letter part of the seat I.D. to an integer (‘A’ = 0, ‘B’ = 1, … ‘F’ = 5). It also needs to change the string digits to an integer (‘1’ = 0, ‘2’ = 1, ‘12’ = 11). These can then be used to check if the seat in the ‘cinema’ list of lists is already booked (1) or not (0). If it is not booked, then it should be changed to booked and the function should return the Boolean value ‘True’, else it should return the Boolean value ‘False’. NOTE: the function will need ‘global’ access to the ‘Cinema’ variable
USER INTERACTION:
This constitutes the ‘main’ program (where it starts). It should:
- Call the displaySeats() function
- Ask the user to enter the seat I.D. they would like to book
- Ask the user to enter their age
- Output the price of the seat 5. Ask the user if they wish to proceed with booking (Y/y/N/n)
- Ask the user if they wish to proceed with booking (Y/y/N/n)
Part 4 should be implemented as a nested set of selection statements that implement the following:
Part 5 should call the bookASeat() function passing the seat I.D., if and only if, the user enters ‘Y’ or ‘y’. If the function returns Boolean ‘True’ the program should output, ‘Seat successfully booked’, else it should output ‘Seat already booked’.
The layout of your program code should be as follows at this point:
Task 2: INTERMEDIATE USER INTERACTION
This task involves the development of two further functions and updating the ‘main’ part of the program to implement an iterating menu system.
FUNCTION: getValidSeatID()
This function will add an element of robustness to your user interaction and stop users from attempting to book an invalid seat ID. You should start by setting a variable ‘seatID’ to ‘None’
The function should use a repetition construct to repeatedly ask the user for a seat ID allowing them to cancel booking a seat by typing in ‘CANCEL’ or ‘cancel’ at any point
Within the loop, the function should check the validity of the seat ID, i.e. it correctly matches the format as described in the bookASeat() function description in Task 1 above.
If and ONLY if it does correctly match the required format, then the ‘seatID’ variable should be set to the seat ID entered by the user.
Else, if the user has not typed in ‘CANCEL’ or ‘cancel’, it should output an appropriate error message.
The loop should terminate once a valid seat ID has been entered by the user, or they have typed in ‘CANCEL’ or ‘cancel’ and the ‘seatID’ should be returned in either case.
Appropriate use of ‘try’ and ‘except’ statements will give you the highest marks with regard to robustness.
USER INTERACTION: Menu System
Replace the code in the main section to implement an iterating menu system. DO NOT use a self-calling function to implement the iteration (looping). The menu should be displayed in each iteration and the user is given the opportunity to enter their menu choice, after which appropriate code should be executed depending upon that choice. The menu displayed should be:
- Book a seat
- Cancel a seat booking
- Quit
If choice ‘1’ is chosen, the following should be executed: displaySeats() function is called, then
The code from the ‘user interaction’ sub-task from Task 1 should be placed here with appropriate use of the getValidSeatID() function and the bookASeat() function
if choice ‘2’ is chosen, the following should be executed: getValidSeatID() is called to get a valid seat number if the seat number is None
if the seat is already booked
Change the seat to not booked output “The seat has been released”
else
output “This seat has not been booked”
if choice ‘3’ is chosen, the following should be executed:
Prompt the user for ‘Are you sure Y/N: ‘ and get their input
If their input is ‘y’ or ‘Y’, enable the main menu loop to naturally terminate
DO NOT use exit() to terminate the loop and the program
Else
Output “Invalid menu choice”
The layout of your program code should be as follows at this point:
Task 3: Permanent Changes to the Data: File Input and Output
At this point, you should have noticed that the ‘cinema’ data structure is not affected permanently by the program, as it is hardcoded into the program code. You are to replace the existing ‘cinema’ data structure variable in the global variables section:
With:
cinema = None
You are then to create two new functions and update the main program section to appropriately call them. You should ensure a copy of the ‘cinema.dat’ file (available with this specification on Canvas) is placed in the same folder as your program file.
Function: readCinemaFile()
This function needs global access to the global ‘cinema’ variable The cinema variable should be initialized to an empty list
This function should open the ‘cinema.dat’ file for ‘read’ access
If this is successful, the function should iterate reading in all of the lines of the file
Each line should be iterated over to create a ‘row’ list and each row appended to the ‘cinema’ list
‘0’ (Character zero) should be stored as an integer 0 (zero) in the ‘cinema’ ‘row’
‘1’ (Character one) should be stored as an integer 1 (one) in the ‘cinema’ ‘row’
Appropriate use of ‘try’ and ‘except’ statements will give you the highest marks with regard to robustness.
Function: writeCinemaFile()
This function needs global access to the global ‘cinema’ variable
The function should open the ‘cinema.dat’ file for ‘write’ access – overwriting the existing file
Each row in the ‘cinema’ variable needs to be turned into a string of the following format:
9,9,9,9,9,9,9,9,9,9,9,9nl
The 9 represents the seat and should be set to character ‘0’ (zero) if the seat is available and character ‘1’ if the seat is booked. The ‘nl’ is a “new-line/carriage return”.
Appropriate use of ‘try’ and ‘except’ statements will give you the highest marks with regard to robustness.
Utilizing the File Functions: Main program
Insert a call to the readCinemaFile() function at the beginning of the main program section; before the menu system code.
Insert a call to the writeCinemaFile() function in the menu option ‘1’ code if the bookASeat() function returns True
Insert a call to the writeCinemaFile() function in the menu option ‘2’ code, but only if the seat was booked and has now been released.
Solution:
Task 1:
def bookASeat(seatID):
"""
Assumes that the format of the seatID parameter has a length
of 2 where the first character is A through F and the second
character is 1 to 12.
Given the seatID, we find the corresponding seat location
then book it.
"""
# Convert the seat ID into row and column index
row = ord(seatID[0]) - ord("A")
col = int(seatID[1:]) - 1
# Can't book if the slot is already taken
if cinema[row][col] != 0:
return False
# Take the slot
cinema[row][col] = 1
return True
def displaySeat():
"""
Display the seating arrangement of the cinema showing
available and occupied seats
"""
# Print the screen
print(" ".ljust(4) + "-" * 24 + "SCREEN HERE" + "-" * 24 + "-")
print()
# Print the column labels
print(" ".ljust(4), end="")
for col in range(len(cinema[0])):
print(str(col + 1).ljust(4), end="")
# Print an aisle where it is needed
if col == 2 or col == 8:
print(" ".ljust(7), end="")
print()
# Display the rows and seats for each column
for row in range(len(cinema)):
print(str(chr(row + ord("A"))).ljust(4), end="")
for col in range(len(cinema[row])):
if cinema[row][col] == 0:
print("O".ljust(4), end="")
else:
print("X".ljust(4), end="")
# Print an aisle where it is needed
if col == 2 or col == 8:
print(" ".ljust(7), end="")
print()
# Print a separator if we're going to print next the deluxe seats
if row == 3:
print()
# Display a legend
print()
print("O = Available. X = Booked.".rjust(45))
print("Rows A, B, C & D = Standard Seats Rows E & F = Deluxe Seats")
# Entry point of the program
if __name__ == '__main__':
displaySeat()
# Get a seat to book and age of user
seatID = input("Enter a seat ID to book: ").strip().upper()
age = int(input("Enter age: "))
# Identify the price based on seat and age
if seatID[0] in "ABCD":
# Set standard seat price
if age < 16:
seatPrice = 2.50
elif age >= 65:
seatPrice = 3
else:
seatPrice = 5
elif seatID[0] in "EF":
# Set deluxe seat price
if age < 16:
seatPrice = 5
elif age >= 65:
seatPrice = 5.50
else:
seatPrice = 7.50
# Confirm booking
print("The seat price is " + "{:.2f}".format(seatPrice))
confirmed = input("Would you like to proceed with the booking? (Y/N) ").strip().lower()
if confirmed:
if bookASeat(seatID):
print("Booking confirmed!")
else:
print("Seat ID is already taken.")
print()
displaySeat()
else:
print("Booking cancelled.")
Task 2:
def bookASeat(seatID):
"""
Assumes that the format of the seatID parameter has a length
of 2 where the first character is A through F and the second
character is 1 to 12.
Given the seatID, we find the corresponding seat location
then book it.
"""
# Convert the seat ID into row and column index
row = ord(seatID[0]) - ord("A")
col = int(seatID[1:]) - 1
# Can't book if the slot is already taken
if cinema[row][col] != 0:
return False
# Take the slot
cinema[row][col] = 1
return True
def displaySeat():
"""
Display the seating arrangement of the cinema showing
available and occupied seats
"""
# Print the screen
print(" ".ljust(4) + "-" * 24 + "SCREEN HERE" + "-" * 24 + "-")
print()
# Print the column labels
print(" ".ljust(4), end="")
for col in range(len(cinema[0])):
print(str(col + 1).ljust(4), end="")
# Print an aisle where it is needed
if col == 2 or col == 8:
print(" ".ljust(7), end="")
print()
# Display the rows and seats for each column
for row in range(len(cinema)):
print(str(chr(row + ord("A"))).ljust(4), end="")
for col in range(len(cinema[row])):
if cinema[row][col] == 0:
print("O".ljust(4), end="")
else:
print("X".ljust(4), end="")
# Print an aisle where it is needed
if col == 2 or col == 8:
print(" ".ljust(7), end="")
print()
# Print a separator if we're going to print next the deluxe seats
if row == 3:
print()
# Display a legend
print()
print("O = Available. X = Booked.".rjust(45))
print("Rows A, B, C & D = Standard Seats Rows E & F = Deluxe Seats")
def getValidSeatID():
"""
Forces user to enter a valid seatID
"""
while True:
seatID = input("Enter a seat ID to book: ").strip().upper()
# Stop on cancel
if seatID == "CANCEL":
return None
# Check that column in seat ID is valid
try:
if len(seatID) < 2\
or seatID[0] not in "ABCDEF"\
or int(seatID[1:]) < 1\
or int(seatID[1:]) > 12:
print("Invalid seat ID.")
else:
return seatID
except:
print("Invalid seat ID.")
# Entry point of the program
if __name__ == '__main__':
while True:
# Print a menu for the user to choose what to do
print("MENU")
print("1. Book a seat")
print("2. Cancel a seat booking")
print("3. Quit")
option = input("Option: ")
print()
if option == "1":
# Book a seat
displaySeat()
seatID = getValidSeatID()
if seatID is not None:
age = int(input("Enter age: "))
# Identify the price based on seat and age
if seatID[0] in "ABCD":
# Set standard seat price
if age < 16:
seatPrice = 2.50
elif age >= 65:
seatPrice = 3
else:
seatPrice = 5
elif seatID[0] in "EF":
# Set deluxe seat price
if age < 16:
seatPrice = 5
elif age >= 65:
seatPrice = 5.50
else:
seatPrice = 7.50
# Confirm booking
print("The seat price is " + "{:.2f}".format(seatPrice))
confirmation = input("Would you like to proceed with the booking? (Y/N) ").strip().upper()
if confirmation == "Y":
if bookASeat(seatID):
print("Booking confirmed")
else:
print("Seat ID is already taken")
else:
print("Booking cancelled")
elif option == "2":
# Cancel a booking
seatID = getValidSeatID()
if seatID is not None:
# Convert the seat ID into row and column index
row = ord(seatID[0]) - ord("A")
col = int(seatID[1:]) - 1
if cinema[row][col] == 1:
cinema[row][col] = 0
print("The seat has been released")
else:
print("The seat has not been booked")
elif option == "3":
# Confirm to quit program
confirmation = input("Are you sure? (Y/N) ").strip().upper()
if confirmation == "Y":
break
else:
print("Invalid menu choice")
print()
Task 3:
# Seating arrangements
cinema = None
def readCinemaFile():
"""
Load the seatings from a file
"""
global cinema
cinema = []
inFile = open("cinema.dat", "r")
if inFile:
try:
for line in inFile:
line = line.strip()
row = []
for token in line.split(","):
row.append(int(token))
cinema.append(row)
except:
print("The cinema.dat file is invalid")
finally:
inFile.close()
else:
print("Failed to open cinema.dat file")
def writeCinemaFile():
"""
Write the cinema seating to a file
:return:
"""
try:
outFile = open("cinema.dat", "w")
for row in cinema:
outFile.write(",".join(map(str, row)) + "\n")
outFile.close()
except Exception as ex:
print("Failed to write to cinema.dat file")
finally:
outFile.close()
def bookASeat(seatID):
"""
Assumes that the format of the seatID parameter has a length
of 2 where the first character is A through F and the second
character is 1 to 12.
Given the seatID, we find the corresponding seat location
then book it.
"""
# Convert the seat ID into row and column index
row = ord(seatID[0]) - ord("A")
col = int(seatID[1:]) - 1
# Can't book if the slot is already taken
if cinema[row][col] != 0:
return False
# Take the slot
cinema[row][col] = 1
return True
def displaySeat():
"""
Display the seating arrangement of the cinema showing
available and occupied seats
"""
# Print the screen
print(" ".ljust(4) + "-" * 24 + "SCREEN HERE" + "-" * 24 + "-")
print()
# Print the column labels
print(" ".ljust(4), end="")
for col in range(len(cinema[0])):
print(str(col + 1).ljust(4), end="")
# Print an aisle where it is needed
if col == 2 or col == 8:
print(" ".ljust(7), end="")
print()
# Display the rows and seats for each column
for row in range(len(cinema)):
print(str(chr(row + ord("A"))).ljust(4), end="")
for col in range(len(cinema[row])):
if cinema[row][col] == 0:
print("O".ljust(4), end="")
else:
print("X".ljust(4), end="")
# Print an aisle where it is needed
if col == 2 or col == 8:
print(" ".ljust(7), end="")
print()
# Print a separator if we're going to print next the deluxe seats
if row == 3:
print()
# Display a legend
print()
print("O = Available. X = Booked.".rjust(45))
print("Rows A, B, C & D = Standard Seats Rows E & F = Deluxe Seats")
def getValidSeatID():
"""
Forces user to enter a valid seatID
"""
while True:
seatID = input("Enter a seat ID to book: ").strip().upper()
# Stop on cancel
if seatID == "CANCEL":
return None
# Check that column in seat ID is valid
try:
if len(seatID) < 2\
or seatID[0] not in "ABCDEF"\
or int(seatID[1:]) < 1\
or int(seatID[1:]) > 12:
print("Invalid seat ID.")
else:
return seatID
except:
print("Invalid seat ID.")
# Entry point of the program
if __name__ == '__main__':
readCinemaFile()
while True:
# Print a menu for the user to choose what to do
print("MENU")
print("1. Book a seat")
print("2. Cancel a seat booking")
print("3. Quit")
option = input("Option: ")
print()
if option == "1":
# Book a seat
displaySeat()
seatID = getValidSeatID()
if seatID is not None:
age = int(input("Enter age: "))
# Identify the price based on seat and age
if seatID[0] in "ABCD":
# Set standard seat price
if age < 16:
seatPrice = 2.50
elif age >= 65:
seatPrice = 3
else:
seatPrice = 5
elif seatID[0] in "EF":
# Set deluxe seat price
if age < 16:
seatPrice = 5
elif age >= 65:
seatPrice = 5.50
else:
seatPrice = 7.50
# Confirm booking
print("The seat price is " + "{:.2f}".format(seatPrice))
confirmation = input("Would you like to proceed with the booking? (Y/N) ").strip().upper()
if confirmation == "Y":
if bookASeat(seatID):
print("Booking confirmed")
else:
print("Seat ID is already taken")
else:
print("Booking cancelled")
elif option == "2":
# Cancel a booking
seatID = getValidSeatID()
if seatID is not None:
# Convert the seat ID into row and column index
row = ord(seatID[0]) - ord("A")
col = int(seatID[1:]) - 1
if cinema[row][col] == 1:
cinema[row][col] = 0
print("The seat has been released")
else:
print("The seat has not been booked")
elif option == "3":
# Confirm to quit program
confirmation = input("Are you sure? (Y/N) ").strip().upper()
if confirmation == "Y":
break
else:
print("Invalid menu choice")
print()
writeCinemaFile()