See Also
Possible Scores
- Quadrilateral score: 45
 - Parallelgram score: 55
 - Rhomboid score: 55
 - Rhombus score: 55
 - Rectangle score: 55
 - Square score: 55
 - Total score: 320
 
// JavaScript Code
/***
 *  Point
 */
function Point(x, y) {
  this.x = Geometry.parseFiniteFloat(x);
  this.y = Geometry.parseFiniteFloat(y);
}
/***
 *  Geometry
 */
Geometry = {
  EPSILON: 0.0000001,
  areVirtuallyEqual: function(a, b) {
    return Math.abs(a - b) < Geometry.EPSILON;
  },
  parseFiniteFloat: function(n) {
    var f = parseFloat(n);
    return (f == NaN || !isFinite(f)) ? undefined : f;
  },
  toDegrees: function(radians) {
    var n = Geometry.parseFiniteFloat(radians);
    return (n == undefined) ? undefined : n * (180 / Math.PI);
  },
  toRadians: function(degrees) {
    var n = Geometry.parseFiniteFloat(degrees);
    return (n == undefined) ? undefined : n * (Math.PI / 180);
  },
  computeAngleUsingCosineRule: function(a, b, c) {
    var A = Geometry.parseFiniteFloat(a);
    var B = Geometry.parseFiniteFloat(b);
    var C = Geometry.parseFiniteFloat(c);
    if (A == undefined || B == undefined || C == undefined) {
      return undefined;
    }    
    return Math.acos((Math.pow(A,2)+Math.pow(B,2)-Math.pow(C,2))/(2*A*B));
  },
  computeAreaOfTriangleUsingHeronsFormula: function(a, b, c) {
    var A = Geometry.parseFiniteFloat(a);
    var B = Geometry.parseFiniteFloat(b);
    var C = Geometry.parseFiniteFloat(c);
    if (A == undefined || B == undefined || C == undefined) {
      return undefined;
    }
    var s = (A+B+C)/2; // semiperimeter
    return Math.sqrt(s*(s-A)*(s-B)*(s-C));
  },
  computeDistanceBetweenPoints: function(p1, p2) {
    var a, b, c; // lengths of sides of a right triangle
    var pt1 = Geometry.parsePoint(p1);
    var pt2 = Geometry.parsePoint(p2);
    if (pt1 == undefined || pt2 == undefined) {
      return undefined;
    }
    // Pythagorean Theorem
    a = pt2.x - pt1.x; // leg
    b = pt2.y - pt1.y; // leg
    c = Math.sqrt(Math.pow(a,2) + Math.pow(b,2)); // hypotenuse
    return c;
  },
  parsePoint: function(p) {
    var x, y;
    if (p != undefined && p.hasOwnProperty('x') && p.hasOwnProperty('y')) {
      x = parseFloat(p.x);
      y = parseFloat(p.y);
      if (x != NaN && y != NaN && isFinite(x) && isFinite(y)) {
        return new Point(x, y);
      }
    }
    return undefined;
  },
  isPoint: function(p) {
    return Geometry.parsePoint(p) != undefined;
  },
  toX: function(radius, azimuth) {
    var r = (radius == undefined) ? 0 : Geometry.parseFiniteFloat(radius);
    var a = (azimuth == undefined) ? 0 : Geometry.parseFiniteFloat(azimuth);
    if (r == undefined || a == undefined) {
      return undefined;
    }
    return r * Math.cos(a);
  },
  toY: function(radius, azimuth) {
    var r = (radius == undefined) ? 0 : Geometry.parseFiniteFloat(radius);
    var a = (azimuth == undefined) ? 0 : Geometry.parseFiniteFloat(azimuth);
    if (r == undefined || a == undefined) {
      return undefined;
    }
    return r * Math.sin(a);
  }
}
/***
 *  Polygon
 *
 *  Given a Polygon with n vertices:
 *
 *    0   identifies the first side, vertex or angle.
 *    1   identifies the second.
 *    n-1 identifies the last.
 *    n   identifies the first.
 *    n+1 identifies the second.
 *    etc.
 *
 *  Similarly:
 *
 *    -1   identifies the last.
 *    -2   identifies the second-to-last.
 *    -n+1 identifies the second.
 *    -n   identifies the first.
 *    -n-1 identifies the last.
 *    etc.
 */
