#include <iomanip>
#include <iostream>
#include <vector>

using namespace std;

/**
   Obiekt pracownika z imieniem i nazwiskiem oraz mechanizmem obliczania wypłaty tygodniowej.
 */
class Employee
{
public:
   /**
      Konstruuje obiekt pracownika bez podanego imienia i nazwiska.
   */
   Employee();

   /**
      @param employee_name imię i nazwisko pracownika
   */
   void set_name(string employee_name);

   /**
      @return imię i nazwisko pracownika
   */
   string get_name() const;

   /**
      Oblicza wypłatę tygodniową.
      @param hours_worked liczba przepracowanych w tygodniu godzin
      @return wypłata za podaną liczbę godzin
   */
   virtual double weekly_pay(int hours_worked) const;
private:
   string name;
};

Employee::Employee()
{
}

void Employee::set_name(string employee_name)
{
   name = employee_name;
}

string Employee::get_name() const
{
   return name; 
}

double Employee::weekly_pay(int hours_worked) const
{
   return 0; 
}

//....................................................................

class HourlyEmployee : public Employee
{
public:
   /**
      @param name imię i nazwisko pracownika
      @param wage stawka godzinowa
   */
   HourlyEmployee(string name, double wage);
 
   virtual double weekly_pay(int hours_worked) const;
private:
   double hourly_wage;
};

HourlyEmployee::HourlyEmployee(string name, double wage)
{
   set_name(name);
   hourly_wage = wage;
}

double HourlyEmployee::weekly_pay(int hours_worked) const
{
   double pay = hours_worked * hourly_wage;
   if (hours_worked > 40)
   {
      pay = pay + ((hours_worked - 40) * 0.5) * hourly_wage;
   }
   return pay;
}

//....................................................................

class SalariedEmployee : public Employee
{
public:
   /**
      @param name imię i nazwisko pracownika
      @param salary wynagrodzenie roczne
    */
   SalariedEmployee(string name, double salary);

   virtual double weekly_pay(int hours_worked) const;
private:
   double annual_salary;
};

SalariedEmployee::SalariedEmployee(string name, double salary)
{
   set_name(name);
   annual_salary = salary;
}

double SalariedEmployee::weekly_pay(int hours_worked) const
{
   const int WEEKS_PER_YEAR = 52;
   return annual_salary / WEEKS_PER_YEAR;
}

//....................................................................

class Manager : public SalariedEmployee
{
public:
   /**
      @param name imię i nazwisko pracownika
      @param salary wynagrodzenie roczne
      @param bonus premia tygodniowa
    */
   Manager(string name, double salary, double bonus);

   virtual double weekly_pay(int hours) const;
private:
   double weekly_bonus;
};

Manager::Manager(string name, double salary, double bonus)
   : SalariedEmployee(name, salary)
{
   weekly_bonus = bonus;
}

double Manager::weekly_pay(int hours) const
{
   return SalariedEmployee::weekly_pay(hours) + weekly_bonus;
}

//....................................................................

int main()
{
   vector<Employee*> staff;
   staff.push_back(new HourlyEmployee("Henryk Morga", 30));
   staff.push_back(new SalariedEmployee("Sylwia Linda", 52000));
   staff.push_back(new Manager("Maria Kowalska", 104000, 50));
      
   for (int i = 0; i < staff.size(); i++)
   {
      cout << "Liczba godzin, które przepracował(a) " << staff[i]->get_name() << ": ";
      int hours;
      cin >> hours;
      cout << "Wynagrodzenie: " << staff[i]->weekly_pay(hours) << endl;
   }

   return 0;
}

