import java.awt.*;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Font;


//MM1 Java   Update 2010/4/14  Takashi OHYAMA
public class mm1 extends Applet implements Runnable{
  Thread th;
  int ksm=1;
  int aruku=20,td=4000;
  int x3,x4;
  int mati=0,ma;
  int km;
  double l1,l2;
  double t1=0,t2m=0,tm=0,mean=0,tis=0,matit=0;
  int tI;
  int Nm=18,eN=10,couN=0,tlimit=14;
  double x1m;
  int xm,xt1,xt2,yt1,yt2;
  String la,mu,NS,meanS,tisS,couNS;
  String laS,muS;
  double matitd[]=new double[Nm];
  double heitd=0;
  String wt,heitS="";


  public void start(){
    if(th==null){
      th=new Thread(this);
      th.start();
    }
  }

  //generate random variables   uniformly distribution between 0 and 1
  public double randm(){
    double rand1m;
    rand1m=Math.random();
    return rand1m;
  }

  //convert to double value
  public double dou(String dous){
    double dou1;
    dou1 = (Double.valueOf(dous)).doubleValue();
    return dou1;
  }


  //log
  public double rog(double aa){
    double rog1;
    rog1=Math.log(aa);
    return rog1;
  }
  String imgK,imgS;
  String img[]=new String[eN];
  String img2[]=new String[Nm];
  int eee;
  Color col1,col2,col3;
  Font fon1,fon2;
  public void init(){
    col1=Color.black;
    col2=Color.white;
    col3=Color.yellow;
    fon1=new Font("Helvetica",Font.ITALIC,30);
    fon2=new Font("Courier",Font.PLAIN,12);
    laS=getParameter("lambda");
    muS=getParameter("mu");
    for(eee=0;eee<eN;eee++){
      img[eee]=""+eee;
    }
  }
  public void run(){

    //l1=lambda   arrival rate(mean time)
    //laS is set from html file : lambda parameter
    l1=dou(laS);
    //l2=mu    service time rate(mean time)
    //muS is set from html file : mu parameter
    l2=dou(muS);
    if(l1==999){//if laS=999 then set lambda to random variable
      l1=0.1+randm()*9.9;
    }
    if(l2==999){//if muS=999 then set mu to random variable
      l2=0.1+randm()*9.9;
    }
    la="lambda="+l1;
    mu="mu="+l2;
    NS="N="+(Nm-1);
    for(;;){
      xt1=(int)(tis*(700/tlimit)+30);
      t1=t1-tm;
      if(t1<=0){
        t1=-rog(randm())/l1;//generate exponential random variable t1. l1 is arrival rate, lambda
      }
      t2m=t2m-tm;
      if(t2m<=0){
        t2m=-rog(randm())/l2;//generate exponential random variable t2m. l2 is service rate, mu
      }
//    if M/M/2 queue: generate the third exponential random variable
//      t3m=t3m-tm;
//      if(t3m<=0){
//        t3m=-rog(randm())/l3;//generate exponential random variable t3m. l3 is service rate 2, mu2
//      }
//    if M/M/3 queue: generate the third exponential random variable
//      t4m=t4m-tm;
//      if(t4m<=0){
//        t4m=-rog(randm())/l4;//generate exponential random variable t4m. l4 is service rate 3, mu3
//      }
      if(mati<=0 || t1<t2m){//if arrival is earlier then next is arrival(t1)
        tm=t1;ksm=1;
      }
      else{//mati>0 && t1>t2m//if service is earlier then next event is service end(t2)
        tm=t2m;ksm=2;
      }
      if(mati>=Nm-1){//if customer is full, then reject any customers. So t2(mu) is next event.
        tm=t2m;ksm=2;
      }
      tI=(int)(tm*td);
      try{
        th.sleep(tI);
      }
      catch (InterruptedException e){}
      tis=tis+tm;
      matit=matit+mati*tm;
      mean=matit/tis;
      tisS="time="+(tis);
      meanS="E[L]="+mean;
      xt2=(int)(tis*(700/tlimit)+30);
      if(ksm==1){//arrival
        for(km=0;km<mati;km++){//set waiting time for all customers in line
          matitd[km]=matitd[km]+tm;
        }
        matitd[mati]=0;
        x1m=randm();
        xm=(int)(eN*x1m);
        imgK=img[xm];
        yt1=270-10*mati;
        yt2=270-10*(mati+1);
        for(x3=10;x3<=550-mati*30;x3=x3+30){
          repaint();
          try{
            th.sleep(aruku);
          }
          catch (InterruptedException e){}
        }
        mati++;
        img2[mati-1]=imgK;
      }//ksm==1
      else{//ksm==2  service ends
        imgS=img2[0];
        yt1=270-10*mati;
        yt2=270-10*(mati-1);
        mati--;
        for(km=1;km<=mati;km++){//customers number(ID) is replaced
          img2[km-1]=img2[km];
        }
        img2[mati]=null;
        matitd[0]=matitd[0]+tm;
        wt="W="+matitd[0];
        heitd=((heitd*couN)+matitd[0])/(couN+1);
        heitS="E[W]="+heitd;
        for(km=0;km<mati;km++){//waiting time
          matitd[km]=matitd[km+1]+tm;
        }
        matitd[mati]=0;
        couN++;
        couNS=""+couN;
        for(x4=580;x4<730;x4=x4+30){
          repaint();
          try{
            th.sleep(aruku);
          }
          catch (InterruptedException e){}
        }
      }//ksm==2
    }//next(;;)
  }
  public void update(Graphics g){
    paint(g);
  }

