Subversion Repositories svn1-original

Rev

Rev 246 | Rev 257 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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