home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Black Box 4
/
BlackBox.cdr
/
progc
/
odoors34.arj
/
RAVOTE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-07
|
24KB
|
500 lines
/* ╔════════════════════════════════════════════════════╗
* ║ ┌─────┐ ║
* ║ │ │┌────┐┌───┐┌──┐ ║
* ║ │ ││ │├───┘│ │ ║
* ║ └─────┘├────┘└─── │ ├────┐ ║
* ║ │ │ │┌───┐┌───┐┌─── ┌── ║
* ║ │ ││ ││ ││ └──┐ ║
* ║ └────┘└───┘└───┘│ ──┘ ║
* ║ ──────────── ║
* ║ Version 3.40 DEMO DOOR ║
* ╚════════════════════════════════════════════════════╝
* (C) Copyright 1992, Brian Pirie. All Rights Reserved.
*
* ┌──────────┐
* │ RAVOTE.C │
* └──────────┘
* RAVote is a sample door written in OpenDoors. This is arelatively
* simple door that allows BBS users to vote anonymously on various topics,
* entered by other users. Users are able to view the results of any of the
* topics, only if they have already voted, and may only vote on each topic
* once. The door automatically uses ANSI graphics if available, and should
* work with any BBS system that produces a DORINFO1.DEF file. On the command-
* line you can specify a path to this file if it is not in the current
* directory. The Sysop (automatically detected by comparing user name to sysop
* name) also has the option of deleting existing questions.
*
* RAVote, of course, also provides all the features available in
* any OpenDoors door (whithout any extra effort on the part of the
* programmer), such as 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. Ravote also runs very quickly and reliably & uses BIOS screen
* updating for maximum compatibility with DesqView & other such environments.
* RAVote will also function perfectly normally in local mode, except that
* if you wish to use Hangup features, you must check the errorlevel returned
* by the door. Hangup still functions normally in remote mode.
*
* RaVote 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 RAVote error
*
* RaVote 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 period). If you wish to compile RaVote, as with any OpenDoors
* door, all you have to do is make sure OPENDOOR.H is present in the default
* directory, and that Turbo C is configured to compile in the OpenDoors
* library file. For more information, please see the accompanying
* documentation.
*/
#include <conio.h>
#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>
#include"opendoor.h" /* Must be included in all doors */
#define MENU_COLOR 0x0b /* Definitions for ANSI colors, if used */
#define INPUT_COLOR 0x0e
#define TITLE_COLOR 0x0c
#define LIST_COLOR 0x0a
int main(int argc,char *argv[]); /* Function prototype declarations */
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 RAVOTE.BBS file */
void delete_question(void); /* Removes a question from the file */
void main_menu(void); /* Displays the RAVote main menu */
struct /* RAVOTE.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];
int main(int argc,char *argv[])
{
/* Tell OpenDoors your name, */
/* registration key & your door's */
/* name at the beginning of any */
/* program */
strcpy(od_registered_to,"[Unregistered]");
od_registration_key=000000000000;
strcpy(od_program_name,"RAVote 3.40");
/* get path to door files from command */
/* line, if any */
if(argc>1) strncpy(od_control.info_path,argv[1],59);
/* display copyright notice */
/* note that since this is the first */
/* call to any OpenDoors function, the */
/* initialization is also done at this */
/* time (such as reading door files, */
/* opening fossil, seting up od_control, */
/* and so on). If you wish to have */
/* access to or to change any of these */
/* values, make sure that you call */
/* od_init() before you do anything */
/* else in your program */
od_disp_str("[RAVote 3.40 - (C) Copyright 1992, Brian Pirie - All rights Reserved]\n\r");
/* Cause OpenDoors to call the */
/* save_file() function before exiting, */
/* under any circumstances. This way, */
/* the data file will be saved, even */
/* if the user looses connection. */
od_control.od_before_exit=save_file;
/* Open the RAVOTE.BBS data file */
if((handle=open("ravote.bbs",O_RDONLY|O_BINARY))==-1)
{ /* Create the file if it does not exist */
handle=open("ravote.bbs",O_RDWR|O_BINARY|O_CREAT,S_IWRITE|S_IREAD);
file.num_questions=0; /* Blank file to zero questions, and */
file.num_users=0; /* Zero users */
write(handle,&file,sizeof(file));
}
else
read(handle,&file,sizeof(file));/* Read data from file if it exists */
close(handle); /* Close the file again */
/* Search for user in RAVOTE.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 RAVote before */
{ /* Add him 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_COLOR); /* Display prompt with time left to user */
od_printf("Select Command (%d mins)\n\r",od_control.caller_timelimit);
od_set_attrib(MENU_COLOR);
switch(key=od_get_key(TRUE)) /* Get user's choice */
{
case 'v': case 'V': /* If user hit V key (upper or lower */
do /* case) */
{
choose_topic(FALSE); /* Allow user to choose question from */
/* those he hasn't voted on yet */
/* If valid topic # entered */
if(topic>=0 && topic<=19)
{ /* Display the question to the user */
od_set_attrib(TITLE_COLOR);
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_COLOR);
/* 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(MENU_COLOR);
od_disp_str("\n\rSelect answer, [O] for other, or [Enter] to pass: ");
/* Allow user to input choice of up to */
/* two characters */
od_set_attrib(INPUT_COLOR);
od_input_str(string,2,32,127);
od_set_attrib(MENU_COLOR);
choice=atoi(string)-1;
/* If user chose "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 his answer to quest */
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 his vote */
}
}
else /* If there is no room for more answers */
{ /* Let the user know */
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 an existing */
{ /* choice */
if(choice>=0 && choice<=file.quest_num_ans[topic])
{
vote(); /* record their vote */
}
}
}
} while(topic!=-1); /* Loop until user is finished voting */
break;
case 'r': 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 abort result display */
display_results(); /* Display results of question */
}
break;
case 'a': case 'A': /* If adding a new question */
od_clr_scr(); /* Clear the screen (if mode turned on) */
if(file.num_questions<20) /* If there is room for another quest. */
{ /* Store user's name as author of quest. */
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_COLOR);
od_input_str(string,59,32,127);
od_set_attrib(MENU_COLOR);
strcpy(file.quest_title[file.num_questions],string);
if(strlen(string)!=0) /* If user didn't abort */
{ /* Get the question itself from user */
od_disp_str("\n\rWhat is your question?\n\r > ");
od_set_attrib(INPUT_COLOR);
od_input_str(string,59,32,127);
od_set_attrib(MENU_COLOR);
strcpy(file.quest_text[file.num_questions],string);
/* If user didn't abort */
if(strlen(string)!=0)
{ /* Get the user's 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_COLOR);
od_disp_str("Do you wish to save this question? (Y/N) ");
/* get yes or no from user */
do choice=od_get_key(TRUE); while(choice!='Y' && choice!='N' && choice!='y' && choice!='n');
if(choice=='y' || choice=='Y')
file.num_questions++;
}
}
}
else /* If no room for a new question, */
{ /* let the user know */
od_disp_str("Sorry, RAVote has a limit of 20 questions.\n\r");
od_disp_str("Press any key to continue...\n\r\n\r");
od_get_key(TRUE);
}
break;
case 'p': case 'P': /* If user wants to page the sysop */
od_page(); /* OpenDoors takes care of the rest */
break;
case 'd': case 'D': /* If user chose 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_COLOR);
od_input_str(string,2,'0','9');
topic=atoi(string)-1;
od_set_attrib(MENU_COLOR);
/* 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_COLOR);
od_disp_str("Are You Sure? (Y/N)\n\r");
od_set_attrib(MENU_COLOR);
do choice=od_get_key(TRUE); while(choice!='Y' && choice!='N' && choice!='y' && choice!='n');
if(choice=='y' || choice=='Y')
{ /* If sysop agrees, it's gone! */
delete_question();
}
}
}
} /* Loop until quit to BBS or logoff */
} while(key!='Q' && key!='q' && key!='G' && key!='g');
if(key=='G' || key=='g') /* If user wishsed to log off */
{ /* Say goodbye */
od_printf("\n\rGoodbye from %s...\n\r",od_control.system_name);
od_exit(11,TRUE); /* Let OpenDoors take care of the rest */
}
else
{ /* Acknoledge 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 RAVOTE.BBS file */
{ /* (called before door termination) */
handle=open("ravote.bbs",O_WRONLY|O_BINARY);
write(handle,&file,sizeof(file));
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_COLOR); /* Get user's answer */
od_printf(" %2d> ",file.quest_num_ans[topic]+1);
od_set_attrib(INPUT_COLOR);
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 quest */
{
register char displayed=FALSE;
for(;;)
{
od_set_attrib(TITLE_COLOR);
od_clr_scr(); /* Clear the screen */
od_disp_str("Choose A Topic:\n\r");
od_set_attrib(LIST_COLOR);
/* display questions */
for(counter=0;counter<file.num_questions;++counter)
{ /* if question should be displayed */
if(file.voted[usernum][counter]==mode)
{
displayed=TRUE; /* spit 'er out! */
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(MENU_COLOR);
od_disp_str("Select topic, or [Enter] to return to main menu: ");
od_set_attrib(INPUT_COLOR);
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 quest */
{
od_set_attrib(TITLE_COLOR); /* display the header */
od_clr_scr();
od_printf("%s\n\r(Created by: %s)\n\r",file.quest_title[topic],file.quest_by[topic]);
od_set_attrib(LIST_COLOR);
/* loop through each answer */
for(counter=0;counter<file.quest_num_ans[topic];++counter)
/* display answer with # & % of votes */
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(MENU_COLOR);
/* Wait for user to hit a key */
od_disp_str("\n\rPress any key to continue...");
od_get_key(TRUE);
od_disp_str("\n\r\n\r");
}
void vote(void) /* function to record user's vote */
{
file.voted[usernum][topic]=TRUE; /* stop him 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 */
{ /* decrement total # of questions */
if(topic==--file.num_questions) return;
/* shuffle all other questions up one */
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)
{
od_clear_keybuffer(); /* Clear any pending keys in buffer */
od_clr_scr(); /* Clear screen */
if(od_send_file("RAVOTE"))
{
return;
}
else if(od_control.caller_ansi) /* Display ANSI title if ANSI mode is on */
{
od_set_attrib(TITLE_COLOR);
od_disp_str("\n\r┌───────────────────────────────────┐\n\r│ ");
od_set_attrib(LIST_COLOR);
od_disp_str("RAVote ■ OpenDoors 3.40 Demo Door ");
od_set_attrib(TITLE_COLOR);
od_disp_str("│\n\r└───────────────────────────────────┘\n\r");
od_disp_str(" Copyright 1992, Brian Pirie\n\r");
}
else /* Display ASCII title if ANSI is off */
{
od_disp_str("\n\r+-----------------------------------+\n\r");
od_disp_str("| RAVote - OpenDoors 3.40 Demo Door |\n\r");
od_disp_str("+-----------------------------------+\n\r");
od_disp_str(" Copyright 1992, Brian Pirie\n\r");
}
od_set_attrib(MENU_COLOR);
/* Display main menu (note that the */
/* delete booth option is only displayed */
/* to the sysop) */
od_disp_str("\n\r [V] Vote on a Topic\n\r");
od_disp_str(" [R] View results\n\r");
od_disp_str(" [A] Add a new question\n\r");
od_disp_str(" [P] Page Sysop\n\r");
if(sysop) od_disp_str(" [D] Delete Booth\n\r");
od_disp_str(" [G] Goodbye (Logoff)\n\r");
od_disp_str(" [Q] Return to BBS\n\r\n\r");
}