Subversion Repositories svn1

Rev

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

Rev Author Line No. Line
1 root 1
/*************************************************************************
2
*           Copyright (C) 1995 Embedded Solutions
3
*                       All rights reserved
4
*
5
* file:     src\report.c
6
*
7
* purpose:  PREFIX -
8
*
9
* functions
10
*       report                  - Report menu
11
*       pri_team                - Print in team order
12
*       pri_leg                 - Print in given leg finishing time
13
*       p_place                 - Print place information
14
*       p_team                  - Print team information
15
*       pri_eleg                - Print on elapsed times for given leg
16
*       pe_place                - Print place and elapsed time information
17
*       pe_team                 - Print team and elapsed time information
18
*       pri_final               - Print final results
19
*       pri_interim             - Print interim results
20
*       print_class_header      - Print a class header
21
*       print_class_stats       - Generate the class stats
22
*       print_legend            - Print the legend
23
*       pi_place                - Return place data
24
*       pr_place                - Return place data
25
*       ck_data                 - Check data for bad times
26
*       srt_place               - Update placing information
27
*       do_big_sort             - Main sort routine for final data
28
*       sort                    - Sort in memory buffer
29
*       sort_comp               - qsort comparison function
30
*       load                    - load report data into memory
31
*       gen_stats               - Generate all the stats
32
*
33
* programmer: David Purdie
34
*
35
* revision  date        by      reason
36
*    e388   11-Oct-88           Option in the final printout to only
37
*                               produce the main result sheet. The leg
38
*                               placing printout is not produced.
39
*
40
*                               Changes to the display format of unknown
41
*                               times of disqualified teams. Only affects
42
*                               the leg-printouts.
43
*                               Disqualified teams show as -- -- --
44
*                               Otherwise they show as     ** ** **
45
*                               or a valid time.
46
*
47
*   e339    31-Oct-88   DDP     Added the "Interim Report" facility
48
*   00.0    27/01/95    DDP     Tidies up the program and formatted the file
49
*   00.1    06-sep-02   DDP     Added support for HTML report generation
50
*
51
**************************************************************************/
52
 
53
#include    <stdio.h>
54
#if defined(HI_TECH_C) || defined(__TURBOC__)
55
#include    <alloc.h>
56
#endif
57
#include    "consts.h"
58
#include    "structs.h"
59
#include    "proto.h"
60
 
61 - 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;
75 - 115
report_type report_html = text;
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
{
75 - 177
    report_html = text;
1 root 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
            */
75 - 248
            if ( report_html == html )
1 root 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
            */
75 - 261
            if ( report_html == 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 );
75 - 263
            if ( report_html == html ) print( "</A>" );
1 root 264
 
265
            print( " %-*s ",     MAX_TM_NAME, team_buf.name );
266
 
75 - 267
            if ( report_html == 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 );
75 - 269
            if ( report_html == html ) print( "</A>" );
1 root 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
 
75 - 420
        if ( report_html == 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 );
75 - 422
        if ( report_html == html ) print( "</A>" );
18 david 423
        print( " " );
424
 
75 - 425
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), ptr->team );
18 david 426
        print( "%-*d", 5, ptr->team );
75 - 427
        if ( report_html == html ) print( "</A>" );
18 david 428
        print( " " );
429
 
75 - 430
        if ( report_html == 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 );
75 - 432
        if ( report_html == html ) print( "</A>" );
18 david 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
    */
75 - 903
    report_html = html;
1 root 904
    pri_final();
75 - 905
    report_html = printed;
906
    pri_final();
907
    report_html = text;
1 root 908
}
909
 
910
 
911
/*========================================================================
912
 *
913
 *  Print final results
914
 *
915
 *  Purpose:
916
 *      This function is called to Print final results
917
 *
918
 *  Parameters:
919
 *      None
920
 *
921
 *  Returns:
922
 *      Nothing
923
 *
924
 *========================================================================*/
925
 
926
void pri_final(void)
927
{
928
    ty_s_data  *ptr;
929
    unsigned    i;
930
    int         j, last_class;
931
    char        suppress_classes;                /* Boolean. Printout class files too */
932
    char        *report_title;
33 - 933
    bool        class_done[MAX_CLASS+1];
75 - 934
    int         lcount;
1 root 935
 
936
    cur( 0, 5 );
937
    printf( "Generate final result printouts\n" );
938
    if( ck_data( -1, C_ELAPSED ) )
75 - 939
        return;
940
                                     /* check data for all legs */
1 root 941
 
942
    /*
943
    **  If a non HTML report then ask if the user want to supress the class
944
    **  printout. For an HTML report always do the class reports as the two
945
    **  are interlinked
946
    */
29 - 947
    if ( ! report_html  && ! report_all)
1 root 948
    {
949
        suppress_classes = getyes( "Do you want to suppress class printouts" );
950
    }
951
    else
952
    {
953
        suppress_classes = FALSE;
954
    }
955
 
956
    /*
957
    **  Sort on every thing
958
    **  Then generate all the stats too
959
    */
960
    printf( "\nSorting the data\n" );
961
    do_big_sort();
962
    gen_stats();
963
 
964
    /*
965
     * Now print the data on the printer 
966
     */
967
    printf( "\nGenerating the printed output\n" );
968
    if( !open_printer( "", "finish", 132, report_html, "Finishing Order" ) )
969
        return;
970
 
971
    /*
972
     * Print out the data 
973
     */
974
    print_class_header( -1, TRUE );                      /* Print the header */
975
 
976
    ptr = sort_data;
977
    sort_team_data( 0, S_L );                     /* Re-sort on elapsed time */
75 - 978
    lcount = 0;
1 root 979
    for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
980
    {
981
        if ( ptr->class == config.nonequestrian_class )
982
            continue;
983
 
984
        g_record( ptr->team, &team_buf );
985
 
986
        /*
987
        **  If printing an HTML report then we need to mark
988
        **  the entry with a reference so that we can link to it
989
        */
75 - 990
        if ( report_html == html )
1 root 991
        {
992
            print( "<A NAME=\"Team_%04d\"></A>",team_buf.numb );
993
        }
994
 
995
        /*
61 - 996
        **  Print the basics (Finishing order)
1 root 997
        **      - Place within complete field
998
        **      - Team number - with HTML reference to team file
999
        **      - Class
1000
        */
75 - 1001
        if ( report_html == printed && lcount %5 == 4 ) print_underline( TRUE );
1 root 1002
        print( "%4.4s ", pr_place( team_buf.leg[0].l_place, ptr->flags.bad_times ) );
75 - 1003
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), team_buf.numb );
1 root 1004
        print( "%4d",  team_buf.numb );
75 - 1005
        if ( report_html == html ) print( "</A>" );
1 root 1006
 
1007
        print( " %-*s", 3, team_buf.class == 0 ? "" : config.team_class[team_buf.class - 1].abr );
1008
 
1009
        /*
1010
        **  Print the per-leg data
1011
        **      - Time
1012
        **      - Leg place
1013
        **      - End place
1014
        */
1015
        for( j = 1; j <= config.num_legs; j++ )
1016
        {
13 david 1017
            /*
1018
            **  Ensure that non-equestrian leg data is not displayed
1019
            */
1020
            if ( j == config.equestrian_leg && team_buf.flags.non_equestrian )
1021
            {
61 - 1022
                print( "  %-8s %4.4s %4.4s", "-- NE --", "NE","NE");
13 david 1023
            }
1024
            else
1025
            {
1026
                print( "  %-8s %4.4s %4.4s",
1 root 1027
                    time_a( team_buf.leg[j].elapsed ),
1028
                    pr_place( team_buf.leg[j].l_place, ptr->flags.bad_times ),
1029
                    pr_place( team_buf.leg[j].le_place,ptr->flags.bad_times )
1030
                  );
13 david 1031
            }
1 root 1032
        }
1033
 
24 - 1034
       /*
61 - 1035
        **  Print the trailer (Finishing order)
1 root 1036
        **      - Total time
1037
        **      - Category place - with reference to category file
1038
        */
61 - 1039
//        print( "  %-8s ",  time_a( team_buf.leg[0].elapsed ) );
1040
        print( "  %-8s ", time_a( ptr->lege[0] ) );
1041
 
75 - 1042
        if ( report_html == 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 - 1043
        print( "%-4.4s", pr_place_ne( team_buf.leg[0].lc_place, ptr->flags.bad_times, ptr->flags.non_equestrian ) );
75 - 1044
        if ( report_html == html ) print( "</A>" );
1045
        if ( report_html == printed && lcount %5 == 4 ) print_underline( FALSE );
1046
        lcount++;
1 root 1047
        print( "\n" );
1048
    }
1049
 
1050
    print_class_stats( -1, TRUE );              /* Print statistics */
18 david 1051
    print_legend(-1, 1 );                       /* Print the legend */
1 root 1052
    close_printer();                            /* Close the printer */
1053
 
1054
    /*
1055
     * Now produce a breakdown on a class by class basis 
1056
     * Now print out the class placement information
1057
     */
1058
 
1059
    if( suppress_classes )
1060
    {
1061
        printf( "WARNING: Class printouts suppressed\n" );
1062
        return;
1063
    }
1064
 
1065
    sort_team_data( 0, S_LC );                 /* Generate class placement data */
1066
    last_class = -1;                           /* Invalid class to start with */
33 - 1067
    memset ( class_done, 0, sizeof(class_done));
1 root 1068
 
33 - 1069
 
1 root 1070
    for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
1071
    {
1072
        /*
1073
        **  Detect a change in the "class"
1074
        **  All data is within the one array of data
1075
        **  Use the in-memory class as this MAY differ from that stored
1076
        **  The non-equestrian class does this.
1077
        */
1078
        if( last_class != ptr->class )
1079
        {
1080
            if( last_class >= 0 )
1081
            {
1082
                print_class_stats( last_class, TRUE );
18 david 1083
                print_legend( last_class, 1 );
1 root 1084
                close_printer();
1085
            }
1086
 
1087
            report_title = tprintf( "Category results for : %-*s", LEN_CLASS_NAME, ptr->class == 0 ? "" : config.team_class[ptr->class - 1].full_name );
1088
 
1089
            if( !open_printer( "", config.team_class[ptr->class - 1].abr, 132, report_html, report_title ) )
1090
                continue;
1091
            print_class_header( last_class = ptr->class, TRUE );
33 - 1092
 
1093
            /*
1094
            **  Mark the class as done
1095
            */
1096
            class_done[ptr->class] = TRUE;
75 - 1097
            lcount = 0;
1 root 1098
        }
1099
 
1100
        /*
1101
        **  Now read in the team record
1102
        */
1103
        g_record( ptr->team, &team_buf );
1104
 
1105
        /*
1106
        **  If printing an HTML report then we need to mark
1107
        **  the entry with a reference so that we can link to it
1108
        */
75 - 1109
        if ( report_html == html )
1 root 1110
            print( "<A NAME=\"Team_%04d\"></A>",team_buf.numb );
1111
 
1112
        /*
1113
        **  Print the basics
1114
        **      - Place within the class
1115
        **      - Team number - with HTML reference to team file
1116
        **      - Class
1117
        */
1118
 
75 - 1119
        if ( report_html == printed && lcount %5 == 4 ) print_underline( TRUE );
1 root 1120
        print( "%4.4s ", pr_place( team_buf.leg[0].lc_place, ptr->flags.bad_times ) );
75 - 1121
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), team_buf.numb );
1 root 1122
        print( "%4d",  team_buf.numb );
75 - 1123
        if ( report_html == html ) print( "</A>" );
1 root 1124
        print( " %-*s", 3, team_buf.class == 0 ? "" : config.team_class[team_buf.class - 1].abr );
1125
 
1126
        for( j = 1; j <= config.num_legs; j++ )
