class FStat implements IQualityMeasure {

	@Override
	public double assessQuality(final List<Double> distances, final int[] classValues) {
		// Order class distances
		HashMap<Integer, List<Double>> classDistances = new HashMap<>();
		for (int i = 0; i < distances.size(); i++) {
			if (!classDistances.containsKey(classValues[i])) {
				classDistances.put(classValues[i], new ArrayList<>());
			}

			classDistances.get(classValues[i]).add(distances.get(i));
		}
		int numClasses = classDistances.size();

		// Calculate class and overall means
		HashMap<Integer, Double> classMeans = new HashMap<>();
		for (Entry<Integer, List<Double>> entry : classDistances.entrySet()) {
			Integer clazz = entry.getKey();
			classMeans.put(clazz, entry.getValue().stream().mapToDouble(a -> a).average().getAsDouble());
		}
		double completeMean = distances.stream().mapToDouble(a -> a).average().getAsDouble();
		double denominator = 0;

		// Calculate actual F score
		double result = 0;
		for (Entry<Integer, Double> entry : classMeans.entrySet()) {
			Integer clazz = entry.getKey();
			double mean = entry.getValue();
			result += Math.pow(mean - completeMean, 2);

			for (Double dist : classDistances.get(clazz)) {
				denominator += Math.pow(dist - mean, 2);
			}
		}
		result /= numClasses - 1;
		denominator /= distances.size() - numClasses;
		if (denominator == 0) {
			throw new IllegalArgumentException("Given arguments yield a 0 " + denominator);
		}
		result /= denominator;

		return result;
	}

}