/******************************************************************************
 * Both classes together
 ******************************************************************************/
 import java.util.*;                         //import utility class

/******************************************************************************
 * Perform analytics on an array
 * Count, sum, average, minimum, maximum, median, standard deviation
 * You can pass data points as args 
 ******************************************************************************/
public class AnalyticsUse
{
    public static void main (String[] args) 
    {   
        double[] dataPoints = {-1, 4, 20.3, 6.5, 8, -60.51, 45, 0, 3};  //use if no data is provided;

        if (args.length > 0)                                            //if data points are provided
        {
            dataPoints = new double[args.length];                       //create an array
            for (int i=0; i < args.length; i++)                         //loop through all args
                dataPoints[i] = Double.parseDouble(args[i]);            //convert from string to double 
        }

        System.out.println("THE ARRAY... " + Arrays.toString(dataPoints) + "\n");

        Analytics obj = new Analytics(dataPoints);                      //create an analytics object
//      dataPoints[0] = -1000;                                          //test: change the value of 1st element
        System.out.println("THE OBJECT...");                                
        System.out.println(obj);                                        //print the object    
    }
}


/**********************************************************************************
 * Perform array analytics computation
 * including: count, sum, average, minimum, maximum, median, standard deviation
 **********************************************************************************/
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);
    }
}