Subversion Repositories svn1-original

Rev

Rev 164 | Rev 174 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
95 - 1
/*************************************************************************
2
*           Copyright (C) 1995 Embedded Solutions
3
*                       All rights reserved
4
*
5
* file:     src\report.c
6
*
7
* purpose:  PREFIX -
8
*
9
* functions
10
*       report                  - Report menu
11
*       pri_team                - Print in team order
12
*       pri_leg                 - Print in given leg finishing time
13
*       p_place                 - Print place information
14
*       p_team                  - Print team information
15
*       pri_eleg                - Print on elapsed times for given leg
16
*       pe_place                - Print place and elapsed time information
17
*       pe_team                 - Print team and elapsed time information
18
*       pri_final               - Print final results
19
*       pri_interim             - Print interim results
20
*       print_class_header      - Print a class header
21
*       print_class_stats       - Generate the class stats
22
*       print_legend            - Print the legend
23
*       pi_place                - Return place data
24
*       pr_place                - Return place data
25
*       ck_data                 - Check data for bad times
26
*       srt_place               - Update placing information
27
*       do_big_sort             - Main sort routine for final data
28
*       sort                    - Sort in memory buffer
29
*       sort_comp               - qsort comparison function
30
*       load                    - load report data into memory
31
*       gen_stats               - Generate all the stats
32
*
33
* programmer: David Purdie
34
*
35
* revision  date        by      reason
36
*    e388   11-Oct-88           Option in the final printout to only
37
*                               produce the main result sheet. The leg
38
*                               placing printout is not produced.
39
*
40
*                               Changes to the display format of unknown
41
*                               times of disqualified teams. Only affects
42
*                               the leg-printouts.
43
*                               Disqualified teams show as -- -- --
44
*                               Otherwise they show as     ** ** **
45
*                               or a valid time.
46
*
47
*   e339    31-Oct-88   DDP     Added the "Interim Report" facility
48
*   00.0    27/01/95    DDP     Tidies up the program and formatted the file
49
*   00.1    06-sep-02   DDP     Added support for HTML report generation
50
*
51
**************************************************************************/
52
 
53
#include    <stdio.h>
54
#if defined(HI_TECH_C) || defined(__TURBOC__)
55
#include    <alloc.h>
56
#endif
57
#include    "consts.h"
58
#include    "structs.h"
59
#include    "proto.h"
60
 
61
void pri_awards_html(void);
62
void pri_awards(void);
63
void pri_master_index(void);
64
char *placing ( int place );
65
void pri_name_index(void);
66
void pri_name_index_body( void );
67
void pri_all_reports (void );
68
void pri_leg_body(int leg);
69
void pri_eleg_body(int leg);
70
void pri_csv_data ( void );
71
 
72
 
162 david 73
//menu_table  rpt_menu[] = {
74
//    { '1', "Print team order", pri_team },
75
//    { '2', "Print end leg times", pri_leg },
76
//    { '3', "Print elapsed leg times", pri_eleg },
77
//    { '4', "Print final results", pri_final },
78
//    { '5', "Print final results(All-HTML)", pri_final_html },
172 david 79
//    { '6', "Print Interim results", pri_interim },
162 david 80
//    { '7', "Update event and class placings", srt_place },
172 david 81
//    { '8', "Display summary information", display_summary },
162 david 82
//    { '9', "Print summary information", pri_summary },
83
//    { 'a', "Print Awards only", pri_awards_html },
84
//    { 'b', "Print Master Index only", pri_master_index },
85
//    { 'c', "Print Name Index only", pri_name_index },
86
//    { 'e', "Export CSV Report Data", pri_csv_data },
87
//    { 'z', "Print all reports", pri_all_reports },
95 - 88
 
162 david 89
//#if defined(HI_TECH_C) || defined(__TURBOC__)
90
//    { 'S', "MS-DOS system", ms_system },
91
//#endif
92
//    { 'q', "Return to main menu", 0 },
93
//    { '\0' }
94
//};
95 - 95
 
96
#define MAX_PLACE 11
97
const char * place_text[] =
98
{
99
    "Zero'th",
100
    "First",
101
    "Second",
102
    "Third",
103
    "Fourth",
104
    "Fifth",
105
    "Sixth",
106
    "Seventh",
107
    "Eighth",
108
    "Ninth",
109
    "Tenth",
110
    "Eleventh"
111
};
112
 
113
int         sort_leg;
114
int         sort_mode;
115
report_type report_html = text;
116
bool        report_all = FALSE;
117
 
118
/* Parameters used by the sort routine to govern its actions */
119
 
120
#define S_L     1                                /* Elasped times */
121
#define S_LE    2                                /* Leg end time */
122
#define S_LC    3                                /* Elapsed times per class */
123
#define S_LEC   4                                /* Leg end time per class */
124
#define S_FIN   5                                /* Sort on finish time at given leg */
125
#define S_TEAM  6                                /* Sort on team order */
126
#define S_CLASS 7                                /* Sort on class/team order */
127
 
128
/*
129
**  Various checking modes
130
*/
131
#define C_ELAPSED   1                            /* Check elapsed times */
132
#define C_END       2                            /* Check end times */
133
#define C_DISQUAL   3                            /* Check disqualified teams */
134
 
135
/*
136
**  Data
137
*/
138
ty_s_data  *sort_data = 0;                       /* pointer to memory */
139
ty_s_aux   *sort_aux = 0;                        /* pointer to aux sort info */
140
ty_s_namedata *sort_name_data = 0;                /* pointer to name info */
141
unsigned    int sort_num;                            /* Number in the array */
142
unsigned    int sort_num_data;                       /* Number in the array */
143
 
144
/*
145
**  A structure to hold statistical information
146
*/
147
typedef struct
148
{
149
    int         team[MAX_LEGS + 1][MAX_CLASS + 1];
150
    struct
151
    {
152
        int     team[MAX_LEGS + 1][MAX_CLASS + 1];
153
        time_t  time[MAX_LEGS + 1][MAX_CLASS + 1];
154
    } fast;
155
    time_t      average[MAX_LEGS + 1][MAX_CLASS + 1];
156
} ty_stats;
157
 
158
ty_stats        stats;                           /* Holds statistics */
159
 
160
/*========================================================================
161
 *
162
 *  Report menu
163
 *
164
 *  Purpose:
165
 *      This function is called to produce the "Report Menu"
166
 *
167
 *  Parameters:
168
 *      None
169
 *
170
 *  Returns:
171
 *      Nothing
172
 *
173
 *========================================================================*/
174
 
162 david 175
//void report(void)
176
//{
177
//    report_html = text;
178
//    if( load_report_data() )
179
//        do_menu( "Report generation", "Select option", rpt_menu );
95 - 180
 
162 david 181
//    if( sort_data )
182
//        free( ( char * ) sort_data );
183
//    if( sort_aux )
184
//        free( ( char * ) sort_aux );
185
//    if ( sort_name_data )
186
//        free( ( char * ) sort_name_data );
187
//    sort_data = ( ty_s_data * ) 0;
188
//    sort_aux = ( ty_s_aux * ) 0;
189
//    sort_name_data = ( ty_s_namedata * ) 0;
190
//}
95 - 191
 
192
/*========================================================================
193
 *
194
 *  Print in team order
195
 *
196
 *  Purpose:
197
 *      This function is called to Print in team order
198
 *      This function may also be used to create an HTML suite of files
199
 *      within the result set
200
 *
201
 *  Parameters:
202
 *      None
203
 *
204
 *  Returns:
205
 *      Nothing
206
 *
207
 *========================================================================*/
208
 
209
void pri_team(void)
210
{
211
    int         i, k;
212
 
162 david 213
    //cur( 0, 5 );
95 - 214
    printf( "Team information - in team order\n" );
215
    printf( "\nPrinting team names\n" );
162 david 216
    //flush_out();
95 - 217
 
218
    if( !open_printer( "", "name", 132, report_html, "Team Names" ) )
219
        return;
220
 
221
    /*
222
     * Print out the data 
223
     * Print out the header
224
     */
225
 
226
    print( "\n" );
227
 
228
    print_underline( TRUE );
229
    print( "%-*s %-*s %-*s", MAX_TM_NAME + 5, "Entry number and name",
230
               LEN_CLASS_NAME, "Category",
231
               config.num_countries == 0 ? 1 : LEN_CNTRY_NAME,
232
               config.num_countries == 0 ? "" : "Country" );
233
    for( k = 0; k < MAX_MEMB; k++ )
234
    {
235
        print( " %-*s", MAX_PERSON_NAME, config.leg_name[k] ? config.leg_name[k] : "Competitor"  );
236
    }
237
    print_underline( FALSE ) ;
238
    print( "\n" );
239
 
240
    for( i = config.min_team; i <= config.max_team; i++ )
241
    {
242
        if( valid_field( i ) && g_record( i, &team_buf ) )
243
        {
244
            /*
245
            **  If printing an HTML report then we need to mark
246
            **  the entry with a reference so that we can link to it
247
            */
248
            if ( report_html == html )
249
            {
250
                print( "<A NAME=\"Team_%04d\">",team_buf.numb );
251
                print( "</A>" );
252
            }
253
 
254
            /*
255
            **  Basic information
256
            **      - Team number - with Xref back to full result
257
            **      - Full team name
258
            **      - Full categoray name - with Xref to category results
259
            **      - Country name
260
            */
261
            if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "finish" ,"html")), team_buf.numb );
262
            print( "%4d",       team_buf.numb );
263
            if ( report_html == html ) print( "</A>" );
264
 
265
            print( " %-*s ",     MAX_TM_NAME, team_buf.name );
266
 
267
            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 );
268
            print( "%-*s",     LEN_CLASS_NAME, team_buf.teamclass == 0 ? "" : config.team_class[team_buf.teamclass - 1].full_name );
269
            if ( report_html == html ) print( "</A>" );
270
 
271
            print( " %-*s",     config.num_countries == 0 ? 1 : LEN_CNTRY_NAME,
272
                                config.num_countries == 0
273
                                || team_buf.country ==
274
 
275
 
276
            for( k = 0; k < MAX_MEMB; k++ )
277
                print( " %-*s", MAX_PERSON_NAME, team_buf.members[k].name );
278
 
279
            print( "\n" );
280
        }
281
    }
282
    close_printer();
283
}
284
 
285
/*========================================================================
286
 *
287
 *  Print in name order
288
 *
289
 *  Purpose:
290
 *      This function is called to print a list of all known competitors
291
 *      This function may also be used to create an HTML suite of files
292
 *      within the result set
293
 *
294
 *  Parameters:
295
 *      None
296
 *
297
 *  Returns:
298
 *      Nothing
299
 *
300
 *========================================================================*/
301
void pri_name_index( void )
302
{
162 david 303
    //cur( 0, 5 );
95 - 304
    printf( "Team Member information - in name order\n" );
305
    printf( "\nPrinting competitor names\n" );
162 david 306
    //flush_out();
95 - 307
    pri_name_index_body();
308
    printf( "Found %d names\n", sort_num_data );
309
    printf( "\nAny key to continue" );
310
    getinp();
311
}
312
 
313
/*========================================================================
314
 *
315
 *  Print in name order
316
 *
317
 *  Purpose:
318
 *      This function is called to print a list of all known competitors
319
 *      This function may also be used to create an HTML suite of files
320
 *      within the result set
321
 *
322
 *  Parameters:
323
 *      None
324
 *
325
 *  Returns:
326
 *      Nothing
327
 *
328
 *========================================================================*/
329
void pri_name_index_body( void )
330
{
331
    ty_s_namedata *ptr;
332
    unsigned    num;
333
    int i;
334
    unsigned int k;
335
    int num_names;
336
 
337
    /*
338
    **  Determine the number of names to allow for
339
    *   Based on the total number of teams
340
    */
341
    num = config.max_team - config.min_team + 1 ;
342
    num *= MAX_MEMB;
343
 
344
    sort_name_data = ( ty_s_namedata * ) calloc ( num , sizeof( ty_s_namedata ) );
345
 
346
    if( sort_name_data == 0 )
347
    {
348
        printf( "\n\nError in allocating memory\n" );
349
        sleep( 5 );
350
        return;
351
    }
352
 
353
    /*
354
    **  Read all teams an extract name information
355
    */
356
    ptr = sort_name_data;
357
    for( i = config.min_team; i <= config.max_team; i++ )
358
    {
359
        if( valid_field( i ) && g_record( i, &team_buf ) )
360
        {
361
            num_names = 0;
362
            for( k = 0; k < MAX_MEMB; k++ )
363
            {
364
                if ( team_buf.members[k].name[0] )
365
                {
366
                    ptr->team = i;
367
                    ptr->leg = k;
368
                    ptr->teamclass = team_buf.teamclass;
369
                    strncpy( ptr->name,team_buf.members[k].name, sizeof(team_buf.members[k].name));
370
                    ptr++;
371
                    num_names++;
372
                }
373
            }
374
 
375
            if ( num_names == 0 )
376
            {
377
                ptr->team = i;
378
                ptr->leg = 0;
379
                ptr->teamclass = team_buf.teamclass;
380
                strncpy( ptr->name,team_buf.name, sizeof(team_buf.members[k].name));
381
                ptr++;
382
            }
383
 
384
        }
385
    }
386
    sort_num_data = ptr - sort_name_data;
387
 
388
    /*
389
    **  Now stort the entries by name:team:leg
390
    */
391
    qsort( ( char * ) sort_name_data, sort_num_data, sizeof( ty_s_namedata ), sort_comp_cname );
392
 
393
    /*
394
    **  Now generate the report
395
    */
396
 
397
    if( !open_printer( "", "competitor", 80, report_html, "Competitor Names" ) )
398
        return;
399
 
400
    /*
401
     * Print out the data 
402
     * Print out the header
403
     */
404
    print( "\n" );
405
 
406
    print_underline( TRUE );
407
    print( "%-*s %-*s %-*s %-*s", MAX_TM_NAME + 5, "Competitor name",
408
               6, "Leg",
409
               5, "Team",
410
               LEN_CLASS_NAME, "Category"
411
               );
412
    print_underline( FALSE ) ;
413
    print( "\n" );
414
 
415
    ptr = sort_name_data;
416
    for( k = 1; k <= sort_num_data; k++, ptr++ )
417
    {
418
        print( "%-*s", MAX_TM_NAME + 5, ptr->name );
419
        print( " " );
420
 
421
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "finish" ,"html")), ptr->team );
422
        print( "%-*d", 6, ptr->leg + 1 );
423
        if ( report_html == html ) print( "</A>" );
424
        print( " " );
425
 
426
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), ptr->team );
427
        print( "%-*d", 5, ptr->team );
428
        if ( report_html == html ) print( "</A>" );
429
        print( " " );
430
 
