
import java.awt.*;
import java.applet.*;
import java.lang.*;
import java.lang.Number;
import java.lang.Math;

/**
 * Draws a clock with the specified modulus.
 * Labels it with representatives for congruence classes in one or more cycles
 * Some of the things in this applet work, but are not used.
 */
 

public class clock extends Applet {
    clockControls controls;
	
    public void init() {
	setLayout(new BorderLayout());
	clockCanvas c = new clockCanvas();
	add("Center", c);
	add("South", controls = new clockControls(c));
    }
    
    public void start() {
		controls.enable();
    }

    public void stop() {
		controls.disable();
    }
    
    public boolean handleEvent(Event e) {
		if (e.id == Event.WINDOW_DESTROY) {
	    	System.exit(0);
		}
		return false;
    }

    public static void main(String args[]) {
	Frame f = new Frame("clock");
	clock	clock = new clock();
	clock.init();
	clock.start();
	f.add("Center", clock);
	f.resize(300, 300);
	f.show();
    }
}
    

class clockCanvas extends Canvas {
	
    int	 modulus = 12;
    int cycles = 1; 
    int firstCycle = 0;
    int hand = 0;
	int term1 = 0;
    int term2 = 0;
 
    public void paint(Graphics g) {
        Point endHand = new Point(xcoord(80,resAngle(this.hand)),
        							ycoord(80,resAngle(this.hand)));
     	g.translate(200,200);
     	g.setColor(Color.white);
     	g.fillOval(-100,-100,200,200);
     	g.setColor(Color.black);
     	g.drawOval(-100,-100,200,200);
     	/*PtoR(endHand, 80, resAngle(hand));*/
     	g.setColor(Color.red);
     	g.drawLine(0,0,endHand.x, endHand.y);
     	drawArrowhead(g,endHand.x, endHand.y,resAngle(hand));
     	g.setColor(Color.green);
     	drawArrowArc(g,0,term1);
     	g.setColor(Color.black);
		for (int i = 0; i < modulus; i++) {
	     		g.drawLine(
	     			xcoord(100,resAngle(i)),
	     			ycoord(100,resAngle(i)),
	     			xcoord(95,resAngle(i)),
	     			ycoord(95,resAngle(i)));
		}
     	g.translate(-5,4);
     	for (int j = firstCycle; j < cycles; j++) {
	     	for (int i = 0; i < modulus; i++) {
	     		g.drawString(
	     			Integer.toString(j*modulus+i),
	     			xcoord(90+20*j,resAngle(j*modulus+i)),
	     			ycoord(90+20*j,resAngle(j*modulus+i)));
			}
		}
     }
     /* Conversion from polar coordinates to rectangular */
    public int xcoord(int r, double theta) {
     	int x = (int)((double)r * Math.cos(-theta * Math.PI / 180));
     	return x;
     	}
	public int ycoord(int r, double theta) {
     	int y = (int)((double)r * Math.sin(-theta * Math.PI / 180));
     	return y;
     	}
     /*Screen angle on a clock corresponding to a residue with respect to the modulus.
           * Clock angles go clockwise and start at top. Screen angles go counterclockwise and start at 3 oclock. */
    public double resAngle(int res) {
     	double theta = (double)(90-360*res/modulus);
     	return theta;
     	}
    public void drawArrowhead(Graphics g, int x, int y, double theta) {
    	g.translate(x,y);
    	g.drawLine(0,0,xcoord(10,theta+180+30),ycoord(10,theta+180+30));
    	g.drawLine(0,0,xcoord(10,theta+180-30),ycoord(10,theta+180-30));
    	g.translate(-x,-y);
    }
    public void drawArrowArc(Graphics g, int a, int b) {
    	if (b-a != 0) {
    	g.drawArc(-110,-110,220,220,(int)(resAngle(a)),(int)(-(b-a)*360/modulus));
    	drawArrowhead(g,xcoord(110,resAngle(b)),
    	              ycoord(110,resAngle(b)),
    	              resAngle(b)-(Math.abs(b-a)/(b-a))*90);
    	}
    }

    public void redraw(int a, int b) {
    {
	this.hand++;
	this.term1 = a;
	this.term2 = b;
	repaint();
    }
    
}
}


class clockControls extends Panel {
    
    TextField n1;
    TextField n2;
    clockCanvas canvas;
	Thread tickerthread;
	
    public clockControls(clockCanvas canvas) {
	this.canvas = canvas;
	add(new Button("Tick"));
	add(new Button("Stop"));
    }

    public boolean action(Event ev, Object arg) {
	if (ev.target instanceof Button) {
	    String buttonLabel = (String)arg;
		if (buttonLabel.equals("Tick")) {
			if (tickerthread == null) {
		    	tickerthread = new Thread(new ticker(1000, this.canvas));
		    	tickerthread.start();
	    	}
		} 
		else if (buttonLabel.equals("Stop")) {
			if (tickerthread != null) {
				tickerthread.stop();
				tickerthread = null;
			}
		}
	    return true;
	}
	return false;
    }
   
}
	
class ticker implements Runnable {
	int interval;
	clockCanvas myclock;
	
	ticker(int interval, clockCanvas myclock) {
		this.interval = interval;
		this.myclock = myclock;
	}
	
	public void run() {
		while(true) {
			try {
				Thread.sleep(interval);
				myclock.redraw(0, 0);
			}
			catch (Exception e) return;
		}	
			
	}
}
