text:
// Copyright (c) 2011-2016 The Cryptonote developers
// Copyright (c) 2016-2018, The Karbo developers
// Copyright (c) 2018-2020 The Cash2 developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>

#include "Common/PathTools.h"
#include "Common/SignalHandler.h"
#include "CryptoNoteCore/Core.h"
#include "CryptoNoteCore/CoreConfig.h"
#include "CryptoNoteCore/CryptoNoteTools.h"
#include "CryptoNoteCore/Currency.h"
#include "CryptoNoteCore/MinerConfig.h"
#include "CryptoNoteProtocol/CryptoNoteProtocolHandler.h"
#include "DaemonCommandsHandler.h"
#include "DaemonConfigurationOptions.h"
#include "DaemonRpcServer.h"
#include "DaemonRpcServerConfigurationOptions.h"
#include "Logging/ConsoleLogger.h"
#include "Logging/LoggerManager.h"
#include "P2p/NodeServer.h"
#include "P2p/NodeServerConfig.h"
#include "crypto/hash.h"
#include "version.h"

#if defined(WIN32)
#include <crtdbg.h>
#endif

int main(int argc, char* argv[])
{

#ifdef WIN32
  _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif

  Logging::LoggerManager logManager;
  Logging::LoggerRef logger(logManager, "Daemon");

  try {

    boost::program_options::options_description daemonConfigurationOptionsDescription("Daemon Configuration Options");
    CryptoNote::DaemonConfigurationOptions::initOptions(daemonConfigurationOptionsDescription);

    boost::program_options::options_description daemonRpcServerConfigurationOptionsDescription("Daemon RPC Server Configuration Options");
    CryptoNote::DaemonRpcServerConfigurationOptions::initOptions(daemonRpcServerConfigurationOptionsDescription);

    boost::program_options::options_description coreConfigurationOptionsDescription("Core Configuration Options");
    CryptoNote::CoreConfig::initOptions(coreConfigurationOptionsDescription);

    boost::program_options::options_description nodeServerConfigurationOptionsDescription("Node Server Configuration Options");
    CryptoNote::NodeServerConfig::initOptions(nodeServerConfigurationOptionsDescription);

    boost::program_options::options_description miningConfigurationOptionsDescription("Mining Configuration Options");
    CryptoNote::MinerConfig::initOptions(miningConfigurationOptionsDescription);

    boost::program_options::options_description allConfigurationOptionsDescription("All Configuration Options");

    allConfigurationOptionsDescription.
      add(daemonConfigurationOptionsDescription).
      add(daemonRpcServerConfigurationOptionsDescription).
      add(nodeServerConfigurationOptionsDescription).
      add(miningConfigurationOptionsDescription);

    boost::program_options::variables_map vm;

    boost::program_options::store(boost::program_options::parse_command_line(argc, argv, allConfigurationOptionsDescription), vm);

    CryptoNote::DaemonConfigurationOptions daemonConfigurationOptions;
    daemonConfigurationOptions.init(vm);

    if (daemonConfigurationOptions.help)
    {
      std::cout << CryptoNote::CRYPTONOTE_NAME << " v" << PROJECT_VERSION_LONG << ENDL << ENDL;
      std::cout << allConfigurationOptionsDescription << std::endl;
      return 0;
    }

    if (daemonConfigurationOptions.printGenesisTransaction) {
      Logging::ConsoleLogger logger;
      CryptoNote::Transaction tx = CryptoNote::CurrencyBuilder(logger).generateGenesisTransaction();
      CryptoNote::BinaryArray txb = CryptoNote::toBinaryArray(tx);
      std::string tx_hex = Common::toHex(txb);

      std::cout << "Insert this line into your coin configuration file as is: " << std::endl;
      std::cout << "const char GENESIS_COINBASE_TX_HEX[] = \"" << tx_hex << "\";" << std::endl;
      return 0;
    }

    std::string dataDirectory = daemonConfigurationOptions.dataDirectory;
    std::string configFile = daemonConfigurationOptions.configFile;

    boost::filesystem::path dataDirectoryPath(dataDirectory);
    boost::filesystem::path configFilePath(configFile);
    if (!configFilePath.has_parent_path()) {
      configFilePath = dataDirectoryPath / configFilePath;
    }

    boost::system::error_code ec;
    if (boost::filesystem::exists(configFilePath, ec)) {
      boost::program_options::store(boost::program_options::parse_config_file<char>(configFilePath.string<std::string>().c_str(), daemonConfigurationOptionsDescription), vm);
    }

    boost::program_options::notify(vm);

    std::string modulePath = Common::NativePathToGeneric(argv[0]);
    std::string logFile = Common::NativePathToGeneric(daemonConfigurationOptions.logFile);

    if (logFile.empty()) {
      logFile = Common::ReplaceExtenstion(modulePath, ".log");
    } else {
      if (!Common::HasParentPath(logFile)) {
        logFile = Common::CombinePath(Common::GetPathDirectory(modulePath), logFile);
      }
    }

    Logging::Level logLevel = static_cast<Logging::Level>(static_cast<int>(Logging::ERROR) + daemonConfigurationOptions.logLevel);

    // configure logging
    Common::JsonValue loggerConfiguration(Common::JsonValue::OBJECT);
    loggerConfiguration.insert("globalLevel", static_cast<int64_t>(logLevel));

    Common::JsonValue& cfgLoggers = loggerConfiguration.insert("loggers", Common::JsonValue::ARRAY);

    Common::JsonValue& fileLogger = cfgLoggers.pushBack(Common::JsonValue::OBJECT);
    fileLogger.insert("type", "file");
    fileLogger.insert("filename", logFile);
    fileLogger.insert("level", static_cast<int64_t>(Logging::TRACE));

    Common::JsonValue& consoleLogger = cfgLoggers.pushBack(Common::JsonValue::OBJECT);
    consoleLogger.insert("type", "console");
    consoleLogger.insert("level", static_cast<int64_t>(Logging::TRACE));
    consoleLogger.insert("pattern", "%T %L ");
    logManager.configure(loggerConfiguration);
    // end configure logging

    logger(Logging::INFO) << CryptoNote::CRYPTONOTE_NAME << " v" << PROJECT_VERSION_LONG;

    if (command_line::get_arg(vm, command_line::arg_version)) {
      std::cout << CryptoNote::CRYPTONOTE_NAME << " v" << PROJECT_VERSION_LONG << ENDL;
      return 0;
    }

    if (daemonConfigurationOptions.osVersion) {
      std::cout << "OS version : " << Tools::get_os_version_string() << ENDL;
      return 0;
    }

    logger(Logging::INFO) << "Module folder : " << argv[0];

    bool testnet_mode = daemonConfigurationOptions.testnet;
    if (testnet_mode) {
      logger(Logging::INFO) << "Starting in testnet mode ...";
    }

    CryptoNote::CurrencyBuilder currencyBuilder(logManager);
    currencyBuilder.testnet(testnet_mode);

    try {
      currencyBuilder.currency();
    } catch (std::exception&) {
      std::cout << "GENESIS_COINBASE_TX_HEX constant has an incorrect value. Please launch : " << CryptoNote::CRYPTONOTE_NAME << "d --print-genesis-tx";
      return 1;
    }

    CryptoNote::Currency currency = currencyBuilder.currency();
    CryptoNote::Core core(currency, nullptr, logManager);

    CryptoNote::Checkpoints checkpoints(logManager);
    for (const CryptoNote::CheckpointData& checkpointData : CryptoNote::CHECKPOINTS) {
      checkpoints.add_checkpoint(checkpointData.blockIndex, checkpointData.blockId);
    }

    if (!testnet_mode) {
      core.set_checkpoints(std::move(checkpoints));
    }

    CryptoNote::CoreConfig coreConfig;
    coreConfig.init(vm);

    if (!coreConfig.configFolderDefaulted) {
      if (!Tools::directoryExists(coreConfig.configFolder)) {
        throw std::runtime_error("Directory does not exist : " + coreConfig.configFolder);
      }
    } else {
      if (!Tools::create_directories_if_necessary(coreConfig.configFolder)) {
        throw std::runtime_error("Can't create directory : " + coreConfig.configFolder);
      }
    }

    System::Dispatcher dispatcher;

    CryptoNote::CryptoNoteProtocolHandler cryptoNoteProtocolHandler(currency, dispatcher, core, nullptr, logManager);
    CryptoNote::NodeServer nodeServer(dispatcher, cryptoNoteProtocolHandler, logManager);

    CryptoNote::DaemonRpcServerConfigurationOptions daemonRpcServerConfigurationOptions;
    daemonRpcServerConfigurationOptions.init(vm);
    CryptoNote::DaemonRpcServer daemonRpcServer(dispatcher, logManager, core, nodeServer, cryptoNoteProtocolHandler, daemonRpcServerConfigurationOptions);

    cryptoNoteProtocolHandler.set_p2p_endpoint(&nodeServer);
    core.set_cryptonote_protocol(&cryptoNoteProtocolHandler);
    DaemonCommandsHandler daemonCommandsHandler(core, nodeServer, logManager);

    // initialize objects
    CryptoNote::NodeServerConfig nodeServerConfig;
    nodeServerConfig.init(vm);
    nodeServerConfig.setTestnet(testnet_mode);

    logger(Logging::INFO) << "Initializing Node Server ...";
    if (!nodeServer.init(nodeServerConfig)) {
      logger(Logging::ERROR, Logging::BRIGHT_RED) << "Failed to initialize Node Server";
      return 1;
    }
    logger(Logging::INFO) << "Node Server initialized OK";

    // initialize core here
    CryptoNote::MinerConfig minerConfig;
    minerConfig.init(vm);

    logger(Logging::INFO) << "Initializing Core ...";
    if (!core.init(coreConfig, minerConfig, true)) {
      logger(Logging::ERROR, Logging::BRIGHT_RED) << "Failed to initialize Core";
      return 1;
    }
    logger(Logging::INFO) << "Core initialized OK";

    // start components
    if (!daemonConfigurationOptions.noConsole) {
      daemonCommandsHandler.start_handling();
    }

    logger(Logging::INFO) << "Starting Daemon RPC Server on network address " << daemonRpcServerConfigurationOptions.getBindAddress() << " ...";
    daemonRpcServer.start();
    daemonRpcServer.setRestrictedRpc(daemonRpcServerConfigurationOptions.restrictedRpc);
    daemonRpcServer.enableCors(daemonRpcServerConfigurationOptions.enableCors);
    logger(Logging::INFO) << "Daemon RPC Server started OK";

    Tools::SignalHandler::install([&daemonCommandsHandler, &nodeServer] {
      daemonCommandsHandler.stop_handling();
      nodeServer.sendStopSignal();
    });

    logger(Logging::INFO) << "Starting Node Server ...";
    nodeServer.run();
    logger(Logging::INFO) << "Node Server stopped";

    daemonCommandsHandler.stop_handling();

    //stop components
    logger(Logging::INFO) << "Stopping Daemon RPC Server ...";
    daemonRpcServer.stop();

    //deinitialize components
    logger(Logging::INFO) << "Deinitializing Core ...";
    core.deinit();
    logger(Logging::INFO) << "Deinitializing Node Server ...";
    nodeServer.deinit();

    core.set_cryptonote_protocol(NULL);
    cryptoNoteProtocolHandler.set_p2p_endpoint(NULL);

  } catch (const std::exception& e) {
    logger(Logging::ERROR, Logging::BRIGHT_RED) << "Exception : " << e.what();
    return 1;
  }

  logger(Logging::INFO) << "Node stopped";
  return 0;
}


text:
#include "logging.hpp"

#include <boost/beast.hpp>
#include <boost/log/trivial.hpp>

namespace ott
{

    namespace util
    {
        void fail(boost::beast::error_code ec, char const* what)
        {
            std::cerr << what << ": " << ec.message() << "\n";
        }
    } // util namespace
} // ott namespace

ext: cpp


text:
#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <Eigen/Dense>
#include "ros/ros.h"
#include "std_msgs/Float32.h"
#include "videoray/Throttle.h"
#include "geometry_msgs/Twist.h"
#include "nav_msgs/Odometry.h"
#include <iostream>
#include <fstream>
#include <signal.h>
#include <sstream>
#include "videoray/Status.h"
#include "videoray/UHRIComm.h"

double depth_ref = 0;
double speed_ref = 0;
double heading_ref = 0;
int VideoRay_Speed = 0;
double sharpturn_speed = 0;
double roll_ = 0;
double pitch_ = 0;
double yaw_ = 0;
double depth_err = 0;
double speed_err = 0;
double heading_err = 0;
double heading = 0;
double heading_weight = 0.5;
double speed_weight = 0.5;
double K_heading = 1;
double K_speed = 10;
double K_depth = 50;
videoray::Throttle throttle_;
//VideoRayComm comm;
float err;
float erry;
float previous_err = 0;
float integral = 0;
float derivative = 0;
float output;
float Kp=0.01;
float Ki=0;
float Kd=0.01;
float des_speed=0;

static const std::string OPENCV_WINDOW = "Image window";
int lowH_low = 0; // 13
int highH_low = 10; // 65 Set Hue
int lowH_high = 160; // 13
int highH_high = 180;

int lowS = 70; //72
int highS = 255; // 192Set Saturation

int lowV = 50; // 193
int highV = 255; //255 Set Value
int imageWidth;
int imageHeight;
int search_top;
int search_bottom;