function Polygon() {
  var vertices = [];
  this.getVertexCount = function() {
    return vertices.length;
  };
  this.getVertex = function(n) {
    var i = this.toIndex(n);
    return (i < 0) ? undefined : vertices[i];
  };
  this.removeVertex = function(n) {
    var i = this.toIndex(n);
    if (i >= 0) {
      vertices.splice(i, 1);
    }
  };
  this.insertVertexAfter = function(n, pole, radius, azimuth) {
    var x = 0;
    var y = 0;
    var point = Geometry.parsePoint(pole);
    var deltaX = Geometry.toX(radius, azimuth);
    var deltaY = Geometry.toY(radius, azimuth);
    if (point != undefined) {
      x += point.x;
      y += point.y;
    }
    if (deltaX != undefined && deltaY != undefined) {
      x += deltaX;
      y += deltaY;
    }
    var newVertex = new Point(x, y);
    vertices.splice(this.toIndex(n) + 1, 0, newVertex);
  };
}
Polygon.prototype = {
  toIndex: function(n) {
    var remainder;
    var vertexCount = this.getVertexCount();
    if (vertexCount > 0) {
      remainder = n % vertexCount;
      return (remainder < 0) ? remainder + vertexCount : remainder;
    }
    return -1;
  },
  getDistanceBetweenVertices: function(n1, n2) {
    var p1 = this.getVertex(n1);
    var p2 = this.getVertex(n2);
    return Geometry.computeDistanceBetweenPoints(p1, p2);
  },
  getLengthOfSide: function(n) {
    return this.getDistanceBetweenVertices(n, n+1);
  },
  getPerimeter: function() {
    var sum = 0;
    for (var i = 0; i < this.getVertexCount(); i++) {
      sum += this.getLengthOfSide(i);
    }
    return sum;
  },
  getArea: function() {
    return Polygon.computeAreaUsingShoelaceFormula(this);
  },
  getInteriorAngle: function(n) {
    var vertexCount = this.getVertexCount();
    if (vertexCount <= 1) {
      return 0;
    }
    else if (vertexCount == 2) {
      return 180;
    }
    else {
      var a = this.getDistanceBetweenVertices(n-1, n);
      var b = this.getDistanceBetweenVertices(n, n+1);
      var c = this.getDistanceBetweenVertices(n+1, n-1);
      return Geometry.computeAngleUsingCosineRule(a, b, c);
    }
  },
  appendVertex: function(pole, radius, azimuth) {
    this.insertVertexAfter(-1, pole, radius, azimuth);
  }
};
Polygon.computeAreaByDividingAndConquering = function(polygon) {
  var a, b, c;
  var poly1, poly2, area1, area2;
  var vertexCount = polygon.getVertexCount();
  if (vertexCount < 3) {
    return 0;
  }
  else if (vertexCount == 3) {
    a = polygon.getLengthOfSide(0);
    b = polygon.getLengthOfSide(1);
    c = polygon.getLengthOfSide(2);
    return Geometry.computeAreaOfTriangleUsingHeronsFormula(a, b, c);
  }
  else {
    poly1 = new Polygon();
    poly1.appendVertex(this.getVertex(0));
    poly1.appendVertex(this.getVertex(1));
    poly1.appendVertex(this.getVertex(2));
    poly2 = new Polygon();
    poly2.appendVertex(this.getVertex(0));
    for (var i=2; i < vertexCount; i++) {
      poly2.appendVertex(this.getVertex(i));
    }
    area1 = Polygon.computeAreaByDividingAndConquering(poly1);
    area2 = Polygon.computeAreaByDividingAndConquering(poly2);
    return area1 + area2;
  }
};
Polygon.computeAreaUsingShoelaceFormula = function(polygon) {
  var sum = 0;
  for (var i=0; i < polygon.getVertexCount(); i++) {
    var p1 = polygon.getVertex(i);
    var p2 = polygon.getVertex(i+1);
    sum += (p1.x * p2.y) - (p2.x * p1.y);
  }
  return 0.5 * Math.abs(sum);
};
/***
 *  Quadrilateral
 */
