/**
 * @file TestRegression.cpp
 * @date Aug 7, 2008
 * @author Ronald Kluth
 *
 * @brief Tests for ODEMx class Regression
 */

#include "TestStatistics.h"
#include "../TestBase/TestBase.h"
#include "../TestData/TestData.h"

/// @cond DOXYGEN_SKIP
SUITE( Statistics )
{
/// @endcond

	/**
	 * @struct RegressionFixture
	 * @brief Helper struct providing set-up/tear-down of Regression tests
	 *
	 * @copydetails EventFixture
	 */
	struct RegressionFixture
	{
		SuiteBase::SimulationTest sim;
		SuiteData::ReportTest reporter;
		Regression regress;

		RegressionFixture()
		:	sim( "RegressionTestSim" ),
			reporter(),
			regress( sim, "RegressionTest" )
			{}
	};

	/**
	 * @test odemx::Regression construction
	 *
	 * Expected effects:
	 * @li label is set correctly
	 * @li statistics manager (Simulation) is set correctly
	 * @li last reset time is current SimTime
	 */
	TEST_FIXTURE( RegressionFixture, ConstructionDestruction )
	{
		data::Label label = "TestRegressionConstructionUserSim";
		std::auto_ptr< Regression > regress( new Regression( sim, label ) );
		CHECK_EQUAL( label, regress->getLabel() );
		CHECK_EQUAL( sim.getTime(), regress->getResetTime() );
	}

	/**
	 * @test odemx::Regression::update()
	 *
	 * Expected function call effects:
	 * @li usage counter is increased by one
	 */
	TEST_FIXTURE( RegressionFixture, Update )
	{
		double x = 1.66, y = 3.11;
		regress.update( x, y );
		regress.update( x, y );
		regress.update( x, y );
		CHECK_EQUAL( x, regress.getXMean() );
		CHECK_EQUAL( y, regress.getYMean() );
	}

	/**
	 * @test odemx::Regression::reset()
	 *
	 * Expected function call effects:
	 * @li the counter value is set to 0
	 * @li the last reset time is set to the sim's time
	 */
	TEST_FIXTURE( RegressionFixture, Reset )
	{
		base::SimTime simTime = 25;

		regress.update( 16.5, 2.3 );
		CHECK( regress.getXMean() > 0 );
		CHECK( regress.getYMean() > 0 );

		regress.reset( simTime );
		CHECK_EQUAL( 0.0, regress.getXMean() );
		CHECK_EQUAL( 0.0, regress.getYMean() );
		CHECK_EQUAL( simTime, regress.getResetTime() );
	}

	/**
	 * @test odemx::Regression computation of correct values
	 *
	 * The values for this test have been taken from a Wikipedia example, which
	 * can be found at http://de.wikipedia.org/wiki/Kleinste-Quadrate-Schätzer.
	 *
	 * Expected effects:
	 * @li the values from the example produce the expected results
	 * @li the report table contains the correct values produced by Regression
	 */
	TEST_FIXTURE( RegressionFixture, WikiExampleAndReport )
	{
		base::SimTime simTime = 25;
		regress.reset( simTime ); // non-0 reset time

		regress.update( 208, 21.6 );
		regress.update( 152, 15.5 );
		regress.update( 113, 10.4 );
		regress.update( 227, 31.0 );
		regress.update( 137, 13.0 );
		regress.update( 238, 32.4 );
		regress.update( 178, 19.0 );
		regress.update( 104, 10.4 );
		regress.update( 191, 19.0 );
		regress.update( 130, 11.8 );

		CHECK_CLOSE( 167.8, regress.getXMean(), 0.00000001 );
		CHECK_CLOSE( 18.41, regress.getYMean(), 0.00000001 );
		CHECK_CLOSE( 0.161234, regress.getEstimatedRegressionCoefficient(), 0.00001 );
		CHECK_CLOSE( 0.92217, regress.getCorrelationCoefficient(), 0.00001 );

		reporter.addReportProducer( regress );
		reporter.generateReport();
		CHECK( reporter.processedTables );

		// check the table
		CHECK_EQUAL( regress.getLabel(), reporter.allTableContent[0][0] );
		CHECK_EQUAL( toString( regress.getResetTime() ), reporter.allTableContent[0][1] );
		CHECK_EQUAL( toString( regress.getUpdateCount() ), reporter.allTableContent[0][2] );
		CHECK_EQUAL( toString( regress.getXMean() ), reporter.allTableContent[0][3] );
		CHECK_EQUAL( toString( regress.getYMean() ), reporter.allTableContent[0][4] );
		CHECK_EQUAL( toString( regress.getDx() ), reporter.allTableContent[0][5] );
		CHECK_EQUAL( toString( regress.getDy() ), reporter.allTableContent[0][6] );
		CHECK_EQUAL( toString( regress.getResidualStandardDeviation() ), reporter.allTableContent[0][7] );
		CHECK_EQUAL( toString( regress.getEstimatedRegressionCoefficient() ), reporter.allTableContent[0][8] );
		CHECK_EQUAL( toString( regress.getIntercept() ), reporter.allTableContent[0][9] );
		CHECK_EQUAL( toString( regress.getRegressionCoefficientStandardDeviation() ), reporter.allTableContent[0][10] );
		CHECK_EQUAL( toString( regress.getCorrelationCoefficient() ), reporter.allTableContent[0][11] );
	}

/// @cond DOXYGEN_SKIP
}
/// @endcond