int cx;
int cy;
  cv::Mat diffPts;
  cv::Mat ptsx, ptsy;
  cv::Mat canny_output;
  cv::Mat imgOriginal; //Input image
  cv::Mat hsvImg; //HSV Image
  cv::Mat mask1;
  cv::Mat mask2;
  cv::Mat threshImg; //Threshimage
  cv::Mat M;
 cv::Mat drawing;
 std::vector< cv::Vec4i > linesP;
  std::vector< std::vector<cv::Point> > contours;
std::vector< std::vector<cv::Point> > biggest_contours;
cv::Scalar color;
cv::RNG rng(12345);
 double dist;
 double dist_new;
size_t largest_contours = 0;
float heading_port, heading_star, speed_port, speed_star, speed_vert; //speed_vert is a new addition
ros::Publisher throttle_pub;
class ImageConverter
{
  ros::NodeHandle nh_;
  image_transport::ImageTransport it_;
  image_transport::Subscriber image_sub_;
  image_transport::Publisher image_pub_;

     ros::Publisher videoray_status_pub_;
public:
  ImageConverter()
    : it_(nh_)
  {

    // Subscribe to input video feed and publish output video feed
    image_sub_ = it_.subscribe("/videoray/camera/image_raw", 1,
      &ImageConverter::imageCb, this);
    image_pub_ = it_.advertise("/image_converter/output_video", 1);
    throttle_pub = nh_.advertise<videoray::Throttle>("/videoray/throttle", 1);
    //throttle_pub = nh_.advertise<videoray::Throttle>("/rqt_thrust_monitor/throttle_cmd", 1);
  }

  ~ImageConverter()
  {
     throttle_.PortInput =  0;
     throttle_.StarInput =  0;
     throttle_.VertInput = 0;
     throttle_pub.publish(throttle_);

    cv::destroyWindow(OPENCV_WINDOW);
  }

  void imageCb(const sensor_msgs::ImageConstPtr& msg)
  {
    cv_bridge::CvImagePtr cv_ptr;
    try
    {
      cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
    }
    catch (cv_bridge::Exception& e)
    {
      ROS_ERROR("cv_bridge exception: %s", e.what());
      return;
    }

imgOriginal = cv_ptr->image;

cv::cvtColor(imgOriginal, hsvImg, CV_BGR2HSV);

cv::inRange( hsvImg, cv::Scalar(lowH_low, lowS, lowV), cv::Scalar(highH_low, highS, highV), mask1);
cv::inRange( hsvImg, cv::Scalar(lowH_high, lowS, lowV), cv::Scalar(highH_high, highS, highV), mask2);
threshImg = mask1 | mask2;
 imageWidth = imgOriginal.size().width;
 imageHeight = imgOriginal.size().height;
std::cout << "width" << imageWidth << std::endl;
std::cout << "height" << imageHeight << std::endl;
 search_top = 3 * imageHeight / 4;
 search_bottom = search_top + 20;
for (int i; i < imageHeight; i++){
for(int j; j < imageWidth; j++){
if ( i < search_top && j < imageWidth){
	hsvImg.at<uchar>(i, j, 0) = 0 ;

}
if (   search_top < i && j > imageWidth){
	hsvImg.at<uchar>(i, j, 0) = 0 ;
}}
}
cv::GaussianBlur(threshImg, threshImg, cv::Size(3,3), 0); //reduce details
cv::dilate(threshImg, threshImg, 0); //removes noise
cv::erode(threshImg, threshImg, 0); //trims image

    cv::Canny( threshImg, canny_output, 100, 100*2, 3 ); //edge detection

    cv::findContours( canny_output, contours, cv::RETR_TREE,cv::CHAIN_APPROX_SIMPLE ); //finds edge
    std::vector<cv::Moments> mu(contours.size() ); //calculates moments
    for( int i = 0; i < contours.size(); i++ )
    {
        mu[i] = cv::moments( contours[i] );
    }
    std::vector<cv::Point2f> mc( contours.size() );
    for( int i = 0; i < contours.size(); i++ )
    {
        //add 1e-5 to avoid division by zero
        mc[i] = cv::Point2f( static_cast<float>(mu[i].m10 / (mu[i].m00 + 1e-5)),
                         static_cast<float>(mu[i].m01 / (mu[i].m00 + 1e-5)) ); //x center, y center
        //std::cout << "mc[" << i << "]=" << mc[i] << std::endl;
    }

    cv::Mat drawing = cv::Mat::zeros( canny_output.size(), CV_8UC3 );
	if (contours.size() > 1 ){
	dist =	cv::arcLength(contours[0], true);
		largest_contours = 0;
	for( size_t i = 0; i < contours.size(); i++ ){
		dist_new = cv::arcLength(contours[i], true);
		//std::cout << "old dist: " << dist << " new dist: " << dist_new << std::endl;
		if ( dist_new > dist) {
			dist = dist_new;
			largest_contours = i;
			//std::cout<< "largest countour: " << i << std::endl;

}
}

        color = cv::Scalar( rng.uniform(0, 256), rng.uniform(0,256), rng.uniform(0,256) );
        cv::drawContours( imgOriginal, contours, (int)largest_contours, color, 2 );//highlight the color
        cv::circle( imgOriginal, mc[largest_contours], 4, color, -1 );

	err = mc[largest_contours].x - imageWidth/2;
	erry = mc[largest_contours].y - imageHeight/2; //added
	speed_port=(err)/imageWidth*30+15;
	speed_star=-(err)/imageWidth*30+15;
	speed_vert=(erry)/imageHeight*40+15; //added

	std::cout<< "speed star " << speed_star << std::endl;
	std::cout<< "speed port " << speed_port << std::endl;
	std::cout<< "speed vert " << speed_vert << std::endl; //added
	//port = left, star = right, vert = up & down

	//if(abs(err)<20){
	  //speed_port = (double)VideoRay_Speed;
	  //speed_star = (double)VideoRay_Speed;
	//}
	//else if(err < -290){
	//sharpturn left
      	  //speed_port = -1 * (double)VideoRay_Speed;
	  //speed_star = (double)VideoRay_Speed;
	//}
	//else if(err<0){
	  //slight turn left
	  //speed_port = 0;
	  //speed_star = (double)VideoRay_Speed;
	//}
	//else if ( err > 290){
	  //sharp turn right
          //speed_port = (double)VideoRay_Speed;
	  //speed_star = -1 * (double)VideoRay_Speed;
	//}
	//else if(err>0){
	  //slight turn right
          //speed_port = (double)VideoRay_Speed;
	  //speed_star = 0;
	//}

  }

cv::namedWindow("imgOriginal", CV_WINDOW_NORMAL);
cv::namedWindow("threshImg", CV_WINDOW_NORMAL);

     /* Create trackbars in "threshImg" window to adjust according to object and environment.*/

  cv::createTrackbar("LowH", "threshImg", &lowH_low, 180); //Hue (0 - 179)
  cv::createTrackbar("HighH", "threshImg", &highH_low, 180);

  cv::createTrackbar("LowS", "threshImg", &lowS, 255); //Saturation (0 - 255)
  cv::createTrackbar("HighS", "threshImg", &highS, 255);

  cv::createTrackbar("LowV", "threshImg", &lowV, 255); //Value (0 - 255)
  cv::createTrackbar("HighV", "threshImg", &highV, 255);

  cv::createTrackbar("Speed", "threshImg", &VideoRay_Speed, 100);

  cv::imshow("imgOriginal", imgOriginal);     // show windows
  cv::imshow("threshImg", threshImg);

    // Update GUI Window
    //cv::imshow(OPENCV_WINDOW, cv_ptr->image);
    cv::waitKey(3);

    // Output modified video stream
     image_pub_.publish(cv_ptr->toImageMsg());
     //VideoRayComm comm;
     //comm.set_vertical_thruster(speed_vert);
     throttle_.PortInput=speed_port;
     throttle_.StarInput=speed_star;
     throttle_.VertInput= speed_vert; //was originally set to 0
     throttle_pub.publish(throttle_);

  }
};
void mySigintHandler(int sig){
 throttle_.PortInput =  0;
 throttle_.StarInput =  0;
 throttle_.VertInput = 0;
 throttle_pub.publish(throttle_);
 ros::shutdown();
}

int main(int argc, char** argv)
{
  ros::init(argc, argv, "image_converter");

 ImageConverter ic;
  signal(SIGINT, mySigintHandler);
  ros::spin();

return 0;
}


text:
/*********************************************************************
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011, MBARI.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the TREX Project nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */
#include "trex/europa/Assembly.hh"
#include "trex/europa/bits/europa_helpers.hh"
#include "private/Schema.hh"
#include "private/CurrentState.hh"

#include "trex/europa/ReactorPropagator.hh"
#include "trex/europa/DeliberationFilter.hh"
#include "trex/europa/SynchronizationManager.hh"

// include plasma header as system files in order to disable warnings
# define TREX_PP_SYSTEM_FILE <ModuleConstraintEngine.hh>
# include <trex/europa/bits/system_header.hh>
# define TREX_PP_SYSTEM_FILE <ModulePlanDatabase.hh>
# include <trex/europa/bits/system_header.hh>
# define TREX_PP_SYSTEM_FILE <ModuleRulesEngine.hh>
# include <trex/europa/bits/system_header.hh>
# define TREX_PP_SYSTEM_FILE <ModuleTemporalNetwork.hh>
# include <trex/europa/bits/system_header.hh>
# define TREX_PP_SYSTEM_FILE <ModuleSolvers.hh>
# include <trex/europa/bits/system_header.hh>
# define TREX_PP_SYSTEM_FILE <ModuleNddl.hh>
# include <trex/europa/bits/system_header.hh>
# define TREX_PP_SYSTEM_FILE <RulesEngine.hh>
# include <trex/europa/bits/system_header.hh>
# define TREX_PP_SYSTEM_FILE <Propagators.hh>
# include <trex/europa/bits/system_header.hh>
# define TREX_PP_SYSTEM_FILE <Schema.hh>
# include <trex/europa/bits/system_header.hh>
# define TREX_PP_SYSTEM_FILE <NddlInterpreter.hh>
# include <trex/europa/bits/system_header.hh>
# define TREX_PP_SYSTEM_FILE <Timeline.hh>
# include <trex/europa/bits/system_header.hh>
# define TREX_PP_SYSTEM_FILE <TokenVariable.hh>
# include <trex/europa/bits/system_header.hh>
# define TREX_PP_SYSTEM_FILE <PlanDatabaseWriter.hh>
# include <trex/europa/bits/system_header.hh>
# define TREX_PP_SYSTEM_FILE <Context.hh>
# include <trex/europa/bits/system_header.hh>
# define TREX_PP_SYSTEM_FILE <tinyxml.h>
# include <trex/europa/bits/system_header.hh>
# define TREX_PP_SYSTEM_FILE <XMLUtils.hh>
# include <trex/europa/bits/system_header.hh>
# define TREX_PP_SYSTEM_FILE <Debug.hh>
# include <trex/europa/bits/system_header.hh>

#include <boost/scope_exit.hpp>

#include <algorithm>
#include <iterator>

using namespace TREX::europa;

namespace {

  struct is_not_merged {
    is_not_merged(bool filt):m_filt(filt) {}

    bool operator()(EUROPA::TokenId const &tok) const {
      return m_filt || !tok->isMerged();
    }

    bool is_fact(EUROPA::TokenId const &tok) const {
      bool ret = tok->isFact();

      if( !( ret || m_filt ) ) {
        if( tok->isActive() ) {
          EUROPA::TokenSet const &merged = tok->getMergedTokens();
          for(EUROPA::TokenSet::const_iterator i=merged.begin();
              merged.end()!=i; ++i)
            if( (*i)->isFact() )
              return true;
        }
      }
      return ret;
    }

    bool is_goal(EUROPA::TokenId const &tok) const {
      bool ret = tok->getState()->baseDomain().isMember(EUROPA::Token::REJECTED);

      if( !(ret || m_filt) ) {
        if( tok->isActive() ) {
          EUROPA::TokenSet const &merged = tok->getMergedTokens();
          for(EUROPA::TokenSet::const_iterator i=merged.begin();
              merged.end()!=i; ++i)
            if( is_goal(*i) )
              return true;
        }
      }
      return ret;
    }

    void merged(EUROPA::TokenId const &tok, EUROPA::TokenSet &result) {
      if( !m_filt && tok->isActive() ) {
        EUROPA::TokenSet const &merged = tok->getMergedTokens();
        result.insert(merged.begin(), merged.end());
      }
    }

    bool const m_filt;
  }; // struct ::is_not_merged

} // ::

/*
 * class TREX::europa::details::CurrentStateId_id_traits
 */

// statics

EUROPA::eint details::CurrentStateId_id_traits::get_id(details::CurrentStateId const &cs) {
  if( cs.isId() )
    return cs->timeline()->getKey();
  return std::numeric_limits<EUROPA::eint>::minus_infinity();
}

/*
 * class TREX:europa::Assembly
 */

// statics

