<commit_before>// --------------------------------------------------------------------------------------------------
//  Copyright (c) 2016 Microsoft Corporation
//  
//  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.
// --------------------------------------------------------------------------------------------------

// Boost:
#include <boost/python.hpp>
#include <boost/python/exception_translator.hpp>
#include <boost/python/register_ptr_to_python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/python/to_python_converter.hpp>

// Malmo:
#include <AgentHost.h>
#ifdef WRAP_ALE
    #include <ALEAgentHost.h>
#endif
#include <ClientPool.h>
#include <MissionSpec.h>
#include <ParameterSet.h>
using namespace malmo;

// STL:
#include <sstream>
#include <cstdint>

// Python:
#include <datetime.h>

// Converts a python list to a vector of strings. Throws a python exception if the conversion fails.
std::vector< std::string > listToStrings( const boost::python::list& list )
{
    std::vector<std::string> strings;
    for( int i = 0; i < len( list ); i++ )
        strings.push_back( boost::python::extract< std::string >( list[i] ) );
    return strings;
}

// A Python wrapper around ArgumentParser::parse().
void parsePythonList( ArgumentParser* p, const boost::python::list& list )
{
    p->parse( listToStrings( list ) );
}

// Make sure we get all of the useful information from xml_schema::exception
void translateXMLSchemaException(xml_schema::exception const& e)
{
    std::ostringstream oss;
    oss << "Caught xml_schema::exception: " << e.what() << "\n" << e;
    PyErr_SetString(PyExc_RuntimeError, oss.str().c_str() );
}

void (AgentHost::*startMissionSimple)(const MissionSpec&, const MissionRecordSpec&) = &AgentHost::startMission;
void (AgentHost::*startMissionComplex)(const MissionSpec&, const ClientPool&, const MissionRecordSpec&, int, std::string) = &AgentHost::startMission;

#ifdef WRAP_ALE
void (ALEAgentHost::*startALEMissionSimple)(const MissionSpec&, const MissionRecordSpec&) = &ALEAgentHost::startMission;
void (ALEAgentHost::*startALEMissionComplex)(const MissionSpec&, const ClientPool&, const MissionRecordSpec&, int, std::string) = &ALEAgentHost::startMission;
#endif

struct ptime_to_python_datetime
{
    static PyObject* convert(boost::posix_time::ptime const& pt)
    {
        // Convert posix_time into python DateTime object:
        boost::gregorian::date date = pt.date();
        boost::posix_time::time_duration td = pt.time_of_day();
        static std::int64_t resolution = boost::posix_time::time_duration::ticks_per_second();
        std::int64_t fracsecs = td.fractional_seconds();
        std::int64_t usecs = (resolution > 1000000) ? fracsecs / (resolution / 1000000) : fracsecs * (1000000 / resolution);

        return PyDateTime_FromDateAndTime((int)date.year(), (int)date.month(), (int)date.day(), td.hours(), td.minutes(), td.seconds(), (int)usecs);
    }
};

