Subversion Repositories svn1-original

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 root 1
/*************************************************************************
2
*           Copyright Xdel Technology Pty. Ltd. 1987
3
*           Copyright (C) 1995 Embedded Solutions
4
*                       All rights reserved
5
*
6
* file:     src\upload.c
7
*
8
* purpose:  Data upload functions
9
*           This module contains all the functions required to upload
10
*           data from the handheld calculators and insert the data
11
*           into the data base as well as functions and a menu to load
12
*           and unload specific data into the data base
13
*
14
* functions
15
*       upload                  - Get Leg to upload
16
*       ins_data                - Insert time info into data base
17
*       supload                 - Extended upload functions menu
18
*       tupload                 - Read in text team information
19
*       t_parse_number          - Parse a number from a CSV line of team text
20
*       t_parse_text            - Parse string from a CSV line of team text
21
*       p_del                   - Test for a delimiter.
22
*       tdnload                 - Generate team name file
23
*       dnload                  - Generate leg timing file
24
*       getfname                - Get a filename from the user
25
*
26
* programmer: David Purdie
27
*
28
* revision  date        by      reason
29
*           May 1990    Margherita Veroni
30
*                               The functions to upload data have been modified
31
*                               to allow leg start times to also be uploaded for
32
*                               any leg. Data being uploaded which contain errors
33
*                               are written to an error file
34
*
35
*   00.0    1-Apr-94    DDP     Changed tdnload() to produce a comma seperated
36
*                               file. This allows external users to see the
37
*                               field delimters better than tabs
38
*
39
*   00.0    27/01/95    DDP     Tidies up the program and formatted the file
40
*
41
**************************************************************************/
42
 
43
#include    <stdio.h>
44
 
45
#include    "consts.h"
46
#include    "structs.h"
47
#include    "proto.h"
48
 
49
/* Variable storage */
50
 
51
char        ufilename[40];                       /* Name of upload file */
52
FILE       *ufile;                               /* Upload file stream */
53
FILE       *efile;                               /* Error file stream */
54
char        line[300];                           /* Input line */
55
char        line_text[133];                      /* Output text */
56
 
57
unsigned char manstart;                          /* Manual start time entry */
58
 
59
 
60
menu_table  sup_menu[] = {
61
    { '1', "Load team information from external file", tupload },
62
    { '2', "Create external team information file", tdnload },
63
    { '3', "Create external leg data file", dnload },
64
    { '4', "Upload time information", upload },
65
    { 'q', "Return to main menu", 0 },
66
    { '\0' }
67
};
68
 
69
/*========================================================================
70
 *
71
 *  Get Leg to upload
72
 *
73
 *  Purpose:
74
 *      This function is called to Get Leg to upload
75
 *          Prompt user for leg number and start / end of leg
76
 *          Open disc file
77
 *          Read and parse text. Enter data into team information
78
 *          Maintain error file of errors.
79
 *
80
 *  Parameters:
81
 *      None
82
 *
83
 *  Returns:
84
 *      Nothing
85
 *
86
 *========================================================================*/
87
 
