text:
// __BEGIN_LICENSE__
//  Copyright (c) 2009-2013, United States Government as represented by the
//  Administrator of the National Aeronautics and Space Administration. All
//  rights reserved.
//
//  The NGT platform is licensed under the Apache License, Version 2.0 (the
//  "License"); you may not use this file except in compliance with the
//  License. You may obtain a copy of the License at
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// __END_LICENSE__

#ifdef _MSC_VER
#pragma warning(disable:4244)
#pragma warning(disable:4267)
#pragma warning(disable:4996)
#endif

#include <iostream>
#include <fstream>
#include <string>

#include <boost/program_options.hpp>
namespace po = boost::program_options;

#include <vw/Cartography/GeoReference.h>
#include <vw/Image/ImageView.h>
#include <vw/Image/MaskViews.h>
#include <vw/Image/Statistics.h>
#include <vw/InterestPoint.h>
#include <vw/FileIO/DiskImageResource.h>
#include <vw/FileIO/DiskImageView.h>

// Not sure which of these we need but we get run-time errors otherwise...
#include <vw/InterestPoint.h>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
#include <vw/Stereo/PreFilter.h>
#include <vw/Stereo/CorrelationView.h>
#include <vw/Stereo/CostFunctions.h>
#include <vw/Stereo/DisparityMap.h>
#include <asp/Core/DemDisparity.h>
#include <asp/Core/LocalHomography.h>
#include <asp/Core/InterestPointMatching.h>

#include <asp/IsisIO/IsisCameraModel.h>

//#include <asp/Tools/stereo.h>
#include <stereo.h> // Using local copy

/// \file stereoIpFind.h Generates a list of pixel pairs from two input images.

struct Parameters
{
  std::string leftFilePath;
  std::string rightFilePath;
  std::string outputPath;

  double elevationGuess;
};

bool parseInputParams(int argc, char *argv[], Parameters &params)
{

  po::options_description general_options("Options");
  general_options.add_options()
    ("help,h",        "Display this help message")
    ("elevationGuess", po::value<double>(&params.elevationGuess)->default_value(0.0),
                       "Estimate of the elevation in the image");

  po::options_description positional("");
    positional.add_options()
      ("left",   po::value<std::string>(&params.leftFilePath),  "The left input file")
      ("right",  po::value<std::string>(&params.rightFilePath), "The right input file")
      ("output", po::value<std::string>(&params.outputPath),    "The output file");

    po::positional_options_description positional_desc;
    positional_desc.add("left",   1);
    positional_desc.add("right",  1);
    positional_desc.add("output", 1);

    std::string usage("[options] <left input path> <right input path> <output path>\n");
    po::variables_map vm;
    try {
      po::options_description all_options;
      all_options.add(general_options).add(positional);

      po::store( po::command_line_parser( argc, argv ).options(all_options).positional(positional_desc).style( po::command_line_style::unix_style ).run(), vm );

      po::notify( vm );
    } catch (po::error const& e) {
      vw::vw_throw( vw::ArgumentErr() << "Error parsing input:\n"
                    << e.what() << "\n" << usage << general_options );
    }

    if ( !vm.count("left") || !vm.count("right") || !vm.count("output") ) {
      vw_throw( vw::ArgumentErr() << "Requires <left input path> <right input path> <output path> input in order to proceed.\n\n"
                << usage << general_options );
    }

    return true;

}

bool produceInterestPoints(const Parameters &params)
{

  // Verify images are present
  boost::filesystem::path leftBoostPath (params.leftFilePath );
  boost::filesystem::path rightBoostPath(params.rightFilePath);

  printf("Checking for input files...\n");
  if (!boost::filesystem::exists(boost::filesystem::path(params.leftFilePath)))
  {
    printf("Error: input file %s is missing!\n", params.leftFilePath.c_str());
    return false;
  }
  if (!boost::filesystem::exists(boost::filesystem::path(params.rightFilePath)))
  {
    printf("Error: input file %s is missing!\n", params.rightFilePath.c_str());
    return false;
  }

  // Load both images
  printf("Loading images left=%s and right=%s...\n",
         params.leftFilePath.c_str(),
         params.rightFilePath.c_str());
  vw::DiskImageView<vw::PixelGray<float> > leftDiskImage (params.leftFilePath );
  vw::DiskImageView<vw::PixelGray<float> > rightDiskImage(params.rightFilePath);

  //TODO: Error checks here?
  printf("Loading camera models...\n");
  vw::camera::IsisCameraModel leftCameraModel(params.leftFilePath);
  vw::camera::IsisCameraModel rightCameraModel(params.rightFilePath);

  //TODO: Where to get these from?
  double noData1 = -32767;
  double noData2 = -32767;

  // Set up Datum object for the moon, then apply the elevation guess
  vw::cartography::Datum datum("D_MOON");
  datum.set_semi_major_axis(datum.semi_major_axis() + params.elevationGuess);
  datum.set_semi_minor_axis(datum.semi_minor_axis() + params.elevationGuess);

  // Call function to find the matching interest points
  printf("Calling ipfind\n");
  bool ipFindResult = asp::ip_matching_w_alignment(true,
                                                   &leftCameraModel, &rightCameraModel,
                                                   leftDiskImage,    rightDiskImage,
                                                   datum, params.outputPath,
                                                   noData1, noData2);

  return ipFindResult;
}

int main( int argc, char *argv[] )
{
  printf("Starting stereoIpFind\n");

  try {

    Parameters params;

    printf("Parsing input parameters...\n");
    if (!parseInputParams(argc, argv, params))
      return 1;

    if (!produceInterestPoints(params))
      return 1;

    printf("stereoIpFind finished!\n");
  }
  catch (const vw::Exception& e) {
    std::cerr << "Error: " << e.what() << std::endl;
  }

  return 0;
}

max_stars_repo_name: NeoGeographyToolkit/Tools

max_issues_repo_name: NeoGeographyToolkit/Tools

max_forks_repo_name: NeoGeographyToolkit/Tools


text:
/*
    Copyright 2019 Tenable, Inc.

    Redistribution and use in source and binary forms, with or without modification,
    are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this
        list of conditions and the following disclaimer.

    2. 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.

    3. Neither the name of the copyright holder 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 HOLDER 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 <cstdlib>
#include <iostream>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <boost/cstdint.hpp>
#include <boost/program_options.hpp>
#include <boost/algorithm/string.hpp>

#include "winbox_session.hpp"
#include "winbox_message.hpp"

namespace
{
    const char s_version[] = "Cache manipulation PoC";

    bool parseCommandLine(int p_argCount, const char* p_argArray[],
                          std::string& p_ip, std::string& p_port, std::string& p_server, std::string& p_domain)
    {
        boost::program_options::options_description description("options");
        description.add_options()
            ("help,h", "A list of command line options")
            ("version,v", "Display version information")
            ("port,p", boost::program_options::value<std::string>(), "The port to connect to")
            ("ip,i", boost::program_options::value<std::string>(), "The ip to connect to")
            ("server,s", boost::program_options::value<std::string>(), "The DNS server to connect to");
            ("domain,d", boost::program_options::value<std::string>(), "The Domain to resolve");

        boost::program_options::variables_map argv_map;
        try
        {
            boost::program_options::store(
                boost::program_options::parse_command_line(
                    p_argCount, p_argArray, description), argv_map);
        }
        catch (const std::exception& e)
        {
            std::cerr << e.what() << std::endl;
            std::cerr << description << std::endl;
            return false;
        }

        boost::program_options::notify(argv_map);
        if (argv_map.empty() || argv_map.count("help"))
        {
            std::cerr << description << std::endl;
            return false;
        }

        if (argv_map.count("version"))
        {
            std::cerr << "Version: " << ::s_version << std::endl;
            return false;
        }

        if (argv_map.count("ip") && argv_map.count("port") && argv_map.count("server"))
        {
            p_ip.assign(argv_map["ip"].as<std::string>());
            p_port.assign(argv_map["port"].as<std::string>());
            p_server.assign(argv_map["server"].as<std::string>());
            return true;
        }
        else
        {
            std::cout << description << std::endl;
        }

        return false;
    }
}

int main(int p_argc, const char** p_argv)
{
    std::string ip;
    std::string port;
    std::string server;
    std::string domain;
    if (!parseCommandLine(p_argc, p_argv, ip, port, server, domain))
    {
        return EXIT_FAILURE;
    }

    in_addr_t server_net = inet_addr(server.c_str());
    if (server_net == 0xffffffff)
    {
        std::cerr << "Failed to convert the server address." << std::endl;
        return EXIT_FAILURE;
    }

    Winbox_Session winboxSession(ip, port);
    if (!winboxSession.connect())
    {
        std::cerr << "Failed to connect to the remote host" << std::endl;
        return EXIT_FAILURE;
    }

    WinboxMessage msg;
    msg.set_to(14);
    msg.set_command(3);
    msg.set_request_id(1);
    msg.set_reply_expected(true);
    msg.add_string(3, domain);
    msg.add_u32(1, server_net);
    std::cout << "-> " << msg.serialize_to_json() << std::endl;
    winboxSession.send(msg);

    msg.reset();
    if (!winboxSession.receive(msg))
    {
        std::cerr << "Error receiving a response." << std::endl;
        return EXIT_FAILURE;
    }

    if (msg.has_error())
    {
        std::cout << "error: " << msg.get_error_string() << std::endl;
    }
    else
    {
        std::cout << "<- " << msg.serialize_to_json() << std::endl;
    }

    return EXIT_SUCCESS;
}

ext: cpp

max_stars_repo_name: Nomanpour/routeros

max_issues_repo_name: Nomanpour/routeros

max_forks_repo_name: Nomanpour/routeros


text:
/********************************************************************************
 * Copyright 2009 The Robotics Group, The Maersk Mc-Kinney Moller Institute,
 * Faculty of Engineering, University of Southern Denmark
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ********************************************************************************/

#include "WorkCellScene.hpp"

#include <rw/core/macros.hpp>
#include <rw/graphics/DrawableNode.hpp>
#include <rw/graphics/DrawableNodeClone.hpp>
#include <rw/graphics/Render.hpp>
#include <rw/kinematics/Frame.hpp>
#include <rw/kinematics/Kinematics.hpp>
#include <rw/kinematics/State.hpp>
#include <rw/models/DeformableObject.hpp>
#include <rw/models/WorkCell.hpp>
#include <rw/graphics/Model3D.hpp>

#include <boost/bind.hpp>
#include <stack>
#include <vector>

namespace rw { namespace kinematics {
    class Frame;
}}    // namespace rw::kinematics

using namespace rw::core;
using namespace rw::geometry;
using namespace rw::graphics;
using namespace rw::kinematics;
using namespace rw::math;
using namespace rw::models;
using namespace rw::sensor;

//----------------------------------------------------------------------------
namespace {
struct FindDrawableVisitor
{
    SceneGraph::NodeVisitor functor;

    FindDrawableVisitor (std::string name, bool findall) : _name (name), _findall (findall)
    {
        functor = boost::ref (*this);
    }

    FindDrawableVisitor (DrawableNode::Ptr d, bool findall) : _findall (findall), _drawable (d)
    {
        functor = boost::ref (*this);
    }

    bool operator() (SceneNode::Ptr& child, SceneNode::Ptr& parent)
    {
        if (child->asDrawableNode ()) {
            bool found = false;
            if (_drawable) {
                // we search for this specific drawable
                if (_drawable == child)
                    found = true;
            }
            else if (child->getName () == _name) {
                found = true;
            }
            DrawableNode::Ptr d = child.cast< DrawableNode > ();
            if (d != NULL && found) {
                if (_findall) {
                    _dnodes.push_back (d);
                    _pnodes.push_back (parent);
                }
                else {
                    _dnode = d;
                    _pnode = parent;
                    return true;
                }
            }
        }
        return false;
    }

    DrawableNode::Ptr _dnode;
    SceneNode::Ptr _pnode;
    std::vector< DrawableNode::Ptr > _dnodes;
    std::vector< SceneNode::Ptr > _pnodes;
    std::string _name;
    bool _findall;
    DrawableNode::Ptr _drawable;    // the one to match
};

struct StaticFilter
{
    SceneGraph::NodeFilter functor;
    StaticFilter (bool retValue) : _retvalue (retValue) { functor = boost::ref (*this); }
    bool operator() (const SceneNode::Ptr&) const { return _retvalue; }
    const bool _retvalue;
};
}    // namespace

