Subversion Repositories svn1-original

Rev

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