#pragma once

#include <string>
#include <utility>
#include <cmath>
#include <memory>

#define PI 3.14

class Figure {
 public:
    explicit Figure(const std::string& name) : name_(name) {}

    virtual std::string Name() {
        return name_;
    }

    virtual double Perimeter() = 0;

    virtual double Area() = 0;

 private:
    const std::string name_;
};

class Rect : public Figure {
 public:
    explicit Rect(const std::string& name, int width, int height) :
    Figure(name), width_(width), height_(height) {}

    double Perimeter() override {
        return 2 * (width_ + height_);
    }

    double Area() override {
        return width_ * height_;
    }

 private:
    const int width_;
    const int height_;
};

class Triangle : public Figure {
 public:
    explicit Triangle(const std::string& name, int a, int b, int c) :
    Figure(name), a_(a), b_(b), c_(c) {}

    double Perimeter() override {
        return a_ + b_ + c_;
    }

    double Area() override {
        double p = static_cast<double>(a_ + b_ + c_) / 2;
        return std::sqrt(p * (p - a_) * (p - b_) * (p - c_));
    }

 private:
    const int a_;
    const int b_;
    const int c_;
};

class Circle : public Figure {
 public:
    explicit Circle(const std::string& name, int r) : Figure(name), r_(r) {}

    double Perimeter() override {
        return 2 * PI * r_;
    }

    double Area() override {
        return PI * std::pow(r_, 2);
    }

 private:
    const int r_;
};

std::shared_ptr<Figure> CreateFigure(std::istringstream& is) {
    std::string figure;
    is >> figure;

    if (figure == "RECT") {
        int width, height;
        is >> width >> height;
        std::shared_ptr<Figure> ptr =
                std::make_shared<Rect>(figure, width, height);
        return ptr;
    } else if (figure == "TRIANGLE") {
        int a, b, c;
        is >> a >> b >> c;
        std::shared_ptr<Figure> ptr =
                std::make_shared<Triangle>(figure, a, b, c);
        return ptr;
    } else if (figure == "CIRCLE") {
        int r;
        is >> r;
        std::shared_ptr<Figure> ptr = std::make_shared<Circle>(figure, r);
        return ptr;
    }

    return nullptr;
}