/**
 * Title:        Double Circular M/M/1 Queues
 * Description:  Implementation of two M/M/1 Queues placed on a Cirlcle
 * Copyright:    Copyright (c) 2002
 * Company:      Columbia University
 * @author Angelos Stavrou
 * @version 1.0
 * Last change:  AS  04-13-2002 10 APR 101    08:59 PM
 */

import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.util.*;
import java.awt.geom.*;

class MainDraw extends JPanel{
public static int numberofpoints;
  public MainDraw() {    }
 /*
    public synchronized void stop() {
        thread = null;
    }

   public void start() {
        thread = new Thread(this);
        thread.setPriority(Thread.MIN_PRIORITY);
        thread.run();

    }

    public void run() {
        Thread me = Thread.currentThread();
        while (thread == me) {
            circular.jDesktopPane1.repaint();
            try {

                thread.sleep(40);
            } catch (InterruptedException e) { break; }
        }
        thread = null;
    }
   */
    public void paint(Graphics g){
        int Q1Start,Q1End, Q2Start, Q2End;
        Q1Start = circular.Q1Start;
        Q1End = circular.Q1End;
        Q2Start = circular.Q2Start;
        Q2End = circular.Q2End;
        Shape pEllipse[] = new Ellipse2D[numberofpoints+1];
        double distance;
        double posx[] = new double [numberofpoints+1];
        double posy[] = new double [numberofpoints+1];
        double cradious;
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        Dimension d = getSize();
        int maxWidth = getWidth()-50;
        int maxHeight = getHeight()-50;
        Shape mEllipse = new Ellipse2D.Double(25,25,450,450);

        for (int i = 0; i < numberofpoints; i++){
            double p1,p2;
            p1=250+(maxHeight/2)*Math.cos(2.*(Math.PI/(new Integer(numberofpoints).doubleValue()))*i);
            p2=250+(maxWidth/2)*Math.sin(2.*(Math.PI/(new Integer(numberofpoints).doubleValue()))*i);
            posx[i]=p1;
            posy[i]=p2;
            cradious=450*Math.PI/numberofpoints;
            pEllipse[i] = new Ellipse2D.Double(posx[i]-cradious/2.,posy[i]-cradious/2.,cradious,cradious);
            g2.draw(pEllipse[i]);
        }
        setBackground(Color.white);
 //       g2.draw(mEllipse);
          for (int p = 0; p < numberofpoints; p++){
          g2.setColor(Color.white);
          g2.fill(pEllipse[p]);
          g2.setColor(Color.black);
          g2.draw(pEllipse[p]);
          }
        if (Q1End >= Q1Start){
          for (int q1 = Q1Start; q1 < Q1End  ; q1++){
            g2.setColor(Color.blue);
            g2.fill(pEllipse[q1]);
          }
        }
        else{
          for (int q1 = Q1Start; q1 < numberofpoints  ; q1++){
            g2.setColor(Color.blue);
            g2.fill(pEllipse[q1]);
          }
          for (int q1 = 0; q1 < Q1End  ; q1++){
            g2.setColor(Color.blue);
            g2.fill(pEllipse[q1]);
          }

        }
        if (Q2End >= Q2Start){
          for (int q2 = Q2Start; q2 < Q2End  ; q2++){
            g2.setColor(Color.red);
            g2.fill(pEllipse[q2]);
          }
        }
        else{
          for (int q2 = Q2Start; q2 < numberofpoints  ; q2++){
            g2.setColor(Color.red);
            g2.fill(pEllipse[q2]);
          }
          for (int q2 = 0; q2 < Q2End  ; q2++){
            g2.setColor(Color.red);
            g2.fill(pEllipse[q2]);
          }
        }

    }

}

class exponential{
    public exponential(){}

    public double nexttime(double mean){
        double seconds = mean*Math.log(1/(1-Math.random()+0.0001));
        System.out.println("The seconds are: "+seconds);
        return seconds;
    }
}


class TTimer {
    public static java.util.Timer timer;

    public TTimer(int time) {
        timer = new java.util.Timer();
        timer.schedule(new CalcA(),0, time*30);

    }
}
class CalcA extends TimerTask {

