Subversion Repositories svn1-original

Rev

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] );
1178
        print( "  Team Name: <A HREF=\"%s#Team_%04d\">", p_filename(filebase, "name" ,"html"), team_buf.numb );
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 );
1182
        print( "%4d ", stats.fast.team[i][0] );
1183
        print( "</A>" );
1184
        print( "Time:%s ", time_a( stats.fast.time[i][0] ) );
1185
 
1186
    }
1187
 
1188
 
1189
    print( "<p><A HREF=\"#%s\">Awards Index</A>","INDEX");
1190
    close_printer();
1191
}
1192
 
1193
/*========================================================================
1194
 *
1195
 *  pri_master_index
1196
 *
1197
 *  Purpose:
1198
 *      This function is called to create an HTML page that references all
1199
 *      the other pages that have been generated
1200
 *
1201
 *      Assume that they are in the same directory
1202
 *
1203
 *  Parameters:
1204
 *      None
1205
 *
1206
 *  Returns:
1207
 *      Nothing
1208
 *
1209
 *========================================================================*/
1210
void pri_master_index_entry(char *name, char *text)
1211
{
1212
    print( "<tr><td>");
1213
    print ("<A HREF=\"%s\">%s</A>\n", p_filename(filebase, name ,"html"), text );
1214
}
1215
 
1216
 
1217
void pri_master_index(void)
1218
{
1219
    int j;
1220
 
1221
    report_html = 1;
1222
    if( !open_printer( "", "index", 132, report_html, "Master Index" ) )
1223
        return;
1224
 
1225
    /*
1226
    **  Names
1227
    */
1228
    print( "<TABLE border=0 align=center>" );
1229
    pri_master_index_entry( "name", "Teams by Name" );
1230
    pri_master_index_entry( "finish", "Finishing Order for all Teams" );
1231
    pri_master_index_entry( "awards", "Prizes and Awards" );
1232
    print( "<tr><td>\n" );
1233
 
1234
    print( "\n" );
1235
    for( j = 1; j <= config.num_class; j++ )
1236
    {
1237
        pri_master_index_entry( config.team_class[j - 1].abr, tprintf("Category Results for: %s", config.team_class[j-1].full_name) );
1238
    }
1239
    print( "</TABLE>" );
1240
 
1241
    close_printer();
1242
}
1243
 
1244
 
1245
/*========================================================================
1246
 *
1247
 *  Print interim results
1248
 *
1249
 *  Purpose:
1250
 *      This function is called to Print interim results
1251
 *
1252
 *  Parameters:
1253
 *      None
1254
 *
1255
 *  Returns:
1256
 *      Nothing
1257
 *
1258
 *========================================================================*/
1259
 