// Defines the API available to Python.
BOOST_PYTHON_MODULE(MalmoPython)
{
    using namespace boost::python;

    // Bind the converter for posix_time to python DateTime
    PyDateTime_IMPORT;
    to_python_converter<boost::posix_time::ptime, ptime_to_python_datetime>();

    class_< ArgumentParser, boost::noncopyable >("ArgumentParser", init< const std::string& >())
        .def( "parse",                     &parsePythonList )
        .def( "addOptionalIntArgument",    &ArgumentParser::addOptionalIntArgument )
        .def( "addOptionalFloatArgument",  &ArgumentParser::addOptionalFloatArgument )
        .def( "addOptionalStringArgument", &ArgumentParser::addOptionalStringArgument )
        .def( "addOptionalFlag",           &ArgumentParser::addOptionalFlag )
        .def( "getUsage",                  &ArgumentParser::getUsage )
        .def( "receivedArgument",          &ArgumentParser::receivedArgument )
        .def( "getIntArgument",            &ArgumentParser::getIntArgument )
        .def( "getFloatArgument",          &ArgumentParser::getFloatArgument )
        .def( "getStringArgument",         &ArgumentParser::getStringArgument )
    ;
    class_< WorldState >( "WorldState", no_init )
        .def_readonly( "is_mission_running",                      &WorldState::is_mission_running )
        .def_readonly( "number_of_observations_since_last_state", &WorldState::number_of_observations_since_last_state )
        .def_readonly( "number_of_rewards_since_last_state",      &WorldState::number_of_rewards_since_last_state )
        .def_readonly( "number_of_video_frames_since_last_state", &WorldState::number_of_video_frames_since_last_state )
        .def_readonly( "observations",                            &WorldState::observations )
        .def_readonly( "rewards",                                 &WorldState::rewards )
        .def_readonly( "video_frames",                            &WorldState::video_frames )
        .def_readonly( "mission_control_messages",                &WorldState::mission_control_messages )
        .def_readonly( "errors",                                  &WorldState::errors )
        .def(self_ns::str(self_ns::self))
    ;
    enum_< AgentHost::VideoPolicy >( "VideoPolicy" )
        .value( "LATEST_FRAME_ONLY",  AgentHost::LATEST_FRAME_ONLY )
        .value( "KEEP_ALL_FRAMES",    AgentHost::KEEP_ALL_FRAMES )
    ;
    enum_< AgentHost::RewardsPolicy >( "RewardsPolicy" )
        .value( "LATEST_REWARD_ONLY",  AgentHost::LATEST_REWARD_ONLY )
        .value( "SUM_REWARDS",         AgentHost::SUM_REWARDS )
        .value( "KEEP_ALL_REWARDS",    AgentHost::KEEP_ALL_REWARDS )
    ;
    enum_< AgentHost::ObservationsPolicy >( "ObservationsPolicy" )
        .value( "LATEST_OBSERVATION_ONLY",  AgentHost::LATEST_OBSERVATION_ONLY )
        .value( "KEEP_ALL_OBSERVATIONS",    AgentHost::KEEP_ALL_OBSERVATIONS )
    ;
    class_< AgentHost, bases< ArgumentParser >, boost::noncopyable >("AgentHost", init<>())
        .def( "startMission",              startMissionSimple )
        .def( "startMission",              startMissionComplex )
        .def( "peekWorldState",            &AgentHost::peekWorldState )
        .def( "getWorldState",             &AgentHost::getWorldState )
        .def( "setVideoPolicy",            &AgentHost::setVideoPolicy )
        .def( "setRewardsPolicy",          &AgentHost::setRewardsPolicy )
        .def( "setObservationsPolicy",     &AgentHost::setObservationsPolicy )
        .def( "sendCommand",               &AgentHost::sendCommand )
        .def(self_ns::str(self_ns::self))
    ;
#ifdef WRAP_ALE
    class_< ALEAgentHost, bases< ArgumentParser >, boost::noncopyable >("ALEAgentHost", init<>())
        .def("startMission",           startALEMissionSimple)
        .def("startMission",           startALEMissionComplex)
        .def("peekWorldState",         &ALEAgentHost::getWorldState)
        .def("getWorldState",          &ALEAgentHost::getWorldState)
        .def("setVideoPolicy",         &ALEAgentHost::setVideoPolicy)
        .def("setRewardsPolicy",       &ALEAgentHost::setRewardsPolicy)
        .def("setObservationsPolicy",  &ALEAgentHost::setObservationsPolicy)
        .def("sendCommand",            &ALEAgentHost::sendCommand)
        .def(self_ns::str(self_ns::self))
        ;
#endif
    class_< MissionSpec >( "MissionSpec", init<>() )
        .def(init< const std::string&, bool >())
        .def("getAsXML",                  &MissionSpec::getAsXML)
        .def("timeLimitInSeconds",        &MissionSpec::timeLimitInSeconds)
        .def("createDefaultTerrain",      &MissionSpec::createDefaultTerrain)
        .def("forceWorldReset",           &MissionSpec::forceWorldReset)
        .def("setWorldSeed",              &MissionSpec::setWorldSeed)
        .def("setTimeOfDay",              &MissionSpec::setTimeOfDay)
        .def("drawBlock",                 &MissionSpec::drawBlock)
        .def("drawCuboid",                &MissionSpec::drawCuboid)<commit_msg>Fix: ALEAgentHost::peekWorldState was bound to getWorldState. This fixes #165.<commit_after>// --------------------------------------------------------------------------------------------------
//  Copyright (c) 2016 Microsoft Corporation
//  
//  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.
// --------------------------------------------------------------------------------------------------

// Boost:
#include <boost/python.hpp>
#include <boost/python/exception_translator.hpp>
#include <boost/python/register_ptr_to_python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/python/to_python_converter.hpp>

// Malmo:
#include <AgentHost.h>
#ifdef WRAP_ALE
    #include <ALEAgentHost.h>
#endif
#include <ClientPool.h>
#include <MissionSpec.h>
#include <ParameterSet.h>
using namespace malmo;

// STL:
#include <sstream>
#include <cstdint>

// Python:
#include <datetime.h>

// Converts a python list to a vector of strings. Throws a python exception if the conversion fails.
std::vector< std::string > listToStrings( const boost::python::list& list )
{
    std::vector<std::string> strings;
    for( int i = 0; i < len( list ); i++ )
        strings.push_back( boost::python::extract< std::string >( list[i] ) );
    return strings;
}

// A Python wrapper around ArgumentParser::parse().
void parsePythonList( ArgumentParser* p, const boost::python::list& list )
{
    p->parse( listToStrings( list ) );
}

// Make sure we get all of the useful information from xml_schema::exception
void translateXMLSchemaException(xml_schema::exception const& e)
{
    std::ostringstream oss;
    oss << "Caught xml_schema::exception: " << e.what() << "\n" << e;
    PyErr_SetString(PyExc_RuntimeError, oss.str().c_str() );
}

void (AgentHost::*startMissionSimple)(const MissionSpec&, const MissionRecordSpec&) = &AgentHost::startMission;
void (AgentHost::*startMissionComplex)(const MissionSpec&, const ClientPool&, const MissionRecordSpec&, int, std::string) = &AgentHost::startMission;

#ifdef WRAP_ALE
void (ALEAgentHost::*startALEMissionSimple)(const MissionSpec&, const MissionRecordSpec&) = &ALEAgentHost::startMission;
void (ALEAgentHost::*startALEMissionComplex)(const MissionSpec&, const ClientPool&, const MissionRecordSpec&, int, std::string) = &ALEAgentHost::startMission;
#endif

struct ptime_to_python_datetime
{
    static PyObject* convert(boost::posix_time::ptime const& pt)
    {
        // Convert posix_time into python DateTime object:
        boost::gregorian::date date = pt.date();
        boost::posix_time::time_duration td = pt.time_of_day();
        static std::int64_t resolution = boost::posix_time::time_duration::ticks_per_second();
        std::int64_t fracsecs = td.fractional_seconds();
        std::int64_t usecs = (resolution > 1000000) ? fracsecs / (resolution / 1000000) : fracsecs * (1000000 / resolution);

        return PyDateTime_FromDateAndTime((int)date.year(), (int)date.month(), (int)date.day(), td.hours(), td.minutes(), td.seconds(), (int)usecs);
    }
};

// Defines the API available to Python.
BOOST_PYTHON_MODULE(MalmoPython)
{
    using namespace boost::python;

    // Bind the converter for posix_time to python DateTime
    PyDateTime_IMPORT;
    to_python_converter<boost::posix_time::ptime, ptime_to_python_datetime>();

    class_< ArgumentParser, boost::noncopyable >("ArgumentParser", init< const std::string& >())
        .def( "parse",                     &parsePythonList )
        .def( "addOptionalIntArgument",    &ArgumentParser::addOptionalIntArgument )
        .def( "addOptionalFloatArgument",  &ArgumentParser::addOptionalFloatArgument )
        .def( "addOptionalStringArgument", &ArgumentParser::addOptionalStringArgument )
        .def( "addOptionalFlag",           &ArgumentParser::addOptionalFlag )
        .def( "getUsage",                  &ArgumentParser::getUsage )
        .def( "receivedArgument",          &ArgumentParser::receivedArgument )
        .def( "getIntArgument",            &ArgumentParser::getIntArgument )
        .def( "getFloatArgument",          &ArgumentParser::getFloatArgument )
        .def( "getStringArgument",         &ArgumentParser::getStringArgument )
    ;
    class_< WorldState >( "WorldState", no_init )
        .def_readonly( "is_mission_running",                      &WorldState::is_mission_running )
        .def_readonly( "number_of_observations_since_last_state", &WorldState::number_of_observations_since_last_state )
        .def_readonly( "number_of_rewards_since_last_state",      &WorldState::number_of_rewards_since_last_state )
        .def_readonly( "number_of_video_frames_since_last_state", &WorldState::number_of_video_frames_since_last_state )
        .def_readonly( "observations",                            &WorldState::observations )
        .def_readonly( "rewards",                                 &WorldState::rewards )
        .def_readonly( "video_frames",                            &WorldState::video_frames )
        .def_readonly( "mission_control_messages",                &WorldState::mission_control_messages )
        .def_readonly( "errors",                                  &WorldState::errors )
        .def(self_ns::str(self_ns::self))
    ;
    enum_< AgentHost::VideoPolicy >( "VideoPolicy" )
        .value( "LATEST_FRAME_ONLY",  AgentHost::LATEST_FRAME_ONLY )
        .value( "KEEP_ALL_FRAMES",    AgentHost::KEEP_ALL_FRAMES )
    ;
    enum_< AgentHost::RewardsPolicy >( "RewardsPolicy" )
        .value( "LATEST_REWARD_ONLY",  AgentHost::LATEST_REWARD_ONLY )
        .value( "SUM_REWARDS",         AgentHost::SUM_REWARDS )
        .value( "KEEP_ALL_REWARDS",    AgentHost::KEEP_ALL_REWARDS )
    ;
    enum_< AgentHost::ObservationsPolicy >( "ObservationsPolicy" )
        .value( "LATEST_OBSERVATION_ONLY",  AgentHost::LATEST_OBSERVATION_ONLY )
        .value( "KEEP_ALL_OBSERVATIONS",    AgentHost::KEEP_ALL_OBSERVATIONS )
    ;
    class_< AgentHost, bases< ArgumentParser >, boost::noncopyable >("AgentHost", init<>())
        .def( "startMission",              startMissionSimple )
        .def( "startMission",              startMissionComplex )
        .def( "peekWorldState",            &AgentHost::peekWorldState )
        .def( "getWorldState",             &AgentHost::getWorldState )
        .def( "setVideoPolicy",            &AgentHost::setVideoPolicy )
        .def( "setRewardsPolicy",          &AgentHost::setRewardsPolicy )
        .def( "setObservationsPolicy",     &AgentHost::setObservationsPolicy )
        .def( "sendCommand",               &AgentHost::sendCommand )
        .def(self_ns::str(self_ns::self))
    ;
#ifdef WRAP_ALE
    class_< ALEAgentHost, bases< ArgumentParser >, boost::noncopyable >("ALEAgentHost", init<>())
        .def("startMission",           startALEMissionSimple)
        .def("startMission",           startALEMissionComplex)
        .def("peekWorldState",         &ALEAgentHost::peekWorldState)
        .def("getWorldState",          &ALEAgentHost::getWorldState)
        .def("setVideoPolicy",         &ALEAgentHost::setVideoPolicy)
        .def("setRewardsPolicy",       &ALEAgentHost::setRewardsPolicy)
        .def("setObservationsPolicy",  &ALEAgentHost::setObservationsPolicy)
        .def("sendCommand",            &ALEAgentHost::sendCommand)
        .def(self_ns::str(self_ns::self))
        ;
#endif
    class_< MissionSpec >( "MissionSpec", init<>() )
        .def(init< const std::string&, bool >())
        .def("getAsXML",                  &MissionSpec::getAsXML)
        .def("timeLimitInSeconds",        &MissionSpec::timeLimitInSeconds)
        .def("createDefaultTerrain",      &MissionSpec::createDefaultTerrain)
        .def("forceWorldReset",           &MissionSpec::forceWorldReset)
        .def("setWorldSeed",              &MissionSpec::setWorldSeed)
        .def("setTimeOfDay",              &MissionSpec::setTimeOfDay)
        .def("drawBlock",                 &MissionSpec::drawBlock)
        .def("drawCuboid",                &MissionSpec::drawCuboid)
{'fraction_non_alphanumeric': 0.13767472820057688, 'fraction_numerical': 0.003716441091635234, 'mean_word_length': 3.0615003379139445, 'pattern_counts': {'":': 0, '<': 85, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2353709', 'n_tokens_mistral': 5306, 'n_tokens_neox': 5145, 'n_words': 1137}