#ifdef	ournix
#include "ournix.h"
#endif
char sccsID[] = "@(#) timesheet3.c V3.1 Copyright Julian H. Stacey 1988-2009" ;

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define GRIPE gripe(start_hour, start_minute, stop_hour, stop_minute)

char	**ARGV ;
int	ARGC ;
char time_hr_min[] = " Hour:Minute\t\t\t";
unsigned	line_u = 1 ;			/* report bad data. */

#if 1
	/* Warning: I found what might have been an over run problem
	 * with timesheet3 -pgj@
	 *  But it seems to have gone away.
	 * I avoided it here by this cludge, but 
	 * the whole program needs a good read, & more checking. 
	 */
#define	HUNDRED	400
#define	TWENTY	40
#else
#define	HUNDRED	100
#define	TWENTY	20
#endif

char rec_line[HUNDRED];
char date_line[HUNDRED];
char rate_line[HUNDRED];
char job_line[HUNDRED];
char who_line[HUNDRED];
char where_s[TWENTY] ;
char who_s[TWENTY] ;
char day_in_week_s[TWENTY];
char time_in_day_s[TWENTY];
char job_description[HUNDRED];
char day_description[HUNDRED];
char who_description[HUNDRED];
char person[HUNDRED]="\0" ;
// char person[HUNDRED] ="\0" ; later in mailn param
#define	JOB_LN	HUNDRED
#define	DAY_LN	HUNDRED
#define	WHO_LN	HUNDRED
unsigned job_ln ;
unsigned day_ln ;
unsigned who_ln ;
	int	start_hour  ;		/* start hour */
	int	start_minute  ;		/* start minute */
	int	stop_hour  ;		/* stop hour */
	int	stop_minute  ;		/* stop minute */

struct rate_s { char *text ; float factor ; } rate_a[] =
	{	/* Pay Rates depending on work, time of day & day in week */
#include "rates.h"
	"",		0.0
	} ;

float	get_rate2(str_p )
	char *str_p;
	{
	struct rate_s	*rate_p ;

	if (0)	{
		printf("get_rate2 in: |%s|\n", str_p );
		printf("get_rate2 00 %d %d %d\n",
			sizeof(char *),
			sizeof(float ),
			sizeof(struct rate_s ) );
		(void) fflush(stdout);
		}

	rate_p = &rate_a[0]	;
	while (1)
		{
		// printf("get_rate2 11:\n");
		// (void) fflush(stdout);
		// printf("get_rate2 22 %s %f:\n",rate_p->text,rate_p->factor);
		if ((rate_p->factor == 0.0 ) ||
		    (*(rate_p->text) == '\0' ) )
			{
			fprintf(stderr,"Illegal rate %s", str_p); 
			GRIPE ;
			}
		if (!strcmp(str_p,rate_p->text))
			{
			printf("%s=%f, ", rate_p->text,  rate_p->factor);
			(void) fflush(stdout);
			return ( rate_p->factor) ;
			}
		rate_p ++ ;
		} ;
	}

float	get_rate1(where_p, day_in_week_p, time_in_day_p )
	char *where_p, *day_in_week_p, *time_in_day_p  ;
	{
	// printf("\nget_rate1: %s %s %s\n", where_p, day_in_week_p, time_in_day_p);
	(void) fflush(stdout);
	return ( get_rate2(where_p) * get_rate2(day_in_week_p) *
		get_rate2(time_in_day_p) ) ;
	}

