package gradebook;

import java.util.Collection;
import java.util.Arrays;
import java.util.Map;

/**
 * The Statistics class computes the number of data points,
 * mean, median and standard deviation for a specific column on
 * the grade spreadsheet.
 */
public abstract class Statistics
{
    //bstanaka

    /**
     * Takes in rows of Student grades and the column specified. Returns an
     * an array of the Grades in the provided column.
     */
    /*@
      requires
         //
         // column and data are not null.
         //
         
         (column != null) && (data != null);
         
      ensures
         //
         // The return value will have all of the grades for the 
         // given column.
         //
         
         (\forall Grade g_other ;
           Arrays.asList(\result).contains(g_other) <==>
           (\exists int i; 0 <= i && (i < data.students.size() - 1);
             data.students.get(i).grades.contains(g_other)));
         
    @*/
    abstract Grade[] columnToArray(GradedItem column, ClassData data);
    
    /** 
      Takes in a GradedItem column and rows of data and returns the number of
      data points in the column.
    */
    /*@
      requires 
         //
         // column and data are not null.
         //
         
         (column != null) && (data != null);
      
      ensures
         //
         // The return value is the number of items in the given
         // column.
         //
         \result == columnToArray(column, data).length;
    @*/
    abstract int dataPoints(GradedItem column, ClassData data);
    
    
    /**
      Takes in a GradedItem column and rows of data and returns the mean of 
      the items in the column.
    */
    /*@
      requires 
         //
         // The number of items is greater than 0. 
         // Also, column and data are not null.
         //
         
         dataPoints(column, data) > 0 && (column != null) && (data != null);
      
      
      ensures
         //
         // The return value is the mean of the items in the given
         // column.
         //
         
         \result == ((\sum int i; i >= 0 && i <= (dataPoints(column, data)); ((columnToArray(column, data))[i]).points)/(dataPoints(column, data)));
    @*/
    abstract int mean(GradedItem column, ClassData data);
    
    /**
      Takes in a GradedItem column and rows of data and returns the median of
      the items in the column.
    */
    /*@
      /*@
      requires 
         //
         // column and data are not null.
         //
         
         (column != null) && (data != null);
      
      ensures
         //
         // The return value is the median of the items in the given
         // column. The array in the ensures clause needs to be sorted.
         //
         
         \result == ((columnToArray(column, data))[(dataPoints(column, data))/2]).points;
    @*/
    abstract int median(GradedItem column, ClassData data);
    
    /**
      Takes in a GradedItem column and rows of data and returns the standard
      deviation of the items in the column.
    */
    /*@
      /*@
      requires 
         //
         // column and data are not null.
         //
         
         (column != null) && (data != null);
      
      ensures
         //
         // The return value is the standard deviation of the items in
         // the given column.
         //
         
         \result == (Math.sqrt(\sum int i; i >= 0 && i <= (dataPoints(column, data)); Math.round((Math.pow((1.0)*((columnToArray(column, data))[i].points - (mean(column, data))),2)))/(dataPoints(column,data))));         
    @*/
    abstract int stdDeviation(GradedItem column, ClassData data);
}