Subversion Repositories svn1-original

Rev

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

Rev Author Line No. Line
95 - 1
/*************************************************************************
2
*           Copyright (C) 1995 Embedded Solutions
3
*                       All rights reserved
4
*
5
* file:     src\config.c
6
*
7
* purpose:  Configuration module
8
*           This module will read in the configuration file and set up
9
*           all the configuration parameters
10
*
11
* functions
12
*       compact                 - Compact a string
13
*       conf_menu               - Configuration Menu
14
*       configure               - Read in the configuration file
15
*       d_class                 - Update the class information
16
*       d_cntry                 - Display / Update Country list
17
*       d_config                - Configuration Update and Display
18
*       define_class            - Update the class information
19
*       define_config           - Alter the configuration file
20
*       define_country          - Define a new entry in the county list
21
*       display_class           - Display the class information
22
*       display_config          - Display the marathon configuration
23
*       display_country         - Display the current country list
24
*       f_comp_int              - Qsort callback: Sort by team
25
*       r_config                - Read in the configuration file
26
*       rd_config               - Read in the configuration file
27
*       valid_field             - Validate a team number
28
*       wt_config               - Write out the configuration file
29
*
30
* programmer: David Purdie
31
*
32
* revision  date        by      reason
33
*   00.0    27/01/95    DDP     Tidies up the program and formatted the file
34
*
35
**************************************************************************/
36
 
37
#include    "consts.h"
38
#include    "structs.h"
39
#include    "proto.h"
40
 
99 david 41
#include    "QApplication"
42
 
95 - 43
/*
44
**  Local definitions
45
*/
46
char        confile[20];                         /* Name of the config file */
47
char        datfile[20];                         /* Name of the data file */
48
char        filebase[20];                        /* Event file name base */
49
 
50
MARA_CFG    config;                              /* Working configuration */
51
MARA_CFG    newcfg;                              /* Play configuration */
52
 
53
t_class_summary class_summary;                   /* Class summary data */
54
 
55
menu_table  cnf_menu[] = {
56
    {'1', "Display current configuration", display_config},
57
    {'2', "Alter configuration", ( void ( * )( void ) ) define_config},
58
    {'3', "Display category configuration", display_class},
59
    {'4', "Alter category configuration", ( void ( * )( void ) ) define_class},
60
    {'5', "Display country list", display_country},
61
    {'6', "Alter country list", define_country},
62
    {'7', "Display winners list", display_winners},
63
    {'8', "Alter winners list",  ( void ( * )( void ) ) define_winners},
64
    {'q', "Return to main menu", 0},
65
    {'\0'}
66
};
67
 
68
/*========================================================================
69
 *
70
 *  Read in the configuration file
71
 *
72
 *  Purpose:
73
 *      This function is called to read in the configuration file
74
 *
75
 *  Parameters:
76
 *      c_name      Name of the configuartion file
77
 *      mode        TRUE: Create the file
78
 *
79
 *  Returns:
80
 *      Returns TRUE if the system was configured ok
81
 *
82
 *========================================================================*/
83
 
84
bool configure( char *c_name, int mode )
85
{
86
 
87
    FILE        * fcon;
88
    bool        ok = FALSE;
89
 
90
    strncpy( filebase, c_name, 8 );
91
    strcpy( confile, filebase );
92
    strcat( confile, ".cnf" );
93
    strcpy( datfile, filebase );
94
    strcat( datfile, ".dat" );
95
 
96
    fcon = fopen( confile, "rb" );
97
    if ( fcon )
98
        fclose( fcon );
99
 
100
    if( mode )
101
    {
102
        if( fcon )
103
        {
104
            printf( "Configuration file already exists\n" );
105
            ok = FALSE;
106
        }
107
        else
108
        {
109
            ok = define_config(  );              /* Generate the configuration */
110
            if( ok )
111
                ok = define_class(  );
112
        }
113
    }
114
    else if( fcon )
115
        ok = rd_config(  );                      /* read in the existing config */
116
    else
117
    {
118
        ok = FALSE;
119
        printf( "Configuration file not found\n" );
120
    }
121
 
122
    /*
123
     **  Post read calculations and fixups
124
     */
125
    if( config.datafilename[0] )
126
    {
127
        strcpy( datfile, config.datafilename );
128
        strcat( datfile, ".dat" );
129
    }
130
    config.nonequestrian_class = lookup_class( config.nonequestrian_class_abr, &config );
131
    return ( ok );
132
}
133
 
134
/*========================================================================
135
 *
136
 *  Configuration Menu
137
 *
138
 *  Purpose:
139
 *      This function is called to display the configuartion menu
140
 *
141
 *  Parameters:
142
 *      None
143
 *
144
 *  Returns:
145
 *      Nothing
146
 *
147
 *========================================================================*/
148
 
149
void conf_menu( void )
150
{
151
    do_menu( "Event configuration", "Select option", cnf_menu );
152
}
153
 
154
/*========================================================================
155
 *
156
 *  Alter the configuration file
157
 *
158
 *  Purpose:
159
 *      This function is called to alter the configuration file
160
 *
161
 *  Parameters:
162
 *      None
163
 *
164
 *  Returns:
165
 *      TRUE    - Configuration changed
166
 *      FALSE   - Configuration not changed
167
 *
168
 *========================================================================*/
169
 
