#include <iostream>
#include <cmath>

using namespace std;

double rect_integral(double a, double b, int n, int choice);
double trap_integral(double a, double b, int n, int choice);

class FunctionInterface
{
public:
    virtual ~FunctionInterface() {};
    virtual double Calculate(double x) = 0;
    virtual std::string GetName() = 0;
};

class Function1: public FunctionInterface
{
public:
    FunctionInterface() {}

    double Calculate (double x)
    {
        return 2.0*pow(x,5.0) +pow(x,3.0) -10*x +2;
    }
    
    std::string GetName()
    {
        return m_Name;
    }
private:
    static const std::string m_Name = "2x^5 + x^3 -10x+2";
};

class Function2: public FunctionInterface
{
public:
    FunctionInterface() {}

    double Calculate (double x)
    {
        return 6*pow(x,2.0) -x +10;
    }

    std::string GetName()
    {
        return m_Name;
    }
private:
    static const m_Name = "6x^2 - x +10";
};



int main () {
    FunctionInterface* functions[2];
    functions[0] = new Function1();
    functions[1] = new Function2();
    
  start:
    int choice;
    int n;
    double a;
    double b;
    bool trap = false;
    bool rect = false;

    cout << "Functions available: \n\n";
    for (int i=0; i<2; i++)
        cout << "  " << i << "  " << functions[i].GetName() << '\n';
    cout << endl;

    cout << "Choose a function (1, 2, 3, 4, 5, other(quit)) " << endl;
    cin >> choice;

    if (choice >= 0 && choice < 2)
    {
        char method = ' ';
        do {
            cout << "Would you like to calculate the area using the rectangle,"
                 << " trapezoid, or both (1, 2, 3): " << endl;
            cin >> method;
        } while (method < '1' || method > '3');

        switch (method) {
            case '1':
                rect = true;
                cout <<"How many rectangles do you want? " << endl;
                break;
            case '2':
                trap = true;
                cout <<"How many trapezoids do you want? " << endl;
                break;
            case '3':
                trap = true;
                rect = true;
                cout <<"How many rectangles/trapezoids do you want? " << endl;
        }

        cin >> n;

        cout <<"Please select a starting point, a: " << endl;
        cin >> a;

        cout <<"Please select an ending point, b: " << endl;
        cin >> b;

        if (rect) {
            cout << "The area under " << function[choice]->GetName()
                 << " between " << a << " and " <<  b
                 << " is: " <<  rect_integral(a, b, n, *function[choice]) <<" in rectangles" << endl;
        }

        if (trap) {
            cout << "The area under " << function[choice]->GetName()
                 << " between " << a << " and " <<  b
                 << " is: " <<  trap_integral(a, b, n, *function[choice]) << " in trapezoids" << endl;
        }
    }
int again;
cout << "Would you like to go again? Yes = 1 " <<endl;
cin >> again;

if (again == 1)
   goto start;

    return 0;
}
// end of int main() start of functions


double rect_integral(double a, double b, int n, FunctionInterface& function)
{
    double width = (b-a)/n;

    double x = a;
    double total_area = 0;
    for(int i = 1; i <= n; i++) {
        x = width *i;
        total_area += width * function.Calculate(x);
    }
           
    return total_area;
}   

double trap_integral(double a, double b, int n, FunctionInterface& function)
{
    double x =a; 

    double interiml, interimr;
    double total_area = 0;
    for(int i = 1; i <= n; i++) {
        x = width *i;
        interiml = width * fx(x);
        x = width*i;
        interimr = width * function.Calculate(x);
        total_area += (interiml + interimr)/2;
    }
    
    return total_area;
}