EUROPA::LabelStr const Assembly::TREX_TIMELINE("AgentTimeline");
EUROPA::LabelStr const Assembly::EXTERNAL_MODE("External");
EUROPA::LabelStr const Assembly::OBSERVE_MODE("Observe");
EUROPA::LabelStr const Assembly::INTERNAL_MODE("Internal");
EUROPA::LabelStr const Assembly::PRIVATE_MODE("Private");
EUROPA::LabelStr const Assembly::IGNORE_MODE("Ignore");
EUROPA::LabelStr const Assembly::MISSION_END("MISSION_END");
EUROPA::LabelStr const Assembly::MISSION_START("MISSION_START");
EUROPA::LabelStr const Assembly::TICK_DURATION("TICK_DURATION");
EUROPA::LabelStr const Assembly::CLOCK_VAR("AGENT_CLOCK");

std::string const Assembly::MODE_ATTR("mode");
std::string const Assembly::DEFAULT_ATTR("defaultPredicate");
std::string const Assembly::PLAN_ATTR("with_plan");

std::string const Assembly::UNDEFINED_PRED("undefined");
std::string const Assembly::FAILED_PRED("Failed");

bool Assembly::actions_supported() {
#ifdef EUROPA_HAVE_EFFECT
  return true;
#else
  return false;
#endif
}

// structors

Assembly::Assembly(std::string const &name, size_t steps,
                   size_t depth)
  :m_in_synchronization(false), m_name(name),
   m_debug_file(m_trex_schema->service()),
   m_synchSteps(steps), m_synchDepth(depth),
   m_archiving(false) {
     m_debug_file.open(m_trex_schema->file_name(m_name+"/europa.log"));
     m_debug.open(utils::async_buffer_sink(m_debug_file));
     m_trex_schema->setStream(m_debug);

  //  redirect log output to <name>/europa.log
  //  m_trex_schema->setStream(m_debug, m_name+"/europa.log");
  if( m_synchSteps==0 )
    m_synchSteps = std::numeric_limits<unsigned int>::max();
  else
    debugMsg("trex:always", "Limiting synchronization to "
             <<m_synchSteps<<" steps");
  if( m_synchDepth==0 )
    m_synchDepth = m_synchSteps;
  else if( m_synchDepth<m_synchSteps )
    debugMsg("trex:always", "Limiting synchronization depth to "
             <<m_synchDepth);

  // load the differrent europa modules we need
  addModule((new EUROPA::ModuleConstraintEngine())->getId());
  addModule((new EUROPA::ModuleConstraintLibrary())->getId());
  addModule((new EUROPA::ModulePlanDatabase())->getId());
  addModule((new EUROPA::ModuleRulesEngine())->getId());
  addModule((new EUROPA::ModuleTemporalNetwork())->getId());
  addModule((new EUROPA::ModuleSolvers())->getId());
  addModule((new EUROPA::ModuleNddl())->getId());

  // complete base class Initialization
  doStart();

  // gather europa entry points
  m_schema = ((EUROPA::Schema *)getComponent("Schema"))->getId();
  m_cstr_engine = ((EUROPA::ConstraintEngine *)getComponent("ConstraintEngine"))->getId();
  m_plan = ((EUROPA::PlanDatabase *)getComponent("PlanDatabase"))->getId();

  // Register the new propagator used for reactor related constraints
  new ReactorPropagator(*this, EUROPA::LabelStr("trex"), m_cstr_engine);

  m_cstr_engine->setAutoPropagation(false);

  // Get extra europa extensions
  m_trex_schema->registerComponents(*this);

  m_synchListener.reset(new synchronization_listener(*this));
  m_ce_listener.reset(new ce_listener(*this));
  m_proxy.reset(new listener_proxy(*this));

  //EUROPA::DomainComparator::setComparator((EUROPA::Schema *)m_schema);
}

Assembly::~Assembly() {
  setStream();
  // debugMsg("trex:end", "Destroying "<<m_name);
  m_proxy.reset();
  m_ce_listener.reset();
  m_synchListener.reset();
  // cleanup base class
  doShutdown();
}

// modifiers

void Assembly::init_clock_vars() {
  EUROPA::ConstrainedVariableId
    mission_end = plan_db()->getGlobalVariable(MISSION_END),
    mission_start = plan_db()->getGlobalVariable(MISSION_START),
    tick_factor = plan_db()->getGlobalVariable(TICK_DURATION);

  m_clock = plan_db()->getGlobalVariable(CLOCK_VAR);

  if( mission_end.isNoId() )
    throw EuropaException("Unable to find variable "+MISSION_END.toString());
  if( mission_start.isNoId() )
    throw EuropaException("Unable to find variable "+MISSION_START.toString());
  if( tick_factor.isNoId() )
    throw EuropaException("Unable to find variable "+TICK_DURATION.toString());
  if( m_clock.isNoId() )
    throw EuropaException("Unable to find variable "+CLOCK_VAR.toString());

  mission_start->restrictBaseDomain(EUROPA::IntervalIntDomain(initial_tick(),
							      initial_tick()));
  mission_end->restrictBaseDomain(EUROPA::IntervalIntDomain(final_tick(),
							    final_tick()));
  tick_factor->restrictBaseDomain(EUROPA::IntervalIntDomain(tick_duration(),
							    tick_duration()));
  m_clock->restrictBaseDomain(EUROPA::IntervalIntDomain(initial_tick(),
                                                        final_tick()));
}

void Assembly::add_state_var(EUROPA::TimelineId const &tl) {
  EUROPA::ObjectId obj(tl);

  if( internal(obj) || external(obj) ) {
    if( m_agent_timelines.find(tl->getKey())==m_agent_timelines.end() ) {
      details::CurrentStateId
        state = (new details::CurrentState(*this, tl))->getId();
      bool tl_internal = internal(obj);

      debugMsg("trex:timeline", "Adding State flaw manager for "
               <<tl->getName()
	       <<"\n\t* Current T-REX mode is "
               <<(tl_internal?"In":"Ex")<<"ternal.");
      m_agent_timelines.insert(state);
    }
  } else {
    debugMsg("trex:always", "WARNING attempted to create a state"
             <<" flaw manager for non public timeline "
	     <<tl->getName());
  }
}

void Assembly::new_tick() {
  bool auto_prop = constraint_engine()->getAutoPropagation();
  constraint_engine()->setAutoPropagation(false);

  debugMsg("trex:tick", "START new_tick["<<now()<< "]-----------------------------------------------------");
  debugMsg("trex:tick", "Updating clock to ["<<now()<<", "<<final_tick()<<"]");
  m_clock->restrictBaseDomain(EUROPA::IntervalIntDomain(now(), final_tick()));

  debugMsg("trex:tick", "Updating non-started goals to start after "<<now());
  boost::filter_iterator<details::is_rejectable,
                         EUROPA::TokenSet::const_iterator>
    t(m_roots.begin(), m_roots.end()), end_t(m_roots.end(), m_roots.end());
  EUROPA::IntervalIntDomain future(now(),
                                   std::numeric_limits<EUROPA::eint>::infinity());

  for(; end_t!=t; ++t) {
    EUROPA::TokenId active = (*t);

    if( (*t)->isMerged() )
      active = (*t)->getActiveToken();

    debugMsg("trex:tick", "Checking start & end times of "
             <<(*t)->getUnqualifiedPredicateName()
             <<'('<<(*t)->getKey()<<") : "
             <<active->start()->lastDomain().toString()
             <<" -> "<<active->end()->lastDomain().toString());

    if( now()<=active->start()->lastDomain().getUpperBound() ) {
      debugMsg("trex:tick", "Maintaining token start time to be after "<<now());
      debugMsg("trex:tick", "Before: "<<(*t)->toString()<<".start="<<(*t)->start()->baseDomain().toString()<<" * "<<active->start()->lastDomain().toString());
      details::restrict_base(*t, (*t)->start(), future);
      details::restrict_base(*t, (*t)->end(), EUROPA::IntervalIntDomain(now()+1,
                                                                        std::numeric_limits<EUROPA::eint>::infinity()));
      debugMsg("trex:tick", "After: "<<(*t)->toString()<<".start="<<(*t)->start()->baseDomain().toString()<<" * "<<active->start()->lastDomain().toString());
    } else if( now()<=active->end()->lastDomain().getUpperBound() ) {
      debugMsg("trex:tick", "Maintaining token end time to be after "<<now());
      debugMsg("trex:tick", "Before: "<<(*t)->toString()<<".end="<<(*t)->end()->baseDomain().toString()<<" * "<<active->end()->lastDomain().toString());
      details::restrict_base(*t, (*t)->end(), future);
      debugMsg("trex:tick", "After: "<<(*t)->toString()<<".end="<<(*t)->end()->baseDomain().toString()<<" * "<<active->end()->lastDomain().toString());
    }
  }
  debugMsg("trex:tick", "END new_tick["<<now()<< "]-----------------------------------------------------");
  // constraint_engine()->propagate();
  constraint_engine()->setAutoPropagation(auto_prop);
}

void Assembly::terminate(EUROPA::TokenId const &tok) {
  details::is_rejectable rejectable;
  EUROPA::TokenId active = tok;

  if( !tok->isCommitted() &&
     m_committed.find(tok)==m_committed.end() ) {
    if( m_completed.insert(tok).second )
      m_updated_commit = true;
  }

  details::restrict_base(tok, tok->end(),
                         details::active(tok)->end()->lastDomain());
  // I assume here that if a goals ends time is in the past then the goal is completed

  if( tok->isMerged() ) {
    active = tok->getActiveToken();
    if( rejectable(active) && discard(active) ) {
      details::restrict_base(active, active->end(), tok->end()->baseDomain());
      details::restrict_base(active, active->start(), tok->start()->baseDomain());
      if( !active->isCommitted() )
        if( m_completed.insert(active).second )
          m_updated_commit = true;
    }
  } else if( tok->isActive() )
    discard(tok);
  for(EUROPA::TokenSet::const_iterator i=active->getMergedTokens().begin();
      active->getMergedTokens().end()!=i; ++i) {
    if( rejectable(*i) && discard(*i) ) {
      details::restrict_base(*i, (*i)->end(), tok->end()->baseDomain());
      details::restrict_base(*i, (*i)->start(), tok->start()->baseDomain());
      if( !(*i)->isCommitted() )
        if( m_completed.insert(*i).second )
          m_updated_commit = true;
    }
  }
}

// manipulators

void Assembly::setStream() const {
  m_trex_schema->setStream(m_debug);
}

bool Assembly::locate_nddl(std::string &nddl) const {
  bool found;
  nddl = m_trex_schema->use(nddl, found);
  return found;
}

bool Assembly::playTransaction(std::string const &nddl, bool isFile) {
  std::string const &path = m_trex_schema->nddl_path();
  std::string ret;

  // configure search path for nddl
  getLanguageInterpreter("nddl")->getEngine()->getConfig()->setProperty("nddl.includePath", path);

  // parse nddl
  try {
    ret = executeScript("nddl", nddl, isFile);
  } catch(EUROPA::PSLanguageExceptionList const &l_err) {
    std::ostringstream err;
    err<<"Error while parsing "<<nddl<<":\n"<<l_err;
    throw EuropaException(err.str());
  } catch(Error const &error) {
    throw EuropaException("Error on parsing "+nddl+": "+error.getMsg());
  }
  if( !ret.empty() )
    throw EuropaException("Error returned after parsing "+nddl+": "+ret);

  return constraint_engine()->constraintConsistent();
}

void Assembly::configure_solvers(std::string const &synchronizer,
				 std::string const &planner) {
  debugMsg("trex:init", "Loading planner configuration from \""<<planner<<"\".");
  UNIQ_PTR<EUROPA::TiXmlElement>
    xml_cfg(EUROPA::initXml(planner.c_str()));

  debugMsg("trex:init", "Injecting global filter for planning horizon");
  EUROPA::TiXmlElement
    *filter=dynamic_cast<EUROPA::TiXmlElement *>(xml_cfg->InsertBeforeChild(xml_cfg->FirstChild(),
									    EUROPA::TiXmlElement("FlawFilter")));

  filter->SetAttribute("component", TO_STRING_EVAL(TREX_DELIB_FILT));
  debugMsg("trex:init", "Configuring europa planner with xml:\n"<<(*xml_cfg));
  m_planner = (new EUROPA::SOLVERS::Solver(plan_db(), *xml_cfg))->getId();

  if( synchronizer!=planner ) {
    debugMsg("trex:init", "Loading synchronizer configuration from \""<<planner<<"\".");
    xml_cfg.reset(EUROPA::initXml(synchronizer.c_str()));
    debugMsg("trex:init", "Injecting global filter for synchronizer horizon");
    filter = dynamic_cast<EUROPA::TiXmlElement *>(xml_cfg->InsertBeforeChild(xml_cfg->FirstChild(),
									     EUROPA::TiXmlElement("FlawFilter")));
  } else {
    debugMsg("trex:init", "Altering planner config for synchronizer");
    debugMsg("trex:init", "Altering global filter for synchronizer horizon");
  }

  filter->SetAttribute("component", TO_STRING_EVAL(TREX_SYNCH_FILT));
  debugMsg("trex:init", "Injecting current state flaws manager with priority of "<<TREX_SYNCH_PRIORITY);

  EUROPA::TiXmlElement synch(TO_STRING_EVAL(TREX_SYNCH_MGR)),
    handler("FlawHandler");
  synch.SetAttribute("defaultPriority", TREX_SYNCH_PRIORITY);
  handler.SetAttribute("component", TO_STRING_EVAL(TREX_SYNCH_HANDLER));
  synch.InsertEndChild(handler);
  xml_cfg->InsertEndChild(synch);

  debugMsg("trex:init", "Configuring europa synchronizer with xml:\n"<<(*xml_cfg));
  m_synchronizer = (new EUROPA::SOLVERS::Solver(plan_db(), *xml_cfg))->getId();

  debugMsg("trex:init", "Adding synchronizer activity listener");
  m_synchronizer->addListener(m_synchListener->getId());
}