88
void upload(void)
89
{
90
    int         hh, mm, ss;                      /* Team times */
91
    int         error = 0;                       /* Count of errors */
92
    int         ntms = 0;                        /* Number of teams uploaded */
93
    char        stend[] = "E";                   /* Start or End time */
94
    char       *filename;                        /* Name of file to open */
95
    char       *err_filename;                    /* Name of an error file to open */
96
 
97
    cur( 0, 5 );
98
    while( TRUE )
99
    {
100
        leg = 0;
101
        d_field( 0, 6, "Enter leg to upload :", D_NUMBER, 1, ( char * ) &leg,
102
                 TRUE, M_UPDATE );
103
        if( leg == 0 )
104
            return;                              /* Null leg - just exit */
105
        if( leg <= config.num_legs )             /* Valid leg number - Exit loop */
106
            break;
107
        beep();                                  /* Make a noise and wait for valid number */
108
    }
109
 
110
 
111
    /*
112
     * Find out if Start or End of leg times to be uploaded 
113
     */
114
 
115
    do
116
    {
117
        d_field( 0, 7, "Start or End of leg to upload :", D_USTRING, 1, stend,
118
                 TRUE, M_UPDATE );
119
    } while( ( stend[0] != 'S' ) && ( stend[0] != 'E' ) );
120
    manstart = ( ( stend[0] == 'S' ) ? TRUE : FALSE );
121
    printf( "\n" );
122
 
123
    /*
124
     * Locate the required data file and prepare for processing 
125
     */
126
    filename = tprintf( "%s%d" , manstart ? "Sleg" : "leg" , leg );
127
    ufile = fopen( filename, "rt" );
128
    if( ufile == 0 )
129
    {
130
        printf( "Cannot locate data file - %s\n", filename );
131
        beep();
132
        sleep( 5 );
133
        return;
134
    }
135
 
136
    /*
137
     * create an error file for this leg data 
138
     * duplicate times will stored here
139
     */
140
    err_filename = tprintf( "%s%d.err" , manstart ? "Sleg" : "leg" , leg );
141
    efile = fopen( err_filename, "at" );
142
 
143
    /*
144
     * Process each entry in the file 
145
     */
146
 
147
    if( leg > config.num_legs )
148
        printf( "\nUploading leg%d start information\n", leg );
149
 
150
    while( fgets( line, 101, ufile ) )
151
    {
152
        if( sscanf( line, "%d %d:%d:%d", &team, &hh, &mm, &ss ) != 4 )
153
        {
154
            printf( "Upload error - %s", line );
155
            error++;
156
        }
157
        else
158
        {
159
            if( !ins_data( team, hh, mm, ss ) )
160
                error++;
161
            ntms++;
162
        }
163
    }
164
 
165
    printf( "%d errors detected. %d teams uploaded. Any key to continue ", error, ntms );
166
    getinp();
167
 
168
    fclose( ufile );
169
    fclose( efile );
170
}
171
 
172
/*========================================================================
173
 *
174
 *  Insert time info into data base
175
 *
176
 *  Purpose:
177
 *      This helper function is called to Insert time info into data base
178
 *          Read record
179
 *          Read and convert time
180
 *          Write record
181
 *              Maintain error file
182
 *          Display errors on screen
183
 *
184
 *  Parameters:
185
 *      tm          Team
186
 *      hh          hours
187
 *      mm          minutes
188
 *      ss          seconds
189
 *
190
 *  Returns:
191
 *      Nothing
192
 *
193
 *========================================================================*/
194
 
195
int ins_data( int tm, int hh, int mm, int ss )
196
{
197
    time_t      l_time;                          /* Leg time */
198
    int         ok = TRUE;
199
 
200
    /*
201
     * Calculate the time for the team 
202
     */
203
 
204
    l_time = conv_time( hh, mm, ss );
205
 
206
    /*
207
     * If an error is found - invalid team, team not found or dual time for team
208
     * a message is output to the screen and the data is written to error file
209
     * FALSE is returned
210
     */
211
 
212
    if( !valid_field( tm ) )
213
    {
214
        printf( "Invalid team - %d %2.2d:%2.2d:%2.2d\n", tm, hh, mm, ss );
215
        fprintf( efile, "Invalid team - %d %2.2d:%2.2d:%2.2d\n", tm, hh, mm,
216
                 ss );
217
        ok = FALSE;
218
        return ( ok );
219
    }
220
    if( !g_record( tm, &team_buf ) )
221
    {
222
        printf( "Team not found -% d %2.2d:%2.2d:%2.2d\n", tm, hh, mm, ss );
223
        fprintf( efile, "Team not found - %d %2.2d:%2.2d:%2.2d\n", tm, hh, mm, ss );
224
        ok = FALSE;
225
    }
226
    if( !manstart )
227
    {                                            /* Normal upload */
228
        if( team_buf.leg[leg].end > 0 && team_buf.leg[leg].end != l_time )
229
        {
230
            printf( "Dual time for %d - %2.2d:%2.2d:%2.2d and %s\n", tm, hh,
231
                    mm, ss, time_a( team_buf.leg[leg].end ) );
232
            fprintf( efile, "Dual time for %d - %2.2d:%2.2d:%2.2d and %s\n",
233
                        tm, hh, mm, ss, time_a( team_buf.leg[leg].end )
234
                    ); /* write  duplicate time to error file */
235
            ok = FALSE;
236
            return ( ok );                       /* keep time already in database */
237
        }
238
        team_buf.leg[leg].end = l_time;
239
    }
240
    else
241
    {                                            /* Uplaod start time */
242
        team_buf.leg[leg].start = l_time;
243
        team_buf.leg[leg].manual = TRUE;
244
    }
245
    set_times( &team_buf );                      /* Calc start of next leg */
246
    ( void ) test_times( &team_buf, 0 );         /* Calc elapsed times etc */
247
    put_team_record( tm, &team_buf );
248
    return ( ok );
249
}
250
 
