Subversion Repositories svn1

Rev

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

Rev Author Line No. Line
91 - 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"
170 - 57
#include    "mainwindow.h"
91 - 58
 
59
void pri_awards_html(void);
254 - 60
void pri_summary_html(void);
91 - 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 */
227 - 103
#define S_LC_NE 8                                /* Elapsed times per class, with NE sorted by real class */
246 - 104
#define S_IFIN  9                                /* Sort on elapsed time at given leg */
91 - 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 */
195 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 */
91 - 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;
170 - 143
    team_type   team_buf;
91 - 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;
170 - 231
    team_type   team_buf;
91 - 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
    {
170 - 248
        MainWindow::showMessage("Error in allocating memory");
91 - 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;
195 david 363
 
91 - 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:
195 david 538
 *      leg             - Leg number to print
91 - 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
    /*
158 david 551
     * Sort the data in finishing order
91 - 552
     */
553
 
554
    if( ck_data( leg, C_ELAPSED ) )
555
        return;                                  /* Check data for this leg */
246 - 556
    sort_team_data( leg, S_IFIN );               /* Sort the data on elapsed time */
91 - 557
 
558
 
559
    /*
158 david 560
     * Now print the data on the printer
91 - 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
    /*
158 david 573
     * Print out the data
91 - 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
    /*
158 david 626
     * Insert the leg statistics
91 - 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
 
158 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
// *========================================================================*/
91 - 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
195 david 679
 *      information in a 20-character field
91 - 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;
170 - 766
    team_type   team_buf;
91 - 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 );
246 - 819
        print( "%4.4s ", pr_place( team_buf.leg[0].l_place, ptr->flags.bad_times || ptr->flags.non_equestrian ) );
91 - 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 ),
246 - 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 )
91 - 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 );
246 - 860
        print( "%-4.4s", pr_place( team_buf.leg[0].lc_place, ptr->flags.bad_times ) );
91 - 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
 
222 - 876
    sort_team_data( 0, S_LC );                 /* Generate class placement data */
91 - 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
    {
246 - 883
        int flags = 0;
884
 
91 - 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 );
246 - 917
        flags = ptr->flags.bad_times;
918
        if ( ptr->teamclass != config.nonequestrian_class )
919
        {
920
            flags |= ptr->flags.non_equestrian;
921
        }
91 - 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 );
246 - 938
        print( "%4.4s ", pr_place( team_buf.leg[0].lc_place, flags ) );
91 - 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 ),
246 - 956
                       pr_place( team_buf.leg[j].lc_place,  flags ),
957
                       pr_place( team_buf.leg[j].lec_place, flags ) );
91 - 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 );
246 - 970
        print( "%4.4s", pr_place( team_buf.leg[0].l_place, flags || (ptr->teamclass == config.nonequestrian_class)));
91 - 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
    {
987
        if ( class_done[j] )
988
        {
989
            continue;
990
        }
991
 
992
        report_title = tprintf( "Category results for : %-*s", LEN_CLASS_NAME, config.team_class[j - 1].full_name );
993
 
994
        if( !open_printer( "", config.team_class[j - 1].abr, 132, report_html, report_title ) )
995
            continue;
996
        print_class_header( j-1, TRUE );
997
        print( "\nThere were no competitors in this class\n" );
998
        print_legend(j,1);
999
        close_printer();
1000
    }
1001
 
1002
 
1003
    /*
1004
    **  If we are generating an HTML report then we need to create the file
1005
    **  that contains all the team names - the assumption is that this data
1006
    **  is available
1007
    */
272 david 1008
    if ( report_html == html )
91 - 1009
    {
1010
        pri_team();
1011
    }
1012
 
1013
    /*
1014
    **  Generate the awards report.
1015
    **  This is only available as an HTML report
1016
    */
272 david 1017
    if ( report_html == html )
91 - 1018
    {
1019
        pri_awards_html();
1020
    }
1021
 
1022
    /*
1023
    **  Generate the master index page
1024
    */
272 david 1025
    if ( report_html == html )
91 - 1026
    {
1027
        pri_master_index();
1028
    }
1029
 
1030
    pri_name_index_body();
1031
}
1032
 
1033
/*========================================================================
1034
 *
1035
 *  Place to text
1036
 *
1037
 *  Purpose:
1038
 *      This function is called to convert a place to text
1039
 *
1040
 *  Parameters:
1041
 *      place
1042
 *
1043
 *  Returns:
1044
 *      text
1045
 *
1046
 *========================================================================*/
1047
 
1048
char *placing ( int place )
1049
{
1050
    if ( place > MAX_PLACE )
1051
    {
1052
        return tprintf( "Place: %d", place);
1053
    }
1054
    return tprintf ("%s Place", place_text[place]);
1055
}
1056
 
1057
/*========================================================================
1058
 *
1059
 *  Print award results
1060
 *
1061
 *  Purpose:
1062
 *      This function is called to Print award results
1063
 *      Keep the page to 80 cols, so that it can be pronted on A4
1064
 *
1065
 *  Parameters:
1066
 *      None
1067
 *
1068
 *  Returns:
1069
 *      Nothing
1070
 *
1071
 *========================================================================*/
1072
void pri_awards_html(void)
1073
{
1074
    report_type saved = report_html;
1075
    /*
1076
    **  Generate ALL results with HTML tags
1077
    */
1078
    report_html = html;
1079
    pri_awards();
1080
    report_html = saved;
1081
}
1082
 
1083
/*========================================================================
1084
 *
1085
 *  Print award results
1086
 *
1087
 *  Purpose:
1088
 *      This function is called to Print award results
1089
 *      Keep the page to 80 cols, so that it can be pronted on A4
1090
 *
1091
 *  Parameters:
1092
 *      None
1093
 *
1094
 *  Returns:
1095
 *      Nothing
1096
 *
1097
 *========================================================================*/
1098
void pri_awards(void)
1099
{
1100
    int j;
1101
    int i;
1102
    int k;
1103
    int windex;
1104
    int winmax;
1105
    ty_s_data  *ptr;
170 - 1106
    team_type   team_buf;
91 - 1107
    int         last_class;
1108
    char    solid_line[100];
1109
 
1110
    /*
1111
    **  Calculate Summary information
1112
    **  Should cache the data
1113
    */
1114
    t_class_summary sdata;
1115
    calc_class_summary( & sdata );
1116
 
1117
 
1118
    if( !open_printer( "", "awards", 80, report_html, "Prizes and Awards" ) )
1119
        return;
1120
 
1121
    memset ( solid_line, 0, sizeof( solid_line ));
1122
    memset ( solid_line, '-', 80 );
1123
 
1124
    /*
1125
    **  Generate an index for this page
1126
    */
1127
    print( "\n");
1128
    if ( report_html == html )
1129
    {
1130
        print( "<hr>" );
1131
        print( "<A NAME=\"%s\"></A>",url_encode("INDEX"));
1132
    }
1133
    print( "Award Categories");
1134
 
1135
    for( j = 1; j <= config.num_class; j++ )
1136
    {
1137
        /*
1138
        **  Header for the class
1139
        */
1140
        if ( config.class_winners[j-1] <= 0 )
1141
            continue;
1142
 
1143
        winmax = config.class_winners[j-1];
1144
        {
227 - 1145
            int valid =   sdata.teamclass[j].valid;
91 - 1146
            if ( valid < winmax )
1147
                winmax = valid;
1148
        }
1149
 
1150
        print( "\n");
1151
        print( "    ");
1152
        if ( report_html == html ) print( "<A HREF=\"#%s\">",url_encode(config.team_class[j-1].full_name));
1153
        print( "%s",  tprintf( "%-*s", LEN_CLASS_NAME ,config.team_class[j-1].full_name ));
1154
        if ( report_html == html ) print( "</A>" );
1155
        print( "  %3d Awards", winmax );
1156
        if ( config.class_winners[j-1] != winmax )
1157
            print( " from a maximum of %3d", config.class_winners[j-1] );
1158
 
1159
    }
1160
 
1161
    /*
1162
    **  Manual entries
1163
    */
227 - 1164
    if ( config.class_ne_winners_by_class )
1165
    {
1166
        print( "\n");
1167
        print( "    ");
1168
        if ( report_html == html ) print( "<A HREF=\"#%s_by_cat\">",url_encode(config.team_class[config.nonequestrian_class-1].full_name));
1169
        print( "%s",  tprintf( "%-*s", LEN_CLASS_NAME ,config.team_class[config.nonequestrian_class-1].full_name ));
1170
        if ( report_html == html ) print( "</A>" );
1171
        print (" by Category");
1172
    }
1173
 
1174
 
91 - 1175
    print( "\n");
1176
    print( "    ");
1177
    if ( report_html == html ) print( "<A HREF=\"#%s\">",url_encode("Hall Of Fame"));
1178
    print( "%s",  "Hall Of Fame" );
1179
    if ( report_html == html ) print( "</A>" );
1180
 
1181
    print( "\n");
1182
    print( "    ");
1183
    if ( report_html == html ) print( "<A HREF=\"#%s\">",url_encode("FASTEST"));
1184
    print( "%s",  "FASTEST" );
1185
    if ( report_html == html ) print( "</A>" );
1186
 
1187
    /*
1188
    **  Sort the data by class
1189
    */
227 - 1190
    sort_team_data( 0, S_LC );     /* Generate class placement data */
91 - 1191
    last_class = -1;                /* Invalid class to start with */
1192
 
1193
    /*
1194
    **  Process each category
1195
    */
1196
    print( "\n");
1197
    for( j = 1; ; j++ )
1198
    {
1199
        /*
1200
        **  Tail for previous entry
1201
        */
227 - 1202
        //if ( config.class_ne_winners_by_class && j == config.nonequestrian_class )
1203
        //    continue;
1204
 
91 - 1205
        if ( j != 1 )
1206
            if ( report_html == html ) print( "<A HREF=\"#%s\">Awards Index</A>",url_encode("INDEX"));
1207
 
1208
        if ( j > config.num_class  )
1209
            break;
1210
 
1211
        /*
1212
        **  Header for the class
1213
        */
1214
        print( "\n");
1215
        if ( report_html == html )
1216
        {
1217
            print( "<hr>" );
1218
            print( "<A name=\"%s\"></A>",url_encode(config.team_class[j-1].full_name));
1219
        }
1220
        else
1221
        {
1222
            print( "%s\n", solid_line);
1223
        }
1224
        print( "Category: ");
1225
        if ( report_html == html ) print( "<A HREF=\"%s\">",url_encode(p_filename(filebase, config.team_class[j - 1].abr ,"html")));
1226
        print( "%s",  config.team_class[j-1].full_name );
1227
        if ( report_html == html ) print( "</A>" );
1228
 
1229
        if ( config.class_winners[j-1] <= 0 )
1230
        {
1231
            print( "\n");
1232
            print( "No winners awarded" );
1233
            continue;
1234
        }
1235
 
1236
        /*
1237
        **  Enties for 'n' the best teams as configured
1238
        */
1239
        windex = 0;                     /* Winners done */
1240
        unsigned int i;
1241
        for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
1242
        {
1243
            if ( ptr->teamclass != j )
1244
            {
1245
                continue;
1246
            }
1247
 
1248
            /*
1249
            **  Now read in the team record
1250
            */
1251
            if( valid_field( ptr->team ) && g_record( ptr->team, &team_buf ) )
1252
            {
1253
                /*
1254
                **  Ensure we have a valid team
1255
                **  Can't award disqualified teams
1256
                **  Can't award NE teams unless its a NE award
1257
                */
1258
                if ( ptr->flags.bad_times )
1259
                    break;
1260
 
1261
                if ( ptr->teamclass != config.nonequestrian_class  && ptr->flags.non_equestrian )
1262
                    break;
1263
 
1264
                /*
1265
                **  Count the entry
1266
                */
1267
                windex++;
1268
 
1269
                /*
1270
                **  If printing an HTML report then we need to mark
1271
                **  the entry with a reference so that we can link to it
1272
                */
1273
                print( "\n");
1274
                if ( report_html == html )
1275
                {
1276
                    print( "<A NAME=\"Team_%04d\">",team_buf.numb );
1277
                    print( "</A>" );
1278
                }
1279
 
1280
                /*
1281
                **  Basic information
1282
                **      - Team number - with Xref back to full result
1283
                **      - Full team name
1284
                **      - Full categoray name
1285
                */
1286
                print( "%s", placing(windex) );
1287
 
1288
                print( "  Team Name: ");
1289
                if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), team_buf.numb );
1290
                print( "%-*s ",     MAX_TM_NAME, team_buf.name );
1291
                    if ( report_html == html ) print( "</A>" );
1292
 
1293
                print( "  Number: ");
1294
                if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "finish" ,"html")), team_buf.numb );