function Quadrilateral(s0, s1, s2, a1, a2) {
  var azimuth0 = 0; // First side is parallel to the x-axis
  var azimuth1 = Geometry.toRadians(180-a1);
  var azimuth2 = Geometry.toRadians((180-a1)+(180-a2));
  var polygon = new Polygon();
  polygon.appendVertex(new Point(0,0));
  polygon.appendVertex(polygon.getVertex(-1), s0, azimuth0);
  polygon.appendVertex(polygon.getVertex(-1), s1, azimuth1);
  polygon.appendVertex(polygon.getVertex(-1), s2, azimuth2);
  this.area = function() {
    return polygon.getArea();
  }
  this.perimeter = function() {
    return polygon.getPerimeter();
  }
  this.side = function(n) {
    return polygon.getLengthOfSide(n);
  }
  this.angle = function(n) {
    return Geometry.toDegrees(polygon.getInteriorAngle(n));
  }
}
Quadrilateral.isSquare = function(q) {
  return (
    Geometry.areVirtuallyEqual(q.side(0), q.side(1)) &&
    Geometry.areVirtuallyEqual(q.side(0), q.side(2)) &&
    Geometry.areVirtuallyEqual(q.side(0), q.side(3)) &&
    Geometry.areVirtuallyEqual(q.angle(0), 90) &&
    Geometry.areVirtuallyEqual(q.angle(0), q.angle(1)) &&
    Geometry.areVirtuallyEqual(q.angle(0), q.angle(2)) &&
    Geometry.areVirtuallyEqual(q.angle(0), q.angle(3))
  );
}
/***
 * Parallelogram
 */
function Parallelogram(s02, s13, a13) {
  Quadrilateral.call(this, s02, s13, s02, a13, 180-a13);
}
/***
 * Rhomboid
 */
function Rhomboid(s02, s13, a13) {
}
/***
 * Rhombus
 */
function Rhombus(s0123, a13) {
}
/***
 * Rectangle
 */
function Rectangle(s02, s13) {
}
/***
 * Square
 */
function Square(s0123) {
}
// JavaScript grade function
/***
 *  grade
 */