431
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">",(p_filename(filebase, config.team_class[ptr->teamclass - 1].abr ,"html")), ptr->team );
432
        print( "%-*s", LEN_CLASS_NAME, ptr->teamclass == 0 ? "" : config.team_class[ptr->teamclass - 1].abr );
433
        if ( report_html == html ) print( "</A>" );
434
        print( " " );
435
 
436
        if ( ptr->multi ) print( "* ");
437
        print( "\n" );
438
    }
439
 
440
    print_legend( -1, 0 );
441
    close_printer();
442
 
443
}
444
 
445
/*========================================================================
446
 *
447
 *  Print in given leg finishing time
448
 *
449
 *  Purpose:
450
 *      This function is called to Print in given leg finishing time
451
 *
452
 *  Parameters:
453
 *      None
454
 *
455
 *  Returns:
456
 *      Nothing
457
 *
458
 *========================================================================*/
459
 
162 david 460
//void pri_leg(void)
461
//{
462
//    int         leg = 0;
95 - 463
 
464
 
162 david 465
//    /*
466
//     * This function is used to provide interum print-outs
467
//     * The team data is sorted by time at leg-end and the times printed are
468
//     * real times at leg end.
469
//     * This operation is designed to be quick - it doesn't update the disk file
470
//     * and is not available in an HTML version - yet
471
//     */
95 - 472
 
162 david 473
//    cur( 0, 5 );
474
//    printf( "Leg finishing time report\n" );
475
//    while( TRUE )
476
//    {
477
//        d_field( 0, 7, "Enter leg to print :", D_NUMBER, 1, ( char * ) &leg,
478
//                 TRUE, M_UPDATE );
479
//        if( abort_flag )
480
//            return;
481
//        if( leg <= config.num_legs )
482
//            break;
483
//        beep();
484
//    }
95 - 485
 
162 david 486
//    pri_leg_body ( leg );
487
//}
95 - 488
 
489
void pri_leg_body(int leg)    
490
{
491
    ty_s_data  *ptr;
492
    int         i, k;
493
    /*
494
     * Sort the data in finishing order 
495
     */
496
 
497
    printf( "\nSorting the data\n" );
162 david 498
    //flush_out();
95 - 499
    if( ck_data( leg, C_END ) )
500
        return;                                  /* Check data for this leg */
501
    sort_team_data( leg, S_FIN );                /* Sort the data */
502
 
503
 
504
    /*
505
     * Now print the data on the printer 
506
     */
507
    if( !open_printer( "",
508
                        tprintf("lg%1.1d", leg ),
509
                        80,
510
                        report_html,
511
                        leg ? tprintf ("Finish order for Leg %d.", leg)
512
                            : "Final team finish order"
513
                     ) )
514
    {
515
        return;
516
    }
517
 
518
    /*
519
     * Print out the data 
520
     */
521
    print( "PRELIMINARY RESULTS ONLY\n\n" );
522
 
523
    print_underline( TRUE );
524
    print( "%4s %4s %-8s  ", "Plce", "Team", "Time" );
525
    print( "%4s %4s %-8s  ", "Plce", "Team", "Time" );
526
    print( "|" );
527
    print( "%4s %4s %-8s  ", "Team", "Plce", "Time" );
528
    print( "%4s %4s %-8s\n", "Team", "Plce", "Time" );
529
    print_underline( FALSE );
530
 
531
    for( ptr = sort_data, k = 0, i = config.min_team; i <= config.max_team; )
532
    {
533
        p_place( ptr++, leg, k++ );
534
        p_place( ptr++, leg, k++ );
535
        print( "|" );
536
        while( i <= config.max_team && !valid_field( i ) )
537
            i++;
538
        p_team( i++, leg );
539
        while( i <= config.max_team && !valid_field( i ) )
540
            i++;
541
        p_team( i++, leg );
542
        print( "\n" );
543
    }
544
 
545
    printf( "\n\n" );
546
    print_underline( TRUE );
547
    print( "%4s %4s %-8s  ", "Plce", "Team", "Time" );
548
//    print( "%4s %4s %-8s  ", "Plce", "Team", "Time" );
549
    print( "|" );
550
//    print( "%4s %4s %-8s  ", "Team", "Plce", "Time" );
551
    print( "%4s %4s %-8s\n", "Team", "Plce", "Time" );
552
    print_underline( FALSE );
553
 
554
    for( ptr = sort_data, k = 0, i = config.min_team; i <= config.max_team; )
555
    {
556
        p_place( ptr++, leg, k++ );
557
//        p_place( ptr++, leg, k++ );
558
        print( "|" );
559
        while( i <= config.max_team && !valid_field( i ) )
560
            i++;
561
        p_team( i++, leg );
562
//        while( i <= config.max_team && !valid_field( i ) )
563
//            i++;
564
//        p_team( i++, leg );
565
        print( "\n" );
566
    }
567
 
568
 
569
    /*
570
     * Insert the leg statistics 
571
     */
572
 
573
    gen_stats();                               /* Generate all stats */
574
    print( "\nLeg statistics\n" );
575
    print( "Fastest team: %4d time : %s.",
576
           stats.fast.team[leg][0], time_a( stats.fast.time[leg][0] ) );
577
    print( " Average time: %s\n", time_a( stats.average[leg][0] ) );
578
 
579
    close_printer();
580
}
581
 
582
/*========================================================================
583
 *
584
 *  Print place information
585
 *
586
 *  Purpose:
587
 *      This helper function is called to Print place information
588
 *      in a 20-character field
589
 *
590
 *  Parameters:
591
 *      ptr         Address of the place data
592
 *      leg         Leg to print
593
 *      k           Current index into sorted array. Simply
594
 *                  used to determine if the entry is valid
595
 *                  or if it should be space-filled
596
 *
597
 *  Returns:
598
 *      Nothing
599
 *
600
 *========================================================================*/
601
 
602
void p_place( ty_s_data * ptr, int leg, unsigned k )
603
{
604
    if( k < sort_num )
605
    {
606
        print( "%4.4s %4d %8s  ",
607
               pr_place( ptr->place, ptr->flags.bad_times ),
608
               ptr->team, time_fa( ptr->leg[leg], ptr->flags.disqualified ) );
609
    }
610
    else
611
    {
612
        print( "%20s", "" );
613
    }
614
}
615
 
616
/*========================================================================
617
 *
618
 *  Print team information
619
 *
620
 *  Purpose:
621
 *      This helper function is called to Print team information
622
 *      in a 20-character field
623
 *
624
 *  Parameters:
625
 *      i           team to print
626
 *      leg         Leg to print
627
 *
628
 *  Returns:
629
 *      Nothing
630
 *
631
 *========================================================================*/
632
 
633
void p_team( int i, int leg )
634
{
635
    ty_s_data  *ptra;                            /* Pointer to sort data */
636
    int         found = FALSE;
637
    unsigned    j;
638
 
639
    if( valid_field( i ) )
640
    {
641
        ptra = sort_data;
642
        for( j = 1; j <= sort_num; j++, ptra++ )
643
            if( i == ptra->team )
644
            {
645
                found = TRUE;
646
                break;
647
            }
648
    }
649
    if( found )
650
    {
651
        print( "%4d %4.4s %8s  ",
652
               ptra->team,
653
               pr_place( ptra->place, ptra->flags.bad_times ),
654
               time_fa( ptra->leg[leg], ptra->flags.disqualified ) );
655
    }
656
    else
657
    {
658
        print( "%20s", "" );
659
    }
660
}
661
 
662
/*========================================================================
663
 *
664
 *  Print on elapsed times for given leg
665
 *
666
 *  Purpose:
667
 *      This function is called to Print on elapsed times for given leg
668
 *
669
 *  Parameters:
670
 *      None
671
 *
672
 *  Returns:
673
 *      Nothing
674
 *
675
 *========================================================================*/
676
 
162 david 677
//void pri_eleg(void)
678
//{
679
//    int         leg = 0;
95 - 680
 
681
 
162 david 682
//    /*
683
//     * This function is used to provide interum print-outs
684
//     * The team data is sorted by time at leg-elapsed and the times printed are
685
//     * real times at leg end.
686
//     * This operation is designed to be quick - it doesn't update the disk file
687
//     * and is not available in an HTML version - yet
688
//     */
95 - 689
 
162 david 690
//    cur( 0, 5 );
691
//    printf( "Leg elapsed time report\n" );
692
//    while( TRUE )
693
//    {
694
//        d_field( 0, 7, "Enter leg to print :", D_NUMBER, 1, ( char * ) &leg,
695
//                 TRUE, M_UPDATE );
696
//        if( abort_flag )
697
//            return;
698
//        if( leg <= config.num_legs )
699
//            break;
700
//        beep();
701
//    }
702
//    pri_eleg_body(leg);
703
//}
95 - 704
 
705
 
706
void pri_eleg_body( int leg)
707
{
708
    ty_s_data  *ptr;
709
    int         i, k;
710
 
711
    /*
162 david 712
     * Sort the data in finishing order
95 - 713
     */
714
 
715
    printf( "\nSorting the data\n" );
162 david 716
    //flush_out();
95 - 717
    if( ck_data( leg, C_ELAPSED ) )
718
        return;                                  /* Check data for this leg */
719
    sort_team_data( leg, S_L );                  /* Sort the data on elapsed time */
720
 
721
 
722
    /*
162 david 723
     * Now print the data on the printer
95 - 724
     */
725
    if( !open_printer( "", tprintf( "le%1.1d", leg ),
726
                       80,
727
                       report_html,
728
                       leg ? tprintf( "Elapsed time order for Leg %d.", leg )
729
                           : tprintf( "Final elapsed team finishing order." )
730
                     ) )
731
    {
732
        return;
733
    }
734
 
735
    /*
162 david 736
     * Print out the data
95 - 737
     */
738
    print( "PRELIMINARY RESULTS ONLY\n\n" );
739
 
740
    print_underline( TRUE );
741
    print( "%4s %4s %-8s  ", "Plce", "Team", "Time" );
742
    print( "%4s %4s %-8s  ", "Plce", "Team", "Time" );
743
    print( "|" );
744
    print( "%4s %4s %-8s  ", "Team", "Plce", "Time" );
745
    print( "%4s %4s %-8s\n", "Team", "Plce", "Time" );
746
    print_underline( FALSE );
747
 
748
 
749
    for( ptr = sort_data, k = 0, i = config.min_team; i <= config.max_team; )
750
    {
751
        pe_place( ptr++, leg, k++ );
752
        pe_place( ptr++, leg, k++ );
753
        print( "|" );
754
        while( i <= config.max_team && !valid_field( i ) )
755
            i++;
756
        pe_team( i++, leg );
757
        while( i <= config.max_team && !valid_field( i ) )
758
            i++;
759
        pe_team( i++, leg );
760
        print( "\n" );
761
    }
762
 
763
    print( "\n\n" );
764
    print_underline( TRUE );
765
    print( "%4s %4s %-8s  ", "Plce", "Team", "Time" );
766
//    print( "%4s %4s %-8s  ", "Plce", "Team", "Time" );
767
    print( "|" );
768
//    print( "%4s %4s %-8s  ", "Team", "Plce", "Time" );
769
    print( "%4s %4s %-8s\n", "Team", "Plce", "Time" );
770
    print_underline( FALSE );
771
 
772
 
773
    for( ptr = sort_data, k = 0, i = config.min_team; i <= config.max_team; )
774
    {
775
        pe_place( ptr++, leg, k++ );
776
//        pe_place( ptr++, leg, k++ );
777
        print( "|" );
778
        while( i <= config.max_team && !valid_field( i ) )
779
            i++;
780
        pe_team( i++, leg );
781
//        while( i <= config.max_team && !valid_field( i ) )
782
//            i++;
783
//        pe_team( i++, leg );
784
        print( "\n" );
785
    }
786
 
787
 
788
    /*
162 david 789
     * Insert the leg statistics
95 - 790
     */
791
 
792
    gen_stats();                               /* Generate all stats */
793
    print( "\nLeg statistics\n" );
794
    print( "Fastest team: %4d time : %s.",
795
           stats.fast.team[leg][0], time_a( stats.fast.time[leg][0] ) );
796
    print( " Average time: %s\n", time_a( stats.average[leg][0] ) );
797
 
798
    close_printer();
799
}
800
 
162 david 801
///*========================================================================
802
// *
803
// *  Print place information
804
// *
805
// *  Purpose:
806
// *      This helper function is called to Print place and elapsed information
807
// *      in a 20-character field
808
// *
809
// *  Parameters:
810
// *      ptr         Address of the place data
811
// *      leg         Leg to print
812
// *      k           Current index into sorted array. Simply
813
// *                  used to determine if the entry is valid
814
// *                  or if it should be space-filled
815
// *
816
// *  Returns:
817
// *      Nothing
818
// *
819
// *========================================================================*/
95 - 820
 
821
void pe_place( ty_s_data * ptr, int leg, unsigned k )
822
{
823
    if( k < sort_num )
824
    {
825
        print( "%4.4s %4d %8s  ",
826
               pr_place( ptr->place, ptr->flags.bad_times ),
827
               ptr->team,
828
               time_fa( ptr->lege[leg], ptr->flags.disqualified ) );
829
    }
830
    else
831
    {
832
        print( "%20s", "" );
833
    }
834
}
835
 
836
/*========================================================================
837
 *
838
 *  Print team information
839
 *
840
 *  Purpose:
841
 *      This helper function is called to Print team and elapsed time
842
 *      information
843
 *      in a 20-character field
844
 *
845
 *  Parameters:
846
 *      i           Team to print
847
 *      leg         Leg to print
848
 *
849
 *  Returns:
850
 *      Nothing
851
 *
852
 *========================================================================*/
853
 
854
void pe_team( int i, int leg )
855
{
856
    ty_s_data  *ptra;                            /* Pointer to sort data */
857
    int         found = FALSE;
858
    unsigned    j;
859
 
860
    if( valid_field( i ) )
861
    {
862
        ptra = sort_data;
863
        for( j = 1; j <= sort_num; j++, ptra++ )
864
            if( i == ptra->team )
865
            {
866
                found = TRUE;
867
                break;
868
            }
869
    }
870
    if( found )
871
    {
872
        print( "%4d %4.4s %8s  ",
873
               ptra->team,
874
               pr_place( ptra->place, ptra->flags.bad_times ),
875
               time_fa( ptra->lege[leg], ptra->flags.disqualified ) );
876
    }
877
    else
878
    {
879
        print( "%20s", "" );
880
    }
881
}
882
 
883
/*========================================================================
884
 *
885
 *  Print final results in HTML
886
 *
887
 *  Purpose:
888
 *      This function is called to Print final results with HTML formatting
889
 *      All result files are created
890
 *
891
 *  Parameters:
892
 *      None
893
 *
894
 *  Returns:
895
 *      Nothing
896
 *
897
 *========================================================================*/
898
 