1127
        {
1128
            /*
1129
            **  Ensure that non-equestrian leg data is not displayed
1130
            */
61 - 1131
            if ( j == config.equestrian_leg && (ptr->class == config.nonequestrian_class || ptr->flags.non_equestrian) )
1 root 1132
            {
61 - 1133
                print( "  %-8s %4.4s %4.4s", "-- NE --", "NE","NE");
1 root 1134
            }
1135
            else
1136
            {
1137
                print( "  %-8s %4.4s %4.4s", time_a( team_buf.leg[j].elapsed ),
61 - 1138
                       pr_place( team_buf.leg[j].lc_place,  ptr->flags.bad_times ),
1 root 1139
                       pr_place( team_buf.leg[j].lec_place, ptr->flags.bad_times ) );
1140
            }
1141
        }
1142
 
1143
        /*
1144
        **  Print the trailer
1145
        **      - Total time
1146
        **      - Overall place - with reference to overall place file
1147
        */
1148
        /* print( "  %-8s ", time_a( team_buf.leg[0].elapsed ) ); */
1149
        print( "  %-8s ", time_a( ptr->lege[0] ) );
1150
 
75 - 1151
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "finish" ,"html")), team_buf.numb );
61 - 1152
        print( "%4.4s", pr_place( team_buf.leg[0].l_place, ptr->flags.bad_times || (ptr->class == config.nonequestrian_class)));
75 - 1153
        if ( report_html == html ) print( "</A>" );
1 root 1154
 
75 - 1155
        if ( report_html == printed && lcount %5 == 4 ) print_underline( FALSE );
1156
        lcount++;
1 root 1157
        print( "\n" );
1158
    }
1159
 
1160
    print_class_stats( last_class, TRUE );
18 david 1161
    print_legend(last_class,1);
1 root 1162
    close_printer();
1163
 
33 - 1164
    /*
1165
    **  Pickup missed classes and create a report
1166
    */
1167
    for( j = 1; j <= config.num_class; j++ )
1168
    {
1169
        if ( class_done[j] )
1170
        {
1171
            continue;
1172
        }
1 root 1173
 
33 - 1174
        report_title = tprintf( "Category results for : %-*s", LEN_CLASS_NAME, config.team_class[j - 1].full_name );
1175
 
1176
        if( !open_printer( "", config.team_class[j - 1].abr, 132, report_html, report_title ) )
1177
            continue;
1178
        print_class_header( j-1, TRUE );
1179
        print( "\nThere were no competitors in this class\n" );
1180
        print_legend(j,1);
1181
        close_printer();
1182
    }
1183
 
1184
 
1 root 1185
    /*
1186
    **  If we are generating an HTML report then we need to create the file
1187
    **  that contains all the team names - the assumption is that this data
1188
    **  is available
1189
    */
1190
    if ( report_html )
1191
    {
1192
        pri_team();
1193
    }
1194
 
1195
    /*
1196
    **  Generate the awards report.
1197
    **  This is only available as an HTML report
1198
    */
1199
    if ( report_html )
1200
    {
61 - 1201
        pri_awards_html();
1 root 1202
    }
1203
 
1204
    /*
1205
    **  Generate the master index page
1206
    */
1207
    if ( report_html )
1208
    {
1209
        pri_master_index();
1210
    }
1211
 
18 david 1212
    pri_name_index_body();
1 root 1213
}
1214
 
1215
/*========================================================================
1216
 *
1217
 *  Place to text
1218
 *
1219
 *  Purpose:
1220
 *      This function is called to convert a place to text
1221
 *
1222
 *  Parameters:
1223
 *      place
1224
 *
1225
 *  Returns:
1226
 *      text
1227
 *
1228
 *========================================================================*/
1229
 
1230
char *placing ( int place )
1231
{
1232
    if ( place > MAX_PLACE )
1233
    {
1234
        return tprintf( "Place: %d", place);
1235
    }
1236
    return tprintf ("%s Place", place_text[place]);
1237
}
1238
 
1239
/*========================================================================
1240
 *
1241
 *  Print award results
1242
 *
1243
 *  Purpose:
1244
 *      This function is called to Print award results
27 - 1245
 *      Keep the page to 80 cols, so that it can be pronted on A4
1 root 1246
 *
1247
 *  Parameters:
1248
 *      None
1249
 *
1250
 *  Returns:
1251
 *      Nothing
1252
 *
1253
 *========================================================================*/
61 - 1254
void pri_awards_html(void)
1255
{
75 - 1256
    report_type saved = report_html;
61 - 1257
    /*
1258
    **  Generate ALL results with HTML tags
1259
    */
75 - 1260
    report_html = html;
61 - 1261
    pri_awards();
66 - 1262
    report_html = saved;
61 - 1263
}
1264
 
1265
/*========================================================================
1266
 *
1267
 *  Print award results
1268
 *
1269
 *  Purpose:
1270
 *      This function is called to Print award results
1271
 *      Keep the page to 80 cols, so that it can be pronted on A4
1272
 *
1273
 *  Parameters:
1274
 *      None
1275
 *
1276
 *  Returns:
1277
 *      Nothing
1278
 *
1279
 *========================================================================*/
1 root 1280
void pri_awards(void)
1281
{
1282
    int j;
1283
    int i;
1284
    int k;
1285
    int windex;
72 - 1286
    int winmax;
1 root 1287
    ty_s_data  *ptr;
1288
    int         last_class;
71 - 1289
    char    solid_line[100];
1 root 1290
 
72 - 1291
    /*
1292
    **  Calculate Summary information
1293
    **  Should cache the data
1294
    */
1295
    t_class_summary sdata;
1296
    calc_class_summary( & sdata );
1297
 
1298
 
27 - 1299
    if( !open_printer( "", "awards", 80, report_html, "Prizes and Awards" ) )
1 root 1300
        return;
1301
 
71 - 1302
    memset ( solid_line, 0, sizeof( solid_line ));
1303
    memset ( solid_line, '-', 80 );
1304
 
1 root 1305
    /*
1306
    **  Generate an index for this page
1307
    */
1308
    print( "\n");
75 - 1309
    if ( report_html == html )
61 - 1310
    {
1311
        print( "<hr>" );
68 - 1312
        print( "<A NAME=\"%s\"></A>",url_encode("INDEX"));
61 - 1313
    }
1 root 1314
    print( "Award Categories");
1315
 
1316
    for( j = 1; j <= config.num_class; j++ )
1317
    {
1318
        /*
1319
        **  Header for the class
1320
        */
1321
        if ( config.class_winners[j-1] <= 0 )
1322
            continue;
1323
 
72 - 1324
        winmax = config.class_winners[j-1];
1325
        {
1326
            int valid =   sdata.class[j].total
1327
                        - sdata.class[j].disqualified;
1328
//                        - sdata.class[j].non_equestrian;
1329
            if ( valid < winmax )
1330
                winmax = valid;
1331
        }
1332
 
1 root 1333
        print( "\n");
61 - 1334
        print( "    ");
75 - 1335
        if ( report_html == html ) print( "<A HREF=\"#%s\">",url_encode(config.team_class[j-1].full_name));
72 - 1336
        print( "%s",  tprintf( "%-*s", LEN_CLASS_NAME ,config.team_class[j-1].full_name ));
75 - 1337
        if ( report_html == html ) print( "</A>" );
72 - 1338
        print( "  %3d Awards", winmax );
1339
        if ( config.class_winners[j-1] != winmax )
1340
            print( " from a maximum of %3d", config.class_winners[j-1] );
1341
 
1 root 1342
    }
1343
 
1344
    /*
1345
    **  Manual entries
1346
    */
1347
    print( "\n");
61 - 1348
    print( "    ");
75 - 1349
    if ( report_html == html ) print( "<A HREF=\"#%s\">",url_encode("Hall Of Fame"));
1 root 1350
    print( "%s",  "Hall Of Fame" );
75 - 1351
    if ( report_html == html ) print( "</A>" );
1 root 1352
 
1353
    print( "\n");
61 - 1354
    print( "    ");
75 - 1355
    if ( report_html == html ) print( "<A HREF=\"#%s\">",url_encode("FASTEST"));
1 root 1356
    print( "%s",  "FASTEST" );
75 - 1357
    if ( report_html == html ) print( "</A>" );
1 root 1358
 
1359
    /*
1360
    **  Sort the data by class
1361
    */
1362
    sort_team_data( 0, S_LC );      /* Generate class placement data */
1363
    last_class = -1;                /* Invalid class to start with */
1364
 
1365
    /*
1366
    **  Process each category
1367
    */
71 - 1368
    print( "\n");
1 root 1369
    for( j = 1; ; j++ )
1370
    {
1371
        /*
1372
        **  Tail for previous entry
1373
        */
1374
        if ( j != 1 )
75 - 1375
            if ( report_html == html ) print( "<A HREF=\"#%s\">Awards Index</A>",url_encode("INDEX"));
1 root 1376
 
1377
        if ( j > config.num_class  )
1378
            break;
1379
 
1380
        /*
1381
        **  Header for the class
1382
        */
1383
        print( "\n");
75 - 1384
        if ( report_html == html )
61 - 1385
        {
1386
            print( "<hr>" );
68 - 1387
            print( "<A name=\"%s\"></A>",url_encode(config.team_class[j-1].full_name));
61 - 1388
        }
1389
        else
1390
        {
71 - 1391
            print( "%s\n", solid_line);
61 - 1392
        }
1393
        print( "Category: ");
75 - 1394
        if ( report_html == html ) print( "<A HREF=\"%s\">",url_encode(p_filename(filebase, config.team_class[j - 1].abr ,"html")));
1 root 1395
        print( "%s",  config.team_class[j-1].full_name );
75 - 1396
        if ( report_html == html ) print( "</A>" );
1 root 1397
 
61 - 1398
        if ( config.class_winners[j-1] <= 0 )
1 root 1399
        {
1400
            print( "\n");
1401
            print( "No winners awarded" );
1402
            continue;
1403
        }
1404
 
1405
        /*
1406
        **  Enties for 'n' the best teams as configured
1407
        */
1408
        windex = 0;                     /* Winners done */
1409
        for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
1410
        {
1411
            if ( ptr->class != j )
1412
            {
1413
                continue;
1414
            }
1415
 
1416
            /*
1417
            **  Now read in the team record
1418
            */
1419
            if( valid_field( ptr->team ) && g_record( ptr->team, &team_buf ) )
1420
            {
72 - 1421
                /*
1422
                **  Ensure we have a valid team
1423
                **  Can't award disqualified teams
1424
                **  Can't award NE teams unless its a NE award
1425
                */
1426
                if ( ptr->flags.bad_times )
1427
                    break;
1428
 
1429
                if ( ptr->class != config.nonequestrian_class  && ptr->flags.non_equestrian )
1430
                    break;
1431
 
1432
                /*
1433
                **  Count the entry
1434
                */
1 root 1435
                windex++;
1436
 
1437
                /*
1438
                **  If printing an HTML report then we need to mark
1439
                **  the entry with a reference so that we can link to it
1440
                */
1441
                print( "\n");
75 - 1442
                if ( report_html == html )
61 - 1443
                {
1444
                    print( "<A NAME=\"Team_%04d\">",team_buf.numb );
1445
                    print( "</A>" );
1446
                }
1 root 1447
 
1448
                /*
1449
                **  Basic information
1450
                **      - Team number - with Xref back to full result
1451
                **      - Full team name
1452
                **      - Full categoray name
1453
                */
1454
                print( "%s", placing(windex) );
1455
 
61 - 1456
                print( "  Team Name: ");
75 - 1457
                if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), team_buf.numb );
1 root 1458
                print( "%-*s ",     MAX_TM_NAME, team_buf.name );
75 - 1459
                    if ( report_html == html ) print( "</A>" );
1 root 1460
 
61 - 1461
                print( "  Number: ");
75 - 1462
                if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "finish" ,"html")), team_buf.numb );
