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

double pi = 3.14;

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

class Triangle : public Figure {
 public:
    double a;
    double b;
    double c;

    Triangle(double a1, double b1, double c1) : a(a1), b(b1), c(c1) {}

    std::string Name() const {
        return "TRIANGLE";
    }

    double Perimeter() const {
        return a + b + c;
    }

    double Area() const {
        double p = Perimeter() / 2;
        return sqrt(p * (p - a) * (p - b) * (p - c));
    }
};

class Rect : public Figure {
 public:
    double w;
    double h;

    Rect(double w1, double h1) : w(w1), h(h1) {}

    std::string Name() const {
        return "RECT";
    }

    double Area() const {
        return w * h;
    }

    double Perimeter() const {
        return 2 * (w + h);
    }
};

class Circle : public Figure {
 public:
    double r;

    explicit Circle(double r1) : r(r1) {}

    std::string Name() const {
        return "CIRCLE";
    }

    double Area() const {
        return pi * pow(r, 2);
    }

    double Perimeter() const {
        return 2 * pi * r;
    }
};

std::shared_ptr<Figure> CreateFigure(std::istringstream& is) {
    std::string kof;
    is >> kof;
    if (kof == "RECT") {
        double w, h;

        is >> w >> h;

        return std::make_shared<Rect>(w, h);
    } else if (kof == "TRIANGLE") {
        double a;
        double b;
        double c;

        is >> a >> b >> c;

        return std::make_shared<Triangle>(a, b, c);
    } else {
        double r;

        is >> r;

        return std::make_shared<Circle>(r);
    }
}