899
void pri_final_html(void)
900
{
901
    /*
902
    **  Generate ALL results with HTML tags
903
    */
904
    report_html = html;
905
    pri_final();
906
    report_html = printed;
907
    pri_final();
908
    report_html = text;
909
}
910
 
911
 
912
/*========================================================================
913
 *
914
 *  Print final results
915
 *
916
 *  Purpose:
917
 *      This function is called to Print final results
918
 *
919
 *  Parameters:
920
 *      None
921
 *
922
 *  Returns:
923
 *      Nothing
924
 *
925
 *========================================================================*/
926
 
927
void pri_final(void)
928
{
929
    ty_s_data  *ptr;
930
    unsigned    i;
931
    int         j, last_class;
932
    char        suppress_classes;                /* Boolean. Printout class files too */
933
    char        *report_title;
934
    bool        class_done[MAX_CLASS+1];
935
    int         lcount;
936
 
162 david 937
    //cur( 0, 5 );
95 - 938
    printf( "Generate final result printouts\n" );
939
    if( ck_data( -1, C_ELAPSED ) )
940
        return;
941
                                     /* check data for all legs */
942
 
943
    /*
944
    **  If a non HTML report then ask if the user want to supress the class
945
    **  printout. For an HTML report always do the class reports as the two
946
    **  are interlinked
947
    */
948
    if ( ! report_html  && ! report_all)
949
    {
162 david 950
        suppress_classes = FALSE; //getyes( "Do you want to suppress class printouts" );
95 - 951
    }
952
    else
953
    {
954
        suppress_classes = FALSE;
955
    }
956
 
957
    /*
958
    **  Sort on every thing
959
    **  Then generate all the stats too
960
    */
961
    printf( "\nSorting the data\n" );
962
    do_big_sort();
963
    gen_stats();
964
 
965
    /*
966
     * Now print the data on the printer 
967
     */
968
    printf( "\nGenerating the printed output\n" );
969
    if( !open_printer( "", "finish", 132, report_html, "Finishing Order" ) )
970
        return;
971
 
972
    /*
973
     * Print out the data 
974
     */
975
    print_class_header( -1, TRUE );                      /* Print the header */
976
 
977
    ptr = sort_data;
978
    sort_team_data( 0, S_L );                     /* Re-sort on elapsed time */
979
    lcount = 0;
980
    for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
981
    {
982
        if ( ptr->teamclass == config.nonequestrian_class )
983
            continue;
984
 
985
        g_record( ptr->team, &team_buf );
986
 
987
        /*
988
        **  If printing an HTML report then we need to mark
989
        **  the entry with a reference so that we can link to it
990
        */
991
        if ( report_html == html )
992
        {
993
            print( "<A NAME=\"Team_%04d\"></A>",team_buf.numb );
994
        }
995
 
996
        /*
997
        **  Print the basics (Finishing order)
998
        **      - Place within complete field
999
        **      - Team number - with HTML reference to team file
1000
        **      - Class
1001
        */
1002
        if ( report_html == printed && lcount %5 == 4 ) print_underline( TRUE );
1003
        print( "%4.4s ", pr_place( team_buf.leg[0].l_place, ptr->flags.bad_times ) );
1004
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), team_buf.numb );
1005
        print( "%4d",  team_buf.numb );
1006
        if ( report_html == html ) print( "</A>" );
1007
 
1008
        print( " %-*s", 3, team_buf.teamclass == 0 ? "" : config.team_class[team_buf.teamclass - 1].abr );
1009
 
1010
        /*
1011
        **  Print the per-leg data
1012
        **      - Time
1013
        **      - Leg place
1014
        **      - End place
1015
        */
1016
        for( j = 1; j <= config.num_legs; j++ )
1017
        {
1018
            /*
1019
            **  Ensure that non-equestrian leg data is not displayed
1020
            */
1021
            if ( j == config.equestrian_leg && team_buf.flags.non_equestrian )
1022
            {
1023
                print( "  %-8s %4.4s %4.4s", "-- NE --", "NE","NE");
1024
            }
1025
            else
1026
            {
1027
                print( "  %-8s %4.4s %4.4s",
1028
                    time_a( team_buf.leg[j].elapsed ),
1029
                    pr_place( team_buf.leg[j].l_place, ptr->flags.bad_times ),
1030
                    pr_place( team_buf.leg[j].le_place,ptr->flags.bad_times )
1031
                  );
1032
            }
1033
        }
1034
 
1035
       /*
1036
        **  Print the trailer (Finishing order)
1037
        **      - Total time
1038
        **      - Category place - with reference to category file
1039
        */
1040
//        print( "  %-8s ",  time_a( team_buf.leg[0].elapsed ) );
1041
        print( "  %-8s ", time_a( ptr->lege[0] ) );
1042
 
1043
        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 );
1044
        print( "%-4.4s", pr_place_ne( team_buf.leg[0].lc_place, ptr->flags.bad_times, ptr->flags.non_equestrian ) );
1045
        if ( report_html == html ) print( "</A>" );
1046
        if ( report_html == printed && lcount %5 == 4 ) print_underline( FALSE );
1047
        lcount++;
1048
        print( "\n" );
1049
    }
1050
 
1051
    print_class_stats( -1, TRUE );              /* Print statistics */
1052
    print_legend(-1, 1 );                       /* Print the legend */
1053
    close_printer();                            /* Close the printer */
1054
 
1055
    /*
1056
     * Now produce a breakdown on a class by class basis 
1057
     * Now print out the class placement information
1058
     */
1059
 
1060
    if( suppress_classes )
1061
    {
1062
        printf( "WARNING: Class printouts suppressed\n" );
1063
        return;
1064
    }
1065
 
1066
    sort_team_data( 0, S_LC );                 /* Generate class placement data */
1067
    last_class = -1;                           /* Invalid class to start with */
1068
    memset ( class_done, 0, sizeof(class_done));
1069
 
1070
 
1071
    for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
1072
    {
1073
        /*
1074
        **  Detect a change in the "class"
1075
        **  All data is within the one array of data
1076
        **  Use the in-memory class as this MAY differ from that stored
1077
        **  The non-equestrian class does this.
1078
        */
1079
        if( last_class != ptr->teamclass )
1080
        {
1081
            if( last_class >= 0 )
1082
            {
1083
                print_class_stats( last_class, TRUE );
1084
                print_legend( last_class, 1 );
1085
                close_printer();
1086
            }
1087
 
1088
            report_title = tprintf( "Category results for : %-*s", LEN_CLASS_NAME, ptr->teamclass == 0 ? "" : config.team_class[ptr->teamclass - 1].full_name );
1089
 
1090
            if( !open_printer( "", config.team_class[ptr->teamclass - 1].abr, 132, report_html, report_title ) )
1091
                continue;
1092
            print_class_header( last_class = ptr->teamclass, TRUE );
1093
 
1094
            /*
1095
            **  Mark the class as done
1096
            */
1097
            class_done[ptr->teamclass] = TRUE;
1098
            lcount = 0;
1099
        }
1100
 
1101
        /*
1102
        **  Now read in the team record
1103
        */
1104
        g_record( ptr->team, &team_buf );
1105
 
1106
        /*
1107
        **  If printing an HTML report then we need to mark
1108
        **  the entry with a reference so that we can link to it
1109
        */
1110
        if ( report_html == html )
1111
            print( "<A NAME=\"Team_%04d\"></A>",team_buf.numb );
1112
 
1113
        /*
1114
        **  Print the basics
1115
        **      - Place within the class
1116
        **      - Team number - with HTML reference to team file
1117
        **      - Class
1118
        */
1119
 
1120
        if ( report_html == printed && lcount %5 == 4 ) print_underline( TRUE );
1121
        print( "%4.4s ", pr_place( team_buf.leg[0].lc_place, ptr->flags.bad_times ) );
1122
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), team_buf.numb );
1123
        print( "%4d",  team_buf.numb );
1124
        if ( report_html == html ) print( "</A>" );
1125
        print( " %-*s", 3, team_buf.teamclass == 0 ? "" : config.team_class[team_buf.teamclass - 1].abr );
1126
 
1127
        for( j = 1; j <= config.num_legs; j++ )
1128
        {
1129
            /*
1130
            **  Ensure that non-equestrian leg data is not displayed
1131
            */
1132
            if ( j == config.equestrian_leg && (ptr->teamclass == config.nonequestrian_class || ptr->flags.non_equestrian) )
1133
            {
1134
                print( "  %-8s %4.4s %4.4s", "-- NE --", "NE","NE");
1135
            }
1136
            else
1137
            {
1138
                print( "  %-8s %4.4s %4.4s", time_a( team_buf.leg[j].elapsed ),
1139
                       pr_place( team_buf.leg[j].lc_place,  ptr->flags.bad_times ),
1140
                       pr_place( team_buf.leg[j].lec_place, ptr->flags.bad_times ) );
1141
            }
1142
        }
1143
 
1144
        /*
1145
        **  Print the trailer
1146
        **      - Total time
1147
        **      - Overall place - with reference to overall place file
1148
        */
1149
        /* print( "  %-8s ", time_a( team_buf.leg[0].elapsed ) ); */
1150
        print( "  %-8s ", time_a( ptr->lege[0] ) );
1151
 
1152
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "finish" ,"html")), team_buf.numb );
1153
        print( "%4.4s", pr_place( team_buf.leg[0].l_place, ptr->flags.bad_times || (ptr->teamclass == config.nonequestrian_class)));
1154
        if ( report_html == html ) print( "</A>" );
1155
 
1156
        if ( report_html == printed && lcount %5 == 4 ) print_underline( FALSE );
1157
        lcount++;
1158
        print( "\n" );
1159
    }
1160
 
1161
    print_class_stats( last_class, TRUE );
1162
    print_legend(last_class,1);
1163
    close_printer();
1164
 
1165
    /*
1166
    **  Pickup missed classes and create a report
1167
    */
1168
    for( j = 1; j <= config.num_class; j++ )
1169
    {
1170
        if ( class_done[j] )
1171
        {
1172
            continue;
1173
        }
1174
 
1175
        report_title = tprintf( "Category results for : %-*s", LEN_CLASS_NAME, config.team_class[j - 1].full_name );
1176
 
1177
        if( !open_printer( "", config.team_class[j - 1].abr, 132, report_html, report_title ) )
1178
            continue;
1179
        print_class_header( j-1, TRUE );
1180
        print( "\nThere were no competitors in this class\n" );
1181
        print_legend(j,1);
1182
        close_printer();
1183
    }
1184
 
1185
 
1186
    /*
1187
    **  If we are generating an HTML report then we need to create the file
1188
    **  that contains all the team names - the assumption is that this data
1189
    **  is available
1190
    */
1191
    if ( report_html )
1192
    {
1193
        pri_team();
1194
    }
1195
 
1196
    /*
1197
    **  Generate the awards report.
1198
    **  This is only available as an HTML report
1199
    */
1200
    if ( report_html )
1201
    {
1202
        pri_awards_html();
1203
    }
1204
 
1205
    /*
1206
    **  Generate the master index page
1207
    */
1208
    if ( report_html )
1209
    {
1210
        pri_master_index();
1211
    }
1212
 
1213
    pri_name_index_body();
1214
}
1215
 
1216
/*========================================================================
1217
 *
1218
 *  Place to text
1219
 *
1220
 *  Purpose:
1221
 *      This function is called to convert a place to text
1222
 *
1223
 *  Parameters:
1224
 *      place
1225
 *
1226
 *  Returns:
1227
 *      text
1228
 *
1229
 *========================================================================*/
1230
 
1231
char *placing ( int place )
1232
{
1233
    if ( place > MAX_PLACE )
1234
    {
1235
        return tprintf( "Place: %d", place);
1236
    }
1237
    return tprintf ("%s Place", place_text[place]);
1238
}
1239
 
1240
/*========================================================================
1241
 *
1242
 *  Print award results
1243
 *
1244
 *  Purpose:
1245
 *      This function is called to Print award results
1246
 *      Keep the page to 80 cols, so that it can be pronted on A4
1247
 *
1248
 *  Parameters:
1249
 *      None
1250
 *
1251
 *  Returns:
1252
 *      Nothing
1253
 *
1254
 *========================================================================*/
1255
void pri_awards_html(void)
1256
{
1257
    report_type saved = report_html;
1258
    /*
1259
    **  Generate ALL results with HTML tags
1260
    */
1261
    report_html = html;
1262
    pri_awards();
1263
    report_html = saved;
1264
}
1265
 
1266
/*========================================================================
1267
 *
1268
 *  Print award results
1269
 *
1270
 *  Purpose:
1271
 *      This function is called to Print award results
1272
 *      Keep the page to 80 cols, so that it can be pronted on A4
1273
 *
1274
 *  Parameters:
1275
 *      None
1276
 *
1277
 *  Returns:
1278
 *      Nothing
1279
 *
1280
 *========================================================================*/