1295
                print( "%4d",       team_buf.numb );
1296
                if ( report_html == html ) print( "</A>" );
1297
 
1298
 
1299
                for( k = 0; k < MAX_MEMB; k++ )
1300
                {
1301
 
1302
                    /*
1303
                    **  Skip equestrian leg in the non-equestion display
1304
                    */
1305
                    if ( k + 1 == config.equestrian_leg && ptr->teamclass == config.nonequestrian_class)
1306
                        continue;
1307
 
1308
                    print( "\n");
1309
                    print( "    ");
1310
                    print( "%-*s", MAX_PERSON_NAME, config.leg_name[k] ? config.leg_name[k] : "Competitor"  );
1311
                    print( " %-*s", MAX_PERSON_NAME, team_buf.members[k].name );
1312
 
1313
                    print( "  %-8s", time_a( team_buf.leg[k+1].elapsed ) );
1314
                }
1315
 
1316
                print( "\n");
1317
                print( "    ");
1318
                print_bold( TRUE );
1319
                print( "%-*s %-*s  %-8s", MAX_PERSON_NAME , "Total" ,MAX_PERSON_NAME, "",time_a( team_buf.leg[0].elapsed ) );
1320
                print_bold( FALSE );
1321
                print( "\n" );
1322
            }
1323
 
1324
 
1325
            /*
1326
            **  More to do
1327
            */
1328
            if ( windex >= config.class_winners[j-1] )
1329
            {
1330
                break;
1331
            }
1332
        }
1333
    }
1334
 
1335
    /*
227 - 1336
    ** Non Equestrian winners by category
1337
    */
1338
    if ( config.class_ne_winners_by_class)
1339
    {
1340
        bool header_done = false;
1341
 
1342
        /*
1343
        **  Sort the data by class with NE data sorted by real class
1344
        */
1345
        sort_team_data( 0, S_LC_NE );      /* Generate class placement data */
1346
        last_class = -1;                   /* Invalid class to start with */
1347
 
1348
        /*
1349
        **  Only process the Non Equestrian teams in this pass
1350
        */
1351
        print( "\n");
1352
        for( j = 1; ; j++ )
1353
        {
1354
            /*
1355
            **  Tail for previous entry
1356
            */
1357
            if ( j == config.nonequestrian_class)
1358
                continue;
1359
 
1360
            if ( j != 1 )
1361
                if ( report_html == html ) print( "<A HREF=\"#%s\">Awards Index</A>",url_encode("INDEX"));
1362
 
1363
            if ( j > config.num_class  )
1364
                break;
1365
 
1366
            /*
1367
            **  Header for the (sub) class
1368
            */
1369
            if ( !header_done )
1370
            {
1371
                header_done = true;
1372
                if ( report_html == html )
1373
                {
1374
                    print( "<A name=\"%s_by_cat\"></A>",url_encode(config.team_class[config.nonequestrian_class-1].full_name));
1375
                }
1376
            }
1377
 
1378
            print( "\n");
1379
            if ( report_html == html )
1380
            {
1381
                print( "<hr>" );
1382
                print( "<A name=\"%s\"></A>",url_encode(config.team_class[j-1].full_name));
1383
            }
1384
            else
1385
            {
1386
                print( "%s\n", solid_line);
1387
            }
1388
            print( "Category: ");
1389
            if ( report_html == html ) print( "<A HREF=\"%s\">",url_encode(p_filename(filebase, config.team_class[config.nonequestrian_class - 1].abr ,"html")));
1390
            print( "%s",  config.team_class[config.nonequestrian_class-1].full_name );
1391
            if ( report_html == html ) print( "</A>" );
1392
 
1393
            print (" :: ");
1394
 
1395
            if ( report_html == html ) print( "<A HREF=\"%s\">",url_encode(p_filename(filebase, config.team_class[j - 1].abr ,"html")));
1396
            print( "%s",  config.team_class[j-1].full_name );
1397
            if ( report_html == html ) print( "</A>" );
1398
 
1399
            if ( config.class_ne_winners[j-1] <= 0 )
1400
            {
1401
                print( "\n");
1402
                print( "No winners awarded" );
1403
                if ( report_html == html ) print("<br>");
1404
                continue;
1405
            }
1406
 
1407
            /*
1408
            **  Enties for 'n' the best teams as configured
1409
            */
1410
            windex = 0;                     /* Winners done */
1411
            unsigned int i;
1412
            for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
1413
            {
1414
                if ( ptr->teamclass != config.nonequestrian_class ||  ptr->real_teamclass != j )
1415
                {
1416
                    continue;
1417
                }
1418
 
1419
                /*
1420
                **  Now read in the team record
1421
                */
1422
                if( valid_field( ptr->team ) && g_record( ptr->team, &team_buf ) )
1423
                {
1424
                    /*
1425
                    **  Ensure we have a valid team
1426
                    **  Can't award disqualified teams
1427
                    **  Can't award NE teams unless its a NE award
1428
                    */
1429
                    if ( ptr->flags.bad_times )
1430
                        break;
1431
 
1432
                    if ( ptr->teamclass != config.nonequestrian_class  && ptr->flags.non_equestrian )
1433
                        break;
1434
 
1435
                    /*
1436
                    **  Count the entry
1437
                    */
1438
                    windex++;
1439
 
1440
                    /*
1441
                    **  If printing an HTML report then we need to mark
1442
                    **  the entry with a reference so that we can link to it
1443
                    */
1444
                    print( "\n");
1445
                    if ( report_html == html )
1446
                    {
1447
                        print( "<A NAME=\"Team_%04d\">",team_buf.numb );
1448
                        print( "</A>" );
1449
                    }
1450
 
1451
                    /*
1452
                    **  Basic information
1453
                    **      - Team number - with Xref back to full result
1454
                    **      - Full team name
1455
                    **      - Full categoray name
1456
                    */
1457
                    print( "%s", placing(windex) );
1458
 
1459
                    print( "  Team Name: ");
1460
                    if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), team_buf.numb );
1461
                    print( "%-*s ",     MAX_TM_NAME, team_buf.name );
1462
                        if ( report_html == html ) print( "</A>" );
1463
 
1464
                    print( "  Number: ");
1465
                    if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "finish" ,"html")), team_buf.numb );
1466
                    print( "%4d",       team_buf.numb );
1467
                    if ( report_html == html ) print( "</A>" );
1468
 
1469
 
1470
                    for( k = 0; k < MAX_MEMB; k++ )
1471
                    {
1472
 
1473
                        /*
1474
                        **  Skip equestrian leg in the non-equestion display
1475
                        */
1476
                        if ( k + 1 == config.equestrian_leg && ptr->teamclass == config.nonequestrian_class)
1477
                            continue;
1478
 
1479
                        print( "\n");
1480
                        print( "    ");
1481
                        print( "%-*s", MAX_PERSON_NAME, config.leg_name[k] ? config.leg_name[k] : "Competitor"  );
1482
                        print( " %-*s", MAX_PERSON_NAME, team_buf.members[k].name );
1483
 
1484
                        print( "  %-8s", time_a( team_buf.leg[k+1].elapsed ) );
1485
                    }
1486
 
1487
                    print( "\n");
1488
                    print( "    ");
1489
                    print_bold( TRUE );
1490
                    print( "%-*s %-*s  %-8s", MAX_PERSON_NAME , "Total" ,MAX_PERSON_NAME, "",time_a( team_buf.leg[0].elapsed ) );
1491
                    print_bold( FALSE );
1492
                    print( "\n" );
1493
                }
1494
 
1495
 
1496
                /*
1497
                **  More to do
1498
                */
1499
                if ( windex >= config.class_ne_winners[j-1] )
1500
                {
1501
                    break;
1502
                }
1503
            }
1504
        }
1505
    }
1506
 
1507
    /*
91 - 1508
    **  Generate the Hall of Fame information
1509
    */
1510
    print( "\n");
1511
    if ( report_html == html )
1512
    {
1513
        print( "<hr>" );
1514
        print( "<A name=\"%s\"></A>",url_encode("Hall Of Fame"));
1515
    }
1516
    else
1517
    {
1518
        print( "%s\n", solid_line);
1519
    }
1520
    print( "%s",  "Hall of Fame" );
1521
 
1522
    if ( config.num_fame  )
1523
    {
1524
        for( i = 1; i <= config.num_fame; i++ )
1525
        {
1526
            print( "\n");
1527
            print( "    %-*s", MAX_PERSON_NAME, config.hall_fame[i-1] );
1528
        }
1529
    }
1530
    else
1531
    {
195 david 1532
        qDebug( "There are no new stars for the Hall of Fame");
91 - 1533
    }
1534
    if ( report_html == html ) print( "\n");
1535
    if ( report_html == html ) print( "<A HREF=\"#%s\">Awards Index</A>",url_encode("INDEX"));
1536
 
1537
    /*
1538
    **  Generate the FASTEST information
1539
    */
1540
    print( "\n" );
1541
    print( "\n");
