Subversion Repositories svn1-original

Rev

Details | Last modification | View Log | RSS feed

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