header
//---------------------------------------------------------
// GrossPay7.cpp
//
// Calculate and display the gross pay given the hourly
// wage and the number of hours worked.
//
// This version uses an employeeRecord class in which the
// gross pay is calculated on demand (when the getGrossPay
// method is invoked).
//
// This version also makes use of an employeeList class
// that maintains a list of employee records.
//
// D. Searls
// Asbury College
// Oct 2006
//---------------------------------------------------------

#include <string>
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;

const int MAXSIZE = 100;

class employeeRecord
{
private:

// Data members

    string id;        // Employee identifier
    double hours;     // Hours worked
    double wage;      // Hourly wage
  
public:

// Class constructors

    //-----------------------------------------------------
    // Default Constructor
    //
    // Construct a new employee whose identifier is the
    // empty string and whose hours and hourly wage are
    // both zero.
    //-----------------------------------------------------
    employeeRecord()
    {
        id = "";
        hours = 0.0;
        wage = 0.0;
    }
    
    //-----------------------------------------------------
    // Initialization Constructor
    //
    // Preconditions: empHours >= 0
    //                empWage  >= 0
    //
    // Construct a new employee with the specified
    // identifier, hours, and hourly wage. If the specified
    // hours is negative, the employee's hours will be set
    // to zero. If the specified hourly wage is negative,
    // the employee's hourly wage will be set to zero.
    //
    // In Parameters: empId, empHours, empWage
    //-----------------------------------------------------
    employeeRecord(string empId, double empHours, double empWage)
    {
        id = empId;
        
        if (empHours >= 0.0)
        {
            hours = empHours;
        }
        else
        {
            hours = 0.0;
        }
        
        if (empWage >= 0.0)
        {
            wage = empWage;
        }
        else
        {
            wage = 0.0;
        }
    }
    
    //-----------------------------------------------------
    // Copy Constructor
    //
    // Construct a new employee having the same state as
    // the specified employee.
    //
    // In Parameter: emp
    //-----------------------------------------------------
    employeeRecord(const employeeRecord& emp)
    {
        id = emp.id;
        hours = emp.hours;
        wage = emp.wage;
    }

// Member functions

    //-----------------------------------------------------
    // setIdentifier
    //
    // Set the employee's identifier to the specifed value.
    //-----------------------------------------------------
    void setIdentifier(string newId)
    {
        id = newId;
    }
    
    //-----------------------------------------------------
    // setHours
    //
    // Precondition: newHours >= 0
    //
    // Set the employee's hours worked to the specifed
    // value. If the specified value is negative, the
    // employee's hours will not be changed.
    //-----------------------------------------------------
    void setHours(double newHours)
    {
        if (newHours >= 0.0)
        {
            hours = newHours;
        }
    }
    
    //-----------------------------------------------------
    // setWage
    //
    // Precondition: newWage >= 0
    //
    // Set the employee's hourly wage to the specifed value.
    // If the specified value is negative, the employee's
    // wage will not be changed.
    //-----------------------------------------------------
    void setWage(double newWage)
    {
        if (newWage >= 0)
        {
            wage = newWage;
        }
    }
    
    //-----------------------------------------------------
    // getIdentifier
    //
    // Get the employee's identifier.
    //-----------------------------------------------------
    string getIdentifier() const
    {
        return id;
    }

    //-----------------------------------------------------
    // getHours
    //
    // Get the employee's hours worked.
    //-----------------------------------------------------
    double getHours() const
    {
        return hours;
    }

    //-----------------------------------------------------
    // getWage
    //
    // Get the employee's hourly wage.
    //-----------------------------------------------------
    double getWage() const
    {
        return wage;
    }
    
    //-----------------------------------------------------
    // getGrossPay
    //
    // Get the employee's gross pay.
    //-----------------------------------------------------
    double getGrossPay() const
    {
       const double MAXHOURS = 40.0;
       const double OT_MULTIPLIER = 1.5; 
       double grossPay;
        
        if (hours <= MAXHOURS)
        {
            grossPay = hours * wage;
        }
        else
        {
            grossPay = MAXHOURS * wage
                       + (hours - MAXHOURS)
                         * OT_MULTIPLIER * wage;
        }
        return grossPay;
    }      
};

class employeeList
{
private:

    static const int MAXSIZE = 100;
    employeeRecord list[MAXSIZE];
    int n;
    
public:

    //-----------------------------------------------------
    // Construct a default (empty) employee list.
    //-----------------------------------------------------
    employeeList()
    {
        n = 0;
    }
    
