<commit_before>// Copyright (c) 2016, Joseph Mirabel
// Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
//
// This file is part of hpp-pinocchio.
// hpp-pinocchio is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// hpp-pinocchio is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-pinocchio. If not, see <http://www.gnu.org/licenses/>.

#include <hpp/pinocchio/urdf/util.hh>

#include <urdf_parser/urdf_parser.h>

#include <hpp/fcl/mesh_loader/loader.h>

#include <pinocchio/parsers/utils.hpp>
#include <pinocchio/parsers/urdf.hpp>
#include <pinocchio/multibody/geometry.hpp>
#include <pinocchio/algorithm/geometry.hpp>
#include <pinocchio/algorithm/model.hpp>
#include <pinocchio/parsers/srdf.hpp>

#include <hpp/util/debug.hh>

#include <hpp/pinocchio/joint.hh>
#include <hpp/pinocchio/joint-collection.hh>
#include <hpp/pinocchio/device.hh>
#include <hpp/pinocchio/humanoid-robot.hh>

namespace hpp {
  namespace pinocchio {
    namespace urdf {
      namespace {
#ifdef HPP_DEBUG
        const bool verbose = true;
#else
        const bool verbose = false;
#endif

        JointPtr_t findSpecialJoint (const HumanoidRobotPtr_t& robot, const std::string& linkName)
        {
          return robot->getJointByBodyName (linkName);
        }

        void setSpecialJoints (const HumanoidRobotPtr_t& robot, std::string prefix)
        {
          if (!prefix.empty() && *prefix.rbegin() != '/') prefix += "/";
          try {
            robot->waist (robot->getJointByName(prefix + "root_joint"));
          } catch (const std::exception&) {
            hppDout (notice, "No waist joint found");
          }
          try {
            robot->chest (findSpecialJoint (robot, prefix + "chest"));
          } catch (const std::exception&) {
            hppDout (notice, "No chest joint found");
          }
          try {
            robot->leftWrist (findSpecialJoint (robot, prefix + "l_wrist"));
          } catch (const std::exception&) {
            hppDout (notice, "No left wrist joint found");
          }
          try {
            robot->rightWrist (findSpecialJoint (robot, prefix + "r_wrist"));
          } catch (const std::exception&) {
            hppDout (notice, "No right wrist joint found");
          }
          try {
            robot->leftAnkle (findSpecialJoint (robot, prefix + "l_ankle"));
          } catch (const std::exception&) {
            hppDout (notice, "No left ankle joint found");
          }
          try {
            robot->rightAnkle (findSpecialJoint (robot, prefix + "r_ankle"));
          } catch (const std::exception&) {
            hppDout (notice, "No right ankle joint found");
          }
          try {
            robot->gazeJoint (findSpecialJoint (robot, prefix + "gaze"));
          } catch (const std::exception&) {
            hppDout (notice, "No gaze joint found");
          }
        }

        void fillGaze (const HumanoidRobotPtr_t robot)
        {
          vector3_t dir, origin;
          // Gaze direction is defined by the gaze joint local
          // orientation.
          dir[0] = 1;
          dir[1] = 0;
          dir[2] = 0;
          // Gaze position should is defined by the gaze joint local
          // origin.
          origin[0] = 0;
          origin[1] = 0;
          origin[2] = 0;
          robot->gaze (dir, origin);
        }

        JointModelVariant buildJoint (const std::string& type)
        {
          if (type == "freeflyer")          return JointCollection::JointModelFreeFlyer();
          else if (type == "planar")        return JointCollection::JointModelPlanar();
          else if (type == "prismatic_x")   return JointCollection::JointModelPX();
          else if (type == "prismatic_y")   return JointCollection::JointModelPY();
          else if (type == "translation3d") return JointCollection::JointModelTranslation();
          else                          throw  std::invalid_argument
            ("Root joint type \"" + type + "\" is currently not available.");
        }

        void setPrefix (const std::string& prefix,
            Model& model, GeomModel& geomModel,
            const JointIndex& idFirstJoint,
            const FrameIndex& idFirstFrame)
        {
          for (JointIndex i = idFirstJoint; i < model.joints.size(); ++i) {
            model.names[i] = prefix + model.names[i];
          }
          for (FrameIndex i = idFirstFrame; i < model.frames.size(); ++i) {
            ::pinocchio::Frame& f = model.frames[i];
            f.name = prefix + f.name;
          }
          BOOST_FOREACH(::pinocchio::GeometryObject& go, geomModel.geometryObjects) {
            go.name = prefix + go.name;
          }
        }

        void setRootJointBounds(Model& model,
            const JointIndex& rtIdx,
            const std::string& rootType)
        {
          value_type b = std::numeric_limits<value_type>::infinity();
          if (rootType == "freeflyer") {
            const std::size_t idx = model.joints[rtIdx].idx_q();
            model.upperPositionLimit.segment<3>(idx).setConstant(+b);
            model.lowerPositionLimit.segment<3>(idx).setConstant(-b);
            // Quaternion bounds
            b = 1.01;
            const size_type quat_idx = idx + 3;
            model.upperPositionLimit.segment<4>(quat_idx).setConstant(+b);
            model.lowerPositionLimit.segment<4>(quat_idx).setConstant(-b);
          } else if (rootType == "planar") {
            const std::size_t idx = model.joints[rtIdx].idx_q();
            model.upperPositionLimit.segment<2>(idx).setConstant(+b);
            model.lowerPositionLimit.segment<2>(idx).setConstant(-b);
            // Unit complex bounds
            b = 1.01;
            const size_type cplx_idx = idx + 2;
            model.upperPositionLimit.segment<2>(cplx_idx).setConstant(+b);
            model.lowerPositionLimit.segment<2>(cplx_idx).setConstant(-b);
          }
        }

        std::string makeModelPath (const std::string& package,
                                   const std::string& type,
                                   const std::string& modelName,
                                   const std::string& suffix = "")
        {
          std::stringstream ss;
          ss << "package://" << package << "/" << type << "/" << modelName << suffix << "." << type;
          return ss.str();
        }

        template <bool XmlString>
        void _removeCollisionPairs (
            const Model& model,
            GeomModel& geomModel,
            const std::string& srdf,
            bool verbose)
        {
          ::pinocchio::srdf::removeCollisionPairsFromXML
            (model, geomModel, srdf, verbose);
        }

        template <>
        void _removeCollisionPairs<false> (
            const Model& model,
            GeomModel& geomModel,
            const std::string& srdf,
            bool verbose)
        {
          ::pinocchio::srdf::removeCollisionPairs
            (model, geomModel, srdf, verbose);
        }

        template <bool srdfAsXmlString>
        void _loadModel (const DevicePtr_t& robot,
                        const FrameIndex&  baseFrame,
                        std::string prefix,
                        const std::string& rootType,
                        const ::urdf::ModelInterfaceSharedPtr urdfTree,
                        const std::istream& urdfStream,
                        const std::string& srdf)
        {
          if (!urdfTree)
            throw std::invalid_argument ("Failed to parse URDF. Use check_urdf command to know what's wrong.");

          ModelPtr_t model = (baseFrame==0 ? robot->modelPtr() : ModelPtr_t(new Model));
          const JointIndex idFirstJoint = model->joints.size();
          const FrameIndex idFirstFrame = model->frames.size();
          if (rootType == "anchor")
            ::pinocchio::urdf::buildModel(urdfTree, *model, verbose);
          else
            ::pinocchio::urdf::buildModel(urdfTree, buildJoint(rootType), *model, verbose);

          hppDout (notice, "Finished parsing URDF file.");

          GeomModel geomModel;

          std::vector<std::string> baseDirs = ::pinocchio::rosPaths();
          fcl::MeshLoaderPtr loader (new fcl::CachedMeshLoader (fcl::BV_OBB));
          ::pinocchio::urdf::buildGeom(*model, urdfStream, ::pinocchio::COLLISION, geomModel, baseDirs, loader);
          geomModel.addAllCollisionPairs();

          if (!srdf.empty()) {
            _removeCollisionPairs<srdfAsXmlString>
              (*model, geomModel, srdf, verbose);
            if(!srdfAsXmlString)
              ::pinocchio::srdf::loadReferenceConfigurations(*model,srdf,verbose);
            else{
              hppDout(warning,"Neutral configuration won't be extracted from SRDF string.");
              //TODO : A method getNeutralConfigurationFromSrdfString must be added in Pinocchio,
              // similarly to removeCollisionPairsFromSrdf / removeCollisionPairsFromSrdfString
            }
          }

          if (!prefix.empty()) {
            if (*prefix.rbegin() != '/') prefix += "/";
            setPrefix(prefix, *model, geomModel, idFirstJoint, idFirstFrame);
          }

          // Update root joint bounds
          assert((rootType == "anchor")
              || (model->names[idFirstJoint] == prefix + "root_joint"));
          setRootJointBounds(*model, idFirstJoint, rootType);

          if (baseFrame == 0)
            ::pinocchio::appendGeometryModel(robot->geomModel(), geomModel);
          else {
            ModelPtr_t m (new Model);
            GeomModelPtr_t gm (new GeomModel);
            ::pinocchio::appendModel(robot->model(), *model,
                robot->geomModel(), geomModel,
                baseFrame, Transform3f::Identity(),
                *m, *gm);
          }

          robot->createData();
          robot->createGeomData();

          hppDout (notice, "Finished parsing SRDF file.");
        }

      }

      void loadRobotModel (const DevicePtr_t& robot,
			   const std::string& rootJointType,
			   const std::string& package,
			   const std::string& modelName,
			   const std::string& urdfSuffix,
                           const std::string& srdfSuffix)
      {
        loadModel (robot, 0, "", rootJointType,
            makeModelPath(package, "urdf", modelName, urdfSuffix),
            makeModelPath(package, "srdf", modelName, srdfSuffix));
      }

      void loadRobotModel (const DevicePtr_t& robot,
                           const FrameIndex&  baseFrame,
			   const std::string& prefix,
			   const std::string& rootJointType,
			   const std::string& package,
			   const std::string& modelName,
			   const std::string& urdfSuffix,
                           const std::string& srdfSuffix)
      {
        loadModel (robot, baseFrame,
            (prefix.empty() ? "" : prefix + "/"),
            rootJointType,
            makeModelPath(package, "urdf", modelName, urdfSuffix),
            makeModelPath(package, "srdf", modelName, srdfSuffix));
      }

      void setupHumanoidRobot (const HumanoidRobotPtr_t& robot,
          const std::string& prefix)
      {
	// Look for special joints and attach them to the model.
	setSpecialJoints (robot, prefix);
	// Fill gaze position and direction.
	fillGaze (robot);
      }

