Subversion Repositories svn1

Rev

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