private static void addDatumAndCreateIfNeeded(
     long itemID, float value, FastByIDMap<RunningAverage> averages) {
   RunningAverage itemAverage = averages.get(itemID);
   if (itemAverage == null) {
     itemAverage = new FullRunningAverage();
     averages.put(itemID, itemAverage);
   }
   itemAverage.addDatum(value);
 }
 @Override
 public void setPreference(long userID, long itemID, float value) throws TasteException {
   DataModel dataModel = getDataModel();
   double prefDelta;
   try {
     Float oldPref = dataModel.getPreferenceValue(userID, itemID);
     prefDelta = oldPref == null ? value : value - oldPref;
   } catch (NoSuchUserException nsee) {
     prefDelta = value;
   }
   super.setPreference(userID, itemID, value);
   try {
     buildAveragesLock.writeLock().lock();
     RunningAverage itemAverage = itemAverages.get(itemID);
     if (itemAverage == null) {
       RunningAverage newItemAverage = new FullRunningAverage();
       newItemAverage.addDatum(prefDelta);
       itemAverages.put(itemID, newItemAverage);
     } else {
       itemAverage.changeDatum(prefDelta);
     }
     RunningAverage userAverage = userAverages.get(userID);
     if (userAverage == null) {
       RunningAverage newUserAveragae = new FullRunningAverage();
       newUserAveragae.addDatum(prefDelta);
       userAverages.put(userID, newUserAveragae);
     } else {
       userAverage.changeDatum(prefDelta);
     }
     overallAveragePrefValue.changeDatum(prefDelta);
   } finally {
     buildAveragesLock.writeLock().unlock();
   }
 }
  @Test
  public void testEvaluate() throws Exception {
    DataModel model = getDataModel();
    Recommender recommender1 = new SlopeOneRecommender(model);
    Recommender recommender2 = new ItemAverageRecommender(model);
    RecommenderEvaluator evaluator = new PreferenceBasedRecommenderEvaluator();

    RunningAverage tracker = new FullRunningAverage();
    evaluator.evaluate(recommender1, recommender2, 100, tracker, Formula.MEANRANK);
    double eval = tracker.getAverage();
    assertEquals(0.185294508934021, eval, EPSILON);
  }
 private float doEstimatePreference(long userID, long itemID) {
   buildAveragesLock.readLock().lock();
   try {
     RunningAverage itemAverage = itemAverages.get(itemID);
     if (itemAverage == null) {
       return Float.NaN;
     }
     RunningAverage userAverage = userAverages.get(userID);
     if (userAverage == null) {
       return Float.NaN;
     }
     double userDiff = userAverage.getAverage() - overallAveragePrefValue.getAverage();
     return (float) (itemAverage.getAverage() + userDiff);
   } finally {
     buildAveragesLock.readLock().unlock();
   }
 }
 @Override
 public void removePreference(long userID, long itemID) throws TasteException {
   DataModel dataModel = getDataModel();
   Float oldPref = dataModel.getPreferenceValue(userID, itemID);
   super.removePreference(userID, itemID);
   if (oldPref != null) {
     try {
       buildAveragesLock.writeLock().lock();
       RunningAverage itemAverage = itemAverages.get(itemID);
       if (itemAverage == null) {
         throw new IllegalStateException("No preferences exist for item ID: " + itemID);
       }
       itemAverage.removeDatum(oldPref);
       RunningAverage userAverage = userAverages.get(userID);
       if (userAverage == null) {
         throw new IllegalStateException("No preferences exist for user ID: " + userID);
       }
       userAverage.removeDatum(oldPref);
       overallAveragePrefValue.removeDatum(oldPref);
     } finally {
       buildAveragesLock.writeLock().unlock();
     }
   }
 }
 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();
   }
 }