Loading...
Based on the requirements and use cases, identify the main objects of the system and analyze how they interact and relate to each other...
showtimes: movie name, time, theather
theater meta: theaterName, seats per theater
booking: userId, bookingId, timestamp
For each class, define the attributes (data) it will hold and the methods (functions) that operate on the attributes. Ensure they align with the object's responsibilities and adhere to the principle of encapsulation. Write your code in the code editor below.
from __future__ import annotations
from typing import List, Dict
from threading import Lock
from datetime import datetime
class Show:
def init(self, show_id: str, movie: Movie, screen: Screen, start_time: datetime):
self.show_id = show_id
self.movie = movie
self.screen = screen
self.start_time = start_time
self.seat_availability: Dict[Seat, SeatStatus] = {seat: SeatStatus.AVAILABLE for seat in screen.get_seats()}
self._lock = Lock()
def get_available_seats(self) -> List[Seat]:
with self._lock:
return [seat for seat, status in self.seat_availability.items() if status == SeatStatus.AVAILABLE]
def lock_seats(self, seats: List[Seat]) -> bool:
with self._lock:
if any(self.seat_availability[seat] != SeatStatus.AVAILABLE for seat in seats):
return False
for seat in seats:
self.seat_availability[seat] = SeatStatus.HELD
return True
def confirm_seats(self, seats: List[Seat]) -> None:
with self._lock:
for seat in seats:
self.seat_availability[seat] = SeatStatus.BOOKED
def release_seats(self, seats: List[Seat]) -> None:
with self._lock:
for seat in seats:
if self.seat_availability[seat] != SeatStatus.BOOKED:
self.seat_availability[seat] = SeatStatus.AVAILABLE
from future import annotations
from datetime import datetime, timedelta
from threading import RLock
from typing import List
class Booking:
HOLD_TIMEOUT_MINUTES = 10
def __init__(self, booking_id: str, show: Show, seats: List[Seat], user_id: str, pricing_strategy: PricingStrategy):
self.booking_id = booking_id
self.show = show
self.seats = seats.copy()
self.user_id = user_id
self.status = BookingStatus.PENDING
self.created_at = datetime.now()
self.total_amount = sum(pricing_strategy.calculate_price(seat, show) for seat in seats)
self.payment = None
self._lock = RLock()
def confirm(self, payment: Payment) -> bool:
with self._lock:
if self.status != BookingStatus.PENDING:
return False
if payment.status != PaymentStatus.SUCCESS:
return False
self.payment = payment
self.status = BookingStatus.CONFIRMED
self.show.confirm_seats(self.seats)
return True
def cancel(self) -> bool:
with self._lock:
if self.status != BookingStatus.CONFIRMED:
return False
self.status = BookingStatus.CANCELLED
self.show.release_seats(self.seats)
if self.payment:
self.payment.refund()
return True
def is_expired(self) -> bool:
return self.status == BookingStatus.PENDING and datetime.now() > self.created_at + timedelta(minutes=self.HOLD_TIMEOUT_MINUTES)
def expire(self):
with self._lock:
if self.is_expired():
self.status = BookingStatus.EXPIRED
self.show.release_seats(self.seats)
Explain design tradeoffs you considered. Check and explain whether your design adheres to SOLID principles. Explain how your design can handle changes in scale and whether it would be easy to extend with new functionalities. Identify areas for future improvement...