function grade() {
  function comparisonScore(gold, uut) {
    var score = 0;
    for (var i=0; i<4; i++) {
      if (uut.side != undefined &&
          Geometry.areVirtuallyEqual(uut.side(i), gold.side(i)))
        score += 3;
      if (uut.angle != undefined &&
          Geometry.areVirtuallyEqual(uut.angle(i), gold.angle(i)))
        score += 2;
    }
    if (uut.area != undefined &&
        Geometry.areVirtuallyEqual(uut.area(), gold.area()))
      score += 5;
    if (uut.perimeter != undefined &&
        Geometry.areVirtuallyEqual(uut.perimeter(), gold.perimeter()))
      score += 5;
    return score;
  }
  var score;
  var total = 0;
  if (Quadrilateral != undefined) {
    var g1 = new Quadrilateral(1, 2, 3, 90, 90);
    score = 0;
    score += Geometry.areVirtuallyEqual(g1.side(3), Math.sqrt(8)) ? 5 : -50;
    score += Geometry.areVirtuallyEqual(g1.angle(3), 45) ? 5 : -50;
    score += Geometry.areVirtuallyEqual(g1.perimeter(), 6+Math.sqrt(8)) ? 5 : -50;
    score += Geometry.areVirtuallyEqual(g1.area(), 4) ? 5 : -50;
    if (Quadrilateral.isSquare != undefined)
      score += Quadrilateral.isSquare(g1) ? 0 : 5;
    if (Quadrilateral.isRhomboid != undefined)
      score += Quadrilateral.isRhomboid(g1) ? 0 : 5;
    if (Quadrilateral.isRhombus != undefined)
      score += Quadrilateral.isRhombus(g1) ? 0 : 5;
    if (Quadrilateral.isRectangle != undefined)
      score += Quadrilateral.isRectangle(g1) ? 0 : 5;
    if (Quadrilateral.isParallelogram != undefined)
      score += Quadrilateral.isParallelogram(g1) ? 0 : 5;
  }
  total += score;
  console.log("Quadrilateral score: " + score);
  if (Quadrilateral != undefined && Parallelogram != undefined) {
    var g2 = new Quadrilateral(1, 2, 1, 45, 135);
    var t2 = new Parallelogram(1, 2, 45);
    score = 0;
    score += comparisonScore(g2, t2);
    if (Quadrilateral.isSquare != undefined)
      score += Quadrilateral.isSquare(g2) ? 0 : 5;
    if (Quadrilateral.isRhomboid != undefined)
      score += Quadrilateral.isRhomboid(g2) ? 5 : 0;
    if (Quadrilateral.isRhombus != undefined)
      score += Quadrilateral.isRhombus(g2) ? 0 : 5;
    if (Quadrilateral.isRectangle != undefined)
      score += Quadrilateral.isRectangle(g2) ? 0 : 5;
    if (Quadrilateral.isParallelogram != undefined)
      score += Quadrilateral.isParallelogram(g2) ? 5 : 0;
  }
  total += score;
  console.log("Parallelgram score: " + score);
  if (Quadrilateral != undefined && Rhomboid != undefined) {
    var g3 = new Quadrilateral(1, 2, 1, 45, 135);
    var t3 = new Rhomboid(1, 2, 45);
    score = 0;
    score += comparisonScore(g3, t3);
    if (Quadrilateral.isSquare != undefined)
      score += Quadrilateral.isSquare(g3) ? 0 : 5;
    if (Quadrilateral.isRhomboid != undefined)
      score += Quadrilateral.isRhomboid(g3) ? 5 : 0;
    if (Quadrilateral.isRhombus != undefined)
      score += Quadrilateral.isRhombus(g3) ? 0 : 5;
    if (Quadrilateral.isRectangle != undefined)
      score += Quadrilateral.isRectangle(g3) ? 0 : 5;
    if (Quadrilateral.isParallelogram != undefined)
      score += Quadrilateral.isParallelogram(g3) ? 5 : 0;
  }
  total += score;
  console.log("Rhomboid score: " + score);
  if (Quadrilateral != undefined && Rhombus != undefined) {
    var g4 = new Quadrilateral(1, 1, 1, 45, 135);
    var t4 = new Rhombus(1, 45);
    score = 0;
    score += comparisonScore(g4, t4);
    if (Quadrilateral.isSquare != undefined)
      score += Quadrilateral.isSquare(g4) ? 0 : 5;
    if (Quadrilateral.isRhomboid != undefined)
      score += Quadrilateral.isRhomboid(g4) ? 0 : 5;
    if (Quadrilateral.isRhombus != undefined)
      score += Quadrilateral.isRhombus(g4) ? 5 : 0;
    if (Quadrilateral.isRectangle != undefined)
      score += Quadrilateral.isRectangle(g4) ? 0 : 5;
    if (Quadrilateral.isParallelogram != undefined)
      score += Quadrilateral.isParallelogram(g4) ? 5 : 0;
  }
  total += score;
  console.log("Rhombus score: " + score);
  if (Quadrilateral != undefined && Rectangle != undefined) {
    var g5 = new Quadrilateral(2, 4, 2, 90, 90);
    var t5 = new Rectangle(2, 4);
    score = 0;
    score += comparisonScore(g5, t5);
    if (Quadrilateral.isSquare != undefined)
      score += Quadrilateral.isSquare(g5) ? 0 : 5;
    if (Quadrilateral.isRhomboid != undefined)
      score += Quadrilateral.isRhomboid(g5) ? 0 : 5;
    if (Quadrilateral.isRhombus != undefined)
      score += Quadrilateral.isRhombus(g5) ? 0 : 5;
    if (Quadrilateral.isRectangle != undefined)
      score += Quadrilateral.isRectangle(g5) ? 5 : 0;
    if (Quadrilateral.isParallelogram != undefined)
      score += Quadrilateral.isParallelogram(g5) ? 5 : 0;
  }
  total += score;
  console.log("Rectangle score: " + score);
  if (Quadrilateral != undefined && Square != undefined) {
    var side6 = Math.sqrt(2);
    var g6 = new Quadrilateral(side6, side6, side6, 90, 90);
    var t6 = new Square(side6);
    score = 0;
    score += comparisonScore(g6, t6);
    if (Quadrilateral.isSquare != undefined)
      score += Quadrilateral.isSquare(g6) ? 5 : 0;
    if (Quadrilateral.isRhomboid != undefined)
      score += Quadrilateral.isRhomboid(g6) ? 0 : 5;
    if (Quadrilateral.isRhombus != undefined)
      score += Quadrilateral.isRhombus(g6) ? 5 : 0;
    if (Quadrilateral.isRectangle != undefined)
      score += Quadrilateral.isRectangle(g6) ? 5 : 0;
    if (Quadrilateral.isParallelogram != undefined)
      score += Quadrilateral.isParallelogram(g6) ? 5 : 0;
  }
  total += score;
  console.log("Square score: " + score);
  console.log("Total score: " + total);
}
//Java Code
// Polygon.java
import java.util.ArrayList;
/***
 *  Polygon
 *
 *  Given a Polygon with n vertices:
 *
 *    0   identifies the first side, vertex or angle.
 *    1   identifies the second.
 *    n-1 identifies the last.
 *    n   identifies the first.
 *    n+1 identifies the second.
 *    etc.
 *
 *  Similarly:
 *
 *    -1   identifies the last.
 *    -2   identifies the second-to-last.
 *    -n+1 identifies the second.
 *    -n   identifies the first.
 *    -n-1 identifies the last.
 *    etc.
 */