//----------------------------------------------------------------------------

// Struct used for transfer of visual state for frames when the same workcell is reloaded
// Frame-level values will override the values for individual drawables, but only if the first value
// of the following pairs are set to true (only when that particular value is set by the user).
struct WorkCellScene::FrameVisualState
{
    FrameVisualState () :
        visible (false, true), highlighted (false, false), alpha (false, 1.0),
        frameAxisVisible (false, false), dtype (false, DrawableNode::SOLID), dmask (false, 0),
        frameLabelVisible (false, false)
    {}
    std::pair< bool, bool > visible;
    std::pair< bool, bool > highlighted;
    std::pair< bool, double > alpha;
    std::pair< bool, bool > frameAxisVisible;
    std::pair< bool, DrawableNode::DrawType > dtype;
    std::pair< bool, unsigned int > dmask;
    std::pair< bool, bool > frameLabelVisible;
};

WorkCellScene::WorkCellScene (SceneGraph::Ptr scene) :
    _scene (scene), _fk (NULL), _worldNode (scene->makeGroupNode ("World"))
{
    _scene->addChild (_worldNode, _scene->getRoot ());
    setWorkCell (NULL);
}

WorkCellScene::~WorkCellScene ()
{
    clearCache ();
}

void WorkCellScene::clearCache ()
{
    _frameNodeMap.clear ();
}

void WorkCellScene::draw (SceneGraph::RenderInfo& info)
{
    _scene->draw (info);
}

void WorkCellScene::workCellChangedListener (int)
{
    State state = _wc->getDefaultState ();
    updateSceneGraph (state);
}

void WorkCellScene::setWorkCell (rw::models::WorkCell::Ptr wc)
{
    if (_wc == wc)
        return;

    // if the workcell name matches the old one then see if we can transfer states of frames to the
    // next workcell
    std::map< std::string, FrameVisualState > fnameToStateMap;
    if (wc != NULL && _wc != NULL && wc->getName () == _wc->getName ()) {
        typedef std::pair< const Frame* const, FrameVisualState > StateMapData;
        for (StateMapData& data : _frameStateMap) {
            fnameToStateMap[data.first->getName ()] = data.second;
        }
    }

    // Unlink nodes in existing SceneGraph, so they can be destructed.
    if (!_wc.isNull ()) {
        const State state = _wc->getDefaultState ();
        std::stack< Frame* > frames;
        frames.push (_wc->getWorldFrame ());

        while (!frames.empty ()) {
            Frame* frame = frames.top ();
            frames.pop ();
            FrameNodeMap::iterator it = _frameNodeMap.find (frame);
            if (it != _frameNodeMap.end ()) {
                GroupNode::Ptr parentNode = _frameNodeMap[frame->getParent (state)];
                parentNode->removeChild (it->second);
                _scene->removeDrawables (it->second);
            }
            Frame::iterator_pair iter = frame->getChildren (state);
            for (; iter.first != iter.second; ++iter.first) {
                Frame* child = &(*iter.first);
                frames.push (child);
            }
        }
    }

    _frameStateMap.clear ();
    _frameDrawableMap.clear ();
    _nodeFrameMap.clear ();
    _frameNodeMap.clear ();
    _wc = wc;
    _scene->getRoot ()->removeChild (_worldNode);

    if (wc != NULL) {
        _wc->workCellChangedEvent ().add (
            boost::bind (&WorkCellScene::workCellChangedListener, this, boost::arg< 1 > ()), this);
        State state = _wc->getDefaultState ();
        updateSceneGraph (state);
    }
    else {
        // std::cout << "************************* CLEAR *****************************" <<
        // std::endl;
        _worldNode = _scene->makeGroupNode ("World");
        _scene->addChild (_worldNode, _scene->getRoot ());
    }

    if (wc != NULL) {
        typedef std::pair< std::string, FrameVisualState > StateStringMapData;
        for (StateStringMapData data : fnameToStateMap) {
            Frame* frame = _wc->findFrame (data.first);
            if (frame != NULL) {
                if (data.second.visible.first)
                    setVisible (data.second.visible.second, frame);
                if (data.second.frameAxisVisible.first)
                    setFrameAxisVisible (data.second.frameAxisVisible.second, frame);
                if (data.second.highlighted.first)
                    setHighlighted (data.second.highlighted.second, frame);
                if (data.second.alpha.first)
                    setTransparency (data.second.alpha.second, frame);
                if (data.second.dtype.first)
                    setDrawMask (data.second.dmask.second, frame);
                if (data.second.dtype.first)
                    setDrawType (data.second.dtype.second, frame);
                if (data.second.frameLabelVisible.first)
                    setFrameLabelVisible (data.second.frameLabelVisible.second, frame);
            }
        }
    }
}

rw::models::WorkCell::Ptr WorkCellScene::getWorkCell ()
{
    return _wc;
}

void WorkCellScene::setState (const State& state)
{
    _fk.reset (state);

    // iterate through all frame-node pairs and set the node transformations accordingly
    for (FrameNodeMap::value_type data : _frameNodeMap) {
        if ((data.first != NULL) && (data.second != NULL)) {
            // 1. we update the transform of each GroupNode
            data.second->setTransform (data.first->getTransform (state));

            // 2. also make sure that all parent relationships are updated
            if (data.first != _wc->getWorldFrame () && Kinematics::isDAF (data.first)) {
                const Frame* parent = data.first->getParent (state);
                if (!data.second->hasParent (_frameNodeMap[parent])) {
                    // 1. we remove the child from its parent
                    std::list< SceneNode::Ptr > pnodes = data.second->_parentNodes;
                    for (SceneNode::Ptr parentNode : pnodes) {
                        if (parentNode->asGroupNode ()) {
                            parentNode->asGroupNode ()->removeChild (data.second);
                        }
                    }
                    // 2. and add the daf to its new parent
                    _scene->addChild (data.second, _frameNodeMap[parent]);
                }
            }
        }
    }

    // also iterate through all deformable objects and update their geometries
    typedef std::map< DeformableObject::Ptr, std::vector< Model3D::Ptr > > DeformObjectMap;
    for (DeformObjectMap::value_type data : _deformableObjectsMap) {
        for (Model3D::Ptr model : data.second) {
            data.first->update (model, state);
        }
    }
}

GroupNode::Ptr WorkCellScene::getWorldNode ()
{
    return _worldNode;
}

void WorkCellScene::updateSceneGraph (State& state)
{
    // here we find all drawables that belong to frames and order them according to translucency
    _fk.reset (state);
    // first check that the WORLD frame is in the scene, if its not add it
    _frameNodeMap[NULL]               = _scene->getRoot ();    // for world frame parent
    _nodeFrameMap[_scene->getRoot ()] = NULL;
    RW_ASSERT (_scene->getRoot () != NULL);
    std::stack< Frame* > frames;
    std::set< Frame* > exists;
    frames.push (_wc->getWorldFrame ());

    while (!frames.empty ()) {
        Frame* frame = frames.top ();
        exists.insert (frame);
        frames.pop ();
        // std::cout << "Frame: " << frame->getName() << std::endl;
        // make sure that the frame is in the scene
        if (_frameNodeMap.find (frame) == _frameNodeMap.end ()) {
            GroupNode::Ptr parentNode = _frameNodeMap[frame->getParent (state)];
            // frame is not in the scene, add it.
            GroupNode::Ptr node = _scene->makeGroupNode (frame->getName ());
            _scene->addChild (node, parentNode);
            _frameNodeMap[frame] = node;
            _nodeFrameMap[node]  = frame;
        }

        // the frame is there, check that the parent relationship is correct
        GroupNode::Ptr node       = _frameNodeMap[frame];
        _nodeFrameMap[node]       = frame;
        GroupNode::Ptr parentNode = _frameNodeMap[frame->getParent (state)];

        if (node == NULL) {
            RW_WARN ("Node is null!");
            continue;
        }
        if (parentNode == NULL) {
            RW_WARN ("ParentNode is null!");
            continue;
        }

        // now for each DrawableInfo on frame check that they are on the frame

        // The information of drawables is located in SceneDescriptor and "model::Object"s
        // first check if there is any object with a frame "frame" in it
        std::vector< Object::Ptr > objs = _wc->getObjects ();
        State state                     = _wc->getDefaultState ();

        for (Object::Ptr obj : objs) {
            // just test if this object has anything to do with the frame
            if (obj->getBase () != frame)
                continue;

            _frameDrawableMap[frame].clear ();

            // check if obj is deformable object
            if (DeformableObject::Ptr dobj = obj.cast< DeformableObject > ()) {
                // make deep copy of the models.
                std::vector< Model3D::Ptr > models = dobj->getModels (state);
                // update the models with current state
                _deformableObjectsMap[dobj] = models;
                for (Model3D::Ptr model : models) {
                    DrawableNode::Ptr dnode =
                        _scene->makeDrawable (model->getName (), model, model->getMask ());
                    _scene->addChild (dnode, node);
                    _frameDrawableMap[frame].push_back (dnode);
                }
            }
            else {
                // the collision info is the geometry and visualization is Model3D
                // in case no models are available the collision geometry will be used
                std::vector< Geometry::Ptr > geoms = obj->getGeometry (state);
                for (Geometry::Ptr geom : geoms) {
                    if (geom->getFrame () != frame)
                        continue;

                    DrawableGeometryNode::Ptr dnode =
                        _scene->makeDrawable (geom->getName (), geom, geom->getMask ());
                    _scene->addChild (dnode, node);
                    _frameDrawableMap[frame].push_back (dnode);
                }

                for (Model3D::Ptr geomodel : obj->getModels ()) {
                    Model3D::Ptr model;
                    model = geomodel;
                    DrawableNode::Ptr dnode =
                        _scene->makeDrawable (model->getName (), model, model->getMask ());
                    _scene->addChild (dnode, node);
                    _frameDrawableMap[frame].push_back (dnode);
                }
            }
        }

        Frame::iterator_pair iter = frame->getChildren (state);
        for (; iter.first != iter.second; ++iter.first) {
            Frame* child = &(*iter.first);
            frames.push (child);
        }
    }

    _worldNode = _frameNodeMap[_wc->getWorldFrame ()];

    // Removing non-exsisting frames from NodeFrameMap
    std::set< GroupNode::Ptr > doesntExist;
    for (NodeFrameMap::iterator elem = _nodeFrameMap.begin (); elem != _nodeFrameMap.end ();) {
        if (!(exists.find (elem->second) != exists.end () || elem->second == NULL)) {
            doesntExist.insert (elem->first);
            elem = _nodeFrameMap.erase (elem);
        }
        else {
            elem++;
        }
    }
    // Removing non-exsisting nodes from FrameNodeMap
    typedef std::map< const rw::kinematics::Frame*, GroupNode::Ptr > FrameNodeMap;
    for (FrameNodeMap::iterator elem = _frameNodeMap.begin (); elem != _frameNodeMap.end ();) {
        if (doesntExist.find (elem->second) != doesntExist.end ()) {
            const GroupNode::Ptr gnode = elem->second;
            elem                       = _frameNodeMap.erase (elem);
            if (gnode->_childNodes.size () != 0) {
                RW_WARN ("The deleted frame has undeleted children");
            }
            // Removing SceneNode parents
            std::list< SceneNode::Ptr > parent = gnode->_parentNodes;
            while (parent.size () > 0) {
                for (auto par : _frameNodeMap) {
                    if (par.second->getName () == parent.back ()->getName ()) {
                        par.second->removeChild (gnode);
                    }
                }
                parent.pop_back ();
            }
        }
        else {
            elem++;
        }
    }
}

void WorkCellScene::setVisible (bool visible, const Frame* f)
{
    if (_frameNodeMap.find (f) == _frameNodeMap.end ())
        return;
    _frameStateMap[f].visible.first  = true;
    _frameStateMap[f].visible.second = visible;
    for (SceneNode::Ptr& d : _frameNodeMap[f]->_childNodes) {
        if (DrawableNode* dnode = d->asDrawableNode ())
            dnode->setVisible (visible);
    }
}

bool WorkCellScene::isVisible (const Frame* f) const
{
    if (_frameNodeMap.find (f) == _frameNodeMap.end ())
        return false;
    const std::map< const Frame*, FrameVisualState >::const_iterator it = _frameStateMap.find (f);
    if (it != _frameStateMap.end ())
        return it->second.visible.second;
    else
        return false;
}

