public boolean action(Event evt, Object arg)
  {int hit;

   if (arg.equals("Load Pattern"))
     {
      patc=0;
      clearHistory();
      readPattern(pattern_filename.getText());
      //dumpPattern();
    } 
   else if (arg.equals("Train"))
    {
    int cc=toInt(epochs.getText());
    System.out.println("* Training Epoch Started ["+cc+" steps] *");
    train(cc);
    double err=testPattern();
    System.err.println( "* Epoch Done *");
    cv.repaint();

    }
   else if (arg.equals("Make Network from Pattern"))
    {
    System.err.println("Making a new network for "+pattern_filename.getText());
    netFromPattern(pattern_filename.getText());
    //dumpPattern();
    cv.repaint();
    System.err.println("Made a new network for "+pattern_filename.getText()+" and loaded the patterns.");
    }
   else if (arg.equals("Make Network from Weight"))
    {
     System.err.println("Making a new network from the weight file "+weight_filename.getText());
     netFromWeight(weight_filename.getText());
     cv.repaint();
    }
   else if (arg.equals("Load Weight"))
    {
     totalit=0;
     System.err.println("Loading weights from "+weight_filename.getText());
     clearHistory();
     installWeight(weight_filename.getText()); 
     cv.repaint();
    }
   else if (arg.equals("Generate Weight File"))
    {
     System.err.println("Writing weight file "+weight_filename.getText());
     writeWeight(weight_filename.getText());
    }
    else if (arg.equals("Randomize Weights"))
    {
     initNet();
    }

   else if (arg.equals("Test"))
    {
    double terr=testPattern();
    }
    else if (arg.equals("QUIT"))
    {
      System.exit(0);
    }
   else return super.action(evt,arg);
   return true;
 }



}

class MyCanvas extends Canvas
{
 public MyCanvas(BP owner)
 { this.owner=owner;
   
 }


 private int[][] drawlayer(Graphics g,int x, int y, int R, int gap,double v[],int size)
 {
  int X=x;
  int Y=y;
  int offset=(wi-size*(R+gap)-gap)/2;
  if (offset<0) {offset=0; System.err.println("Overflow occured during drawlayer...");}
  int[][] p=new int[size][3]; 
  for (int i=0;i<size;i++)
  { p[i][0]=x+offset+R/2; p[i][1]=y; p[i][2]=y+R;
    g.drawArc(x+offset,y,R,R,0,360);
    g.fillArc(x+offset,y,R,R,0,(int)(0.5+360*v[i]));
    x+=R+gap;
    if ((i+1)%30==0) x+=R+gap;
    if (p[i][0]>wi-R-R/2) {x=X; y+=5*R;}
  } 
  return p;
 }

 private boolean showOK(int from,int to)
 {
  if (showexc==null) return true;
  if (drawingfrom==0)   // from=X to=Y
  {
   if (showexc.x==0 && from==showexc.y) return true; //showthis
   if (showexc.x==1 &&   to==showexc.y) return true; //showthis
  } else
  if (drawingfrom==1)   // from=Y to=Z
  {
   if (showexc.x==1 && from==showexc.y) return true; //showthis
   if (showexc.x==2 &&   to==showexc.y) return true; //showthis
  } 
  return false; //don't show
 }
 
 private void drawconn(Graphics g,int[][] X,int[][] Y,int xd,int yd,double[][] w, double thresh) 
 {
  for (int j=0;j<yd;j++)
   {
    for (int i=0;i<xd;i++)
     { 
      if (!showOK(i,j)) continue;
      double st=Math.abs(w[j][i]);
      double tt=0;
      if (st==0) continue;
      if (w[j][i]<0) g.setColor(Color.blue);
               else  g.setColor(Color.red);
      if (thresh==0) tt=Math.log(st+1)/Math.log(Math.exp(1)); 
      else tt=Math.log(st/thresh)/Math.log(Math.exp(1)); // log2 of st
      int htness=(int)(tt+.5);
      if (tt<0) htness=-1;
      if (tt>5) htness=5;

      //if (st>=thresh)
      for (int t=-1;t<htness;t++)
       g.drawLine(X[i][0]+t,X[i][1],Y[j][0]+t,Y[j][2]);

     }
     
   }
 }



