#include <stdlib.h>
#include <iostream.h>


const int n  = 10;
const int n5 =  6;
const int n6 =  3;
const int nT = 50;


int f1() {
  return random(4) + 2;
}
int f2() {
  return random(10);
}

template <class T>
class TQueue {

public:
  TQueue()
  {
    front = back = 0;
  }
  ~TQueue();

  T get();
  void put(const T&);

  int is_empty()
  {
    return((!front) ? 1 : 0);
  }

private:

  class TQueueItem {
  public:
    TQueueItem(T value): item(value), next(0)
    {
    }

    T item;
    TQueueItem *next;
  };

  TQueueItem *front, *back;
};

template <class T>
TQueue<T> :: ~TQueue()
{
  while(!is_empty()) (void)get();
}

template <class T>
void TQueue<T> :: put(const T &value)
{
  TQueueItem *pt = new TQueueItem(value);
  if(is_empty()) {
    front = back = pt;
  }
  else {
    back -> next = pt;
    back = pt;
  }
}

template <class T>
T TQueue<T> :: get()
{
  if(is_empty()) {
    cout << "Trying to Get from the empty queue !\n";
    exit(-1);
  }

  TQueueItem *pt = front;
  front = front -> next;

  T value = pt -> item;
  delete pt;

  return value;
}


class TClient {

  int ID;

public:
  int get_id() const
  {
    return ID;
  }
  TClient(int value): ID(value)
  {
  }

};



enum status {
  _busy = 0, _waiting, _vacation
};

class TCasher {

  status state;
  const int work_time, ID;
  int working_time, this_client;

public:
  TCasher(int _id, int _work):
    ID(_id), work_time(_work), state(_waiting)
    {
      working_time = work_time;
    }


  status Handle(int &changed) {

    changed = 0;

    if(state == _busy) {
      this_client -= 1;
      working_time -= 1;

      if(!this_client) state = _waiting, changed = 1;
    }

    if(state == _vacation) {

      working_time += 1;
      if(working_time > 0)
        state = _waiting, working_time = work_time, changed = 1;

    }

    if(state == _waiting) {

      if(!changed) working_time -= 1;
      if(working_time <= 0)
        state = _vacation, working_time = -n6, changed = 1;
    }

    return state;
  }

  void next() {

    state = _busy;
    this_client = f2();

  }

};




class TManager {

  TQueue<TClient> queue;
  TCasher *cash_workers[n];

  int current_time, after_prev_enter;

public:
  TManager();
  ~TManager();

  void run();
};

TManager :: TManager():
  current_time(0), after_prev_enter(0)
{
  for(int i = 0; i < n; i++)
    cash_workers[i] = new TCasher(i + 1, n5);
}
TManager :: ~TManager() {
  for(int i = 0; i < n; i++)
    delete cash_workers[i];
}

void TManager :: run() {

  static int client_entered = 0;

  while((current_time <= nT) || (!queue.is_empty())) {

    for(int i = 0; i < n; i++) {
      int status_changed = 0;
      status curr_status =
        cash_workers[i] -> Handle(status_changed);

      if(status_changed)
        // statistics
        switch(curr_status) {
          case _vacation:
            cout << "casher #" << i << " goes to rest at:: " << current_time << endl;
            break;
          case _waiting:
            cout << "casher #" << i << " awaiting at:: " << current_time << endl;
            break;
        }

        if(curr_status == _waiting)
          if(!queue.is_empty()) {

            TClient client = queue.get();
            cout << "client #" << client.get_id() << " sent to casher #" << i << " at:: " << current_time << endl;
            cash_workers[i] -> next();

          }

    }


    if(current_time <= nT) {

      after_prev_enter += 1;
      if(after_prev_enter > f1()) {

        after_prev_enter = 0;
        TClient client(++client_entered);
        queue.put(client);

      }

    }
    current_time += 1;
  }

  cout << client_entered << endl;

}


int main() {

  TManager bank;
  bank.run();

  return 0;
}