void WorkCellScene::setHighlighted (bool highlighted, const Frame* f)
{
    if (_frameDrawableMap.find (f) == _frameDrawableMap.end ()) {
        return;
    }

    _frameStateMap[f].highlighted.first  = true;
    _frameStateMap[f].highlighted.second = highlighted;

    for (DrawableNode::Ptr& d : _frameDrawableMap[f]) {
        d->setHighlighted (highlighted);
    }
}

bool WorkCellScene::isHighlighted (const Frame* f) const
{
    const std::map< const Frame*, FrameVisualState >::const_iterator it = _frameStateMap.find (f);
    if (it != _frameStateMap.end ())
        return it->second.highlighted.second;
    else
        return false;
}

void WorkCellScene::setFrameAxisVisible (bool visible, Frame* f, double size)
{
    if (_frameNodeMap.find (f) == _frameNodeMap.end ()) {
        return;
    }
    _frameStateMap[f].frameAxisVisible.first  = true;
    _frameStateMap[f].frameAxisVisible.second = visible;
    GroupNode::Ptr node                       = _frameNodeMap[f];
    if (visible) {
        if (node->hasChild ("FrameAxis")) {
            // remove current frameaxis
            removeDrawable ("FrameAxis", f);
        }

        // Add a frame axis of specified size
        DrawableNode::Ptr frameAxisNode =
            _scene->makeDrawableFrameAxis ("FrameAxis", size, DrawableNode::Virtual);
        if (!frameAxisNode.isNull ()) {
            frameAxisNode->setName ("FrameAxis");
            addDrawable (frameAxisNode, f);
        }
        //_frameDrawableMap[f].push_back(dnode);
        // node->addChild( dnode );
        _scene->update ();
    }
    else if (!visible && node->hasChild ("FrameAxis")) {
        // remove leaf
        // node->removeChild( "FrameAxis" );
        removeDrawable ("FrameAxis", f);
        _scene->update ();
    }
}

bool WorkCellScene::isFrameAxisVisible (const Frame* f) const
{
    if (_frameNodeMap.find (f) == _frameNodeMap.end ())
        RW_THROW ("Frame is not in the scene!");
    const std::map< const Frame*, FrameVisualState >::const_iterator it = _frameStateMap.find (f);
    if (it != _frameStateMap.end ())
        return it->second.frameAxisVisible.second;
    else
        return false;
}

void WorkCellScene::setFrameLabelVisible (bool visible, Frame::Ptr f)
{
    if (_frameNodeMap.find (f.get ()) == _frameNodeMap.end ()) {
        return;
    }
    _frameStateMap[f.get ()].frameLabelVisible.first  = true;
    _frameStateMap[f.get ()].frameLabelVisible.second = visible;
    GroupNode::Ptr node                               = _frameNodeMap[f.get ()];
    if (visible) {
        if (node->hasChild ("FrameLabel")) {
            // remove current frameLabel
            removeDrawable ("FrameLabel", f.get ());
        }

        // Add a frame axis of specified size
        DrawableNode::Ptr frameLabelNode = _scene->makeDrawable ("FrameLabel", f->getName (), f);
        if (!frameLabelNode.isNull ()) {
            frameLabelNode->setName ("FrameLabel");
            addDrawable (frameLabelNode, f.get ());
        }

        _scene->update ();
    }
    else if (!visible && node->hasChild ("FrameLabel")) {
        removeDrawable ("FrameLabel", f.get ());
        _scene->update ();
    }
}

bool WorkCellScene::isFrameLabelVisible (const Frame::Ptr f) const
{
    if (_frameNodeMap.find (f.get ()) == _frameNodeMap.end ()) {
        RW_THROW ("Frame is not in the scene!");
    }
    const std::map< const Frame*, FrameVisualState >::const_iterator it =
        _frameStateMap.find (f.get ());
    if (it != _frameStateMap.end ()) {
        return it->second.frameLabelVisible.second;
    }

    return false;
}

void WorkCellScene::setDrawType (DrawableNode::DrawType type, const Frame* f)
{
    if (_frameNodeMap.find (f) == _frameNodeMap.end ())
        return;
    _frameStateMap[f].dtype.first  = true;
    _frameStateMap[f].dtype.second = type;
    for (DrawableNode::Ptr& d : _frameDrawableMap[f]) {
        d->setDrawType (type);
    }
}

DrawableNode::DrawType WorkCellScene::getDrawType (const Frame* f) const
{
    if (_frameNodeMap.find (f) == _frameNodeMap.end ())
        RW_THROW ("Frame is not in the scene!");
    const std::map< const Frame*, FrameVisualState >::const_iterator it = _frameStateMap.find (f);
    if (it != _frameStateMap.end ())
        return it->second.dtype.second;
    else
        return DrawableNode::SOLID;
}

void WorkCellScene::setDrawMask (unsigned int mask, const Frame* f)
{
    if (_frameNodeMap.find (f) == _frameNodeMap.end ())
        RW_THROW ("Frame is not in the scene!");
    _frameStateMap[f].dmask.first  = true;
    _frameStateMap[f].dmask.second = mask;
    for (DrawableNode::Ptr& d : _frameDrawableMap[f]) {
        d->setMask (mask);
    }
}

unsigned int WorkCellScene::getDrawMask (const Frame* f) const
{
    if (_frameNodeMap.find (f) == _frameNodeMap.end ())
        RW_THROW ("Frame is not in the scene!");
    const std::map< const Frame*, FrameVisualState >::const_iterator it = _frameStateMap.find (f);
    if (it != _frameStateMap.end ())
        return it->second.dmask.second;
    else
        return DrawableNode::SOLID;
}

void WorkCellScene::setTransparency (double alpha, const Frame* f)
{
    if (_frameNodeMap.find (f) == _frameNodeMap.end ())
        return;
    _frameStateMap[f].alpha.first  = true;
    _frameStateMap[f].alpha.second = alpha;
    for (DrawableNode::Ptr& d : _frameDrawableMap[f]) {
        d->setTransparency ((float) alpha);
    }
}

void WorkCellScene::addDrawable (DrawableNode::Ptr drawable, Frame* frame)
{
    if (_wc == NULL)
        RW_THROW (
            "Scene is not initialized with WorkCell yet! Drawable cannot be attached to Frame.");
    // add frame to frame map
    _frameDrawableMap[frame].push_back (drawable);

    // get or create the
    if (_frameNodeMap.find (frame) == _frameNodeMap.end ()) {
        // the frame is not in the scene, add it
        State state = _wc->getDefaultState ();

        Frame* p = frame->getParent (state);

        std::stack< Frame* > frames;
        frames.push (frame);
        while (_frameNodeMap.find (p) == _frameNodeMap.end ()) {
            frames.push (p);
            p = p->getParent (state);
            RW_ASSERT (p != NULL);
        }

        while (!frames.empty ()) {
            Frame* f = frames.top ();
            frames.pop ();

            // now f's parent is supposed to have a node allready
            RW_ASSERT (_frameNodeMap.find (f->getParent (state)) != _frameNodeMap.end ());

            GroupNode::Ptr pnode = _frameNodeMap[f->getParent (state)];
            GroupNode::Ptr child = _scene->makeGroupNode (f->getName ());
            GroupNode::addChild (child, pnode);
            _frameNodeMap[f]     = child;
            _nodeFrameMap[child] = f;
        }
    }

    _frameNodeMap[frame]->addChild (drawable);
}

DrawableNode::Ptr WorkCellScene::addDrawable (const std::string& filename, Frame* frame, int dmask)
{
    DrawableNode::Ptr drawable = _scene->makeDrawable (filename, dmask);
    drawable->setMask (dmask);
    addDrawable (drawable, frame);
    return drawable;
}

DrawableNode::Ptr WorkCellScene::addFrameAxis (const std::string& name, double size, Frame* frame,
                                               int dmask)
{
    DrawableNode::Ptr drawable = _scene->makeDrawableFrameAxis (name, size, dmask);
    addDrawable (drawable, frame);
    return drawable;
}

DrawableGeometryNode::Ptr WorkCellScene::addGeometry (const std::string& name, Geometry::Ptr geom,
                                                      Frame* frame, int dmask)
{
    DrawableGeometryNode::Ptr drawable = _scene->makeDrawable (name, geom);
    drawable->setMask (dmask);
    addDrawable (drawable, frame);
    return drawable;
}

DrawableNode::Ptr WorkCellScene::addModel3D (const std::string& name, Model3D::Ptr model,
                                             Frame* frame, int dmask)
{
    DrawableNode::Ptr drawable = _scene->makeDrawable (name, model);
    drawable->setMask (dmask);
    addDrawable (drawable, frame);
    return drawable;
}

DrawableNode::Ptr WorkCellScene::addImage (const std::string& name, const class Image& img,
                                           Frame* frame, int dmask)
{
    DrawableNode::Ptr drawable = _scene->makeDrawable (name, img);
    drawable->setMask (dmask);
    addDrawable (drawable, frame);
    return drawable;
}

DrawableNode::Ptr WorkCellScene::addScan (const std::string& name,
                                          const class rw::geometry::PointCloud& scan, Frame* frame,
                                          int dmask)
{
    DrawableNode::Ptr drawable = _scene->makeDrawable (name, scan);
    drawable->setMask (dmask);
    addDrawable (drawable, frame);
    return drawable;
}

DrawableGeometryNode::Ptr WorkCellScene::addLines (const std::string& name,
                                                   const std::vector< Line >& lines, Frame* frame,
                                                   int dmask)
{
    DrawableGeometryNode::Ptr drawable = _scene->makeDrawable (name, lines);
    if (drawable == NULL)
        return drawable;
    drawable->setMask (dmask);
    addDrawable (drawable, frame);
    return drawable;
}

DrawableNode::Ptr WorkCellScene::addText (const std::string& name, const std::string& text,
                                          Frame::Ptr frame, int dmask)
{
    DrawableNode::Ptr drawable = _scene->makeDrawable (name, text, frame);
    drawable->setMask (dmask);
    addDrawable (drawable, frame.get ());
    return drawable;
}

DrawableNode::Ptr WorkCellScene::addRender (const std::string& name, Render::Ptr render,
                                            Frame* frame, int dmask)
{
    DrawableNode::Ptr drawable = _scene->makeDrawable (name, render);
    drawable->setMask (dmask);
    addDrawable (drawable, frame);
    return drawable;
}

std::vector< DrawableNode::Ptr > WorkCellScene::getDrawables ()
{
    return _scene->getDrawables ();
}

std::vector< DrawableNode::Ptr > WorkCellScene::getDrawables (const Frame* f) const
{
    std::map< const Frame*, std::vector< DrawableNode::Ptr > >::const_iterator it =
        _frameDrawableMap.find (f);
    if (it == _frameDrawableMap.end ())
        return std::vector< DrawableNode::Ptr > ();
    else
        return it->second;
}

std::vector< DrawableNode::Ptr > WorkCellScene::getDrawablesRec (Frame* f, State&)
{
    if (_frameNodeMap.find (f) == _frameNodeMap.end ())
        return std::vector< DrawableNode::Ptr > ();
    return _scene->getDrawablesRec (_frameNodeMap[f]);
}

DrawableNode::Ptr WorkCellScene::findDrawable (const std::string& name)
{
    return _scene->findDrawable (name);
}

DrawableNode::Ptr WorkCellScene::findDrawable (const std::string& name, const Frame* f)
{
    const FrameNodeMap::const_iterator it = _frameNodeMap.find (f);
    if (it == _frameNodeMap.end ())
        return NULL;
    else
        return _scene->findDrawable (name, it->second);
}

std::vector< DrawableNode::Ptr > WorkCellScene::findDrawables (const std::string& name)
{
    return _scene->findDrawables (name);
}

bool WorkCellScene::removeDrawable (DrawableNode::Ptr drawable)
{
    const std::list< SceneNode::Ptr > parents = drawable->_parentNodes;
    for (std::list< SceneNode::Ptr >::const_iterator itP = parents.begin (); itP != parents.end ();
         itP++) {
        const GroupNode::Ptr gn = (*itP)->asGroupNode ();
        if (gn.isNull ())
            continue;
        const NodeFrameMap::const_iterator itF = _nodeFrameMap.find (gn);
        if (itF == _nodeFrameMap.end ())
            continue;
        std::map< const Frame*, std::vector< DrawableNode::Ptr > >::iterator itD =
            _frameDrawableMap.find (itF->second);
        if (itD == _frameDrawableMap.end ())
            continue;
        std::vector< DrawableNode::Ptr >& drawables = itD->second;
        for (std::vector< DrawableNode::Ptr >::iterator itDrawables = drawables.begin ();
             itDrawables != drawables.end ();
             itDrawables++) {
            if ((*itDrawables) == drawable) {
                drawables.erase (itDrawables);
                break;
            }
        }
    }

    return _scene->removeDrawable (drawable);
}