      void loadUrdfModel (const DevicePtr_t& robot,
                          const FrameIndex&  baseFrame,
                          const std::string& prefix,
			  const std::string& rootJointType,
			  const std::string& package,
			  const std::string& filename)
      {
        loadModel (robot, baseFrame,
            (prefix.empty() ? "" : prefix + "/"),
            rootJointType,
            makeModelPath(package, "urdf", filename), "");
      }

      void loadUrdfModel (const DevicePtr_t& robot,
			  const std::string& rootType,
			  const std::string& package,
			  const std::string& filename)
      {
        loadModel (robot, 0, "", rootType,
            makeModelPath(package, "urdf", filename), "");
      }

        void loadModel (const DevicePtr_t& robot,
                        const FrameIndex&  baseFrame,
                        const std::string& prefix,
                        const std::string& rootType,
                        const std::string& urdfPath,
                        const std::string& srdfPath)
        {
          std::vector<std::string> baseDirs = ::pinocchio::rosPaths();

          std::string urdfFileName = ::pinocchio::retrieveResourcePath(urdfPath, baseDirs);
          if (urdfFileName == "") {
            throw std::invalid_argument (std::string ("Unable to retrieve ") +
                urdfPath);
          }

          std::string srdfFileName;
          if (!srdfPath.empty()) {
            srdfFileName = ::pinocchio::retrieveResourcePath(srdfPath, baseDirs);
            if (srdfFileName == "") {
              throw std::invalid_argument (std::string ("Unable to retrieve ") +
                  srdfPath);
            }
          }

          ::urdf::ModelInterfaceSharedPtr urdfTree = ::urdf::parseURDFFile(urdfFileName);
          std::ifstream urdfStream (urdfFileName.c_str());
          _loadModel <false> (robot, baseFrame, prefix, rootType,
              urdfTree, urdfStream, srdfFileName);
        }

        void loadModelFromString (const DevicePtr_t& robot,
                                  const FrameIndex&  baseFrame,
                                  const std::string& prefix,
                                  const std::string& rootType,
                                  const std::string& urdfString,
                                  const std::string& srdfString)
        {
          ::urdf::ModelInterfaceSharedPtr urdfTree = ::urdf::parseURDF(urdfString);
          std::istringstream urdfStream (urdfString);
          _loadModel <true> (robot, baseFrame, prefix, rootType,
              urdfTree, urdfStream, srdfString);
        }
    } // end of namespace urdf.
  } // end of namespace pinocchio.
} // end of namespace  hpp.
<commit_msg>Make MeshLoader static to avoid reloading the same mesh several times.<commit_after>// Copyright (c) 2016, Joseph Mirabel
// Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
//
// This file is part of hpp-pinocchio.
// hpp-pinocchio is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// hpp-pinocchio is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-pinocchio. If not, see <http://www.gnu.org/licenses/>.

#include <hpp/pinocchio/urdf/util.hh>

#include <urdf_parser/urdf_parser.h>

#include <hpp/fcl/mesh_loader/loader.h>

#include <pinocchio/parsers/utils.hpp>
#include <pinocchio/parsers/urdf.hpp>
#include <pinocchio/multibody/geometry.hpp>
#include <pinocchio/algorithm/geometry.hpp>
#include <pinocchio/algorithm/model.hpp>
#include <pinocchio/parsers/srdf.hpp>

#include <hpp/util/debug.hh>

#include <hpp/pinocchio/joint.hh>
#include <hpp/pinocchio/joint-collection.hh>
#include <hpp/pinocchio/device.hh>
#include <hpp/pinocchio/humanoid-robot.hh>

namespace hpp {
  namespace pinocchio {
    namespace urdf {
      namespace {
#ifdef HPP_DEBUG
        const bool verbose = true;
#else
        const bool verbose = false;
#endif

        JointPtr_t findSpecialJoint (const HumanoidRobotPtr_t& robot, const std::string& linkName)
        {
          return robot->getJointByBodyName (linkName);
        }

        void setSpecialJoints (const HumanoidRobotPtr_t& robot, std::string prefix)
        {
          if (!prefix.empty() && *prefix.rbegin() != '/') prefix += "/";
          try {
            robot->waist (robot->getJointByName(prefix + "root_joint"));
          } catch (const std::exception&) {
            hppDout (notice, "No waist joint found");
          }
          try {
            robot->chest (findSpecialJoint (robot, prefix + "chest"));
          } catch (const std::exception&) {
            hppDout (notice, "No chest joint found");
          }
          try {
            robot->leftWrist (findSpecialJoint (robot, prefix + "l_wrist"));
          } catch (const std::exception&) {
            hppDout (notice, "No left wrist joint found");
          }
          try {
            robot->rightWrist (findSpecialJoint (robot, prefix + "r_wrist"));
          } catch (const std::exception&) {
            hppDout (notice, "No right wrist joint found");
          }
          try {
            robot->leftAnkle (findSpecialJoint (robot, prefix + "l_ankle"));
          } catch (const std::exception&) {
            hppDout (notice, "No left ankle joint found");
          }
          try {
            robot->rightAnkle (findSpecialJoint (robot, prefix + "r_ankle"));
          } catch (const std::exception&) {
            hppDout (notice, "No right ankle joint found");
          }
          try {
            robot->gazeJoint (findSpecialJoint (robot, prefix + "gaze"));
          } catch (const std::exception&) {
            hppDout (notice, "No gaze joint found");
          }
        }

        void fillGaze (const HumanoidRobotPtr_t robot)
        {
          vector3_t dir, origin;
          // Gaze direction is defined by the gaze joint local
          // orientation.
          dir[0] = 1;
          dir[1] = 0;
          dir[2] = 0;
          // Gaze position should is defined by the gaze joint local
          // origin.
          origin[0] = 0;
          origin[1] = 0;
          origin[2] = 0;
          robot->gaze (dir, origin);
        }

        JointModelVariant buildJoint (const std::string& type)
        {
          if (type == "freeflyer")          return JointCollection::JointModelFreeFlyer();
          else if (type == "planar")        return JointCollection::JointModelPlanar();
          else if (type == "prismatic_x")   return JointCollection::JointModelPX();
          else if (type == "prismatic_y")   return JointCollection::JointModelPY();
          else if (type == "translation3d") return JointCollection::JointModelTranslation();
          else                          throw  std::invalid_argument
            ("Root joint type \"" + type + "\" is currently not available.");
        }

        void setPrefix (const std::string& prefix,
            Model& model, GeomModel& geomModel,
            const JointIndex& idFirstJoint,
            const FrameIndex& idFirstFrame)
        {
          for (JointIndex i = idFirstJoint; i < model.joints.size(); ++i) {
            model.names[i] = prefix + model.names[i];
          }
          for (FrameIndex i = idFirstFrame; i < model.frames.size(); ++i) {
            ::pinocchio::Frame& f = model.frames[i];
            f.name = prefix + f.name;
          }
          BOOST_FOREACH(::pinocchio::GeometryObject& go, geomModel.geometryObjects) {
            go.name = prefix + go.name;
          }
        }

        void setRootJointBounds(Model& model,
            const JointIndex& rtIdx,
            const std::string& rootType)
        {
          value_type b = std::numeric_limits<value_type>::infinity();
          if (rootType == "freeflyer") {
            const std::size_t idx = model.joints[rtIdx].idx_q();
            model.upperPositionLimit.segment<3>(idx).setConstant(+b);
            model.lowerPositionLimit.segment<3>(idx).setConstant(-b);
            // Quaternion bounds
            b = 1.01;
            const size_type quat_idx = idx + 3;
            model.upperPositionLimit.segment<4>(quat_idx).setConstant(+b);
            model.lowerPositionLimit.segment<4>(quat_idx).setConstant(-b);
          } else if (rootType == "planar") {
            const std::size_t idx = model.joints[rtIdx].idx_q();
            model.upperPositionLimit.segment<2>(idx).setConstant(+b);
            model.lowerPositionLimit.segment<2>(idx).setConstant(-b);
            // Unit complex bounds
            b = 1.01;
            const size_type cplx_idx = idx + 2;
            model.upperPositionLimit.segment<2>(cplx_idx).setConstant(+b);
            model.lowerPositionLimit.segment<2>(cplx_idx).setConstant(-b);
          }
        }

        std::string makeModelPath (const std::string& package,
                                   const std::string& type,
                                   const std::string& modelName,
                                   const std::string& suffix = "")
        {
          std::stringstream ss;
          ss << "package://" << package << "/" << type << "/" << modelName << suffix << "." << type;
          return ss.str();
        }

        template <bool XmlString>
        void _removeCollisionPairs (
            const Model& model,
            GeomModel& geomModel,
            const std::string& srdf,
            bool verbose)
        {
          ::pinocchio::srdf::removeCollisionPairsFromXML
            (model, geomModel, srdf, verbose);
        }

        template <>
        void _removeCollisionPairs<false> (
            const Model& model,
            GeomModel& geomModel,
            const std::string& srdf,
            bool verbose)
        {
          ::pinocchio::srdf::removeCollisionPairs
            (model, geomModel, srdf, verbose);
        }

        template <bool srdfAsXmlString>
        void _loadModel (const DevicePtr_t& robot,
                        const FrameIndex&  baseFrame,
                        std::string prefix,
                        const std::string& rootType,
                        const ::urdf::ModelInterfaceSharedPtr urdfTree,
                        const std::istream& urdfStream,
                        const std::string& srdf)
        {
          if (!urdfTree)
            throw std::invalid_argument ("Failed to parse URDF. Use check_urdf command to know what's wrong.");

          ModelPtr_t model = (baseFrame==0 ? robot->modelPtr() : ModelPtr_t(new Model));
          const JointIndex idFirstJoint = model->joints.size();
          const FrameIndex idFirstFrame = model->frames.size();
          if (rootType == "anchor")
            ::pinocchio::urdf::buildModel(urdfTree, *model, verbose);
          else
            ::pinocchio::urdf::buildModel(urdfTree, buildJoint(rootType), *model, verbose);

          hppDout (notice, "Finished parsing URDF file.");

          GeomModel geomModel;

          std::vector<std::string> baseDirs = ::pinocchio::rosPaths();
          static fcl::MeshLoaderPtr loader (new fcl::CachedMeshLoader (fcl::BV_OBB));
          ::pinocchio::urdf::buildGeom(*model, urdfStream, ::pinocchio::COLLISION, geomModel, baseDirs, loader);
          geomModel.addAllCollisionPairs();

          if (!srdf.empty()) {
            _removeCollisionPairs<srdfAsXmlString>
              (*model, geomModel, srdf, verbose);
            if(!srdfAsXmlString)
              ::pinocchio::srdf::loadReferenceConfigurations(*model,srdf,verbose);
            else{
              hppDout(warning,"Neutral configuration won't be extracted from SRDF string.");
              //TODO : A method getNeutralConfigurationFromSrdfString must be added in Pinocchio,
              // similarly to removeCollisionPairsFromSrdf / removeCollisionPairsFromSrdfString
            }
          }

          if (!prefix.empty()) {
            if (*prefix.rbegin() != '/') prefix += "/";
            setPrefix(prefix, *model, geomModel, idFirstJoint, idFirstFrame);
          }

          // Update root joint bounds
          assert((rootType == "anchor")
              || (model->names[idFirstJoint] == prefix + "root_joint"));
          setRootJointBounds(*model, idFirstJoint, rootType);

          if (baseFrame == 0)
            ::pinocchio::appendGeometryModel(robot->geomModel(), geomModel);
          else {
            ModelPtr_t m (new Model);
            GeomModelPtr_t gm (new GeomModel);
            ::pinocchio::appendModel(robot->model(), *model,
                robot->geomModel(), geomModel,
                baseFrame, Transform3f::Identity(),
                *m, *gm);
          }

          robot->createData();
          robot->createGeomData();

          hppDout (notice, "Finished parsing SRDF file.");
        }

      }

