Example #1
0
  /**
   * Generates a QuestionSetWrapper containing valid question, answer pairs Skip elements introduces
   * randomness to the result query but at the cost of perhaps not having enough elements in the
   * result query if the ResultSet was small to begin with
   *
   * @param difficulty
   * @return
   * @throws SQLException
   */
  @SuppressWarnings("unchecked")
  private static Question generateQuestion(int difficulty, int choiceSize, boolean skipElements)
      throws SQLException {

    // Question parameters
    int answer = 0, indexSelected = 0;
    String question = null;
    List<String> choices = new ArrayList<>(choiceLimit);
    ArrayList<SQLGenreSet> genres = null;
    ArrayList<String> movies = null;
    ArrayList<Integer> years = null;
    ArrayList<Integer> aids = null;
    ArrayList<Integer> mids = null;
    boolean dbConnect = false;
    switch ((int) (Math.random() * questionTypeN)) {
      case 0:
        // what year is this movie released?
        if (!questionCache.containsKey(getCacheKey(0, difficulty))
            || Math.random() <= refreshThreshold) {
          dbConnect = true;
          loadIndex(0, difficulty, choiceSize, skipElements);
        }

        movies =
            (ArrayList<String>) questionCache.get(getCacheKey(0, difficulty)).getPropertyList();
        years = (ArrayList<Integer>) questionCache.get(getCacheKey(0, difficulty)).getAnswerList();
        //
        if (movies.size() < resultThreshold) {
          System.out.println(
              "Insufficient amount of elements for question type: (" + movies.size() + ", 0)");
          System.out.println("Re-generating question without skipping");
          return generateQuestion(difficulty, choiceSize, false);
        } else {
          System.out.println("Valid result set, proceeding with computations");
          if (!questionCache.containsKey(getCacheKey(0, difficulty)) || dbConnect) {
            questionCache.put(
                getCacheKey(0, difficulty), new QuestionSetWrapper<String, Integer>(movies, years));
          }
        }
        indexSelected = (int) (Math.random() * movies.size());
        question = "What year was " + movies.get(indexSelected) + " first released?";
        int yearSelected = years.get(indexSelected);
        String yearStr = Integer.toString(yearSelected);
        // populate choices with (choiceLimit - 1) elements
        for (int i = 0; i < choiceLimit - 1; ++i) {

          if (Math.random() > 0.70) {
            int randomCloseYear = yearSelected;
            if (yearSelected < 2000 && Math.random() > 0.50) {
              randomCloseYear += 1 + ((int) (10 * Math.random()));
            } else {
              randomCloseYear -= 1 + ((int) (10 * Math.random()));
            }
            String randomCloseYearString = Integer.toString(randomCloseYear);
            if (!choices.contains(randomCloseYearString)) {
              choices.add(randomCloseYearString);
            } else {
              --i;
            }
          } else {
            // random number from 1900 to 2015
            int randomYear = 1900 + ((int) (Math.random() * 116));
            String randomYearString = Integer.toString(randomYear);
            if (randomYear != yearSelected && !choices.contains(randomYearString)) {
              choices.add(randomYearString);
            } else {
              // just redo calculation
              --i;
            }
          }
        }
        answer = (int) (Math.random() * (choices.size() + 1));
        choices.add(answer, yearStr);
        return new Question(question, choices, answer);
      case 1:
        // what set of genres best matches this movie?
        if (!questionCache.containsKey(getCacheKey(1, difficulty))
            || Math.random() <= refreshThreshold) {
          dbConnect = true;
          loadIndex(1, difficulty, choiceSize, skipElements);
        }
        movies =
            (ArrayList<String>) questionCache.get(getCacheKey(1, difficulty)).getPropertyList();
        genres =
            (ArrayList<SQLGenreSet>) questionCache.get(getCacheKey(1, difficulty)).getAnswerList();

        if (movies.size() < resultThreshold) {
          System.out.println(
              "Insufficient amount of elements for question type: (" + movies.size() + ", 1)");
          System.out.println("Re-generating question without skipping");
          return generateQuestion(difficulty, choiceSize, false);
        } else {
          System.out.println("Valid result set, proceeding with computations");
        }
        indexSelected = (int) (Math.random() * movies.size());
        String movieSelected = movies.get(indexSelected);
        question = "What set of genres best matches the movie " + movieSelected + "?";
        SQLGenreSet genreSetSelected = genres.get(indexSelected);
        HashSet<SQLGenreSet> genresChosen = new HashSet<>();
        for (int i = 0; i < choiceLimit - 1; ++i) {
          int index = (int) (Math.random() * movies.size());
          SQLGenreSet genreSet = genres.get(index);
          if (index != indexSelected
              && !genresChosen.contains(genreSet)
              && !genreSet.equals(genreSetSelected)) {
            choices.add(genreSet.toString());
            genresChosen.add(genreSet);
          } else if (Math.random() > 0.10) {
            --i;
          }
        }
        answer = (int) (Math.random() * (choices.size() + 1));
        choices.add(answer, genreSetSelected.toString());
        return new Question(question, choices, answer);
      case 2:
        // which of these movies is the oldest?
        movies = null;
        years = null;
        if (!questionCache.containsKey(getCacheKey(0, difficulty))
            || Math.random() <= refreshThreshold) {
          dbConnect = true;
          loadIndex(0, difficulty, choiceSize, skipElements);
        }

        movies =
            (ArrayList<String>) questionCache.get(getCacheKey(0, difficulty)).getPropertyList();
        years = (ArrayList<Integer>) questionCache.get(getCacheKey(0, difficulty)).getAnswerList();

        if (movies.size() < resultThreshold) {
          System.out.println(
              "Insufficient amount of elements for question type: (" + movies.size() + ", 3)");
          System.out.println("Re-generating question without skipping");
          return generateQuestion(difficulty, choiceSize, false);
        } else {
          System.out.println("Valid result set, proceeding with computations");
        }
        // randomly generate 5 movies that were made in different years
        TreeMap<Integer, String> movieYearPair = new TreeMap<>();
        for (int i = 0; i < choiceLimit; ++i) {
          indexSelected = (int) (Math.random() * movies.size());
          if (movieYearPair.containsKey(years.get(indexSelected))) {
            --i;
            continue;
          }
          movieYearPair.put(years.get(indexSelected), movies.get(indexSelected));
        }
        movies = new ArrayList<String>(movieYearPair.values());
        years = new ArrayList<Integer>(movieYearPair.keySet());
        years.remove(0);
        String lowestYearString = movies.remove(0);
        int iter_size = movies.size();
        for (int i = 0; i < iter_size; ++i) {
          int random_index = (int) (movies.size() * Math.random());
          choices.add(movies.remove(random_index));
          years.remove(random_index);
        }
        answer = (int) (Math.random() * (choices.size() + 1));
        choices.add(answer, lowestYearString);
        question = "Which of these movies (";
        for (int i = 0; i < choices.size(); ++i) {
          question = question + choices.get(i) + ((i == choices.size() - 1) ? "" : ", ");
        }
        question = question + ") was made the earliest?";
        return new Question(question, choices, answer);
      case 3:
        /*
        // which movie has actor X acted in
        if (!cacheContainsKey(3, difficulty) || Math.random() <= refreshThreshold) {
        	loadIndex(3, difficulty, choiceSize, skipElements);
        }
        // Instead of movies and genres, they are actors and movies but
        // that's good enough
        movies = (ArrayList<String>) questionCache.get(getCacheKey(3, difficulty)).getPropertyList();
        genres = (ArrayList<SQLGenreSet>) questionCache.get(getCacheKey(3, difficulty)).getAnswerList();

        if (movies.size() < resultThreshold) {
        	System.out.println("Insufficient amount of elements for question type: (" + movies.size() + ", 1)");
        	System.out.println("Re-generating question without skipping");
        	return generateQuestion(difficulty, choiceSize, false);
        } else {
        	System.out.println("Valid result set, proceeding with computations");
        }
        indexSelected = (int) (Math.random() * movies.size());
        movieSelected = movies.get(indexSelected);
        question = "What movie has " + movieSelected + " acted in?";
        genreSetSelected = genres.get(indexSelected);
        HashSet<String> chosen3 = new HashSet<>();
        String answer3 = genreSetSelected.getList().remove(0);
        genreSetSelected.addGenre(answer3);
        chosen3.add(answer3);

        for (int i = 0; i < choiceLimit - 1; ++i) {
        	int index = (int) (Math.random() * movies.size());
        	SQLGenreSet genreSet = genres.get(index);
        	if (index != indexSelected) {
        		if (genreSet.getList().size() == 0) {
        			--i;
        			continue;
        		}
        		String movanswer = genreSet.getList().remove(0);
        		if (!genreSetSelected.contains(movanswer) && !chosen3.contains(movanswer)) {
        			choices.add(movanswer);
        			chosen3.add(movanswer);
        		} else {
        			--i;
        		}
        	} else if (Math.random() > 0.10) {
        		--i;
        	}
        }
        answer = (int) (Math.random() * (choices.size() + 1));
        choices.add(answer, answer3);
        return new Question(question, choices, answer);*/

      case 4:

        /*// which movie has actor X not acted in
        	if (!cacheContainsKey(3, difficulty) || Math.random() <= refreshThreshold) {
        		loadIndex(3, difficulty, choiceSize, skipElements);
        	}
        	// Instead of movies and genres, they are actors and movies but
        	// that's good enough
        	movies = (ArrayList<String>) questionCache.get(getCacheKey(3, difficulty)).getPropertyList();
        	genres = (ArrayList<SQLGenreSet>) questionCache.get(getCacheKey(3, difficulty)).getAnswerList();

        	if (movies.size() < resultThreshold) {
        		System.out.println("Insufficient amount of elements for question type: (" + movies.size() + ", 1)");
        		System.out.println("Re-generating question without skipping");
        		return generateQuestion(difficulty, choiceSize, false);
        	} else {
        		System.out.println("Valid result set, proceeding with computations");
        	}
        	indexSelected = (int) (Math.random() * movies.size());
        	movieSelected = movies.get(indexSelected);
        	question = "What movie has " + movieSelected + " NOT acted in?";
        	genreSetSelected = genres.get(indexSelected);
        	HashSet<String> chosen4 = new HashSet<>();
        	for (int i = 0; i < choiceLimit - 1 && i < genreSetSelected.getList().size(); ++i) {
        		chosen4.add(genreSetSelected.getList().get(i));
        	}
        	String answer4 = null;
        	while (answer4 == null) {
        		int index = (int) (Math.random() * movies.size());
        		SQLGenreSet genreSet = genres.get(index);
        		if (index != indexSelected) {
        			if (genreSet.getList().size() == 0) {
        				continue;
        			}
        			String movanswer = genreSet.getList().remove(0);
        			if (!genreSetSelected.contains(movanswer) && !chosen4.contains(movanswer)) {
        				choices.add(movanswer);
        				answer4 = movanswer;
        			}
        		}
        	}
        	answer = (int) (Math.random() * (choices.size() + 1));
        	choices.add(answer, answer4);
        	return new Question(question, choices, answer);
        */
      case 5:
      case 6:
        // just re-generate question since incomplete code
        return generateQuestion(difficulty, choiceSize, skipElements);
      case 7:
        // has actor X acted in same movie as actor Y?
        if (!cacheContainsKey(7, difficulty) || Math.random() <= refreshThreshold) {
          loadIndex(7, difficulty, choiceSize, skipElements);
        }
        mids = (ArrayList<Integer>) questionCache.get(getCacheKey(7, difficulty)).getPropertyList();
        aids = (ArrayList<Integer>) questionCache.get(getCacheKey(7, difficulty)).getAnswerList();
        int actor1 = -1, actor2 = -1;
        for (int i = 0; i < choiceSize * 2 && (actor1 == -1 || actor2 == -1); i++) {
          int randomVal = aids.get((int) (Math.random() * mids.size()));
          if (actor1 == -1) {
            actor1 = randomVal;
          } else if (randomVal == actor1) {
            continue;
          } else {
            actor2 = randomVal;
            break;
          }
        }
        Connection conn = DBConnect.getConnection();
        HashSet<Integer> actor1MovieSet = new HashSet<>();
        HashSet<Integer> actor2MovieSet = new HashSet<>();
        String a1Name = "", a2Name = "";
        try {
          Statement statement = conn.createStatement();
          ResultSet rs =
              statement.executeQuery("select mid as mid from movie.acts where aid = " + actor1);
          while (rs.next()) {
            int movieID = rs.getInt("mid");
            actor1MovieSet.add(movieID);
          }
          statement = conn.createStatement();
          rs = statement.executeQuery("select mid as mid from movie.acts where aid = " + actor1);
          while (rs.next()) {
            int movieID = rs.getInt("mid");
            actor2MovieSet.add(movieID);
          }
          statement = conn.createStatement();
          rs =
              statement.executeQuery("select name as name from movie.actors where aid = " + actor1);
          if (rs.next()) {
            a1Name = rs.getString("name");
          } else {
            System.out.println("actor id " + actor1 + " does not have a name");
          }
          statement = conn.createStatement();
          rs =
              statement.executeQuery("select name as name from movie.actors where aid = " + actor2);
          if (rs.next()) {
            a2Name = rs.getString("name");
          } else {
            System.out.println("actor id " + actor2 + " does not have a name");
          }
        } finally {
          if (conn != null) {
            conn.close();
          }
        }
        answer = 1;
        for (int mid : actor1MovieSet) {
          if (actor2MovieSet.contains(mid)) {
            answer = 0;
            break;
          }
        }
        question = "Have " + a1Name + " and " + a2Name + " acted in the same movie?";
        choices.add("True");
        choices.add("False");
        return new Question(question, choices, answer);
      case 8:
        // which set of genres is movie X NOT about?
        if (!questionCache.containsKey(getCacheKey(1, difficulty))
            || Math.random() <= refreshThreshold) {
          dbConnect = true;
          loadIndex(1, difficulty, choiceSize, skipElements);
        }
        movies =
            (ArrayList<String>) questionCache.get(getCacheKey(1, difficulty)).getPropertyList();
        genres =
            (ArrayList<SQLGenreSet>) questionCache.get(getCacheKey(1, difficulty)).getAnswerList();
        if (movies.size() < resultThreshold) {
          System.out.println(
              "Insufficient amount of elements for question type: (" + movies.size() + ", 8)");
          System.out.println("Re-generating question without skipping");
          return generateQuestion(difficulty, choiceSize, false);
        } else {
          System.out.println("Valid result set, proceeding with computations");
        }
        indexSelected = (int) (Math.random() * movies.size());
        movieSelected = movies.get(indexSelected);
        question = "Which of these genres does not match the genre of " + movieSelected + "?";
        genreSetSelected = genres.get(indexSelected);
        if (genreSetSelected.size() == 0) {
          return generateQuestion(difficulty, choiceSize, skipElements);
          // just redo, we selected bad data on random
        }
        ArrayList<String> choiceCandidates = genreSetSelected.getScrambledList();
        for (int i = 0; i < choiceLimit - 1 && i < choiceCandidates.size(); ++i) {
          choices.add(choiceCandidates.get(i));
        }
        answer = (int) (Math.random() * (choices.size() + 1));
        ArrayList<String> genresSetComplement = new ArrayList<>();
        for (String s : ALL_GENRES) {
          if (!genreSetSelected.contains(s)) {
            genresSetComplement.add(s);
          }
        }
        if (genresSetComplement.isEmpty()) {
          System.out.println("Genres set complement is empty, re-generating question.");
          System.out.println("Genres set was " + genreSetSelected.toString());
          return generateQuestion(difficulty, choiceSize, skipElements);
        }
        choices.add(
            answer, genresSetComplement.get((int) (Math.random() * genresSetComplement.size())));
        return new Question(question, choices, answer);
      case 9:

      case 10:
        // which actor is associated with date of birth x?
        ArrayList<String> aName = null;
        ArrayList<String> aDOB = null;
        if (!questionCache.containsKey(getCacheKey(10, difficulty))
            || Math.random() <= refreshThreshold) {
          dbConnect = true;
          loadIndex(10, difficulty, choiceSize, skipElements);
        }
        aName =
            (ArrayList<String>) questionCache.get(getCacheKey(10, difficulty)).getPropertyList();
        aDOB = (ArrayList<String>) questionCache.get(getCacheKey(10, difficulty)).getAnswerList();
        if (aName.size() < resultThreshold) {
          System.out.println(
              "Insufficient amount of elements for question type: (" + aName.size() + ", 10)");
          System.out.println("Re-generating question without skipping");
          return generateQuestion(difficulty, choiceSize, false);
        } else {
          System.out.println("Valid result set, proceeding with computations");
        }
        ArrayList<Integer> randomSelects = new ArrayList<>();
        for (int i = 0; i < choiceLimit; ++i) {
          int randomIndex = (int) (Math.random() * aName.size());
          if (!randomSelects.contains(randomIndex) && !choices.contains(aDOB.get(randomIndex))) {
            randomSelects.add(randomIndex);
            choices.add(aDOB.get(randomIndex));
          } else {
            --i;
          }
        }
        // randomSelects now contains 5 random indices to (actor, DOB) pair
        answer = (int) (Math.random() * randomSelects.size());
        question =
            "On which day was actor "
                + aName.get(randomSelects.get(answer))
                + " born? (YYYY-MM-DD)";
        return new Question(question, choices, answer);
      default:
    }
    return null;
  }