package edu.neu.ccs.pyramid.eval;

import edu.neu.ccs.pyramid.calibration.BucketInfo;
import edu.neu.ccs.pyramid.util.Pair;

import java.util.stream.Stream;

public class CalibrationEval {
    
    public static double mse(Stream<Pair<Double, Integer>> stream){
        return stream.mapToDouble(pair->Math.pow(pair.getFirst()-pair.getSecond(),2)).average().getAsDouble();
    }

    public static double error(Stream<Pair<Double, Integer>> stream, int numBuckets){
        BucketInfo bucketInfo = BucketInfo.aggregate(stream, numBuckets);
        double sum = 0;
        for (int i=0;i<bucketInfo.getNumBuckets();i++){
            double count = bucketInfo.getCounts()[i];
            sum += count*Math.abs(bucketInfo.getSumProbs()[i]/count-bucketInfo.getSums()[i]/count);
        }
        return sum/stream.count();
    }

    public static double sharpness(Stream<Pair<Double, Integer>> stream, int numBuckets){
        long total = stream.count();
        BucketInfo bucketInfo = BucketInfo.aggregate(stream, numBuckets);
        double[] accuracies = new double[bucketInfo.getNumBuckets()];
        for (int i=0;i<bucketInfo.getNumBuckets();i++){
            accuracies[i] = bucketInfo.getSums()[i]/bucketInfo.getCounts()[i];
        }
        double average = 0;
        for (int i=0;i<bucketInfo.getNumBuckets();i++){
            average += bucketInfo.getSums()[i];
        }

        average/=total;
        double sum = 0;
        for (int i=0;i<bucketInfo.getNumBuckets();i++){
            double count = bucketInfo.getCounts()[i];
            sum += count*Math.pow(accuracies[i]-average,2);
        }
        return sum/(total-1);
    }

    public static double variance(Stream<Pair<Double, Integer>> stream){
        long count = stream.count();
        double sum = stream.mapToDouble(pair->pair.getSecond()).sum();
        double sumSquare = stream.mapToDouble(pair->Math.pow(pair.getSecond(),2)).sum();
        return (sumSquare-sum*sum/count)/(count-1);

    }


}

@@ -789,33 +789,161 @@
     
-return sum/stream.c
+int total = 0;%0A        for (int i=0;i%3CbucketInfo.getNumBuckets();i++)%7B%0A            total += bucketInfo.getC
 ount
+s
 ()
+%5Bi%5D;%0A        %7D%0A        return sum/total
 ;%0A  
@@ -1041,44 +1041,8 @@
 s)%7B%0A
-        long total = stream.count();
 %0A   
@@ -1466,24 +1466,162 @@
 %0A        %7D%0A%0A
+        int total = 0;%0A        for (int i=0;i%3CbucketInfo.getNumBuckets();i++)%7B%0A            total += bucketInfo.getCounts()%5Bi%5D;%0A        %7D%0A%0A
         aver
@@ -1958,35 +1958,136 @@
     
-long count = stream
+VarResult varResult = stream.collect(()-%3Enew VarResult(),VarResult::add, VarResult::add);%0A        double count = varResult
 .count
-()
 ;%0A  
@@ -2109,56 +2109,186 @@
 m = 
-stream.mapToDouble(pair-%3Epair.getSecond()).
+varResult.sum;%0A        double sumSquare = varResult.sumSquare;%0A        return (sumSquare-sum*sum/count)/(count-1);%0A%0A    %7D%0A%0A%0A%0A    public static class VarResult%7B%0A        double 
 sum
-()
 ;%0A  
@@ -2313,132 +2313,450 @@
 uare
- = stream.mapToDouble(pair-%3EMath.pow(pair.getSecond(),2)).sum();%0A        return (sumSquare-sum*sum/count)/(count-1);%0A%0A
+;%0A        double count;%0A%0A        public VarResult() %7B%0A        %7D%0A%0A         void add(VarResult varResult)%7B%0A            this.sum += varResult.sum;%0A            this.count += varResult.count;%0A            this.sumSquare += varResult.sumSquare;%0A        %7D%0A%0A         void add(Pair%3CDouble, Integer%3E pair)%7B%0A            this.sum += pair.getSecond();%0A            this.count += 1;%0A            this.sumSquare += Math.pow(pair.getSecond(),2);%0A    
     %7D%0A%0A
+    %7D
 %0A%7D%0A

fix stream issue