170
bool define_config( void )
171
{
172
    int         i, j;
173
    int         error;
174
    bool        changed = FALSE;
175
    int         num_teams;
176
 
177
    /*
178
     **  Copy working configuration into a temp structure for
179
     **  use within the function
180
     */
181
    newcfg = config;
182
 
183
    do
184
    {
185
        error = 0;
186
        num_teams = 0;
187
        d_config( &newcfg, M_UPDATE );
188
        printf( "\n" );
189
 
190
        compact( newcfg.event_name );               /* Rip of leading white_space */
191
        for( i = 0; i < MAX_LEGS; i++ )
192
            compact( newcfg.leg_name[i] );
193
        compact( newcfg.addendum );
194
        compact( newcfg.datafilename );
195
 
196
        /*
197
         * Do all sorts of consistency tests on the data 
198
         * Firstly - calculate the number of legs. Justify the data in the array
199
         */
200
 
201
        newcfg.num_legs = 0;
202
        for( i = 0; i < MAX_LEGS; i++ )
203
            if( newcfg.leg_name[i][0] )
204
                newcfg.num_legs++;
205
        for( i = newcfg.num_legs; i < MAX_LEGS; i++ )
206
            if( newcfg.leg_name[i][0] )
207
            {
208
                printf( "Configuration error: Missing leg\n" );
209
                error++;
210
            }
211
 
212
 
213
        /*
214
         * Now do the team numbering stuff 
215
         */
216
 
217
        for( i = 0; i < MAX_TMS_SPLIT; i++ )
218
        {
219
            if( newcfg.t_def[i].start == 0 && newcfg.t_def[i].end == 0 )
220
                continue;
221
            if( newcfg.t_def[i].start > newcfg.t_def[i].end )
222
            {
223
                printf
224
                    ( "Team definition error : End greater than start. %d to %d\n",
225
                      newcfg.t_def[i].start, newcfg.t_def[i].end );
226
                error++;
227
            }
228
            for( j = 0; j < i; j++ )
229
            {
230
                if( ( newcfg.t_def[i].start >= newcfg.t_def[j].start
231
                      && newcfg.t_def[i].start <= newcfg.t_def[j].end )
232
                    || ( newcfg.t_def[i].end >= newcfg.t_def[j].start
233
                         && newcfg.t_def[i].end <= newcfg.t_def[j].end ) )
234
                {
235
                    printf
236
                        ( "Team definition error : Overlapping definition. %d to %d\n",
237
                          newcfg.t_def[i].start, newcfg.t_def[i].end );
238
                    error++;
239
                }
240
            }
241
        }
242
 
243
        /*
244
         * Determine the number of team splits
245
         * There may be blank entries - these will be removed by sorting the array
246
         */
247
        qsort( ( char * ) newcfg.t_def, MAX_TMS_SPLIT, sizeof( *newcfg.t_def ), f_comp_int );
248
        for( newcfg.num_teams = 0; newcfg.num_teams < MAX_TMS_SPLIT; newcfg.num_teams++ )
249
            if( !newcfg.t_def[newcfg.num_teams].start )
250
                break;
251
 
252
        newcfg.min_team = newcfg.t_def[0].start;
253
        newcfg.max_team = newcfg.t_def[newcfg.num_teams - 1].end;
254
 
255
        /*
256
         **  Limit the number of entrants
257
         */
258
        for( i = 0; i < MAX_TMS_SPLIT; i++ )
259
        {
260
            if( newcfg.t_def[i].start )
261
            {
262
                num_teams += newcfg.t_def[i].end - newcfg.t_def[i].start + 1;
263
            }
264
        }
265
#if defined(LIMIT_TEAMS) && (LIMIT_TEAMS > 0)
266
        if( num_teams > LIMIT_TEAMS )
267
        {
268
            printf( "Maximum number of teams exceeded - reduce number of teams\n" );
269
            error++;
270
        }
271
#endif
272
 
273
#if defined (HI_TECH_C) || defined (__TURBOC__)
274
 
275
        /*
276
         * Ensure that the number of teams allocated can fit within available
277
         * Memory space. Ie: Can we malloc the report data structures
278
         */
279
        {
280
            long        sz;
281
 
282
            sz = sizeof( ty_s_data ) > sizeof( ty_s_aux ) ?
283
                sizeof( ty_s_data ) : sizeof( ty_s_aux );
284
            if( sz * ( newcfg.max_team - newcfg.min_team + 2 ) > ( 1024L * 64L ) )
285
            {
286
                printf( "Too many teams: Reduce team spread.\n" );
287
                error++;
288
            }
289
        }
290
#endif
291
 
292
        /*
293
         **  Ensure the non-equestrian class and the equestrian leg are valid
294
         */
295
        if( newcfg.equestrian_leg )
296
        {
297
            if( newcfg.equestrian_leg > newcfg.num_legs )
298
            {
299
                printf( "Invalid non-equestrian leg number.\n" );
300
                error++;
301
            }
302
 
303
            /*
304
             **  Ensure that the entered non-equestrian class name does exist
305
             */
306
            newcfg.nonequestrian_class = lookup_class( newcfg.nonequestrian_class_abr, &newcfg );
307
            if( newcfg.nonequestrian_class == 0 )
308
                printf( "WARNING: Non-equestrian class not found\n" );
309
        }
310
 
311
        abort_flag = FALSE;
312
        if( error )
313
        {
314
            printf( "Configuration error - error must be corrected\n" );
315
            printf( "Any key to continue " );
316
            ( void ) getinp(  );
317
            continue;
318
        }
319
        else
320
        {
321
            printf( "Install configuration (Y)es, (D)iscard, (E)dit again :" );
322
            switch ( getfnc( "*YDEA" ) )
323
            {
324
            case 'Y':
325
                error = ( newcfg.num_legs == 0 || newcfg.num_teams == 0 );
326
                if( error )
327
                    printf( "\nConfiguration not installed. No legs or teams defined\n" );
328
                else
329
                {
330
                    config = newcfg;
331
                    wt_config(  );               /* Write out the data */
332
                    changed = TRUE;
333
                }
334
                break;
335
 
336
            case 'D':
337
                break;
338
 
339
            default:
340
                error = TRUE;
341
                break;
342
            }
343
        }
344
    }
345
    while( error );
346
 
347
    return ( changed );
348
}
349
 
350
 
351
/*========================================================================
352
 *
353
 *  Display the marathon configuration
354
 *
355
 *  Purpose:
356
 *      This function is called to Display the marathon configuration
357
 *
358
 *  Parameters:
359
 *      None
360
 *
361
 *  Returns:
362
 *      Nothing
363
 *
364
 *========================================================================*/