EUROPA::ConstrainedVariableId Assembly::get_tick_const() {
  std::ostringstream oss;
  oss<<"__trex_tick_"<<now();
  std::string name(oss.str());
  EUROPA::DataTypeId type = m_clock->getDataType();

  if( m_tick_const.isNoId() || m_tick_const->getName()!=name ) {
    UNIQ_PTR<EUROPA::Domain> base(type->baseDomain().copy());
    base->set(now());

    debugMsg("trex:always", "Creating const "<<name);
    m_tick_const = m_cstr_engine->createVariable(type->getName().c_str(),
						 *base, true, true,
						 name.c_str());
    m_tick_const->incRefCount();
  }
  debugMsg("trex:always", "Current tick : "<<m_tick_const->getName()
	   <<'='<<m_tick_const->toString());
  return m_tick_const;
}

void Assembly::notify(details::CurrentState const &state) {
  EUROPA::LabelStr obj_name = state.timeline()->getName();

  if( is_internal(obj_name) ) {
    debugMsg("trex:notify", "Post observation "<<state.timeline()->toString()
             <<'.'<<state.current()->getUnqualifiedPredicateName()<<":\n"
             <<state.current()->toLongString());
    notify(obj_name, state.current());
  } // else if( is_external(obj_name) ) {
    // EUROPA::TokenId cur = state.current();
    // if( cur->isInactive() ) {
  /* Do not do thaT !!! it breaks the plan */
  //   plan_db()->getClient()->activate(cur);
  // }
  // }
}

bool Assembly::commit_externals() {
  bool auto_prop = m_cstr_engine->getAutoPropagation();

  m_cstr_engine->setAutoPropagation(false);

  BOOST_SCOPE_EXIT((&auto_prop)(&m_cstr_engine)) {
    m_cstr_engine->setAutoPropagation(auto_prop);
  } BOOST_SCOPE_EXIT_END;

  for(external_iterator i=begin_external(); end_external()!=i; ++i) {
    if( !(*i)->commit() ) {
      debugMsg("trex:always", "["<<now()
               <<"] failed to integrate state of external timeline "
               <<(*i)->timeline()->getName());
      return false;
    } /* else {
      EUROPA::TokenId cur = (*i)->current();
      if(cur->isMerged()) {
        EUROPA::TokenId act = cur->getActiveToken();
        cur->cancel();
        plan_db()->getClient()->merge(cur, act);
      }

      }*/

  }
  return true;
}

bool Assembly::do_synchronize() {
  m_in_synchronization = true;

  BOOST_SCOPE_EXIT((&m_in_synchronization)) {
    m_in_synchronization = false;
  } BOOST_SCOPE_EXIT_END;

  debugMsg("trex:synch", "Execute synchronization with steps="<<m_synchSteps
	   <<" depth="<<m_synchDepth);
  if( !synchronizer()->solve(m_synchSteps, m_synchDepth) ) {
    debugMsg("trex:synch", "Failed to resolve synchronization for tick "<<now());
    if( synchronizer()->getStepCount()>m_synchSteps ) {
      debugMsg("trex:always", "synchronization did exceed its maximum steps ("
               <<m_synchSteps<<')');
    } else if( synchronizer()->getDepth()>m_synchDepth ) {
      debugMsg("trex:always", "synchronization did exceed its maximum depth ("
               <<m_synchDepth<<')');
    }
    return false;
  }
  for(internal_iterator i=begin_internal(); end_internal()!=i; ++i)
    (*i)->commit(); // It was consistent from synchronizer => never fail

  // On success clear decisions as they are now assertions
  synchronizer()->clear();
  return true;
}

void Assembly::erase(EUROPA::TokenSet &set, EUROPA::TokenId const &tok) {
  EUROPA::TokenSet::iterator i = set.find(tok);
  if( set.end()!=i ) {
    if( m_iter==i )
      ++m_iter;
    set.erase(i);
  }
}

namespace {

  void deep_cancel(EUROPA::DbClientId cli, EUROPA::TokenId tok) {

    if( tok->isActive() ) {
      EUROPA::TokenSet slaves = tok->slaves(), to_del;
      for(EUROPA::TokenSet::iterator i=slaves.begin(); slaves.end()!=i; ++i) {
	if( !(*i)->isFact() ) {
	  deep_cancel(cli, *i);
	  to_del.insert(*i);
	}
      }
      for(EUROPA::TokenSet::iterator i=to_del.begin(); to_del.end()!=i; ++i)
	cli->deleteToken(*i);
    }
    if( !tok->isInactive() )
      cli->cancel(tok);
  }

}

bool Assembly::relax(bool aggressive) {
  details::is_rejectable rejectable;
  EUROPA::DbClientId cli = plan_db()->getClient();
  std::string relax_name = "RELAX";
  bool auto_prop = m_cstr_engine->getAutoPropagation();

  m_cstr_engine->setAutoPropagation(false);

  BOOST_SCOPE_EXIT((&auto_prop)(&m_cstr_engine)) {
    m_cstr_engine->setAutoPropagation(auto_prop);
  } BOOST_SCOPE_EXIT_END;

  if( aggressive )
    relax_name = "AGGRESSIVE "+relax_name;

  debugMsg("trex:relax", "["<<now()
           <<"] =================== START "<<relax_name<<" =================");
  // Clean up decisions made by solvers
  debugMsg("trex:relax", "Cancelling current decisions");
  // We can just clear them as we just goinfg to do the cleaning ourselve
  synchronizer()->clear();
  planner()->reset();
  m_updated_commit = m_updated_commit || aggressive; // ask for archiving whenever we have a full relax

  // Use m_iter for robust iteration
  m_iter = m_roots.begin();
  debugMsg("trex:relax", "Evaluating "<<m_roots.size()<<" root tokens.");

  while( m_roots.end()!=m_iter ) {
    EUROPA::TokenId tok = *(m_iter++);

    debugMsg("trex:relax", "Evaluating relaxation of "<<tok->toString()
             <<"\n\tPredicate: "<<tok->getPredicateName()
             <<"\n\tObjects: "<<tok->getObject()->toString()
             <<"\n\tstart: "<<tok->start()->lastDomain().toString()
             <<"\n\tend: "<<tok->end()->lastDomain().toString());

    if( tok->end()->baseDomain().getUpperBound()<=now() ) {
      debugMsg("trex:relax", "\t- "<<tok->getKey()
               <<" necessarily ends in the past");
      if( tok->isFact() ) {
        debugMsg("trex:relax", "\t- "<<tok->getKey()<<" is a fact");
        if( aggressive ) {
          debugMsg("trex:relax", "\t- destroying "<<tok->getKey()
                   <<" (aggressive)");
          if( !tok->isInactive() )
	    deep_cancel(cli, tok);
          cli->deleteToken(tok);
        } else if( tok->isMerged() ) {

 	  EUROPA::TokenId active = tok->getActiveToken();
	  active->incRefCount();
          cli->cancel(active);
          if( !aggressive ) {
            debugMsg("trex:relax", "\t- activate fact "<<tok->getKey());
            // cli->activate(tok);
          }
	  active->decRefCount();
        }
      } else {
        bool can_reject = rejectable(tok);

        if( can_reject || aggressive ) {
          if( can_reject ) {
            debugMsg("trex:relax", "\t- destroying the goal "<<tok->getKey());
          } else {
            debugMsg("trex:relax", "\t- destroying past token "<<tok->getKey()
                     <<" (aggressive)");
          }
          if( !tok->isInactive() )
            deep_cancel(cli, tok);
          cli->deleteToken(tok);
        }
      }
    } else {
      if( tok->isFact() ) {
        if( tok->isMerged() ) {
          debugMsg("trex:relax", "\t- give room for fact "<<tok->getKey()
		   <<" (cancel active="<<tok->getActiveToken()->getKey()<<")");
	  EUROPA::TokenId active = tok->getActiveToken();
	  active->incRefCount();
          cli->cancel(active);
          if( !aggressive ) {
            debugMsg("trex:relax", "\t- activate fact "<<tok->getKey());
            // cli->activate(tok);
          }
	  active->decRefCount();
        } /*else if( tok->isActive() ) {
            cli->cancel(tok);
            }*/
      } else if( !tok->isInactive() ) {
        debugMsg("trex:relax", "\t- cancelling non fact "<<tok->getKey());
        deep_cancel(cli, tok);
	if( is_action(tok) ) {
	  debugMsg("trex:relax", "\t- delete action "<<tok->getKey());
	  cli->deleteToken(tok);
	} else if( rejectable(tok) ) {
	  if( tok->start()->lastDomain().getUpperBound()>=now() ) {
	    tok->start()->restrictBaseDomain(EUROPA::IntervalIntDomain(now(),
								       std::numeric_limits<EUROPA::eint>::infinity()));
	  }
	}
      }
    }
  }

  debugMsg("trex:relax", "["<<now()<<"] =================== END "
           <<relax_name<<" =================");
  bool ret = constraint_engine()->propagate();
  if( !ret )
    debugMsg("trex:relax", "RELAX FAILURE !!!!");
  return ret;
}

void Assembly::replace(EUROPA::TokenId const &tok) {
  if( !tok->isMerged() )
    throw EuropaException("Attempted to replace a non merged token.");

  EUROPA::ObjectDomain
    const &dom = details::active(tok)->getObject()->lastDomain();
  std::list<EUROPA::ObjectId> objs = dom.makeObjectList();
  // Find the CurrentState if any
  state_iterator pos = m_agent_timelines.find(objs.front()->getKey());
  EUROPA::TokenId active = tok->getActiveToken();

  if( m_agent_timelines.end()!=pos ) {
    (*pos)->replaced(tok);
    tok->cancel();
  } else {
    details::restrict_bases(active, tok);
    tok->cancel();
  }
  if( m_committed.end()==m_committed.find(active) ) {
    m_completed.insert(active);
    m_updated_commit = true;
  }
  // Make dsure that this guy will stay on the current spot
  tok->end()->restrictBaseDomain(active->end()->lastDomain());
  tok->start()->restrictBaseDomain(active->start()->lastDomain());
}