class Polygon {
  private ArrayList<Point> vertices = new ArrayList<Point>();
  private int toIndex(int n) {
    int remainder;
    int vertexCount = this.getVertexCount();
    if (vertexCount > 0) {
      remainder = n % vertexCount;
      return (remainder < 0) ? remainder + vertexCount : remainder;
    }
    return -1;
  }
  public int getVertexCount() {
    return vertices.size();
  }
  public Point getVertex(int n) {
    int i = this.toIndex(n);
    return (i < 0) ? null : vertices.get(i);
  }
  public void removeVertex(int n) {
    int i = this.toIndex(n);
    if (i >= 0) {
      vertices.remove(i);
    }
  }
  public void insertVertexAfter(int n, Point pole, double radius, double azimuth) {
    double x = pole.x + Geometry.toX(radius, azimuth);
    double y = pole.y + Geometry.toY(radius, azimuth);
    Point newVertex = new Point(x, y);
    vertices.add(this.toIndex(n) + 1, newVertex);
  }
  public void insertVertexBefore(int n, Point pole, double radius, double azimuth) {
    double x = pole.x + Geometry.toX(radius, azimuth);
    double y = pole.y + Geometry.toY(radius, azimuth);
    Point newVertex = new Point(x, y);
    vertices.add(this.toIndex(n), newVertex);
  }
  public void appendVertex(Point pole, double radius, double azimuth) {
    this.insertVertexAfter(-1, pole, radius, azimuth);
  }
  public void appendVertex(Point pole) {
    this.appendVertex(pole, 0, 0);
  }
  public double getDistanceBetweenVertices(int n1, int n2) {
    Point p1 = this.getVertex(n1);
    Point p2 = this.getVertex(n2);
    return Geometry.computeDistanceBetweenPoints(p1, p2);
  }
  public double getLengthOfSide(int n) {
    return this.getDistanceBetweenVertices(n, n+1);
  }
  public double getPerimeter() {
    double sum = 0;
    for (int i = 0; i < this.getVertexCount(); i++) {
      sum += this.getLengthOfSide(i);
    }
    return sum;
  }
  public double getInteriorAngle(int n) {
    int vertexCount = this.getVertexCount();
    if (vertexCount <= 1) {
      return 0;
    }
    else if (vertexCount == 2) {
      return 180;
    }
    else {
      double a = this.getDistanceBetweenVertices(n-1, n);
      double b = this.getDistanceBetweenVertices(n, n+1);
      double c = this.getDistanceBetweenVertices(n+1, n-1);
      return Geometry.computeAngleUsingCosineRule(a, b, c);
    }
  }
  public double getArea() {
    return this.computeAreaUsingShoelaceFormula();
  }
  // OPTION A for computing area
  private double computeAreaByDividingAndConquering() {
    Polygon poly1, poly2;
    double a, b, c;
    double area1, area2;
    int vertexCount = this.getVertexCount();
    if (vertexCount < 3) {
      return 0;
    }
    else if (vertexCount == 3) {
      a = this.getLengthOfSide(0);
      b = this.getLengthOfSide(1);
      c = this.getLengthOfSide(2);
      return Geometry.computeAreaOfTriangleUsingHeronsFormula(a, b, c);
    }
    else {
      poly1 = new Polygon();
      poly1.appendVertex(this.getVertex(0));
      poly1.appendVertex(this.getVertex(1));
      poly1.appendVertex(this.getVertex(2));
      poly2 = new Polygon();
      poly2.appendVertex(this.getVertex(0));
      for (int i=2; i < vertexCount; i++) {
        poly2.appendVertex(this.getVertex(i));
      }
      area1 = poly1.computeAreaByDividingAndConquering();
      area2 = poly2.computeAreaByDividingAndConquering();
      return area1 + area2;
    }
  }
  // OPTION B for computing area
  private double computeAreaUsingShoelaceFormula() {
    double sum = 0;
    for (int i=0; i < this.getVertexCount(); i++) {
      Point p1 = this.getVertex(i);
      Point p2 = this.getVertex(i+1);
      sum += (p1.x * p2.y) - (p2.x * p1.y);
    }
    return 0.5 * Math.abs(sum);
  }
}
// Geometry.java
/***
 *  Geometry
 */