      void loadRobotModel (const DevicePtr_t& robot,
			   const std::string& rootJointType,
			   const std::string& package,
			   const std::string& modelName,
			   const std::string& urdfSuffix,
                           const std::string& srdfSuffix)
      {
        loadModel (robot, 0, "", rootJointType,
            makeModelPath(package, "urdf", modelName, urdfSuffix),
            makeModelPath(package, "srdf", modelName, srdfSuffix));
      }

      void loadRobotModel (const DevicePtr_t& robot,
                           const FrameIndex&  baseFrame,
			   const std::string& prefix,
			   const std::string& rootJointType,
			   const std::string& package,
			   const std::string& modelName,
			   const std::string& urdfSuffix,
                           const std::string& srdfSuffix)
      {
        loadModel (robot, baseFrame,
            (prefix.empty() ? "" : prefix + "/"),
            rootJointType,
            makeModelPath(package, "urdf", modelName, urdfSuffix),
            makeModelPath(package, "srdf", modelName, srdfSuffix));
      }

      void setupHumanoidRobot (const HumanoidRobotPtr_t& robot,
          const std::string& prefix)
      {
	// Look for special joints and attach them to the model.
	setSpecialJoints (robot, prefix);
	// Fill gaze position and direction.
	fillGaze (robot);
      }

      void loadUrdfModel (const DevicePtr_t& robot,
                          const FrameIndex&  baseFrame,
                          const std::string& prefix,
			  const std::string& rootJointType,
			  const std::string& package,
			  const std::string& filename)
      {
        loadModel (robot, baseFrame,
            (prefix.empty() ? "" : prefix + "/"),
            rootJointType,
            makeModelPath(package, "urdf", filename), "");
      }

      void loadUrdfModel (const DevicePtr_t& robot,
			  const std::string& rootType,
			  const std::string& package,
			  const std::string& filename)
      {
        loadModel (robot, 0, "", rootType,
            makeModelPath(package, "urdf", filename), "");
      }

        void loadModel (const DevicePtr_t& robot,
                        const FrameIndex&  baseFrame,
                        const std::string& prefix,
                        const std::string& rootType,
                        const std::string& urdfPath,
                        const std::string& srdfPath)
        {
          std::vector<std::string> baseDirs = ::pinocchio::rosPaths();

          std::string urdfFileName = ::pinocchio::retrieveResourcePath(urdfPath, baseDirs);
          if (urdfFileName == "") {
            throw std::invalid_argument (std::string ("Unable to retrieve ") +
                urdfPath);
          }

          std::string srdfFileName;
          if (!srdfPath.empty()) {
            srdfFileName = ::pinocchio::retrieveResourcePath(srdfPath, baseDirs);
            if (srdfFileName == "") {
              throw std::invalid_argument (std::string ("Unable to retrieve ") +
                  srdfPath);
            }
          }

          ::urdf::ModelInterfaceSharedPtr urdfTree = ::urdf::parseURDFFile(urdfFileName);
          std::ifstream urdfStream (urdfFileName.c_str());
          _loadModel <false> (robot, baseFrame, prefix, rootType,
              urdfTree, urdfStream, srdfFileName);
        }

        void loadModelFromString (const DevicePtr_t& robot,
                                  const FrameIndex&  baseFrame,
                                  const std::string& prefix,
                                  const std::string& rootType,
                                  const std::string& urdfString,
                                  const std::string& srdfString)
        {
          ::urdf::ModelInterfaceSharedPtr urdfTree = ::urdf::parseURDF(urdfString);
          std::istringstream urdfStream (urdfString);
          _loadModel <true> (robot, baseFrame, prefix, rootType,
              urdfTree, urdfStream, srdfString);
        }
    } // end of namespace urdf.
  } // end of namespace pinocchio.
} // end of namespace  hpp.
<|endoftext|>


<commit_before><commit_msg>Fixing simplex identation<commit_after><|endoftext|>


<commit_before>//===--- Alloc.cpp - Swift Language ABI Allocation Support ----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Allocation ABI Shims While the Language is Bootstrapped
//
//===----------------------------------------------------------------------===//
//===--- Alloc.h - Swift Language Allocation ABI --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Swift Allocation ABI
//
//===----------------------------------------------------------------------===//

#include "Alloc.h"
#include <stdlib.h>
#include <unistd.h>

struct SwiftHeapObject *
swift_alloc(struct SwiftHeapMetadata *metadata,
            size_t requiredSize,
            size_t requiredAlignment)
{
  size_t mask = requiredAlignment - 1;
  struct SwiftHeapMetadata **object;
  for (;;) {
    object = reinterpret_cast<struct SwiftHeapMetadata **>(
      calloc(1, (requiredSize + mask) & ~mask));
    if (object) {
      break;
    }
    sleep(1); // XXX FIXME -- Enqueue this thread and resume after free()
  }
  *object = metadata;
  return reinterpret_cast<struct SwiftHeapObject *>(object);
}

struct SwiftHeapObject *
swift_retain(struct SwiftHeapObject *object)
{
  ++object->runtimePrivateData;
  return object;
}

void
swift_release(struct SwiftHeapObject *object)
{
  if (--object->runtimePrivateData > 0) {
    return;
  }
  size_t allocSize = object->metadata->destroy(object);
  if (allocSize) {
    swift_dealloc(object, allocSize);
  }
}

void
swift_dealloc(struct SwiftHeapObject *object, size_t allocatedSize)
{
  free(object);
}
<commit_msg>Make retain/release NULL check object for now<commit_after>//===--- Alloc.cpp - Swift Language ABI Allocation Support ----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Allocation ABI Shims While the Language is Bootstrapped
//
//===----------------------------------------------------------------------===//
//===--- Alloc.h - Swift Language Allocation ABI --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Swift Allocation ABI
//
//===----------------------------------------------------------------------===//

#include "Alloc.h"
#include <stdlib.h>
#include <unistd.h>

struct SwiftHeapObject *
swift_alloc(struct SwiftHeapMetadata *metadata,
            size_t requiredSize,
            size_t requiredAlignment)
{
  size_t mask = requiredAlignment - 1;
  struct SwiftHeapMetadata **object;
  for (;;) {
    object = reinterpret_cast<struct SwiftHeapMetadata **>(
      calloc(1, (requiredSize + mask) & ~mask));
    if (object) {
      break;
    }
    sleep(1); // XXX FIXME -- Enqueue this thread and resume after free()
  }
  *object = metadata;
  return reinterpret_cast<struct SwiftHeapObject *>(object);
}

struct SwiftHeapObject *
swift_retain(struct SwiftHeapObject *object)
{
  if (!object) {
    return NULL;
  }
  ++object->runtimePrivateData;
  return object;
}

void
swift_release(struct SwiftHeapObject *object)
{
  if (!object) {
    return;
  }
  if (--object->runtimePrivateData > 0) {
    return;
  }
  size_t allocSize = object->metadata->destroy(object);
  if (allocSize) {
    swift_dealloc(object, allocSize);
  }
}

void
swift_dealloc(struct SwiftHeapObject *object, size_t allocatedSize)
{
  free(object);
}
<|endoftext|>


<commit_before>#include <atomic>
#include <map>
#include <set>

#include "block.hpp"
#include "hash.hpp"
#include "hvectors.hpp"

struct processFunctor_t {
	virtual ~processFunctor_t () {}

	virtual bool initialize (const char*) {
		return false;
	}
	virtual void operator() (const Block&) = 0;
};

struct whitelisted_t : processFunctor_t {
	HSet<hash256_t> whitelist;

	bool initialize (const char* arg) {
		if (strncmp(arg, "-w", 2) == 0) {
			const auto fileName = std::string(arg + 2);
			const auto file = fopen(fileName.c_str(), "r");
			assert(file != nullptr);

			fseek(file, 0, SEEK_END);
			const auto fileSize = ftell(file);
			fseek(file, 0, SEEK_SET);

			assert(sizeof(this->whitelist[0]) == 32);
			assert(fileSize % sizeof(this->whitelist[0]) == 0);

			this->whitelist.resize(fileSize / sizeof(hash256_t));
			const auto read = fread(&this->whitelist[0], fileSize, 1, file);
			assert(read == 1);

			fclose(file);
			assert(!this->whitelist.empty());
			assert(std::is_sorted(this->whitelist.begin(), this->whitelist.end()));

			std::cerr << "Whitelisted " << this->whitelist.size() << " hashes" << std::endl;

			return true;
		}

		return false;
	}

	bool shouldSkip (const Block& block) const {
		if (this->whitelist.empty()) return false;

		hash256_t hash;
		hash256(&hash[0], block.header);
		return !this->whitelist.contains(hash);
	}

	bool shouldSkip (const hash256_t& hash) const {
		if (this->whitelist.empty()) return false;

		return !this->whitelist.contains(hash);
	}
};

// XXX: fwrite can be used without sizeof(sbuf) < PIPE_BUF (4096 bytes)

// BLOCK_HEADER > stdout
struct dumpHeaders : whitelisted_t {
	void operator() (const Block& block) {
		if (this->shouldSkip(block)) return;

		fwrite(block.header.begin, 80, 1, stdout);
	}
};

// SCRIPT_LENGTH | SCRIPT > stdout
struct dumpScripts : whitelisted_t {
	void operator() (const Block& block) {
		if (this->shouldSkip(block)) return;

		uint8_t sbuf[4096];
		const auto maxScriptLength = sizeof(sbuf) - sizeof(uint16_t);

		auto transactions = block.transactions();
		while (!transactions.empty()) {
			const auto& transaction = transactions.front();

			for (const auto& input : transaction.inputs) {
				if (input.script.length() > maxScriptLength) continue;
				const auto scriptLength = static_cast<uint16_t>(input.script.length());

				Slice(sbuf, sbuf + sizeof(sbuf)).put(scriptLength);
				memcpy(sbuf + sizeof(uint16_t), input.script.begin, scriptLength);
				fwrite(sbuf, sizeof(uint16_t) + scriptLength, 1, stdout);
			}

			for (const auto& output : transaction.outputs) {
				if (output.script.length() > maxScriptLength) continue;
				const auto scriptLength = static_cast<uint16_t>(output.script.length());

				Slice(sbuf, sbuf + sizeof(sbuf)).put(scriptLength);
				memcpy(sbuf + sizeof(uint16_t), output.script.begin, scriptLength);
				fwrite(sbuf, sizeof(uint16_t) + scriptLength, 1, stdout);
			}

			transactions.popFront();
		}
	}
};

