Rev 339 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/************************************************************************** Copyright (C) 1995 Embedded Solutions* All rights reserved** file: src\report.c** purpose: PREFIX -** functions* report - Report menu* pri_team - Print in team order* pri_leg - Print in given leg finishing time* p_place - Print place information* p_team - Print team information* pri_eleg - Print on elapsed times for given leg* pe_place - Print place and elapsed time information* pe_team - Print team and elapsed time information* pri_final - Print final results* pri_interim - Print interim results* print_class_header - Print a class header* print_class_stats - Generate the class stats* print_legend - Print the legend* pi_place - Return place data* pr_place - Return place data* ck_data - Check data for bad times* srt_place - Update placing information* do_big_sort - Main sort routine for final data* sort - Sort in memory buffer* sort_comp - qsort comparison function* load - load report data into memory* gen_stats - Generate all the stats** programmer: David Purdie** revision date by reason* e388 11-Oct-88 Option in the final printout to only* produce the main result sheet. The leg* placing printout is not produced.** Changes to the display format of unknown* times of disqualified teams. Only affects* the leg-printouts.* Disqualified teams show as -- -- --* Otherwise they show as ** ** *** or a valid time.** e339 31-Oct-88 DDP Added the "Interim Report" facility* 00.0 27/01/95 DDP Tidies up the program and formatted the file* 00.1 06-sep-02 DDP Added support for HTML report generation***************************************************************************/#include <stdio.h>#include "consts.h"#include "structs.h"#include "proto.h"#include "mainwindow.h"void pri_awards_html(void);void pri_summary_html(void);void pri_awards(void);void pri_master_index(void);char *placing ( int place );void pri_name_index(void);void pri_name_index_body( void );void pri_all_reports (void );void pri_leg_body(int leg);void pri_eleg_body(int leg);void pri_csv_data ( void );#define MAX_PLACE 11const char * place_text[] ={"Zero'th","First","Second","Third","Fourth","Fifth","Sixth","Seventh","Eighth","Ninth","Tenth","Eleventh"};int sort_leg;int sort_mode;bool sort_withEquestrian;report_type report_html = text;bool report_all = FALSE;/* Parameters used by the sort routine to govern its actions */#define S_L 1 /* Elasped times */#define S_LE 2 /* Leg end time */#define S_LC 3 /* Elapsed times per class */#define S_LEC 4 /* Leg end time per class */#define S_FIN 5 /* Sort on finish time at given leg */#define S_TEAM 6 /* Sort on team order */#define S_CLASS 7 /* Sort on class/team order */#define S_LC_NE 8 /* Elapsed times per class, with NE sorted by real class */#define S_IFIN 9 /* Sort on elapsed time at given leg *//*** Various checking modes*/#define C_ELAPSED 1 /* Check elapsed times */#define C_END 2 /* Check end times */#define C_DISQUAL 3 /* Check disqualified teams *//*** Data*/ty_s_data *sort_data = 0; /* pointer to memory */ty_s_aux *sort_aux = 0; /* pointer to aux sort info */ty_s_namedata *sort_name_data = 0; /* pointer to name info */unsigned int sort_num; /* Number in the array */unsigned int sort_num_data; /* Number in the array */ty_stats stats; /* Holds statistics *//*========================================================================** Print in team order** Purpose:* This function is called to Print in team order* This function may also be used to create an HTML suite of files* within the result set** Parameters:* None** Returns:* Nothing**========================================================================*/void pri_team(void){int i, k;team_type team_buf;if( !open_printer( "", "name", 132, report_html, "Team Names" ) )return;/** Print out the data* Print out the header*/print( "\n" );print_underline( TRUE );print( "%-*s %-*s %-*s", MAX_TM_NAME + 5, "Entry number and name",LEN_CLASS_NAME, "Category",config.num_countries == 0 ? 1 : LEN_CNTRY_NAME,config.num_countries == 0 ? "" : "Country" );for( k = 0; k < MAX_MEMB; k++ ){print( " %-*s", MAX_PERSON_NAME, config.leg_name[k] ? config.leg_name[k] : "Competitor" );}print_underline( FALSE ) ;print( "\n" );for( i = config.min_team; i <= config.max_team; i++ ){if( valid_field( i ) && g_record( i, &team_buf ) ){/*** If printing an HTML report then we need to mark** the entry with a reference so that we can link to it*/if ( report_html == html ){print( "<A NAME=\"Team_%04d\">",team_buf.numb );print( "</A>" );}/*** Basic information** - Team number - with Xref back to full result** - Full team name** - Full categoray name - with Xref to category results** - Country name*/if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "finish" ,"html")), team_buf.numb );print( "%4d", team_buf.numb );if ( report_html == html ) print( "</A>" );print( " %-*s ", MAX_TM_NAME, team_buf.name );if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">",url_encode(p_filename(filebase, config.team_class[team_buf.teamclass - 1].abr ,"html")), team_buf.numb );print( "%-*s", LEN_CLASS_NAME, team_buf.teamclass == 0 ? "" : config.team_class[team_buf.teamclass - 1].full_name );if ( report_html == html ) print( "</A>" );print( " %-*s", config.num_countries == 0 ? 1 : LEN_CNTRY_NAME,config.num_countries == 0|| team_buf.country ==0 ? "" : config.country_name[team_buf.country - 1].full_name );for( k = 0; k < MAX_MEMB; k++ )print( " %-*s", MAX_PERSON_NAME, team_buf.members[k].name );print( "\n" );}}close_printer();}/*========================================================================** Print in name order** Purpose:* This function is called to print a list of all known competitors* This function may also be used to create an HTML suite of files* within the result set** Parameters:* None** Returns:* Nothing**========================================================================*/void pri_name_index_body( void ){ty_s_namedata *ptr;team_type team_buf;unsigned num;int i;unsigned int k;int num_names;/*** Determine the number of names to allow for* Based on the total number of teams*/num = config.max_team - config.min_team + 1 ;num *= MAX_MEMB;sort_name_data = ( ty_s_namedata * ) calloc ( num , sizeof( ty_s_namedata ) );if( sort_name_data == 0 ){MainWindow::showMessage("Error in allocating memory");return;}/*** Read all teams an extract name information*/ptr = sort_name_data;for( i = config.min_team; i <= config.max_team; i++ ){if( valid_field( i ) && g_record( i, &team_buf ) ){num_names = 0;for( k = 0; k < MAX_MEMB; k++ ){if ( team_buf.members[k].name[0] ){ptr->team = i;ptr->leg = k;ptr->teamclass = team_buf.teamclass;strncpy( ptr->name,team_buf.members[k].name, sizeof(team_buf.members[k].name));ptr++;num_names++;}}if ( num_names == 0 ){ptr->team = i;ptr->leg = 0;ptr->teamclass = team_buf.teamclass;strncpy( ptr->name,team_buf.name, sizeof(team_buf.members[k].name));ptr++;}}}sort_num_data = ptr - sort_name_data;/*** Now stort the entries by name:team:leg*/qsort( ( char * ) sort_name_data, sort_num_data, sizeof( ty_s_namedata ), sort_comp_cname );/*** Now generate the report*/if( !open_printer( "", "competitor", 80, report_html, "Competitor Names" ) )return;/** Print out the data* Print out the header*/print( "\n" );print_underline( TRUE );print( "%-*s %-*s %-*s %-*s", MAX_TM_NAME + 5, "Competitor name",6, "Leg",5, "Team",LEN_CLASS_NAME, "Category");print_underline( FALSE ) ;print( "\n" );ptr = sort_name_data;for( k = 1; k <= sort_num_data; k++, ptr++ ){print( "%-*s", MAX_TM_NAME + 5, ptr->name );print( " " );if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "finish" ,"html")), ptr->team );print( "%-*d", 6, ptr->leg + 1 );if ( report_html == html ) print( "</A>" );print( " " );if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), ptr->team );print( "%-*d", 5, ptr->team );if ( report_html == html ) print( "</A>" );print( " " );if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">",(p_filename(filebase, config.team_class[ptr->teamclass - 1].abr ,"html")), ptr->team );print( "%-*s", LEN_CLASS_NAME, ptr->teamclass == 0 ? "" : config.team_class[ptr->teamclass - 1].abr );if ( report_html == html ) print( "</A>" );print( " " );if ( ptr->multi ) print( "* ");print( "\n" );}print_legend( -1, 0 );close_printer();}/*========================================================================** Print in given leg finishing time** Purpose:* This function is called to Print in given leg finishing time** Parameters:* None** Returns:* Nothing**========================================================================*/void pri_leg_body(int leg){ty_s_data *ptr;int i, k;/** Sort the data in finishing order*/if( ck_data( leg, C_END ) )return; /* Check data for this leg */sort_team_data( leg, S_FIN, true ); /* Sort the data *//** Now print the data on the printer*/if( !open_printer( "",tprintf("lg%1.1d", leg ),80,report_html,leg ? tprintf ("Finish order for Leg %d.", leg): "Final team finish order") ){return;}/** Print out the data*/print( "PRELIMINARY RESULTS ONLY\n\n" );print_underline( TRUE );print( "%4s %4s %-8s ", "Plce", "Team", "Time" );print( "%4s %4s %-8s ", "Plce", "Team", "Time" );print( "|" );print( "%4s %4s %-8s ", "Team", "Plce", "Time" );print( "%4s %4s %-8s\n", "Team", "Plce", "Time" );print_underline( FALSE );for( ptr = sort_data, k = 0, i = config.min_team; i <= config.max_team; ){p_place( ptr++, leg, k++ );p_place( ptr++, leg, k++ );print( "|" );while( i <= config.max_team && !valid_field( i ) )i++;p_team( i++, leg );while( i <= config.max_team && !valid_field( i ) )i++;p_team( i++, leg );print( "\n" );}print_underline( TRUE );print( "%4s %4s %-8s ", "Plce", "Team", "Time" );// print( "%4s %4s %-8s ", "Plce", "Team", "Time" );print( "|" );// print( "%4s %4s %-8s ", "Team", "Plce", "Time" );print( "%4s %4s %-8s\n", "Team", "Plce", "Time" );print_underline( FALSE );for( ptr = sort_data, k = 0, i = config.min_team; i <= config.max_team; ){p_place( ptr++, leg, k++ );// p_place( ptr++, leg, k++ );print( "|" );while( i <= config.max_team && !valid_field( i ) )i++;p_team( i++, leg );// while( i <= config.max_team && !valid_field( i ) )// i++;// p_team( i++, leg );print( "\n" );}/** Insert the leg statistics*/gen_stats(); /* Generate all stats */print( "\nLeg statistics\n" );print( "Fastest team: %4d time : %s.",stats.fast.team[leg][0], time_a( stats.fast.time[leg][0] ) );print( " Average time: %s\n", time_a( stats.average[leg][0] ) );close_printer();}/*========================================================================** Print place information** Purpose:* This helper function is called to Print place information* in a 20-character field** Parameters:* ptr Address of the place data* leg Leg to print* k Current index into sorted array. Simply* used to determine if the entry is valid* or if it should be space-filled** Returns:* Nothing**========================================================================*/void p_place( ty_s_data * ptr, int leg, unsigned k ){if( k < sort_num ){print( "%4.4s %4d %8s ",pr_place( ptr->place, ptr->flags.bad_times ),ptr->team, time_fa( ptr->leg[leg], ptr->flags.disqualified ) );}else{print( "%20s", "" );}}/*========================================================================** Print team information** Purpose:* This helper function is called to Print team information* in a 20-character field** Parameters:* i team to print* leg Leg to print** Returns:* Nothing**========================================================================*/void p_team( int i, int leg ){ty_s_data *ptra; /* Pointer to sort data */int found = FALSE;unsigned j;if( valid_field( i ) ){ptra = sort_data;for( j = 1; j <= sort_num; j++, ptra++ )if( i == ptra->team ){found = TRUE;break;}}if( found ){print( "%4d %4.4s %8s ",ptra->team,pr_place( ptra->place, ptra->flags.bad_times ),time_fa( ptra->leg[leg], ptra->flags.disqualified ) );}else{print( "%20s", "" );}}/*========================================================================** Print on elapsed times for given leg** Purpose:* This function is called to Print on elapsed times for given leg** Parameters:* leg - Leg number to print** Returns:* Nothing**========================================================================*/void pri_eleg_body( int leg){ty_s_data *ptr;int i, k;/** Sort the data in finishing order*/if( ck_data( leg, C_ELAPSED ) )return; /* Check data for this leg */sort_team_data( leg, S_IFIN, true ); /* Sort the data on elapsed time *//** Now print the data on the printer*/if( !open_printer( "", tprintf( "le%1.1d", leg ),80,report_html,leg ? tprintf( "Elapsed time order for Leg %d.", leg ): tprintf( "Final elapsed team finishing order." )) ){return;}/** Print out the data*/print( "PRELIMINARY RESULTS ONLY\n\n" );print_underline( TRUE );print( "%4s %4s %-8s ", "Plce", "Team", "Time" );print( "%4s %4s %-8s ", "Plce", "Team", "Time" );print( "|" );print( "%4s %4s %-8s ", "Team", "Plce", "Time" );print( "%4s %4s %-8s\n", "Team", "Plce", "Time" );print_underline( FALSE );for( ptr = sort_data, k = 0, i = config.min_team; i <= config.max_team; ){pe_place( ptr++, leg, k++ );pe_place( ptr++, leg, k++ );print( "|" );while( i <= config.max_team && !valid_field( i ) )i++;pe_team( i++, leg );while( i <= config.max_team && !valid_field( i ) )i++;pe_team( i++, leg );print( "\n" );}print( "\n\n" );print_underline( TRUE );print( "%4s %4s %-8s ", "Plce", "Team", "Time" );// print( "%4s %4s %-8s ", "Plce", "Team", "Time" );print( "|" );// print( "%4s %4s %-8s ", "Team", "Plce", "Time" );print( "%4s %4s %-8s\n", "Team", "Plce", "Time" );print_underline( FALSE );for( ptr = sort_data, k = 0, i = config.min_team; i <= config.max_team; ){pe_place( ptr++, leg, k++ );// pe_place( ptr++, leg, k++ );print( "|" );while( i <= config.max_team && !valid_field( i ) )i++;pe_team( i++, leg );// while( i <= config.max_team && !valid_field( i ) )// i++;// pe_team( i++, leg );print( "\n" );}/** Insert the leg statistics*/gen_stats(); /* Generate all stats */print( "\nLeg statistics\n" );print( "Fastest team: %4d time : %s.",stats.fast.team[leg][0], time_a( stats.fast.time[leg][0] ) );print( " Average time: %s\n", time_a( stats.average[leg][0] ) );close_printer();}///*========================================================================// *// * Print place information// *// * Purpose:// * This helper function is called to Print place and elapsed information// * in a 20-character field// *// * Parameters:// * ptr Address of the place data// * leg Leg to print// * k Current index into sorted array. Simply// * used to determine if the entry is valid// * or if it should be space-filled// *// * Returns:// * Nothing// *// *========================================================================*/void pe_place( ty_s_data * ptr, int leg, unsigned k ){if( k < sort_num ){print( "%4.4s %4d %8s ",pr_place( ptr->place, ptr->flags.bad_times ),ptr->team,time_fa( ptr->lege[leg], ptr->flags.disqualified ) );}else{print( "%20s", "" );}}/*========================================================================** Print team information** Purpose:* This helper function is called to Print team and elapsed time* information in a 20-character field** Parameters:* i Team to print* leg Leg to print** Returns:* Nothing**========================================================================*/void pe_team( int i, int leg ){ty_s_data *ptra; /* Pointer to sort data */int found = FALSE;unsigned j;if( valid_field( i ) ){ptra = sort_data;for( j = 1; j <= sort_num; j++, ptra++ )if( i == ptra->team ){found = TRUE;break;}}if( found ){print( "%4d %4.4s %8s ",ptra->team,pr_place( ptra->place, ptra->flags.bad_times ),time_fa( ptra->lege[leg], ptra->flags.disqualified ) );}else{print( "%20s", "" );}}/*========================================================================** Print final results in HTML** Purpose:* This function is called to Print final results with HTML formatting* All result files are created** Parameters:* None** Returns:* Nothing**========================================================================*/void pri_final_html(void){/*** Generate ALL results with HTML tags*/report_html = html;pri_final();report_html = printed;pri_final();report_html = text;}/*========================================================================** Print final results** Purpose:* This function is called to Print final results** Parameters:* None** Returns:* Nothing**========================================================================*/void pri_final(void){ty_s_data *ptr;team_type team_buf;unsigned i;int j, last_class;char *report_title;bool class_done[MAX_CLASS+1];int lcount;bool isNeClass = false;int place;if( ck_data( -1, C_ELAPSED ) )return;/*** Sort on every thing** Then generate all the stats too*/do_big_sort();gen_stats();/** Now print the data on the printer*/if( !open_printer( "", "finish", 132, report_html, "Finishing Order" ) )return;/** Print out the data*/print_class_header( -1, TRUE ); /* Print the header */ptr = sort_data;sort_team_data( 0, S_L, true ); /* Re-sort on elapsed time */lcount = 0;for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ ){if ( ptr->teamclass == config.nonequestrian_class )continue;g_record( ptr->team, &team_buf );/*** If this is a NE team then dummy up some of the data that hasn't been stored in team_buf*/if (ptr->flags.non_equestrian){team_buf.leg[0].l_place = sort_aux[ptr->team].leq_place[0];team_buf.leg[0].lc_place = sort_aux[ptr->team].lq_place[0];;}/*** If printing an HTML report then we need to mark** the entry with a reference so that we can link to it*/if ( report_html == html ){print( "<A NAME=\"Team_%04d\"></A>",team_buf.numb );}/*** Print the basics (Finishing order)** - Place within complete field** - Team number - with HTML reference to team file** - Class*/if ( report_html == printed && lcount %5 == 4 ) print_underline( TRUE );print( "%4.4s ", pn_place( team_buf.leg[0].l_place, ptr->flags.bad_times, ptr->flags.non_equestrian ) );if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), team_buf.numb );print( "%4d", team_buf.numb );if ( report_html == html ) print( "</A>" );print( " %-*s", 3, team_buf.teamclass == 0 ? "" : config.team_class[team_buf.teamclass - 1].abr );/*** Print the per-leg data** - Time** - Leg place** - End place*/for( j = 1; j <= config.num_legs; j++ ){bool isEquestrianLeg = (j == config.equestrian_leg && team_buf.flags.non_equestrian);bool afterEquestrianLeg = (team_buf.flags.non_equestrian && j > config.equestrian_leg);/*** Ensure that non-equestrian leg data is not displayed*/if ( isEquestrianLeg ){print( " %-8s %4.4s %4.4s", "-- NE --", "NE","NE");}else{print( " %-8s %4.4s %4.4s",time_a( team_buf.leg[j].elapsed ),pr_place( team_buf.leg[j].l_place, ptr->flags.bad_times ),pn_place( team_buf.leg[j].le_place,ptr->flags.bad_times, afterEquestrianLeg ));}}/*** Print the trailer (Finishing order)** - Total time** - Category place - with reference to category file*/// print( " %-8s ", time_a( team_buf.leg[0].elapsed ) );print( " %-8s ", time_a( ptr->lege[0] ) );if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">",url_encode(p_filename(filebase, config.team_class[team_buf.teamclass - 1].abr ,"html")), team_buf.numb );print( "%-4.4s", pn_place( team_buf.leg[0].lc_place, ptr->flags.bad_times, ptr->flags.non_equestrian && 0 ) );if ( report_html == html ) print( "</A>" );if ( report_html == printed && lcount %5 == 4 ) print_underline( FALSE );lcount++;print( "\n" );}print_class_stats( -1, TRUE ); /* Print statistics */print_legend(-1, 1 ); /* Print the legend */close_printer(); /* Close the printer *//** Now produce a breakdown on a class by class basis* Now print out the class placement information*/sort_team_data( 0, S_LC, true ); /* Generate class placement data */last_class = -1; /* Invalid class to start with */memset ( class_done, 0, sizeof(class_done));place = 1;for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ ){int flags = 0;bool eflags;/*** Detect a change in the "class"** All data is within the one array of data** Use the in-memory class as this MAY differ from that stored** The non-equestrian class does this.*/if( last_class != ptr->teamclass ){if( last_class >= 0 ){print_class_stats( last_class, TRUE );print_legend( last_class, 1 );close_printer();}/*** Determine if this is the crazy dummy Non-equestrian class*/isNeClass = (ptr->teamclass == config.nonequestrian_class );place = 1;report_title = tprintf( "Category results for : %-*s", LEN_CLASS_NAME, ptr->teamclass == 0 ? "" : config.team_class[ptr->teamclass - 1].full_name );if( !open_printer( "", config.team_class[ptr->teamclass - 1].abr, 132, report_html, report_title ) )continue;print_class_header( last_class = ptr->teamclass, TRUE );/*** Mark the class as done*/class_done[ptr->teamclass] = TRUE;lcount = 0;}/*** Now read in the team record*/g_record( ptr->team, &team_buf );flags = ptr->flags.bad_times;eflags = (ptr->teamclass != config.nonequestrian_class && ptr->flags.non_equestrian);/*** Dummy up the data for the dummy nonEquestrian Class** Its not stored in the team_buf for backwards compatability*/if( isNeClass){for( j = 0; j <= config.num_legs; j++ ){team_buf.leg[j].lc_place = sort_aux[ptr->team].lq_place[j];team_buf.leg[j].lec_place = sort_aux[ptr->team].leq_place[j];;}}else{if (ptr->flags.non_equestrian){team_buf.leg[0].lc_place = place++; //sort_aux[ptr->team].lq_place[0];team_buf.leg[0].lec_place = sort_aux[ptr->team].leq_place[0];eflags = false;}}/*** If printing an HTML report then we need to mark** the entry with a reference so that we can link to it*/if ( report_html == html )print( "<A NAME=\"Team_%04d\"></A>",team_buf.numb );/*** Print the basics** - Place within the class** - Team number - with HTML reference to team file** - Class*/if ( report_html == printed && lcount %5 == 4 ) print_underline( TRUE );print( "%4.4s ", pn_place( team_buf.leg[0].lc_place, flags , eflags ) );if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), team_buf.numb );print( "%4d", team_buf.numb );if ( report_html == html ) print( "</A>" );print( " %-*s", 3, team_buf.teamclass == 0 ? "" : config.team_class[team_buf.teamclass - 1].abr );for( j = 1; j <= config.num_legs; j++ ){bool isEquestrianLeg = (j == config.equestrian_leg && (ptr->teamclass == config.nonequestrian_class || ptr->flags.non_equestrian));bool afterEquestrianLeg = ((ptr->teamclass == config.nonequestrian_class || ptr->flags.non_equestrian) && j > config.equestrian_leg);/*** Ensure that non-equestrian leg data is not displayed*/if ( isEquestrianLeg ){print( " %-8s %4.4s %4.4s", "-- NE --", "NE","NE");}else{print( " %-8s %4.4s %4.4s", time_a( team_buf.leg[j].elapsed ),pr_place( team_buf.leg[j].lc_place, flags ),pn_place( team_buf.leg[j].lec_place, flags, afterEquestrianLeg ) );}}/*** Print the trailer** - Total time** - Overall place - with reference to overall place file*//* print( " %-8s ", time_a( team_buf.leg[0].elapsed ) ); */print( " %-8s ", time_a( ptr->lege[0] ) );if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "finish" ,"html")), team_buf.numb );print( "%4.4s", pn_place( team_buf.leg[0].l_place, flags , ptr->flags.non_equestrian));if ( report_html == html ) print( "</A>" );if ( report_html == printed && lcount %5 == 4 ) print_underline( FALSE );lcount++;print( "\n" );}print_class_stats( last_class, TRUE );print_legend(last_class,1);close_printer();/*** Pickup missed classes and create a report*/for( j = 1; j <= config.num_class; j++ ){if ( class_done[j] || !config.team_class[j-1].abr[0] ){continue;}report_title = tprintf( "Category results for : %-*s", LEN_CLASS_NAME, config.team_class[j - 1].full_name );if( !open_printer( "", config.team_class[j - 1].abr, 132, report_html, report_title ) )continue;print_class_header( j-1, TRUE );print( "\nThere were no competitors in this class\n" );print_legend(j,1);close_printer();}/*** If we are generating an HTML report then we need to create the file** that contains all the team names - the assumption is that this data** is available*/if ( report_html == html || report_html == printed){pri_team();}/*** Generate the awards report.** This is only available as an HTML report*/if ( report_html == html || report_html == printed){pri_awards_html();}/*** Generate the master index page*/if ( report_html == html ){pri_master_index();}pri_name_index_body();}/*========================================================================** Place to text** Purpose:* This function is called to convert a place to text** Parameters:* place** Returns:* text**========================================================================*/char *placing ( int place ){if ( place > MAX_PLACE ){return tprintf( "Place: %d", place);}return tprintf ("%s Place", place_text[place]);}/*========================================================================** Print award results** Purpose:* This function is called to Print award results* Keep the page to 80 cols, so that it can be pronted on A4** Parameters:* None** Returns:* Nothing**========================================================================*/void pri_awards_html(void){report_type saved = report_html;/*** Generate ALL results with HTML tags*/report_html = html;pri_awards();report_html = printed;pri_awards();report_html = saved;}/*========================================================================** Print award results** Purpose:* This function is called to Print award results* Keep the page to 80 cols, so that it can be pronted on A4** Parameters:* None** Returns:* Nothing**========================================================================*/void pri_awards(void){int j;int i;int k;int windex;int winmax;ty_s_data *ptr;team_type team_buf;int last_class;char solid_line[100];bool header_done = false;/*** Calculate Summary information** Should cache the data*/t_class_summary sdata;calc_class_summary( & sdata );if( !open_printer( "", "awards", 80, report_html, "Prizes and Awards" ) )return;memset ( solid_line, 0, sizeof( solid_line ));memset ( solid_line, '-', 80 );/*** Generate an index for this page*/print( "\n");if ( report_html == html ){print( "<hr>" );print( "<A NAME=\"%s\"></A>",url_encode("INDEX"));}print( "Award Categories - Full Event");for( j = 1; j <= config.num_class; j++ ){/*** Header for the class*/if (!config.team_class[j - 1].abr[0])continue;if (config.class_winners[j - 1] <= 0)continue;winmax = config.class_winners[j-1];{int valid = sdata.teamclass[j].valid_ev;if ( valid < winmax )winmax = valid;}print( "\n");print( " ");if ( report_html == html ) print( "<A HREF=\"#%s\">",url_encode(config.team_class[j-1].full_name));print( "%s", tprintf( "%-*s", LEN_CLASS_NAME ,config.team_class[j-1].full_name ));if ( report_html == html ) print( "</A>" );print( " %3d Awards", winmax );if ( config.class_winners[j-1] != winmax )print( " from a maximum of %3d", config.class_winners[j-1] );}/*** NE Award Categories*/if ( config.class_ne_winners_by_class ){print( "\n");print( "Award Categories - Non Equestrian");for( j = 1; j <= config.num_class; j++ ){/*** Header for the class*/if (!config.team_class[j - 1].abr[0])continue;if ( config.class_ne_winners[j-1] <= 0 )continue;winmax = config.class_ne_winners[j-1];{int valid = sdata.teamclass[j].valid_ne;if ( valid < winmax )winmax = valid;}print( "\n");print( " ");if ( report_html == html ) print( "<A HREF=\"#%s_NE\">",url_encode(config.team_class[j-1].full_name));print( "%s", tprintf( "%-*s", LEN_CLASS_NAME ,config.team_class[j-1].full_name ));if ( report_html == html ) print( "</A>" );print( " %3d Awards", winmax );if ( config.class_ne_winners[j-1] != winmax )print( " from a maximum of %3d", config.class_ne_winners[j-1] );}}/*** Manual entries*/print( "\n");print( "Miscellaneous");print( "\n");print( " ");if ( report_html == html ) print( "<A HREF=\"#%s_by_cat\">",url_encode("Full Event"));print( "%s", tprintf( "%-*s", LEN_CLASS_NAME ,"Full Event"));if ( report_html == html ) print( "</A>" );print (" by Category");if ( config.class_ne_winners_by_class ){print( "\n");print( " ");if ( report_html == html ) print( "<A HREF=\"#%s_by_cat\">",url_encode(config.team_class[config.nonequestrian_class-1].full_name));print( "%s", tprintf( "%-*s", LEN_CLASS_NAME ,config.team_class[config.nonequestrian_class-1].full_name ));if ( report_html == html ) print( "</A>" );print (" by Category");}print( "\n");print( " ");if ( report_html == html ) print( "<A HREF=\"#%s\">",url_encode("Hall Of Fame"));print( "%s", "Hall Of Fame" );if ( report_html == html ) print( "</A>" );print( "\n");print( " ");if ( report_html == html ) print( "<A HREF=\"#%s\">",url_encode("FASTEST"));print( "%s", "FASTEST" );if ( report_html == html ) print( "</A>" );/*** Sort the data by class*/sort_team_data( 0, S_LC, true ); /* Generate class placement data */last_class = -1; /* Invalid class to start with *//*** Process each category*/print( "\n");for( j = 1; ; j++ ){if (!config.team_class[j - 1].abr[0])continue;/*** Tail for previous entry*///if ( config.class_ne_winners_by_class && j == config.nonequestrian_class )// continue;if ( j != 1 )if ( report_html == html ) print( "<A HREF=\"#%s\">Awards Index</A>",url_encode("INDEX"));if ( j > config.num_class )break;/*** Header for the class*/print( "\n");if ( report_html == html ){print( "<hr>" );if ( !header_done ){header_done = true;if ( report_html == html ){print( "<A name=\"%s_by_cat\"></A>",url_encode("Full Event"));}}print( "<A name=\"%s\"></A>",url_encode(config.team_class[j-1].full_name));}else{print( "%s\n", solid_line);}print( "Category: ");if ( report_html == html ) print( "<A HREF=\"%s\">",url_encode(p_filename(filebase, config.team_class[j - 1].abr ,"html")));print( "%s", config.team_class[j-1].full_name );if ( report_html == html ) print( "</A>" );if ( config.class_winners[j-1] <= 0 ){print( "\n");print( "No winners awarded" );if ( report_html == html ) print("<br>");continue;}/*** Enties for 'n' the best teams as configured*/windex = 0; /* Winners done */unsigned int i;for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ ){if ( ptr->teamclass != j ){continue;}/*** Now read in the team record*/if( valid_field( ptr->team ) && g_record( ptr->team, &team_buf ) ){/*** Ensure we have a valid team** Can't award disqualified teams** Can't award NE teams unless its a NE award*/if ( ptr->flags.bad_times )break;if ( ptr->teamclass != config.nonequestrian_class && ptr->flags.non_equestrian )break;/*** Count the entry*/windex++;/*** If printing an HTML report then we need to mark** the entry with a reference so that we can link to it*/print( "\n");if ( report_html == html ){print( "<A NAME=\"Team_%04d\">",team_buf.numb );print( "</A>" );}/*** Basic information** - Team number - with Xref back to full result** - Full team name** - Full categoray name*/print( "%s", placing(windex) );print( " Team Name: ");if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), team_buf.numb );print( "%-*s ", MAX_TM_NAME, team_buf.name );if ( report_html == html ) print( "</A>" );print( " Number: ");if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "finish" ,"html")), team_buf.numb );print( "%4d", team_buf.numb );if ( report_html == html ) print( "</A>" );for( k = 0; k < MAX_MEMB; k++ ){/*** Skip equestrian leg in the non-equestion display*/if ( k + 1 == config.equestrian_leg && ptr->teamclass == config.nonequestrian_class)continue;print( "\n");print( " ");print( "%-*s", MAX_PERSON_NAME, config.leg_name[k] ? config.leg_name[k] : "Competitor" );print( " %-*s", MAX_PERSON_NAME, team_buf.members[k].name );print( " %-8s", time_a( team_buf.leg[k+1].elapsed ) );}print( "\n");print( " ");print_bold( TRUE );print( "%-*s %-*s %-8s", MAX_PERSON_NAME , "Total" ,MAX_PERSON_NAME, "",time_a( team_buf.leg[0].elapsed ) );print_bold( FALSE );print( "\n" );}/*** More to do*/if ( windex >= config.class_winners[j-1] ){break;}}}/*** Non Equestrian winners by category*/if ( config.class_ne_winners_by_class){header_done = false;/*** Sort the data by class with NE data sorted by real class*/sort_team_data( 0, S_LC_NE, true ); /* Generate class placement data */last_class = -1; /* Invalid class to start with *//*** Only process the Non Equestrian teams in this pass*/print( "\n");for( j = 1; ; j++ ){if (!config.team_class[j - 1].abr[0])continue;/*** Tail for previous entry*/if ( j == config.nonequestrian_class)continue;if ( j != 1 )if ( report_html == html ) print( "<A HREF=\"#%s\">Awards Index</A>",url_encode("INDEX"));if ( j > config.num_class )break;/*** Header for the (sub) class*/if ( !header_done ){header_done = true;if ( report_html == html ){print( "<A name=\"%s_by_cat\"></A>",url_encode(config.team_class[config.nonequestrian_class-1].full_name));}}print( "\n");if ( report_html == html ){print( "<hr>" );print( "<A name=\"%s_NE\"></A>",url_encode(config.team_class[j-1].full_name));}else{print( "%s\n", solid_line);}print( "Category: ");if ( report_html == html ) print( "<A HREF=\"%s\">",url_encode(p_filename(filebase, config.team_class[config.nonequestrian_class - 1].abr ,"html")));print( "%s", config.team_class[config.nonequestrian_class-1].full_name );if ( report_html == html ) print( "</A>" );print (" :: ");if ( report_html == html ) print( "<A HREF=\"%s\">",url_encode(p_filename(filebase, config.team_class[j - 1].abr ,"html")));print( "%s", config.team_class[j-1].full_name );if ( report_html == html ) print( "</A>" );if ( config.class_ne_winners[j-1] <= 0 ){print( "\n");print( "No winners awarded" );if ( report_html == html ) print("<br>");continue;}/*** Enties for 'n' the best teams as configured*/windex = 0; /* Winners done */unsigned int i;for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ ){if ( ptr->teamclass != config.nonequestrian_class || ptr->real_teamclass != j ){continue;}/*** Now read in the team record*/if( valid_field( ptr->team ) && g_record( ptr->team, &team_buf ) ){/*** Ensure we have a valid team** Can't award disqualified teams** Can't award NE teams unless its a NE award*/if ( ptr->flags.bad_times )break;if ( ptr->teamclass != config.nonequestrian_class && ptr->flags.non_equestrian )break;/*** Count the entry*/windex++;/*** If printing an HTML report then we need to mark** the entry with a reference so that we can link to it*/print( "\n");if ( report_html == html ){print( "<A NAME=\"Team_%04d\">",team_buf.numb );print( "</A>" );}/*** Basic information** - Team number - with Xref back to full result** - Full team name** - Full categoray name*/print( "%s", placing(windex) );print( " Team Name: ");if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), team_buf.numb );print( "%-*s ", MAX_TM_NAME, team_buf.name );if ( report_html == html ) print( "</A>" );print( " Number: ");if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "finish" ,"html")), team_buf.numb );print( "%4d", team_buf.numb );if ( report_html == html ) print( "</A>" );for( k = 0; k < MAX_MEMB; k++ ){/*** Skip equestrian leg in the non-equestion display*/if ( k + 1 == config.equestrian_leg && ptr->teamclass == config.nonequestrian_class)continue;print( "\n");print( " ");print( "%-*s", MAX_PERSON_NAME, config.leg_name[k] ? config.leg_name[k] : "Competitor" );print( " %-*s", MAX_PERSON_NAME, team_buf.members[k].name );print( " %-8s", time_a( team_buf.leg[k+1].elapsed ) );}print( "\n");print( " ");print_bold( TRUE );print( "%-*s %-*s %-8s", MAX_PERSON_NAME , "Total" ,MAX_PERSON_NAME, "",time_a( team_buf.leg[0].elapsed ) );print_bold( FALSE );print( "\n" );}/*** More to do*/if ( windex >= config.class_ne_winners[j-1] ){break;}}}}/*** Generate the Hall of Fame information*/print( "\n");if ( report_html == html ){print( "<hr>" );print( "<A name=\"%s\"></A>",url_encode("Hall Of Fame"));}else{print( "%s\n", solid_line);}print( "%s", "Hall of Fame" );if ( config.num_fame ){for( i = 1; i <= config.num_fame; i++ ){print( "\n");print( " %-*s", MAX_PERSON_NAME, config.hall_fame[i-1] );}}else{qDebug( "There are no new stars for the Hall of Fame");}if ( report_html == html ) print( "\n");if ( report_html == html ) print( "<A HREF=\"#%s\">Awards Index</A>",url_encode("INDEX"));/*** Generate the FASTEST information*/print( "\n" );print( "\n");if ( report_html == html ){print( "<hr>" );print( "<A name=\"%s\"></A>",url_encode("FASTEST"));}else{print( "%s\n", solid_line);}print( "%s", "FASTEST" );/*** Sort the data and then generate the stats - again*/do_big_sort();gen_stats();for( i = 1; i <= config.num_legs; i++ ){g_record( stats.fast.team[i][0], &team_buf );print( "\n");print( " %-13s ", config.leg_name[i - 1] );print( " Name: ");if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), team_buf.numb );print( "%-*s", MAX_PERSON_NAME, team_buf.members[i-1].name );if ( report_html == html ) print( "</A>" );print( " Team:");if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "finish" ,"html")), team_buf.numb );print( "%4d" , stats.fast.team[i][0] );if ( report_html == html ) print( "</A> " );print( " Time:%s ", time_a( stats.fast.time[i][0] ) );}if ( report_html == html ) print( "\n");if ( report_html == html ) print( "<A HREF=\"#%s\">Awards Index</A>",url_encode("INDEX"));print( "\n");close_printer();}/*========================================================================** pri_master_index** Purpose:* This function is called to create an HTML page that references all* the other pages that have been generated** Assume that they are in the same directory** Parameters:* None** Returns:* Nothing**========================================================================*/void pri_master_index_entry(const char *name, const char *text){print( "<tr><td>");print ("<A HREF=\"%s\">%s</A>\n", url_encode(p_filename(filebase, name ,"html")), text );}void pri_master_index(void){int j;report_html = html;if( !open_printer( "", "index", 132, report_html, "Master Index" ) )return;/*** Names*/print( "<TABLE border=0 align=center>" );pri_master_index_entry( "name", "Team list" );pri_master_index_entry( "competitor", "Competitor list" );pri_master_index_entry( "finish", "Finishing Order for all Teams" );pri_master_index_entry( "awards", "Prizes and Awards" );print( "<tr><td>\n" );print( "\n" );for( j = 1; j <= config.num_class; j++ ){if (!config.team_class[j - 1].abr[0])continue;pri_master_index_entry( config.team_class[j - 1].abr, tprintf("Category Results for: %s", config.team_class[j-1].full_name) );}print( "</TABLE>" );close_printer();/*** A small page to hold the Leg End displays*/if( !open_printer( "", "legindex", 132, report_html, "Master Index with trace data" ) )return;/*** Names*/print( "<TABLE border=0 align=center>" );#if 1pri_master_index_entry( "name", "Team list" );pri_master_index_entry( "competitor", "Competitor list" );pri_master_index_entry( "finish", "Finishing Order for all Teams" );pri_master_index_entry( "awards", "Prizes and Awards" );print( "<tr><td>\n" );print( "\n" );pri_master_index_entry( "summary", "Category Summary" );for( j = 1; j <= config.num_class; j++ ){if (!config.team_class[j - 1].abr[0])continue;pri_master_index_entry( config.team_class[j - 1].abr, tprintf("Category Results for: %s", config.team_class[j-1].full_name) );}#endifprint( "<tr><td>\n" );print( "\n" );for ( int leg = 1; leg <= config.num_legs; leg ++ ){pri_master_index_entry( tprintf("lg%1.1d", leg), tprintf("Leg End Results for: %d", leg) );}print( "<tr><td>\n" );print( "\n" );for ( int leg = 1; leg <= config.num_legs; leg ++ ){pri_master_index_entry( tprintf("le%1.1d", leg), tprintf("Leg Elapsed Time Results for: %d", leg) );}print( "</TABLE>" );close_printer();/*** Tell the main system about this new report*/MainWindow::registerReport(getPrinterFile(), "Master Leg Index");}/*========================================================================** Print interim results** Purpose:* This function is called to Print interim results** Parameters:* None** Returns:* Nothing**========================================================================*/void pri_interim(void){ty_s_data *ptr;team_type team_buf;unsigned i;int j, last_class;char *report_title;if ( ! report_all ){ck_data( -1, C_DISQUAL ); /* Check the data - dummy check */}do_big_sort(); /* Sort on every thing */gen_stats(); /* Generate the stats too *//** Now print the data on the printer*/if( !open_printer( "", "int", 132, report_html, "Interim Results" ) )return;/** Print out the data*/print_class_header( -1, FALSE ); /* Print the header */ptr = sort_data;sort_team_data( 0, S_TEAM, true ); /* Re-sort on team number */for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ ){if ( ptr->teamclass == config.nonequestrian_class )continue;g_record( ptr->team, &team_buf );print( "%4d %4.4s %-*s",team_buf.numb,pi_place( team_buf.leg[config.num_legs].le_place,ptr->flags.disqualified, team_buf.leg[0].elapsed ),3,team_buf.teamclass ==0 ? "" : config.team_class[team_buf.teamclass - 1].abr );for( j = 1; j <= config.num_legs; j++ ){print( " %-8s %4.4s %4.4s",time_fa( team_buf.leg[j].elapsed,ptr->flags.disqualified ),pi_place( team_buf.leg[j].l_place, ptr->flags.disqualified,team_buf.leg[j].elapsed ),pi_place( team_buf.leg[j].le_place,ptr->flags.disqualified,team_buf.leg[j].elapsed ) );}print( " %-8s %4.4s\n",time_fa( team_buf.leg[0].elapsed, ptr->flags.disqualified ),pi_place( team_buf.leg[config.num_legs].lec_place,ptr->flags.disqualified, team_buf.leg[0].elapsed ) );}print_class_stats( -1, FALSE ); /* Print statistics */print_legend(-1, 1); /* Print the legend */close_printer(); /* Close the printer *//** Now produce a breakdown on a class by class basis* Now print out the class placement information*/sort_team_data( 0, S_CLASS, true ); /* Generate class placement data */last_class = -1; /* Invalid class to start with */for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ ){/*** Detect a change in the "class"** All data is within the one array of data** Use the in-memory class as this MAY differ from that stored** The non-equestrian class does this.*/if( last_class != ptr->teamclass ){if( last_class >= 0 ){print_class_stats( last_class, TRUE );print_legend(last_class, 1);close_printer();}report_title = tprintf( "Interim Category results for : %-*s", LEN_CLASS_NAME, team_buf.teamclass == 0 ? "" : config.team_class[ptr->teamclass - 1].full_name );if( !open_printer( "", tprintf( "i%2s", config.team_class[ptr->teamclass - 1].abr ), 132, report_html, report_title ) )continue;print_class_header( last_class = ptr->teamclass, FALSE );}/*** Now read in the team record*/g_record( ptr->team, &team_buf );print( "%4d %4.4s %-*s",team_buf.numb,pi_place( team_buf.leg[config.num_legs].lec_place,ptr->flags.disqualified, team_buf.leg[0].elapsed ),3,team_buf.teamclass ==0 ? "" : config.team_class[team_buf.teamclass - 1].abr );for( j = 1; j <= config.num_legs; j++ ){print( " %-8s %4.4s %4.4s",time_fa( team_buf.leg[j].elapsed,ptr->flags.disqualified ),pi_place( team_buf.leg[j].lc_place,ptr->flags.disqualified,team_buf.leg[j].elapsed ),pi_place( team_buf.leg[j].lec_place,ptr->flags.disqualified,team_buf.leg[j].elapsed ) );}print( " %-8s %4.4s\n",time_fa( team_buf.leg[0].elapsed, ptr->flags.disqualified ),pi_place( team_buf.leg[config.num_legs].le_place,ptr->flags.disqualified, team_buf.leg[0].elapsed ) );}print_class_stats( last_class, FALSE );print_legend(last_class, 1);close_printer();}/*----------------------------------------------------------------------------** FUNCTION : pri_csv_data**** DESCRIPTION : Generate a CSV file of all the report data** It can then be used to play with the data externally****** INPUTS : None**** RETURNS : Yes it does**----------------------------------------------------------------------------*/void pri_csv_data ( void ){int i;int j;int age_sum;team_type team_buf;/*** Sort on every thing** Then generate all the stats too*/do_big_sort();gen_stats();/** Now print the data on the printer*/if( !open_printer( "full_data", "csv", 2000, text, NULL ) )return;/*** Print headings*/csv_print( "%s", "Team Number" );csv_print( "%s", "Team Name" );csv_print( "%s", "Class Full");csv_print( "%s", "Class Abr");csv_print( "%s", "Class Start Time");csv_print( "%s", "Class Start Time Number");csv_print( "%s", "Team Country");for( j = 1; j <= config.num_legs; j++ ){csv_print( "%s", "Leg Number" );csv_print( "%s", "Leg Name");csv_print( "%s", "Competitor Name");csv_print( "%s", "Sex" );csv_print( "%s", "Age");csv_print( "%s", "Start Time");csv_print( "%s", "Start Time Number");csv_print( "%s", "End Time" );csv_print( "%s", "End Time Number" );csv_print( "%s", "Elapsed Time");csv_print( "%s", "Elapsed Time Number");csv_print( "%s", "Leg Place");csv_print( "%s", "Leg End Place");csv_print( "%s", "Leg Class Place");csv_print( "%s", "Leg End Class Place");csv_print( "%s", "Manual");}j = 0;csv_print( "%s", "Team Start Time");csv_print( "%s", "Team Start Time Number");csv_print( "%s", "Team End Time");csv_print( "%s", "Team End Time Number");csv_print( "%s", "Team Elapsed Time");csv_print( "%s", "Team Elapsed Time Number");// csv_print( "%s", team_buf.leg[j].l_place );csv_print( "%s", "Team Leg End Place");// csv_print( "%s", team_buf.leg[j].lc_place );csv_print( "%s", "Team Leg Class Place");// csv_print( "%s", team_buf.leg[j].manual );csv_print( "%s", "Total Team Age");csv_print( "%s", "Flag:valid Team");csv_print( "%s", "Flag:bad_times" );csv_print( "%s", "Flag:disqualified" );csv_print( "%s", "Flag:non_equestrian" );csv_print( "%s", "Flag:vet_check" );csv_print("\n");for( i = config.min_team; i <= config.max_team; i++ ){if( valid_field( i ) && g_record( i, &team_buf ) ){/*** Basic information** - Team number - with Xref back to full result** - Full team name** - Full categoray name - with Xref to category results** - Country name*/csv_print( "%d", team_buf.numb );csv_print( "%s", team_buf.name );csv_print( "%s", team_buf.teamclass == 0 ? "" : config.team_class[team_buf.teamclass - 1].full_name );csv_print( "%s", team_buf.teamclass == 0 ? "" : config.team_class[team_buf.teamclass - 1].abr );csv_print( "%s", time_a (team_buf.teamclass == 0 ? 0 : config.team_class[team_buf.teamclass - 1].start ));csv_print( "%d", team_buf.teamclass == 0 ? 0 : config.team_class[team_buf.teamclass - 1].start );csv_print( "%s", config.num_countries == 0|| team_buf.country ==0 ? "" : config.country_name[team_buf.country - 1].full_name );age_sum = 0;for( j = 1; j <= config.num_legs; j++ ){csv_print( "%d", j );csv_print( "%s", config.leg_name[j - 1] );csv_print( "%s", team_buf.members[j-1].name );csv_print( "%s", ( team_buf.members[j-1].sex == male ) ? "Male" : "Female" );csv_print( "%d", team_buf.members[j-1].age );if ( age_sum >= 0 ){ushort age = team_buf.members[j-1].age;if ( age > 0 && age < 255 ){age_sum += age;}else{age_sum = -1;}}csv_print( "%s", time_a(team_buf.leg[j].start ));csv_print( "%d", team_buf.leg[j].start );csv_print( "%s", time_a(team_buf.leg[j].end ));csv_print( "%d", team_buf.leg[j].end );csv_print( "%s", time_a(team_buf.leg[j].elapsed ));csv_print( "%d", team_buf.leg[j].elapsed );csv_print( "%d", team_buf.leg[j].l_place );csv_print( "%d", team_buf.leg[j].le_place );csv_print( "%d", team_buf.leg[j].lc_place );csv_print( "%d", team_buf.leg[j].lec_place );csv_print( "%d", team_buf.leg[j].manual );}j = 0;csv_print( "%s", time_a(team_buf.leg[j].start ));csv_print( "%d", team_buf.leg[j].start );csv_print( "%s", time_a(team_buf.leg[j].end ));csv_print( "%d", team_buf.leg[j].end );csv_print( "%s", time_a(team_buf.leg[j].elapsed ));csv_print( "%d", team_buf.leg[j].elapsed );// csv_print( "%d", team_buf.leg[j].l_place );csv_print( "%d", team_buf.leg[j].le_place );// csv_print( "%d", team_buf.leg[j].lc_place );csv_print( "%d", team_buf.leg[j].lec_place );// csv_print( "%d", team_buf.leg[j].manual );csv_print( "%d", age_sum );csv_print( "%d", team_buf.flags.valid );csv_print( "%d", team_buf.flags.bad_times );csv_print( "%d", team_buf.flags.disqualified );csv_print( "%d", team_buf.flags.non_equestrian );csv_print( "%d", team_buf.flags.vet_check );//How about class placingscsv_print( "\n" );}}close_printer();}/*========================================================================** Print all reports at once* Its all so fast, these days ...** Purpose:* This function is called to print all reports at once** Parameters:* None** Returns:* Nothing**========================================================================*/void pri_all_reports ( void ){int leg;report_all = TRUE;pri_team();for ( leg = 1; leg <= config.num_legs; leg ++ ){pri_leg_body ( leg );pri_eleg_body ( leg );report_html = html;pri_leg_body ( leg );pri_eleg_body ( leg );//report_html = printed;////pri_leg_body ( leg );//pri_eleg_body ( leg );report_html = text;}pri_final();pri_final_html();pri_csv_data();pri_summary_html();pri_summary();pri_awards_html();pri_awards();pri_master_index();pri_interim();report_all = FALSE;}/*========================================================================** Print a class header** Purpose:* This function is called to print a class header** Parameters:* class Name of this class* final False - prelim results** Returns:* Nothing**========================================================================*/void print_class_header( int teamclass, int final ){int j;/*** Give a clear indication that the report is preliminary*/if( !final )print( "PRELIMINARY RESULTS ONLY\n\n" );/*** Now printout the column headings** This is a two line display**** Line-1 Leg names*/print( "%-*s %-*s %-*s", 4, "", 4, "", 3, "" );for( j = 1; j <= config.num_legs; j++ ){print_bold( TRUE );print( " %-*s", 18, config.leg_name[j - 1] );print_bold( FALSE );}print( " %-8s %-4s\n", "Total", ( teamclass < 0 ) ? "Cat" : "Fin" );/*** Line-2 Details*/print_underline( TRUE );print( "%-*s %*s %-*s", 4, final ? "Plce" : "Team",4, final ? "Team" : "Plce",3, "Cat" );for( j = 1; j <= config.num_legs; j++ )print( " %-8s %-4s %-4s", "Time", " LP", " EP" );print( " %-8s %-4s\n", "Time", "Plce" );print_underline( FALSE );}/*========================================================================** Generate the class stats** Purpose:* This function is called to Generate the class stats** Parameters:* c Class to print* final TRUE: Final data* FALSE: Interim data** Returns:* Nothing**========================================================================*/void print_class_stats( int c, int final ){int i, j;const char *title;if( c < 0 ){title = "Event";c = 0;}else{title = "Category";}print( "\n" );if ( report_html ) print_underline(TRUE);print( "%s statistics", title );if ( report_html ) print_underline(FALSE);print( "\n" );/*** Print the names of the different legs*/print( "%-*s ", LEN_CLASS_NAME, "" );for( i = 1; i <= config.num_legs; i++ ){print_bold( TRUE );print( "%-13s ", config.leg_name[i - 1] );print_bold( FALSE );}print( "%-13s \n", final ? "Total" : "" );/*** Print the fastest teams for each leg and overall** Add cross references to the team names for the fastest teams*/print( "%*s : ", LEN_CLASS_NAME, "Fastest" );for( i = 0; i <= config.num_legs; i++ ){j = i + 1;if( i >= config.num_legs ){if( final )j = 0; /* Leg-0 last */elsebreak;}if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), stats.fast.team[j][c] );print( "%4d", stats.fast.team[j][c] );if ( report_html == html ) print( "</A>" );print( " %s ", time_a( stats.fast.time[j][c] ) );}print( "\n" );/*** Print the average time for each leg*/print( "%*s : ", LEN_CLASS_NAME, "Average" );for( i = 0; i <= config.num_legs; i++ ){j = i + 1;if( i >= config.num_legs ){if( final )j = 0; /* Leg-0 last */elsebreak;}print( " %s ", time_a( stats.average[j][c] ) );}}/*========================================================================** Print the legend** Purpose:* This function is called to Print the legend** Parameters:* class - Class currently being printed* full - Display full legend** Returns:* Nothing**========================================================================*/void print_legend ( int teamclass, int full ){int i;char line[201];FILE *adfile = NULL;int count;/** First the categories*/print( "\n\n" );if ( report_html ) print_underline(TRUE);print( "Category abbreviations" );if ( report_html ) print_underline(FALSE);print( "\n" );for( i = 1, count = 0; i <= config.num_class; i++ ){if (!config.team_class[i - 1].abr[0])continue;#if 0/*** Skip any non-equestrian class in the legend** Don't want to tell the general user whats goes on, unless we actually** creating the non-equestrian report.*/if ( class != config.nonequestrian_class && i == config.nonequestrian_class )continue;#endifif ( report_html == html ) print( "<A HREF=\"%s\">",url_encode(p_filename(filebase, config.team_class[i - 1].abr ,"html")) );print( "%-*s", 3, config.team_class[i - 1].abr );if ( report_html == html ) print( "</A>" );print( " : %-*s ", LEN_CLASS_NAME, config.team_class[i - 1].full_name );if( !( ++count % 5 ) )print( "\n" );}/*** Add link to the finish order report*/if ( report_html == html ){print( "<A HREF=\"%s\">", url_encode(p_filename(filebase, "finish" ,"html")) );print( "%-*s", 3, "All" );print( "</A>" );print( " : %-*s ", LEN_CLASS_NAME, "Finishing Order" );}/*** Country data - if countries have been defined*/if( config.num_countries ){print( "\n\n" );if ( report_html ) print_underline(TRUE);print( "Country abbreviations" );if ( report_html ) print_underline(FALSE);print( "\n" );for( i = 0, count = 0; i < MAX_COUNTRY; i++ ){if( config.country_name[i].abr[0] ){print( "%-*s : %-*s ", 4, config.country_name[i].abr,LEN_CNTRY_NAME, config.country_name[i].full_name );if( !( ++count % 5 ) )print( "\n" );}}}print( "\n" );/** Other comments*/if ( full ){print( "\nPlace numbers (LP and EP)\n" );print( "LP - Placing based on elapsed time within the leg. Cat Plce - Placing within the category.\n" );print( "EP - Placing based on accumulated times to the end of that leg. Fin Plce - Overall placing within the event.\n" );print( "U - Placing not available.\n" );}/** Insert the contents of the config.addendum file* or a defualt message*/if( config.addendum[0] ){QString name = QmConfig::getAddendemFile(config.addendum);if (! name.isEmpty()){adfile = fopen( qPrintable(name), "rt" ); /* Open the file for reading */}}if( adfile ){while( fgets( line, sizeof(line)-1, adfile ) )print( "%s", line );}else{print( "\nTiming and Results by\n" );print( "Embedded Solutions\n" );}}/*========================================================================** Return place data** Purpose:* This function is called to return place data** This routine is called to fill a print team_buffer - to allow for* multiple calls to this function ( before the data is used ) a number* of static team_buffers are maintained** Parameters:* num place - if not bad_times* disq Disqualified flag* time Time data is based on** Returns:* This function returns a pointer to the character string for the* number or a pointer to a bad_times string.**========================================================================*/const char *pi_place( int num, int disq, time_t time ){static char store[2][5]; /* 2 stores for 4 digit numbers */static int i = 0; /* Current index into store */static const char *dis = "D"; /* Disqualified */static const char *non = "-"; /* Invalid time */if( disq ) /* Disqualified team */return ( dis );if( time <= 0 ) /* Unknown time */return ( non );i++;if( i >= 2 )i = 0; /* Select next entry */sprintf( store[i], "%4d", num );return ( store[i] );}/*========================================================================** Return place data** Purpose:* This function is called to Return place data** This routine is called to fill a print team_buffer - to allow for* multiple calls to this function ( before the data is used ) a number* of static team_buffers are maintained** Parameters:* num place - if not bad_times* disq Disqualified flag** Returns:* This function returns a pointer to the character string for the* number or a pointer to a bad_times string.**========================================================================*/const char *pr_place( int num, int disq ){static char store[2][5]; /* 2 stores for 4 digit numbers */static int i = 0; /* Current index into store */static const char *dis = "U";if( disq )return ( dis );i++;if( i >= 2 )i = 0; /* Select next entry */sprintf( store[i], "%4d", num );return ( store[i] );}/*========================================================================** Return place data or NE flag** Purpose:* This function is called to Return place data** This routine is called to fill a print team_buffer - to allow for* multiple calls to this function ( before the data is used ) a number* of static team_buffers are maintained** Parameters:* num place - if not bad_times* disq Disqualified flag* flag Flag NE data** Returns:* This function returns a pointer to the character string for the* number or a pointer to a bad_times string.**========================================================================*/const char *pn_place( int num, int disq, bool flag ){static char store[2][5]; /* 2 stores for 4 digit numbers */static int i = 0; /* Current index into store */static const char *dis = "U";static const char *alt = "NE";if( disq )return ( dis );if (flag)return ( alt );i++;if( i >= 2 )i = 0; /* Select next entry */sprintf( store[i], "%4d", num );return ( store[i] );}/*========================================================================** Check data for bad times** Purpose:* This function is called to Check data for bad times* Scan the sort data structure and locate entries that have incorrect* times.** Entries that have invalid leg times are displayed to the operator* and the report process can be aborted** Parameters:* leg Leg to test* mode Either end or elapsed times to be tested** Returns:* Returns FALSE if the report operation is to be aborted**========================================================================*/bool ck_data( int leg, int mode ){ty_s_data *ptr;unsigned i;int bad = 0;int k;int bad_leg;time_t *t; /* An array of times */ptr = sort_data;for( i = 1; i <= sort_num; i++, ptr++ ){bad_leg = 0;if( mode == C_DISQUAL ){ptr->flags.bad_times = ptr->flags.disqualified;continue;}if( mode == C_ELAPSED )t = ptr->lege;elset = ptr->leg;ptr->flags.bad_times = ptr->flags.disqualified;if( ! ptr->flags.bad_times ){if( leg <= 0 ){for( k = 0; k <= config.num_legs; k++ ){if ( !(config.equestrian_leg && ptr->flags.non_equestrian && config.equestrian_leg == k ))bad_leg |= ( t[k] <= 0 );}}else{bad_leg = t[leg] <= 0;}if( bad_leg ){ptr->flags.bad_times = TRUE;if ( ! report_all ){qDebug( "Team with incorrect time information: %d", ptr->team );bad++;}}}}if( bad ){qDebug( "%d teams with incorrect times. These have been flagged as unplaced", bad );}return ( FALSE );}/*========================================================================** Update placing information** Purpose:* This function is called to Update placing information** This routine will rip through the data generating the team placing in* a) Within a leg* b) At the end of a leg* c) Within a leg by class* d) At the end of a leg by class** This function is provided to allow the display routines to* be accessed and updated without the need to run a report** Parameters:* xxxx a ptr to the xxxx stuff** Returns:* Nothing**========================================================================*/void srt_place(void){if( ck_data( -1, C_ELAPSED ) )return;do_big_sort();/** Generate the stats*/gen_stats();}/*========================================================================** Calculate summary information** Purpose:* This function is called to calculate summary information** Parameters:* ptr - Address of a summary structure to fill in** Returns:* Nothing**========================================================================*/void calc_class_summary( t_class_summary * ptr ){int i;team_type team_buf;/*** Reset the data*/memset ( ptr, 0, sizeof (*ptr ));/** Extract the required data from the data base* Only save that information required for the operation*/for( i = config.min_team; i <= config.max_team; i++ ){if( valid_field( i ) && g_record( i, &team_buf ) ){bool valid = true;bool valid_ne = true;if ( team_buf.flags.disqualified ){ptr->teamclass[team_buf.teamclass].disqualified++;ptr->total.disqualified++;valid = false;valid_ne = false;}if ( team_buf.flags.vet_check ){ptr->teamclass[team_buf.teamclass].vet_check++;ptr->total.vet_check++;valid = false;valid_ne = false;}if ( config.nonequestrian_class && team_buf.flags.non_equestrian ){ptr->teamclass[team_buf.teamclass].non_equestrian++;ptr->total.non_equestrian++;valid = false;}else{valid_ne = false;}ptr->total.total++;ptr->teamclass[team_buf.teamclass].total++;if ( valid ){ptr->total.valid++;ptr->teamclass[team_buf.teamclass].valid++;if ( ! team_buf.flags.bad_times ){ptr->total.valid_ev++;ptr->teamclass[team_buf.teamclass].valid_ev++;}}if ( valid_ne ){if ( ! team_buf.flags.bad_times ){ptr->total.valid_ne++;ptr->teamclass[team_buf.teamclass].valid_ne++;}}}}/*** Fix up the totals for the non equestrians** This is not a real category but a summary of the others.*/if ( config.nonequestrian_class ){ptr->teamclass[config.nonequestrian_class].total += ptr->total.non_equestrian;ptr->teamclass[config.nonequestrian_class].valid += ptr->teamclass[config.nonequestrian_class].total;}}/*========================================================================** Print summary results** Purpose:* This function is called to Print summary results* Keep the page to 80 cols, so that it can be pronted on A4** Parameters:* None** Returns:* Nothing**========================================================================*/void pri_summary_html(void){report_type saved = report_html;/*** Generate ALL results with HTML tags*/report_html = html;pri_summary();report_html = printed;pri_summary();report_html = saved;}/*========================================================================** Print summary information** Purpose:* This function is called to print summary information** Parameters:* None** Returns:* Nothing**========================================================================*/void pri_summary (void){t_class_summary data;int i;if( !open_printer( "", "summary", 80, report_html, "Summary Information" ) )return;calc_class_summary( & data );/*** Display summary stats*/print( "%*s : %-7s %-7s %-7s %-7s %-7s %-7s %-7s\n",LEN_CLASS_NAME, "Category","Total","Valid","Disq","NonEq","VetChk","CompEv","CompNe");for( i = 0; i < config.num_class; i++ ){if (!config.team_class[i].abr[0])continue;/*** The non-equestrian leg does not have any data** Suppress the display*/if ( config.nonequestrian_class == i+1 )continue;if ( report_html == html ) print( "<A HREF=\"%s\">",url_encode(p_filename(filebase, config.team_class[i].abr ,"html")) );print( "%*s ", LEN_CLASS_NAME, config.team_class[i].full_name );if ( report_html == html ) print( "</A>" );print( ": %-7d %-7d %-7d %-7d %-7d %-7d %-7d\n",data.teamclass[i+1].total,data.teamclass[i+1].valid,data.teamclass[i+1].disqualified,data.teamclass[i+1].non_equestrian,data.teamclass[i+1].vet_check,data.teamclass[i+1].valid_ev,data.teamclass[i+1].valid_ne);}print( "\n" );print( "%*s : %-7d %-7d %-7d%-7d %-7d %-7d %-7d\n",LEN_CLASS_NAME, "Totals",data.total.total,data.total.valid,data.total.disqualified,data.total.non_equestrian,data.total.vet_check,data.total.valid_ev,data.total.valid_ne);close_printer();}/*========================================================================** Main sort routine for final data** Purpose:* This function is called to do the report sort routine for final data* This routine will fill all the gaps in the sort_aux structure** Parameters:* None** Returns:* Nothing**========================================================================*/void do_big_sort(void){int i, k, q; /* Looooopy things */unsigned j;ty_s_data *ptr; /* Pointer to sort data */int teamclass; /* Current class */int teamclassq; /* Current class */team_type team_buf;for( i = 0; i <= config.num_legs; i++ ){bool sortWithEq = (i == 0);/*** Sort on leg elapsed time** Then save the teams elapsed place in each leg*/sort_team_data( i, S_L, sortWithEq );for( j = 1, k = 1, q = 1, ptr = sort_data; j <= sort_num; ptr++, j++ ){sort_aux[ptr->team].team = ptr->team;if (ptr->isNeData) {sort_aux[ptr->team].lq_place[i] = q++;} else {sort_aux[ptr->team].l_place[i] = k++;}}/*** Sort on leg end time** Then save the teams place at the end of each leg*/sort_team_data( i, S_LE, sortWithEq);for( j = 1, k = 1, q = 1, ptr = sort_data; j <= sort_num; ptr++, j++ ){if (ptr->isNeData) {sort_aux[ptr->team].leq_place[i] = q++;}else {sort_aux[ptr->team].le_place[i] = k++;}}/*** Sort on elapsed time per class** Then save the teams elapsed place in each leg per class*/sort_team_data( i, S_LC, sortWithEq );teamclass = -1;teamclassq = -1;for( k = 1, j = 1, q = 1, ptr = sort_data; j <= sort_num; j++, ptr++ ){bool isNe = false;if ( sortWithEq && ptr->teamclass == config.nonequestrian_class ) {if ( !ptr->isNeData)isNe = true;}else {if (ptr->isNeData)isNe = true;}if (isNe) {if( teamclassq != ptr->teamclass ){q = 1;teamclassq = ptr->teamclass;}sort_aux[ptr->team].lq_place[i] = q++;}else {if( teamclass != ptr->teamclass ){k = 1;teamclass = ptr->teamclass;}sort_aux[ptr->team].lc_place[i] = k++;}}/*** Sort on end time per class** Then save the teams place at the end of each leg per class*/sort_team_data( i, S_LEC, sortWithEq );teamclass = -1;teamclassq = -1;for( k = 1, j = 1, q = 1, ptr = sort_data; j <= sort_num; j++, ptr++ ){bool isNe = false;if ( sortWithEq && ptr->teamclass == config.nonequestrian_class ) {if ( !ptr->isNeData)isNe = true;}else {if (ptr->isNeData)isNe = true;}if (isNe) {if( teamclassq != ptr->teamclass ){q = 1;teamclassq = ptr->teamclass;}sort_aux[ptr->team].leq_place[i] = q++;}else {if( teamclass != ptr->teamclass ){k = 1;teamclass = ptr->teamclass;}sort_aux[ptr->team].lec_place[i] = k++;}}}/*** Write the place information back to disk for use in the displays*/for( i = config.min_team; i <= config.max_team; i++ ){if( sort_aux[i].team && valid_field( i ) && g_record( i, &team_buf ) ){for( k = 0; k <= config.num_legs; k++ ){team_buf.leg[k].l_place = sort_aux[i].l_place[k];team_buf.leg[k].le_place = sort_aux[i].le_place[k];team_buf.leg[k].lc_place = sort_aux[i].lc_place[k];team_buf.leg[k].lec_place = sort_aux[i].lec_place[k];}put_team_record( i, &team_buf );}}}/*========================================================================** Sort in memory buffer** Purpose:* This function is called to Sort in memory buffer** Parameters:* leg Requested leg* mode Defines the sort mode* withEq Sort with equestrian data (True=Normal)** Returns:* Nothing**========================================================================*/void sort_team_data( int leg, int mode, bool withEq ){unsigned j;ty_s_data *ptr;sort_leg = leg; /* Leg is global for the comparison function */sort_mode = mode; /* Mode is global for compare function */sort_withEquestrian = withEq; /* Mode is global for compare function */qsort( ( char * ) sort_data, sort_num, sizeof( ty_s_data ), sort_comp );/** Insert "place data" into the sorted data* This simply the index into the array of data - after its been* sorted.*/ptr = sort_data;for( j = 1; j <= sort_num; j++, ptr++ ){ptr->place = j;}}/*========================================================================** qsort comparison function** Purpose:* This function is called by qsort as a Sort comparison function** Parameters:* a - 1st record* b - 2nd record** Returns:* value to qsort* Return negative if 'a' is less than 'b',* zero if 'a' == 'b'* positive if 'a' > 'b'**========================================================================*/int sort_comp( const void * aa, const void * bb ){const ty_s_data * a = (ty_s_data *)aa;const ty_s_data * b = (ty_s_data *)bb;int i; /* One of those */time_t ta, tb; /* Leg times */int na, nb; /* Number of valid legs */time_t tta, ttb; /* Temp times *//*** Sorting on Team Number*/if( sort_mode == S_TEAM )return ( a->team - b->team );/*** Sorting on Class and Team Number*/if( sort_mode == S_CLASS ){if( a->teamclass != b->teamclass )return ( a->teamclass - b->teamclass );elsereturn ( a->team - b->team );}/*** Sorting within a class** First sort on the class*/if( sort_mode == S_LEC || sort_mode == S_LC || sort_mode == S_LC_NE ) { /* Sort within a class */if (a->teamclass != b->teamclass)return ( a->teamclass - b->teamclass );}/*** Always put the nonequestrian_class at the end** Simplifies the creation of ordered lists as these** Entries are not present in the main body*/if ( sort_withEquestrian && ( a->teamclass == config.nonequestrian_class || b->teamclass == config.nonequestrian_class )){if ( a->teamclass == config.nonequestrian_class && b->teamclass == config.nonequestrian_class ){/*** Both are non equestrian** S_LC_NE - Elapsed times per class, with NE sorted by real class** Only used in awards*/if (sort_mode == S_LC_NE ){if ( a->real_teamclass != b->real_teamclass ){return ( a->real_teamclass - b->real_teamclass );}}}else{/*** Only one in non-equestrian** Place Non-equestrian AFTER equestrian*/return ( a->teamclass == config.nonequestrian_class ? 1 : -1 );}}/*** Now we need to examine the times as we have sorted** on every thing else.**** If one of the teams has bad_times, then that team is placed** lower in the sorting order. If both teams have bad times** then sort on team number. ie: Unplaced teams are sorted on** team number**** If not sorting within a class (ie Overall), then Non_Equestrian** is better than a bad time. Places NE before disqualified***/if( a->flags.bad_times || b->flags.bad_times || ( sort_withEquestrian && a->flags.non_equestrian) || (sort_withEquestrian && b->flags.non_equestrian)) /* Valid data has precedence */{if( a->flags.bad_times && b->flags.bad_times ){return ( a->team - b->team );}else if( a->flags.bad_times || b->flags.bad_times ){return ( a->flags.bad_times ? 1 : -1 );}if( sort_mode != S_FIN && sort_mode != S_IFIN ){if( a->flags.non_equestrian && b->flags.non_equestrian ){/*** Both are non equestrian** Let the time sort operate ...*///return ( a->team - b->team );}else{/* One is equestrian *//* Good times better than NE */return ( a->flags.non_equestrian ? 1 : -1 );}}}/*** Before we sort on times we must determine which time to** use. Finish time, Leg end times, Leg Elapsed times.*/switch ( sort_mode ){/*** Sort on finish times*/case S_FIN:ta = a->leg[sort_leg];tb = b->leg[sort_leg];break;/*** Sort on accumulated leg times*/case S_LE:case S_LEC:if( sort_leg ){/*** Calculate accumulated time up to the desired leg** If the two teams have a different number of valid** leg times then order by the team that has completed** more legs.*/ta = tb = ( time_t ) 0;na = nb = 0;for( i = 1; i <= sort_leg; i++ ){tta = a->lege[i];ttb = b->lege[i];if( tta > 0 ){na++;ta += tta;}if( ttb > 0 ){nb++;tb += ttb;}}if( na != nb )return ( nb - na );}else{ta = a->leg[sort_leg] - a->start;tb = b->leg[sort_leg] - b->start;}break;/*** Sort on Elapsed times*/case S_LC_NE:case S_LC:case S_L:case S_IFIN:ta = a->lege[sort_leg];tb = b->lege[sort_leg];break;/*** Just to be sure ...*/default:return ( 0 );}/*** If we are ignore Equestrian config then place the Equestrian data last*/#if 0if (a->isNeData != b->isNeData) {return ( a->isNeData ? 1 : -1 );}#endif#if 1if (sort_withEquestrian) {if (a->isNeData != b->isNeData)return ( a->isNeData ? 1 : -1 );}#endifif ( a->team == b->team) {return ( a->isNeData ? 1 : -1 );}/*** Finally. Compare the required team times*/if( ta == tb )return ( a->team - b->team );if( ( ta > 0 ) && ( tb > 0 ) )return ( ( int ) ( ta - tb ) );return ( ( ta > 0 ) ? -1 : 1 );}/*========================================================================** qsort comparison function - competitor names** Purpose:* This function is called by qsort as a Sort comparison function** Parameters:* a - 1st record* b - 2nd record** Returns:* value to qsort**========================================================================*/int sort_comp_cname( const void * aa, const void * bb ){ty_s_namedata * a = (ty_s_namedata *)aa;ty_s_namedata * b = (ty_s_namedata *)bb;int i; /* One of those *//*** Sort by name*/i = strcmp ( a->name, b->name );if ( i )return ( i );a->multi=1;b->multi=1;/*** Sort by Leg*/i = a->leg - b->leg;if ( i )return ( i );/*** Sorting on Team Number*/return ( a->team - b->team );}/*========================================================================** load report data into memory** Purpose:* This routine will pull all the data into memory* Not all the team data is loaded. Only that essential for the* operation of the sort routine is loaded** Parameters:* None** Returns:* TRUE - All is well**========================================================================*/bool load_report_data(void){ty_s_data *ptr; /* pointer to sort data type */ty_s_data *last;int j;unsigned num;team_type team_buf;/** Fetch memory for the data store*/if( sort_data )free( ( char * ) sort_data );sort_data = 0;if( sort_aux )free( ( char * ) sort_aux );sort_aux = 0;sort_num = 0; /* Counter of records in the array *//*** Allocate memory for the data structures** This will be free'd*/num = config.max_team - config.min_team + 1 ;/*** Allow for non-equestrian teams - since some of the data is loaded twice** OLD: Take a guess that at most 1/2 the teams will be non-equestrian** NEW: Memory is cheap. Assume all teams could be non-equestrian*/// OLD: num = num * 3 / 2;num = num * 2;sort_data = ( ty_s_data * ) calloc ( num , sizeof( ty_s_data ) );sort_aux = ( ty_s_aux * ) calloc( num + 1, sizeof( ty_s_aux ) );if( sort_data == 0 || sort_aux == 0 ){MainWindow::showMessage("Error in allocating memory");return ( FALSE );}/*** Load data into the memory based data structure** Only load data for valid-teams** Load essential data** Team Number, class and flags** Leg end and elapsed times*/ptr = sort_data;for( int team = config.min_team; team <= config.max_team; team++ ){if( valid_field( team ) ){g_record( team, &team_buf );if( team_buf.flags.valid ){last = ptr;ptr->team = team;ptr->isNeData = false;for( j = 0; j < MAX_LEGS + 1; j++ ){ptr->lege[j] = team_buf.leg[j].elapsed;ptr->leg[j] = team_buf.leg[j].end;}ptr->start = team_buf.leg[0].start;ptr->teamclass = team_buf.teamclass;ptr->real_teamclass = team_buf.teamclass;ptr->flags = team_buf.flags;// if (ptr->flags.non_equestrian)// ptr->flags.disqualified = true;if (ptr->flags.vet_check)ptr->flags.disqualified = true;ptr++;sort_num++;/*** If non-equestrian support is enabled then** duplicate and modify data for the non-equestrian teams** - Change the class** - Modify the leg time*/#if 1if ( config.nonequestrian_class && team_buf.flags.non_equestrian ){ptr->team = team;ptr->isNeData = true;ptr->lege[0] = 0;for( j = 0; j < MAX_LEGS + 1; j++ ){if ( j == config.equestrian_leg ){last->lege[j] = ptr->lege[j] = 0;if ( config.equestrian_leg > 1 )last->leg[j] = ptr->leg[j] = ptr->leg[j-1];}else{if ( j )last-> lege[j] = ptr->lege[j] = team_buf.leg[j].elapsed;last->leg[j] = ptr->leg[j] = team_buf.leg[j].end;ptr->lege[0] += ptr->lege[j] ;last->lege[0] = ptr->lege[0] ;}}last->start = ptr->start = team_buf.leg[0].start;ptr->teamclass = config.nonequestrian_class;ptr->real_teamclass = team_buf.teamclass;ptr->flags = team_buf.flags;// ptr->flags.disqualified = false;ptr++;sort_num++;}#endif}}}return ( TRUE );}/*========================================================================** Generate all the stats** Purpose:* This function is called to Generate all the stats** Parameters:* None** Returns:* Nothing**========================================================================*/void gen_stats(void){ty_s_data *ptr;unsigned i;int j;int k;/** Init all the stats*/for( i = 0; i <= MAX_LEGS; i++ ){for( j = 0; j <= MAX_CLASS; j++ ){stats.team[i][j] = 0;stats.fast.team[i][j] = 0;stats.fast.time[i][j] = ( time_t ) - 1;stats.average[i][j] = 0;}}for( i = 1, ptr = sort_data; i <= sort_num; i++, ptr++ ){/*** If there is any bad times in the team record, then none** of the data can be trusted.**** If the team has been disqualified, then don't use any** of the data.*/if( ptr->flags.bad_times || ptr->flags.disqualified )continue;/*** Ignore non-Equestrian, unless we are processing the psuedo NE class*/if ( ptr->teamclass != config.nonequestrian_class && ptr->flags.non_equestrian)continue;for( j = 0; j <= config.num_legs; j++ ){if( ptr->lege[j] <= 0 ) /* Ignore bad data */continue;/*** Determine fastest team : overall** Ignore the non-equestrian data as this is in the list twice*/if( ( ptr->lege[j] < stats.fast.time[j][0] )|| ( stats.fast.time[j][0] < 0 ) ){if ( ptr->teamclass != config.nonequestrian_class ){stats.fast.team[j][0] = ptr->team;stats.fast.time[j][0] = ptr->lege[j];}}/*** Determine fastest team : within a class*/if( ( ptr->lege[j] < stats.fast.time[j][ptr->teamclass] )|| stats.fast.time[j][ptr->teamclass] < 0 ){stats.fast.team[j][ptr->teamclass] = ptr->team;stats.fast.time[j][ptr->teamclass] = ptr->lege[j];}/*** Sum the end times : overall*/if ( ptr->teamclass != config.nonequestrian_class ){stats.average[j][0] += ptr->lege[j];stats.team[j][0]++;}/*** Sum the end times : within a class*/stats.average[j][ptr->teamclass] += ptr->lege[j];stats.team[j][ptr->teamclass]++;}}/** Calculate the averages* Can ignore that fact that some categories don't exists* The results will be -1*/for( k = 0; k <= config.num_legs; k++ ){for( j = 0; j <= config.num_class; j++ ){if( stats.team[k][j] )stats.average[k][j] /= stats.team[k][j];elsestats.average[k][j] = ( time_t ) - 1;}}}/********************************* EOF ***********************************/