header
//---------------------------------------------------------
// GrossPay12.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;

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 DEFAULTCAPACITY = 10;
    employeeRecord* list;
    int mySize;
    int myCapacity;
    
public:

    //-----------------------------------------------------
    // Construct a default (empty) employee list.
    //-----------------------------------------------------
    employeeList()
    {
        list = new (nothrow) employeeRecord[DEFAULTCAPACITY];
        if (list == NULL)
        {
            cout << "FATAL ERROR: Memory allocation failed in default\n";
            cout << "constructor of the employeeList class.\n";
            exit(0);
        }
        mySize = 0;
        myCapacity = DEFAULTCAPACITY;
    }
    
    //-----------------------------------------------------
    // Construct an empty employee list having the
    // specified capacity. The capacity must be greater
    // than the default capacity (10). Otherwise, the
    // default capacity will be used..
    //
    // In Parameter: capacity
    //-----------------------------------------------------
    employeeList(int capacity)
    {

        if (capacity < DEFAULTCAPACITY)
        {
            myCapacity = DEFAULTCAPACITY;
        }
        else
        {
            myCapacity = capacity;
        }
        list = new (nothrow) employeeRecord[myCapacity];
        if (list == NULL)
        {
            cout << "FATAL ERROR: Memory allocation failed in the\n";
            cout << "initialization constructor of the employeeList\n";
            cout << "class.\n";
            exit(0);
        }
        mySize = 0;
    }   
    
    //-----------------------------------------------------
    // Construct a new list that is a copy of the specified
    // list.
    //
    // In Parameter: theList
    //-----------------------------------------------------
    employeeList(const employeeList& theList)
    {
        myCapacity = theList.myCapacity;
        list = new (nothrow) employeeRecord[myCapacity];
        if (list == NULL)
        {
            cout << "FATAL ERROR: Memory allocation failed in the copy\n";
            cout << "constructor of the employeeList class.\n";
            exit(0);
        }
        mySize = 0;
        while (mySize < theList.mySize)
        {
            list[mySize] = theList.list[mySize];
            mySize++;
        }
    }
    
    //-----------------------------------------------------
    // Return the memory allocated for the list back to
    // the operating system.
    //-----------------------------------------------------
    ~employeeList()
    {
        delete [] list;
    }
    
    //-----------------------------------------------------
    // Append a new employee to the list. If the list is
    // full, this method does nothing.
    //
    // In Parameter: newEmployee
    //-----------------------------------------------------
    void append(employeeRecord newEmployee)
    {
        if (mySize < myCapacity)
        {
            list[mySize] = newEmployee;
            mySize++;
        }
    }
    
    //-----------------------------------------------------
    // 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 < mySize)
        {
            list[position] = list[mySize-1];
            mySize--;
        }
    }
    
    //-----------------------------------------------------
    // 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 >= mySize)
        {
            position = 0;
        }
        return list[position];
    }
    
    //-----------------------------------------------------
    // Set the attributes of the employee at the specified
    // position to the specified values.
    //
    // Pre-conditions: 0 <= position < mySize (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 < mySize)
        {
            list[position].setIdentifier(newID);
            if (newHours >= 0.0)
            {
                list[position].setHours(newHours);
            }
            if (newWage >= 0.0)
            {
                list[position].setWage(newWage);
            }
        }
    }
    
    //-----------------------------------------------------
    // Return the length of the list.
    //-----------------------------------------------------
    int length() const
    {
        return mySize;
    }
    
    //-----------------------------------------------------
    // Return true if the list is full and false otherwise.
    //-----------------------------------------------------
    bool isFull() const
    {
        return mySize == myCapacity;
    }
    
};
    
//*********************************************************
// 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()
{
    employeeRecord emp("Test", 8.0, 10.0);
    employeeList empData;

    getEmployeeData(empData);
    displayGrossPay(empData);
    cout << endl;
    cout << "Press Enter to continue...";
    cin.get();
    cout << endl;
    
    // Test copy constructor
    
    employeeList clone(empData);
    cout << "Clone list: \n";
    displayGrossPay(clone);
    cout << "Press Enter to continue...";
    cin.get();
    cout << endl;
    
    // Test initialization constructor
    
    employeeList bigList(200);
    while (!(bigList.isFull()))
    {
        bigList.append(emp);
    }
    cout << "Big list:\n";
    displayGrossPay(bigList);
    cout << "Press Enter to continue...";
    cin.get();
    cout << endl;
    
    // Test setEmployeeAt method    

    empData.setEmployeeAt(3, "8", 32.0, 25.0);
    empData.setEmployeeAt(20, "20", 50.0, 40.0);
    cout << "Employee list with modified record:\n";
    displayGrossPay(empData);
    cout << endl;
    cout << "Press Enter to continue...";
    cin.get();
    cout << endl;
    
    // Test deleteAt method
    
    empData.deleteAt(3);
    empData.deleteAt(20);
    cout << "Employee list with deleted record:\n";
    displayGrossPay(empData);
    
    return 0;
}