Week 6 Assignment
Variant 1: Student Course Tracker
A university needs a system to manage student course enrollments. The system should log every enrollment action, validate course codes, compute GPA, and support creating students from registration strings.
- Write a decorator
log_action(func)that defines awrapper(*args, **kwargs)inside. The wrapper should print"[ACTION] {func.__name__} executed", call the original function with the same arguments, and return its result. - Create a class
Studentwith:__init__(self, name, student_id)— stores the student’s name, student ID, and initializes an empty dictionary_courses(course_code → grade as an integer).- A class variable
_total_studentsstarting at0, incremented in__init__each time a new student is created. - An instance method
enroll(self, course_code, grade)decorated with@log_action— convertscourse_codeto uppercase, then adds it to_courseswith the given grade. Returns the string"{name} enrolled in {course_code} with grade {grade}". - An instance method
gpa(self)— computes and returns the average of all grades in_courses, rounded to 1 decimal place. If no courses exist, returns0.0. - An instance method
best_course(self)— returns the course code with the highest grade. If no courses exist, returns"No courses". - A class method
from_registration(cls, data)— takes a string in the format"Name-ID"(e.g.,"Dilshod-2612345"), splits it, and returns a newStudentobject. - A static method
is_valid_id(student_id)— returnsTrueif the student ID is exactly 7 characters long and all characters are digits,Falseotherwise. - A class method
total_students(cls)— returns_total_students.
Input
s1 = Student("Aziza", "2601001")
s1.enroll("math101", 85)
s1.enroll("phys201", 92)
s1.enroll("eng102", 78)
s2 = Student.from_registration("Jasur-2601002")
s2.enroll("CS101", 95)
s2.enroll("math101", 88)
print(f"{s1.name}: GPA = {s1.gpa()}, Best = {s1.best_course()}")
print(f"{s2.name}: GPA = {s2.gpa()}, Best = {s2.best_course()}")
print(f"Valid ID '2601001': {Student.is_valid_id('2601001')}")
print(f"Valid ID '26A': {Student.is_valid_id('26A')}")
print(f"Total students: {Student.total_students()}")
Expected Output
[ACTION] enroll executed
[ACTION] enroll executed
[ACTION] enroll executed
[ACTION] enroll executed
[ACTION] enroll executed
Aziza: GPA = 85.0, Best = PHYS201
Jasur: GPA = 91.5, Best = CS101
Valid ID '2601001': True
Valid ID '26A': False
Total students: 2
Variant 2: Product Inventory System
A warehouse needs a system to manage product inventory. The system should log stock changes, validate product codes, compute total inventory value, and support creating products from catalog strings.
- Write a decorator
track_change(func)that defines awrapper(*args, **kwargs)inside. The wrapper should call the original function with the same arguments, capture its return value, print"[STOCK] {return_value}", and return the result. - Create a class
Productwith:__init__(self, name, price, quantity)— stores the product name, price (float), and quantity (int).- A class variable
_all_products— an empty list that collects everyProductinstance created (appendselfin__init__). - An instance method
restock(self, amount)decorated with@track_change— addsamounttoquantityand returns the string"{name}: added {amount}, now {quantity}". - An instance method
sell(self, amount)decorated with@track_change— ifamountis greater thanquantity, returns the string"Not enough {name} in stock"without changing quantity. Otherwise, subtractsamountfromquantityand returns"{name}: sold {amount}, now {quantity}". - An instance method
total_value(self)— returnsprice * quantityrounded to 2 decimal places. - A class method
from_catalog(cls, entry)— takes a string in the format"Name:Price:Quantity"(e.g.,"Laptop:999.99:10"), parses it, converts price to float and quantity to int, and returns a newProduct. - A static method
is_valid_code(code)— returnsTrueifcodestarts with"PRD-"and the rest are digits (e.g.,"PRD-001"),Falseotherwise. - A class method
warehouse_value(cls)— returns the sum oftotal_value()for all products in_all_products, rounded to 2 decimal places.
Input
p1 = Product("Keyboard", 45.50, 20)
p2 = Product.from_catalog("Monitor:299.99:5")
p1.restock(10)
p1.sell(25)
p1.sell(50)
p2.sell(2)
print(f"{p1.name}: value = ${p1.total_value()}")
print(f"{p2.name}: value = ${p2.total_value()}")
print(f"Valid code 'PRD-001': {Product.is_valid_code('PRD-001')}")
print(f"Valid code 'ABC-123': {Product.is_valid_code('ABC-123')}")
print(f"Warehouse total: ${Product.warehouse_value()}")
Expected Output
[STOCK] Keyboard: added 10, now 30
[STOCK] Keyboard: sold 25, now 5
[STOCK] Not enough Keyboard in stock
[STOCK] Monitor: sold 2, now 3
Keyboard: value = $227.5
Monitor: value = $899.97
Valid code 'PRD-001': True
Valid code 'ABC-123': False
Warehouse total: $1127.47
Variant 3: Library Book Manager
A library needs a system to manage book borrowing. The system should log borrow and return actions, validate ISBNs, compute availability, and support creating books from catalog entries.
- Write a decorator
log_operation(func)that defines awrapper(*args, **kwargs)inside. The wrapper should call the original function with the same arguments, capture its return value. If the return value isTrue, print"[OK] {func.__name__} successful". IfFalse, print"[FAIL] {func.__name__} denied". Return the result. - Create a class
Bookwith:__init__(self, title, total_copies)— stores the title, total number of copies (int), initializes_borrowedto0, and appendsselfto the class variable_library.- A class variable
_library— an empty list that collects everyBookinstance created. - An instance method
borrow(self)decorated with@log_operation— if_borrowedis already equal tototal_copies, returnsFalse. Otherwise, increments_borrowedby 1 and returnsTrue. - An instance method
return_book(self)decorated with@log_operation— if_borrowedis0, returnsFalse. Otherwise, decrements_borrowedby 1 and returnsTrue. - An instance method
available(self)— returnstotal_copies - _borrowed. - An instance method
usage_percent(self)— returns the percentage of copies currently borrowed, rounded to 1 decimal place (e.g., 2 borrowed out of 5 total →40.0). - A class method
from_entry(cls, entry)— takes a string in the format"Title:Copies"(e.g.,"Python Basics:3"), parses it, converts copies to int, and returns a newBook. - A static method
is_valid_isbn(isbn)— returnsTrueifisbnis exactly 13 characters long and all characters are digits,Falseotherwise. - A class method
total_available(cls)— returns the total number of available (not borrowed) copies across all books in_library.
Input
b1 = Book("Data Structures", 2)
b2 = Book.from_entry("Algorithms:3")
b1.borrow()
b1.borrow()
b1.borrow()
b1.return_book()
b2.borrow()
b2.return_book()
b2.return_book()
print(f"{b1.title}: available = {b1.available()}, usage = {b1.usage_percent()}%")
print(f"{b2.title}: available = {b2.available()}, usage = {b2.usage_percent()}%")
print(f"Valid ISBN '9781234567890': {Book.is_valid_isbn('9781234567890')}")
print(f"Valid ISBN '978-12345': {Book.is_valid_isbn('978-12345')}")
print(f"Total available in library: {Book.total_available()}")
Expected Output
[OK] borrow successful
[OK] borrow successful
[FAIL] borrow denied
[OK] return_book successful
[OK] borrow successful
[OK] return_book successful
[FAIL] return_book denied
Data Structures: available = 1, usage = 50.0%
Algorithms: available = 3, usage = 0.0%
Valid ISBN '9781234567890': True
Valid ISBN '978-12345': False
Total available in library: 4
Variant 4: Employee Task Tracker
A company needs a system to manage employee task assignments. The system should log every task assignment, validate employee codes, compute average performance scores, and support creating employees from HR records.
- Write a decorator
log_action(func)that defines awrapper(*args, **kwargs)inside. The wrapper should print"[ACTION] {func.__name__} executed", call the original function with the same arguments, and return its result. - Create a class
Employeewith:__init__(self, name, emp_code)— stores the employee’s name, employee code, and initializes an empty dictionary_tasks(task_name → score as an integer).- A class variable
_total_employeesstarting at0, incremented in__init__each time a new employee is created. - An instance method
assign_task(self, task_name, score)decorated with@log_action— convertstask_nameto uppercase, then adds it to_taskswith the given score. Returns the string"{name} assigned {task_name} with score {score}". - An instance method
avg_score(self)— computes and returns the average of all scores in_tasks, rounded to 1 decimal place. If no tasks exist, returns0.0. - An instance method
top_task(self)— returns the task name with the highest score. If no tasks exist, returns"No tasks". - A class method
from_record(cls, data)— takes a string in the format"Name-Code"(e.g.,"Sardor-3301001"), splits it, and returns a newEmployeeobject. - A static method
is_valid_code(emp_code)— returnsTrueif the employee code is exactly 7 characters long and all characters are digits,Falseotherwise. - A class method
total_employees(cls)— returns_total_employees.
Input
e1 = Employee("Sardor", "3301001")
e1.assign_task("report", 90)
e1.assign_task("analysis", 76)
e1.assign_task("design", 84)
e2 = Employee.from_record("Kamola-3301002")
e2.assign_task("Testing", 88)
e2.assign_task("review", 95)
print(f"{e1.name}: Avg = {e1.avg_score()}, Top = {e1.top_task()}")
print(f"{e2.name}: Avg = {e2.avg_score()}, Top = {e2.top_task()}")
print(f"Valid code '3301001': {Employee.is_valid_code('3301001')}")
print(f"Valid code '33B': {Employee.is_valid_code('33B')}")
print(f"Total employees: {Employee.total_employees()}")
Expected Output
[ACTION] assign_task executed
[ACTION] assign_task executed
[ACTION] assign_task executed
[ACTION] assign_task executed
[ACTION] assign_task executed
Sardor: Avg = 83.3, Top = REPORT
Kamola: Avg = 91.5, Top = REVIEW
Valid code '3301001': True
Valid code '33B': False
Total employees: 2
Variant 5: Athlete Training Tracker
A sports academy needs a system to manage athlete training sessions. The system should log every training session, validate athlete IDs, compute average intensity, and support creating athletes from roster strings.
- Write a decorator
log_action(func)that defines awrapper(*args, **kwargs)inside. The wrapper should print"[ACTION] {func.__name__} executed", call the original function with the same arguments, and return its result. - Create a class
Athletewith:__init__(self, name, athlete_id)— stores the athlete’s name, athlete ID, and initializes an empty dictionary_sessions(exercise_name → intensity as an integer).- A class variable
_total_athletesstarting at0, incremented in__init__each time a new athlete is created. - An instance method
add_session(self, exercise, intensity)decorated with@log_action— convertsexerciseto uppercase, then adds it to_sessionswith the given intensity. Returns the string"{name} trained {exercise} at intensity {intensity}". - An instance method
avg_intensity(self)— computes and returns the average of all intensity values in_sessions, rounded to 1 decimal place. If no sessions exist, returns0.0. - An instance method
hardest_session(self)— returns the exercise name with the highest intensity. If no sessions exist, returns"No sessions". - A class method
from_roster(cls, data)— takes a string in the format"Name-ID"(e.g.,"Bobur-5501001"), splits it, and returns a newAthleteobject. - A static method
is_valid_id(athlete_id)— returnsTrueif the athlete ID is exactly 7 characters long and all characters are digits,Falseotherwise. - A class method
total_athletes(cls)— returns_total_athletes.
Input
a1 = Athlete("Bobur", "5501001")
a1.add_session("sprints", 95)
a1.add_session("weights", 80)
a1.add_session("swimming", 70)
a2 = Athlete.from_roster("Nilufar-5501002")
a2.add_session("Cycling", 82)
a2.add_session("sprints", 91)
print(f"{a1.name}: Avg = {a1.avg_intensity()}, Hardest = {a1.hardest_session()}")
print(f"{a2.name}: Avg = {a2.avg_intensity()}, Hardest = {a2.hardest_session()}")
print(f"Valid ID '5501001': {Athlete.is_valid_id('5501001')}")
print(f"Valid ID '55X': {Athlete.is_valid_id('55X')}")
print(f"Total athletes: {Athlete.total_athletes()}")
Expected Output
[ACTION] add_session executed
[ACTION] add_session executed
[ACTION] add_session executed
[ACTION] add_session executed
[ACTION] add_session executed
Bobur: Avg = 81.7, Hardest = SPRINTS
Nilufar: Avg = 86.5, Hardest = SPRINTS
Valid ID '5501001': True
Valid ID '55X': False
Total athletes: 2
Variant 6: Chef Recipe Tracker
A culinary school needs a system to manage chef recipe submissions. The system should log every recipe submission, validate chef license numbers, compute average ratings, and support creating chefs from enrollment strings.
- Write a decorator
log_action(func)that defines awrapper(*args, **kwargs)inside. The wrapper should print"[ACTION] {func.__name__} executed", call the original function with the same arguments, and return its result. - Create a class
Chefwith:__init__(self, name, license_no)— stores the chef’s name, license number, and initializes an empty dictionary_recipes(recipe_name → rating as an integer).- A class variable
_total_chefsstarting at0, incremented in__init__each time a new chef is created. - An instance method
submit_recipe(self, recipe_name, rating)decorated with@log_action— convertsrecipe_nameto uppercase, then adds it to_recipeswith the given rating. Returns the string"{name} submitted {recipe_name} rated {rating}". - An instance method
avg_rating(self)— computes and returns the average of all ratings in_recipes, rounded to 1 decimal place. If no recipes exist, returns0.0. - An instance method
best_recipe(self)— returns the recipe name with the highest rating. If no recipes exist, returns"No recipes". - A class method
from_enrollment(cls, data)— takes a string in the format"Name-License"(e.g.,"Zulfiya-7701001"), splits it, and returns a newChefobject. - A static method
is_valid_license(license_no)— returnsTrueif the license number is exactly 7 characters long and all characters are digits,Falseotherwise. - A class method
total_chefs(cls)— returns_total_chefs.
Input
c1 = Chef("Zulfiya", "7701001")
c1.submit_recipe("plov", 93)
c1.submit_recipe("lagman", 87)
c1.submit_recipe("shashlik", 79)
c2 = Chef.from_enrollment("Otabek-7701002")
c2.submit_recipe("Somsa", 96)
c2.submit_recipe("manti", 85)
print(f"{c1.name}: Avg = {c1.avg_rating()}, Best = {c1.best_recipe()}")
print(f"{c2.name}: Avg = {c2.avg_rating()}, Best = {c2.best_recipe()}")
print(f"Valid license '7701001': {Chef.is_valid_license('7701001')}")
print(f"Valid license '77Z': {Chef.is_valid_license('77Z')}")
print(f"Total chefs: {Chef.total_chefs()}")
Expected Output
[ACTION] submit_recipe executed
[ACTION] submit_recipe executed
[ACTION] submit_recipe executed
[ACTION] submit_recipe executed
[ACTION] submit_recipe executed
Zulfiya: Avg = 86.3, Best = PLOV
Otabek: Avg = 90.5, Best = SOMSA
Valid license '7701001': True
Valid license '77Z': False
Total chefs: 2
Variant 7: Medicine Inventory System
A pharmacy needs a system to manage medicine stock. The system should log stock changes, validate medicine codes, compute total inventory value, and support creating medicines from supplier lists.
- Write a decorator
track_change(func)that defines awrapper(*args, **kwargs)inside. The wrapper should call the original function with the same arguments, capture its return value, print"[STOCK] {return_value}", and return the result. - Create a class
Medicinewith:__init__(self, name, price, quantity)— stores the medicine name, price (float), and quantity (int).- A class variable
_all_medicines— an empty list that collects everyMedicineinstance created (appendselfin__init__). - An instance method
receive(self, amount)decorated with@track_change— addsamounttoquantityand returns the string"{name}: received {amount}, now {quantity}". - An instance method
dispense(self, amount)decorated with@track_change— ifamountis greater thanquantity, returns the string"Not enough {name} available"without changing quantity. Otherwise, subtractsamountfromquantityand returns"{name}: dispensed {amount}, now {quantity}". - An instance method
total_value(self)— returnsprice * quantityrounded to 2 decimal places. - A class method
from_supplier(cls, entry)— takes a string in the format"Name:Price:Quantity"(e.g.,"Aspirin:12.50:100"), parses it, converts price to float and quantity to int, and returns a newMedicine. - A static method
is_valid_code(code)— returnsTrueifcodestarts with"MED-"and the rest are digits (e.g.,"MED-045"),Falseotherwise. - A class method
pharmacy_value(cls)— returns the sum oftotal_value()for all medicines in_all_medicines, rounded to 2 decimal places.
Input
m1 = Medicine("Paracetamol", 8.75, 50)
m2 = Medicine.from_supplier("Ibuprofen:12.30:30")
m1.receive(20)
m1.dispense(45)
m1.dispense(100)
m2.dispense(10)
print(f"{m1.name}: value = ${m1.total_value()}")
print(f"{m2.name}: value = ${m2.total_value()}")
print(f"Valid code 'MED-045': {Medicine.is_valid_code('MED-045')}")
print(f"Valid code 'RX-100': {Medicine.is_valid_code('RX-100')}")
print(f"Pharmacy total: ${Medicine.pharmacy_value()}")
Expected Output
[STOCK] Paracetamol: received 20, now 70
[STOCK] Paracetamol: dispensed 45, now 25
[STOCK] Not enough Paracetamol available
[STOCK] Ibuprofen: dispensed 10, now 20
Paracetamol: value = $218.75
Ibuprofen: value = $246.0
Valid code 'MED-045': True
Valid code 'RX-100': False
Pharmacy total: $464.75
Variant 8: Food Supply Tracker
A restaurant chain needs a system to manage food ingredient supplies. The system should log supply changes, validate supplier codes, compute total supply cost, and support creating ingredients from order forms.
- Write a decorator
track_change(func)that defines awrapper(*args, **kwargs)inside. The wrapper should call the original function with the same arguments, capture its return value, print"[STOCK] {return_value}", and return the result. - Create a class
Ingredientwith:__init__(self, name, cost_per_unit, units)— stores the ingredient name, cost per unit (float), and units (int).- A class variable
_all_ingredients— an empty list that collects everyIngredientinstance created (appendselfin__init__). - An instance method
order(self, amount)decorated with@track_change— addsamounttounitsand returns the string"{name}: ordered {amount}, now {units}". - An instance method
use(self, amount)decorated with@track_change— ifamountis greater thanunits, returns the string"Not enough {name} in kitchen"without changing units. Otherwise, subtractsamountfromunitsand returns"{name}: used {amount}, now {units}". - An instance method
total_cost(self)— returnscost_per_unit * unitsrounded to 2 decimal places. - A class method
from_order_form(cls, entry)— takes a string in the format"Name:Cost:Units"(e.g.,"Flour:2.50:40"), parses it, converts cost to float and units to int, and returns a newIngredient. - A static method
is_valid_code(code)— returnsTrueifcodestarts with"ING-"and the rest are digits (e.g.,"ING-012"),Falseotherwise. - A class method
kitchen_value(cls)— returns the sum oftotal_cost()for all ingredients in_all_ingredients, rounded to 2 decimal places.
Input
i1 = Ingredient("Rice", 3.20, 60)
i2 = Ingredient.from_order_form("Olive Oil:15.75:8")
i1.order(15)
i1.use(50)
i1.use(100)
i2.use(3)
print(f"{i1.name}: cost = ${i1.total_cost()}")
print(f"{i2.name}: cost = ${i2.total_cost()}")
print(f"Valid code 'ING-012': {Ingredient.is_valid_code('ING-012')}")
print(f"Valid code 'FD-999': {Ingredient.is_valid_code('FD-999')}")
print(f"Kitchen total: ${Ingredient.kitchen_value()}")
Expected Output
[STOCK] Rice: ordered 15, now 75
[STOCK] Rice: used 50, now 25
[STOCK] Not enough Rice in kitchen
[STOCK] Olive Oil: used 3, now 5
Rice: cost = $80.0
Olive Oil: cost = $78.75
Valid code 'ING-012': True
Valid code 'FD-999': False
Kitchen total: $158.75
Variant 9: Stationery Supply Manager
An office needs a system to manage stationery supplies. The system should log supply changes, validate item codes, compute total supply cost, and support creating items from purchase orders.
- Write a decorator
track_change(func)that defines awrapper(*args, **kwargs)inside. The wrapper should call the original function with the same arguments, capture its return value, print"[STOCK] {return_value}", and return the result. - Create a class
Supplywith:__init__(self, name, unit_price, stock)— stores the supply name, unit price (float), and stock (int).- A class variable
_all_supplies— an empty list that collects everySupplyinstance created (appendselfin__init__). - An instance method
add_stock(self, amount)decorated with@track_change— addsamounttostockand returns the string"{name}: added {amount}, now {stock}". - An instance method
distribute(self, amount)decorated with@track_change— ifamountis greater thanstock, returns the string"Not enough {name} in storage"without changing stock. Otherwise, subtractsamountfromstockand returns"{name}: distributed {amount}, now {stock}". - An instance method
total_cost(self)— returnsunit_price * stockrounded to 2 decimal places. - A class method
from_purchase_order(cls, entry)— takes a string in the format"Name:Price:Stock"(e.g.,"Pens:1.25:200"), parses it, converts price to float and stock to int, and returns a newSupply. - A static method
is_valid_code(code)— returnsTrueifcodestarts with"SUP-"and the rest are digits (e.g.,"SUP-007"),Falseotherwise. - A class method
office_value(cls)— returns the sum oftotal_cost()for all supplies in_all_supplies, rounded to 2 decimal places.
Input
s1 = Supply("Notebooks", 4.50, 40)
s2 = Supply.from_purchase_order("Markers:2.80:25")
s1.add_stock(10)
s1.distribute(35)
s1.distribute(100)
s2.distribute(5)
print(f"{s1.name}: cost = ${s1.total_cost()}")
print(f"{s2.name}: cost = ${s2.total_cost()}")
print(f"Valid code 'SUP-007': {Supply.is_valid_code('SUP-007')}")
print(f"Valid code 'OFF-010': {Supply.is_valid_code('OFF-010')}")
print(f"Office total: ${Supply.office_value()}")
Expected Output
[STOCK] Notebooks: added 10, now 50
[STOCK] Notebooks: distributed 35, now 15
[STOCK] Not enough Notebooks in storage
[STOCK] Markers: distributed 5, now 20
Notebooks: cost = $67.5
Markers: cost = $56.0
Valid code 'SUP-007': True
Valid code 'OFF-010': False
Office total: $123.5
Variant 10: Equipment Rental Manager
A rental shop needs a system to manage equipment lending. The system should log rent and return actions, validate equipment serial numbers, compute availability, and support creating equipment from inventory sheets.
- Write a decorator
log_operation(func)that defines awrapper(*args, **kwargs)inside. The wrapper should call the original function with the same arguments, capture its return value. If the return value isTrue, print"[OK] {func.__name__} successful". IfFalse, print"[FAIL] {func.__name__} denied". Return the result. - Create a class
Equipmentwith:__init__(self, name, total_units)— stores the name, total number of units (int), initializes_rentedto0, and appendsselfto the class variable_inventory.- A class variable
_inventory— an empty list that collects everyEquipmentinstance created. - An instance method
rent(self)decorated with@log_operation— if_rentedis already equal tototal_units, returnsFalse. Otherwise, increments_rentedby 1 and returnsTrue. - An instance method
return_item(self)decorated with@log_operation— if_rentedis0, returnsFalse. Otherwise, decrements_rentedby 1 and returnsTrue. - An instance method
available(self)— returnstotal_units - _rented. - An instance method
rental_rate(self)— returns the percentage of units currently rented, rounded to 1 decimal place (e.g., 2 rented out of 5 total →40.0). - A class method
from_sheet(cls, entry)— takes a string in the format"Name:Units"(e.g.,"Drill:4"), parses it, converts units to int, and returns a newEquipment. - A static method
is_valid_serial(serial)— returnsTrueifserialis exactly 13 characters long and all characters are digits,Falseotherwise. - A class method
total_available(cls)— returns the total number of available (not rented) units across all equipment in_inventory.
Input
e1 = Equipment("Projector", 2)
e2 = Equipment.from_sheet("Camera:3")
e1.rent()
e1.rent()
e1.rent()
e1.return_item()
e2.rent()
e2.return_item()
e2.return_item()
print(f"{e1.name}: available = {e1.available()}, rental = {e1.rental_rate()}%")
print(f"{e2.name}: available = {e2.available()}, rental = {e2.rental_rate()}%")
print(f"Valid serial '1234567890123': {Equipment.is_valid_serial('1234567890123')}")
print(f"Valid serial '123-456': {Equipment.is_valid_serial('123-456')}")
print(f"Total available in shop: {Equipment.total_available()}")
Expected Output
[OK] rent successful
[OK] rent successful
[FAIL] rent denied
[OK] return_item successful
[OK] rent successful
[OK] return_item successful
[FAIL] return_item denied
Projector: available = 1, rental = 50.0%
Camera: available = 3, rental = 0.0%
Valid serial '1234567890123': True
Valid serial '123-456': False
Total available in shop: 4
Variant 11: Ticket Booth Manager
A theater needs a system to manage ticket sales. The system should log sell and refund actions, validate booking codes, compute seat availability, and support creating shows from schedule entries.
- Write a decorator
log_operation(func)that defines awrapper(*args, **kwargs)inside. The wrapper should call the original function with the same arguments, capture its return value. If the return value isTrue, print"[OK] {func.__name__} successful". IfFalse, print"[FAIL] {func.__name__} denied". Return the result. - Create a class
Showwith:__init__(self, title, total_seats)— stores the title, total number of seats (int), initializes_soldto0, and appendsselfto the class variable_schedule.- A class variable
_schedule— an empty list that collects everyShowinstance created. - An instance method
sell_ticket(self)decorated with@log_operation— if_soldis already equal tototal_seats, returnsFalse. Otherwise, increments_soldby 1 and returnsTrue. - An instance method
refund_ticket(self)decorated with@log_operation— if_soldis0, returnsFalse. Otherwise, decrements_soldby 1 and returnsTrue. - An instance method
seats_left(self)— returnstotal_seats - _sold. - An instance method
sold_percent(self)— returns the percentage of seats currently sold, rounded to 1 decimal place (e.g., 2 sold out of 5 total →40.0). - A class method
from_schedule(cls, entry)— takes a string in the format"Title:Seats"(e.g.,"Hamlet:3"), parses it, converts seats to int, and returns a newShow. - A static method
is_valid_booking(code)— returnsTrueifcodeis exactly 13 characters long and all characters are digits,Falseotherwise. - A class method
total_seats_left(cls)— returns the total number of available (unsold) seats across all shows in_schedule.
Input
s1 = Show("Romeo and Juliet", 2)
s2 = Show.from_schedule("Hamlet:3")
s1.sell_ticket()
s1.sell_ticket()
s1.sell_ticket()
s1.refund_ticket()
s2.sell_ticket()
s2.refund_ticket()
s2.refund_ticket()
print(f"{s1.title}: seats left = {s1.seats_left()}, sold = {s1.sold_percent()}%")
print(f"{s2.title}: seats left = {s2.seats_left()}, sold = {s2.sold_percent()}%")
print(f"Valid booking '4567890123456': {Show.is_valid_booking('4567890123456')}")
print(f"Valid booking '456-789': {Show.is_valid_booking('456-789')}")
print(f"Total seats left: {Show.total_seats_left()}")
Expected Output
[OK] sell_ticket successful
[OK] sell_ticket successful
[FAIL] sell_ticket denied
[OK] refund_ticket successful
[OK] sell_ticket successful
[OK] refund_ticket successful
[FAIL] refund_ticket denied
Romeo and Juliet: seats left = 1, sold = 50.0%
Hamlet: seats left = 3, sold = 0.0%
Valid booking '4567890123456': True
Valid booking '456-789': False
Total seats left: 4
Variant 12: Parking Lot Manager
A parking garage needs a system to manage parking spots. The system should log entry and exit actions, validate license plates, compute occupancy, and support creating lots from city records.
- Write a decorator
log_operation(func)that defines awrapper(*args, **kwargs)inside. The wrapper should call the original function with the same arguments, capture its return value. If the return value isTrue, print"[OK] {func.__name__} successful". IfFalse, print"[FAIL] {func.__name__} denied". Return the result. - Create a class
ParkingLotwith:__init__(self, location, total_spots)— stores the location, total number of spots (int), initializes_occupiedto0, and appendsselfto the class variable_all_lots.- A class variable
_all_lots— an empty list that collects everyParkingLotinstance created. - An instance method
enter(self)decorated with@log_operation— if_occupiedis already equal tototal_spots, returnsFalse. Otherwise, increments_occupiedby 1 and returnsTrue. - An instance method
exit_lot(self)decorated with@log_operation— if_occupiedis0, returnsFalse. Otherwise, decrements_occupiedby 1 and returnsTrue. - An instance method
free_spots(self)— returnstotal_spots - _occupied. - An instance method
occupancy_rate(self)— returns the percentage of spots currently occupied, rounded to 1 decimal place (e.g., 2 occupied out of 5 total →40.0). - A class method
from_record(cls, entry)— takes a string in the format"Location:Spots"(e.g.,"Downtown:3"), parses it, converts spots to int, and returns a newParkingLot. - A static method
is_valid_plate(plate)— returnsTrueifplateis exactly 13 characters long and all characters are digits,Falseotherwise. - A class method
total_free(cls)— returns the total number of free spots across all lots in_all_lots.
Input
l1 = ParkingLot("Central Mall", 2)
l2 = ParkingLot.from_record("Airport:3")
l1.enter()
l1.enter()
l1.enter()
l1.exit_lot()
l2.enter()
l2.exit_lot()
l2.exit_lot()
print(f"{l1.location}: free = {l1.free_spots()}, occupancy = {l1.occupancy_rate()}%")
print(f"{l2.location}: free = {l2.free_spots()}, occupancy = {l2.occupancy_rate()}%")
print(f"Valid plate '0123456789012': {ParkingLot.is_valid_plate('0123456789012')}")
print(f"Valid plate '012-345': {ParkingLot.is_valid_plate('012-345')}")
print(f"Total free spots: {ParkingLot.total_free()}")
Expected Output
[OK] enter successful
[OK] enter successful
[FAIL] enter denied
[OK] exit_lot successful
[OK] enter successful
[OK] exit_lot successful
[FAIL] exit_lot denied
Central Mall: free = 1, occupancy = 50.0%
Airport: free = 3, occupancy = 0.0%
Valid plate '0123456789012': True
Valid plate '012-345': False
Total free spots: 4