Subversion Repositories svn1-original

Rev

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

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