From dc6ec90bb082bc593dbef54f225f32b1660f17e4 Mon Sep 17 00:00:00 2001 From: Nathan <Nathan.baker303@gmail.com> Date: Sun, 10 Nov 2024 08:10:16 +0000 Subject: [PATCH] added menus 'n' stuff to main_cli updated objects and classes --- .idea/.gitignore | 3 + .idea/advanced-software.iml | 12 ++ .idea/git_toolbox_blame.xml | 6 + .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 7 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + main.py | 168 ++++++++++++------ src/__init__.py | 18 +- src/constants.py | 23 ++- src/dbfunc.py | 19 +- src/screenObj.py | 30 ++-- src/staffUser.py | 23 ++- 13 files changed, 226 insertions(+), 103 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/advanced-software.iml create mode 100644 .idea/git_toolbox_blame.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/advanced-software.iml b/.idea/advanced-software.iml new file mode 100644 index 0000000..94219bf --- /dev/null +++ b/.idea/advanced-software.iml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="PYTHON_MODULE" version="4"> + <component name="NewModuleRootManager"> + <content url="file://$MODULE_DIR$" /> + <orderEntry type="jdk" jdkName="Python 3.12" jdkType="Python SDK" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> + <component name="PyDocumentationSettings"> + <option name="format" value="GOOGLE" /> + <option name="myDocStringFormat" value="Google" /> + </component> +</module> \ No newline at end of file diff --git a/.idea/git_toolbox_blame.xml b/.idea/git_toolbox_blame.xml new file mode 100644 index 0000000..7dc1249 --- /dev/null +++ b/.idea/git_toolbox_blame.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="GitToolBoxBlameSettings"> + <option name="version" value="2" /> + </component> +</project> \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ +<component name="InspectionProjectProfileManager"> + <settings> + <option name="USE_PROJECT_PROFILE" value="false" /> + <version value="1.0" /> + </settings> +</component> \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..db8786c --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="Black"> + <option name="sdkName" value="Python 3.12" /> + </component> + <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12" project-jdk-type="Python SDK" /> +</project> \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..6e98194 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ProjectModuleManager"> + <modules> + <module fileurl="file://$PROJECT_DIR$/.idea/advanced-software.iml" filepath="$PROJECT_DIR$/.idea/advanced-software.iml" /> + </modules> + </component> +</project> \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="VcsDirectoryMappings"> + <mapping directory="" vcs="Git" /> + </component> +</project> \ No newline at end of file diff --git a/main.py b/main.py index a505e98..0a76411 100644 --- a/main.py +++ b/main.py @@ -1,93 +1,147 @@ +import logging +logging.basicConfig(level=logging.DEBUG, format="{asctime} - {levelname} - {message}", style="{", datefmt="%Y-%m-%d %H:%M") from src import * - - - - - - - """_summary_ -- logic should be seprate from the GUI +- logic should be separate from the GUI - this file handles interfacing with the database and classes. -- most functionalisty should also be here +- most functionality should also be here - using main() as a test function during development, and after can be used as a CLI version of the program. -'idealy there should be a sort of intermeditary between the GUI and database, for example last year most groups queried the database directly from tkintet, although thats not ideal.' - lecturer idk there name +'ideally there should be a sort of intermediary between the GUI and database, for example last year most groups queried the database directly from tkinter, although that's not ideal.' - lecturer idk there name 'you should be able to make python classes directly from your class diagram' - same lecturer """ -def loginAttempt(username, password): +def loginAttempt(username: str, password: str) -> StaffUser | ManagerUser | AdminUser | None: """_summary_ - quereies database for matching args + queries database for matching args returns user(staff, admin or manager) obj if found else returns None type. Args: - username (_type_): _description_ - password (_type_): _description_ - - Returns: - staffUser: _description_ - or - None + username (str): encrypted username + password (str): encrypted password """ - return True # testing passthrough - + del_later = StaffUser() + del_later.userName = username + del_later.userPass = password + return del_later + +def staffUser_options_cli(user:StaffUser) -> None: + selection = True + while selection: + selection = input("Menu options:\n" + " 1. View Listings \n" + " 2. Create booking \n" + " 3. Logout \n" + " please return a number to select: ") + # switch case: + if selection == "1": + logging.debug("selection 1, View listings") + user.viewFilmListings() + # get from cinema the listings and display film data in dict/jason + # user.viewFilmListings() + # format and display data + elif selection == "2": + logging.debug("selection 2, Create booking") + # create booking obj and display attributes for selection + # save booking to cinema and db + # user.createBooking() + elif selection == "3": + logging.debug("selection 3, logout") + user.logout() + exit() + else: + print("Invalid input, please input an integer value corresponding with an option.") + selection = True + +def managerUser_options_cli(user:ManagerUser) -> None: + selection = True + while selection: + selection = input("Menu options:\n" + " 1. View Listings \n" + " 2. Create booking \n" + " 3. Logout \n" + " please return a number to select: ") + # switch case: + if selection == "1": + logging.debug("selection 1, View listings") + elif selection == "2": + logging.debug("selection 2, Create booking") + elif selection == "3": + logging.debug("selection 3, logout") + user.logout() + exit() + else: + print("Invalid input, please input an integer value corresponding with an option.") + selection = False + +def adminUser_options_cli(user:AdminUser) -> None: + selection = True + while selection: + selection = input("Menu options:\n" + " 1. View Listings \n" + " 2. Create booking \n" + " 3. Logout \n" + " please return a number to select: ") + # switch case: + if selection == "1": + logging.debug("selection 1, View listings") + elif selection == "2": + logging.debug("selection 2, Create booking") + elif selection == "3": + logging.debug("selection 3, logout") + user.logout() + exit() + else: + print("Invalid input, please input an integer value corresponding with an option.") + selection = False -def logout(): +def load_cinema(cinemaID) -> Cinema: pass -def load_cinema(): - pass +def san(string:str) -> str: + """ + String sanitization function + Args: + string (str): string variable to be sanitized. + Returns: + string but without any escape chars + """ + return string.strip().replace('/', '_').replace('\\', '_') def save(): pass -def cli_main() -> None: - print("\n\nSTARTING CINEMA MANAGEMENT SYSTEM.\n\n\n\n") +def main_cli() -> None: + print("\n\nSTARTING CINEMA MANAGEMENT SYSTEM.\n\n") + # test db is connected.... +# if not getConnection(): +# logging.critical("Database cannot connect, or dose not exist. \nClosing application.") +# exit() user = None - while user == None: + while user is None: username = str(input("To login please enter your\nUsername: ")) password = str(input("Password: ")) user = loginAttempt(username=username, password=password) - if user == None: + if user is None: print("Login attempt failed please try again.") else: break - print("successful login, loading menue...") - # load user - # load cinema/s that user is linked to - #cinema = Cinema() - # display options - selection = input("Menue options:\n\ - 1. Veiw Listings \n\ - 2. Create booking \n\ - 3. Logout \n\ - please return a number to select: ") - # switch case: - if selection == "1": - print("1") - # get from cinema the listings and display film data in dict/jason - # user.veiwFilmListings() - # format and display data - pass - elif selection == "2": - print("2") - # create booking obj and display attributes for selection - # save booking to cinema and db - # user.createBooking() - pass - elif selection == "3": - print("3") - #user.logout() - pass - + print("successful login, loading menu...") + user.login() + + if user.permissionLevel == 1: + managerUser_options_cli(user) + elif user.permissionLevel == 2: + adminUser_options_cli(user) + else: + staffUser_options_cli(user) # following code will only execute if run directly from this file. if __name__ == "__main__": - cli_main() \ No newline at end of file + main_cli() \ No newline at end of file diff --git a/src/__init__.py b/src/__init__.py index d3718c6..c20c3f1 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1,13 +1,14 @@ -from .staffUser import * -from .adminUser import * -from .cinemaObj import * -from .managerUser import * -from .bookingObj import * -from .reportObj import * -from .screenObj import * +from .staffUser import StaffUser +from .adminUser import AdminUser +from .cinemaObj import Cinema +from .managerUser import ManagerUser +from .bookingObj import Booking +from .reportObj import Report +from .screenObj import Screen from .constants import * from .dbfunc import * +""" __all__ = ["adminUser", "bookingObj", "cinemaObj", @@ -17,4 +18,5 @@ __all__ = ["adminUser", "managerUser", "reportObj", "screenObj", - "staffUser"] \ No newline at end of file + "staffUser"] +""" \ No newline at end of file diff --git a/src/constants.py b/src/constants.py index ffd8f86..dc652f5 100644 --- a/src/constants.py +++ b/src/constants.py @@ -1,10 +1,15 @@ +# all constants are followed by docstrings labeling them, these strings show on hover in most IDEs(vscode and pycharm at least) -# screeen size in meaters -MAX_screen_size:float = 100.0 -MIN_screen_size:float = 0.0 -# screen resolution in px -MAX_screen_resolution:int = 5000 -MIN_screen_resolution:int = 0 -# seating capacity in screen room -MAX_screen_capacity:int = 500 -MIN_screen_capacity:int = 0 +# screenObj: +MAX_SIZE:float = 100.0 +"""Maximum screen size in meters""" +MIN_SIZE:float = 0.0 +"""Minimum screen size in meters""" +MAX_RES:int = 5000 +"""Maximum screen resolution in px""" +MIN_RES:int = 0 +"""Minimum screen resolution in px""" +MAX_CAP:int = 500 +"""Maximum screen room seating capacity""" +MIN_CAP:int = 0 +"""Minimum screen room seating capacity""" diff --git a/src/dbfunc.py b/src/dbfunc.py index 229334e..bb66166 100644 --- a/src/dbfunc.py +++ b/src/dbfunc.py @@ -1,3 +1,4 @@ +import logging import mysql.connector from mysql.connector import errorcode @@ -8,7 +9,7 @@ passwd = "" def getConnection(db=""): - # if specifyed database + # if specified database if db != "": try: @@ -18,15 +19,15 @@ def getConnection(db=""): database = db) except mysql.connector.Error as err: if err.errno == errorcode.ER_ACCESS_DENIED_ERROR: - print("Username or Password is not working") + logging.error("Username or Password is not working") elif err.errno == errorcode.ER_BAD_DB_ERROR: - print("Database dose not exist") + logging.error("Database dose not exist") else: - print(err) + logging.error(err) else: - print("Connected to server.") + logging.info("Connected to server.") return conn - # if database not specifyed try defult from line 5 + # if database not specified try default from line 5 else: try: conn = mysql.connector.connect(host = hostname, @@ -34,9 +35,9 @@ def getConnection(db=""): password = passwd) except mysql.connector.Error as err: if err.errno == errorcode.ER_ACCESS_DENIED_ERROR: - print("Username or Password is not working") + logging.error("Username or Password is not working") else: - print(err) + logging.error(err) else: - print("Connected to server, without database.") + logging.error("Connected to server, without database.") return conn \ No newline at end of file diff --git a/src/screenObj.py b/src/screenObj.py index 497576c..efcbae7 100644 --- a/src/screenObj.py +++ b/src/screenObj.py @@ -1,4 +1,4 @@ -from .constants import MIN_screen_capacity, MAX_screen_capacity, MIN_screen_resolution, MAX_screen_resolution, MIN_screen_size, MAX_screen_size +from .constants import MIN_CAP, MAX_CAP, MIN_RES, MAX_RES, MIN_SIZE, MAX_SIZE class Screen(object): """_summary_ @@ -6,14 +6,14 @@ class Screen(object): Args: object (_type_): _description_ """ - def __init__(self, id:int, capacity:int=0, sizeH:int=0, sizeW:int=0, resolutionH:float=0.0, resolutionW:float=0.0, isIMAX:bool=False) -> None: - self.id = id - self.capacity:int = capacity - self.screenSizeHeight:int = sizeH - self.screenSizeWidth:int = sizeW - self.screenResolutionHeight = resolutionH - self.screenResolutionWidth = resolutionW - self.isIMAX:bool = isIMAX + def __init__(self) -> None: + self.id = 0 + self.capacity: int = 0 + self.screenSizeHeight: int = 0 + self.screenSizeWidth: int = 0 + self.screenResolutionHeight: int = 0 + self.screenResolutionWidth: int = 0 + self.isIMAX: bool = False def __str__(self) -> str: return f"Screen(id={self.id}, capacity={self.capacity}, screenSize={self.screenSize}, screenResolution={self.screenResolution}, isIMAX={self.isIMAX})" @@ -28,27 +28,27 @@ class Screen(object): # Getters, inherited from Object class # Setters def set_capacity(self, value:int) -> None: - if MIN_screen_capacity >= value >= MAX_screen_capacity: + if MIN_CAP >= value >= MAX_CAP: self.capacity = value else: # log - print(f"Error; input({value}) out of range {MIN_screen_capacity}-{MAX_screen_capacity}.") + print(f"Error; input({value}) out of range {MIN_CAP}-{MAX_CAP}.") def set_screen_size(self, height:float, width:float) -> None: - if MIN_screen_size >= height >= MAX_screen_size or MIN_screen_size >= width >= MAX_screen_size: + if MIN_SIZE >= height >= MAX_SIZE or MIN_SIZE >= width >= MAX_SIZE: self.screenSizeHeight = float(height) self.screenSizeWidth = float(width) else: # log - print(f"Error, input values:{height}m, {width}m out of bounds {MIN_screen_size}-{MAX_screen_size}m") + print(f"Error, input values:{height}m, {width}m out of bounds {MIN_SIZE}-{MAX_SIZE}m") def set_screen_resolution(self, height:int, width:int) -> None: - if MIN_screen_resolution >= height >= MAX_screen_resolution or MIN_screen_resolution >= width >= MAX_screen_resolution: + if MIN_RES >= height >= MAX_RES or MIN_RES >= width >= MAX_RES: self.screenSizeHeight = height self.screenSizeWidth = width else: # log - print(f"Error, input values:{width}x{height}p out of bounds {MIN_screen_resolution}-{MAX_screen_resolution}") + print(f"Error, input values:{width}x{height}p out of bounds {MIN_RES}-{MAX_RES}") diff --git a/src/staffUser.py b/src/staffUser.py index bc22794..eed2bbe 100644 --- a/src/staffUser.py +++ b/src/staffUser.py @@ -8,6 +8,7 @@ class StaffUser(object): self.userName:str = self.encrypt("") self.userPass:str = self.encrypt("") self.permissionLevel:int = 0 + self.cinemas = [0] def __str__(self): if self.permissionLevel == 1: @@ -18,19 +19,31 @@ class StaffUser(object): userType = "BookingStaff" return f"{userType} user object(userID={self.userID}, userName={self.userName}, userPass={self.userPass})" +# @property +# def options_list(self) -> dict: +# """_summary_ +# functions in a dict, to be used as labels and callable function pairs +# Returns: +# dict: _description_ +# """ +# options:dict = {"View film Listings":self.viewFilmListing, "Create booking":self.createBooking, "Logout":self.logout} +# return options + def login(self): - pass + print("this is the login func") def logout(self): pass - def veiwFilmListing(self, cinemaID): - pass + def viewFilmListings(self): + print("this is the viewFilmListing func") + # load cinema.showings + listing_format = f"" def createBooking(self): - pass + print("this is the createBooking func") - def manageBooking(): + def manageBooking(self): pass def encrypt(self, inputString): -- GitLab