// PREV_TX_HASH | PREV_TX_VOUT | TX_HASH > stdout
struct dumpTxOutIndex : whitelisted_t {
	void operator() (const Block& block) {
		if (this->shouldSkip(block)) return;

		uint8_t sbuf[68];

		auto transactions = block.transactions();
		while (!transactions.empty()) {
			const auto& transaction = transactions.front();

			hash256(sbuf + 36, transaction.data);

			for (const auto& input : transaction.inputs) {
				memcpy(sbuf, input.hash.begin, 32);
				Slice(sbuf + 32, sbuf + 36).put(input.vout);

				fwrite(sbuf, sizeof(sbuf), 1, stdout);
			}

			transactions.popFront();
		}
	}
};

auto perc (uint64_t a, uint64_t ab) {
	return static_cast<double>(a) / static_cast<double>(ab);
}

struct dumpStatistics : whitelisted_t {
	std::atomic_ulong inputs;
	std::atomic_ulong outputs;
	std::atomic_ulong transactions;
	std::atomic_ulong version1;
	std::atomic_ulong version2;
	std::atomic_ulong locktimesGt0;

	dumpStatistics () {
		this->inputs = 0;
		this->outputs = 0;
		this->transactions = 0;
		this->version1 = 0;
		this->version2 = 0;
		this->locktimesGt0 = 0;
	}

	~dumpStatistics () {
		std::cout <<
			"Transactions:\t" << this->transactions << '\n' <<
			"-- Inputs:\t" << this->inputs << " (ratio " << perc(this->inputs, this->transactions) << ") \n" <<
			"-- Outputs:\t" << this->outputs << " (ratio " << perc(this->outputs, this->transactions) << ") \n" <<
			"-- Version1:\t" << this->version1 << " (" << perc(this->version1, this->transactions) * 100 << "%) \n" <<
			"-- Version2:\t" << this->version2 << " (" << perc(this->version2, this->transactions) * 100 << "%) \n" <<
			"-- Locktimes (>0):\t" << this->locktimesGt0 << " (" << perc(this->locktimesGt0, this->transactions) * 100 << "%) \n" <<
			std::endl;
	}

	void operator() (const Block& block) {
		if (this->shouldSkip(block)) return;

		auto transactions = block.transactions();
		this->transactions += transactions.length();

		while (!transactions.empty()) {
			const auto& transaction = transactions.front();

			this->inputs += transaction.inputs.size();
			this->outputs += transaction.outputs.size();

			this->version1 += transaction.version == 1;
			this->version2 += transaction.version == 2;
			this->locktimesGt0 += transaction.locktime > 0;

			transactions.popFront();
		}
	}
};

// SHA1(TX_HASH | VOUT) | SHA1(OUTPUT_SCRIPT) > stdout
struct dumpScriptIndexMap : whitelisted_t {
	void operator() (const Block& block) {
		if (this->shouldSkip(block)) return;

		uint8_t sbuf[40] = {};
		uint8_t tbuf[36] = {};

		auto transactions = block.transactions();
		while (!transactions.empty()) {
			const auto& transaction = transactions.front();

			hash256(tbuf, transaction.data);

			uint32_t vout = 0;
			for (const auto& output : transaction.outputs) {
				Slice(tbuf + 32, tbuf + sizeof(tbuf)).put(vout);
				++vout;

				sha1(sbuf, tbuf, sizeof(tbuf));
				sha1(sbuf + 20, output.script);

				fwrite(sbuf, sizeof(sbuf), 1, stdout);
			}

			transactions.popFront();
		}
	}
};

const uint8_t COINBASE[32] = {};

// BLOCK_HASH | TX_HASH | SHA1(PREVIOUS_OUTPUT_SCRIPT) > stdout
// BLOCK_HASH | TX_HASH | SHA1(OUTPUT_SCRIPT) > stdout
struct dumpScriptIndex : whitelisted_t {
	HMap<hash160_t, hash160_t> txOuts;

	bool initialize (const char* arg) {
		if (whitelisted_t::initialize(arg)) return true;
		if (strncmp(arg, "-i", 2) == 0) {
			const auto fileName = std::string(arg + 2);
			const auto file = fopen(fileName.c_str(), "r");
			assert(file != nullptr);

			fseek(file, 0, SEEK_END);
			const auto fileSize = ftell(file);
			fseek(file, 0, SEEK_SET);

			assert(sizeof(this->txOuts[0]) == 40);
			assert(fileSize % sizeof(this->txOuts[0]) == 0);

			this->txOuts.resize(fileSize / sizeof(this->txOuts[0]));
			const auto read = fread(&this->txOuts[0], fileSize, 1, file);
			assert(read == 1);

			fclose(file);
			assert(!this->txOuts.empty());
			assert(std::is_sorted(this->txOuts.begin(), this->txOuts.end()));

			std::cerr << "Mapped " << this->txOuts.size() << " txOuts" << std::endl;

			return true;
		}

		return false;
	}

	void operator() (const Block& block) {
		hash256_t hash;
		hash256(&hash[0], block.header);
		if (this->shouldSkip(hash)) return;

		uint8_t sbuf[84] = {};
		memcpy(sbuf, &hash[0], 32);

		auto transactions = block.transactions();
		while (!transactions.empty()) {
			const auto& transaction = transactions.front();

			hash256(sbuf + 32, transaction.data);

			if (!this->txOuts.empty()) {
				for (const auto& input : transaction.inputs) {
					// Coinbase input?
					if (
						input.vout == 0xffffffff &&
						memcmp(input.hash.begin, COINBASE, sizeof(COINBASE)) == 0
					) {
						sha1(&hash[0], input.script);
						memcpy(sbuf + 64, &hash[0], 20);
						fwrite(sbuf, sizeof(sbuf), 1, stdout);

						continue;
					}

					hash160_t hash;
					sha1(&hash[0], input.data.take(36));

					const auto txOutIter = this->txOuts.find(hash);
					assert(txOutIter != this->txOuts.end());

					memcpy(sbuf + 64, &(txOutIter->second)[0], 20);
					fwrite(sbuf, sizeof(sbuf), 1, stdout);
				}
			}

			for (const auto& output : transaction.outputs) {
				sha1(sbuf + 64, output.script);
				fwrite(sbuf, sizeof(sbuf), 1, stdout);
			}

			transactions.popFront();
		}
	}
};
<commit_msg>functors; add output values over time dump<commit_after>#include <atomic>
#include <map>
#include <set>

#include "block.hpp"
#include "hash.hpp"
#include "hvectors.hpp"

struct processFunctor_t {
	virtual ~processFunctor_t () {}

	virtual bool initialize (const char*) {
		return false;
	}
	virtual void operator() (const Block&) = 0;
};

struct whitelisted_t : processFunctor_t {
	HSet<hash256_t> whitelist;

	bool initialize (const char* arg) {
		if (strncmp(arg, "-w", 2) == 0) {
			const auto fileName = std::string(arg + 2);
			const auto file = fopen(fileName.c_str(), "r");
			assert(file != nullptr);

			fseek(file, 0, SEEK_END);
			const auto fileSize = ftell(file);
			fseek(file, 0, SEEK_SET);

			assert(sizeof(this->whitelist[0]) == 32);
			assert(fileSize % sizeof(this->whitelist[0]) == 0);

			this->whitelist.resize(fileSize / sizeof(hash256_t));
			const auto read = fread(&this->whitelist[0], fileSize, 1, file);
			assert(read == 1);

			fclose(file);
			assert(!this->whitelist.empty());
			assert(std::is_sorted(this->whitelist.begin(), this->whitelist.end()));

			std::cerr << "Whitelisted " << this->whitelist.size() << " hashes" << std::endl;

			return true;
		}

		return false;
	}

	bool shouldSkip (const Block& block) const {
		if (this->whitelist.empty()) return false;

		hash256_t hash;
		hash256(&hash[0], block.header);
		return !this->whitelist.contains(hash);
	}

	bool shouldSkip (const hash256_t& hash) const {
		if (this->whitelist.empty()) return false;

		return !this->whitelist.contains(hash);
	}
};

// XXX: fwrite can be used without sizeof(sbuf) < PIPE_BUF (4096 bytes)

// BLOCK_HEADER > stdout
struct dumpHeaders : whitelisted_t {
	void operator() (const Block& block) {
		if (this->shouldSkip(block)) return;

		fwrite(block.header.begin, 80, 1, stdout);
	}
};

// SCRIPT_LENGTH | SCRIPT > stdout
struct dumpScripts : whitelisted_t {
	void operator() (const Block& block) {
		if (this->shouldSkip(block)) return;

		uint8_t sbuf[4096];
		const auto maxScriptLength = sizeof(sbuf) - sizeof(uint16_t);

		auto transactions = block.transactions();
		while (!transactions.empty()) {
			const auto& transaction = transactions.front();

			for (const auto& input : transaction.inputs) {
				if (input.script.length() > maxScriptLength) continue;
				const auto scriptLength = static_cast<uint16_t>(input.script.length());

				Slice(sbuf, sbuf + sizeof(sbuf)).put(scriptLength);
				memcpy(sbuf + sizeof(uint16_t), input.script.begin, scriptLength);
				fwrite(sbuf, sizeof(uint16_t) + scriptLength, 1, stdout);
			}

			for (const auto& output : transaction.outputs) {
				if (output.script.length() > maxScriptLength) continue;
				const auto scriptLength = static_cast<uint16_t>(output.script.length());

				Slice(sbuf, sbuf + sizeof(sbuf)).put(scriptLength);
				memcpy(sbuf + sizeof(uint16_t), output.script.begin, scriptLength);
				fwrite(sbuf, sizeof(uint16_t) + scriptLength, 1, stdout);
			}

			transactions.popFront();
		}
	}
};

// PREV_TX_HASH | PREV_TX_VOUT | TX_HASH > stdout
struct dumpTxOutIndex : whitelisted_t {
	void operator() (const Block& block) {
		if (this->shouldSkip(block)) return;

		uint8_t sbuf[68];

		auto transactions = block.transactions();
		while (!transactions.empty()) {
			const auto& transaction = transactions.front();

			hash256(sbuf + 36, transaction.data);

			for (const auto& input : transaction.inputs) {
				memcpy(sbuf, input.hash.begin, 32);
				Slice(sbuf + 32, sbuf + 36).put(input.vout);

				fwrite(sbuf, sizeof(sbuf), 1, stdout);
			}

			transactions.popFront();
		}
	}
};

