#pragma once
#include <math.h>
#include <memory>
#include <string>

class Figure {
 public:
  virtual const char *Name() const = 0;
  virtual double Perimeter() const = 0;
  virtual double Area() const = 0;
  virtual ~Figure() {}
};

class Triangle : public Figure {
 public:
  Triangle(int a, int b, int c) : a(a), b(b), c(c), name("TRIANGLE") {}
  const char *Name() const override {
    return name.c_str();
  }
  double Perimeter() const override {
    return a + b + c;
  }
  double Area() const override {
    double half_p = Perimeter() / 2;
    return sqrt(half_p * (half_p - a) * (half_p - b) * (half_p - c));
  }

 private:
  int a;
  int b;
  int c;
  std::string name;
};

class Rect : public Figure {
 public:
  Rect(int a, int b) : a(a), b(b), name("RECT") {}
  const char *Name() const override {
    return name.c_str();
  }
  double Perimeter() const override {
    return 2 * (a + b);
  }
  double Area() const override {
    return a * b;
  }

 private:
  int a;
  int b;
  std::string name;
};

class Circle : public Figure {
 public:
  explicit Circle(int r) : r(r), name("CIRCLE") {}
  const char *Name() const override {
    return name.c_str();
  }
  double Perimeter() const override {
    return 2 * r * 3.14;
  }
  double Area() const override {
    return 3.14 * r * r;
  }

 private:
  int r;
  std::string name;
};

std::shared_ptr<Figure> CreateFigure(std::istream &is) {
  std::string fig;
  is >> fig;
  if (fig == "TRIANGLE") {
    int a, b, c;
    is >> a >> b >> c;
    std::shared_ptr<Figure> p = std::make_shared<Triangle>(a, b, c);
    return p;
  } else if (fig == "CIRCLE") {
    int r;
    is >> r;
    std::shared_ptr<Figure> p = std::make_shared<Circle>(r);
    return p;
  } else {
    int a, b;
    is >> a >> b;
    std::shared_ptr<Figure> p = std::make_shared<Rect>(a, b);
    return p;
  }
}