1 root 1463
                print( "%4d",       team_buf.numb );
75 - 1464
                if ( report_html == html ) print( "</A>" );
1 root 1465
 
1466
 
1467
                for( k = 0; k < MAX_MEMB; k++ )
1468
                {
1469
 
1470
                    /*
1471
                    **  Skip equestrian leg in the non-equestion display
1472
                    */
1473
                    if ( k + 1 == config.equestrian_leg && ptr->class == config.nonequestrian_class)
1474
                        continue;
1475
 
1476
                    print( "\n");
1477
                    print( "    ");
1478
                    print( "%-*s", MAX_PERSON_NAME, config.leg_name[k] ? config.leg_name[k] : "Competitor"  );
1479
                    print( " %-*s", MAX_PERSON_NAME, team_buf.members[k].name );
1480
 
1481
                    print( "  %-8s", time_a( team_buf.leg[k+1].elapsed ) );
1482
                }
1483
 
1484
                print( "\n");
1485
                print( "    ");
1486
                print_bold( TRUE );
1487
                print( "%-*s %-*s  %-8s", MAX_PERSON_NAME , "Total" ,MAX_PERSON_NAME, "",time_a( team_buf.leg[0].elapsed ) );
1488
                print_bold( FALSE );
1489
                print( "\n" );
1490
            }
1491
 
1492
 
1493
            /*
1494
            **  More to do
1495
            */
1496
            if ( windex >= config.class_winners[j-1] )
1497
            {
1498
                break;
1499
            }
1500
        }
1501
    }
1502
 
1503
    /*
1504
    **  Generate the Hall of Fame information
1505
    */
1506
    print( "\n");
75 - 1507
    if ( report_html == html )
61 - 1508
    {
1509
        print( "<hr>" );
68 - 1510
        print( "<A name=\"%s\"></A>",url_encode("Hall Of Fame"));
61 - 1511
    }
71 - 1512
    else
1513
    {
1514
        print( "%s\n", solid_line);
1515
    }
1 root 1516
    print( "%s",  "Hall of Fame" );
1517
 
1518
    if ( config.num_fame  )
1519
    {
1520
        for( i = 1; i <= config.num_fame; i++ )
1521
        {
61 - 1522
            print( "\n");
1523
            print( "    %-*s", MAX_PERSON_NAME, config.hall_fame[i-1] );
1 root 1524
        }
1525
    }
1526
    else
1527
    {
1528
        printf( "\n    There are no new stars for the Hall of Fame");
1529
    }
75 - 1530
    if ( report_html == html ) print( "\n");
1531
    if ( report_html == html ) print( "<A HREF=\"#%s\">Awards Index</A>",url_encode("INDEX"));
1 root 1532
 
1533
    /*
1534
    **  Generate the FASTEST information
1535
    */
61 - 1536
    print( "\n" );
71 - 1537
    print( "\n");
75 - 1538
    if ( report_html == html )
61 - 1539
    {
1540
        print( "<hr>" );
68 - 1541
        print( "<A name=\"%s\"></A>",url_encode("FASTEST"));
61 - 1542
    }
1543
    else
1544
    {
71 - 1545
        print( "%s\n", solid_line);
61 - 1546
    }
1 root 1547
    print( "%s",  "FASTEST" );
1548
 
1549
    /*
1550
    **  Sort the data and then generate the stats - again
1551
    */
1552
    do_big_sort();
1553
    gen_stats();
1554
 
1555
    for( i = 1; i <= config.num_legs; i++ )
1556
    {
1557
        g_record( stats.fast.team[i][0], &team_buf );
1558
 
1559
        print( "\n");
1560
        print( "    %-13s ", config.leg_name[i - 1] );
61 - 1561
        print( "  Name: ");
75 - 1562
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), team_buf.numb );
1 root 1563
        print( "%-*s", MAX_PERSON_NAME, team_buf.members[i-1].name );
75 - 1564
        if ( report_html == html ) print( "</A>" );
61 - 1565
        print( "  Team :");
75 - 1566
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "finish" ,"html")), team_buf.numb );
27 - 1567
        print( "%4d" , stats.fast.team[i][0] );
75 - 1568
        if ( report_html == html ) print( "</A> " );
27 - 1569
        print( "Time:%s ", time_a( stats.fast.time[i][0] ) );
1 root 1570
 
1571
    }
1572
 
75 - 1573
    if ( report_html == html ) print( "\n");
1574
    if ( report_html == html ) print( "<A HREF=\"#%s\">Awards Index</A>",url_encode("INDEX"));
61 - 1575
    print( "\n");
1 root 1576
    close_printer();
1577
}
1578
 
1579
/*========================================================================
1580
 *
1581
 *  pri_master_index
1582
 *
1583
 *  Purpose:
1584
 *      This function is called to create an HTML page that references all
1585
 *      the other pages that have been generated
1586
 *
1587
 *      Assume that they are in the same directory
1588
 *
1589
 *  Parameters:
1590
 *      None
1591
 *
1592
 *  Returns:
1593
 *      Nothing
1594
 *
1595
 *========================================================================*/
1596
void pri_master_index_entry(char *name, char *text)
1597
{
1598
    print( "<tr><td>");
68 - 1599
    print ("<A HREF=\"%s\">%s</A>\n", url_encode(p_filename(filebase, name ,"html")), text );
1 root 1600
}
1601
 
1602
 
1603
void pri_master_index(void)
1604
{
1605
    int j;
1606
 
75 - 1607
    report_html = html;
1 root 1608
    if( !open_printer( "", "index", 132, report_html, "Master Index" ) )
1609
        return;
1610
 
1611
    /*
1612
    **  Names
1613
    */
1614
    print( "<TABLE border=0 align=center>" );
18 david 1615
    pri_master_index_entry( "name", "Team list" );
1616
    pri_master_index_entry( "competitor", "Competitor list" );
1 root 1617
    pri_master_index_entry( "finish", "Finishing Order for all Teams" );
1618
    pri_master_index_entry( "awards", "Prizes and Awards" );
1619
    print( "<tr><td>\n" );
1620
 
1621
    print( "\n" );
1622
    for( j = 1; j <= config.num_class; j++ )
1623
    {
1624
        pri_master_index_entry( config.team_class[j - 1].abr, tprintf("Category Results for: %s", config.team_class[j-1].full_name) );
1625
    }
32 - 1626
 
1 root 1627
    print( "</TABLE>" );
1628
 
1629
    close_printer();
32 - 1630
 
1631
    /*
1632
    **  A small page to hold the Leg End displays
1633
    */
1634
 
1635
    if( !open_printer( "", "legindex", 132, report_html, "Master Index with trace data" ) )
1636
        return;
1637
 
1638
    /*
1639
    **  Names
1640
    */
1641
    print( "<TABLE border=0 align=center>" );
1642
#if 1
1643
    pri_master_index_entry( "name", "Team list" );
1644
    pri_master_index_entry( "competitor", "Competitor list" );
1645
    pri_master_index_entry( "finish", "Finishing Order for all Teams" );
1646
    pri_master_index_entry( "awards", "Prizes and Awards" );
1647
    print( "<tr><td>\n" );
1648
 
1649
    print( "\n" );
1650
    for( j = 1; j <= config.num_class; j++ )
1651
    {
1652
        pri_master_index_entry( config.team_class[j - 1].abr, tprintf("Category Results for: %s", config.team_class[j-1].full_name) );
1653
    }
1654
#endif
1655
    print( "<tr><td>\n" );
1656
 
1657
    print( "\n" );
1658
    for ( leg = 1; leg <= config.num_legs; leg ++ )
1659
    {
1660
        pri_master_index_entry( tprintf("lg%1.1d", leg), tprintf("Leg End Results for: %d", leg) );    
1661
    }
1662
 
1663
    print( "<tr><td>\n" );
1664
    print( "\n" );
1665
 
1666
    for ( leg = 1; leg <= config.num_legs; leg ++ )
1667
    {
1668
        pri_master_index_entry( tprintf("le%1.1d", leg), tprintf("Leg Elapsed Time Results for: %d", leg) );
1669
    }    
1670
 
1671
 
1672
    print( "</TABLE>" );
1673
 
1674
    close_printer();
1675
 
1 root 1676
}
1677
 
1678
 
1679
/*========================================================================
1680
 *
1681
 *  Print interim results
1682
 *
1683
 *  Purpose:
1684
 *      This function is called to Print interim results
1685
 *
1686
 *  Parameters:
1687
 *      None
1688
 *
1689
 *  Returns:
1690
 *      Nothing
1691
 *
1692
 *========================================================================*/
1693
 