void Assembly::archive(EUROPA::eint date) {
  using EUROPA::Token;
  // return;
  bool auto_prop = m_cstr_engine->getAutoPropagation();
  EUROPA::eint cur = now();

  m_cstr_engine->setAutoPropagation(false);
  m_archiving = true;
  debugMsg("trex:archive",
	   '['<<cur<<"] ============= START archiving ============");

  BOOST_SCOPE_EXIT((&auto_prop)(&m_cstr_engine)(&cur)(&m_archiving)) {
    debugMsg("trex:archive",
             '['<<cur<<"] ============= END archiving ============");
    m_cstr_engine->setAutoPropagation(auto_prop);
    m_archiving = false;
  } BOOST_SCOPE_EXIT_END;
#ifdef TREX_ARCHIVE_Greedy
  EUROPA::DbClientId cli = plan_db()->getClient();
  size_t deleted = 0;
  m_updated_commit = false;

  debugMsg("trex:archive", "Checking for completed root tokens");
  m_iter = m_roots.begin();
  while( m_roots.end()!=m_iter ) {
    EUROPA::TokenId tok = *(m_iter++);
    if( !tok->isCommitted() &&
       details::active(tok)->end()->lastDomain().getUpperBound() <= date
       && m_committed.end()!=m_committed.find(tok) ) {
      debugMsg("trex:archive", "Terminating "<<tok->getPredicateName()
               <<'('<<tok->getKey()<<')');
      terminate(tok);
    }
  }

  debugMsg("trex:archive", "Evaluating "<<m_completed.size()
           <<" completed tokens.");
  m_iter = m_completed.begin();
  while( m_completed.end()!=m_iter ) {
    EUROPA::TokenId tok = *(m_iter++);
    if( !tok.isId() ) {
      debugMsg("trex:always", "WARNING: token reference "<<tok<<" is not valid.");
      m_completed.erase(tok);
      continue;
    }
    std::string type;
    if( is_action(tok) )
      type = "action";
    else
      type = "predicate";

    if( details::upperBound(details::active(tok)->end()) > cur ) {
      debugMsg("trex:always", "WARNING: "<<type<<" "
	       <<tok->getPredicateName()<<'('<<tok->getKey()
	       <<") is no longer completed (end=["
	       <<details::lowerBound(details::active(tok)->end())<<", "
	       <<details::upperBound(details::active(tok)->end())<<"])");
      m_completed.erase(tok);
      continue;
    } else {
      EUROPA::TokenId master = tok->master();

      if( master.isNoId() ) {
        if( tok->isInactive() ) {
          debugMsg("trex:archive", "Discard ROOT inactive completed "<<type<<" "
                   <<tok->getPredicateName()<<'('
                   <<tok->getKey()<<')');
          discard(tok);
          //tok->discard();
	  delete static_cast<Token*>(tok);
          ++deleted;
        } else if( tok->isMerged() ) {
          EUROPA::TokenId active = tok->getActiveToken();
          if( m_committed.find(active)!=m_committed.end() ) {
            debugMsg("trex:archive", "Discard ROOT merged completed "<<type<<" "
                     <<tok->getPredicateName()<<'('
                     <<tok->getKey()<<')');
            replace(tok);
            discard(tok);
	    delete static_cast<Token*>(tok);
            ++deleted;
          } else if( m_completed.find(active)==m_completed.end() ) {
            details::restrict_base(tok, tok->start(),
                                   tok->start()->lastDomain());
            details::restrict_base(tok, tok->end(), tok->end()->lastDomain());
            terminate(active);
          }
        } else if( tok->isActive() ) {
          debugMsg("trex:archive", "Commit ROOT active completed "<<type<<" "
                   <<tok->getPredicateName()<<'('
                   <<tok->getKey()<<')');
          m_committed.insert(tok);
          m_completed.erase(tok);
          m_updated_commit = true;
        }
      } else if( m_committed.end()!=m_committed.find(master) ) {
        if( tok->isMerged() ) {
          EUROPA::TokenId active = tok->getActiveToken();
          if( m_committed.find(active)!=m_committed.end() ) {
            debugMsg("trex:archive", "Cancel merged completed "<<type<<" "
                     <<tok->getPredicateName()<<'('
                     <<tok->getKey()<<')');
            replace(tok);
          } else if( m_completed.find(active)==m_completed.end() ) {
            debugMsg("trex:archive", "Marking active ("<<master->getKey()
                     <<") counterpart of "<<type<<" "
                     <<tok->getPredicateName()<<'('
                     <<tok->getKey()<<") as completed");
            terminate(active);
          }
        } else if( tok->isActive() ) {
          debugMsg("trex:archive", "Making active "<<type<<" "
                   <<tok->getPredicateName()<<'('
                   <<tok->getKey()<<") committed");
          m_committed.insert(tok);
          m_completed.erase(tok);
          m_updated_commit = true;
        } else {
          debugMsg("trex:archive", type<<" "<<tok->getPredicateName()
                   <<'('<<tok->getKey()<<") is completed but neither active nor merged");
        }
      } else if( details::upperBound(master->end())<=cur ) {
        debugMsg("trex:archive", type<<" "<<tok->getPredicateName()
                 <<'('<<tok->getKey()<<") marked as completed as its end="
                 <<master->end()->lastDomain()<<"<="<<cur);
        terminate(master);
      }
    }
  }

  debugMsg("trex:archive", "Evaluate "<<m_committed.size()
           <<" committed tokens");
  m_iter = m_committed.begin();
  while( m_committed.end()!=m_iter ) {
    EUROPA::TokenId tok = *(m_iter++);
    if( tok->isActive() ) {
      bool can_delete = true;
      EUROPA::TokenSet tmp = tok->getMergedTokens();
      // Check that all masters are committed
      for(EUROPA::TokenSet::const_iterator i=tmp.begin();
          tmp.end()!=i; ++i) {
        EUROPA::TokenId master = (*i)->master();
        if( master.isId() ) {
          if( m_committed.find(master)==m_committed.end() ) {
            if( can_delete ) {
              debugMsg("trex:archive", "Cannot delete "
                       <<tok->getPredicateName()<<'('
                       <<tok->getKey()
                       <<"): one of its master is not yet committed:\n\t-"
                       <<(is_action(master)?"action":"predicate")
                       <<" "<<master->getPredicateName()<<'('<<master->getKey()<<")");
              can_delete = false;
            }
            if( details::upperBound(master->end())<=date ) {
              debugMsg("trex:archive", "Adding "<<tok->getPredicateName()
                       <<'('<<tok->getKey()<<")'s master "<<(is_action(master)?"action":"predicate")
                       <<" "<<master->getPredicateName()<<'('<<master->getKey()<<") to completed list");
              terminate(master);
            }
          }
        }
      }
      // Check its slaves
      tmp = tok->slaves();

      for(EUROPA::TokenSet::const_iterator i=tmp.begin();
          tmp.end()!=i; ++i) {
        EUROPA::TokenId i_active = details::active(*i);

        if( details::upperBound(i_active->end())<=date ) {
          if( !(*i)->isInactive() ) {
            EUROPA::TokenSet::const_iterator j = m_committed.find(i_active);

            if(m_committed.end()==j ) {
              if( can_delete ) {
                debugMsg("trex:archive", "Cannot delete "<<(is_action(tok)?"action":"predicate")<<" "
                         <<tok->getPredicateName()<<'('
                         <<tok->getKey()
                         <<"): one of its slaves is part of the plan:\n\t- "
                         <<(is_action(*i)?"action ":"predicate ")<<(*i)->getPredicateName()
                         <<'('<<(*i)->getKey()<<") |"<<details::active(*i)->start()->lastDomain()<<", "
                         <<details::active(*i)->end()->lastDomain()<<"|.");
                can_delete = false;
              }
              if( m_completed.end()!=m_completed.find(*i) ) {
                debugMsg("trex:archive", "Adding slave "<<(is_action(*i)?"action ":"predicate ")
                         <<(*i)->getPredicateName()
                         <<'('<<(*i)->getKey()<<") to completed tokens.");
                terminate(*i);
              }
            } else {
              if( (*i)->isMerged() ) {
                debugMsg("trex:archive", "Cancel merged completed slave "<<(is_action(*i)?"action ":"predicate ")
                         <<(*i)->getPredicateName()<<'('
                         <<(*i)->getKey()<<')');
                replace(*i);
              } else {
                // Tricky situation where I need to try to cancl thistoken without killing (*i)
              }
            }
          }

        } else if( details::upperBound(i_active->start())<date ) {
          EUROPA::ObjectDomain const &dom = (*i)->getObject()->lastDomain();
          EUROPA::ObjectId obj = dom.makeObjectList().front();
          state_iterator pos = m_agent_timelines.find(obj->getKey());
          if( m_agent_timelines.end()==pos ||
              !((*pos)->external() && 0==look_ahead(obj)) ) {
            if( can_delete ) {
              debugMsg("trex:archive", "Cannot delete "<<(is_action(tok)?"action":"predicate")<<" "
                       <<tok->getPredicateName()<<'('
                       <<tok->getKey()
                       <<"): one of its slaves is not finished yet:\n\t- "
                       <<(is_action(*i)?"action ":"predicate ")<<(*i)->getPredicateName()
                       <<'('<<(*i)->getKey()<<')');
              can_delete = false;
            }
          }
        } else {
          if( can_delete ) {
            debugMsg("trex:archive", "Cannot delete "<<(is_action(tok)?"action":"predicate")<<" "
                     <<tok->getPredicateName()<<'('
                     <<tok->getKey()
                     <<"): one of its slaves is not yet started ("<<date<<"):\n\t- "
                     <<(is_action(*i)?"action ":"predicate ")<<(*i)->getPredicateName()
                     <<'('<<(*i)->getKey()<<':'<<i_active->getKey()<<")["<<(*i)->getState()->lastDomain().toString()<<"]"
 		     <<"\n\t    start=="<<i_active->start()->toString()<<"<="<<details::upperBound(i_active->start())
 		     <<"\n\t    end=="<<i_active->end()->toString()<<"<="<<details::upperBound(i_active->end()));
            can_delete = false;
          }
        }
      }
      if( can_delete ) {
        debugMsg("trex:archive", "Destroy "<<(is_action(tok)?"action":"predicate")<<" "
                 <<tok->getPredicateName()<<'('<<tok->getKey()
                 <<") as all its slaves are now inactives and in the past.");
        discard(tok);
	EUROPA::IntervalIntDomain st = tok->start()->lastDomain(), en = tok->end()->lastDomain();

	details::restrict_bases(tok);
	if( tok->isActive() ) {
	  // Need to propagate the values to all the merged tokens
	  // NOTE: this is not very acceptable as I may lose this information
	  //       should the merged tokens been removed ... ideally I should
	  //       activate another one instead and/or make sured that the one
	  //       to be activated is marked as potential deletion
	  //       Still it worked fine in the case of lsts PLanner to forget
	  //       the past and something like this is obviously need to ensure
	  //       proper archiving
	  EUROPA::TokenSet merged = tok->getMergedTokens();
	  cli->cancel(tok);
	  for(EUROPA::TokenSet::iterator i=merged.begin(); merged.end()!=i; ++i)
	    details::restrict_bases(*i, tok);
	} else
	  cli->cancel(tok);
        if( tok->master().isNoId() )
          delete static_cast<Token*>(tok);
          //tok->discard();
        ++deleted;
      }
    } else {
      debugMsg("trex:archive", (is_action(tok)?"action":"predicate")<<" "<<tok->getPredicateName()
               <<'('<<tok->getKey()<<") is not active.\n\tSet it complete.");
      m_committed.erase(tok);
      terminate(tok);
    }
  }

  // Needf
  debugMsg("trex:archive", "Archived "<<deleted<<" tokens [updated="<<m_updated_commit<<"].");
  constraint_engine()->propagate();

  // plan_db()->archive(now()-1);

#elif defined(TREX_ARCHIVE_EuropaDefault)

  // Just rely on the europa archival : safe but inefficient
  plan_db()->archive(date-1);
#endif
}

EUROPA::TokenId Assembly::create_token(EUROPA::ObjectId const &obj,
                                       std::string const &name,
                                       bool fact) {
  EUROPA::DbClientId cli = plan_db()->getClient();
  bool rejectable = !fact;

  if( !schema()->isPredicate(name.c_str()) )
    throw EuropaException("Unknown predicate \""+name+"\" for object "
                          +obj->getName());
  EUROPA::TokenId tok = cli->createToken(name.c_str(), NULL, rejectable, fact);

  if( !tok.isId() )
    throw EuropaException("Failed to create token "+name);

  // Restrict token domain to obj
  EUROPA::ConstrainedVariableId obj_var = tok->getObject();
  obj_var->specify(obj->getKey());

  //std::cerr<<"Created "<<tok->getPredicateName()<<'('<<tok->getKey()<<')'<<std::endl;
  return tok;
}

EUROPA::TokenId Assembly::new_obs(EUROPA::ObjectId const &obj,
                                  std::string &pred,
                                  bool &undefined) {
  if( !external(obj) )
    throw EuropaException(obj->toString()+"is not an External timeline");
  state_iterator handler = m_agent_timelines.find(obj->getKey());

  undefined = false;

  if( !have_predicate(obj, pred) ) {
    std::string prev = pred;
    pred = UNDEFINED_PRED;
    if( !have_predicate(obj, pred) )
      throw EuropaException("Unable to create token "+prev+" or "+UNDEFINED_PRED+
                            " for timeline "+obj->toString());
    undefined = true;
  }
  return (*handler)->new_obs(pred, false);
}

void Assembly::recalled(EUROPA::TokenId const &tok) {
  if( tok.isId() ) {
    // Very aggressive way to handle this
    debugMsg("trex:recall", "Goal "<<tok->toString()<<" recalled.");

    if( !tok->isInactive() ) {
      debugMsg("trex:recall", "Cancelling "<<tok->toString());
      plan_db()->getClient()->cancel(tok);
    }
    debugMsg("trex:recall", "Destroying "<<tok->toString());
    plan_db()->getClient()->deleteToken(tok);
  } else
    debugMsg("trex:always",
             "["<<now()<<"] Attempted to recall an invalid token.");
}

// observers

bool Assembly::with_plan(EUROPA::ObjectId const &obj) const {
  if( is_agent_timeline(obj) ) {
    EUROPA::ConstrainedVariableId var = attribute(obj, PLAN_ATTR);
    if( var.isId() && var->lastDomain().isSingleton() )
      return var->lastDomain().getSingletonValue()!=0.0;
  }
  return false;
}

bool Assembly::is_action(EUROPA::TokenId const &tok) const {
#ifdef EUROPA_HAVE_EFFECT
  // std::cerr<<"EVAL is_action("<<tok->getPredicateName()<<"("<<tok->getKey()<<"))"<<std::endl;
  return tok->hasAttributes(EUROPA::PSTokenType::ACTION);
#else
  return false;
#endif
}

bool Assembly::is_predicate(EUROPA::TokenId const &tok) const {
#ifdef EUROPA_HAVE_EFFECT
  return tok->hasAttributes(EUROPA::PSTokenType::PREDICATE);
#else
  return true;
#endif
}

bool Assembly::is_condition(EUROPA::TokenId const &tok) const {
#ifdef EUROPA_HAVE_EFFECT
  return tok->hasAttributes(EUROPA::PSTokenType::CONDITION);
#else
  return false;
#endif
}

bool Assembly::is_effect(EUROPA::TokenId const &tok) const {
#ifdef EUROPA_HAVE_EFFECT
  return tok->hasAttributes(EUROPA::PSTokenType::EFFECT);
#else
  return false;
#endif
}

bool Assembly::is_goal(EUROPA::TokenId const &tok) const {
  EUROPA::StateDomain const &state = tok->getState()->baseDomain();
  return state.isMember(EUROPA::Token::REJECTED) && internal(tok);
}

bool Assembly::internal(EUROPA::TokenId const &tok) const {
  EUROPA::ObjectDomain const &dom = tok->getObject()->lastDomain();
  std::list<EUROPA::ObjectId> objs = dom.makeObjectList();

  for(std::list<EUROPA::ObjectId>::const_iterator o=objs.begin();
      objs.end()!=o; ++o)
    if( !internal(*o) )
      return false;
  return true;
}