  public void run(){
   if (circular.running == 0){
    TTimer.timer.cancel(); //Terminate the timer thread
    return;
  }



  if (circular.Q1LastArrival == 0){
    circular.Q1LastArrival = -(1./circular.vL1)*Math.log(1.-Math.random());
  }
  else if(circular.Q1LastDeparture == 0 ){
    circular.Q1LastDeparture = -(1./circular.vM1)*Math.log(1.-Math.random());
  }
  else if (circular.Q2LastArrival == 0){
    circular.Q2LastArrival = -(1./circular.vL2)*Math.log(1.-Math.random());
  }
  else if(circular.Q2LastDeparture == 0){
    circular.Q2LastDeparture = -(1./circular.vM2)*Math.log(1.-Math.random());
  }

 /* System.out.println("The seconds for the Queue 1 Arrival are: "+circular.Q1LastArrival);
  System.out.println("The seconds for the Queue 1 Departure are: "+circular.Q1LastDeparture);
  System.out.println("The seconds for the Queue 2 Arrival are: "+circular.Q2LastArrival);
  System.out.println("The seconds for the Queue 2 Departure are: "+circular.Q2LastDeparture);
  System.out.println(circular.Q1Start+"|"+circular.Q1End+"|"+circular.Q2Start+"|"+circular.Q2End);
  System.out.println(circular.vL1+"|"+circular.vM1+"|"+circular.vL2+"|"+circular.vM2);
   */
  double minimumofall = Math.min(circular.Q1LastArrival,Math.min(circular.Q1LastDeparture,Math.min
  (circular.Q2LastArrival,circular.Q2LastDeparture)));
  circular.minofall= minimumofall;
  if (circular.Q1LastArrival == minimumofall){
      circular.Q1LastArrival =0;
      circular.Q1LastDeparture = circular.Q1LastDeparture - minimumofall;
      circular.Q2LastArrival = circular.Q2LastArrival - minimumofall;
      circular.Q2LastDeparture = circular.Q2LastDeparture - minimumofall;
      System.out.println("We have an arrival for Queue 1");
      circular.Q1End++;
      circular.Q1End=circular.Q1End%circular.DrawPanel.numberofpoints;
  }
  else if (circular.Q1LastDeparture == minimumofall){
      circular.Q1LastArrival = circular.Q1LastArrival - minimumofall;
      circular.Q1LastDeparture = 0;
      circular.Q2LastArrival = circular.Q2LastArrival - minimumofall;
      circular.Q2LastDeparture = circular.Q2LastDeparture - minimumofall;
      System.out.println("We have an departure for Queue 1");
      if (circular.Q1Start != circular.Q1End){
        circular.Q1Start++;
        circular.Q1Start=circular.Q1Start%circular.DrawPanel.numberofpoints;
      }
  }
  else if (circular.Q2LastArrival == minimumofall){
      circular.Q2LastArrival =0;
      circular.Q2LastDeparture = circular.Q2LastDeparture - minimumofall;
      circular.Q1LastArrival = circular.Q1LastArrival - minimumofall;
      circular.Q1LastDeparture = circular.Q1LastDeparture - minimumofall;
      System.out.println("We have an arrival for Queue 2");
      circular.Q2End++;
      circular.Q2End=circular.Q2End%circular.DrawPanel.numberofpoints;
  }
  else if (circular.Q2LastDeparture == minimumofall){
      circular.Q2LastArrival = circular.Q2LastArrival - minimumofall;
      circular.Q2LastDeparture = 0;
      circular.Q1LastArrival = circular.Q1LastArrival - minimumofall;
      circular.Q1LastDeparture = circular.Q1LastDeparture - minimumofall;
      System.out.println("We have an departure for Queue 2");
      if (circular.Q2Start != circular.Q2End){
        circular.Q2Start++;
        circular.Q2Start=circular.Q2Start%circular.DrawPanel.numberofpoints;
      }
  }
  circular.jDesktopPane1.repaint();
  }
}


public class circular extends javax.swing.JApplet {

public static int Q1Start;
public static int Q1End;
public static int Q2Start;
public static int Q2End;
public static double Q1LastArrival;
public static double Q1LastDeparture;
public static double Q2LastArrival;
public static double Q2LastDeparture;
public static int running;
public static double vL1,vM1,vL2,vM2;
public static double minofall;


