/**
  * Exports the simple user IDs and associated item IDs in the data model.
  *
  * @return a {@link FastByIDMap} mapping user IDs to {@link FastIDSet}s representing that user's
  *     associated items
  */
 public static FastByIDMap<FastIDSet> toDataMap(DataModel dataModel) throws TasteException {
   FastByIDMap<FastIDSet> data = new FastByIDMap<>(dataModel.getNumUsers());
   LongPrimitiveIterator it = dataModel.getUserIDs();
   while (it.hasNext()) {
     long userID = it.nextLong();
     data.put(userID, dataModel.getItemIDsFromUser(userID));
   }
   return data;
 }
  public static void main(String[] args) throws IOException, TasteException {
    String file = "datafile/item.csv";
    DataModel model = new FileDataModel(new File(file));
    UserSimilarity user = new EuclideanDistanceSimilarity(model);
    NearestNUserNeighborhood neighbor = new NearestNUserNeighborhood(NEIGHBORHOOD_NUM, user, model);
    Recommender r = new GenericUserBasedRecommender(model, neighbor, user);
    LongPrimitiveIterator iter = model.getUserIDs();

    while (iter.hasNext()) {
      long uid = iter.nextLong();
      List<RecommendedItem> list = r.recommend(uid, RECOMMENDER_NUM);
      System.out.printf("uid:%s", uid);
      for (RecommendedItem ritem : list) {
        System.out.printf("(%s,%f)", ritem.getItemID(), ritem.getValue());
      }
      System.out.println();
    }
  }
 private void buildAverageDiffs() throws TasteException {
   try {
     buildAveragesLock.writeLock().lock();
     DataModel dataModel = getDataModel();
     LongPrimitiveIterator it = dataModel.getUserIDs();
     while (it.hasNext()) {
       long userID = it.nextLong();
       PreferenceArray prefs = dataModel.getPreferencesFromUser(userID);
       int size = prefs.length();
       for (int i = 0; i < size; i++) {
         long itemID = prefs.getItemID(i);
         float value = prefs.getValue(i);
         addDatumAndCreateIfNeeded(itemID, value, itemAverages);
         addDatumAndCreateIfNeeded(userID, value, userAverages);
         overallAveragePrefValue.addDatum(value);
       }
     }
   } finally {
     buildAveragesLock.writeLock().unlock();
   }
 }
  public static void main(String[] args)
      throws FileNotFoundException, TasteException, IOException, OptionException {
    DataModel model;
    model = new FileDataModel(new File("datasets/ratingsForMahout.dat"));

    File movieMapFile = new File("datasets/moviesForMahout.dat");
    HashMap<Long, String> movieMap = new HashMap<Long, String>();
    Scanner scan = new Scanner(movieMapFile);
    while (scan.hasNextLine()) {
      String[] line = scan.nextLine().split("\\|");
      movieMap.put(Long.parseLong(line[0]), line[1]);
    }
    scan.close();

    UserSimilarity userSimilarity = new PearsonCorrelationSimilarity(model);
    UserNeighborhood neighborhood = new NearestNUserNeighborhood(3, userSimilarity, model);
    Recommender recommender = new GenericUserBasedRecommender(model, neighborhood, userSimilarity);
    Recommender cachingRecommender = new CachingRecommender(recommender);

    for (LongPrimitiveIterator it = model.getUserIDs(); it.hasNext(); ) {
      long userId = it.nextLong();
      List<RecommendedItem> recommendations = cachingRecommender.recommend(userId, 10);
      if (recommendations.size() == 0) {
        System.out.println("User " + userId + ": no recommendations");
      }
      for (RecommendedItem recommendedItem : recommendations) {
        System.out.println(
            "User "
                + userId
                + ": "
                + movieMap.get(recommendedItem.getItemID())
                + "; value="
                + recommendedItem.getValue());
      }
    }
  }
  @Override
  public double evaluate(
      RecommenderBuilder recommenderBuilder,
      DataModelBuilder dataModelBuilder,
      DataModel dataModel,
      double trainingPercentage,
      double evaluationPercentage)
      throws TasteException {
    Preconditions.checkNotNull(recommenderBuilder);
    Preconditions.checkNotNull(dataModel);
    Preconditions.checkArgument(
        trainingPercentage >= 0.0 && trainingPercentage <= 1.0,
        "Invalid trainingPercentage: "
            + trainingPercentage
            + ". Must be: 0.0 <= trainingPercentage <= 1.0");
    Preconditions.checkArgument(
        evaluationPercentage >= 0.0 && evaluationPercentage <= 1.0,
        "Invalid evaluationPercentage: "
            + evaluationPercentage
            + ". Must be: 0.0 <= evaluationPercentage <= 1.0");

    log.info("Beginning evaluation using {} of {}", trainingPercentage, dataModel);

    int numUsers = dataModel.getNumUsers();
    FastByIDMap<PreferenceArray> trainingPrefs =
        new FastByIDMap<PreferenceArray>(1 + (int) (evaluationPercentage * numUsers));
    FastByIDMap<PreferenceArray> testPrefs =
        new FastByIDMap<PreferenceArray>(1 + (int) (evaluationPercentage * numUsers));

    totalOfTrainingRatingsFromSource = 0;
    totalOfTrainingRatingsFromTargetWithContext = 0;
    totalOfTrainingRatingsFromTargetWithoutContext = 0;
    totalOfTestRatings = 0;

    LongPrimitiveIterator it = dataModel.getUserIDs();
    while (it.hasNext()) {
      long userID = it.nextLong();
      if (random.nextDouble() < evaluationPercentage) {
        splitOneUsersPrefs(trainingPercentage, trainingPrefs, testPrefs, userID, dataModel);
      }
    }

    // System.out.println("Training (Source, TargetWithoutContext, TargetWithContext):
    // "+totalOfTrainingRatingsFromSource+"/"+totalOfTrainingRatingsFromTargetWithoutContext+"/"+totalOfTrainingRatingsFromTargetWithContext);
    // int totalTraining =
    // (totalOfTrainingRatingsFromSource+totalOfTrainingRatingsFromTargetWithContext+totalOfTrainingRatingsFromTargetWithoutContext);
    // System.out.println("Training/Test: "+totalTraining+"/"+totalOfTestRatings);

    DataModel newDataModel =
        dataModel instanceof ContextualDataModel
            ? new ContextualDataModel(trainingPrefs)
            : new GenericDataModel(trainingPrefs);

    DataModel trainingModel =
        dataModelBuilder == null ? newDataModel : dataModelBuilder.buildDataModel(trainingPrefs);

    Recommender recommender = recommenderBuilder.buildRecommender(trainingModel);

    double result = getEvaluation(testPrefs, recommender);
    log.info("Evaluation result: {}", result);
    return result;
  }