Subversion Repositories svn1-original

Rev

Rev 46 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*************************************************************************
*           Copyright (C) 1995 Embedded Solutions
*                       All rights reserved
*
* file:     src\teamupd.c
*
* purpose:  Team data edit and display
*           This module contains all the functions required to define and
*           alter the team definitions
*
* functions
*       team_update             - Update team data on the screen
*       team_display            - Display team data on the screen
*       leg_mods                - Modify team leg times
*       d_display               - Display all team information
*       d_leg                   - Display / Update leg time information
*       d_field                 - Display / Update field on the screen
*       g_tnum                  - Get a team number from the operator
*       g_record                - Read a team record from disk
*       clr_team                - Clear team data from file
*       put_team_record         - Save team record to disk
*       init_team_data          - Initialize the team data file
*       fix_team_data           - Close team data file
*
* programmer: David Purdie
*
* revision  date        by      reason
*   00.0    27/01/95    DDP     Tidies up the program and formatted the file
*
**************************************************************************/

#ifndef HI_TECH_C
#include    <fcntl.h>
/*#include  <memory.h> */
#endif

#include    "consts.h"
#include    "structs.h"
#include    "proto.h"
int         team;                                /* Current team number */
team_type   team_buf;                            /* Holds team data currently under display */
int         team_fd;                             /* Team data file descriptor */
int         leg = 0;                             /* Leg under investigation */

/*========================================================================
 *
 *  Update team data on the screen
 *
 *  Purpose:
 *      This function is called to update team data on the screen
 *      This function will prompt the operator to select a team number
 *      If the team is defined then the data will be displayed on the screen
 *
 *  Parameters:
 *      None
 *
 *  Returns:
 *      TRUE - Change made
 *
 *========================================================================*/

void team_update(void)
{
    if( !g_tnum( 0, n_lines - 2, "Enter team number" ) )
        return;                        /* Exit operation */

    /*
     **  Fetch the team record into memory
     **  If the record does not exist a record with an invalid flag
     **  will be returned
     */

    do
    {
        clearscreen();
        g_record( team, &team_buf );
        d_display( M_TEAM );
        put_team_record( team, &team_buf );

    } while( g_tnum( 0, n_lines - 2, "Enter next team or RETURN to exit" ) );
}

/*=======================================================================
 *
 *  Display team data on the screen
 *
 *  Purpose:
 *      This function is called to Display team data on the screen
 *      This function will prompt the operator to select a team number
 *      If the team is defined then the data will be displayed on the screen
 *
 *  Parameters:
 *      None
 *
 *  Returns:
 *      TRUE - Change made
 *
 *========================================================================*/

void team_display(void)
{
    if( !g_tnum( 0, n_lines - 2, "Enter team number" ) )
        return;                        /* Exit operation */

    /*
     * Fetch the team record into memory
     * If the record does not exist a record with an invalid flag
     * will be returned
     */

    do
    {
        clearscreen();
        if( g_record( team, &team_buf ) )
            d_display( M_DISPLAY );
        else
        {
            cur( 0, n_lines - 1 );
            printf( "Team %-1d has not yet been entered", team );
            beep();
        }
    } while( g_tnum( 0, n_lines - 2, "Enter next team or RETURN to exit" ) );
}

/*========================================================================
 *
 *  Modify team leg times
 *
 *  Purpose:
 *      This function is called to modify team leg times
 *      This function will prompt the operator to select a team number
 *      If the team is defined then the data will be displayed on the screen
 *
 *  Parameters:
 *      None
 *
 *  Returns:
 *      TRUE - Change made
 *
 *========================================================================*/
void leg_mods(void)
{
    if( !g_tnum( 0, n_lines - 2, "Enter team number" ) )
        return;                        /* Exit operation */

    /*
     **  Fetch the team record into memory
     ** If the record does not exist a record with an invalid flag
     ** will be returned
     */

    do
    {
        clearscreen();
        if( g_record( team, &team_buf ) )
        {
            set_times( &team_buf );
            d_display( M_LEGS );
            put_team_record( team, &team_buf );
        }
        else
        {
            cur( 0, n_lines - 1 );
            printf( "Team %-1d has not yet been entered", team );
            beep();
        }
    } while( g_tnum( 0, n_lines - 2, "Enter next team or RETURN to exit" ) );

}

/*========================================================================
 *
 *  Display all team information
 *
 *  Purpose:
 *      This function is called to display all the team information
 *
 *  Parameters:
 *      operation       Operation to perform
 *
 *  Returns:
 *      Nothing
 *
 *========================================================================*/