main(argc, argv)
	int argc ; char **argv ;
	{
	/* Input */
	int	break_minutes  ;		/* lunch & other breaks, in minutes */

	/* Internal calculations */
	long		start_l, stop_l, tmp_l ;	/* temporaries */
	int		silent = 1 ;

	float		factor_numeric ;

	int	session_hours_flat = 0 ;	/* hours that session */
	int	session_minutes_flat = 0 ;	/* minutes that day */
	int	cumulative_hours_flat = 0 ;	/* hours total */
	int	cumulative_minutes_flat = 0 ;	/* minutes total */

	/* Factored hours & mins eg Night rate may be = 1.5 */
	float	session_minutes_factored ;	/* hours that session */
	float	cumulative_minutes_factored = 0.0 ;	/* hours total */
	/* To avoid cumulative floating divide error, do not keep
		the total in hours, but minutes, & just convert minutes to
		hours on output. */
	char *job_p ;
	char *day_p ;
	char *who_p ;
	char *xx_p ;
	int ch_i ;

	/* ---- */
	// ARGV = argv ;
	// ARGC= argc ;
#ifdef	VSL	/* { */
#include	"../../include/vsl.h"
#endif		/* } */
	// Process arguments.
	// Note This does not take multiple file, but a single stdin.
	while ( --argc )
		{
		if (**++argv == '-')
			switch ((*argv)[1])
				{
				case 'p':	/* person */
					if ( !--argc || ( *++argv == '\0' ) )
						syntax() ;
					strcpy(person,*argv) ;
					break;
				default:
					fprintf(stderr,
						"Unknown option - ignored\n");
					break;
				}
			else syntax() ;
		}
	if (!silent)
		{
		// Syntax complex, exemplified by example in "data".
		// Extra hints:
		printf(
		 "Hints:\tOvernight session:\t\tStart 21:00,\tEnd 26:00\n");
		printf(
		 "\t\tInclude previous total:\t\tStart 0:0,\tEnd 52:30\n");
		printf(
		 "\t\tDeduct mistake:\t\t\tLunch -80\n\n");
		}
	// Take input from stdin pipe.
	do	{
		/* Zero them in case we report a syntax error while they
		   would otherwise have random or old values */
		start_hour = start_minute = stop_hour = stop_minute
			= break_minutes = 0 ;
		rec_line[0] = date_line[0] = rate_line[0] =
		job_line[0] = who_line[0] = '\0' ;
	/* -- Look for ^@Rec */
		if ((scanf("%s", rec_line) < 1) ||
			 strncmp("@Rec",  rec_line, strlen("@Rec"))) GRIPE ;
		line_u++ ;

	/* -- Look for ^@Day multi word line (usually Date Day) */
		if ((scanf("%s", &date_line ) < 1 ) ||
			 strncmp("@Day", date_line, strlen("@Day"))) GRIPE ;
		/* Swallow space before date & day */
		while (1)
			{
			if ((ch_i = getchar() ) == EOF ) GRIPE ;
			if (( (char)ch_i != ' ') &&
				( (char)ch_i != '\t')) break ;
			}
		/* Swallow rest of date line */
		day_p = day_description ; day_ln = DAY_LN ;
		while	(( (char)ch_i != '\n') && ( (char)ch_i != '\0') &&
				--day_ln )
			{
			*day_p++ = (char)ch_i ;
			if ((ch_i = getchar() ) == EOF ) GRIPE ;
			}
		*day_p = '\0';
		line_u++ ;

	/* -- Look for ^@Who single word */
		if ((scanf("%s", &who_line ) < 1 ) ||
			 strncmp("@Who", who_line, strlen("@Who"))) GRIPE ;
		/* Swallow space before persons initials */
		while (1)
			{
			if ((ch_i = getchar() ) == EOF ) GRIPE ;
			if (( (char)ch_i != ' ') &&
				( (char)ch_i != '\t')) break ;
			}
		/* Swallow rest of who line */
		who_p = who_description ; who_ln = WHO_LN ;
		while	(( (char)ch_i != '\n') && ( (char)ch_i != '\0') &&
				--who_ln )
			{
			*who_p++ = (char)ch_i ;
			if ((ch_i = getchar() ) == EOF ) GRIPE ;
			}
		*who_p = '\0';
		/* Strip any trailing space or words */
		for ( xx_p = who_description ;
			(*xx_p != ' ' ) && (*xx_p != '\t' ) &&
				(*xx_p != '\0' ) ;
			xx_p++ ) ;
			*xx_p = '\0' ;
		// printf("Debug who %s\n",who_description);

		if ( person[0] != '\0' )	// Filter for just one person.
			{
			printf("%s person=%s\n",
				strcmp(person,who_description) ?
				"Excluding"
				:
				"Including"
				,
				who_description);
			}
		line_u++ ;

	/* -- Look for ^@Rate word x word x word */
		if ((scanf("%s %s x %s x %s",
				&rate_line,
				&where_s,
				&day_in_week_s,
				&time_in_day_s
				) != 4) ||
			 strncmp("@Rate", rate_line, strlen("@Rate"))) GRIPE ;
		line_u++ ;
	/* -- Look for ^@Job multi word description .... */
		if ((scanf("%s", &job_line ) < 1 ) ||
			 strncmp("@Job", job_line, strlen("@Job"))) GRIPE ;
		/* Swallow space before job description */
		while (1)
			{
			if ((ch_i = getchar() ) == EOF ) GRIPE ;
			if (( (char)ch_i != ' ') &&
				( (char)ch_i != '\t')) break ;
			}
		/* Swallow rest of job line */
		job_p = job_description ; job_ln = JOB_LN ;
		while	(( (char)ch_i != '\n') && ( (char)ch_i != '\0') &&
				--job_ln )
			{
			*job_p++ = (char)ch_i ;
			if ((ch_i = getchar() ) == EOF ) GRIPE ;
			}
		*job_p = '\0';

		line_u++ ;
	/* -- Look for start time ^[0-9][0-9]:[0-9][0-9] */
		if (!silent) printf("%02d\tStart%s", line_u, time_hr_min);
		if ((scanf("%d:%d", &start_hour , &start_minute) != 2) ||
			( start_hour < 0 ) || (start_hour > 23) ||
			( start_minute < 0 ) || (start_minute > 59) ) GRIPE ;
		start_l = start_hour * 60 + start_minute ;
		line_u++ ;
	/* -- Look for stop time ^[0-9][0-9]:[0-9][0-9] */
		if (!silent) printf("\tStop %s\t", time_hr_min);
		if ((scanf("%d:%d", &stop_hour, &stop_minute) != 2) ||
			( stop_hour < 0 )
			/* No check of ( stop_hour > 24),
			  Allows entry of
			  overnight jobs stopping at 3am as 27:00 */
			 || ( stop_minute < 0 ) || (stop_minute > 59)
			) GRIPE ;
		stop_l = stop_hour * 60 + stop_minute ;

		if ( 0 > (tmp_l = (stop_l - start_l ))) GRIPE ;
		line_u++ ;
	/* -- Look for break minute time ^[0-9][0-9] */
		/* No checks here, so we can cludge totals */
		if (!silent) printf("\tLunch Duration, (Mins.):\t\t\t\t");
		if ((scanf("%d", &break_minutes) != 1) ||
			( break_minutes < 0 ) ) GRIPE;
		/* no check of if ( break_minutes > 60 )
			Allow people to book a lunch break of eg 70 mins,
			plus other breaks (perhaps to nip out shopping,
			or for higher priority work on a different project etc)
		 */
		if ( tmp_l < (long) break_minutes ) GRIPE;
		tmp_l -= (long) break_minutes ;

		line_u++ ;

	/* -- Finished input of a session record, now output. */

		// printf("\n") ;
		printf("%s: ", day_description) ;
		printf("%s\n", job_description) ;

		/* Start & Finish Times */
		printf("%02d:%02d-%02d:%02d, ",
			start_hour, start_minute, stop_hour, stop_minute);

		/* Minutes Off On Breaks */
		printf("Breaks=%3u,", (unsigned)break_minutes);
			/* might be a few hours so need 3 digits */

		/* Session in Hours & Minutes (also used to detext EOF) */
		session_hours_flat = tmp_l / 60 ;
		session_minutes_flat = tmp_l % 60 ;

		// Now accumulate if either for all people, or right person.
		if ( ( person[0] == '\0' )	// All People, Or
		     ||
		   ( ( person[0] != '\0' ) &&
		       !strcmp(person,who_description) ) )
			{
			printf(" SessionFlat=%2d:%02d, ",
				session_hours_flat, session_minutes_flat );

			/*
			 * printf("\nDebug: Accumulating %s %s\n",
			 *	(*person == '\0' ) ? "" : "person" ,
			 *	person);
			 */

			/* Cumulative of all sessions in Hours & Minutes */
			cumulative_hours_flat += session_hours_flat ;
			cumulative_minutes_flat += session_minutes_flat ;
			cumulative_hours_flat += cumulative_minutes_flat / 60 ;
			cumulative_minutes_flat %= 60 ;
			printf("TotalFlat=%3d:%02d\n",
				 cumulative_hours_flat,
				cumulative_minutes_flat );
				/* 3 digits is enough for a a few
				   months of hours, sure a years
				   worth of hours goes into 4 digits,
				   even just for one person, but
				   billing doesnt wait half a year!
				 */

			/* Factor Text */
			// printf("\n%6s, %6s, %7s, ",
				/*	6: "w_site" "w_full" "w_high" "w_low"
					6: "d_week" "d_sat" "d_sun" "d_hol"
					7: "t_night" "t_day" "t_eve"
				*/
				// where_s, day_in_week_s, time_in_day_s );

			/* Factor Numeric */
			factor_numeric =
				get_rate1(where_s, day_in_week_s,
				time_in_day_s ) ;
			printf(" Rate=%f\n", factor_numeric );

			/* Factored Session in Hours */
			session_minutes_factored = factor_numeric *
				( session_hours_flat * 60 +
				session_minutes_flat ) ;
			printf("SessionVar=%-2f, ",
				session_minutes_factored / 60 );

			/* Factored Cumulative in Hours */
			cumulative_minutes_factored +=
				session_minutes_factored ;
			printf("TotalVar=\%-3f", cumulative_minutes_factored / 60 );

			}
		printf("\n\n");
		}
	while (session_hours_flat || session_minutes_flat) ;
	if ( person[0] != '\0' )
		{
		printf("Person %s: ",person) ;
		printf("TotalFlat=%3d:%02d, ",
			cumulative_hours_flat, cumulative_minutes_flat );
		printf("TotalVar=\%-3f\n", cumulative_minutes_factored / 60 );
		}
	exit(0);
	}

gripe(start_hour, start_minute, stop_hour, stop_minute)
	int	start_hour ;	/* start hour */
	int	start_minute ;	/* start minute */
	int	stop_hour ;	/* stop hour */
	int	stop_minute ;	/* stop minute */
	{
	printf("\nLine %u, Who=\"%s\", Job=\"%s\"\n Where=\"%s\", Day_In_Week=\"%s\", Time_In_Day=\"%s\"\n%02d=%02d-%02d:%02d\n",
		line_u,
		who_s,
		job_description,
		where_s,
		day_in_week_s,
		time_in_day_s,
		start_hour,
		start_minute,
		stop_hour,
		stop_minute
		);
	printf("something strange with numbers, ");
	(void) scanf("%*s\n") ;
	printf("try again.\n");
	(void) fflush(stdout);
	/* I used to allow a return, as this used to take interactive input,
	   but I havent done that for years now, it only ever
	   processes a log, so just exit, else it often loops forever
	   */
	exit(1);
	}

syntax()
	{
	fprintf(stderr,"Fatal error, Command Syntax: %s [-p person]\n",
		*ARGV ) ;
	fprintf(stderr,
		"PS note data must come from stdin, never from a file\n");
	}