251
/*========================================================================
252
 *
253
 *  Extended upload functions menu
254
 *
255
 *  Purpose:
256
 *      This function is called to Extended upload functions
257
 *
258
 *  Parameters:
259
 *      None
260
 *
261
 *  Returns:
262
 *      Nothing
263
 *
264
 *========================================================================*/
265
 
266
void supload(void)
267
{
268
    do_menu( "Extended data manipulation", "Select option", sup_menu ); /* Call a menu to do it */
269
}
270
 
271
/*========================================================================
272
 *
273
 *  Read in text team information
274
 *
275
 *  Purpose:
276
 *      This function is called to do Read in text team information
277
 *      from a file
278
 *
279
 *      The source file is a comma seperated file and may contain the
280
 *      folowing items
281
 *
282
 *      Team Number     - Mandatory
283
 *      Team Name       - Mandatory
284
 *      Team Catagory   - Mandatory
285
 *
286
 *      Team Names ...  - Optional
287
 *
288
 *  Parameters:
289
 *      None
290
 *
291
 *  Returns:
292
 *      Nothing
293
 *
294
 *========================================================================*/
295
 
296
void tupload(void)
297
{
298
    int         error = 0;
299
    int         i;
300
    char       *linep;
301
    int         class_count[MAX_CLASS];
302
    int         total;
303
 
304
    cur( 0, 5 );
305
    printf( "Read text file of team information" );
306
 
307
    if( !getfname( "Enter name of the file to read :", ".csv" ) )
308
        return;
309
    printf( "\n" );
310
 
311
    ufile = fopen( ufilename, "rt" );             /* Open the file for reading */
312
    if( ufile == 0 )
313
    {
314
        printf( "Cannot locate data file - %s\n", ufilename );
315
        beep();
316
        sleep( 5 );
317
        return;
318
    }
319
 
320
    memset ( class_count, 0, sizeof( class_count ));
321
 
322
    /*
323
    **  Get the data from the file
324
    **  Read in lines one by one
325
    */
326
    while( fgets( line, sizeof(line) - 10 , ufile ) )
327
    {
328
        linep = line;
31 - 329
        int has_data = 0;
1 root 330
        /*
331
        **  Skip blank lines
332
        **  Skip leading white space
333
        */
31 - 334
        for ( linep = line; *linep; linep++ )
335
        {
336
            if ( *linep == (char)0xA0 || *linep == '"' || *linep == ',' || *linep == '\n' ||*linep == '\r')
337
            {
338
                continue;
339
            }
340
            has_data = 1;
341
        }
342
        if ( !has_data )
343
            continue;
344
 
1 root 345
        for ( linep = line; isspace( *linep ); linep++ )
346
        {
347
        }
348
        if ( ! *linep )
349
            continue;
350
 
351
        /*
352
        **  The first entry on the line should be team number
353
        **  If it is not a valid team number then skip
354
        */
355
 
356
        if( ! t_parse_number( &linep, &team ) )
357
        {
358
            printf( "No team number: %-30s.\n", line );
359
            error++;
360
        }
361
        else if( ! valid_field( team ) )
362
        {
363
            printf ( "Invalid team number: %d\n", team );
364
            error++;
365
        }
366
        else
367
        {
368
            g_record( team, &team_buf );
369
 
370
            /*
371
            **  Extract a team information from the CSV file
372
            **  These fields will be
373
            **      - Team Name
374
            **      - Category
375
            **      - Member names
376
            */
377
            if ( t_parse_text( &linep, line_text ) )
378
            {
379
                strncpy (team_buf.name,line_text,MAX_TM_NAME);
31 - 380
                if ( ! *line_text )
381
                {
382
                    printf( "Team: %d - No Team Name:%50.50s...\n", team, line );
383
                }
1 root 384
            }
385
 
31 - 386
            if ( t_parse_text( &linep, line_text )  && *line_text)
1 root 387
            {
388
                int cat_found = 0;
389
                team_buf.class = lookup_class( line_text, NULL );
390
                if ( team_buf.class > 0)
391
                {
392
                    /*
393
                    **  The team has a category
394
                    **  Now flag the team as valid - it has ALL
395
                    **  the basic information
396
                    */
397
                    team_buf.flags.valid = TRUE;
398
                    cat_found =1;
399
 
400
                    if ( team_buf.class < MAX_CLASS )
401
                        class_count[team_buf.class]++;
402
                }
403
 
31 - 404
                if ( !cat_found )
1 root 405
                {
406
                    printf( "Team: %d - Invalid category:%s\n", team,line_text );
407
                    error++;
408
                }
409
            }
31 - 410
            else
411
            {
412
                printf( "Team: %d - No category:%50.50s...\n", team, line );
413
                error++;
414
            }
1 root 415
 
416
            for( i = 0; i < MAX_MEMB; i++ )
417
            {
418
                if ( t_parse_text( &linep, line_text ) )
419
                {
420
                    strncpy (team_buf.members[i].name,line_text,MAX_PERSON_NAME);
421
                }
45 - 422
 
423
                int age;
424
                if ( t_parse_number( &linep, &age ) )
425
                {
426
                    team_buf.members[i].age = age;
427
                }
1 root 428
            }
429
 
430
            put_team_record( team, &team_buf );
431
        }
432
 
31 - 433
/*
434
**       printf( ">>>:%s\n", line );
435
**       if ( 'q' == getinp() ) break;
436
*/       
437
 
1 root 438
    }
439
 
440
    /*
441
    **  Display a few upload stats
442
    */
443
    total = 0;
444
    for( i = 0; i < config.num_class; i++ )
445
    {
446
        printf( "%*s : %d\n", LEN_CLASS_NAME, config.team_class[i].full_name, class_count[i+1] );
447
        total += class_count[i+1];
448
    }
449
 
450
    printf( "\n%*s : %d\n", LEN_CLASS_NAME, "Total Uploaded", total );
451
    printf( "%*s : %d\n", LEN_CLASS_NAME, "Errors", error );
452
 
453
 
454
    printf( "\nAny key to continue " );
455
    getinp();
456
 
457
    fclose( ufile );
458
}
459
 