1542
    if ( report_html == html )
1543
    {
1544
        print( "<hr>" );
1545
        print( "<A name=\"%s\"></A>",url_encode("FASTEST"));
1546
    }
1547
    else
1548
    {
1549
        print( "%s\n", solid_line);
1550
    }
1551
    print( "%s",  "FASTEST" );
1552
 
1553
    /*
1554
    **  Sort the data and then generate the stats - again
1555
    */
1556
    do_big_sort();
1557
    gen_stats();
1558
 
1559
    for( i = 1; i <= config.num_legs; i++ )
1560
    {
1561
        g_record( stats.fast.team[i][0], &team_buf );
1562
 
1563
        print( "\n");
1564
        print( "    %-13s ", config.leg_name[i - 1] );
1565
        print( "  Name: ");
1566
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), team_buf.numb );
1567
        print( "%-*s", MAX_PERSON_NAME, team_buf.members[i-1].name );
1568
        if ( report_html == html ) print( "</A>" );
242 - 1569
        print( "  Team:");
91 - 1570
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "finish" ,"html")), team_buf.numb );
1571
        print( "%4d" , stats.fast.team[i][0] );
1572
        if ( report_html == html ) print( "</A> " );
242 - 1573
        print( "  Time:%s ", time_a( stats.fast.time[i][0] ) );
91 - 1574
 
1575
    }
1576
 
1577
    if ( report_html == html ) print( "\n");
1578
    if ( report_html == html ) print( "<A HREF=\"#%s\">Awards Index</A>",url_encode("INDEX"));
1579
    print( "\n");
1580
    close_printer();
1581
}
1582
 
1583
/*========================================================================
1584
 *
1585
 *  pri_master_index
1586
 *
1587
 *  Purpose:
1588
 *      This function is called to create an HTML page that references all
1589
 *      the other pages that have been generated
1590
 *
1591
 *      Assume that they are in the same directory
1592
 *
1593
 *  Parameters:
1594
 *      None
1595
 *
1596
 *  Returns:
1597
 *      Nothing
1598
 *
1599
 *========================================================================*/
1600
void pri_master_index_entry(const char *name, const char *text)
1601
{
1602
    print( "<tr><td>");
1603
    print ("<A HREF=\"%s\">%s</A>\n", url_encode(p_filename(filebase, name ,"html")), text );
1604
}
1605
 
1606
 
1607
void pri_master_index(void)
1608
{
1609
    int j;
1610
 
1611
    report_html = html;
1612
    if( !open_printer( "", "index", 132, report_html, "Master Index" ) )
1613
        return;
1614
 
1615
    /*
1616
    **  Names
1617
    */
1618
    print( "<TABLE border=0 align=center>" );
1619
    pri_master_index_entry( "name", "Team list" );
1620
    pri_master_index_entry( "competitor", "Competitor list" );
1621
    pri_master_index_entry( "finish", "Finishing Order for all Teams" );
1622
    pri_master_index_entry( "awards", "Prizes and Awards" );
1623
    print( "<tr><td>\n" );
1624
 
1625
    print( "\n" );
1626
    for( j = 1; j <= config.num_class; j++ )
1627
    {
1628
        pri_master_index_entry( config.team_class[j - 1].abr, tprintf("Category Results for: %s", config.team_class[j-1].full_name) );
1629
    }
1630
 
1631
    print( "</TABLE>" );
1632
 
1633
    close_printer();
1634
 
1635
    /*
1636
    **  A small page to hold the Leg End displays
1637
    */
1638
 
1639
    if( !open_printer( "", "legindex", 132, report_html, "Master Index with trace data" ) )
1640
        return;
1641
 
1642
    /*
1643
    **  Names
1644
    */
1645
    print( "<TABLE border=0 align=center>" );
1646
#if 1
1647
    pri_master_index_entry( "name", "Team list" );
1648
    pri_master_index_entry( "competitor", "Competitor list" );
1649
    pri_master_index_entry( "finish", "Finishing Order for all Teams" );
1650
    pri_master_index_entry( "awards", "Prizes and Awards" );
1651
    print( "<tr><td>\n" );
1652
 
1653
    print( "\n" );
254 - 1654
    pri_master_index_entry( "summary", "Category Summary" );
91 - 1655
    for( j = 1; j <= config.num_class; j++ )
1656
    {
1657
        pri_master_index_entry( config.team_class[j - 1].abr, tprintf("Category Results for: %s", config.team_class[j-1].full_name) );
1658
    }
1659
#endif
1660
    print( "<tr><td>\n" );
1661
 
1662
    print( "\n" );
170 - 1663
    for ( int leg = 1; leg <= config.num_legs; leg ++ )
91 - 1664
    {
1665
        pri_master_index_entry( tprintf("lg%1.1d", leg), tprintf("Leg End Results for: %d", leg) );    
1666
    }
1667
 
1668
    print( "<tr><td>\n" );
1669
    print( "\n" );
1670
 
170 - 1671
    for ( int leg = 1; leg <= config.num_legs; leg ++ )
91 - 1672
    {
1673
        pri_master_index_entry( tprintf("le%1.1d", leg), tprintf("Leg Elapsed Time Results for: %d", leg) );
1674
    }    
1675
 
1676
 
1677
    print( "</TABLE>" );
1678
 
1679
    close_printer();
203 - 1680
    /*
1681
     ** Tell the main system about this new report
1682
     */
272 david 1683
    MainWindow::registerReport(getPrinterFile(), "Master Leg Index");
91 - 1684
 
1685
}
1686
 
1687
 
1688
/*========================================================================
1689
 *
1690
 *  Print interim results
1691
 *
1692
 *  Purpose:
1693
 *      This function is called to Print interim results
1694
 *
1695
 *  Parameters:
1696
 *      None
1697
 *
1698
 *  Returns:
1699
 *      Nothing
1700
 *
1701
 *========================================================================*/
1702
 