auto perc (uint64_t a, uint64_t ab) {
	return static_cast<double>(a) / static_cast<double>(ab);
}

struct dumpStatistics : whitelisted_t {
	std::atomic_ulong inputs;
	std::atomic_ulong outputs;
	std::atomic_ulong transactions;
	std::atomic_ulong version1;
	std::atomic_ulong version2;
	std::atomic_ulong locktimesGt0;

	dumpStatistics () {
		this->inputs = 0;
		this->outputs = 0;
		this->transactions = 0;
		this->version1 = 0;
		this->version2 = 0;
		this->locktimesGt0 = 0;
	}

	~dumpStatistics () {
		std::cout <<
			"Transactions:\t" << this->transactions << '\n' <<
			"-- Inputs:\t" << this->inputs << " (ratio " << perc(this->inputs, this->transactions) << ") \n" <<
			"-- Outputs:\t" << this->outputs << " (ratio " << perc(this->outputs, this->transactions) << ") \n" <<
			"-- Version1:\t" << this->version1 << " (" << perc(this->version1, this->transactions) * 100 << "%) \n" <<
			"-- Version2:\t" << this->version2 << " (" << perc(this->version2, this->transactions) * 100 << "%) \n" <<
			"-- Locktimes (>0):\t" << this->locktimesGt0 << " (" << perc(this->locktimesGt0, this->transactions) * 100 << "%) \n" <<
			std::endl;
	}

	void operator() (const Block& block) {
		if (this->shouldSkip(block)) return;

		auto transactions = block.transactions();
		this->transactions += transactions.length();

		while (!transactions.empty()) {
			const auto& transaction = transactions.front();

			this->inputs += transaction.inputs.size();
			this->outputs += transaction.outputs.size();

			this->version1 += transaction.version == 1;
			this->version2 += transaction.version == 2;
			this->locktimesGt0 += transaction.locktime > 0;

			transactions.popFront();
		}
	}
};

// HEIGHT | VALUE > stdout
struct dumpOutputValuesOverHeight : whitelisted_t {
	void operator() (const Block& block) {
		if (this->shouldSkip(block)) return;

		uint8_t sbuf[12] = {};
		Slice(sbuf, sbuf + sizeof(sbuf)).put(block.utc());

		auto transactions = block.transactions();
		while (!transactions.empty()) {
			const auto& transaction = transactions.front();

			for (const auto& output : transaction.outputs) {
				Slice(sbuf + 4, sbuf + sizeof(sbuf)).put(output.value);

				fwrite(sbuf, sizeof(sbuf), 1, stdout);
			}

			transactions.popFront();
		}
	}
};

// SHA1(TX_HASH | VOUT) | SHA1(OUTPUT_SCRIPT) > stdout
struct dumpScriptIndexMap : whitelisted_t {
	void operator() (const Block& block) {
		if (this->shouldSkip(block)) return;

		uint8_t sbuf[40] = {};
		uint8_t tbuf[36] = {};

		auto transactions = block.transactions();
		while (!transactions.empty()) {
			const auto& transaction = transactions.front();

			hash256(tbuf, transaction.data);

			uint32_t vout = 0;
			for (const auto& output : transaction.outputs) {
				Slice(tbuf + 32, tbuf + sizeof(tbuf)).put(vout);
				++vout;

				sha1(sbuf, tbuf, sizeof(tbuf));
				sha1(sbuf + 20, output.script);

				fwrite(sbuf, sizeof(sbuf), 1, stdout);
			}

			transactions.popFront();
		}
	}
};

const uint8_t COINBASE[32] = {};

// BLOCK_HASH | TX_HASH | SHA1(PREVIOUS_OUTPUT_SCRIPT) > stdout
// BLOCK_HASH | TX_HASH | SHA1(OUTPUT_SCRIPT) > stdout
struct dumpScriptIndex : whitelisted_t {
	HMap<hash160_t, hash160_t> txOuts;

	bool initialize (const char* arg) {
		if (whitelisted_t::initialize(arg)) return true;
		if (strncmp(arg, "-i", 2) == 0) {
			const auto fileName = std::string(arg + 2);
			const auto file = fopen(fileName.c_str(), "r");
			assert(file != nullptr);

			fseek(file, 0, SEEK_END);
			const auto fileSize = ftell(file);
			fseek(file, 0, SEEK_SET);

			assert(sizeof(this->txOuts[0]) == 40);
			assert(fileSize % sizeof(this->txOuts[0]) == 0);

			this->txOuts.resize(fileSize / sizeof(this->txOuts[0]));
			const auto read = fread(&this->txOuts[0], fileSize, 1, file);
			assert(read == 1);

			fclose(file);
			assert(!this->txOuts.empty());
			assert(std::is_sorted(this->txOuts.begin(), this->txOuts.end()));

			std::cerr << "Mapped " << this->txOuts.size() << " txOuts" << std::endl;

			return true;
		}

		return false;
	}

	void operator() (const Block& block) {
		hash256_t hash;
		hash256(&hash[0], block.header);
		if (this->shouldSkip(hash)) return;

		uint8_t sbuf[84] = {};
		memcpy(sbuf, &hash[0], 32);

		auto transactions = block.transactions();
		while (!transactions.empty()) {
			const auto& transaction = transactions.front();

			hash256(sbuf + 32, transaction.data);

			if (!this->txOuts.empty()) {
				for (const auto& input : transaction.inputs) {
					// Coinbase input?
					if (
						input.vout == 0xffffffff &&
						memcmp(input.hash.begin, COINBASE, sizeof(COINBASE)) == 0
					) {
						sha1(&hash[0], input.script);
						memcpy(sbuf + 64, &hash[0], 20);
						fwrite(sbuf, sizeof(sbuf), 1, stdout);

						continue;
					}

					hash160_t hash;
					sha1(&hash[0], input.data.take(36));

					const auto txOutIter = this->txOuts.find(hash);
					assert(txOutIter != this->txOuts.end());

					memcpy(sbuf + 64, &(txOutIter->second)[0], 20);
					fwrite(sbuf, sizeof(sbuf), 1, stdout);
				}
			}

			for (const auto& output : transaction.outputs) {
				sha1(sbuf + 64, output.script);
				fwrite(sbuf, sizeof(sbuf), 1, stdout);
			}

			transactions.popFront();
		}
	}
};
<|endoftext|>


<commit_before>#pragma once

#include <string>
#include <string_view>
#include <vector>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <iterator>
#include <utility>
#include <initializer_list>
#include <numeric>
#include <functional>
#include <cassert>

#include "acmacs-base/sfinae.hh"
#include "acmacs-base/to-string.hh"

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

namespace std
{
    inline unsigned long stoul(std::string_view src) { return stoul(std::string(src)); }
}

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

namespace string
{
      // ----------------------------------------------------------------------

    inline std::string first_letter_of_words(std::string s)
    {
        std::string result;
        bool add = true;
        for (char c: s) {
            if (c == ' ') {
                add = true;
            }
            else if (add) {
                result.push_back(c);
                add = false;
            }
        }
        return result;
    }

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

    namespace _internal {
        template <typename InputIterator, typename Source> inline std::pair<InputIterator, InputIterator> strip_begin_end(Source& source)
        {
            auto predicate = [](auto c) { return std::isspace(c); }; // have to use lambda, other compiler cannot infer Predicate type from isspace
            auto e = std::find_if_not(source.rbegin(), source.rend(), predicate);
            auto b = std::find_if_not(source.begin(), e.base(), predicate);
            return std::make_pair(b, e.base());
        }
    } // namespace _internal

    // inline std::string& strip(std::string& source)
    // {
    //     auto be = _internal::strip_begin_end<std::string::iterator>(source);
    //     source.erase(be.second, source.end()); // erase at the end first
    //     source.erase(source.begin(), be.first); // invalidates be.second!
    //     return source;
    // }

    // inline std::string strip(std::string&& source)
    // {
    //     auto be = _internal::strip_begin_end<std::string::iterator>(source);
    //     source.erase(be.second, source.end()); // erase at the end first
    //     source.erase(source.begin(), be.first); // invalidates be.second!
    //     return source;
    // }

    inline std::string strip(std::string source)
    {
        auto be = _internal::strip_begin_end<std::string::const_iterator>(source);
        return std::string(be.first, be.second);
    }

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

    template <typename S, typename = std::enable_if_t<acmacs::sfinae::is_string_v<S>>> inline std::string replace(S source, std::string look_for, std::string replace_with)
    {
        std::string result;
        std::string::size_type start = 0;
        while (true) {
            const auto pos = source.find(look_for, start);
            if (pos != std::string::npos) {
                result.append(source.begin() + static_cast<std::string::difference_type>(start), source.begin() + static_cast<std::string::difference_type>(pos));
                result.append(replace_with);
                start = pos + look_for.size();
            }
            else {
                result.append(source.begin() + static_cast<std::string::difference_type>(start), source.end());
                break;
            }
        }
        return result;
    }

    inline std::string replace(std::string source, char look_for, char replace_with)
    {
        for (std::string::size_type pos = source.find(look_for); pos != std::string::npos; pos = source.find(look_for, pos + 1))
            source[pos] = replace_with;
        return source;
    }

    template <typename ... Args> inline std::string replace(std::string source, std::string l1, std::string r1, std::string l2, std::string r2, Args ... args)
    {
        return replace(replace(source, l1, r1), l2, r2, args ...);
    }

    inline std::string replace_spaces(std::string source, char replacement)
    {
        std::transform(source.begin(), source.end(), source.begin(), [replacement](char c) {
            if (std::isspace(c))
                c = replacement;
            return c;
        });
        return source;
    }

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

    namespace _internal
    {
        template <typename Iter, typename F> inline std::string transform(Iter first, Iter last, F func)
        {
            std::string result;
            std::transform(first, last, std::back_inserter(result), func);
            return result;
        }

        template <typename Iter, typename F> inline std::string copy_if(Iter first, Iter last, F func)
        {
            std::string result;
            std::copy_if(first, last, std::back_inserter(result), func);
            return result;
        }
    }

    template <typename S> inline std::string lower(const S& source) { return _internal::transform(source.begin(), source.end(), ::tolower); }
    inline std::string lower(const char* source) { return _internal::transform(source, source + std::strlen(source), ::tolower); }
    inline std::string lower(char* source) { return lower(const_cast<const char*>(source)); }

