/*
 * University of Utah
 * 2003 High School Programming Contest
 * Question Answering
 *
 * Filename: QASys.cpp
 * 
 * Description:
 * This program implements a basic question answering systems.  This system
 * using a very simple approach of key word matching.  This program expects
 * a single command line parameter: the name of a file containing a story.
 *
 * The format of the story file should be as follows.  Each line contains
 * a single sentence of the story.  The questions follow the story in the
 * file, one question per line.  Each question begins with its number 
 * (beginning at 1) and a period. Example: "1. Is this a question?".
 *
 * Upon performing question answering, the program outputs to 
 * standard out one sentence per line which answers each question.  The
 * sentence that answers each question must exactly match the input sentence.
 *
 * Modification History:
 * 2/18/2003 - Initial Release
 */

#include <iostream>
#include <fstream>
#include <vector>
#include "sentence.h"

using namespace std;

// A vector of sentence objects makes up the story and the set of questions.
typedef vector<sentence> sentences;

// Function prototypes.
void readFile(sentences &story, sentences &questions, char* filename);
void runQA(sentences story, sentences questions);
sentence keyWords(sentences story, sentence question);

// Main 
// The filename of the input story is expected as a single 
// command line parameter.  If it is not provided, a message
// is output to the screen and the program execution is terminated.
// Otherwise, the question answering analysis is performed and 
// the answer setences for each question is output to standard out.
int main(int argc, char* argv[]) {
  if (argc != 2) {
    cout << "Expecting command line parameter." << endl;
    cout << "Proper syntax:" << endl;
    cout << "  " << argv[0] << "<story filename>" << endl;
    return 1;
  }
  sentences story;
  sentences questions;
  readFile(story, questions, argv[1]);
  runQA(story, questions);
  return 0;
}

// Reads the specified file into the "story" and "questions".
// "story" and "questions" are passed by reference because the additions
// that this function makes should be retained for use later in the 
// program.
// 
// Parameters:
// story - vector of sentence objects containing each sentence in the story
// questions - vector of sentence objects containg each question in the story
// filename - name of a file containg the story and questions formatted as 
//   decribed above
void readFile(sentences &story, sentences &questions, char* filename) {
  ifstream input;
  input.open(filename, ios::in);
  string line;
  // Load each sentence in the story
  while (true) {
    getline(input, line);
    // Reached questions when a line begins with "1." so break loop.
    if (line.substr(0, 2) == "1.")
      break;
    if (line.length() != 0)
      story.push_back(line);
  } 
  
  // Load each question
  while (!input.eof()) {
    questions.push_back(line.substr(2));
    getline(input, line);
  }   
  input.close();
} 

// Applies the question answering method for each question and 
// outputs the sentence which is determined to best answer the
// question.
// 
// Parameters:
// story - vector of sentence objects containing the story.  This
//   function should not modify this data.
// questions - vector of sentence objects containing each question. 
//   This function should not modify this data.
void runQA(sentences story, sentences questions) {
  // Possible design would be to create an additional function 
  // for each new method and call it from within this loop.
  for	(int i = 0; i < questions.size(); i++) {
    sentence answer = keyWords(story, questions[i]);
    cout << answer.originalSentence() << endl;
  }
}

// A very simple question answering method.  Works by finding the 
// sentence in the story which has the most words in common with
// the question.  That sentence is determined to best answer
// the question.
//
// Parameters:
// story - vector of sentence objects containing the story. This 
//   function should not modify this data.
// questions - vector of sentence objects containing each question.
//   This function should not modify this data.
// 
// Returns the sentence which best answers the question.
sentence keyWords(sentences story, sentence question) {
  int bestMatch = -1;
  int bestIndex = 0;
  // go through each sentence in the story
  for (int i = 0; i < story.size(); i++) {
    int matchCount = 0;
    // go through each word in the current story sentence
    for (int j = 0; j < story[i].size(); j++) {
      // go through each word in the question's sentence
      for (int k = 0; k < question.size(); k++) {
	if (story[i][j] == question[k]) {
	  matchCount++;
	}
      }
    }
    // Is this sentence better than the previous best sentence?
    if (matchCount > bestMatch) {
      bestMatch = matchCount;
      bestIndex = i;
    }
  }
  return story[bestIndex];
}