void d_display( int operation )
{
    int         valid = team_buf.flags.valid;
    int         opr;
    int         i, j;
    int         age_sum;

    /*
     **  Refresh the entire display (using a recursive call)
     */
    if( operation != M_DISPLAY )
        d_display( M_DISPLAY );


    /*
     **  Display the team number
     **      This cannot be edited.
     */
    d_field( 0, 0, "Team number : ", D_NUMBER, 6, &team_buf.numb, TRUE,
             M_DISPLAY );

    /*
     **  Determine the type of operation required
     **      Update or Display
     */
    opr = ( operation & M_TEAM ) ? M_UPDATE : M_DISPLAY;

    /*
     **  Display / Update the team name
     */
    do
    {
        d_field( 20, 0, "Team name : ", D_STRING, MAX_TM_NAME, team_buf.name,
                 valid, opr );
        if( abort_flag )
            return;
    } while( ( opr == M_UPDATE ) && ( !strlen( team_buf.name ) ) );

    /*
     **  Display / Update the class
     */
    do
    {
        d_field( 0, 1, "Class : ", D_CLASS, 1, &team_buf.class, valid, opr );
        if( abort_flag )
            return;
    } while( ( opr == M_UPDATE ) && !team_buf.class );

    /*
     **  The record is now active
     **  It may not be usefull, but it has the start of a valid recird
     */
    if( opr == M_UPDATE )
        team_buf.flags.valid = TRUE;

    /*
     **  Display / Update the country name
     */
    d_field( 30, 1, "Country :", D_COUNTRY, 4, &team_buf.country, valid,
             opr );
    if( abort_flag )
        return;

    /*
     **  Display / Update the name and sex of each team member
     */
    age_sum = 0;
    opr = ( operation & M_TEAM ) ? M_UPDATE : M_DISPLAY;
    for( i = 0; i < MAX_MEMB; i++ )
    {
        d_field( 0, 3 + i, "Name : ", D_STRING, MAX_PERSON_NAME,
                 team_buf.members[i].name, valid, opr );
        if( abort_flag )
            return;

        d_field( MAX_PERSON_NAME + 10, 3 + i, "Sex : ", D_SEX, 0,
                 &team_buf.members[i].sex, valid, opr );
        if( abort_flag )
            return;

        d_field( MAX_PERSON_NAME + 25, 3 + i, "Age : ", D_AGE, 3,
                 &team_buf.members[i].age, valid, opr );
        if( abort_flag )
            return;

        /*
        **  Sum ages
        **  -1 indicates invalid age
        */
        if ( age_sum >= 0 )
        {
            ushort age = team_buf.members[i].age;
            if ( age > 0 && age < 255 )
            {
                age_sum += age;
            }
            else
            {
                age_sum = -1;
            }
        }

    }

    /*
     **  Display / Update the leg informarion for each configured leg
     */
    for( j = 1; j <= config.num_legs; j++, i++ )
    {
        d_leg( 4 + i, j, &team_buf.leg[j], valid, operation );
        if( abort_flag )
        {
            i += config.num_legs - j + 1;
            break;
        }
    }

    /*
     **  Display the summary information
     **      For the team
     **      Event and class placing information
     **      Total age
     */
    d_leg( 4 + i, 0, &team_buf.leg[0], valid, M_DISPLAY );

    d_field( 0, 6 + i, "Event placing : ", D_NUMBER, 1,
             &team_buf.leg[0].le_place, valid, M_DISPLAY );
    d_field( 20, 6 + i, "Class placing : ", D_NUMBER, 1,
             &team_buf.leg[0].lec_place, valid, M_DISPLAY );
    d_field( 40, 6 + i, "Total Age : ", D_STRING, 5,
             age_a(age_sum), valid, M_DISPLAY );
             

    if( team_buf.flags.non_equestrian )
        d_field( 0, 7 + i, "Non-Equestrian", D_NULL, 1, 0, valid, M_DISPLAY );
    else if( team_buf.flags.disqualified )
        d_field( 0, 7 + i, "Disqualified", D_NULL, 1, 0, valid, M_DISPLAY );

}

/*========================================================================
 *
 *  Display / Update leg time information
 *
 *  Purpose:
 *      This function is called to display and update the leg
 *      time information.
 *
 *  Parameters:
 *      y           Screen position
 *      leg         Leg to process
 *      data        Leg data
 *      valid       Data valid flag
 *      operation   Operation to perform
 *
 *  Returns:
 *      Nothing
 *
 *========================================================================*/
