Subversion Repositories svn1-original

Rev

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

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