# L-28 MCS 507 Wed 26 Oct 2011 : restaurant.py

# Simulation of a restaurent with one waiter.

from threading import *
import time
import random

class Customer(Thread):
   """
   Customer enters, waits for table,
   orders food, waits for food, eats,
   waits for bill and then leaves.
   """
   def __init__(self,t,S):
      """
      Initializes customer with name t,
      sets initial state to zero, and
      stores the shared state list S.
      """
      Thread.__init__(self,name=t)
      self.state = 0
      self.shs = S

   def move(self):
      """
      For even stages, moves up after delay.
      """
      n = self.getName()
      r = random.randint(1,10)
      time.sleep(r)
      self.state = self.state + 1
      self.shs[int(n)] = self.state

   def wait(self):
      """
      Needs waiter for odd stages.
      """
      n = int(self.getName())
      while True:
         time.sleep(5)
         if self.state < self.shs[n]: break
      self.state = self.state + 1

   def show(self):
      """
      Returns string representation of state.
      """
      if self.state == 0:
         return ' enters restaurant'
      elif self.state == 1:
         return ' waits for table'
      elif self.state == 2:
         return ' orders food'
      elif self.state == 3:
         return ' waits for food'
      elif self.state == 4:
         return ' eats food'
      elif self.state == 5:
         return ' waits for bill'
      else:
         return ' pays and leaves'

   def run(self):
      """
      Customer passes through stages.
      """
      n = self.getName()
      while self.state < 6: 
         if self.state % 2 == 0:
            self.move()
         else:
            self.wait()
         print n + self.show()

class Waiter(Thread):
   """
   Waiter checks the state list and
   advances odd states to next level.
   """
   def __init__(self,t,S):
      """
      Initializes waiter with name t,
      and stores the shared state list S.
      """
      Thread.__init__(self,name=t)
      self.shs = S

   def run(self):
      """
      Advances odd states of customers,
      while otherwise busy waiting.
      """
      while True:
         time.sleep(5)
         done = True
         for i in range(0,len(self.shs)):
            if self.shs[i] % 2 == 1:
               time.sleep(random.randint(1,3))
               self.shs[i] = self.shs[i] + 1
            if self.shs[i] < 6: done = False
         if done: break

def main():
   """
   Simulation of restaurant with one server.
   """
   Shared = []
   s = Waiter('w',Shared)
   n = input('give #customers : ')
   T = []
   for i in range(0,n):
      T.append(Customer(str(i),Shared))
   for t in T: Shared.append(0)
   s.start()
   for t in T: t.start()
   print "simulation starts..."

if __name__ == "__main__": main()