1281
void pri_awards(void)
1282
{
1283
    int j;
1284
    int i;
1285
    int k;
1286
    int windex;
1287
    int winmax;
1288
    ty_s_data  *ptr;
1289
    int         last_class;
1290
    char    solid_line[100];
1291
 
1292
    /*
1293
    **  Calculate Summary information
1294
    **  Should cache the data
1295
    */
1296
    t_class_summary sdata;
1297
    calc_class_summary( & sdata );
1298
 
1299
 
1300
    if( !open_printer( "", "awards", 80, report_html, "Prizes and Awards" ) )
1301
        return;
1302
 
1303
    memset ( solid_line, 0, sizeof( solid_line ));
1304
    memset ( solid_line, '-', 80 );
1305
 
1306
    /*
1307
    **  Generate an index for this page
1308
    */
1309
    print( "\n");
1310
    if ( report_html == html )
1311
    {
1312
        print( "<hr>" );
1313
        print( "<A NAME=\"%s\"></A>",url_encode("INDEX"));
1314
    }
1315
    print( "Award Categories");
1316
 
1317
    for( j = 1; j <= config.num_class; j++ )
1318
    {
1319
        /*
1320
        **  Header for the class
1321
        */
1322
        if ( config.class_winners[j-1] <= 0 )
1323
            continue;
1324
 
1325
        winmax = config.class_winners[j-1];
1326
        {
1327
            int valid =   sdata.teamclass[j].total
1328
                        - sdata.teamclass[j].disqualified;
1329
//                        - sdata.teamclass[j].non_equestrian;
1330
            if ( valid < winmax )
1331
                winmax = valid;
1332
        }
1333
 
1334
        print( "\n");
1335
        print( "    ");
1336
        if ( report_html == html ) print( "<A HREF=\"#%s\">",url_encode(config.team_class[j-1].full_name));
1337
        print( "%s",  tprintf( "%-*s", LEN_CLASS_NAME ,config.team_class[j-1].full_name ));
1338
        if ( report_html == html ) print( "</A>" );
1339
        print( "  %3d Awards", winmax );
1340
        if ( config.class_winners[j-1] != winmax )
1341
            print( " from a maximum of %3d", config.class_winners[j-1] );
1342
 
1343
    }
1344
 
1345
    /*
1346
    **  Manual entries
1347
    */
1348
    print( "\n");
1349
    print( "    ");
1350
    if ( report_html == html ) print( "<A HREF=\"#%s\">",url_encode("Hall Of Fame"));
1351
    print( "%s",  "Hall Of Fame" );
1352
    if ( report_html == html ) print( "</A>" );
1353
 
1354
    print( "\n");
1355
    print( "    ");
1356
    if ( report_html == html ) print( "<A HREF=\"#%s\">",url_encode("FASTEST"));
1357
    print( "%s",  "FASTEST" );
1358
    if ( report_html == html ) print( "</A>" );
1359
 
1360
    /*
1361
    **  Sort the data by class
1362
    */
1363
    sort_team_data( 0, S_LC );      /* Generate class placement data */
1364
    last_class = -1;                /* Invalid class to start with */
1365
 
1366
    /*
1367
    **  Process each category
1368
    */
1369
    print( "\n");
1370
    for( j = 1; ; j++ )
1371
    {
1372
        /*
1373
        **  Tail for previous entry
1374
        */
1375
        if ( j != 1 )
1376
            if ( report_html == html ) print( "<A HREF=\"#%s\">Awards Index</A>",url_encode("INDEX"));
1377
 
1378
        if ( j > config.num_class  )
1379
            break;
1380
 
1381
        /*
1382
        **  Header for the class
1383
        */
1384
        print( "\n");
1385
        if ( report_html == html )
1386
        {
1387
            print( "<hr>" );
1388
            print( "<A name=\"%s\"></A>",url_encode(config.team_class[j-1].full_name));
1389
        }
1390
        else
1391
        {
1392
            print( "%s\n", solid_line);
1393
        }
1394
        print( "Category: ");
1395
        if ( report_html == html ) print( "<A HREF=\"%s\">",url_encode(p_filename(filebase, config.team_class[j - 1].abr ,"html")));
1396
        print( "%s",  config.team_class[j-1].full_name );
1397
        if ( report_html == html ) print( "</A>" );
1398
 
1399
        if ( config.class_winners[j-1] <= 0 )
1400
        {
1401
            print( "\n");
1402
            print( "No winners awarded" );
1403
            continue;
1404
        }
1405
 
1406
        /*
1407
        **  Enties for 'n' the best teams as configured
1408
        */
1409
        windex = 0;                     /* Winners done */
1410
        unsigned int i;
1411
        for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
1412
        {
1413
            if ( ptr->teamclass != j )
1414
            {
1415
                continue;
1416
            }
1417
 
1418
            /*
1419
            **  Now read in the team record
1420
            */
1421
            if( valid_field( ptr->team ) && g_record( ptr->team, &team_buf ) )
1422
            {
1423
                /*
1424
                **  Ensure we have a valid team
1425
                **  Can't award disqualified teams
1426
                **  Can't award NE teams unless its a NE award
1427
                */
1428
                if ( ptr->flags.bad_times )
1429
                    break;
1430
 
1431
                if ( ptr->teamclass != config.nonequestrian_class  && ptr->flags.non_equestrian )
1432
                    break;
1433
 
1434
                /*
1435
                **  Count the entry
1436
                */
1437
                windex++;
1438
 
1439
                /*
1440
                **  If printing an HTML report then we need to mark
1441
                **  the entry with a reference so that we can link to it
1442
                */
1443
                print( "\n");
1444
                if ( report_html == html )
1445
                {
1446
                    print( "<A NAME=\"Team_%04d\">",team_buf.numb );
1447
                    print( "</A>" );
1448
                }
1449
 
1450
                /*
1451
                **  Basic information
1452
                **      - Team number - with Xref back to full result
1453
                **      - Full team name
1454
                **      - Full categoray name
1455
                */
1456
                print( "%s", placing(windex) );
1457
 
1458
                print( "  Team Name: ");
1459
                if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), team_buf.numb );
1460
                print( "%-*s ",     MAX_TM_NAME, team_buf.name );
1461
                    if ( report_html == html ) print( "</A>" );
1462
 
1463
                print( "  Number: ");
1464
                if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "finish" ,"html")), team_buf.numb );
1465
                print( "%4d",       team_buf.numb );
1466
                if ( report_html == html ) print( "</A>" );
1467
 
1468
 
1469
                for( k = 0; k < MAX_MEMB; k++ )
1470
                {
1471
 
1472
                    /*
1473
                    **  Skip equestrian leg in the non-equestion display
1474
                    */
1475
                    if ( k + 1 == config.equestrian_leg && ptr->teamclass == config.nonequestrian_class)
1476
                        continue;
1477
 
1478
                    print( "\n");
1479
                    print( "    ");
1480
                    print( "%-*s", MAX_PERSON_NAME, config.leg_name[k] ? config.leg_name[k] : "Competitor"  );
1481
                    print( " %-*s", MAX_PERSON_NAME, team_buf.members[k].name );
1482
 
1483
                    print( "  %-8s", time_a( team_buf.leg[k+1].elapsed ) );
1484
                }
1485
 
1486
                print( "\n");
1487
                print( "    ");
1488
                print_bold( TRUE );
1489
                print( "%-*s %-*s  %-8s", MAX_PERSON_NAME , "Total" ,MAX_PERSON_NAME, "",time_a( team_buf.leg[0].elapsed ) );
1490
                print_bold( FALSE );
1491
                print( "\n" );
1492
            }
1493
 
1494
 
1495
            /*
1496
            **  More to do
1497
            */
1498
            if ( windex >= config.class_winners[j-1] )
1499
            {
1500
                break;
1501
            }
1502
        }
1503
    }
1504
 
1505
    /*
1506
    **  Generate the Hall of Fame information
1507
    */
1508
    print( "\n");
1509
    if ( report_html == html )
1510
    {
1511
        print( "<hr>" );
1512
        print( "<A name=\"%s\"></A>",url_encode("Hall Of Fame"));
1513
    }
1514
    else
1515
    {
1516
        print( "%s\n", solid_line);
1517
    }
1518
    print( "%s",  "Hall of Fame" );
1519
 
1520
    if ( config.num_fame  )
1521
    {
1522
        for( i = 1; i <= config.num_fame; i++ )
1523
        {
1524
            print( "\n");
1525
            print( "    %-*s", MAX_PERSON_NAME, config.hall_fame[i-1] );
1526
        }
1527
    }
1528
    else
1529
    {
1530
        printf( "\n    There are no new stars for the Hall of Fame");
1531
    }
1532
    if ( report_html == html ) print( "\n");
1533
    if ( report_html == html ) print( "<A HREF=\"#%s\">Awards Index</A>",url_encode("INDEX"));
1534
 
1535
    /*
1536
    **  Generate the FASTEST information
1537
    */
1538
    print( "\n" );
1539
    print( "\n");
1540
    if ( report_html == html )
1541
    {
1542
        print( "<hr>" );
1543
        print( "<A name=\"%s\"></A>",url_encode("FASTEST"));
1544
    }
1545
    else
1546
    {
1547
        print( "%s\n", solid_line);
1548
    }
1549
    print( "%s",  "FASTEST" );
1550
 
1551
    /*
1552
    **  Sort the data and then generate the stats - again
1553
    */
1554
    do_big_sort();
1555
    gen_stats();
1556
 
1557
    for( i = 1; i <= config.num_legs; i++ )
1558
    {
1559
        g_record( stats.fast.team[i][0], &team_buf );
1560
 
1561
        print( "\n");
1562
        print( "    %-13s ", config.leg_name[i - 1] );
1563
        print( "  Name: ");
1564
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), team_buf.numb );
1565
        print( "%-*s", MAX_PERSON_NAME, team_buf.members[i-1].name );
1566
        if ( report_html == html ) print( "</A>" );
1567
        print( "  Team :");
1568
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "finish" ,"html")), team_buf.numb );
1569
        print( "%4d" , stats.fast.team[i][0] );
1570
        if ( report_html == html ) print( "</A> " );
1571
        print( "Time:%s ", time_a( stats.fast.time[i][0] ) );
1572
 
1573
    }
1574
 
1575
    if ( report_html == html ) print( "\n");
1576
    if ( report_html == html ) print( "<A HREF=\"#%s\">Awards Index</A>",url_encode("INDEX"));
1577
    print( "\n");
1578
    close_printer();
1579
}
1580
 
1581
/*========================================================================
1582
 *
1583
 *  pri_master_index
1584
 *
1585
 *  Purpose:
1586
 *      This function is called to create an HTML page that references all
1587
 *      the other pages that have been generated
1588
 *
1589
 *      Assume that they are in the same directory
1590
 *
1591
 *  Parameters:
1592
 *      None
1593
 *
1594
 *  Returns:
1595
 *      Nothing
1596
 *
1597
 *========================================================================*/
1598
void pri_master_index_entry(const char *name, const char *text)
1599
{
1600
    print( "<tr><td>");
1601
    print ("<A HREF=\"%s\">%s</A>\n", url_encode(p_filename(filebase, name ,"html")), text );
1602
}
1603
 
1604
 
1605
void pri_master_index(void)
1606
{
1607
    int j;
1608
 
1609
    report_html = html;
1610
    if( !open_printer( "", "index", 132, report_html, "Master Index" ) )
1611
        return;
1612
 
1613
    /*
1614
    **  Names
1615
    */
1616
    print( "<TABLE border=0 align=center>" );
1617
    pri_master_index_entry( "name", "Team list" );
1618
    pri_master_index_entry( "competitor", "Competitor list" );
1619
    pri_master_index_entry( "finish", "Finishing Order for all Teams" );
1620
    pri_master_index_entry( "awards", "Prizes and Awards" );
1621
    print( "<tr><td>\n" );
1622
 
1623
    print( "\n" );
1624
    for( j = 1; j <= config.num_class; j++ )
1625
    {
1626
        pri_master_index_entry( config.team_class[j - 1].abr, tprintf("Category Results for: %s", config.team_class[j-1].full_name) );
1627
    }
1628
 
1629
    print( "</TABLE>" );
1630
 
1631
    close_printer();
1632
 
1633
    /*
1634
    **  A small page to hold the Leg End displays
1635
    */
1636
 
1637
    if( !open_printer( "", "legindex", 132, report_html, "Master Index with trace data" ) )
1638
        return;
1639
 
1640
    /*
1641
    **  Names
1642
    */
1643
    print( "<TABLE border=0 align=center>" );
1644
#if 1
1645
    pri_master_index_entry( "name", "Team list" );
1646
    pri_master_index_entry( "competitor", "Competitor list" );
1647
    pri_master_index_entry( "finish", "Finishing Order for all Teams" );
1648
    pri_master_index_entry( "awards", "Prizes and Awards" );
1649
    print( "<tr><td>\n" );
1650
 
1651
    print( "\n" );
1652
    for( j = 1; j <= config.num_class; j++ )
1653
    {
1654
        pri_master_index_entry( config.team_class[j - 1].abr, tprintf("Category Results for: %s", config.team_class[j-1].full_name) );
1655
    }
1656
#endif
1657
    print( "<tr><td>\n" );
1658
 
1659
    print( "\n" );
1660
    for ( leg = 1; leg <= config.num_legs; leg ++ )
1661
    {
1662
        pri_master_index_entry( tprintf("lg%1.1d", leg), tprintf("Leg End Results for: %d", leg) );    
1663
    }
1664
 
1665
    print( "<tr><td>\n" );
1666
    print( "\n" );
1667
 
1668
    for ( leg = 1; leg <= config.num_legs; leg ++ )
1669
    {
1670
        pri_master_index_entry( tprintf("le%1.1d", leg), tprintf("Leg Elapsed Time Results for: %d", leg) );
1671
    }    
1672
 
1673
 
1674
    print( "</TABLE>" );
1675
 
1676
    close_printer();
1677
 
1678
}
1679
 
1680
 
1681
/*========================================================================
1682
 *
1683
 *  Print interim results
1684
 *
1685
 *  Purpose:
1686
 *      This function is called to Print interim results
1687
 *
1688
 *  Parameters:
1689
 *      None
1690
 *
1691
 *  Returns:
1692
 *      Nothing
1693
 *
1694
 *========================================================================*/
1695
 