class Geometry {
  public static boolean areVirtuallyEqual(double a, double b) {
    return Math.abs(a - b) < 0.0000001;
  }
  public static double toDegrees(double radians) {
    return radians * (180 / Math.PI);
  }
  public static double toRadians(double degrees) {
    return degrees * (Math.PI / 180);
  }
  public static double computeDistanceBetweenPoints(Point p1, Point p2) {
    // Pythagorean Theorem
    double a = p2.x - p1.x; // leg
    double b = p2.y - p1.y; // leg
    double c = Math.sqrt(Math.pow(a,2) + Math.pow(b,2)); // hypotenuse
    return c;
  }
  public static double computeAngleUsingCosineRule(double a, double b, double c) {
    return Math.acos((Math.pow(a,2)+Math.pow(b,2)-Math.pow(c,2))/(2*a*b));
  }
  public static double computeAreaOfTriangleUsingHeronsFormula(double a, double b, double c) {
    double s = (a+b+c)/2; // semiperimeter
    return Math.sqrt(s*(s-a)*(s-b)*(s-c));
  }
  public static double toX(double radius, double azimuth) {
    return radius * Math.cos(azimuth);
  }
  public static double toY(double radius, double azimuth) {
    return radius * Math.sin(azimuth);
  }
}
// Point.java
/***
 *  Point
 */
class Point {
  public double x;
  public double y;
  Point(double x, double y) {
    this.x = x;
    this.y = y;
  }
}
// Quadrilateral.java
/***
 *  Quadrilateral
 */
