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

package sumulationsecondlab;


import java.util.Stack;

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

    FEL fel;
    double time;
    State s;
    double totalBusyTime;
    public int maximumQL;

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

    protected void init() {
        totalBusyTime=maximumQL=0;
        fel = new FEL();
        time = 0;
        s = new State();
        double runTime = 1000;
//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.remove();
            // 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++;
        }
        fel.insert(new Event(Event.ARRIVAL,time+nextArrivalTime()));
    }

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

        }
    }

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

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

}
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 newFEL extends Stack
class FEL extends Stack {

    public void insert(Event e){

        int x=position(e);
        System.out.println("the position of Satck: "+x);
            if(x==-1){
              push(e);
            }
            else{
              push(e);
            }
       }
    // get immenent event
    public Event remove() {
        Event e=(Event)pop();
        //pop();
         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;
    }
}


