/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package sumulationsecondlab;
import java.util.Stack;
/**
 *
 * @author Student
 */
public class SingleServerse {


  State s;
  EventList FutureEventList;
  WaitingList Customers;

 public static final int ARRIVAL = 1, DEPARTURE = 2, STOP = 3;
 public static double Clock, LastEventTime,TotalBusyTime, TotalResponseTime;
 public static long  TotalCustomers, NumberOfDepartures,MaxQueueLength;

    public SingleServerse() {

      Initialization();
      simulate();
      ReportGeneration();

    }

public static void main(String[] args){

    new SingleServer();


}

public void Initialization()   {
    s=new State();
    FutureEventList = new EventList();
    Customers = new WaitingList();
    TotalCustomers  = 1000;
    Clock = 0.0;
    s.queueLength = 0;
    s.serverStatus = 0;;
    LastEventTime = 0.0;
    TotalBusyTime = 0.0 ;
    MaxQueueLength = 0;
    TotalResponseTime = 0.0;
    NumberOfDepartures = 0;
    // create first arrival event
    Event evt = new Event(ARRIVAL, nextArrivalTime());
    FutureEventList.insert( evt );
 }
public void simulate()
{

     while(NumberOfDepartures < TotalCustomers ) {
        Event evt = FutureEventList.pop();  // get the imminent event
        Clock = evt.eventTime;              // advance simulation time
        if( evt.eventType == ARRIVAL )
            ProcessArrival(evt);
        else
            ProcessDeparture(evt);
        }
   }

 public void ProcessArrival(Event evt) {
  Customers.add(evt);
  s.queueLength++;
  // if the server is idle, fetch the event, do statistics
  // and put into service
  if(s.serverStatus == 0)
      ScheduleDeparture();
  else
      TotalBusyTime += Clock - LastEventTime;  // server is busy

  // adjust max queue length statistics
  if (MaxQueueLength < s.queueLength)
      MaxQueueLength = s.queueLength;

  // schedule the next arrival
  Event next_arrival = new Event(ARRIVAL, nextArrivalTime());
  FutureEventList.insert( next_arrival );
  LastEventTime = Clock;
 }

 public  void ScheduleDeparture() {
  Event depart = new Event(DEPARTURE,nextServiceTime());
  FutureEventList.insert(depart);
  s.serverStatus = 1;
  s.queueLength--;
 }

public void ProcessDeparture(Event e) {
 // get the customer description
 Event finished = (Event) Customers.remove();
 // if there are customers in the queue then schedule
 // the departure of the next one
  if( s.queueLength > 0 )
      ScheduleDeparture();
  else
      s.serverStatus = 0;
  TotalResponseTime += Clock - finished.eventTime;
  TotalBusyTime += Clock - LastEventTime ;
  NumberOfDepartures++;
  LastEventTime = Clock;
 }

public static void ReportGeneration() {
double serverUtilization   = (TotalBusyTime/Clock)*100; //server busy time in percent
double avgResponseTime  = TotalResponseTime/TotalCustomers;

System.out.println( "\tNUMBER OF CUSTOMERS SERVED        " + TotalCustomers );
System.out.println( "\tSERVER UTILIZATION                   " + serverUtilization+"%" );
System.out.println( "\tMAXIMUM LINE LENGTH                     " + MaxQueueLength );
System.out.println( "\tAVERAGE RESPONSE TIME  " +avgResponseTime+"MINUTES");

System.out.println( "\tSIMULATION RUNLENGTH        " + Clock + " MINUTES" );
System.out.println( "\tNUMBER OF DEPARTURES     " + NumberOfDepartures );
}



 protected double nextArrivalTime(){
           return Clock+1+Math.random()*6;
    }
protected double nextServiceTime(){
           return Clock+1+Math.random()*4;
    }


}

class Event{
    public double eventTime;
    public int eventType;

    public Event(int type, double time)
    {
    this.eventType = type;
    this.eventTime = time;
    }
}












