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

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


import java.util.LinkedList;
import java.util.Stack;

/**
 *
 * @author Admin
 */
public class Stastics {
    FEL fel;
    double time;
    State s;
    double totalBusyTime;
    int maximumQL;
    Stack waitList;
    double id;

    public Stastics() {
        init();
        simulate();
    }

    protected void init() {
        totalBusyTime=maximumQL=0;
        fel = new FEL();
        time = 0;
        s = new State();
        double runTime = 1000;
        waitList = new Stack();
//add first arrival and STOP
        fel.insert(new Event(Event.ARRIVAL,nextArrivalTime()));
        fel.insert(new Event(Event.STOP,runTime));
    }

    protected void simulate() {
        boolean done = false;
        while(!done) {
            //get imminent event
            Event e = fel.pop();
            // advance clock
            time = e.time;

            if(e.type == Event.STOP) {
                done = true;
            } else if(e.type == Event.ARRIVAL) {
                Arrival(e);
            } else if(e.type == Event.DEPARTURE) {

                Departure(e);

                }
            }
        System.out.println("Total Busy Time : "+totalBusyTime);
        System.out.println("Maximum QL: "+maximumQL);
        System.out.println("Maximum QL: "+maximumQL);
        System.out.println("Server utilization: "+totalBusyTime/1000.0);

    }
     protected void Arrival(Event e) {
        if(s.serverState == State.IDLE) {
            s.serverState = State.BUSY;
            totalBusyTime++;
            fel.insert(new Event(Event.DEPARTURE,time+nextServiceTime()));
        } else
        {
            //s.queueLen++;
            //maximumQL++;
            waitList.push(new Customer(e.time,id+nextId()));
        }
        fel.insert(new Event(Event.ARRIVAL,time+nextArrivalTime()));
    }

protected void Departure(Event e) {
    int x = fel.position(e);
    int y = s.queueLen;
        if(s.queueLen == 0) {
            s.serverState = State.IDLE;
        }
        else {
        //s.queueLen--;
        waitList.pop();
        fel.insert(new Event(Event.DEPARTURE,time+nextServiceTime()));
        }
    }

protected double nextArrivalTime(){
           return 1+Math.random()*6;
    }
protected double nextServiceTime(){
           return 1+Math.random()*8;
    }
protected double nextId(){
           return 1+Math.random()*100;
    }

public static void main(String[] args) {
         new SingleServer();
    }

}
class State {
    public int queueLen;
    public int  serverState;
    public static final int IDLE = 0;
    public static final int BUSY = 1;

    public State(){
         queueLen=0;
        serverState=IDLE;
    }
}

class FEL extends LinkedList {

    public void insert(Event e){

        int x=position(e);
        //System.out.println("the position of the linked list: "+x);
            if(x==-1){
              add(e);
            }
            else{
              add(x,e);
            }
       }
    // get immenent event
    public Event pop() {
        Event e=(Event)remove();
         return e;
    }

    public int position(Event e){
        int len=size();
        int index=-1;
        if(len>0){
        for(int i=0;i<len;i++){
            if(e.time<(double)((Event)get(i)).time)
            {
                index=i;
                break;
            }
        }
    }
        return index;
}
}

class Event {
    public int type;
    public double time;
    public static final int ARRIVAL = 0;
    public static final int DEPARTURE = 1;
    public static final int STOP = 2;

    public Event(int type,double t) {
        this.time=t;
        this.type=type;
    }
}
class Customer{
    double time;
    double ID;

    public Customer(double t,double id) {
        time = t;
        ID = id;
    }
}
