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