home *** CD-ROM | disk | FTP | other *** search
- /* EZVOTE.C - EZVote is an example door written in OpenDoors. This is a
- * relatively simple door that allows BBS users to vote anonymously
- * on various topics, entered by other users. Users are able to view
- * the results of voting on a topics, only if they have already
- * voted on the topic, and may only vote on each topic once. The
- * door automatically uses ANSI or AVATAR graphics if available, and
- * will work with nearly any BBS system. When in the door, the sysop
- * (automatically detected by comparing user name to sysop name)
- * also has the option of deleting existing questions.
- *
- * EZVote also provides all of the features that are available in
- * any OpenDoors door, without any extra effort on the part of the
- * programmer. These features include sysop chatting, paging, full
- * status line, shell to DOS, time adjusting, hangup & lockout, and
- * other function keys. It does, of course, properly monitor carrier
- * detect, user inactivity and user time left. EZVote also runs very
- * quickly and reliably is automatically DesqView aware. EZVote will
- * also function perfectly normally in local mode.
- *
- * In addition to these features, EZVote's operation can be
- * customized using the EZVOTE.CFG file. This accompanying
- * configuration file is automatically read by OpenDoor's built in
- * configuration file system. EZVote also makes use of OpenDoor's
- * logfile sub-system.
- *
- * EZVote will exit with one of the following errorlevels:
- * 0 - Critical Door error (no fossil, etc.)
- * 1 - Carrier lost, user off-line
- * 2 - Sysop terminated call, user off-line
- * 3 - User time used up, user STILL ON-LINE
- * 4 - Keyboard inactivity timeout, user off-line
- * 5 - Sysop dropped user back to BBS, user ON-LINE
- * 10 - User chose to return to BBS
- * 11 - User chose to logoff, user off-line
- * 12 - Critical EZVote error
- *
- * EZVote may be recompiled or changed as you wish, under the
- * conditions of the OpenDoors "licence" (ie, if you haven't
- * registered, you can not distribute any doors compiled in
- * OpenDoors, and may only use OpenDoors for a three week evaluation
- * period). If you wish to compile EZVote, as with any OpenDoors
- * door, all you must do is to ensure OPENDOOR.H is present in the
- * default directory, and that Turbo C(++) / Borland C++ is
- * configured to link your program with the appropriate OpenDoors
- * library file. For more detailed information on this example
- * program please see the OPENDOORS.DOC file.
- */
-
-
- #include <conio.h>
- #include <io.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys\stat.h>
- #include <alloc.h>
-
- #include "opendoor.h" /* Must be included in all doors */
-
-
- char menu_text=0x02; /* EZVote default display colours */
- char menu_highlight=0x0a;
- char input_colour=0x0f;
- char title_text=0x0c;
- char title_lines=0x04;
- char copyright_colour=0x04;
- char list_colour=0x02;
-
-
- void choose_topic(int mode); /* Allows user to choose a question */
- void display_results(void); /* Displays the results of a question */
- void vote(void); /* Places the user's vote */
- int add_answer(void); /* Adds a new answer to the question */
- void save_file(void); /* Saves the EZVOTE.BBS file */
- void delete_question(void); /* Removes a question from the file */
- void main_menu(void); /* Displays the EZVote main menu */
-
-
- struct file_struct /* EZVOTE.BBS file format */
- {
- int num_questions; /* Number of questions in the file */
- char quest_title[20][60], /* The "Title" of each question */
- quest_by[20][36], /* Who wrote each question */
- quest_text[20][60]; /* The actual question itself */
- int quest_num_ans[20]; /* The number of answers to each quest. */
- char quest_answers[20][20][60]; /* The possible answers for each quest. */
- int total_votes[20], /* # of times quest. has been voted on */
- votes[20][20], /* # of votes each chioce has recieved */
- num_users; /* Number of users who have used door */
- char user[200][36], /* Each user's name */
- voted[200][20]; /* Has the user voted on each question? */
- } *file;
-
- /* Variables used by the door */
- int handle, counter, usernum, topic, choice, key, sysop;
- char string[80];
-
-
- main()
- { /* Attempt to allocate memory for file structure */
- if((file=malloc(sizeof(struct file_struct)))==NULL)
- {
- printf("Not enough available memory for EZVote for run!\n");
- return(12);
- }
-
-
- strcpy(od_registered_to,"[Unregistered]"); /* OpenDoors registration info */
- od_registration_key=000000000000;
-
- strcpy(od_program_name,"EZVote 4.10"); /* Name of door program */
-
-
- /* Initialize OpenDoors, using the configuration file EZVOTE.CFG */
- od_init_with_config("EZVOTE.CFG",NULL);
-
-
- od_log_open(); /* Open the log file and begin logging door activities */
-
-
-
- /* Cause OpenDoors to call the save_file() function before exiting, under any
- * circumstances. This way, the EZVOTE.BBS data file will be saved, even if
- * if the user looses connection.
- */
- od_control.od_before_exit=save_file;
-
-
- /* Open the EZVOTE.BBS data file */
- if((handle=open("EZVOTE.BBS",O_RDONLY|O_BINARY))==-1)
- { /* Create the file if it does not exist */
- od_log_write("EZVOTE.BBS data file not found, creating new one");
- handle=open("EZVOTE.BBS",O_RDWR|O_BINARY|O_CREAT,S_IWRITE|S_IREAD);
- file->num_questions=0; /* Blank file to zero questions, and zero users */
- file->num_users=0;
- write(handle,file,sizeof(struct file_struct));
- }
- else /* Read data from file if it exists */
- read(handle,file,sizeof(struct file_struct));
- close(handle); /* Close the file again */
-
- /* Search for user in EZVOTE.BBS */
- for(usernum=0;usernum<file->num_users;++usernum)
- if(strcmp(file->user[usernum],od_control.user_name)==0) break;
-
- if(usernum==file->num_users) /* If user hasn't used EZVote before */
- { /* Add him/her to the file */
- if(++file->num_users>200) od_exit(12,FALSE);
- strcpy(file->user[usernum],od_control.user_name);
- for(counter=0;counter<20;++counter)
- file->voted[usernum][counter]=FALSE;
- }
- /* Check if the user is the sysop */
- sysop=strcmp(od_control.user_name,od_control.sysop_name)==0;
-
- do
- {
- main_menu(); /* Display the main menu */
-
- od_set_attrib(input_colour); /* Display prompt with time remaining */
- od_printf("Select Command (%d mins)\n\r",od_control.user_timelimit);
- od_set_attrib(menu_text);
-
- /* Get user's choice */
- switch(key=od_get_answer("vrapdqg\n\r"))
- {
- case 'v': /* If user pressed V key (upper or lower case) */
- do
- { /* Allow user to choose a topic to vote on */
- choose_topic(FALSE);
-
- /* If valid topic # entered */
- if(topic>=0 && topic<=19)
- { /* Display the question to the user */
- od_set_attrib(title_text);
- od_disp_str("\n\r\n\r");od_clr_scr();
- od_disp_str(file->quest_text[topic]);
- od_disp_str("\n\r");
- od_set_attrib(list_colour);
-
- /* Display possible answers to user */
- for(counter=0;counter<file->quest_num_ans[topic];++counter)
- {
- od_printf(" %2d.) %s\n\r",counter+1,file->quest_answers[topic][counter]);
- }
- /* Get user's choice */
- od_set_attrib(input_colour);
- od_disp_str("\n\rSelect answer, [O] for other, or [Enter] to pass: ");
-
- /* Allow user to input choice of up to two characters */
- od_input_str(string,2,32,127);
- choice=atoi(string)-1;
-
- /* If user selected "other" option */
- if(string[0]=='o' || string[0]=='O')
- { /* If room to add another answer */
- if(file->quest_num_ans[topic]<20)
- { /* Allow user to add an answer to question */
- od_disp_str("\n\r\n\rWhat is your \"Other\" answer?\n\r");
- if(add_answer())
- { /* If user actually added answer */
- choice=file->quest_num_ans[topic]-1;
- vote(); /* Record user's vote */
- }
- }
- else /* If there is no room for more answers */
- { /* Indicate this to user */
- od_disp_str("\n\r\n\rThis question already has 20 answers!\n\r");
- od_disp_str("Press any key to continue...\n\r");
- od_get_key(TRUE);
- }
- }
-
- else /* If user voted for a possible option */
- {
- if(choice>=0 && choice<=file->quest_num_ans[topic])
- {
- vote(); /* Record user's vote */
- }
- }
- }
-
- } while(topic!=-1); /* Loop until user is finished voting */
- break;
-
-
- case 'r': /* If user wants to display results */
- for(;;)
- {
- choose_topic(TRUE); /* Allow user to choose a topic */
- if(topic==-1) break; /* Exit loop if user wishes to abort */
- display_results(); /* Display results of question */
- }
- break;
-
-
- case 'a': /* If adding a new question */
- od_clr_scr(); /* Clear the screen (if enabled) */
-
- /* If there is room for another question */
- if(file->num_questions<20)
- {
- /* Store user's name as author of question */
- strcpy(file->quest_by[file->num_questions],od_control.user_name);
- file->total_votes[file->num_questions]=0;
-
- /* Get question title from user */
- od_disp_str("\n\r\n\rWhat is the title of your question?\n\r > ");
- od_set_attrib(input_colour);
- od_input_str(string,59,32,127);
- od_set_attrib(menu_text);
- strcpy(file->quest_title[file->num_questions],string);
-
- if(strlen(string)!=0) /* If user did not abort */
- { /* Get the question itself from user */
- od_disp_str("\n\rWhat is your question?\n\r > ");
- od_set_attrib(input_colour);
- od_input_str(string,59,32,127);
- od_set_attrib(menu_text);
- strcpy(file->quest_text[file->num_questions],string);
- /* If user did not abort */
- if(strlen(string)!=0)
- { /* Get the possible answers */
- od_disp_str("\n\rNow, enter the possible answers to your question:\n\r");
- topic=file->num_questions;
- file->quest_num_ans[topic]=0;
- while(add_answer());
-
- /* Confirm question creation */
- od_set_attrib(menu_text);
- od_disp_str("Do you wish to save this question? (Y/N) ");
- choice=od_get_answer("yn");
-
- if(choice=='y') /* If confirmed */
- {
- file->num_questions++; /* Make addition permanent */
- /* Record addition in log file */
- od_log_write("User created new question");
- }
- }
- }
- }
- else /* If no room for a new question, inform user */
- {
- od_disp_str("Sorry, EZVote has a limit of 20 questions.\n\r");
- od_disp_str("Press any key to continue...\n\r\n\r");
- od_log_write("User attempting to create new question, 20 question limit reached");
- od_get_key(TRUE);
- }
-
- break;
-
-
- case 'p': /* If user wants to page the sysop */
- od_page(); /* OpenDoors takes care of the rest */
- break;
-
- case 'd': /* If user pressed delete key */
- if(sysop) /* If it is the sysop */
- {
- od_clr_scr(); /* Clear the screen */
-
- /* Ask which question to delete */
- od_disp_str("Please enter question number to delete: ");
- od_set_attrib(input_colour);
- od_input_str(string,2,'0','9');
- topic=atoi(string)-1;
- od_set_attrib(menu_text);
- /* If valid choice */
- if(topic>=0 && topic<file->num_questions)
- { /* Confirm question deletion */
- od_printf("\n\r\n\r Delete: %s\n\r\n\r",file->quest_title[topic]);
- od_set_attrib(title_text);
- od_disp_str("Are You Sure? (Y/N)\n\r");
- od_set_attrib(menu_text);
- choice=od_get_answer("yn");
-
- /* If confirmed, delete question */
- if(choice=='y') delete_question();
- }
- }
- } /* Loop until quit to BBS or logoff */
- } while(key!='q' && key!='g');
-
- if(key=='g') /* If user wishsed to log off */
- { /* Display "goodbye" line */
- od_printf("\n\rGoodbye from %s...\n\r",od_control.system_name);
- od_exit(11,TRUE); /* Let OpenDoors take care of the rest */
- }
- else
- { /* Acknowledge return to BBS */
- od_printf("\n\rReturning you to %s...\n\r",od_control.system_name);
- od_exit(10,FALSE); /* Again OpenDoors does the rest */
- }
-
- return(0);
- }
-
-
- void save_file(void) /* Function to save EZVOTE.BBS file */
- { /* (called before door termination) */
- handle=open("EZVOTE.BBS",O_WRONLY|O_BINARY);
- write(handle,file,sizeof(struct file_struct));
- close(handle);
- }
-
-
- int add_answer(void) /* Function to add answer to file */
- { /* Check for room to add answer */
- if(file->quest_num_ans[topic]>=20) return(FALSE);
-
- od_set_attrib(menu_text); /* Get user's answer */
- od_printf(" %2d> ",file->quest_num_ans[topic]+1);
- od_set_attrib(input_colour);
- od_input_str(string,59,32,127);
- if(strlen(string)==0) return(FALSE);
- /* If no abort, add to question */
- file->votes[topic][file->quest_num_ans[topic]]=0;
- strcpy(file->quest_answers[topic][file->quest_num_ans[topic]++],string);
- return(TRUE);
- }
-
-
-
- void choose_topic(int mode) /* Function to let user to choose question */
- {
- register char displayed=FALSE;
-
- for(;;)
- {
- od_set_attrib(title_text);
- od_clr_scr(); /* Clear the screen */
- od_disp_str("Choose A Topic:\n\r");
- od_set_attrib(list_colour);
- /* Display questions */
- for(counter=0;counter<file->num_questions;++counter)
- { /* If question should be displayed */
- if(file->voted[usernum][counter]==mode)
- {
- displayed=TRUE; /* Display question */
- od_printf(" %d.) %s\n\r",counter+1,file->quest_title[counter]);
- }
- }
- /* if no topics were displayed... */
- if(!displayed) od_disp_str("\n\r No Topics to choose from.\n\r\n\r");
-
- od_set_attrib(input_colour);
- od_disp_str("Select topic, or [Enter] to return to main menu: ");
-
- od_input_str(string,2,'0','9'); /* Get user's choice */
-
- topic=atoi(string)-1; /* Convert string to number */
-
- if(topic==-1) return; /* If user aborted, exit */
- /* If valid question, exit */
- if(topic<file->num_questions && topic>=0 && file->voted[usernum][topic]==mode) return;
- }
- }
-
-
-
- void display_results(void) /* Function to display results of question */
- {
- od_set_attrib(title_text); /* Display the header */
- od_clr_scr();
- od_disp_str(file->quest_title[topic]);
- od_set_attrib(title_lines);
- od_printf("\n\r(Created by: %s)\n\r",file->quest_by[topic]);
-
- od_set_attrib(list_colour);
- /* Loop through each answer, displaying statistics */
- for(counter=0;counter<file->quest_num_ans[topic];++counter)
- od_printf(" %-3d %3d%% %s\n\r",file->votes[topic][counter],(file->votes[topic][counter]*100)/file->total_votes[topic],file->quest_answers[topic][counter]);
-
- od_set_attrib(input_colour);
- /* Wait for user to press a key */
- od_disp_str("\n\rPress [Enter] continue...");
- od_get_answer("\n\r");
- od_disp_str("\n\r\n\r");
- }
-
-
-
- void vote(void) /* Function to record user's vote */
- {
- file->voted[usernum][topic]=TRUE; /* Stop user from voting on it again */
- ++file->total_votes[topic]; /* Increase total number of votes */
- ++file->votes[topic][choice]; /* Add user's vote */
- display_results(); /* Show user results of question to date */
- }
-
-
-
- void delete_question(void) /* Function to delete a question */
- {
- if(topic==--file->num_questions) return;
- memcpy(file->quest_title[topic],file->quest_title[topic+1],60*(19-topic));
- memcpy(file->quest_by[topic],file->quest_by[topic+1],36*(19-topic));
- memcpy(file->quest_text[topic],file->quest_text[topic+1],60*(19-topic));
- memcpy(&file->quest_num_ans[topic],&file->quest_num_ans[topic+1],2*(19-topic));
- memcpy(file->quest_answers[topic],file->quest_answers[topic+1],1200*(19-topic));
- memcpy(&file->total_votes[topic],&file->total_votes[topic+1],2*(19-topic));
- memcpy(file->votes[topic],file->votes[topic+1],40*(19-topic));
- for(counter=0;counter<file->num_users;++counter)
- memcpy(&file->voted[counter][topic],&file->voted[counter][topic+1],19-topic);
- }
-
-
-
- void main_menu(void) /* Function to display the main menu */
- {
- od_clear_keybuffer(); /* Remove any waiting keypresses in keyboard buffer */
-
- od_clr_scr(); /* Clear screen */
-
-
- /* Use EZVOTE.ASC/ANS/AVT to display the menu, if one of these files exists */
- if(od_send_file("EZVOTE")) return;
-
- /* Otherwise, display built-in menu */
-
- else if(od_control.user_ansi) /* Display graphics title if ANSI or */
- { /* AVATAR modes are available */
- od_set_attrib(title_lines);
- od_disp_str("\n\r───────────────────────────────────────────────────────────────────────────────\n\r");
- od_set_attrib(title_text);
- od_disp_str(" EZVote ■ OpenDoors 4.10 Example Door");
- od_set_attrib(title_lines);
- od_disp_str("\n\r───────────────────────────────────────────────────────────────────────────────\n\r");
- od_set_attrib(copyright_colour);
- od_set_cursor(5,25);
- od_disp_str("Copyright 1993 by Brian Pirie\n\r\n\r\n\r");
- }
- else /* Display non-graphics title if graphics mode is not available */
- {
- od_disp_str("\n\r-------------------------------------------------------------------------------\n\r");
- od_disp_str(" EZVote - OpenDoors 4.10 Example Door");
- od_disp_str("\n\r-------------------------------------------------------------------------------\n\r");
- od_disp_str(" Copyright 1993 by Brian Pirie\n\r\n\r\n\r");
- }
-
- od_set_attrib(menu_text); od_disp_str("\n\r [");
- od_set_attrib(menu_highlight); od_disp_str("V");
- od_set_attrib(menu_text); od_disp_str("] Vote on a Topic\n\r [");
- od_set_attrib(menu_highlight); od_disp_str("R");
- od_set_attrib(menu_text); od_disp_str("] View results\n\r [");
- od_set_attrib(menu_highlight); od_disp_str("A");
- od_set_attrib(menu_text); od_disp_str("] Add a new question\n\r [");
- od_set_attrib(menu_highlight); od_disp_str("P");
- od_set_attrib(menu_text); od_disp_str("] Page Sysop\n\r [");
- if(sysop)
- {
- od_set_attrib(menu_highlight); od_disp_str("D");
- od_set_attrib(menu_text); od_disp_str("] Delete Booth\n\r [");
- }
- od_set_attrib(menu_highlight); od_disp_str("G");
- od_set_attrib(menu_text); od_disp_str("] Goodbye (Logoff)\n\r [");
- od_set_attrib(menu_highlight); od_disp_str("Q");
- od_set_attrib(menu_text); od_disp_str("] Return to BBS\n\r\n\r\n\r");
- }
-