import java.io.*;
import javax.swing.*;
import javax.swing.JComponent;
import java.awt.*;
import java.awt.Graphics;
import java.util.*;
import java.lang.Math;
import java.lang.System;
import java.lang.Object;


public class cell
{

   private String id = null;
   private double curr_Frame = 0.0;
   private double stop_Frame = 0.0;
   private double x = 0;
   private double y = 0;
   private double x_curr = 0;
   private double y_curr = 0;
   private int x_goal = 0;
   private int y_goal = 0;
   private double curr_speed = 0.0;
   private double curr_direction = 0.0;
   private double curr_runtime = 0.0;
   private double curr_stopFrame = 0.0;
   private double speed = 0.0;
   private double direction = 0.0;
   private double runtime = 0.0;
   private double sctrPos = 0.0;
   private int arrayPos = 0;
   private int arrayX = 0;
   private int arrayY = 0;
   private Random randomNumerGenerator = new Random();
   private double randomNumber;
   private JLabel aLabel = new JLabel( "Start Motion" );
   private JFrame theWindow = new JFrame( "Simulation" );
   private Container contentPane = theWindow.getContentPane();
   private char[][] grid = new char[400][400];
   private JPanel thePanel = new JPanel();
   //class MyTableModel extends AbstractTableModel{};
   //private TableModel theGrid = new MyTableModel();
   //private JTable theTable = new JTable(400,400);

   public cell( String ID )
   {
      id = ID;
   }

   // Returns the current frame number.
   public double getCurrFrame()
   {
      return curr_Frame;
   }

   // Increase the current frame number by one.
   public void incrementFrame()
   {
	  curr_Frame++;
   }

   // Calculate upon which frame the motion will stop (change).
   public double getStopFrame()
   {
	  stop_Frame = this.getRequiredFrames() + this.getCurrFrame();
	  this.setStopFrame(stop_Frame);
      return stop_Frame;
   }

   // Set the stopping frame.
   public void setStopFrame(double sf)
   {
      curr_stopFrame = sf;
   }

   // Return the frame on which the current run will terminate.
   public double getCurrSF()
   {
	  return curr_stopFrame;
   }

   // Set required number of frames to approximately 100*runtime.
   public double getRequiredFrames()
   {
	  return Math.round(this.getCurrRntm() * 100);
   }

   // Use speed distribution to determine the speed.
   public double getSpeed()
   {
      // Generate a random number, uniformly distributed on [0.0, 1.0)
      randomNumber = randomNumerGenerator.nextDouble();
      // Produces a random number from the maxwell distribution (2-D).
      // The parameter (based upon Michelle's data) is 2008.75.
      speed = Math.sqrt((-2008.75)*Math.log(1-randomNumber));
      this.setSpeed(speed);
      return speed;
   }

   // Set this to be the current speed for future movement until end of run.
   public void setSpeed(double spd)
   {
	  curr_speed = spd;
   }

   // Return the speed being currently used.
   public double getCurrSpd()
   {
	  return curr_speed;
   }

   // Use runtime distribution to determine how long run will last.
   public double getRuntime()
   {
      // Generate a random number, uniformly distributed on [0.0, 1.0)
      randomNumber = randomNumerGenerator.nextDouble();
      // Runtime has exponetial distribution, mean = 0.2171
      runtime = -0.2171 * Math.log(1- randomNumber);
      this.setRuntime(runtime);
      return runtime;
   }

   // Set this to be the current runtime for futur movement until end of run.
   public void setRuntime(double rntm)
   {
   	  curr_runtime = rntm;
   }

   // Return the runtime currently being used.
   public double getCurrRntm()
   {
   	  return curr_runtime;
   }

   // Use the direction distribution to determine the direction for the next run.
   public double getDirection()
   {
      // Generate a random number, uniformly distributed on [0.0, 1.0)
      randomNumber = randomNumerGenerator.nextDouble();
      // Direction has uniform distribution on [0.0, 360.0)
      direction = 360 * randomNumber;
      this.setDirection(direction);
      return direction;
   }

