Subversion Repositories svn1-original

Rev

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