void d_leg( int y, int leg, leg_type * data, int valid, int operation )
{
    int         i;
    int         oprs, oprf;

    /*
     **  Display the field header
     */
    if( operation == M_DISPLAY )
    {
        if( leg != 0 )
        {
            d_field( 0, y, "Leg ", D_NUMBER, 1, &leg, TRUE, M_DISPLAY );
            d_field( 7, y, "", D_STRING, MAX_LEG_NAME,
                     config.leg_name[leg - 1], TRUE, M_DISPLAY );
        }
        else
            d_field( 0, y, "Overall team times", D_STRING, 0, "", TRUE,
                     M_DISPLAY );
    }

    /*
     **  If we are doing an update,. then ensure that all the team times
     **  have been tested
     */

    if( operation & M_ALL )
        test_times( &team_buf, 0 );              /* Set up all team times */

    oprs = ( ( parallel_legs )
             || ( operation & M_ALEGS )
             || ( operation & M_LEGS ) ) ? M_UPDATE : M_DISPLAY;

    oprf = ( operation & M_LEGS ) ? M_UPDATE : M_DISPLAY;

    /*
     **  if start time edited then flag as manual entry
     **  redo calculations and refresh screen with new information
     */

    if( d_field
        ( 25, y, data->manual ? "MS " : " S ", D_TIME, 8, &data->start, valid,
          oprs ) )
    {
        data->manual = TRUE;
        test_times( &team_buf, 0 );
        for( i = leg; i <= config.num_legs; i++ )
            d_leg( y + i - leg, i, &team_buf.leg[i], valid, M_DISPLAY );
        d_leg( y + i - leg, 0, &team_buf.leg[0], valid, M_DISPLAY );
    }

    /*
     **  If time changed then redo calcs and refresh screen
     */
    if( d_field( 37, y, "F ", D_TIME, 8, &data->end, valid, oprf ) )
    {
        set_times( &team_buf );
        test_times( &team_buf, 0 );
        for( i = leg; i <= config.num_legs; i++ )
            d_leg( y + i - leg, i, &team_buf.leg[i], valid, M_DISPLAY );
        d_leg( y + i - leg, 0, &team_buf.leg[0], valid, M_DISPLAY );
    }

    d_field( 48, y, "E ", D_TIME, 8, &data->elapsed, valid, M_DISPLAY );
    if( leg == 0 )
    {
        d_field( 60, y, "", D_STRING, 10,
                 ( team_buf.flags.bad_times ==
                   TRUE ) ? "Incomplete" : "          ", valid, M_DISPLAY );
    }
    else
    {
        d_field( 60, y, "", D_NUMBER, 4, &data->le_place, valid, M_DISPLAY );
        d_field( 65, y, "", D_NUMBER, 4, &data->l_place, valid, M_DISPLAY );
        d_field( 70, y, "", D_NUMBER, 4, &data->lec_place, valid, M_DISPLAY );
        d_field( 75, y, "", D_NUMBER, 4, &data->lc_place, valid, M_DISPLAY );
    }
}

/*========================================================================
 *
 *  Display / Update simple time information
 *
 *  Purpose:
 *      This function is called to display and update the leg
 *      time information.
 *
 *  Parameters:
 *      x, y        Screen position
 *      prompt      Prompt to display
 *      data        Address of time data
 *      valid       Data valid flag
 *
 *  Returns:
 *      Nothing
 *
 *========================================================================*/
void d_time( int x, int y, char *prompt, time_t *data, int valid )
{
        d_field( x, y, prompt, D_TIME, 8, ( char * ) data, valid, M_DISPLAY );
        d_field( x, y, prompt, D_TIME, 8, ( char * ) data, valid, M_UPDATE );
}

/*========================================================================
 *
 *  Display / Update field on the screen
 *
 *  Purpose:
 *      
 *      This function is called to display and update a field on the screen
 *      This routine will display a record from the team structure
 *      The type of data and other parameters is passed in
 *      This function is fundimental to the entire display subsystem
 *
 *
 *
 *  Parameters:
 *      x           The screen col
 *      y           The line number
 *      prompt      The field lable
 *      type        type of field
 *      length      Length of the numeric field
 *      data        Pointer to the data
 *      valid       data field is valid
 *      operation   Operation type
 *
 *  Returns:
 *      TRUE - Change has been made
 *
 *========================================================================*/