bool WorkCellScene::removeDrawables (const Frame* f)
{
    std::map< const Frame*, std::vector< DrawableNode::Ptr > >::iterator itD =
        _frameDrawableMap.find (f);
    if (itD != _frameDrawableMap.end ()) {
        std::vector< DrawableNode::Ptr >& drawables = itD->second;
        drawables.clear ();
    }

    const FrameNodeMap::const_iterator it = _frameNodeMap.find (f);
    if (it == _frameNodeMap.end ())
        return false;
    else
        return _scene->removeDrawables (it->second);
}

bool WorkCellScene::removeDrawable (const std::string& name)
{
    FindDrawableVisitor visitor (name, false);
    SceneNode::Ptr root = _worldNode.cast< SceneNode > ();
    _scene->traverse (root, visitor.functor, StaticFilter (false).functor);
    if (visitor._dnode.isNull ())
        return true;
    if (GroupNode* const gn = visitor._pnode->asGroupNode ()) {
        const NodeFrameMap::const_iterator itF = _nodeFrameMap.find (gn);
        if (itF != _nodeFrameMap.end ()) {
            std::map< const Frame*, std::vector< DrawableNode::Ptr > >::iterator itD =
                _frameDrawableMap.find (itF->second);
            if (itD != _frameDrawableMap.end ()) {
                std::vector< DrawableNode::Ptr >& drawables = itD->second;
                for (std::vector< DrawableNode::Ptr >::iterator itDrawables = drawables.begin ();
                     itDrawables != drawables.end ();
                     itDrawables++) {
                    if ((*itDrawables)->getName () == name) {
                        drawables.erase (itDrawables);
                        break;
                    }
                }
            }
        }
    }

    return _scene->removeDrawable (name);
}

bool WorkCellScene::removeDrawables (const std::string& name)
{
    const std::vector< DrawableNode::Ptr > drawables = _scene->findDrawables (name);
    for (std::vector< DrawableNode::Ptr >::const_iterator it = drawables.begin ();
         it != drawables.end ();
         it++) {
        const DrawableNode::Ptr d                 = *it;
        const std::list< SceneNode::Ptr > parents = d->_parentNodes;
        for (std::list< SceneNode::Ptr >::const_iterator itP = parents.begin ();
             itP != parents.end ();
             itP++) {
            const GroupNode::Ptr gn = (*itP)->asGroupNode ();
            if (gn.isNull ())
                continue;
            const NodeFrameMap::const_iterator itF = _nodeFrameMap.find (gn);
            if (itF == _nodeFrameMap.end ())
                continue;
            std::map< const Frame*, std::vector< DrawableNode::Ptr > >::iterator itD =
                _frameDrawableMap.find (itF->second);
            if (itD == _frameDrawableMap.end ())
                continue;
            std::vector< DrawableNode::Ptr >& drawables = itD->second;
            for (std::vector< DrawableNode::Ptr >::iterator itDrawables = drawables.begin ();
                 itDrawables != drawables.end ();) {
                if ((*itDrawables)->getName () == name) {
                    itDrawables = drawables.erase (itDrawables);
                }
                else {
                    itDrawables++;
                }
            }
        }
    }

    return _scene->removeDrawables (name);
}

bool WorkCellScene::removeDrawable (DrawableNode::Ptr drawable, const Frame* f)
{
    std::map< const Frame*, std::vector< DrawableNode::Ptr > >::iterator itD =
        _frameDrawableMap.find (f);
    if (itD != _frameDrawableMap.end ()) {
        std::vector< DrawableNode::Ptr >& drawables = itD->second;
        for (std::vector< DrawableNode::Ptr >::iterator it = drawables.begin ();
             it != drawables.end ();
             it++) {
            if ((*it) == drawable) {
                drawables.erase (it);
                break;
            }
        }
    }

    const FrameNodeMap::const_iterator it = _frameNodeMap.find (f);
    if (it == _frameNodeMap.end ())
        return false;
    else
        return _scene->removeDrawable (drawable, it->second);
}

bool WorkCellScene::removeDrawable (const std::string& name, const Frame* f)
{
    std::map< const Frame*, std::vector< DrawableNode::Ptr > >::iterator itD =
        _frameDrawableMap.find (f);
    if (itD != _frameDrawableMap.end ()) {
        std::vector< DrawableNode::Ptr >& drawables = itD->second;
        for (std::vector< DrawableNode::Ptr >::iterator it = drawables.begin ();
             it != drawables.end ();
             it++) {
            if ((*it)->getName () == name) {
                drawables.erase (it);
                break;
            }
        }
    }

    const FrameNodeMap::const_iterator it = _frameNodeMap.find (f);
    if (it == _frameNodeMap.end ())
        return false;
    else
        return _scene->removeChild (name, it->second);
}

Frame* WorkCellScene::getFrame (DrawableNode::Ptr d) const
{
    GroupNode::Ptr gn = d->_parentNodes.front ().cast< GroupNode > ();
    if (gn == NULL) {
        RW_WARN ("Group Node is NULL");
        return NULL;
    }
    // std::cout << "GroupeNode: " << gn->getName() << std::endl;
    const NodeFrameMap::const_iterator it = _nodeFrameMap.find (gn);
    if (it != _nodeFrameMap.end ())
        return it->second;
    else
        return NULL;
}

GroupNode::Ptr WorkCellScene::getNode (const Frame* frame) const
{
    const FrameNodeMap::const_iterator it = _frameNodeMap.find (frame);
    if (it != _frameNodeMap.end ())
        return it->second;
    else
        return NULL;
}


text: #include <boost/hana/intersperse.hpp>

ext: hpp

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
#include "mapgen/mapgen.hpp"

#include <fstream>
#include <set>

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_ALTERNATIVE_INIT_API
#include <boost/test/unit_test.hpp>

constexpr char csv1[] = "a,b,c,d,e\n"
                        "0,10,4,9,10\n"
                        "2,0,3,2,4\n"
                        "3,5,0,6,8\n"
                        "9,2,4,0,3\n"
                        "9,2,3,6,0\n";

// Example from "http://www.ams.org/samplings/feature-column/fcarc-tsp"
constexpr char csv2[] = "a,b,c,d,e\n"
                        "0,6,9,inf,10\n"
                        "6,0,11,inf,inf\n"
                        "9,11,0,inf,14\n"
                        "inf,inf,inf,0,8\n"
                        "10,inf,14,8,0\n";

bool init_unit_test() {
	std::ofstream file1("mapgen_1.csv");
	file1 << csv1;

	std::ofstream file2("mapgen_2.csv");
	file2 << csv2;

	return true;
}

int main(int argc, char* argv[]) {
	return ::boost::unit_test::unit_test_main(&init_unit_test, argc, argv);
}

BOOST_AUTO_TEST_CASE(mapgen_basic_csv) {
	using awesome::MapGen;
	MapGen::MapGraph map = MapGen::fromFile("mapgen_1.csv"),
	                 expected{{"a", "b", {10}}, {"a", "c", {4}}, {"a", "d", {9}}, {"a", "e", {10}},
	                          {"b", "a", {2}},  {"b", "c", {3}}, {"b", "d", {2}}, {"b", "e", {4}},
	                          {"c", "a", {3}},  {"c", "b", {5}}, {"c", "d", {6}}, {"c", "e", {8}},
	                          {"d", "a", {9}},  {"d", "b", {2}}, {"d", "c", {4}}, {"d", "e", {3}},
	                          {"e", "a", {9}},  {"e", "b", {2}}, {"e", "c", {3}}, {"e", "d", {6}}};

	BOOST_CHECK_EQUAL(map, expected);
}

BOOST_AUTO_TEST_CASE(mapgen_csv_with_inf) {
	using awesome::MapGen;
	MapGen::MapGraph map = MapGen::fromFile("mapgen_2.csv"), expected{{"a", "b", {6}},
	                                                                  {"a", "c", {9}},
	                                                                  {"a", "e", {10}},
	                                                                  {"b", "a", {6}},
	                                                                  {"b", "c", {11}},
	                                                                  {"c", "a", {9}},
	                                                                  {"c", "b", {11}},
	                                                                  {"c", "e", {14}},
	                                                                  {"d", "e", {8}},
	                                                                  {"e", "a", {10}},
	                                                                  {"e", "c", {14}},
	                                                                  {"e", "d", {8}}};

	BOOST_CHECK_EQUAL(map, expected);
}

BOOST_AUTO_TEST_CASE(mapgen_random) {
	using awesome::MapGen;

	MapGen::MapGraph map = MapGen::random(10);

	BOOST_CHECK_EQUAL(map.getVerticesCount(), 10);
	// 2×n(n-1)/2 = 90
	// ×2 because we store it as a directed graph
	BOOST_CHECK_EQUAL(map.getEdgesCount(), 90);
}


text:
/*
// Licensed to DynamoBI Corporation (DynamoBI) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  DynamoBI licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at

//   http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
*/

#include "fennel/common/CommonPreamble.h"
#include "fennel/common/FemEnums.h"
#include "fennel/test/ExecStreamUnitTestBase.h"
#include "fennel/lcs/LcsClusterAppendExecStream.h"
#include "fennel/sorter/ExternalSortExecStream.h"
#include "fennel/lbm/LbmGeneratorExecStream.h"
#include "fennel/lbm/LbmSplicerExecStream.h"
#include "fennel/lbm/LbmEntryDump.h"
#include "fennel/btree/BTreeBuilder.h"
#include "fennel/ftrs/BTreeInsertExecStream.h"
#include "fennel/ftrs/BTreeSearchExecStream.h"
#include "fennel/ftrs/BTreeExecStream.h"
#include "fennel/tuple/StandardTypeDescriptor.h"
#include "fennel/tuple/TupleDescriptor.h"
#include "fennel/exec/MockProducerExecStream.h"
#include "fennel/exec/ExecStreamEmbryo.h"
#include "fennel/exec/SplitterExecStream.h"
#include "fennel/exec/BarrierExecStream.h"
#include "fennel/exec/ExecStreamGraph.h"
#include "fennel/cache/Cache.h"
#include "fennel/common/TraceSource.h"
#include <stdarg.h>

#include <boost/test/test_tools.hpp>

using namespace fennel;

/**
 * Testcase for loading multiple clusters.
 */
class LbmLoadBitmapTest : public ExecStreamUnitTestBase
{
protected:
    StandardTypeDescriptorFactory stdTypeFactory;
    TupleAttributeDescriptor attrDesc_int64;

    /**
     * BTrees corresponding to the clusters
     */
    vector<boost::shared_ptr<BTreeDescriptor> > bTreeClusters;

    /**
     * Saved root pageids of btrees corresponding to clusters; used to
     * append to existing table
     */
    vector<PageId> savedBTreeClusterRootIds;

    /**
     * BTrees corresponding to the bitmaps
     */
    vector<boost::shared_ptr<BTreeDescriptor> > bTreeBitmaps;

    /**
     * Saved root pageids of btrees corresponding to bitmaps; used to
     * append to existing table
     */
    vector<PageId> savedBTreeBitmapRootIds;

    /**
     * Entry dumps corresponding to the bitmaps
     */
    vector<boost::shared_ptr<LbmEntryDump> > entryDumps;

    /**
     * Initializes a BTreeExecStreamParam structure
     */
    void initBTreeExecStreamParam(
        BTreeExecStreamParams &param, shared_ptr<BTreeDescriptor> pBTreeDesc);

    /**
     * Initializes BTreeParams structure
     */
    void initBTreeParam(
        BTreeParams &param, shared_ptr<BTreeDescriptor> pBTreeDesc);

    /**
     * Initializes a cluster scan def structure for a generator exec stream
     */
    void initClusterScanDef(
        LbmGeneratorExecStreamParams &generatorParams,
        struct LcsClusterScanDef &clusterScanDef,
        uint bTreeIndex,
        DynamicParamId paramId);

    /**
     * Initializes BTreeExecStreamParam corresponding to a bitmap index
     */
    void  initBTreeBitmapDesc(
        TupleDescriptor &param, TupleProjection &keyProj, uint nKeys);

