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

package sumulationsecondlab;

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

public class SingleServer {
    FEL fel;
    FCL fcl;
    double time;
    State s;
    double totalBusyTime;
    int maximumQL;

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

    protected void init() {
        totalBusyTime=maximumQL=0;
        fel = new FEL();
        fcl=new FCL();
        time = 0;
        s = new State();
        double runTime = 1000;
    
        fel.insert(new Event(Event.ARRIVAL,nextArrivalTime()));
        fcl.insert(new Customer(nextCustID(),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("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) {
        if(s.queueLen == 0) {
            s.serverState = State.IDLE;
        } else {
            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;
    }
protected double nextCustID(){
           return 1+Math.random()*50;
    }
public static void main(String[] args) {
         new SingleServer();
    }

}

class Customer{
    public static double custID;
    double time;
    public Customer(double id, double t){

        custID=id;
        time=t;
    }

}


class FCL 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 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);
            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;
    }
}

  
//    public static void main(String[] args) {
//        // TODO code application logic here
//    }