bool d_field( int x,
              int y,
              char *prompt,
              int type, int length, void *data, int valid, int operation )
{
    time_t      t;
    int         i;
    sex_type    s;
    int         change = 0;
    int         idata;

    /*
     **  Position the cursor and display the field title
     */
    cur( x, y );
    printf( "%s", prompt );

    /*
     **  If the ABORT flag is set then DISPLAY the field
     */
    if( abort_flag )
        operation = M_DISPLAY;

    /*
     **  Display the current field value
     **      Only if the data field is valid
     **      Only if the M_DISPLAY operation is requested
     */
    if( valid && ( operation == M_DISPLAY ) )
    {
        switch ( type )
        {
        case D_STRING:
        case D_USTRING:
            printf( "%-*.*s", length, length, (char *)data );
            break;

        case D_NUMBER:
            printf( "%-*d", length, *( short * ) data );
            break;

        case D_SEX:
            if( *( sex_type * ) data != unknown )
                printf( "%s",
                        ( *( sex_type * ) data ==
                          male ) ? "Male" : "Female" );
            break;

        case D_TIME:
            printf( "%s", time_a( *( time_t * ) data ) );
            break;

        case D_CLASS:
            if( *( short * ) data > 0 )
            {
                printf( "%2.2s", config.team_class[( *( int * ) data ) - 1].abr );
                printf( "  %-*.*s", LEN_CLASS_NAME, LEN_CLASS_NAME,
                        config.team_class[( *( int * ) data ) - 1].full_name );
            }
            break;

        case D_COUNTRY:
            if( *( short * ) data > 0 )
            {
                printf( "%4.4s",
                        config.country_name[( *( int * ) data ) - 1].abr );
                printf( "  %-*.*s", LEN_CNTRY_NAME, LEN_CNTRY_NAME,
                        config.country_name[( *( int * ) data ) -
                                            1].full_name );
            }
            break;

        case D_AGE:
            if( *( uchar * ) data > 0 )
            {
                printf( "%-*d", length, *( uchar * ) data );
            }
            break;
            

        case D_NULL:
            break;

        default:
            printf( "Unknown data type" );
            break;
        }
    }

    /*
     **  If updating the field then extract the required information
     */
    if( operation == M_UPDATE )
    {
        switch ( type )
        {
        case D_STRING:
            change = ( getstring( length, data, Alphanum ) );
            break;

        case D_USTRING:
            change = ( getstring( length, data, AlphnumUpper ) );
            break;

        case D_NUMBER:
            idata = *(short *)data;
            change = getnum( length, &idata );
            if ( change )
                *( short *)data = idata;
            break;

        case D_SEX:
            if( ( s = getsex() ) != unknown )
            {
                change = ( *( sex_type * ) data != s );
                *( sex_type * ) data = s;
            }
            break;

        case D_TIME:
            if( ( t = get_time(*( time_t * ) data) ) >= 0 )
            {
                change = ( *( time_t * ) data != t );
                *( time_t * ) data = t;
            }
            break;

        case D_CLASS:
            if( ( i = getclass() ) != 0 )
            {
                change = *( short * ) data != i;
                *( short * ) data = i;
            }
            break;

        case D_COUNTRY:
            if( ( i = getcountry() ) != 0 )
            {
                change = *( short * ) data != i;
                *( short * ) data = i;
            }
            break;

        case D_AGE:
            idata = *(uchar *)data;
            change = getnum( length, &idata );
            if ( change )
                *( uchar *)data = idata;
            break;
            

        case D_NULL:
            break;

        default:
            printf( "Unknown data type" );
            break;
        }

        /*
         **  Having accepted the input now DISPLAY the data (once again)
         **      Done to allow aborted field to re-display original values
         */
        d_field( x, y, prompt, type, length, data, TRUE, M_DISPLAY );
    }
    return ( change );
}

/*========================================================================
 *
 *  Get a team number from the operator
 *
 *  Purpose:
 *      This function is called to Get a team number from the operator
 *          Prompt the operator for a team number
 *          Verify that the team number is valid
 *          Allow escape characters in the process
 *
 *          This routine will return TRUE if the team number is valid
 *          The team number is returned in the global variable "team"
 *
 *  Parameters:
 *      x,y         Screen coords
 *      prompt      Operator prompt
 *
 *  Returns:
 *      TRUE    : Number OK
 *
 *========================================================================*/
