// Recall that in order to use the classes InputStreamReader and
// BufferedReader we must import the java.io package.

import java.io.*;

public class Trig {

// According to the specifications of the problem we must have seven
// instance methods. Since we are dealing with real numbers we will
// make the type double.

   double angle;
   double sine;
   double cosine;
   double tangent;
   double cotangent;
   double secant;
   double cosecant;

   public Trig(double angle) {

// This is the constructor for the class. Recall that in this class
// the constructor must initialize the instance variable angle and
// then call six of the instance methods to initialize the other
// instance variables.

      this.angle = angle;
      sine = sin();
      cosine = cos();
      tangent = tan();
      cotangent = cot();
      secant = sec();
      cosecant = csc();
   }

   public static double equiv(double angle) {

// Because the series for sine and cosine require an angle measured
// in radians, we must make the conversion. The formula is that the
// radian measure of an angle is its degree measure times pi divided
// 180.

      return(angle*3.1415926535/180);
   }

   private int factorial(int n) {

// This is a private method because it is needed in order to compute
// the terms in the series for sine and cosine.

// We initialize an int variable called product to 1. We do this because
// 1 is the multiplicative identity.

      int product = 1;

// Recall that the factorial of a number n is the product of that number
// with all of the positive integers less than it. So we start a counter
// variable at 2 and have it run to the number and multiply the accumulating
// product by each value of counter.

      for (int counter=2;counter <= n;counter++)
         product *= counter;

      return(product);
   }

   public double sin() {

// We now compute the sine of the angle.

// Recall that since the first line of the constructor initializes
// the instance variable angle, that value is known to the instance
// methods.

// Since the first term in the series for the sine is the angle itself
// measured in radians we can initialize a double variable called sum
// to the radian equivalent of angle. Note here that we don't necessarily
// need to use the name of the class in the call to the class method
// equiv. It is done here for instructional purposes.

      double sum = Trig.equiv(angle);

// The next term in the series for sine has the power 3. So we
// initialize an int variable called counter to 3.

      int counter = 3;

// We now compute the value of that term.

      double nextTerm = Math.pow(Trig.equiv(angle),counter);
      nextTerm /= factorial(counter);

// Recall that the condition to keep adding or subtracting terms
// is if the term is greater than or equal to 0.00005. So this is
// the condition on our while loop.

      while (nextTerm >= 0.00005) {

// We must decide whether to add the term or subtract it. Notice
// that we add the term if the power has remainder 1 when divided
// by 4, and we subtract the term if the power has remainder 3 when
// divided by 4.

         if (counter % 4 == 1)
            sum += nextTerm;
         else
            sum -= nextTerm;

// Since the powers change by 2 we must increment counter by 2.

         counter += 2;

// We must now compute the next term in the series.

         nextTerm = Math.pow(Trig.equiv(angle),counter);
         nextTerm /= factorial(counter);
      }

      return(sum);
   }

   public double cos() {

// Notice that the first term in the series for the cosine is 1
// so we can initialize a double variable called sum to 1.

      double sum = 1;

// The first term in the series for the cosine has the power 2.

      int counter = 2;

// We now compute the first term.

      double nextTerm = Math.pow(Trig.equiv(angle),counter);
      nextTerm /= factorial(counter);

      while (nextTerm >= 0.00005) {

// Notice here that if the power has remainder 0 when divided by 4,
// then we add the term. If the power has remainder 2 when divided by 4,
// then we subtract the term.

         if (counter % 4 == 0)
            sum += nextTerm;
         else
            sum -= nextTerm;

// Since the powers go up by 2, we must increment counter by 2.

         counter += 2;

// We now compute the next term.

         nextTerm = Math.pow(Trig.equiv(angle),counter);
         nextTerm /= factorial(counter);
      }

      return(sum);
   }

   public double tan() {

// The tangent of an angle is its sine divided by its cosine.

      return(sin()/cos());
   }

   public double cot() {

// The cotangent of an angle is its cosine divided by its sine.

      return(cos()/sin());
   }

   public double sec() {

// The secant of an angle is the reciprocal of its cosine.

      return(1/cos());
   }

   public double csc() {

// The cosecant of an angle is the reciprocal of its sine.

      return(1/sin());
   }

   public String toString() {

// Recall that the toString method is used to create a String
// equivalent of the object. We now format the output.

      String outputLine = "\n";
      outputLine += "Original Angle:" + "\t\t" + angle + "\n";
      outputLine += "Radian Equivalent:" + "\t" + Trig.equiv(angle) + "\n";
      outputLine += "Sine:" + "\t\t\t" + sine + "\n";
      outputLine += "Cosine:" + "\t\t\t" + cosine + "\n";
      outputLine += "Tangent:" + "\t\t" + tangent + "\n";
      outputLine += "Cotangent:" + "\t\t" + cotangent + "\n";
      outputLine += "Secant:" + "\t\t\t" + secant + "\n";
      outputLine += "Cosecant:" + "\t\t" + cosecant + "\n";

      return(outputLine);
   }

   public static void main(String[] args) throws IOException {

// Recall that since we are going to use the classes InputStreamReader
// and BufferedReader we must include throws IOException in the
// header of the main method.

      InputStreamReader stream = new InputStreamReader(System.in);
      BufferedReader keyboard = new BufferedReader(stream);

      System.out.println("Please enter your angle in degrees.");

      double angle = new Double(keyboard.readLine()).doubleValue();

      System.out.println("\n" + "Here is the information I've computed about your angle.");

// Now we make a call to the constructor of our class. The right-hand
// side calls the constructor for the Trig class and sends it the parameter
// angle. The constructor returns an object of type Trig and places it
// into the variable myTrig.

      Trig myTrig = new Trig(angle);

// Since the constructor does all of the work, we only need to send the
// object to the System.out.println method. Recall that when we use an
// object as the parameter to System.out.println, then whatever the toString
// method defined in the class returns is what gets printed.

      System.out.println(myTrig);
   }

}

 
