home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume10
/
tourney
/
part01
/
tourney.c
< prev
Wrap
C/C++ Source or Header
|
1990-03-06
|
19KB
|
854 lines
/***********************************************************************
* tourney - a curses-based program to keep track of the NCAA Basketball
* tournament.
*
* Author: Jack Alexander
* jack@jimi.cs.unlv.edu
*
* (c) 1989, by the author. Feel free to hack this code up as long as
* you don't remove the author's name or the copyright notice.
* I will attempt to maintain a current version based on valid
* changes sent to me at the above email address.
*
* Please send me any WORTHWHILE changes.
*
*
* WARNING: There is absolutely NO WARRANTY OF ANY KIND associated with
* this program, even for fitness of purpose. If you choose to run this
* software, it is at your own risk.
*
*/
#include <stdio.h>
#include <curses.h>
#include <fcntl.h>
#include <errno.h>
#include "get.h"
#define STANDINGS_FILE "standings" /* file used to output standings */
#define MASTER_FILE "#MASTER" /* file of results */
#define ENTRY_FILE "players/#ENTRIES" /* list of people in contest */
#define TEAM_FILE "teams" /* Name of the file for list of teams */
#define PLAYER_DIR "players" /* Directory for people's picks */
#define PLAYER_FILE "players/%s" /* Where to put people's picks */
#define TEAMS 64 /* Number of teams in tournament */
#define ROUNDS 7 /* results levels */
#define NAMESZ 20 /* Length of team names */
#define PATHSZ 14 /* max filename */
/* Main menu option values: */
#define MAIN_MENU_NAME " NCAA Basketball Tournament Tracker "
#define SETUP 1
#define UPDATE 2
#define SHOW_STANDINGS 3
#define EXIT 4
/* Setup menu option values: */
#define SETUP_MENU_NAME " Tournament Setup menu "
#define ENTER_TEAMS 1
#define ENTER_PERSON 2
#define PRINT_PERSON 3
#define REMOVE_PERSON 4
#define RETURN 5
int games[ROUNDS] = { 64, 32, 16, 8, 4, 2, 1 }; /* teams per round */
int points[ROUNDS] = { 0, 1, 2, 4, 8, 16, 32 }; /* points per round */
static char *region_name[] = {
"West", "East", "Midwest", "Southeast"
};
typedef struct menu_list {
char entry[50];
int value;
};
typedef struct entry {
char name[NAMESZ+1];
unsigned char round[ROUNDS][TEAMS];
};
struct menu_list mainmenu[EXIT] = {
"Setup tournament database", SETUP,
"Edit game results", UPDATE,
"Show pool standings", SHOW_STANDINGS,
"QUIT", EXIT,
};
struct menu_list setupmenu[RETURN] = {
"Edit list of teams in the tournament", ENTER_TEAMS,
"Enter a person into the pool, or edit their entry", ENTER_PERSON,
"Create a printable file of a person's entry", PRINT_PERSON,
"Remove an entry from the tournament", REMOVE_PERSON,
"RETURN to main menu", RETURN,
};
main()
{
int done=FALSE;
tourney_init();
while(!done)
switch(main_menu()) {
case SETUP:
setup_menu();
break;
case UPDATE:
enter_updates();
break;
case SHOW_STANDINGS:
show_standings();
break;
case EXIT:
cleanup();
done=TRUE;
break;
}
}
tourney_init()
{
initscr();
}
cleanup()
{
endwin();
}
enter_updates()
{
struct entry tr;
int rnd;
char title[80];
if(read_entry(MASTER_FILE,&tr,0))
return;
init();
while(1) {
clear();
printw("Enter the round that you want to edit. ESC to abort.");
printw("\n\nRound: ");
if(get_num(8,2,1,1,6,&rnd)==GET_ESCAPE) {
de_init();
return;
}
sprintf(title," Enter the results for round %d ",rnd);
if(edit_round(title,"The winner was ",rnd,games[rnd],&tr,1)) {
printw("\n Do you want to save this update (y/n)? ");
refresh();
if(getch()=='y')
save_entry(&tr);
}
else
save_entry(&tr);
}
}
show_standings()
{
FILE *fpin, *fpout, *fopen();
struct entry master, this_guy;
char name[NAMESZ+1], errmsg[80], sort[80];
int score, i, count=0;
if((fpin=fopen(ENTRY_FILE,"r"))==NULL) {
terror("ERROR opening entry master file");
return;
}
if((fpout=fopen(STANDINGS_FILE,"w"))==NULL) {
terror("ERROR opening standings output file");
return;
}
if(read_entry(MASTER_FILE,&master,0)) {
terror("ERROR opening results file");
return;
}
clear();
printw("Processing entries...");
move(5,0);
refresh();
while(fgets(name,NAMESZ,fpin)!=NULL) {
for(i=0;i<strlen(name);i++)
if(name[i]=='\n')
name[i]='\0';
if(read_entry(name,&this_guy,1)) {
move(5,0);
continue;
}
if((score = calculate_score(&master,&this_guy))<0)
fprintf(fpout,"*** %-20.20s ***** incomplete entry *****\n",name);
else
fprintf(fpout,"%3d %-20.20s\n",score,name);
count++;
}
fclose(fpin);
fclose(fpout);
if(count>1) {
sprintf(sort,"/bin/sort %s -o %s",STANDINGS_FILE,STANDINGS_FILE);
system(sort);
}
sprintf(errmsg,"Output is in '%s'",STANDINGS_FILE);
terror(errmsg);
}
calculate_score(master,cur)
struct entry *master, *cur;
{
int i, j, score=0;
for(i=1;i<ROUNDS;i++)
for(j=0;j<games[i];j++)
if(cur->round[i][j]==TEAMS+1)
return(-1); /* incomplete entry */
else if(master->round[i][j] == cur->round[i][j])
score += points[i];
return(score);
}
setup_menu()
{
int rcode;
while(rcode!=RETURN)
switch(rcode=menu(setupmenu,RETURN,SETUP_MENU_NAME)) {
case ENTER_TEAMS:
enter_teams();
break;
case ENTER_PERSON:
enter_picks();
break;
case PRINT_PERSON:
print_picks("");
break;
case REMOVE_PERSON:
remove_pick();
break;
case RETURN:
break;
}
}
main_menu()
{
return(menu(mainmenu,EXIT,MAIN_MENU_NAME));
}
menu(sels,q,name)
struct menu_list sels[];
int q;
char name[];
{
int i;
clear();
standout();
printw(name);
standend();
printw("\n\n");
for(i=0;i<q;i++)
printw("%2d. %s\n",i+1,sels[i].entry);
for(i=0;i<1 || i>q;) {
move(q+4,0);
printw("Which ?");
refresh();
i=getch()-'0';
}
return(sels[i-1].value);
}
remove_pick()
{
char entrant[PATHSZ+1], filename[80], tmp[80];
FILE *fpin, *fpout, *fopen();
int i;
init();
clear();
printw("Enter the name of the entrant you want to REMOVE\n\n");
printw("Name: ");
entrant[0]='\0';
if(getst(PATHSZ,7,2,entrant,PATHSZ+1,NULL,LETTER_ONLY,NULL)==GET_ESCAPE) {
de_init();
return;
}
de_init(); /* input is over for this routine */
for(i=0;i<NAMESZ;i++)
tmp[i]= (entrant[i]==' ')? '_':entrant[i];
sprintf(filename,PLAYER_FILE,tmp);
if(unlink(filename)<0) {
terror("ERROR unlinking entry file");
return;
}
sprintf(filename,"%stourney.XXXXXX",PLAYER_FILE);
mktemp(filename);
if((fpout=fopen(filename,"w"))==NULL) {
terror("ERROR opening temporary file");
return;
}
if((fpin=fopen(ENTRY_FILE,"r"))==NULL) {
terror("ERROR opening entry file (list of people)");
return;
}
while(fgets(tmp,NAMESZ,fpin)!=NULL) {
for(i=strlen(tmp);i>=0;i--)
if(tmp[i]=='\n') {
tmp[i]='\0';
break;
}
if(strcmp(tmp,entrant))
fprintf(fpout,"%s\n",tmp);
}
fclose(fpout);
fclose(fpin);
if(unlink(ENTRY_FILE)<0) { /* remove old entry file */
terror("ERROR unlinking old entry file");
return;
}
link(filename,ENTRY_FILE); /* link to new version */
unlink(filename); /* remove temporary file */
}
print_picks(name)
char name[];
{
char entrant[NAMESZ+1], errmsg[80], teams[TEAMS][NAMESZ+1],
filename[PATHSZ+1];
struct entry tr;
int i, j;
FILE *fp, *fopen();
clear();
if(read_teams(teams)) {
terror("ERROR opening teams file");
return;
}
init();
if(name[0]=='\0') {
printw("Enter the name of the entrant\n\n");
printw("Name: ");
entrant[0]='\0';
if(getst(PATHSZ,7,2,entrant,PATHSZ+1,NULL,LETTER_ONLY,NULL)==GET_ESCAPE) {
de_init();
return;
}
}
else
strcpy(entrant,name);
if(read_entry(entrant,&tr,1)) {
sprintf(errmsg,"There is no '%s' on file.",entrant);
de_init();
return;
}
for(i=0;i<ROUNDS;i++)
for(j=0;j<games[i];j++)
if(tr.round[i][j] >= TEAMS) {
terror("ERROR this entry has not been completly entered");
de_init();
return;
}
clear();
filename[0]='\0';
printw("Enter the name of the output file.\n\n");
printw("File Name: ");
if(getst(PATHSZ,11,2,filename,PATHSZ+1,NULL,LETTER_ONLY,NULL)==GET_ESCAPE) {
de_init();
return;
}
de_init();
for(i=0;i<strlen(filename);i++)
if(filename[i]==' ')
filename[i]='_';
if((fp=fopen(filename,"w"))==NULL) {
sprintf(errmsg,"ERROR opening file '%s', errno=%d",filename,errno);
terror(errmsg);
return;
}
for(i=0;i<4;i++) {
fprintf(fp,"==============================================================================\n");
fprintf(fp,"SELECTIONS FOR ENTRANT: %-12.12s %12.12s Region page %d\n",entrant,region_name[i],i+1);
fprintf(fp,"==============================================================================\n");
/* This code is a little ugly, but a fancy little
loop would have been more time consuming that
I felt it was worth... */
fprintf(fp,"%s\n",teams[tr.round[0][16*i]]);
fprintf(fp," %s\n",teams[tr.round[1][8*i]]);
fprintf(fp,"%s\n",teams[tr.round[0][16*i + 1]]);
fprintf(fp," %s\n",teams[tr.round[2][4*i]]);
fprintf(fp,"%s\n",teams[tr.round[0][16*i + 2]]);
fprintf(fp," %s\n",teams[tr.round[1][8*i + 1]]);
fprintf(fp,"%s\n",teams[tr.round[0][16*i + 3]]);
fprintf(fp," %s\n",
teams[tr.round[3][2*i]]);
fprintf(fp,"%s\n",teams[tr.round[0][16*i + 4]]);
fprintf(fp," %s\n",teams[tr.round[1][8*i + 2]]);
fprintf(fp,"%s\n",teams[tr.round[0][16*i + 5]]);
fprintf(fp," %s\n",teams[tr.round[2][4*i+1]]);
fprintf(fp,"%s\n",teams[tr.round[0][16*i + 6]]);
fprintf(fp," %s\n",teams[tr.round[1][8*i + 3]]);
fprintf(fp,"%s\n",teams[tr.round[0][16*i + 7]]);
fprintf(fp," Final Four: %-s\n",
teams[tr.round[4][i]]);
fprintf(fp,"%s\n",teams[tr.round[0][16*i + 8]]);
fprintf(fp," %s\n",teams[tr.round[1][8*i + 4]]);
fprintf(fp,"%s\n",teams[tr.round[0][16*i + 9]]);
fprintf(fp," %s\n",teams[tr.round[2][4*i+2]]);
fprintf(fp,"%s\n",teams[tr.round[0][16*i + 10]]);
fprintf(fp," %s\n",teams[tr.round[1][8*i + 5]]);
fprintf(fp,"%s\n",teams[tr.round[0][16*i + 11]]);
fprintf(fp," %s\n",
teams[tr.round[3][2*i+1]]);
fprintf(fp,"%s\n",teams[tr.round[0][16*i + 12]]);
fprintf(fp," %s\n",teams[tr.round[1][8*i + 6]]);
fprintf(fp,"%s\n",teams[tr.round[0][16*i + 13]]);
fprintf(fp," %s\n",teams[tr.round[2][4*i+3]]);
fprintf(fp,"%s\n",teams[tr.round[0][16*i + 14]]);
fprintf(fp," %s\n",teams[tr.round[1][8*i + 7]]);
fprintf(fp,"%s\n",teams[tr.round[0][16*i + 15]]);
if(i!=3)
fprintf(fp,"%c",12); /* form feed at all but last */
}
fprintf(fp,"\n\n\n\nFinal four on down to champion:");
fprintf(fp,"-------------------------------\n\n\n");
fprintf(fp,"%-s\n",teams[tr.round[4][0]]);
fprintf(fp," %s\n",teams[tr.round[5][0]]);
fprintf(fp,"%-s\n",teams[tr.round[4][1]]);
fprintf(fp," %s **** NATIONAL CHAMPION ****\n",
teams[tr.round[6][0]]);
fprintf(fp,"%-s\n",teams[tr.round[4][2]]);
fprintf(fp," %s\n",teams[tr.round[5][1]]);
fprintf(fp,"%-s\n",teams[tr.round[4][3]]);
fclose(fp);
}
enter_picks()
{
char teams[TEAMS][NAMESZ+1], entrant[NAMESZ+1], title[80],
blurb[80];
int round, game, p, i, save_flag=0, print_flag=1;
struct entry tr;
clear();
init();
printw("Enter the name of the entrant (must be a unique name)\n\n");
printw("Name: ");
if(getst(PATHSZ,7,2,entrant,PATHSZ+1,NULL,LETTER_ONLY,NULL)==GET_ESCAPE)
return;
if(!read_entry(entrant,&tr,1)) {
printw("\n\n\nThis person is already on file. Do you wish to edit their entry (y/n)?");
refresh();
if(getch()!='y') {
de_init();
return;
}
}
else {
save_flag = 1;
clear_entry(&tr);
sprintf(tr.name,entrant);
}
sprintf(blurb,"%s picks ",entrant);
for(i=1;i<ROUNDS;i++) {
sprintf(title," Enter round %d picks for entrant '%s' ",
i,entrant);
if(edit_round(title,blurb,i,games[i],&tr,0)) {
printw("\n\n Do you want to save this entry (y/n)? ");
refresh();
if(getch()=='y')
save_entry(&tr);
else
print_flag=save_flag=0;
i=ROUNDS+1;
}
}
if(i==ROUNDS)
save_entry(&tr);
if(save_flag)
update_entry_list(entrant);
if(print_flag) {
printw("\nThe entry for '%s' has been saved.\n",entrant);
printw("\nDo you want to create a printable file of this entry (y/n)?");
refresh();
if(getch()=='y')
print_picks(entrant);
}
de_init();
}
save_teams(teams)
char teams[TEAMS][NAMESZ+1];
{
int i;
FILE *fp, *fopen();
if((fp=fopen(TEAM_FILE,"w"))==NULL) {
clear();
terror("ERROR opening teams file");
return;
}
for(i=0;i<TEAMS;i++)
fprintf(fp,"%s\n",(teams[i][0]=='\0')? "#":teams[i]);
fclose(fp);
}
read_teams(teams)
char teams[TEAMS][NAMESZ+1];
{
FILE *fp, *fopen();
int i, j;
if((fp=fopen(TEAM_FILE,"r"))<0) {
return(1);
}
for(i=0;i<TEAMS;i++) {
if(fgets(teams[i],NAMESZ,fp)==NULL)
break;
else if(teams[i][0]=='#')
teams[i][0]='\0';
else
for(j=0;j<NAMESZ;j++)
if(teams[i][j]=='\n') {
teams[i][j] = '\0';
break;
}
}
for(;i<TEAMS;i++)
teams[i][0]='\0';
fclose(fp);
return(0);
}
terror(s)
char s[];
{
char dummy[11];
standout();
printw("\n\n%s\n\n",s);
standend();
printw("Press RETURN to continue...");
refresh();
scanw("%10.10s",dummy);
}
enter_teams()
{
char teams[TEAMS][NAMESZ+1], the_header[80];
static char *headers[] = {
" ENTER TEAMS IN %s ",
" ENTER TEAMS IN %s ",
" ENTER TEAMS IN %s ",
" ENTER TEAMS IN %s ",
};
int i=0, done=0, r;
read_teams(teams); /* get currently saved team info */
i=0;
while(!done) {
sprintf(the_header, headers[i], region_name[i]);
switch(r=editlist(the_header,i*16,(i+1)*16,teams)) {
case GET_DOWN:
case GET_RIGHT:
if(i!=3)
i++;
else {
done=1;
save_teams(teams);
init_standings();
}
break;
case GET_UP:
case GET_LEFT:
if(i)
i--;
break;
case -1: /* ABORT! */
move(21,0);
printw("Are you sure you want to abort (y/n)?");
refresh();
if(getch()=='y')
done = 1;
break;
default:
move(21,0);
printw("editlist returns %d\n",r);
break;
}
}
return;
}
editlist(title,i1,i2,names)
char title[], names[TEAMS][NAMESZ+1];
int i1, i2;
{
int state = 0, i, j, game, rval, done=0, rcode=0, y;
clear();
standout();
printw(title);
standend();
edit_msg();
init();
for(i=i1,j=2;i!=i2;i++,j++) {
move(j,0);
if((i%2) == 0) {
game = i/2 + 1;
printw("Game #%02d, team #1: ", game);
}
else
printw(" team #2: ");
getst(NAMESZ,21,j,names[i],NAMESZ+1,NULL,SHOW,NULL);
}
refresh();
i=0;
while(!done) {
y = 2+i;
switch(getst(NAMESZ,21,y,names[i+i1],NAMESZ+1,NULL,ALL_ALPHA,NULL))
{
case GET_ESCAPE:
done=1;
rcode= -1;
break;
case GET_RETURN:
case GET_RIGHT:
case GET_DOWN:
i++;
if(i+i1 == i2) {
done=1;
rcode = GET_DOWN;
}
break;
case GET_UP:
case GET_LEFT:
i--;
if(i<0) {
i=0;
done=1;
rcode=GET_LEFT;
}
break;
default:
break;
}
}
de_init();
return(rcode);
}
edit_msg()
{
standout();
move(22,0);
printw(" To change regions, scroll off the top and bottom ends of current region. ");
move(23,0);
printw(" Use arrow keys for cursor movement, ESC to abort, and control-x to delete ");
standend();
}
init_standings()
{
struct entry tr;
clear_entry(&tr);
sprintf(tr.name,MASTER_FILE);
save_entry(&tr);
}
clear_entry(e)
struct entry *e;
{
int i, j;
for(i=0;i<ROUNDS;i++)
for(j=0;j<TEAMS;j++)
e->round[i][j]= (i==0)? j: TEAMS+1;
}
read_entry(name,e,flag)
char name[];
struct entry *e;
int flag; /* if set, no error messages */
{
char filename[80],tmp[NAMESZ+1], errmsg[80];
int fd, i;
for(i=0;i<NAMESZ;i++)
tmp[i]= (name[i]==' ')? '_':name[i];
sprintf(filename,PLAYER_FILE,tmp);
if((fd=open(filename,O_RDONLY))<0) {
if(!flag) {
sprintf(errmsg,"ERROR reading entry '%s', errno=%d",
filename,errno);
terror(errmsg);
}
return(1);
}
read(fd,e,sizeof(struct entry));
close(fd);
return(0);
}
save_entry(e)
struct entry *e;
{
char filename[80],tmp[NAMESZ+1], errmsg[80];
int fd, i;
for(i=0;i<NAMESZ;i++)
tmp[i]= (e->name[i]==' ')? '_':e->name[i];
sprintf(filename,PLAYER_FILE,tmp);
if((fd=open(filename,O_CREAT|O_WRONLY,0600))<0) {
sprintf(errmsg,"ERROR saving entry, errno=%d",errno);
terror(errmsg);
return(1);
}
if(write(fd,e,sizeof(struct entry))!=sizeof(struct entry)) {
sprintf(errmsg,"ERROR in write of entry, errno=%d",errno);
terror(errmsg);
}
close(fd);
}
/* title is the line on top of the screen.
* prompt is the message to display prior to showing current selection
* rnd in the round number (1-6)
* entires is the number of games this round
* e is this person's entry structure (pointer to)
* non is flag, if set then person can select neither team (results not in)
*/
edit_round(title,prompt,rnd,entries,e,non)
char title[], prompt[];
int entries, rnd,non;
struct entry *e;
{
int i, winner1, winner2, c, done, toggle, x, x2;
char teams[TEAMS][NAMESZ+1], *p;
static char neither[] = "neither -- Game not played yet";
if(read_teams(teams)) {
terror("ERROR: have to enter tournament teams before results");
return(1);
}
clear();
standout();
printw(title);
standend();
if(rnd!=1) /* check to see if previous round is complete */
for(i=0;i<games[rnd-1];i++)
if(e->round[rnd-1][i]== TEAMS+1) {
clear();
terror("ERROR: previous round incomplete");
return(1);
}
move(22,0);
standout();
printw(" Use the space bar to select advancing team, RETURN once the correct team is \n");
printw(" displayed. Use left arrow to go to a previously entered game. ESC to abort ");
standend();
for(i=0;i<games[rnd];i++) {
move(3,0);
printw("Game %d:\n------------\n\n",i+1);
printw("%s\n vs %s\n%s\n",
teams[e->round[rnd-1][i*2]], prompt,
teams[e->round[rnd-1][i*2+1]]);
winner1 = e->round[rnd-1][i*2];
winner2 = e->round[rnd-1][i*2+1];
done = toggle = 0;
if(e->round[rnd][i] == winner1)
toggle = 0;
else if(non) {
if(e->round[rnd][i] == winner2)
toggle = 1;
else
toggle = 2;
}
else
toggle = 1;
x = strlen(prompt) + 19;
while(!done) {
move(7,x);
standout();
switch(toggle) {
case 0:
p = teams[winner1];
break;
case 1:
p = teams[winner2];
break;
case 2:
p = neither;
break;
}
printw("%s\n",p);
standend();
x2 = x + strlen(p) +1;
move(7,x2);
clrtoeol(); /* get rid of "standend" char on some terminals */
refresh();
switch(c = getch()) {
case ' ':
if(non)
toggle = ++toggle % 3;
else
toggle = ++toggle % 2;
break;
case GET_RETURN:
case GET_DOWN:
done=1;
break;
case GET_LEFT:
if(i==0)
break;
done = 2;
break;
case GET_ESCAPE:
return(1);
}
if(done==2)
i-=2;
else
switch(toggle) {
case 0:
e->round[rnd][i] = winner1;
break;
case 1:
e->round[rnd][i] = winner2;
break;
case 2:
e->round[rnd][i] = TEAMS+1;
break;
}
}
}
return(0);
}
update_entry_list(name)
char name[];
{
FILE *fp, *fopen();
if((fp=fopen(ENTRY_FILE,"a"))==NULL) {
terror("ERROR opening entry file (list of people)");
return;
}
fprintf(fp,"%s\n",name);
fclose(fp);
}