1+ # Name: Abdiaziz Bishar Hussein
2+ # Description: A terminal-based personal movie catalog manager using OOP, file handling, and collections.
3+
4+ from dataclasses import dataclass
5+
6+ @dataclass
7+ class CatalogItem :
8+ """Represents a single item in the catalog."""
9+ title : str
10+ year : int
11+
12+ def __str__ (self ) -> str :
13+ """Optional: Custom string representation for nicer printing."""
14+ return f"{ self .title } ({ self .year } )"
15+
16+
17+ class Catalog :
18+ """Manages a collection of CatalogItem objects."""
19+ def __init__ (self ):
20+ self .items : list [CatalogItem ] = []
21+
22+ def add_item (self , item : CatalogItem ) -> None :
23+ """Adds a CatalogItem to the internal list."""
24+ self .items .append (item )
25+
26+ def list_all (self ) -> None :
27+ """Prints all items in a readable format."""
28+ if not self .items :
29+ print ("\n Your catalog is currently empty." )
30+ return
31+
32+ print ("\n --- Current Catalog Items ---" )
33+ for index , item in enumerate (self .items , 1 ):
34+ print (f"{ index } . { item } " )
35+ print ("----------------------------" )
36+
37+
38+ def load_catalog (path : str , catalog : Catalog ) -> None :
39+ """Loads catalog data from a text file. Handles FileNotFoundError gracefully."""
40+ try :
41+ with open (path , "r" , encoding = "utf-8" ) as file :
42+ for line in file :
43+ # Strip newline characters and skip empty lines
44+ cleaned_line = line .strip ()
45+ if not cleaned_line :
46+ continue
47+
48+ # Split line by the pipe character
49+ title , year_str = cleaned_line .split ("|" )
50+
51+ # Create the item and add it to the catalog
52+ item = CatalogItem (title = title , year = int (year_str ))
53+ catalog .add_item (item )
54+ print (f"\n [System] Successfully loaded data from { path } ." )
55+ except FileNotFoundError :
56+ # If missing, do nothing and start with an empty catalog as required
57+ print (f"\n [System] '{ path } ' not found. Starting with a fresh catalog." )
58+ except (ValueError , IndexError ):
59+ print (f"\n [Warning] Found corrupted data line in '{ path } '. Skipping bad entry." )
60+
61+
62+ def save_catalog (path : str , catalog : Catalog ) -> None :
63+ """Saves the catalog items back to the text file using the 'title|year' format."""
64+ with open (path , "w" , encoding = "utf-8" ) as file :
65+ for item in catalog .items :
66+ file .write (f"{ item .title } |{ item .year } \n " )
67+ print (f"[System] Catalog successfully saved to '{ path } '." )
68+
69+
70+ def main ():
71+ # Initialize the catalog tracking object
72+ catalog = Catalog ()
73+ data_file = "catalog_data.txt"
74+
75+ # Load any existing data before entering the interactive loop
76+ load_catalog (data_file , catalog )
77+
78+ while True :
79+ print ("\n My Catalog — Movies" )
80+ print ("1) Add 2) List 3) Save 4) Quit" )
81+
82+ choice = input ("Pick (1-4): " ).strip ()
83+
84+ if choice == "1" :
85+ title = input ("Title: " ).strip ()
86+ if not title :
87+ print ("Title cannot be empty. Item not added." )
88+ continue
89+
90+ try :
91+ year = int (input ("Year: " ).strip ())
92+ new_item = CatalogItem (title = title , year = year )
93+ catalog .add_item (new_item )
94+ print (f"Added: { new_item } " )
95+ except ValueError :
96+ print ("Invalid input. Year must be a valid integer. Item not added." )
97+
98+ elif choice == "2" :
99+ catalog .list_all ()
100+
101+ elif choice == "3" :
102+ save_catalog (data_file , catalog )
103+
104+ elif choice == "4" :
105+ print ("\n Saving final changes..." )
106+ save_catalog (data_file , catalog )
107+ print ("Saved. Bye!" )
108+ break
109+
110+ else :
111+ print ("Invalid choice. Please select an option between 1 and 4." )
112+
113+
114+ if __name__ == "__main__" :
115+ main ()
0 commit comments