//------------------------------------------------------------------------------
//	Copyright (C) 2010 Humboldt-Universitaet zu Berlin
//
//	This library is free software; you can redistribute it and/or
//	modify it under the terms of the GNU Lesser General Public
//	License as published by the Free Software Foundation; either
//	version 2.1 of the License, or (at your option) any later version.
//
//	This library is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//	Lesser General Public License for more details.
//
//	You should have received a copy of the GNU Lesser General Public
//	License along with this library; if not, write to the Free Software
//	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//------------------------------------------------------------------------------

/**
 * @file Example_Statistics.cpp
 * @author Ronald Kluth
 * @date created at 2010/04/13
 * @brief Example showing how to use the StatisticsBuffer
 * @since 3.0
*/

/**
 * @example Example_Statistics.cpp
 * The typical usage of ODEMx logging is shown.
 *
 * This example shows the use of the statistics channel on the producer's
 * side and the use of a StatisticsBuffer on the log consumer side.
 * For this purpose, the class StopWatch is again specialized in order
 * to log statistical data.
 */

#include "Example_Producer_StopWatch.h"
using namespace odemx;

class StatisticsStopWatch: public StopWatch {
public:
	StatisticsStopWatch( base::Simulation& sim, const data::Label& label )
	:	StopWatch( sim, label )
	{}
	void start() {
		StopWatch::start();
		//
		// We count the number of uses of this object
		//
		statistics << count( "uses" );
	}
	void stop() {
		StopWatch::stop();
		//
		// We compute accumulated statistics about the duration measured with
		// the StopWatch.
		//
		statistics << update( "duration", StopWatch::getDuration() );
	}
};

int main() {
	using data::buffer::StatisticsBuffer;
	typedef std::tr1::shared_ptr< StatisticsBuffer > BufferPtr;
	base::Simulation& sim = getDefaultSimulation();
	//
	// Initializing the buffer with true mean we want to store update pairs.
	//
	BufferPtr buf = StatisticsBuffer::create( sim, "Statistics Buffer", true );
	sim.addConsumer( data::channel_id::statistics, buf );
	//
	// In order to produce a good value distribution, we use the watch
	// 10000 times.
	//
	odemx::random::Normal normal( sim, "Normal Distribution", 42, 5 );
	StatisticsStopWatch watch( sim, "Statistics Stop Watch" );
	int i = 10000;
	while( i-- ) {
		watch.start();
		sim.setCurrentTime( sim.getTime() + normal.sample() );
		watch.stop();
	}
	//
	// Now we can use the stored update pairs to produce a histogram
	// for displaying the normal distribution.
	//
	const StatisticsBuffer::UpdateDeque& updates = buf->getUpdates( watch.getLabel(), "duration" );
	statistics::Histogram histogram( sim, "StopWatch Duration", 20, 70, 25 );
	for( StatisticsBuffer::UpdateDeque::size_type i = 0; i < updates.size(); ++i ) {
		histogram.update( updates[ i ].second );
	}

	data::output::XmlReport report( "Example_Statistics.xml" );
	report.addReportProducer( *buf );
	report.addReportProducer( histogram );
	report.generateReport();
}
