Subversion Repositories svn1-original

Rev

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