1696
void pri_interim(void)
1697
{
1698
    ty_s_data  *ptr;
1699
    unsigned    i;
1700
    int         j, last_class;
1701
    char        suppress_classes = FALSE;                /* Boolean. Printout class files too */
1702
    char       *report_title;
1703
 
1704
    if ( ! report_all )
1705
    {
162 david 1706
        //cur( 0, 5 );
95 - 1707
        printf( "Generate interim result printouts\n" );
1708
        ck_data( -1, C_DISQUAL );                    /* Check the data - dummy check */
162 david 1709
        suppress_classes = FALSE; //getyes( "Do you want to suppress class printouts" );
95 - 1710
        printf( "\nSorting the data\n" );
1711
    }
1712
    do_big_sort();                             /* Sort on every thing */
1713
    gen_stats();                               /* Generate the stats too */
1714
 
1715
    printf( "\nGenerating the printed output\n" );
1716
 
1717
    /*
1718
     * Now print the data on the printer 
1719
     */
1720
 
1721
    if( !open_printer( "", "int", 132, report_html, "Interim Results" ) )
1722
        return;
1723
 
1724
    /*
1725
     * Print out the data 
1726
     */
1727
    print_class_header( -1, FALSE );                     /* Print the header */
1728
 
1729
    ptr = sort_data;
1730
    sort_team_data( 0, S_TEAM );                   /* Re-sort on team number */
1731
    for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
1732
    {
1733
        if ( ptr->teamclass == config.nonequestrian_class )
1734
            continue;
1735
 
1736
        g_record( ptr->team, &team_buf );
1737
 
1738
        print( "%4d %4.4s %-*s",
1739
               team_buf.numb,
1740
               pi_place( team_buf.leg[config.num_legs].le_place,
1741
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ),
1742
               3,
1743
               team_buf.teamclass ==
1744
 
1745
        for( j = 1; j <= config.num_legs; j++ )
1746
        {
1747
            print( "  %-8s %4.4s %4.4s",
1748
                   time_fa( team_buf.leg[j].elapsed,
1749
                            ptr->flags.disqualified ),
1750
                   pi_place( team_buf.leg[j].l_place, ptr->flags.disqualified,
1751
                             team_buf.leg[j].elapsed ),
1752
                   pi_place( team_buf.leg[j].le_place,
1753
                             ptr->flags.disqualified,
1754
                             team_buf.leg[j].elapsed ) );
1755
        }
1756
        print( "  %-8s %4.4s\n",
1757
               time_fa( team_buf.leg[0].elapsed, ptr->flags.disqualified ),
1758
               pi_place( team_buf.leg[config.num_legs].lec_place,
1759
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ) );
1760
    }
1761
 
1762
    print_class_stats( -1, FALSE );             /* Print statistics */
1763
    print_legend(-1, 1);                        /* Print the legend */
1764
    close_printer();                            /* Close the printer */
1765
 
1766
 
1767
    /*
1768
     * Now produce a breakdown on a class by class basis 
1769
     * Now print out the class placement information
1770
     */
1771
 
1772
    if( suppress_classes )
1773
    {
1774
        printf( "WARNING: Class printouts suppressed\n" );
1775
        return;
1776
    }
1777
 
1778
    sort_team_data( 0, S_CLASS );              /* Generate class placement data */
1779
    last_class = -1;                             /* Invalid class to start with */
1780
 
1781
    for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
1782
    {
1783
        /*
1784
        **  Detect a change in the "class"
1785
        **  All data is within the one array of data
1786
        **  Use the in-memory class as this MAY differ from that stored
1787
        **  The non-equestrian class does this.
1788
        */
1789
        if( last_class != ptr->teamclass )
1790
        {
1791
            if( last_class >= 0 )
1792
            {
1793
                print_class_stats( last_class, TRUE );
1794
                print_legend(last_class, 1);
1795
                close_printer();
1796
            }
1797
 
1798
            report_title = tprintf( "Interim Category results for : %-*s", LEN_CLASS_NAME, team_buf.teamclass == 0 ? "" : config.team_class[ptr->teamclass - 1].full_name );
1799
 
1800
            if( !open_printer( "", tprintf( "i%2s", config.team_class[ptr->teamclass - 1].abr ), 132, report_html, report_title ) )
1801
                continue;
1802
            print_class_header( last_class = ptr->teamclass, FALSE );
1803
        }
1804
 
1805
        /*
1806
        **  Now read in the team record
1807
        */
1808
        g_record( ptr->team, &team_buf );
1809
        print( "%4d %4.4s %-*s",
1810
               team_buf.numb,
1811
               pi_place( team_buf.leg[config.num_legs].lec_place,
1812
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ),
1813
               3,
1814
               team_buf.teamclass ==
1815
 
1816
        for( j = 1; j <= config.num_legs; j++ )
1817
        {
1818
            print( "  %-8s %4.4s %4.4s",
1819
                   time_fa( team_buf.leg[j].elapsed,
1820
                            ptr->flags.disqualified ),
1821
                   pi_place( team_buf.leg[j].lc_place,
1822
                             ptr->flags.disqualified,
1823
                             team_buf.leg[j].elapsed ),
1824
                   pi_place( team_buf.leg[j].lec_place,
1825
                             ptr->flags.disqualified,
1826
                             team_buf.leg[j].elapsed ) );
1827
        }
1828
        print( "  %-8s %4.4s\n",
1829
               time_fa( team_buf.leg[0].elapsed, ptr->flags.disqualified ),
1830
               pi_place( team_buf.leg[config.num_legs].le_place,
1831
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ) );
1832
    }
1833
 
1834
    print_class_stats( last_class, FALSE );
1835
    print_legend(last_class, 1);
1836
    close_printer();
1837
 
1838
}
1839
 
1840
/*----------------------------------------------------------------------------
1841
** FUNCTION           : pri_csv_data
1842
**
1843
** DESCRIPTION        : Generate a CSV file of all the report data
1844
**                      It can then be used to play with the data externally
1845
**
1846
**
1847
** INPUTS             : None
1848
**
1849
** RETURNS            : Yes it does
1850
**
1851
----------------------------------------------------------------------------*/
1852
 
1853
 
1854
void pri_csv_data ( void )
1855
{
1856
    int i;
1857
    int j;
1858
    int age_sum;
1859
 
1860
    /*
1861
    **  Sort on every thing
1862
    **  Then generate all the stats too
1863
    */
1864
    printf( "\nSorting the data\n" );
1865
    do_big_sort();
1866
    gen_stats();
1867
 
1868
    /*
1869
     * Now print the data on the printer 
1870
     */
1871
 
1872
    if( !open_printer( "full_data", "csv", 2000, text, NULL ) )
1873
        return;
1874
 
1875
    printf( "\nGenerating the printed output\n" );
1876
 
1877
    /*
1878
    **  Print headings
1879
    */
1880
    csv_print( "%s",   "Team Number" );
1881
    csv_print( "%s",   "Team Name" );
1882
 
1883
    csv_print( "%s",    "Class Full");
1884
    csv_print( "%s",    "Class Abr");
1885
    csv_print( "%s",    "Class Start Time");
1886
    csv_print( "%s",    "Class Start Time Number");
1887
 
1888
    csv_print( "%s",    "Team Country");
1889
 
1890
    for( j = 1; j <= config.num_legs; j++ )
1891
    {
1892
        csv_print( "%s", "Leg Number" );
1893
        csv_print( "%s", "Leg Name");
1894
        csv_print( "%s", "Competitor Name");
1895
        csv_print( "%s", "Sex" );
1896
        csv_print( "%s", "Age");
1897
        csv_print( "%s", "Start Time");
1898
        csv_print( "%s", "Start Time Number");
1899
        csv_print( "%s", "End Time" );
1900
        csv_print( "%s", "End Time Number" );
1901
        csv_print( "%s", "Elapsed Time");
1902
        csv_print( "%s", "Elapsed Time Number");
1903
        csv_print( "%s", "Leg Place");
1904
        csv_print( "%s", "Leg End Place");
1905
        csv_print( "%s", "Leg Class Place");
1906
        csv_print( "%s", "Leg End Class Place");
1907
        csv_print( "%s", "Manual");
1908
    }
1909
 
1910
    j = 0;
1911
    csv_print( "%s", "Team Start Time");
1912
    csv_print( "%s", "Team Start Time Number");
1913
    csv_print( "%s", "Team End Time");
1914
    csv_print( "%s", "Team End Time Number");
1915
    csv_print( "%s", "Team Elapsed Time");
1916
    csv_print( "%s", "Team Elapsed Time Number");
1917
//            csv_print( "%s", team_buf.leg[j].l_place );
1918
    csv_print( "%s", "Team Leg End Place");
1919
//            csv_print( "%s", team_buf.leg[j].lc_place );
1920
    csv_print( "%s", "Team Leg Class Place");
1921
//            csv_print( "%s", team_buf.leg[j].manual );
1922
 
1923
    csv_print( "%s", "Total Team Age");
1924
    csv_print( "%s", "Flag:valid Team");
1925
    csv_print( "%s", "Flag:bad_times" );
1926
    csv_print( "%s", "Flag:disqualified" );
1927
    csv_print( "%s", "Flag:non_equestrian" );
1928
    csv_print("\n");
1929
 
1930
 
1931
    for( i = config.min_team; i <= config.max_team; i++ )
1932
    {
1933
        if( valid_field( i ) && g_record( i, &team_buf ) )
1934
        {
1935
            /*
1936
            **  Basic information
1937
            **      - Team number - with Xref back to full result
1938
            **      - Full team name
1939
            **      - Full categoray name - with Xref to category results
1940
            **      - Country name
1941
            */
1942
            csv_print( "%d",   team_buf.numb );
1943
            csv_print( "%s",   team_buf.name );
1944
 
1945
            csv_print( "%s",    team_buf.teamclass == 0 ? "" : config.team_class[team_buf.teamclass - 1].full_name );
1946
            csv_print( "%s",    team_buf.teamclass == 0 ? "" : config.team_class[team_buf.teamclass - 1].abr );
1947
            csv_print( "%s",    time_a (team_buf.teamclass == 0 ? 0 : config.team_class[team_buf.teamclass - 1].start ));
1948
            csv_print( "%d",    team_buf.teamclass == 0 ? 0 : config.team_class[team_buf.teamclass - 1].start );
1949
 
1950
            csv_print( "%s",    config.num_countries == 0
1951
                                || team_buf.country ==
1952
 
1953
 
1954
            age_sum = 0;
1955
            for( j = 1; j <= config.num_legs; j++ )
1956
            {
1957
                csv_print( "%d", j );
1958
                csv_print( "%s", config.leg_name[j - 1] );
1959
                csv_print( "%s", team_buf.members[j-1].name );
1960
                csv_print( "%s", ( team_buf.members[j-1].sex == male ) ? "Male" : "Female" );
1961
                csv_print( "%d", team_buf.members[j-1].age );
1962
                if ( age_sum >= 0 )
1963
                {
1964
                    ushort age = team_buf.members[j-1].age;
1965
                    if ( age > 0 && age < 255 )
1966
                    {
1967
                        age_sum += age;
1968
                    }
1969
                    else
1970
                    {
1971
                        age_sum = -1;
1972
                    }
1973
                }
1974
 
1975
 
1976
                csv_print( "%s", time_a(team_buf.leg[j].start ));
1977
                csv_print( "%d", team_buf.leg[j].start );
1978
                csv_print( "%s", time_a(team_buf.leg[j].end ));
1979
                csv_print( "%d", team_buf.leg[j].end );
1980
                csv_print( "%s", time_a(team_buf.leg[j].elapsed ));
1981
                csv_print( "%d", team_buf.leg[j].elapsed );
1982
                csv_print( "%d", team_buf.leg[j].l_place );
1983
                csv_print( "%d", team_buf.leg[j].le_place );
1984
                csv_print( "%d", team_buf.leg[j].lc_place );
1985
                csv_print( "%d", team_buf.leg[j].lec_place );
1986
                csv_print( "%d", team_buf.leg[j].manual );
1987
            }
1988
 
1989
            j = 0;
1990
            csv_print( "%s", time_a(team_buf.leg[j].start ));
1991
            csv_print( "%d", team_buf.leg[j].start );
1992
            csv_print( "%s", time_a(team_buf.leg[j].end ));
1993
            csv_print( "%d", team_buf.leg[j].end );
1994
            csv_print( "%s", time_a(team_buf.leg[j].elapsed ));
1995
            csv_print( "%d", team_buf.leg[j].elapsed );
1996
//            csv_print( "%d", team_buf.leg[j].l_place );
1997
            csv_print( "%d", team_buf.leg[j].le_place );
1998
//            csv_print( "%d", team_buf.leg[j].lc_place );
1999
            csv_print( "%d", team_buf.leg[j].lec_place );
2000
//            csv_print( "%d", team_buf.leg[j].manual );
2001
 
2002
            csv_print( "%d", age_sum );
2003
            csv_print( "%d", team_buf.flags.valid );
2004
            csv_print( "%d", team_buf.flags.bad_times );
2005
            csv_print( "%d", team_buf.flags.disqualified );
2006
            csv_print( "%d", team_buf.flags.non_equestrian );
2007
 
2008
//How about class placings
2009
 
2010
 
2011
            csv_print( "\n" );
2012
        }
2013
    }
2014
 
2015
    close_printer();
2016
}
2017
 
2018
 
2019
/*========================================================================
2020
 *
2021
 *  Print all reports at once
2022
 *  Its all so fast, these days ...
2023
 *
2024
 *  Purpose:
2025
 *      This function is called to print all reports at once
2026
 *
2027
 *  Parameters:
2028
 *      None
2029
 *
2030
 *  Returns:
2031
 *      Nothing
2032
 *
2033
 *========================================================================*/
2034
 
2035
void pri_all_reports ( void )
2036
{
2037
    int leg;
2038
    report_all = TRUE;
2039
 
2040
    pri_team();
2041
 
2042
    for ( leg = 1; leg <= config.num_legs; leg ++ )
2043
    {
2044
        pri_leg_body ( leg );
2045
        pri_eleg_body ( leg );
2046
 
2047
        report_html = html;
2048
 
2049
        pri_leg_body ( leg );
2050
        pri_eleg_body ( leg );        
2051
 
2052
        report_html = text;
2053
    }
2054
 
2055
    pri_final();
2056
    pri_final_html();
2057
    pri_csv_data();
2058
    pri_summary();
2059
    pri_awards_html();
2060
    pri_awards();
2061
    pri_master_index();
2062
 
172 david 2063
    pri_interim();
2064
 
95 - 2065
    report_all = FALSE;
2066
}
2067
 
2068
 
2069
/*========================================================================
2070
 *
2071
 *  Print a class header
2072
 *
2073
 *  Purpose:
2074
 *      This function is called to print a class header
2075
 *
2076
 *  Parameters:
2077
 *      class           Name of this class
2078
 *      final           False - prelim results
2079
 *
2080
 *  Returns:
2081
 *      Nothing
2082
 *
2083
 *========================================================================*/
2084
 
2085
void print_class_header( int teamclass, int final )
2086
{
2087
    int         j;
2088
 
2089
    /*
2090
    **  Give a clear indication that the report is preliminary
2091
    */
2092
 
2093
    if( !final )
2094
        print( "PRELIMINARY RESULTS ONLY\n\n" );
2095
 
2096
    /*
2097
    **  Now printout the column headings
2098
    **  This is a two line display
2099
    **
2100
    **  Line-1  Leg names
2101
    */
2102
    print( "%-*s %-*s %-*s", 4, "", 4, "", 3, "" );
2103
    for( j = 1; j <= config.num_legs; j++ )
2104
    {
2105
        print_bold( TRUE );
2106
        print( "  %-*s", 18, config.leg_name[j - 1] );
2107
        print_bold( FALSE );
2108
    }
2109
    print( "  %-8s %-4s\n", "Total", ( teamclass < 0 ) ? "Cat" : "Fin" );
2110
 
2111
 
2112
    /*
2113
    **  Line-2  Details
2114
    */
2115
    print_underline( TRUE );
2116
    print( "%-*s %*s %-*s", 4, final ? "Plce" : "Team",
2117
                            4, final ? "Team" : "Plce",
2118
                            3, "Cat" );
2119
 
2120
    for( j = 1; j <= config.num_legs; j++ )
2121
        print( "  %-8s %-4s %-4s", "Time", " LP", " EP" );
2122
 
2123
    print( "  %-8s %-4s\n", "Time", "Plce" );
2124
    print_underline( FALSE );
2125
}
2126
 
2127
/*========================================================================
2128
 *
2129
 *  Generate the class stats
2130
 *
2131
 *  Purpose:
2132
 *      This function is called to Generate the class stats
2133
 *
2134
 *  Parameters:
2135
 *      c           Class to print
2136
 *      final       TRUE: Final data
2137
 *                  FALSE: Interim data
2138
 *
2139
 *  Returns:
2140
 *      Nothing
2141
 *
2142
 *========================================================================*/
2143
 
2144
void print_class_stats( int c, int final )
2145
{
2146
    int         i, j;
2147
    const char        *title;
2148
 
2149
    if( c < 0 )
2150
    {
2151
        title = "Event";
2152
        c = 0;
2153
    }
2154
    else
2155
    {
2156
        title = "Category";
2157
    }
2158
 
2159
    print( "\n" );
2160
    if ( report_html ) print_underline(TRUE);
2161
    print( "%s statistics", title );
2162
    if ( report_html ) print_underline(FALSE);
2163
    print( "\n" );
2164
 
2165
 
2166
    /*
2167
    **  Print the names of the different legs
2168
    */
2169
    print( "%-*s       ", LEN_CLASS_NAME, "" );
2170
    for( i = 1; i <= config.num_legs; i++ )
2171
    {
2172
        print_bold( TRUE );
2173
        print( "%-13s  ", config.leg_name[i - 1] );
2174
        print_bold( FALSE );
2175
    }
2176
    print( "%-13s  \n", final ? "Total" : "" );
2177
 
2178
    /*
2179
    **  Print the fastest teams for each leg and overall
2180
    **  Add cross references to the team names for the fastest teams
2181
    */
2182
    print( "%*s : ", LEN_CLASS_NAME, "Fastest" );
2183
    for( i = 0; i <= config.num_legs; i++ )
2184
    {
2185
        j = i + 1;
2186
        if( i >= config.num_legs )
2187
        {
2188
            if( final )
2189
                j = 0;                           /* Leg-0 last */
2190
            else
2191
                break;
2192
        }
2193
 
2194
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), stats.fast.team[j][c] );
2195
        print( "%4d",  stats.fast.team[j][c] );
2196
        if ( report_html == html ) print( "</A>" );
2197
        print( " %s  ", time_a( stats.fast.time[j][c] ) );
2198
    }
2199
    print( "\n" );
2200
 
2201
    /*
2202
    **  Print the average time for each leg
2203
    */
2204
    print( "%*s : ", LEN_CLASS_NAME, "Average" );
2205
    for( i = 0; i <= config.num_legs; i++ )
2206
    {
2207
        j = i + 1;
2208
        if( i >= config.num_legs )
2209
        {
2210
            if( final )
2211
                j = 0;                           /* Leg-0 last */
2212
            else
2213
                break;
2214
        }
2215
        print( "     %s  ", time_a( stats.average[j][c] ) );
2216
    }
2217
}
2218
 
2219
/*========================================================================
2220
 *
2221
 *  Print the legend
2222
 *
2223
 *  Purpose:
2224
 *      This function is called to Print the legend
2225
 *
2226
 *  Parameters:
2227
 *      class       - Class currently being printed
2228
 *      full        - Display full legend
2229
 *
2230
 *  Returns:
2231
 *      Nothing
2232
 *
2233
 *========================================================================*/
2234
 
2235
void print_legend ( int teamclass, int full )
2236
{
2237
 
2238
    int         i;
2239
    char        line[201];
2240
    FILE       *adfile = NULL;
2241
    int         count;
2242
 
2243
    /*
2244
     * First the categories 
2245
     */
2246
    print( "\n\n" );
2247
    if ( report_html ) print_underline(TRUE);
2248
    print( "Category abbreviations" );
2249
    if ( report_html ) print_underline(FALSE);
2250
    print( "\n" );
2251
 
2252
 
2253
    for( i = 1, count = 0; i <= config.num_class; i++ )
2254
    {
2255
#if 0
2256
        /*
2257
        **  Skip any non-equestrian class in the legend
2258
        **  Don't want to tell the general user whats goes on, unless we actually
2259
        **  creating the non-equestrian report.
2260
        */
2261
        if ( class != config.nonequestrian_class  && i == config.nonequestrian_class )
2262
            continue;
2263
#endif
2264
        if ( report_html == html ) print( "<A HREF=\"%s\">",url_encode(p_filename(filebase, config.team_class[i - 1].abr ,"html")) );
2265
        print( "%-*s", 3, config.team_class[i - 1].abr );
2266
        if ( report_html == html ) print( "</A>" );
2267
        print( " : %-*s  ", LEN_CLASS_NAME, config.team_class[i - 1].full_name );
2268
 
2269
        if( !( ++count % 5 ) )
2270
            print( "\n" );
2271
    }
2272
 
2273
    /*
2274
    **  Add link to the finish order report
2275
    */
2276
    if ( report_html == html )
2277
    {
2278
        print( "<A HREF=\"%s\">", url_encode(p_filename(filebase, "finish" ,"html")) );
2279
        print( "%-*s", 3, "All" );
2280
        print( "</A>" );
2281
        print( " : %-*s  ", LEN_CLASS_NAME, "Finishing Order" );
2282
    }
2283
 
2284
    /*
2285
    **  Country data - if countries have been defined
2286
    */
2287
    if( config.num_countries )
2288
    {
2289
        print( "\n\n" );
2290
        if ( report_html ) print_underline(TRUE);
2291
        print( "Country abbreviations" );
2292
        if ( report_html ) print_underline(FALSE);
2293
        print( "\n" );
2294
 
2295
        for( i = 0, count = 0; i < MAX_COUNTRY; i++ )
2296
        {
2297
            if( config.country_name[i].abr[0] )
2298
            {
2299
                print( "%-*s : %-*s  ", 4, config.country_name[i].abr,
2300
                       LEN_CNTRY_NAME, config.country_name[i].full_name );
2301
                if( !( ++count % 5 ) )
2302
                    print( "\n" );
2303
            }
2304
        }
2305
    }
2306
    print( "\n" );
2307
 
2308
    /*
2309
     * Other comments 
2310
     */
2311
    if ( full )
2312
    {
2313
        print( "\nPlace numbers (LP and EP)\n" );
2314
        print( "LP - Placing based on elapsed time within the leg.                Cat Plce - Placing within the category.\n" );
2315
        print( "EP - Placing based on accumulated times to the end of that leg.   Fin Plce - Overall placing within the event.\n" );
2316
        print( "U  - Placing not available.\n" );
2317
    }
2318
 
2319
    /*
2320
     *  Insert the contents of the config.addendum file
2321
     *  or a defualt message
2322
     */
2323
    if( config.addendum[0] )
2324
        adfile = fopen( config.addendum, "rt" );  /* Open the file for reading */
2325
 
2326
    if( adfile )
2327
    {
2328
        while( fgets( line, sizeof(line)-1, adfile ) )
2329
            print( "%s", line );
2330
    }
2331
    else
2332
    {
2333
        print( "\nTiming and Results by\n" );
2334
        print( "Embedded Solutions\n" );
2335
    }
2336
}
2337
 
2338
/*========================================================================
2339
 *
2340
 *  Return place data
2341
 *
2342
 *  Purpose:
2343
 *      This function is called to return place data
2344
 *
2345
 *      This routine is called to fill a print team_buffer - to allow for
2346
 *      multiple calls to this function ( before the data is used ) a number
2347
 *      of static team_buffers are maintained
2348
 *
2349
 *  Parameters:
2350
 *      num         place - if not bad_times
2351
 *      disq        Disqualified flag
2352
 *      time        Time data is based on
2353
 *
2354
 *  Returns:
2355
 *      This function returns a pointer to the character string for the
2356
 *      number or a pointer to a bad_times string.
2357
 *
2358
 *========================================================================*/
2359
 
2360
const char       *pi_place( int num, int disq, time_t time )
2361
{
2362
    static char store[2][5];                     /* 2 stores for 4 digit numbers */
2363
    static int  i = 0;                           /* Current index into store */
2364
    static const char *dis = "D";                      /* Disqualified */
2365
    static const char *non = "-";                      /* Invalid time */
2366
 
2367
    if( disq )                                   /* Disqualified team */
2368
        return ( dis );
2369
    if( time <= 0 )                              /* Unknown time */
2370
        return ( non );
2371
 
2372
    i++;
2373
    if( i >= 2 )
2374
        i = 0;                                   /* Select next entry */
2375
    sprintf( store[i], "%4d", num );
2376
    return ( store[i] );
2377
 
2378
}
2379
 
2380
/*========================================================================
2381
 *
2382
 *  Return place data
2383
 *
2384
 *  Purpose:
2385
 *      This function is called to Return place data
2386
 *
2387
 *      This routine is called to fill a print team_buffer - to allow for
2388
 *      multiple calls to this function ( before the data is used ) a number
2389
 *      of static team_buffers are maintained
2390
 *
2391
 *  Parameters:
2392
 *      num         place - if not bad_times
2393
 *      disq        Disqualified flag
2394
 *
2395
 *  Returns:
2396
 *      This function returns a pointer to the character string for the
2397
 *      number or a pointer to a bad_times string.
2398
 *
2399
 *========================================================================*/
2400
 
2401
const char *pr_place( int num, int disq )
2402
{
2403
    static char store[2][5];                     /* 2 stores for 4 digit numbers */
2404
    static int  i = 0;                           /* Current index into store */
2405
    static const char *dis = "U";
2406
 
2407
    if( disq )
2408
        return ( dis );
2409
 
2410
    i++;
2411
    if( i >= 2 )
2412
        i = 0;                                   /* Select next entry */
2413
    sprintf( store[i], "%4d", num );
2414
    return ( store[i] );
2415
 
2416
}
2417
 
2418
/*========================================================================
2419
 *
2420
 *  Return place data
2421
 *
2422
 *  Purpose:
2423
 *      This function is called to Return place data
2424
 *
2425
 *      This routine is called to fill a print team_buffer - to allow for
2426
 *      multiple calls to this function ( before the data is used ) a number
2427
 *      of static team_buffers are maintained
2428
 *
2429
 *  Parameters:
2430
 *      num         place - if not bad_times
2431
 *      disq        Disqualified flag
2432
 *      ne          Non Equestrian Flag
2433
 *
2434
 *  Returns:
2435
 *      This function returns a pointer to the character string for the
2436
 *      number or a pointer to a bad_times string.
2437
 *
2438
 *========================================================================*/
2439
 
2440
const char *pr_place_ne( int num, int disq, int ne )
2441
{
2442
    static char store[2][5];                     /* 2 stores for 4 digit numbers */
2443
    static int  i = 0;                           /* Current index into store */
2444
    static const char *dis = "U";
2445
 
2446
    if( disq && ! ne )
2447
         return ( dis );
2448
 
2449
    if( ++i >= 2 )
2450
        i = 0;                                   /* Select next entry */
2451
    sprintf( store[i], "%4d", num );
2452
    return ( store[i] );
2453
 
2454
}
2455
 
2456
/*========================================================================
2457
 *
2458
 *  Check data for bad times
2459
 *
2460
 *  Purpose:
2461
 *      This function is called to Check data for bad times
2462
 *      Scan the sort data structure and locate entries that have incorrect
2463
 *      times.
2464
 *      
2465
 *      Entries that have invalid leg times are displayed to the operator
2466
 *      and the report process can be aborted
2467
 *
2468
 *  Parameters:
2469
 *      leg         Leg to test
2470
 *      mode            Either end or elapsed times to be tested
2471
 *
2472
 *  Returns:
2473
 *      Returns FALSE if the report operation is to be aborted
2474
 *
2475
 *========================================================================*/
2476
 
2477
bool ck_data( int leg, int mode )
2478
{
2479
    ty_s_data  *ptr;
2480
    unsigned    i;
2481
    int         bad = 0;
2482
    int         j = 0;
2483
    int         k, bad_leg;
2484
    time_t     *t;                               /* An array of times */
2485
 
2486
 
2487
 
2488
    ptr = sort_data;
2489
    for( i = 1; i <= sort_num; i++, ptr++ )
2490
    {
2491
        bad_leg = 0;
2492
        if( mode == C_DISQUAL )
2493
        {
2494
            ptr->flags.bad_times = ptr->flags.disqualified;
2495
            continue;
2496
        }
2497
 
2498
        if( mode == C_ELAPSED )
2499
            t = ptr->lege;
2500
        else
2501
            t = ptr->leg;
2502
 
2503
 
2504
        if ( leg >= 0 )
2505
        {
2506
            ptr->flags.bad_times = (ptr->flags.disqualified && ! ptr->flags.non_equestrian);
2507
        }
2508
        else
2509
        {
2510
            ptr->flags.bad_times = ptr->flags.disqualified;
2511
        }
2512
 
2513
        if( ! ptr->flags.bad_times )
2514
        {
2515
            if( leg <= 0 )
2516
            {
2517
                for( k = 0; k <= config.num_legs; k++ )
2518
                {
2519
                    if ( !(config.equestrian_leg && ptr->flags.non_equestrian && config.equestrian_leg == k  ))
2520
                        bad_leg |= ( t[k] <= 0 );
2521
                }
2522
            }
2523
            else
2524
            {
2525
                bad_leg = t[leg] <= 0;
2526
            }
2527
 
2528
            if( bad_leg )
2529
            {
2530
                ptr->flags.bad_times = TRUE;
2531
 
2532
                if ( ! report_all )
2533
                {
2534
                    if( !bad )
2535
                        printf( "Team with incorrect time information\n" );
2536
                    if( ++j > 15 )
2537
                    {
2538
                        printf( "\n" );
2539
                        j = 0;
2540
                    }
2541
                    printf( "%4d ", ptr->team );
2542
                    bad++;
2543
                }
2544
            }
2545
        }
2546
    }
2547
 
2548
    if( bad )
2549
    {
160 - 2550
        printf( "\n%d teams with incorrect times.\nThese have been flagged as unplaced - continue report\n", bad );
2551
        return ( FALSE );
2552
//        return ( !getyes
2553
//                 ( "These have been flagged as unplaced - continue report" ) );
95 - 2554
    }
2555
    return ( FALSE );
2556
}
2557
 
2558
/*========================================================================
2559
 *
2560
 *  Update placing information
2561
 *
2562
 *  Purpose:
2563
 *      This function is called to Update placing information
2564
 *
2565
 *      This routine will rip through the data generating the team placing in
2566
 *      a) Within a leg
2567
 *      b) At the end of a leg
2568
 *      c) Within a leg by  class
2569
 *      d) At the end of a leg by class
2570
 *
2571
 *      This function is provided to allow the display routines to
2572
 *      be accessed and updated without the need to run a report
2573
 *
2574
 *  Parameters:
2575
 *      xxxx        a ptr to the xxxx stuff
2576
 *
2577
 *  Returns:
2578
 *      Nothing
2579
 *
2580
 *========================================================================*/
2581
 
2582
void srt_place(void)
2583
{
2584
    int         i, j;
2585
 
160 - 2586
//    cur( 0, 5 );
2587
//    printf( "Update the team placings to the data base\n" );
2588
//    flush_out();
95 - 2589
    if( ck_data( -1, C_ELAPSED ) )
2590
        return;
2591
    do_big_sort();
2592
 
2593
    /*
2594
     * Generate the stats and display them on the screen for interest
2595
     * This operation will not hurt - so why not
2596
     */
2597
 
2598
    gen_stats();
2599
    printf( "\nEvent statistics\n\n" );
2600
    printf( "%-*s   %-13s ", LEN_CLASS_NAME, "", "Overall" );
2601
    for( i = 1; i <= config.num_legs; i++ )
2602
        printf( "%-13s ", config.leg_name[i - 1] );
2603
 
2604
    for( j = 0; j <= config.num_class; j++ )
2605
    {
2606
        printf( "\n%-*s : ", LEN_CLASS_NAME,
2607
                j ? config.team_class[j - 1].full_name : "Overall" );
2608
        for( i = 0; i <= config.num_legs; i++ )
2609
        {
2610
            printf( "%4d ", stats.fast.team[i][j] );
2611
            printf( "%s ", time_a( stats.fast.time[i][j] ) );
2612
        }
2613
        printf( "\n%*s : ", LEN_CLASS_NAME, "Average" );
2614
        for( i = 0; i <= config.num_legs; i++ )
2615
        {
2616
            printf( "     %s ", time_a( stats.average[i][j] ) );
2617
        }
2618
    }
160 - 2619
//    printf( "\nAny key to continue" );
2620
//    ( void ) getinp();
95 - 2621
}
2622
 
2623
/*========================================================================
2624
 *
2625
 *  Calculate summary information
2626
 *
2627
 *  Purpose:
2628
 *      This function is called to calculate summary information
2629
 *
2630
 *  Parameters:
2631
 *      ptr         - Address of a summary structure to fill in
2632
 *
2633
 *  Returns:
2634
 *      Nothing
2635
 *
2636
 *========================================================================*/
2637
 
2638
void calc_class_summary( t_class_summary * ptr )
2639
{
2640
    int i;
2641
 
2642
    /*
2643
    **  Reset the data
2644
    */
2645
    memset ( ptr, 0, sizeof (*ptr ));
2646
 
2647
    /*
2648
     * Extract the required data from the data base
2649
     * Only save that information required for the operation
2650
     */
2651
 
2652
    for( i = config.min_team; i <= config.max_team; i++ )
2653
    {
2654
        if( valid_field( i ) && g_record( i, &team_buf ) )
2655
        {
2656
            ptr->total.total++;
2657
            ptr->teamclass[team_buf.teamclass].total++;
2658
 
2659
            if ( team_buf.flags.disqualified )
2660
            {
2661
                ptr->teamclass[team_buf.teamclass].disqualified++;
2662
                ptr->total.disqualified++;
2663
            }
2664
 
2665
            if ( config.nonequestrian_class && team_buf.flags.non_equestrian )
2666
            {
2667
                ptr->teamclass[team_buf.teamclass].non_equestrian++;
2668
                ptr->total.non_equestrian++;
2669
            }
2670
        }
2671
    }
2672
 
2673
    /*
2674
    **  Fix up the totals for the non equestrians
2675
    **  This is not a real category but a summary of the others.
2676
    */
2677
    if ( config.nonequestrian_class  )
2678
    {
2679
        ptr->teamclass[config.nonequestrian_class].total += ptr->total.non_equestrian;
2680
    }
2681
}
2682
 
2683
/*========================================================================
2684
 *
2685
 *  Display summary information
2686
 *
2687
 *  Purpose:
2688
 *      This function is called to display summary information
2689
 *
2690
 *  Parameters:
2691
 *      None
2692
 *
2693
 *  Returns:
2694
 *      Nothing
2695
 *
2696
 *========================================================================*/
2697
 
172 david 2698
//void display_summary (void)
2699
//{
95 - 2700
 
172 david 2701
//    t_class_summary data;
2702
//    int         i;
2703
//    //int         line = 2;
95 - 2704
 
172 david 2705
//    //cur( 0, line );
2706
//    printf( "Generating Summary Information" );
2707
//    calc_class_summary( & data );
95 - 2708
 
2709
 
172 david 2710
//    /*
2711
//    **  Display summary stats
2712
//    */
95 - 2713
 
172 david 2714
//    //cur( 0, line );
2715
//    //console_clreol();
2716
//    printf( "Summary Information\n\n" );
2717
//    printf( "%*s : %-7s %-7s%-7s\n", LEN_CLASS_NAME,
2718
//                                      "Category",
2719
//                                      "Total",
2720
//                                      "Disq",
2721
//                                      "NonEq" );
95 - 2722
 
172 david 2723
//    for( i = 0; i < config.num_class; i++ )
2724
//    {
2725
//        /*
2726
//        **  The non-equestrian leg does not have any data
2727
//        **  Supress the display
2728
//        */
2729
//        if ( config.nonequestrian_class == i+1  )
2730
//            continue;
95 - 2731
 
172 david 2732
//        printf( "%*s : %-7d %-7d %-7d\n", LEN_CLASS_NAME,
2733
//                                          config.team_class[i].full_name,
2734
//                                          data.teamclass[i+1].total,
2735
//                                          data.teamclass[i+1].disqualified,
2736
//                                          data.teamclass[i+1].non_equestrian );
2737
//    }
95 - 2738
 
172 david 2739
//    printf( "\n" );
2740
//    printf( "%*s : %-7d %-7d %-7d\n", LEN_CLASS_NAME,
2741
//                                      "Totals",
2742
//                                      data.total.total,
2743
//                                      data.total.disqualified,
2744
//                                      data.total.non_equestrian );
95 - 2745
 
172 david 2746
////    printf( "\nAny key to continue " );
2747
////    getinp();
2748
//}
95 - 2749
 
2750
/*========================================================================
2751
 *
2752
 *  Print summary information
2753
 *
2754
 *  Purpose:
2755
 *      This function is called to print summary information
2756
 *
2757
 *  Parameters:
2758
 *      None
2759
 *
2760
 *  Returns:
2761
 *      Nothing
2762
 *
2763
 *========================================================================*/
2764
 
2765
void pri_summary (void)
2766
{
2767
 
2768
    t_class_summary data;
2769
    int         i;
162 david 2770
    //int         line = 2;
95 - 2771
 
2772
 
2773
    if( !open_printer( "", "summary", 132, text, "Summary Information" ) )
2774
        return;
2775
 
162 david 2776
    //cur( 0, line );
95 - 2777
    printf( "Generating Summary Information" );
2778
    calc_class_summary( & data );
2779
 
2780
 
2781
    /*
2782
    **  Display summary stats
2783
    */
2784
 
2785
    print( "%*s : %-7s %-7s%-7s\n", LEN_CLASS_NAME,
2786
                                      "Category",
2787
                                      "Total",
2788
                                      "Disq",
2789
                                      "NonEq" );
2790
 
2791
    for( i = 0; i < config.num_class; i++ )
2792
    {
2793
        /*
2794
        **  The non-equestrian leg does not have any data
2795
        **  Supress the display
2796
        */
2797
        if ( config.nonequestrian_class == i+1  )
2798
            continue;
2799
 
2800
        print( "%*s : %-7d %-7d %-7d\n", LEN_CLASS_NAME,
2801
                                          config.team_class[i].full_name,
2802
                                          data.teamclass[i+1].total,
2803
                                          data.teamclass[i+1].disqualified,
2804
                                          data.teamclass[i+1].non_equestrian );
2805
    }
2806
 
2807
    print( "\n" );
2808
    print( "%*s : %-7d %-7d %-7d\n", LEN_CLASS_NAME,
2809
                                      "Totals",
2810
                                      data.total.total,
2811
                                      data.total.disqualified,
2812
                                      data.total.non_equestrian );
2813
 
2814
    close_printer();
2815
    if ( !report_all )
2816
    {
2817
        printf( "\nAny key to continue " );
2818
        getinp();
2819
    }
2820
}
2821
 
2822
 
2823
 
2824
/*========================================================================
2825
 *
2826
 *  Main sort routine for final data
2827
 *
2828
 *  Purpose:
2829
 *      This function is called to do the report sort routine for final data
2830
 *      This routine will fill all the gaps in the sort_aux structure
2831
 *
2832
 *  Parameters:
2833
 *      None
2834
 *
2835
 *  Returns:
2836
 *      Nothing
2837
 *
2838
 *========================================================================*/
2839
 
2840
void do_big_sort(void)
2841
{
2842
    int         i, k;                            /* Looooopy things */
2843
    unsigned    j;
2844
    ty_s_data  *ptr;                             /* Pointer to sort data */
2845
    int         teamclass;                           /* Current class */
2846
 
160 - 2847
//    printf( "Sorting it ALL out" );
2848
//    flush_out();
95 - 2849
 
2850
    for( i = 0; i <= config.num_legs; i++ )
2851
    {
2852
        /*
2853
        **  Sort on leg elapsed time
2854
        **  Then save the teams elapsed place in each leg
2855
        */
2856
        sort_team_data( i, S_L );
2857
        for( j = 1, k = 1, ptr = sort_data; j <= sort_num; ptr++, j++ )
2858
        {
2859
            if ( ptr->teamclass == config.nonequestrian_class )
2860
                continue;
2861
 
2862
            sort_aux[ptr->team].l_place[i] = k++;
2863
            sort_aux[ptr->team].team = ptr->team;
2864
        }
2865
 
2866
        /*
2867
        **  Sort on leg end time
2868
        **  Then save the teams place at the end of each leg
2869
        */
2870
        sort_team_data( i, S_LE );
2871
        for( j = 1, k = 1, ptr = sort_data; j <= sort_num; ptr++, j++ )
2872
        {
2873
            if ( ptr->teamclass == config.nonequestrian_class )
2874
                continue;
2875
 
2876
            sort_aux[ptr->team].le_place[i] = k++;
2877
        }
2878
 
2879
        /*
2880
        **  Sort on elapsed time per class
2881
        **  The save the teams elapsed place in each leg per class
2882
        */
2883
        sort_team_data( i, S_LC );
2884
        teamclass = -1;
2885
        for( k = 1, j = 1, ptr = sort_data; j <= sort_num; j++, ptr++ )
2886
        {
2887
            if( teamclass != ptr->teamclass )
2888
            {
2889
                k = 1;
2890
                teamclass = ptr->teamclass;
2891
            }
2892
            sort_aux[ptr->team].lc_place[i] = k++;
2893
        }
2894
 
2895
        /*
2896
        **  Sort on end time per class
2897
        **  Then save the teams place at the end of each leg per class
2898
        */
2899
        sort_team_data( i, S_LEC );
2900
        teamclass = -1;
2901
        for( k = 1, j = 1, ptr = sort_data; j <= sort_num; j++, ptr++ )
2902
        {
2903
            if( teamclass != ptr->teamclass )
2904
            {
2905
                k = 1;
2906
                teamclass = ptr->teamclass;
2907
            }
2908
            sort_aux[ptr->team].lec_place[i] = k++;
2909
        }
2910
    }
2911
 
2912
    /*
2913
    **  Write the place information back to disk for use in the displays
2914
    */
160 - 2915
//    printf( "\nWriting it all back to the disk file" );
2916
//    flush_out();
95 - 2917
 
2918
    for( i = config.min_team; i <= config.max_team; i++ )
2919
    {
2920
        if( sort_aux[i].team && valid_field( i ) && g_record( i, &team_buf ) )
2921
        {
2922
            for( k = 0; k <= config.num_legs; k++ )
2923
            {
2924
                team_buf.leg[k].l_place = sort_aux[i].l_place[k];
2925
                team_buf.leg[k].le_place = sort_aux[i].le_place[k];
2926
                team_buf.leg[k].lc_place = sort_aux[i].lc_place[k];
2927
                team_buf.leg[k].lec_place = sort_aux[i].lec_place[k];
2928
            }
2929
            put_team_record( i, &team_buf );
2930
        }
2931
    }
2932
}
2933
 
2934
/*========================================================================
2935
 *
2936
 *  Sort in memory buffer
2937
 *
2938
 *  Purpose:
2939
 *      This function is called to Sort in memory buffer
2940
 *
2941
 *  Parameters:
2942
 *      leg         Requested leg
2943
 *      mode        Defines the sort mode
2944
 *
2945
 *  Returns:
2946
 *      Nothing
2947
 *
2948
 *========================================================================*/
2949
 
2950
void sort_team_data( int leg, int mode )
2951
{
2952
 
2953
    unsigned    j;
2954
    ty_s_data  *ptr;
2955
 
2956
    sort_leg = leg;                              /* Leg is global for the comparison function */
2957
    sort_mode = mode;                            /* Mode is global for compare function */
2958
 
2959
    qsort( ( char * ) sort_data, sort_num, sizeof( ty_s_data ), sort_comp );
2960
 
2961
    /*
2962
     * Insert "place data" into the sorted data
2963
     * This simply the index into the array of data - after its been
2964
     * sorted.
2965
     */
2966
    ptr = sort_data;
2967
    for( j = 1; j <= sort_num; j++, ptr++ )
2968
        ptr->place = j;
2969
 
2970
}
2971
 
2972
/*========================================================================
2973
 *
2974
 *  qsort comparison function
2975
 *
2976
 *  Purpose:
2977
 *      This function is called by qsort as a Sort comparison function
2978
 *
2979
 *  Parameters:
2980
 *      a       - 1st record
2981
 *      b       - 2nd record
2982
 *
2983
 *  Returns:
2984
 *      value to qsort
2985
 *
2986
 *========================================================================*/
2987
 
2988
int sort_comp( const void * aa, const void * bb )
2989
{
2990
    const ty_s_data * a = (ty_s_data *)aa;
2991
    const ty_s_data * b = (ty_s_data *)bb;
2992
 
2993
 
2994
    int         i;                               /* One of those */
2995
    time_t      ta, tb;                          /* Leg times */
2996
    int         na, nb;                          /* Number of valid legs */
2997
    time_t      tta, ttb;                        /* Temp times */
2998
 
2999
    /*
3000
    **  Sorting on Team Number
3001
    */
3002
    if( sort_mode == S_TEAM )
3003
        return ( a->team - b->team );
3004
 
3005
    /*
3006
    **  Sorting on Class and Team Number
3007
    */
3008
    if( sort_mode == S_CLASS )
3009
    {
3010
        if( a->teamclass != b->teamclass )
3011
            return ( a->teamclass - b->teamclass );
3012
        else
3013
            return ( a->team - b->team );
3014
    }
3015
 
3016
    /*
3017
    **  Sorting within a class
3018
    **  First sort on the class
3019
    */
3020
    if( sort_mode == S_LEC || sort_mode == S_LC )   /* Sort within a class */
3021
        if( a->teamclass != b->teamclass )
3022
            return ( a->teamclass - b->teamclass );
3023
 
3024
#if 1
3025
    /*
3026
    **  Always put the nonequestrian_class at the end
3027
    **  Simplifies the creation of ordered lists as these
3028
    **  Entries are not present in the main body
3029
    */
3030
    if ( a->teamclass == config.nonequestrian_class ||  b->teamclass == config.nonequestrian_class )
3031
    {
3032
        if ( a->teamclass == config.nonequestrian_class &&  b->teamclass == config.nonequestrian_class )
3033
        {
3034
        }
3035
        else
3036
        {
3037
            return ( a->teamclass == config.nonequestrian_class ? 1 : -1 );
3038
        }
3039
 
3040
    }
3041
#endif
3042
 
3043
    /*
3044
    **  Now we need to examine the times as we have sorted
3045
    **  on every thing else.
3046
    **
3047
    **  If one of the teams has bad_times, then that team is placed
3048
    **  lower in the sorting order. If both teams have bad times
3049
    **  then sort on team number. ie: Unplaced teams are sorted on
3050
    **  team number
3051
    **
3052
    **  If not sorting within a class (ie Overall), then Non_Equestrian
3053
    **  is better than a bad time. Places NE before disqualified
3054
    **
3055
    **
3056
    **  Note: NE also have bad_times set
3057
    */
3058
#if 1
3059
    if( a->flags.bad_times || b->flags.bad_times )  /* Valid data has precedence */
3060
    {
3061
        if( a->flags.bad_times && b->flags.bad_times )
3062
        {
3063
            if( a->flags.non_equestrian || b->flags.non_equestrian )
3064
            {
3065
                if( a->flags.non_equestrian && b->flags.non_equestrian )
3066
                {
3067
                    /*
3068
                    **  Both are non equestrian
3069
                    **  Let the time sort operate ...
3070
                    */
3071
                    //return ( a->team - b->team );
3072
                }
3073
                else
3074
                {
3075
                    /* One is equestrian */
3076
                    /* Good times better than NE */
3077
                    return ( a->flags.non_equestrian ? -1 : 1 );
3078
                }
3079
            }
3080
            else
3081
            {
3082
                /* Neither is equestrian */
3083
                return ( a->team - b->team );
3084
            }
3085
        }
3086
        else
3087
            return ( a->flags.bad_times ? 1 : -1 );
3088
    }
3089
#else
3090
    if( a->flags.bad_times || b->flags.bad_times )  /* Valid data has precedence */
3091
    {
3092
        if( a->flags.bad_times && b->flags.bad_times )
3093
            return ( a->team - b->team );
3094
        else
3095
            return ( a->flags.bad_times ? 1 : -1 );
3096
    }
3097
 
3098
    /*
3099
    **  Not sorting within a class ie: Overall
3100
    **  Non-Equestrian is at the end, so that it doesn't get counted in the
3101
    **  finishing order
3102
    */
3103
    if( sort_mode == S_LE || sort_mode == S_L )     /* Sort NOT within a class */
3104
    {
3105
        if( a->flags.non_equestrian || b->flags.non_equestrian )
3106
        {
3107
            if( a->flags.non_equestrian && b->flags.non_equestrian )
3108
                return ( a->team - b->team );
3109
            else
3110
                return ( a->flags.non_equestrian ? 1 : -1 );
3111
        }
3112
    }
3113
#endif
3114
 
3115
    /*
3116
    **  Before we sort on times we must determine which time to
3117
    **  use. Finish time, Leg end times, Leg Elapsed times.
3118
    */
3119
 
3120
    switch ( sort_mode )
3121
    {
3122
      /*
3123
      **    Sort on finish times
3124
      */
3125
      case S_FIN:
3126
        ta = a->leg[sort_leg];
3127
        tb = b->leg[sort_leg];
3128
        break;
3129
 
3130
 
3131
      /*
3132
      **    Sort on accumulated leg times
3133
      */
3134
      case S_LE:
3135
      case S_LEC:
3136
        if( sort_leg )
3137
        {
3138
            /*
3139
            **  Calculate accumulated time up to the desired leg
3140
            **  If the two teams have a different number of valid
3141
            **  leg times then order by the team that has completed
3142
            **  more legs.
3143
            */
3144
            ta = tb = ( time_t ) 0;
3145
            na = nb = 0;
3146
            for( i = 1; i <= sort_leg; i++ )
3147
            {
3148
                tta = a->lege[i];
3149
                ttb = b->lege[i];
3150
                if( tta > 0 )
3151
                {
3152
                    na++;
3153
                    ta += tta;
3154
                }
3155
                if( ttb > 0 )
3156
                {
3157
                    nb++;
3158
                    tb += ttb;
3159
                }
3160
            }
3161
            if( na != nb )
3162
                return ( nb - na );
3163
        }
3164
        else
3165
        {
3166
            ta = a->leg[sort_leg] - a->start;
3167
            tb = b->leg[sort_leg] - b->start;
3168
        }
3169
        break;
3170
 
3171
      /*
3172
      **    Sort on Elapsed times
3173
      */
3174
      case S_LC:
3175
      case S_L:
3176
        ta = a->lege[sort_leg];
3177
        tb = b->lege[sort_leg];
3178
        break;
3179
 
3180
      /*
3181
      **    Just to be sure ...
3182
      */
3183
      default:
3184
        return ( 0 );
3185
    }
3186
 
3187
    /*
3188
    **  Finally. Compare the required team times
3189
    */
3190
    if( ta == tb )
3191
        return ( a->team - b->team );
3192
    if( ( ta > 0 ) && ( tb > 0 ) )
3193
        return ( ( int ) ( ta - tb ) );
3194
    return ( ( ta > 0 ) ? -1 : 1 );
3195
}
3196
 
3197
/*========================================================================
3198
 *
3199
 *  qsort comparison function - competitor names
3200
 *
3201
 *  Purpose:
3202
 *      This function is called by qsort as a Sort comparison function
3203
 *
3204
 *  Parameters:
3205
 *      a       - 1st record
3206
 *      b       - 2nd record
3207
 *
3208
 *  Returns:
3209
 *      value to qsort
3210
 *
3211
 *========================================================================*/
3212
 
3213
int sort_comp_cname( const void * aa, const void * bb )
3214
{
3215
    ty_s_namedata * a = (ty_s_namedata *)aa;
3216
    ty_s_namedata * b = (ty_s_namedata *)bb;
3217
 
3218
 
3219
    int         i;                               /* One of those */
3220
 
3221
    /*
3222
    **  Sort by name
3223
    */
3224
    i = strcmp ( a->name, b->name );
3225
    if ( i )
3226
        return ( i );
3227
    a->multi=1;
3228
    b->multi=1;
3229
 
3230
    /*
3231
    **  Sort by Leg
3232
    */
3233
    i = a->leg - b->leg;
3234
    if ( i )
3235
        return ( i );
3236
 
3237
    /*
3238
    **  Sorting on Team Number
3239
    */
3240
    return ( a->team - b->team );
3241
 
3242
}
3243
 
3244
/*========================================================================
3245
 *
3246
 *  load report data into memory
3247
 *
3248
 *  Purpose:
3249
 *      This routine will pull all the data into memory 
3250
 *      Not all the team data is loaded. Only that essential for the
3251
 *      operation of the sort routine is loaded
3252
 *
3253
 *  Parameters:
3254
 *      None
3255
 *
3256
 *  Returns:
3257
 *      TRUE - All is well
3258
 *
3259
 *========================================================================*/
3260
 
3261
bool load_report_data(void)
3262
{
3263
 
3264
    ty_s_data  *ptr;                             /* pointer to sort data type */
3265
    ty_s_data  *last;
3266
    int         j;
3267
    unsigned    num;
3268
 
160 - 3269
    //printf( "Loading team information - This will not hurt" );
3270
    //flush_out();
95 - 3271
 
3272
    /*
3273
     * Fetch memory for the data store
3274
     */
3275
 
3276
    if( sort_data )
3277
        free( ( char * ) sort_data );
3278
    sort_data = 0;
3279
 
3280
    if( sort_aux )
3281
        free( ( char * ) sort_aux );
3282
    sort_aux = 0;
3283
    sort_num = 0;                                /* Counter of records in the array */
3284
 
3285
    /*
3286
    **  Allocate memory for the data structures
3287
    **  This will be free'd
3288
    */
3289
    num = config.max_team - config.min_team + 1 ;
3290
 
3291
    /*
3292
    **  Allow for non-equestrian teams - since some of the data is loaded twice
3293
    **  Take a guess that at most 1/2 the teams will be non-equestrian
3294
    */
3295
    num = num * 3 / 2;
3296
 
3297
    sort_data = ( ty_s_data * ) calloc ( num , sizeof( ty_s_data ) );
3298
    sort_aux = ( ty_s_aux * ) calloc( num + 1, sizeof( ty_s_aux ) );
3299
 
3300
    if( sort_data == 0 || sort_aux == 0 )
3301
    {
160 - 3302
        printf( "Error in allocating memory" );
95 - 3303
        sleep( 5 );
3304
        return ( FALSE );
3305
    }
3306
 
3307
    /*
3308
    **  Load data into the memory based data structure
3309
    **  Only load data for valid-teams
3310
    **  Load essential data
3311
    **      Team Number, class and flags
3312
    **      Leg end and elapsed times
3313
    */
3314
    ptr = sort_data;
3315
    for( team = config.min_team; team <= config.max_team; team++ )
3316
    {
3317
        if( valid_field( team ) )
3318
        {
3319
            g_record( team, &team_buf );
3320
            if( team_buf.flags.valid )
3321
            {
3322
                last = ptr;
3323
                ptr->team = team;
3324
                for( j = 0; j < MAX_LEGS + 1; j++ )
3325
                {
3326
                    ptr->lege[j] = team_buf.leg[j].elapsed;
3327
                    ptr->leg[j] = team_buf.leg[j].end;
3328
                }
3329
                ptr->start = team_buf.leg[0].start;
3330
                ptr->teamclass = team_buf.teamclass;
3331
 
3332
                ptr->flags = team_buf.flags;
3333
                ptr++;
3334
                sort_num++;
3335
 
3336
                /*
3337
                **  If non-equestrian support is enabled then
3338
                **  duplicate and modify data for the non-equestrian teams
3339
                **      - Change the class
3340
                **      - Modify the leg time
3341
                */
3342
#if 1
3343
                if ( config.nonequestrian_class && team_buf.flags.non_equestrian )
3344
                {
3345
                    ptr->team = team;
3346
                    ptr->lege[0] = 0;
3347
 
3348
                    for( j = 0; j < MAX_LEGS + 1; j++ )
3349
                    {
3350
                        if ( j == config.equestrian_leg )
3351
                        {
3352
                            last->lege[j] = ptr->lege[j] = 0;
3353
                            if ( config.equestrian_leg > 1 )
3354
                                last->leg[j] = ptr->leg[j] = ptr->leg[j-1];
3355
                        }
3356
                        else
3357
                        {
3358
                            if ( j )
3359
                                last-> lege[j] = ptr->lege[j] = team_buf.leg[j].elapsed;
3360
                            last->leg[j] = ptr->leg[j] = team_buf.leg[j].end;
3361
                            ptr->lege[0] += ptr->lege[j] ;
3362
                            last->lege[0] = ptr->lege[0] ;
3363
                        }
3364
                    }
3365
 
3366
                    last->start = ptr->start = team_buf.leg[0].start;
3367
                    ptr->teamclass = config.nonequestrian_class;
3368
                    ptr->flags = team_buf.flags;
3369
                    ptr->flags.disqualified = 0;
3370
 
3371
 
3372
                    ptr++;
3373
                    sort_num++;
3374
                }
3375
#endif
3376
            }
3377
        }
3378
    }
3379
    return ( TRUE );
3380
}
3381
 
3382
/*========================================================================
3383
 *
3384
 *  Generate all the stats
3385
 *
3386
 *  Purpose:
3387
 *      This function is called to Generate all the stats
3388
 *
3389
 *  Parameters:
3390
 *      None
3391
 *
3392
 *  Returns:
3393
 *      Nothing
3394
 *
3395
 *========================================================================*/
3396
 
3397
void gen_stats(void)
3398
{
3399
    ty_s_data  *ptr;
3400
    unsigned    i;
3401
    int         j;
3402
    int         k;
3403
 
3404
    /*
3405
     * Init all the stats 
3406
     */
3407
    for( i = 0; i <= MAX_LEGS; i++ )
3408
    {
3409
        for( j = 0; j <= MAX_CLASS; j++ )
3410
        {
3411
            stats.team[i][j] = 0;
3412
            stats.fast.team[i][j] = 0;
3413
            stats.fast.time[i][j] = ( time_t ) - 1;
3414
            stats.average[i][j] = 0;
3415
        }
3416
    }
3417
 
3418
    for( i = 1, ptr = sort_data; i <= sort_num; i++, ptr++ )
3419
    {
3420
        /*
3421
        **  If there is any bad times in the team record, then none
3422
        **  of the data can be trusted.
3423
        **
3424
        **  If the team has been disqualified, then don't use any
3425
        **  of the data.
3426
        */
3427
        if( ptr->flags.bad_times || ptr->flags.disqualified )
3428
            continue;
3429
 
3430
        for( j = 0; j <= config.num_legs; j++ )
3431
        {
3432
            if( ptr->lege[j] <= 0 )              /* Ignore bad data */
3433
                continue;
3434
 
3435
            /*
3436
            **  Determine fastest team : overall
3437
            **  Ignore the non-equestrian data as this is in the list twice
3438
            */
3439
            if( ( ptr->lege[j] < stats.fast.time[j][0] )
3440
                || ( stats.fast.time[j][0] < 0 ) )
3441
            {
3442
                if ( ptr->teamclass != config.nonequestrian_class )
3443
                {
3444
                    stats.fast.team[j][0] = ptr->team;
3445
                    stats.fast.time[j][0] = ptr->lege[j];
3446
                }
3447
            }
3448
 
3449
            /*
3450
            **  Determine fastest team : within a class
3451
            */
3452
            if( ( ptr->lege[j] < stats.fast.time[j][ptr->teamclass] )
3453
                || stats.fast.time[j][ptr->teamclass] < 0 )
3454
            {
3455
                stats.fast.team[j][ptr->teamclass] = ptr->team;
3456
                stats.fast.time[j][ptr->teamclass] = ptr->lege[j];
3457
            }
3458
 
3459
            /*
3460
            **  Sum the end times : overall
3461
            */
3462
            if ( ptr->teamclass != config.nonequestrian_class )
3463
            {
3464
                stats.average[j][0] += ptr->lege[j];
3465
                stats.team[j][0]++;
3466
            }
3467
 
3468
 
3469
            /*
3470
            **  Sum the end times : within a class
3471
            */
3472
            stats.average[j][ptr->teamclass] += ptr->lege[j];
3473
            stats.team[j][ptr->teamclass]++;
3474
        }
3475
    }
3476
 
3477
    /*
3478
     * Calculate the averages
3479
     */
3480
    for( k = 0; k <= config.num_legs; k++ )
3481
    {
3482
        for( j = 0; j <= config.num_class; j++ )
3483
        {
3484
            if( stats.team[k][j] )
3485
                stats.average[k][j] /= stats.team[k][j];
3486
            else
3487
                stats.average[k][j] = ( time_t ) - 1;
3488
        }
3489
    }
3490
}
3491
 
3492
/********************************* EOF ***********************************/