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

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);  // в случае некорретных данных
    }
}