1
\$\begingroup\$

I have an use case where I want to see how many slots have been used for a date in a restaurant. The slot can be deducted based either number of diners or per booking. Also I have to cater a case where a booking is made for multiple dates and then i have to consider those dates as well when checking how many slots have been used

Here's is what classes I have and the model I have created

RestaurantBookingStat - This represents a booking made for a restaurant on a date with total customers for a booking and number of days (in case someone books for multiple days - corporate booking) Not adding getter and setter to avoid verbosity

public class RestaurantBookStat {
  private LocalDate startDate;
  private int dinersInBooking;
  private int numberOfDays;
}

SlotDeductionType: Enum represents whether to deduct based on booking or diner

public enum SlotDeductionType {
  DEDUCT_PER_DINER,
  DEDUCT_PER_BOOKING
}

SlotDeductionMode - Represents if I just just consider startDate or also numberOfDays to expand all possible startdate

public enum SlotDeductionMode {
  DEDUCT_FROM_START_DATE_FOR_BOOKING,
  DEDUCT_FROM_EACH_START_DATE_BASED_ON_NUMBER_OF_DAYS
}

I am trying to calculate slot used for a restaurant based on deduction mode and deductionType and so far this is what I have (just for showing purpose. Otherwise everything is in spring and not all in same class)

public static void main(String args[]){
    RestaurantBookStat bookingStat1 = new RestaurantBookStat();
    bookingStat1.setStartDate(LocalDate.of(2021, 9, 13));
    bookingStat1.setDinersInBooking(2);
    bookingStat1.setNumberOfDays(3);

    RestaurantBookStat bookingStat2 = new RestaurantBookStat();
    bookingStat2.setStartDate(LocalDate.of(2021, 9, 12));
    bookingStat2.setDinersInBooking(3);
    bookingStat2.setNumberOfDays(2);

    RestaurantBookStat bookingStat3 = new RestaurantBookStat();
    bookingStat3.setStartDate(LocalDate.of(2021, 9, 13));
    bookingStat3.setDinersInBooking(1);
    bookingStat3.setNumberOfDays(1);

    List<RestaurantBookStat> bookingStats = List.of(bookingStat1, bookingStat2, bookingStat3);
    System.out.println(getSlotUsedForEachDate(bookingStats, DEDUCT_FROM_START_DATE_FOR_BOOKING, DEDUCT_PER_DINER));
    System.out.println(getSlotUsedForEachDate(bookingStats, DEDUCT_FROM_START_DATE_FOR_BOOKING, DEDUCT_PER_BOOKING));
  }

  public static Map<LocalDate, Long>  getSlotUsedForEachDate(List<RestaurantBookStat> bookingStats, SlotDeductionMode slotDeductionMode, SlotDeductionType deductionType){

    if(DEDUCT_PER_DINER == deductionType && DEDUCT_FROM_START_DATE_FOR_BOOKING == slotDeductionMode){
      return bookingStats.stream()
          .collect(
              Collectors.groupingBy(
                  RestaurantBookStat::getStartDate,
                  Collectors.summingLong(RestaurantBookStat::getDinersInBooking)));
      // Output {2021-09-13=3, 2021-09-12=3} Correct
    }else if (DEDUCT_PER_BOOKING == deductionType && DEDUCT_FROM_START_DATE_FOR_BOOKING == slotDeductionMode){
      return bookingStats.stream()
          .collect(
              Collectors.groupingBy(
                  RestaurantBookStat::getStartDate,
                  Collectors.counting()));
      //Output {2021-09-13=2, 2021-09-12=1} Correct
    }else if (DEDUCT_PER_DINER == deductionType && DEDUCT_FROM_EACH_START_DATE_BASED_ON_NUMBER_OF_DAYS == slotDeductionMode){
      //for each date and number of days, expand the dates and create additional bookings stats for expanded dates and then use the list
      //Expected Output {12-09-2021=3, 13-09-2021=6, 14-09-2021=3}
      return null; //Todo
    }
    // not showing all other scenarios as rest are all variations of the above cases
    throw new UnsupportedOperationException();
  }

I have difficulty in the logic to expand dates and have them part of the slot used for each date. Any pointers will be helpful

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

What made me stumble when reading

Your use-cases and problem description reads almost fluently and most of it sounds plausible.

Though I rarely found names or words from your narrative in your code. Moreover, it sounds rather technically.

Sometimes you don't need to translate your problem into a completely different computer-language. Rather you could depict the things and behavior from your narrative description in equally named objects and verbs, the model. These structures and behaviors can often be similarly arranged in the programming language.

Problem domain & language

Your first paragraph describes the use-case with terms from the restaurant domain. There are keywords like "slot", "booking" (reservation), "diner".

Sounds like a booking/reservation system that calculates the (free) capacity of a restaurant (based on tables, seats).

There seem to be different options for a booking/reservation:

  • how many slots have been used (1) for a date
  • can be deducted based either (a) number of diners
  • .. or (b) per booking.
  • .. case where a booking is made (2) for multiple dates.

Now let's try to describe the entities (objects) and their attributes using the domain-language. Then figure out how these objects could interact to solve the problem.

Start with a base class

Following the KISS principle a simple booking could be:

  • a table for 4 people today (or simply new Reservation(LocalDate.now(), 4)
class Reservation {
  LocalDate date;
  int numberOfGuests;
}

Extend for a diner-series

Now suppose the guests like it there so much, that they want to book for the whole week, or each Friday for 7 weeks in sequence. In both cases, the reservation has the same number of seats but 7 different dates.

The class could reflect that: reservation, not single but series with (a) the same number of seats, but a (b) set of different dates

class ReservationSeries {
  Set<LocalDate> dates;
  int numberOfGuests;
}

Those were the objects (classes) and their attributes (fields) - without behavior (methods) or interaction with other objects (e.g. a calendar, the restaurant's seating-capacity, etc.).

Scheduling & Capacity

I assume the scarce resource here is the place per time - you call it slot. A restaurant which has a constraint number of slots (seats/tables) per evening. So the numberOfGuests reflects your number of diners. This number requested/demanded can to be calculated per day, even projected against a given capacity (per day).

For a given collection of Reservations it should be possible to calculate the demand per day, or the usage of capacity per day.

Deduction = Simulation?

I have difficulties to grasp the purpose of this deduction modes and types.

If both parameters are used to simulate the capacity of the restaurant under certain conditions, I would propose a class BookingSimulator with different simulation contexts with different (booking/recurrence) strategies. See Strategy design pattern.

If both parameters represent reservation-options for the guest (user) to submit different specific types of reservations (either single-date, date-series, company-bundle, etc.), then I would use a factory method to create instances of different sub-classes. They could all inherit from the base-class Reservation or implement an interface Reservation. See Factory Method design pattern.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.