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;

}