Subversion Repositories svn1

Rev

Rev 1 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 root 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(void);
62
void pri_master_index(void);
63
char *placing ( int place );
64
 
65
 
66
menu_table  rpt_menu[] = {
67
    { '1', "Print team order", pri_team },
68
    { '2', "Print end leg times", pri_leg },
69
    { '3', "Print elapsed leg times", pri_eleg },
70
    { '4', "Print final results", pri_final },
71
    { '5', "Print final results(All-HTML)", pri_final_html },
72
    { '6', "Print Interim results", pri_interim },
73
    { '7', "Update event and class placings", srt_place },
74
    { '8', "Display summary information", display_summary },
75
    { 'a', "Print Awards only", pri_awards },
76
    { 'b', "Print Master Index only", pri_master_index },
77
 
78
#if defined(HI_TECH_C) || defined(__TURBOC__)
79
    { 'S', "MS-DOS system", ms_system },
80
#endif
81
    { 'q', "Return to main menu", 0 },
82
    { '\0' }
83
};
84
 
85
#define MAX_PLACE 11
86
char * place_text[] =
87
{
88
    "Zero'th",
89
    "First",
90
    "Second",
91
    "Third",
92
    "Fourth",
93
    "Fifth",
94
    "Sixth",
95
    "Seventh",
96
    "Eighth",
97
    "Ninth",
98
    "Tenth",
99
    "Eleventh"
100
};
101
 
102
int         sort_leg;
103
int         sort_mode;
104
bool        report_html = FALSE;
105
 
106
/* Parameters used by the sort routine to govern its actions */
107
 
108
#define S_L     1                                /* Elasped times */
109
#define S_LE    2                                /* Leg end time */
110
#define S_LC    3                                /* Elapsed times per class */
111
#define S_LEC   4                                /* Leg end time per class */
112
#define S_FIN   5                                /* Sort on finish time at given leg */
113
#define S_TEAM  6                                /* Sort on team order */
114
#define S_CLASS 7                                /* Sort on class/team order */
115
 
116
/*
117
**  Various checking modes
118
*/
119
#define C_ELAPSED   1                            /* Check elapsed times */
120
#define C_END       2                            /* Check end times */
121
#define C_DISQUAL   3                            /* Check disqualified teams */
122
 
123
/*
124
**  Data
125
*/
126
ty_s_data  *sort_data = 0;                       /* pointer to memory */
127
ty_s_aux   *sort_aux = 0;                        /* pointer to aux sort info */
128
unsigned    sort_num;                            /* Number in the array */
129
 
130
/*
131
**  A structure to hold statistical information
132
*/
133
typedef struct
134
{
135
    int         team[MAX_LEGS + 1][MAX_CLASS + 1];
136
    struct
137
    {
138
        int     team[MAX_LEGS + 1][MAX_CLASS + 1];
139
        time_t  time[MAX_LEGS + 1][MAX_CLASS + 1];
140
    } fast;
141
    time_t      average[MAX_LEGS + 1][MAX_CLASS + 1];
142
} ty_stats;
143
 
144
ty_stats        stats;                           /* Holds statistics */
145
 
146
/*========================================================================
147
 *
148
 *  Report menu
149
 *
150
 *  Purpose:
151
 *      This function is called to produce the "Report Menu"
152
 *
153
 *  Parameters:
154
 *      None
155
 *
156
 *  Returns:
157
 *      Nothing
158
 *
159
 *========================================================================*/
160
 
161
void report(void)
162
{
163
    report_html = FALSE;
164
    if( load_report_data() )
165
        do_menu( "Report generation", "Select option", rpt_menu );
166
 
167
    if( sort_data )
168
        free( ( char * ) sort_data );
169
    if( sort_aux )
170
        free( ( char * ) sort_aux );
171
    sort_data = ( ty_s_data * ) 0;
172
    sort_aux = ( ty_s_aux * ) 0;
173
}
174
 
175
/*========================================================================
176
 *
177
 *  Print in team order
178
 *
179
 *  Purpose:
180
 *      This function is called to Print in team order
181
 *      This function may also be used to create an HTML suite of files
182
 *      within the result set
183
 *
184
 *  Parameters:
185
 *      None
186
 *
187
 *  Returns:
188
 *      Nothing
189
 *
190
 *========================================================================*/
191
 
