/*
	Applet "Centres" by Keith Dear, November 1997
	keith.dear@anu.edu.au
*/

import java.applet.*;
import java.awt.*;

public class Centres extends Applet {
  final int LINEPOS=50, LINELEN=10;	// position and length of data
  final int LINELEFT=50, LINERIGHT=450;	// limits of the number-line
  final int MAXPOINTS=50;
  int oldx, j, n;
  int oldMedian, oldMean;
  int data[] = new int[MAXPOINTS];

public void init() {
  resize(500,100);			// for appletviewer
  setBackground(Color.white);
}

public void update(Graphics g) {	// not cleared first
  paint(g);
}

public void paint(Graphics g) {
  int mean=0, median=0;
  g.setColor(Color.black);
  g.drawLine(LINELEFT, LINEPOS, LINERIGHT, LINEPOS);
  if (oldx>0) {
    g.setColor(getBackground());
    g.drawLine(oldx,LINEPOS+1,oldx,LINEPOS+LINELEN);	// erase point
    oldx=0;
  }
  if (n>0) {
    g.setColor(Color.blue);
    for (int i=0; i<n; i++) {
      mean += data[i];
      g.drawLine(data[i], LINEPOS+1, data[i], LINEPOS+LINELEN);
    }
    mean /= n;
    if (n%2==0) { 			// n is even
	median = (data[n/2-1] + data[n/2])/2;
    } else {				// n is odd
	median = data[(n-1)/2];
    }
  }
  drawCentre(g, getBackground(), oldMedian);
  drawCentre(g, getBackground(), oldMean);
  if (n>0) {
    if (mean==median) {
      drawCentre(g, Color.orange, median);
    } else {
      drawCentre(g, Color.green, median);
      drawCentre(g, Color.red, mean);
    }
    oldMedian = median;
    oldMean = mean;
  }
}

private void drawCentre(Graphics g, Color c, int m) {
  g.setColor(c);
  g.drawLine(m, LINEPOS-1, m, LINEPOS-14);
  for (int i=1; i<4; i++) {
    g.drawLine(m-i, LINEPOS-2*i, m-i, LINEPOS-14+2*i);
    g.drawLine(m+i, LINEPOS-2*i, m+i, LINEPOS-14+2*i);
  }
}

// is the mouse near the line?
public boolean legal(int x, int y) {
  return (y>LINEPOS & y<LINEPOS+50 & x>LINELEFT & x<LINERIGHT);
}

public boolean mouseDown(Event event, int x, int y) {
  j = -1;				// no point identified yet
  if (legal(x,y)) {
    for (int i=0; i<n; i++) { 
	if (Math.abs(data[i]-x)<3) {	// close enough to count?
	  j=i;
	  break;
	}
    }
    if (j==-1 & n<MAXPOINTS) {		// add a new point
      j = n;
      data[n++] = x;
      sortj();
      repaint();
    }
  }
  return true;
}

public boolean mouseDrag(Event event, int x, int y) {
  if (j>=0 & oldx==0) {
    oldx = data[j];
    data[j] = x;
    sortj();
    repaint();
  }
  return true;
}

public boolean mouseUp(Event event, int x, int y) {
  if (j>=0) {
    if (legal(x,y)) {
      sortj();
    } else {				// remove this point
      oldx = data[j];
      n--;
      for (int i=j; i<n; i++) {
	data[i] = data[i+1]; 
      }
      repaint();
    }
  }
  return true;
}

// put point j in the right position in data[],
// kept sorted so that the median is easy to find
private void sortj() {
  if (n==1) return;
  if (j==0) {
    if (data[0]>data[1]) {
	swap(1);
	sortj();
    }
  } else if (j==n-1) {
    if (data[j-1]>data[j]) {
	swap(j-1);
	sortj();
    }
  } else {			// current point is interior
    if (data[j]<data[j-1]) {
	swap(j-1);
	sortj();
    } else if (data[j]>data[j+1]) {
	swap(j+1);
	sortj();
    }
  }
}

private void swap(int k) {
  int temp = data[j];
  data[j] = data[k];
  data[k] = temp;
  j = k;			// keep track of the current point
}

}