   // Set this direction for use until the end of the run.
   public void setDirection(double dir)
   {
   	  curr_direction = dir;
   }

   // Returnt he current direction.
   public double getCurrDir()
   {
   	  return curr_direction;
   }

   // Dist. = Rate*Time
   public double getTotalDistance()
   {
	  return this.getCurrSpd()*this.getCurrRntm();
   }

   // Find portion of distance per frame.
   public double getIntervalDistance()
   {
      return (this.getTotalDistance())/(this.getRequiredFrames());
   }

   // Amount of movement in X direction.
   public double getDeltaX()
   {
	  return this.getIntervalDistance()*Math.cos(0.0174533*(this.getCurrDir()));
   }

   // Amount of movement in Y direction.
   public double getDeltaY()
   {
   	  return this.getIntervalDistance()*Math.sin(0.0174533*(this.getCurrDir()));
   }

   // Current X coordinate.
   public double getCurrX()
   {
	  return x_curr;
   }

   // Current Y coordinate.
   public double getCurrY()
   {
	  return y_curr;
   }

   // Make move in X direction, then reset curr.
   public double getNextX()
   {
	  x_curr+=this.getDeltaX();
	  return this.getCurrX();
   }

   // Make move in Y direction, then reset curr.
   public double getNextY()
   {
	  y_curr+=this.getDeltaY();
	  return this.getCurrY();
   }

   // Make the movements.  This method returns nothing, but the location
   // changes can be observed through the getCurr methods.
   public void makeMove()
   {
	  this.setSpeed(this.getSpeed());
	  this.setDirection(this.getDirection());
	  this.setRuntime(this.getRuntime());
	  this.setStopFrame(this.getStopFrame());
	  while(this.getCurrFrame() < this.getCurrSF())
	  {
		 x = this.getNextX();
         y = this.getNextY();
         this.incrementFrame();
	  }
   }

   // Make the moves incrementally, showing the graphics after each move.
   public void makeIncrementMove()
   {
	  this.setSpeed(this.getSpeed());
	  this.setDirection(this.getDirection());
	  this.setRuntime(this.getRuntime());
	  this.setStopFrame(this.getStopFrame());
	  while(this.getCurrFrame() < this.getCurrSF())
	  {
		 x = this.getNextX();
         y = this.getNextY();
//         draw(g,this.getArrayX(x),this.getArrayY(y));
         //thePanel.repaint();
         this.incrementFrame();
	  }
   }

   // One step in the scatter-plot method will be four "array" cells.
   // This method finds the equivalent array cell, given a sp position.
   public int arrayEquivalent(double spPos)
   {
	  sctrPos = spPos;
	  arrayPos = (int)Math.round(sctrPos*4);
	  return arrayPos;
   }

   // Get the current array X position, given an array sp position.
   public int getArrayX(double spX)
   {
	  return arrayX = (int)this.arrayEquivalent(spX);
   }

   // Get the current array Y position, given an array sp position.
   public int getArrayY(double spY)
   {
   	  return arrayY = (int)this.arrayEquivalent(spY);
   }

   // Show the array by printing to the screen (not graphical).
   public void showArray()
   {
	  for( int row = 0; row < 400; row++ )
	  {
		 for( int col = 0; col < 400; col++ )
		    System.out.print( grid[row][col] + " " );
         System.out.println();
	  }
   }

   // Use the drawString method to draw a graphic cell id
   // in the specified location of the panel.
/*   public void draw(Graphics g, int the_x, int the_y)
   {
      g.drawString(id, the_x, the_y);
   }
*/
   /*public void paintComponent(Graphics g)
   {
	  super.paintComponent(g);
   }*/

   // Construct the graphics panel.  Call this method once, first in main.
/*   public void showGraphics()
   {
	  theWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	  theWindow.setSize(400,400);
	  theWindow.setLocation(50,50);
	  //thePanel.add(theTable);
	  contentPane.add(thePanel, "Center");
	  theWindow.show();
   }

*/






}



45



