Subversion Repositories svn1-original

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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