460
 
461
/*========================================================================
462
 *
463
 *  Parse a number from a CSV text file
464
 *
465
 *  Purpose:
466
 *      This helper function is called to Parse line of team text
467
 *
468
 *  Parameters:
469
 *      linep           Current input source pointer
470
 *                      Will be updated to point to end of the field
45 - 471
 *                      If the field is a valid number
1 root 472
 *      number          Number extracted
473
 *
474
 *  Returns:
475
 *      TRUE - Number extracted OK
476
 *      FALSE - No number extracted
477
 *
478
 *========================================================================*/
479
 
480
bool t_parse_number( char **linep, int *number )
481
{
482
    long    lnumber;
45 - 483
    char    *work = *linep;
1 root 484
 
485
    /*
486
    **  Expecting a number
487
    **  strtol will remove leading white space
488
    */
45 - 489
    lnumber = strtol( work, &work, 10 );
1 root 490
 
491
    /*
492
    **  Skip the trailing delimiter(s)
493
    */
45 - 494
    while ( p_del(work) )
1 root 495
    {
45 - 496
        work++;
1 root 497
    }
498
 
499
    /*
500
    **  A valid number ?
501
    */
502
    if ( lnumber == 0 )
503
        return FALSE;
504
 
505
    *number = (int) lnumber;
45 - 506
    *linep = work;
1 root 507
    return TRUE;
508
}
509
 