365
 
366
void display_config( void )
367
{
368
    d_config( &config, M_DISPLAY );
369
 
370
    cur( 0, n_lines - 1 );
371
    printf( "Any key to return to main menu :" );
372
    getinp(  );
373
}
374
 
375
 
376
/*========================================================================
377
 *
378
 *  Display the class information
379
 *
380
 *  Purpose:
381
 *      This function is called to display the class information
382
 *
383
 *  Parameters:
384
 *      None
385
 *
386
 *  Returns:
387
 *      Nothing
388
 *
389
 *========================================================================*/
390
 
391
void display_class( void )
392
{
393
    d_class( &config, M_DISPLAY );
394
 
395
    cur( 0, n_lines - 1 );
396
    printf( "Any key to continue :" );
397
    getinp(  );
398
}
399
 
400
/*========================================================================
401
 *
402
 *  Update the class information
403
 *
404
 *  Purpose:
405
 *      This function is called to update the class information
406
 *
407
 *  Parameters:
408
 *      None
409
 *
410
 *  Returns:
411
 *      Nothing
412
 *
413
 *========================================================================*/
414
 
415
bool define_class( void )
416
{
417
    int         error;
418
    int         i;
419
    bool        changed = FALSE;
420
 
421
    /*
422
     **  Copy working configuration into a temp structure for
423
     **  use within the function
424
     */
425
    newcfg = config;
426
 
427
    do
428
    {
429
        error = 0;
430
        d_class( &newcfg, M_UPDATE );
431
        printf( "\n" );
432
 
433
        /*
434
         **  Now do the Class definitions
435
         */
436
        for( i = 0; i < MAX_CLASS; i++ )
437
        {
438
            compact( newcfg.team_class[i].abr );
439
            compact( newcfg.team_class[i].full_name );
440
        }
441
 
442
        for( i = 0; i < MAX_CLASS; i++ )
443
        {
444
            if( ( newcfg.team_class[i].abr[0] == '\0' ) != ( newcfg.team_class[i].full_name[0] == '\0' ) )
445
            {
446
                printf( "Configuration error. Class without description\n" );
447
                error++;
448
            }
449
            if( newcfg.team_class[i].abr[0] != '\0' && newcfg.team_class[i].start < 0L )
450
            {
451
                printf( "Configuration error. Bad start time on class\n" );
452
                error++;
453
            }
454
        }
455
 
456
        newcfg.num_class = 0;
457
        for( i = 0; i < MAX_CLASS; i++ )
458
            if( newcfg.team_class[i].full_name[0] )
459
                newcfg.num_class++;
460
 
461
        for( i = newcfg.num_class; i < MAX_CLASS; i++ )
462
            if( newcfg.team_class[i].full_name[0] )
463
            {
464
                printf( "Configuration error: Missing Class name. Gaps not allowed\n" );
465
                error++;
466
            }
467
 
468
        if( newcfg.num_class == 0 )
469
        {
470
            printf( "Error: No categories defined\n" );
471
            error++;
472
        }
473
 
474
        newcfg.nonequestrian_class = lookup_class( newcfg.nonequestrian_class_abr, &newcfg );
475
        if( newcfg.equestrian_leg && newcfg.nonequestrian_class == 0 )
476
            printf( "WARNING: Non-equestrian class not found\n" );
477
 
478
        abort_flag = FALSE;
479
        if( error )
480
        {
481
            printf( "Any key to continue " );
482
            getinp(  );
483
        }
484
        else
485
        {
486
            printf( "Install configuration (Y)es, (D)iscard, (E)dit again :" );
487
            switch ( getfnc( "*YDEA" ) )
488
            {
489
            case 'Y':
490
                config = newcfg;
491
                wt_config(  );
492
                changed = TRUE;
493
                break;
494
 
495
            case 'D':
496
                break;
497
 
498
            default:
499
                error = TRUE;
500
                break;
501
            }
502
        }
503
    } while( error && ! abort_flag );
504
    return ( changed );
505
}
506
 
507
/*========================================================================
508
 *
509
 *  Update the class information
510
 *
511
 *  Purpose:
512
 *      This function is called to update the class information
513
 *      Display the marathon classes from the system parameters.
514
 *
515
 *      This routine can only be utilized after the screen system
516
 *      has been initialized.
517
 *
518
 *  Parameters:
519
 *      operation       Operation to perform
520
 *
521
 *  Returns:
522
 *      Nothing
523
 *
524
 *========================================================================*/
525
 
526
void d_class( MARA_CFG * config, int operation )
527
{
528
    int         i, j, k;
529
    int         maxitr;                          /* Max number of definitions during update */
530
    int         opr;
531
 
532
    abort_flag = FALSE;
533
    if( operation == M_UPDATE )
534
    {
535
        opr = M_UPDATE;
536
        d_class( config, M_PREDISPLAY );         /* Force display before update */
537
    }
538
    else
539
    {
540
        opr = M_DISPLAY;
541
        clearscreen(  );
542
    }
543
 
544
    i = 0;                                       /* Set line 0 */
545
    d_field( 0, i++, "Category definitions", D_NULL, 0, ( char * ) 0, TRUE, M_DISPLAY );
546
    i++;
547
 
548
    maxitr = ( operation == M_DISPLAY ) ? config->num_class : MAX_CLASS;
549
 
550
    for( j = 0, k = 0; j < maxitr; j++ )
551
    {
552
        bool        non_equestrian = FALSE;
553
 
554
        d_field( 0 + k, i, "Cat:", D_USTRING, 2, ( char * ) config->team_class[j].abr, TRUE, opr );
555
 
556
        if( ( config->team_class[j].abr[0] == config->nonequestrian_class_abr[0] )
557
            && ( config->team_class[j].abr[1] == config->nonequestrian_class_abr[1] ) )
558
        {
559
            non_equestrian = TRUE;
560
        }
561
 
562
        d_field( 8 + k, i, ":", D_STRING, LEN_CLASS_NAME,
563
                 config->team_class[j].full_name, TRUE, opr );
564
 
565
        if( !non_equestrian )
566
            d_field( LEN_CLASS_NAME + 10 + k, i, "Start:", D_TIME, 8,
567
                     ( char * ) &config->team_class[j].start, TRUE, opr );
568
 
569
        /*
570
         **  Step to next column or row
571
         */
572
        k += 40;
573
        if( !( ( j + 1 ) % 2 ) )
574
        {
575
            k = 0;
576
            i++;
577
        }
578
    }
579
}
580
 