    //-----------------------------------------------------
    // Construct a new list that is a copy of the specified
    // list.
    //
    // In Parameter: theList
    //-----------------------------------------------------
    employeeList(const employeeList& theList)
    {
        n = 0;
        while (n < theList.n)
        {
            list[n] = theList.list[n];
            n++;
        }
    }
    
    //-----------------------------------------------------
    // Append a new employee to the list. If the list is
    // full, this method does nothing.
    //
    // In Parameter: newEmployee
    //-----------------------------------------------------
    void append(employeeRecord newEmployee)
    {
        if (n < MAXSIZE)
        {
            list[n] = newEmployee;
            n++;
        }
    }
    
    //-----------------------------------------------------
    // Delete the employee at the specified position.
    //
    // Pre-condition: 0 <= position < n (length of list)
    //
    // If the specified position is invalid, this method
    // will do nothing.
    //
    // In Parameter: position
    //-----------------------------------------------------
    void deleteAt(int position)
    {
        if (0 <= position && position < n)
        {
            list[position] = list[n-1];
            n--;
        }
    }
    
    //-----------------------------------------------------
    // Return the employee at the specified position.
    //
    // Pre-condition: 0 <= position < n (length of list)
    //
    // If the specified position is invalid, this method
    // will return the employee at position 0.
    //
    // In Parameter: position
    //-----------------------------------------------------
    employeeRecord getEmployeeAt(int position) const
    {
        if (position < 0 || position >= n)
        {
            position = 0;
        }
        return list[position];
    }
    
    //-----------------------------------------------------
    // Set the attributes of the employee at the specified
    // position to the specified values.
    //
    // Pre-conditions: 0 <= position < n (length of list)
    //                 newHours >= 0.0
    //                 newWage >= 0.0
    //
    // If the specified position is invalid, this method
    // does nothing. If newHours or newWage is invalid the
    // corresponding attribute will be left unchanged.
    //
    // In Parameters: position, newID, newHours, newWage
    //-----------------------------------------------------
    void setEmployeeAt(int position, string newID,
                       double newHours, double newWage)
    {
        if (0 <= position && position < n)
        {
            list[position].setIdentifier(newID);
            list[position].setHours(newHours);
            list[position].setWage(newWage);
        }
    }
    
    //-----------------------------------------------------
    // Return the length of the list.
    //-----------------------------------------------------
    int length() const
    {
        return n;
    }
    
    //-----------------------------------------------------
    // Return true if the list is full and false otherwise.
    //-----------------------------------------------------
    bool isFull() const
    {
        return n == MAXSIZE;
    }
    
};
    
//*********************************************************
// getEmployeeData
//
// Out Parameters: data
//
// Returns: void
//*********************************************************
void getEmployeeData(employeeList& data)
{
    ifstream infile;
    string identity;
    double wageRate;
    double hours;
    employeeRecord emp;
    
    infile.open("EmployeeData.txt");
    infile >> identity >> wageRate >> hours;
    while (!infile.fail() && !data.isFull())
    {
        emp.setIdentifier(identity);
        emp.setHours(hours);
        emp.setWage(wageRate);
        data.append(emp);
        
        infile >> identity >> wageRate >> hours;
    }
    infile.close();
}

//*********************************************************
// displayGrossPay
//
// In Parameter: data
//
// Returns: void
//*********************************************************
void displayGrossPay(const employeeList& data)
{
    cout << fixed << setprecision(2);
    cout << "Employee  Gross Pay" << endl;
    cout << "--------  ---------" << endl;
    for (int i = 0; i < data.length(); i++)
    {
        cout << setw(8) << data.getEmployeeAt(i).getIdentifier()
                << setw(11) << data.getEmployeeAt(i).getGrossPay() << endl;
    }
}

//*********************************************************
//              M A I N   D R I V E R
//*********************************************************
int main()
{
    employeeList empData;

    getEmployeeData(empData);
    displayGrossPay(empData);
    cout << endl;
    
    // Perform some additional tests on employeeList objects.
    
    employeeList clone(empData);    

    empData.setEmployeeAt(3, "8", 32.0, 25.0);
    displayGrossPay(empData);
    cout << endl;
    
    empData.deleteAt(3);
    displayGrossPay(empData);
    cout << "Length of empData: " << empData.length() << endl << endl;
    
    displayGrossPay(clone);
    cout << "Length of clone: " << clone.length() << endl;
    
    return 0;
}