  public static void initComponents2(){
    DrawPanel.numberofpoints=Integer.parseInt(Mem.getText());
    Q1Start=0;
    Q1End=0;
    Q2Start=Math.round(DrawPanel.numberofpoints/2);
    Q2End=Math.round(DrawPanel.numberofpoints/2);
    minofall=0;
    //running = 0;
    DrawPanel.repaint();
  }
    /** Creates new form circular */
    public circular() {
        initComponents();
        initComponents2();
        DrawPanel.numberofpoints=Integer.parseInt(Mem.getText());
        DrawPanel.repaint();
    }
    public static void  main(String[] args) {
        javax.swing.JApplet circularApplet = new circular();
        JFrame MainFrame = new JFrame("Double Queue Model Project for Modeling and Evaluation Class");
        MainFrame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {System.exit(0);}
            public void windowDeiconified(WindowEvent e) {  }
            public void windowIconified(WindowEvent e) {  }
        });
        MainFrame.getContentPane().add("Center", circularApplet);
        MainFrame.pack();
        MainFrame.setSize(new Dimension(800,600));
        MainFrame.show();


    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents() {//GEN-BEGIN:initComponents
        jDesktopPane1 = new javax.swing.JDesktopPane();
        DrawPanel = new MainDraw();
        M1 = new javax.swing.JTextField();
        jLabelMu1 = new javax.swing.JLabel();
        L1 = new javax.swing.JTextField();
        jLabelL1 = new javax.swing.JLabel();
        JLablelL2 = new javax.swing.JLabel();
        M2 = new javax.swing.JTextField();
        JLabelMem = new javax.swing.JLabel();
        Mem = new javax.swing.JTextField();
        JLabelMu2 = new javax.swing.JLabel();
        L2 = new javax.swing.JTextField();
        Start = new javax.swing.JButton();
        Reset = new javax.swing.JButton();

        DrawPanel.setBorder(new javax.swing.border.EtchedBorder());
        jDesktopPane1.add(DrawPanel, javax.swing.JLayeredPane.DEFAULT_LAYER);
        DrawPanel.setBounds(10, 30, 500, 500);

        M1.setText("1");
        M1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                M1ActionPerformed(evt);
            }
        });

        jDesktopPane1.add(M1, javax.swing.JLayeredPane.DEFAULT_LAYER);
        M1.setBounds(530, 130, 20, 20);

        jLabelMu1.setText("Mu 1");
        jDesktopPane1.add(jLabelMu1, javax.swing.JLayeredPane.DEFAULT_LAYER);
        jLabelMu1.setBounds(530, 110, 27, 16);

        L1.setText("1");
        L1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                L1ActionPerformed(evt);
            }
        });

        jDesktopPane1.add(L1, javax.swing.JLayeredPane.DEFAULT_LAYER);
        L1.setBounds(530, 70, 20, 20);

        jLabelL1.setText("Lambda 1");
        jDesktopPane1.add(jLabelL1, javax.swing.JLayeredPane.DEFAULT_LAYER);
        jLabelL1.setBounds(530, 50, 56, 16);

        JLablelL2.setText("Lambda 2");
        jDesktopPane1.add(JLablelL2, javax.swing.JLayeredPane.DEFAULT_LAYER);
        JLablelL2.setBounds(630, 50, 56, 20);

        M2.setText("1.2");
        M2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                M2ActionPerformed(evt);
            }
        });

        jDesktopPane1.add(M2, javax.swing.JLayeredPane.DEFAULT_LAYER);
        M2.setBounds(630, 130, 20, 20);

        JLabelMem.setForeground(java.awt.Color.green);
        JLabelMem.setText("Total Memory Cells");
        jDesktopPane1.add(JLabelMem, javax.swing.JLayeredPane.DEFAULT_LAYER);
        JLabelMem.setBounds(550, 160, 110, 30);

        Mem.setText("150");
        Mem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                MemActionPerformed(evt);
            }
        });

        Mem.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                MemFocusLost(evt);
            }
        });

        jDesktopPane1.add(Mem, javax.swing.JLayeredPane.DEFAULT_LAYER);
        Mem.setBounds(590, 190, 40, 20);

        JLabelMu2.setText("Mu 2");
        jDesktopPane1.add(JLabelMu2, javax.swing.JLayeredPane.DEFAULT_LAYER);
        JLabelMu2.setBounds(630, 110, 27, 16);

        L2.setText("1.2");
        L2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                L2ActionPerformed(evt);
            }
        });

        jDesktopPane1.add(L2, javax.swing.JLayeredPane.DEFAULT_LAYER);
        L2.setBounds(630, 70, 20, 20);

        Start.setText("Start");
        Start.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                StartActionPerformed(evt);
            }
        });

        jDesktopPane1.add(Start, javax.swing.JLayeredPane.DEFAULT_LAYER);
        Start.setBounds(520, 220, 62, 26);

        Reset.setText("Reset");
        Reset.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ResetActionPerformed(evt);
            }
        });

        jDesktopPane1.add(Reset, javax.swing.JLayeredPane.DEFAULT_LAYER);
        Reset.setBounds(640, 220, 67, 26);

        getContentPane().add(jDesktopPane1, java.awt.BorderLayout.CENTER);

    }//GEN-END:initComponents

    private void MemFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_MemFocusLost
        DrawPanel.numberofpoints=Integer.parseInt(Mem.getText());
        DrawPanel.repaint();
        jDesktopPane1.repaint();
    }//GEN-LAST:event_MemFocusLost

    private void ResetActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ResetActionPerformed
        circular.running = 0;
        L1.enable();
        M1.enable();
        L2.enable();
        M2.enable();
        Mem.enable();
        circular.initComponents2();
        jDesktopPane1.repaint();
    }//GEN-LAST:event_ResetActionPerformed

    private void StartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_StartActionPerformed
        L1.disable();
        M1.disable();
        L2.disable();
        M2.disable();
        Mem.disable();
        circular.running = 1;
        circular.vL1 = Double.parseDouble(circular.L1.getText());
        circular.vM1 = Double.parseDouble(circular.M1.getText());
        circular.vL2 = Double.parseDouble(circular.L2.getText());
        circular.vM2 = Double.parseDouble(circular.M2.getText());
        Q1LastArrival =-(1./vL1)*Math.log(1.-Math.random());
        Q1LastDeparture =-(1./vM1)*Math.log(1.-Math.random());
        Q2LastArrival = -(1./vL2)*Math.log(1.-Math.random());
        Q2LastDeparture =-(1./vM2)*Math.log(1.-Math.random());
        DrawPanel.numberofpoints=Integer.parseInt(Mem.getText());
        circular.initComponents2();
        jDesktopPane1.repaint();
        new TTimer(1);

    }//GEN-LAST:event_StartActionPerformed

    private void L2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_L2ActionPerformed
        // Add your handling code here:
    }//GEN-LAST:event_L2ActionPerformed

    private void M2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_M2ActionPerformed
        // Add your handling code here:
    }//GEN-LAST:event_M2ActionPerformed

    private void L1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_L1ActionPerformed
        // Add your handling code here:
    }//GEN-LAST:event_L1ActionPerformed

    private void MemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_MemActionPerformed
        DrawPanel.numberofpoints=Integer.parseInt(Mem.getText());
        DrawPanel.repaint();
    }//GEN-LAST:event_MemActionPerformed

    private void M1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_M1ActionPerformed
        // Add your handling code here:
    }//GEN-LAST:event_M1ActionPerformed


    // Variables declaration - do not modify//GEN-BEGIN:variables
    public static javax.swing.JDesktopPane jDesktopPane1;
    public static MainDraw DrawPanel;
    public static javax.swing.JTextField M1;
    private javax.swing.JLabel jLabelMu1;
    public static javax.swing.JTextField L1;
    private javax.swing.JLabel jLabelL1;
    private javax.swing.JLabel JLablelL2;
    public static javax.swing.JTextField M2;
    private javax.swing.JLabel JLabelMem;
    public static javax.swing.JTextField Mem;
    private javax.swing.JLabel JLabelMu2;
    public static javax.swing.JTextField L2;
    private javax.swing.JButton Start;
    private javax.swing.JButton Reset;
    // End of variables declaration//GEN-END:variables

}