bool Assembly::internal(EUROPA::ObjectId const &obj) const {
  return is_agent_timeline(obj) && is_internal(obj->getName());
}

bool Assembly::external(EUROPA::TokenId const &tok) const {
  EUROPA::ObjectDomain const &dom = tok->getObject()->lastDomain();
  std::list<EUROPA::ObjectId> objs = dom.makeObjectList();

  for(std::list<EUROPA::ObjectId>::const_iterator o=objs.begin();
      objs.end()!=o; ++o)
    if( !external(*o) )
      return false;
  return true;
}

bool Assembly::external(EUROPA::ObjectId const &obj) const {
  return is_agent_timeline(obj) && is_external(obj->getName());
}

size_t Assembly::look_ahead(EUROPA::ObjectId const &obj) {
  if( !is_agent_timeline(obj) )
    return 0;
  return look_ahead(obj->getName());
}

bool Assembly::ignored(EUROPA::TokenId const &tok) const {
  EUROPA::ObjectDomain const &dom = tok->getObject()->lastDomain();
  std::list<EUROPA::ObjectId> objs = dom.makeObjectList();

  for(std::list<EUROPA::ObjectId>::const_iterator o=objs.begin();
      objs.end()!=o; ++o)
    if( !ignored(*o) )
      return false;
  return !objs.empty(); // we do not ignore tokens with no possible object
}

bool Assembly::is_agent_timeline(EUROPA::TokenId const &token) const {
  return schema()->isA(token->getBaseObjectType(), TREX_TIMELINE);
}

bool Assembly::have_predicate(EUROPA::ObjectId const &obj,
                              std::string &name) const {
  EUROPA::LabelStr obj_type = obj->getType();

  if( !schema()->isPredicate(name.c_str()) ) {
    std::string long_name = obj_type.toString()+"."+name;
    if( schema()->isPredicate(long_name.c_str()) )
      name = long_name;
    else
      return false;
  }
  return schema()->canBeAssigned(obj_type, name.c_str());
}

EUROPA::ConstrainedVariableId Assembly::attribute(EUROPA::ObjectId const &obj,
                                                  std::string const &attr) const {
  std::string full_name = obj->getName()+"."+attr;
  EUROPA::ConstrainedVariableId var = obj->getVariable(full_name);
  if( var.isNoId() )
    throw EuropaException("Variable \""+full_name+"\" does not exist.");
  return var;
}

std::ostream &Assembly::print_domain(std::ostream &out,
                            EUROPA::ConstrainedVariableId const &var) const {
  EUROPA::Domain const &dom = var->lastDomain();

  if( dom.isSingleton() ) {
    EUROPA::edouble val = dom.getSingletonValue();

    if( m_schema->isObjectType(dom.getTypeName()) )
      return out<<dom.toString();
    else {
      EUROPA::DataTypeId type = var->getDataType();
      return out<<type->toString(val);
    }
  } else if( dom.isInterval() ) {
    return out<<dom;
  } else {
    return out<<dom.toString();
  }
}

void Assembly::print_plan(std::ostream &out, bool expanded) const {
  EUROPA::TokenSet const tokens = plan_db()->getTokens();
  is_not_merged filter(false);
  std::set<EUROPA::eint> instants;

  out<<"digraph plan_"<<now()<<" {\n"
     <<"  node[shape=\"box\"];\n\n";
  if( !expanded )
    out<<"  graph[rankdir=\"LR\"];\n";
  boost::filter_iterator<is_not_merged, EUROPA::TokenSet::const_iterator>
    it(filter, tokens.begin(), tokens.end()),
    endi(filter, tokens.end(), tokens.end());
  // Iterate through plan tokens
  for( ; endi!=it; ++it) {
    std::string name;
    EUROPA::ObjectVarId obj = (*it)->getObject();
    if( obj->getLastDomain().isSingleton() ) {
      std::list<EUROPA::ObjectId> objs = obj->getLastDomain().makeObjectList();
      std::ostringstream oss;
      oss<<objs.front()->getName()<<'.'<<(*it)->getUnqualifiedPredicateName();
      name = oss.str();
    } else
      name = (*it)->getPredicateName();

    EUROPA::eint key = (*it)->getKey();
    // display the token as a node
    out<<"  t"<<key<<"[label=\""<<name
       <<'('<<key<<") {\\n";
    if( (*it)->isIncomplete() )
      out<<"incomplete\\n";
    out<<"nref="<<(*it)->refCount()<<"\\n";
    if( !(*it)->isInactive() )
      print_domain(out<<"  STATE: "<<std::flush, (*it)->getState())
        <<"\\n"<<std::flush;
    else
      out<<"  STATE: INACTIVE\\n"<<std::flush;
#ifdef EUROPA_HAVE_EFFECT
    out<<"type: ";
    if( is_action(*it) )
      out<<"ACTION";
    else if( is_predicate(*it) )
      out<<"PREDICATE";
    else
      out<<"???";
    out<<"\\n"<<std::flush;
#endif // EUROPA_HAVE_EFFECT
    print_domain(out<<"  start="<<std::flush, (*it)->start());
    print_domain(out<<"\\n  duration="<<std::flush, (*it)->duration());
    print_domain(out<<"\\n  end="<<std::flush, (*it)->end())<<"\\n"<<std::flush;

    std::vector<EUROPA::ConstrainedVariableId> const &attrs = (*it)->parameters();

    for(std::vector<EUROPA::ConstrainedVariableId>::const_iterator a=attrs.begin();
        attrs.end()!=a; ++a)
      print_domain(out<<"  "<<(*a)->getName()<<'='<<std::flush, *a)<<"\\n";

    if( (*it)->isActive() ) {
      EUROPA::TokenSet const &merged = (*it)->getMergedTokens();
      if( !merged.empty() ) {
        out<<"merged={";
        EUROPA::TokenSet::const_iterator m = merged.begin();
        out<<(*m)->getKey()<<'['<<(*m)->refCount()<<']';
        for(++m; merged.end()!=m; ++m)
          out<<", "<<(*m)->getKey()<<'['<<(*m)->refCount()<<']';
        out<<"}\\n";
      }
    }
    out<<"}\"";
    if( ignored(*it) )
      out<<" color=grey"; // ignored tokens are greyed
    else if( filter.is_fact(*it) )
      out<<" color=red"; // fact tokens are red
    else if(m_goals.find(*it)!=m_goals.end())
      out<<" color=blue";
    if( (*it)->isCommitted() ||
        m_committed.find(*it)!=m_committed.end() )
      out<<" fontcolor=red";
    std::ostringstream styles;
    bool comma = false;

    if( filter.is_goal(*it) ) {
      styles<<"rounded"; // goal have rounded corner
      comma=true;
    }
    if( m_completed.end()!=m_completed.find(*it) ) {
      if( comma )
        styles.put(',');
      else
        comma = true;
      styles<<"dashed";
    }
#ifdef EUROPA_HAVE_EFFECT
    if( is_action(*it) ) {
      if( comma )
        styles.put(',');
      else
        comma = true;
      styles<<"filled"; // actions are filled
    }
#endif // EUROPA_HAVE_EFFECT
    if( comma )
      out<<" style=\""<<styles.str()<<"\" "; // display style modifiers
    out<<"];"<<std::endl;
    if( (*it)->isMerged() ) {
      EUROPA::eint active = (*it)->getActiveToken()->getKey();
      // connect the merged token to its active counterpart
      out<<"  t"<<key<<"->t"<<active<<"[color=grey];\n";
    }
    if( expanded ) {
      EUROPA::TokenSet toks;
      toks.insert(*it);
      filter.merged(*it, toks);
      // display the relation to the master token(s)
      for(EUROPA::TokenSet::const_iterator t=toks.begin(); toks.end()!=t; ++t) {
        EUROPA::TokenId master = (*t)->master();

        if( master.isId() ) {
          out<<"  t"<<master->getKey()<<"->t"<<key
             <<"[label=\""<<(*t)->getRelation();
#ifdef EUROPA_HAVE_EFFECT
          if( is_effect(*t) )
            out<<"\\n(effect)";
          if( is_condition(*t) )
            out<<"\\n(condition)";
#endif // EUROPA_HAVE_EFFECT
          out<<"\"];\n";
          // if( (*it)!=(*t) )
          //   out<<" color=grey";
        }
      }
    } else {
      EUROPA::eint lb, ub;
      lb = (*it)->start()->lastDomain().getLowerBound();
      // ub = (*it)->start()->lastDomain().getUpperBound();

      if( lb>std::numeric_limits<EUROPA::eint>::minus_infinity() ) {
        if( instants.insert(lb).second )
          out<<"  \"i"<<lb<<"\"[shape=point, label=\""<<lb<<"\"];\n";
        out<<"  \"i"<<lb<<"\"->t"<<(*it)->getKey()<<"[color=grey style=dashed weight=1000];\n";
      }
      // if( ub<std::numeric_limits<EUROPA::eint>::infinity() ) {
      //   if( instants.insert(ub).second )
      // 	out<<"  i"<<ub<<"[shape=point, label=\""<<ub<<"\"];\n";
      //   out<<"  t"<<(*it)->getKey()<<"->i"<<ub"[weight=10.0];\n";
      // }

      // lb = (*it)->start()->lastDomain().getLowerBound();
      ub = (*it)->end()->lastDomain().getUpperBound();

      // if( lb>std::numeric_limits<EUROPA::eint>::minus_infinity() ) {
      //   if( instants.insert(lb).second )
      // 	out<<"  i"<<lb<<"[shape=point, label=\""<<lb<<"\"];\n";
      //   out<<"  i"<<lb<<"->t"<<(*it)->getKey()<<"[weight=10.0];\n";
      // }
      if( ub<std::numeric_limits<EUROPA::eint>::infinity() ) {
        if( instants.insert(ub).second )
          out<<"  \"i"<<ub<<"\"[shape=point, label=\""<<ub<<"\"];\n";
        out<<"  t"<<(*it)->getKey()<<"->\"i"<<ub<<"\"[color=grey style=dashed weight=1000];\n";
      }
    }
  }
  if( !instants.empty() ) {
    std::set<EUROPA::eint>::const_iterator i=instants.begin();
    EUROPA::eint pred = *(i++);
    EUROPA::eint max = 100+(*instants.rbegin())-pred;
    out<<"  subgraph instants_cluster {\n"
       <<"   node[shape=point];\n"
       <<"   edge[color=none];\n"
       <<"   \"i"<<pred<<"\"[label=\""<<pred<<"\"];\n";

    for(;instants.end()!=i; ++i) {
      out<<"   \"i"<<pred<<"\"->\"i"<<(*i)<<"\"[weight=\""
         <<(max-((*i)-pred))<<"\"];\n";
      pred = *i;
      out<<"   \"i"<<pred<<"\"[label=\""<<pred<<"\"];\n";
    }
    out<<"  }\n";
  }
  out<<"}"<<std::endl;
}

void Assembly::getFuturePlan()
{
  internal_iterator it = begin_internal(), end = end_internal();
  for(; it!=end; ++it)
    {
      EUROPA::TimelineId timeline((*it)->timeline());
      const std::list<EUROPA::TokenId>& tokens = timeline->getTokenSequence();
      for(std::list<EUROPA::TokenId>::const_iterator token = tokens.begin();
          token!=tokens.end(); ++token)
        {
          if((*token)->end()->lastDomain().getLowerBound()>now()+1)
            {
              plan_dispatch(timeline,*token);
            }
        }
    }
}

void Assembly::backtracking(EUROPA::SOLVERS::DecisionPointId &dp) {
  debugMsg("trex:always", "["<<now()<<"] Last decision : "<<m_synchronizer->getLastExecutedDecision());
}

void Assembly::print_context(std::ostream &out, EUROPA::ConstrainedVariableId const &v) const {
  // EUROPA::TokenId tok = details::parent_token(v);
  details::var_print(out<<"Local context for ", v)<<":\n";
  // out<<"  - base domain: "<<v->baseDomain().toString()
  //    <<"\n  - last domain: "<<v->lastDomain().toString()
  //    <<"\n  - europa violation explanation: "<<v->getViolationExpl()<<'\n';
  // EUROPA::ConstraintSet constraints;
  // v->constraints(constraints);
  // if( !constraints.empty() ) {
  //   out<<"  - related constraints:\n";
  //   for(EUROPA::ConstraintSet::const_iterator c=constraints.begin(); constraints.end()!=c; ++c) {
  //     EUROPA::ConstraintId cstr = *c;
  //     std::vector<EUROPA::ConstrainedVariableId> const &scope = cstr->getScope();
  //     size_t i, end_i = scope.size();

  //     out<<"\t+ "<<cstr->getName()<<'(';
  //     for(i=0; i<end_i; ++i) {
  //       if( i>0 )
  //         out<<", ";
  //       details::var_print(out, scope[i]);
  //       if( scope[i]!=v )
  //         out<<"="<<scope[i]->lastDomain().toString();
  //     }
  //     out<<")\n";
  //   }
  // }
}

/*
 * class TREX::europa::Assembly::ce_listener
 */

Assembly::ce_listener::ce_listener(Assembly &owner)
  :EUROPA::ConstraintEngineListener(owner.m_cstr_engine), m_owner(owner) {}