class Quadrilateral {
  private Polygon polygon;
  Quadrilateral(double s0, double s1, double s2, double a1, double a2) {
    double azimuth0 = 0; // First side is parallel to the x-axis
    double azimuth1 = Geometry.toRadians(180-a1);
    double azimuth2 = Geometry.toRadians((180-a1)+(180-a2));
    this.polygon = new Polygon();
    polygon.appendVertex(new Point(0,0));
    polygon.appendVertex(polygon.getVertex(-1), s0, azimuth0);
    polygon.appendVertex(polygon.getVertex(-1), s1, azimuth1);
    polygon.appendVertex(polygon.getVertex(-1), s2, azimuth2);
  }
  public double area() {
    return polygon.getArea();
  }
  public double perimeter() {
    return polygon.getPerimeter();
  }
  public double side(int n) {
    return polygon.getLengthOfSide(n);
  }
  public double angle(int n) {
    return Geometry.toDegrees(polygon.getInteriorAngle(n));
  }
  public static boolean isSquare(Quadrilateral q) {
    return (
      Geometry.areVirtuallyEqual(q.side(0), q.side(1)) &&
      Geometry.areVirtuallyEqual(q.side(0), q.side(2)) &&
      Geometry.areVirtuallyEqual(q.side(0), q.side(3)) &&
      Geometry.areVirtuallyEqual(q.angle(0), 90) &&
      Geometry.areVirtuallyEqual(q.angle(0), q.angle(1)) &&
      Geometry.areVirtuallyEqual(q.angle(0), q.angle(2)) &&
      Geometry.areVirtuallyEqual(q.angle(0), q.angle(3))
    );
  }
  public static boolean isRectangle(Quadrilateral q) {
    return false;
  }
  public static boolean isRhomboid(Quadrilateral q) {
    return false;
  }
  public static boolean isRhombus(Quadrilateral q) {
    return false;
  }
  public static boolean isParallelogram(Quadrilateral q) {
    return false;
  }
}
// Parallelogram.java
/***
 * Parallelogram
 */
class Parallelogram extends Quadrilateral {
  Parallelogram(double s02, double s13, double a13) {
    super(s02, s13, s02, a13, 180-a13);
  }
}
// Rhomboid.java
/***
 * Rhomboid
 */
class Rhomboid extends Quadrilateral {
  Rhomboid(double s02, double s13, double a13) {
    super(0d, 0d, 0d, 0d, 0d);
  }
}
// Rhombus.java
/***
 * Rhombus
 */
class Rhombus extends Quadrilateral {
  Rhombus(double s0123, double a13) {
    super(0d, 0d, 0d, 0d, 0d);
  }
}
// Rectangle.java
/***
 * Rectangle
 */
class Rectangle extends Quadrilateral {
  Rectangle(double s02, double s13) {
    super(0d, 0d, 0d, 0d, 0d);
  }
}
// Square.java
/***
 * Square
 */
class Square extends Rectangle {
  Square(double s0123) {
    super(0d, 0d);
  }
}
// Grader.java
/***
 *  Grader
 */