    /**
     * Initializes a tuple descriptor corresponding to a bitmap index
     */
    void initBTreeTupleDesc(TupleDescriptor &tupleDesc, uint nKeys);

    void testLoad(
        uint nRows, uint nClusters, std::vector<int> &repeatSeqValues,
        bool newRoot, bool dumpEntries, string testName,
        bool dynamicRootPageId);

public:
    explicit LbmLoadBitmapTest()
    {
        FENNEL_UNIT_TEST_CASE(LbmLoadBitmapTest, testLoad50);
        FENNEL_UNIT_TEST_CASE(LbmLoadBitmapTest, testLoad5000);
        FENNEL_UNIT_TEST_CASE(LbmLoadBitmapTest, testLoad10000);
        FENNEL_UNIT_TEST_CASE(LbmLoadBitmapTest, testAppend);
        FENNEL_UNIT_TEST_CASE(LbmLoadBitmapTest, testLoadDynamicRoot50);
    }

    void testCaseSetUp();
    void testCaseTearDown();

    void testLoadSmall(bool dynamicRootPageId);

    void testLoad50();
    void testLoad5000();
    void testLoad10000();
    void testAppend();
    void testLoadDynamicRoot50();
};

void LbmLoadBitmapTest::testLoad50()
{
    testLoadSmall(false);
}

void LbmLoadBitmapTest::testLoadDynamicRoot50()
{
    testLoadSmall(true);
}

void LbmLoadBitmapTest::testLoadSmall(bool dynamicRootPageId)
{
    // small load
    uint nRows = 50;
    uint nClusters = 4;
    std::vector<int> repeatSeqValues;

    // first column will contain all unique values; the remaining columns
    // have a repeating sequence based on the value set in the vector
    repeatSeqValues.push_back(nRows);
    repeatSeqValues.push_back(5);
    repeatSeqValues.push_back(9);
    repeatSeqValues.push_back(19);
    testLoad(
        nRows, nClusters, repeatSeqValues, true, true, "testLoad50",
        dynamicRootPageId);
}

void LbmLoadBitmapTest::testLoad5000()
{
    uint nRows = 5000;
    uint nClusters = 2;
    std::vector<int> repeatSeqValues;

    // test with a larger number of distinct values to force buffer flushing
    repeatSeqValues.push_back(nRows);
    repeatSeqValues.push_back(200);
    testLoad(
        nRows, nClusters, repeatSeqValues, true, true, "testLoad5000", false);
}

void LbmLoadBitmapTest::testLoad10000()
{
    // larger rowset to force bitmaps exceeding their buffer sizes
    uint nRows = 10000;
    uint nClusters = 4;
    std::vector<int> repeatSeqValues;

    repeatSeqValues.push_back(nRows);
    repeatSeqValues.push_back(5);
    repeatSeqValues.push_back(9);
    repeatSeqValues.push_back(19);
    testLoad(
        nRows, nClusters, repeatSeqValues, true, true, "testLoad10000", false);
}

void LbmLoadBitmapTest::testAppend()
{
    // parameters for test
    uint nRows = 60;
    uint nClusters = 4;
    std::vector<int> repeatSeqValues1;
    std::vector<int> repeatSeqValues2;

    // Set up the column generators for empty load and append.

    // column 1
    repeatSeqValues1.push_back(nRows);
    repeatSeqValues2.push_back(nRows);

    // column 2
    repeatSeqValues1.push_back(23);
    repeatSeqValues2.push_back(31);

    // column 3
    repeatSeqValues1.push_back(1);
    repeatSeqValues2.push_back(2);

    // column 4
    repeatSeqValues1.push_back(7);
    repeatSeqValues2.push_back(29);

    // load into empty btree
    testLoad(
        nRows, nClusters, repeatSeqValues1, true,  true, "testAppendNewRoot",
        false);

    // append some new values
    resetExecStreamTest();
    testLoad(
        nRows, nClusters, repeatSeqValues2, false, true, "testAppendOldRoot",
        false);
}

/**
 * Loads a table with nClusters clusters, 1 column per cluster, and nRows rows.
 * Each column has a repeating sequence of values based on the value in the
 * repeatSeqValues vector.  E.g., a repeating sequence of n will have values:
 * (0, 1, 2, ..., n-1, 0, 1, 2, ..., n-1, 0, 1, 2, ...).
 *
 * Bitmap indexes are then created on each column as well as a multi-key
 * index that is created on all columns.
 *
 * If newRoot is false, this is testing an append to an existing table.
 */
void LbmLoadBitmapTest::testLoad(
    uint nRows, uint nClusters, std::vector<int> &repeatSeqValues, bool newRoot,
    bool dumpEntries, string testName, bool dynamicRootPageId)
{
    // 0. reset member fields.
    for (uint i = 0; i < bTreeClusters.size(); i++) {
        bTreeClusters[i]->segmentAccessor.reset();
    }
    for (uint i = 0; i < bTreeBitmaps.size(); i++) {
        bTreeBitmaps[i]->segmentAccessor.reset();
    }
    bTreeClusters.clear();
    bTreeBitmaps.clear();
    entryDumps.clear();

    // 1. setup mock input stream

    MockProducerExecStreamParams mockParams;
    for (uint i = 0; i < nClusters; i++) {
        mockParams.outputTupleDesc.push_back(attrDesc_int64);
    }
    mockParams.nRows = nRows;

    vector<boost::shared_ptr<ColumnGenerator<int64_t> > > columnGenerators;
    SharedInt64ColumnGenerator col;
    assert(repeatSeqValues.size() == nClusters);
    for (uint i = 0; i < repeatSeqValues.size(); i++) {
        col =
            SharedInt64ColumnGenerator(
                new RepeatingSeqColumnGenerator(repeatSeqValues[i]));
        columnGenerators.push_back(col);
    }
    mockParams.pGenerator.reset(
        new CompositeExecStreamGenerator(columnGenerators));

    ExecStreamEmbryo mockStreamEmbryo;
    mockStreamEmbryo.init(new MockProducerExecStream(), mockParams);
    mockStreamEmbryo.getStream()->setName("MockProducerExecStream");

    // 2. setup splitter stream for cluster loads

    SplitterExecStreamParams splitterParams;
    ExecStreamEmbryo splitterStreamEmbryo;
    splitterStreamEmbryo.init(new SplitterExecStream(), splitterParams);
    splitterStreamEmbryo.getStream()->setName("ClusterSplitterExecStream");

    // 3. setup loader streams

    vector<ExecStreamEmbryo> lcsAppendEmbryos;
    for (uint i = 0; i < nClusters; i++) {
        LcsClusterAppendExecStreamParams lcsAppendParams;
        boost::shared_ptr<BTreeDescriptor> pBTreeDesc =
            boost::shared_ptr<BTreeDescriptor> (new BTreeDescriptor());
        bTreeClusters.push_back(pBTreeDesc);

        // initialize the btree parameter portion of lcsAppendParams
        // BTree tuple desc has two columns (rid, clusterPageid)
        (lcsAppendParams.tupleDesc).push_back(attrDesc_int64);
        (lcsAppendParams.tupleDesc).push_back(attrDesc_int64);

        // BTree key only has one column which is the first column.
        (lcsAppendParams.keyProj).push_back(0);

        initBTreeExecStreamParam(lcsAppendParams, pBTreeDesc);

        // output two values (rows inserted, starting rid value)
        lcsAppendParams.outputTupleDesc.push_back(attrDesc_int64);
        lcsAppendParams.outputTupleDesc.push_back(attrDesc_int64);

        lcsAppendParams.inputProj.push_back(i);

        // create an empty page to start the btree

        if (newRoot) {
            BTreeBuilder builder(*pBTreeDesc, pRandomSegment);
            builder.createEmptyRoot();
            savedBTreeClusterRootIds.push_back(builder.getRootPageId());
        }
        lcsAppendParams.rootPageId = pBTreeDesc->rootPageId =
            savedBTreeClusterRootIds[i];

        // Now use the above initialized parameter

        ExecStreamEmbryo lcsAppendStreamEmbryo;
        lcsAppendStreamEmbryo.init(
            new LcsClusterAppendExecStream(), lcsAppendParams);
        std::ostringstream oss;
        oss << "LcsClusterAppendExecStream" << "#" << i;
        lcsAppendStreamEmbryo.getStream()->setName(oss.str());
        lcsAppendEmbryos.push_back(lcsAppendStreamEmbryo);
    }

    // 4. setup barrier stream for cluster loads

    BarrierExecStreamParams barrierParams;
    barrierParams.outputTupleDesc.push_back(attrDesc_int64);
    barrierParams.outputTupleDesc.push_back(attrDesc_int64);
    barrierParams.returnMode = BARRIER_RET_ANY_INPUT;

    ExecStreamEmbryo clusterBarrierStreamEmbryo;
    clusterBarrierStreamEmbryo.init(new BarrierExecStream(), barrierParams);
    clusterBarrierStreamEmbryo.getStream()->setName("ClusterBarrierExecStream");

    // create a DAG with the above, but without the final output sink
    prepareDAG(
        mockStreamEmbryo, splitterStreamEmbryo, lcsAppendEmbryos,
        clusterBarrierStreamEmbryo, false);

    // 5. setup splitter stream for create bitmaps

    splitterStreamEmbryo.init(
        new SplitterExecStream(), splitterParams);
    splitterStreamEmbryo.getStream()->setName("BitmapSplitterExecStream");

    // create streams for bitmap generator, sort, and bitmap splicer,
    // 1 index on each column and then an index on all columns

    std::vector<std::vector<ExecStreamEmbryo> > createBitmapStreamList;
    for (uint i = 0; i < nClusters + 1; i++) {
        if (i == 1 && nClusters == 1) {
            /*
             * There's only one column.
             * Do not bother to build the composite index.
             */
            break;
        }

        std::vector<ExecStreamEmbryo> createBitmapStream;

        // 6. setup generator

        LbmGeneratorExecStreamParams generatorParams;
        struct LcsClusterScanDef clusterScanDef;
        clusterScanDef.clusterTupleDesc.push_back(attrDesc_int64);

        // first nCluster generators only scan a single column; the
        // last one scans all columns
        if (i < nClusters) {
            DynamicParamId paramId =
                (dynamicRootPageId)
                ? DynamicParamId(nClusters + i + 2)
                : DynamicParamId(0);
            initClusterScanDef(generatorParams, clusterScanDef, i, paramId);
        } else {
            for (uint j = 0; j < nClusters; j++) {
                DynamicParamId paramId =
                    (dynamicRootPageId)
                    ? DynamicParamId(nClusters + 2 + j)
                    : DynamicParamId(0);
                initClusterScanDef(generatorParams, clusterScanDef, j, paramId);
            }
        }

        TupleProjection proj;
        if (i < nClusters) {
            proj.push_back(0);
        } else {
            for (uint j = 0; j < nClusters; j++) {
                proj.push_back(j);
            }
        }
        generatorParams.outputProj = proj;
        generatorParams.insertRowCountParamId = DynamicParamId(i + 1);
        generatorParams.createIndex = false;

        boost::shared_ptr<BTreeDescriptor> pBTreeDesc =
            boost::shared_ptr<BTreeDescriptor> (new BTreeDescriptor());
        bTreeBitmaps.push_back(pBTreeDesc);

        /*
         * Setup the dump objects.
         */
        if (dumpEntries) {
            ostringstream traceName;
            traceName << testName << " Index " << i;
            boost::shared_ptr<LbmEntryDump> pEntryDump =
                boost::shared_ptr<LbmEntryDump>(
                    new LbmEntryDump(
                        TRACE_INFO,
                        shared_from_this(),
                        traceName.str()));
            entryDumps.push_back(pEntryDump);
        }

        // BTree tuple desc has the key columns + starting Rid + varbinary
        // field for bit segments/bit descriptors
        uint nKeys;
        if (i < nClusters) {
            nKeys = 2;
        } else {
            nKeys = nClusters + 1;
        }
        initBTreeTupleDesc(generatorParams.outputTupleDesc, nKeys);

        initBTreeBitmapDesc(
            generatorParams.tupleDesc, generatorParams.keyProj, nKeys);
        initBTreeExecStreamParam(generatorParams, pBTreeDesc);

        // create an empty page to start the btree

        if (newRoot) {
            BTreeBuilder builder(*pBTreeDesc, pRandomSegment);
            builder.createEmptyRoot();
            savedBTreeBitmapRootIds.push_back(builder.getRootPageId());
        }
        generatorParams.rootPageId = pBTreeDesc->rootPageId =
            savedBTreeBitmapRootIds[i];
        if (dynamicRootPageId && i < nClusters) {
            SharedDynamicParamManager pDynamicParamManager =
                pGraph->getDynamicParamManager();
            DynamicParamId paramId = DynamicParamId(nClusters + i + 2);
            pDynamicParamManager->createParam(paramId, attrDesc_int64);
            TupleDatum pageIdDatum;
            PageId rootPageId = savedBTreeBitmapRootIds[i];
            pageIdDatum.pData = (PConstBuffer) &rootPageId;
            pageIdDatum.cbData = sizeof(PageId);
            pDynamicParamManager->writeParam(paramId, pageIdDatum);
        }

        ExecStreamEmbryo generatorStreamEmbryo;
        generatorStreamEmbryo.init(
            new LbmGeneratorExecStream(), generatorParams);
        std::ostringstream oss;
        oss << "LbmGeneratorExecStream" << "#" << i;
        generatorStreamEmbryo.getStream()->setName(oss.str());
        createBitmapStream.push_back(generatorStreamEmbryo);

        // 7. setup sorter

        ExternalSortExecStreamParams sortParams;
        initBTreeBitmapDesc(
            sortParams.outputTupleDesc, sortParams.keyProj, nKeys);
        sortParams.distinctness = DUP_ALLOW;
        sortParams.pTempSegment = pRandomSegment;
        sortParams.pCacheAccessor = pCache;
        sortParams.scratchAccessor =
            pSegmentFactory->newScratchSegment(pCache, 10);
        sortParams.storeFinalRun = false;
        sortParams.partitionKeyCount = 0;
        sortParams.estimatedNumRows = MAXU;
        sortParams.earlyClose = false;

        ExecStreamEmbryo sortStreamEmbryo;
        sortStreamEmbryo.init(
            ExternalSortExecStream::newExternalSortExecStream(), sortParams);
        sortStreamEmbryo.getStream()->setName("ExternalSortExecStream");
        std::ostringstream oss2;
        oss2 << "ExternalSortExecStream" << "#" << i;
        sortStreamEmbryo.getStream()->setName(oss2.str());
        createBitmapStream.push_back(sortStreamEmbryo);

        // 8. setup splicer

        LbmSplicerExecStreamParams splicerParams;
        splicerParams.createNewIndex = false;
        splicerParams.scratchAccessor =
            pSegmentFactory->newScratchSegment(pCache, 15);
        splicerParams.pCacheAccessor = pCache;
        BTreeParams bTreeParams;
        initBTreeBitmapDesc(
            bTreeParams.tupleDesc, bTreeParams.keyProj, nKeys);
        initBTreeParam(bTreeParams, pBTreeDesc);
        bTreeParams.rootPageId = pBTreeDesc->rootPageId;
        splicerParams.bTreeParams.push_back(bTreeParams);
        splicerParams.insertRowCountParamId = DynamicParamId(i + 1);
        splicerParams.writeRowCountParamId = DynamicParamId(0);
        splicerParams.outputTupleDesc.push_back(attrDesc_int64);

        ExecStreamEmbryo splicerStreamEmbryo;
        splicerStreamEmbryo.init(new LbmSplicerExecStream(), splicerParams);
        std::ostringstream oss3;
        oss3 << "LbmSplicerExecStream" << "#" << i;
        splicerStreamEmbryo.getStream()->setName(oss3.str());
        createBitmapStream.push_back(splicerStreamEmbryo);

        // connect the sorter and splicer to generator and then add this
        // newly connected stream to the list of create bitmap stream embryos
        createBitmapStreamList.push_back(createBitmapStream);
    }

    // 9. setup barrier stream for create bitmaps

    barrierParams.outputTupleDesc.clear();
    barrierParams.outputTupleDesc.push_back(attrDesc_int64);

    ExecStreamEmbryo barrierStreamEmbryo;
    barrierStreamEmbryo.init(
        new BarrierExecStream(), barrierParams);
    barrierStreamEmbryo.getStream()->setName("BitmapBarrierExecStream");

    // create the bitmap stream graph, with the load stream graph from
    // above as the source
    SharedExecStream pOutputStream = prepareDAG(
        clusterBarrierStreamEmbryo, splitterStreamEmbryo,
        createBitmapStreamList, barrierStreamEmbryo, true, false);

    // set up a generator which can produce the expected output
    RampExecStreamGenerator expectedResultGenerator(mockParams.nRows);

    verifyOutput(*pOutputStream, 1, expectedResultGenerator);

    if (dumpEntries) {
        for (uint i = 0; i < entryDumps.size(); i++) {
            entryDumps[i]->dump(*(bTreeBitmaps[i].get()), true);
        }
    }
}