void Assembly::ce_listener::notifyPropagationPreempted() {
  if( m_owner.m_in_synchronization ) {
    debugMsg("trex:always", "["<<m_owner.now()<<"] search preempted during synchronization");

    if( !m_empty_vars.empty() ) {
      debugMsg("trex:always", "======================================================================");
      debugMsg("trex:always", "["<<m_owner.now()<<"] "<<m_empty_vars.size()<<" variables are empty:");
      for(EUROPA::ConstrainedVariableSet::const_iterator v=m_empty_vars.begin(); m_empty_vars.end()!=v; ++v) {
        std::ostringstream oss;
        m_owner.print_context(oss, *v);
        debugMsg("trex:always", oss.str()<<"\n");
      }
      debugMsg("trex:always", "======================================================================");
    }
  }
}

/*
 * class TREX::europa::Assembly::synchronization_listener
 */

void Assembly::synchronization_listener::notifyCreated(EUROPA::SOLVERS::DecisionPointId& dp) {
  debugMsg("trex:synch:search", "New decision point ["<<dp->getKey()<<"]");
  m_progress = true;
}

void Assembly::synchronization_listener::notifyDeleted(EUROPA::SOLVERS::DecisionPointId& dp) {
  debugMsg("trex:synch:search", "Delete decision point ["<<dp->getKey()<<"](backtrack)");
}

void Assembly::synchronization_listener::notifyStepSucceeded(EUROPA::SOLVERS::DecisionPointId& dp) {
  debugMsg("trex:synch:search", "Executed decision point ["<<dp->getKey()<<"]: "<<dp->toString());
  m_progress = true;
}

void Assembly::synchronization_listener::notifyStepFailed(EUROPA::SOLVERS::DecisionPointId &dp) {
  // This callback is not active yet but is the one I want
  // ... should be available on europa 2.7 (or any version number after 2.6)
  debugMsg("trex:synch:search", "Failed decision point ["<<dp->getKey()<<"]: "<<dp->toString());
}

void Assembly::synchronization_listener::notifyUndone(EUROPA::SOLVERS::DecisionPointId &dp) {
  debugMsg("trex:synch:search", "Undid decision point ["<<dp->getKey()<<"]");
}

void Assembly::synchronization_listener::notifyRetractSucceeded(EUROPA::SOLVERS::DecisionPointId& dp) {
  m_progress = true;
  debugMsg("trex:always", "["<<m_owner.now()<<"] Backtrack completed (depth="<<m_owner.synchronizer()->getDepth()<<")");
}

void Assembly::synchronization_listener::notifyRetractNotDone(EUROPA::SOLVERS::DecisionPointId& dp) {
  if( m_progress ) {
    m_progress = false;
    debugMsg("trex:always", "["<<m_owner.now()<<"] start to backtrack (depth="<<m_owner.synchronizer()->getDepth()<<")");
    m_owner.backtracking(dp);
  }
}

/*
 * class TREX::europa::Assembly::listener_proxy
 */

void Assembly::listener_proxy::notifyAdded(EUROPA::TokenId const &token) {
    // Adds goal when added to the plan
    thread_duration duration;
    thread_clock::time_point start = thread_clock::now();
    if(m_owner.is_goal(token)) {
      m_owner.m_goals.insert(token);
    }
    duration = thread_clock::now()-start;
    if(m_owner.time_values.find(m_owner.now())==m_owner.time_values.end())
        m_owner.time_values[m_owner.now()]=duration.count();
    else
        m_owner.time_values[m_owner.now()]+=duration.count();
    //std::cout<<"Added: "<<m_owner.now()<<": "<<m_owner.time_values[m_owner.now()]<<std::endl;

    EUROPA::TokenId master = token->master();
    if( master.isNoId() ) {
      m_owner.m_roots.insert(token);
      m_owner.m_updated_commit = true;
    // token->incRefCount();
    }
}

void Assembly::listener_proxy::notifyRemoved(EUROPA::TokenId const &token) {
  // Removes goal when removed from plan
  thread_duration duration;
  thread_clock::time_point start = thread_clock::now();
  m_owner.m_goals.erase(token);
  duration = thread_clock::now()-start;
    if(m_owner.time_values.find(m_owner.now())==m_owner.time_values.end())
        m_owner.time_values[m_owner.now()]=duration.count();
    else
        m_owner.time_values[m_owner.now()]+=duration.count();
  //std::cout<<"Removed: "<<m_owner.now()<<": "<<m_owner.time_values[m_owner.now()]<<std::endl;

  m_owner.erase(m_owner.m_roots, token);
  m_owner.erase(m_owner.m_completed, token);
  m_owner.erase(m_owner.m_committed, token);

  if( m_owner.is_agent_timeline(token) ) {
    if( token->isFact() ) {
      // Not very efficient bu  it should do for now ...
      for (Assembly::state_iterator i=m_owner.m_agent_timelines.begin();
           m_owner.m_agent_timelines.end()!=i; ++i)
        (*i)->erased(token);
    }
    m_owner.discard(token);
  }
}

void Assembly::listener_proxy::notifyActivated(EUROPA::TokenId const &token)
{
    thread_duration duration;
    thread_clock::time_point start = thread_clock::now();

    if(m_owner.is_goal(token))
    {
        EUROPA::TokenSet tokens;
        tokens.insert(token);
        // Searchs for and adds all subgoals
        m_owner.subgoalSearch(tokens);
    } else if(m_owner.conditionOfGoal(token)) {
        EUROPA::TokenSet tokens;
        tokens.insert(token);
        m_owner.subgoalSearch(tokens);
    }

    duration = thread_clock::now()-start;
    if(m_owner.time_values.find(m_owner.now())==m_owner.time_values.end())
        m_owner.time_values[m_owner.now()]=duration.count();
    else
        m_owner.time_values[m_owner.now()]+=duration.count();
    //std::cout<<"Activated: "<<m_owner.now()<<": "<<m_owner.time_values[m_owner.now()]<<std::endl;
}

void Assembly::listener_proxy::notifyDeactivated(EUROPA::TokenId const &token) {
  // Checks and erases the token if it was considered a goal
  thread_duration duration;
  thread_clock::time_point start = thread_clock::now();
  if(!m_owner.is_goal(token) && !m_owner.conditionOfGoal(token) && m_owner.is_subgoal(token))
  {
    EUROPA::TokenSet temp;
    temp.insert(token);
    m_owner.removeSubgoals(temp);
  }

  duration = thread_clock::now()-start;
    if(m_owner.time_values.find(m_owner.now())==m_owner.time_values.end())
        m_owner.time_values[m_owner.now()]=duration.count();
    else
        m_owner.time_values[m_owner.now()]+=duration.count();
  //std::cout<<"Deactived: "<<m_owner.now()<<": "<<m_owner.time_values[m_owner.now()]<<std::endl;

  if( m_owner.is_agent_timeline(token) ) {
    debugMsg("trex:token", "cancel "<<token->getPredicateName()
             <<'('<<token->getKey()<<')');
    if( !m_owner.m_archiving )
      m_owner.cancel(token); // do not recall during archiving !!!!
  }
}

void Assembly::listener_proxy::notifyMerged(EUROPA::TokenId const &token) {
    thread_duration duration;
    thread_clock::time_point start = thread_clock::now();
    m_owner.m_masters[token] = token->getActiveToken();
    if(m_owner.is_goal(token) || m_owner.is_subgoal(token))
    {
        EUROPA::TokenSet tokens = token->getActiveToken()->getMergedTokens();
        tokens.insert(token->getActiveToken());
        // Searchs for and adds all subgoals
        m_owner.subgoalSearch(tokens);
    }
    // Check to find if the active token is in a goal, then it search for effect and conditions
    else if(m_owner.is_subgoal(token->getActiveToken()))
    {
        EUROPA::TokenSet tokens;
        tokens.insert(token);
        // Searchs for and adds all subgoals
        m_owner.subgoalSearch(tokens);
    }

    duration = thread_clock::now()-start;
    if(m_owner.time_values.find(m_owner.now())==m_owner.time_values.end())
        m_owner.time_values[m_owner.now()]=duration.count();
    else
        m_owner.time_values[m_owner.now()]+=duration.count();
    //std::cout<<"Merged: "<<m_owner.now()<<": "<<m_owner.time_values[m_owner.now()]<<std::endl;
}

void Assembly::listener_proxy::notifySplit(EUROPA::TokenId const &token) {
  // Checks and erases the token if it was considered a goal
  thread_duration duration;
  thread_clock::time_point start = thread_clock::now();
  if(m_owner.is_subgoal(token) && m_owner.conditionOfGoal(token))
  {
      EUROPA::TokenSet temp = m_owner.m_masters[token]->getMergedTokens();
      temp.insert(m_owner.m_masters[token]);
      EUROPA::TokenSet::iterator it;
      bool remove = true;
      for(it=temp.begin();  it!=temp.end(); ++it)
      {
          if(m_owner.is_goal(*it) || m_owner.conditionOfGoal(*it))
          {
              remove = false;
          }
      }
      if(remove)
      {
          m_owner.removeSubgoals(temp);
      }
  } else {
     EUROPA::TokenSet temp;
     temp.insert(token);
     m_owner.removeSubgoals(temp);
  }
  m_owner.m_masters.erase(token);

  duration = thread_clock::now()-start;
    if(m_owner.time_values.find(m_owner.now())==m_owner.time_values.end())
        m_owner.time_values[m_owner.now()]=duration.count();
    else
        m_owner.time_values[m_owner.now()]+=duration.count();
  //std::cout<<"Split: "<<m_owner.now()<<": "<<m_owner.time_values[m_owner.now()]<<std::endl;

  // EUROPA::TokenId master = token->master();
  // if( master.isId() )
  //   token->decRefCount();
}

void Assembly::listener_proxy::notifyRejected(EUROPA::TokenId const &token) {
  debugMsg("trex:always", "["<<m_owner.now()<<"] Token "
           <<token->getPredicateName()<<'('
           <<token->getKey()<<") is rejected.");
  m_owner.rejected(token);
}

void Assembly::listener_proxy::notifyReinstated(EUROPA::TokenId const &token) {
  debugMsg("trex:always", "["<<m_owner.now()<<"] Token "
           <<token->getPredicateName()<<'('
           <<token->getKey()<<") is no longer rejected.");
}

void Assembly::listener_proxy::notifyCommitted(EUROPA::TokenId const &token) {
  m_owner.erase(m_owner.m_completed, token);
  m_owner.m_committed.insert(token);
}

void Assembly::listener_proxy::notifyTerminated(EUROPA::TokenId const &token) {

}

/**
    Listener_proxy helper functions
*/
bool Assembly::actionEffect(const EUROPA::TokenId& token) {
  EUROPA::TokenId master = token->master();
  if(master.isId()) {
    if(is_action(master) && is_effect(token))
      return true;
  }
  return false;
}

bool Assembly::conditionOfGoal(const EUROPA::TokenId& token)
{
    if(token->master().isId())
        if(is_action(token->master()) && is_condition(token))
        {
            EUROPA::TokenSet slaves = token->master()->slaves();
            EUROPA::TokenSet::iterator it = slaves.begin(), end = slaves.end();
            for(; it!=end; it++)
            {
                if(is_effect(*it) && is_subgoal(*it))
                {
                    return true;
                }
            }
        }
    return false;
}

EUROPA::TokenSet Assembly::conditions(const EUROPA::TokenId& token)
{
    EUROPA::TokenSet slaves = token->slaves(), conditions;
    for(EUROPA::TokenSet::iterator it = slaves.begin(), end = slaves.end();
        it!=end; it++)
    {
        if(is_condition((*it)))
            conditions.insert((*it));
    }
    EUROPA::TokenSet merged;
    for(EUROPA::TokenSet::iterator it = conditions.begin(), end = conditions.end();
        it!=end; it++)
    {
        if((*it)->isActive())
        {
            EUROPA::TokenSet temp = (*it)->getMergedTokens();
            merged.insert(temp.begin(), temp.end());
        } else {
            EUROPA::TokenId active = (*it)->getActiveToken();
            if(active.isId())
            {
                EUROPA::TokenSet temp = active->getMergedTokens();
                merged.insert(temp.begin(), temp.end());
                merged.insert(active);
            }
        }
    }
    conditions.insert(merged.begin(),merged.end());
    return conditions;
}

bool Assembly::is_subgoal(const EUROPA::TokenId& token)
{
    return m_goals.find(token)!=m_goals.end();
}

void Assembly::subgoalSearch(EUROPA::TokenSet& tokens)
{
    EUROPA::TokenSet::iterator it, condIt;
    m_goals.insert(tokens.begin(), tokens.end());
    while(!tokens.empty())
    {
        it = tokens.begin();
        if(actionEffect((*it)))
        {
            EUROPA::TokenSet conds = conditions((*it)->master());
            for(condIt=conds.begin(); condIt!=conds.end(); ++condIt)
            {
                if(m_goals.insert(*condIt).second==true)
                    tokens.insert(*condIt);
            }
        }
        tokens.erase(it);
    }
}

void Assembly::removeSubgoals(EUROPA::TokenSet tokens)
{
    EUROPA::TokenSet::iterator it;
    while(!tokens.empty())
    {
        it = tokens.begin();
        m_goals.erase(*it);
        if(actionEffect((*it)))
        {
            EUROPA::TokenSet conds = conditions((*it)->master());
            for(EUROPA::TokenSet::iterator cond=conds.begin(); cond!= conds.end(); ++cond)
            {
                if(m_goals.erase(*cond)>=1)
                    tokens.insert(*cond);
            }
        }
        tokens.erase(it);
    }
}