1703
void pri_interim(void)
1704
{
1705
    ty_s_data  *ptr;
170 - 1706
    team_type   team_buf;
91 - 1707
    unsigned    i;
1708
    int         j, last_class;
1709
    char       *report_title;
1710
 
1711
    if ( ! report_all )
1712
    {
195 david 1713
        ck_data( -1, C_DISQUAL );              /* Check the data - dummy check */
91 - 1714
    }
1715
    do_big_sort();                             /* Sort on every thing */
1716
    gen_stats();                               /* Generate the stats too */
1717
 
1718
    /*
1719
     * Now print the data on the printer 
1720
     */
1721
 
1722
    if( !open_printer( "", "int", 132, report_html, "Interim Results" ) )
1723
        return;
1724
 
1725
    /*
1726
     * Print out the data 
1727
     */
1728
    print_class_header( -1, FALSE );                     /* Print the header */
1729
 
1730
    ptr = sort_data;
1731
    sort_team_data( 0, S_TEAM );                   /* Re-sort on team number */
1732
    for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
1733
    {
1734
        if ( ptr->teamclass == config.nonequestrian_class )
1735
            continue;
1736
 
1737
        g_record( ptr->team, &team_buf );
1738
 
1739
        print( "%4d %4.4s %-*s",
1740
               team_buf.numb,
1741
               pi_place( team_buf.leg[config.num_legs].le_place,
1742
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ),
1743
               3,
1744
               team_buf.teamclass ==
1745
 
1746
        for( j = 1; j <= config.num_legs; j++ )
1747
        {
1748
            print( "  %-8s %4.4s %4.4s",
1749
                   time_fa( team_buf.leg[j].elapsed,
1750
                            ptr->flags.disqualified ),
1751
                   pi_place( team_buf.leg[j].l_place, ptr->flags.disqualified,
1752
                             team_buf.leg[j].elapsed ),
1753
                   pi_place( team_buf.leg[j].le_place,
1754
                             ptr->flags.disqualified,
1755
                             team_buf.leg[j].elapsed ) );
1756
        }
1757
        print( "  %-8s %4.4s\n",
1758
               time_fa( team_buf.leg[0].elapsed, ptr->flags.disqualified ),
1759
               pi_place( team_buf.leg[config.num_legs].lec_place,
1760
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ) );
1761
    }
1762
 
1763
    print_class_stats( -1, FALSE );             /* Print statistics */
1764
    print_legend(-1, 1);                        /* Print the legend */
1765
    close_printer();                            /* Close the printer */
1766
 
1767
 
1768
    /*
1769
     * Now produce a breakdown on a class by class basis 
1770
     * Now print out the class placement information
1771
     */
1772
 
1773
    sort_team_data( 0, S_CLASS );              /* Generate class placement data */
1774
    last_class = -1;                             /* Invalid class to start with */
1775
 
1776
    for( ptr = sort_data, i = 0; i < sort_num; i++, ptr++ )
1777
    {
1778
        /*
1779
        **  Detect a change in the "class"
1780
        **  All data is within the one array of data
1781
        **  Use the in-memory class as this MAY differ from that stored
1782
        **  The non-equestrian class does this.
1783
        */
1784
        if( last_class != ptr->teamclass )
1785
        {
1786
            if( last_class >= 0 )
1787
            {
1788
                print_class_stats( last_class, TRUE );
1789
                print_legend(last_class, 1);
1790
                close_printer();
1791
            }
1792
 
1793
            report_title = tprintf( "Interim Category results for : %-*s", LEN_CLASS_NAME, team_buf.teamclass == 0 ? "" : config.team_class[ptr->teamclass - 1].full_name );
1794
 
1795
            if( !open_printer( "", tprintf( "i%2s", config.team_class[ptr->teamclass - 1].abr ), 132, report_html, report_title ) )
1796
                continue;
1797
            print_class_header( last_class = ptr->teamclass, FALSE );
1798
        }
1799
 
1800
        /*
1801
        **  Now read in the team record
1802
        */
1803
        g_record( ptr->team, &team_buf );
1804
        print( "%4d %4.4s %-*s",
1805
               team_buf.numb,
1806
               pi_place( team_buf.leg[config.num_legs].lec_place,
1807
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ),
1808
               3,
1809
               team_buf.teamclass ==
1810
 
1811
        for( j = 1; j <= config.num_legs; j++ )
1812
        {
1813
            print( "  %-8s %4.4s %4.4s",
1814
                   time_fa( team_buf.leg[j].elapsed,
1815
                            ptr->flags.disqualified ),
1816
                   pi_place( team_buf.leg[j].lc_place,
1817
                             ptr->flags.disqualified,
1818
                             team_buf.leg[j].elapsed ),
1819
                   pi_place( team_buf.leg[j].lec_place,
1820
                             ptr->flags.disqualified,
1821
                             team_buf.leg[j].elapsed ) );
1822
        }
1823
        print( "  %-8s %4.4s\n",
1824
               time_fa( team_buf.leg[0].elapsed, ptr->flags.disqualified ),
1825
               pi_place( team_buf.leg[config.num_legs].le_place,
1826
                         ptr->flags.disqualified, team_buf.leg[0].elapsed ) );
1827
    }
1828
 
1829
    print_class_stats( last_class, FALSE );
1830
    print_legend(last_class, 1);
1831
    close_printer();
1832
 
1833
}
1834
 
1835
/*----------------------------------------------------------------------------
1836
** FUNCTION           : pri_csv_data
1837
**
1838
** DESCRIPTION        : Generate a CSV file of all the report data
1839
**                      It can then be used to play with the data externally
1840
**
1841
**
1842
** INPUTS             : None
1843
**
1844
** RETURNS            : Yes it does
1845
**
1846
----------------------------------------------------------------------------*/
1847
 
1848
 
1849
void pri_csv_data ( void )
1850
{
1851
    int i;
1852
    int j;
1853
    int age_sum;
170 - 1854
    team_type   team_buf;
91 - 1855
 
1856
    /*
1857
    **  Sort on every thing
1858
    **  Then generate all the stats too
1859
    */
1860
    do_big_sort();
1861
    gen_stats();
1862
 
1863
    /*
1864
     * Now print the data on the printer 
1865
     */
1866
 
1867
    if( !open_printer( "full_data", "csv", 2000, text, NULL ) )
1868
        return;
1869
 
1870
    /*
1871
    **  Print headings
1872
    */
1873
    csv_print( "%s",   "Team Number" );
1874
    csv_print( "%s",   "Team Name" );
1875
 
1876
    csv_print( "%s",    "Class Full");
1877
    csv_print( "%s",    "Class Abr");
1878
    csv_print( "%s",    "Class Start Time");
1879
    csv_print( "%s",    "Class Start Time Number");
1880
 
1881
    csv_print( "%s",    "Team Country");
1882
 
1883
    for( j = 1; j <= config.num_legs; j++ )
1884
    {
1885
        csv_print( "%s", "Leg Number" );
1886
        csv_print( "%s", "Leg Name");
1887
        csv_print( "%s", "Competitor Name");
1888
        csv_print( "%s", "Sex" );
1889
        csv_print( "%s", "Age");
1890
        csv_print( "%s", "Start Time");
1891
        csv_print( "%s", "Start Time Number");
1892
        csv_print( "%s", "End Time" );
1893
        csv_print( "%s", "End Time Number" );
1894
        csv_print( "%s", "Elapsed Time");
1895
        csv_print( "%s", "Elapsed Time Number");
1896
        csv_print( "%s", "Leg Place");
1897
        csv_print( "%s", "Leg End Place");
1898
        csv_print( "%s", "Leg Class Place");
1899
        csv_print( "%s", "Leg End Class Place");
1900
        csv_print( "%s", "Manual");
1901
    }
1902
 
1903
    j = 0;
1904
    csv_print( "%s", "Team Start Time");
1905
    csv_print( "%s", "Team Start Time Number");
1906
    csv_print( "%s", "Team End Time");
1907
    csv_print( "%s", "Team End Time Number");
1908
    csv_print( "%s", "Team Elapsed Time");
1909
    csv_print( "%s", "Team Elapsed Time Number");
1910
//            csv_print( "%s", team_buf.leg[j].l_place );
1911
    csv_print( "%s", "Team Leg End Place");
1912
//            csv_print( "%s", team_buf.leg[j].lc_place );
1913
    csv_print( "%s", "Team Leg Class Place");
1914
//            csv_print( "%s", team_buf.leg[j].manual );
1915
 
1916
    csv_print( "%s", "Total Team Age");
1917
    csv_print( "%s", "Flag:valid Team");
1918
    csv_print( "%s", "Flag:bad_times" );
1919
    csv_print( "%s", "Flag:disqualified" );
1920
    csv_print( "%s", "Flag:non_equestrian" );
246 - 1921
    csv_print( "%s", "Flag:vet_check" );
91 - 1922
    csv_print("\n");
1923
 
1924
 
1925
    for( i = config.min_team; i <= config.max_team; i++ )
1926
    {
1927
        if( valid_field( i ) && g_record( i, &team_buf ) )
1928
        {
1929
            /*
1930
            **  Basic information
1931
            **      - Team number - with Xref back to full result
1932
            **      - Full team name
1933
            **      - Full categoray name - with Xref to category results
1934
            **      - Country name
1935
            */
1936
            csv_print( "%d",   team_buf.numb );
1937
            csv_print( "%s",   team_buf.name );
1938
 
1939
            csv_print( "%s",    team_buf.teamclass == 0 ? "" : config.team_class[team_buf.teamclass - 1].full_name );
1940
            csv_print( "%s",    team_buf.teamclass == 0 ? "" : config.team_class[team_buf.teamclass - 1].abr );
1941
            csv_print( "%s",    time_a (team_buf.teamclass == 0 ? 0 : config.team_class[team_buf.teamclass - 1].start ));
1942
            csv_print( "%d",    team_buf.teamclass == 0 ? 0 : config.team_class[team_buf.teamclass - 1].start );
1943
 
1944
            csv_print( "%s",    config.num_countries == 0
1945
                                || team_buf.country ==
1946
 
1947
 
1948
            age_sum = 0;
1949
            for( j = 1; j <= config.num_legs; j++ )
1950
            {
1951
                csv_print( "%d", j );
1952
                csv_print( "%s", config.leg_name[j - 1] );
1953
                csv_print( "%s", team_buf.members[j-1].name );
1954
                csv_print( "%s", ( team_buf.members[j-1].sex == male ) ? "Male" : "Female" );
1955
                csv_print( "%d", team_buf.members[j-1].age );
1956
                if ( age_sum >= 0 )
1957
                {
1958
                    ushort age = team_buf.members[j-1].age;
1959
                    if ( age > 0 && age < 255 )
1960
                    {
1961
                        age_sum += age;
1962
                    }
1963
                    else
1964
                    {
1965
                        age_sum = -1;
1966
                    }
1967
                }
1968
 
1969
 
1970
                csv_print( "%s", time_a(team_buf.leg[j].start ));
1971
                csv_print( "%d", team_buf.leg[j].start );
1972
                csv_print( "%s", time_a(team_buf.leg[j].end ));
1973
                csv_print( "%d", team_buf.leg[j].end );
1974
                csv_print( "%s", time_a(team_buf.leg[j].elapsed ));
1975
                csv_print( "%d", team_buf.leg[j].elapsed );
1976
                csv_print( "%d", team_buf.leg[j].l_place );
1977
                csv_print( "%d", team_buf.leg[j].le_place );
1978
                csv_print( "%d", team_buf.leg[j].lc_place );
1979
                csv_print( "%d", team_buf.leg[j].lec_place );
1980
                csv_print( "%d", team_buf.leg[j].manual );
1981
            }
1982
 
1983
            j = 0;
1984
            csv_print( "%s", time_a(team_buf.leg[j].start ));
1985
            csv_print( "%d", team_buf.leg[j].start );
1986
            csv_print( "%s", time_a(team_buf.leg[j].end ));
1987
            csv_print( "%d", team_buf.leg[j].end );
1988
            csv_print( "%s", time_a(team_buf.leg[j].elapsed ));
1989
            csv_print( "%d", team_buf.leg[j].elapsed );
1990
//            csv_print( "%d", team_buf.leg[j].l_place );
1991
            csv_print( "%d", team_buf.leg[j].le_place );
1992
//            csv_print( "%d", team_buf.leg[j].lc_place );
1993
            csv_print( "%d", team_buf.leg[j].lec_place );
1994
//            csv_print( "%d", team_buf.leg[j].manual );
1995
 
1996
            csv_print( "%d", age_sum );
1997
            csv_print( "%d", team_buf.flags.valid );
1998
            csv_print( "%d", team_buf.flags.bad_times );
1999
            csv_print( "%d", team_buf.flags.disqualified );
2000
            csv_print( "%d", team_buf.flags.non_equestrian );
246 - 2001
            csv_print( "%d", team_buf.flags.vet_check );
91 - 2002
 
2003
//How about class placings
2004
 
2005
 
2006
            csv_print( "\n" );
2007
        }
2008
    }
2009
 
2010
    close_printer();
2011
}
2012
 
2013
 
2014
/*========================================================================
2015
 *
2016
 *  Print all reports at once
2017
 *  Its all so fast, these days ...
2018
 *
2019
 *  Purpose:
2020
 *      This function is called to print all reports at once
2021
 *
2022
 *  Parameters:
2023
 *      None
2024
 *
2025
 *  Returns:
2026
 *      Nothing
2027
 *
2028
 *========================================================================*/
2029
 
2030
void pri_all_reports ( void )
2031
{
2032
    int leg;
2033
    report_all = TRUE;
2034
 
2035
    pri_team();
2036
 
2037
    for ( leg = 1; leg <= config.num_legs; leg ++ )
2038
    {
2039
        pri_leg_body ( leg );
2040
        pri_eleg_body ( leg );
2041
 
2042
        report_html = html;
2043
 
2044
        pri_leg_body ( leg );
2045
        pri_eleg_body ( leg );        
2046
 
2047
        report_html = text;
2048
    }
2049
 
2050
    pri_final();
2051
    pri_final_html();
2052
    pri_csv_data();
254 - 2053
    pri_summary_html();
91 - 2054
    pri_summary();
2055
    pri_awards_html();
2056
    pri_awards();
2057
    pri_master_index();
2058
 
168 david 2059
    pri_interim();
2060
 
91 - 2061
    report_all = FALSE;
2062
}
2063
 
2064
 
2065
/*========================================================================
2066
 *
2067
 *  Print a class header
2068
 *
2069
 *  Purpose:
2070
 *      This function is called to print a class header
2071
 *
2072
 *  Parameters:
2073
 *      class           Name of this class
2074
 *      final           False - prelim results
2075
 *
2076
 *  Returns:
2077
 *      Nothing
2078
 *
2079
 *========================================================================*/
2080
 
2081
void print_class_header( int teamclass, int final )
2082
{
2083
    int         j;
2084
 
2085
    /*
2086
    **  Give a clear indication that the report is preliminary
2087
    */
2088
 
2089
    if( !final )
2090
        print( "PRELIMINARY RESULTS ONLY\n\n" );
2091
 
2092
    /*
2093
    **  Now printout the column headings
2094
    **  This is a two line display
2095
    **
2096
    **  Line-1  Leg names
2097
    */
2098
    print( "%-*s %-*s %-*s", 4, "", 4, "", 3, "" );
2099
    for( j = 1; j <= config.num_legs; j++ )
2100
    {
2101
        print_bold( TRUE );
2102
        print( "  %-*s", 18, config.leg_name[j - 1] );
2103
        print_bold( FALSE );
2104
    }
2105
    print( "  %-8s %-4s\n", "Total", ( teamclass < 0 ) ? "Cat" : "Fin" );
2106
 
2107
 
2108
    /*
2109
    **  Line-2  Details
2110
    */
2111
    print_underline( TRUE );
2112
    print( "%-*s %*s %-*s", 4, final ? "Plce" : "Team",
2113
                            4, final ? "Team" : "Plce",
2114
                            3, "Cat" );
2115
 
2116
    for( j = 1; j <= config.num_legs; j++ )
2117
        print( "  %-8s %-4s %-4s", "Time", " LP", " EP" );
2118
 
2119
    print( "  %-8s %-4s\n", "Time", "Plce" );
2120
    print_underline( FALSE );
2121
}
2122
 
2123
/*========================================================================
2124
 *
2125
 *  Generate the class stats
2126
 *
2127
 *  Purpose:
2128
 *      This function is called to Generate the class stats
2129
 *
2130
 *  Parameters:
2131
 *      c           Class to print
2132
 *      final       TRUE: Final data
2133
 *                  FALSE: Interim data
2134
 *
2135
 *  Returns:
2136
 *      Nothing
2137
 *
2138
 *========================================================================*/
2139
 
2140
void print_class_stats( int c, int final )
2141
{
2142
    int         i, j;
2143
    const char        *title;
2144
 
2145
    if( c < 0 )
2146
    {
2147
        title = "Event";
2148
        c = 0;
2149
    }
2150
    else
2151
    {
2152
        title = "Category";
2153
    }
2154
 
2155
    print( "\n" );
2156
    if ( report_html ) print_underline(TRUE);
2157
    print( "%s statistics", title );
2158
    if ( report_html ) print_underline(FALSE);
2159
    print( "\n" );
2160
 
2161
 
2162
    /*
2163
    **  Print the names of the different legs
2164
    */
2165
    print( "%-*s       ", LEN_CLASS_NAME, "" );
2166
    for( i = 1; i <= config.num_legs; i++ )
2167
    {
2168
        print_bold( TRUE );
2169
        print( "%-13s  ", config.leg_name[i - 1] );
2170
        print_bold( FALSE );
2171
    }
2172
    print( "%-13s  \n", final ? "Total" : "" );
2173
 
2174
    /*
2175
    **  Print the fastest teams for each leg and overall
2176
    **  Add cross references to the team names for the fastest teams
2177
    */
2178
    print( "%*s : ", LEN_CLASS_NAME, "Fastest" );
2179
    for( i = 0; i <= config.num_legs; i++ )
2180
    {
2181
        j = i + 1;
2182
        if( i >= config.num_legs )
2183
        {
2184
            if( final )
2185
                j = 0;                           /* Leg-0 last */
2186
            else
2187
                break;
2188
        }
2189
 
2190
        if ( report_html == html ) print( "<A HREF=\"%s#Team_%04d\">", url_encode(p_filename(filebase, "name" ,"html")), stats.fast.team[j][c] );
2191
        print( "%4d",  stats.fast.team[j][c] );
2192
        if ( report_html == html ) print( "</A>" );
2193
        print( " %s  ", time_a( stats.fast.time[j][c] ) );
2194
    }
2195
    print( "\n" );
2196
 
2197
    /*
2198
    **  Print the average time for each leg
2199
    */
2200
    print( "%*s : ", LEN_CLASS_NAME, "Average" );
2201
    for( i = 0; i <= config.num_legs; i++ )
2202
    {
2203
        j = i + 1;
2204
        if( i >= config.num_legs )
2205
        {
2206
            if( final )
2207
                j = 0;                           /* Leg-0 last */
2208
            else
2209
                break;
2210
        }
2211
        print( "     %s  ", time_a( stats.average[j][c] ) );
2212
    }
2213
}
2214
 
2215
/*========================================================================
2216
 *
2217
 *  Print the legend
2218
 *
2219
 *  Purpose:
2220
 *      This function is called to Print the legend
2221
 *
2222
 *  Parameters:
2223
 *      class       - Class currently being printed
2224
 *      full        - Display full legend
2225
 *
2226
 *  Returns:
2227
 *      Nothing
2228
 *
2229
 *========================================================================*/
2230
 
2231
void print_legend ( int teamclass, int full )
2232
{
2233
 
2234
    int         i;
2235
    char        line[201];
2236
    FILE       *adfile = NULL;
2237
    int         count;
2238
 
2239
    /*
2240
     * First the categories 
2241
     */
2242
    print( "\n\n" );
2243
    if ( report_html ) print_underline(TRUE);
2244
    print( "Category abbreviations" );
2245
    if ( report_html ) print_underline(FALSE);
2246
    print( "\n" );
2247
 
2248
 
2249
    for( i = 1, count = 0; i <= config.num_class; i++ )
2250
    {
2251
#if 0
2252
        /*
2253
        **  Skip any non-equestrian class in the legend
2254
        **  Don't want to tell the general user whats goes on, unless we actually
2255
        **  creating the non-equestrian report.
2256
        */
2257
        if ( class != config.nonequestrian_class  && i == config.nonequestrian_class )
2258
            continue;
2259
#endif
2260
        if ( report_html == html ) print( "<A HREF=\"%s\">",url_encode(p_filename(filebase, config.team_class[i - 1].abr ,"html")) );
2261
        print( "%-*s", 3, config.team_class[i - 1].abr );
2262
        if ( report_html == html ) print( "</A>" );
2263
        print( " : %-*s  ", LEN_CLASS_NAME, config.team_class[i - 1].full_name );
2264
 
2265
        if( !( ++count % 5 ) )
2266
            print( "\n" );
2267
    }
2268
 
2269
    /*
2270
    **  Add link to the finish order report
2271
    */
2272
    if ( report_html == html )
2273
    {
2274
        print( "<A HREF=\"%s\">", url_encode(p_filename(filebase, "finish" ,"html")) );
2275
        print( "%-*s", 3, "All" );
2276
        print( "</A>" );
2277
        print( " : %-*s  ", LEN_CLASS_NAME, "Finishing Order" );
2278
    }
2279
 
2280
    /*
2281
    **  Country data - if countries have been defined
2282
    */
2283
    if( config.num_countries )
2284
    {
2285
        print( "\n\n" );
2286
        if ( report_html ) print_underline(TRUE);
2287
        print( "Country abbreviations" );
2288
        if ( report_html ) print_underline(FALSE);
2289
        print( "\n" );
2290
 
2291
        for( i = 0, count = 0; i < MAX_COUNTRY; i++ )
2292
        {
2293
            if( config.country_name[i].abr[0] )
2294
            {
2295
                print( "%-*s : %-*s  ", 4, config.country_name[i].abr,
2296
                       LEN_CNTRY_NAME, config.country_name[i].full_name );
2297
                if( !( ++count % 5 ) )
2298
                    print( "\n" );
2299
            }
2300
        }
2301
    }
2302
    print( "\n" );
2303
 
2304
    /*
2305
     * Other comments 
2306
     */
2307
    if ( full )
2308
    {
2309
        print( "\nPlace numbers (LP and EP)\n" );
2310
        print( "LP - Placing based on elapsed time within the leg.                Cat Plce - Placing within the category.\n" );
2311
        print( "EP - Placing based on accumulated times to the end of that leg.   Fin Plce - Overall placing within the event.\n" );
2312
        print( "U  - Placing not available.\n" );
2313
    }
2314
 
2315
    /*
2316
     *  Insert the contents of the config.addendum file
2317
     *  or a defualt message
2318
     */
2319
    if( config.addendum[0] )
199 david 2320
    {
2321
        const char *name = QmConfig::getAddendemFile(config.addendum);
2322
        if (name)
2323
            adfile = fopen( name, "rt" );  /* Open the file for reading */
2324
    }
91 - 2325
 
2326
    if( adfile )
2327
    {
2328
        while( fgets( line, sizeof(line)-1, adfile ) )
2329
            print( "%s", line );
2330
    }
2331
    else
2332
    {
2333
        print( "\nTiming and Results by\n" );
2334
        print( "Embedded Solutions\n" );
2335
    }
2336
}
2337
 
2338
/*========================================================================
2339
 *
2340
 *  Return place data
2341
 *
2342
 *  Purpose:
2343
 *      This function is called to return place data
2344
 *
2345
 *      This routine is called to fill a print team_buffer - to allow for
2346
 *      multiple calls to this function ( before the data is used ) a number
2347
 *      of static team_buffers are maintained
2348
 *
2349
 *  Parameters:
2350
 *      num         place - if not bad_times
2351
 *      disq        Disqualified flag
2352
 *      time        Time data is based on
2353
 *
2354
 *  Returns:
2355
 *      This function returns a pointer to the character string for the
2356
 *      number or a pointer to a bad_times string.
2357
 *
2358
 *========================================================================*/
2359
 
2360
const char       *pi_place( int num, int disq, time_t time )
2361
{
2362
    static char store[2][5];                     /* 2 stores for 4 digit numbers */
2363
    static int  i = 0;                           /* Current index into store */
2364
    static const char *dis = "D";                      /* Disqualified */
2365
    static const char *non = "-";                      /* Invalid time */
2366
 
2367
    if( disq )                                   /* Disqualified team */
2368
        return ( dis );
2369
    if( time <= 0 )                              /* Unknown time */
2370
        return ( non );
2371
 
2372
    i++;
2373
    if( i >= 2 )
2374
        i = 0;                                   /* Select next entry */
2375
    sprintf( store[i], "%4d", num );
2376
    return ( store[i] );
2377
 
2378
}
2379
 
2380
/*========================================================================
2381
 *
2382
 *  Return place data
2383
 *
2384
 *  Purpose:
2385
 *      This function is called to Return place data
2386
 *
2387
 *      This routine is called to fill a print team_buffer - to allow for
2388
 *      multiple calls to this function ( before the data is used ) a number
2389
 *      of static team_buffers are maintained
2390
 *
2391
 *  Parameters:
2392
 *      num         place - if not bad_times
2393
 *      disq        Disqualified flag
2394
 *
2395
 *  Returns:
2396
 *      This function returns a pointer to the character string for the
2397
 *      number or a pointer to a bad_times string.
2398
 *
2399
 *========================================================================*/
2400
 
2401
const char *pr_place( int num, int disq )
2402
{
2403
    static char store[2][5];                     /* 2 stores for 4 digit numbers */
2404
    static int  i = 0;                           /* Current index into store */
2405
    static const char *dis = "U";
2406
 
2407
    if( disq )
2408
        return ( dis );
2409
 
2410
    i++;
2411
    if( i >= 2 )
2412
        i = 0;                                   /* Select next entry */
2413
    sprintf( store[i], "%4d", num );
2414
    return ( store[i] );
2415
 
2416
}
2417
 
2418
/*========================================================================
2419
 *
2420
 *  Check data for bad times
2421
 *
2422
 *  Purpose:
2423
 *      This function is called to Check data for bad times
2424
 *      Scan the sort data structure and locate entries that have incorrect
2425
 *      times.
2426
 *      
2427
 *      Entries that have invalid leg times are displayed to the operator
2428
 *      and the report process can be aborted
2429
 *
2430
 *  Parameters:
189 - 2431
 *      leg             Leg to test
91 - 2432
 *      mode            Either end or elapsed times to be tested
2433
 *
2434
 *  Returns:
2435
 *      Returns FALSE if the report operation is to be aborted
2436
 *
2437
 *========================================================================*/
2438
 
2439
bool ck_data( int leg, int mode )
2440
{
2441
    ty_s_data  *ptr;
2442
    unsigned    i;
2443
    int         bad = 0;
189 - 2444
    int         k;
2445
    int         bad_leg;
91 - 2446
    time_t     *t;                               /* An array of times */
2447
 
2448
    ptr = sort_data;
2449
    for( i = 1; i <= sort_num; i++, ptr++ )
2450
    {
2451
        bad_leg = 0;
2452
        if( mode == C_DISQUAL )
2453
        {
2454
            ptr->flags.bad_times = ptr->flags.disqualified;
2455
            continue;
2456
        }
2457
 
2458
        if( mode == C_ELAPSED )
2459
            t = ptr->lege;
2460
        else
2461
            t = ptr->leg;
2462
 
2463
 
246 - 2464
        ptr->flags.bad_times = ptr->flags.disqualified;
91 - 2465
        if( ! ptr->flags.bad_times )
2466
        {
2467
            if( leg <= 0 )
2468
            {
2469
                for( k = 0; k <= config.num_legs; k++ )
2470
                {
2471
                    if ( !(config.equestrian_leg && ptr->flags.non_equestrian && config.equestrian_leg == k  ))
2472
                        bad_leg |= ( t[k] <= 0 );
2473
                }
2474
            }
2475
            else
2476
            {
2477
                bad_leg = t[leg] <= 0;
2478
            }
2479
 
2480
            if( bad_leg )
2481
            {
2482
                ptr->flags.bad_times = TRUE;
2483
 
2484
                if ( ! report_all )
2485
                {
189 - 2486
                    printf( "Team with incorrect time information: %d", ptr->team  );
91 - 2487
                    bad++;
2488
                }
2489
            }
2490
        }
2491
    }
2492
 
2493
    if( bad )
2494
    {
189 - 2495
        printf( "%d teams with incorrect times. These have been flagged as unplaced", bad );
91 - 2496
    }
2497
    return ( FALSE );
2498
}
2499
 
2500
/*========================================================================
2501
 *
2502
 *  Update placing information
2503
 *
2504
 *  Purpose:
2505
 *      This function is called to Update placing information
2506
 *
2507
 *      This routine will rip through the data generating the team placing in
2508
 *      a) Within a leg
2509
 *      b) At the end of a leg
2510
 *      c) Within a leg by  class
2511
 *      d) At the end of a leg by class
2512
 *
2513
 *      This function is provided to allow the display routines to
2514
 *      be accessed and updated without the need to run a report
2515
 *
2516
 *  Parameters:
2517
 *      xxxx        a ptr to the xxxx stuff
2518
 *
2519
 *  Returns:
2520
 *      Nothing
2521
 *
2522
 *========================================================================*/
2523
 
2524
void srt_place(void)
2525
{
2526
    if( ck_data( -1, C_ELAPSED ) )
2527
        return;
2528
    do_big_sort();
2529
 
2530
    /*
195 david 2531
     * Generate the stats
91 - 2532
     */
2533
    gen_stats();
2534
}
2535
 
2536
/*========================================================================
2537
 *
2538
 *  Calculate summary information
2539
 *
2540
 *  Purpose:
2541
 *      This function is called to calculate summary information
2542
 *
2543
 *  Parameters:
2544
 *      ptr         - Address of a summary structure to fill in
2545
 *
2546
 *  Returns:
2547
 *      Nothing
2548
 *
2549
 *========================================================================*/
2550
 
2551
void calc_class_summary( t_class_summary * ptr )
2552
{
2553
    int i;
170 - 2554
    team_type   team_buf;
91 - 2555
 
2556
    /*
2557
    **  Reset the data
2558
    */
2559
    memset ( ptr, 0, sizeof (*ptr ));
2560
 
2561
    /*
2562
     * Extract the required data from the data base
2563
     * Only save that information required for the operation
2564
     */
2565
 
2566
    for( i = config.min_team; i <= config.max_team; i++ )
2567
    {
2568
        if( valid_field( i ) && g_record( i, &team_buf ) )
2569
        {
227 - 2570
            bool valid = true;
91 - 2571
 
2572
            if ( team_buf.flags.disqualified )
2573
            {
2574
                ptr->teamclass[team_buf.teamclass].disqualified++;
2575
                ptr->total.disqualified++;
227 - 2576
                valid = false;
228 - 2577
 
91 - 2578
            }
2579
 
225 - 2580
            if ( team_buf.flags.vet_check )
2581
            {
2582
                ptr->teamclass[team_buf.teamclass].vet_check++;
2583
                ptr->total.vet_check++;
227 - 2584
                valid = false;
225 - 2585
            }
2586
 
91 - 2587
            if ( config.nonequestrian_class && team_buf.flags.non_equestrian )
2588
            {
2589
                ptr->teamclass[team_buf.teamclass].non_equestrian++;
2590
                ptr->total.non_equestrian++;
227 - 2591
                valid = false;
91 - 2592
            }
227 - 2593
 
2594
            ptr->total.total++;
2595
            ptr->teamclass[team_buf.teamclass].total++;
2596
            if ( valid )
2597
            {
2598
                ptr->total.valid++;
2599
                ptr->teamclass[team_buf.teamclass].valid++;
2600
            }
91 - 2601
        }
2602
    }
2603
 
2604
    /*
2605
    **  Fix up the totals for the non equestrians
2606
    **  This is not a real category but a summary of the others.
2607
    */
2608
    if ( config.nonequestrian_class  )
2609
    {
2610
        ptr->teamclass[config.nonequestrian_class].total += ptr->total.non_equestrian;
227 - 2611
        ptr->teamclass[config.nonequestrian_class].valid += ptr->teamclass[config.nonequestrian_class].total;
91 - 2612
    }
2613
}
2614
 
2615
/*========================================================================
2616
 *
254 - 2617
 *  Print summary results
2618
 *
2619
 *  Purpose:
2620
 *      This function is called to Print summary results
2621
 *      Keep the page to 80 cols, so that it can be pronted on A4
2622
 *
2623
 *  Parameters:
2624
 *      None
2625
 *
2626
 *  Returns:
2627
 *      Nothing
2628
 *
2629
 *========================================================================*/
2630
void pri_summary_html(void)
2631
{
2632
    report_type saved = report_html;
2633
    /*
2634
    **  Generate ALL results with HTML tags
2635
    */
2636
    report_html = html;
2637
    pri_summary();
2638
    report_html = saved;
2639
}
2640
 
2641
/*========================================================================
2642
 *
91 - 2643
 *  Print summary information
2644
 *
2645
 *  Purpose:
2646
 *      This function is called to print summary information
2647
 *
2648
 *  Parameters:
2649
 *      None
2650
 *
2651
 *  Returns:
2652
 *      Nothing
2653
 *
2654
 *========================================================================*/
2655
 
2656
void pri_summary (void)
2657
{
2658
 
2659
    t_class_summary data;
2660
    int         i;
2661
 
254 - 2662
    if( !open_printer( "", "summary", 80, report_html, "Summary Information" ) )
91 - 2663
        return;
2664
 
2665
    calc_class_summary( & data );
2666
 
2667
 
2668
    /*
2669
    **  Display summary stats
2670
    */
2671
 
254 - 2672
    print( "%*s : %-7s %-7s%-7s%-7s%-7s\n",
2673
                                      LEN_CLASS_NAME, "Category",
91 - 2674
                                      "Total",
253 - 2675
                                      "Valid",
91 - 2676
                                      "Disq",
253 - 2677
                                      "NonEq",
2678
                                      "VetChck"
2679
                                       );
91 - 2680
 
2681
    for( i = 0; i < config.num_class; i++ )
2682
    {
2683
        /*
2684
        **  The non-equestrian leg does not have any data
2685
        **  Supress the display
2686
        */
2687
        if ( config.nonequestrian_class == i+1  )
2688
            continue;
2689
 
254 - 2690
        if ( report_html == html ) print( "<A HREF=\"%s\">",url_encode(p_filename(filebase, config.team_class[i].abr ,"html")) );
2691
        print( "%*s ", LEN_CLASS_NAME, config.team_class[i].full_name );
2692
        if ( report_html == html ) print( "</A>" );
2693
 
2694
        print( ": %-7d %-7d %-7d%-7d %-7d\n",
91 - 2695
                                          data.teamclass[i+1].total,
253 - 2696
                                          data.teamclass[i+1].valid,
91 - 2697
                                          data.teamclass[i+1].disqualified,
253 - 2698
                                          data.teamclass[i+1].non_equestrian,
2699
                                          data.teamclass[i+1].vet_check
2700
                                          );
91 - 2701
    }
2702
 
2703
    print( "\n" );
254 - 2704
    print( "%*s : %-7d %-7d %-7d%-7d %-7d\n",
2705
                                      LEN_CLASS_NAME, "Totals",
91 - 2706
                                      data.total.total,
253 - 2707
                                      data.total.valid,
91 - 2708
                                      data.total.disqualified,
253 - 2709
                                      data.total.non_equestrian,
2710
                                      data.total.vet_check
2711
                                      );
91 - 2712
 
2713
    close_printer();
2714
}
2715
 
2716
 
2717
 
2718
/*========================================================================
2719
 *
2720
 *  Main sort routine for final data
2721
 *
2722
 *  Purpose:
2723
 *      This function is called to do the report sort routine for final data
2724
 *      This routine will fill all the gaps in the sort_aux structure
2725
 *
2726
 *  Parameters:
2727
 *      None
2728
 *
2729
 *  Returns:
2730
 *      Nothing
2731
 *
2732
 *========================================================================*/
2733
 
2734
void do_big_sort(void)
2735
{
2736
    int         i, k;                            /* Looooopy things */
2737
    unsigned    j;
2738
    ty_s_data  *ptr;                             /* Pointer to sort data */
2739
    int         teamclass;                           /* Current class */
170 - 2740
    team_type   team_buf;
91 - 2741
 
2742
    for( i = 0; i <= config.num_legs; i++ )
2743
    {
2744
        /*
2745
        **  Sort on leg elapsed time
2746
        **  Then save the teams elapsed place in each leg
2747
        */
2748
        sort_team_data( i, S_L );
2749
        for( j = 1, k = 1, ptr = sort_data; j <= sort_num; ptr++, j++ )
2750
        {
2751
            if ( ptr->teamclass == config.nonequestrian_class )
2752
                continue;
2753
 
2754
            sort_aux[ptr->team].l_place[i] = k++;
2755
            sort_aux[ptr->team].team = ptr->team;
2756
        }
2757
 
2758
        /*
2759
        **  Sort on leg end time
2760
        **  Then save the teams place at the end of each leg
2761
        */
2762
        sort_team_data( i, S_LE );
2763
        for( j = 1, k = 1, ptr = sort_data; j <= sort_num; ptr++, j++ )
2764
        {
2765
            if ( ptr->teamclass == config.nonequestrian_class )
2766
                continue;
2767
 
2768
            sort_aux[ptr->team].le_place[i] = k++;
2769
        }
2770
 
2771
        /*
2772
        **  Sort on elapsed time per class
2773
        **  The save the teams elapsed place in each leg per class
2774
        */
2775
        sort_team_data( i, S_LC );
2776
        teamclass = -1;
2777
        for( k = 1, j = 1, ptr = sort_data; j <= sort_num; j++, ptr++ )
2778
        {
2779
            if( teamclass != ptr->teamclass )
2780
            {
2781
                k = 1;
2782
                teamclass = ptr->teamclass;
2783
            }
2784
            sort_aux[ptr->team].lc_place[i] = k++;
2785
        }
2786
 
2787
        /*
2788
        **  Sort on end time per class
2789
        **  Then save the teams place at the end of each leg per class
2790
        */
2791
        sort_team_data( i, S_LEC );
2792
        teamclass = -1;
2793
        for( k = 1, j = 1, ptr = sort_data; j <= sort_num; j++, ptr++ )
2794
        {
2795
            if( teamclass != ptr->teamclass )
2796
            {
2797
                k = 1;
2798
                teamclass = ptr->teamclass;
2799
            }
2800
            sort_aux[ptr->team].lec_place[i] = k++;
2801
        }
2802
    }
2803
 
2804
    /*
2805
    **  Write the place information back to disk for use in the displays
2806
    */
2807
    for( i = config.min_team; i <= config.max_team; i++ )
2808
    {
2809
        if( sort_aux[i].team && valid_field( i ) && g_record( i, &team_buf ) )
2810
        {
2811
            for( k = 0; k <= config.num_legs; k++ )
2812
            {
2813
                team_buf.leg[k].l_place = sort_aux[i].l_place[k];
2814
                team_buf.leg[k].le_place = sort_aux[i].le_place[k];
2815
                team_buf.leg[k].lc_place = sort_aux[i].lc_place[k];
2816
                team_buf.leg[k].lec_place = sort_aux[i].lec_place[k];
2817
            }
2818
            put_team_record( i, &team_buf );
2819
        }
2820
    }
2821
}
2822
 
2823
/*========================================================================
2824
 *
2825
 *  Sort in memory buffer
2826
 *
2827
 *  Purpose:
2828
 *      This function is called to Sort in memory buffer
2829
 *
2830
 *  Parameters:
2831
 *      leg         Requested leg
2832
 *      mode        Defines the sort mode
2833
 *
2834
 *  Returns:
2835
 *      Nothing
2836
 *
2837
 *========================================================================*/
2838
 
2839
void sort_team_data( int leg, int mode )
2840
{
2841
 
2842
    unsigned    j;
2843
    ty_s_data  *ptr;
2844
 
2845
    sort_leg = leg;                              /* Leg is global for the comparison function */
2846
    sort_mode = mode;                            /* Mode is global for compare function */
2847
 
2848
    qsort( ( char * ) sort_data, sort_num, sizeof( ty_s_data ), sort_comp );
2849
 
2850
    /*
2851
     * Insert "place data" into the sorted data
2852
     * This simply the index into the array of data - after its been
2853
     * sorted.
2854
     */
2855
    ptr = sort_data;
2856
    for( j = 1; j <= sort_num; j++, ptr++ )
246 - 2857
    {
91 - 2858
        ptr->place = j;
246 - 2859
    }
91 - 2860
 
2861
}
2862
 
2863
/*========================================================================
2864
 *
2865
 *  qsort comparison function
2866
 *
2867
 *  Purpose:
2868
 *      This function is called by qsort as a Sort comparison function
2869
 *
2870
 *  Parameters:
2871
 *      a       - 1st record
2872
 *      b       - 2nd record
2873
 *
2874
 *  Returns:
2875
 *      value to qsort
246 - 2876
 *      Return negative if 'a' is less than 'b',
2877
 *             zero if 'a' == 'b'
2878
 *             positive if 'a' > 'b'
91 - 2879
 *
2880
 *========================================================================*/
2881
 
2882
int sort_comp( const void * aa, const void * bb )
2883
{
2884
    const ty_s_data * a = (ty_s_data *)aa;
2885
    const ty_s_data * b = (ty_s_data *)bb;
2886
 
2887
 
2888
    int         i;                               /* One of those */
2889
    time_t      ta, tb;                          /* Leg times */
2890
    int         na, nb;                          /* Number of valid legs */
2891
    time_t      tta, ttb;                        /* Temp times */
2892
 
2893
    /*
2894
    **  Sorting on Team Number
2895
    */
2896
    if( sort_mode == S_TEAM )
2897
        return ( a->team - b->team );
2898
 
2899
    /*
2900
    **  Sorting on Class and Team Number
2901
    */
2902
    if( sort_mode == S_CLASS )
2903
    {
2904
        if( a->teamclass != b->teamclass )
2905
            return ( a->teamclass - b->teamclass );
2906
        else
2907
            return ( a->team - b->team );
2908
    }
2909
 
2910
    /*
2911
    **  Sorting within a class
2912
    **  First sort on the class
2913
    */
227 - 2914
    if( sort_mode == S_LEC || sort_mode == S_LC || sort_mode == S_LC_NE )   /* Sort within a class */
91 - 2915
        if( a->teamclass != b->teamclass )
2916
            return ( a->teamclass - b->teamclass );
2917
 
2918
    /*
2919
    **  Always put the nonequestrian_class at the end
2920
    **  Simplifies the creation of ordered lists as these
2921
    **  Entries are not present in the main body
2922
    */
2923
    if ( a->teamclass == config.nonequestrian_class ||  b->teamclass == config.nonequestrian_class )
2924
    {
2925
        if ( a->teamclass == config.nonequestrian_class &&  b->teamclass == config.nonequestrian_class )
2926
        {
246 - 2927
            /*
2928
            **  Both are non equestrian
2929
            **      S_LC_NE - Elapsed times per class, with NE sorted by real class
2930
            **                Only used in awards
2931
            */
227 - 2932
            if (sort_mode == S_LC_NE )
2933
            {
2934
                if ( a->real_teamclass != b->real_teamclass )
2935
                {
2936
                    return ( a->real_teamclass - b->real_teamclass );
2937
                }
2938
            }
91 - 2939
        }
2940
        else
2941
        {
246 - 2942
            /*
2943
            **  Only one in non-equestrian
2944
            **  Place Non-equestrian AFTER equestrian
2945
            */
91 - 2946
            return ( a->teamclass == config.nonequestrian_class ? 1 : -1 );
2947
        }
2948
 
2949
    }
2950
 
2951
    /*
2952
    **  Now we need to examine the times as we have sorted
2953
    **  on every thing else.
2954
    **
2955
    **  If one of the teams has bad_times, then that team is placed
2956
    **  lower in the sorting order. If both teams have bad times
2957
    **  then sort on team number. ie: Unplaced teams are sorted on
2958
    **  team number
2959
    **
2960
    **  If not sorting within a class (ie Overall), then Non_Equestrian
2961
    **  is better than a bad time. Places NE before disqualified
2962
    **
2963
    */
246 - 2964
    if( a->flags.bad_times || b->flags.bad_times || a->flags.non_equestrian || b->flags.non_equestrian)  /* Valid data has precedence */
91 - 2965
    {
2966
        if( a->flags.bad_times && b->flags.bad_times )
2967
        {
246 - 2968
            return ( a->team - b->team );
91 - 2969
        }
246 - 2970
        else if( a->flags.bad_times || b->flags.bad_times )
2971
        {
91 - 2972
            return ( a->flags.bad_times ? 1 : -1 );
246 - 2973
        }
2974
        if( sort_mode != S_FIN && sort_mode != S_IFIN )
91 - 2975
        {
2976
            if( a->flags.non_equestrian && b->flags.non_equestrian )
246 - 2977
            {
2978
                /*
2979
                **  Both are non equestrian
2980
                **  Let the time sort operate ...
2981
                */
2982
                //return ( a->team - b->team );
2983
            }
91 - 2984
            else
246 - 2985
            {
2986
                /* One is equestrian */
2987
                /* Good times better than NE */
91 - 2988
                return ( a->flags.non_equestrian ? 1 : -1 );
246 - 2989
            }
91 - 2990
        }
2991
    }
2992
 
2993
    /*
2994
    **  Before we sort on times we must determine which time to
2995
    **  use. Finish time, Leg end times, Leg Elapsed times.
2996
    */
2997
 
2998
    switch ( sort_mode )
2999
    {
3000
      /*
3001
      **    Sort on finish times
3002
      */
3003
      case S_FIN:
3004
        ta = a->leg[sort_leg];
3005
        tb = b->leg[sort_leg];
3006
        break;
3007
 
3008
 
3009
      /*
3010
      **    Sort on accumulated leg times
3011
      */
3012
      case S_LE:
3013
      case S_LEC:
3014
        if( sort_leg )
3015
        {
3016
            /*
3017
            **  Calculate accumulated time up to the desired leg
3018
            **  If the two teams have a different number of valid
3019
            **  leg times then order by the team that has completed
3020
            **  more legs.
3021
            */
3022
            ta = tb = ( time_t ) 0;
3023
            na = nb = 0;
3024
            for( i = 1; i <= sort_leg; i++ )
3025
            {
3026
                tta = a->lege[i];
3027
                ttb = b->lege[i];
3028
                if( tta > 0 )
3029
                {
3030
                    na++;
3031
                    ta += tta;
3032
                }
3033
                if( ttb > 0 )
3034
                {
3035
                    nb++;
3036
                    tb += ttb;
3037
                }
3038
            }
3039
            if( na != nb )
3040
                return ( nb - na );
3041
        }
3042
        else
3043
        {
3044
            ta = a->leg[sort_leg] - a->start;
3045
            tb = b->leg[sort_leg] - b->start;
3046
        }
3047
        break;
3048
 
3049
      /*
3050
      **    Sort on Elapsed times
3051
      */
227 - 3052
      case S_LC_NE:
91 - 3053
      case S_LC:
3054
      case S_L:
246 - 3055
      case S_IFIN:
91 - 3056
        ta = a->lege[sort_leg];
3057
        tb = b->lege[sort_leg];
3058
        break;
3059
 
3060
      /*
3061
      **    Just to be sure ...
3062
      */
3063
      default:
3064
        return ( 0 );
3065
    }
3066
 
3067
    /*
3068
    **  Finally. Compare the required team times
3069
    */
3070
    if( ta == tb )
3071
        return ( a->team - b->team );
3072
    if( ( ta > 0 ) && ( tb > 0 ) )
3073
        return ( ( int ) ( ta - tb ) );
3074
    return ( ( ta > 0 ) ? -1 : 1 );
3075
}
3076
 
3077
/*========================================================================
3078
 *
3079
 *  qsort comparison function - competitor names
3080
 *
3081
 *  Purpose:
3082
 *      This function is called by qsort as a Sort comparison function
3083
 *
3084
 *  Parameters:
3085
 *      a       - 1st record
3086
 *      b       - 2nd record
3087
 *
3088
 *  Returns:
3089
 *      value to qsort
3090
 *
3091
 *========================================================================*/
3092
 
3093
int sort_comp_cname( const void * aa, const void * bb )
3094
{
3095
    ty_s_namedata * a = (ty_s_namedata *)aa;
3096
    ty_s_namedata * b = (ty_s_namedata *)bb;
3097
 
3098
 
3099
    int         i;                               /* One of those */
3100
 
3101
    /*
3102
    **  Sort by name
3103
    */
3104
    i = strcmp ( a->name, b->name );
3105
    if ( i )
3106
        return ( i );
3107
    a->multi=1;
3108
    b->multi=1;
3109
 
3110
    /*
3111
    **  Sort by Leg
3112
    */
3113
    i = a->leg - b->leg;
3114
    if ( i )
3115
        return ( i );
3116
 
3117
    /*
3118
    **  Sorting on Team Number
3119
    */
3120
    return ( a->team - b->team );
3121
 
3122
}
3123
 
3124
/*========================================================================
3125
 *
3126
 *  load report data into memory
3127
 *
3128
 *  Purpose:
3129
 *      This routine will pull all the data into memory 
3130
 *      Not all the team data is loaded. Only that essential for the
3131
 *      operation of the sort routine is loaded
3132
 *
3133
 *  Parameters:
3134
 *      None
3135
 *
3136
 *  Returns:
3137
 *      TRUE - All is well
3138
 *
3139
 *========================================================================*/
3140
 
3141
bool load_report_data(void)
3142
{
3143
 
3144
    ty_s_data  *ptr;                             /* pointer to sort data type */
3145
    ty_s_data  *last;
3146
    int         j;
3147
    unsigned    num;
170 - 3148
    team_type   team_buf;
91 - 3149
 
3150
    /*
3151
     * Fetch memory for the data store
3152
     */
3153
 
3154
    if( sort_data )
3155
        free( ( char * ) sort_data );
3156
    sort_data = 0;
3157
 
3158
    if( sort_aux )
3159
        free( ( char * ) sort_aux );
3160
    sort_aux = 0;
3161
    sort_num = 0;                                /* Counter of records in the array */
3162
 
3163
    /*
3164
    **  Allocate memory for the data structures
3165
    **  This will be free'd
3166
    */
3167
    num = config.max_team - config.min_team + 1 ;
3168
 
3169
    /*
3170
    **  Allow for non-equestrian teams - since some of the data is loaded twice
3171
    **  Take a guess that at most 1/2 the teams will be non-equestrian
3172
    */
3173
    num = num * 3 / 2;
3174
 
3175
    sort_data = ( ty_s_data * ) calloc ( num , sizeof( ty_s_data ) );
3176
    sort_aux = ( ty_s_aux * ) calloc( num + 1, sizeof( ty_s_aux ) );
3177
 
3178
    if( sort_data == 0 || sort_aux == 0 )
3179
    {
170 - 3180
        MainWindow::showMessage("Error in allocating memory");
91 - 3181
        return ( FALSE );
3182
    }
3183
 
3184
    /*
3185
    **  Load data into the memory based data structure
3186
    **  Only load data for valid-teams
3187
    **  Load essential data
3188
    **      Team Number, class and flags
3189
    **      Leg end and elapsed times
3190
    */
3191
    ptr = sort_data;
170 - 3192
    for( int team = config.min_team; team <= config.max_team; team++ )
91 - 3193
    {
3194
        if( valid_field( team ) )
3195
        {
3196
            g_record( team, &team_buf );
3197
            if( team_buf.flags.valid )
3198
            {
3199
                last = ptr;
3200
                ptr->team = team;
3201
                for( j = 0; j < MAX_LEGS + 1; j++ )
3202
                {
3203
                    ptr->lege[j] = team_buf.leg[j].elapsed;
3204
                    ptr->leg[j] = team_buf.leg[j].end;
3205
                }
3206
                ptr->start = team_buf.leg[0].start;
3207
                ptr->teamclass = team_buf.teamclass;
227 - 3208
                ptr->real_teamclass = team_buf.teamclass;
91 - 3209
 
3210
                ptr->flags = team_buf.flags;
246 - 3211
//                if (ptr->flags.non_equestrian)
3212
//                    ptr->flags.disqualified = true;
225 - 3213
                if (ptr->flags.vet_check)
3214
                    ptr->flags.disqualified = true;
246 - 3215
 
91 - 3216
                ptr++;
3217
                sort_num++;
3218
 
246 - 3219
 
91 - 3220
                /*
3221
                **  If non-equestrian support is enabled then
3222
                **  duplicate and modify data for the non-equestrian teams
3223
                **      - Change the class
3224
                **      - Modify the leg time
3225
                */
3226
#if 1
3227
                if ( config.nonequestrian_class && team_buf.flags.non_equestrian )
3228
                {
3229
                    ptr->team = team;
3230
                    ptr->lege[0] = 0;
3231
 
3232
                    for( j = 0; j < MAX_LEGS + 1; j++ )
3233
                    {
3234
                        if ( j == config.equestrian_leg )
3235
                        {
3236
                            last->lege[j] = ptr->lege[j] = 0;
3237
                            if ( config.equestrian_leg > 1 )
3238
                                last->leg[j] = ptr->leg[j] = ptr->leg[j-1];
3239
                        }
3240
                        else
3241
                        {
3242
                            if ( j )
3243
                                last-> lege[j] = ptr->lege[j] = team_buf.leg[j].elapsed;
3244
                            last->leg[j] = ptr->leg[j] = team_buf.leg[j].end;
3245
                            ptr->lege[0] += ptr->lege[j] ;
3246
                            last->lege[0] = ptr->lege[0] ;
3247
                        }
3248
                    }
3249
 
3250
                    last->start = ptr->start = team_buf.leg[0].start;
3251
                    ptr->teamclass = config.nonequestrian_class;
227 - 3252
                    ptr->real_teamclass = team_buf.teamclass;
91 - 3253
                    ptr->flags = team_buf.flags;
246 - 3254
//                    ptr->flags.disqualified = false;
91 - 3255
 
3256
                    ptr++;
3257
                    sort_num++;
3258
                }
3259
#endif
3260
            }
3261
        }
3262
    }
3263
    return ( TRUE );
3264
}
3265
 
3266
/*========================================================================
3267
 *
3268
 *  Generate all the stats
3269
 *
3270
 *  Purpose:
3271
 *      This function is called to Generate all the stats
3272
 *
3273
 *  Parameters:
3274
 *      None
3275
 *
3276
 *  Returns:
3277
 *      Nothing
3278
 *
3279
 *========================================================================*/
3280
 
3281
void gen_stats(void)
3282
{
3283
    ty_s_data  *ptr;
3284
    unsigned    i;
3285
    int         j;
3286
    int         k;
3287
 
3288
    /*
3289
     * Init all the stats 
3290
     */
3291
    for( i = 0; i <= MAX_LEGS; i++ )
3292
    {
3293
        for( j = 0; j <= MAX_CLASS; j++ )
3294
        {
3295
            stats.team[i][j] = 0;
3296
            stats.fast.team[i][j] = 0;
3297
            stats.fast.time[i][j] = ( time_t ) - 1;
3298
            stats.average[i][j] = 0;
3299
        }
3300
    }
3301
 
3302
    for( i = 1, ptr = sort_data; i <= sort_num; i++, ptr++ )
3303
    {
3304
        /*
3305
        **  If there is any bad times in the team record, then none
3306
        **  of the data can be trusted.
3307
        **
3308
        **  If the team has been disqualified, then don't use any
3309
        **  of the data.
3310
        */
246 - 3311
        if( ptr->flags.bad_times || ptr->flags.disqualified  )
91 - 3312
            continue;
3313
 
246 - 3314
        /*
3315
        **  Ignore non-Equestrian, unless we are processing the psuedo NE class
3316
        */
3317
        if ( ptr->teamclass != config.nonequestrian_class && ptr->flags.non_equestrian)
3318
            continue;
3319
 
3320
 
91 - 3321
        for( j = 0; j <= config.num_legs; j++ )
3322
        {
3323
            if( ptr->lege[j] <= 0 )              /* Ignore bad data */
3324
                continue;
3325
 
3326
            /*
3327
            **  Determine fastest team : overall
3328
            **  Ignore the non-equestrian data as this is in the list twice
3329
            */
3330
            if( ( ptr->lege[j] < stats.fast.time[j][0] )
3331
                || ( stats.fast.time[j][0] < 0 ) )
3332
            {
3333
                if ( ptr->teamclass != config.nonequestrian_class )
3334
                {
3335
                    stats.fast.team[j][0] = ptr->team;
3336
                    stats.fast.time[j][0] = ptr->lege[j];
3337
                }
3338
            }
3339
 
3340
            /*
3341
            **  Determine fastest team : within a class
3342
            */
3343
            if( ( ptr->lege[j] < stats.fast.time[j][ptr->teamclass] )
3344
                || stats.fast.time[j][ptr->teamclass] < 0 )
3345
            {
3346
                stats.fast.team[j][ptr->teamclass] = ptr->team;
3347
                stats.fast.time[j][ptr->teamclass] = ptr->lege[j];
3348
            }
3349
 
3350
            /*
3351
            **  Sum the end times : overall
3352
            */
3353
            if ( ptr->teamclass != config.nonequestrian_class )
3354
            {
3355
                stats.average[j][0] += ptr->lege[j];
3356
                stats.team[j][0]++;
3357
            }
3358
 
3359
 
3360
            /*
3361
            **  Sum the end times : within a class
3362
            */
3363
            stats.average[j][ptr->teamclass] += ptr->lege[j];
3364
            stats.team[j][ptr->teamclass]++;
3365
        }
3366
    }
3367
 
3368
    /*
3369
     * Calculate the averages
3370
     */
3371
    for( k = 0; k <= config.num_legs; k++ )
3372
    {
3373
        for( j = 0; j <= config.num_class; j++ )
3374
        {
3375
            if( stats.team[k][j] )
3376
                stats.average[k][j] /= stats.team[k][j];
3377
            else
3378
                stats.average[k][j] = ( time_t ) - 1;
3379
        }
3380
    }
3381
}
3382
 
3383
/********************************* EOF ***********************************/