581
/*========================================================================
582
 *
583
 *  Configuration Update and Display
584
 *
585
 *  Purpose:
586
 *      This function is called to Configuration Update and Display
587
 *
588
 *  Parameters:
589
 *      operation       Operation to perform
590
 *
591
 *  Returns:
592
 *      Nothing
593
 *
594
 *========================================================================*/
595
 
596
void d_config( MARA_CFG * config, int operation )
597
{
598
    int         i, j, k;
599
    int         maxitr;                          /* Max number of definitions during update */
600
    int         opr;
601
 
602
    abort_flag = FALSE;
603
    if( operation == M_UPDATE )
604
    {
605
        opr = M_UPDATE;
606
        d_config( config, M_PREDISPLAY );        /* Force display before update */
607
    }
608
    else
609
    {
610
        opr = M_DISPLAY;
611
        clearscreen(  );
612
    }
613
    i = 0;                                       /* Set line 0 */
614
 
615
    d_field( 0, i++, "Marathon configuration", D_NULL, 0, ( char * ) 0, TRUE, M_DISPLAY );
616
    d_field( 0, ++i, "Name: ", D_STRING, MAX_EVENT_NAME, config->event_name, TRUE, opr );
617
 
618
    /*
619
     * display the leg names 
620
     */
621
 
622
    i += 2;
623
    maxitr = ( operation == M_DISPLAY ) ? config->num_legs : MAX_LEGS;
624
    for( j = 1; j <= maxitr; j++, i++ )
625
    {
626
        d_field( 0, i, "Leg ", D_NUMBER, 1, ( char * ) &j, TRUE, M_DISPLAY );
627
        d_field( 6, i, ": ", D_STRING, MAX_LEG_NAME, config->leg_name[j - 1], TRUE, opr );
628
    }
629
    abort_flag = FALSE;                          /* Trap aborts at the next field */
630
 
631
 
632
    /*
633
     * Display the team break definitions 
634
     */
635
 
636
    i++;
637
 
638
    d_field( 0, i++, "Valid team numbers are in the following ranges", D_NULL,
639
             0, ( char * ) 0, TRUE, M_DISPLAY );
640
 
641
    maxitr = ( operation == M_DISPLAY ) ? config->num_teams : MAX_TMS_SPLIT;
642
    for( k = 0, j = 0; j < maxitr; j++ )
643
    {
644
        d_field( k + 0, i, "From ", D_NUMBER, 4, ( char * ) &config->t_def[j].start, TRUE, opr );
645
        d_field( k + 9, i, " to ", D_NUMBER, 4, ( char * ) &config->t_def[j].end, TRUE, opr );
646
        k += 20;
647
        if( !( ( j + 1 ) % 4 ) )
648
        {
649
            k = 0;
650
            i++;
651
        }
652
    }
653
 
654
    /*
655
     * Name of legend config->addendum file 
656
     */
657
 
658
    abort_flag = FALSE;
659
    i++;
660
    d_field( 0, i++, "Legend addendum file :", D_STRING,
661
             ( int ) sizeof( config->addendum ) - 1, ( char * ) config->addendum, TRUE, opr );
662
 
663
    /*
664
     * Name of the alternate data file 
665
     */
666
    d_field( 0, i++, "Data filename :", D_STRING,
667
             ( int ) sizeof( config->datafilename ) - 1,
668
             ( char * ) config->datafilename, TRUE, opr );
669
 
670
    /*
671
     **  Non-equestrian configuration information
672
     */
673
    abort_flag = FALSE;
674
    i++;
675
    d_field( 0, i++, "Equestrian Leg :", D_NUMBER, 1, ( char * ) &config->equestrian_leg, TRUE, opr );
676
    d_field( 0, i++, "Non-Equestrian Category :", D_USTRING,
677
             ( int ) sizeof( config->nonequestrian_class_abr ) - 1,
678
             ( char * ) config->nonequestrian_class_abr, TRUE, opr );
679
 
680
    /*
681
    **  Print control
682
    */
683
    abort_flag = FALSE;
684
    i++;
685
    d_field(  0, i,   "Lines Per Page :", D_NUMBER, 3, ( char * ) &config->lines_per_page, TRUE, opr );
686
    d_field( 30, i++, "Perf Skip :", D_NUMBER, 1, ( char * ) &config->perf_skip, TRUE, opr );
687
}
688
 
689
/*========================================================================
690
 *
691
 *  Display the current country list
692
 *
693
 *  Purpose:
694
 *      This function is called to Display the current country list
695
 *
696
 *  Parameters:
697
 *      None
698
 *
699
 *  Returns:
700
 *      Nothing
701
 *
702
 *========================================================================*/
703
 
704
void display_country( void )
705
{
706
    d_cntry( &config, M_DISPLAY );
707
 
708
    cur( 0, n_lines - 1 );
709
    printf( "Any key to return to main menu :" );
710
    ( void ) getinp(  );
711
}
712
 
713
/*========================================================================
714
 *
715
 *  Define a new entry in the county list
716
 *
717
 *  Purpose:
718
 *      This function is called to Define a new entry in the county list
719
 *
720
 *  Parameters:
721
 *      None
722
 *
723
 *  Returns:
724
 *      Nothing
725
 *
726
 *========================================================================*/
727
 
