Gym Chain Booking Portal
Design an online booking portal for an offline gym chain — admin gym/class management and customer bookings, with concurrency-safe capacity limits.
An existing gym chain that's completely offline wants to start an online portal for managing bookings. The portal has two views: an admin view for managing gyms and classes, and a customer view for booking into them.
This one tests whether you can enforce capacity limits correctly at two nested levels — a gym's overall max accommodation and each class's own max limit — while keeping bookings thread-safe under concurrent customers competing for the same class slot.
Objective
The primary objective of this project is to design and implement an in-memory gym booking system as a plain Java driver-class program, where admins manage gyms and classes within capacity constraints, and customers book, view, and cancel their own class bookings safely under concurrency.
Functional Requirements
Requirements split naturally along the two portal views: what an admin can do, and what a customer can do. Both act on the same underlying gym/class/booking state, so capacity checks and concurrency matter across both.
Part 1 — Admin Flows
Part 2 — Customer Flows
A class's max_limit counts toward its gym's overall max_accomodation, and that accommodation limit must be validated at class-creation time, not just at booking time. Each customer may hold at most one booking per class — a repeat bookClass call for the same customer and class should be rejected.
Example Usage
The source problem gives a short example chain of calls; here it is, extended slightly to exercise cancellation and lookup as well.
1. Create a gym
addGym("Gym1", "Indira Nagar", 100)
→ Success: returns gym1_id
2. Create a class within the gym
addClass("gym1_id", "cardio", 20, "6:00", "7:00")
→ Success: returns class1_id
3. Book a customer into the class
bookClass("customer1", "gym1_id", "class1_id")
→ Success: returns booking1_id
4. View the customer's bookings
getAllBookings("customer1")
→ [ { bookingId: "booking1_id", gymId: "gym1_id", classId: "class1_id" } ]
5. Cancel the booking
cancelBooking("booking1_id")
→ Success: booking1_id canceled
The chain of calls shows the full lifecycle for one customer: a gym and class are created within capacity limits, the customer books successfully and can retrieve that booking, and cancelling it removes it cleanly without affecting the gym or class themselves.
Guidelines
Use in-memory data structures only — no databases. Handle exceptions gracefully, and handle concurrency and race conditions explicitly (this is directly evaluated). Do not implement authentication. Write plain Java with a driver class to demonstrate the solution — no frameworks like Spring. Cover corner cases and validations, discussing with the interviewer what real-world validations would be needed. No UI is required. Get the expected/core behavior working first, then move to good-to-have improvements. You're free to state and justify your own reasonable assumptions.