192
void pri_team(void)
193
{
194
    int         i, k;
195
 
196
    cur( 0, 5 );
197
    printf( "Team information - in team order\n" );
198
    printf( "\nPrinting team names\n" );
199
    flush_out();
200
 
201
    if( !open_printer( "", "name", 132, report_html, "Team Names" ) )
202
        return;
203
 
204
    /*
205
     * Print out the data 
206
     * Print out the header
207
     */
208
 
209
    print( "\n" );
210
 
211
    print_underline( TRUE );
212
    print( "%-*s %-*s %-*s", MAX_TM_NAME + 5, "Entry number and name",
213
               LEN_CLASS_NAME, "Category",
214
               config.num_countries == 0 ? 1 : LEN_CNTRY_NAME,
215
               config.num_countries == 0 ? "" : "Country" );
216
    for( k = 0; k < MAX_MEMB; k++ )
217
    {
218
        print( " %-*s", MAX_PERSON_NAME, config.leg_name[k] ? config.leg_name[k] : "Competitor"  );
219
    }
220
    print_underline( FALSE ) ;
221
    print( "\n" );
222
 
223
    for( i = config.min_team; i <= config.max_team; i++ )
224
    {
225
        if( valid_field( i ) && g_record( i, &team_buf ) )
226
        {
227
            /*
228
            **  If printing an HTML report then we need to mark
229
            **  the entry with a reference so that we can link to it
230
            */
231
            if ( report_html )
232
            {
233
                print( "<A NAME=\"Team_%04d\">",team_buf.numb );
234
                print( "</A>" );
235
            }
236
 
237
            /*
238
            **  Basic information
239
            **      - Team number - with Xref back to full result
240
            **      - Full team name
241
            **      - Full categoray name - with Xref to category results
242
            **      - Country name
243
            */
244
            if ( report_html ) print( "<A HREF=\"%s#Team_%04d\">", p_filename(filebase, "finish" ,"html"), team_buf.numb );
245
            print( "%4d",       team_buf.numb );
246
            if ( report_html ) print( "</A>" );
247
 
248
            print( " %-*s ",     MAX_TM_NAME, team_buf.name );
249
 
250
            if ( report_html ) print( "<A HREF=\"%s#Team_%04d\">",p_filename(filebase, config.team_class[team_buf.class - 1].abr ,"html"), team_buf.numb );
251
            print( "%-*s",     LEN_CLASS_NAME, team_buf.class == 0 ? "" : config.team_class[team_buf.class - 1].full_name );
252
            if ( report_html ) print( "</A>" );
253
 
254
            print( " %-*s",     config.num_countries == 0 ? 1 : LEN_CNTRY_NAME,
255
                                config.num_countries == 0
256
                                || team_buf.country ==
257
 
258
 
259
            for( k = 0; k < MAX_MEMB; k++ )
260
                print( " %-*s", MAX_PERSON_NAME, team_buf.members[k].name );
261
 
262
            print( "\n" );
263
        }
264
    }
265
    close_printer();
266
}
267
 
268
 
269
/*========================================================================
270
 *
271
 *  Print in given leg finishing time
272
 *
273
 *  Purpose:
274
 *      This function is called to Print in given leg finishing time
275
 *
276
 *  Parameters:
277
 *      None
278
 *
279
 *  Returns:
280
 *      Nothing
281
 *
282
 *========================================================================*/
283
 
284
void pri_leg(void)
285
{
286
    int         leg = 0;
287
    ty_s_data  *ptr;
288
    int         i, k;
289
 
290
    /*
291
     * This function is used to provide interum print-outs
292
     * The team data is sorted by time at leg-end and the times printed are
293
     * real times at leg end.
294
     * This operation is designed to be quick - it doesn't update the disk file
295
     * and is not available in an HTML version - yet
296
     */
297
 
298
    cur( 0, 5 );
299
    printf( "Leg finishing time report\n" );
300
    while( TRUE )
301
    {
302
        d_field( 0, 7, "Enter leg to print :", D_NUMBER, 1, ( char * ) &leg,
303
                 TRUE, M_UPDATE );
304
        if( abort_flag )
305
            return;
306
        if( leg <= config.num_legs )
307
            break;
308
        beep();
309
    }
310
 
311
    /*
312
     * Sort the data in finishing order 
313
     */
314
 
315
    printf( "\nSorting the data\n" );
316
    flush_out();
317
    if( ck_data( leg, C_END ) )
318
        return;                                  /* Check data for this leg */
319
    sort_team_data( leg, S_FIN );                /* Sort the data */
320
 
321
 
322
    /*
323
     * Now print the data on the printer 
324
     */
325
    if( !open_printer( "",
326
                        tprintf("lg%1.1d", leg ),
327
                        80,
328
                        report_html,
329
                        leg ? tprintf ("Finish order for Leg %d.", leg)
330
                            : "Final team finish order"
331
                     ) )
332
    {
333
        return;
334
    }
335
 
336
    /*
337
     * Print out the data 
338
     */
339
    print( "PRELIMINARY RESULTS ONLY\n\n" );
340
 
341
    print_underline( TRUE );
342
    print( "%4s %4s %-8s  ", "Plce", "Team", "Time" );
343
    print( "%4s %4s %-8s  ", "Plce", "Team", "Time" );
344
    print( "|" );
345
    print( "%4s %4s %-8s  ", "Team", "Plce", "Time" );
346
    print( "%4s %4s %-8s\n", "Team", "Plce", "Time" );
347
    print_underline( FALSE );
348
 
349
    for( ptr = sort_data, k = 0, i = config.min_team; i <= config.max_team; )
350
    {
351
        p_place( ptr++, leg, k++ );
352
        p_place( ptr++, leg, k++ );
353
        print( "|" );
354
        while( i <= config.max_team && !valid_field( i ) )
355
            i++;
356
        p_team( i++, leg );
357
        while( i <= config.max_team && !valid_field( i ) )
358
            i++;
359
        p_team( i++, leg );
360
        print( "\n" );
361
    }
362
 
363
    /*
364
     * Insert the leg statistics 
365
     */
366
 
367
    gen_stats();                               /* Generate all stats */
368
    print( "\nLeg statistics\n" );
369
    print( "Fastest team: %4d time : %s.",
370
           stats.fast.team[leg][0], time_a( stats.fast.time[leg][0] ) );
371
    print( " Average time: %s\n", time_a( stats.average[leg][0] ) );
372
 
373
    close_printer();
374
}
375
 
376
/*========================================================================
377
 *
378
 *  Print place information
379
 *
380
 *  Purpose:
381
 *      This helper function is called to Print place information
382
 *      in a 20-character field
383
 *
384
 *  Parameters:
385
 *      ptr         Address of the place data
386
 *      leg         Leg to print
387
 *      k           Current index into sorted array. Simply
388
 *                  used to determine if the entry is valid
389
 *                  or if it should be space-filled
390
 *
391
 *  Returns:
392
 *      Nothing
393
 *
394
 *========================================================================*/
395
 
396
void p_place( ty_s_data * ptr, int leg, unsigned k )
397
{
398
    if( k < sort_num )
399
    {
400
        print( "%4.4s %4d %8s  ",
401
               pr_place( ptr->place, ptr->flags.bad_times ),
402
               ptr->team, time_fa( ptr->leg[leg], ptr->flags.disqualified ) );
403
    }
404
    else
405
    {
406
        print( "%20s", "" );
407
    }
408
}
409
 
410
/*========================================================================
411
 *
412
 *  Print team information
413
 *
414
 *  Purpose:
415
 *      This helper function is called to Print team information
416
 *      in a 20-character field
417
 *
418
 *  Parameters:
419
 *      i           team to print
420
 *      leg         Leg to print
421
 *
422
 *  Returns:
423
 *      Nothing
424
 *
425
 *========================================================================*/
426
 
427
void p_team( int i, int leg )
428
{
429
    ty_s_data  *ptra;                            /* Pointer to sort data */
430
    int         found = FALSE;
431
    unsigned    j;
432
 
433
    if( valid_field( i ) )
434
    {
435
        ptra = sort_data;
436
        for( j = 1; j <= sort_num; j++, ptra++ )
437
            if( i == ptra->team )
438
            {
439
                found = TRUE;
440
                break;
441
            }
442
    }
443
    if( found )
444
    {
445
        print( "%4d %4.4s %8s  ",
446
               ptra->team,
447
               pr_place( ptra->place, ptra->flags.bad_times ),
448
               time_fa( ptra->leg[leg], ptra->flags.disqualified ) );
449
    }
450
    else
451
    {
452
        print( "%20s", "" );
453
    }
454
}
455
 
456
/*========================================================================
457
 *
458
 *  Print on elapsed times for given leg
459
 *
460
 *  Purpose:
461
 *      This function is called to Print on elapsed times for given leg
462
 *
463
 *  Parameters:
464
 *      None
465
 *
466
 *  Returns:
467
 *      Nothing
468
 *
469
 *========================================================================*/
470
 
471
void pri_eleg(void)
472
{
473
    int         leg = 0;
474
    ty_s_data  *ptr;
475
    int         i, k;
476
 
477
    /*
478
     * This function is used to provide interum print-outs
479
     * The team data is sorted by time at leg-elapsed and the times printed are
480
     * real times at leg end.
481
     * This operation is designed to be quick - it doesn't update the disk file
482
     * and is not available in an HTML version - yet
483
     */
484
 
485
    cur( 0, 5 );
486
    printf( "Leg elapsed time report\n" );
487
    while( TRUE )
488
    {
489
        d_field( 0, 7, "Enter leg to print :", D_NUMBER, 1, ( char * ) &leg,
490
                 TRUE, M_UPDATE );
491
        if( abort_flag )
492
            return;
493
        if( leg <= config.num_legs )
494
            break;
495
        beep();
496
    }
497
 
498
    /*
499
     * Sort the data in finishing order 
500
     */
501
 
502
    printf( "\nSorting the data\n" );
503
    flush_out();
504
    if( ck_data( leg, C_ELAPSED ) )
505
        return;                                  /* Check data for this leg */
506
    sort_team_data( leg, S_L );                  /* Sort the data on elapsed time */
507
 
508
 
509
    /*
510
     * Now print the data on the printer 
511
     */
512
    if( !open_printer( "", tprintf( "le%1.1d", leg ),
513
                       80,
514
                       report_html,
515
                       leg ? tprintf( "Elapsed time order for Leg %d.", leg )
516
                           : tprintf( "Final elapsed team finishing order." )
517
                     ) )
518
    {
519
        return;
520
    }
521
 
522
    /*
523
     * Print out the data 
524
     */
525
    print( "PRELIMINARY RESULTS ONLY\n\n" );
526
 
527
    print_underline( TRUE );
528
    print( "%4s %4s %-8s  ", "Plce", "Team", "Time" );
529
    print( "%4s %4s %-8s  ", "Plce", "Team", "Time" );
530
    print( "|" );
531
    print( "%4s %4s %-8s  ", "Team", "Plce", "Time" );
532
    print( "%4s %4s %-8s\n", "Team", "Plce", "Time" );
533
    print_underline( FALSE );
534
 
535
    for( ptr = sort_data, k = 0, i = config.min_team; i <= config.max_team; )
536
    {
537
        pe_place( ptr++, leg, k++ );
538
        pe_place( ptr++, leg, k++ );
539
        print( "|" );
540
        while( i <= config.max_team && !valid_field( i ) )
541
            i++;
542
        pe_team( i++, leg );
543
        while( i <= config.max_team && !valid_field( i ) )
544
            i++;
545
        pe_team( i++, leg );
546
        print( "\n" );
547
    }
548
 
549
    /*
550
     * Insert the leg statistics 
551
     */
552
 
553
    gen_stats();                               /* Generate all stats */
554
    print( "\nLeg statistics\n" );
555
    print( "Fastest team: %4d time : %s.",
556
           stats.fast.team[leg][0], time_a( stats.fast.time[leg][0] ) );
557
    print( " Average time: %s\n", time_a( stats.average[leg][0] ) );
558
 
559
    close_printer();
560
}
561
 
562
/*========================================================================
563
 *
564
 *  Print place information
565
 *
566
 *  Purpose:
567
 *      This helper function is called to Print place and elapsed information
568
 *      in a 20-character field
569
 *
570
 *  Parameters:
571
 *      ptr         Address of the place data
572
 *      leg         Leg to print
573
 *      k           Current index into sorted array. Simply
574
 *                  used to determine if the entry is valid
575
 *                  or if it should be space-filled
576
 *
577
 *  Returns:
578
 *      Nothing
579
 *
580
 *========================================================================*/
581
 
582
void pe_place( ty_s_data * ptr, int leg, unsigned k )
583
{
584
    if( k < sort_num )
585
    {
586
        print( "%4.4s %4d %8s  ",
587
               pr_place( ptr->place, ptr->flags.bad_times ),
588
               ptr->team,
589
               time_fa( ptr->lege[leg], ptr->flags.disqualified ) );
590
    }
591
    else
592
    {
593
        print( "%20s", "" );
594
    }
595
}
596
 
597
/*========================================================================
598
 *
599
 *  Print team information
600
 *
601
 *  Purpose:
602
 *      This helper function is called to Print team and elapsed time
603
 *      information
604
 *      in a 20-character field
605
 *
606
 *  Parameters:
607
 *      i           Team to print
608
 *      leg         Leg to print
609
 *
610
 *  Returns:
611
 *      Nothing
612
 *
613
 *========================================================================*/
614
 
615
void pe_team( int i, int leg )
616
{
617
    ty_s_data  *ptra;                            /* Pointer to sort data */
618
    int         found = FALSE;
619
    unsigned    j;
620
 
621
    if( valid_field( i ) )
622
    {
623
        ptra = sort_data;
624
        for( j = 1; j <= sort_num; j++, ptra++ )
625
            if( i == ptra->team )
626
            {
627
                found = TRUE;
628
                break;
629
            }
630
    }
631
    if( found )
632
    {
633
        print( "%4d %4.4s %8s  ",
634
               ptra->team,
635
               pr_place( ptra->place, ptra->flags.bad_times ),
636
               time_fa( ptra->lege[leg], ptra->flags.disqualified ) );
637
    }
638
    else
639
    {
640
        print( "%20s", "" );
641
    }
642
}
643
 
644
/*========================================================================
645
 *
646
 *  Print final results in HTML
647
 *
648
 *  Purpose:
649
 *      This function is called to Print final results with HTML formatting
650
 *      All result files are created
651
 *
652
 *  Parameters:
653
 *      None
654
 *
655
 *  Returns:
656
 *      Nothing
657
 *
658
 *========================================================================*/
659
 
660
void pri_final_html(void)
661
{
662
    /*
663
    **  Generate ALL results with HTML tags
664
    */
665
    report_html = TRUE;
666
    pri_final();
667
    report_html = FALSE;
668
}
669
 
670
 
671
/*========================================================================
672
 *
673
 *  Print final results
674
 *
675
 *  Purpose:
676
 *      This function is called to Print final results
677
 *
678
 *  Parameters:
679
 *      None
680
 *
681
 *  Returns:
682
 *      Nothing
683
 *
684
 *========================================================================*/
685
 
686
void pri_final(void)
687
{
688
    ty_s_data  *ptr;
689
    unsigned    i;
690
    int         j, last_class;
691
    char        suppress_classes;                /* Boolean. Printout class files too */
692
    char        *report_title;
693
 
694
    cur( 0, 5 );
695
    printf( "Generate final result printouts\n" );
696
    if( ck_data( -1, C_ELAPSED ) )
697
        return;                                  /* check data for all legs */
698
 
699
    /*
700
    **  If a non HTML report then ask if the user want to supress the class
701
    **  printout. For an HTML report always do the class reports as the two
702
    **  are interlinked
703
    */
704
    if ( ! report_html )
705
    {
706
        suppress_classes = getyes( "Do you want to suppress class printouts" );
707
    }
708
    else
709
    {
710
        suppress_classes = FALSE;
711
    }
712
 
713
    /*
714
    **  Sort on every thing
715
    **  Then generate all the stats too
716
    */
717
    printf( "\nSorting the data\n" );
718
    do_big_sort();
719
    gen_stats();
720
 
721
    /*
722
     * Now print the data on the printer 
723
     */
724
    printf( "\nGenerating the printed output\n" );
725
    if( !open_printer( "", "finish", 132, report_html, "Finishing Order" ) )
726
        return;
727
 
728
    /*
729
     * Print out the data 
730
     */
731
    print_class_header( -1, TRUE );                      /* Print the header */
732
 
733
    ptr = sort_data;
734
    sort_team_data( 0, S_L );                     /* Re-sort on elapsed time */
735
    for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
736
    {
737
        if ( ptr->class == config.nonequestrian_class )
738
            continue;
739
 
740
        g_record( ptr->team, &team_buf );
741
 
742
        /*
743
        **  If printing an HTML report then we need to mark
744
        **  the entry with a reference so that we can link to it
745
        */
746
        if ( report_html )
747
        {
748
            print( "<A NAME=\"Team_%04d\"></A>",team_buf.numb );
749
        }
750
 
751
        /*
752
        **  Print the basics
753
        **      - Place within complete field
754
        **      - Team number - with HTML reference to team file
755
        **      - Class
756
        */
757
        print( "%4.4s ", pr_place( team_buf.leg[0].l_place, ptr->flags.bad_times ) );
758
        if ( report_html ) print( "<A HREF=\"%s#Team_%04d\">", p_filename(filebase, "name" ,"html"), team_buf.numb );
759
        print( "%4d",  team_buf.numb );
760
        if ( report_html ) print( "</A>" );
761
 
762
        print( " %-*s", 3, team_buf.class == 0 ? "" : config.team_class[team_buf.class - 1].abr );
763
 
764
        /*
765
        **  Print the per-leg data
766
        **      - Time
767
        **      - Leg place
768
        **      - End place
769
        */
770
        for( j = 1; j <= config.num_legs; j++ )
771
        {
772
            print( "  %-8s %4.4s %4.4s",
773
                    time_a( team_buf.leg[j].elapsed ),
774
                    pr_place( team_buf.leg[j].l_place, ptr->flags.bad_times ),
775
                    pr_place( team_buf.leg[j].le_place,ptr->flags.bad_times )
776
                  );
777
        }
778
 
779
        /*
780
        **  Print the trailer
781
        **      - Total time
782
        **      - Category place - with reference to category file
783
        */
784
        print( "  %-8s ",  time_a( team_buf.leg[0].elapsed ) );
785
        if ( report_html ) print( "<A HREF=\"%s#Team_%04d\">",p_filename(filebase, config.team_class[team_buf.class - 1].abr ,"html"), team_buf.numb );
786
        print( "%-4.4s", pr_place( team_buf.leg[0].lc_place, ptr->flags.bad_times ) );
787
        if ( report_html ) print( "</A>" );
788
 
789
        print( "\n" );
790
    }
791
 
792
    print_class_stats( -1, TRUE );              /* Print statistics */
793
    print_legend(-1);                            /* Print the legend */
794
    close_printer();                            /* Close the printer */
795
 
796
    /*
797
     * Now produce a breakdown on a class by class basis 
798
     * Now print out the class placement information
799
     */
800
 
801
    if( suppress_classes )
802
    {
803
        printf( "WARNING: Class printouts suppressed\n" );
804
        return;
805
    }
806
 
807
    sort_team_data( 0, S_LC );                 /* Generate class placement data */
808
    last_class = -1;                           /* Invalid class to start with */
809
 
810
    for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
811
    {
812
        /*
813
        **  Detect a change in the "class"
814
        **  All data is within the one array of data
815
        **  Use the in-memory class as this MAY differ from that stored
816
        **  The non-equestrian class does this.
817
        */
818
        if( last_class != ptr->class )
819
        {
820
            if( last_class >= 0 )
821
            {
822
                print_class_stats( last_class, TRUE );
823
                print_legend( last_class );
824
                close_printer();
825
            }
826
 
827
            report_title = tprintf( "Category results for : %-*s", LEN_CLASS_NAME, ptr->class == 0 ? "" : config.team_class[ptr->class - 1].full_name );
828
 
829
            if( !open_printer( "", config.team_class[ptr->class - 1].abr, 132, report_html, report_title ) )
830
                continue;
831
            print_class_header( last_class = ptr->class, TRUE );
832
        }
833
 
834
        /*
835
        **  Now read in the team record
836
        */
837
        g_record( ptr->team, &team_buf );
838
 
839
        /*
840
        **  If printing an HTML report then we need to mark
841
        **  the entry with a reference so that we can link to it
842
        */
843
        if ( report_html )
844
            print( "<A NAME=\"Team_%04d\"></A>",team_buf.numb );
845
 
846
        /*
847
        **  Print the basics
848
        **      - Place within the class
849
        **      - Team number - with HTML reference to team file
850
        **      - Class
851
        */
852
 
853
        print( "%4.4s ", pr_place( team_buf.leg[0].lc_place, ptr->flags.bad_times ) );
854
        if ( report_html ) print( "<A HREF=\"%s#Team_%04d\">", p_filename(filebase, "name" ,"html"), team_buf.numb );
855
        print( "%4d",  team_buf.numb );
856
        if ( report_html ) print( "</A>" );
857
        print( " %-*s", 3, team_buf.class == 0 ? "" : config.team_class[team_buf.class - 1].abr );
858
 
859
        for( j = 1; j <= config.num_legs; j++ )
860
        {
861
            /*
862
            **  Ensure that non-equestrian leg data is not displayed
863
            */
864
            if ( j == config.equestrian_leg && ptr->class == config.nonequestrian_class)
865
            {
866
                print( "  %-8s %4.4s %4.4s", "-- -- --", "-","-");
867
            }
868
            else
869
            {
870
                print( "  %-8s %4.4s %4.4s", time_a( team_buf.leg[j].elapsed ),
871
                       pr_place( team_buf.leg[j].lc_place, ptr->flags.bad_times ),
872
                       pr_place( team_buf.leg[j].lec_place, ptr->flags.bad_times ) );
873
            }
874
        }
875
 
876
        /*
877
        **  Print the trailer
878
        **      - Total time
879
        **      - Overall place - with reference to overall place file
880
        */
881
        /* print( "  %-8s ", time_a( team_buf.leg[0].elapsed ) ); */
882
        print( "  %-8s ", time_a( ptr->lege[0] ) );
883
 
884
        if ( report_html ) print( "<A HREF=\"%s#Team_%04d\">", p_filename(filebase, "finish" ,"html"), team_buf.numb );
885
        print( "%4.4s", pr_place( team_buf.leg[0].l_place, ptr->flags.bad_times | (ptr->class == config.nonequestrian_class) ) );
886
        if ( report_html ) print( "</A>" );
887
 
888
        print( "\n" );
889
    }
890
 
891
    print_class_stats( last_class, TRUE );
892
    print_legend(last_class);
893
    close_printer();
894
 
895
 
896
    /*
897
    **  If we are generating an HTML report then we need to create the file
898
    **  that contains all the team names - the assumption is that this data
899
    **  is available
900
    */
901
    if ( report_html )
902
    {
903
        pri_team();
904
    }
905
 
906
    /*
907
    **  Generate the awards report.
908
    **  This is only available as an HTML report
909
    */
910
    if ( report_html )
911
    {
912
        pri_awards();
913
    }
914
 
915
    /*
916
    **  Generate the master index page
917
    */
918
    if ( report_html )
919
    {
920
        pri_master_index();
921
    }
922
 
923
}
924
 
925
/*========================================================================
926
 *
927
 *  Place to text
928
 *
929
 *  Purpose:
930
 *      This function is called to convert a place to text
931
 *
932
 *  Parameters:
933
 *      place
934
 *
935
 *  Returns:
936
 *      text
937
 *
938
 *========================================================================*/
939
 
940
char *placing ( int place )
941
{
942
    if ( place > MAX_PLACE )
943
    {
944
        return tprintf( "Place: %d", place);
945
    }
946
    return tprintf ("%s Place", place_text[place]);
947
}
948
 
949
/*========================================================================
950
 *
951
 *  Print award results
952
 *
953
 *  Purpose:
954
 *      This function is called to Print award results
955
 *
956
 *  Parameters:
957
 *      None
958
 *
959
 *  Returns:
960
 *      Nothing
961
 *
962
 *========================================================================*/
963
void pri_awards(void)
964
{
965
    int j;
966
    int i;
967
    int k;
968
    int windex;
969
    ty_s_data  *ptr;
970
    int         last_class;
971
 
972
    report_html = 1;
973
    if( !open_printer( "", "awards", 132, report_html, "Prizes and Awards" ) )
974
        return;
975
 
976
    /*
977
    **  Generate an index for this page
978
    */
979
    print( "\n");
980
    print( "<hr>" );
981
    print( "<A NAME=\"%s\"></A>","INDEX");
982
    print( "Award Categories");
983
 
984
    for( j = 1; j <= config.num_class; j++ )
985
    {
986
        /*
987
        **  Header for the class
988
        */
989
        if ( config.class_winners[j-1] <= 0 )
990
            continue;
991
 
992
        print( "\n");
993
        print( "    <A HREF=\"#%s\">",config.team_class[j-1].full_name);
994
        print( "%s",  config.team_class[j-1].full_name );
995
        print( "</A>" );
996
    }
997
 
998
    /*
999
    **  Manual entries
1000
    */
1001
    print( "\n");
1002
    print( "    <A HREF=\"#%s\">","Hall Of Fame");
1003
    print( "%s",  "Hall Of Fame" );
1004
    print( "</A>" );
1005
 
1006
    print( "\n");
1007
    print( "    <A HREF=\"#%s\">","FASTEST");
1008
    print( "%s",  "FASTEST" );
1009
    print( "</A>" );
1010
 
1011
    /*
1012
    **  Sort the data by class
1013
    */
1014
    sort_team_data( 0, S_LC );      /* Generate class placement data */
1015
    last_class = -1;                /* Invalid class to start with */
1016
 
1017
    /*
1018
    **  Process each category
1019
    */
1020
    for( j = 1; ; j++ )
1021
    {
1022
        /*
1023
        **  Tail for previous entry
1024
        */
1025
        if ( j != 1 )
1026
            print( "<A HREF=\"#%s\">Awards Index</A>","INDEX");
1027
 
1028
        if ( j > config.num_class  )
1029
            break;
1030
 
1031
        /*
1032
        **  Header for the class
1033
        */
1034
        print( "\n");
1035
        print( "<hr>" );
1036
        print( "<A name=\"%s\"></A>",config.team_class[j-1].full_name);
1037
        print( "<A HREF=\"%s\">",p_filename(filebase, config.team_class[j - 1].abr ,"html"));
1038
        print( "%s",  config.team_class[j-1].full_name );
1039
        print( "</A>" );
1040
 
1041
                if ( config.class_winners[j-1] <= 0 )
1042
        {
1043
            print( "\n");
1044
            print( "No winners awarded" );
1045
            continue;
1046
        }
1047
 
1048
        /*
1049
        **  Enties for 'n' the best teams as configured
1050
        */
1051
        windex = 0;                     /* Winners done */
1052
        for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
1053
        {
1054
            if ( ptr->class != j )
1055
            {
1056
                continue;
1057
            }
1058
 
1059
            /*
1060
            **  Now read in the team record
1061
            */
1062
            if( valid_field( ptr->team ) && g_record( ptr->team, &team_buf ) )
1063
            {
1064
                windex++;
1065
 
1066
                /*
1067
                **  If printing an HTML report then we need to mark
1068
                **  the entry with a reference so that we can link to it
1069
                */
1070
                print( "\n");
1071
                print( "<A NAME=\"Team_%04d\">",team_buf.numb );
1072
                print( "</A>" );
1073
 
1074
                /*
1075
                **  Basic information
1076
                **      - Team number - with Xref back to full result
1077
                **      - Full team name
1078
                **      - Full categoray name
1079
                */
1080
                print( "%s", placing(windex) );
1081
 
1082
                print( "  Team Name: <A HREF=\"%s#Team_%04d\">", p_filename(filebase, "name" ,"html"), team_buf.numb );
1083
                print( "%-*s ",     MAX_TM_NAME, team_buf.name );
1084
                print( "</A>" );
1085
 
1086
                print( "  Number: <A HREF=\"%s#Team_%04d\">", p_filename(filebase, "finish" ,"html"), team_buf.numb );
1087
                print( "%4d",       team_buf.numb );
1088
                print( "</A>" );
1089
 
1090
 
1091
                for( k = 0; k < MAX_MEMB; k++ )
1092
                {
1093
 
1094
                    /*
1095
                    **  Skip equestrian leg in the non-equestion display
1096
                    */
1097
                    if ( k + 1 == config.equestrian_leg && ptr->class == config.nonequestrian_class)
1098
                        continue;
1099
 
1100
                    print( "\n");
1101
                    print( "    ");
1102
                    print( "%-*s", MAX_PERSON_NAME, config.leg_name[k] ? config.leg_name[k] : "Competitor"  );
1103
                    print( " %-*s", MAX_PERSON_NAME, team_buf.members[k].name );
1104
 
1105
                    print( "  %-8s", time_a( team_buf.leg[k+1].elapsed ) );
1106
                }
1107
 
1108
                print( "\n");
1109
                print( "    ");
1110
                print_bold( TRUE );
1111
                print( "%-*s %-*s  %-8s", MAX_PERSON_NAME , "Total" ,MAX_PERSON_NAME, "",time_a( team_buf.leg[0].elapsed ) );
1112
                print_bold( FALSE );
1113
                print( "\n" );
1114
            }
1115
 
1116
 
1117
            /*
1118
            **  More to do
1119
            */
1120
            if ( windex >= config.class_winners[j-1] )
1121
            {
1122
                break;
1123
            }
1124
        }
1125
    }
1126
 
1127
    /*
1128
    **  Generate the Hall of Fame information
1129
    */
1130
    print( "\n");
1131
    print( "<hr>" );
1132
    print( "<A name=\"%s\"></A>","Hall Of Fame");
1133
    print( "%s",  "Hall of Fame" );
1134
 
1135
    if ( config.num_fame  )
1136
    {
1137
        for( i = 1; i <= config.num_fame; i++ )
1138
        {
1139
            print( "\n    %-*s", MAX_PERSON_NAME, config.hall_fame[i-1] );
1140
        }
1141
    }
1142
    else
1143
    {
1144
        printf( "\n    There are no new stars for the Hall of Fame");
1145
    }
1146
    print( "<p><A HREF=\"#%s\">Awards Index</A>","INDEX");
1147
 
1148
    /*
1149
    **  Generate the FASTEST information
1150
    */
1151
    print( "<hr>" );
1152
    print( "<A name=\"%s\"></A>","FASTEST");
1153
    print( "%s",  "FASTEST" );
1154
 
1155
    /*
1156
    **  Sort the data and then generate the stats - again
1157
    */
1158
    do_big_sort();
1159
    gen_stats();
1160
 
1161
    for( i = 1; i <= config.num_legs; i++ )
1162
    {
1163
        g_record( stats.fast.team[i][0], &team_buf );
1164
 
1165
        print( "\n");
1166
        print( "    %-13s ", config.leg_name[i - 1] );
1167
        print( "  Team Name: <A HREF=\"%s#Team_%04d\">", p_filename(filebase, "name" ,"html"), team_buf.numb );
1168
        print( "%-*s", MAX_PERSON_NAME, team_buf.members[i-1].name );
1169
        print( "</A>" );
1170
        print( "  Team :<A HREF=\"%s#Team_%04d\">", p_filename(filebase, "finish" ,"html"), team_buf.numb );
1171
        print( "%4d ", stats.fast.team[i][0] );
1172
        print( "</A>" );
1173
        print( "Time:%s ", time_a( stats.fast.time[i][0] ) );
1174
 
1175
    }
1176
 
1177
 
1178
    print( "<p><A HREF=\"#%s\">Awards Index</A>","INDEX");
1179
    close_printer();
1180
}
1181
 
1182
/*========================================================================
1183
 *
1184
 *  pri_master_index
1185
 *
1186
 *  Purpose:
1187
 *      This function is called to create an HTML page that references all
1188
 *      the other pages that have been generated
1189
 *
1190
 *      Assume that they are in the same directory
1191
 *
1192
 *  Parameters:
1193
 *      None
1194
 *
1195
 *  Returns:
1196
 *      Nothing
1197
 *
1198
 *========================================================================*/
1199
void pri_master_index_entry(char *name, char *text)
1200
{
1201
    print( "<tr><td>");
1202
    print ("<A HREF=\"%s\">%s</A>\n", p_filename(filebase, name ,"html"), text );
1203
}
1204
 
1205
 
1206
void pri_master_index(void)
1207
{
1208
    int j;
1209
 
1210
    report_html = 1;
1211
    if( !open_printer( "", "index", 132, report_html, "Master Index" ) )
1212
        return;
1213
 
1214
    /*
1215
    **  Names
1216
    */
1217
    print( "<TABLE border=0 align=center>" );
1218
    pri_master_index_entry( "name", "Teams by Name" );
1219
    pri_master_index_entry( "finish", "Finishing Order for all Teams" );
1220
    pri_master_index_entry( "awards", "Prizes and Awards" );
1221
    print( "<tr><td>\n" );
1222
 
1223
    print( "\n" );
1224
    for( j = 1; j <= config.num_class; j++ )
1225
    {
1226
        pri_master_index_entry( config.team_class[j - 1].abr, tprintf("Category Results for: %s", config.team_class[j-1].full_name) );
1227
    }
1228
    print( "</TABLE>" );
1229
 
1230
    close_printer();
1231
}
1232
 
1233
 
1234
/*========================================================================
1235
 *
1236
 *  Print interim results
1237
 *
1238
 *  Purpose:
1239
 *      This function is called to Print interim results
1240
 *
1241
 *  Parameters:
1242
 *      None
1243
 *
1244
 *  Returns:
1245
 *      Nothing
1246
 *
1247
 *========================================================================*/
1248
 
1249
void pri_interim(void)
1250
{
1251
    ty_s_data  *ptr;
1252
    unsigned    i;
1253
    int         j, last_class;
1254
    char        suppress_classes;                /* Boolean. Printout class files too */
1255
    char       *report_title;
1256
 
1257
    cur( 0, 5 );
1258
    printf( "Generate interim result printouts\n" );
1259
    ck_data( -1, C_DISQUAL );                    /* Check the data - dummy check */
1260
    suppress_classes = getyes( "Do you want to suppress class printouts" );
1261
    printf( "\nSorting the data\n" );
1262
    do_big_sort();                             /* Sort on every thing */
1263
    gen_stats();                               /* Generate the stats too */
1264
 
1265
    printf( "\nGenerating the printed output\n" );
1266
 
1267
    /*
1268
     * Now print the data on the printer 
1269
     */
1270
 
1271
    if( !open_printer( "", "int", 132, report_html, "Interim Results" ) )
1272
        return;
1273
 
1274
    /*
1275
     * Print out the data 
1276
     */
1277
    print_class_header( -1, FALSE );                     /* Print the header */
1278
 
1279
    ptr = sort_data;
1280
    sort_team_data( 0, S_TEAM );                   /* Re-sort on team number */
1281
    for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
1282
    {
1283
        if ( ptr->class == config.nonequestrian_class )
1284
            continue;
1285
 
1286
        g_record( ptr->team, &team_buf );
1287
 
1288
        print( "%4d %4.4s %-*s",
1289
               team_buf.numb,
1290
               pi_place( team_buf.leg[config.num_legs].le_place,
1291
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ),
1292
               3,
1293
               team_buf.class ==
1294
 
1295
        for( j = 1; j <= config.num_legs; j++ )
1296
        {
1297
            print( "  %-8s %4.4s %4.4s",
1298
                   time_fa( team_buf.leg[j].elapsed,
1299
                            ptr->flags.disqualified ),
1300
                   pi_place( team_buf.leg[j].l_place, ptr->flags.disqualified,
1301
                             team_buf.leg[j].elapsed ),
1302
                   pi_place( team_buf.leg[j].le_place,
1303
                             ptr->flags.disqualified,
1304
                             team_buf.leg[j].elapsed ) );
1305
        }
1306
        print( "  %-8s %4.4s\n",
1307
               time_fa( team_buf.leg[0].elapsed, ptr->flags.disqualified ),
1308
               pi_place( team_buf.leg[config.num_legs].lec_place,
1309
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ) );
1310
    }
1311
 
1312
    print_class_stats( -1, FALSE );             /* Print statistics */
1313
    print_legend(-1);                             /* Print the legend */
1314
    close_printer();                            /* Close the printer */
1315
 
1316
 
1317
    /*
1318
     * Now produce a breakdown on a class by class basis 
1319
     * Now print out the class placement information
1320
     */
1321
 
1322
    if( suppress_classes )
1323
    {
1324
        printf( "WARNING: Class printouts suppressed\n" );
1325
        return;
1326
    }
1327
 
1328
    sort_team_data( 0, S_CLASS );              /* Generate class placement data */
1329
    last_class = -1;                             /* Invalid class to start with */
1330
 
1331
    for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
1332
    {
1333
        /*
1334
        **  Detect a change in the "class"
1335
        **  All data is within the one array of data
1336
        **  Use the in-memory class as this MAY differ from that stored
1337
        **  The non-equestrian class does this.
1338
        */
1339
        if( last_class != ptr->class )
1340
        {
1341
            if( last_class >= 0 )
1342
            {
1343
                print_class_stats( last_class, TRUE );
1344
                print_legend(last_class);
1345
                close_printer();
1346
            }
1347
 
1348
            report_title = tprintf( "Interim Category results for : %-*s", LEN_CLASS_NAME, team_buf.class == 0 ? "" : config.team_class[ptr->class - 1].full_name );
1349
 
1350
            if( !open_printer( "", tprintf( "i%2s", config.team_class[ptr->class - 1].abr ), 132, report_html, report_title ) )
1351
                continue;
1352
            print_class_header( last_class = ptr->class, FALSE );
1353
        }
1354
 
1355
        /*
1356
        **  Now read in the team record
1357
        */
1358
        g_record( ptr->team, &team_buf );
1359
        print( "%4d %4.4s %-*s",
1360
               team_buf.numb,
1361
               pi_place( team_buf.leg[config.num_legs].lec_place,
1362
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ),
1363
               3,
1364
               team_buf.class ==
1365
 
1366
        for( j = 1; j <= config.num_legs; j++ )
1367
        {
1368
            print( "  %-8s %4.4s %4.4s",
1369
                   time_fa( team_buf.leg[j].elapsed,
1370
                            ptr->flags.disqualified ),
1371
                   pi_place( team_buf.leg[j].lc_place,
1372
                             ptr->flags.disqualified,
1373
                             team_buf.leg[j].elapsed ),
1374
                   pi_place( team_buf.leg[j].lec_place,
1375
                             ptr->flags.disqualified,
1376
                             team_buf.leg[j].elapsed ) );
1377
        }
1378
        print( "  %-8s %4.4s\n",
1379
               time_fa( team_buf.leg[0].elapsed, ptr->flags.disqualified ),
1380
               pi_place( team_buf.leg[config.num_legs].le_place,
1381
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ) );
1382
    }
1383
 
1384
    print_class_stats( last_class, FALSE );
1385
    print_legend(last_class);
1386
    close_printer();
1387
 
1388
}
1389
 
1390
/*========================================================================
1391
 *
1392
 *  Print a class header
1393
 *
1394
 *  Purpose:
1395
 *      This function is called to print a class header
1396
 *
1397
 *  Parameters:
1398
 *      class           Name of this class
1399
 *      final           False - prelim results
1400
 *
1401
 *  Returns:
1402
 *      Nothing
1403
 *
1404
 *========================================================================*/
1405
 
1406
void print_class_header( int class, int final )
1407
{
1408
    int         j;
1409
 
1410
    /*
1411
    **  Give a clear indication that the report is preliminary
1412
    */
1413
 
1414
    if( !final )
1415
        print( "PRELIMINARY RESULTS ONLY\n\n" );
1416
 
1417
    /*
1418
    **  Now printout the column headings
1419
    **  This is a two line display
1420
    **
1421
    **  Line-1  Leg names
1422
    */
1423
    print( "%-*s %-*s %-*s", 4, "", 4, "", 3, "" );
1424
    for( j = 1; j <= config.num_legs; j++ )
1425
    {
1426
        print_bold( TRUE );
1427
        print( "  %-*s", 18, config.leg_name[j - 1] );
1428
        print_bold( FALSE );
1429
    }
1430
    print( "  %-8s %-4s\n", "Total", ( class < 0 ) ? "Cat" : "Fin" );
1431
 
1432
 
1433
    /*
1434
    **  Line-2  Details
1435
    */
1436
    print_underline( TRUE );
1437
    print( "%-*s %*s %-*s", 4, final ? "Plce" : "Team",
1438
                            4, final ? "Team" : "Plce",
1439
                            3, "Cat" );
1440
 
1441
    for( j = 1; j <= config.num_legs; j++ )
1442
        print( "  %-8s %-4s %-4s", "Time", " LP", " EP" );
1443
 
1444
    print( "  %-8s %-4s\n", "Time", "Plce" );
1445
    print_underline( FALSE );
1446
}
1447
 
1448
/*========================================================================
1449
 *
1450
 *  Generate the class stats
1451
 *
1452
 *  Purpose:
1453
 *      This function is called to Generate the class stats
1454
 *
1455
 *  Parameters:
1456
 *      c           Class to print
1457
 *      final       TRUE: Final data
1458
 *                  FALSE: Interim data
1459
 *
1460
 *  Returns:
1461
 *      Nothing
1462
 *
1463
 *========================================================================*/
1464
 
1465
void print_class_stats( int c, int final )
1466
{
1467
    int         i, j;
1468
    char        *title;
1469
 
1470
    if( c < 0 )
1471
    {
1472
        title = "Event";
1473
        c = 0;
1474
    }
1475
    else
1476
    {
1477
        title = "Category";
1478
    }
1479
 
1480
    print( "\n" );
1481
    if ( report_html ) print_underline(TRUE);
1482
    print( "%s statistics", title );
1483
    if ( report_html ) print_underline(FALSE);
1484
    print( "\n" );
1485
 
1486
 
1487
    /*
1488
    **  Print the names of the different legs
1489
    */
1490
    print( "%-*s       ", LEN_CLASS_NAME, "" );
1491
    for( i = 1; i <= config.num_legs; i++ )
1492
    {
1493
        print_bold( TRUE );
1494
        print( "%-13s  ", config.leg_name[i - 1] );
1495
        print_bold( FALSE );
1496
    }
1497
    print( "%-13s  \n", final ? "Total" : "" );
1498
 
1499
    /*
1500
    **  Print the fastest teams for each leg and overall
1501
    **  Add cross references to the team names for the fastest teams
1502
    */
1503
    print( "%*s : ", LEN_CLASS_NAME, "Fastest" );
1504
    for( i = 0; i <= config.num_legs; i++ )
1505
    {
1506
        j = i + 1;
1507
        if( i >= config.num_legs )
1508
        {
1509
            if( final )
1510
                j = 0;                           /* Leg-0 last */
1511
            else
1512
                break;
1513
        }
1514
 
1515
        if ( report_html ) print( "<A HREF=\"%s#Team_%04d\">", p_filename(filebase, "name" ,"html"), stats.fast.team[j][c] );
1516
        print( "%4d",  stats.fast.team[j][c] );
1517
        if ( report_html ) print( "</A>" );
1518
        print( " %s  ", time_a( stats.fast.time[j][c] ) );
1519
    }
1520
    print( "\n" );
1521
 
1522
    /*
1523
    **  Print the average time for each leg
1524
    */
1525
    print( "%*s : ", LEN_CLASS_NAME, "Average" );
1526
    for( i = 0; i <= config.num_legs; i++ )
1527
    {
1528
        j = i + 1;
1529
        if( i >= config.num_legs )
1530
        {
1531
            if( final )
1532
                j = 0;                           /* Leg-0 last */
1533
            else
1534
                break;
1535
        }
1536
        print( "     %s  ", time_a( stats.average[j][c] ) );
1537
    }
1538
}
1539
 
1540
/*========================================================================
1541
 *
1542
 *  Print the legend
1543
 *
1544
 *  Purpose:
1545
 *      This function is called to Print the legend
1546
 *
1547
 *  Parameters:
1548
 *      class       - Class currently being printed
1549
 *
1550
 *  Returns:
1551
 *      Nothing
1552
 *
1553
 *========================================================================*/
1554
 
1555
void print_legend ( int class )
1556
{
1557
 
1558
    int         i;
1559
    char        line[201];
1560
    FILE       *adfile = NULL;
1561
    int         count;
1562
 
1563
    /*
1564
     * First the categories 
1565
     */
1566
    print( "\n\n" );
1567
    if ( report_html ) print_underline(TRUE);
1568
    print( "Category abbreviations" );
1569
    if ( report_html ) print_underline(FALSE);
1570
    print( "\n" );
1571
 
1572
 
1573
    for( i = 1, count = 0; i <= config.num_class; i++ )
1574
    {
1575
#if 0
1576
        /*
1577
        **  Skip any non-equestrian class in the legend
1578
        **  Don't want to tell the general user whats goes on, unless we actually
1579
        **  creating the non-equestrian report.
1580
        */
1581
        if ( class != config.nonequestrian_class  && i == config.nonequestrian_class )
1582
            continue;
1583
#endif
1584
        if ( report_html ) print( "<A HREF=\"%s\">",p_filename(filebase, config.team_class[i - 1].abr ,"html") );
1585
        print( "%-*s", 3, config.team_class[i - 1].abr );
1586
        if ( report_html ) print( "</A>" );
1587
        print( " : %-*s  ", LEN_CLASS_NAME, config.team_class[i - 1].full_name );
1588
 
1589
        if( !( ++count % 5 ) )
1590
            print( "\n" );
1591
    }
1592
 
1593
    /*
1594
    **  Add link to the finish order report
1595
    */
1596
    if ( report_html )
1597
    {
1598
        print( "<A HREF=\"%s\">", p_filename(filebase, "finish" ,"html") );
1599
        print( "%-*s", 3, "All" );
1600
        print( "</A>" );
1601
        print( " : %-*s  ", LEN_CLASS_NAME, "Finishing Order" );
1602
    }
1603
 
1604
    /*
1605
    **  Country data - if countries have been defined
1606
    */
1607
    if( config.num_countries )
1608
    {
1609
        print( "\n\n" );
1610
        if ( report_html ) print_underline(TRUE);
1611
        print( "Country abbreviations" );
1612
        if ( report_html ) print_underline(FALSE);
1613
        print( "\n" );
1614
 
1615
        for( i = 0, count = 0; i < MAX_COUNTRY; i++ )
1616
        {
1617
            if( config.country_name[i].abr[0] )
1618
            {
1619
                print( "%-*s : %-*s  ", 4, config.country_name[i].abr,
1620
                       LEN_CNTRY_NAME, config.country_name[i].full_name );
1621
                if( !( ++count % 5 ) )
1622
                    print( "\n" );
1623
            }
1624
        }
1625
    }
1626
 
1627
    /*
1628
     * Other comments 
1629
     */
1630
 
1631
    print( "\n\nPlace numbers (LP and EP)\n" );
1632
    print( "LP - Placing based on elapsed time within the leg.                Cat Plce - Placing within the category.\n" );
1633
    print( "EP - Placing based on accumulated times to the end of that leg.   Fin Plce - Overall placing within the event.\n" );
1634
 
1635
    /*
1636
     *  Insert the contents of the config.addendum file
1637
     *  or a defualt message
1638
     */
1639
    if( config.addendum[0] )
1640
        adfile = fopen( config.addendum, "rt" );  /* Open the file for reading */
1641
 
1642
    if( adfile )
1643
    {
1644
        while( fgets( line, sizeof(line)-1, adfile ) )
1645
            print( "%s", line );
1646
    }
1647
    else
1648
    {
1649
        print( "\nTiming and Results by\n" );
1650
        print( "Embedded Solutions\n" );
1651
    }
1652
}
1653
 
1654
/*========================================================================
1655
 *
1656
 *  Return place data
1657
 *
1658
 *  Purpose:
1659
 *      This function is called to return place data
1660
 *
1661
 *      This routine is called to fill a print team_buffer - to allow for
1662
 *      multiple calls to this function ( before the data is used ) a number
1663
 *      of static team_buffers are maintained
1664
 *
1665
 *  Parameters:
1666
 *      num         place - if not bad_times
1667
 *      disq        Disqualified flag
1668
 *      time        Time data is based on
1669
 *
1670
 *  Returns:
1671
 *      This function returns a pointer to the character string for the
1672
 *      number or a pointer to a bad_times string.
1673
 *
1674
 *========================================================================*/
1675
 
1676
char       *pi_place( int num, int disq, time_t time )
1677
{
1678
    static char store[2][5];                     /* 2 stores for 4 digit numbers */
1679
    static int  i = 0;                           /* Current index into store */
1680
    static char *dis = "D";                      /* Disqualified */
1681
    static char *non = "-";                      /* Invalid time */
1682
 
1683
    if( disq )                                   /* Disqualified team */
1684
        return ( dis );
1685
    if( time <= 0 )                              /* Unknown time */
1686
        return ( non );
1687
 
1688
    i++;
1689
    if( i >= 2 )
1690
        i = 0;                                   /* Select next entry */
1691
    sprintf( store[i], "%4d", num );
1692
    return ( store[i] );
1693
 
1694
}
1695
 
1696
/*========================================================================
1697
 *
1698
 *  Return place data
1699
 *
1700
 *  Purpose:
1701
 *      This function is called to Return place data
1702
 *
1703
 *      This routine is called to fill a print team_buffer - to allow for
1704
 *      multiple calls to this function ( before the data is used ) a number
1705
 *      of static team_buffers are maintained
1706
 *
1707
 *  Parameters:
1708
 *      num         place - if not bad_times
1709
 *      disq        Disqualified flag
1710
 *
1711
 *  Returns:
1712
 *      This function returns a pointer to the character string for the
1713
 *      number or a pointer to a bad_times string.
1714
 *
1715
 *========================================================================*/
1716
 
1717
char *pr_place( int num, int disq )
1718
{
1719
    static char store[2][5];                     /* 2 stores for 4 digit numbers */
1720
    static int  i = 0;                           /* Current index into store */
1721
    static char *dis = "U";
1722
 
1723
    if( disq )
1724
        return ( dis );
1725
 
1726
    i++;
1727
    if( i >= 2 )
1728
        i = 0;                                   /* Select next entry */
1729
    sprintf( store[i], "%4d", num );
1730
    return ( store[i] );
1731
 
1732
}
1733
 
1734
/*========================================================================
1735
 *
1736
 *  Check data for bad times
1737
 *
1738
 *  Purpose:
1739
 *      This function is called to Check data for bad times
1740
 *      Scan the sort data structure and locate entries that have incorrect
1741
 *      times.
1742
 *      
1743
 *      Entries that have invalid leg times are displayed to the operator
1744
 *      and the report process can be aborted
1745
 *
1746
 *  Parameters:
1747
 *      leg         Leg to test
1748
 *      mode            Either end or elapsed times to be tested
1749
 *
1750
 *  Returns:
1751
 *      Returns FALSE if the report operation is to be aborted
1752
 *
1753
 *========================================================================*/
1754
 
1755
bool ck_data( int leg, int mode )
1756
{
1757
    ty_s_data  *ptr;
1758
    unsigned    i;
1759
    int         bad = 0;
1760
    int         j = 0;
1761
    int         k, bad_leg;
1762
    time_t     *t;                               /* An array of times */
1763
 
1764
    ptr = sort_data;
1765
    for( i = 1; i <= sort_num; i++, ptr++ )
1766
    {
1767
        bad_leg = 0;
1768
        if( mode == C_DISQUAL )
1769
        {
1770
            ptr->flags.bad_times = ptr->flags.disqualified;
1771
            continue;
1772
        }
1773
 
1774
        if( mode == C_ELAPSED )
1775
            t = ptr->lege;
1776
        else
1777
            t = ptr->leg;
1778
 
1779
        if( ( ptr->flags.bad_times = ptr->flags.disqualified ) == FALSE )
1780
        {
1781
            if( leg <= 0 )
1782
            {
1783
                for( k = 0; k <= config.num_legs; k++ )
1784
                {
1785
                    if ( !(config.equestrian_leg && ptr->flags.non_equestrian && config.equestrian_leg == k  ))
1786
                        bad_leg |= ( t[k] <= 0 );
1787
                }
1788
            }
1789
            else
1790
            {
1791
                bad_leg = t[leg] <= 0;
1792
            }
1793
 
1794
            if( bad_leg )
1795
            {
1796
                ptr->flags.bad_times = TRUE;
1797
                if( !bad )
1798
                    printf( "Team with incorrect time information\n" );
1799
                if( ++j > 15 )
1800
                {
1801
                    printf( "\n" );
1802
                    j = 0;
1803
                }
1804
                printf( "%4d ", ptr->team );
1805
                bad++;
1806
            }
1807
        }
1808
    }
1809
 
1810
    if( bad )
1811
    {
1812
        printf( "\n%d teams with incorrect times.\n", bad );
1813
        return ( !getyes
1814
                 ( "These have been flagged as unplaced - continue report" ) );
1815
    }
1816
    return ( FALSE );
1817
}
1818
 
1819
/*========================================================================
1820
 *
1821
 *  Update placing information
1822
 *
1823
 *  Purpose:
1824
 *      This function is called to Update placing information
1825
 *
1826
 *      This routine will rip through the data generating the team placing in
1827
 *      a) Within a leg
1828
 *      b) At the end of a leg
1829
 *      c) Within a leg by  class
1830
 *      d) At the end of a leg by class
1831
 *
1832
 *      This function is provided to allow the display routines to
1833
 *      be accessed and updated without the need to run a report
1834
 *
1835
 *  Parameters:
1836
 *      xxxx        a ptr to the xxxx stuff
1837
 *
1838
 *  Returns:
1839
 *      Nothing
1840
 *
1841
 *========================================================================*/
1842
 
1843
void srt_place(void)
1844
{
1845
    int         i, j;
1846
 
1847
    cur( 0, 5 );
1848
    printf( "Update the team placings to the data base\n" );
1849
    flush_out();
1850
    if( ck_data( -1, C_ELAPSED ) )
1851
        return;
1852
    do_big_sort();
1853
 
1854
    /*
1855
     * Generate the stats and display them on the screen for interest
1856
     * This operation will not hurt - so why not
1857
     */
1858
 
1859
    gen_stats();
1860
    printf( "\nEvent statistics\n\n" );
1861
    printf( "%-*s   %-13s ", LEN_CLASS_NAME, "", "Overall" );
1862
    for( i = 1; i <= config.num_legs; i++ )
1863
        printf( "%-13s ", config.leg_name[i - 1] );
1864
 
1865
    for( j = 0; j <= config.num_class; j++ )
1866
    {
1867
        printf( "\n%-*s : ", LEN_CLASS_NAME,
1868
                j ? config.team_class[j - 1].full_name : "Overall" );
1869
        for( i = 0; i <= config.num_legs; i++ )
1870
        {
1871
            printf( "%4d ", stats.fast.team[i][j] );
1872
            printf( "%s ", time_a( stats.fast.time[i][j] ) );
1873
        }
1874
        printf( "\n%*s : ", LEN_CLASS_NAME, "Average" );
1875
        for( i = 0; i <= config.num_legs; i++ )
1876
        {
1877
            printf( "     %s ", time_a( stats.average[i][j] ) );
1878
        }
1879
    }
1880
    printf( "\nAny key to continue" );
1881
    ( void ) getinp();
1882
}
1883
 
1884
/*========================================================================
1885
 *
1886
 *  Calculate summary information
1887
 *
1888
 *  Purpose:
1889
 *      This function is called to calculate summary information
1890
 *
1891
 *  Parameters:
1892
 *      ptr         - Address of a summary structure to fill in
1893
 *
1894
 *  Returns:
1895
 *      Nothing
1896
 *
1897
 *========================================================================*/
1898
 
1899
void calc_class_summary( t_class_summary * ptr )
1900
{
1901
    int i;
1902
 
1903
    /*
1904
    **  Reset the data
1905
    */
1906
    memset ( ptr, 0, sizeof (*ptr ));
1907
 
1908
    /*
1909
     * Extract the required data from the data base
1910
     * Only save that information required for the operation
1911
     */
1912
 
1913
    for( i = config.min_team; i <= config.max_team; i++ )
1914
    {
1915
        if( valid_field( i ) && g_record( i, &team_buf ) )
1916
        {
1917
            ptr->total.total++;
1918
            ptr->class[team_buf.class].total++;
1919
 
1920
            if ( team_buf.flags.disqualified )
1921
            {
1922
                ptr->class[team_buf.class].disqualified++;
1923
                ptr->total.disqualified++;
1924
            }
1925
 
1926
            if ( config.nonequestrian_class && team_buf.flags.non_equestrian )
1927
            {
1928
                ptr->class[team_buf.class].non_equestrian++;
1929
                ptr->total.non_equestrian++;
1930
            }
1931
        }
1932
    }
1933
}
1934
 
1935
/*========================================================================
1936
 *
1937
 *  Display summary information
1938
 *
1939
 *  Purpose:
1940
 *      This function is called to display summary information
1941
 *
1942
 *  Parameters:
1943
 *      None
1944
 *
1945
 *  Returns:
1946
 *      Nothing
1947
 *
1948
 *========================================================================*/
1949
 
1950
void display_summary (void)
1951
{
1952
 
1953
    t_class_summary data;
1954
    int         i;
1955
    int         line = 2;
1956
 
1957
    cur( 0, line );
1958
    printf( "Generating Summary Information" );
1959
    calc_class_summary( & data );
1960
 
1961
 
1962
    /*
1963
    **  Display summary stats
1964
    */
1965
 
1966
    cur( 0, line );
1967
    console_clreol();
1968
    printf( "Summary Information\n\n" );
1969
    printf( "%*s : %-7s %-7s%-7s\n", LEN_CLASS_NAME,
1970
                                      "Category",
1971
                                      "Total",
1972
                                      "Disq",
1973
                                      "NonEq" );
1974
 
1975
    for( i = 0; i < config.num_class; i++ )
1976
    {
1977
        /*
1978
        **  The non-equestrian leg does not have any data
1979
        **  Supress the display
1980
        */
1981
        if ( config.nonequestrian_class == i+1  )
1982
            continue;
1983
 
1984
        printf( "%*s : %-7d %-7d %-7d\n", LEN_CLASS_NAME,
1985
                                          config.team_class[i].full_name,
1986
                                          data.class[i+1].total,
1987
                                          data.class[i+1].disqualified,
1988
                                          data.class[i+1].non_equestrian );
1989
    }
1990
 
1991
    printf( "\n" );
1992
    printf( "%*s : %-7d %-7d %-7d\n", LEN_CLASS_NAME,
1993
                                      "Totals",
1994
                                      data.total.total,
1995
                                      data.total.disqualified,
1996
                                      data.total.non_equestrian );
1997
 
1998
    printf( "\nAny key to continue " );
1999
    getinp();
2000
}
2001
 
2002
 
2003
/*========================================================================
2004
 *
2005
 *  Main sort routine for final data
2006
 *
2007
 *  Purpose:
2008
 *      This function is called to do the report sort routine for final data
2009
 *      This routine will fill all the gaps in the sort_aux structure
2010
 *
2011
 *  Parameters:
2012
 *      None
2013
 *
2014
 *  Returns:
2015
 *      Nothing
2016
 *
2017
 *========================================================================*/
2018
 
2019
void do_big_sort(void)
2020
{
2021
    int         i, k;                            /* Looooopy things */
2022
    unsigned    j;
2023
    ty_s_data  *ptr;                             /* Pointer to sort data */
2024
    int         class;                           /* Current class */
2025
 
2026
    printf( "Sorting it ALL out" );
2027
    flush_out();
2028
 
2029
    for( i = 0; i <= config.num_legs; i++ )
2030
    {
2031
        /*
2032
        **  Sort on leg elapsed time
2033
        **  The save the teams elapsed place in each leg
2034
        */
2035
        sort_team_data( i, S_L );
2036
        for( j = 1, ptr = sort_data; j <= sort_num; j++, ptr++ )
2037
        {
2038
            sort_aux[ptr->team].l_place[i] = j;
2039
            sort_aux[ptr->team].team = ptr->team;
2040
        }
2041
 
2042
        /*
2043
        **  Sort on leg end time
2044
        **  Then save the teams place at the end of each leg
2045
        */
2046
        sort_team_data( i, S_LE );
2047
        for( j = 1, ptr = sort_data; j <= sort_num; j++, ptr++ )
2048
            sort_aux[ptr->team].le_place[i] = j;
2049
 
2050
        /*
2051
        **  Sort on elapsed time per class
2052
        **  The save the teams elapsed place in each leg per class
2053
        */
2054
        sort_team_data( i, S_LC );
2055
        class = -1;
2056
        for( k = 1, j = 1, ptr = sort_data; j <= sort_num; j++, ptr++ )
2057
        {
2058
            if( class != ptr->class )
2059
            {
2060
                k = 1;
2061
                class = ptr->class;
2062
            }
2063
            sort_aux[ptr->team].lc_place[i] = k++;
2064
        }
2065
 
2066
        /*
2067
        **  Sort on end time per class
2068
        **  Then save the teams place at the end of each leg per class
2069
        */
2070
        sort_team_data( i, S_LEC );
2071
        class = -1;
2072
        for( k = 1, j = 1, ptr = sort_data; j <= sort_num; j++, ptr++ )
2073
        {
2074
            if( class != ptr->class )
2075
            {
2076
                k = 1;
2077
                class = ptr->class;
2078
            }
2079
            sort_aux[ptr->team].lec_place[i] = k++;
2080
        }
2081
    }
2082
 
2083
    /*
2084
    **  Write the place information back to disk for use in the displays
2085
    */
2086
    printf( "\nWriting it all back to the disk file" );
2087
    flush_out();
2088
 
2089
    for( i = config.min_team; i <= config.max_team; i++ )
2090
    {
2091
        if( sort_aux[i].team && valid_field( i ) && g_record( i, &team_buf ) )
2092
        {
2093
            for( k = 0; k <= config.num_legs; k++ )
2094
            {
2095
                team_buf.leg[k].l_place = sort_aux[i].l_place[k];
2096
                team_buf.leg[k].le_place = sort_aux[i].le_place[k];
2097
                team_buf.leg[k].lc_place = sort_aux[i].lc_place[k];
2098
                team_buf.leg[k].lec_place = sort_aux[i].lec_place[k];
2099
            }
2100
            put_team_record( i, &team_buf );
2101
        }
2102
    }
2103
}
2104
 
2105
/*========================================================================
2106
 *
2107
 *  Sort in memory buffer
2108
 *
2109
 *  Purpose:
2110
 *      This function is called to Sort in memory buffer
2111
 *
2112
 *  Parameters:
2113
 *      leg         Requested leg
2114
 *      mode        Defines the sort mode
2115
 *
2116
 *  Returns:
2117
 *      Nothing
2118
 *
2119
 *========================================================================*/
2120
 
2121
void sort_team_data( int leg, int mode )
2122
{
2123
 
2124
    unsigned    j;
2125
    ty_s_data  *ptr;
2126
 
2127
    sort_leg = leg;                              /* Leg is global for the comparison function */
2128
    sort_mode = mode;                            /* Mode is global for compare function */
2129
 
2130
    qsort( ( char * ) sort_data, sort_num, sizeof( ty_s_data ), sort_comp );
2131
 
2132
    /*
2133
     * Insert "place data" into the sorted data
2134
     * This simply the index into the array of data - after its been
2135
     * sorted.
2136
     */
2137
    ptr = sort_data;
2138
    for( j = 1; j <= sort_num; j++, ptr++ )
2139
        ptr->place = j;
2140
 
2141
}
2142
 
2143
/*========================================================================
2144
 *
2145
 *  qsort comparison function
2146
 *
2147
 *  Purpose:
2148
 *      This function is called by qsort as a Sort comparison function
2149
 *
2150
 *  Parameters:
2151
 *      a       - 1st record
2152
 *      b       - 2nd record
2153
 *
2154
 *  Returns:
2155
 *      value to qsort
2156
 *
2157
 *========================================================================*/
2158
 
2159
int sort_comp( const void * aa, const void * bb )
2160
{
2161
    const ty_s_data * a = aa;
2162
    const ty_s_data * b = bb;
2163
 
2164
 
2165
    int         i;                               /* One of those */
2166
    time_t      ta, tb;                          /* Leg times */
2167
    int         na, nb;                          /* Number of valid legs */
2168
    time_t      tta, ttb;                        /* Temp times */
2169
 
2170
    /*
2171
    **  Sorting on Team Number
2172
    */
2173
    if( sort_mode == S_TEAM )
2174
        return ( a->team - b->team );
2175
 
2176
    /*
2177
    **  Sorting on Class and Team Number
2178
    */
2179
    if( sort_mode == S_CLASS )
2180
    {
2181
        if( a->class != b->class )
2182
            return ( a->class - b->class );
2183
        else
2184
            return ( a->team - b->team );
2185
    }
2186
 
2187
    /*
2188
    **  Sorting within a class
2189
    **  First sort on the class
2190
    */
2191
    if( sort_mode == S_LEC || sort_mode == S_LC )   /* Sort within a class */
2192
        if( a->class != b->class )
2193
            return ( a->class - b->class );
2194
 
2195
    /*
2196
    **  Now we need to examine the times as we have sorted
2197
    **  on every thing else.
2198
    **
2199
    **  If one of the teams has bad_times, then that team is placed
2200
    **  lower in the sorting order. If both teams have bad times
2201
    **  then sort on team number. ie: Unplaced teams are sorted on
2202
    **  team number
2203
    */
2204
    if( a->flags.bad_times || b->flags.bad_times )  /* Valid data has precedence */
2205
    {
2206
        if( a->flags.bad_times && b->flags.bad_times )
2207
            return ( a->team - b->team );
2208
        else
2209
            return ( a->flags.bad_times ? 1 : -1 );
2210
    }
2211
 
2212
    /*
2213
    **  Not sorting within a class ie: Overall
2214
    **  Non-Equestrian is at the end, so that it doesn't get counted in the
2215
    **  finishing order
2216
    */
2217
    if( sort_mode == S_LE || sort_mode == S_L )     /* Sort NOT within a class */
2218
    {
2219
        if( a->flags.non_equestrian || b->flags.non_equestrian )
2220
        {
2221
            if( a->flags.non_equestrian && b->flags.non_equestrian )
2222
                return ( a->team - b->team );
2223
            else
2224
                return ( a->flags.non_equestrian ? 1 : -1 );
2225
        }
2226
    }
2227
 
2228
 
2229
    /*
2230
    **  Before we sort on times we must determine which time to
2231
    **  use. Finish time, Leg end times, Leg Elapsed times.
2232
    */
2233
 
2234
    switch ( sort_mode )
2235
    {
2236
      /*
2237
      **    Sort on finish times
2238
      */
2239
      case S_FIN:
2240
        ta = a->leg[sort_leg];
2241
        tb = b->leg[sort_leg];
2242
        break;
2243
 
2244
 
2245
      /*
2246
      **    Sort on accumulated leg times
2247
      */
2248
      case S_LE:
2249
      case S_LEC:
2250
        if( sort_leg )
2251
        {
2252
            /*
2253
            **  Calculate accumulated time up to the desired leg
2254
            **  If the two teams have a different number of valid
2255
            **  leg times then order by the team that has completed
2256
            **  more legs.
2257
            */
2258
            ta = tb = ( time_t ) 0;
2259
            na = nb = 0;
2260
            for( i = 1; i <= sort_leg; i++ )
2261
            {
2262
                tta = a->lege[i];
2263
                ttb = b->lege[i];
2264
                if( tta > 0 )
2265
                {
2266
                    na++;
2267
                    ta += tta;
2268
                }
2269
                if( ttb > 0 )
2270
                {
2271
                    nb++;
2272
                    tb += ttb;
2273
                }
2274
            }
2275
            if( na != nb )
2276
                return ( nb - na );
2277
        }
2278
        else
2279
        {
2280
            ta = a->leg[sort_leg] - a->start;
2281
            tb = b->leg[sort_leg] - b->start;
2282
        }
2283
        break;
2284
 
2285
      /*
2286
      **    Sort on Elapsed times
2287
      */
2288
      case S_LC:
2289
      case S_L:
2290
        ta = a->lege[sort_leg];
2291
        tb = b->lege[sort_leg];
2292
        break;
2293
 
2294
      /*
2295
      **    Just to be sure ...
2296
      */
2297
      default:
2298
        return ( 0 );
2299
    }
2300
 
2301
    /*
2302
    **  Finally. Compare the required team times
2303
    */
2304
    if( ta == tb )
2305
        return ( a->team - b->team );
2306
    if( ( ta > 0 ) && ( tb > 0 ) )
2307
        return ( ( int ) ( ta - tb ) );
2308
    return ( ( ta > 0 ) ? -1 : 1 );
2309
}
2310
 
2311
/*========================================================================
2312
 *
2313
 *  load report data into memory
2314
 *
2315
 *  Purpose:
2316
 *      This routine will pull all the data into memory 
2317
 *      Not all the team data is loaded. Only that essential for the
2318
 *      operation of the sort routine is loaded
2319
 *
2320
 *  Parameters:
2321
 *      None
2322
 *
2323
 *  Returns:
2324
 *      TRUE - All is well
2325
 *
2326
 *========================================================================*/
2327
 
2328
bool load_report_data(void)
2329
{
2330
 
2331
    ty_s_data  *ptr;                             /* pointer to sort data type */
2332
    int         j;
2333
    unsigned    num;
2334
 
2335
    printf( "Loading team information - This will not hurt" );
2336
    flush_out();
2337
 
2338
    /*
2339
     * Fetch memory for the data store
2340
     */
2341
 
2342
    if( sort_data )
2343
        free( ( char * ) sort_data );
2344
    sort_data = 0;
2345
 
2346
    if( sort_aux )
2347
        free( ( char * ) sort_aux );
2348
    sort_aux = 0;
2349
    sort_num = 0;                                /* Counter of records in the array */
2350
 
2351
    /*
2352
    **  Allocate memory for the data structures
2353
    **  This will be free'd
2354
    */
2355
    num = config.max_team - config.min_team + 1 ;
2356
 
2357
    /*
2358
    **  Allow for non-equestrian teams - since some of the data is loaded twice
2359
    **  Take a guess that at most 1/2 the teams will be non-equestrian
2360
    */
2361
    num = num * 3 / 2;
2362
 
2363
    sort_data = ( ty_s_data * ) calloc ( num , sizeof( ty_s_data ) );
2364
    sort_aux = ( ty_s_aux * ) calloc( num + 1, sizeof( ty_s_aux ) );
2365
 
2366
    if( sort_data == 0 || sort_aux == 0 )
2367
    {
2368
        printf( "\n\nError in allocating memory\n" );
2369
        sleep( 5 );
2370
        return ( FALSE );
2371
    }
2372
 
2373
    /*
2374
    **  Load data into the memory based data structure
2375
    **  Only load data for valid-teams
2376
    **  Load essential data
2377
    **      Team Number, class and flags
2378
    **      Leg end and elapsed times
2379
    */
2380
    ptr = sort_data;
2381
    for( team = config.min_team; team <= config.max_team; team++ )
2382
    {
2383
        if( valid_field( team ) )
2384
        {
2385
            g_record( team, &team_buf );
2386
            if( team_buf.flags.valid )
2387
            {
2388
                ptr->team = team;
2389
                for( j = 0; j < MAX_LEGS + 1; j++ )
2390
                {
2391
                    ptr->lege[j] = team_buf.leg[j].elapsed;
2392
                    ptr->leg[j] = team_buf.leg[j].end;
2393
                }
2394
                ptr->start = team_buf.leg[0].start;
2395
                ptr->class = team_buf.class;
2396
 
2397
                ptr->flags = team_buf.flags;
2398
                ptr++;
2399
                sort_num++;
2400
 
2401
                /*
2402
                **  If non-equestrian support is enabled then
2403
                **  duplicate and modify data for the non-equestrian teams
2404
                **      - Change the class
2405
                **      - Modify the leg time
2406
                */
2407
                if ( config.nonequestrian_class && team_buf.flags.non_equestrian )
2408
                {
2409
                    ptr->team = team;
2410
                    ptr->lege[0] = 0;
2411
 
2412
                    for( j = 0; j < MAX_LEGS + 1; j++ )
2413
                    {
2414
                        if ( j == config.equestrian_leg )
2415
                        {
2416
                            ptr->lege[j] = 0;
2417
                            if ( config.equestrian_leg > 1 )
2418
                                ptr->leg[j] = ptr->leg[j-1];
2419
                        }
2420
                        else
2421
                        {
2422
                            if ( j )
2423
                                ptr->lege[j] = team_buf.leg[j].elapsed;
2424
                            ptr->leg[j] = team_buf.leg[j].end;
2425
                            ptr->lege[0] += ptr->lege[j] ;
2426
                        }
2427
                    }
2428
 
2429
                    ptr->start = team_buf.leg[0].start;
2430
                    ptr->class = config.nonequestrian_class;
2431
                    ptr->flags = team_buf.flags;
2432
                    ptr->flags.disqualified = 0;
2433
                    ptr++;
2434
                    sort_num++;
2435
                }
2436
            }
2437
        }
2438
    }
2439
    return ( TRUE );
2440
}
2441
 
2442
/*========================================================================
2443
 *
2444
 *  Generate all the stats
2445
 *
2446
 *  Purpose:
2447
 *      This function is called to Generate all the stats
2448
 *
2449
 *  Parameters:
2450
 *      None
2451
 *
2452
 *  Returns:
2453
 *      Nothing
2454
 *
2455
 *========================================================================*/
2456
 
2457
void gen_stats(void)
2458
{
2459
    ty_s_data  *ptr;
2460
    unsigned    i;
2461
    int         j;
2462
    int         k;
2463
 
2464
    /*
2465
     * Init all the stats 
2466
     */
2467
    for( i = 0; i <= MAX_LEGS; i++ )
2468
    {
2469
        for( j = 0; j <= MAX_CLASS; j++ )
2470
        {
2471
            stats.team[i][j] = 0;
2472
            stats.fast.team[i][j] = 0;
2473
            stats.fast.time[i][j] = ( time_t ) - 1;
2474
            stats.average[i][j] = 0;
2475
        }
2476
    }
2477
 
2478
    for( i = 1, ptr = sort_data; i <= sort_num; i++, ptr++ )
2479
    {
2480
        /*
2481
        **  If there is any bad times in the team record, then none
2482
        **  of the data can be trusted.
2483
        **
2484
        **  If the team has been disqualified, then don't use any
2485
        **  of the data.
2486
        */
2487
        if( ptr->flags.bad_times || ptr->flags.disqualified )
2488
            continue;
2489
 
2490
        for( j = 0; j <= config.num_legs; j++ )
2491
        {
2492
            if( ptr->lege[j] <= 0 )              /* Ignore bad data */
2493
                continue;
2494
 
2495
            /*
2496
            **  Determine fastest team : overall
2497
            **  Ignore the non-equestrian data as this is in the list twice
2498
            */
2499
            if( ( ptr->lege[j] < stats.fast.time[j][0] )
2500
                || ( stats.fast.time[j][0] < 0 ) )
2501
            {
2502
                if ( ptr->class != config.nonequestrian_class )
2503
                {
2504
                    stats.fast.team[j][0] = ptr->team;
2505
                    stats.fast.time[j][0] = ptr->lege[j];
2506
                }
2507
            }
2508
 
2509
            /*
2510
            **  Determine fastest team : within a class
2511
            */
2512
            if( ( ptr->lege[j] < stats.fast.time[j][ptr->class] )
2513
                || stats.fast.time[j][ptr->class] < 0 )
2514
            {
2515
                stats.fast.team[j][ptr->class] = ptr->team;
2516
                stats.fast.time[j][ptr->class] = ptr->lege[j];
2517
            }
2518
 
2519
            /*
2520
            **  Sum the end times : overall
2521
            */
2522
            if ( ptr->class != config.nonequestrian_class )
2523
            {
2524
                stats.average[j][0] += ptr->lege[j];
2525
                stats.team[j][0]++;
2526
            }
2527
 
2528
 
2529
            /*
2530
            **  Sum the end times : within a class
2531
            */
2532
            stats.average[j][ptr->class] += ptr->lege[j];
2533
            stats.team[j][ptr->class]++;
2534
        }
2535
    }
2536
 
2537
    /*
2538
     * Calculate the averages
2539
     */
2540
    for( k = 0; k <= config.num_legs; k++ )
2541
    {
2542
        for( j = 0; j <= config.num_class; j++ )
2543
        {
2544
            if( stats.team[k][j] )
2545
                stats.average[k][j] /= stats.team[k][j];
2546
            else
2547
                stats.average[k][j] = ( time_t ) - 1;
2548
        }
2549
    }
2550
}
2551
 
2552
/********************************* EOF ***********************************/