728
void define_country( void )
729
{
730
    int         error;
731
    ty_t_country *ptr;
732
    int         i;
733
 
734
    /*
735
     **  Copy working configuration into a temp structure for
736
     **  use within the function
737
     */
738
    newcfg = config;
739
 
740
    do
741
    {
742
        error = 0;
743
        newcfg.num_countries = 0;
744
 
745
        /*
746
         * Get the operator to update the screen 
747
         */
748
 
749
        d_cntry( &newcfg, M_UPDATE );               /* Update the country data */
750
        printf( "\n" );
751
 
752
        /*
753
         * Now check the data that has been entered. 
754
         */
755
 
756
        ptr = newcfg.country_name;
757
        for( i = 0; i < MAX_COUNTRY; i++, ptr++ )
758
        {
759
            compact( ptr->abr );
760
            compact( ptr->full_name );
761
            if( ( ptr->abr[0] == '\0' ) != ( ptr->full_name[0] == '\0' ) )
762
            {
763
                error++;
764
                printf( "Missing field\n" );
765
            }
766
            if( ptr->abr[0] )
767
                newcfg.num_countries++;
768
        }
769
 
770
        if( error )
771
        {
772
            printf( "Configuration error - error must be corrected\n" );
773
            printf( "Any key to continue " );
774
            ( void ) getinp(  );
775
        }
776
        else
777
        {
778
            printf( "Install configuration (Y)es, (D)iscard, (E)dit again :" );
779
            switch ( getfnc( "*YDEA" ) )
780
            {
781
            case 'Y':
782
                config = newcfg;
783
                wt_config(  );                   /* Write out the data */
784
                break;
785
 
786
            case 'D':
787
                break;
788
 
789
            default:
790
                error = TRUE;
791
                break;
792
            }
793
        }
794
    } while( error );
795
    return;
796
}
797
 
798
 
799
/*========================================================================
800
 *
801
 *  Display / Update Country list
802
 *
803
 *  Purpose:
804
 *      This function is called to Display or Update Country list
805
 *
806
 *  Parameters:
807
 *      operation           Operation to perform
808
 *
809
 *  Returns:
810
 *      Nothing
811
 *
812
 *========================================================================*/
813
 
814
void d_cntry( MARA_CFG * config, int operation )
815
{
816
    int         i, j, k;
817
    int         opr;
818
 
819
    abort_flag = FALSE;
820
    if( operation == M_UPDATE )
821
    {
822
        opr = M_UPDATE;
823
        d_cntry( config, M_PREDISPLAY );         /* Force display before update */
824
    }
825
    else
826
    {
827
        opr = M_DISPLAY;
828
        clearscreen(  );
829
    }
830
    i = 0;                                       /* Set line 0 */
831
 
832
    d_field( 0, i++, "Country classifications", D_NULL, 0, ( char * ) 0, TRUE, M_DISPLAY );
833
 
834
    /*
835
     * Display the country names 
836
     */
837
 
838
    i++;
839
 
840
    for( j = 0, k = 0; j < MAX_COUNTRY; j++ )
841
    {
842
        d_field( 0 + k, i, "Country: ", D_STRING, 4,
843
                 ( char * ) config->country_name[j].abr, TRUE, opr );
844
        d_field( 13 + k, i, ": ", D_STRING, LEN_CNTRY_NAME,
845
                 config->country_name[j].full_name, TRUE, opr );
846
 
847
        k += 40;
848
        if( !( ( j + 1 ) % 2 ) )
849
        {
850
            k = 0;
851
            i++;
852
        }
853
    }
854
}
855
 
856
/*========================================================================
857
 *
858
 *  Display the Winners List
859
 *
860
 *  Purpose:
861
 *      This function is called to Display the current winners list
862
 *
863
 *  Parameters:
864
 *      None
865
 *
866
 *  Returns:
867
 *      Nothing
868
 *
869
 *========================================================================*/
870
 
871
void display_winners( void )
872
{
873
    calc_class_summary( & class_summary );
874
    d_winners( &config, M_DISPLAY );
875
 
876
    cur( 0, n_lines - 1 );
877
    printf( "Any key to return to main menu :" );
878
    ( void ) getinp(  );
879
}
880
 
881
/*========================================================================
882
 *
883
 *  Update the winners information
884
 *
885
 *  Purpose:
886
 *      This function is called to update the winners information
887
 *
888
 *  Parameters:
889
 *      None
890
 *
891
 *  Returns:
892
 *      Nothing
893
 *
894
 *========================================================================*/
895
 
896
bool define_winners( void )
897
{
898
    int         error;
899
    int         i;
900
    bool        changed = FALSE;
901
 
902
    /*
903
    **  Update the class summary info to give the user a hint
904
    */
905
    calc_class_summary( & class_summary );
906
 
907
    /*
908
     **  Copy working configuration into a temp structure for
909
     **  use within the function
910
     */
911
    newcfg = config;
912
 
913
    /*
914
    **  Edit and sanity test the cnfig data until the user is happy
915
    **  with it - or is ready to discard it.
916
    */
917
    do
918
    {
919
        error = 0;
920
        d_winners ( &newcfg, M_UPDATE );
921
        printf( "\n" );
922
 
923
        /*
924
        **  Sanity test of the data
925
        */
926
        for( i = 0; i < MAX_CLASS; i++ )
927
        {
928
            if( newcfg.team_class[i].abr[0] != '\0' && newcfg.class_winners[i] == 0 )
929
            {
930
                printf( "  Warning: Class without winners: %s\n", newcfg.team_class[i].abr );
931
            }
932
 
933
            if ( newcfg.class_winners[i] > class_summary.teamclass[i+1].total )
934
            {
935
                printf( "  Warning: Num winners greater than those in class: %s\n", newcfg.team_class[i].abr );
936
            }
937
        }
938
 
939
 
940
        newcfg.num_fame = 0;
941
        for( i = 0; i < MAX_FAME; i++ )
942
            if( newcfg.hall_fame[i][0] )
943
                newcfg.num_fame++;
944
 
945
        for( i = newcfg.num_fame; i < MAX_FAME; i++ )
946
            if( newcfg.hall_fame[i][0] )
947
            {
948
                printf( "Configuration error: Missing Fame name. Gaps not allowed\n" );
949
                error++;
950
                break;
951
            }
952
 
953
        abort_flag = FALSE;
954
        if( error )
955
        {
956
            printf( "Any key to continue " );
957
            getinp(  );
958
        }
959
        else
960
        {
961
            printf( "Install configuration (Y)es, (D)iscard, (E)dit again :" );
962
            switch ( getfnc( "*YDEA" ) )
963
            {
964
            case 'Y':
965
                config = newcfg;
966
                wt_config(  );
967
                changed = TRUE;
968
                break;
969
 
970
            case 'D':
971
                break;
972
 
973
            default:
974
                error = TRUE;
975
                break;
976
            }
977
        }
978
    } while( error && ! abort_flag );
979
    return ( changed );
980
}
981
 