    template <typename S> inline std::string upper(const S& source) { return _internal::transform(source.begin(), source.end(), ::toupper); }
    inline std::string upper(const char* source) { return _internal::transform(source, source + std::strlen(source), ::toupper); }
    inline std::string upper(char* source) { return upper(const_cast<const char*>(source)); }

    // inline std::string& capitalize(std::string& source)
    // {
    //     if (!source.empty()) {
    //         std::transform(source.begin(), source.begin() + 1, source.begin(), ::toupper);
    //         std::transform(source.begin() + 1, source.end(), source.begin() + 1, ::tolower);
    //     }
    //     return source;
    // }

    template <typename S> inline std::string capitalize(const S& source)
    {
        std::string result;
        if (!source.empty()) {
            std::transform(source.begin(), source.begin() + 1, std::back_inserter(result), ::toupper);
            std::transform(source.begin() + 1, source.end(), std::back_inserter(result), ::tolower);
        }
        return result;
    }

    template <typename S> inline std::string remove_spaces(const S& source) { return _internal::copy_if(source.begin(), source.end(), [](auto c) -> bool { return !std::isspace(c); }); }
    inline std::string remove_spaces(const char* source) { return remove_spaces(std::string_view(source, std::strlen(source))); }
    inline std::string remove_spaces(char* source) { return remove_spaces(std::string_view(source, std::strlen(source))); }

      // ----------------------------------------------------------------------
      // ends_with
      // ----------------------------------------------------------------------

    template <typename S> inline bool ends_with(const S& data, const char* end)
    {
        const std::string_view end_view{end};
        return std::string_view(data.data() + data.size() - end_view.size(), end_view.size()) == end_view;
    }

      // ----------------------------------------------------------------------
      // compare
      // ----------------------------------------------------------------------

    inline int compare(const char* a, size_t al, const char* b, size_t bl)
    {
        auto r = std::memcmp(a, b, std::min(al, bl));
        if (r == 0 && al != bl)
            return al < bl ? -1 : 1;
        else
            return r;
    }

    inline int compare(const std::string& a, const std::string& b) { return compare(a.c_str(), a.size(), b.c_str(), b.size()); }
    inline int compare(const std::string& a, const char* b) { return compare(a.c_str(), a.size(), b, std::strlen(b)); }
    inline int compare(const char* a, const std::string& b) { return compare(a, std::strlen(a), b.c_str(), b.size()); }

    inline int compare(std::initializer_list<std::string> as, std::initializer_list<std::string> bs)
    {
        assert(as.size() == bs.size());
        for (auto ap = as.begin(), bp = bs.begin(); ap != as.end(); ++ap, ++bp) {
            if (const auto r = compare(*ap, *bp); r != 0)
                return r;
        }
        return 0;
    }

      // ----------------------------------------------------------------------
      // join
      // ----------------------------------------------------------------------

    template <typename Iterator> inline std::string join(std::string separator, Iterator first, Iterator last)
    {
        std::string result;
        if (first != last) {
              // Note last - first below does not supported for std::set
              // const size_t resulting_size = std::accumulate(first, last, separator.size() * static_cast<size_t>(last - first - 1), [](size_t acc, const std::string& n) -> size_t { return acc + n.size(); });
              // result.reserve(resulting_size);
            for ( ; first != last; ++first) {
                const auto f_s = acmacs::to_string(*first);
                if (!f_s.empty()) {
                    if (!result.empty())
                        result.append(separator);
                    result.append(f_s);
                }
            }
        }
        return result;
    }

    template <typename Iterator, typename Converter> inline std::string join(std::string separator, Iterator first, Iterator last, Converter convert)
    {
        std::string result;
        for ( ; first != last; ++first) {
            const auto f_s = convert(*first);
            if (!f_s.empty()) {
                if (!result.empty())
                    result.append(separator);
                result.append(f_s);
            }
        }
        return result;
    }

    template <typename Collection> inline std::string join(std::string separator, const Collection& values)
    {
        return join(separator, std::begin(values), std::end(values));
    }

    inline std::string join(std::string separator, std::initializer_list<std::string>&& values)
    {
        return join(separator, std::begin(values), std::end(values));
    }

    inline std::string join(std::string separator, std::initializer_list<std::string_view>&& values)
    {
        return join(separator, std::begin(values), std::end(values));
    }

    inline std::string join(std::initializer_list<std::string>&& parts)
    {
        // std::vector<std::string> p{parts};
        // return join(" ", std::begin(p), std::remove(std::begin(p), std::end(p), std::string()));
        return join(" ", std::begin(parts), std::end(parts));
    }

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

    template <typename S> inline std::string_view string_view(const S& aSrc, size_t aOffset)
    {
        return std::string_view(aSrc.data() + aOffset, aSrc.size() - aOffset);
    }

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

    template <typename S1, typename S2> inline size_t hamming_distance(S1&& first, S2&& second)
    {
        const auto size = std::min(first.size(), second.size());
        size_t dist = 0;
        for (size_t index = 0; index < size; ++index) {
            if (first[index] != second[index])
                ++dist;
        }
        return dist;
    }

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

    namespace detail
    {
        template <typename S> inline std::string concat_to_string(S src, size_t precision = 6)
        {
            if constexpr (std::is_convertible_v<S, std::string>)
                return static_cast<std::string>(src);
            else if constexpr (std::is_same_v<S, double> || std::is_same_v<S, long double>)
                return acmacs::to_string(src, precision);
            else
                return acmacs::to_string(src);
        }
    }

    template <typename S1, typename S2, typename... Args> inline std::string concat(S1 s1, S2 s2, Args... args)
    {
        auto result = detail::concat_to_string(s1);
        result.append(detail::concat_to_string(s2));
        if constexpr (sizeof...(args) > 0)
            return concat(result, args...);
        else
            return result;
    }

    template <typename S1, typename S2, typename... Args> inline std::string concat_precise(S1 s1, S2 s2, Args... args)
    {
        auto result = detail::concat_to_string(s1, 32);
        result.append(detail::concat_to_string(s2, 32));
        if constexpr (sizeof...(args) > 0)
            return concat_precise(result, args...);
        else
            return result;
    }

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

} // namespace string

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>porting to gcc8<commit_after>#pragma once

#include <string>
#include <string_view>
#include <vector>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <iterator>
#include <utility>
#include <initializer_list>
#include <numeric>
#include <functional>
#include <cassert>

#include "acmacs-base/sfinae.hh"
#include "acmacs-base/to-string.hh"

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

namespace std
{
    inline unsigned long stoul(std::string_view src) { return stoul(std::string(src)); }
}

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

namespace string
{
      // ----------------------------------------------------------------------

    inline std::string first_letter_of_words(std::string s)
    {
        std::string result;
        bool add = true;
        for (char c: s) {
            if (c == ' ') {
                add = true;
            }
            else if (add) {
                result.push_back(c);
                add = false;
            }
        }
        return result;
    }

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

    namespace _internal {
        template <typename InputIterator, typename Source> inline std::pair<InputIterator, InputIterator> strip_begin_end(Source& source)
        {
            auto predicate = [](auto c) { return std::isspace(c); }; // have to use lambda, other compiler cannot infer Predicate type from isspace
            auto e = std::find_if_not(source.rbegin(), source.rend(), predicate);
            auto b = std::find_if_not(source.begin(), e.base(), predicate);
            return std::make_pair(b, e.base());
        }
    } // namespace _internal

    // inline std::string& strip(std::string& source)
    // {
    //     auto be = _internal::strip_begin_end<std::string::iterator>(source);
    //     source.erase(be.second, source.end()); // erase at the end first
    //     source.erase(source.begin(), be.first); // invalidates be.second!
    //     return source;
    // }

    // inline std::string strip(std::string&& source)
    // {
    //     auto be = _internal::strip_begin_end<std::string::iterator>(source);
    //     source.erase(be.second, source.end()); // erase at the end first
    //     source.erase(source.begin(), be.first); // invalidates be.second!
    //     return source;
    // }

    inline std::string strip(std::string source)
    {
        auto be = _internal::strip_begin_end<std::string::const_iterator>(source);
        return std::string(be.first, be.second);
    }

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

    template <typename S, typename = std::enable_if_t<acmacs::sfinae::is_string_v<S>>> inline std::string replace(S source, std::string look_for, std::string replace_with)
    {
        std::string result;
        std::string::size_type start = 0;
        while (true) {
            const auto pos = source.find(look_for, start);
            if (pos != std::string::npos) {
                result.append(source.begin() + static_cast<std::string::difference_type>(start), source.begin() + static_cast<std::string::difference_type>(pos));
                result.append(replace_with);
                start = pos + look_for.size();
            }
            else {
                result.append(source.begin() + static_cast<std::string::difference_type>(start), source.end());
                break;
            }
        }
        return result;
    }

    inline std::string replace(std::string source, char look_for, char replace_with)
    {
        for (std::string::size_type pos = source.find(look_for); pos != std::string::npos; pos = source.find(look_for, pos + 1))
            source[pos] = replace_with;
        return source;
    }

    template <typename ... Args> inline std::string replace(std::string source, std::string l1, std::string r1, std::string l2, std::string r2, Args ... args)
    {
        return replace(replace(source, l1, r1), l2, r2, args ...);
    }

    inline std::string replace_spaces(std::string source, char replacement)
    {
        std::transform(source.begin(), source.end(), source.begin(), [replacement](char c) {
            if (std::isspace(c))
                c = replacement;
            return c;
        });
        return source;
    }

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

    namespace _internal
    {
        template <typename Iter, typename F> inline std::string transform(Iter first, Iter last, F func)
        {
            std::string result;
            std::transform(first, last, std::back_inserter(result), func);
            return result;
        }

        template <typename Iter, typename F> inline std::string copy_if(Iter first, Iter last, F func)
        {
            std::string result;
            std::copy_if(first, last, std::back_inserter(result), func);
            return result;
        }
    }

    template <typename S> inline std::string lower(const S& source) { return _internal::transform(source.begin(), source.end(), ::tolower); }
    inline std::string lower(const char* source) { return _internal::transform(source, source + std::strlen(source), ::tolower); }
    inline std::string lower(char* source) { return lower(const_cast<const char*>(source)); }

    template <typename S> inline std::string upper(const S& source) { return _internal::transform(source.begin(), source.end(), ::toupper); }
    inline std::string upper(const char* source) { return _internal::transform(source, source + std::strlen(source), ::toupper); }
    inline std::string upper(char* source) { return upper(const_cast<const char*>(source)); }

    // inline std::string& capitalize(std::string& source)
    // {
    //     if (!source.empty()) {
    //         std::transform(source.begin(), source.begin() + 1, source.begin(), ::toupper);
    //         std::transform(source.begin() + 1, source.end(), source.begin() + 1, ::tolower);
    //     }
    //     return source;
    // }

