Subversion Repositories svn1-original

Rev

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

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