982
 
983
/*========================================================================
984
 *
985
 *  Display / Update winners list
986
 *
987
 *  Purpose:
988
 *      This function is called to Display or Update winners list
989
 *
990
 *  Parameters:
991
 *      operation           Operation to perform
992
 *
993
 *  Returns:
994
 *      Nothing
995
 *
996
 *========================================================================*/
997
 
998
void d_winners( MARA_CFG * config, int operation )
999
{
1000
    int         i, j, k;
1001
    int         maxitr;                          /* Max number of definitions during update */
1002
    int         opr;
1003
 
1004
    abort_flag = FALSE;
1005
    if( operation == M_UPDATE )
1006
    {
1007
        opr = M_UPDATE;
1008
        d_winners( config, M_PREDISPLAY );         /* Force display before update */
1009
    }
1010
    else
1011
    {
1012
        opr = M_DISPLAY;
1013
        clearscreen(  );
1014
    }
1015
 
1016
    i = 0;                                       /* Set line 0 */
1017
    d_field( 0, i++, "Winner definitions", D_NULL, 0, ( char * ) 0, TRUE, M_DISPLAY );
1018
    i++;
1019
 
1020
    maxitr = config->num_class;
1021
 
1022
    for( j = 0, k = 0; j < maxitr; j++ )
1023
    {
1024
        d_field( 0 + k, i, "Cat:", D_USTRING, 2, ( char * ) config->team_class[j].abr, TRUE, M_DISPLAY );
1025
 
1026
        d_field( 7 + k, i, ":", D_STRING, LEN_CLASS_NAME,
1027
                 config->team_class[j].full_name, TRUE, M_DISPLAY );
1028
 
1029
        d_field( LEN_CLASS_NAME + 9 + k, i, "Num:", D_NUMBER, 3,
1030
                     ( char * ) &class_summary.teamclass[j+1].total, TRUE, M_DISPLAY );
1031
 
1032
        d_field( LEN_CLASS_NAME + 9 + 7 + k, i, "Win:", D_NUMBER, 3,
1033
                     ( char * ) &config->class_winners[j], TRUE, opr );
1034
 
1035
        /*
1036
         **  Step to next column or row
1037
         */
1038
        k += 40;
1039
        if( !( ( j + 1 ) % 2 ) )
1040
        {
1041
            k = 0;
1042
            i++;
1043
        }
1044
    }
1045
 
1046
    abort_flag =  FALSE;
1047
    i += 2;
1048
    d_field( 0, i++, "Hall of Fame", D_NULL, 0, ( char * ) 0, TRUE, M_DISPLAY );
1049
    for( j = 0, k = 0; j < MAX_FAME; j++ )
1050
    {
1051
        d_field( k, i, "Name : ", D_STRING, MAX_PERSON_NAME,
1052
                 &config->hall_fame[j], TRUE, opr );
1053
        k += 40;
1054
        if( !( ( j + 1 ) % 2 ) )
1055
        {
1056
            k = 0;
1057
            i++;
1058
        }
1059
    }
1060
}
1061
 
1062
 
1063
/*========================================================================
1064
 *
1065
 *  Read in the configuration file
1066
 *
1067
 *  Purpose:
1068
 *      This function is called to read in the configuration file
1069
 *
1070
 *  Parameters:
1071
 *      None
1072
 *
1073
 *  Returns:
1074
 *      Nothing
1075
 *
1076
 *========================================================================*/
1077
 
1078
bool rd_config( void )
1079
{
1080
    FILE       *fcon;
1081
    int         ok;
1082
 
1083
 
1084
    fcon = fopen( confile, "rb" );
1085
    if( ! fcon )
1086
    {
1087
        printf( "Configuration file %s not found\n", confile );
1088
        return ( FALSE );
1089
    }
1090
    ok = r_config( fcon );
1091
 
1092
    fclose( fcon );
1093
    return ( ok );
1094
}
1095
 
1096
/*========================================================================
1097
 *
1098
 *  Read in the configuration file
1099
 *
1100
 *  Purpose:
1101
 *      This function is called to read in the configuration file
1102
 *      NOTE: Must be maintained with the Writer function
1103
 *
1104
 *  Parameters:
1105
 *      fcon        File number of the config file
1106
 *
1107
 *  Returns:
1108
 *      FALSE if an error is encountered
1109
 *
1110
 *========================================================================*/
1111
 
