Assignment Description Part 1: Our team must setup a configuration management, test management, and bug tracking system. We have to play with these tools, use them, and understand what they can do. Part 2: Each team member must develop a program (using Java, C, or C++) that classifies triangles according to the following specification: “A program reads three numbers. The three numbers represent the lengths of the sides of a triangle. The program prints a message that states whether the triangle is scalene, isosceles, or equilateral, and whether it is a right triangle as well.” The program should be able to pass a basic sanity test. Once completed, a copy of the program should be given to teammates. Author(s) William Rozzo, Jennie Vongsoasup, and Jonathan Wesel Summary Summary of Results: Part 1: All three of us are familiar with Eclipse and Subversion, so we decided to use these tools as our development GUI and configuration management system. We created a shared code repository in Google Code: http://code.google.com/p/stevens-misc-code/. Initially, we were going to use Bugzilla as our bug tracking and test management system. However, we had problems installing Bugzilla, so we decided to use Mantis and TestLink instead. We encountered several difficulties installing and configuring Mantis with our web server. Part 2: All three of us decided to write our triangle program in Java. Although all of us know Java, several members of the team have not developed Java programs in a long time. Additionally, we had to refresh our memories on triangle terminology, such as determining if a triangle is equilateral, isosceles, scalene, or right. We each created our own programs and posted our source code in Appendix A of this document. All three programs had varying lines of code and code complexity. Significant Findings or Learning All three of us had difficulty installing Bugzilla, so we decided to use Mantis instead. We had to install Apache, MySQL, and PHP. It took us several hours (over 8) to install and configure Mantis for our web server. The main source of difficulty is decided to be an incompatibility with Mantis/MySQL and the OS of the available webserver. Changing the OS fixed the issues. Honor pledge I pledge on my honor that I have not given or received any unauthorized assistance on this assignment/examination. I further pledge that I have not copied any material from a book, article, the Internet or any other source except where I have expressly cited the source. Detailed results Description of Techniques Used: For Part 1 of this assignment, we installed Eclipse and Subversion on our local machines. We created a shared code repository in Google Code: http://code.google.com/p/stevens-misc-code/ Figure 1: Eclipse with Subversion installed After we installed Eclipse and Subversion on our local machines, we attempted to install Bugzilla on Jon’s web server. We encountered several issues configuring Perl with Bugzilla, so we tried installing Mantis instead. We also had several problems configuring Mantis with MySQL, but we were successful with installing and configuring Mantis with our web server after several painful hours. Figure 2: Mantis Main Screen Figure 3: Mantis View Issues page Figure 4: Mantis Defect Summary Page For part 2 of this assignment, all three of us created our own Triangle programs using Java. All three of our programs have varying lines of code and complexity. We conducted sanity tests on our programs by checking for an isosceles, equilateral, scalene, and right triangles. Our source code and test results are illustrated in Appendix A and B, respectively. Assumptions or Constraints Made: We made the following assumptions for this assignment: • All triangles have three sides and the user must input three sides. • The user can input decimal or integer values only. • The user is only interested in one pass through the program (program does not restart unless re executed, all previous information/calculations are lost). • theorem. A triangle is considered to be a right triangle if it follows the Pythagorean • We must create sanity checks to ensure that a triangle is isosceles, equilateral, scalene, and/or right. • Our bug tracking system must utilize a database to track defect records. Description of Data Inputs Used: For our Triangle programs, we assumed that the user can only input decimal or integer values. We prompt the user to input three lengths of a triangle. After the user provides his/her input, our program determines whether the triangle is isosceles, equilateral, scalene, and/or right. We conducted sanity tests on each of our source code as illustrated in Appendix B of this document. Explanation of Results: We were able to successfully install and configure Eclipse, Subversion, and Mantis. Each of us were able to create three different Triangle programs using Java. All of our programs passed basic sanity tests that check if the triangle is isosceles, equilateral, scalene, and/or right. However, several of our programs do not test if a triangle is valid (the sum of the shortest two sides of a triangle must be greater than the largest side of a triangle). Also, some of our programs do not check for invalid user input, such as a user inputting a string value. After we finished our programs, each of us checked our source code into our repository. Appendix A Jennie’s Source Code: import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.regex.Pattern; public class Triangle { /** * @param args */ public static void main(String[] args) { try { System.out.println("This program determines if a triangle is equilateral, isosceles, or scalene based on user's input \n"); int[] anArray; anArray = new int[3]; for (int i = 1; i <= 3; i++) { System.out.println("Enter triangle length of side " + i + ": "); BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in)); String side = bufferRead.readLine(); boolean isInteger = Pattern.matches("^\\d*", side); // Check to see if input is a valid number. If not, keep prompting user to enter valid number while (!isInteger) { System.out.println("Invaid triangle length. Please enter a numeric triangle length for side " + i + ": "); bufferRead = new BufferedReader(new InputStreamReader(System.in)); side = bufferRead.readLine(); isInteger = Pattern.matches("^\\d*", side); } anArray[i - 1] = Integer.parseInt(side); } String result = ""; // Check if triangle is equilateral, scalene, or isosceles if (anArray[0] == anArray[1] && anArray[1] == anArray[2] && anArray[0] == anArray[2]) { result = "equilateral"; } else if (anArray[0] != anArray[1] && anArray[1] != anArray[2] && anArray[0] != anArray[2]) { result = "scalene"; } else { result = "isosceles"; } // Check if triangle is a right triangle if (((anArray[0] * anArray[0]) + (anArray[1] * anArray[1]) == (anArray[2] * anArray[2])) || ((anArray[1] * anArray[1]) + (anArray[2] * anArray[2]) == (anArray[0] * anArray[0])) || ((anArray[0] * anArray[0]) + (anArray[2] * anArray[2]) == (anArray[1] * anArray[1]))) { result += " and right"; } System.out.println("A triangle with lengths " + anArray[0] + ", " + anArray[1] + ", and " + anArray[2] + " is " + result); } catch(IOException e) { e.printStackTrace(); } } } Will’s Source Code: /* * Programmer: Will Rozzo * Course: SSW 567 * * Problem: Triangle Program * “A program reads three numbers. The three numbers represent the * lengths of the sides of a triangle. The program prints a message that * states whether the triangle is scalene, isosceles, or equilateral, * and whether it is a right triangle as well.” * * Class: Triangle * Description: This is the triangle object. This class is responsible for all * calculations having to do with a triangle. Such as angles, * determining triangle type, and whether the received sides truly * make a valid triangle. This class provides an interface allowing * one to set new side lengths and request updated angles. */ public class Triangle { private final int NUM_SIDES = 3; private double[] sides; private double[] angles; private String name; public Triangle() { sides = new double[NUM_SIDES]; angles = new double[NUM_SIDES]; name = "Invalid"; for(int i=0; i<NUM_SIDES; i++) { sides[i] = 0.0; angles[i] = 0.0; } } public Triangle(double side0, double side1, double side2) { sides = new double[NUM_SIDES]; angles = new double[NUM_SIDES]; setSides(side0, side1, side2); } /* * Given three side lengths, this method determines what kind * of triangle the three side lengths make based on how many * equal sides exist. */ private String evaluateTriangleType() { String triangleType = "Invalid Triangle!"; int numEqualSides = getEqualSideCount(); switch(numEqualSides){ case 1: triangleType = "Scalene"; break; case 2: triangleType = "Isosceles"; break; case 3: triangleType = "Equilateral"; break; default: triangleType = "Invalid Triangle!"; break; } return triangleType; } /* * Given three sides, this method returns how many of these sides * are equal (1 meaning none, 2 meaning 2 sides equal, and three * meaning all sides equal). */ private int getEqualSideCount() { int numEqualSides = 1; double currSide = 0.0; for(int i=0; i<sides.length; i++) { currSide = sides[i]; if(numEqualSides < NUM_SIDES) { for(int j=i+1; j<sides.length; j++) { if(currSide == sides[j]) numEqualSides++; } } } return numEqualSides; } /* * Knowning only the three side lengths, this method uses the * law of cosines to determine the three angles. * c^2 = a^2 + b^2 - 2ab*Cos(gamma) == arcCos((c^2 - a^2 - b^2) / -2ab) = gamma * a^2 = b^2 + c^2 - 2bc*Cos(alpha) == arcCos((a^2 - b^2 - c^2) / -2bc) = alpha * b^2 = a^2 + c^2 - 2ac*Cos(beta) == arcCos((b^2 - a^2 - c^2) / -2ac) = beta */ private double[] calculateAngles() { double[] angles = {0.0,0.0,0.0}; double gamma = 0.0; double alpha = 0.0; double beta = 0.0; int hypotenuseIndex = getHypotenuseIndex(); double a = 0.0; double b = 0.0; double c = sides[hypotenuseIndex]; switch(hypotenuseIndex){ case 0: a = sides[1]; b = sides[2]; break; case 1: a = sides[0]; b = sides[2]; break; case 2: a = sides[0]; b = sides[1]; break; default: c = sides[0]; a = sides[1]; b = sides[2]; break; } double aSquared = a * a; double bSquared = b * b; double cSquared = c * c; double negTwoAB = -2 * a * b; double negTwoBC = -2 * b * c; double negTwoAC = -2 * a * c; gamma = Math.toDegrees(Math.acos((cSquared - aSquared - bSquared) / negTwoAB)); alpha = Math.toDegrees(Math.acos((aSquared - bSquared - cSquared) / negTwoBC)); beta = Math.toDegrees(Math.acos((bSquared - aSquared - cSquared) / negTwoAC)); angles[0] = gamma; angles[1] = alpha; angles[2] = beta; return angles; } /* * This method returns the index within the sides array that has the * greatest length. */ private int getHypotenuseIndex() { int hypotenuseIndex = 0; double hypotenuse = sides[0]; for(int i=1; i<sides.length; i++) { if(sides[i] > hypotenuse) { hypotenuseIndex = i; hypotenuse } } return hypotenuseIndex; } /* * Public Methods = sides[i]; * The following methods provide an external interface to the * triangle object. */ public boolean isRightTriangle() { boolean right = false; for(int i=0; i<angles.length; i++) { if((angles[i] >= 90.0) && (angles[i] <= 90.5)) right = true; } return right; } public double[] getSides() { return sides; } public double[] getAngles() { return angles; } public String getName() { return name; } public void setSides(double side0, double side1, double side2) { sides[0] = side0; sides[1] = side1; sides[2] = side2; angles = calculateAngles(); name = evaluateTriangleType(); } public boolean isValidTriangle() { boolean valid = false; double a = sides[0]; double b = sides[1]; double c = sides[2]; if(((a+b)>c) && ((a+c)>b) && ((b+c)>a)) { valid = true; } return valid; } } /* * Programmer: Will Rozzo * Course: SSW 567 * * Problem: Triangle Program * “A program reads three numbers. The three numbers represent the * lengths of the sides of a triangle. The program prints a message that * states whether the triangle is scalene, isosceles, or equilateral, * and whether it is a right triangle as well.” * * Class: TriangleEvaluator * Description: This is the main driver. Parses user input from either the * command line or from prompts. Uses the Triangle class to * generate a triangle based on the data received from the user. * The triangle object is the queried for information which is * then relayed to the user. */ import java.util.Scanner; public class TriangleEvaluator { private final static int NUM_SIDES = 3; public static void main(String[] args) { Triangle triangle; int numSidesMissing = 0; double singleSide = 0.0; double[] sides = ParseArgs(args); double[] angles = {0.0,0.0,0.0}; String triangleType = "Invalid"; boolean right = false; // Determine how many sides we still need to gather from the user for(int i=0; i<NUM_SIDES; i++) { if(sides[i] == 0.0) numSidesMissing++; } System.out.println("\nTriangle Evaluator\n"); Scanner userInput = new Scanner(System.in); while(numSidesMissing > 0) { System.out.println("\nPlease enter a triangle side " + "length ("+numSidesMissing+" remaining):\n"); try { singleSide = toDouble(userInput.next()); if(singleSide > 0.0) { sides[NUM_SIDES-numSidesMissing] = singleSide; numSidesMissing--; } else { System.out.println("Invalid Input!"); } } catch (Exception e) { System.out.println("Invalid Input!"); } } triangle = new Triangle(sides[0], sides[1], sides[2]); for(int i=0; i<NUM_SIDES; i++) { System.out.println("Side "+ (i+1) +" = " + sides[i]); } if(triangle.isValidTriangle()) { triangleType = triangle.getName(); angles right = triangle.getAngles(); = triangle.isRightTriangle(); for(int i=0; i<NUM_SIDES; i++) { System.out.println("angle "+ (i+1) +" = " + angles[i]); } if(right) System.out.println("This is a right "+ triangleType +" triangle"); else System.out.println("This is a "+ triangleType +" triangle"); } else System.out.println("This is NOT a valid triangle"); } public static double[] ParseArgs(String[] args) { final String HELP = "-help"; double[] sides = {0.0,0.0,0.0}; double currSide = 0.0; int sideNum = 0; int argLength = args.length; // User attempted to pass arguments if(argLength > 0) { for(int i=0; i<argLength; i++) { if(args[i].equalsIgnoreCase(HELP)) { System.out.println("\n --- HELP --- \n" + "This program evaluates three triangle side\n" + "lengths and prints whether the triange is\n" + "scalene, isosceles, or equilateral. \n" + "Additionally, it will inform the user whether\n" + "or not the triangle is a right triangle.\n\n" + "Example commands:\n" + "Triangle -help : Prints help info.\n" + "Triangle 1 2 3 : Evaluates the three arguments as side lengths.\n" + "Triangle 1 -help 2 3 : Reads three sides and prints help.\n" + "Triangle 1 2 arguments, will query the user for the missing side length.\n" + "Triangle 1 "Triangle 1 2 3 4 : Assumes incomplete : \"\"\n" + : Any extra side lengths are ignored.\n" + "Triangle a * - : Any non-integer arguments are ignored.\n" + "Triangle : User will be queried for all side lengths.\n"); } else { if(sideNum < 3) { currSide = toDouble(args[i]); if(currSide >= 0) { sides[sideNum] = currSide; sideNum++; } } } // end if HELP } // end for loop }// End if args exist return sides; } // Returns 0 if the value was invalid public static double toDouble(String potentialDbl) { double myDouble = 0.0; try { myDouble = Double.parseDouble(potentialDbl); if(myDouble <= 0.0) myDouble = 0.0; } catch (NumberFormatException e) { myDouble = 0.0; } return myDouble; } } Jon’s Source Code: public class Triangle { int a,b,c; String type; boolean right; public Triangle(int x, int y, int z){ a = x; b = y; c = z; type = checkType(); right = checkRight(); } private boolean checkRight() { if(!isValid() || checkType() == "equilateral") return false; if((a*a + b*b) == c*c || (b*b + c*c) == a*a || (a*a + c*c) == b*b) return true; return false; } public String getType(){ return type; } public boolean isRight(){ return right; } private String checkType(){ if(!isValid()) return "invalid"; if(isEquilateral()) return "equilateral"; if(isScalene()) return "scalene"; return "isosceles"; } private boolean isScalene() { return a != b && a != c && b != c; } private boolean isEquilateral() { return a == b && b == c; } private boolean isValid() { if (a <= 0 || b <= 0 || c <= 0) return false; if (a >= b && a >= c) return a < b + c; if (b >= a && b >= c) return b < a + c; return c < a + b; } public String getDescription() { if(!isValid()) return "The triangle is invalid."; String desc = "The triangle is " + getType() + " and is"; if(!isRight()) desc += " not"; desc += " a right triangle."; return desc; } } public class TriangleIdentifier { public static void main(String[] args) { if(args.length != 3){ System.out.println("TriangleIdentifier requires 3 arguments. \n" + "Usage: TriangleIndentifier <a> <b> <c>"); return; } try{ Triangle t = new Triangle(Integer.parseInt(args[0]), Integer.parseInt(args[1]), Integer.parseInt(args[2])); System.out.println(t.getDescription()); }catch(NumberFormatException e){ System.out.println("Invalid arguments. Expecting 3 integers.\n" + "Usage: TriangleIndentifier <a> <b> <c>"); } } } public class SanityCheck { public static void main(String[] args) { Triangle invalid = new Triangle(1,2,3); Triangle isosceles = new Triangle(3,4,4); Triangle scalene = new Triangle(2,3,4); Triangle equilateral = new Triangle(3,3,3); Triangle scaleneright = new Triangle(3,4,5); System.out.println("Invalid Test (1,2,3): " + invalid.getDescription()); System.out.println("Isosceles Test (3,4,4): " + isosceles.getDescription()); System.out.println("Scalene Test (2,3,4): " + scalene.getDescription()); System.out.println("Equilateral Test (3,3,3): " + equilateral.getDescription()); System.out.println("Scalene Right Test (3,4,5): " + scaleneright.getDescription()); } } Appendix B Test Results on Jennie’s Program: Test case 1: Generate an Equilateral triangle This program determines if a triangle is equilateral, isosceles, or scalene based on user's input Enter triangle length of side 1: 4 Enter triangle length of side 2: 4 Enter triangle length of side 3: 4 A triangle with lengths 4, 4, and 4 is equilateral Test case 2: Generate a Scalene triangle This program determines if a triangle is equilateral, isosceles, or scalene based on user's input Enter triangle length of side 1: 5 Enter triangle length of side 2: 6 Enter triangle length of side 3: 7 A triangle with lengths 5, 6, and 7 is scalene Test case 3: Generate an Isosceles triangle This program determines if a triangle is equilateral, isosceles, or scalene based on user's input Enter triangle length of side 1: 4 Enter triangle length of side 2: 4 Enter triangle length of side 3: 5 A triangle with lengths 4, 4, and 5 is isosceles Test case 4: Generate a Right Triangle This program determines if a triangle is equilateral, isosceles, or scalene based on user's input Enter triangle length of side 1: 3 Enter triangle length of side 2: 4 Enter triangle length of side 3: 5 A triangle with lengths 3, 4, and 5 is scalene and right Test Results on Will’s Program: Test case 1: Generate an Equilateral triangle Test case 2: Generate a Scalene triangle Test case 3: Generate an Isosceles triangle Test case 4: Generate a Right Scalene Test case 5: Generate a Right Isosceles Test Results on Jon’s Program: