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