1112
bool r_config( FILE *fcon )
1113
{
1114
    int         len;                             /* Length of data read */
1115
 
1116
    /*
1117
     * Event name 
1118
     */
1119
printf( "Reading: Event Name\n" );
1120
    len = fread( config.event_name, sizeof( config.event_name ), 1 , fcon );
1121
    if( len != 1 )
1122
        return ( FALSE );
1123
 
1124
    /*
1125
     * Leg names 
1126
     */
1127
printf( "Reading: Leg Names\n" );
1128
    len = fread( config.leg_name, sizeof( config.leg_name ), 1 , fcon );
1129
    if( len != 1 )
1130
        return ( FALSE );
1131
 
1132
    /*
1133
     * Team definitions 
1134
     */
1135
printf( "Reading: Team Defs\n" );
1136
 
1137
    len = fread( config.t_def, sizeof( config.t_def ), 1 , fcon );
1138
    if( len != 1 )
1139
        return ( FALSE );
1140
 
1141
    /*
1142
     * Number of legs 
1143
     */
1144
 
1145
printf( "Reading: Leg Nums\n" );
1146
    len = fread( &config.num_legs, sizeof( config.num_legs ), 1 , fcon );
1147
    if( len != 1)
1148
        return ( FALSE );
1149
 
1150
    /*
1151
     * Number of team splits 
1152
     */
1153
 
1154
printf( "Reading: Team Splits\n" );
1155
    len = fread( &config.num_teams, sizeof( config.num_teams ), 1 , fcon );
1156
    if( len != 1 )
1157
        return ( FALSE );
1158
 
1159
    config.min_team = config.t_def[0].start;
1160
    config.max_team = config.t_def[config.num_teams - 1].end;
1161
 
1162
    /*
1163
     * Class information 
1164
     */
1165
printf( "Reading: Class Data\n" );
1166
    len = fread( config.team_class, sizeof( config.team_class ), 1 , fcon );
1167
    if( len != 1 )
1168
        return ( FALSE );
1169
    len = fread( &config.num_class, sizeof( config.num_class ), 1 , fcon );
1170
    if( len != 1 )
1171
        return ( FALSE );
1172
 
1173
    /*
1174
     * Country list 
1175
     */
1176
 
1177
printf( "Reading: Country Data, Name\n" );
1178
    len = fread( config.country_name, sizeof( config.country_name ), 1 , fcon );
1179
    if( len != 1 )
1180
        return ( FALSE );
1181
printf( "Reading: Country Data, Number\n" );
1182
    len = fread( &config.num_countries, sizeof( config.num_countries ), 1 , fcon );
1183
    if( len != 1 )
1184
        return ( FALSE );
1185
 
1186
    /*
1187
     * Addendum file 
1188
     */
1189
 
1190
printf( "Reading: Addendum File\n" );
1191
    len = fread( config.addendum, sizeof( config.addendum ), 1 , fcon );
1192
    if( len != 1 )
1193
        return ( feof( fcon ) );
1194
 
1195
    /*
1196
     * Name of the data file 
1197
     */
1198
 
1199
printf( "Reading: Name of data file\n" );
1200
    len = fread( config.datafilename, sizeof( config.datafilename ) , 1 , fcon );
1201
    if( len != 1 )
1202
        return ( feof( fcon ) );
1203
 
1204
    /*
1205
     **  Non-equestrian configuration information
1206
     */
1207
printf( "Reading: NonEquest\n" );
1208
    len = fread( config.nonequestrian_class_abr, sizeof( config.nonequestrian_class_abr ), 1 , fcon );
1209
    if( len != 1 )
1210
        return ( feof( fcon ) );
1211
printf( "Reading: NonEquest-2\n" );
1212
    len = fread( &config.equestrian_leg, sizeof( config.equestrian_leg ), 1 , fcon );
1213
    if( len != 1 )
1214
        return ( FALSE );
1215
 
1216
    /*
1217
    **  .txt file output control. Lines per page and perf-skipping
1218
    */
1219
printf( "Reading: Output Control\n" );
1220
    len = fread( &config.lines_per_page, sizeof( config.lines_per_page ), 1 , fcon );
1221
    if( len != 1 )
1222
        return ( feof( fcon ) );
1223
 
1224
printf( "Reading: Output Control-2\n" );
1225
    len = fread( &config.perf_skip, sizeof( config.perf_skip ), 1 , fcon );
1226
    if( len != 1 )
1227
        return ( FALSE );
1228
 
1229
printf( "Reading: Winners Info\n" );
1230
    len = fread( &config.class_winners, sizeof( config.class_winners ), 1 , fcon );
1231
    if( len != 1 )
1232
        return ( FALSE );
1233
 
1234
printf( "Reading: Hall of Fame Info\n" );
1235
    len = fread( &config.hall_fame, sizeof( config.hall_fame ), 1 , fcon );
1236
    if( len != 1 )
1237
        return ( FALSE );
1238
 
1239
printf( "Reading: Hall of Fame Numbers\n" );
1240
    len = fread( &config.num_fame, sizeof( config.num_fame ), 1 , fcon );
1241
    if( len != 1 )
1242
        return ( feof( fcon ) );
1243
 
1244
 
1245
    return ( TRUE );
1246
}
1247
 
1248
/*========================================================================
1249
 *
1250
 *  Write out the configuration file
1251
 *
1252
 *  Purpose:
1253
 *      This function is called to write the configuration file
1254
 *      NOTE: Must be maintained with the Reader function
1255
 *
1256
 *  Parameters:
1257
 *      None
1258
 *
1259
 *  Returns:
1260
 *      FALSE   : Error encountered
1261
 *
1262
 *========================================================================*/
1263
 
