public static double userBasedCustomPrediction (long targetItemId, LinkedList<IdSimilarityPair> topNeighborsList, HashMap<Long, HashMap<Long, RatingDatePair>> userItemRatingMap, HashMap<Long, Double> usersAvgRating, double amplification, double presenceBoost) throws ParseException{
		
		double prediction = 0.d;
		double sumOfSimilarities = 0d;
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		
		for(IdSimilarityPair idSim : topNeighborsList){
			long currentNeighbor = idSim.id;
			double currentSimilarity = Math.pow(idSim.similarity, amplification);
			
			HashMap<Long, RatingDatePair> neighborFV = userItemRatingMap.get(currentNeighbor);
			
			if(neighborFV.containsKey(targetItemId)){
				//get oldest and most recent rating dates
				Date oldest = sdf.parse("2050-12-31");
				Date newest = sdf.parse("1970-01-01");
				for(Long itemKey : neighborFV.keySet()){
					Date currentDate = sdf.parse(neighborFV.get(itemKey).getRatingDate());
					if(currentDate.getTime() < oldest.getTime()){
						oldest = currentDate;
					}
					if(currentDate.getTime() > newest.getTime()){
						newest = currentDate;
					}
				}
				long ratingPeriod = (newest.getTime() - oldest.getTime())/(1000*60*60*24);
				Date ratingDate = sdf.parse(neighborFV.get(targetItemId).getRatingDate());
				double oldRate = (ratingPeriod<5) ? 0 : ( ( (newest.getTime() - ratingDate.getTime() ) / (1000d*60d*60d*24d) ) / (double)ratingPeriod );
				double freshnessBoosting = Math.exp((1d-oldRate)/3d);
				
				prediction += presenceBoost*freshnessBoosting*currentSimilarity*neighborFV.get(targetItemId).getRating();
				sumOfSimilarities += presenceBoost*currentSimilarity*freshnessBoosting;
			}
			else{
				prediction += currentSimilarity*usersAvgRating.get(currentNeighbor);
				sumOfSimilarities += currentSimilarity;
			}
		}
		
		if(sumOfSimilarities==0){
			double neighborsAvg = 0d;
			for(Long user : usersAvgRating.keySet()){
				neighborsAvg += usersAvgRating.get(user);
			}
			return neighborsAvg/usersAvgRating.keySet().size();
		}
		
		return prediction / sumOfSimilarities;
	}