Trig Drill
<< Birds | OtherProjectsTrailIndex | Guassian Elimination >>
Ngon.java
import java.awt.Polygon;
public class Ngon extends Polygon
{
public Ngon(int sides, int left, int top, int radius){
this(sides, left, top, radius, 0);
}
public Ngon(int sides, int left, int top, int radius, double degrees){
double start=degrees*Math.PI/180.0;
for(double theta=start; theta<2*Math.PI+start; theta+=2*Math.PI/sides)
addPoint((int)(radius*Math.cos(theta)), (int)(radius*Math.sin(theta+Math.PI)));
translate(left+radius,top+radius);
}
public int getX(int i){
return this.xpoints[i];
}
public int getY(int i){
return this.ypoints[i];
}
public int getCenterX(){return getBounds().x + getBounds().width/2;}
public int getCenterY(){return getBounds().y + getBounds().height/2;}
}
CircleButton.java
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
public class CircleButton
{
// instance variables - replace the example below with your own
private Rectangle bounds;
protected Color color;
private String name;
protected boolean hilight;
protected boolean pressed;
private Font font=new Font("SansSerif",Font.BOLD, 14);
/**
* Constructor for objects of class CircleButton
*/
public CircleButton(int x, int y, int size, String name, Color color)
{
this(x,y,size,size,name,color);
}
public CircleButton(int x, int y, int width, int height, String name, Color color)
{
bounds = new Rectangle(x,y,width,height);
this.color = color;
this.name = name;
this.hilight=false;
this.pressed=false;
}
public void draw(Graphics g)
{
if (hilight){
g.setColor(Color.BLACK);
g.fillOval(bounds.x-4, bounds.y-4, bounds.width+8, bounds.height+8);
}
if (pressed)
g.setColor(Color.BLACK);
else
g.setColor(color);
g.fillOval(bounds.x, bounds.y, bounds.width, bounds.height);
g.setFont(font);
if (pressed)
g.setColor(Color.WHITE);
else
g.setColor(Color.BLACK);
int x=bounds.x+(bounds.width-name.length()*7)/2;
int y=bounds.y+(bounds.height/2+4);
g.drawString(name, x, y);
}
public void setHilight(boolean b){ hilight=b;}
public boolean isHilighted() {return hilight;}
public void setPressed(boolean b){ pressed=b;}
public boolean isPressed() { return pressed; }
public boolean contains(int x, int y){
return bounds.contains(x,y);
}
public String getName() {return name;}
public void setName(String s){name=s;}
public Color getColor(){return color;}
public void setColor(Color c){color=c;}
public void setBounds(Rectangle r){bounds=r;}
public Rectangle getBounds(){return bounds;}
public int getX(){return bounds.x;}
public int getY(){return bounds.y;}
public int getSize(){return bounds.width;}
public void setFont(Font f){font=f;}
public Font getFont(){return font;}
public int getCenterX(){return bounds.x + bounds.width/2;}
public int getCenterY(){return bounds.y + bounds.height/2;}
}
QuestionButton.java
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
public class QuestionButton extends CircleButton
{
private boolean visable;
private String question,answer;
public QuestionButton(int x, int y, int width, int height, String name, Color color) {
super(x, y, width, height, name, color);
visable=true;
}
public boolean isVisable(){return visable;}
public void setVisable(boolean b){ visable=b;}
public void draw(Graphics g){
if (!visable)
return;
setFont(new Font("serif", Font.ITALIC + Font.BOLD, 36));
if (hilight){
g.setColor(Color.BLACK);
g.fillOval(getBounds().x-4, getBounds().y-4, getBounds().width+8, getBounds().height+8);
}
if (pressed)
g.setColor(Color.BLACK);
else
g.setColor(color);
g.fillOval(getBounds().x, getBounds().y, getBounds().width, getBounds().height);
if (pressed)
g.setColor(Color.WHITE);
else
g.setColor(Color.BLACK);
int x=getBounds().x+(getBounds().width-getName().length()*18)/2;
int y=getBounds().y+(getBounds().height/2+10);
g.setFont(getFont());
g.drawString(getName(), x, y);
}
public void setQuestion(String q, String a){
question=q;
answer=a;
}
public void showQuestion(){
this.setName(question);
}
public void showAnswer(){
this.setName(question+answer);
}
public String getAnswer() {
return answer;
}
}
AnswerButton.java
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
public class AnswerButton extends CircleButton
{
private boolean visable;
public AnswerButton(int x, int y, int width, int height, String name, Color color) {
super(x, y, width, height, name, color);
visable=true;
}
public boolean isVisable(){return visable;}
public void setVisable(boolean b){ visable=b;}
public void draw(Graphics g){
if (visable){
//g.setFont(new Font("sansserif",Font.BOLD,14));
super.draw(g);
}
}
}
Stats.java
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
public class Stats
{
private ArrayList<Double> d;
private double sum, sumSq;
DecimalFormat df;
public Stats(){
d=new ArrayList<Double>();
sum=0;
sumSq=0;
df=new DecimalFormat("#.##");
}
public void add(double x){
d.add(x);
sum+=x;
sumSq+=x*x;
}
public double getMean(){
if (d.size()>0)
return sum/d.size();
return 0;
}
public String getMeanString(){
if(d.size()<1)
return "";
return df.format(getMean());
}
public double getSD(){
if (d.size()<2)
return 0;
return Math.sqrt((sumSq-(sum*sum/d.size()))/(d.size()-1));
}
public String getSDString(){
if(d.size()<2)
return "";
return df.format(getSD());
}
public double getQuartile(int q){
int n=d.size();
if(n<4)
if(n>0)
return d.get(0);
else
return 0;
Collections.sort(d);
int index=q*n/4;
boolean even=n%q==0;
if (q==3){
even=n%4==0;
}
if (even)
return 0.5*( d.get(index)+ d.get(index-1));
return d.get(index);
}
public String getIQRString(){
if (d.size()<4)
return "";
return "between "+df.format(getQuartile(1))+" and "+df.format(getQuartile(3));
}
public String getQuartileString(int q){
return df.format(getQuartile(q));
}
public int n(){ return d.size();}
}
TrigDrill3.java
import java.applet.Applet;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
public class TrigDrill3 extends Applet implements MouseListener,MouseMotionListener
{
private HashMap<String,String> sin, cos, tan,csc,sec,cot;
private Image virtualMem;
private BufferedImage img;
private Graphics gBuffer;
private ArrayList<AnswerButton> btns;
private QuestionButton qBtn;
private Rectangle easyBtn,resetBtn;
private Stats stats;
private Font big,small;
private boolean easyMode, started;
private String message;
public static final String pi="\u03c0";
public static final String root="\u221A";
public static final String[] angles={"-"+pi+"/2", "-"+pi+"/3", "-"+pi+"/4", "-"+pi+"/6",
"0", pi+"/6", pi+"/4", pi+"/3",
pi+"/2", "2"+pi+"/3", "3"+pi+"/4", "5"+pi+"/6",
pi, "7"+pi+"/6", "5"+pi+"/4", "4"+pi+"/3",
"3"+pi+"/2", "5"+pi+"/3", "7"+pi+"/4", "11"+pi+"/6"};
public static final String[] functions={"arcsin", "arccos", "arctan", "arccsc", "arcsec","arccot"};
public static final String[] ratios = {"0", "1/2",root+"3/3",root+"2/2",root+"3/2","1","2"+root+"3/3",
"undefined", "-1/2","-"+root+"3/3","-"+root+"2/2","-"+root+"3/2","-1","-"+root+"2",
"-"+root+"3","-2"+root+"3/3"};
private Color btnColor, bgColor;
private int centerX, centerY, count, correct;
private DecimalFormat df;
long startTime;
public void initAnswers(){
sin = new HashMap<String,String>();
cos = new HashMap<String,String>();
tan = new HashMap<String,String>();
csc = new HashMap<String,String>();
sec = new HashMap<String,String>();
cot = new HashMap<String,String>();
sec.put(pi, "-1");
sec.put("5"+pi+"/6", "-2"+root+"3/3");
sec.put("3"+pi+"/4","-"+root+"2");
sec.put("2"+pi+"/3", "-2");
sec.put(pi+"/2", "undefined");
sec.put(pi+"/3", "2");
sec.put(pi+"/4",root+"2");
sec.put(pi+"/6", "2"+root+"3/3");
sec.put("0", "1");
cos.put(pi, "-1");
cos.put("5"+pi+"/6", "-"+root+"3/2");
cos.put("3"+pi+"/4","-"+root+"2/2");
cos.put("2"+pi+"/3", "-1/2");
cos.put(pi+"/2", "0");
cos.put(pi+"/3", "1/2");
cos.put(pi+"/4",root+"2/2");
cos.put(pi+"/6", root+"3/2");
cos.put("0", "1");
sin.put(angles[0], "-1");
sin.put(angles[1], "-"+root+"3/2");
sin.put(angles[2], "-"+root+"2/2");
sin.put(angles[3], "-1/2");
sin.put(angles[4], "0");
sin.put(angles[5], "1/2");
sin.put(angles[6], root+"2/2");
sin.put(angles[7], root+"3/2");
sin.put(angles[8], "1");
csc.put(angles[0], "-1");
csc.put(angles[1], "-2"+root+"3/3");
csc.put(angles[2], "-"+root+"2");
csc.put(angles[3], "-2");
csc.put(angles[4], "undefined");
csc.put(angles[5], "2");
csc.put(angles[6], root+"2");
csc.put(angles[7], "2"+root+"3/3");
csc.put(angles[8], "1");
tan.put(angles[0], "undefined");
tan.put(angles[1], "-"+root+"3");
tan.put(angles[2], "-1");
tan.put(angles[3], "-"+root+"3/3");
tan.put(angles[4], "0");
tan.put(angles[5], root+"3/3");
tan.put(angles[6], "1");
tan.put(angles[7], root+"3");
tan.put(angles[8], "undefined");
cot.put(angles[0], "0");
cot.put(angles[1], "-"+root+"3/3");
cot.put(angles[2], "-1");
cot.put(angles[3], "-"+root+"3");
cot.put(angles[4], "undefined");
cot.put(angles[5], root+"3");
cot.put(angles[6], "1");
cot.put(angles[7], root+"3/3");
cot.put(angles[8], "0");
}
public void makeQuestion(){
int max=6;
if (easyMode)
max=3;
int f = (int)(max*Math.random());
//for sin,csc,tan,cot, angles 0 through 8
int a = (int)(9*Math.random());
if (f==1 || f==4){//for cos,sec angle 4 through 12
a+=4;
}
//repair so undefined is ok
if ((f==3 || f==2) && a==0)//csc or tan undefined
a=8;
if ((f==5 ||f==4) && a==12)//sec or cot undefined
a=4;
String answer=angles[a];
String question="";
if (f==0)
question=sin.get(answer);
else if (f==1)
question=cos.get(answer);
else if (f==2)
question=tan.get(answer);
else if (f==3)
question=csc.get(answer);
else if (f==4)
question=sec.get(answer);
else if (f==5)
question=cot.get(answer);
question=functions[f]+"("+question+")=";
qBtn.setQuestion(question, answer);
}
public void init(){
easyMode=true;
started=false;
count=0;
correct=0;
df=new DecimalFormat("##.#");
virtualMem = createImage(getWidth(),getHeight());
gBuffer = virtualMem.getGraphics();
message=" Press Start to begin";
big = new Font("serif", Font.ITALIC + Font.BOLD, 36);
small = new Font("Ariel",Font.BOLD,14);
//bgColor = new Color(255, 204,167);
bgColor = new Color(226, 182,138);
btnColor = new Color(255, 230,211);
initAnswers();
Ngon shape = new Ngon(16, 30, 110, 180,-90);
btns = new ArrayList<AnswerButton>();
for (int i=0; i<16; i++)
btns.add(new AnswerButton(shape.getX(i),shape.getY(i),65,25 ,angles[i], btnColor) );
centerX=btns.get(0).getCenterX();
centerY=btns.get(4).getCenterY();
qBtn=new QuestionButton(105,20, 300,55,"Start", Color.YELLOW);
easyBtn=new Rectangle(375,525,125,25);
resetBtn=new Rectangle(0,0,95,25);
stats = new Stats();
addMouseListener(this);
addMouseMotionListener(this);
}
public void paint(Graphics g){
gBuffer.setColor(bgColor);
gBuffer.fillRect(0, 0, getWidth(), getHeight());
gBuffer.setColor(Color.BLACK);
gBuffer.drawLine(centerX, 110, centerX, 480);
gBuffer.drawLine(32, centerY, 400, centerY);
gBuffer.setColor(btnColor);
//gBuffer.fillRect(easyBtn.x, easyBtn.y, easyBtn.width, easyBtn.height);
//gBuffer.fillRect(resetBtn.x, resetBtn.y, resetBtn.width, resetBtn.height);
for (int i=0; i<btns.size(); i++){
AnswerButton b=btns.get(i);
if (b.isHilighted()){
gBuffer.drawLine(centerX, centerY, b.getCenterX(), b.getCenterY());
gBuffer.drawLine(b.getCenterX(), centerY, b.getCenterX(), b.getCenterY());
}
b.draw(gBuffer);
}
qBtn.draw(gBuffer);
gBuffer.setFont(small);
gBuffer.drawString(message, 120,100);
gBuffer.drawString(correct+" out of "+count+" correct", 20,20);
if (count>0)
gBuffer.drawString(df.format(100*(double)correct/count)+"%", 20,40);
if (easyMode)
gBuffer.drawString("Easy Mode On", 380, 545);
else
gBuffer.drawString("Easy Mode Off", 380, 545);
if (stats.n()>3){
gBuffer.drawString("Mean time: "+stats.getMeanString(), 10, 515);
gBuffer.drawString("Half your correct times are ", 10, 530);
gBuffer.drawString(stats.getIQRString()+" secs", 10, 545);
}
g.drawImage(virtualMem,0,0,this);
}
public void mouseClicked(MouseEvent e){}
public void mousePressed(MouseEvent e){
int x=e.getX();
int y=e.getY();
for(CircleButton c:btns)
c.setPressed(c.contains(x,y));
qBtn.setPressed(qBtn.contains(x,y));
repaint();
}
public void mouseReleased(MouseEvent e){
int x=e.getX();
int y=e.getY();
for(AnswerButton c:btns){
c.setPressed(false);
if(c.contains(x,y))
doButton(c);
}
if (qBtn.contains(x,y)){
qBtn.setPressed(false);
if (!started){
started=true;
message="";
this.makeQuestion();
startTime= new Date().getTime();
qBtn.setColor(Color.YELLOW);
qBtn.showQuestion();
}
}
if (resetBtn.contains(x,y)){
count=0; correct=0; stats=new Stats();
}
if (easyBtn.contains(x,y)){
easyMode=!easyMode;
}
repaint();
}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseMoved(MouseEvent e){
int x=e.getX();
int y=e.getY();
//if(!gameOver)
for(CircleButton c:btns){
c.setHilight(c.contains(x,y));
}
qBtn.setHilight(qBtn.contains(x,y));
repaint();
}
public void mouseDragged(MouseEvent e){}
public void doButton(AnswerButton b) {
if(!started)
return;
double time=(new Date().getTime()-startTime)/1000.0;
started=false;
qBtn.showAnswer();
message="Time:"+time;
count++;
if (b.getName().equals(qBtn.getAnswer() )){
message="Correct! You got that in "+time+" secs.";
stats.add(time);
correct++;
qBtn.setColor(Color.GREEN);
}else{
message="No, not "+b.getName();
qBtn.setColor(Color.RED);
}
repaint();
}
public void update(Graphics g){ paint(g); }
}