510
/*========================================================================
511
 *
512
 *  Parse a text field from a CSV text file
513
 *
514
 *  Purpose:
515
 *      This helper function is called to Parse line of team text
516
 *
517
 *  Parameters:
518
 *      linep           Current input source pointer
519
 *                      Will be updated to point to end of the field
520
 *      number          Address of buffer to insert text into
521
 *
522
 *  Returns:
523
 *      TRUE - Field extracted OK
524
 *      FALSE - No field extracted
525
 *
526
 *========================================================================*/
527
 
528
bool t_parse_text( char **linep, char *text )
529
{
530
    char    uch;
531
    char    *textp = text;
532
    bool    quoted = FALSE;
533
 
534
    /*
535
    **  If we have already reached the end of the line tne indicate
536
    **  That there is no data
537
    */
538
    uch = **linep;
539
    if ( uch == '\n' || uch == '\r' || uch == '\0' )
540
        return ( FALSE );
541
 
542
    /*
543
    **  Extract the next record
544
    */
545
    while ( TRUE )
546
    {
547
        uch = **linep;
548
 
549
        /*
550
        **  End of the field
551
        */
552
        if ( uch == '\n' || uch == '\r' || uch == '\0' )
553
            break;
554
 
555
        (*linep)++;
31 - 556
 
557
        /*
558
        ** Ugly character from MS CSV files
559
        */
560
        if ( uch == (char) 0xA0 )
561
        {
562
            continue;
563
        }
564
 
1 root 565
        if ( !quoted && uch == ',' )
566
        {
567
            break;
568
        }
569
 
570
        /*
571
        **  An unquoted " will start scanning for a matching quote
572
        */
573
        if ( !quoted && uch == '"' )
574
        {
575
            quoted = TRUE;
576
            continue;
577
        }
578
 
579
 
580
        /*
581
        **  A quoted " may be en embedded quote or the end of a quote
582
        */
583
        if ( quoted && uch == '"' )
584
        {
585
            if ( **linep != '"' )
586
            {
587
                quoted = FALSE;
588
                continue;
589
            }
590
 
591
            /*
592
            **  Skip one " and pick up the next
593
            */
594
            (*linep)++;
595
 
596
        }
597
 
598
        /*
599
        **  Save this character
600
        */
601
        *textp++ = uch;
602
    }
603
 
604
    /*
605
    **  Clean up the extracted string
606
    */
607
    *textp = 0;
608
    compact ( text );
609
 
610
    return ( TRUE );
611
}
612
 
613
/*========================================================================
614
 *
615
 *  Test for a delimiter.
616
 *
617
 *  Purpose:
618
 *      This function is called to Test for a delimiter.
619
 *
620
 *  Parameters:
621
 *      c           Character to test
622
 *
623
 *  Returns:
624
 *      TRUE if a delimter (space, tab or comma)
625
 *
626
 *========================================================================*/
627
 
628
char p_del( char *c )
629
{
630
    return ( *c == ' ' || *c == '\t' || *c == ',' || *c == '\0' || *c == '\n' || *c == '\r');
631
}
632
 
633
char p_eol( char *c )
634
{
635
    return ( *c == '\0' || *c == '\n' || *c == '\r' );
636
}
637
 
638
/*========================================================================
639
 *
640
 *  Generate team name file
641
 *
642
 *  Purpose:
643
 *      This function is called to Generate team name file
644
 *
645
 *      The file contains team number,Team name,Team class
646
 *      The operator is prompted to enter the name of the file
647
 *
648
 *  Parameters:
649
 *      None
650
 *
651
 *  Returns:
652
 *      Nothing
653
 *
654
 *========================================================================*/
655
 
