/***************************************************************************
 *   Copyright (C) 2005 by Robot Group Leipzig                             *
 *    martius@informatik.uni-leipzig.de                                    *
 *    fhesse@informatik.uni-leipzig.de                                     *
 *    der@informatik.uni-leipzig.de                                        *
 *    guettler@informatik.uni-leipzig.de                                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 *                                                                         *
 *   $Log: measureadapter.cpp,v $
 *   Revision 1.2  2008/04/17 14:54:45  martius
 *   randomGen added, which is a random generator with long period and an
 *    internal state. Each Agent has an instance and passed it to the controller
 *    and the wiring. This is good for
 *   a) repeatability on agent basis,
 *   b) parallel execution as done in ode_robots
 *
 *   Revision 1.1  2008/01/17 10:04:04  der
 *   first version
 *
 *
 *                                                                         *
 ***************************************************************************/
#include "measureadapter.h"
#include <sstream>


MeasureAdapter::MeasureAdapter(AbstractController* controller) : AbstractControllerAdapter(controller)
{
  st = new StatisticTools();
}

MeasureAdapter::~MeasureAdapter()
{
  if (st)
    free(st);
}

std::list<ComplexMeasure*> MeasureAdapter::addSensorComplexMeasure(char* measureName, ComplexMeasureMode mode,int numberBins, int stepSize)
{
  std::list<ComplexMeasure*> cmlist;
  if (initialized)
  {
    for (int i=0;i<controller->getSensorNumber();i++)
    {
      std::stringstream name;
      name << measureName << " [" << i << "]";
      ComplexMeasure* cm = new ComplexMeasure(name.str().c_str(),mode,numberBins);
      switch (mode)
      {
      case ENT:
        cm->addObservable(sensorValues[i],-1.0,1.0);
        cm->setStepSize(stepSize);
        break;
      case ENTSLOW:
        cm->addObservable(sensorValues[i],-1.0,1.0);
        break;
      default:
        break;
      }
      st->addMeasure(cm);
      cmlist.push_back(cm);
    }
  }
  else
  {
    std::cerr << "ERROR: The method" << std::endl
    << "       addSensorComplexMeasure(char* measureName, ComplexMeasureMode mode,int numberBins, int stepSize)"
    << std::endl << "must be called before the initialization of the Agent!" << std::endl;
    exit(1);
  }
  return cmlist;
}

/****************************************************************************/
/*	BEGIN methods of AbstractController                                 */
/****************************************************************************/

void MeasureAdapter::init(const int sensornumber, const int motornumber, RandGen* randGen)
{
  // call the same method of super class
  AbstractControllerAdapter::init( sensornumber,motornumber, randGen);
  // allocate memory for controlled Motors and sensors
  this->motorValues = (motor*) malloc(sizeof(motor) * motornumber);
  this->sensorValues = (sensor*) malloc(sizeof(sensor) * sensornumber);
}

void MeasureAdapter::step(const sensor* sensors, int sensornumber, motor* motors, int motornumber)
{
  AbstractControllerAdapter::step(sensors,sensornumber,motors,motornumber);
  // store motor and sensor values in motorValues and sensorValues
  for (int i=0;i<motornumber;i++)
    motorValues[i]=motors[i];
  for (int i=0;i<sensornumber;i++)
    sensorValues[i]=sensors[i];
  st->doOnCallBack();
}

void MeasureAdapter::stepNoLearning(const sensor* sensors , int sensornumber, motor* motors, int motornumber)
{
  AbstractControllerAdapter::stepNoLearning(sensors,sensornumber,motors,motornumber);
  // store motor and sensor values in motorValues and sensorValues
  for (int i=0;i<motornumber;i++)
    motorValues[i]=motors[i];
  for (int i=0;i<sensornumber;i++)
    sensorValues[i]=sensors[i];
  st->doOnCallBack();
}

/****************************************************************************/
/*	END methods of AbstractController                                   */
/****************************************************************************/

  /****************************************************************************/
  /*	BEGIN methods of Storeable                                           	*/
  /****************************************************************************/

bool MeasureAdapter::store(FILE* f) const {
  return controller->store(f);
}

bool MeasureAdapter::restore(FILE* f) {
  return controller->restore(f);
}

  /****************************************************************************/
  /*	END methods of Storeable                                          	    */
  /****************************************************************************/

/****************************************************************************/
/*	BEGIN methods of Inspectable                                        */
/****************************************************************************/

std::list<Inspectable::iparamkey> MeasureAdapter::getInternalParamNames() const
{
  std::list<Inspectable::iparamkey> list = AbstractControllerAdapter::getInternalParamNames();
  list+= st->getInternalParamNames();
  return list;
}

std::list<Inspectable::iparamval> MeasureAdapter::getInternalParams() const
{
  std::list<Inspectable::iparamval> vals = AbstractControllerAdapter::getInternalParams();
  vals+= st->getInternalParams();
  return vals;
}

/****************************************************************************/
/*	END methods of Inspectable                                          */
/****************************************************************************/
