/**********************************************************************************
 * Perform array analytics computation
 * including: count, sum, average, minimum, maximum, median, standard deviation
 **********************************************************************************/
import java.util.*;                         //import utility class

public class Analytics
{
    double[] dataPoints;                    //array of data points 
    int      count;
    double   sum;
    double   average;
    double   median;
    double   min;
    double   max;
    double   stdDev;

    Analytics(double[] dataPoints)                                      //constructor
    {
        this.dataPoints = dataPoints;                                   //store incoming array as a reference
//      this.dataPoints = Arrays.copyOf(dataPoints, dataPoints.length); //store incoming array as a copy
   
        this.compute();                                                 //call the compute method
    }

    private void compute()
    {
        min = Double.POSITIVE_INFINITY;                 //set to highest possible value
        max = Double.NEGATIVE_INFINITY;                 //set to lowest possible value

        for (int i=0; i < dataPoints.length; i++)
        {
            count += 1;                                             //count
            sum   += dataPoints[i];                                 //sum
            if (dataPoints[i] < min)  min = dataPoints[i];          //if less than prev min? take it
            if (dataPoints[i] > max)  max = dataPoints[i];          //if more than prev max? take it 
        }
        average = sum/count;                                        //average        

        //Mean ---------------------------------
        Arrays.sort(dataPoints);                                    //sort the array
        median = (count%2 == 1)                                     //if count is odd
            ?  dataPoints[count/2]                                  //median= mid point 
            : (dataPoints[count/2] + dataPoints[count/2-1]) / 2;    //median= average of 2 mid points
        
        //standard deviation -------------------
        double sqDelta = 0;                                 //square of deltas      
        for (double element : dataPoints)                   //loop through all elements                 
            sqDelta += Math.pow(element-average,2);         //add to square of delta
        stdDev = Math.sqrt(sqDelta/count);                  //square root of average(square of deltas)
    }

    public String toString()
    {                
        String str =   "Data points: " + Arrays.toString(dataPoints)
                   + "\nCount......: " + count 
                   + "\nSum........: " + sum 
                   + "\nAverage....: " + average 
                   + "\nMedian.....: " + median 
                   + "\nMinimum....: " + min
                   + "\nMaximum....: " + max 
                   + "\nStd.Dev....: " + stdDev; 
        return(str);
    }
}