TestCase * Grader07::testSpellCheck(std::string filename)
{
  Commands07 cmds07;
  std::vector<std::string> words;
  std::vector<SpellCheckCmd> commands;

  cmds07.readReads("words", words);
  cmds07.loadSpellCheckCommands(filename, commands);

  if(words.size() == 0){
    return failed("cannot read input file #1");
  }

  if(commands.size() == 0){
    return failed("cannot read input file #2");
  }

  Stopwatch watch;
  watch.start();

  ISpellCheck * checker = (ISpellCheck *) createObject("ISpellCheck");
  if(checker == NULL){
    return nullObject("ISpellCheck");
  }

  watch.pause();
  checker->loadDictionary(words);
  watch.unpause();

  for(size_t i = 0; i < commands.size(); ++i){
    SpellCheckCmd cmd = commands[i];
    std::vector<std::string> product_corrections = checker->suggestCorrections(cmd.word);
    watch.pause();
    std::sort(product_corrections.begin(), product_corrections.end());
    if(product_corrections != cmd.corrections){
      return failed("corrections mismatch");
    }
    watch.unpause();
  }

  watch.stop();
  return passed(watch.getTime());
}
TestCase * Grader07::testStringSearch(std::string cmds_filename, std::string input_filename)
{
  std::vector<StringSearchCmd> commands;

  Commands07 cmds07;
  cmds07.loadStringSearchCommmands(cmds_filename, commands);
  std::string to_search = cmds07.readStringFile(input_filename);

  if(commands.size() == 0){
    return failed("cannot read input file #1");
  }

  if(to_search == ""){
    return failed("cannot read input file #2");
  }

  Stopwatch watch;
  watch.start();

  IStringSearch * searcher = (IStringSearch *) createObject("IStringSearch");
  if(searcher == NULL){
    return nullObject("IStringSearch");
  }

  watch.pause();
  searcher->prepareText(to_search);
  watch.unpause();

  for(size_t i = 0; i < commands.size(); ++i){
    StringSearchCmd cmd = commands[i];
    std::vector<int> product_results = searcher->search(cmd.to_find);
    if(product_results.size() != cmd.positions.size()){
      return failed("incorrect return size");
    }
    std::sort(product_results.begin(), product_results.end());
    if(product_results != cmd.positions){
      return failed("at least one incorrect return index");
    }
  }

  watch.stop();
  return passed(watch.getTime());
}
TestCase * Grader02::testWorkload4(int len, int order, int merge_count,
	int merge_len){

	std::vector<int> input;
	std::vector<int> sorted;
	createVector(input, sorted, order, len, false);

	Stopwatch watch;
	watch.start();

	IPriorityQueue * queue = (IPriorityQueue *)createObject("IPriorityQueue4");
	if (queue == NULL){
		return nullObject("IPriorityQueue4");
	}

	watch.pause();
	GoldPriorityQueue gold_queue(sorted);

	for (size_t i = 0; i < merge_len; ++i){
		int key = input[i];
		std::string value = randomValue();
		gold_queue.push_back(key, value);

		watch.unpause();
		IKeyValue * key_value = (IKeyValue *)createObject("IKeyValue4");
		if (key_value == NULL){
			return nullObject("IKeyValue4");
		}

		key_value->setKey(key);
		key_value->setValue(value);

		queue->enqueue(key_value);

		int size = queue->size();
		if (size != gold_queue.size()){
			return failed("after enqueue, size is incorrect");
		}

		int user_key = queue->lowestKey();
		IVectorString * user_values = queue->lowestValues();
		gold_queue.iterate();
		int gold_key = gold_queue.lowestKey();
		std::vector<std::string> values = gold_queue.getValues(gold_key);
		watch.pause();

		if (gold_key != user_key){
			return failed("after enqueue, lowest key is incorrect");
		}

		if (valuesEqual(user_values, values) == false){
			return failed("after enqueue, values incorrect");
		}
	}

	for (int i = 1; i < merge_count; ++i){
		watch.unpause();
		IPriorityQueue * queue2 = (IPriorityQueue *)createObject("IPriorityQueue4");
		if (queue == NULL){
			return nullObject("IPriorityQueue4");
		}

		watch.pause();

		for (int j = (i * merge_len); j < ((i + 1) * merge_len); ++j){
			int key = input[j];
			std::string value = randomValue();
			gold_queue.push_back(key, value);

			watch.unpause();
			IKeyValue * key_value = (IKeyValue *)createObject("IKeyValue4");
			if (key_value == NULL){
				return nullObject("IKeyValue4");
			}

			key_value->setKey(key);
			key_value->setValue(value);

			queue2->enqueue(key_value);
			watch.pause();
		}

		watch.unpause();
		queue->merge(queue2);
		watch.pause();

		gold_queue.iterate();

		watch.unpause();
		int user_key = queue->lowestKey();
		IVectorString * user_values = queue->lowestValues();
		watch.pause();

		int gold_key = gold_queue.lowestKey();
		std::vector<std::string> values = gold_queue.getValues(gold_key);

		if (gold_key != user_key){
			return failed("during dequeue, lowest key is incorrect");
		}

		if (valuesEqual(user_values, values) == false){
			return failed("during dequeue, values incorrect");
		}
	}

	return passed(watch.getTime());
}
TestCase * Grader02::testWorkload1(int len, int order){

	std::vector<int> input;
	std::vector<int> sorted;
	createVector(input, sorted, order, len, true);

	Stopwatch watch;
	watch.start();

	IPriorityQueue * queue = (IPriorityQueue *)createObject("IPriorityQueue1");
	if (queue == NULL){
		return nullObject("IPriorityQueue1");
	}

	watch.pause();
	GoldPriorityQueue gold_queue(sorted);
	for (size_t i = 0; i < input.size(); ++i){
		int key = input[i];
		std::string value = randomValue();
		gold_queue.push_back(key, value);

		watch.unpause();
		IKeyValue * key_value = (IKeyValue *)createObject("IKeyValue1");
		if (key_value == NULL){
			return nullObject("IKeyValue1");
		}

		key_value->setKey(key);
		key_value->setValue(value);

		queue->enqueue(key_value);

		int size = queue->size();
		if (size != gold_queue.size()){
			return failed("after enqueue, size is incorrect");
		}

		int user_key = queue->lowestKey();
		IVectorString * user_values = queue->lowestValues();
		gold_queue.iterate();
		int gold_key = gold_queue.lowestKey();
		std::vector<std::string> values = gold_queue.getValues(gold_key);
		watch.pause();

		if (gold_key != user_key){
			return failed("after enqueue, lowest key is incorrect");
		}

		if (valuesEqual(user_values, values) == false){
			return failed("after enqueue, values incorrect");
		}

		bool check_sort = true;
		if (len != 10 && i % 100 != 0){
			check_sort = false;
		}

		if (check_sort){
			watch.unpause();
			IVectorKeyValue * user_sorted = queue->returnSorted();
			watch.pause();
			if (sortedEqual(user_sorted, gold_queue.returnSorted()) == false){
				return failed("after enqueue, sorted is not equal");
			}
		}
	}

	gold_queue.iterate();
	int count = 0;
	while (gold_queue.hasNext()){
		watch.unpause();
		int user_key = queue->lowestKey();
		IVectorString * user_values = queue->lowestValues();
		watch.pause();

		int gold_key = gold_queue.lowestKey();
		std::vector<std::string> values = gold_queue.getValues(gold_key);

		if (gold_key != user_key){
			return failed("during dequeue, lowest key is incorrect");
		}

		if (valuesEqual(user_values, values) == false){
			return failed("during dequeue, values incorrect");
		}

		watch.unpause();
		int size = queue->size();
		watch.pause();
		if (size != gold_queue.size()){
			return failed("during dequeue, size is incorrect");
		}

		bool check_sort = true;
		if (len != 10 && count % 100 != 0){
			check_sort = false;
		}

		if (check_sort){
			IVectorKeyValue * user_sorted = queue->returnSorted();
			std::vector<std::pair<int, std::string> > gold_sorted = gold_queue.returnSorted();
			if (sortedEqual(user_sorted, gold_sorted) == false){
				return failed("during dequeue, sorted is not equal");
			}
		}

		watch.unpause();
		queue->dequeue();
		watch.pause();
		gold_queue.dequeue();
		++count;
	}

	return passed(watch.getTime());
}