void LbmLoadBitmapTest::initBTreeExecStreamParam(
    BTreeExecStreamParams &param, shared_ptr<BTreeDescriptor> pBTreeDesc)
{
    param.scratchAccessor = pSegmentFactory->newScratchSegment(pCache, 15);
    param.pCacheAccessor = pCache;
    initBTreeParam(param, pBTreeDesc);
}

void LbmLoadBitmapTest::initBTreeParam(
    BTreeParams &param, shared_ptr<BTreeDescriptor> pBTreeDesc)
{
    param.pSegment = pRandomSegment;
    param.pRootMap = 0;
    param.rootPageIdParamId = DynamicParamId(0);

    pBTreeDesc->segmentAccessor.pSegment = param.pSegment;
    pBTreeDesc->segmentAccessor.pCacheAccessor = pCache;
    pBTreeDesc->tupleDescriptor = param.tupleDesc;
    pBTreeDesc->keyProjection = param.keyProj;
    param.pageOwnerId = pBTreeDesc->pageOwnerId;
    param.segmentId = pBTreeDesc->segmentId;
}

void LbmLoadBitmapTest::initClusterScanDef(
    LbmGeneratorExecStreamParams &generatorParams,
    struct LcsClusterScanDef &clusterScanDef,
    uint bTreeIndex,
    DynamicParamId paramId)
{
    clusterScanDef.pSegment =
        bTreeClusters[bTreeIndex]->segmentAccessor.pSegment;
    clusterScanDef.pCacheAccessor =
        bTreeClusters[bTreeIndex]->segmentAccessor.pCacheAccessor;
    clusterScanDef.tupleDesc = bTreeClusters[bTreeIndex]->tupleDescriptor;
    clusterScanDef.keyProj = bTreeClusters[bTreeIndex]->keyProjection;
    clusterScanDef.rootPageIdParamId = paramId;
    clusterScanDef.rootPageId =
        (opaqueToInt(paramId) > 0)
        ? NULL_PAGE_ID
        : bTreeClusters[bTreeIndex]->rootPageId;
    clusterScanDef.pageOwnerId = bTreeClusters[bTreeIndex]->pageOwnerId;
    clusterScanDef.segmentId = bTreeClusters[bTreeIndex]->segmentId;
    clusterScanDef.pRootMap = 0;
    generatorParams.lcsClusterScanDefs.push_back(clusterScanDef);
}

void LbmLoadBitmapTest::initBTreeBitmapDesc(
    TupleDescriptor &tupleDesc, TupleProjection &keyProj, uint nKeys)
{
    initBTreeTupleDesc(tupleDesc, nKeys);

    // btree key consists of the key columns + starting rid
    for (uint j = 0; j < nKeys; j++) {
        keyProj.push_back(j);
    }
}

void LbmLoadBitmapTest::initBTreeTupleDesc(
    TupleDescriptor &tupleDesc, uint nKeys)
{
    for (uint i = 0; i < nKeys; i++) {
        tupleDesc.push_back(attrDesc_int64);
    }
    uint varColSize;

    // The default page size is 4K.
    varColSize = pRandomSegment->getUsablePageSize() / 8;
    // varColSize = 256;

    tupleDesc.push_back(
        TupleAttributeDescriptor(
            stdTypeFactory.newDataType(STANDARD_TYPE_VARBINARY), true,
            varColSize));
    tupleDesc.push_back(
        TupleAttributeDescriptor(
            stdTypeFactory.newDataType(STANDARD_TYPE_VARBINARY), true,
            varColSize));
}

void LbmLoadBitmapTest::testCaseSetUp()
{
    ExecStreamUnitTestBase::testCaseSetUp();

    attrDesc_int64 = TupleAttributeDescriptor(
        stdTypeFactory.newDataType(STANDARD_TYPE_INT_64));
}

void LbmLoadBitmapTest::testCaseTearDown()
{
    for (uint i = 0; i < bTreeClusters.size(); i++) {
        bTreeClusters[i]->segmentAccessor.reset();
    }
    for (uint i = 0; i < bTreeBitmaps.size(); i++) {
        bTreeBitmaps[i]->segmentAccessor.reset();
    }
    bTreeClusters.clear();
    bTreeBitmaps.clear();
    savedBTreeClusterRootIds.clear();
    savedBTreeBitmapRootIds.clear();
    entryDumps.clear();

    ExecStreamUnitTestBase::testCaseTearDown();
}

FENNEL_UNIT_TEST_SUITE(LbmLoadBitmapTest);

// End LbmLoadBitmapTest.cpp


text:
// -----------------------------------------------------------------------
// pion-common: a collection of common libraries used by the Pion Platform
// -----------------------------------------------------------------------
// Copyright (C) 2007-2011 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
//

#ifndef PION_STATIC_LINKING

#include <boost/filesystem.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/fstream.hpp>
#include <pion/PionConfig.hpp>
#include <pion/PionPlugin.hpp>
#include <pion/PionUnitTestDefs.hpp>
#include <boost/test/unit_test.hpp>
#include "PluginsUsedByUnitTests/InterfaceStub.hpp"

using namespace pion;

#if defined(PION_WIN32)
	static const std::string directoryOfPluginsForTests = "PluginsUsedByUnitTests/.libs";
	static const std::string sharedLibExt = ".dll";
#else
	#if defined(PION_XCODE)
		static const std::string directoryOfPluginsForTests = "PluginsUsedByUnitTests";
	#else
		static const std::string directoryOfPluginsForTests = "PluginsUsedByUnitTests/.libs";
	#endif
	static const std::string sharedLibExt = ".so";
#endif

class EmptyPluginPtr_F : public PionPluginPtr<InterfaceStub> {
public:
	EmptyPluginPtr_F() {
		BOOST_REQUIRE(GET_DIRECTORY(m_old_cwd, DIRECTORY_MAX_SIZE) != NULL);
		BOOST_REQUIRE(CHANGE_DIRECTORY(directoryOfPluginsForTests.c_str()) == 0);
	}
	~EmptyPluginPtr_F() {
		BOOST_CHECK(CHANGE_DIRECTORY(m_old_cwd) == 0);
	}

private:
	char m_old_cwd[DIRECTORY_MAX_SIZE+1];
};

BOOST_FIXTURE_TEST_SUITE(EmptyPluginPtr_S, EmptyPluginPtr_F)

BOOST_AUTO_TEST_CASE(checkIsOpenReturnsFalse) {
	BOOST_CHECK(!is_open());
}

BOOST_AUTO_TEST_CASE(checkCreateThrowsException) {
	BOOST_CHECK_THROW(create(), PluginUndefinedException);
}

BOOST_AUTO_TEST_CASE(checkDestroyThrowsException) {
	InterfaceStub* s = NULL;
	BOOST_CHECK_THROW(destroy(s), PluginUndefinedException);
}

BOOST_AUTO_TEST_CASE(checkOpenThrowsExceptionForNonExistentPlugin) {
	BOOST_REQUIRE(!boost::filesystem::exists("NoSuchPlugin" + sharedLibExt));
	BOOST_CHECK_THROW(open("NoSuchPlugin"), PluginNotFoundException);
}

BOOST_AUTO_TEST_CASE(checkGetPluginNameReturnsEmptyString) {
	BOOST_CHECK_EQUAL(getPluginName(), "");
}

BOOST_AUTO_TEST_CASE(checkPluginInstancePtrCreate) {
	PionPluginInstancePtr<InterfaceStub> m_instance_ptr;
	BOOST_CHECK(m_instance_ptr.empty());
	BOOST_CHECK(m_instance_ptr.get() == NULL);
	BOOST_REQUIRE(boost::filesystem::exists("hasCreateAndDestroy" + sharedLibExt));
	BOOST_CHECK_NO_THROW(m_instance_ptr.create("hasCreateAndDestroy"));
	BOOST_CHECK(! m_instance_ptr.empty());
	BOOST_CHECK(m_instance_ptr.get() != NULL);
}