1260
void pri_interim(void)
1261
{
1262
    ty_s_data  *ptr;
1263
    unsigned    i;
1264
    int         j, last_class;
1265
    char        suppress_classes;                /* Boolean. Printout class files too */
1266
    char       *report_title;
1267
 
1268
    cur( 0, 5 );
1269
    printf( "Generate interim result printouts\n" );
1270
    ck_data( -1, C_DISQUAL );                    /* Check the data - dummy check */
1271
    suppress_classes = getyes( "Do you want to suppress class printouts" );
1272
    printf( "\nSorting the data\n" );
1273
    do_big_sort();                             /* Sort on every thing */
1274
    gen_stats();                               /* Generate the stats too */
1275
 
1276
    printf( "\nGenerating the printed output\n" );
1277
 
1278
    /*
1279
     * Now print the data on the printer 
1280
     */
1281
 
1282
    if( !open_printer( "", "int", 132, report_html, "Interim Results" ) )
1283
        return;
1284
 
1285
    /*
1286
     * Print out the data 
1287
     */
1288
    print_class_header( -1, FALSE );                     /* Print the header */
1289
 
1290
    ptr = sort_data;
1291
    sort_team_data( 0, S_TEAM );                   /* Re-sort on team number */
1292
    for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
1293
    {
1294
        if ( ptr->class == config.nonequestrian_class )
1295
            continue;
1296
 
1297
        g_record( ptr->team, &team_buf );
1298
 
1299
        print( "%4d %4.4s %-*s",
1300
               team_buf.numb,
1301
               pi_place( team_buf.leg[config.num_legs].le_place,
1302
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ),
1303
               3,
1304
               team_buf.class ==
1305
 
1306
        for( j = 1; j <= config.num_legs; j++ )
1307
        {
1308
            print( "  %-8s %4.4s %4.4s",
1309
                   time_fa( team_buf.leg[j].elapsed,
1310
                            ptr->flags.disqualified ),
1311
                   pi_place( team_buf.leg[j].l_place, ptr->flags.disqualified,
1312
                             team_buf.leg[j].elapsed ),
1313
                   pi_place( team_buf.leg[j].le_place,
1314
                             ptr->flags.disqualified,
1315
                             team_buf.leg[j].elapsed ) );
1316
        }
1317
        print( "  %-8s %4.4s\n",
1318
               time_fa( team_buf.leg[0].elapsed, ptr->flags.disqualified ),
1319
               pi_place( team_buf.leg[config.num_legs].lec_place,
1320
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ) );
1321
    }
1322
 
1323
    print_class_stats( -1, FALSE );             /* Print statistics */
1324
    print_legend(-1);                             /* Print the legend */
1325
    close_printer();                            /* Close the printer */
1326
 
1327
 
1328
    /*
1329
     * Now produce a breakdown on a class by class basis 
1330
     * Now print out the class placement information
1331
     */
1332
 
1333
    if( suppress_classes )
1334
    {
1335
        printf( "WARNING: Class printouts suppressed\n" );
1336
        return;
1337
    }
1338
 
1339
    sort_team_data( 0, S_CLASS );              /* Generate class placement data */
1340
    last_class = -1;                             /* Invalid class to start with */
1341
 
1342
    for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
1343
    {
1344
        /*
1345
        **  Detect a change in the "class"
1346
        **  All data is within the one array of data
1347
        **  Use the in-memory class as this MAY differ from that stored
1348
        **  The non-equestrian class does this.
1349
        */
1350
        if( last_class != ptr->class )
1351
        {
1352
            if( last_class >= 0 )
1353
            {
1354
                print_class_stats( last_class, TRUE );
1355
                print_legend(last_class);
1356
                close_printer();
1357
            }
1358
 
1359
            report_title = tprintf( "Interim Category results for : %-*s", LEN_CLASS_NAME, team_buf.class == 0 ? "" : config.team_class[ptr->class - 1].full_name );
1360
 
1361
            if( !open_printer( "", tprintf( "i%2s", config.team_class[ptr->class - 1].abr ), 132, report_html, report_title ) )
1362
                continue;
1363
            print_class_header( last_class = ptr->class, FALSE );
1364
        }
1365
 
1366
        /*
1367
        **  Now read in the team record
1368
        */
1369
        g_record( ptr->team, &team_buf );
1370
        print( "%4d %4.4s %-*s",
1371
               team_buf.numb,
1372
               pi_place( team_buf.leg[config.num_legs].lec_place,
1373
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ),
1374
               3,
1375
               team_buf.class ==
1376
 
1377
        for( j = 1; j <= config.num_legs; j++ )
1378
        {
1379
            print( "  %-8s %4.4s %4.4s",
1380
                   time_fa( team_buf.leg[j].elapsed,
1381
                            ptr->flags.disqualified ),
1382
                   pi_place( team_buf.leg[j].lc_place,
1383
                             ptr->flags.disqualified,
1384
                             team_buf.leg[j].elapsed ),
1385
                   pi_place( team_buf.leg[j].lec_place,
1386
                             ptr->flags.disqualified,
1387
                             team_buf.leg[j].elapsed ) );
1388
        }
1389
        print( "  %-8s %4.4s\n",
1390
               time_fa( team_buf.leg[0].elapsed, ptr->flags.disqualified ),
1391
               pi_place( team_buf.leg[config.num_legs].le_place,
1392
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ) );
1393
    }
1394
 
1395
    print_class_stats( last_class, FALSE );
1396
    print_legend(last_class);
1397
    close_printer();
1398
 
1399
}
1400
 
1401
/*========================================================================
1402
 *
1403
 *  Print a class header
1404
 *
1405
 *  Purpose:
1406
 *      This function is called to print a class header
1407
 *
1408
 *  Parameters:
1409
 *      class           Name of this class
1410
 *      final           False - prelim results
1411
 *
1412
 *  Returns:
1413
 *      Nothing
1414
 *
1415
 *========================================================================*/
1416
 
1417
void print_class_header( int class, int final )
1418
{
1419
    int         j;
1420
 
1421
    /*
1422
    **  Give a clear indication that the report is preliminary
1423
    */
1424
 
1425
    if( !final )
1426
        print( "PRELIMINARY RESULTS ONLY\n\n" );
1427
 
1428
    /*
1429
    **  Now printout the column headings
1430
    **  This is a two line display
1431
    **
1432
    **  Line-1  Leg names
1433
    */
1434
    print( "%-*s %-*s %-*s", 4, "", 4, "", 3, "" );
1435
    for( j = 1; j <= config.num_legs; j++ )
1436
    {
1437
        print_bold( TRUE );
1438
        print( "  %-*s", 18, config.leg_name[j - 1] );
1439
        print_bold( FALSE );
1440
    }
1441
    print( "  %-8s %-4s\n", "Total", ( class < 0 ) ? "Cat" : "Fin" );
1442
 
1443
 
1444
    /*
1445
    **  Line-2  Details
1446
    */
1447
    print_underline( TRUE );
1448
    print( "%-*s %*s %-*s", 4, final ? "Plce" : "Team",
1449
                            4, final ? "Team" : "Plce",
1450
                            3, "Cat" );
1451
 
1452
    for( j = 1; j <= config.num_legs; j++ )
1453
        print( "  %-8s %-4s %-4s", "Time", " LP", " EP" );
1454
 
1455
    print( "  %-8s %-4s\n", "Time", "Plce" );
1456
    print_underline( FALSE );
1457
}
1458
 
1459
/*========================================================================
1460
 *
1461
 *  Generate the class stats
1462
 *
1463
 *  Purpose:
1464
 *      This function is called to Generate the class stats
1465
 *
1466
 *  Parameters:
1467
 *      c           Class to print
1468
 *      final       TRUE: Final data
1469
 *                  FALSE: Interim data
1470
 *
1471
 *  Returns:
1472
 *      Nothing
1473
 *
1474
 *========================================================================*/
1475
 
1476
void print_class_stats( int c, int final )
1477
{
1478
    int         i, j;
1479
    char        *title;
1480
 
1481
    if( c < 0 )
1482
    {
1483
        title = "Event";
1484
        c = 0;
1485
    }
1486
    else
1487
    {
1488
        title = "Category";
1489
    }
1490
 
1491
    print( "\n" );
1492
    if ( report_html ) print_underline(TRUE);
1493
    print( "%s statistics", title );
1494
    if ( report_html ) print_underline(FALSE);
1495
    print( "\n" );
1496
 
1497
 
1498
    /*
1499
    **  Print the names of the different legs
1500
    */
1501
    print( "%-*s       ", LEN_CLASS_NAME, "" );
1502
    for( i = 1; i <= config.num_legs; i++ )
1503
    {
1504
        print_bold( TRUE );
1505
        print( "%-13s  ", config.leg_name[i - 1] );
1506
        print_bold( FALSE );
1507
    }
1508
    print( "%-13s  \n", final ? "Total" : "" );
1509
 
1510
    /*
1511
    **  Print the fastest teams for each leg and overall
1512
    **  Add cross references to the team names for the fastest teams
1513
    */
1514
    print( "%*s : ", LEN_CLASS_NAME, "Fastest" );
1515
    for( i = 0; i <= config.num_legs; i++ )
1516
    {
1517
        j = i + 1;
1518
        if( i >= config.num_legs )
1519
        {
1520
            if( final )
1521
                j = 0;                           /* Leg-0 last */
1522
            else
1523
                break;
1524
        }
1525
 
1526
        if ( report_html ) print( "<A HREF=\"%s#Team_%04d\">", p_filename(filebase, "name" ,"html"), stats.fast.team[j][c] );
1527
        print( "%4d",  stats.fast.team[j][c] );
1528
        if ( report_html ) print( "</A>" );
1529
        print( " %s  ", time_a( stats.fast.time[j][c] ) );
1530
    }
1531
    print( "\n" );
1532
 
1533
    /*
1534
    **  Print the average time for each leg
1535
    */
1536
    print( "%*s : ", LEN_CLASS_NAME, "Average" );
1537
    for( i = 0; i <= config.num_legs; i++ )
1538
    {
1539
        j = i + 1;
1540
        if( i >= config.num_legs )
1541
        {
1542
            if( final )
1543
                j = 0;                           /* Leg-0 last */
1544
            else
1545
                break;
1546
        }
1547
        print( "     %s  ", time_a( stats.average[j][c] ) );
1548
    }
1549
}
1550
 
1551
/*========================================================================
1552
 *
1553
 *  Print the legend
1554
 *
1555
 *  Purpose:
1556
 *      This function is called to Print the legend
1557
 *
1558
 *  Parameters:
1559
 *      class       - Class currently being printed
1560
 *
1561
 *  Returns:
1562
 *      Nothing
1563
 *
1564
 *========================================================================*/
1565
 
1566
void print_legend ( int class )
1567
{
1568
 
1569
    int         i;
1570
    char        line[201];
1571
    FILE       *adfile = NULL;
1572
    int         count;
1573
 
1574
    /*
1575
     * First the categories 
1576
     */
1577
    print( "\n\n" );
1578
    if ( report_html ) print_underline(TRUE);
1579
    print( "Category abbreviations" );
1580
    if ( report_html ) print_underline(FALSE);
1581
    print( "\n" );
1582
 
1583
 
1584
    for( i = 1, count = 0; i <= config.num_class; i++ )
1585
    {
1586
#if 0
1587
        /*
1588
        **  Skip any non-equestrian class in the legend
1589
        **  Don't want to tell the general user whats goes on, unless we actually
1590
        **  creating the non-equestrian report.
1591
        */
1592
        if ( class != config.nonequestrian_class  && i == config.nonequestrian_class )
1593
            continue;
1594
#endif
1595
        if ( report_html ) print( "<A HREF=\"%s\">",p_filename(filebase, config.team_class[i - 1].abr ,"html") );
1596
        print( "%-*s", 3, config.team_class[i - 1].abr );
1597
        if ( report_html ) print( "</A>" );
1598
        print( " : %-*s  ", LEN_CLASS_NAME, config.team_class[i - 1].full_name );
1599
 
1600
        if( !( ++count % 5 ) )
1601
            print( "\n" );
1602
    }
1603
 
1604
    /*
1605
    **  Add link to the finish order report
1606
    */
1607
    if ( report_html )
1608
    {
1609
        print( "<A HREF=\"%s\">", p_filename(filebase, "finish" ,"html") );
1610
        print( "%-*s", 3, "All" );
1611
        print( "</A>" );
1612
        print( " : %-*s  ", LEN_CLASS_NAME, "Finishing Order" );
1613
    }
1614
 
1615
    /*
1616
    **  Country data - if countries have been defined
1617
    */
1618
    if( config.num_countries )
1619
    {
1620
        print( "\n\n" );
1621
        if ( report_html ) print_underline(TRUE);
1622
        print( "Country abbreviations" );
1623
        if ( report_html ) print_underline(FALSE);
1624
        print( "\n" );
1625
 
1626
        for( i = 0, count = 0; i < MAX_COUNTRY; i++ )
1627
        {
1628
            if( config.country_name[i].abr[0] )
1629
            {
1630
                print( "%-*s : %-*s  ", 4, config.country_name[i].abr,
1631
                       LEN_CNTRY_NAME, config.country_name[i].full_name );
1632
                if( !( ++count % 5 ) )
1633
                    print( "\n" );
1634
            }
1635
        }
1636
    }
1637
 
1638
    /*
1639
     * Other comments 
1640
     */
1641
 
1642
    print( "\n\nPlace numbers (LP and EP)\n" );
1643
    print( "LP - Placing based on elapsed time within the leg.                Cat Plce - Placing within the category.\n" );
1644
    print( "EP - Placing based on accumulated times to the end of that leg.   Fin Plce - Overall placing within the event.\n" );
1645
 
1646
    /*
1647
     *  Insert the contents of the config.addendum file
1648
     *  or a defualt message
1649
     */
1650
    if( config.addendum[0] )
1651
        adfile = fopen( config.addendum, "rt" );  /* Open the file for reading */
1652
 
1653
    if( adfile )
1654
    {
1655
        while( fgets( line, sizeof(line)-1, adfile ) )
1656
            print( "%s", line );
1657
    }
1658
    else
1659
    {
1660
        print( "\nTiming and Results by\n" );
1661
        print( "Embedded Solutions\n" );
1662
    }
1663
}
1664
 
1665
/*========================================================================
1666
 *
1667
 *  Return place data
1668
 *
1669
 *  Purpose:
1670
 *      This function is called to return place data
1671
 *
1672
 *      This routine is called to fill a print team_buffer - to allow for
1673
 *      multiple calls to this function ( before the data is used ) a number
1674
 *      of static team_buffers are maintained
1675
 *
1676
 *  Parameters:
1677
 *      num         place - if not bad_times
1678
 *      disq        Disqualified flag
1679
 *      time        Time data is based on
1680
 *
1681
 *  Returns:
1682
 *      This function returns a pointer to the character string for the
1683
 *      number or a pointer to a bad_times string.
1684
 *
1685
 *========================================================================*/
1686
 
1687
char       *pi_place( int num, int disq, time_t time )
1688
{
1689
    static char store[2][5];                     /* 2 stores for 4 digit numbers */
1690
    static int  i = 0;                           /* Current index into store */
1691
    static char *dis = "D";                      /* Disqualified */
1692
    static char *non = "-";                      /* Invalid time */
1693
 
1694
    if( disq )                                   /* Disqualified team */
1695
        return ( dis );
1696
    if( time <= 0 )                              /* Unknown time */
1697
        return ( non );
1698
 
1699
    i++;
1700
    if( i >= 2 )
1701
        i = 0;                                   /* Select next entry */
1702
    sprintf( store[i], "%4d", num );
1703
    return ( store[i] );
1704
 
1705
}
1706
 
1707
/*========================================================================
1708
 *
1709
 *  Return place data
1710
 *
1711
 *  Purpose:
1712
 *      This function is called to Return place data
1713
 *
1714
 *      This routine is called to fill a print team_buffer - to allow for
1715
 *      multiple calls to this function ( before the data is used ) a number
1716
 *      of static team_buffers are maintained
1717
 *
1718
 *  Parameters:
1719
 *      num         place - if not bad_times
1720
 *      disq        Disqualified flag
1721
 *
1722
 *  Returns:
1723
 *      This function returns a pointer to the character string for the
1724
 *      number or a pointer to a bad_times string.
1725
 *
1726
 *========================================================================*/
1727
 
1728
char *pr_place( int num, int disq )
1729
{
1730
    static char store[2][5];                     /* 2 stores for 4 digit numbers */
1731
    static int  i = 0;                           /* Current index into store */
1732
    static char *dis = "U";
1733
 
1734
    if( disq )
1735
        return ( dis );
1736
 
1737
    i++;
1738
    if( i >= 2 )
1739
        i = 0;                                   /* Select next entry */
1740
    sprintf( store[i], "%4d", num );
1741
    return ( store[i] );
1742
 
1743
}
1744
 
1745
/*========================================================================
1746
 *
1747
 *  Check data for bad times
1748
 *
1749
 *  Purpose:
1750
 *      This function is called to Check data for bad times
1751
 *      Scan the sort data structure and locate entries that have incorrect
1752
 *      times.
1753
 *      
1754
 *      Entries that have invalid leg times are displayed to the operator
1755
 *      and the report process can be aborted
1756
 *
1757
 *  Parameters:
1758
 *      leg         Leg to test
1759
 *      mode            Either end or elapsed times to be tested
1760
 *
1761
 *  Returns:
1762
 *      Returns FALSE if the report operation is to be aborted
1763
 *
1764
 *========================================================================*/
1765
 
1766
bool ck_data( int leg, int mode )
1767
{
1768
    ty_s_data  *ptr;
1769
    unsigned    i;
1770
    int         bad = 0;
1771
    int         j = 0;
1772
    int         k, bad_leg;
1773
    time_t     *t;                               /* An array of times */
1774
 
1775
    ptr = sort_data;
1776
    for( i = 1; i <= sort_num; i++, ptr++ )
1777
    {
1778
        bad_leg = 0;
1779
        if( mode == C_DISQUAL )
1780
        {
1781
            ptr->flags.bad_times = ptr->flags.disqualified;
1782
            continue;
1783
        }
1784
 
1785
        if( mode == C_ELAPSED )
1786
            t = ptr->lege;
1787
        else
1788
            t = ptr->leg;
1789
 
1790
        if( ( ptr->flags.bad_times = ptr->flags.disqualified ) == FALSE )
1791
        {
1792
            if( leg <= 0 )
1793
            {
1794
                for( k = 0; k <= config.num_legs; k++ )
1795
                {
1796
                    if ( !(config.equestrian_leg && ptr->flags.non_equestrian && config.equestrian_leg == k  ))
1797
                        bad_leg |= ( t[k] <= 0 );
1798
                }
1799
            }
1800
            else
1801
            {
1802
                bad_leg = t[leg] <= 0;
1803
            }
1804
 
1805
            if( bad_leg )
1806
            {
1807
                ptr->flags.bad_times = TRUE;
1808
                if( !bad )
1809
                    printf( "Team with incorrect time information\n" );
1810
                if( ++j > 15 )
1811
                {
1812
                    printf( "\n" );
1813
                    j = 0;
1814
                }
1815
                printf( "%4d ", ptr->team );
1816
                bad++;
1817
            }
1818
        }
1819
    }
1820
 
1821
    if( bad )
1822
    {
1823
        printf( "\n%d teams with incorrect times.\n", bad );
1824
        return ( !getyes
1825
                 ( "These have been flagged as unplaced - continue report" ) );
1826
    }
1827
    return ( FALSE );
1828
}
1829
 
1830
/*========================================================================
1831
 *
1832
 *  Update placing information
1833
 *
1834
 *  Purpose:
1835
 *      This function is called to Update placing information
1836
 *
1837
 *      This routine will rip through the data generating the team placing in
1838
 *      a) Within a leg
1839
 *      b) At the end of a leg
1840
 *      c) Within a leg by  class
1841
 *      d) At the end of a leg by class
1842
 *
1843
 *      This function is provided to allow the display routines to
1844
 *      be accessed and updated without the need to run a report
1845
 *
1846
 *  Parameters:
1847
 *      xxxx        a ptr to the xxxx stuff
1848
 *
1849
 *  Returns:
1850
 *      Nothing
1851
 *
1852
 *========================================================================*/
1853
 
1854
void srt_place(void)
1855
{
1856
    int         i, j;
1857
 
1858
    cur( 0, 5 );
1859
    printf( "Update the team placings to the data base\n" );
1860
    flush_out();
1861
    if( ck_data( -1, C_ELAPSED ) )
1862
        return;
1863
    do_big_sort();
1864
 
1865
    /*
1866
     * Generate the stats and display them on the screen for interest
1867
     * This operation will not hurt - so why not
1868
     */
1869
 
1870
    gen_stats();
1871
    printf( "\nEvent statistics\n\n" );
1872
    printf( "%-*s   %-13s ", LEN_CLASS_NAME, "", "Overall" );
1873
    for( i = 1; i <= config.num_legs; i++ )
1874
        printf( "%-13s ", config.leg_name[i - 1] );
1875
 
1876
    for( j = 0; j <= config.num_class; j++ )
1877
    {
1878
        printf( "\n%-*s : ", LEN_CLASS_NAME,
1879
                j ? config.team_class[j - 1].full_name : "Overall" );
1880
        for( i = 0; i <= config.num_legs; i++ )
1881
        {
1882
            printf( "%4d ", stats.fast.team[i][j] );
1883
            printf( "%s ", time_a( stats.fast.time[i][j] ) );
1884
        }
1885
        printf( "\n%*s : ", LEN_CLASS_NAME, "Average" );
1886
        for( i = 0; i <= config.num_legs; i++ )
1887
        {
1888
            printf( "     %s ", time_a( stats.average[i][j] ) );
1889
        }
1890
    }
1891
    printf( "\nAny key to continue" );
1892
    ( void ) getinp();
1893
}
1894
 
1895
/*========================================================================
1896
 *
1897
 *  Calculate summary information
1898
 *
1899
 *  Purpose:
1900
 *      This function is called to calculate summary information
1901
 *
1902
 *  Parameters:
1903
 *      ptr         - Address of a summary structure to fill in
1904
 *
1905
 *  Returns:
1906
 *      Nothing
1907
 *
1908
 *========================================================================*/
1909
 
1910
void calc_class_summary( t_class_summary * ptr )
1911
{
1912
    int i;
1913
 
1914
    /*
1915
    **  Reset the data
1916
    */
1917
    memset ( ptr, 0, sizeof (*ptr ));
1918
 
1919
    /*
1920
     * Extract the required data from the data base
1921
     * Only save that information required for the operation
1922
     */
1923
 
1924
    for( i = config.min_team; i <= config.max_team; i++ )
1925
    {
1926
        if( valid_field( i ) && g_record( i, &team_buf ) )
1927
        {
1928
            ptr->total.total++;
1929
            ptr->class[team_buf.class].total++;
1930
 
1931
            if ( team_buf.flags.disqualified )
1932
            {
1933
                ptr->class[team_buf.class].disqualified++;
1934
                ptr->total.disqualified++;
1935
            }
1936
 
1937
            if ( config.nonequestrian_class && team_buf.flags.non_equestrian )
1938
            {
1939
                ptr->class[team_buf.class].non_equestrian++;
1940
                ptr->total.non_equestrian++;
1941
            }
1942
        }
1943
    }
13 david 1944
 
1945
    /*
1946
    **  Fix up the totals for the non equestrians
1947
    **  This is not a real category but a summary of the others.
1948
    */
1949
    if ( config.nonequestrian_class  )
1950
    {
1951
        ptr->class[config.nonequestrian_class].total += ptr->total.non_equestrian;
1952
    }
1 root 1953
}
1954
 
1955
/*========================================================================
1956
 *
1957
 *  Display summary information
1958
 *
1959
 *  Purpose:
1960
 *      This function is called to display summary information
1961
 *
1962
 *  Parameters:
1963
 *      None
1964
 *
1965
 *  Returns:
1966
 *      Nothing
1967
 *
1968
 *========================================================================*/
1969
 
1970
void display_summary (void)
1971
{
1972
 
1973
    t_class_summary data;
1974
    int         i;
1975
    int         line = 2;
1976
 
1977
    cur( 0, line );
1978
    printf( "Generating Summary Information" );
1979
    calc_class_summary( & data );
1980
 
1981
 
1982
    /*
1983
    **  Display summary stats
1984
    */
1985
 
1986
    cur( 0, line );
1987
    console_clreol();
1988
    printf( "Summary Information\n\n" );
1989
    printf( "%*s : %-7s %-7s%-7s\n", LEN_CLASS_NAME,
1990
                                      "Category",
1991
                                      "Total",
1992
                                      "Disq",
1993
                                      "NonEq" );
1994
 
1995
    for( i = 0; i < config.num_class; i++ )
1996
    {
1997
        /*
1998
        **  The non-equestrian leg does not have any data
1999
        **  Supress the display
2000
        */
2001
        if ( config.nonequestrian_class == i+1  )
2002
            continue;
2003
 
2004
        printf( "%*s : %-7d %-7d %-7d\n", LEN_CLASS_NAME,
2005
                                          config.team_class[i].full_name,
2006
                                          data.class[i+1].total,
2007
                                          data.class[i+1].disqualified,
2008
                                          data.class[i+1].non_equestrian );
2009
    }
2010
 
2011
    printf( "\n" );
2012
    printf( "%*s : %-7d %-7d %-7d\n", LEN_CLASS_NAME,
2013
                                      "Totals",
2014
                                      data.total.total,
2015
                                      data.total.disqualified,
2016
                                      data.total.non_equestrian );
2017
 
2018
    printf( "\nAny key to continue " );
2019
    getinp();
2020
}
2021
 
13 david 2022
/*========================================================================
2023
 *
2024
 *  Print summary information
2025
 *
2026
 *  Purpose:
2027
 *      This function is called to print summary information
2028
 *
2029
 *  Parameters:
2030
 *      None
2031
 *
2032
 *  Returns:
2033
 *      Nothing
2034
 *
2035
 *========================================================================*/
1 root 2036
 
13 david 2037
void pri_summary (void)
2038
{
2039
 
2040
    t_class_summary data;
2041
    int         i;
2042
    int         line = 2;
2043
 
2044
 
2045
    if( !open_printer( "", "summary", 132, 0, "Summary Information" ) )
2046
        return;
2047
 
2048
    cur( 0, line );
2049
    printf( "Generating Summary Information" );
2050
    calc_class_summary( & data );
2051
 
2052
 
2053
    /*
2054
    **  Display summary stats
2055
    */
2056
 
2057
    print( "%*s : %-7s %-7s%-7s\n", LEN_CLASS_NAME,
2058
                                      "Category",
2059
                                      "Total",
2060
                                      "Disq",
2061
                                      "NonEq" );
2062
 
2063
    for( i = 0; i < config.num_class; i++ )
2064
    {
2065
        /*
2066
        **  The non-equestrian leg does not have any data
2067
        **  Supress the display
2068
        */
2069
        if ( config.nonequestrian_class == i+1  )
2070
            continue;
2071
 
2072
        print( "%*s : %-7d %-7d %-7d\n", LEN_CLASS_NAME,
2073
                                          config.team_class[i].full_name,
2074
                                          data.class[i+1].total,
2075
                                          data.class[i+1].disqualified,
2076
                                          data.class[i+1].non_equestrian );
2077
    }
2078
 
2079
    print( "\n" );
2080
    print( "%*s : %-7d %-7d %-7d\n", LEN_CLASS_NAME,
2081
                                      "Totals",
2082
                                      data.total.total,
2083
                                      data.total.disqualified,
2084
                                      data.total.non_equestrian );
2085
 
2086
    close_printer();
2087
    printf( "\nAny key to continue " );
2088
    getinp();
2089
}
2090
 
2091
 
2092
 
1 root 2093
/*========================================================================
2094
 *
2095
 *  Main sort routine for final data
2096
 *
2097
 *  Purpose:
2098
 *      This function is called to do the report sort routine for final data
2099
 *      This routine will fill all the gaps in the sort_aux structure
2100
 *
2101
 *  Parameters:
2102
 *      None
2103
 *
2104
 *  Returns:
2105
 *      Nothing
2106
 *
2107
 *========================================================================*/
2108
 
2109
void do_big_sort(void)
2110
{
2111
    int         i, k;                            /* Looooopy things */
2112
    unsigned    j;
2113
    ty_s_data  *ptr;                             /* Pointer to sort data */
2114
    int         class;                           /* Current class */
2115
 
2116
    printf( "Sorting it ALL out" );
2117
    flush_out();
2118
 
2119
    for( i = 0; i <= config.num_legs; i++ )
2120
    {
2121
        /*
2122
        **  Sort on leg elapsed time
2123
        **  The save the teams elapsed place in each leg
2124
        */
2125
        sort_team_data( i, S_L );
2126
        for( j = 1, ptr = sort_data; j <= sort_num; j++, ptr++ )
2127
        {
2128
            sort_aux[ptr->team].l_place[i] = j;
2129
            sort_aux[ptr->team].team = ptr->team;
2130
        }
2131
 
2132
        /*
2133
        **  Sort on leg end time
2134
        **  Then save the teams place at the end of each leg
2135
        */
2136
        sort_team_data( i, S_LE );
2137
        for( j = 1, ptr = sort_data; j <= sort_num; j++, ptr++ )
2138
            sort_aux[ptr->team].le_place[i] = j;
2139
 
2140
        /*
2141
        **  Sort on elapsed time per class
2142
        **  The save the teams elapsed place in each leg per class
2143
        */
2144
        sort_team_data( i, S_LC );
2145
        class = -1;
2146
        for( k = 1, j = 1, ptr = sort_data; j <= sort_num; j++, ptr++ )
2147
        {
2148
            if( class != ptr->class )
2149
            {
2150
                k = 1;
2151
                class = ptr->class;
2152
            }
2153
            sort_aux[ptr->team].lc_place[i] = k++;
2154
        }
2155
 
2156
        /*
2157
        **  Sort on end time per class
2158
        **  Then save the teams place at the end of each leg per class
2159
        */
2160
        sort_team_data( i, S_LEC );
2161
        class = -1;
2162
        for( k = 1, j = 1, ptr = sort_data; j <= sort_num; j++, ptr++ )
2163
        {
2164
            if( class != ptr->class )
2165
            {
2166
                k = 1;
2167
                class = ptr->class;
2168
            }
2169
            sort_aux[ptr->team].lec_place[i] = k++;
2170
        }
2171
    }
2172
 
2173
    /*
2174
    **  Write the place information back to disk for use in the displays
2175
    */
2176
    printf( "\nWriting it all back to the disk file" );
2177
    flush_out();
2178
 
2179
    for( i = config.min_team; i <= config.max_team; i++ )
2180
    {
2181
        if( sort_aux[i].team && valid_field( i ) && g_record( i, &team_buf ) )
2182
        {
2183
            for( k = 0; k <= config.num_legs; k++ )
2184
            {
2185
                team_buf.leg[k].l_place = sort_aux[i].l_place[k];
2186
                team_buf.leg[k].le_place = sort_aux[i].le_place[k];
2187
                team_buf.leg[k].lc_place = sort_aux[i].lc_place[k];
2188
                team_buf.leg[k].lec_place = sort_aux[i].lec_place[k];
2189
            }
2190
            put_team_record( i, &team_buf );
2191
        }
2192
    }
2193
}
2194
 
2195
/*========================================================================
2196
 *
2197
 *  Sort in memory buffer
2198
 *
2199
 *  Purpose:
2200
 *      This function is called to Sort in memory buffer
2201
 *
2202
 *  Parameters:
2203
 *      leg         Requested leg
2204
 *      mode        Defines the sort mode
2205
 *
2206
 *  Returns:
2207
 *      Nothing
2208
 *
2209
 *========================================================================*/
2210
 
2211
void sort_team_data( int leg, int mode )
2212
{
2213
 
2214
    unsigned    j;
2215
    ty_s_data  *ptr;
2216
 
2217
    sort_leg = leg;                              /* Leg is global for the comparison function */
2218
    sort_mode = mode;                            /* Mode is global for compare function */
2219
 
2220
    qsort( ( char * ) sort_data, sort_num, sizeof( ty_s_data ), sort_comp );
2221
 
2222
    /*
2223
     * Insert "place data" into the sorted data
2224
     * This simply the index into the array of data - after its been
2225
     * sorted.
2226
     */
2227
    ptr = sort_data;
2228
    for( j = 1; j <= sort_num; j++, ptr++ )
2229
        ptr->place = j;
2230
 
2231
}
2232
 
2233
/*========================================================================
2234
 *
2235
 *  qsort comparison function
2236
 *
2237
 *  Purpose:
2238
 *      This function is called by qsort as a Sort comparison function
2239
 *
2240
 *  Parameters:
2241
 *      a       - 1st record
2242
 *      b       - 2nd record
2243
 *
2244
 *  Returns:
2245
 *      value to qsort
2246
 *
2247
 *========================================================================*/
2248
 
2249
int sort_comp( const void * aa, const void * bb )
2250
{
2251
    const ty_s_data * a = aa;
2252
    const ty_s_data * b = bb;
2253
 
2254
 
2255
    int         i;                               /* One of those */
2256
    time_t      ta, tb;                          /* Leg times */
2257
    int         na, nb;                          /* Number of valid legs */
2258
    time_t      tta, ttb;                        /* Temp times */
2259
 
2260
    /*
2261
    **  Sorting on Team Number
2262
    */
2263
    if( sort_mode == S_TEAM )
2264
        return ( a->team - b->team );
2265
 
2266
    /*
2267
    **  Sorting on Class and Team Number
2268
    */
2269
    if( sort_mode == S_CLASS )
2270
    {
2271
        if( a->class != b->class )
2272
            return ( a->class - b->class );
2273
        else
2274
            return ( a->team - b->team );
2275
    }
2276
 
2277
    /*
2278
    **  Sorting within a class
2279
    **  First sort on the class
2280
    */
2281
    if( sort_mode == S_LEC || sort_mode == S_LC )   /* Sort within a class */
2282
        if( a->class != b->class )
2283
            return ( a->class - b->class );
2284
 
2285
    /*
2286
    **  Now we need to examine the times as we have sorted
2287
    **  on every thing else.
2288
    **
2289
    **  If one of the teams has bad_times, then that team is placed
2290
    **  lower in the sorting order. If both teams have bad times
2291
    **  then sort on team number. ie: Unplaced teams are sorted on
2292
    **  team number
2293
    */
2294
    if( a->flags.bad_times || b->flags.bad_times )  /* Valid data has precedence */
2295
    {
2296
        if( a->flags.bad_times && b->flags.bad_times )
2297
            return ( a->team - b->team );
2298
        else
2299
            return ( a->flags.bad_times ? 1 : -1 );
2300
    }
2301
 
2302
    /*
2303
    **  Not sorting within a class ie: Overall
2304
    **  Non-Equestrian is at the end, so that it doesn't get counted in the
2305
    **  finishing order
2306
    */
2307
    if( sort_mode == S_LE || sort_mode == S_L )     /* Sort NOT within a class */
2308
    {
2309
        if( a->flags.non_equestrian || b->flags.non_equestrian )
2310
        {
2311
            if( a->flags.non_equestrian && b->flags.non_equestrian )
2312
                return ( a->team - b->team );
2313
            else
2314
                return ( a->flags.non_equestrian ? 1 : -1 );
2315
        }
2316
    }
2317
 
2318
 
2319
    /*
2320
    **  Before we sort on times we must determine which time to
2321
    **  use. Finish time, Leg end times, Leg Elapsed times.
2322
    */
2323
 
2324
    switch ( sort_mode )
2325
    {
2326
      /*
2327
      **    Sort on finish times
2328
      */
2329
      case S_FIN:
2330
        ta = a->leg[sort_leg];
2331
        tb = b->leg[sort_leg];
2332
        break;
2333
 
2334
 
2335
      /*
2336
      **    Sort on accumulated leg times
2337
      */
2338
      case S_LE:
2339
      case S_LEC:
2340
        if( sort_leg )
2341
        {
2342
            /*
2343
            **  Calculate accumulated time up to the desired leg
2344
            **  If the two teams have a different number of valid
2345
            **  leg times then order by the team that has completed
2346
            **  more legs.
2347
            */
2348
            ta = tb = ( time_t ) 0;
2349
            na = nb = 0;
2350
            for( i = 1; i <= sort_leg; i++ )
2351
            {
2352
                tta = a->lege[i];
2353
                ttb = b->lege[i];
2354
                if( tta > 0 )
2355
                {
2356
                    na++;
2357
                    ta += tta;
2358
                }
2359
                if( ttb > 0 )
2360
                {
2361
                    nb++;
2362
                    tb += ttb;
2363
                }
2364
            }
2365
            if( na != nb )
2366
                return ( nb - na );
2367
        }
2368
        else
2369
        {
2370
            ta = a->leg[sort_leg] - a->start;
2371
            tb = b->leg[sort_leg] - b->start;
2372
        }
2373
        break;
2374
 
2375
      /*
2376
      **    Sort on Elapsed times
2377
      */
2378
      case S_LC:
2379
      case S_L:
2380
        ta = a->lege[sort_leg];
2381
        tb = b->lege[sort_leg];
2382
        break;
2383
 
2384
      /*
2385
      **    Just to be sure ...
2386
      */
2387
      default:
2388
        return ( 0 );
2389
    }
2390
 
2391
    /*
2392
    **  Finally. Compare the required team times
2393
    */
2394
    if( ta == tb )
2395
        return ( a->team - b->team );
2396
    if( ( ta > 0 ) && ( tb > 0 ) )
2397
        return ( ( int ) ( ta - tb ) );
2398
    return ( ( ta > 0 ) ? -1 : 1 );
2399
}
2400
 
2401
/*========================================================================
2402
 *
2403
 *  load report data into memory
2404
 *
2405
 *  Purpose:
2406
 *      This routine will pull all the data into memory 
2407
 *      Not all the team data is loaded. Only that essential for the
2408
 *      operation of the sort routine is loaded
2409
 *
2410
 *  Parameters:
2411
 *      None
2412
 *
2413
 *  Returns:
2414
 *      TRUE - All is well
2415
 *
2416
 *========================================================================*/
2417
 
2418
bool load_report_data(void)
2419
{
2420
 
2421
    ty_s_data  *ptr;                             /* pointer to sort data type */
2422
    int         j;
2423
    unsigned    num;
2424
 
2425
    printf( "Loading team information - This will not hurt" );
2426
    flush_out();
2427
 
2428
    /*
2429
     * Fetch memory for the data store
2430
     */
2431
 
2432
    if( sort_data )
2433
        free( ( char * ) sort_data );
2434
    sort_data = 0;
2435
 
2436
    if( sort_aux )
2437
        free( ( char * ) sort_aux );
2438
    sort_aux = 0;
2439
    sort_num = 0;                                /* Counter of records in the array */
2440
 
2441
    /*
2442
    **  Allocate memory for the data structures
2443
    **  This will be free'd
2444
    */
2445
    num = config.max_team - config.min_team + 1 ;
2446
 
2447
    /*
2448
    **  Allow for non-equestrian teams - since some of the data is loaded twice
2449
    **  Take a guess that at most 1/2 the teams will be non-equestrian
2450
    */
2451
    num = num * 3 / 2;
2452
 
2453
    sort_data = ( ty_s_data * ) calloc ( num , sizeof( ty_s_data ) );
2454
    sort_aux = ( ty_s_aux * ) calloc( num + 1, sizeof( ty_s_aux ) );
2455
 
2456
    if( sort_data == 0 || sort_aux == 0 )
2457
    {
2458
        printf( "\n\nError in allocating memory\n" );
2459
        sleep( 5 );
2460
        return ( FALSE );
2461
    }
2462
 
2463
    /*
2464
    **  Load data into the memory based data structure
2465
    **  Only load data for valid-teams
2466
    **  Load essential data
2467
    **      Team Number, class and flags
2468
    **      Leg end and elapsed times
2469
    */
2470
    ptr = sort_data;
2471
    for( team = config.min_team; team <= config.max_team; team++ )
2472
    {
2473
        if( valid_field( team ) )
2474
        {
2475
            g_record( team, &team_buf );
2476
            if( team_buf.flags.valid )
2477
            {
2478
                ptr->team = team;
2479
                for( j = 0; j < MAX_LEGS + 1; j++ )
2480
                {
2481
                    ptr->lege[j] = team_buf.leg[j].elapsed;
2482
                    ptr->leg[j] = team_buf.leg[j].end;
2483
                }
2484
                ptr->start = team_buf.leg[0].start;
2485
                ptr->class = team_buf.class;
2486
 
2487
                ptr->flags = team_buf.flags;
2488
                ptr++;
2489
                sort_num++;
2490
 
2491
                /*
2492
                **  If non-equestrian support is enabled then
2493
                **  duplicate and modify data for the non-equestrian teams
2494
                **      - Change the class
2495
                **      - Modify the leg time
2496
                */
2497
                if ( config.nonequestrian_class && team_buf.flags.non_equestrian )
2498
                {
2499
                    ptr->team = team;
2500
                    ptr->lege[0] = 0;
2501
 
2502
                    for( j = 0; j < MAX_LEGS + 1; j++ )
2503
                    {
2504
                        if ( j == config.equestrian_leg )
2505
                        {
2506
                            ptr->lege[j] = 0;
2507
                            if ( config.equestrian_leg > 1 )
2508
                                ptr->leg[j] = ptr->leg[j-1];
2509
                        }
2510
                        else
2511
                        {
2512
                            if ( j )
2513
                                ptr->lege[j] = team_buf.leg[j].elapsed;
2514
                            ptr->leg[j] = team_buf.leg[j].end;
2515
                            ptr->lege[0] += ptr->lege[j] ;
2516
                        }
2517
                    }
2518
 
2519
                    ptr->start = team_buf.leg[0].start;
2520
                    ptr->class = config.nonequestrian_class;
2521
                    ptr->flags = team_buf.flags;
2522
                    ptr->flags.disqualified = 0;
2523
                    ptr++;
2524
                    sort_num++;
2525
                }
2526
            }
2527
        }
2528
    }
2529
    return ( TRUE );
2530
}
2531
 
2532
/*========================================================================
2533
 *
2534
 *  Generate all the stats
2535
 *
2536
 *  Purpose:
2537
 *      This function is called to Generate all the stats
2538
 *
2539
 *  Parameters:
2540
 *      None
2541
 *
2542
 *  Returns:
2543
 *      Nothing
2544
 *
2545
 *========================================================================*/
2546
 
2547
void gen_stats(void)
2548
{
2549
    ty_s_data  *ptr;
2550
    unsigned    i;
2551
    int         j;
2552
    int         k;
2553
 
2554
    /*
2555
     * Init all the stats 
2556
     */
2557
    for( i = 0; i <= MAX_LEGS; i++ )
2558
    {
2559
        for( j = 0; j <= MAX_CLASS; j++ )
2560
        {
2561
            stats.team[i][j] = 0;
2562
            stats.fast.team[i][j] = 0;
2563
            stats.fast.time[i][j] = ( time_t ) - 1;
2564
            stats.average[i][j] = 0;
2565
        }
2566
    }
2567
 
2568
    for( i = 1, ptr = sort_data; i <= sort_num; i++, ptr++ )
2569
    {
2570
        /*
2571
        **  If there is any bad times in the team record, then none
2572
        **  of the data can be trusted.
2573
        **
2574
        **  If the team has been disqualified, then don't use any
2575
        **  of the data.
2576
        */
2577
        if( ptr->flags.bad_times || ptr->flags.disqualified )
2578
            continue;
2579
 
2580
        for( j = 0; j <= config.num_legs; j++ )
2581
        {
2582
            if( ptr->lege[j] <= 0 )              /* Ignore bad data */
2583
                continue;
2584
 
2585
            /*
2586
            **  Determine fastest team : overall
2587
            **  Ignore the non-equestrian data as this is in the list twice
2588
            */
2589
            if( ( ptr->lege[j] < stats.fast.time[j][0] )
2590
                || ( stats.fast.time[j][0] < 0 ) )
2591
            {
2592
                if ( ptr->class != config.nonequestrian_class )
2593
                {
2594
                    stats.fast.team[j][0] = ptr->team;
2595
                    stats.fast.time[j][0] = ptr->lege[j];
2596
                }
2597
            }
2598
 
2599
            /*
2600
            **  Determine fastest team : within a class
2601
            */
2602
            if( ( ptr->lege[j] < stats.fast.time[j][ptr->class] )
2603
                || stats.fast.time[j][ptr->class] < 0 )
2604
            {
2605
                stats.fast.team[j][ptr->class] = ptr->team;
2606
                stats.fast.time[j][ptr->class] = ptr->lege[j];
2607
            }
2608
 
2609
            /*
2610
            **  Sum the end times : overall
2611
            */
2612
            if ( ptr->class != config.nonequestrian_class )
2613
            {
2614
                stats.average[j][0] += ptr->lege[j];
2615
                stats.team[j][0]++;
2616
            }
2617
 
2618
 
2619
            /*
2620
            **  Sum the end times : within a class
2621
            */
2622
            stats.average[j][ptr->class] += ptr->lege[j];
2623
            stats.team[j][ptr->class]++;
2624
        }
2625
    }
2626
 
2627
    /*
2628
     * Calculate the averages
2629
     */
2630
    for( k = 0; k <= config.num_legs; k++ )
2631
    {
2632
        for( j = 0; j <= config.num_class; j++ )
2633
        {
2634
            if( stats.team[k][j] )
2635
                stats.average[k][j] /= stats.team[k][j];
2636
            else
2637
                stats.average[k][j] = ( time_t ) - 1;
2638
        }
2639
    }
2640
}
2641
 
2642
/********************************* EOF ***********************************/