
// WaitingRoom.java
// Andrew Davison, ad@coe.psu.ac.th, May 2023

/* The Sleeping barber problem:
  https://en.wikipedia.org/wiki/Sleeping_barber_problem

  WaitingRoom implements two methods:
    * addCustomer(int custID) --> seat number
    * getCustomer(int barberID)  --> custID

  Internally WaitingRoom assigns an increasing ticket number
  to each new customer, and uses that to select the next customer
  for a barber. However, addCustomer() does not return the 
  ticket number but the index for the custs[] array, which can
  be viewed as the seat assigned to the waiting customer.

  addCustomer() will finish by adding the tuple (ALERT) to
  the space in order to wake up a sleeping barber.

  getCustomer() adds the tuple:
     ("HAIRCUT", custID, barberID)
  which records that this barber is cutting the hair of 
  this customer.

  Usage:
    > compile.bat WaitingRoom.java

    Part of the application made up of:
       * BarberShop.java
       * Barber.java
       * WaitingRoom.java
       * Customer.java
*/

import org.jspace.*;


public class WaitingRoom
{
  private int[] tickets;   // ticket numbers assigned to customers
  private int ticketNum = 1;
  private int[] custs;     // customer IDs

  private Space space;


  public WaitingRoom(int roomSize, Space s)
  {
    space = s;
    System.out.println("Waiting room has space for " + 
                                    roomSize + " customers");

    tickets = new int[roomSize];
    custs = new int[roomSize];
    for(int i=0; i < roomSize; i++) {
      tickets[i] = Integer.MAX_VALUE;  // used as the dummy value
                     // since the code looks for the smallest number
      custs[i] = -1;
    }
  } // end of WaitingRoom()



  public synchronized int addCustomer(int custID)
                              throws InterruptedException
  // returns the custs[] idx, which is like a seat number
  {
    int i =0;
    while(i < tickets.length) {
      if (tickets[i] == Integer.MAX_VALUE)
        // this means that there's no ticket assigned to 'seat' i
        break;
      i++;
    }

    if (i == tickets.length) {
      // System.out.println("No space in the waiting room");
      return -1;
    }
    else {
      System.out.println("Customer " + custID + 
                           " assigned ticket " + ticketNum);
      tickets[i] = ticketNum;  // seat i is now taken
      custs[i]= custID;
      ticketNum++;

      space.put("ALERT");
        // must do this BEFORE leaving critical region;
        /* note that the customer ID is not stored in the
           ALERT tuple. This means the barber selects any 
           ALERT tuple, and WaitingRoom returns the next 
           customer ID in the queue.
        */

      return i;   // this is treated by the customer as a seat number
    }
  } // end of addCustomer()



  public synchronized int getCustomer(int barberID)
                   throws InterruptedException
  /* return the ID of the next customer in the queue, which
     is the one with the smallest ticket number */
  {
    // find smallest ticket no. and its index position
    int minTicket = Integer.MAX_VALUE;
    int idx = -1;
    for (int i=0; i < tickets.length; i++)
      if (tickets[i] < minTicket) {
        minTicket = tickets[i];
        idx = i;
      }

    if (idx != -1) {
      // use the index to lookup the associated customer ID
      int custID = custs[idx];
      System.out.println("Assigning customer " + custID + 
                         " with ticket " + minTicket +
                         " to barber " + barberID);

      // delete this ticket and customer ID from arrays
      tickets[idx] = Integer.MAX_VALUE;
      custs[idx] = -1;
      space.put("HAIRCUT", custID, barberID);   
             // must do this BEFORE leaving critical region
      return custID;
    }
    else {
      // System.out.println("No customer was found");
      return -1;
    }
  } // end of getCustomer()


} // end of WaitingRoom class