class Grader {
  public static void main(String[] args) {
    Grader.grade();
  }
  static int comparisonScore(Quadrilateral gold, Quadrilateral uut) {
    int score = 0;
    for (int i=0; i<4; i++) {
      if (Geometry.areVirtuallyEqual(uut.side(i), gold.side(i)))
        score += 3;
      if (Geometry.areVirtuallyEqual(uut.angle(i), gold.angle(i)))
        score += 2;
    }
    if (Geometry.areVirtuallyEqual(uut.area(), gold.area()))
      score += 5;
    if (Geometry.areVirtuallyEqual(uut.perimeter(), gold.perimeter()))
      score += 5;
    return score;
  }
  static void grade() {
    int score;
    int total = 0;
    Quadrilateral g1 = new Quadrilateral(1, 2, 3, 90, 90);
    score = 0;
    score += Geometry.areVirtuallyEqual(g1.side(3), Math.sqrt(8)) ? 5 : -50;
    score += Geometry.areVirtuallyEqual(g1.angle(3), 45) ? 5 : -50;
    score += Geometry.areVirtuallyEqual(g1.perimeter(), 6+Math.sqrt(8)) ? 5 : -50;
    score += Geometry.areVirtuallyEqual(g1.area(), 4) ? 5 : -50;
    score += Quadrilateral.isSquare(g1) ? 0 : 5;
    score += Quadrilateral.isRhomboid(g1) ? 0 : 5;
    score += Quadrilateral.isRhombus(g1) ? 0 : 5;
    score += Quadrilateral.isRectangle(g1) ? 0 : 5;
    score += Quadrilateral.isParallelogram(g1) ? 0 : 5;
    total += score;
    System.out.println("Quadrilateral score: " + score);
    Quadrilateral g2 = new Quadrilateral(1, 2, 1, 45, 135);
    Quadrilateral t2 = new Parallelogram(1, 2, 45);
    score = 0;
    score += Grader.comparisonScore(g2, t2);
    score += Quadrilateral.isSquare(g2) ? 0 : 5;
    score += Quadrilateral.isRhomboid(g2) ? 5 : 0;
    score += Quadrilateral.isRhombus(g2) ? 0 : 5;
    score += Quadrilateral.isRectangle(g2) ? 0 : 5;
    score += Quadrilateral.isParallelogram(g2) ? 5 : 0;
    total += score;
    System.out.println("Parallelgram score: " + score);
    Quadrilateral g3 = new Quadrilateral(1, 2, 1, 45, 135);
    Quadrilateral t3 = new Rhomboid(1, 2, 45);
    score = 0;
    score += Grader.comparisonScore(g3, t3);
    score += Quadrilateral.isSquare(g3) ? 0 : 5;
    score += Quadrilateral.isRhomboid(g3) ? 5 : 0;
    score += Quadrilateral.isRhombus(g3) ? 0 : 5;
    score += Quadrilateral.isRectangle(g3) ? 0 : 5;
    score += Quadrilateral.isParallelogram(g3) ? 5 : 0;
    total += score;
    System.out.println("Rhomboid score: " + score);
    Quadrilateral g4 = new Quadrilateral(1, 1, 1, 45, 135);
    Quadrilateral t4 = new Rhombus(1, 45);
    score = 0;
    score += Grader.comparisonScore(g4, t4);
    score += Quadrilateral.isSquare(g4) ? 0 : 5;
    score += Quadrilateral.isRhomboid(g4) ? 0 : 5;
    score += Quadrilateral.isRhombus(g4) ? 5 : 0;
    score += Quadrilateral.isRectangle(g4) ? 0 : 5;
    score += Quadrilateral.isParallelogram(g4) ? 5 : 0;
    total += score;
    System.out.println("Rhombus score: " + score);
    Quadrilateral g5 = new Quadrilateral(2, 4, 2, 90, 90);
    Quadrilateral t5 = new Rectangle(2, 4);
    score = 0;
    score += Grader.comparisonScore(g5, t5);
    score += Quadrilateral.isSquare(g5) ? 0 : 5;
    score += Quadrilateral.isRhomboid(g5) ? 0 : 5;
    score += Quadrilateral.isRhombus(g5) ? 0 : 5;
    score += Quadrilateral.isRectangle(g5) ? 5 : 0;
    score += Quadrilateral.isParallelogram(g5) ? 5 : 0;
    total += score;
    System.out.println("Rectangle score: " + score);
    double side6 = Math.sqrt(2);
    Quadrilateral g6 = new Quadrilateral(side6, side6, side6, 90, 90);
    Quadrilateral t6 = new Square(side6);
    score = 0;
    score += Grader.comparisonScore(g6, t6);
    score += Quadrilateral.isSquare(g6) ? 5 : 0;
    score += Quadrilateral.isRhomboid(g6) ? 0 : 5;
    score += Quadrilateral.isRhombus(g6) ? 5 : 0;
    score += Quadrilateral.isRectangle(g6) ? 5 : 0;
    score += Quadrilateral.isParallelogram(g6) ? 5 : 0;
    total += score;
    System.out.println("Square score: " + score);
    System.out.println("Total score: " + total);
  }
}