BOOST_AUTO_TEST_CASE(checkPluginInstancePtrDereferencing) {
	PionPluginInstancePtr<InterfaceStub> m_instance_ptr;
	BOOST_CHECK_NO_THROW(m_instance_ptr.create("hasCreateAndDestroy"));
	const PionPluginInstancePtr<InterfaceStub>& const_ref = m_instance_ptr;
	InterfaceStub &a = *m_instance_ptr;
	const InterfaceStub &b = *const_ref;
	a.method();
	b.const_method();
	m_instance_ptr->method();
	const_ref->const_method();
}

BOOST_AUTO_TEST_CASE(checkOpenThrowsExceptionForNonPluginDll) {
	BOOST_REQUIRE(boost::filesystem::exists("hasNoCreate" + sharedLibExt));
	BOOST_CHECK_THROW(open("hasNoCreate"), PluginMissingCreateException);
}

BOOST_AUTO_TEST_CASE(checkOpenThrowsExceptionForPluginWithoutDestroy) {
	BOOST_REQUIRE(boost::filesystem::exists("hasCreateButNoDestroy" + sharedLibExt));
	BOOST_CHECK_THROW(open("hasCreateButNoDestroy"), PluginMissingDestroyException);
}

BOOST_AUTO_TEST_CASE(checkOpenDoesntThrowExceptionForValidPlugin) {
	BOOST_REQUIRE(boost::filesystem::exists("hasCreateAndDestroy" + sharedLibExt));
	BOOST_CHECK_NO_THROW(open("hasCreateAndDestroy"));
}

BOOST_AUTO_TEST_CASE(checkOpenFileDoesntThrowExceptionForValidPlugin) {
	BOOST_REQUIRE(boost::filesystem::exists("hasCreateAndDestroy" + sharedLibExt));
	BOOST_CHECK_NO_THROW(openFile("hasCreateAndDestroy" + sharedLibExt));
}

BOOST_AUTO_TEST_SUITE_END()

class EmptyPluginPtrWithPluginInSubdirectory_F : public EmptyPluginPtr_F {
public:
	EmptyPluginPtrWithPluginInSubdirectory_F() {
		boost::filesystem::remove_all("dir1");
		boost::filesystem::create_directory("dir1");
		boost::filesystem::create_directory("dir1/dir2");
		boost::filesystem::rename("hasCreateAndDestroy" + sharedLibExt, "dir1/dir2/hasCreateAndDestroy" + sharedLibExt);
	}
	~EmptyPluginPtrWithPluginInSubdirectory_F() {
		boost::filesystem::rename("dir1/dir2/hasCreateAndDestroy" + sharedLibExt, "hasCreateAndDestroy" + sharedLibExt);
		boost::filesystem::remove_all("dir1");
	}
};

BOOST_FIXTURE_TEST_SUITE(EmptyPluginPtrWithPluginInSubdirectory_S, EmptyPluginPtrWithPluginInSubdirectory_F)

BOOST_AUTO_TEST_CASE(checkOpenFileWithPathWithForwardSlashes) {
	BOOST_CHECK_NO_THROW(openFile("dir1/dir2/hasCreateAndDestroy" + sharedLibExt));
}

#ifdef PION_WIN32
BOOST_AUTO_TEST_CASE(checkOpenFileWithPathWithBackslashes) {
	BOOST_CHECK_NO_THROW(openFile("dir1\\dir2\\hasCreateAndDestroy" + sharedLibExt));
}
#endif

#ifdef PION_WIN32
BOOST_AUTO_TEST_CASE(checkOpenFileWithPathWithMixedSlashes) {
	BOOST_CHECK_NO_THROW(openFile("dir1\\dir2/hasCreateAndDestroy" + sharedLibExt));
}
#endif

BOOST_AUTO_TEST_SUITE_END()

/*
This is an example of a slightly different style of tests, where the object being
tested is included in the fixture, rather than inherited by the fixture.
These tests are a subset of those in the previous suite, for comparison purposes.
*/
struct EmptyPluginPtr2_F {
	EmptyPluginPtr2_F() : m_pluginPtr() {
		BOOST_REQUIRE(GET_DIRECTORY(m_old_cwd, DIRECTORY_MAX_SIZE) != NULL);
		BOOST_REQUIRE(CHANGE_DIRECTORY(directoryOfPluginsForTests.c_str()) == 0);
	}
	~EmptyPluginPtr2_F() {
		BOOST_CHECK(CHANGE_DIRECTORY(m_old_cwd) == 0);
	}

	char m_old_cwd[DIRECTORY_MAX_SIZE+1];
	PionPluginPtr<InterfaceStub> m_pluginPtr;
};

BOOST_FIXTURE_TEST_SUITE(EmptyPluginPtr2_S, EmptyPluginPtr2_F)

BOOST_AUTO_TEST_CASE(checkIsOpenReturnsFalse) {
	BOOST_CHECK(!m_pluginPtr.is_open());
}

BOOST_AUTO_TEST_CASE(checkCreateThrowsException) {
	BOOST_CHECK_THROW(m_pluginPtr.create(), PionPlugin::PluginUndefinedException);
}

BOOST_AUTO_TEST_CASE(checkDestroyThrowsException) {
	InterfaceStub* s = NULL;
	BOOST_CHECK_THROW(m_pluginPtr.destroy(s), PionPlugin::PluginUndefinedException);
}

BOOST_AUTO_TEST_CASE(checkOpenThrowsExceptionForNonExistentPlugin) {
	BOOST_CHECK_THROW(m_pluginPtr.open("NoSuchPlugin"), PionPlugin::PluginNotFoundException);
}

BOOST_AUTO_TEST_CASE(checkGetPluginNameReturnsEmptyString) {
	BOOST_CHECK_EQUAL(m_pluginPtr.getPluginName(), "");
}

BOOST_AUTO_TEST_CASE(checkOpenDoesntThrowExceptionForValidPlugin) {
	BOOST_REQUIRE(boost::filesystem::exists("hasCreateAndDestroy" + sharedLibExt));
	BOOST_CHECK_NO_THROW(m_pluginPtr.open("hasCreateAndDestroy"));
}

BOOST_AUTO_TEST_SUITE_END()

struct PluginPtrWithPluginLoaded_F : EmptyPluginPtr_F {
	PluginPtrWithPluginLoaded_F() {
		s = NULL;
		open("hasCreateAndDestroy");
	}
	~PluginPtrWithPluginLoaded_F() {
		if (s) destroy(s);
	}

	InterfaceStub* s;
};

BOOST_FIXTURE_TEST_SUITE(PluginPtrWithPluginLoaded_S, PluginPtrWithPluginLoaded_F)

BOOST_AUTO_TEST_CASE(checkIsOpenReturnsTrue) {
	BOOST_CHECK(is_open());
}

BOOST_AUTO_TEST_CASE(checkGetPluginNameReturnsPluginName) {
	BOOST_CHECK_EQUAL(getPluginName(), "hasCreateAndDestroy");
}

BOOST_AUTO_TEST_CASE(checkCreateReturnsSomething) {
	BOOST_CHECK((s = create()) != NULL);
}

BOOST_AUTO_TEST_CASE(checkDestroyDoesntThrowExceptionAfterCreate) {
	s = create();
	BOOST_CHECK_NO_THROW(destroy(s));
	s = NULL;
}

BOOST_AUTO_TEST_SUITE_END()

#ifdef PION_WIN32
	static const std::string fakePluginInSandboxWithExt = "sandbox\\fakePlugin.dll";
#else
	static const std::string fakePluginInSandboxWithExt = "sandbox/fakePlugin.so";
#endif
	static const std::string fakeConfigFileInSandboxWithExt = "sandbox/fakeConfigFile.conf";

class Sandbox_F {
public:
	Sandbox_F() {
# if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3
        m_cwd = boost::filesystem::current_path().string();
#else
        m_cwd = boost::filesystem::current_path().directory_string();
#endif

		boost::filesystem::remove_all("sandbox");
		BOOST_REQUIRE(boost::filesystem::create_directory("sandbox"));
		BOOST_REQUIRE(boost::filesystem::create_directory("sandbox/dir1"));
		BOOST_REQUIRE(boost::filesystem::create_directory("sandbox/dir1/dir1A"));
		BOOST_REQUIRE(boost::filesystem::create_directory("sandbox/dir2"));
		boost::filesystem::ofstream emptyFile(fakePluginInSandboxWithExt.c_str());
		emptyFile.close();
		boost::filesystem::ofstream emptyFile2(fakeConfigFileInSandboxWithExt.c_str());
		emptyFile2.close();
		m_path_to_file = "arbitraryString";
	}
	~Sandbox_F() {
		BOOST_REQUIRE(CHANGE_DIRECTORY(m_cwd.c_str()) == 0);
		boost::filesystem::remove_all("sandbox");
	}
	std::string m_path_to_file;

private:
	std::string m_cwd;
};

BOOST_FIXTURE_TEST_SUITE(Sandbox_S, Sandbox_F)

BOOST_AUTO_TEST_CASE(checkFindPluginFileReturnsFalseForNonexistentPlugin) {
	BOOST_CHECK(!PionPlugin::findPluginFile(m_path_to_file, "nonexistentPlugin"));
}

BOOST_AUTO_TEST_CASE(checkFindPluginFileReturnsFalseForExistingDirectory) {
	BOOST_CHECK(!PionPlugin::findPluginFile(m_path_to_file, "sandbox"));
}

BOOST_AUTO_TEST_CASE(checkFindPluginFileLeavesPathUnchangedForNonexistentPlugin) {
	BOOST_CHECK(!PionPlugin::findPluginFile(m_path_to_file, "nonexistentPlugin"));
	BOOST_CHECK_EQUAL(m_path_to_file, "arbitraryString");
}

BOOST_AUTO_TEST_CASE(checkFindPluginFileReturnsTrueForExistingPlugin) {
	BOOST_CHECK(PionPlugin::findPluginFile(m_path_to_file, "sandbox/fakePlugin"));
}

BOOST_AUTO_TEST_CASE(checkFindPluginFileReturnsCorrectPathForExistingPlugin) {
	BOOST_CHECK(PionPlugin::findPluginFile(m_path_to_file, "sandbox/fakePlugin"));
	BOOST_CHECK_EQUAL(m_path_to_file, fakePluginInSandboxWithExt);
}

BOOST_AUTO_TEST_CASE(checkFindPluginFileReturnsFalseForPluginNotOnSearchPath) {
	BOOST_CHECK(!PionPlugin::findPluginFile(m_path_to_file, "fakePlugin"));
}

BOOST_AUTO_TEST_CASE(checkFindConfigFileReturnsFalseForNonexistentConfigFile) {
	BOOST_CHECK(!PionPlugin::findConfigFile(m_path_to_file, "nonexistentConfigFile"));
}

BOOST_AUTO_TEST_CASE(checkFindConfigFileReturnsFalseForExistingDirectory) {
	BOOST_CHECK(!PionPlugin::findConfigFile(m_path_to_file, "sandbox"));
}

BOOST_AUTO_TEST_CASE(checkFindConfigFileReturnsTrueForExistingConfigFile) {
	BOOST_CHECK(PionPlugin::findConfigFile(m_path_to_file, "sandbox/fakeConfigFile"));
}

BOOST_AUTO_TEST_CASE(checkFindConfigFileReturnsCorrectPathForExistingConfigFile) {
	BOOST_CHECK(PionPlugin::findConfigFile(m_path_to_file, "sandbox/fakeConfigFile"));
	BOOST_CHECK(boost::filesystem::equivalent(m_path_to_file, fakeConfigFileInSandboxWithExt));
}

BOOST_AUTO_TEST_CASE(checkAddPluginDirectoryThrowsExceptionForNonexistentDirectory) {
	BOOST_CHECK_THROW(PionPlugin::addPluginDirectory("nonexistentDir"), PionPlugin::DirectoryNotFoundException);
}

BOOST_AUTO_TEST_CASE(checkAddPluginDirectoryWithCurrentDirectory) {
	BOOST_CHECK_NO_THROW(PionPlugin::addPluginDirectory("."));
}