  //drawing screen
  public void paint(java.awt.Graphics g){
    if(xt1==30){
      g.setColor(col1);
      g.fillRect(1,1,700,300);
      g.setColor(col2);
      g.drawLine(30,271,700,271);
      g.drawLine(30,101,700,101);
      for(eee=0;eee<=6;eee++){
        g.drawLine(30+100*eee,272,30+100*eee,278);
      }
      for(eee=1;eee<=5;eee++){
        g.drawString(""+(eee*tlimit/7),23+eee*100,290);
      }
      g.drawString("time=0",20,288);
      g.drawString("time="+(tlimit-tlimit/7),620,288);
      g.drawLine(29,270,29,100);
      for(eee=0;eee<=Nm-1;eee++){
        g.drawLine(29,270-10*eee,22,270-10*eee);
      }
      g.drawString("0",10,274);
      g.drawString("10",5,174);
      g.drawLine(30,171,700,171);
      g.setColor(col2);
      g.setFont(fon1);
      g.drawString("*",550,60);
      g.drawLine(582,0,582,30);
      g.setFont(fon2);
      for(eee=3;eee<=Nm-1;eee++){
        g.drawString(""+eee,585-eee*30,50);
      }
      g.drawString(la,1,76);
      g.drawString(mu,201,76);
      g.drawString(NS,401,76);
    }
    g.setFont(fon1);
    for(ma=1;ma<=mati;ma++){
      g.setColor(col3);
      g.drawString(img2[ma-1],580-ma*30,30);
      g.setColor(col1);
      g.fillRect(550-ma*30,0,30,30);
    }
    if(ksm==1){
      g.setColor(col3);
      g.drawString(imgK,x3,30);
      g.setColor(col1);
      g.fillRect(x3-30,0,30,30);
    }
    if(ksm==2){
      g.setColor(col3);
      g.drawString(imgS,x4,30);
      g.setColor(col1);
      g.fillRect(x4-30,0,30,30);
    }
    g.fillRect(1,80,700,18);
    g.fillRect(500,63,200,17);
    g.fillRect(610,31,100,15);
    g.setColor(col2);
    g.drawLine(582,0,582,30);
    g.setFont(fon2);
    g.drawString(tisS,1,97);
    g.drawString(meanS,251,97);
    g.drawString(heitS,501,97);
    g.drawString(wt,501,76);
    g.drawString(couNS,611,45);
    g.setColor(col3);
    if(tis<tlimit+1){
      g.drawLine(xt1,yt1,xt2,yt1);
      g.drawLine(xt2,yt1,xt2,yt2);
    }
  }

  //sleep time
  public void stop(){
    if(th!=null){
      th.stop();
      th=null;
    }
  }
}

