hw8_fncts.cpp
/*
Programmer: Jennifer Leopold
Date: October 31, 2016
File: hw8_functs.cpp
Purpose: This file contains the definitions of the functions
for the program that generates answers for candidates
during a debate.
*/
#include "hw8_functs.h"
using namespace std;
void constructAnswer(char answer[ANSWER_LENGTH],
const int candidateNum)
{
char sentenceFromFile[PARTIAL_ANSWER_LENGTH];
char prefix[PARTIAL_ANSWER_LENGTH];
char interjection[PARTIAL_ANSWER_LENGTH];
char extractedPortion[PARTIAL_ANSWER_LENGTH];
int numSentences;
int sentenceLength;
// Initialize answer to empty string
strcpy(answer, "");
// Sometimes append a "prefix" remark to candidate's answer
if ((rand() % 100) <= CHANCE_OF_APPENDING_PREFIX)
{
// Randomly select a prefix remark
getPrefixFromFile(prefix);
if (DEBUG)
cout << "prefix = " << prefix << endl;
strcpy(answer, prefix);
strcat(answer, " ");
}
// Randomly determine # sentences that candidate's
// answer will contain (MIN_NUM_SENTENCES..MAX_NUM_SENTENCES)
numSentences = myRand(MIN_NUM_SENTENCES, MAX_NUM_SENTENCES);
if (DEBUG)
cout << "numSentences = " << numSentences << endl;
for (int i = 1; i <= numSentences; i++)
{
// Randomly select this sentence from candidateNum's
// "sentence" file
getSentenceFromFile(sentenceFromFile, candidateNum);
if (DEBUG)
cout << "Sentence from file is: ["
<< sentenceFromFile << "]\n";
// Break the sentence up into numSentences many equal
// portions, and extract the ith portion
extractPortionFromSentence(sentenceFromFile,
numSentences, i,
extractedPortion);
if (DEBUG)
cout << "extracted portion is: ["
<< extractedPortion << "]\n";
// Capitalize the 1st letter
extractedPortion[0] = toupper(extractedPortion[0]);
// Append the extracted portion to the answer constructed
// thus far
strcat(answer, extractedPortion);
// Sometimes insert a remark into candidate's answer
if ((rand() % 100) <= CHANCE_OF_INSERTING_INTERJECTION)
{
// Randomly select a remark from candidateNum's
// "interjection" file
getInterjectionFromFile(interjection, candidateNum);
if (DEBUG)
cout << "interjection is: [" << interjection << "]\n";;
strcat(answer, interjection);
strcat(answer, " ");
}
else strcat(answer, " ");
// Randomly select a punctuation symbol to end this
// sentence
sentenceLength = strlen(answer);
if (isspace(answer[sentenceLength-1]))
sentenceLength--;
answer[sentenceLength-1] = chooseEndingPunctuationChar();
answer[sentenceLength] = '\0';
strcat(answer, " ");
}
return;
}
char chooseEndingPunctuationChar()
{
char ch;
if ((rand() % 100) >= CHANCE_FOR_PERIOD)
ch = '.';
else
{
if ((rand() % 100) >= CHANCE_FOR_NONPERIOD)
ch = '?';
else ch = '!';
}
return(ch);
}
void extractPortionFromSentence
(char sentence[PARTIAL_ANSWER_LENGTH],
const int numPortions, const int desiredPortion,
char extractedPortion[PARTIAL_ANSWER_LENGTH])
{
int numWhitespaceChars = 0;
int whitespaceCharsPerPortion;
int i, j;
if (DEBUG)
cout << "desiredPortion = " << desiredPortion << endl;
// Count whitespace chars in sentence
i = 0;
while (static_cast<unsigned int>(i) < strlen(sentence))
{
if (isspace(sentence[i])) numWhitespaceChars++;
i++;
}
if (DEBUG)
cout << "numWhitespaceChars = "
<< numWhitespaceChars << endl;
// Determine # whitespace chars per portion of sentence
// (based on numPortions)
whitespaceCharsPerPortion =
static_cast<int>
(static_cast<float>(numWhitespaceChars)/numPortions
+ 0.6); // round up
if (DEBUG)
cout << "whitespaceCharsPerPortion = "
<< whitespaceCharsPerPortion << endl;
// Count until you've seen (desiredPortion-1) *
// whitespaceCharsPerPortion many whitespace chars
// in sentence
i = 0;
numWhitespaceChars = 0;
while (numWhitespaceChars <
((desiredPortion-1) * whitespaceCharsPerPortion))
{
if (isspace(sentence[i])) numWhitespaceChars++;
i++;
}
// If count ended on a space, go one more
if (isspace(sentence[i])) i++;
// Portion of the sentence we want is from position i until
// whitespaceCharsPerPortion many whitespace chars processed
j = 0;
numWhitespaceChars = 0;
while ((numWhitespaceChars <= whitespaceCharsPerPortion) &&
(static_cast<unsigned int>(i) < strlen(sentence)))
{
extractedPortion[j] = sentence[i];
if (isspace(sentence[i])) numWhitespaceChars++;
i++;
j++;
}
extractedPortion[j] = '\0';
return;
}
void getPrefixFromFile(char prefix[PARTIAL_ANSWER_LENGTH])
{
ifstream fin;
int numEntriesInFile = 0, entryNum;
char filename[MAX_LENGTH_FILENAME];
fin.clear(); // reset connection
strcpy(filename, PREFIX_FILENAME.c_str());
fin.open(filename);
if (!fin)
cout << "Cannot open " << PREFIX_FILENAME << "!\n";
else
{
// Read until end-of-file to determine # entries in file
while (fin.getline(prefix, PARTIAL_ANSWER_LENGTH-1))
numEntriesInFile++;
fin.close();
// Re-open the file
fin.clear();
fin.open(filename);
// Choose random number corresponding to a line
// in the file
entryNum = (rand() % numEntriesInFile) + 1;
// Read lines 1..entryNum in the file
// (last entry read will be the one we return)
for (short i = 1; i <= entryNum; i++)
fin.getline(prefix, PARTIAL_ANSWER_LENGTH-1);
fin.close();
}
return;
}
void getSentenceFromFile(char sentence[PARTIAL_ANSWER_LENGTH],
const int candidateNum)
{
ifstream fin;
int numEntriesInFile, entryNum;
char filename[MAX_LENGTH_FILENAME];
fin.clear(); // reset connection
strcpy(filename, SENTENCE_FILENAMES[candidateNum].c_str());
fin.open(filename);
if (!fin)
cout << "Cannot open "
<< SENTENCE_FILENAMES[candidateNum] << "!\n";
else
{
fin >> numEntriesInFile;
fin.ignore(500, '\n');
// Choose random number corresponding to a line
// in the file
entryNum = (rand() % numEntriesInFile) + 1;
// Read lines 1..entryNum in the file
// (last entry read will be the one we return)
for (short i = 1; i <= entryNum; i++)
fin.getline(sentence, PARTIAL_ANSWER_LENGTH-1);
fin.close();
}
return;
}
void getInterjectionFromFile
(char interjection[PARTIAL_ANSWER_LENGTH],
const int candidateNum)
{
ifstream fin;
int numEntriesInFile, entryNum;
char filename[MAX_LENGTH_FILENAME];
fin.clear(); // reset connection
strcpy(filename,
INTERJECTION_FILENAMES[candidateNum].c_str());
fin.open(filename);
if (!fin)
cout << "Cannot open "
<< INTERJECTION_FILENAMES[candidateNum] << "!\n";
else
{
fin >> numEntriesInFile;
fin.ignore(500, '\n');
// Choose random number corresponding to a line
// in the file
entryNum = (rand() % numEntriesInFile) + 1;
// Read lines 1..entryNum in the file
// (last entry read will be the one we return)
for (short i = 1; i <= entryNum; i++)
fin.getline(interjection, PARTIAL_ANSWER_LENGTH-1);
fin.close();
}
return;
}
int myRand(const int low, const int high)
{
return((rand() % (high - low + 1)) + low);
}
int scoreAlphaChar(const char ch)
{
int val;
switch (tolower(ch))
{
case 'e' :
case 'a' :
case 'i' :
case 'o' :
case 'n' :
case 'r' :
case 't' :
case 'l' :
case 's' :
case 'u' : val = 1;
break;
case 'd' :
case 'g' : val = 2;
break;
case 'b' :
case 'c' :
case 'm' :
case 'p' : val = 3;
break;
case 'f' :
case 'h' :
case 'v' :
case 'w' :
case 'y' : val = 4;
break;
case 'k' : val = 5;
break;
case 'j' :
case 'x' : val = 8;
break;
case 'q' :
case 'z' : val = 10;
break;
default : val = 0;
}
return(val);
}
int scoreAnswer(const char answer[ANSWER_LENGTH])
{
int charScore, wordScore = 0, totalScore = 0;
int chance;
char ch;
// Go through each char in the answer to determine
// total score
for (int i = 0;
static_cast<unsigned int>(i) < strlen(answer); i++)
{
ch = answer[i];
// Each alphabetic char is assigned particular value
if (isalpha(ch))
{
charScore = scoreAlphaChar(ch);
// Sometimes char gets its value multiplied
chance = rand() % 100;
if (chance < TRIPLE_LETTER_CHANCE)
charScore *= TRIPLE_LETTER_MULTIPLIER;
else if (chance < DOUBLE_LETTER_CHANCE)
charScore *= DOUBLE_LETTER_MULTIPLIER;
// Add char value to word score total
wordScore += charScore;
}
// Whitespace or punctuation delimits a word
if (isspace(ch) || ispunct(ch))
{
// Sometimes word gets its value multiplied
chance = rand() % 100;
if (chance < TRIPLE_WORD_CHANCE)
wordScore *= TRIPLE_WORD_MULTIPLIER;
else if (chance < DOUBLE_WORD_CHANCE)
wordScore *= DOUBLE_WORD_MULTIPLIER;
// Add word score to answer score total
totalScore += wordScore;
wordScore = 0;
}
}
return(totalScore);
}
void outputResults(const int score[NUM_CANDIDATES])
{
int minScore = score[0];
int winner = 0;
cout << "\nOh, enough already -- this is ridiculous!!!\n\n";
// Output each candidate's score, winner is the one with
// lowest score
for (int i = 0; i < NUM_CANDIDATES; i++)
{
cout << "Candidate " << i + 1
<< "'s score is " << score[i] << endl;
if (score[i] < minScore)
{
minScore = score[i];
winner = i;
}
}
cout << "\nThe winner of the debate is candidate "
<< winner + 1 << endl;
cout << "\nThis concludes our 2016 presidential debate.\n";
return;
}