/************************************************************************* * 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 /*#include */ #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 ***********************************/