Functional Scope (In-Scope)
- Dynamic Calendar & Overlap Logic: Atomic reservation window check with custom multi-night discounts, weekend pricing spikes, and peak summer/winter holiday additions.
- Striped Lock Concurrency Isolation: Locks individual listing schedules to eliminate system-wide bottlenecks and race conditions.
- Geo-Spatial Radius Haversine Searching: Fast spherical math filtering to find listings inside maximum kilometer bounds.
- Double-Blind Review release Strategy: Blocks guest/host feedback visibility until both are verified or the window closes.
Explicit Boundaries (Out-of-Scope)
- Physical Payment Terminals: Stubbed with hold token captures without bank routing or merchant reconciliation systems.
- Active WebSocket Chatting: skips live typing signals and websocket channel setups between host and guest.
Production reference implementations demonstrating double-blind reviews, geo-radius checks, and atomic date reservations in Java and Python:
// ─── JAVA BLUEPRINT ──────────────────────────────────────────────────────────
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantLock;
enum BookingStatus {
PENDING_HOLD, CONFIRMED, CANCELLED
}
class DateRange {
private final LocalDate checkIn;
private final LocalDate checkOut;
public DateRange(LocalDate checkIn, LocalDate checkOut) {
if (checkIn == null || checkOut == null || !checkIn.isBefore(checkOut)) {
throw new IllegalArgumentException("Invalid dates: checkIn must be before checkOut.");
}
this.checkIn = checkIn;
this.checkOut = checkOut;
}
public LocalDate getCheckIn() { return checkIn; }
public LocalDate getCheckOut() { return checkOut; }
public boolean overlaps(DateRange other) {
return this.checkIn.isBefore(other.checkOut) && other.checkIn.isBefore(this.checkOut);
}
public long durationDays() {
return ChronoUnit.DAYS.between(checkIn, checkOut);
}
}
class Listing {
private final String id;
private final String hostId;
private final String title;
private final double latitude;
private final double longitude;
private final double basePricePerNight;
private final int capacity;
public Listing(String id, String hostId, String title, double latitude, double longitude, double basePricePerNight, int capacity) {
this.id = id;
this.hostId = hostId;
this.title = title;
this.latitude = latitude;
this.longitude = longitude;
this.basePricePerNight = basePricePerNight;
this.capacity = capacity;
}
public String getId() { return id; }
public String getHostId() { return hostId; }
public String getTitle() { return title; }
public double getLatitude() { return latitude; }
public double getLongitude() { return longitude; }
public double getBasePricePerNight() { return basePricePerNight; }
public int getCapacity() { return capacity; }
}
class Booking {
private final String id;
private final String listingId;
private final String guestId;
private final DateRange dateRange;
private final double totalAmount;
private BookingStatus status;
private String paymentHoldId;
public Booking(String id, String listingId, String guestId, DateRange dateRange, double totalAmount) {
this.id = id;
this.listingId = listingId;
this.guestId = guestId;
this.dateRange = dateRange;
this.totalAmount = totalAmount;
this.status = BookingStatus.PENDING_HOLD;
}
public String getId() { return id; }
public String getListingId() { return listingId; }
public String getGuestId() { return guestId; }
public DateRange getDateRange() { return dateRange; }
public double getTotalAmount() { return totalAmount; }
public synchronized BookingStatus getStatus() { return status; }
public synchronized void setStatus(BookingStatus status) { this.status = status; }
public synchronized String getPaymentHoldId() { return paymentHoldId; }
public synchronized void setPaymentHoldId(String paymentHoldId) { this.paymentHoldId = paymentHoldId; }
}
class Review {
private final String authorId;
private final String targetId;
private final int rating;
private final String comment;
public Review(String authorId, String targetId, int rating, String comment) {
this.authorId = authorId;
this.targetId = targetId;
this.rating = rating;
this.comment = comment;
}
public String getAuthorId() { return authorId; }
public String getTargetId() { return targetId; }
public int getRating() { return rating; }
public String getComment() { return comment; }
}
class DynamicPricingEngine {
public static double calculatePrice(Listing listing, DateRange range) {
double total = 0.0;
LocalDate current = range.getCheckIn();
while (current.isBefore(range.getCheckOut())) {
double price = listing.getBasePricePerNight();
// Weekend surcharge (+20% for Friday/Saturday)
if (current.getDayOfWeek() == java.time.DayOfWeek.FRIDAY || current.getDayOfWeek() == java.time.DayOfWeek.SATURDAY) {
price *= 1.2;
}
// Seasonal surcharge (+15% during peak months June/December)
int month = current.getMonthValue();
if (month == 6 || month == 12) {
price *= 1.15;
}
total += price;
current = current.plusDays(1);
}
// Multi-night discount: 7+ nights gets 10% off
long nights = range.durationDays();
if (nights >= 7) {
total *= 0.9;
}
return Math.round(total * 100.0) / 100.0;
}
}
class PropertyRentalService {
private final ConcurrentHashMap<String, Listing> listings = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, List<Booking>> listingBookings = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, ReentrantLock> listingLocks = new ConcurrentHashMap<>();
// Mutual blind review repository: BookingID -> Map(AuthorID -> Review)
private final ConcurrentHashMap<String, ConcurrentHashMap<String, Review>> blindReviews = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, CopyOnWriteArrayList<Review>> activeReviews = new ConcurrentHashMap<>();
private ReentrantLock getListingLock(String listingId) {
return listingLocks.computeIfAbsent(listingId, k -> new ReentrantLock());
}
public void addListing(Listing listing) {
listings.put(listing.getId(), listing);
}
// Atomic date-range reservation utilizing per-listing lock striping
public Booking createBookingRequest(String bookingId, String listingId, String guestId, LocalDate checkIn, LocalDate checkOut) {
Listing listing = listings.get(listingId);
if (listing == null) throw new IllegalArgumentException("Listing not found.");
DateRange requestedRange = new DateRange(checkIn, checkOut);
ReentrantLock lock = getListingLock(listingId);
lock.lock();
try {
List<Booking> bookings = listingBookings.computeIfAbsent(listingId, k -> new ArrayList<>());
// Check for date range overlap
for (Booking existing : bookings) {
if (existing.getStatus() != BookingStatus.CANCELLED) {
if (existing.getDateRange().overlaps(requestedRange)) {
throw new IllegalStateException("Requested dates overlap with existing booking.");
}
}
}
double totalAmount = DynamicPricingEngine.calculatePrice(listing, requestedRange);
Booking newBooking = new Booking(bookingId, listingId, guestId, requestedRange, totalAmount);
bookings.add(newBooking);
return newBooking;
} finally {
lock.unlock();
}
}
public void confirmBooking(String bookingId, String paymentHoldId) {
Booking booking = findBooking(bookingId);
if (booking == null) throw new IllegalArgumentException("Booking not found");
ReentrantLock lock = getListingLock(booking.getListingId());
lock.lock();
try {
if (booking.getStatus() != BookingStatus.PENDING_HOLD) {
throw new IllegalStateException("Booking is not in PENDING_HOLD state.");
}
booking.setPaymentHoldId(paymentHoldId);
booking.setStatus(BookingStatus.CONFIRMED);
} finally {
lock.unlock();
}
}
public void cancelBooking(String bookingId) {
Booking booking = findBooking(bookingId);
if (booking == null) throw new IllegalArgumentException("Booking not found");
ReentrantLock lock = getListingLock(booking.getListingId());
lock.lock();
try {
booking.setStatus(BookingStatus.CANCELLED);
} finally {
lock.unlock();
}
}
private Booking findBooking(String bookingId) {
for (List<Booking> list : listingBookings.values()) {
synchronized (list) {
for (Booking b : list) {
if (b.getId().equals(bookingId)) {
return b;
}
}
}
}
return null;
}
// Double-blind review submission logic
public void submitReview(String bookingId, String authorId, String targetId, int rating, String comment) {
Review review = new Review(authorId, targetId, rating, comment);
ConcurrentHashMap<String, Review> bookingMap = blindReviews.computeIfAbsent(bookingId, k -> new ConcurrentHashMap<>());
bookingMap.put(authorId, review);
// When both guest and host reviews are posted, make both public simultaneously
if (bookingMap.size() == 2) {
for (Review r : bookingMap.values()) {
activeReviews.computeIfAbsent(r.getTargetId(), k -> new CopyOnWriteArrayList<>()).add(r);
}
blindReviews.remove(bookingId);
}
}
public List<Review> getPublicReviews(String targetId) {
return activeReviews.getOrDefault(targetId, new CopyOnWriteArrayList<>());
}
public List<Listing> searchProperties(double userLat, double userLon, double maxDistanceKm, LocalDate checkIn, LocalDate checkOut, int guestsCount) {
List<Listing> matched = new ArrayList<>();
DateRange requestedRange = new DateRange(checkIn, checkOut);
for (Listing listing : listings.values()) {
if (listing.getCapacity() < guestsCount) continue;
double dist = haversineDistance(userLat, userLon, listing.getLatitude(), listing.getLongitude());
if (dist > maxDistanceKm) continue;
boolean isAvailable = true;
ReentrantLock lock = getListingLock(listing.getId());
lock.lock();
try {
List<Booking> bookings = listingBookings.get(listing.getId());
if (bookings != null) {
for (Booking b : bookings) {
if (b.getStatus() != BookingStatus.CANCELLED) {
if (b.getDateRange().overlaps(requestedRange)) {
isAvailable = false;
break;
}
}
}
}
} finally {
lock.unlock();
}
if (isAvailable) {
matched.add(listing);
}
}
return matched;
}
private double haversineDistance(double lat1, double lon1, double lat2, double lon2) {
final int R = 6371; // Radius of Earth in km
double latDistance = Math.toRadians(lat2 - lat1);
double lonDistance = Math.toRadians(lon2 - lon1);
double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
+ Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
* Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c;
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
System.out.println("=== STARTING AIRBNB PROPERTY RENTAL SYSTEM SIMULATION ===");
PropertyRentalService service = new PropertyRentalService();
Listing cozyCabin = new Listing("listing-1", "host-123", "Cozy Lakeside Cabin", 45.4215, -75.6972, 120.00, 4);
Listing urbanLoft = new Listing("listing-2", "host-456", "Modern Downtown Loft", 45.4230, -75.6990, 200.00, 2);
service.addListing(cozyCabin);
service.addListing(urbanLoft);
// 1. Search Properties Test
System.out.println("--- Search Properties within 2km of center ---");
List<Listing> searchResults = service.searchProperties(
45.4210, -75.6960, 2.0,
LocalDate.of(2026, 6, 1), LocalDate.of(2026, 6, 8), 2
);
for (Listing l : searchResults) {
System.out.println(" Found: " + l.getTitle() + " at Base Price: $" + l.getBasePricePerNight());
}
// 2. Concurrency Booking Race Test (Overlapping dates on same listing)
System.out.println("\n--- Concurrent Booking Race Test ---");
ExecutorService executor = Executors.newFixedThreadPool(3);
CountDownLatch latch = new CountDownLatch(1);
Runnable guestAttempt1 = () -> {
try {
latch.await();
Booking b = service.createBookingRequest("book-100", "listing-1", "guest-abc",
LocalDate.of(2026, 6, 1), LocalDate.of(2026, 6, 5));
System.out.println(" [SUCCESS] Guest ABC booked: " + b.getId() + " total amount $" + b.getTotalAmount());
service.confirmBooking(b.getId(), "hold-token-xyz");
System.out.println(" [SUCCESS] Guest ABC payment confirmed.");
} catch (Exception e) {
System.out.println(" [FAILED] Guest ABC booking failed: " + e.getMessage());
}
};
Runnable guestAttempt2 = () -> {
try {
latch.await();
Booking b = service.createBookingRequest("book-101", "listing-1", "guest-def",
LocalDate.of(2026, 6, 3), LocalDate.of(2026, 6, 8)); // Overlapping!
System.out.println(" [SUCCESS] Guest DEF booked: " + b.getId());
} catch (Exception e) {
System.out.println(" [FAILED] Guest DEF booking failed: " + e.getMessage());
}
};
executor.submit(guestAttempt1);
executor.submit(guestAttempt2);
latch.countDown();
executor.shutdown();
executor.awaitTermination(2, TimeUnit.SECONDS);
// 3. Double-blind review release test
System.out.println("\n--- Double-Blind Review Release Test ---");
System.out.println("Submitting Guest Review for stay book-100...");
service.submitReview("book-100", "guest-abc", "host-123", 5, "Amazing host and beautiful view!");
System.out.println("Checking public reviews for host-123: " + service.getPublicReviews("host-123").size() + " reviews.");
System.out.println("Submitting Host Review for stay book-100...");
service.submitReview("book-100", "host-123", "guest-abc", 5, "Very polite guest, left place clean.");
System.out.println("Both submitted! Public reviews for host-123: " + service.getPublicReviews("host-123").size());
for (Review r : service.getPublicReviews("host-123")) {
System.out.println(" - Review: Rating " + r.getRating() + ", " + r.getComment());
}
System.out.println("=== AIRBNB PROPERTY RENTAL SYSTEM SIMULATION COMPLETE ===");
}
}