1694
void pri_interim(void)
1695
{
1696
    ty_s_data  *ptr;
1697
    unsigned    i;
1698
    int         j, last_class;
29 - 1699
    char        suppress_classes = FALSE;                /* Boolean. Printout class files too */
1 root 1700
    char       *report_title;
1701
 
29 - 1702
    if ( ! report_all )
1703
    {
1704
        cur( 0, 5 );
1705
        printf( "Generate interim result printouts\n" );
1706
        ck_data( -1, C_DISQUAL );                    /* Check the data - dummy check */
1707
        suppress_classes = getyes( "Do you want to suppress class printouts" );
1708
        printf( "\nSorting the data\n" );
1709
    }
1 root 1710
    do_big_sort();                             /* Sort on every thing */
1711
    gen_stats();                               /* Generate the stats too */
1712
 
1713
    printf( "\nGenerating the printed output\n" );
1714
 
1715
    /*
1716
     * Now print the data on the printer 
1717
     */
1718
 
1719
    if( !open_printer( "", "int", 132, report_html, "Interim Results" ) )
1720
        return;
1721
 
1722
    /*
1723
     * Print out the data 
1724
     */
1725
    print_class_header( -1, FALSE );                     /* Print the header */
1726
 
1727
    ptr = sort_data;
1728
    sort_team_data( 0, S_TEAM );                   /* Re-sort on team number */
1729
    for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
1730
    {
1731
        if ( ptr->class == config.nonequestrian_class )
1732
            continue;
1733
 
1734
        g_record( ptr->team, &team_buf );
1735
 
1736
        print( "%4d %4.4s %-*s",
1737
               team_buf.numb,
1738
               pi_place( team_buf.leg[config.num_legs].le_place,
1739
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ),
1740
               3,
1741
               team_buf.class ==
1742
 
1743
        for( j = 1; j <= config.num_legs; j++ )
1744
        {
1745
            print( "  %-8s %4.4s %4.4s",
1746
                   time_fa( team_buf.leg[j].elapsed,
1747
                            ptr->flags.disqualified ),
1748
                   pi_place( team_buf.leg[j].l_place, ptr->flags.disqualified,
1749
                             team_buf.leg[j].elapsed ),
1750
                   pi_place( team_buf.leg[j].le_place,
1751
                             ptr->flags.disqualified,
1752
                             team_buf.leg[j].elapsed ) );
1753
        }
1754
        print( "  %-8s %4.4s\n",
1755
               time_fa( team_buf.leg[0].elapsed, ptr->flags.disqualified ),
1756
               pi_place( team_buf.leg[config.num_legs].lec_place,
1757
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ) );
1758
    }
1759
 
1760
    print_class_stats( -1, FALSE );             /* Print statistics */
18 david 1761
    print_legend(-1, 1);                        /* Print the legend */
1 root 1762
    close_printer();                            /* Close the printer */
1763
 
1764
 
1765
    /*
1766
     * Now produce a breakdown on a class by class basis 
1767
     * Now print out the class placement information
1768
     */
1769
 
1770
    if( suppress_classes )
1771
    {
1772
        printf( "WARNING: Class printouts suppressed\n" );
1773
        return;
1774
    }
1775
 
1776
    sort_team_data( 0, S_CLASS );              /* Generate class placement data */
1777
    last_class = -1;                             /* Invalid class to start with */
1778
 
1779
    for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
1780
    {
1781
        /*
1782
        **  Detect a change in the "class"
1783
        **  All data is within the one array of data
1784
        **  Use the in-memory class as this MAY differ from that stored
1785
        **  The non-equestrian class does this.
1786
        */
1787
        if( last_class != ptr->class )
1788
        {
1789
            if( last_class >= 0 )
1790
            {
1791
                print_class_stats( last_class, TRUE );
18 david 1792
                print_legend(last_class, 1);
1 root 1793
                close_printer();
1794
            }
1795
 
1796
            report_title = tprintf( "Interim Category results for : %-*s", LEN_CLASS_NAME, team_buf.class == 0 ? "" : config.team_class[ptr->class - 1].full_name );
1797
 
1798
            if( !open_printer( "", tprintf( "i%2s", config.team_class[ptr->class - 1].abr ), 132, report_html, report_title ) )
1799
                continue;
1800
            print_class_header( last_class = ptr->class, FALSE );
1801
        }
1802
 
1803
        /*
1804
        **  Now read in the team record
1805
        */
1806
        g_record( ptr->team, &team_buf );
1807
        print( "%4d %4.4s %-*s",
1808
               team_buf.numb,
1809
               pi_place( team_buf.leg[config.num_legs].lec_place,
1810
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ),
1811
               3,
1812
               team_buf.class ==
1813
 
1814
        for( j = 1; j <= config.num_legs; j++ )
1815
        {
1816
            print( "  %-8s %4.4s %4.4s",
1817
                   time_fa( team_buf.leg[j].elapsed,
1818
                            ptr->flags.disqualified ),
1819
                   pi_place( team_buf.leg[j].lc_place,
1820
                             ptr->flags.disqualified,
1821
                             team_buf.leg[j].elapsed ),
1822
                   pi_place( team_buf.leg[j].lec_place,
1823
                             ptr->flags.disqualified,
1824
                             team_buf.leg[j].elapsed ) );
1825
        }
1826
        print( "  %-8s %4.4s\n",
1827
               time_fa( team_buf.leg[0].elapsed, ptr->flags.disqualified ),
1828
               pi_place( team_buf.leg[config.num_legs].le_place,
1829
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ) );
1830
    }
1831
 
1832
    print_class_stats( last_class, FALSE );
18 david 1833
    print_legend(last_class, 1);
1 root 1834
    close_printer();
1835
 
1836
}
1837
 
61 - 1838
/*----------------------------------------------------------------------------
1839
** FUNCTION           : pri_csv_data
1840
**
1841
** DESCRIPTION        : Generate a CSV file of all the report data
1842
**                      It can then be used to play with the data externally
1843
**
1844
**
1845
** INPUTS             : None
1846
**
1847
** RETURNS            : Yes it does
1848
**
1849
----------------------------------------------------------------------------*/
1850
 
1851
 
1852
void pri_csv_data ( void )
1853
{
1854
    int i;
1855
    int j;
1856
    int age_sum;
1857
 
1858
    /*
1859
    **  Sort on every thing
1860
    **  Then generate all the stats too
1861
    */
1862
    printf( "\nSorting the data\n" );
1863
    do_big_sort();
1864
    gen_stats();
1865
 
1866
    /*
1867
     * Now print the data on the printer 
1868
     */
1869
 
1870
    if( !open_printer( "full_data", "csv", 2000, FALSE, NULL ) )
1871
        return;
1872
 
1873
    printf( "\nGenerating the printed output\n" );
1874
 
1875
    /*
1876
    **  Print headings
1877
    */
1878
    csv_print( "%s",   "Team Number" );
1879
    csv_print( "%s",   "Team Name" );
1880
 
1881
    csv_print( "%s",    "Class Full");
1882
    csv_print( "%s",    "Class Abr");
1883
    csv_print( "%s",    "Class Start Time");
1884
    csv_print( "%s",    "Class Start Time Number");
1885
 
1886
    csv_print( "%s",    "Team Country");
1887
 
1888
    for( j = 1; j <= config.num_legs; j++ )
1889
    {
1890
        csv_print( "%s", "Leg Number" );
1891
        csv_print( "%s", "Leg Name");
1892
        csv_print( "%s", "Competitor Name");
1893
        csv_print( "%s", "Sex" );
1894
        csv_print( "%s", "Age");
1895
        csv_print( "%s", "Start Time");
1896
        csv_print( "%s", "Start Time Number");
1897
        csv_print( "%s", "End Time" );
1898
        csv_print( "%s", "End Time Number" );
1899
        csv_print( "%s", "Elapsed Time");
1900
        csv_print( "%s", "Elapsed Time Number");
1901
        csv_print( "%s", "Leg Place");
1902
        csv_print( "%s", "Leg End Place");
1903
        csv_print( "%s", "Leg Class Place");
1904
        csv_print( "%s", "Leg End Class Place");
1905
        csv_print( "%s", "Manual");
1906
    }
1907
 
1908
    j = 0;
1909
    csv_print( "%s", "Team Start Time");
1910
    csv_print( "%s", "Team Start Time Number");
1911
    csv_print( "%s", "Team End Time");
1912
    csv_print( "%s", "Team End Time Number");
1913
    csv_print( "%s", "Team Elapsed Time");
1914
    csv_print( "%s", "Team Elapsed Time Number");
1915
//            csv_print( "%s", team_buf.leg[j].l_place );
1916
    csv_print( "%s", "Team Leg End Place");
1917
//            csv_print( "%s", team_buf.leg[j].lc_place );
1918
    csv_print( "%s", "Team Leg Class Place");
1919
//            csv_print( "%s", team_buf.leg[j].manual );
1920
 
1921
    csv_print( "%s", "Total Team Age");
1922
    csv_print( "%s", "Flag:valid Team");
1923
    csv_print( "%s", "Flag:bad_times" );
1924
    csv_print( "%s", "Flag:disqualified" );
1925
    csv_print( "%s", "Flag:non_equestrian" );
1926
    csv_print("\n");
1927
 
1928
 
1929
    for( i = config.min_team; i <= config.max_team; i++ )
1930
    {
1931
        if( valid_field( i ) && g_record( i, &team_buf ) )
1932
        {
1933
            /*
1934
            **  Basic information
1935
            **      - Team number - with Xref back to full result
1936
            **      - Full team name
1937
            **      - Full categoray name - with Xref to category results
1938
            **      - Country name
1939
            */
1940
            csv_print( "%d",   team_buf.numb );
1941
            csv_print( "%s",   team_buf.name );
1942
 
1943
            csv_print( "%s",    team_buf.class == 0 ? "" : config.team_class[team_buf.class - 1].full_name );
1944
            csv_print( "%s",    team_buf.class == 0 ? "" : config.team_class[team_buf.class - 1].abr );
1945
            csv_print( "%s",    time_a (team_buf.class == 0 ? 0 : config.team_class[team_buf.class - 1].start ));
1946
            csv_print( "%d",    team_buf.class == 0 ? 0 : config.team_class[team_buf.class - 1].start );
1947
 
1948
            csv_print( "%s",    config.num_countries == 0
1949
                                || team_buf.country ==
1950
 
1951
 
1952
            age_sum = 0;
1953
            for( j = 1; j <= config.num_legs; j++ )
1954
            {
1955
                csv_print( "%d", j );
1956
                csv_print( "%s", config.leg_name[j - 1] );
1957
                csv_print( "%s", team_buf.members[j-1].name );
1958
                csv_print( "%s", ( team_buf.members[j-1].sex == male ) ? "Male" : "Female" );
1959
                csv_print( "%d", team_buf.members[j-1].age );
1960
                if ( age_sum >= 0 )
1961
                {
1962
                    ushort age = team_buf.members[j-1].age;
1963
                    if ( age > 0 && age < 255 )
1964
                    {
1965
                        age_sum += age;
1966
                    }
1967
                    else
1968
                    {
1969
                        age_sum = -1;
1970
                    }
1971
                }
1972
 
1973
 
1974
                csv_print( "%s", time_a(team_buf.leg[j].start ));
1975
                csv_print( "%d", team_buf.leg[j].start );
1976
                csv_print( "%s", time_a(team_buf.leg[j].end ));
1977
                csv_print( "%d", team_buf.leg[j].end );
1978
                csv_print( "%s", time_a(team_buf.leg[j].elapsed ));
1979
                csv_print( "%d", team_buf.leg[j].elapsed );
1980
                csv_print( "%d", team_buf.leg[j].l_place );
1981
                csv_print( "%d", team_buf.leg[j].le_place );
1982
                csv_print( "%d", team_buf.leg[j].lc_place );
1983
                csv_print( "%d", team_buf.leg[j].lec_place );
1984
                csv_print( "%d", team_buf.leg[j].manual );
1985
            }
1986
 
1987
            j = 0;
1988
            csv_print( "%s", time_a(team_buf.leg[j].start ));
1989
            csv_print( "%d", team_buf.leg[j].start );
1990
            csv_print( "%s", time_a(team_buf.leg[j].end ));
1991
            csv_print( "%d", team_buf.leg[j].end );
1992
            csv_print( "%s", time_a(team_buf.leg[j].elapsed ));
1993
            csv_print( "%d", team_buf.leg[j].elapsed );
1994
//            csv_print( "%d", team_buf.leg[j].l_place );
1995
            csv_print( "%d", team_buf.leg[j].le_place );
1996
//            csv_print( "%d", team_buf.leg[j].lc_place );
1997
            csv_print( "%d", team_buf.leg[j].lec_place );
1998
//            csv_print( "%d", team_buf.leg[j].manual );
1999
 
2000
            csv_print( "%d", age_sum );
2001
            csv_print( "%d", team_buf.flags.valid );
2002
            csv_print( "%d", team_buf.flags.bad_times );
2003
            csv_print( "%d", team_buf.flags.disqualified );
2004
            csv_print( "%d", team_buf.flags.non_equestrian );
2005
 
2006
//How about class placings
2007
 
2008
 
2009
            csv_print( "\n" );
2010
        }
2011
    }
2012
 
2013
    close_printer();
2014
}
2015
 
2016
 
1 root 2017
/*========================================================================
2018
 *
29 - 2019
 *  Print all reports at once
61 - 2020
 *  Its all so fast, these days ...
29 - 2021
 *
2022
 *  Purpose:
2023
 *      This function is called to print all reports at once
2024
 *
2025
 *  Parameters:
2026
 *      None
2027
 *
2028
 *  Returns:
2029
 *      Nothing
2030
 *
2031
 *========================================================================*/
2032
 
2033
void pri_all_reports ( void )
2034
{
2035
    int leg;
2036
    report_all = TRUE;
2037
 
2038
    pri_team();
2039
 
2040
    for ( leg = 1; leg <= config.num_legs; leg ++ )
2041
    {
2042
        pri_leg_body ( leg );
2043
        pri_eleg_body ( leg );
32 - 2044
 
75 - 2045
        report_html = html;
32 - 2046
 
2047
        pri_leg_body ( leg );
2048
        pri_eleg_body ( leg );        
2049
 
75 - 2050
        report_html = text;
29 - 2051
    }
2052
 
2053
    pri_final();
2054
    pri_final_html();
61 - 2055
    pri_csv_data();
29 - 2056
    pri_summary();
61 - 2057
    pri_awards_html();
29 - 2058
    pri_awards();
2059
    pri_master_index();
72 - 2060
 
29 - 2061
    report_all = FALSE;
2062
}
2063
 
2064
 
2065
/*========================================================================
2066
 *
1 root 2067
 *  Print a class header
2068
 *
2069
 *  Purpose:
2070
 *      This function is called to print a class header
2071
 *
2072
 *  Parameters:
2073
 *      class           Name of this class
2074
 *      final           False - prelim results
2075
 *
2076
 *  Returns:
2077
 *      Nothing
2078
 *
2079
 *========================================================================*/
2080
 
2081
void print_class_header( int class, int final )
2082
{
2083
    int         j;
2084
 
2085
    /*
2086
    **  Give a clear indication that the report is preliminary
2087
    */
2088
 
2089
    if( !final )
2090
        print( "PRELIMINARY RESULTS ONLY\n\n" );
2091
 
2092
    /*
2093
    **  Now printout the column headings
2094
    **  This is a two line display
2095
    **
2096
    **  Line-1  Leg names
2097
    */
2098
    print( "%-*s %-*s %-*s", 4, "", 4, "", 3, "" );
2099
    for( j = 1; j <= config.num_legs; j++ )
2100
    {
2101
        print_bold( TRUE );
2102
        print( "  %-*s", 18, config.leg_name[j - 1] );
2103
        print_bold( FALSE );
2104
    }
2105
    print( "  %-8s %-4s\n", "Total", ( class < 0 ) ? "Cat" : "Fin" );
2106
 
2107
 
2108
    /*
2109
    **  Line-2  Details
2110
    */
2111
    print_underline( TRUE );
2112
    print( "%-*s %*s %-*s", 4, final ? "Plce" : "Team",
2113
                            4, final ? "Team" : "Plce",
2114
                            3, "Cat" );
2115
 
2116
    for( j = 1; j <= config.num_legs; j++ )
2117
        print( "  %-8s %-4s %-4s", "Time", " LP", " EP" );
2118
 
2119
    print( "  %-8s %-4s\n", "Time", "Plce" );
2120
    print_underline( FALSE );
2121
}
2122
 
2123
/*========================================================================
2124
 *
2125
 *  Generate the class stats
2126
 *
2127
 *  Purpose:
2128
 *      This function is called to Generate the class stats
2129
 *
2130
 *  Parameters:
2131
 *      c           Class to print
2132
 *      final       TRUE: Final data
2133
 *                  FALSE: Interim data
2134
 *
2135
 *  Returns:
2136
 *      Nothing
2137
 *
2138
 *========================================================================*/
2139
 
2140
void print_class_stats( int c, int final )
2141
{
2142
    int         i, j;
2143
    char        *title;
2144
 
2145
    if( c < 0 )
2146
    {
2147
        title = "Event";
2148
        c = 0;
2149
    }
2150
    else
2151
    {
2152
        title = "Category";
2153
    }
2154
 
2155
    print( "\n" );
2156
    if ( report_html ) print_underline(TRUE);
2157
    print( "%s statistics", title );
2158
    if ( report_html ) print_underline(FALSE);
2159
    print( "\n" );
2160
 
2161
 
2162
    /*
2163
    **  Print the names of the different legs
2164
    */
2165
    print( "%-*s       ", LEN_CLASS_NAME, "" );
2166
    for( i = 1; i <= config.num_legs; i++ )
2167
    {
2168
        print_bold( TRUE );
2169
        print( "%-13s  ", config.leg_name[i - 1] );
2170
        print_bold( FALSE );
2171
    }
2172
    print( "%-13s  \n", final ? "Total" : "" );
2173
 
2174
    /*
2175
    **  Print the fastest teams for each leg and overall
2176
    **  Add cross references to the team names for the fastest teams
2177
    */
2178
    print( "%*s : ", LEN_CLASS_NAME, "Fastest" );
2179
    for( i = 0; i <= config.num_legs; i++ )
2180
    {
2181
        j = i + 1;
2182
        if( i >= config.num_legs )
2183
        {
2184
            if( final )
2185
                j = 0;                           /* Leg-0 last */
2186
            else
2187
                break;
2188
        }
2189
 
75 - 2190
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), stats.fast.team[j][c] );
1 root 2191
        print( "%4d",  stats.fast.team[j][c] );
75 - 2192
        if ( report_html == html ) print( "</A>" );
1 root 2193
        print( " %s  ", time_a( stats.fast.time[j][c] ) );
2194
    }
2195
    print( "\n" );
2196
 
2197
    /*
2198
    **  Print the average time for each leg
2199
    */
2200
    print( "%*s : ", LEN_CLASS_NAME, "Average" );
2201
    for( i = 0; i <= config.num_legs; i++ )
2202
    {
2203
        j = i + 1;
2204
        if( i >= config.num_legs )
2205
        {
2206
            if( final )
2207
                j = 0;                           /* Leg-0 last */
2208
            else
2209
                break;
2210
        }
2211
        print( "     %s  ", time_a( stats.average[j][c] ) );
2212
    }
2213
}
2214
 
2215
/*========================================================================
2216
 *
2217
 *  Print the legend
2218
 *
2219
 *  Purpose:
2220
 *      This function is called to Print the legend
2221
 *
2222
 *  Parameters:
2223
 *      class       - Class currently being printed
18 david 2224
 *      full        - Display full legend
1 root 2225
 *
2226
 *  Returns:
2227
 *      Nothing
2228
 *
2229
 *========================================================================*/
2230
 
18 david 2231
void print_legend ( int class, int full )
1 root 2232
{
2233
 
2234
    int         i;
2235
    char        line[201];
2236
    FILE       *adfile = NULL;
2237
    int         count;
2238
 
2239
    /*
2240
     * First the categories 
2241
     */
2242
    print( "\n\n" );
2243
    if ( report_html ) print_underline(TRUE);
2244
    print( "Category abbreviations" );
2245
    if ( report_html ) print_underline(FALSE);
2246
    print( "\n" );
2247
 
2248
 
2249
    for( i = 1, count = 0; i <= config.num_class; i++ )
2250
    {
2251
#if 0
2252
        /*
2253
        **  Skip any non-equestrian class in the legend
2254
        **  Don't want to tell the general user whats goes on, unless we actually
2255
        **  creating the non-equestrian report.
2256
        */
2257
        if ( class != config.nonequestrian_class  && i == config.nonequestrian_class )
2258
            continue;
2259
#endif
75 - 2260
        if ( report_html == html ) print( "<A HREF=\"%s\">",url_encode(p_filename(filebase, config.team_class[i - 1].abr ,"html")) );
1 root 2261
        print( "%-*s", 3, config.team_class[i - 1].abr );
75 - 2262
        if ( report_html == html ) print( "</A>" );
1 root 2263
        print( " : %-*s  ", LEN_CLASS_NAME, config.team_class[i - 1].full_name );
2264
 
2265
        if( !( ++count % 5 ) )
2266
            print( "\n" );
2267
    }
2268
 
2269
    /*
2270
    **  Add link to the finish order report
2271
    */
75 - 2272
    if ( report_html == html )
1 root 2273
    {
68 - 2274
        print( "<A HREF=\"%s\">", url_encode(p_filename(filebase, "finish" ,"html")) );
1 root 2275
        print( "%-*s", 3, "All" );
2276
        print( "</A>" );
2277
        print( " : %-*s  ", LEN_CLASS_NAME, "Finishing Order" );
2278
    }
2279
 
2280
    /*
2281
    **  Country data - if countries have been defined
2282
    */
2283
    if( config.num_countries )
2284
    {
2285
        print( "\n\n" );
2286
        if ( report_html ) print_underline(TRUE);
2287
        print( "Country abbreviations" );
2288
        if ( report_html ) print_underline(FALSE);
2289
        print( "\n" );
2290
 
2291
        for( i = 0, count = 0; i < MAX_COUNTRY; i++ )
2292
        {
2293
            if( config.country_name[i].abr[0] )
2294
            {
2295
                print( "%-*s : %-*s  ", 4, config.country_name[i].abr,
2296
                       LEN_CNTRY_NAME, config.country_name[i].full_name );
2297
                if( !( ++count % 5 ) )
2298
                    print( "\n" );
2299
            }
2300
        }
2301
    }
18 david 2302
    print( "\n" );
1 root 2303
 
2304
    /*
2305
     * Other comments 
2306
     */
18 david 2307
    if ( full )
2308
    {
2309
        print( "\nPlace numbers (LP and EP)\n" );
2310
        print( "LP - Placing based on elapsed time within the leg.                Cat Plce - Placing within the category.\n" );
2311
        print( "EP - Placing based on accumulated times to the end of that leg.   Fin Plce - Overall placing within the event.\n" );
61 - 2312
        print( "U  - Placing not available.\n" );
18 david 2313
    }
1 root 2314
 
2315
    /*
2316
     *  Insert the contents of the config.addendum file
2317
     *  or a defualt message
2318
     */
2319
    if( config.addendum[0] )
2320
        adfile = fopen( config.addendum, "rt" );  /* Open the file for reading */
2321
 
2322
    if( adfile )
2323
    {
2324
        while( fgets( line, sizeof(line)-1, adfile ) )
2325
            print( "%s", line );
2326
    }
2327
    else
2328
    {
2329
        print( "\nTiming and Results by\n" );
2330
        print( "Embedded Solutions\n" );
2331
    }
2332
}
2333
 
2334
/*========================================================================
2335
 *
2336
 *  Return place data
2337
 *
2338
 *  Purpose:
2339
 *      This function is called to return place data
2340
 *
2341
 *      This routine is called to fill a print team_buffer - to allow for
2342
 *      multiple calls to this function ( before the data is used ) a number
2343
 *      of static team_buffers are maintained
2344
 *
2345
 *  Parameters:
2346
 *      num         place - if not bad_times
2347
 *      disq        Disqualified flag
2348
 *      time        Time data is based on
2349
 *
2350
 *  Returns:
2351
 *      This function returns a pointer to the character string for the
2352
 *      number or a pointer to a bad_times string.
2353
 *
2354
 *========================================================================*/
2355
 
2356
char       *pi_place( int num, int disq, time_t time )
2357
{
2358
    static char store[2][5];                     /* 2 stores for 4 digit numbers */
2359
    static int  i = 0;                           /* Current index into store */
2360
    static char *dis = "D";                      /* Disqualified */
2361
    static char *non = "-";                      /* Invalid time */
2362
 
2363
    if( disq )                                   /* Disqualified team */
2364
        return ( dis );
2365
    if( time <= 0 )                              /* Unknown time */
2366
        return ( non );
2367
 
2368
    i++;
2369
    if( i >= 2 )
2370
        i = 0;                                   /* Select next entry */
2371
    sprintf( store[i], "%4d", num );
2372
    return ( store[i] );
2373
 
2374
}
2375
 
2376
/*========================================================================
2377
 *
2378
 *  Return place data
2379
 *
2380
 *  Purpose:
2381
 *      This function is called to Return place data
2382
 *
2383
 *      This routine is called to fill a print team_buffer - to allow for
2384
 *      multiple calls to this function ( before the data is used ) a number
2385
 *      of static team_buffers are maintained
2386
 *
2387
 *  Parameters:
2388
 *      num         place - if not bad_times
2389
 *      disq        Disqualified flag
2390
 *
2391
 *  Returns:
2392
 *      This function returns a pointer to the character string for the
2393
 *      number or a pointer to a bad_times string.
2394
 *
2395
 *========================================================================*/
2396
 
2397
char *pr_place( int num, int disq )
2398
{
2399
    static char store[2][5];                     /* 2 stores for 4 digit numbers */
2400
    static int  i = 0;                           /* Current index into store */
2401
    static char *dis = "U";
2402
 
2403
    if( disq )
2404
        return ( dis );
2405
 
2406
    i++;
2407
    if( i >= 2 )
2408
        i = 0;                                   /* Select next entry */
2409
    sprintf( store[i], "%4d", num );
2410
    return ( store[i] );
2411
 
2412
}
2413
 
2414
/*========================================================================
2415
 *
61 - 2416
 *  Return place data
2417
 *
2418
 *  Purpose:
2419
 *      This function is called to Return place data
2420
 *
2421
 *      This routine is called to fill a print team_buffer - to allow for
2422
 *      multiple calls to this function ( before the data is used ) a number
2423
 *      of static team_buffers are maintained
2424
 *
2425
 *  Parameters:
2426
 *      num         place - if not bad_times
2427
 *      disq        Disqualified flag
2428
 *      ne          Non Equestrian Flag
2429
 *
2430
 *  Returns:
2431
 *      This function returns a pointer to the character string for the
2432
 *      number or a pointer to a bad_times string.
2433
 *
2434
 *========================================================================*/
2435
 
2436
char *pr_place_ne( int num, int disq, int ne )
2437
{
2438
    static char store[2][5];                     /* 2 stores for 4 digit numbers */
2439
    static int  i = 0;                           /* Current index into store */
2440
    static char *dis = "U";
2441
 
2442
    if( disq && ! ne )
2443
         return ( dis );
2444
 
2445
    if( ++i >= 2 )
2446
        i = 0;                                   /* Select next entry */
2447
    sprintf( store[i], "%4d", num );
2448
    return ( store[i] );
2449
 
2450
}
2451
 
2452
/*========================================================================
2453
 *
1 root 2454
 *  Check data for bad times
2455
 *
2456
 *  Purpose:
2457
 *      This function is called to Check data for bad times
2458
 *      Scan the sort data structure and locate entries that have incorrect
2459
 *      times.
2460
 *      
2461
 *      Entries that have invalid leg times are displayed to the operator
2462
 *      and the report process can be aborted
2463
 *
2464
 *  Parameters:
2465
 *      leg         Leg to test
2466
 *      mode            Either end or elapsed times to be tested
2467
 *
2468
 *  Returns:
2469
 *      Returns FALSE if the report operation is to be aborted
2470
 *
2471
 *========================================================================*/
2472
 
2473
bool ck_data( int leg, int mode )
2474
{
2475
    ty_s_data  *ptr;
2476
    unsigned    i;
2477
    int         bad = 0;
2478
    int         j = 0;
2479
    int         k, bad_leg;
2480
    time_t     *t;                               /* An array of times */
2481
 
29 - 2482
 
2483
 
1 root 2484
    ptr = sort_data;
2485
    for( i = 1; i <= sort_num; i++, ptr++ )
2486
    {
2487
        bad_leg = 0;
2488
        if( mode == C_DISQUAL )
2489
        {
2490
            ptr->flags.bad_times = ptr->flags.disqualified;
2491
            continue;
2492
        }
2493
 
2494
        if( mode == C_ELAPSED )
2495
            t = ptr->lege;
2496
        else
2497
            t = ptr->leg;
2498
 
61 - 2499
 
2500
        if ( leg >= 0 )
1 root 2501
        {
61 - 2502
            ptr->flags.bad_times = (ptr->flags.disqualified && ! ptr->flags.non_equestrian);
2503
        }
2504
        else
2505
        {
2506
            ptr->flags.bad_times = ptr->flags.disqualified;
2507
        }
2508
 
2509
        if( ! ptr->flags.bad_times )
2510
        {
1 root 2511
            if( leg <= 0 )
2512
            {
2513
                for( k = 0; k <= config.num_legs; k++ )
2514
                {
2515
                    if ( !(config.equestrian_leg && ptr->flags.non_equestrian && config.equestrian_leg == k  ))
2516
                        bad_leg |= ( t[k] <= 0 );
2517
                }
2518
            }
2519
            else
2520
            {
2521
                bad_leg = t[leg] <= 0;
2522
            }
2523
 
2524
            if( bad_leg )
2525
            {
2526
                ptr->flags.bad_times = TRUE;
29 - 2527
 
2528
                if ( ! report_all )
1 root 2529
                {
29 - 2530
                    if( !bad )
2531
                        printf( "Team with incorrect time information\n" );
2532
                    if( ++j > 15 )
2533
                    {
2534
                        printf( "\n" );
2535
                        j = 0;
2536
                    }
2537
                    printf( "%4d ", ptr->team );
2538
                    bad++;
1 root 2539
                }
2540
            }
2541
        }
2542
    }
2543
 
2544
    if( bad )
2545
    {
2546
        printf( "\n%d teams with incorrect times.\n", bad );
2547
        return ( !getyes
2548
                 ( "These have been flagged as unplaced - continue report" ) );
2549
    }
2550
    return ( FALSE );
2551
}
2552
 
2553
/*========================================================================
2554
 *
2555
 *  Update placing information
2556
 *
2557
 *  Purpose:
2558
 *      This function is called to Update placing information
2559
 *
2560
 *      This routine will rip through the data generating the team placing in
2561
 *      a) Within a leg
2562
 *      b) At the end of a leg
2563
 *      c) Within a leg by  class
2564
 *      d) At the end of a leg by class
2565
 *
2566
 *      This function is provided to allow the display routines to
2567
 *      be accessed and updated without the need to run a report
2568
 *
2569
 *  Parameters:
2570
 *      xxxx        a ptr to the xxxx stuff
2571
 *
2572
 *  Returns:
2573
 *      Nothing
2574
 *
2575
 *========================================================================*/
2576
 
2577
void srt_place(void)
2578
{
2579
    int         i, j;
2580
 
2581
    cur( 0, 5 );
2582
    printf( "Update the team placings to the data base\n" );
2583
    flush_out();
2584
    if( ck_data( -1, C_ELAPSED ) )
2585
        return;
2586
    do_big_sort();
2587
 
2588
    /*
2589
     * Generate the stats and display them on the screen for interest
2590
     * This operation will not hurt - so why not
2591
     */
2592
 
2593
    gen_stats();
2594
    printf( "\nEvent statistics\n\n" );
2595
    printf( "%-*s   %-13s ", LEN_CLASS_NAME, "", "Overall" );
2596
    for( i = 1; i <= config.num_legs; i++ )
2597
        printf( "%-13s ", config.leg_name[i - 1] );
2598
 
2599
    for( j = 0; j <= config.num_class; j++ )
2600
    {
2601
        printf( "\n%-*s : ", LEN_CLASS_NAME,
2602
                j ? config.team_class[j - 1].full_name : "Overall" );
2603
        for( i = 0; i <= config.num_legs; i++ )
2604
        {
2605
            printf( "%4d ", stats.fast.team[i][j] );
2606
            printf( "%s ", time_a( stats.fast.time[i][j] ) );
2607
        }
2608
        printf( "\n%*s : ", LEN_CLASS_NAME, "Average" );
2609
        for( i = 0; i <= config.num_legs; i++ )
2610
        {
2611
            printf( "     %s ", time_a( stats.average[i][j] ) );
2612
        }
2613
    }
2614
    printf( "\nAny key to continue" );
2615
    ( void ) getinp();
2616
}
2617
 
2618
/*========================================================================
2619
 *
2620
 *  Calculate summary information
2621
 *
2622
 *  Purpose:
2623
 *      This function is called to calculate summary information
2624
 *
2625
 *  Parameters:
2626
 *      ptr         - Address of a summary structure to fill in
2627
 *
2628
 *  Returns:
2629
 *      Nothing
2630
 *
2631
 *========================================================================*/
2632
 
2633
void calc_class_summary( t_class_summary * ptr )
2634
{
2635
    int i;
2636
 
2637
    /*
2638
    **  Reset the data
2639
    */
2640
    memset ( ptr, 0, sizeof (*ptr ));
2641
 
2642
    /*
2643
     * Extract the required data from the data base
2644
     * Only save that information required for the operation
2645
     */
2646
 
2647
    for( i = config.min_team; i <= config.max_team; i++ )
2648
    {
2649
        if( valid_field( i ) && g_record( i, &team_buf ) )
2650
        {
2651
            ptr->total.total++;
2652
            ptr->class[team_buf.class].total++;
2653
 
2654
            if ( team_buf.flags.disqualified )
2655
            {
2656
                ptr->class[team_buf.class].disqualified++;
2657
                ptr->total.disqualified++;
2658
            }
2659
 
2660
            if ( config.nonequestrian_class && team_buf.flags.non_equestrian )
2661
            {
2662
                ptr->class[team_buf.class].non_equestrian++;
2663
                ptr->total.non_equestrian++;
2664
            }
2665
        }
2666
    }
13 david 2667
 
2668
    /*
2669
    **  Fix up the totals for the non equestrians
2670
    **  This is not a real category but a summary of the others.
2671
    */
2672
    if ( config.nonequestrian_class  )
2673
    {
2674
        ptr->class[config.nonequestrian_class].total += ptr->total.non_equestrian;
2675
    }
1 root 2676
}
2677
 
2678
/*========================================================================
2679
 *
2680
 *  Display summary information
2681
 *
2682
 *  Purpose:
2683
 *      This function is called to display summary information
2684
 *
2685
 *  Parameters:
2686
 *      None
2687
 *
2688
 *  Returns:
2689
 *      Nothing
2690
 *
2691
 *========================================================================*/
2692
 
2693
void display_summary (void)
2694
{
2695
 
2696
    t_class_summary data;
2697
    int         i;
2698
    int         line = 2;
2699
 
2700
    cur( 0, line );
2701
    printf( "Generating Summary Information" );
2702
    calc_class_summary( & data );
2703
 
2704
 
2705
    /*
2706
    **  Display summary stats
2707
    */
2708
 
2709
    cur( 0, line );
2710
    console_clreol();
2711
    printf( "Summary Information\n\n" );
2712
    printf( "%*s : %-7s %-7s%-7s\n", LEN_CLASS_NAME,
2713
                                      "Category",
2714
                                      "Total",
2715
                                      "Disq",
2716
                                      "NonEq" );
2717
 
2718
    for( i = 0; i < config.num_class; i++ )
2719
    {
2720
        /*
2721
        **  The non-equestrian leg does not have any data
2722
        **  Supress the display
2723
        */
2724
        if ( config.nonequestrian_class == i+1  )
2725
            continue;
2726
 
2727
        printf( "%*s : %-7d %-7d %-7d\n", LEN_CLASS_NAME,
2728
                                          config.team_class[i].full_name,
2729
                                          data.class[i+1].total,
2730
                                          data.class[i+1].disqualified,
2731
                                          data.class[i+1].non_equestrian );
2732
    }
2733
 
2734
    printf( "\n" );
2735
    printf( "%*s : %-7d %-7d %-7d\n", LEN_CLASS_NAME,
2736
                                      "Totals",
2737
                                      data.total.total,
2738
                                      data.total.disqualified,
2739
                                      data.total.non_equestrian );
2740
 
2741
    printf( "\nAny key to continue " );
2742
    getinp();
2743
}
2744
 
13 david 2745
/*========================================================================
2746
 *
2747
 *  Print summary information
2748
 *
2749
 *  Purpose:
2750
 *      This function is called to print summary information
2751
 *
2752
 *  Parameters:
2753
 *      None
2754
 *
2755
 *  Returns:
2756
 *      Nothing
2757
 *
2758
 *========================================================================*/
1 root 2759
 
13 david 2760
void pri_summary (void)
2761
{
2762
 
2763
    t_class_summary data;
2764
    int         i;
2765
    int         line = 2;
2766
 
2767
 
2768
    if( !open_printer( "", "summary", 132, 0, "Summary Information" ) )
2769
        return;
2770
 
2771
    cur( 0, line );
2772
    printf( "Generating Summary Information" );
2773
    calc_class_summary( & data );
2774
 
2775
 
2776
    /*
2777
    **  Display summary stats
2778
    */
2779
 
2780
    print( "%*s : %-7s %-7s%-7s\n", LEN_CLASS_NAME,
2781
                                      "Category",
2782
                                      "Total",
2783
                                      "Disq",
2784
                                      "NonEq" );
2785
 
2786
    for( i = 0; i < config.num_class; i++ )
2787
    {
2788
        /*
2789
        **  The non-equestrian leg does not have any data
2790
        **  Supress the display
2791
        */
2792
        if ( config.nonequestrian_class == i+1  )
2793
            continue;
2794
 
2795
        print( "%*s : %-7d %-7d %-7d\n", LEN_CLASS_NAME,
2796
                                          config.team_class[i].full_name,
2797
                                          data.class[i+1].total,
2798
                                          data.class[i+1].disqualified,
2799
                                          data.class[i+1].non_equestrian );
2800
    }
2801
 
2802
    print( "\n" );
2803
    print( "%*s : %-7d %-7d %-7d\n", LEN_CLASS_NAME,
2804
                                      "Totals",
2805
                                      data.total.total,
2806
                                      data.total.disqualified,
2807
                                      data.total.non_equestrian );
2808
 
2809
    close_printer();
29 - 2810
    if ( !report_all )
2811
    {
2812
        printf( "\nAny key to continue " );
2813
        getinp();
2814
    }
13 david 2815
}
2816
 
2817
 
2818
 
1 root 2819
/*========================================================================
2820
 *
2821
 *  Main sort routine for final data
2822
 *
2823
 *  Purpose:
2824
 *      This function is called to do the report sort routine for final data
2825
 *      This routine will fill all the gaps in the sort_aux structure
2826
 *
2827
 *  Parameters:
2828
 *      None
2829
 *
2830
 *  Returns:
2831
 *      Nothing
2832
 *
2833
 *========================================================================*/
2834
 
2835
void do_big_sort(void)
2836
{
2837
    int         i, k;                            /* Looooopy things */
2838
    unsigned    j;
2839
    ty_s_data  *ptr;                             /* Pointer to sort data */
2840
    int         class;                           /* Current class */
2841
 
2842
    printf( "Sorting it ALL out" );
2843
    flush_out();
2844
 
2845
    for( i = 0; i <= config.num_legs; i++ )
2846
    {
2847
        /*
2848
        **  Sort on leg elapsed time
61 - 2849
        **  Then save the teams elapsed place in each leg
1 root 2850
        */
2851
        sort_team_data( i, S_L );
61 - 2852
        for( j = 1, k = 1, ptr = sort_data; j <= sort_num; ptr++, j++ )
1 root 2853
        {
61 - 2854
            if ( ptr->class == config.nonequestrian_class )
2855
                continue;
2856
 
2857
            sort_aux[ptr->team].l_place[i] = k++;
1 root 2858
            sort_aux[ptr->team].team = ptr->team;
2859
        }
2860
 
2861
        /*
2862
        **  Sort on leg end time
2863
        **  Then save the teams place at the end of each leg
2864
        */
2865
        sort_team_data( i, S_LE );
61 - 2866
        for( j = 1, k = 1, ptr = sort_data; j <= sort_num; ptr++, j++ )
2867
        {
2868
            if ( ptr->class == config.nonequestrian_class )
2869
                continue;
2870
 
2871
            sort_aux[ptr->team].le_place[i] = k++;
2872
        }
1 root 2873
 
2874
        /*
2875
        **  Sort on elapsed time per class
2876
        **  The save the teams elapsed place in each leg per class
2877
        */
2878
        sort_team_data( i, S_LC );
2879
        class = -1;
2880
        for( k = 1, j = 1, ptr = sort_data; j <= sort_num; j++, ptr++ )
2881
        {
2882
            if( class != ptr->class )
2883
            {
2884
                k = 1;
2885
                class = ptr->class;
2886
            }
2887
            sort_aux[ptr->team].lc_place[i] = k++;
2888
        }
2889
 
2890
        /*
2891
        **  Sort on end time per class
2892
        **  Then save the teams place at the end of each leg per class
2893
        */
2894
        sort_team_data( i, S_LEC );
2895
        class = -1;
2896
        for( k = 1, j = 1, ptr = sort_data; j <= sort_num; j++, ptr++ )
2897
        {
2898
            if( class != ptr->class )
2899
            {
2900
                k = 1;
2901
                class = ptr->class;
2902
            }
2903
            sort_aux[ptr->team].lec_place[i] = k++;
2904
        }
2905
    }
2906
 
2907
    /*
2908
    **  Write the place information back to disk for use in the displays
2909
    */
2910
    printf( "\nWriting it all back to the disk file" );
2911
    flush_out();
2912
 
2913
    for( i = config.min_team; i <= config.max_team; i++ )
2914
    {
2915
        if( sort_aux[i].team && valid_field( i ) && g_record( i, &team_buf ) )
2916
        {
2917
            for( k = 0; k <= config.num_legs; k++ )
2918
            {
2919
                team_buf.leg[k].l_place = sort_aux[i].l_place[k];
2920
                team_buf.leg[k].le_place = sort_aux[i].le_place[k];
2921
                team_buf.leg[k].lc_place = sort_aux[i].lc_place[k];
2922
                team_buf.leg[k].lec_place = sort_aux[i].lec_place[k];
2923
            }
2924
            put_team_record( i, &team_buf );
2925
        }
2926
    }
2927
}
2928
 
2929
/*========================================================================
2930
 *
2931
 *  Sort in memory buffer
2932
 *
2933
 *  Purpose:
2934
 *      This function is called to Sort in memory buffer
2935
 *
2936
 *  Parameters:
2937
 *      leg         Requested leg
2938
 *      mode        Defines the sort mode
2939
 *
2940
 *  Returns:
2941
 *      Nothing
2942
 *
2943
 *========================================================================*/
2944
 
2945
void sort_team_data( int leg, int mode )
2946
{
2947
 
2948
    unsigned    j;
2949
    ty_s_data  *ptr;
2950
 
2951
    sort_leg = leg;                              /* Leg is global for the comparison function */
2952
    sort_mode = mode;                            /* Mode is global for compare function */
2953
 
2954
    qsort( ( char * ) sort_data, sort_num, sizeof( ty_s_data ), sort_comp );
2955
 
2956
    /*
2957
     * Insert "place data" into the sorted data
2958
     * This simply the index into the array of data - after its been
2959
     * sorted.
2960
     */
2961
    ptr = sort_data;
2962
    for( j = 1; j <= sort_num; j++, ptr++ )
2963
        ptr->place = j;
2964
 
2965
}
2966
 
2967
/*========================================================================
2968
 *
2969
 *  qsort comparison function
2970
 *
2971
 *  Purpose:
2972
 *      This function is called by qsort as a Sort comparison function
2973
 *
2974
 *  Parameters:
2975
 *      a       - 1st record
2976
 *      b       - 2nd record
2977
 *
2978
 *  Returns:
2979
 *      value to qsort
2980
 *
2981
 *========================================================================*/
2982
 
2983
int sort_comp( const void * aa, const void * bb )
2984
{
2985
    const ty_s_data * a = aa;
2986
    const ty_s_data * b = bb;
2987
 
2988
 
2989
    int         i;                               /* One of those */
2990
    time_t      ta, tb;                          /* Leg times */
2991
    int         na, nb;                          /* Number of valid legs */
2992
    time_t      tta, ttb;                        /* Temp times */
2993
 
2994
    /*
2995
    **  Sorting on Team Number
2996
    */
2997
    if( sort_mode == S_TEAM )
2998
        return ( a->team - b->team );
2999
 
3000
    /*
3001
    **  Sorting on Class and Team Number
3002
    */
3003
    if( sort_mode == S_CLASS )
3004
    {
3005
        if( a->class != b->class )
3006
            return ( a->class - b->class );
3007
        else
3008
            return ( a->team - b->team );
3009
    }
3010
 
3011
    /*
3012
    **  Sorting within a class
3013
    **  First sort on the class
3014
    */
3015
    if( sort_mode == S_LEC || sort_mode == S_LC )   /* Sort within a class */
3016
        if( a->class != b->class )
3017
            return ( a->class - b->class );
3018
 
61 - 3019
#if 1
1 root 3020
    /*
61 - 3021
    **  Always put the nonequestrian_class at the end
3022
    **  Simplifies the creation of ordered lists as these
3023
    **  Entries are not present in the main body
3024
    */
3025
    if ( a->class == config.nonequestrian_class ||  b->class == config.nonequestrian_class )
3026
    {
3027
        if ( a->class == config.nonequestrian_class &&  b->class == config.nonequestrian_class )
3028
        {
3029
        }
3030
        else
3031
        {
3032
            return ( a->class == config.nonequestrian_class ? 1 : -1 );
3033
        }
3034
 
3035
    }
3036
#endif
3037
 
3038
    /*
1 root 3039
    **  Now we need to examine the times as we have sorted
3040
    **  on every thing else.
3041
    **
3042
    **  If one of the teams has bad_times, then that team is placed
3043
    **  lower in the sorting order. If both teams have bad times
3044
    **  then sort on team number. ie: Unplaced teams are sorted on
3045
    **  team number
61 - 3046
    **
3047
    **  If not sorting within a class (ie Overall), then Non_Equestrian
3048
    **  is better than a bad time. Places NE before disqualified
3049
    **
3050
    **
3051
    **  Note: NE also have bad_times set
1 root 3052
    */
61 - 3053
#if 1
1 root 3054
    if( a->flags.bad_times || b->flags.bad_times )  /* Valid data has precedence */
3055
    {
3056
        if( a->flags.bad_times && b->flags.bad_times )
61 - 3057
        {
3058
            if( a->flags.non_equestrian || b->flags.non_equestrian )
3059
            {
3060
                if( a->flags.non_equestrian && b->flags.non_equestrian )
3061
                {
3062
                    /*
3063
                    **  Both are non equestrian
3064
                    **  Let the time sort operate ...
3065
                    */
3066
                    //return ( a->team - b->team );
3067
                }
3068
                else
3069
                {
3070
                    /* One is equestrian */
3071
                    /* Good times better than NE */
3072
                    return ( a->flags.non_equestrian ? -1 : 1 );
3073
                }
3074
            }
3075
            else
3076
            {
3077
                /* Neither is equestrian */
3078
                return ( a->team - b->team );
3079
            }
3080
        }
3081
        else
3082
            return ( a->flags.bad_times ? 1 : -1 );
3083
    }
3084
#else
3085
    if( a->flags.bad_times || b->flags.bad_times )  /* Valid data has precedence */
3086
    {
3087
        if( a->flags.bad_times && b->flags.bad_times )
1 root 3088
            return ( a->team - b->team );
3089
        else
3090
            return ( a->flags.bad_times ? 1 : -1 );
3091
    }
3092
 
3093
    /*
3094
    **  Not sorting within a class ie: Overall
3095
    **  Non-Equestrian is at the end, so that it doesn't get counted in the
3096
    **  finishing order
3097
    */
3098
    if( sort_mode == S_LE || sort_mode == S_L )     /* Sort NOT within a class */
3099
    {
3100
        if( a->flags.non_equestrian || b->flags.non_equestrian )
3101
        {
3102
            if( a->flags.non_equestrian && b->flags.non_equestrian )
3103
                return ( a->team - b->team );
3104
            else
3105
                return ( a->flags.non_equestrian ? 1 : -1 );
3106
        }
3107
    }
61 - 3108
#endif
1 root 3109
 
3110
    /*
3111
    **  Before we sort on times we must determine which time to
3112
    **  use. Finish time, Leg end times, Leg Elapsed times.
3113
    */
3114
 
3115
    switch ( sort_mode )
3116
    {
3117
      /*
3118
      **    Sort on finish times
3119
      */
3120
      case S_FIN:
3121
        ta = a->leg[sort_leg];
3122
        tb = b->leg[sort_leg];
3123
        break;
3124
 
3125
 
3126
      /*
3127
      **    Sort on accumulated leg times
3128
      */
3129
      case S_LE:
3130
      case S_LEC:
3131
        if( sort_leg )
3132
        {
3133
            /*
3134
            **  Calculate accumulated time up to the desired leg
3135
            **  If the two teams have a different number of valid
3136
            **  leg times then order by the team that has completed
3137
            **  more legs.
3138
            */
3139
            ta = tb = ( time_t ) 0;
3140
            na = nb = 0;
3141
            for( i = 1; i <= sort_leg; i++ )
3142
            {
3143
                tta = a->lege[i];
3144
                ttb = b->lege[i];
3145
                if( tta > 0 )
3146
                {
3147
                    na++;
3148
                    ta += tta;
3149
                }
3150
                if( ttb > 0 )
3151
                {
3152
                    nb++;
3153
                    tb += ttb;
3154
                }
3155
            }
3156
            if( na != nb )
3157
                return ( nb - na );
3158
        }
3159
        else
3160
        {
3161
            ta = a->leg[sort_leg] - a->start;
3162
            tb = b->leg[sort_leg] - b->start;
3163
        }
3164
        break;
3165
 
3166
      /*
3167
      **    Sort on Elapsed times
3168
      */
3169
      case S_LC:
3170
      case S_L:
3171
        ta = a->lege[sort_leg];
3172
        tb = b->lege[sort_leg];
3173
        break;
3174
 
3175
      /*
3176
      **    Just to be sure ...
3177
      */
3178
      default:
3179
        return ( 0 );
3180
    }
3181
 
3182
    /*
3183
    **  Finally. Compare the required team times
3184
    */
3185
    if( ta == tb )
3186
        return ( a->team - b->team );
3187
    if( ( ta > 0 ) && ( tb > 0 ) )
3188
        return ( ( int ) ( ta - tb ) );
3189
    return ( ( ta > 0 ) ? -1 : 1 );
3190
}
3191
 
3192
/*========================================================================
3193
 *
18 david 3194
 *  qsort comparison function - competitor names
3195
 *
3196
 *  Purpose:
3197
 *      This function is called by qsort as a Sort comparison function
3198
 *
3199
 *  Parameters:
3200
 *      a       - 1st record
3201
 *      b       - 2nd record
3202
 *
3203
 *  Returns:
3204
 *      value to qsort
3205
 *
3206
 *========================================================================*/
3207
 
3208
int sort_comp_cname( const void * aa, const void * bb )
3209
{
25 - 3210
    ty_s_namedata * a = (ty_s_namedata *)aa;
3211
    ty_s_namedata * b = (ty_s_namedata *)bb;
18 david 3212
 
3213
 
3214
    int         i;                               /* One of those */
3215
 
3216
    /*
3217
    **  Sort by name
3218
    */
3219
    i = strcmp ( a->name, b->name );
3220
    if ( i )
3221
        return ( i );
3222
    a->multi=1;
3223
    b->multi=1;
3224
 
3225
    /*
3226
    **  Sort by Leg
3227
    */
3228
    i = a->leg - b->leg;
3229
    if ( i )
3230
        return ( i );
3231
 
3232
    /*
3233
    **  Sorting on Team Number
3234
    */
3235
    return ( a->team - b->team );
3236
 
3237
}
3238
 
3239
/*========================================================================
3240
 *
1 root 3241
 *  load report data into memory
3242
 *
3243
 *  Purpose:
3244
 *      This routine will pull all the data into memory 
3245
 *      Not all the team data is loaded. Only that essential for the
3246
 *      operation of the sort routine is loaded
3247
 *
3248
 *  Parameters:
3249
 *      None
3250
 *
3251
 *  Returns:
3252
 *      TRUE - All is well
3253
 *
3254
 *========================================================================*/
3255
 
3256
bool load_report_data(void)
3257
{
3258
 
3259
    ty_s_data  *ptr;                             /* pointer to sort data type */
61 - 3260
    ty_s_data  *last;
1 root 3261
    int         j;
3262
    unsigned    num;
3263
 
3264
    printf( "Loading team information - This will not hurt" );
3265
    flush_out();
3266
 
3267
    /*
3268
     * Fetch memory for the data store
3269
     */
3270
 
3271
    if( sort_data )
3272
        free( ( char * ) sort_data );
3273
    sort_data = 0;
3274
 
3275
    if( sort_aux )
3276
        free( ( char * ) sort_aux );
3277
    sort_aux = 0;
3278
    sort_num = 0;                                /* Counter of records in the array */
3279
 
3280
    /*
3281
    **  Allocate memory for the data structures
3282
    **  This will be free'd
3283
    */
3284
    num = config.max_team - config.min_team + 1 ;
3285
 
3286
    /*
3287
    **  Allow for non-equestrian teams - since some of the data is loaded twice
3288
    **  Take a guess that at most 1/2 the teams will be non-equestrian
3289
    */
3290
    num = num * 3 / 2;
3291
 
3292
    sort_data = ( ty_s_data * ) calloc ( num , sizeof( ty_s_data ) );
3293
    sort_aux = ( ty_s_aux * ) calloc( num + 1, sizeof( ty_s_aux ) );
3294
 
3295
    if( sort_data == 0 || sort_aux == 0 )
3296
    {
3297
        printf( "\n\nError in allocating memory\n" );
3298
        sleep( 5 );
3299
        return ( FALSE );
3300
    }
3301
 
3302
    /*
3303
    **  Load data into the memory based data structure
3304
    **  Only load data for valid-teams
3305
    **  Load essential data
3306
    **      Team Number, class and flags
3307
    **      Leg end and elapsed times
3308
    */
3309
    ptr = sort_data;
3310
    for( team = config.min_team; team <= config.max_team; team++ )
3311
    {
3312
        if( valid_field( team ) )
3313
        {
3314
            g_record( team, &team_buf );
3315
            if( team_buf.flags.valid )
3316
            {
61 - 3317
                last = ptr;
1 root 3318
                ptr->team = team;
3319
                for( j = 0; j < MAX_LEGS + 1; j++ )
3320
                {
3321
                    ptr->lege[j] = team_buf.leg[j].elapsed;
3322
                    ptr->leg[j] = team_buf.leg[j].end;
3323
                }
3324
                ptr->start = team_buf.leg[0].start;
3325
                ptr->class = team_buf.class;
3326
 
3327
                ptr->flags = team_buf.flags;
3328
                ptr++;
3329
                sort_num++;
3330
 
3331
                /*
3332
                **  If non-equestrian support is enabled then
3333
                **  duplicate and modify data for the non-equestrian teams
3334
                **      - Change the class
3335
                **      - Modify the leg time
3336
                */
61 - 3337
#if 1
1 root 3338
                if ( config.nonequestrian_class && team_buf.flags.non_equestrian )
3339
                {
3340
                    ptr->team = team;
3341
                    ptr->lege[0] = 0;
3342
 
3343
                    for( j = 0; j < MAX_LEGS + 1; j++ )
3344
                    {
3345
                        if ( j == config.equestrian_leg )
3346
                        {
61 - 3347
                            last->lege[j] = ptr->lege[j] = 0;
1 root 3348
                            if ( config.equestrian_leg > 1 )
61 - 3349
                                last->leg[j] = ptr->leg[j] = ptr->leg[j-1];
1 root 3350
                        }
3351
                        else
3352
                        {
3353
                            if ( j )
61 - 3354
                                last-> lege[j] = ptr->lege[j] = team_buf.leg[j].elapsed;
3355
                            last->leg[j] = ptr->leg[j] = team_buf.leg[j].end;
1 root 3356
                            ptr->lege[0] += ptr->lege[j] ;
61 - 3357
                            last->lege[0] = ptr->lege[0] ;
1 root 3358
                        }
3359
                    }
3360
 
61 - 3361
                    last->start = ptr->start = team_buf.leg[0].start;
1 root 3362
                    ptr->class = config.nonequestrian_class;
3363
                    ptr->flags = team_buf.flags;
3364
                    ptr->flags.disqualified = 0;
61 - 3365
 
3366
 
1 root 3367
                    ptr++;
3368
                    sort_num++;
3369
                }
61 - 3370
#endif
1 root 3371
            }
3372
        }
3373
    }
3374
    return ( TRUE );
3375
}
3376
 
3377
/*========================================================================
3378
 *
3379
 *  Generate all the stats
3380
 *
3381
 *  Purpose:
3382
 *      This function is called to Generate all the stats
3383
 *
3384
 *  Parameters:
3385
 *      None
3386
 *
3387
 *  Returns:
3388
 *      Nothing
3389
 *
3390
 *========================================================================*/
3391
 
3392
void gen_stats(void)
3393
{
3394
    ty_s_data  *ptr;
3395
    unsigned    i;
3396
    int         j;
3397
    int         k;
3398
 
3399
    /*
3400
     * Init all the stats 
3401
     */
3402
    for( i = 0; i <= MAX_LEGS; i++ )
3403
    {
3404
        for( j = 0; j <= MAX_CLASS; j++ )
3405
        {
3406
            stats.team[i][j] = 0;
3407
            stats.fast.team[i][j] = 0;
3408
            stats.fast.time[i][j] = ( time_t ) - 1;
3409
            stats.average[i][j] = 0;
3410
        }
3411
    }
3412
 
3413
    for( i = 1, ptr = sort_data; i <= sort_num; i++, ptr++ )
3414
    {
3415
        /*
3416
        **  If there is any bad times in the team record, then none
3417
        **  of the data can be trusted.
3418
        **
3419
        **  If the team has been disqualified, then don't use any
3420
        **  of the data.
3421
        */
3422
        if( ptr->flags.bad_times || ptr->flags.disqualified )
3423
            continue;
3424
 
3425
        for( j = 0; j <= config.num_legs; j++ )
3426
        {
3427
            if( ptr->lege[j] <= 0 )              /* Ignore bad data */
3428
                continue;
3429
 
3430
            /*
3431
            **  Determine fastest team : overall
3432
            **  Ignore the non-equestrian data as this is in the list twice
3433
            */
3434
            if( ( ptr->lege[j] < stats.fast.time[j][0] )
3435
                || ( stats.fast.time[j][0] < 0 ) )
3436
            {
3437
                if ( ptr->class != config.nonequestrian_class )
3438
                {
3439
                    stats.fast.team[j][0] = ptr->team;
3440
                    stats.fast.time[j][0] = ptr->lege[j];
3441
                }
3442
            }
3443
 
3444
            /*
3445
            **  Determine fastest team : within a class
3446
            */
3447
            if( ( ptr->lege[j] < stats.fast.time[j][ptr->class] )
3448
                || stats.fast.time[j][ptr->class] < 0 )
3449
            {
3450
                stats.fast.team[j][ptr->class] = ptr->team;
3451
                stats.fast.time[j][ptr->class] = ptr->lege[j];
3452
            }
3453
 
3454
            /*
3455
            **  Sum the end times : overall
3456
            */
3457
            if ( ptr->class != config.nonequestrian_class )
3458
            {
3459
                stats.average[j][0] += ptr->lege[j];
3460
                stats.team[j][0]++;
3461
            }
3462
 
3463
 
3464
            /*
3465
            **  Sum the end times : within a class
3466
            */
3467
            stats.average[j][ptr->class] += ptr->lege[j];
3468
            stats.team[j][ptr->class]++;
3469
        }
3470
    }
3471
 
3472
    /*
3473
     * Calculate the averages
3474
     */
3475
    for( k = 0; k <= config.num_legs; k++ )
3476
    {
3477
        for( j = 0; j <= config.num_class; j++ )
3478
        {
3479
            if( stats.team[k][j] )
3480
                stats.average[k][j] /= stats.team[k][j];
3481
            else
3482
                stats.average[k][j] = ( time_t ) - 1;
3483
        }
3484
    }
3485
}
3486
 
3487
/********************************* EOF ***********************************/