#pragma once
#include <memory>
#include <cmath>
#include <string>

class Figure {
 public:
  virtual std::string Name() = 0;
  virtual double Perimeter() = 0;
  virtual double Area() = 0;
};

class Rect : public Figure {
 public:
  double h, w;
  std::string name = "RECT";
  Rect(double width, double height) {
    h = height;
    w = width;
  }
  std::string Name() {
    return name;
  }
  double Perimeter() {
    return (h + w) * 2;
  }
  double Area() {
    return h * w;
  }
};

class Triangle : public Figure {
 public:
  double a, b, c;
  std::string name = "TRIANGLE";;
  Triangle(double a_t, double b_t, double c_t) {
    a = a_t;
    b = b_t;
    c = c_t;
  }
  std::string Name() {
    return name;
  }
  double Perimeter() {
    return a + b + c;
  }
  double Area() {
    double pol_p = Perimeter() / 2;
    return sqrt(pol_p * (pol_p - a) * (pol_p - b) * (pol_p - c));
  }
};

class Circle : public Figure {
 public:
  double r;
  const double pi = 3.14;
  std::string name = "CIRCLE";

  explicit Circle(double rad) {
    r = rad;
  }
  std::string Name() {
    return name;
  }
  double Perimeter() {
    return 2 * pi * r;
  }
  double Area() {
    return pi * pow(r, 2);
  }
};

std::shared_ptr<Figure> CreateFigure(std::istringstream &is) {
  std::string figure;
  int64_t a, b, c;
  is >> figure;
  if (figure == "RECT") {
    is >> a >> b;
    return std::make_shared<Rect>(a, b);
  } else if (figure == "TRIANGLE") {
    is >> a >> b >> c;
    return std::make_shared<Triangle>(a, b, c);
  } else if (figure == "CIRCLE") {
    is >> a;
    return std::make_shared<Circle>(a);
  } else {
    return std::make_shared<Rect>(0, 0);
  }
}