656
void tdnload(void)
657
{
658
    int         i;
659
 
660
    cur( 0, 5 );
661
    printf( "Create text file of team information" );
662
 
663
    if( !getfname( "Enter name of the file to create :", ".txt" ) )
664
        return;
665
    printf( "\n" );
666
 
667
    ufile = fopen( ufilename, "wt" );             /* Open the file for writing */
668
    if( ufile == 0 )
669
    {
670
        printf( "Cannot create data file - %s\n", ufilename );
671
        beep();
672
        sleep( 5 );
673
        return;
674
    }
675
 
676
    /*
677
     * Put the data into the file 
678
     */
679
 
680
    for( i = config.min_team; i <= config.max_team; i++ )
681
    {
682
        if( valid_field( i ) && g_record( i, &team_buf ) )
683
        {
684
            fprintf( ufile, "%-5d,%-30s,%-5s\n",
685
                     team_buf.numb,
686
                     team_buf.name,
687
                     team_buf.class >
688
 
689
        }
690
    }
691
    fclose( ufile );
692
}
693
 
694
/*========================================================================
695
 *
696
 *  Generate leg timing file
697
 *
698
 *  Purpose:
699
 *      This function is called to Generate leg timing file
700
 *
701
 *  Parameters:
702
 *      None
703
 *
704
 *  Returns:
705
 *      Nothing
706
 *
707
 *========================================================================*/
708
 
709
void dnload(void)
710
{
711
    int         i;
712
    char        stend[] = "E";
713
 
714
    cur( 0, 5 );
715
    printf( "Generate leg data files" );
716
    while( TRUE )
717
    {
718
        leg = 0;
719
        d_field( 0, 6, "Enter leg to save :", D_NUMBER, 1, ( char * ) &leg,
720
                 TRUE, M_UPDATE );
721
        if( leg == 0 )
722
            return;                              /* Null leg - just exit */
723
        if( leg <= config.num_legs )             /* Valid leg number - exit loop */
724
            break;
725
        beep();                                /* Make a noise and keep waiting for valid number */
726
 
727
    }
728
 
729
 
730
    /*
731
     * Find out if Start or End of leg times to be saved 
732
     */
733
 
734
    do
735
    {
736
        d_field( 0, 7, "Start of End of leg to save :", D_USTRING, 1, stend,
737
                 TRUE, M_UPDATE );
738
    } while( ( stend[0] != 'S' ) && ( stend[0] != 'E' ) );
739
    manstart = ( stend[0] == 'S' ? TRUE : FALSE );
740
 
741
    /*
742
     * Locate the required data file and prepare for processing 
743
     */
744
 
745
    printf( "\n" );
746
    sprintf( ufilename, ( manstart ? "Sleg%d" : "leg%d" ), leg );   /* Create the file name */
747
    ufile = fopen( ufilename, "wt" );             /* Open the file for writing */
748
    if( ufile == 0 )
749
    {
750
        printf( "Cannot create data file - %s\n", ufilename );
751
        beep();
752
        sleep( 5 );
753
        return;
754
    }
755
 
756
    /*
757
     * Write the data to the data file 
758
     */
759
 
760
    for( i = config.min_team; i <= config.max_team; i++ )
761
    {
762
        if( valid_field( i ) && g_record( i, &team_buf ) )
763
        {
764
            if( !manstart
765
                && ( leg <= config.num_legs && team_buf.leg[leg].end >= 0 ) )
766
                fprintf( ufile, "%d %s\n", i,
767
                         time_a( team_buf.leg[leg].end ) );
768
 
769
            if( manstart && team_buf.leg[leg].start >= 0 )
770
                fprintf( ufile, "%d %s\n", i,
771
                         time_a( team_buf.leg[leg].start ) );
772
        }
773
    }
774
    fclose( ufile );
775
}
776
 
777
/*========================================================================
778
 *
779
 *  Get a filename from the user
780
 *
781
 *  Purpose:
782
 *      This function is called to Get a filename from the user
783
 *
784
 *  Parameters:
785
 *      prompt      User prompt
786
 *      ext         File extension
787
 *
788
 *  Returns:
789
 *      TRUE: all is well
790
 *
791
 *========================================================================*/
792
 
793
char getfname( char *prompt, char *ext )
794
{
795
    /*
796
    **  Create a default name if non is present
797
    */
798
    if ( ! *ufilename )
799
    {
800
        sprintf( ufilename, "%s%s", filebase, ext );
801
    }
802
 
803
    d_field( 0, 6, prompt, D_STRING, 40, ufilename, TRUE, M_UPDATE );
804
    if( abort_flag )
805
        return ( FALSE );
806
 
807
    compact( ufilename );
808
    if( ufilename[0] )
809
        return ( TRUE );
810
    return ( FALSE );
811
}
812
 
813
/********************************* EOF ***********************************/