//********************************************************
//
// Assignment 6 - Structures
//
// Name: <rHaroon Malik>
//
// Class: C Programming, <Fall 2026>
//
// Date: <10/14/2026>
//
// Description: Program which determines overtime and 
// gross pay for a set of employees with outputs sent 
// to standard output (the screen).
//
// Call by Value design
//
//********************************************************
// Defines and Includes
#include <stdio.h>

// Define Constants
#define SIZE 5
#define STD_HOURS 40.0
#define OT_RATE 1.5

// Define a global structure type.
// Employee variables are declared locally in main.
struct employee
{
    long int clockNumber;
    float wageRate;
    float hours;
    float overtimeHrs;
    float grossPay;
};

// Function prototypes
float getHours(long int clockNumber);
float getOvertime(float hours);
float getGrossPay(float wageRate, float hours, float overtimeHrs);
void printHeader(void);
void printEmp(long int clockNumber, float wageRate, float hours,
              float overtimeHrs, float grossPay);

int main(void)
{
    // Store employee information in a local array.
    struct employee employeeData[SIZE] = {
        { 98401, 10.60f, 0.0f, 0.0f, 0.0f },
        { 526488, 9.75f, 0.0f, 0.0f, 0.0f },
        { 765349, 10.50f, 0.0f, 0.0f, 0.0f },
        { 34645, 12.25f, 0.0f, 0.0f, 0.0f },
        { 127615, 8.35f, 0.0f, 0.0f, 0.0f }
    };

    int i; // loop and array index

    // Read hours and calculate overtime and gross pay.
    for (i = 0; i < SIZE; ++i)
    {
        employeeData[i].hours =
            getHours(employeeData[i].clockNumber);

        employeeData[i].overtimeHrs =
            getOvertime(employeeData[i].hours);

        employeeData[i].grossPay =
            getGrossPay(employeeData[i].wageRate,
                        employeeData[i].hours,
                        employeeData[i].overtimeHrs);
    }

    // Print the column headers.
    printHeader();

    // Print each employee.
    for (i = 0; i < SIZE; ++i)
    {
        printEmp(employeeData[i].clockNumber,
                 employeeData[i].wageRate,
                 employeeData[i].hours,
                 employeeData[i].overtimeHrs,
                 employeeData[i].grossPay);
    }

    printf("\n");

    return 0;
}

//**************************************************************
// Function: getHours
//
// Purpose: Obtains the number of hours worked by an employee.
//
// Parameters: clockNumber - unique employee ID
//
// Returns: hoursWorked - hours worked in a given week
//**************************************************************

float getHours(long int clockNumber)
{
    float hoursWorked;
    int inputStatus;
    int character;

    // Continue prompting until valid, nonnegative hours are entered.
    do
    {
        printf("\nEnter hours worked by emp # %06li: ", clockNumber);
        inputStatus = scanf("%f", &hoursWorked);

        if (inputStatus == EOF)
        {
            return 0.0f;
        }

        // Discard the remaining input on this line.
        while ((character = getchar()) != '\n' && character != EOF)
        {
        }

        if (inputStatus != 1)
        {
            printf("Invalid input. Please enter a number.\n");
        }
        else if (hoursWorked < 0.0f)
        {
            printf("Hours cannot be negative. Please try again.\n");
        }
    } while (inputStatus != 1 || hoursWorked < 0.0f);

    return hoursWorked;
}

//**************************************************************
// Function: getOvertime
//
// Purpose: Calculates hours worked beyond the standard workweek.
//
// Parameters: hours - total hours worked for the week
//
// Returns: overtime hours
//**************************************************************

float getOvertime(float hours)
{
    if (hours > STD_HOURS)
    {
        return hours - STD_HOURS;
    }

    return 0.0f;
}

//**************************************************************
// Function: getGrossPay
//
// Purpose: Calculates regular pay plus overtime pay.
//
// Parameters:
//     wageRate - hourly wage rate
//     hours - total hours worked for the week
//     overtimeHrs - overtime hours worked for the week
//
// Returns: gross pay for the week
//**************************************************************

float getGrossPay(float wageRate, float hours, float overtimeHrs)
{
    float regularHours = hours - overtimeHrs;

    return (regularHours * wageRate) +
           (overtimeHrs * wageRate * OT_RATE);
}

//**************************************************************
// Function: printHeader
//
// Purpose: Prints the initial table header information.
//
// Parameters: none
//
// Returns: void
//**************************************************************

void printHeader(void)
{
    printf("\n\n*** Pay Calculator ***\n");
    printf("\n Clock#  Wage Hours   OT    Gross\n");
    printf("----------------------------------------\n");
}

//**************************************************************
// Function: printEmp
//
// Purpose: Prints information for one employee in table format.
//
// Parameters:
//     clockNumber - unique employee ID
//     wageRate - hourly wage rate
//     hours - hours worked for the week
//     overtimeHrs - overtime hours worked for the week
//     grossPay - gross pay for the week
//
// Returns: void
//**************************************************************

void printEmp(long int clockNumber, float wageRate, float hours,
              float overtimeHrs, float grossPay)
{
    printf("\n %06li %5.2f %5.1f %4.1f %8.2f",
           clockNumber, wageRate, hours, overtimeHrs, grossPay);
}