/* * utility.c * * Misc utility routines for the pinewood derby program. */ /*** *** Include files ***/ #include #include #include #include #include #include "pragmas.h" #include "pinewood.h" /* * average * * Get the average race time for the user. */ long int average(int user) { int heat; int runs; long int total; for (runs = 0, total = 0L, heat = 0; heat < NRACES; heat++) { if (Database[user].run[heat] != 0) { total += Database[user].run[heat]; runs++; } } if (runs > 1) total = (total + (runs / 2)) / runs; if (total == 0) total = 9999; return (total); } /* * count_races * * return the number of races this user has participated in. * * If the user is -1, find the max number of races run. */ int count_races(int user) { int race; int rv; if (user == -1) { race = 0; for (user = 0; user < Nusers; user++) { if ((rv = count_races(user)) > race) race = rv; } } else { for (race = 0; race < NRACES; race++) { if (Database[user].run[race] == 0) break; } } return (race); } /* * find_rank * * Find the relative ranking. */ int find_rank(long int times[], int car) { int cn; int rank; rank = 1; for (cn = 0; cn < NLANES; cn++) { if ((times[cn] != 0) && (times[cn] < times[car])) rank++; } return (rank); } /* * format_time * * Format a time as an appropriate number. */ char * format_time(long int time_val) { static char retval[20]; sprintf(retval, "%2ld.%03ld", time_val / 1000, time_val % 1000); return (retval); } /* * init_db * * Initialize one database entry. */ void init_db(int user, bool_t full) { int run; if (full) { Database[user].name[0] = '\0'; Database[user].car[0] = '\0'; } for (run = 0; run < NRACES; run++) { Database[user].run[run] = 0; Database[user].lane[run] = 0; } Database[user].racenum = 0; Database_dirty = TRUE; } /* * read_database * * Read the database file */ void read_database(void) { char buffer[300]; char *cptr; char *end; FILE *fp; int run; if ((fp = fopen(DATABASE, "r")) != NULL) { for (Nusers = 0; Nusers < NUSERS; Nusers++) { init_db(Nusers, TRUE); if (fgets(buffer, sizeof(buffer), fp) == NULL) break; if ((cptr = strchr(buffer, '\n')) != NULL) *cptr = '\0'; if ((cptr = strchr(buffer, '\t')) != NULL) *cptr++ = '\0'; xstrncpy(Database[Nusers].name, buffer, NSIZE); sprintf(Database[Nusers].car, "%d", atoi(cptr)); if (strlen(Database[Nusers].car) == 1) { Database[Nusers].car[2] = '\0'; Database[Nusers].car[1] = Database[Nusers].car[0]; Database[Nusers].car[0] = '0'; } if ((cptr = strchr(cptr, '\t')) != NULL) cptr++; end = cptr; for (run = 0; run < NRACES && end != NULL; run++) { Database[Nusers].run[run] = strtol(end, &cptr, 10); Database[Nusers].lane[run] = atoi(cptr + 1); end = strchr(cptr, '\t'); } } fclose(fp); } Database_dirty = FALSE; } /* * read_ranks * * Read the rank to den mapping file. * * This allows us to know: * What order to attempt to run races * What dens are what ranks * What dens to combine together * Title reports */ void read_ranks(void) { char buffer[200]; char *cptr; int den; FILE *file; if ((file = fopen(RANKFILE, "r")) == NULL) { fprintf(stderr, "Cannot open rank file\n"); exit(1); } Nranks = 0; while ((fgets(buffer, sizeof(buffer), file) != NULL) && (Nranks < NRANKS - 1)) { if ((cptr = strchr(buffer, '\n')) != NULL) *cptr = '\0'; if (buffer[0] == '#' || buffer[0] == '\0') continue; for (cptr = buffer; *cptr != '\0' && !isspace(*cptr); cptr++) ; if (*cptr == '\0') continue; *cptr++ = '\0'; Ranks[Nranks].name = strdup(buffer); for (den = 0; den < 9 && cptr != NULL && *cptr != '\0'; den++) Ranks[Nranks].dens[den] = (int) strtol(cptr, &cptr, 10); Ranks[Nranks].dens[den] = -1; Nranks++; } fclose(file); } /* * save_database * * Save the current database file under a filename based upon * the time. Because everything will be basically happening * on the same night, this will be sufficient. */ void save_database(void) { time_t curtime; char fname[100]; struct tm *tm; (void) time(&curtime); tm = localtime(&curtime); sprintf(fname, "pine%02d%02d.dat", tm->tm_hour, tm->tm_min); (void) remove(fname); (void) rename(DATABASE, fname); } /* * write_database * * Write the current database out to the database file. */ void write_database(void) { FILE *fp; int run; int user; Database_dirty = FALSE; if ((fp = fopen(DATABASE, "w")) != NULL) { for (user = 0; user < Nusers; user++) { fprintf(fp, "%s\t", Database[user].name); fprintf(fp, "%s\t", Database[user].car); for (run = 0; run < NRACES; run++) { if (run != 0) fprintf(fp, "\t"); fprintf(fp, "%ld:%d", Database[user].run[run], Database[user].lane[run]); } fprintf(fp, "\n"); } fclose(fp); } } /* * xstrncpy * * Copy a certain number of characters. */ void xstrncpy(char *dest, char *src, size_t len) { strncpy(dest, src, len); dest[len] = '\0'; }