#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#if defined ( __GNUC__ ) || ( _MSC_VER )
# if defined ( _MSC_VER ) && ( _MSC_VER >= 1020 )
# pragma warning ( disable : 4996 )
# pragma warning ( disable : 4172 )
# endif
#ifndef BUFSIZ
#define BUFSIZ 512
#endif
#ifndef NULL
#define NULL 0
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#define MAXREC 10
#define MAXWORKDAYS 5
const float SALARYLEVEL1 = 380.00;
const float SALARYLEVEL2 = 450.00;
const float SALARYLEVEL3 = 550.00;
const float WEEKLYALLOWANCE = 500.00;
/* Nested structs to hold employee data */
typedef struct _DAILYTIMERECORD
{
double regularhoursworked;
time_t regulartimein;
time_t regulartimeout;
double overtimehoursworked;
time_t overtimein;
time_t overtimeout;
double latehours;
double undertimehours;
size_t holiday;
} DAILYTIMERECORD;
typedef struct _WEEKLYTIMERECORD
{
char coveragedate[BUFSIZ];
double regularincome;
double overtimeincome;
double grossincome;
double netincome;
double taxdeductions;
double sssdeductions;
double totalweeklyregularhoursworked;
double totalweeklyovertimehoursworked;
DAILYTIMERECORD dailytimerecord[MAXWORKDAYS];
} WEEKLYTIMERECORD;
typedef struct _EMPLOYEERECORD
{
char code[BUFSIZ];
char name[BUFSIZ];
size_t level;
double rate;
WEEKLYTIMERECORD weeklytimerecord;
} EMPLOYEERECORD;
/****************************************/
/* Employee Records Container. Can hold maximum of MAXREC records */
static EMPLOYEERECORD records[MAXREC] = { 0 };
static char * workdays[MAXWORKDAYS] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" };
typedef enum _InputFilter { EMPCODEINPUT, EMPTIMEINPUT, EMPCOVDATEINPUT } InputFilter;
typedef enum _WorkDay { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY } WorkDay;
typedef enum _PrintInfo { EMPLOYEEINFO, EMPLOYEEHOURS } PrintInfo;
//*********************** Function Prototypes *************************//
int ReadEmployeeRecords( const char * );
int WriteEmployeeTimeRecords ( char *, size_t );
int FindEmployeeRecord ( const char * );
int FilterInput ( char *, InputFilter );
char * GetEmployeeCodeInput ( );
void GetEmployeeRegularHours ( size_t, size_t );
void GetEmployeeOvertimeHours ( size_t, size_t );
void GetHoliday ( size_t, size_t );
void GetCoverageDate ( size_t );
void ComputeWeeklySalary ( size_t );
void DisplayRecords ( PrintInfo, size_t, size_t );
int RunApp ( );
void ResetRecords ( size_t );
//*********************************************************************//
/* Main entry */
int main ( int argc, char ** argv )
{
if ( RunApp () < 0 )
exit ( EXIT_FAILURE );
return 0;
}
/*
Read records from the file pointed to by filein.
*/
int ReadEmployeeRecords( const char * filein )
{
FILE * pfile;
char * linebuffer;
char * pch;
const char * delim = ":";
size_t index = 0;
pfile = fopen ( filein, "r" );
if ( pfile == NULL )
{
printf ( "Error opening file %s: %s\n", filein, strerror ( errno ) );
return -1;
}
linebuffer = ( char * ) malloc ( sizeof ( char ) * BUFSIZ );
if ( linebuffer == NULL )
{
fclose ( pfile );
printf ( "Error allocating memory space.\n" );
return -1;
}
while ( fgets ( linebuffer, BUFSIZ, pfile ) )
{
if ( index == MAXREC )
{
/* printf ( "Maximum number of %d records allowed in records container has been reached.\n", MAXREC ); */
free ( linebuffer );
fclose ( pfile );
return 0;
}
if ( ferror ( pfile ) != 0 )
{
printf ( "Error reading from input file %s: %s\n",
filein, strerror ( errno ) );
free ( linebuffer );
fclose ( pfile );
return -1;
}
if ( linebuffer[0] == '#' || linebuffer[0] == '\n' )
continue;
linebuffer[strlen ( linebuffer ) - 1] = '\0';
pch = strtok ( linebuffer, delim );
memcpy (records[index].code, pch, strlen ( pch ) );
records[index].code[strlen ( pch ) ] = '\0';
pch = strtok ( NULL, delim );
memcpy (records[index].name, pch, strlen ( pch ) );
records[index].name[strlen ( pch ) ] = '\0';
pch = strtok ( NULL, delim );
sscanf ( pch, "%d", &records[index].level );
if ( records[index].level == 1 )
records[index].rate = SALARYLEVEL1;
else if ( records[index].level == 2 )
records[index].rate = SALARYLEVEL2;
else if ( records[index].level == 3 )
records[index].rate = SALARYLEVEL3;
++index;
}
free ( linebuffer );
return 0;
}
/*
Write records to dtr.txt.
*/
int WriteEmployeeTimeRecords ( char * fileout, size_t index )
{
FILE * pfile;
int ret = -1;
struct tm * tminfo;
char buffer[BUFSIZ];
size_t i;
pfile = fopen ( fileout, "a" );
if ( pfile == NULL )
{
printf ( "Error opening file %s: %s\n", fileout, strerror ( errno ) );
return ret;
}
fprintf ( pfile, "%s|", records[index].code );
for ( i = MONDAY; i <= FRIDAY; ++i )
{
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[i].regulartimein );
strftime ( buffer, BUFSIZ, "%H:%M", tminfo );
if ( fprintf ( pfile, "%s|", buffer ) < 0 )
break;
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[i].regulartimeout );
strftime ( buffer, BUFSIZ, "%H:%M", tminfo );
if ( fprintf ( pfile, "%s|", buffer ) < 0 )
break;
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[i].overtimein );
strftime ( buffer, BUFSIZ, "%H:%M", tminfo );
if ( fprintf ( pfile, "%s|", buffer ) < 0 )
break;
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[i].overtimeout );
strftime ( buffer, BUFSIZ, "%H:%M", tminfo );
if ( i == FRIDAY )
{
if ( fprintf ( pfile, "%s\n", buffer ) < 0 )
break;
}
else
{
if ( fprintf ( pfile, "%s|", buffer ) < 0 )
break;
}
ret = 0;
}
fclose ( pfile );
return ret;
}
/*
Attempt to locate a matching string defined by pointer to parameter rec.
*/
int FindEmployeeRecord ( const char * rec )
{
char * pch;
int i, found = -1;
if ( rec == NULL )
return -1;
for ( i = 0; i < MAXREC; ++i )
{
pch = strstr ( records[i].code, rec );
if ( pch != NULL )
{
found = i;
break;
}
}
return found;
}
/*
Check the format of the string input.
*/
int FilterInput ( char * input, InputFilter filter )
{
const int EMPCODEMAXLEN = 8;
const int EMPTIMEINPUTLEN = 5;
const int EMPCOVDATELEN = 15;
int ret = -1;
if ( input[0] == '\n' )
{
ret = 0;
return ret;
}
input[ strlen ( input ) - 1 ] = '\0';
switch ( filter )
{
case EMPCODEINPUT : if ( strlen ( input ) != EMPCODEMAXLEN )
ret = -1;
else if ( ! ( ( input[0] == 'A' && input[3] == '-' ) &&
( input[1] >= '0' && input[1] <= '9' ) &&
( input[2] >= '0' && input[2] <= '9' ) &&
( input[4] >= '0' && input[4] <= '9' ) &&
( input[5] >= '0' && input[5] <= '9' ) &&
( input[6] >= '0' && input[6] <= '9' ) &&
( input[7] >= '0' && input[7] <= '9' ) ) )
ret = -1;
else
ret = 0;
break;
case EMPTIMEINPUT : if ( strlen ( input ) != EMPTIMEINPUTLEN )
ret = -1;
else if ( ! ( ( input[0] >= '0' && input[0] <= '2' ) &&
( input[1] >= '0' && input[1] <= '9' ) &&
( input[2] == ':' ) &&
( input[3] >= '0' && input[3] <= '5' ) &&
( input[4] >= '0' && input[3] <= '9' ) ) )
ret = -1;
else
ret = 0;
break;
case EMPCOVDATEINPUT : if ( strlen ( input ) != EMPCOVDATELEN )
ret = -1;
else if ( ! ( ( input[0] >= 'A' && input[0] <= 'Z' ) &&
( input[1] >= 'a' && input[1] <= 'z' ) &&
( input[2] >= 'a' && input[2] <= 'z' ) &&
( isspace ( input[3] ) ) &&
( input[4] >= '0' && input[4] <= '2' ) &&
( input[5] >= '0' && input[5] <= '9' ) &&
( input[6] == '-' ) &&
( input[7] >= '0' && input[7] <= '3' ) &&
( input[8] >= '0' && input[8] <= '9' ) &&
( input[9] == ',' ) &&
( isspace ( input[10] ) ) &&
( input[11] == '2' ) &&
( input[12] == '0' ) &&
( input[13] >= '0' && input[13] <= '1' ) &&
( input[14] >= '0' && input[14] <= '9' ) ) )
ret = -1;
else
ret = 0;
break;
default : printf ( "Invalid filter code.\n");
break;
}
return ret;
}
/*
Retrieve employee code from input stream.
*/
char * GetEmployeeCodeInput ( )
{
char buffer[BUFSIZ];
while ( TRUE )
{
printf ( "Enter Employee Code (AXX-XXXX): " );
fgets ( buffer, BUFSIZ, stdin );
buffer[0] = toupper ( buffer[0] );
if ( FilterInput ( buffer, EMPCODEINPUT ) < 0 )
{
printf ( "Invalid input.\n" );
continue;
}
return buffer;
}
}
/*
Get employee regular hours.
*/
void GetEmployeeRegularHours ( size_t index, size_t day )
{
char tmpbuf[BUFSIZ];
struct tm * tminfo;
double diff = 0.0;
while ( TRUE )
{
printf ( "Enter Time-in for %s (00:00): ", workdays[day] );
fgets ( tmpbuf, BUFSIZ, stdin );
if ( FilterInput ( tmpbuf, EMPTIMEINPUT ) < 0 )
{
printf ( "Invalid Time-in input format for %s.\n", workdays[day] );
continue;
}
/* Valid input format for time-in */
time ( &records[index].weeklytimerecord.dailytimerecord[day].regulartimein );
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[day].regulartimein );
/* We only need to invalidate the hour/min/sec */
tminfo->tm_hour = tminfo->tm_min = tminfo->tm_sec = 0;
/* If string other than newline was entered... */
if ( tmpbuf[0] != '\n' )
{
tminfo->tm_hour = atoi ( strtok ( tmpbuf, ":" ) );
tminfo->tm_min = atoi ( strtok ( NULL, ":" ) );
}
else /* ...else, make a dummy regular time in/out with zero hour/min/sec */
{
records[index].weeklytimerecord.dailytimerecord[day].regulartimein = mktime ( tminfo );
records[index].weeklytimerecord.dailytimerecord[day].regulartimeout = mktime ( tminfo );
return;
}
/* Valid regular time-in must be between 07:00 and 17:00 */
if ( tminfo->tm_hour < 7 || tminfo->tm_hour > 16 )
{
printf ( "Invalid Time-in for %s, hours must be between 07:00 - 16:00.\n", workdays[day] );
continue;
}
/* Latest start work hour must not exceed 16:00 */
if ( tminfo->tm_hour == 16 && tminfo->tm_min > 0 )
{
printf ( "Invalid Time-in for %s, latest work hour must be 16:00.\n", workdays[day] );
continue;
}
/*
Check if the employee came in late for work.
If so, find out how many hours late then record it.
*/
if ( tminfo->tm_hour > 8 )
{
records[index].weeklytimerecord.dailytimerecord[day].latehours = tminfo->tm_hour - 8;
}
/* If we arrived here then we have a valid regular time-in input */
records[index].weeklytimerecord.dailytimerecord[day].regulartimein = mktime ( tminfo );
/* Get regular time-out input */
while ( TRUE )
{
printf ( "Enter Time-out for %s (00:00): ", workdays[day] );
fgets ( tmpbuf, BUFSIZ, stdin );
if ( FilterInput ( tmpbuf, EMPTIMEINPUT ) < 0 )
{
printf ( "Invalid Time-out input format for %s.\n", workdays[day] );
continue;
}
/* Valid input format for regular time-out */
time ( &records[index].weeklytimerecord.dailytimerecord[day].regulartimeout );
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[day].regulartimeout );
tminfo->tm_hour = tminfo->tm_min = tminfo->tm_sec = 0;
if ( tmpbuf[0] != '\n' )
{
tminfo->tm_hour = atoi ( strtok ( tmpbuf, ":" ) );
tminfo->tm_min = atoi ( strtok ( NULL, ":" ) );
}
else
continue;
if ( tminfo->tm_hour > 17 )
{
printf ( "Time-out hour cannot be greater than 15:00.\n" );
continue;
}
/* If we arrived here then we have a valid regular time-out input */
records[index].weeklytimerecord.dailytimerecord[day].regulartimeout = mktime ( tminfo );
break;
}
/* Find the difference between time-out and time-in hours for this day */
diff = difftime ( records[index].weeklytimerecord.dailytimerecord[day].regulartimeout,
records[index].weeklytimerecord.dailytimerecord[day].regulartimein );
/*
If this employee worked from 08:00 - 17:00, we need to subtract lunch hour so
he/she will have a full 8 hours of work time.
*/
if ( diff > 28800 )
{
diff -= 3600;
}
/* Time-out hour cannot be less than Time-in */
if ( diff <= 0 )
{
printf ( "Time-out hour cannot be less than or equal to Time-in hour.\n" );
continue;
}
/* Difference between time-in and time-out must be at least one hour */
if ( diff - 3600 < 3600 )
{
printf ( "Difference between Time-in and Time-out must be greater than one hour.\n" );
continue;
}
/* The hours input is valid, get the total regular hours worked for this day */
records[index].weeklytimerecord.dailytimerecord[day].regularhoursworked = diff / 3600;
/* Check for late hours */
tminfo->tm_hour = 8; tminfo->tm_min = 0; tminfo->tm_sec = 0;
diff = difftime ( records[index].weeklytimerecord.dailytimerecord[day].regulartimein, mktime ( tminfo ) );
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[day].regulartimein );
if ( tminfo->tm_hour <= 0 )
records[index].weeklytimerecord.dailytimerecord[day].latehours = 0;
else
records[index].weeklytimerecord.dailytimerecord[day].latehours = tminfo->tm_hour - 8;
/* Check for undertime hours */
tminfo->tm_hour = 17; tminfo->tm_min = 0; tminfo->tm_sec = 0;
diff = difftime ( records[index].weeklytimerecord.dailytimerecord[day].regulartimeout, mktime ( tminfo ) );
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[day].regulartimeout );
if ( tminfo->tm_hour >= 17 )
records[index].weeklytimerecord.dailytimerecord[day].undertimehours = 0;
else
records[index].weeklytimerecord.dailytimerecord[day].undertimehours = 17 - tminfo->tm_hour;
/* Is this day a holiday */
GetHoliday ( index, day );
/*
If it is a holiday, make necessary adjustments by switching regular hours worked
and overtime hours worked. Note that this day will still show up as regular hours
in dtr.txt.
*/
if ( records[index].weeklytimerecord.dailytimerecord[day].holiday == 1 )
{
records[index].weeklytimerecord.dailytimerecord[day].overtimehoursworked
= records[index].weeklytimerecord.dailytimerecord[day].regularhoursworked;
records[index].weeklytimerecord.dailytimerecord[day].regularhoursworked = 0;
}
break;
}
}
/*
Get employee regular hours.
*/
void GetEmployeeOvertimeHours ( size_t index, size_t day )
{
char tmpbuf[BUFSIZ];
struct tm * tminfo;
double diff = 0.0;
/* If this day is a holiday just return since it is already overtime pay */
if ( records[index].weeklytimerecord.dailytimerecord[day].holiday == 1 )
{
time ( &records[index].weeklytimerecord.dailytimerecord[day].overtimein );
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[day].overtimein );
tminfo->tm_hour = tminfo->tm_min = tminfo->tm_sec = 0;
records[index].weeklytimerecord.dailytimerecord[day].overtimein = mktime ( tminfo );
records[index].weeklytimerecord.dailytimerecord[day].overtimeout = mktime ( tminfo );
return;
}
/* Make sure the employee worked regular hours today before we process his/her overtime */
if ( records[index].weeklytimerecord.dailytimerecord[day].regularhoursworked == 0 )
return;
while ( TRUE )
{
printf ( "Enter Overtime-in for %s (00:00): ", workdays[day] );
fgets ( tmpbuf, BUFSIZ, stdin );
if ( FilterInput ( tmpbuf, EMPTIMEINPUT ) < 0 )
{
printf ( "Invalid Overtime-in input format for %s.\n", workdays[day] );
continue;
}
/* Valid input format for overtime-in */
time ( &records[index].weeklytimerecord.dailytimerecord[day].overtimein );
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[day].overtimein );
/* We only need to invalidate the hour/min/sec */
tminfo->tm_hour = tminfo->tm_min = tminfo->tm_sec = 0;
/* If string other than newline was entered... */
if ( tmpbuf[0] != '\n' )
{
tminfo->tm_hour = atoi ( strtok ( tmpbuf, ":" ) );
tminfo->tm_min = atoi ( strtok ( NULL, ":" ) );
}
else /* ...else, make a dummy regular time in/out with zero hour/min/sec */
{
records[index].weeklytimerecord.dailytimerecord[day].overtimein = mktime ( tminfo );
records[index].weeklytimerecord.dailytimerecord[day].overtimeout = mktime ( tminfo );
return;
}
/* Valid overtime-in must begin at 17:30 */
if ( ! ( tminfo->tm_hour == 17 && tminfo->tm_min == 30 ) )
{
printf ( "Overtime-in must begin at 17:30.\n" );
continue;
}
/* If we arrived here then we have a valid overtime-in input */
records[index].weeklytimerecord.dailytimerecord[day].overtimein = mktime ( tminfo );
/* Get overtime-out input */
while ( TRUE )
{
printf ( "Enter Overtime-out for %s (00:00): ", workdays[day] );
fgets ( tmpbuf, BUFSIZ, stdin );
if ( FilterInput ( tmpbuf, EMPTIMEINPUT ) < 0 )
{
printf ( "Invalid Overtime-out input format for %s.\n", workdays[day] );
continue;
}
/* Valid input for overtime-out*/
time ( &records[index].weeklytimerecord.dailytimerecord[day].overtimeout );
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[day].overtimeout);
tminfo->tm_hour = tminfo->tm_min = tminfo->tm_sec = 0;
if ( tmpbuf[0] != '\n' )
{
tminfo->tm_hour = atoi ( strtok ( tmpbuf, ":" ) );
tminfo->tm_min = atoi ( strtok ( NULL, ":" ) );
}
if ( ! ( tminfo->tm_hour >= 18 && tminfo->tm_hour <= 20 ) )
{
printf ( "Overtime-out must be between 18:00 and 20:30.\n" );
continue;
}
if ( tminfo->tm_hour == 18 && tminfo->tm_min < 30 )
{
printf ( "Overtime-out must be between 18:30 and 20:30.\n" );
continue;
}
/* If we arrived here then we have a valid overtime-out input */
records[index].weeklytimerecord.dailytimerecord[day].overtimeout = mktime ( tminfo );
break;
}
/* Find the difference between overtime-out and overtime-in hours for this day */
diff = difftime ( records[index].weeklytimerecord.dailytimerecord[day].overtimeout,
records[index].weeklytimerecord.dailytimerecord[day].overtimein );
/* The hours input is valid, get the total overtime hours worked for this day */
records[index].weeklytimerecord.dailytimerecord[day].overtimehoursworked = diff / 3600;
break;
}
}
/*
Check if this day is a holiday.
*/
void GetHoliday ( size_t index, size_t day )
{
char buffer[BUFSIZ];
while ( TRUE )
{
printf ( "Is %s a holiday (y/n)?: ", workdays[day] );
fgets ( buffer, BUFSIZ, stdin );
buffer[0] = tolower ( buffer[0] );
if ( buffer[0] == 'y' )
records[index].weeklytimerecord.dailytimerecord[day].holiday = 1;
else if ( buffer[0] == 'n' )
records[index].weeklytimerecord.dailytimerecord[day].holiday = 0;
else
continue;
break;
}
}
/*
Get coverage date for this work week.
*/
void GetCoverageDate ( size_t index )
{
char buffer[BUFSIZ];
size_t i;
while ( TRUE )
{
printf ( "Coverage Date (Ex: Mar 05-09, 2012) : " );
memset ( buffer, 0, sizeof ( buffer ) );
fgets ( buffer, BUFSIZ, stdin );
buffer[0] = toupper ( buffer[0] );
if ( FilterInput ( buffer, EMPCOVDATEINPUT ) < 0 )
{
printf ( "Invalid coverage date format.\n" );
continue;
}
if ( buffer[7] == 3 && buffer[8] > 1 )
{
printf ( "Day cannot exceed 31.\n" );
continue;
}
for ( i = MONDAY; i <= FRIDAY; ++i )
strncpy ( records[index].weeklytimerecord.coveragedate, buffer, strlen ( buffer ) );
break;
}
}
/*
Display employee work and hours information.
*/
void DisplayRecords ( PrintInfo pi, size_t index, size_t code )
{
printf ( "\n******************************************************************************" );
printf ("\nEmployee Name: %s\nEmployee Code: %s\nSalary Level: %d\nSalary Rate: Php %.2f/day\n",
records[index].name, records[index].code, records[index].level, records[index].rate );
printf ( "******************************************************************************\n" );
if ( pi != EMPLOYEEINFO && code != -1 )
{
printf ( "Date Covered: %s\nTotal Number of Work Hours: %d Hrs.\nOvertime Hours: %d Hrs.\nRegular Income: Php %.2f\nOvertime Income: Php %.2f\nGross Income: Php %.2f\n",
records[index].weeklytimerecord.coveragedate, ( int ) records[index].weeklytimerecord.totalweeklyregularhoursworked,
( int ) records[index].weeklytimerecord.totalweeklyovertimehoursworked,
records[index].weeklytimerecord.regularincome, records[index].weeklytimerecord.overtimeincome,
records[index].weeklytimerecord.grossincome );
printf ( "Deductions:\n* Tax: Php %.2f\n* SSS: Php %.2f\nNet Income: %.2f\n",
records[index].weeklytimerecord.taxdeductions, records[index].weeklytimerecord.sssdeductions, records[index].weeklytimerecord.netincome );
printf ( "******************************************************************************\n\n" );
}
}
/*
Calculate weekly salary for this employee.
*/
void ComputeWeeklySalary ( size_t index )
{
double hourlyrate = records[index].rate / 8;
size_t i;
for ( i = MONDAY; i <= FRIDAY; ++i )
{
/*
If the regular hours worked for this day is less than 8, we need to offset it.
If we don't and there are late hours, those late hours are subtracted against
regular hours worked twice.
*/
if ( records[index].weeklytimerecord.dailytimerecord[i].regularhoursworked < 8 )
records[index].weeklytimerecord.dailytimerecord[i].regularhoursworked = 8;
/* Add all regular hours worked for this week */
records[index].weeklytimerecord.totalweeklyregularhoursworked
+= records[index].weeklytimerecord.dailytimerecord[i].regularhoursworked
- ( records[index].weeklytimerecord.dailytimerecord[i].latehours
+ records[index].weeklytimerecord.dailytimerecord[i].undertimehours );
/* Add all overtime hours worked for this week */
records[index].weeklytimerecord.totalweeklyovertimehoursworked
+= records[index].weeklytimerecord.dailytimerecord[i].overtimehoursworked;
}
/* Regular and Overtime income */
records[index].weeklytimerecord.regularincome
= hourlyrate
* ( int ) records[index].weeklytimerecord.totalweeklyregularhoursworked;
/*
NC4 COC2 (Procedural) - Reviewer.
For educational purposes only! Do not sell this code!
Disclaimer:
This source code is based on my interpretations of the specifications described in:
COMPUTER PROGRAMMING NC IV (COC 2 DEVELOP APPLICATIONS USING PROCEDURAL – PROGRAMMING LANGUAGE).
However, I do not guarantee the correctness of this code.
Your can freely distribute this as long as proper credit is given to the author.
ezroot - 6/19/2012
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <errno.h>
/* Needs gcc or MSVC */
#if defined ( __GNUC__ ) || ( _MSC_VER )
# if defined ( _MSC_VER ) && ( _MSC_VER >= 1020 )
# pragma warning ( disable : 4996 )
# pragma warning ( disable : 4172 )
# endif
#ifndef BUFSIZ
#define BUFSIZ 512
#endif
#ifndef NULL
#define NULL 0
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#define MAXREC 10
#define MAXWORKDAYS 5
const float SALARYLEVEL1 = 380.00;
const float SALARYLEVEL2 = 450.00;
const float SALARYLEVEL3 = 550.00;
const float WEEKLYALLOWANCE = 500.00;
/* Nested structs to hold employee data */
typedef struct _DAILYTIMERECORD
{
double regularhoursworked;
time_t regulartimein;
time_t regulartimeout;
double overtimehoursworked;
time_t overtimein;
time_t overtimeout;
double latehours;
double undertimehours;
size_t holiday;
} DAILYTIMERECORD;
typedef struct _WEEKLYTIMERECORD
{
char coveragedate[BUFSIZ];
double regularincome;
double overtimeincome;
double grossincome;
double netincome;
double taxdeductions;
double sssdeductions;
double totalweeklyregularhoursworked;
double totalweeklyovertimehoursworked;
DAILYTIMERECORD dailytimerecord[MAXWORKDAYS];
} WEEKLYTIMERECORD;
typedef struct _EMPLOYEERECORD
{
char code[BUFSIZ];
char name[BUFSIZ];
size_t level;
double rate;
WEEKLYTIMERECORD weeklytimerecord;
} EMPLOYEERECORD;
/****************************************/
/* Employee Records Container. Can hold maximum of MAXREC records */
static EMPLOYEERECORD records[MAXREC] = { 0 };
static char * workdays[MAXWORKDAYS] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" };
typedef enum _InputFilter { EMPCODEINPUT, EMPTIMEINPUT, EMPCOVDATEINPUT } InputFilter;
typedef enum _WorkDay { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY } WorkDay;
typedef enum _PrintInfo { EMPLOYEEINFO, EMPLOYEEHOURS } PrintInfo;
//*********************** Function Prototypes *************************//
int ReadEmployeeRecords( const char * );
int WriteEmployeeTimeRecords ( char *, size_t );
int FindEmployeeRecord ( const char * );
int FilterInput ( char *, InputFilter );
char * GetEmployeeCodeInput ( );
void GetEmployeeRegularHours ( size_t, size_t );
void GetEmployeeOvertimeHours ( size_t, size_t );
void GetHoliday ( size_t, size_t );
void GetCoverageDate ( size_t );
void ComputeWeeklySalary ( size_t );
void DisplayRecords ( PrintInfo, size_t, size_t );
int RunApp ( );
void ResetRecords ( size_t );
//*********************************************************************//
/* Main entry */
int main ( int argc, char ** argv )
{
if ( RunApp () < 0 )
exit ( EXIT_FAILURE );
return 0;
}
/*
Read records from the file pointed to by filein.
*/
int ReadEmployeeRecords( const char * filein )
{
FILE * pfile;
char * linebuffer;
char * pch;
const char * delim = ":";
size_t index = 0;
pfile = fopen ( filein, "r" );
if ( pfile == NULL )
{
printf ( "Error opening file %s: %s\n", filein, strerror ( errno ) );
return -1;
}
linebuffer = ( char * ) malloc ( sizeof ( char ) * BUFSIZ );
if ( linebuffer == NULL )
{
fclose ( pfile );
printf ( "Error allocating memory space.\n" );
return -1;
}
while ( fgets ( linebuffer, BUFSIZ, pfile ) )
{
if ( index == MAXREC )
{
/* printf ( "Maximum number of %d records allowed in records container has been reached.\n", MAXREC ); */
free ( linebuffer );
fclose ( pfile );
return 0;
}
if ( ferror ( pfile ) != 0 )
{
printf ( "Error reading from input file %s: %s\n",
filein, strerror ( errno ) );
free ( linebuffer );
fclose ( pfile );
return -1;
}
if ( linebuffer[0] == '#' || linebuffer[0] == '\n' )
continue;
linebuffer[strlen ( linebuffer ) - 1] = '\0';
pch = strtok ( linebuffer, delim );
memcpy (records[index].code, pch, strlen ( pch ) );
records[index].code[strlen ( pch ) ] = '\0';
pch = strtok ( NULL, delim );
memcpy (records[index].name, pch, strlen ( pch ) );
records[index].name[strlen ( pch ) ] = '\0';
pch = strtok ( NULL, delim );
sscanf ( pch, "%d", &records[index].level );
if ( records[index].level == 1 )
records[index].rate = SALARYLEVEL1;
else if ( records[index].level == 2 )
records[index].rate = SALARYLEVEL2;
else if ( records[index].level == 3 )
records[index].rate = SALARYLEVEL3;
++index;
}
free ( linebuffer );
return 0;
}
/*
Write records to dtr.txt.
*/
int WriteEmployeeTimeRecords ( char * fileout, size_t index )
{
FILE * pfile;
int ret = -1;
struct tm * tminfo;
char buffer[BUFSIZ];
size_t i;
pfile = fopen ( fileout, "a" );
if ( pfile == NULL )
{
printf ( "Error opening file %s: %s\n", fileout, strerror ( errno ) );
return ret;
}
fprintf ( pfile, "%s|", records[index].code );
for ( i = MONDAY; i <= FRIDAY; ++i )
{
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[i].regulartimein );
strftime ( buffer, BUFSIZ, "%H:%M", tminfo );
if ( fprintf ( pfile, "%s|", buffer ) < 0 )
break;
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[i].regulartimeout );
strftime ( buffer, BUFSIZ, "%H:%M", tminfo );
if ( fprintf ( pfile, "%s|", buffer ) < 0 )
break;
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[i].overtimein );
strftime ( buffer, BUFSIZ, "%H:%M", tminfo );
if ( fprintf ( pfile, "%s|", buffer ) < 0 )
break;
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[i].overtimeout );
strftime ( buffer, BUFSIZ, "%H:%M", tminfo );
if ( i == FRIDAY )
{
if ( fprintf ( pfile, "%s\n", buffer ) < 0 )
break;
}
else
{
if ( fprintf ( pfile, "%s|", buffer ) < 0 )
break;
}
ret = 0;
}
fclose ( pfile );
return ret;
}
/*
Attempt to locate a matching string defined by pointer to parameter rec.
*/
int FindEmployeeRecord ( const char * rec )
{
char * pch;
int i, found = -1;
if ( rec == NULL )
return -1;
for ( i = 0; i < MAXREC; ++i )
{
pch = strstr ( records[i].code, rec );
if ( pch != NULL )
{
found = i;
break;
}
}
return found;
}
/*
Check the format of the string input.
*/
int FilterInput ( char * input, InputFilter filter )
{
const int EMPCODEMAXLEN = 8;
const int EMPTIMEINPUTLEN = 5;
const int EMPCOVDATELEN = 15;
int ret = -1;
if ( input[0] == '\n' )
{
ret = 0;
return ret;
}
input[ strlen ( input ) - 1 ] = '\0';
switch ( filter )
{
case EMPCODEINPUT : if ( strlen ( input ) != EMPCODEMAXLEN )
ret = -1;
else if ( ! ( ( input[0] == 'A' && input[3] == '-' ) &&
( input[1] >= '0' && input[1] <= '9' ) &&
( input[2] >= '0' && input[2] <= '9' ) &&
( input[4] >= '0' && input[4] <= '9' ) &&
( input[5] >= '0' && input[5] <= '9' ) &&
( input[6] >= '0' && input[6] <= '9' ) &&
( input[7] >= '0' && input[7] <= '9' ) ) )
ret = -1;
else
ret = 0;
break;
case EMPTIMEINPUT : if ( strlen ( input ) != EMPTIMEINPUTLEN )
ret = -1;
else if ( ! ( ( input[0] >= '0' && input[0] <= '2' ) &&
( input[1] >= '0' && input[1] <= '9' ) &&
( input[2] == ':' ) &&
( input[3] >= '0' && input[3] <= '5' ) &&
( input[4] >= '0' && input[3] <= '9' ) ) )
ret = -1;
else
ret = 0;
break;
case EMPCOVDATEINPUT : if ( strlen ( input ) != EMPCOVDATELEN )
ret = -1;
else if ( ! ( ( input[0] >= 'A' && input[0] <= 'Z' ) &&
( input[1] >= 'a' && input[1] <= 'z' ) &&
( input[2] >= 'a' && input[2] <= 'z' ) &&
( isspace ( input[3] ) ) &&
( input[4] >= '0' && input[4] <= '2' ) &&
( input[5] >= '0' && input[5] <= '9' ) &&
( input[6] == '-' ) &&
( input[7] >= '0' && input[7] <= '3' ) &&
( input[8] >= '0' && input[8] <= '9' ) &&
( input[9] == ',' ) &&
( isspace ( input[10] ) ) &&
( input[11] == '2' ) &&
( input[12] == '0' ) &&
( input[13] >= '0' && input[13] <= '1' ) &&
( input[14] >= '0' && input[14] <= '9' ) ) )
ret = -1;
else
ret = 0;
break;
default : printf ( "Invalid filter code.\n");
break;
}
return ret;
}
/*
Retrieve employee code from input stream.
*/
char * GetEmployeeCodeInput ( )
{
char buffer[BUFSIZ];
while ( TRUE )
{
printf ( "Enter Employee Code (AXX-XXXX): " );
fgets ( buffer, BUFSIZ, stdin );
buffer[0] = toupper ( buffer[0] );
if ( FilterInput ( buffer, EMPCODEINPUT ) < 0 )
{
printf ( "Invalid input.\n" );
continue;
}
return buffer;
}
}
/*
Get employee regular hours.
*/
void GetEmployeeRegularHours ( size_t index, size_t day )
{
char tmpbuf[BUFSIZ];
struct tm * tminfo;
double diff = 0.0;
while ( TRUE )
{
printf ( "Enter Time-in for %s (00:00): ", workdays[day] );
fgets ( tmpbuf, BUFSIZ, stdin );
if ( FilterInput ( tmpbuf, EMPTIMEINPUT ) < 0 )
{
printf ( "Invalid Time-in input format for %s.\n", workdays[day] );
continue;
}
/* Valid input format for time-in */
time ( &records[index].weeklytimerecord.dailytimerecord[day].regulartimein );
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[day].regulartimein );
/* We only need to invalidate the hour/min/sec */
tminfo->tm_hour = tminfo->tm_min = tminfo->tm_sec = 0;
/* If string other than newline was entered... */
if ( tmpbuf[0] != '\n' )
{
tminfo->tm_hour = atoi ( strtok ( tmpbuf, ":" ) );
tminfo->tm_min = atoi ( strtok ( NULL, ":" ) );
}
else /* ...else, make a dummy regular time in/out with zero hour/min/sec */
{
records[index].weeklytimerecord.dailytimerecord[day].regulartimein = mktime ( tminfo );
records[index].weeklytimerecord.dailytimerecord[day].regulartimeout = mktime ( tminfo );
return;
}
/* Valid regular time-in must be between 07:00 and 17:00 */
if ( tminfo->tm_hour < 7 || tminfo->tm_hour > 16 )
{
printf ( "Invalid Time-in for %s, hours must be between 07:00 - 16:00.\n", workdays[day] );
continue;
}
/* Latest start work hour must not exceed 16:00 */
if ( tminfo->tm_hour == 16 && tminfo->tm_min > 0 )
{
printf ( "Invalid Time-in for %s, latest work hour must be 16:00.\n", workdays[day] );
continue;
}
/*
Check if the employee came in late for work.
If so, find out how many hours late then record it.
*/
if ( tminfo->tm_hour > 8 )
{
records[index].weeklytimerecord.dailytimerecord[day].latehours = tminfo->tm_hour - 8;
}
/* If we arrived here then we have a valid regular time-in input */
records[index].weeklytimerecord.dailytimerecord[day].regulartimein = mktime ( tminfo );
/* Get regular time-out input */
while ( TRUE )
{
printf ( "Enter Time-out for %s (00:00): ", workdays[day] );
fgets ( tmpbuf, BUFSIZ, stdin );
if ( FilterInput ( tmpbuf, EMPTIMEINPUT ) < 0 )
{
printf ( "Invalid Time-out input format for %s.\n", workdays[day] );
continue;
}
/* Valid input format for regular time-out */
time ( &records[index].weeklytimerecord.dailytimerecord[day].regulartimeout );
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[day].regulartimeout );
tminfo->tm_hour = tminfo->tm_min = tminfo->tm_sec = 0;
if ( tmpbuf[0] != '\n' )
{
tminfo->tm_hour = atoi ( strtok ( tmpbuf, ":" ) );
tminfo->tm_min = atoi ( strtok ( NULL, ":" ) );
}
else
continue;
if ( tminfo->tm_hour > 17 )
{
printf ( "Time-out hour cannot be greater than 15:00.\n" );
continue;
}
/* If we arrived here then we have a valid regular time-out input */
records[index].weeklytimerecord.dailytimerecord[day].regulartimeout = mktime ( tminfo );
break;
}
/* Find the difference between time-out and time-in hours for this day */
diff = difftime ( records[index].weeklytimerecord.dailytimerecord[day].regulartimeout,
records[index].weeklytimerecord.dailytimerecord[day].regulartimein );
/*
If this employee worked from 08:00 - 17:00, we need to subtract lunch hour so
he/she will have a full 8 hours of work time.
*/
if ( diff > 28800 )
{
diff -= 3600;
}
/* Time-out hour cannot be less than Time-in */
if ( diff <= 0 )
{
printf ( "Time-out hour cannot be less than or equal to Time-in hour.\n" );
continue;
}
/* Difference between time-in and time-out must be at least one hour */
if ( diff - 3600 < 3600 )
{
printf ( "Difference between Time-in and Time-out must be greater than one hour.\n" );
continue;
}
/* The hours input is valid, get the total regular hours worked for this day */
records[index].weeklytimerecord.dailytimerecord[day].regularhoursworked = diff / 3600;
/* Check for late hours */
tminfo->tm_hour = 8; tminfo->tm_min = 0; tminfo->tm_sec = 0;
diff = difftime ( records[index].weeklytimerecord.dailytimerecord[day].regulartimein, mktime ( tminfo ) );
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[day].regulartimein );
if ( tminfo->tm_hour <= 0 )
records[index].weeklytimerecord.dailytimerecord[day].latehours = 0;
else
records[index].weeklytimerecord.dailytimerecord[day].latehours = tminfo->tm_hour - 8;
/* Check for undertime hours */
tminfo->tm_hour = 17; tminfo->tm_min = 0; tminfo->tm_sec = 0;
diff = difftime ( records[index].weeklytimerecord.dailytimerecord[day].regulartimeout, mktime ( tminfo ) );
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[day].regulartimeout );
if ( tminfo->tm_hour >= 17 )
records[index].weeklytimerecord.dailytimerecord[day].undertimehours = 0;
else
records[index].weeklytimerecord.dailytimerecord[day].undertimehours = 17 - tminfo->tm_hour;
/* Is this day a holiday */
GetHoliday ( index, day );
/*
If it is a holiday, make necessary adjustments by switching regular hours worked
and overtime hours worked. Note that this day will still show up as regular hours
in dtr.txt.
*/
if ( records[index].weeklytimerecord.dailytimerecord[day].holiday == 1 )
{
records[index].weeklytimerecord.dailytimerecord[day].overtimehoursworked
= records[index].weeklytimerecord.dailytimerecord[day].regularhoursworked;
records[index].weeklytimerecord.dailytimerecord[day].regularhoursworked = 0;
}
break;
}
}
/*
Get employee regular hours.
*/
void GetEmployeeOvertimeHours ( size_t index, size_t day )
{
char tmpbuf[BUFSIZ];
struct tm * tminfo;
double diff = 0.0;
/* If this day is a holiday just return since it is already overtime pay */
if ( records[index].weeklytimerecord.dailytimerecord[day].holiday == 1 )
{
time ( &records[index].weeklytimerecord.dailytimerecord[day].overtimein );
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[day].overtimein );
tminfo->tm_hour = tminfo->tm_min = tminfo->tm_sec = 0;
records[index].weeklytimerecord.dailytimerecord[day].overtimein = mktime ( tminfo );
records[index].weeklytimerecord.dailytimerecord[day].overtimeout = mktime ( tminfo );
return;
}
/* Make sure the employee worked regular hours today before we process his/her overtime */
if ( records[index].weeklytimerecord.dailytimerecord[day].regularhoursworked == 0 )
return;
while ( TRUE )
{
printf ( "Enter Overtime-in for %s (00:00): ", workdays[day] );
fgets ( tmpbuf, BUFSIZ, stdin );
if ( FilterInput ( tmpbuf, EMPTIMEINPUT ) < 0 )
{
printf ( "Invalid Overtime-in input format for %s.\n", workdays[day] );
continue;
}
/* Valid input format for overtime-in */
time ( &records[index].weeklytimerecord.dailytimerecord[day].overtimein );
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[day].overtimein );
/* We only need to invalidate the hour/min/sec */
tminfo->tm_hour = tminfo->tm_min = tminfo->tm_sec = 0;
/* If string other than newline was entered... */
if ( tmpbuf[0] != '\n' )
{
tminfo->tm_hour = atoi ( strtok ( tmpbuf, ":" ) );
tminfo->tm_min = atoi ( strtok ( NULL, ":" ) );
}
else /* ...else, make a dummy regular time in/out with zero hour/min/sec */
{
records[index].weeklytimerecord.dailytimerecord[day].overtimein = mktime ( tminfo );
records[index].weeklytimerecord.dailytimerecord[day].overtimeout = mktime ( tminfo );
return;
}
/* Valid overtime-in must begin at 17:30 */
if ( ! ( tminfo->tm_hour == 17 && tminfo->tm_min == 30 ) )
{
printf ( "Overtime-in must begin at 17:30.\n" );
continue;
}
/* If we arrived here then we have a valid overtime-in input */
records[index].weeklytimerecord.dailytimerecord[day].overtimein = mktime ( tminfo );
/* Get overtime-out input */
while ( TRUE )
{
printf ( "Enter Overtime-out for %s (00:00): ", workdays[day] );
fgets ( tmpbuf, BUFSIZ, stdin );
if ( FilterInput ( tmpbuf, EMPTIMEINPUT ) < 0 )
{
printf ( "Invalid Overtime-out input format for %s.\n", workdays[day] );
continue;
}
/* Valid input for overtime-out*/
time ( &records[index].weeklytimerecord.dailytimerecord[day].overtimeout );
tminfo = localtime ( &records[index].weeklytimerecord.dailytimerecord[day].overtimeout);
tminfo->tm_hour = tminfo->tm_min = tminfo->tm_sec = 0;
if ( tmpbuf[0] != '\n' )
{
tminfo->tm_hour = atoi ( strtok ( tmpbuf, ":" ) );
tminfo->tm_min = atoi ( strtok ( NULL, ":" ) );
}
if ( ! ( tminfo->tm_hour >= 18 && tminfo->tm_hour <= 20 ) )
{
printf ( "Overtime-out must be between 18:00 and 20:30.\n" );
continue;
}
if ( tminfo->tm_hour == 18 && tminfo->tm_min < 30 )
{
printf ( "Overtime-out must be between 18:30 and 20:30.\n" );
continue;
}
/* If we arrived here then we have a valid overtime-out input */
records[index].weeklytimerecord.dailytimerecord[day].overtimeout = mktime ( tminfo );
break;
}
/* Find the difference between overtime-out and overtime-in hours for this day */
diff = difftime ( records[index].weeklytimerecord.dailytimerecord[day].overtimeout,
records[index].weeklytimerecord.dailytimerecord[day].overtimein );
/* The hours input is valid, get the total overtime hours worked for this day */
records[index].weeklytimerecord.dailytimerecord[day].overtimehoursworked = diff / 3600;
break;
}
}
/*
Check if this day is a holiday.
*/
void GetHoliday ( size_t index, size_t day )
{
char buffer[BUFSIZ];
while ( TRUE )
{
printf ( "Is %s a holiday (y/n)?: ", workdays[day] );
fgets ( buffer, BUFSIZ, stdin );
buffer[0] = tolower ( buffer[0] );
if ( buffer[0] == 'y' )
records[index].weeklytimerecord.dailytimerecord[day].holiday = 1;
else if ( buffer[0] == 'n' )
records[index].weeklytimerecord.dailytimerecord[day].holiday = 0;
else
continue;
break;
}
}
/*
Get coverage date for this work week.
*/
void GetCoverageDate ( size_t index )
{
char buffer[BUFSIZ];
size_t i;
while ( TRUE )
{
printf ( "Coverage Date (Ex: Mar 05-09, 2012) : " );
memset ( buffer, 0, sizeof ( buffer ) );
fgets ( buffer, BUFSIZ, stdin );
buffer[0] = toupper ( buffer[0] );
if ( FilterInput ( buffer, EMPCOVDATEINPUT ) < 0 )
{
printf ( "Invalid coverage date format.\n" );
continue;
}
if ( buffer[7] == 3 && buffer[8] > 1 )
{
printf ( "Day cannot exceed 31.\n" );
continue;
}
for ( i = MONDAY; i <= FRIDAY; ++i )
strncpy ( records[index].weeklytimerecord.coveragedate, buffer, strlen ( buffer ) );
break;
}
}
/*
Display employee work and hours information.
*/
void DisplayRecords ( PrintInfo pi, size_t index, size_t code )
{
printf ( "\n******************************************************************************" );
printf ("\nEmployee Name: %s\nEmployee Code: %s\nSalary Level: %d\nSalary Rate: Php %.2f/day\n",
records[index].name, records[index].code, records[index].level, records[index].rate );
printf ( "******************************************************************************\n" );
if ( pi != EMPLOYEEINFO && code != -1 )
{
printf ( "Date Covered: %s\nTotal Number of Work Hours: %d Hrs.\nOvertime Hours: %d Hrs.\nRegular Income: Php %.2f\nOvertime Income: Php %.2f\nGross Income: Php %.2f\n",
records[index].weeklytimerecord.coveragedate, ( int ) records[index].weeklytimerecord.totalweeklyregularhoursworked,
( int ) records[index].weeklytimerecord.totalweeklyovertimehoursworked,
records[index].weeklytimerecord.regularincome, records[index].weeklytimerecord.overtimeincome,
records[index].weeklytimerecord.grossincome );
printf ( "Deductions:\n* Tax: Php %.2f\n* SSS: Php %.2f\nNet Income: %.2f\n",
records[index].weeklytimerecord.taxdeductions, records[index].weeklytimerecord.sssdeductions, records[index].weeklytimerecord.netincome );
printf ( "******************************************************************************\n\n" );
}
}
/*
Calculate weekly salary for this employee.
*/
void ComputeWeeklySalary ( size_t index )
{
double hourlyrate = records[index].rate / 8;
size_t i;
for ( i = MONDAY; i <= FRIDAY; ++i )
{
/*
If the regular hours worked for this day is less than 8, we need to offset it.
If we don't and there are late hours, those late hours are subtracted against
regular hours worked twice.
*/
if ( records[index].weeklytimerecord.dailytimerecord[i].regularhoursworked < 8 )
records[index].weeklytimerecord.dailytimerecord[i].regularhoursworked = 8;
/* Add all regular hours worked for this week */
records[index].weeklytimerecord.totalweeklyregularhoursworked
+= records[index].weeklytimerecord.dailytimerecord[i].regularhoursworked
- ( records[index].weeklytimerecord.dailytimerecord[i].latehours
+ records[index].weeklytimerecord.dailytimerecord[i].undertimehours );
/* Add all overtime hours worked for this week */
records[index].weeklytimerecord.totalweeklyovertimehoursworked
+= records[index].weeklytimerecord.dailytimerecord[i].overtimehoursworked;
}
/* Regular and Overtime income */
records[index].weeklytimerecord.regularincome
= hourlyrate
* ( int ) records[index].weeklytimerecord.totalweeklyregularhoursworked;
records[index].weeklytimerecord.overtimeincome
= hourlyrate
* 1.1
* ( int ) records[index].weeklytimerecord.totalweeklyovertimehoursworked;
/* Gross income */
records[index].weeklytimerecord.grossincome
= records[index].weeklytimerecord.regularincome
+ records[index].weeklytimerecord.overtimeincome;
/* Tax */
records[index].weeklytimerecord.taxdeductions
= records[index].weeklytimerecord.grossincome
* 0.1;
/* SSS/GSIS */
if ( records[index].level == 1 )
records[index].weeklytimerecord.sssdeductions
= records[index].rate
* 0.010;
else if ( records[index].level == 2 )
records[index].weeklytimerecord.sssdeductions
= records[index].rate
* 0.015;
else if ( records[index].level == 3 )
records[index].weeklytimerecord.sssdeductions
= records[index].rate
* 0.020;
/* Net income */
records[index].weeklytimerecord.netincome
= ( records[index].weeklytimerecord.grossincome
- ( records[index].weeklytimerecord.taxdeductions
+ records[index].weeklytimerecord.sssdeductions ) )
+ WEEKLYALLOWANCE;
}
/*
Program runner.
*/
int RunApp ( )
{
char * filein = "employee.txt";
char * fileout = "dtr.txt";
char * tmpbuf;
char buffer[BUFSIZ];
size_t day;
int index;
printf ( "Tesda NC IV Reviewer\n\n");
if ( ReadEmployeeRecords ( filein ) < 0 )
exit ( EXIT_FAILURE );
while ( TRUE )
{
tmpbuf = GetEmployeeCodeInput ( );
index = FindEmployeeRecord ( tmpbuf );
if ( index < 0 )
{
printf ( "Employee code not found.\n" );
continue;
}
DisplayRecords ( EMPLOYEEINFO, index, -1 );
for ( day = MONDAY; day < MAXWORKDAYS; ++day )
{
GetEmployeeRegularHours ( index, day );
GetEmployeeOvertimeHours ( index, day );
}
GetCoverageDate ( index );
ComputeWeeklySalary ( index );
DisplayRecords ( EMPLOYEEHOURS, index, 0 );
if ( WriteEmployeeTimeRecords ( fileout, index ) < 0 )
exit ( EXIT_FAILURE );
printf ( "Continue (y/n)?: " );
fgets ( buffer, BUFSIZ, stdin );
if ( toupper ( buffer[0] ) == 'Y' )
{
ResetRecords ( index );
continue;
}
break;
}
return 0;
}
/* Reset Time Records */
void ResetRecords ( size_t index )
{
size_t i;
strncpy ( records[index].weeklytimerecord.coveragedate, "", 0 );
records[index].weeklytimerecord.regularincome =
records[index].weeklytimerecord.overtimeincome =
records[index].weeklytimerecord.grossincome =
records[index].weeklytimerecord.netincome =
records[index].weeklytimerecord.taxdeductions =
records[index].weeklytimerecord.sssdeductions =
records[index].weeklytimerecord.totalweeklyregularhoursworked =
records[index].weeklytimerecord.totalweeklyovertimehoursworked = 0;
for ( i = MONDAY; i <= FRIDAY; ++i )
{
records[index].weeklytimerecord.dailytimerecord[i].regularhoursworked =
records[index].weeklytimerecord.dailytimerecord[i].overtimehoursworked =
records[index].weeklytimerecord.dailytimerecord[i].latehours =
records[index].weeklytimerecord.dailytimerecord[i].undertimehours = 0;
records[index].weeklytimerecord.dailytimerecord[i].regulartimein =
records[index].weeklytimerecord.dailytimerecord[i].regulartimeout =
records[index].weeklytimerecord.dailytimerecord[i].overtimein =
records[index].weeklytimerecord.dailytimerecord[i].overtimeout = 0;
}
records[index].weeklytimerecord.dailytimerecord[i].holiday = 0;
}
#else
#error "You need MSVC or GCC compiler!"
#endif
thank you.. hope you can help me.