// FILE: statexam.cxx
// Written by Michael Main (main@colorado.edu)
// Modified by Jim Rogers Jan/2001, Jan/2002
// This program calls five test functions to test the statisitician class.
// Maximum number of points from this program is 80.

#include <iostream>
#include <cstdlib>
#include <cmath>
#include <string.h>    // Provides memcpy function
#include "stats.h"

using namespace std;
using namespace CS256_Asgn_2;

bool close(double a, double b)
{
    const double EPSILON = 1e-5;
    return (fabs(a-b) < EPSILON);
}

int test1( )
{
    // Test program for basic statistician functions.
    // Returns 34 if everything goes okay

    statistician s, t;
    int i;
    double r = 0;

    if (s.length( ) || t.length( )) return 0;
    if (s.sum( ) || t.sum( )) return 1;

    for (i = 1; i <= 10000; i++)
    {
	s.next(i);
	r += i;
    };

    if (t.length( ) || t.sum( )) return 4;
    if (s.length( ) != 10000) return 7;
    if (!close(s.sum( ), r)) return 10;
    if (!close(s.mean( ), r/10000)) return 13;
    
    // Reset and then retest everything
    s.reset( );
    t.reset( );
    r = 0;
    
    if (s.length( ) || t.length( )) return 16;
    if (s.sum( ) || t.sum( )) return 19;

    for (i = 1; i <= 10000; i++)
    {
	s.next(i);
	r += i;
    };

    if (t.length( ) || t.sum( )) return 22;
    if (s.length( ) != 10000) return 25;
    if (!close(s.sum( ), r)) return 28;
    if (!close(s.mean( ), r/10000)) return 31;

    return 34;
}

int test2( )
{
    // Test program for minimum/maximum statistician functions.
    // Returns 4 if everything goes okay

    statistician s, t, u;
    double r = 1000;
    char n[15] = "10000000000000";

    if (s.length( ) || t.length( )) return 0;
    if (s.sum( ) || t.sum( )) return 0;

    memcpy(&r, n, sizeof(double));
    r = 1/r;
    s.next(r);
    if ( s.length() == 0 ) return 0;
    if ((s.minimum( ) != r) || (s.maximum( ) != r)) return 0;
    r *= -1;
    t.next(r);
    if ( t.length() == 0 ) return 0;
    if ((t.minimum( ) != r) || (t.maximum( ) != r)) return 1;

    u.next(100); u.next(-1); u.next(101); u.next(3);
    if ((u.minimum( ) != -1) || (u.maximum( ) != 101)) return 2;

    return 4;
}

int test3( )
{
    // Test program for + operator of the statistician
    // Returns 4 if everything goes okay

    statistician s, t, u, v;

    if (s.length( ) || t.length( )) return 0;
    if (s.sum( ) || t.sum( )) return 0;

    t.next(5);
    u.next(0); u.next(10); u.next(10); u.next(20);

    v = s + s;
    if (v.length( ) || v.sum( )) return 0;
    v = s + u;
    if (!(u == v)) return 1;
    v = t + s;
    if (!(t == v)) return 1;
    v = t + u;
    if (v.length( ) != 5) return 2;
    if (!close(v.sum( ), 45)) return 2;
    if (v.minimum( ) != 0) return 2;
    if (v.maximum( ) != 20) return 2;
    if (!close(v.mean( ), 45.0/5)) return 2;
    v = v + t;
    if (v.length( ) != 6) return 3;
    if (!close(v.sum( ), 50)) return 3;
    if (v.minimum( ) != 0) return 3;
    if (v.maximum( ) != 20) return 3;
    if (!close(v.mean( ), 50.0/6)) return 3;
    return 4;
}

int test4( )
{
    // Test program for * operator of the statistician
    // Returns 4 if everything goes okay

    statistician s, t, u;

    if (s.length( ) || t.length( )) return 0;
    if (s.sum( ) || t.sum( )) return 0;

    u.next(0); u.next(10); u.next(10); u.next(20);

    s = 2*u;
    if (s.length( ) != 4) return 0;
    if (!close(s.sum( ), 80)) return 0;
    if (s.minimum( ) != 0) return 0;
    if (s.maximum( ) != 40) return 0;
    if (!close(s.mean( ), 80.0/4)) return 0;

    s = -2*u;
    if (s.length( ) != 4) return 1;
    if (!close(s.sum( ), -80)) return 1;
    if (s.minimum( ) != -40) return 1;
    if (s.maximum( ) != 0) return 1;
    if (!close(s.mean( ), -80.0/4)) return 1;

    s = 0*u;
    if (s.length( ) != 4) return 2;
    if (!close(s.sum( ), 0)) return 2;
    if (s.minimum( ) != 0) return 2;
    if (s.maximum( ) != 0) return 2;
    if (!close(s.mean( ), 0)) return 2;

    s = 10 * t;
    if (s.length( ) != 0) return 3;
    if (s.sum( ) != 0) return 3;

    return 4;
}

int test5( )
{
    // Test program for == operator of the statistician.
    // Returns 4 if everything goes okay

    statistician r, s, t, u, v, w, x, y, z;

    if (s.length( ) || t.length( )) return 0;
    if (s.sum( ) || t.sum( )) return 0;

    t.next(10);
    u.next(0); u.next(10); u.next(10); u.next(20);
    v.next(5); v.next(0); v.next(20); v.next(15);
    y.next(0); y.next(15); y.next(20); y.next(15);
    r.next(10); r.next(5); r.next(5); r.next(20);
    z.next(0); z.next(0); z.next(0); z.next(40);
    w.next(0);
    x.next(0); x.next(0);
    
    if (!(s == s)) return 0;
    if (s == t) return 1;
    if (t == s) return 1;
    if (s == w) return 2;
    if (w == s) return 2;
    if (u == t) return 2;
    if (!(u == v)) return 2;
    if (u == y) return 3;
    if (u == z) return 3;
    if (u == r) return 3;
    if (w == x) return 3;

    return 4;
}

int main( )
{
    int value = 0;
    int result;
    
    cerr << "Running statistician tests:" << endl;
 
    cerr << "TEST 1:  ";
    result = test1( );
    value += result;
    if (result == 34) cerr << "Passed. (34/34 points)"  << endl;
    else cerr << "Errors. (" << result << "/34 points)" << endl; 
 
    cerr << "\nTEST 2:  ";
    result = test2( );
    value += result;
    if (result == 4) cerr << "Passed. (4/4 points)" << endl;
    else cerr << "Errors. (" << result << "/4 points.)" << endl; 
 
    cerr << "\nTEST 3:  ";
    result = test3( );
    value += result;
    if (result == 4) cerr << "Passed. (4/4 points)" << endl;
    else cerr << "Errors. (" << result << "/4 points.)" << endl; 
 
    cerr << "\nTEST 4:  ";
    result = test4( );
    value += result;
    if (result == 4) cerr << "Passed. (4/4 points)" << endl;
    else cerr << "Errors. (" << result << "/4 points.)" << endl; 

    cerr << "\nTEST 5:  ";
    result = test5( );
    value += result;
    if (result == 4) cerr << "Passed. (4/4 points)" << endl;
    else cerr << "Errors. (" << result << "/4 points.)" << endl; 

    cerr << "If you submit the statistician now, this part of the\n";
    cerr << "grade will be " << value << " points out of 50.\n";
    
    return EXIT_SUCCESS;

}