    template <typename S> inline std::string capitalize(const S& source)
    {
        std::string result;
        if (!source.empty()) {
            std::transform(source.begin(), source.begin() + 1, std::back_inserter(result), ::toupper);
            std::transform(source.begin() + 1, source.end(), std::back_inserter(result), ::tolower);
        }
        return result;
    }

    template <typename S> inline std::string remove_spaces(const S& source) { return _internal::copy_if(source.begin(), source.end(), [](auto c) -> bool { return !std::isspace(c); }); }
    inline std::string remove_spaces(const char* source) { return remove_spaces(std::string_view(source, std::strlen(source))); }
    inline std::string remove_spaces(char* source) { return remove_spaces(std::string_view(source, std::strlen(source))); }

      // ----------------------------------------------------------------------
      // ends_with
      // ----------------------------------------------------------------------

    template <typename S> inline bool ends_with(const S& data, const char* end)
    {
        const std::string_view end_view{end};
        return std::string_view(data.data() + data.size() - end_view.size(), end_view.size()) == end_view;
    }

      // ----------------------------------------------------------------------
      // compare
      // ----------------------------------------------------------------------

    inline int compare(const char* a, size_t al, const char* b, size_t bl)
    {
        auto r = std::memcmp(a, b, std::min(al, bl));
        if (r == 0 && al != bl)
            return al < bl ? -1 : 1;
        else
            return r;
    }

    inline int compare(const std::string& a, const std::string& b) { return compare(a.c_str(), a.size(), b.c_str(), b.size()); }
    inline int compare(const std::string& a, const char* b) { return compare(a.c_str(), a.size(), b, std::strlen(b)); }
    inline int compare(const char* a, const std::string& b) { return compare(a, std::strlen(a), b.c_str(), b.size()); }

    inline int compare(std::initializer_list<std::string> as, std::initializer_list<std::string> bs)
    {
        assert(as.size() == bs.size());
        for (auto ap = as.begin(), bp = bs.begin(); ap != as.end(); ++ap, ++bp) {
            if (const auto r = compare(*ap, *bp); r != 0)
                return r;
        }
        return 0;
    }

      // ----------------------------------------------------------------------
      // join
      // ----------------------------------------------------------------------

    template <typename Iterator> inline std::string join(std::string separator, Iterator first, Iterator last)
    {
        std::string result;
        if (first != last) {
              // Note last - first below does not supported for std::set
              // const size_t resulting_size = std::accumulate(first, last, separator.size() * static_cast<size_t>(last - first - 1), [](size_t acc, const std::string& n) -> size_t { return acc + n.size(); });
              // result.reserve(resulting_size);
            for ( ; first != last; ++first) {
                const auto f_s = acmacs::to_string(*first);
                if (!f_s.empty()) {
                    if (!result.empty())
                        result.append(separator);
                    result.append(f_s);
                }
            }
        }
        return result;
    }

    template <typename Iterator, typename Converter> inline std::string join(std::string separator, Iterator first, Iterator last, Converter convert)
    {
        std::string result;
        for ( ; first != last; ++first) {
            const auto f_s = convert(*first);
            if (!f_s.empty()) {
                if (!result.empty())
                    result.append(separator);
                result.append(f_s);
            }
        }
        return result;
    }

    template <typename Collection> inline std::string join(std::string separator, const Collection& values)
    {
        return join(separator, std::begin(values), std::end(values));
    }

    inline std::string join(std::string separator, std::initializer_list<std::string>&& values)
    {
        return join(separator, std::begin(values), std::end(values));
    }

    inline std::string join(std::string separator, std::initializer_list<std::string_view>&& values)
    {
        return join(separator, std::begin(values), std::end(values));
    }

    inline std::string join(std::initializer_list<std::string>&& parts)
    {
        // std::vector<std::string> p{parts};
        // return join(" ", std::begin(p), std::remove(std::begin(p), std::end(p), std::string()));
        return join(" ", std::begin(parts), std::end(parts));
    }

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

    template <typename S> inline std::string_view string_view(const S& aSrc, size_t aOffset)
    {
        return std::string_view(aSrc.data() + aOffset, aSrc.size() - aOffset);
    }

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

    template <typename S1, typename S2> inline size_t hamming_distance(S1&& first, S2&& second)
    {
        const auto size = std::min(first.size(), second.size());
        size_t dist = 0;
        for (size_t index = 0; index < size; ++index) {
            if (first[index] != second[index])
                ++dist;
        }
        return dist;
    }

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

    namespace detail
    {
        template <typename S> inline std::string concat_to_string(S src, [[maybe_unused]] size_t precision = 6)
        {
            if constexpr (std::is_convertible_v<S, std::string>)
                return static_cast<std::string>(src);
            else if constexpr (std::is_same_v<S, double> || std::is_same_v<S, long double>)
                return acmacs::to_string(src, precision);
            else
                return acmacs::to_string(src);
        }
    }

    template <typename S1, typename S2, typename... Args> inline std::string concat(S1 s1, S2 s2, Args... args)
    {
        auto result = detail::concat_to_string(s1);
        result.append(detail::concat_to_string(s2));
        if constexpr (sizeof...(args) > 0)
            return concat(result, args...);
        else
            return result;
    }

    template <typename S1, typename S2, typename... Args> inline std::string concat_precise(S1 s1, S2 s2, Args... args)
    {
        auto result = detail::concat_to_string(s1, 32);
        result.append(detail::concat_to_string(s2, 32));
        if constexpr (sizeof...(args) > 0)
            return concat_precise(result, args...);
        else
            return result;
    }

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

} // namespace string

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>// Petter Strandmark 2013.

#include <list>
#include <sstream>
#include <vector>

#define UNICODE
#include <cinder/app/AppBasic.h>
#include <cinder/gl/TextureFont.h>

#include <mcts.h>

#include "go.h"

using namespace ci;
using namespace ci::app;
using namespace std;

// We'll create a new Cinder Application by deriving from the AppBasic class
class GoApp: public AppBasic
{
  public:
	GoApp();
	void setup();

	void mouseDown( MouseEvent event );
	void keyDown( KeyEvent event );
	void update();
	void draw();

	static const int M = 9;
	static const int N = 9;

	static const int board_x = 25;
	static const int board_y = 25;
	static const int board_width = 40;

	GoState<M, N> state;

	enum PlayerType {HUMAN, COMPUTER};
	PlayerType player1, player2;
	MCTS::ComputeOptions player1_options, player2_options;

	enum GameStatus {WAITING_FOR_USER, COMPUTER_THINKING, GAME_OVER, GAME_ERROR};
	GameStatus game_status;
	std::string error_string;

	// Compute move.
	std::future<GoState<M, N>::Move> computed_move;
	void next_player();
	void start_compute_move();
	void check_for_computed_move();

	// Drawing text.
	Font				mFont;
	gl::TextureFontRef	mTextureFont;
};

GoApp::GoApp()
{ }

void GoApp::setup()
{
	//state = GoState<M, N>(board);
	player1 = COMPUTER;
	player2 = COMPUTER;

	player1_options.max_iterations = -1;
	player1_options.max_time = 2.0;

	player2_options.max_iterations = -1;
	player2_options.max_time = 0.5;

	if (player1 == HUMAN) {
		game_status = WAITING_FOR_USER;
	}
	else {
		start_compute_move();
	}

	mFont = Font("Times New Roman", 24 );
	mTextureFont = gl::TextureFont::create( mFont );
}

void GoApp::start_compute_move()
{
	//game_status = WAITING_FOR_USER;
	//return;

	game_status = COMPUTER_THINKING;

	MCTS::ComputeOptions options;
	if (state.player_to_move == 1) {
		options = player1_options;
	}
	else {
		options = player2_options;
	}

	GoState<M, N> state_copy = state;
	computed_move =
		std::async(std::launch::async,
			[state_copy, options]()
			{
				//auto best_move = MCTS::compute_move(state_copy, options);
				//return best_move;

				auto moves = state_copy.get_moves();
				if (moves.size() == 1) {
					return moves[0];
				}

				auto tree = MCTS::compute_tree(state_copy, options, 1241 * std::time(0));
				typedef MCTS::Node<GoState<M, N>> Node;
				auto best_child = *std::max_element( tree->children.begin(), tree->children.end(), [](Node* lhs, Node* rhs) { return lhs->visits < rhs->visits; } );
				return best_child->move;
			});
}

void GoApp::check_for_computed_move()
{
	//return;

	if (game_status != COMPUTER_THINKING) {
		return;
	}

	auto status = computed_move.wait_for(std::chrono::seconds(0));
	if (status == std::future_status::ready) {
		try {
			auto move = computed_move.get();
			state.do_move(move);

			// Are there any more moves possible?
			if (state.get_moves().empty()) {
				game_status = GAME_OVER;
			}
			else {
				next_player();
			}

		} catch (std::exception& error) {
			game_status = GAME_ERROR;
			error_string = error.what();
		}
	}
}

void GoApp::next_player()
{
	if (state.player_to_move == 1) {
		if (player1 == HUMAN) {
			game_status = WAITING_FOR_USER;
		}
		else {
			start_compute_move();
		}
	}
	else if (state.player_to_move == 2) {
		if (player2 == HUMAN) {
			game_status = WAITING_FOR_USER;
		}
		else {
			start_compute_move();
		}
	}
}

void GoApp::mouseDown(MouseEvent event)
{
	if (game_status != WAITING_FOR_USER) {
		return;
	}

	int x = event.getX();
	int j = (x - board_x + board_width/2) / board_width;
	int y = event.getY();
	int i = (y - board_y + board_width/2) / board_width;

	try {
		if (state.is_move_possible(i, j)) {
			state.do_move(GoState<M, N>::ij_to_ind(i, j));

			// Are there any more moves possible?
			if (state.get_moves().empty()) {
				game_status = GAME_OVER;
			}
			else {
				next_player();
			}
		}
	} catch (std::exception& error) {
		game_status = GAME_ERROR;
		error_string = error.what();
	}
}

void GoApp::keyDown( KeyEvent event )
{
	if (event.getChar() == 'p') {
		if (game_status == WAITING_FOR_USER) {
			state.do_move(GoState<M, N>::pass);

			// Computer makes the next move.
			start_compute_move();
		}
	}
	else if (event.getChar() == 'r') {
		state = GoState<M, N>();
		setup();
	}
	else if (event.getChar() == 'd') {
		state.dump_board("board.txt");
		error_string = "Board dumped.";
		game_status = GAME_ERROR;
	}
}

void GoApp::update()
{
	check_for_computed_move();
}

