Subversion Repositories svn1-original

Rev

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

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