package tudo.streamingrec.evaluation.metrics;

import it.unimi.dsi.fastutil.doubles.DoubleArrayList;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import tudo.streamingrec.data.Transaction;

/**
 * Mean Reciprocal Rank Metric
 * @author MJ
 *
 */
public class MRR extends HypothesisTestableMetric{
	private static final long serialVersionUID = 2820604512185295616L;
	// result storage
	private DoubleArrayList results = new DoubleArrayList();

	@Override
	public void evaluate(Transaction transaction, LongArrayList recommendations,
			LongOpenHashSet userTransactions) {
		//if there is no ground truth, there is nothing to evaluate
		if (userTransactions == null || userTransactions.isEmpty()) {
			return;
		}
		
		// if the algorithm does not return any recommendations, count it as 0
		if (recommendations.isEmpty()) {
			results.add(0);
			return;
		}

		// calculate the MRR
		// if the algorithm retrieves less than k recommendations, we calculate
		// the real k value for this case
		int realK = Math.min(k, recommendations.size());
		// iterate over relevant items and calculate recall rank
		for (Long itemID : userTransactions) {
			for (int i = 0; i < realK; i++) {
				if (itemID == recommendations.getLong(i)) {
					results.add(1d/(i+1));
					return;
				}
			}
		}
		//nothing found -> count as zero
		results.add(0);
	}

	@Override
	public double getResults() {
		//return the average result
		return getAvg(results);
	}

	@Override
	public DoubleArrayList getDetailedResults() {
		//return the detailed results for t-tests
		return results;
	}
}