void GoApp::draw()
{
	gl::clear( Color( 0.9f, 0.5f, 0.05f ) );

	gl::color( 0.0f, 0.0f, 0.0f );
	for (int i = 0; i < M; ++i) {
		int x  = board_x + i * board_width;
		int y1 = board_y;
		int y2 = board_y + (M-1) * board_width;
		gl::drawLine(Vec2f(x, y1), Vec2f(x, y2));

		int y  = board_y + i * board_width;
		int x1 = board_x;
		int x2 = board_x + (N-1) * board_width;
		gl::drawLine(Vec2f(x1, y), Vec2f(x2, y));
	}

	for (int i = 0; i < M; ++i) {
	for (int j = 0; j < N; ++j) {
		Vec2f pos(board_x + j * board_width, board_y + i * board_width );

		if ( ! state.is_move_possible(i, j)) {
			gl::color( 1.0f, 0.0f, 0.0f );
			gl::drawSolidCircle(pos, 4.0f );
		}

		if (state.get_pos(i, j) == GoState<M, N>::player1) {
			gl::color( 0.0f, 0.0f, 0.0f );
			gl::drawSolidCircle(pos, board_width / 2 - 1);
		}
		else if (state.get_pos(i, j) == GoState<M, N>::player2) {
			gl::color( 1.0f, 1.0f, 1.0f );
			gl::drawSolidCircle(pos, board_width / 2 - 1);
		}
	}}

	stringstream sout;
	if (game_status == WAITING_FOR_USER) {
		sout << "Make your move!" << endl;
	}
	else if (game_status == COMPUTER_THINKING) {
		sout << "Computing..." << endl;
	}
	else if (game_status == GAME_OVER) {
		sout << "Game over!" << endl;
	}
	else if (game_status == GAME_ERROR) {
		sout << "ERROR:\n" << error_string << endl;
	}

	sout << "Player 1 (black) score: " << state.get_player_score(1) << endl;
	sout << "Player 2 (white) score: " << state.get_player_score(2) << endl;

	//sout << "Board hash: " << state.previous_board_hash_value << " -> " << state.compute_hash_value() << endl;
	//for (auto move: state.get_moves()) {
	//	sout << move << " ";
	//}

	Rectf boundsRect(board_x, board_y + M * board_width + 20,
	                 getWindowWidth() - 40, getWindowHeight() - 40 );
	gl::enableAlphaBlending();
	gl::color( ColorA( 0, 0, 0, 1.0f ) );
	mTextureFont->drawStringWrapped( sout.str(), boundsRect );
}

// This line tells Cinder to actually create the application
CINDER_APP_BASIC( GoApp, RendererGl )
<commit_msg>Helper markers for 9x9 board.<commit_after>// Petter Strandmark 2013.

#include <list>
#include <sstream>
#include <vector>

#define UNICODE
#include <cinder/app/AppBasic.h>
#include <cinder/gl/TextureFont.h>

#include <mcts.h>

#include "go.h"

using namespace ci;
using namespace ci::app;
using namespace std;

// We'll create a new Cinder Application by deriving from the AppBasic class
class GoApp: public AppBasic
{
  public:
	GoApp();
	void setup();

	void mouseDown( MouseEvent event );
	void keyDown( KeyEvent event );
	void update();
	void draw();

	static const int M = 9;
	static const int N = 9;

	static const int board_x = 25;
	static const int board_y = 25;
	static const int board_width = 40;

	GoState<M, N> state;

	enum PlayerType {HUMAN, COMPUTER};
	PlayerType player1, player2;
	MCTS::ComputeOptions player1_options, player2_options;

	enum GameStatus {WAITING_FOR_USER, COMPUTER_THINKING, GAME_OVER, GAME_ERROR};
	GameStatus game_status;
	std::string error_string;

	// Compute move.
	std::future<GoState<M, N>::Move> computed_move;
	void next_player();
	void start_compute_move();
	void check_for_computed_move();

	// Drawing text.
	Font				mFont;
	gl::TextureFontRef	mTextureFont;
};

GoApp::GoApp()
{ }

void GoApp::setup()
{
	//state = GoState<M, N>(board);
	player1 = COMPUTER;
	player2 = COMPUTER;

	player1_options.max_iterations = -1;
	player1_options.max_time = 2.0;

	player2_options.max_iterations = -1;
	player2_options.max_time = 0.5;

	if (player1 == HUMAN) {
		game_status = WAITING_FOR_USER;
	}
	else {
		start_compute_move();
	}

	mFont = Font("Times New Roman", 24 );
	mTextureFont = gl::TextureFont::create( mFont );
}

void GoApp::start_compute_move()
{
	//game_status = WAITING_FOR_USER;
	//return;

	game_status = COMPUTER_THINKING;

	MCTS::ComputeOptions options;
	if (state.player_to_move == 1) {
		options = player1_options;
	}
	else {
		options = player2_options;
	}

	GoState<M, N> state_copy = state;
	computed_move =
		std::async(std::launch::async,
			[state_copy, options]()
			{
				//auto best_move = MCTS::compute_move(state_copy, options);
				//return best_move;

				auto moves = state_copy.get_moves();
				if (moves.size() == 1) {
					return moves[0];
				}

				auto tree = MCTS::compute_tree(state_copy, options, 1241 * std::time(0));
				typedef MCTS::Node<GoState<M, N>> Node;
				auto best_child = *std::max_element( tree->children.begin(), tree->children.end(), [](Node* lhs, Node* rhs) { return lhs->visits < rhs->visits; } );
				return best_child->move;
			});
}

void GoApp::check_for_computed_move()
{
	//return;

	if (game_status != COMPUTER_THINKING) {
		return;
	}

	auto status = computed_move.wait_for(std::chrono::seconds(0));
	if (status == std::future_status::ready) {
		try {
			auto move = computed_move.get();
			state.do_move(move);

			// Are there any more moves possible?
			if (state.get_moves().empty()) {
				game_status = GAME_OVER;
			}
			else {
				next_player();
			}

		} catch (std::exception& error) {
			game_status = GAME_ERROR;
			error_string = error.what();
		}
	}
}

void GoApp::next_player()
{
	if (state.player_to_move == 1) {
		if (player1 == HUMAN) {
			game_status = WAITING_FOR_USER;
		}
		else {
			start_compute_move();
		}
	}
	else if (state.player_to_move == 2) {
		if (player2 == HUMAN) {
			game_status = WAITING_FOR_USER;
		}
		else {
			start_compute_move();
		}
	}
}

void GoApp::mouseDown(MouseEvent event)
{
	if (game_status != WAITING_FOR_USER) {
		return;
	}

	int x = event.getX();
	int j = (x - board_x + board_width/2) / board_width;
	int y = event.getY();
	int i = (y - board_y + board_width/2) / board_width;

	try {
		if (state.is_move_possible(i, j)) {
			state.do_move(GoState<M, N>::ij_to_ind(i, j));

			// Are there any more moves possible?
			if (state.get_moves().empty()) {
				game_status = GAME_OVER;
			}
			else {
				next_player();
			}
		}
	} catch (std::exception& error) {
		game_status = GAME_ERROR;
		error_string = error.what();
	}
}

void GoApp::keyDown( KeyEvent event )
{
	if (event.getChar() == 'p') {
		if (game_status == WAITING_FOR_USER) {
			state.do_move(GoState<M, N>::pass);

			// Computer makes the next move.
			start_compute_move();
		}
	}
	else if (event.getChar() == 'r') {
		state = GoState<M, N>();
		setup();
	}
	else if (event.getChar() == 'd') {
		state.dump_board("board.txt");
		error_string = "Board dumped.";
		game_status = GAME_ERROR;
	}
}

void GoApp::update()
{
	check_for_computed_move();
}

void GoApp::draw()
{
	gl::clear( Color( 0.9f, 0.5f, 0.05f ) );

	gl::color( 0.0f, 0.0f, 0.0f );
	for (int i = 0; i < M; ++i) {
		int x  = board_x + i * board_width;
		int y1 = board_y;
		int y2 = board_y + (M-1) * board_width;
		gl::drawLine(Vec2f(x, y1), Vec2f(x, y2));

		int y  = board_y + i * board_width;
		int x1 = board_x;
		int x2 = board_x + (N-1) * board_width;
		gl::drawLine(Vec2f(x1, y), Vec2f(x2, y));
	}

	if (M == 9 && N == 9) {
		gl::color( 0.0f, 0.0f, 0.0f );
		gl::drawSolidCircle(Vec2f(board_x + 2 * board_width, board_y + 2 * board_width ), 3.0f);
		gl::drawSolidCircle(Vec2f(board_x + 6 * board_width, board_y + 6 * board_width ), 3.0f);
		gl::drawSolidCircle(Vec2f(board_x + 6 * board_width, board_y + 2 * board_width ), 3.0f);
		gl::drawSolidCircle(Vec2f(board_x + 2 * board_width, board_y + 6 * board_width ), 3.0f);
		gl::drawSolidCircle(Vec2f(board_x + 4 * board_width, board_y + 4 * board_width ), 3.0f);
	}

	for (int i = 0; i < M; ++i) {
	for (int j = 0; j < N; ++j) {
		Vec2f pos(board_x + j * board_width, board_y + i * board_width );

		if ( ! state.is_move_possible(i, j)) {
			gl::color( 1.0f, 0.0f, 0.0f );
			gl::drawSolidCircle(pos, 4.0f );
		}

		if (state.get_pos(i, j) == GoState<M, N>::player1) {
			gl::color( 0.0f, 0.0f, 0.0f );
			gl::drawSolidCircle(pos, board_width / 2 - 1);
		}
		else if (state.get_pos(i, j) == GoState<M, N>::player2) {
			gl::color( 1.0f, 1.0f, 1.0f );
			gl::drawSolidCircle(pos, board_width / 2 - 1);
		}
	}}

	stringstream sout;
	if (game_status == WAITING_FOR_USER) {
		sout << "Make your move!" << endl;
	}
	else if (game_status == COMPUTER_THINKING) {
		sout << "Computing..." << endl;
	}
	else if (game_status == GAME_OVER) {
		sout << "Game over!" << endl;
	}
	else if (game_status == GAME_ERROR) {
		sout << "ERROR:\n" << error_string << endl;
	}

	sout << "Player 1 (black) score: " << state.get_player_score(1) << endl;
	sout << "Player 2 (white) score: " << state.get_player_score(2) << endl;

	//sout << "Board hash: " << state.previous_board_hash_value << " -> " << state.compute_hash_value() << endl;
	//for (auto move: state.get_moves()) {
	//	sout << move << " ";
	//}

	Rectf boundsRect(board_x, board_y + M * board_width + 20,
	                 getWindowWidth() - 40, getWindowHeight() - 40 );
	gl::enableAlphaBlending();
	gl::color( ColorA( 0, 0, 0, 1.0f ) );
	mTextureFont->drawStringWrapped( sout.str(), boundsRect );
}

// This line tells Cinder to actually create the application
CINDER_APP_BASIC( GoApp, RendererGl )
<|endoftext|>


<commit_before><commit_msg>SVN_SILENT rename to namedPipe<commit_after><|endoftext|>