bool g_tnum( int x, int y, char *prompt )
{
    int         new_team = 0;                   /* team number that will be input */

    while( TRUE )
    {
        team = 0;
        abort_flag = FALSE;
        cur( x, y );
        printf( "%s : ", prompt );
        console_clreol();
        if( !getnum( 6, &new_team ) )
            return ( FALSE );                    /* No input */

        /*
         * verify that the team number is within the allowed numbers 
         */

        if( !valid_field( new_team ) )
        {
            beep();
            printf( "\nTeam %-1d is not valid", new_team );
            continue;
        }
        team = new_team;
        return ( TRUE );
    }
}

/*========================================================================
 *
 *  Read a team record from disk
 *
 *  Purpose:
 *      This function is called to Read a team record from disk
 *      Locate the team record in the team data file
 *      if the record does not exist create a blank record
 *
 *      The function will return FALSE if the record was not on disk
 *      otherwise TRUE
 *
 *  Parameters:
 *      int_team        Team record required
 *      data            Area to return record
 *
 *  Returns:
 *      FALSE : No data available
 *
 *========================================================================*/
bool g_record( int _team, team_type * data )
{
    int         len;                             /* length of record read in */
    long        pos;                             /* File pointer */

    pos = _team;
    pos *= sizeof( team_type );
    len = lseek( team_fd, pos, 0 );
    len = read( team_fd, ( char * ) data, sizeof( team_type ) );
    if( ( len == sizeof( team_type ) ) && ( _team == data->numb ) )
        return ( data->flags.valid );
    else
    {
        clr_team( _team, data );
        return ( FALSE );
    }
}

/*========================================================================
 *
 *  Clear team data from file
 *
 *  Purpose:
 *      This function is called to Clear team data from file
 *      This routine will set the team data to INVALID
 *
 *  Parameters:
 *      tm          Team number
 *      data        Pointer to the data
 *
 *  Returns:
 *      Nothing
 *
 *========================================================================*/
void clr_team( int tm, team_type * data )
{
    int         len;

    memset( ( char * ) data, 0, ( int ) sizeof( team_type ) );
    data->flags.valid = FALSE;
    data->flags.bad_times = TRUE;
    data->numb = tm;
    for( len = 0; len < MAX_LEGS + 1; len++ )
    {
        data->leg[len].start = -1;
        data->leg[len].end = -1;
        data->leg[len].elapsed = -1;
        data->leg[len].l_place = 0;
        data->leg[len].le_place = 0;
        data->leg[len].lec_place = 0;
        data->leg[len].lc_place = 0;
        data->leg[len].manual = 0;
    }
}

/*========================================================================
 *
 *  Save team record to disk
 *
 *  Purpose:
 *      This function is called to save team record to disk
 *
 *  Parameters:
 *      _team       Team number
 *      data        Pointer to the data
 *
 *  Returns:
 *      FALSE : Error in save
 *
 *========================================================================*/
bool put_team_record( int _team, team_type * data )
{
    int         len;                             /* length of record read in */
    long        pos;                             /* file pointer */

    pos = _team;
    pos *= sizeof( team_type );
    lseek( team_fd, pos, 0 );
    len = write( team_fd, ( char * ) data, sizeof( team_type ) );
    if( len != sizeof( team_type ) )
    {
        perror( "Team record write" );
        sleep( 5 );
    }
    return ( len == sizeof( team_type ) );
}

/*========================================================================
 *
 *  Initialize the team data file
 *
 *  Purpose:
 *      This function is called to Initialize the team data file and
 *      prepare it for processing
 *
 *  Parameters:
 *      None
 *
 *  Returns:
 *      FALSE : Error encountered
 *
 *========================================================================*/
bool init_team_data(void)
{

    team_fd = open( datfile, OPEN_RW, 0 );
    if( team_fd < 0 )
    {
        /*
         * file does not exist - create it 
         */
        printf( "The team data file does not exist.\n" );
        if( getyes( "Create the data file" ) )
        {
            team_fd = creat( datfile, 0664 );
            if( team_fd > 0 )
            {
                close( team_fd );                /* Close th file */
                team_fd = open( datfile, OPEN_RW, 644 );
                if( team_fd < 0 )
                    perror( "Team datafile" );
            }
        }
    }
    return ( team_fd >= 0 );
}

/*========================================================================
 *
 *  Close team data file
 *
 *  Purpose:
 *      This function is called to close the team data file
 *
 *  Parameters:
 *      None
 *
 *  Returns:
 *      Nothing
 *
 *========================================================================*/
void fix_team_data(void)
{
    if( team_fd > 0 )
        close( team_fd );
}

/********************************* EOF ***********************************/