/*
  # ifdef EUROPA_HAVE_EFFECT
  #  warning "Greedy plan archiving is not efficient with action tokens."
  # endif // EUROPA_HAVE_EFFECT
  EUROPA::DbClientId cli = plan_db()->getClient();
  size_t deleted = 0;

  debugMsg("trex:archive",
  '['<<now()<<"] ============= START archiving ============");

  debugMsg("trex:archive", "Evaluating "<<m_completed.size()<<" completed tokens.");
  m_iter = m_completed.begin();
  while( m_completed.end()!=m_iter ) {
  EUROPA::TokenId tok = *(m_iter++);

  if( tok->canBeCommitted() ) {
  // details::restrict_bases(tok);
  // constraint_engine()->propagate();
  EUROPA::TokenId master = tok->master();

  if( master.isId() ) {
  if( master->isCommitted() ) {
  debugMsg("trex:archive",
  "Committing "<<tok->getPredicateName()
  <<'('<<tok->getKey()<<") as its master is committed.");
  tok->commit();
  } else if( master->isFact() &&
  master->start()->lastDomain().getUpperBound()<now() ) {
  debugMsg("trex:archive",
  "Committing "<<tok->getPredicateName()
  <<'('<<tok->getKey()<<") as its master is a past fact.");
  tok->commit();
  } else {
  debugMsg("trex:archive", "Cannot commit "
  <<tok->getPredicateName()
  <<'('<<tok->getKey()<<") as its master is neither a fact "
  <<"or committed.");
  }
  } else {
  debugMsg("trex:archive",
  "Committing "<<tok->getPredicateName()
  <<'('<<tok->getKey()<<") as it is a root token.");
  tok->commit();
  }
  } else if( tok->isInactive() ) {
  EUROPA::TokenId master = tok->master();
  if( master.isNoId() ) {
  debugMsg("trex:archive", "Discarding inactive orphan token "
  <<tok->getPredicateName()
  <<'('<<tok->getKey()<<").");
  discard(tok);
  tok->discard();
  // constraint_engine()->propagate();
  debugMsg("trex:archive", EUROPA::PlanDatabaseWriter::toString(plan_db()));

  } else if( master->end()->lastDomain().getUpperBound()<=now() ) {
  if( master->isCommitted() ) {
  debugMsg("trex:archive", "Ignoring inactive justified token "
  <<tok->getPredicateName()
  <<'('<<tok->getKey()<<").");
  m_completed.erase(tok);
  } else
  m_completed.insert(master);
  }
  } else {
  // token is merged
  EUROPA::TokenId active = tok->getActiveToken();
  EUROPA::TokenId master = tok->master();

  if( master.isId() ) {
  if( master->end()->lastDomain().getUpperBound()<=now() ) {
  if( !master->isCommitted() )
  m_completed.insert(master);
  }
  }
  if( master.isNoId() || master->isCommitted() ) {
  debugMsg("trex:archive", "Collapsing "
  <<tok->getPredicateName()<<'('<<tok->getKey()
  <<") with its active counterpart "<<active->getKey());
  details::restrict_bases(active, tok);
  // constraint_engine()->propagate();
  if( tok->isFact() )
  active->makeFact();
  if( active->canBeCommitted() )
  m_completed.insert(active);
  if( master.isNoId() ) {
  debugMsg("trex:archive", "Discarding the redundant token "
  <<tok->getPredicateName()
  <<'('<<tok->getKey()<<").");
  discard(tok);
  cli->cancel(tok);
  tok->discard();
  // constraint_engine()->propagate();
  debugMsg("trex:archive", EUROPA::PlanDatabaseWriter::toString(plan_db()));

  ++deleted;
  }
  } else {
  debugMsg("trex:archive", "Cannot commit "<<tok->getPredicateName()
  <<'('<<tok->getKey()<<") as its master "<<master->getPredicateName()
  <<'('<<master->getKey()<<") is not terminated yet.");
  }
  }
  }

  debugMsg("trex:archive", "Evaluating "<<m_committed.size()<<" committed tokens.");
  m_iter = m_committed.begin();

  while( m_committed.end()!=m_iter ) {
  EUROPA::TokenId tok = *(m_iter++);
  EUROPA::TokenSet slaves_t = tok->slaves();
  bool can_delete = true;

  for(EUROPA::TokenSet::const_iterator t=slaves_t.begin();
  slaves_t.end()!=t; ++t) {
  if( !(*t)->isCommitted() ) {
  if( (*t)->end()->lastDomain().getUpperBound()<=now() ) {
  if( (*t)->canBeCommitted() ) {
  debugMsg("trex:archive", "Committing slave "
  <<(*t)->getPredicateName()<<'('<<(*t)->getKey()
  <<") from master "<<tok->getPredicateName()<<'('
  <<tok->getKey()<<").");
  // details::restrict_bases(*t);
  // constraint_engine()->propagate();
  (*t)->commit();
  } else if( (*t)->isMerged() ) {
  EUROPA::TokenId active = (*t)->getActiveToken();
  if( active->canBeCommitted() ) {
  debugMsg("trex:archive", "Collapsing explained slave "
  <<(*t)->getPredicateName()<<'('
  <<(*t)->getKey()
  <<") with its active counterpart "<<active->getKey());
  //details::restrict_bases(active, *t);
  // constraint_engine()->propagate();
  active->commit();
  } else {
  debugMsg("trex:archive", "Collapsing explained slave "
  <<(*t)->getPredicateName()<<'('
  <<(*t)->getKey()
  <<") with its committed active counterpart "
  <<active->getKey());
  //details::restrict_bases(active, *t);
  // constraint_engine()->propagate();
  }
  } else if( !(*t)->isInactive() ) {
  debugMsg("trex:archive", "Cannot delete "<<
  tok->getPredicateName()<<'('<<tok->getKey()
  <<") as one of its slave is not active,merged or "
  <<"inactive ???");
  can_delete = false;
  }
  } else {
  bool protect = true;
  if( (*t)->isMerged() ) {
  EUROPA::TokenId active = (*t)->getActiveToken();

  if( active->start()->lastDomain().getUpperBound()<now() ) {
  EUROPA::ObjectDomain const &dom = active->getObject()->lastDomain();
  EUROPA::ObjectId obj = dom.makeObjectList().front();

  debugMsg("trex:archive", "Checking if object "<<obj->toString()
  <<" of slave "<<(*t)->getKey()<<" is only an Observe timeline.");

  state_iterator i = m_agent_timelines.find(obj->getKey());
  if( m_agent_timelines.end()!=i ) {
  protect = !((*i)->external() && 0==look_ahead(obj));
  }
  }
  }
  if( protect ) {
  debugMsg("trex:archive", "Cannot delete "<<
  tok->getPredicateName()<<'('<<tok->getKey()
  <<") as one of its slave ("<<(*t)->getKey()<<") is not completed");
  can_delete = false;
  }
  }
  }
  }

  EUROPA::TokenSet merged_t = tok->getMergedTokens();
  merged_t.insert(tok);

  for(EUROPA::TokenSet::const_iterator t=merged_t.begin();
  merged_t.end()!=t; ++t) {
  EUROPA::TokenId master = (*t)->master();
  bool restrict = false;
  if( master.isId() ) {
  if( master->end()->lastDomain().getUpperBound()<=now() ) {
  if( master->isCommitted() )
  restrict = true;
  else
  m_completed.insert(master);
  } else {
  debugMsg("trex:archive", "Cannot delete "<<
  tok->getPredicateName()<<'('<<tok->getKey()
  <<") as one of its masters is not completed");
  can_delete = false;
  }
  } else {
  restrict = true;
  }
  if( restrict )
  details::restrict_bases(tok, *t);
  }
  if( can_delete ) {
  debugMsg("trex:archive", "Archiving "<<
  tok->getPredicateName()<<'('<<tok->getKey()
  <<") all its slaves and masters are committed");

  discard(tok);
  EUROPA::TokenSet slaves = tok->slaves();
  for(EUROPA::TokenSet::iterator i=slaves.begin(); slaves.end()!=i; ++i)
  if( (*i)->isMerged() ) {
  // details::restrict_attributes((*i)->getActiveToken(), *i);
  // constraint_engine()->propagate();
  cli->cancel(*i);
  }
  cli->cancel(tok);
  // constraint_engine()->propagate();
  tok->discard();
  debugMsg("trex:archive", EUROPA::PlanDatabaseWriter::toString(plan_db()));
  ++deleted;
  }
  }

  debugMsg("trex:archive", "Archived "<<deleted<<" token(s)");
  debugMsg("trex:archive",
  '['<<now()<<"] ============= END archiving ============");

*/

ext: cc


text:
#ifndef _MD5_JOIN_HPP
#define _MD5_JOIN_HPP

#include <boost/fusion/include/adapt_struct.hpp>

#include <string>

namespace md5 {
  template< typename vec3 > struct joint {

    std::string name;
    int parent_id;

    vec3 position;
    vec3 orientation;
  };
}

BOOST_FUSION_ADAPT_TPL_STRUCT
  (
    (vec3),
    (md5::joint)(vec3),
    (std::string, name)
    (int, parent_id)
    (vec3, position)
    (vec3, orientation)
  )

#endif /* end of include guard: _MD5_JOIN_HPP */

ext: hpp


text:
#include <boost/mpl/assert.hpp>
#include <nt2/sdk/meta/is_unspecified.hpp>
#include <nt2/sdk/simd/pack.hpp>

using nt2::meta::is_unspecified;
using nt2::simd::pack;

struct test {};

int main()
{
  BOOST_MPL_ASSERT_NOT(( is_unspecified<bool>        ));
  BOOST_MPL_ASSERT_NOT(( is_unspecified<int>         ));
  BOOST_MPL_ASSERT_NOT(( is_unspecified<int*>        ));
  BOOST_MPL_ASSERT_NOT(( is_unspecified< pack<int> > ));
  BOOST_MPL_ASSERT    (( is_unspecified<test>        ));
}


text:
/*
 * SocketBoost.hpp
 *
 *  Created on: Jul 3, 2010
 *      Author: quincy
 */

#ifndef SOCKETBOOST_HPP_
#define SOCKETBOOST_HPP_

#ifdef USE_BOOST_SOCKETS
#include <boost/asio.hpp>
#include <boost/timer.hpp>
#include <vector>
using std::vector;
#include "util/Line_Exception.hpp"
#include <sstream>
#include <time.h>

using namespace boost::asio::ip;
namespace quincySystemLibrary {

class SocketTCP;
/**
 * TCP socket class implementation from boost.
 */
class SocketTCPImp {
private:
	///underlying structure which is used for sending and receiving data.
	tcp::socket *sock;
	///underlying structure which is used to accept connection.
	tcp::acceptor *acceptor;
	boost::asio::io_service io_serve;
	tcp::endpoint endpoint;
public:

	SocketTCPImp();
	/// close the underlying socket.
	virtual ~SocketTCPImp();
	/// After method returns sock is ready to be read.
	void accept(SocketTCPImp *sock)throw(exception);
	void bind(uint32_t port)throw(exception);
	void close()throw(exception);
	string getHostName()throw(exception);
	void connect(string hostname, uint32_t port)throw(exception);
	void listen(uint32_t queueSize)throw(exception);
	/// Non-Blocking receives some data on socket.  Does not read more than len.
	/// does not null terminate buffer
	/// returns number of bytes actually read.
	/// throws exception when socket is closed by peer or when some error happens which closes the socket.
	uint32_t recvNonBlock(char *buffer, uint32_t len)throw(exception);
	/// Blocking receives exactly desired_len amount of data
	/// does not null terminate buffer
	/// throws exception when socket is closed by peer or when some error happens which closes the socket.
	void recvBlock(char *buffer, uint32_t desired_len)throw(exception);
	/// Blocking send.
	/// throws exception when socket is closed by peer or when some error happens which closes the socket.
	/// WARNING: if using POSIX implementation an error on this may signal a SIGPIPE which by default on POSIX systems terminate the process.
	void sendBlock(const char *buffer, uint32_t len)throw(exception);
	/// CAREFUL: this implementation has very bad performance.  Boost::asio does not support select().  This implementation spins on a method which checks if there are any new bytes available to be read.  After every failed check the thread goes to sleep for a millisecond.
	/// Blocks for [ms] until data is ready to be read on socket.
	/// returns true only if data is ready to be read on socket.
	bool select(uint32_t ms_timeout)throw(exception);
	/// CAREFUL: this implementation has very bad performance.  Boost::asio does not support select().  This implementation spins on a method which checks if there are any new bytes available to be read.  After every failed check the thread goes to sleep for a millisecond.
	/// Blocks for [ms] until data is ready to be read on at least one socket.
	/// returns list of sockets which are ready to be read.
	static vector<SocketTCP*> groupSelect(vector<SocketTCPImp*> &sockList, uint32_t ms_timeout);
};

}

#endif
#endif /* SOCKETBOOST_HPP_ */

max_stars_repo_name: quincycs/CollegeProjects

max_issues_repo_name: quincycs/CollegeProjects

max_forks_repo_name: quincycs/CollegeProjects