 public void paint(Graphics g)
 { 
   Dimension d=getSize();
   he=d.height;
   wi=d.width;
   midx=wi/2;
   int mhe=he-40;
   inplev=20+ mhe-mhe/3;
   hidlev=20+ mhe/3;
   outlev=20+ 0;
   
   double thresh=(owner.wscMAX-owner.wsc.getValue());
   thresh/=(owner.wscMAX/owner.wscrealMAX); // 0.wscrealMAX

   if (!owner.valid)
   { g.drawString("No network created",20,he/2); return; }
   else
    g.drawString("Weight display threshold:"+thresh,20,20); 

   xrad=20; xgap=10;
   while ((xrad+xgap)*(owner.Xdim+2) > wi) { xrad--; xgap--;}
   if (xrad<=0) xrad=1; if (xgap<=0) xgap=1; 
   yrad=20; ygap=10;
   while ((yrad+ygap)*(owner.Ydim+2) > wi) { yrad--; ygap--;}
   if (yrad<=0) yrad=1; if (ygap<=0) ygap=1; 
   zrad=20; zgap=10;
   while ((zrad+zgap)*(owner.Zdim+2) > wi)
    { zrad--; zgap--;}
   if (zrad<=0) zrad=1; 
   if (zgap<=0) zgap=1; 
   int xpos[][] = drawlayer(g,20,inplev,xrad,xgap,owner.X,owner.Xdim+1); 
   int ypos[][] = drawlayer(g,20,hidlev,yrad,ygap,owner.Y,owner.Ydim+1); 
   int zpos[][] = drawlayer(g,20,outlev,zrad,zgap,owner.Z,owner.Zdim); 
   lastxpos=xpos;
   lastypos=ypos;
   lastzpos=zpos;
   drawingfrom=0;
   drawconn(g,xpos,ypos,owner.Xdim+1,owner.Ydim+1,owner.w,thresh);
   drawingfrom=1;
   drawconn(g,ypos,zpos,owner.Ydim+1,owner.Zdim,owner.W,thresh);
   drawingfrom=-1;
 }

 public Point which(int x,int y)
 {
  if (lastxpos==null) return null;
  for (int i=0;i<lastxpos.length;i++)
   { if (inunit(x,y,lastxpos[i][0],lastxpos[i][1],lastxpos[i][2]))
       return new Point(0,i);
   }
   for (int i=0;i<lastypos.length;i++)
   { if (inunit(x,y,lastypos[i][0],lastypos[i][1],lastypos[i][2]))
       return new Point(1,i);
   }
   for (int i=0;i<lastzpos.length;i++)
   { if (inunit(x,y,lastzpos[i][0],lastzpos[i][1],lastzpos[i][2]))
       return new Point(2,i);
   }

  return null;
 }

 private boolean inunit(int X,int Y,int x,int yt,int yb)
 {
  double R=(yb-yt)/2;
  double y=(yt+yb)/2.0;
  if ( (X-x)*(X-x)+(Y-y)*(Y-y) <=R*R ) return true; 
  return false;
 }

 public void showThis(Point p)
 {
  showexc=p;
  repaint();
 }
 public void showAll()
 {
  showexc=null;
  repaint();
 }
 public int wi,he,midx,xgap,ygap,zgap,xrad,yrad,zrad;
 public int inplev,hidlev,outlev;
 private BP owner;
 
 private int drawingfrom=-1;
 private Point showexc=null;
 private int[][] lastxpos=null;
 private int[][] lastypos=null;
 private int[][] lastzpos=null;
}

//---------------------------------------------
class ArrayCover 
{
 public double[] val;
 public ArrayCover()
 { val=null;
 }
 public ArrayCover(double[] a)
 {
  val=new double[a.length] ;
  for (int i=0;i<a.length;i++) val[i]=a[i];
 }
 public ArrayCover(int size,double value)
 {
  val=new double[size] ;
  for (int i=0;i<size;i++) val[i]=value;
 }
 public ArrayCover(int size)
 {
  val=new double[size] ;
 }