BOOST_AUTO_TEST_CASE(checkAddPluginDirectoryWithExistingDirectory) {
	BOOST_CHECK_NO_THROW(PionPlugin::addPluginDirectory("sandbox"));
}

BOOST_AUTO_TEST_CASE(checkAddPluginDirectoryOneLevelUp) {
	BOOST_REQUIRE(CHANGE_DIRECTORY("sandbox/dir1") == 0);
	BOOST_CHECK_NO_THROW(PionPlugin::addPluginDirectory(".."));
}

// this test only works in Windows
#ifdef PION_WIN32
BOOST_AUTO_TEST_CASE(checkAddPluginDirectoryWithBackslashes) {
	BOOST_CHECK_NO_THROW(PionPlugin::addPluginDirectory("sandbox\\dir1\\dir1A"));
}
#endif

BOOST_AUTO_TEST_CASE(checkAddPluginDirectoryWithUpAndDownPath) {
	BOOST_REQUIRE(CHANGE_DIRECTORY("sandbox/dir1/dir1A") == 0);
	BOOST_CHECK_NO_THROW(PionPlugin::addPluginDirectory("../../dir2"));
}

BOOST_AUTO_TEST_CASE(checkAddPluginDirectoryThrowsExceptionForInvalidDirectory) {
	BOOST_CHECK_THROW(PionPlugin::addPluginDirectory("x:y"), PionPlugin::DirectoryNotFoundException);
}

BOOST_AUTO_TEST_CASE(checkResetPluginDirectoriesDoesntThrowException) {
	BOOST_CHECK_NO_THROW(PionPlugin::resetPluginDirectories());
}

BOOST_AUTO_TEST_SUITE_END()

class SandboxAddedAsPluginDirectory_F : public Sandbox_F {
public:
	SandboxAddedAsPluginDirectory_F() {
		PionPlugin::addPluginDirectory("sandbox");
	}
	~SandboxAddedAsPluginDirectory_F() {
		PionPlugin::resetPluginDirectories();
	}
};

BOOST_FIXTURE_TEST_SUITE(SandboxAddedAsPluginDirectory_S, SandboxAddedAsPluginDirectory_F)

BOOST_AUTO_TEST_CASE(checkFindPluginFileReturnsTrueForPluginOnSearchPath) {
	BOOST_CHECK(PionPlugin::findPluginFile(m_path_to_file, "fakePlugin"));
}

BOOST_AUTO_TEST_CASE(checkFindPluginFileReturnsTrueAfterChangingDirectory) {
	BOOST_REQUIRE(CHANGE_DIRECTORY("sandbox/dir1") == 0);
	BOOST_CHECK(PionPlugin::findPluginFile(m_path_to_file, "fakePlugin"));
}

BOOST_AUTO_TEST_CASE(checkResetPluginDirectoriesDoesntThrowException) {
	BOOST_CHECK_NO_THROW(PionPlugin::resetPluginDirectories());
}

BOOST_AUTO_TEST_CASE(checkFindPluginFileReturnsFalseForPluginOnSearchPathAfterReset) {
	PionPlugin::resetPluginDirectories();
	BOOST_CHECK(!PionPlugin::findPluginFile(m_path_to_file, "fakePlugin"));
}

BOOST_AUTO_TEST_SUITE_END()

#endif // PION_STATIC_LINKING

max_stars_repo_name: marshallmcmullen/pion

max_issues_repo_name: marshallmcmullen/pion

max_forks_repo_name: marshallmcmullen/pion


text:
// generate by pypp <https://github.com/mugwort-rc/pypp>
// original source code: SPK_Rotator.h

#include <Extensions/Modifiers/SPK_Rotator.h>
#include <boost/python.hpp>

class RotatorWrapper :
    public SPK::Rotator,
    public boost::python::wrapper<SPK::Rotator>
{
public:
    using SPK::Rotator::Rotator;
    std::string getClassName () const {
        if ( auto getClassName = this->get_override("getClassName") ) {
            return getClassName();
        } else {
            return Rotator::getClassName();
        }
    }
};

void init_SPK_Rotator_h() {
    boost::python::class_<RotatorWrapper, boost::python::bases<SPK::Modifier>, std::shared_ptr<SPK::Rotator>>("Rotator")
        .def("getClassName", &SPK::Rotator::getClassName)
        .def("create", &SPK::Rotator::create,
			":brief: Creates and registers a new Rotator\n"
			":return: A new registered Rotator\n",
			boost::python::return_value_policy<boost::python::reference_existing_object>())
        .staticmethod("create")
        ;
}

max_stars_repo_name: chromia/pyspk

max_issues_repo_name: chromia/pyspk

max_forks_repo_name: chromia/pyspk


text: #include <boost/units/physical_dimensions/torque.hpp>


text:
/*! \file
    \brief A comment removing reader.

    Copyright (C) 2019-2021 kaoru  https://www.tetengo.org/
*/

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <iterator>
#include <memory>
#include <queue>
#include <stdexcept>
#include <string>
#include <string_view>
#include <utility>

#include <boost/core/noncopyable.hpp>

#include <tetengo/json/comment_removing_reader.hpp>
#include <tetengo/json/reader.hpp>

namespace tetengo::json
{
    class comment_removing_reader::impl : private boost::noncopyable
    {
    public:
        // constructors and destructor

        impl(std::unique_ptr<reader>&& p_base_reader, std::string single_line_begin) :
        m_p_base_reader{ std::move(p_base_reader) },
        m_single_line_begin{ std::move(single_line_begin) },
        m_queue{}
        {
            if (!m_p_base_reader)
            {
                throw std::invalid_argument{ "p_base_reader is nullptr." };
            }
            if (std::empty(m_single_line_begin))
            {
                throw std::invalid_argument{ "single_line_begin is empty." };
            }
        }

        // functions

        bool has_next_impl() const
        {
            ensure_buffer_filled();
            return !std::empty(m_queue);
        }

        char peek_impl() const
        {
            ensure_buffer_filled();
            if (std::empty(m_queue))
            {
                throw std::logic_error{ "The current position is beyond the termination point." };
            }
            return m_queue.front();
        }

        void next_impl()
        {
            ensure_buffer_filled();
            if (std::empty(m_queue))
            {
                throw std::logic_error{ "The current position is beyond the termination point." };
            }
            m_queue.pop();
        }

        const reader& base_reader_impl() const
        {
            assert(m_p_base_reader);
            return *m_p_base_reader;
        }

    private:
        // static functions

        static std::size_t find_substring(const std::string_view& string_, const std::string_view& substring)
        {
            if (string_.length() < substring.length())
            {
                return std::string_view::npos;
            }

            auto quote = '\0';
            for (auto i = static_cast<std::size_t>(0); i < string_.length() - substring.length(); ++i)
            {
                if (quote == '\0' && (string_[i] == '\'' || string_[i] == '"'))
                {
                    quote = string_[i];
                    continue;
                }
                else if (quote != '\0')
                {
                    if (quote == string_[i])
                    {
                        quote = '\0';
                    }
                    continue;
                }

                auto found = true;
                for (auto j = static_cast<std::size_t>(0); j < substring.length(); ++j)
                {
                    if (string_[i + j] != substring[j])
                    {
                        found = false;
                        break;
                    }
                }

                if (found)
                {
                    return i;
                }
            }

            return std::string_view::npos;
        }

        // variables

        const std::unique_ptr<reader> m_p_base_reader;

        const std::string m_single_line_begin;

        mutable std::queue<char> m_queue;

        // functions

        void ensure_buffer_filled() const
        {
            if (!std::empty(m_queue))
            {
                return;
            }
            while (m_p_base_reader->has_next() && std::empty(m_queue))
            {
                auto line = read_line();
                line = remove_comment(line);
                std::for_each(std::begin(line), std::end(line), [this](const auto c) { m_queue.push(c); });
            }
        }

        std::string read_line() const
        {
            std::string line{};
            while (m_p_base_reader->has_next())
            {
                const auto char_ = m_p_base_reader->peek();
                m_p_base_reader->next();
                line.push_back(char_);
                if (char_ == '\n')
                {
                    break;
                }
            }
            return line;
        }

        std::string remove_comment(const std::string_view& line) const
        {
            const auto single_line_begin_offset = find_substring(line, m_single_line_begin);
            const auto line_feed_offset = line.find_first_of("\r\n");
            const auto comment_removed = line.substr(0, single_line_begin_offset);
            if (single_line_begin_offset != std::string_view::npos && line_feed_offset < line.length())
            {
                return std::string{ comment_removed } + std::string{ line.substr(line_feed_offset) };
            }
            else
            {
                return std::string{ comment_removed };
            }
        }
    };

    comment_removing_reader::comment_removing_reader(
        std::unique_ptr<reader>&& p_reader,
        std::string               single_line_begin) :
    m_p_impl{ std::make_unique<impl>(std::move(p_reader), std::move(single_line_begin)) }
    {}

    comment_removing_reader::~comment_removing_reader() = default;

    bool comment_removing_reader::has_next_impl() const
    {
        return m_p_impl->has_next_impl();
    }

    char comment_removing_reader::peek_impl() const
    {
        return m_p_impl->peek_impl();
    }

    void comment_removing_reader::next_impl()
    {
        m_p_impl->next_impl();
    }

    const reader& comment_removing_reader::base_reader_impl() const
    {
        return m_p_impl->base_reader_impl();
    }

}

max_stars_repo_name: kaorut/tetengo

max_issues_repo_name: kaorut/tetengo

max_forks_repo_name: kaorut/tetengo


text:
//Copyright (c) 2015 Zachary Kann
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.

// ---
// Author: Zachary Kann

// Provides convenient access to simulation parameters as well as the ability
// to read those parameters from an intuitive parameter file.

#include <iostream>
#include <fstream>
#include <string>
#include <armadillo>
#include "xdrfile_xtc.h"
#include "z_constants.hpp"

#ifndef _Z_SIMPARAMS_HPP_
#define _Z_SIMPARAMS_HPP_

enum CombRule {kC6C12, kLB, kGeometric};

class SimParams {
 public:
  // Wrapper for ReadParams
  inline void ReadParams(const std::string& filename) {
    set_filename(filename);
    ReadParams();
  }

  // Extracts box and timestep data from xtc file
  void ExtractTrajMetadata(char *traj, rvec **x_in, arma::rowvec& box);

  // Basically a mutator
  inline void set_temperature(const double temperature) {
    temperature_ = temperature;
    kT_ = KB*temperature;
    beta_ = 1.0/kT_;
  }

  // Basically a mutator
  inline void set_max_time(const double max_time) {
    if (max_time < 1.0e-5)
      max_steps_ = std::numeric_limits<int>::max();
    else
      max_steps_ = max_time / dt_;
  }

  // Mutators
  inline void set_filename(const std::string& filename) {
    filename_ = filename;
  }

  inline void set_comb_rule(const CombRule& comb_rule) {
    comb_rule_ = comb_rule;
  }

  // Mutators
  inline void set_box(arma::rowvec box) { box_ = box; }

  inline void set_box(matrix box_mat) {
    for(int i=0; i<DIMS; i++)
      box_(i) = box_mat[i][i];
  }

  // Basically an accessor
  inline int max_time() const { return (max_steps_*dt_); }

  // Accessors
  inline arma::rowvec box() const { return box_; }
  inline double box(int i) const { return box_(i); }
  inline double temperature() const { return temperature_;}
  inline double kT() const { return kT_;}
  inline double beta() const { return beta_;}
  inline double dt() const { return dt_; }
  inline int steps() const { return steps_; }
  inline int num_atoms() const { return num_atoms_; }
  inline int max_steps() const { return max_steps_; }

 private:
  // Uses parameter file to initialize class members.
  void ReadParams();

  CombRule comb_rule_;
  arma::rowvec box_;
  std::string filename_;
  std::ifstream file_;
  double temperature_;
  double kT_;
  double beta_;
  double dt_;
  int steps_;
  int num_atoms_;
  int max_steps_;
  int numMols_, numChromos_, wAtoms_;
  int numCations_, numAnions_;
  int numIons_, numOthers_;
  double rminOO_, rminOO2_;
  double rminC_, rminA_, rminAH_, rminC2_, rminA2_, rminAH2_;
  double rmin2C_, rmin2A_, rmin2C2_, rmin2A2_;
  double rmin3C_, rmin3A_, rmin3C2_, rmin3A2_;
  double gamm_, gammC_, gammA_;
};
#endif