Rev 31 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/************************************************************************** Copyright (C) 1995 Embedded Solutions* All rights reserved** file: src\legtime.c** purpose: Leg time calculations** functions* set_legs - Menu: Setup leg times* tm_lgs - Set up the leg start times for leg* leg_start - Set up the leg start times* tm_fixedstart - Set the start time for a specific leg* tm_staggered - Set a staggered start time for a specific leg* tm_clearleg - Clear start times on a specific leg* leg_ini - Initialize all stored times* tm_init - Initialize all team data* tm_gen - Generate dummy team names* legs_start_report - Generate starters report* ls_timer - print the current leg entry* ls_team - print next ( numeric ) leg entry* sort_legs - Qsort callback function** programmer: David Purdie** revision date by reason* 11-Oct-89 DDP leg-3 starttime. Now has an option to generate* a printed report of teams and times** 21-May-90 MV now able to set start time and generate* a printed report for any leg* 00.0 27/01/95 DDP Tidies up the program and formatted the file***************************************************************************/#include "consts.h"#include "structs.h"#include "proto.h"#if defined(HI_TECH_C) || defined(__TURBOC__)#include <alloc.h>#endifmenu_table leg_menu[] = {{ '1', "Set start time from category", leg_start },{ '2', "Clear all leg times", leg_ini },{ '3', "Reset team information", tm_init },{ '4', "Generate dummy team names", tm_gen },{ '5', "Set calculated leg start", tm_lgs },{ '6', "Set ordered incremental leg start", tm_lgs1 },{ '7', "Set staggered start time", tm_staggered },{ '8', "Set fixed start time", tm_fixedstart },{ '9', "Clear single leg start times", tm_clearleg },{ 'q', "Return to main menu", 0 },{ '\0' }};/*========================================================================** Menu: Setup leg times** Purpose:* This function is called to produce the menu that will* setup leg times** Parameters:* None** Returns:* Nothing**========================================================================*/void set_legs(void){do_menu( "Leg time setup", "Select option", leg_menu );}/*========================================================================** Set up the leg start times for leg** Purpose:* This function is called to Set up the leg start times for leg* The start time is based on category information** Parameters:* None** Returns:* Nothing**========================================================================*/void tm_lgs1(void){time_t delta; /* The time delta */time_t starttime;int report_it = FALSE; /* Report the operation */int clear_it = FALSE;t_legs *data; /* Address of table */t_legs *dptr; /* Moving pointer */int num_records; /* Number of records in array */int i;cur( 0, 5 );while( TRUE ){leg = 0;d_field( 0, 5, "Enter leg to set start time :", D_NUMBER, 1,( char * ) &leg, TRUE, M_UPDATE );if( leg == 0 )return; /* Null leg - just exit */if( leg <= config.num_legs ) /* Valid leg number - Exit loop */break;beep(); /* Make a noise and wait for valid number */}cur( 0, 5 );printf ( "Setting start times for all valid teams from %-d to %-d for leg %d\n",config.min_team, config.max_team, leg );starttime = 0;do{d_time( 0, 6, "Enter the start time : ", &starttime, TRUE );if( abort_flag )return;if( starttime < 0 )beep();} while( starttime < 0 );delta = 0;do{d_time( 0, 7, "Enter the delta time : ", &delta, TRUE );if( abort_flag )return;if( delta < 0 )beep();} while( delta < 0 );report_it = getyes( "\nGenerate leg start report" );if( abort_flag )return;clear_it = getyes("Invalidate the leg start times" );if( abort_flag )return;/*** Read existing data into memory*/data = ( t_legs * ) calloc( ( unsigned ) ( config.max_team - config.min_team + 2 ), sizeof( t_legs ) ); /* Fetch memory */if( !data ){printf( "\nNo memory for report\n" );return;}/** Extract the required data from the data base* Only save that information required for the operation* - The end time of the previous leg*/dptr = data;num_records = 0;for( i = config.min_team; i <= config.max_team; i++ ){if( valid_field( i ) && g_record( i, &team_buf ) ){dptr->numb = team_buf.numb;dptr->start = team_buf.leg[leg-1].end;dptr->flags = team_buf.flags;dptr++;num_records++;}}/** Sort the data into some logical order*/qsort( ( char * ) data, num_records, sizeof( t_legs ), sort_legs );/*** Update the team information based on the start order** Ignore validity flags as the data will have been sorted with** these in mind.*/for( dptr = data, i = 0; i < num_records; i++, dptr++ ){if( valid_field( dptr->numb ) ){g_record( dptr->numb, &team_buf );team_buf.leg[leg].start = starttime;starttime += delta;team_buf.leg[leg].manual = TRUE;set_times( &team_buf );test_times( &team_buf, 0 );put_team_record( dptr->numb, &team_buf );}if( i % 10 == 0 ){cur( 0, 8 );printf( "Upto entry %d", i );flush_out();}}/*** Release the data*/free( data );if( report_it )legs_start_report(9);if ( clear_it )tm_clearleg_specified( leg, TRUE, 10 );}/*========================================================================** Set up the leg start times for leg** Purpose:* This function is called to Set up the leg start times for leg* The start time is based on current placing with:* A constant offset added ( ie: lunch)* A fixed increment** Parameters:* None** Returns:* Nothing**========================================================================*/void tm_lgs(void){time_t delta; /* The time delta */int report_it = FALSE; /* Report the operation */int clear_it = FALSE;int line = 5; /* Current line */cur( 0, line );while( TRUE ){leg = 0;d_field( 0, line, "Enter leg to set start time :", D_NUMBER, 1,( char * ) &leg, TRUE, M_UPDATE );if( leg == 0 )return; /* Null leg - just exit */if( leg <= config.num_legs ) /* Valid leg number - Exit loop */break;beep(); /* Make a noise and wait for valid number */}cur( 0, ++line );printf ( "Setting start times for all valid teams from %-d to %-d for leg %d\n",config.min_team, config.max_team, leg );delta = 0;line++;do{d_time( 0, line, "Enter the time difference : ", &delta, TRUE );if( abort_flag )return;if( delta < 0 )beep();} while( delta < 0 );line++;report_it = getyes( "\nGenerate leg start report" );if( abort_flag )return;line++;clear_it = getyes("Invalidate the leg start times" );if( abort_flag )return;line++;team = config.min_team; /* Team we are working with */while( team <= config.max_team ){if( valid_field( team ) ){g_record( team, &team_buf );if( team_buf.flags.valid && team_buf.leg[leg - 1].end > 0 ){team_buf.leg[leg].start = team_buf.leg[leg - 1].end + delta;team_buf.leg[leg].manual = TRUE;}elseteam_buf.leg[leg].start = ( time_t ) - 1;set_times( &team_buf );test_times( &team_buf, 0 );put_team_record( team, &team_buf );}if( team % 10 == 0 ){cur( 0, line );printf( "Upto team %d", team );flush_out();}team++;}if( report_it )legs_start_report(++line);if ( clear_it )tm_clearleg_specified( leg, TRUE, ++line );}/*========================================================================** Set up the leg start times** Purpose:* This function is called to Set up the leg start times** Parameters:* None** Returns:* Nothing**========================================================================*/void leg_start(void){team = config.min_team; /* Team we are working with */cur( 0, 5 );printf( "Setting start times for all valid teams from %-d to %-d \n",config.min_team, config.max_team );if( !getyes( "Continue operation" ) )return;while( team <= config.max_team ){if( valid_field( team ) ){( void ) g_record( team, &team_buf );if( team_buf.class > 0 && team_buf.class <= config.num_class )team_buf.leg[0].start =config.team_class[team_buf.class - 1].start;elseteam_buf.leg[0].start = ( time_t ) - 1;team_buf.leg[1].manual = 0;team_buf.leg[1].start = team_buf.leg[0].start;team_buf.leg[0].l_place = 0;team_buf.leg[0].le_place = 0;team_buf.leg[0].lec_place = 0;team_buf.leg[0].lc_place = 0;team_buf.leg[0].manual = FALSE;set_times( &team_buf );test_times( &team_buf, 0 );put_team_record( team, &team_buf );}if( team % 10 == 0 ){cur( 0, 8 );printf( "Upto team %d", team );flush_out();}team++;}}/*========================================================================** Set the start time for a specific leg** Purpose:* This function is called to set the start time for a specific* leg to a specified and fixed time** Parameters:* None** Returns:* Nothing**========================================================================*/void tm_fixedstart(void){time_t starttime; /* The start time */int report_it = FALSE; /* Report the operation */int clear_it = FALSE;int line = 5; /* Current line */cur( 0, 5 );while( TRUE ){leg = 0;d_field( 0, line, "Enter leg to set start time :", D_NUMBER, 1,( char * ) &leg, TRUE, M_UPDATE );if( leg == 0 )return; /* Null leg - just exit */if( leg <= config.num_legs ) /* Valid leg number - Exit loop */break;beep(); /* Make a noise and wait for valid number */}line++;team = config.min_team; /* Team we are working with */cur( 0, line++ );printf( "Setting start times for all valid teams from %-d to %-d for leg %d\n",config.min_team, config.max_team, leg );starttime = 0;do{d_time( 0, line, "Enter the start time : ", &starttime, TRUE );if( abort_flag )return;if( starttime < 0 )beep();} while( starttime < 0 );line++;report_it = getyes( "\nGenerate leg start report" );if( abort_flag )return;line++;clear_it = getyes("Invalidate the leg start times" );if( abort_flag )return;while( team <= config.max_team ){if( valid_field( team ) ){g_record( team, &team_buf );if( team_buf.flags.valid ){team_buf.leg[leg].start = starttime;team_buf.leg[leg].manual = TRUE;}elseteam_buf.leg[leg].start = ( time_t ) - 1;set_times( &team_buf );test_times( &team_buf, 0 );put_team_record( team, &team_buf );}if( team % 10 == 0 ){cur( 0, 8 );printf( "Upto team %d", team );flush_out();}team++;}if( report_it )legs_start_report(++line);if ( clear_it )tm_clearleg_specified( leg, TRUE, ++line );}/*========================================================================** Set a staggered start time for a specific leg** Purpose:* This function is called to set the start time for a specific* leg to a specified and a staggered time** Parameters:* None** Returns:* Nothing**========================================================================*/void tm_staggered(void){time_t starttime; /* The start time */time_t delta; /* The stagger */int report_it = FALSE; /* Report the operation */int clear_it = FALSE;int line = 5; /* Current line */cur( 0, line );while( TRUE ){leg = 0;d_field( 0, 5, "Enter leg to set start time :", D_NUMBER, 1,( char * ) &leg, TRUE, M_UPDATE );if( leg == 0 )return; /* Null leg - just exit */if( leg <= config.num_legs ) /* Valid leg number - Exit loop */break;beep(); /* Make a noise and wait for valid number */}line++;team = config.min_team; /* Team we are working with */cur( 0, line++ );printf( "Setting staggered start times for all valid teams from %-d to %-d for leg %d\n",config.min_team, config.max_team, leg );starttime = 0;do{d_time( 0, line, "Enter the start time : ", &starttime, TRUE );if( abort_flag )return;if( starttime < 0 )beep();} while( starttime < 0 );line++;delta = 0;do{d_time( 0, line, "Enter the stagger time : ", &delta, TRUE );if( abort_flag )return;if( delta < 0 )beep();} while( delta < 0 );line++;report_it = getyes( "\nGenerate leg start report" );if( abort_flag )return;line++;clear_it = getyes("Invalidate the leg start times" );if( abort_flag )return;while( team <= config.max_team ){if( valid_field( team ) ){g_record( team, &team_buf );if( team_buf.flags.valid ){team_buf.leg[leg].start = starttime;starttime += delta;team_buf.leg[leg].manual = TRUE;}elseteam_buf.leg[leg].start = ( time_t ) - 1;set_times( &team_buf );test_times( &team_buf, 0 );put_team_record( team, &team_buf );}if( team % 10 == 0 ){cur( 0, 9 );printf( "Upto team %d", team );flush_out();}team++;}if( report_it )legs_start_report(++line);if ( clear_it )tm_clearleg_specified( leg, TRUE, ++line );}/*========================================================================** Clear start times on a specific leg** Purpose:* This function is called to clear start times on a specifc leg** Parameters:* None** Returns:* Nothing**========================================================================*/void tm_clearleg(void){cur( 0, 5 );while( TRUE ){leg = 0;d_field( 0, 5, "Enter leg to clear start time :", D_NUMBER, 1,( char * ) &leg, TRUE, M_UPDATE );if( leg == 0 )return; /* Null leg - just exit */if( leg <= config.num_legs ) /* Valid leg number - Exit loop */break;beep(); /* Make a noise and wait for valid number */}cur( 0, 5 );printf( "Setting start times for all valid teams from %-d to %-d for leg %d\n",config.min_team, config.max_team, leg );if( !getyes( "Continue operation" ) )return;tm_clearleg_specified( leg, FALSE, 6 );}/*========================================================================** Clear start times on a specific leg** Purpose:* This function is called to clear start times on a specifc leg** Parameters:* cleg - Leg to clear* manual - Force manual, else leave alone* line - Current display line number** Returns:* Nothing**========================================================================*/void tm_clearleg_specified(int cleg, bool manual, int line){/*** Validate the users argument*/if( cleg == 0 )return; /* Null leg - just exit */if( cleg > config.num_legs ) /* Valid leg number - Exit loop */return;leg = cleg;team = config.min_team; /* Team we are working with */while( team <= config.max_team ){if( valid_field( team ) ){g_record( team, &team_buf );team_buf.leg[leg].manual = manual;team_buf.leg[leg].start = ( time_t ) -1;set_times( &team_buf );test_times( &team_buf, 0 );put_team_record( team, &team_buf );}if( team % 10 == 0 ){cur( 0, line );printf( "Upto team %d", team );flush_out();}team++;}}/*========================================================================** Initialize all stored times** Purpose:* This function is called to Initialize all stored times** Parameters:* None** Returns:* Nothing**========================================================================*/void leg_ini(void){int i;team = config.min_team; /* Team we are working with */cur( 0, 5 );printf( "\nInitializing ALL times for all valid teams from %-d to %-d\n",config.min_team, config.max_team );if( !getyes( "Continue operation" ) )return;while( team <= config.max_team ){if( valid_field( team ) ){( void ) g_record( team, &team_buf );for( i = 0; i <= MAX_LEGS; i++ ){team_buf.leg[i].start = team_buf.leg[i].end =team_buf.leg[i].elapsed = ( time_t ) - 1;team_buf.leg[i].l_place = 0;team_buf.leg[i].le_place = 0;team_buf.leg[i].lec_place = 0;team_buf.leg[i].lc_place = 0;team_buf.leg[i].manual = FALSE;}if( team_buf.class > 0 && team_buf.class <= config.num_class )team_buf.leg[0].start =config.team_class[team_buf.class - 1].start;elseteam_buf.leg[0].start = ( time_t ) - 1;team_buf.leg[1].start = team_buf.leg[0].start;team_buf.flags.disqualified = FALSE;team_buf.flags.non_equestrian = FALSE;put_team_record( team, &team_buf );}if( team % 10 == 0 ){cur( 0, 8 );printf( "Upto team %d", team );flush_out();}team++;}}/*========================================================================** Initialize all team data** Purpose:* This function is called to Initialize all team data** Parameters:* None** Returns:* Nothing**========================================================================*/void tm_init(void){team = config.min_team; /* Team we are working with */cur( 0, 5 );printf( "\nDelete ALL team information for all valid teams from %-d to %-d\n",config.min_team, config.max_team );if( !getyes( "Continue operation" ) )return;while( team <= config.max_team ){if( valid_field( team ) ){clr_team( team, &team_buf );put_team_record( team, &team_buf );}if( team % 10 == 0 ){cur( 0, 8 );printf( "Upto team %d", team );flush_out();}team++;}}/*========================================================================** Generate dummy team names** Purpose:* This function is called to Generate dummy team names** Parameters:* None** Returns:* Nothing**========================================================================*/void tm_gen(void){team = config.min_team; /* Team we are working with */cur( 0, 5 );printf( "Generate DUMMY team names for all valid teams from %-d to %-d\n",config.min_team, config.max_team );if( !getyes( "Continue operation" ) )return;while( team <= config.max_team ){if( valid_field( team ) ){( void ) g_record( team, &team_buf );team_buf.flags.valid = TRUE;sprintf( team_buf.name, "Team - %4.4d", team );team_buf.class = 1; /* Set default class */put_team_record( team, &team_buf );}if( team % 10 == 0 ){cur( 0, 8 );printf( "Upto team %d", team );flush_out();}team++;}}/*========================================================================** Generate starters report** Purpose:* This routine is used to generate a list of leg start times* This system can cope with a break at the start of leg** Parameters:* None** Returns:* Nothing**========================================================================*/void legs_start_report(int line){int i;t_legs *data; /* Address of table */t_legs *dptr; /* Moving pointer */int last_team;int num_records = 0; /* Number of records in array */char l_s[40]; /* Name of start time file */cur( 0, line );printf( "Generating Starters report for Leg-%d", leg );data = ( t_legs * ) calloc( ( unsigned ) ( config.max_team - config.min_team + 2 ), sizeof( t_legs ) ); /* Fetch memory */if( !data ){printf( "\nNo memory for report\n" );return;}/** Extract the required data from the data base* Only save that information required for the operation*/dptr = data;for( i = config.min_team; i <= config.max_team; i++ ) /* Print team order data */{if( valid_field( i ) && g_record( i, &team_buf ) ){dptr->numb = team_buf.numb;dptr->start = team_buf.leg[leg].start;dptr->flags = team_buf.flags;dptr++;num_records++;}}/** Sort the data into some logical order*/qsort( ( char * ) data, num_records, sizeof( t_legs ), sort_legs );/*** Now print the data on the printer** - Generte the name of the printer file** - Open the printer*/sprintf( l_s, "l_%d", leg );if( !open_printer( "", l_s, 80, FALSE, "Starters Report" ) )return;/** Print out the header for the file*/print( "\nStarters report for leg:%d %-*s\n", leg, 18, config.leg_name[leg - 1] );print( "Team order listing\n\n" );print_underline (TRUE);print( "%-8s %-5s %-8s | %-5s %-8s", "Time", "Team", "DeltaT", "Team", "Time" );print_underline (FALSE);print( "\n" );last_team = 0;for( dptr = data, i = 0; i < num_records; i++ ){ls_timer( dptr++, i );print( " | " );ls_team( &last_team, data );print( "\n" );}print( "\nTeams without marked times will be started when ALL marked teams\n" );print( "have been started.\n" );/*** Release the resources** - Printer** - Memory*/close_printer();free( data );}/*========================================================================** print the current leg entry** Purpose:* This function is a helper routine to print the current leg entry* in time : Team number order** Parameters:* ptr Pointer to entry* num Entry index** Returns:* Nothing**========================================================================*/void ls_timer( t_legs * ptr, int num ){time_t time;time_t delta;if( num == 0 )delta = ( time_t ) - 1;elsedelta = ptr[0].start - ptr[-1].start;time = ptr->start;if( ptr->flags.disqualified )time = ( time_t ) - 1;print( "%-8s %-5d", time_fa( time, ptr->flags.disqualified ),ptr->numb );print( " %-8s", time_fa( delta, TRUE ) );}/*========================================================================** print next ( numeric ) leg entry** Purpose:* This helper function is called to print next ( numeric ) leg entry* in Team # time order** Parameters:* last Last one found* Used to relocate my self* data Start of data** Returns:* Nothing**========================================================================*/void ls_team( int *last, t_legs * data ){t_legs *min;time_t time;for( min = 0; data->numb; data++ ){if( data->numb > *last && ( min == 0 || data->numb < min->numb ) )min = data;}*last = min->numb; /* Save current team as done */time = min->start;if( min->flags.disqualified )time = ( time_t ) - 1;print( "%-5d %-8s", min->numb,time_fa( time, min->flags.disqualified ) );}/*========================================================================** Qsort callback function** Purpose:* This function is provided to Qsort() to sort the teams** Parameters:* a - Leg entry to compare* b - Leg entry to compare*** Returns:* -1 a < b* 0 a = b* 1 a > b**========================================================================*/int sort_legs( const void * aa, const void * bb ){const t_legs * a = aa;const t_legs * b = bb;int a_bad;int b_bad;a_bad = a->flags.disqualified || a->start <= 0;b_bad = b->flags.disqualified || b->start <= 0;if( a_bad || b_bad ) /* Valid data has precedence */{if( a_bad && b_bad )return ( a->numb - b->numb );elsereturn ( a_bad ? 1 : -1 );}if( a->start == b->start )return ( a->numb - b->numb );else{if( ( a->start > 0 ) && ( b->start > 0 ) )return ( ( int ) ( a->start - b->start ) );elsereturn ( ( a->start > 0 ) ? -1 : 1 );}}/********************************* EOF ***********************************/