Subversion Repositories svn1

Rev

Rev 355 | Details | Compare with Previous | Last modification | View Log | RSS feed

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