1264
bool wt_config( void )
1265
{
1266
    FILE        *fcon;
1267
 
1268
    /*
1269
     **  Open as a binary file
1270
     */
1271
    fcon = fopen( confile, "wb" );
1272
    if( !fcon )
1273
        return ( FALSE );
1274
 
1275
    /*
1276
     **  Write out multiple structures
1277
     **     Event name
1278
     **     Leg names
1279
     **     Team definitions
1280
     **     Number of legs
1281
     **     Number fo team splits
1282
     **     Class information
1283
     **     Number of defined classes
1284
     **     Country list
1285
     **     Number of defined countries
1286
     **     Legend config.addendum file name
1287
     **     Data file name
1288
     */
1289
 
1290
    fwrite( config.event_name, sizeof( config.event_name ), 1, fcon );
1291
    fwrite( config.leg_name, sizeof( config.leg_name ), 1, fcon );
1292
    fwrite( config.t_def, sizeof( config.t_def ), 1, fcon );
1293
    fwrite( &config.num_legs, sizeof( config.num_legs ), 1, fcon );
1294
    fwrite( &config.num_teams, sizeof( config.num_teams ), 1, fcon );
1295
    fwrite( config.team_class, sizeof( config.team_class ), 1, fcon );
1296
    fwrite( &config.num_class, sizeof( config.num_class ), 1, fcon );
1297
    fwrite( config.country_name, sizeof( config.country_name ), 1, fcon );
1298
    fwrite( &config.num_countries, sizeof( config.num_countries ), 1, fcon );
1299
    fwrite( config.addendum, sizeof( config.addendum ), 1, fcon );
1300
    fwrite( config.datafilename, sizeof( config.datafilename ), 1, fcon );
1301
    fwrite( config.nonequestrian_class_abr, sizeof( config.nonequestrian_class_abr ), 1, fcon );
1302
    fwrite( &config.equestrian_leg, sizeof( config.equestrian_leg ), 1, fcon );
1303
    fwrite( &config.lines_per_page, sizeof( config.lines_per_page ), 1, fcon );
1304
    fwrite( &config.perf_skip, sizeof( config.perf_skip ), 1, fcon );
1305
    fwrite( &config.class_winners, sizeof( config.class_winners ), 1, fcon );
1306
    fwrite( &config.hall_fame, sizeof( config.hall_fame ), 1, fcon );
1307
    fwrite( &config.num_fame, sizeof( config.num_fame ), 1, fcon );
1308
 
1309
    fclose( fcon );
1310
    return ( TRUE );
1311
}
1312
 
1313
/*========================================================================
1314
 *
1315
 *  Qsort callback: Sort by team
1316
 *
1317
 *  Purpose:
1318
 *      Function used by the team definition sort operation
1319
 *      It will compare two entries of the team def structure and return an
1320
 *      integer for gt eq lt conditions.
1321
 *      Note : If the start is 0 the team entry does exist and is placed at the
1322
 *      end of the sorted list.
1323
 *
1324
 *  Parameters:
1325
 *      a           comparision entry
1326
 *      b           comparision entry
1327
 *
1328
 *  Returns:
1329
 *      gt, eq, lt as required
1330
 *
1331
 *========================================================================*/
1332
 
1333
int f_comp_int( const void *aa, const void *bb )
1334
{
1335
    const ty_t_def *a = (ty_t_def *)aa;
1336
    const ty_t_def *b = (ty_t_def *)bb;
1337
 
1338
    if( a->start == 0 )
1339
        return ( 1 );
1340
    else if( b->start == 0 )
1341
        return ( -1 );
1342
    else
1343
        return ( a->start - b->start );
1344
}
1345
 
1346
/*========================================================================
1347
 *
1348
 *  Compact a string
1349
 *
1350
 *  Purpose:
1351
 *      This function is called remove leading and trailing spaces from
1352
 *      a string. Treats other non-printing characters as leading
1353
 *      spaces. This solves a problem when importing data from a
1354
 *      Microsoft CSV file with empty fields.
1355
 *
1356
 *  Parameters:
1357
 *      str     Address of the string to compact
1358
 *
1359
 *  Returns:
1360
 *      Nothing
1361
 *
1362
 *========================================================================*/
1363
 
1364
void compact( char *str )
1365
{
1366
    char       *ptr;
1367
 
1368
    ptr = str;
1369
    while( *str && ( isspace( *str ) || !isprint( *str ) ) )
1370
        str++;
1371
    strcpy( ptr, str );
1372
}
1373
 
1374
/*========================================================================
1375
 *
1376
 *  Validate a team number
1377
 *
1378
 *  Purpose:
1379
 *      This function is called to validate a team number
1380
 *
1381
 *  Parameters:
1382
 *      x       Number to validate
1383
 *
1384
 *  Returns:
1385
 *      TRUE    : Valid
1386
 *      FALSE   : Not valid
1387
 *
1388
 *========================================================================*/
1389
 
1390
bool valid_field( int x )
1391
{
1392
    int         i;
1393
 
1394
    for( i = 0; i < config.num_teams; i++ )
1395
    {
1396
        if( x <= config.t_def[i].end && x >= config.t_def[i].start )
1397
            return ( TRUE );
1398
        if( x < config.t_def[i].start )
1399
            break;                               /* Because the list is sorted */
1400
    }
1401
    return ( FALSE );
1402
}
1403
 
1404
/*========================================================================
1405
 *
1406
 *  Get a class descriptor from existing text
1407
 *
1408
 *  Purpose:
1409
 *      This function is called to Get a class descriptor
1410
 *
1411
 *  Parameters:
1412
 *      text    - User text to examine
1413
 *      config  - configuration dtaa to use
1414
 *
1415
 *  Returns:
1416
 *      An integer which is the index into the  config.team_class array
1417
 *      The integer is in the range 1 .. num_class
1418
 *      A value fo zero indicates the text was not found.
1419
 *
1420
 *========================================================================*/
1421
 
150 david 1422
int lookup_class( const char *text, MARA_CFG * config_ptr )
95 - 1423
{
1424
    int         i;
1425
 
1426
    if( config_ptr == NULL )
1427
        config_ptr = &config;
1428
 
1429
    /*
1430
     * Attempt to locate the entered class in the list of defined classes
1431
     */
1432
 
1433
    for( i = 0; i < config_ptr->num_class; i++ )
1434
    {
1435
        if( toupper(text[0]) == toupper(config_ptr->team_class[i].abr[0]) &&
1436
            toupper(text[1]) == toupper(config_ptr->team_class[i].abr[1]) )
1437
            return ( ++i );
1438
    }
1439
    return ( 0 );
1440
}
1441
 
1442
/********************************* EOF ***********************************/