<commit_before>#ifndef RECURSE_HPP
#define RECURSE_HPP

#include <QCoreApplication>
#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostAddress>
#include <QHash>
#include <QStringBuilder>
#include <QVector>
#include "request.hpp"
#include "response.hpp"

#include <iostream>
#include <functional>
using std::function;
using std::bind;
using std::ref;

typedef function<void(Request &request, Response &response, function<void()> next)> next_f;

//!
//! \brief The Recurse class
//! main class of the app
//!
class Recurse : public QObject
{
public:

    Recurse(int & argc, char ** argv, QObject *parent = NULL);
    ~Recurse();

    bool listen(quint64 port, QHostAddress address = QHostAddress::Any);
    void use(next_f next);

private:
    QCoreApplication app;
    QTcpServer m_tcp_server;
    quint64 m_port;
    QVector<next_f> m_middleware;
    int current_middleware = 0;
    void m_next(Request &request, Response &response);
    void http_parse(Request &request);
    QString http_build_header(const Response &response);
};

Recurse::Recurse(int & argc, char ** argv, QObject *parent) : app(argc, argv)
{
    Q_UNUSED(parent);
};

Recurse::~Recurse()
{

};

//!
//! \brief Recurse::listen
//! listen for tcp requests
//!
//! \param port tcp server port
//! \param address tcp server listening address
//!
//! \return true on success
//!
bool Recurse::listen(quint64 port, QHostAddress address)
{
    m_port = port;
    int bound = m_tcp_server.listen(address, port);
    if (!bound)
        return false;

    connect(&m_tcp_server, &QTcpServer::newConnection, [this] {
        qDebug() << "client connected";
        QTcpSocket *client = m_tcp_server.nextPendingConnection();

        connect(client, &QTcpSocket::readyRead, [this, client] {
            Request request;
            Response response;

            request.data = client->readAll();
            QRegExp httpRx("^(?=[A-Z]).* \\/.* HTTP\\/[0-9]\\.[0-9]\\r\\n");
            bool isHttp = request.data.contains(httpRx);

            if (isHttp)
                http_parse(request);

            qDebug() << "client request: " << request.data;

            if (m_middleware.count() > 0)
                m_middleware[current_middleware](request, response, bind(&Recurse::m_next, this, ref(request), ref(response)));

            current_middleware = 0;
            QString header;

            if (isHttp) {
                response.method = request.method;
                response.proto = request.proto;

                if (response.status == 0)
                    response.status = 200;

                header = http_build_header(response);
            }

            QString foo = header + "\r\n\r\n" + response.body;
            std::cout << foo.toStdString() << std::endl;
            // qDebug() << "middleware end; resp:" << foo2;

            // send response to the client
            auto check = client->write(foo.toStdString().c_str(), foo.size());
            qDebug() << "socket write debug:" << check;
            client->close();
        });
    });

    return app.exec();
};

//!
//! \brief Recurse::m_next
//! call next middleware
//!
void Recurse::m_next(Request &request, Response &response)
{
    qDebug() << "calling next:" << current_middleware << " num:" << m_middleware.size();

    if (++current_middleware >= m_middleware.size()) {
        return;
    };

    m_middleware[current_middleware](request, response, bind(&Recurse::m_next, this, ref(request), ref(response)));

};

//!
//! \brief Recurse::use
//! add new middleware
//!
//! \param f middleware function that will be called later
//!
void Recurse::use(next_f f)
{
    m_middleware.push_back(f);
};

//!
//! \brief Recurse::http_parse
//! parse http data
//!
//! \param data reference to data received from the tcp connection
//!
void Recurse::http_parse(Request &request)
{
    QStringList data_list = request.data.split("\r\n");
    bool is_body = false;

    for (int i = 0; i < data_list.size(); ++i) {
        QStringList item_list = data_list.at(i).split(":");

        if (item_list.length() < 2 && item_list.at(0).size() < 1 && !is_body) {
            is_body = true;
            continue;
        }
        else if (i == 0 && item_list.length() < 2) {
            QStringList first_line = item_list.at(0).split(" ");
            request.method = first_line.at(0);
            request.url = first_line.at(1).trimmed();
            request.proto = first_line.at(2).trimmed();
        }
        else if (!is_body) {
            request.header[item_list.at(0).toLower()] = item_list.at(1).trimmed();
        }
        else {
            request.body.append(item_list.at(0));
        }
    }

    qDebug() << "request ctx ready: " << request.method << request.url << request.header << request.proto << request.body;
};

//!
//! \brief Recurse::http_build_header
//! build http header for response
//!
//! \param response reference to the Response instance
//!
QString Recurse::http_build_header(const Response &response)
{
    qDebug() << "resp header:" << response.header["content-type"];

    QString header = response.proto % " " % QString::number(response.status) % " "
        % response.http_codes[response.status] % "\r\n";

    if (response.header["content-type"] == "")
        header += "content-type: text/html; charset=utf-8";
    else
        header += "content-type: " % response.header["content-type"];

    qDebug() << "header" << header;

    return header;
    // response.body = header + "\r\n\r\n" + response.body;
}

#endif // RECURSE_HPP
<commit_msg>response: consolidate response data<commit_after>#ifndef RECURSE_HPP
#define RECURSE_HPP

#include <QCoreApplication>
#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostAddress>
#include <QHash>
#include <QStringBuilder>
#include <QVector>
#include "request.hpp"
#include "response.hpp"

#include <iostream>
#include <functional>
using std::function;
using std::bind;
using std::ref;

typedef function<void(Request &request, Response &response, function<void()> next)> next_f;

//!
//! \brief The Recurse class
//! main class of the app
//!
class Recurse : public QObject
{
public:

    Recurse(int & argc, char ** argv, QObject *parent = NULL);
    ~Recurse();

    bool listen(quint64 port, QHostAddress address = QHostAddress::Any);
    void use(next_f next);

private:
    QCoreApplication app;
    QTcpServer m_tcp_server;
    quint64 m_port;
    QVector<next_f> m_middleware;
    int current_middleware = 0;
    void m_next(Request &request, Response &response);
    void http_parse(Request &request);
    QString http_build_header(const Response &response);
};

Recurse::Recurse(int & argc, char ** argv, QObject *parent) : app(argc, argv)
{
    Q_UNUSED(parent);
};

Recurse::~Recurse()
{

};

//!
//! \brief Recurse::listen
//! listen for tcp requests
//!
//! \param port tcp server port
//! \param address tcp server listening address
//!
//! \return true on success
//!
bool Recurse::listen(quint64 port, QHostAddress address)
{
    m_port = port;
    int bound = m_tcp_server.listen(address, port);
    if (!bound)
        return false;

    connect(&m_tcp_server, &QTcpServer::newConnection, [this] {
        qDebug() << "client connected";
        QTcpSocket *client = m_tcp_server.nextPendingConnection();

        connect(client, &QTcpSocket::readyRead, [this, client] {
            Request request;
            Response response;

            request.data = client->readAll();
            QRegExp httpRx("^(?=[A-Z]).* \\/.* HTTP\\/[0-9]\\.[0-9]\\r\\n");
            bool isHttp = request.data.contains(httpRx);

            if (isHttp)
                http_parse(request);

            qDebug() << "client request: " << request.data;

            if (m_middleware.count() > 0)
                m_middleware[current_middleware](request, response, bind(&Recurse::m_next, this, ref(request), ref(response)));

            current_middleware = 0;
            QString header;

            if (isHttp) {
                response.method = request.method;
                response.proto = request.proto;

                if (response.status == 0)
                    response.status = 200;

                header = http_build_header(response) + "\r\n\r\n";
            }

            QString response_data = header + response.body;

            // send response to the client
            qint64 check = client->write(response_data.toStdString().c_str(), response_data.size());

            qDebug() << "socket write debug:" << check;
            client->close();
        });
    });

    return app.exec();
};

//!
//! \brief Recurse::m_next
//! call next middleware
//!
void Recurse::m_next(Request &request, Response &response)
{
    qDebug() << "calling next:" << current_middleware << " num:" << m_middleware.size();

    if (++current_middleware >= m_middleware.size()) {
        return;
    };

    m_middleware[current_middleware](request, response, bind(&Recurse::m_next, this, ref(request), ref(response)));

};

//!
//! \brief Recurse::use
//! add new middleware
//!
//! \param f middleware function that will be called later
//!
void Recurse::use(next_f f)
{
    m_middleware.push_back(f);
};

//!
//! \brief Recurse::http_parse
//! parse http data
//!
//! \param data reference to data received from the tcp connection
//!
void Recurse::http_parse(Request &request)
{
    QStringList data_list = request.data.split("\r\n");
    bool is_body = false;

    for (int i = 0; i < data_list.size(); ++i) {
        QStringList item_list = data_list.at(i).split(":");

        if (item_list.length() < 2 && item_list.at(0).size() < 1 && !is_body) {
            is_body = true;
            continue;
        }
        else if (i == 0 && item_list.length() < 2) {
            QStringList first_line = item_list.at(0).split(" ");
            request.method = first_line.at(0);
            request.url = first_line.at(1).trimmed();
            request.proto = first_line.at(2).trimmed();
        }
        else if (!is_body) {
            request.header[item_list.at(0).toLower()] = item_list.at(1).trimmed();
        }
        else {
            request.body.append(item_list.at(0));
        }
    }

    qDebug() << "request ctx ready: " << request.method << request.url << request.header << request.proto << request.body;
};

//!
//! \brief Recurse::http_build_header
//! build http header for response
//!
//! \param response reference to the Response instance
//!
QString Recurse::http_build_header(const Response &response)
{
    qDebug() << "resp header:" << response.header["content-type"];

    QString header = response.proto % " " % QString::number(response.status) % " "
        % response.http_codes[response.status] % "\r\n";

    if (response.header["content-type"] == "")
        header += "content-type: text/html; charset=utf-8";
    else
        header += "content-type: " % response.header["content-type"];

    qDebug() << "header" << header;

    return header;
    // response.body = header + "\r\n\r\n" + response.body;
}

#endif // RECURSE_HPP
<|endoftext|>


<commit_before>#ifndef RECURSE_HPP
#define RECURSE_HPP

#include <QCoreApplication>
#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostAddress>
#include <QHash>
#include <QStringBuilder>
#include <QVector>
#include <functional>

#include "request.hpp"
#include "response.hpp"
#include "context.hpp"

//!
//! \brief The Recurse class
//! main class of the app
//!
class Recurse : public QObject
{
    typedef std::function<void()> void_f;
    typedef std::function<void(Context &ctx, void_f next)> next_f;
    typedef std::function<void(Context &ctx)> final_f;

public:
    Recurse(int & argc, char ** argv, QObject *parent = NULL);
    ~Recurse();

    bool listen(quint64 port, QHostAddress address = QHostAddress::Any);
    void use(next_f next);
    void use(QVector<next_f> nexts);
    void use(final_f next);
    void end(Context *ctx);

private:
    QCoreApplication app;
    QTcpServer m_tcp_server;

    quint64 m_port;
    QVector<next_f> m_middleware;

    void m_next(Context *ctx, int current_middleware);
};

Recurse::Recurse(int & argc, char ** argv, QObject *parent) : app(argc, argv)
{
    Q_UNUSED(parent);
};

Recurse::~Recurse()
{

};

//!
//! \brief Recurse::listen
//! listen for tcp requests
//!
//! \param port tcp server port
//! \param address tcp server listening address
//!
//! \return true on success
//!
bool Recurse::listen(quint64 port, QHostAddress address)
{
    m_port = port;
    int bound = m_tcp_server.listen(address, port);
    if (!bound)
        return false;

    connect(&m_tcp_server, &QTcpServer::newConnection, [this] {
        qDebug() << "client connected";

        auto ctx= new Context;
        ctx->request.socket = m_tcp_server.nextPendingConnection();

        connect(ctx->request.socket, &QTcpSocket::readyRead, [this, ctx] {

            QString data(ctx->request.socket->readAll());
            qDebug() << "ctx request: " << data;

            ctx->request.parse(data);

            if (ctx->request.length < ctx->request.header["content-length"].toLongLong())
                    return;

            if (m_middleware.count() > 0) {
                ctx->response.end = std::bind(&Recurse::end, this, ctx);

                m_middleware[0]( *ctx, std::bind(&Recurse::m_next, this, ctx, 0) );
            }
        });
    });

    return app.exec();
};

//!
//! \brief Recurse::m_next
//! call next middleware
//!
void Recurse::m_next(Context *ctx, int current_middleware)
{
    qDebug() << "calling next:" << current_middleware << " num:" << m_middleware.size();

    if (++current_middleware >= m_middleware.size()) {
        return;
    };

    m_middleware[current_middleware]( *ctx, std::bind(&Recurse::m_next, this, ctx, current_middleware) );
};

//!
//! \brief Recurse::use
//! add new middleware
//!
//! \param f middleware function that will be called later
//!
//!
//!
void Recurse::use(next_f f)
{
    m_middleware.push_back(f);
};

//!
//! \brief Recurse::use
//! overloaded function,
//! add multiple middlewares
//! very useful for third party modules
//!
//! \param f vector of middlewares
//!
void Recurse::use(QVector<next_f> f)
{
    for(const auto &g : f)
        m_middleware.push_back(g);
};

//!
//! \brief Recurse::use
//! overloaded function,
//! final middleware that doesn't call next, used for returning response
//!
//! \param f final middleware function that will be called last
//!
void Recurse::use(final_f f)
{
    m_middleware.push_back([f](Context &ctx,  void_f /* next */) {
        f(ctx);
    });
};

//!
//! \brief Recurse::end
//! final function to be called for creating/sending response
//! \param request
//! \param response
//!
void Recurse::end(Context *ctx)
{
    Request &request = ctx->request;
    Response &response = ctx->response;

    qDebug() << "calling end with:" << response.body();

    response.method = request.method;
    response.protocol = request.protocol;

    QString reply = response.create_reply();

    // send response to the client
    qint64 check = request.socket->write(reply.toUtf8());

    qDebug() << "socket write debug:" << check;
    request.socket->close();

    delete ctx;
};

#endif // RECURSE_HPP
<commit_msg>recurse: indentation fix<commit_after>#ifndef RECURSE_HPP
#define RECURSE_HPP

#include <QCoreApplication>
#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostAddress>
#include <QHash>
#include <QStringBuilder>
#include <QVector>
#include <functional>

#include "request.hpp"
#include "response.hpp"
#include "context.hpp"

//!
//! \brief The Recurse class
//! main class of the app
//!
class Recurse : public QObject
{
    typedef std::function<void()> void_f;
    typedef std::function<void(Context &ctx, void_f next)> next_f;
    typedef std::function<void(Context &ctx)> final_f;

public:
    Recurse(int & argc, char ** argv, QObject *parent = NULL);
    ~Recurse();

    bool listen(quint64 port, QHostAddress address = QHostAddress::Any);
    void use(next_f next);
    void use(QVector<next_f> nexts);
    void use(final_f next);
    void end(Context *ctx);

private:
    QCoreApplication app;
    QTcpServer m_tcp_server;

    quint64 m_port;
    QVector<next_f> m_middleware;

    void m_next(Context *ctx, int current_middleware);
};

Recurse::Recurse(int & argc, char ** argv, QObject *parent) : app(argc, argv)
{
    Q_UNUSED(parent);
};

Recurse::~Recurse()
{

};

//!
//! \brief Recurse::listen
//! listen for tcp requests
//!
//! \param port tcp server port
//! \param address tcp server listening address
//!
//! \return true on success
//!
bool Recurse::listen(quint64 port, QHostAddress address)
{
    m_port = port;
    int bound = m_tcp_server.listen(address, port);
    if (!bound)
        return false;

    connect(&m_tcp_server, &QTcpServer::newConnection, [this] {
        qDebug() << "client connected";

        auto ctx= new Context;
        ctx->request.socket = m_tcp_server.nextPendingConnection();

        connect(ctx->request.socket, &QTcpSocket::readyRead, [this, ctx] {

            QString data(ctx->request.socket->readAll());
            qDebug() << "ctx request: " << data;

            ctx->request.parse(data);

            if (ctx->request.length < ctx->request.header["content-length"].toLongLong())
                return;

            if (m_middleware.count() > 0) {
                ctx->response.end = std::bind(&Recurse::end, this, ctx);

                m_middleware[0]( *ctx, std::bind(&Recurse::m_next, this, ctx, 0) );
            }
        });
    });

    return app.exec();
};

//!
//! \brief Recurse::m_next
//! call next middleware
//!
void Recurse::m_next(Context *ctx, int current_middleware)
{
    qDebug() << "calling next:" << current_middleware << " num:" << m_middleware.size();

    if (++current_middleware >= m_middleware.size()) {
        return;
    };

    m_middleware[current_middleware]( *ctx, std::bind(&Recurse::m_next, this, ctx, current_middleware) );
};

//!
//! \brief Recurse::use
//! add new middleware
//!
//! \param f middleware function that will be called later
//!
//!
//!
void Recurse::use(next_f f)
{
    m_middleware.push_back(f);
};

//!
//! \brief Recurse::use
//! overloaded function,
//! add multiple middlewares
//! very useful for third party modules
//!
//! \param f vector of middlewares
//!
void Recurse::use(QVector<next_f> f)
{
    for(const auto &g : f)
        m_middleware.push_back(g);
};

//!
//! \brief Recurse::use
//! overloaded function,
//! final middleware that doesn't call next, used for returning response
//!
//! \param f final middleware function that will be called last
//!
void Recurse::use(final_f f)
{
    m_middleware.push_back([f](Context &ctx,  void_f /* next */) {
        f(ctx);
    });
};

//!
//! \brief Recurse::end
//! final function to be called for creating/sending response
//! \param request
//! \param response
//!
void Recurse::end(Context *ctx)
{
    Request &request = ctx->request;
    Response &response = ctx->response;

    qDebug() << "calling end with:" << response.body();

    response.method = request.method;
    response.protocol = request.protocol;

    QString reply = response.create_reply();

    // send response to the client
    qint64 check = request.socket->write(reply.toUtf8());

    qDebug() << "socket write debug:" << check;
    request.socket->close();

    delete ctx;
};

#endif // RECURSE_HPP
<|endoftext|>


<commit_before>#ifndef COFFEE_MILL_PDB_RESIDUE
#define COFFEE_MILL_PDB_RESIDUE
#include "PDBAtom.hpp"
#include <memory>

namespace coffeemill
{

class PDBResidue
{
  public:
    using size_type      = std::size_t;
    using index_type     = size_type;
    using element_type   = std::shared_ptr<PDBAtom>;
    using container_type = std::vector<element_type>;
    using iterator       = container_type::iterator;
    using const_iterator = container_type::const_iterator;

  public:
    PDBResidue(){}
    PDBResidue(size_type size) : atoms_(size){}
    ~PDBResidue() = default;

    size_type          residue_id() const {return atoms_.front()->residue_id();}
    const std::string& residue()    const {return atoms_.front()->residue();}
    const std::string& chain_id()   const {return atoms_.front()->chain_id();}

    bool      empty() const {return atoms_.empty();}
    size_type size()  const {return atoms_.size();}
    void clear()                            {return atoms_.clear();}
    void push_back(const element_type& atom){return atoms_.push_back(atom);}

    const element_type& front() const {return atoms_.front();}
          element_type& front()       {return atoms_.front();}
    const element_type& back() const {return atoms_.back();}
          element_type& back()       {return atoms_.back();}
    const element_type& at(index_type i) const {return atoms_.at(i);}
          element_type& at(index_type i)       {return atoms_.at(i);}
    const element_type& operator[](index_type i) const {return atoms_[i];}
          element_type& operator[](index_type i)       {return atoms_[i];}

    iterator begin() {return atoms_.begin();}
    iterator end()   {return atoms_.end();}
    const_iterator cbegin() const {return atoms_.cbegin();}
    const_iterator cend()   const {return atoms_.cend();}

    void dump() const
    {
        std::cerr << "residue " << this->residue() << std::endl;
        for(auto item : atoms_) std::cout << *item << std::endl;
    }

  private:
    container_type atoms_;
};

}
#endif /* COFFEE_MILL_PDB_RESIDUE */
<commit_msg>add document of PDBResidue<commit_after>/*!
  @file PDBResidue.hpp
  @brief definition of pdb residue class

  PDBResidue class has several shared pointer of PDBAtom as std::vector.
  this behaves like std::vector.
  Note that this class does not guarantee the member PDBAtoms are the member of
  the same residue and the Atoms are sorted. User must guarantee the point.

  @author Toru Niina (niina.toru.68@gmail.com)
  @date 2016-06-10 13:00
  @copyright Toru Niina 2016 on MIT License
*/

#ifndef COFFEE_MILL_PDB_RESIDUE
#define COFFEE_MILL_PDB_RESIDUE
#include "PDBAtom.hpp"
#include <memory>

namespace coffeemill
{

//! PDBResidue class.
/*!
 * PDBResidue contains shared pointer of PDBAtom as vector.
 * this behaves like std::vector.
 */
class PDBResidue
{
  public:
    using size_type      = std::size_t;
    using index_type     = size_type;
    using element_type   = std::shared_ptr<PDBAtom>;
    using container_type = std::vector<element_type>;
    using iterator       = container_type::iterator;
    using const_iterator = container_type::const_iterator;

  public:

    //! ctor
    PDBResidue(){}
    /*!
     * @brief ctor. allocate the container with size
     * @param size number of residues. equal to size of the container.
    */
    PDBResidue(size_type size) : atoms_(size){}
    //! dtor
    ~PDBResidue() = default;

    /*!
     * @brief residue id of this residue.
     * NOTE: this class does not guarantee the atoms are in the same residue.
     * @return residue id of the 1st PDBAtom.
     */
    size_type          residue_id() const {return atoms_.front()->residue_id();}
    /*!
     * @brief residue name of this residue.
     * NOTE: this class does not guarantee the atoms are in the same residue.
     * @return residue name of the 1st PDBAtom.
     */
    const std::string& residue()    const {return atoms_.front()->residue();}
    /*!
     * @brief chain id of this residue.
     * NOTE: this class does not guarantee the atoms are in the same chain.
     * @return chain id of the 1st PDBAtom.
     */
    const std::string& chain_id()   const {return atoms_.front()->chain_id();}

    //! return whether the container is empty or not
    bool      empty() const {return atoms_.empty();}
    //! return the number of atoms
    size_type size()  const {return atoms_.size();}
    //! clear the container
    void clear(){return atoms_.clear();}
    /*!
     * @brief push new residue into the container.
     * NOTE: this method does not check whether the ATOM line is
     *       in the same residue or not. User must guarantee the point.
     */
    void push_back(const element_type& atom){return atoms_.push_back(atom);}

    //! access to the 1st atom
    const element_type& front() const {return atoms_.front();}
    //! access to the 1st atom
          element_type& front()       {return atoms_.front();}
    //! access to the last atom
    const element_type& back() const {return atoms_.back();}
    //! access to the last atom
          element_type& back()       {return atoms_.back();}
    //! access to the i-th member
    const element_type& at(index_type i) const {return atoms_.at(i);}
    //! access to the i-th member
          element_type& at(index_type i)       {return atoms_.at(i);}
    //! access to the i-th member
    const element_type& operator[](index_type i) const {return atoms_[i];}
    //! access to the i-th member
          element_type& operator[](index_type i)       {return atoms_[i];}

    //! iterator
    iterator begin() {return atoms_.begin();}
    //! iterator
    iterator end()   {return atoms_.end();}
    //! iterator
    const_iterator cbegin() const {return atoms_.cbegin();}
    //! iterator
    const_iterator cend()   const {return atoms_.cend();}

  private:
    container_type atoms_;//!< array of *atoms
};

}
#endif /* COFFEE_MILL_PDB_RESIDUE */
<|endoftext|>


<commit_before>//============================================================================
// Name        : PinballBot.cpp
// Author      : Nico Hauser, David Schmid
// Version     : 0.1
// Description : A reinforcement learning agent that learns to play pinball
//============================================================================

#include <iostream>

#include <SDL2/SDL.h>
#include <SDL2/SDL_main.h>

#include "action/ActionsSim.cpp"

#include "sim/Simulation.h"
#include "sim/Renderer.h"

const bool					SIMULATION			= true;

const bool					RENDER				= true;
const float					FPS					= 60.0f;
const float					TIME_STEP			= 1.0f / FPS;
const float					TICK_INTERVAL		= 1000.0f / FPS;

const Uint8*				KEYS				= SDL_GetKeyboardState(NULL);

bool						quit				= false;

static Uint32				next_time			= 0;

Uint32 timeLeft(void) {
    Uint32 now = SDL_GetTicks();

    if(next_time <= now){
    	return 0;
    }else{
    	return next_time - now;
    }
}

void capFramerate(void) {
	SDL_Delay(timeLeft());
	next_time += TICK_INTERVAL;
}

void runSimulation(){

	Simulation 				sim;
	Renderer				r(320, 640, sim.getWorld());
	SDL_Event				e;

	std::vector<Action> actions = ActionsSim::actionsAvailable(sim);

	while(!quit){

		if(RENDER){
			while( SDL_PollEvent( &e ) != 0 ){
				//User requests quit
				if( e.type == SDL_QUIT ){
					quit = true;
				}

				/* Just for debugging purposes */
				if (KEYS[SDL_SCANCODE_LEFT]){
					sim.enableLeftFlipper();
				}else{
					sim.disableLeftFlipper();
				}

				if (KEYS[SDL_SCANCODE_RIGHT]){
					sim.enableRightFlipper();
				}else{
					sim.disableRightFlipper();
				}

			}
		}

		sim.step(TIME_STEP);

		if(RENDER){
			r.render();
			//sim.debugPlayingBall();
			//sim.getCurrentState();
			capFramerate();
		}
	}
}

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

	if(SIMULATION){
		runSimulation();
	}

	return 0;
}
<commit_msg>Added pause function<commit_after>//============================================================================
// Name        : PinballBot.cpp
// Author      : Nico Hauser, David Schmid
// Version     : 0.1
// Description : A reinforcement learning agent that learns to play pinball
//============================================================================

#include <iostream>

#include <SDL2/SDL.h>
#include <SDL2/SDL_main.h>

#include "action/ActionsSim.cpp"

#include "sim/Simulation.h"
#include "sim/Renderer.h"

const bool					SIMULATION			= true;

const bool					RENDER				= true;
const float					FPS					= 60.0f;
const float					TIME_STEP			= 1.0f / FPS;
const float					TICK_INTERVAL		= 1000.0f / FPS;

const Uint8*				KEYS				= SDL_GetKeyboardState(NULL);

bool						pause				= false;
bool						quit				= false;

static Uint32				next_time			= 0;

Uint32 timeLeft(void) {
    Uint32 now = SDL_GetTicks();

    if(next_time <= now){
    	return 0;
    }else{
    	return next_time - now;
    }
}

void capFramerate(void) {
	SDL_Delay(timeLeft());
	next_time += TICK_INTERVAL;
}

void runSimulation(){

	Simulation 				sim;
	Renderer				r(320, 640, sim.getWorld());
	SDL_Event				e;

	std::vector<Action> actions = ActionsSim::actionsAvailable(sim);

	while(!quit){

		if(RENDER){
			while( SDL_PollEvent( &e ) != 0 ){
				//User requests quit
				if( e.type == SDL_QUIT ){
					quit = true;
				}

				if (KEYS[SDL_SCANCODE_LEFT]){
					sim.enableLeftFlipper();
				}else{
					sim.disableLeftFlipper();
				}

				if (KEYS[SDL_SCANCODE_RIGHT]){
					sim.enableRightFlipper();
				}else{
					sim.disableRightFlipper();
				}

				if (KEYS[SDL_SCANCODE_SPACE]){
					pause = true;
				}else{
					pause = false;
				}

			}
		}

		if(!pause){

			sim.step(TIME_STEP);

				if(RENDER){
					r.render();
					//sim.debugPlayingBall();
					//sim.getCurrentState();
					capFramerate();
				}
		}else{
			next_time = SDL_GetTicks() + TICK_INTERVAL;
		}
	}
}

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

	if(SIMULATION){
		runSimulation();
	}

	return 0;
}
<|endoftext|>


<commit_before>/* dlvhex -- Answer-Set Programming with external interfaces.
 * Copyright (C) 2005, 2006, 2007 Roman Schindlauer
 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Thomas Krennwallner
 * Copyright (C) 2009, 2010 Peter Schüller
 *
 * This file is part of dlvhex.
 *
 * dlvhex 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 2.1 of
 * the License, or (at your option) any later version.
 *
 * dlvhex 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with dlvhex; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 */

/**
 * @file ProgramCtx.cpp
 * @author Thomas Krennwallner
 * @date
 *
 * @brief Program context.
 *
 *
 *
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif // HAVE_CONFIG_H

#include "dlvhex2/ProgramCtx.h"
#include "dlvhex2/Registry.h"
#include "dlvhex2/PluginContainer.h"
#include "dlvhex2/State.h"
//#include "dlvhex2/DLVProcess.h"
#include "dlvhex2/EvalHeuristicEasy.h"

#include <boost/shared_ptr.hpp>

#include <sstream>
#include <iostream>

DLVHEX_NAMESPACE_BEGIN

ProgramCtx::ProgramCtx():
		maxint(0), onlyBestModels(false)
{
}

ProgramCtx::~ProgramCtx()
{
  DBGLOG(DBG,"resetting state");
  state.reset();

  DBGLOG(DBG,"resetting callbacks");
  modelCallbacks.clear();
  finalCallbacks.clear();

  DBGLOG(DBG,"resetting modelBuilder");
  modelBuilder.reset();

  DBGLOG(DBG,"resetting parser");
  parser.reset();

  DBGLOG(DBG,"resetting evalgraph");
  evalgraph.reset();

  DBGLOG(DBG,"resetting compgraph");
  compgraph.reset();

  DBGLOG(DBG,"resetting depgraph");
  depgraph.reset();

  DBGLOG(DBG,"resetting edbList");
  std::vector<InterpretationPtr>::iterator it = edbList.begin();
  while ( it != edbList.end() )
    {
      it->reset();
      it++;
    }
  edb.reset();

  DBGLOG(DBG,"resetting inputProvider");
  inputProvider.reset();

  DBGLOG(DBG,"resetting aspsoftware");
  aspsoftware.reset();

  DBGLOG(DBG,"resetting pluginData");
  pluginData.clear();

  DBGLOG(DBG,"resetting registry, usage count was " << _registry.use_count() << " (it should be 2)");
	if( Logger::Instance().shallPrint(Logger::DBG) )
		_registry->print(Logger::Instance().stream()) << std::endl;
  _registry.reset();

  DBGLOG(DBG,"resetting pluginAtoms");
  pluginAtoms.clear();

  DBGLOG(DBG,"resetting pluginContainer, usage count was " << _pluginContainer.use_count() << " (it should be 1)");
  _pluginContainer.reset();
}

void
ProgramCtx::changeState(const boost::shared_ptr<State>& s)
{
  state = s;
}

// cannot change registry if something is already stored here
void ProgramCtx::setupRegistry(
    RegistryPtr registry)
{
  assert(
      (
        !_registry || // allow to set from nothing
        (idb.empty() && !edb && idbList.size()==0 && edbList.size()==0 && pluginAtoms.empty()) // allow to change if empty
      )
      &&
      "cannot change registry once idb or edb or pluginAtoms contains data");
  _registry = registry;
  _registry->setupAuxiliaryGroundAtomMask();
}

void ProgramCtx::changeRegistry(RegistryPtr registry)
{
  // clear everything that depends on IDs of registry
  idb.clear();
  edb.reset();
  idbList.clear();
  edbList.clear();
  pluginAtoms.clear();

  // setup new registry
  setupRegistry(registry);

  // re-add plugin atoms (using new registry)
  addPluginAtomsFromPluginContainer();
}

void ProgramCtx::setupPluginContainer(
    PluginContainerPtr pluginContainer)
{
  assert(
      (
        !_pluginContainer || // allow to set if unset
        pluginAtoms.empty() // allow to change if no atoms stored
      )
      &&
      "cannot change pluginContainer once pluginAtoms are used");
  _pluginContainer = pluginContainer;
  #warning here we could reset the pointers in all ExternalAtoms if we unset the pluginContainer
}

ASPSolverManager::SoftwareConfigurationPtr
ProgramCtx::getASPSoftware() const
{
  assert(aspsoftware != 0);
  return aspsoftware;
}

void ProgramCtx::setASPSoftware(ASPSolverManager::SoftwareConfigurationPtr software)
{
  aspsoftware = software;
}

void ProgramCtx::showPlugins() { state->showPlugins(this); }
void ProgramCtx::convert() { state->convert(this); }
void ProgramCtx::parse() { state->parse(this); }
void ProgramCtx::moduleSyntaxCheck() { state->moduleSyntaxCheck(this); }
void ProgramCtx::mlpSolver() { state->mlpSolver(this); }
void ProgramCtx::rewriteEDBIDB() { state->rewriteEDBIDB(this); }
void ProgramCtx::safetyCheck() { state->safetyCheck(this); }
void ProgramCtx::createDependencyGraph() { state->createDependencyGraph(this); }
void ProgramCtx::optimizeEDBDependencyGraph() { state->optimizeEDBDependencyGraph(this); }
void ProgramCtx::createComponentGraph() { state->createComponentGraph(this); }
void ProgramCtx::strongSafetyCheck() { state->strongSafetyCheck(this); }
void ProgramCtx::createEvalGraph() { state->createEvalGraph(this); }
void ProgramCtx::setupProgramCtx() { state->setupProgramCtx(this); }
void ProgramCtx::evaluate() { state->evaluate(this); }
void ProgramCtx::postProcess() { state->postProcess(this); }

// ============================== subprogram handling ==============================

bool ProgramCtx::SubprogramAnswerSetCallback::operator()(AnswerSetPtr model){
	answersets.push_back(model->interpretation);
	return true;
}

ProgramCtx::SubprogramAnswerSetCallback::~SubprogramAnswerSetCallback(){}

std::vector<InterpretationPtr> ProgramCtx::evaluateSubprogram(InterpretationConstPtr edb, std::vector<ID>& idb){

	ProgramCtx pc = *this;
//	pc.changeRegistry(this->registry());
	pc.idb = idb;
	pc.edb = InterpretationPtr(new Interpretation(*edb));

	return evaluateSubprogram(pc, false);
}

std::vector<InterpretationPtr> ProgramCtx::evaluateSubprogram(InputProviderPtr& ip, InterpretationConstPtr addFacts){

	ProgramCtx pc = *this;
//	pc.changeRegistry(this->registry());
	pc.idb.clear();
	pc.edb = InterpretationPtr(new Interpretation(this->registry()));
	pc.config.setOption("NumberOfModels",0);
	if( !!addFacts )
		pc.edb->getStorage() |= addFacts->getStorage();
	pc.inputProvider = ip;
	ip.reset();

	return evaluateSubprogram(pc, true);
}

std::vector<InterpretationPtr> ProgramCtx::evaluateSubprogram(ProgramCtx& pc, bool parse){

	DBGLOG(DBG, "Resetting context");
	pc.state.reset();
	pc.modelBuilder.reset();
	pc.parser.reset();
	pc.evalgraph.reset();
	pc.compgraph.reset();
	pc.depgraph.reset();
//	pc.modelBuilderFactory = ctx->modelBuilderFactory;

  if( !pc.evalHeuristic )
  {
    DBGLOG(DBG, "Setting eval heuristics");
    pc.evalHeuristic.reset(new EvalHeuristicEasy);
  }

	DBGLOG(DBG, "Starting state pipeline " << (parse ? "with" : "without") << " parsing");
	if (parse){
		pc.changeState(StatePtr(new ConvertState));
	}else{
		pc.changeState(StatePtr(new SafetyCheckState));
	}

	if (parse){
		pc.convert();
		pc.parse();
	}

	DBGLOG(DBG, "Associate PluginAtom instances with ExternalAtom instances");
	pc.associateExtAtomsWithPluginAtoms(pc.idb, true);

	pc.safetyCheck();
	pc.createDependencyGraph();
	pc.optimizeEDBDependencyGraph();
	pc.createComponentGraph();
	pc.createEvalGraph();
	pc.setupProgramCtx();

	DBGLOG(DBG, "Setting AnswerSetCallback");
	pc.modelCallbacks.clear();
	pc.finalCallbacks.clear();
	SubprogramAnswerSetCallback* spasc = new SubprogramAnswerSetCallback();
	ModelCallbackPtr spascp = ModelCallbackPtr(spasc);
	pc.modelCallbacks.push_back(spascp);

	DBGLOG(DBG, "Evaluate subprogram");
	pc.evaluate();
	std::vector<InterpretationPtr> result;
	BOOST_FOREACH (InterpretationPtr intr, spasc->answersets){
		result.push_back(intr);
	}

	return result;
}

// ============================== end subprogram handling ==============================

#if 0
PluginAtomPtr
PluginContainer::getAtom(const std::string& name) const
{
  PluginAtomMap::const_iterator pa = pluginAtoms.find(name);

  if (pa == pluginAtoms.end())
    return PluginAtomPtr();

  return pa->second;
}

#endif

void ProgramCtx::addPluginAtom(PluginAtomPtr atom)
{
  assert(!!atom);
  assert(!!_registry);
  const std::string& predicate = atom->getPredicate();
  LOG(PLUGIN,"adding PluginAtom '" << predicate << "'");
  if( pluginAtoms.find(predicate) == pluginAtoms.end() )
  {
    atom->setRegistry(_registry);
    pluginAtoms[predicate] = atom;
  }
  else
  {
    LOG(WARNING,"External atom " << predicate << " is already loaded (skipping)");
  }
}

// call processOptions for each loaded plugin
// (this is supposed to remove "recognized" options from pluginOptions)
void ProgramCtx::processPluginOptions(
    std::list<const char*>& pluginOptions)
{
  BOOST_FOREACH(PluginInterfacePtr plugin, pluginContainer()->getPlugins())
  {
    LOG(DBG,"processing options for plugin " << plugin->getPluginName());
    LOG(DBG,"currently have " << printrange(pluginOptions));
	  plugin->processOptions(pluginOptions, *this);
  }
}

void ProgramCtx::addPluginAtomsFromPluginContainer()
{
  assert(!!pluginContainer());
  assert(!!registry());

  BOOST_FOREACH(PluginInterfacePtr plugin, pluginContainer()->getPlugins())
  {
    LOG(DBG,"adding plugin atoms from plugin " << plugin->getPluginName());
    // always freshly create! (pluginatoms are linked to a registry,
    // so when using multiple registries, you have to create multiple pluginatoms)
    BOOST_FOREACH(PluginAtomPtr pap, plugin->createAtoms(*this))
    {
      assert(!!pap);
      const std::string& pred = pap->getPredicate();
      LOG(DBG,"  got plugin atom " << pred);
      if( pluginAtoms.count(pred) != 0 )
      {
        LOG(WARNING,"warning: predicate '" << pred << "' already present in PluginAtomMap (skipping)");
      }
      else
      {
        pap->setRegistry(registry());
        pluginAtoms[pred] = pap;
      }
    }
  }
}

// associate plugins in container to external atoms in registry
void ProgramCtx::associateExtAtomsWithPluginAtoms(
    const Tuple& idb, bool failOnUnknownAtom)
{
  assert(!!_registry);
  DBGLOG_SCOPE(DBG,"aEAwPA",false);
  DBGLOG(DBG,"= associateExtAtomsWithPluginAtoms");

  Tuple eatoms;

  // associate all rules
  for(Tuple::const_iterator it = idb.begin();
      it != idb.end(); ++it)
  {
    assert(it->isRule());
    // skip those without external atoms
    if( !it->doesRuleContainExtatoms() )
      continue;

    // associate all literals in rule body
    const Rule& rule = _registry->rules.getByID(*it);

    // get external atoms (recursively)
    _registry->getExternalAtomsInTuple(rule.body, eatoms);
  }

  // now associate
  for(Tuple::const_iterator it = eatoms.begin();
      it != eatoms.end(); ++it)
  {
    assert(it->isExternalAtom());

    const ExternalAtom& eatom = _registry->eatoms.getByID(*it);
    const std::string& predicate = _registry->getTermStringByID(eatom.predicate);
    // lookup pluginAtom to this eatom predicate
    PluginAtomMap::iterator itpa = pluginAtoms.find(predicate);
    if( itpa != pluginAtoms.end() )
    {
      assert(!!itpa->second);
      // we store this as a POD pointer!
      eatom.pluginAtom = itpa->second.get();
    }
    else
    {
      DBGLOG(DBG,"did not find plugin atom for predicate '" << predicate << "'");
      if( failOnUnknownAtom )
      {
        throw FatalError("did not find plugin atom "
            " for predicate '" + predicate + "'");
      }
    }
  }
}

// setup this ProgramCtx (using setupProgramCtx() for of all plugins)
void ProgramCtx::setupByPlugins()
{
  BOOST_FOREACH(PluginInterfacePtr plugin, pluginContainer()->getPlugins())
  {
    LOG(DBG,"setting up program ctx for plugin " << plugin->getPluginName());
	  plugin->setupProgramCtx(*this);
  }
}

DLVHEX_NAMESPACE_END

// Local Variables:
// mode: C++
// End:
<commit_msg>Inserted the resetting of pluginEnvironment in the destructor of ProgramCtx.<commit_after>/* dlvhex -- Answer-Set Programming with external interfaces.
 * Copyright (C) 2005, 2006, 2007 Roman Schindlauer
 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Thomas Krennwallner
 * Copyright (C) 2009, 2010 Peter Schüller
 *
 * This file is part of dlvhex.
 *
 * dlvhex 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 2.1 of
 * the License, or (at your option) any later version.
 *
 * dlvhex 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with dlvhex; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 */

/**
 * @file ProgramCtx.cpp
 * @author Thomas Krennwallner
 * @date
 *
 * @brief Program context.
 *
 *
 *
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif // HAVE_CONFIG_H

#include "dlvhex2/ProgramCtx.h"
#include "dlvhex2/Registry.h"
#include "dlvhex2/PluginContainer.h"
#include "dlvhex2/State.h"
//#include "dlvhex2/DLVProcess.h"
#include "dlvhex2/EvalHeuristicEasy.h"

#include <boost/shared_ptr.hpp>

#include <sstream>
#include <iostream>

DLVHEX_NAMESPACE_BEGIN

ProgramCtx::ProgramCtx():
		maxint(0), onlyBestModels(false)
{
}

ProgramCtx::~ProgramCtx()
{
  DBGLOG(DBG,"resetting state");
  state.reset();

  DBGLOG(DBG,"resetting callbacks");
  modelCallbacks.clear();
  finalCallbacks.clear();

  DBGLOG(DBG,"resetting modelBuilder");
  modelBuilder.reset();

  DBGLOG(DBG,"resetting parser");
  parser.reset();

  DBGLOG(DBG,"resetting evalgraph");
  evalgraph.reset();

  DBGLOG(DBG,"resetting compgraph");
  compgraph.reset();

  DBGLOG(DBG,"resetting depgraph");
  depgraph.reset();

  DBGLOG(DBG,"resetting edbList");
  std::vector<InterpretationPtr>::iterator it = edbList.begin();
  while ( it != edbList.end() )
    {
      it->reset();
      it++;
    }
  edb.reset();

  DBGLOG(DBG,"resetting inputProvider");
  inputProvider.reset();

  DBGLOG(DBG,"resetting aspsoftware");
  aspsoftware.reset();

  DBGLOG(DBG,"resetting pluginData");
  pluginData.clear();

  DBGLOG(DBG,"resetting pluginEnvironment");
  pluginEnvironment.clear();

  DBGLOG(DBG,"resetting registry, usage count was " << _registry.use_count() << " (it should be 2)");
	if( Logger::Instance().shallPrint(Logger::DBG) )
		_registry->print(Logger::Instance().stream()) << std::endl;
  _registry.reset();

  DBGLOG(DBG,"resetting pluginAtoms");
  pluginAtoms.clear();

  DBGLOG(DBG,"resetting pluginContainer, usage count was " << _pluginContainer.use_count() << " (it should be 1)");
  _pluginContainer.reset();
}

void
ProgramCtx::changeState(const boost::shared_ptr<State>& s)
{
  state = s;
}

// cannot change registry if something is already stored here
void ProgramCtx::setupRegistry(
    RegistryPtr registry)
{
  assert(
      (
        !_registry || // allow to set from nothing
        (idb.empty() && !edb && idbList.size()==0 && edbList.size()==0 && pluginAtoms.empty()) // allow to change if empty
      )
      &&
      "cannot change registry once idb or edb or pluginAtoms contains data");
  _registry = registry;
  _registry->setupAuxiliaryGroundAtomMask();
}

void ProgramCtx::changeRegistry(RegistryPtr registry)
{
  // clear everything that depends on IDs of registry
  idb.clear();
  edb.reset();
  idbList.clear();
  edbList.clear();
  pluginAtoms.clear();

  // setup new registry
  setupRegistry(registry);

  // re-add plugin atoms (using new registry)
  addPluginAtomsFromPluginContainer();
}

void ProgramCtx::setupPluginContainer(
    PluginContainerPtr pluginContainer)
{
  assert(
      (
        !_pluginContainer || // allow to set if unset
        pluginAtoms.empty() // allow to change if no atoms stored
      )
      &&
      "cannot change pluginContainer once pluginAtoms are used");
  _pluginContainer = pluginContainer;
  #warning here we could reset the pointers in all ExternalAtoms if we unset the pluginContainer
}

ASPSolverManager::SoftwareConfigurationPtr
ProgramCtx::getASPSoftware() const
{
  assert(aspsoftware != 0);
  return aspsoftware;
}

void ProgramCtx::setASPSoftware(ASPSolverManager::SoftwareConfigurationPtr software)
{
  aspsoftware = software;
}

void ProgramCtx::showPlugins() { state->showPlugins(this); }
void ProgramCtx::convert() { state->convert(this); }
void ProgramCtx::parse() { state->parse(this); }
void ProgramCtx::moduleSyntaxCheck() { state->moduleSyntaxCheck(this); }
void ProgramCtx::mlpSolver() { state->mlpSolver(this); }
void ProgramCtx::rewriteEDBIDB() { state->rewriteEDBIDB(this); }
void ProgramCtx::safetyCheck() { state->safetyCheck(this); }
void ProgramCtx::createDependencyGraph() { state->createDependencyGraph(this); }
void ProgramCtx::optimizeEDBDependencyGraph() { state->optimizeEDBDependencyGraph(this); }
void ProgramCtx::createComponentGraph() { state->createComponentGraph(this); }
void ProgramCtx::strongSafetyCheck() { state->strongSafetyCheck(this); }
void ProgramCtx::createEvalGraph() { state->createEvalGraph(this); }
void ProgramCtx::setupProgramCtx() { state->setupProgramCtx(this); }
void ProgramCtx::evaluate() { state->evaluate(this); }
void ProgramCtx::postProcess() { state->postProcess(this); }

// ============================== subprogram handling ==============================

bool ProgramCtx::SubprogramAnswerSetCallback::operator()(AnswerSetPtr model){
	answersets.push_back(model->interpretation);
	return true;
}

ProgramCtx::SubprogramAnswerSetCallback::~SubprogramAnswerSetCallback(){}

std::vector<InterpretationPtr> ProgramCtx::evaluateSubprogram(InterpretationConstPtr edb, std::vector<ID>& idb){

	ProgramCtx pc = *this;
//	pc.changeRegistry(this->registry());
	pc.idb = idb;
	pc.edb = InterpretationPtr(new Interpretation(*edb));

	return evaluateSubprogram(pc, false);
}

std::vector<InterpretationPtr> ProgramCtx::evaluateSubprogram(InputProviderPtr& ip, InterpretationConstPtr addFacts){

	ProgramCtx pc = *this;
//	pc.changeRegistry(this->registry());
	pc.idb.clear();
	pc.edb = InterpretationPtr(new Interpretation(this->registry()));
	pc.config.setOption("NumberOfModels",0);
	if( !!addFacts )
		pc.edb->getStorage() |= addFacts->getStorage();
	pc.inputProvider = ip;
	ip.reset();

	return evaluateSubprogram(pc, true);
}

std::vector<InterpretationPtr> ProgramCtx::evaluateSubprogram(ProgramCtx& pc, bool parse){

	DBGLOG(DBG, "Resetting context");
	pc.state.reset();
	pc.modelBuilder.reset();
	pc.parser.reset();
	pc.evalgraph.reset();
	pc.compgraph.reset();
	pc.depgraph.reset();
//	pc.modelBuilderFactory = ctx->modelBuilderFactory;

  if( !pc.evalHeuristic )
  {
    DBGLOG(DBG, "Setting eval heuristics");
    pc.evalHeuristic.reset(new EvalHeuristicEasy);
  }

	DBGLOG(DBG, "Starting state pipeline " << (parse ? "with" : "without") << " parsing");
	if (parse){
		pc.changeState(StatePtr(new ConvertState));
	}else{
		pc.changeState(StatePtr(new SafetyCheckState));
	}

	if (parse){
		pc.convert();
		pc.parse();
	}

	DBGLOG(DBG, "Associate PluginAtom instances with ExternalAtom instances");
	pc.associateExtAtomsWithPluginAtoms(pc.idb, true);

	pc.safetyCheck();
	pc.createDependencyGraph();
	pc.optimizeEDBDependencyGraph();
	pc.createComponentGraph();
	pc.createEvalGraph();
	pc.setupProgramCtx();

	DBGLOG(DBG, "Setting AnswerSetCallback");
	pc.modelCallbacks.clear();
	pc.finalCallbacks.clear();
	SubprogramAnswerSetCallback* spasc = new SubprogramAnswerSetCallback();
	ModelCallbackPtr spascp = ModelCallbackPtr(spasc);
	pc.modelCallbacks.push_back(spascp);

	DBGLOG(DBG, "Evaluate subprogram");
	pc.evaluate();
	std::vector<InterpretationPtr> result;
	BOOST_FOREACH (InterpretationPtr intr, spasc->answersets){
		result.push_back(intr);
	}

	return result;
}

// ============================== end subprogram handling ==============================

#if 0
PluginAtomPtr
PluginContainer::getAtom(const std::string& name) const
{
  PluginAtomMap::const_iterator pa = pluginAtoms.find(name);

  if (pa == pluginAtoms.end())
    return PluginAtomPtr();

  return pa->second;
}

#endif

void ProgramCtx::addPluginAtom(PluginAtomPtr atom)
{
  assert(!!atom);
  assert(!!_registry);
  const std::string& predicate = atom->getPredicate();
  LOG(PLUGIN,"adding PluginAtom '" << predicate << "'");
  if( pluginAtoms.find(predicate) == pluginAtoms.end() )
  {
    atom->setRegistry(_registry);
    pluginAtoms[predicate] = atom;
  }
  else
  {
    LOG(WARNING,"External atom " << predicate << " is already loaded (skipping)");
  }
}

// call processOptions for each loaded plugin
// (this is supposed to remove "recognized" options from pluginOptions)
void ProgramCtx::processPluginOptions(
    std::list<const char*>& pluginOptions)
{
  BOOST_FOREACH(PluginInterfacePtr plugin, pluginContainer()->getPlugins())
  {
    LOG(DBG,"processing options for plugin " << plugin->getPluginName());
    LOG(DBG,"currently have " << printrange(pluginOptions));
	  plugin->processOptions(pluginOptions, *this);
  }
}

void ProgramCtx::addPluginAtomsFromPluginContainer()
{
  assert(!!pluginContainer());
  assert(!!registry());

  BOOST_FOREACH(PluginInterfacePtr plugin, pluginContainer()->getPlugins())
  {
    LOG(DBG,"adding plugin atoms from plugin " << plugin->getPluginName());
    // always freshly create! (pluginatoms are linked to a registry,
    // so when using multiple registries, you have to create multiple pluginatoms)
    BOOST_FOREACH(PluginAtomPtr pap, plugin->createAtoms(*this))
    {
      assert(!!pap);
      const std::string& pred = pap->getPredicate();
      LOG(DBG,"  got plugin atom " << pred);
      if( pluginAtoms.count(pred) != 0 )
      {
        LOG(WARNING,"warning: predicate '" << pred << "' already present in PluginAtomMap (skipping)");
      }
      else
      {
        pap->setRegistry(registry());
        pluginAtoms[pred] = pap;
      }
    }
  }
}

// associate plugins in container to external atoms in registry
void ProgramCtx::associateExtAtomsWithPluginAtoms(
    const Tuple& idb, bool failOnUnknownAtom)
{
  assert(!!_registry);
  DBGLOG_SCOPE(DBG,"aEAwPA",false);
  DBGLOG(DBG,"= associateExtAtomsWithPluginAtoms");

  Tuple eatoms;

  // associate all rules
  for(Tuple::const_iterator it = idb.begin();
      it != idb.end(); ++it)
  {
    assert(it->isRule());
    // skip those without external atoms
    if( !it->doesRuleContainExtatoms() )
      continue;

    // associate all literals in rule body
    const Rule& rule = _registry->rules.getByID(*it);

    // get external atoms (recursively)
    _registry->getExternalAtomsInTuple(rule.body, eatoms);
  }

  // now associate
  for(Tuple::const_iterator it = eatoms.begin();
      it != eatoms.end(); ++it)
  {
    assert(it->isExternalAtom());

    const ExternalAtom& eatom = _registry->eatoms.getByID(*it);
    const std::string& predicate = _registry->getTermStringByID(eatom.predicate);
    // lookup pluginAtom to this eatom predicate
    PluginAtomMap::iterator itpa = pluginAtoms.find(predicate);
    if( itpa != pluginAtoms.end() )
    {
      assert(!!itpa->second);
      // we store this as a POD pointer!
      eatom.pluginAtom = itpa->second.get();
    }
    else
    {
      DBGLOG(DBG,"did not find plugin atom for predicate '" << predicate << "'");
      if( failOnUnknownAtom )
      {
        throw FatalError("did not find plugin atom "
            " for predicate '" + predicate + "'");
      }
    }
  }
}

// setup this ProgramCtx (using setupProgramCtx() for of all plugins)
void ProgramCtx::setupByPlugins()
{
  BOOST_FOREACH(PluginInterfacePtr plugin, pluginContainer()->getPlugins())
  {
    LOG(DBG,"setting up program ctx for plugin " << plugin->getPluginName());
	  plugin->setupProgramCtx(*this);
  }
}

DLVHEX_NAMESPACE_END

// Local Variables:
// mode: C++
// End:
<|endoftext|>


<commit_before>/*
    Copyright (C) 2010 Collabora Ltd. <info@collabora.co.uk>
      @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>

    This library 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 2.1 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "refpointer.h"
#include "quark.h"
#include <glib-object.h>

namespace QGlib {

RefCountedObject *constructWrapper(Type instanceType, void *instance)
{
    Quark q = g_quark_from_static_string("QGlib__wrapper_constructor");
    RefCountedObject *cppClass = NULL;

    for(Type t = instanceType; t.isValid(); t = t.parent()) {
        void *funcPtr = t.quarkData(q);
        if (funcPtr) {
            cppClass = (reinterpret_cast<RefCountedObject *(*)(void*)>(funcPtr))(instance);
            Q_ASSERT_X(cppClass, "QGlib::constructWrapper",
                       "Failed to wrap instance. This is a bug in the bindings library.");
            return cppClass;
        }
    }

    Q_ASSERT_X(false, "QGlib::constructWrapper",
               "No wrapper constructor found for this type. Did you forget to call init()?.");
    return cppClass;
}

namespace Private {

static void qdataDestroyNotify(void *cppInstance)
{
    delete static_cast<RefCountedObject*>(cppInstance);
}

RefCountedObject *wrapObject(void *gobject)
{
    Q_ASSERT(gobject);

    Quark q = g_quark_from_static_string("QGlib__object_wrapper");
    RefCountedObject *obj = static_cast<RefCountedObject*>(g_object_get_qdata(G_OBJECT(gobject), q));

    if (!obj) {
        obj = constructWrapper(Type::fromInstance(gobject), gobject);
        g_object_set_qdata_full(G_OBJECT(gobject), q, obj, &qdataDestroyNotify);
    }

    return obj;
}

RefCountedObject *wrapParamSpec(void *param)
{
    Q_ASSERT(param);

    Quark q = g_quark_from_static_string("QGlib__paramspec_wrapper");
    RefCountedObject *obj = static_cast<RefCountedObject*>(g_param_spec_get_qdata(G_PARAM_SPEC(param), q));

    if (!obj) {
        obj = constructWrapper(Type::fromInstance(param), param);
        g_param_spec_set_qdata_full(G_PARAM_SPEC(param), q, obj, &qdataDestroyNotify);
    }

    return obj;
}

RefCountedObject *wrapInterface(Type interfaceType, void *gobject)
{
    Q_ASSERT(gobject);

    Quark q = Quark::fromString(QLatin1String("QGlib__interface_wrapper__") + interfaceType.name());
    RefCountedObject *obj = static_cast<RefCountedObject*>(g_object_get_qdata(G_OBJECT(gobject), q));

    if (!obj) {
        obj = constructWrapper(interfaceType, gobject);
        g_object_set_qdata_full(G_OBJECT(gobject), q, obj, &qdataDestroyNotify);
    }

    return obj;
}

} //namespace Private
} //namespace QGlib
<commit_msg>src/QGlib/wrap.cpp Include the name of the GType that wasn't registered.<commit_after>/*
    Copyright (C) 2010 Collabora Ltd. <info@collabora.co.uk>
      @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>

    This library 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 2.1 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "refpointer.h"
#include "quark.h"
#include <glib-object.h>

namespace QGlib {

RefCountedObject *constructWrapper(Type instanceType, void *instance)
{
    Quark q = g_quark_from_static_string("QGlib__wrapper_constructor");
    RefCountedObject *cppClass = NULL;

    for(Type t = instanceType; t.isValid(); t = t.parent()) {
        void *funcPtr = t.quarkData(q);
        if (funcPtr) {
            cppClass = (reinterpret_cast<RefCountedObject *(*)(void*)>(funcPtr))(instance);
            Q_ASSERT_X(cppClass, "QGlib::constructWrapper",
                       "Failed to wrap instance. This is a bug in the bindings library.");
            return cppClass;
        }
    }

    QString type_name(g_type_name(instanceType));
    QString error_message("No wrapper constructor found for this type ("+type_name+"). Did you forget to call init()?.");
    Q_ASSERT_X(false, "QGlib::constructWrapper", error_message.toAscii());
    return cppClass;
}

namespace Private {

static void qdataDestroyNotify(void *cppInstance)
{
    delete static_cast<RefCountedObject*>(cppInstance);
}

RefCountedObject *wrapObject(void *gobject)
{
    Q_ASSERT(gobject);

    Quark q = g_quark_from_static_string("QGlib__object_wrapper");
    RefCountedObject *obj = static_cast<RefCountedObject*>(g_object_get_qdata(G_OBJECT(gobject), q));

    if (!obj) {
        obj = constructWrapper(Type::fromInstance(gobject), gobject);
        g_object_set_qdata_full(G_OBJECT(gobject), q, obj, &qdataDestroyNotify);
    }

    return obj;
}

RefCountedObject *wrapParamSpec(void *param)
{
    Q_ASSERT(param);

    Quark q = g_quark_from_static_string("QGlib__paramspec_wrapper");
    RefCountedObject *obj = static_cast<RefCountedObject*>(g_param_spec_get_qdata(G_PARAM_SPEC(param), q));

    if (!obj) {
        obj = constructWrapper(Type::fromInstance(param), param);
        g_param_spec_set_qdata_full(G_PARAM_SPEC(param), q, obj, &qdataDestroyNotify);
    }

    return obj;
}

RefCountedObject *wrapInterface(Type interfaceType, void *gobject)
{
    Q_ASSERT(gobject);

    Quark q = Quark::fromString(QLatin1String("QGlib__interface_wrapper__") + interfaceType.name());
    RefCountedObject *obj = static_cast<RefCountedObject*>(g_object_get_qdata(G_OBJECT(gobject), q));

    if (!obj) {
        obj = constructWrapper(interfaceType, gobject);
        g_object_set_qdata_full(G_OBJECT(gobject), q, obj, &qdataDestroyNotify);
    }

    return obj;
}

} //namespace Private
} //namespace QGlib
<|endoftext|>


<commit_before>
#include <QApplication>
#include "QImageWidget.h"
#include "Raycasting.h"
#include "KinectSpecs.h"

#define DegToRad(angle_degrees) (angle_degrees * M_PI / 180.0)		// Converts degrees to radians.
#define RadToDeg(angle_radians) (angle_radians * 180.0 / M_PI)		// Converts radians to degrees.

static void multDirMatrix(const Eigen::Vector3f &src, const Eigen::Matrix4f &mat, Eigen::Vector3f &dst)
{
	float a, b, c;

	a = src[0] * mat(0, 0) + src[1] * mat(1, 0) + src[2] * mat(2, 0);
	b = src[0] * mat(0, 1) + src[1] * mat(1, 1) + src[2] * mat(2, 1);
	c = src[0] * mat(0, 2) + src[1] * mat(1, 2) + src[2] * mat(2, 2);

	dst.x() = a;
	dst.y() = b;
	dst.z() = c;
}

template <typename Type>
static Eigen::Matrix<Type, 3, 1> compute_normal(
	const Eigen::Matrix<Type, 3, 1>& p1,
	const Eigen::Matrix<Type, 3, 1>& p2,
	const Eigen::Matrix<Type, 3, 1>& p3)
{
	Eigen::Matrix<Type, 3, 1> u = p2 - p1;
	Eigen::Matrix<Type, 3, 1> v = p3 - p1;

	return v.cross(u).normalized();
}

template <typename Type>
static Eigen::Matrix<Type, 3, 1> reflect(const Eigen::Matrix<Type, 3, 1>& i, const Eigen::Matrix<Type, 3, 1>& n)
{
	return i - 2.0 * n * n.dot(i);
}

int raycast_and_render_grid(int argc, char* argv[])
{
	int vx_count = 3;
	int vx_size = 1;

	Eigen::Vector3i voxel_count(vx_count, vx_count, vx_count);
	Eigen::Vector3i voxel_size(vx_size, vx_size, vx_size);

	Eigen::Vector3i volume_size(voxel_count.x() * voxel_size.x(), voxel_count.y() * voxel_size.y(), voxel_count.z() * voxel_size.z());
	Eigen::Vector3f half_volume_size = volume_size.cast<float>() * 0.5f;

	Eigen::Affine3f volume_affine = Eigen::Affine3f::Identity();
	//volume_affine.translate(Eigen::Vector3f(-half_vol_size, -half_vol_size, 0));

	if (argc > 2)
	{
		vx_count = atoi(argv[1]);
		vx_size = atoi(argv[2]);

		voxel_count = Eigen::Vector3i(vx_count, vx_count, vx_count);
		voxel_size = Eigen::Vector3i(vx_size, vx_size, vx_size);
	}

	//
	// create the grid params and set a few voxels with different signals
	// in order to obtain zero crossings
	//
	const int total_voxels = voxel_count.x() * voxel_count.y() * voxel_count.z();
	std::vector<Eigen::Vector2f> tsdf(total_voxels, Eigen::Vector2f::Ones());
	tsdf.at(13)[0] =
	tsdf.at(22)[0] =
	tsdf.at(18)[0] =
	tsdf.at(26)[0] = -1.0f;

	//
	// setup camera parameters
	//
	Eigen::Affine3f camera_to_world = Eigen::Affine3f::Identity();
	camera_to_world.translate(Eigen::Vector3f(half_volume_size.x(), half_volume_size.y(), -4));
	Eigen::Vector3f camera_pos = camera_to_world.matrix().col(3).head<3>();
	float scale = (float)tan(DegToRad(KINECT_V1_FOVY * 0.5f));
	float aspect_ratio = KINECT_V1_ASPECT_RATIO;

	//
	// setup image parameters
	//
	unsigned short image_width = KINECT_V1_COLOR_WIDTH / 4;
	unsigned short image_height = image_width / aspect_ratio;
	unsigned char* image_data = new unsigned char[image_width * image_height * 3]{0}; // rgb
	QImage image(image_data, image_width, image_height, QImage::Format_RGB888);

	//
	// for each pixel, trace a ray
	//
	for (int y = 0; y < image_height; ++y)
	{
		for (int x = 0; x < image_width; ++x)
		{
			// Convert from image space (in pixels) to screen space
			// Screen Space alon X axis = [-aspect ratio, aspect ratio]
			// Screen Space alon Y axis = [-1, 1]
			Eigen::Vector3f screen_coord(
				(2 * (x + 0.5f) / (float)image_width - 1) * aspect_ratio * scale,
				(1 - 2 * (y + 0.5f) / (float)image_height) * scale,
				1.0f);

			Eigen::Vector3f direction;
			multDirMatrix(screen_coord, camera_to_world.matrix(), direction);
			direction.normalize();

			std::vector<int> voxels_zero_crossing;
			if (raycast_tsdf_volume(camera_pos, direction, voxel_count, voxel_size, tsdf, voxels_zero_crossing) > 0)
			{
				if (voxels_zero_crossing.size() == 2)
				{
					image.setPixel(QPoint(x, y), qRgb(128, 128, 0));
				}
				else
				{
					image.setPixel(QPoint(x, y), qRgb(128, 0, 0));
				}
			}
		}
	}

	QApplication app(argc, argv);
	QImageWidget widget;
	widget.setImage(image);
	widget.show();

	return app.exec();
}

int raycast_and_render_two_triangles(int argc, char* argv[])
{
	Eigen::Affine3f camera_to_world = Eigen::Affine3f::Identity();
	camera_to_world.translate(Eigen::Vector3f(2, 2, 5));
	Eigen::Vector3f camera_pos = camera_to_world.matrix().col(3).head<3>();
	float scale = tan(DegToRad(60.f * 0.5f));
	float aspect_ratio = 1.7778f;
	unsigned short image_width = 710;
	unsigned short image_height = 400;
	unsigned char* image_data = new unsigned char[image_width * image_height * 3]{0}; // rgb
	QImage image(image_data, image_width, image_height, QImage::Format_RGB888);

	Eigen::Vector3f hit;
	Eigen::Vector3f v1(0.0f, -1.0f, -2.0f);
	Eigen::Vector3f v2(0.0f, 1.0f, -4.0f);
	Eigen::Vector3f v3(-1.0f, -1.0f, -3.0f);
	Eigen::Vector3f v4(0.0f, -1.0f, -2.0f);
	Eigen::Vector3f v5(0.0f, 1.0f, -4.0f);
	Eigen::Vector3f v6(1.0f, -1.0f, -3.0f);

	Eigen::Vector3f diff_color(1, 0, 0);
	Eigen::Vector3f spec_color(1, 1, 0);
	float spec_shininess = 1.0f;
	Eigen::Vector3f E(0, 0, -1);				// view direction
	Eigen::Vector3f L = Eigen::Vector3f(0.2, -1, -1).normalized();	// light direction
	Eigen::Vector3f N[2] = {
		compute_normal(v1, v2, v3),
		compute_normal(v4, v5, v6) };
	Eigen::Vector3f R[2] = {
		-reflect(L, N[0]).normalized(),
		-reflect(L, N[1]).normalized() };

	for (int y = 0; y < image_height; ++y)
	{
		for (int x = 0; x < image_width; ++x)
		{
			// Convert from image space (in pixels) to screen space
			// Screen Space alon X axis = [-aspect ratio, aspect ratio]
			// Screen Space alon Y axis = [-1, 1]
			Eigen::Vector3f screen_coord(
				(2 * (x + 0.5f) / (float)image_width - 1) * aspect_ratio * scale,
				(1 - 2 * (y + 0.5f) / (float)image_height) * scale,
				-1.0f);

			Eigen::Vector3f direction;
			multDirMatrix(screen_coord, camera_to_world.matrix(), direction);
			direction.normalize();

			bool intersec[2] = {
				triangle_intersection(camera_pos, direction, v1, v2, v3, hit),
				triangle_intersection(camera_pos, direction, v4, v5, v6, hit) };

			for (int i = 0; i < 2; ++i)
			{
				if (intersec[i])
				{
					Eigen::Vector3f diff = diff_color * std::fmax(N[i].dot(L), 0.0f);
					Eigen::Vector3f spec = spec_color * pow(std::fmax(R[i].dot(E), 0.0f), spec_shininess);
					Eigen::Vector3f color = eigen_clamp(diff + spec, 0.f, 1.f) * 255;
					image.setPixel(QPoint(x, y), qRgb(color.x(), color.y(), color.z()));
				}
			}
		}
	}

	QApplication app(argc, argv);
	QImageWidget widget;
	widget.setImage(image);
	widget.show();

	return app.exec();
}

int raycast_volume_test(int argc, char **argv)
{
	//int vx_count = 3;
	//int vx_size = 1;
	//int vx_count = 2;
	//int vx_size = 2;
	int vx_count = 3;
	int vx_size = 16;

	Eigen::Vector3i voxel_count(vx_count, vx_count, vx_count);
	Eigen::Vector3i voxel_size(vx_size, vx_size, vx_size);

	//Eigen::Vector3f ray_origin(0.5f, 0.5f, -1.0f);
	//Eigen::Vector3f ray_target(0.5f, 2.0f, 1.f);	// { 3, 6, 15, 24 }
	//Eigen::Vector3f ray_origin(2.f, 2.f, -2.0f);
	//Eigen::Vector3f ray_target(2.f, 2.f, 2.f);	// { 3, 7 }

	Eigen::Vector3f ray_origin(64.f, 64.f, -32.0f);
	Eigen::Vector3f ray_target(8.f, 8.f, 40.f);	// { 3, 7 }

	Eigen::Vector3f ray_direction = (ray_target - ray_origin).normalized();

	if (argc > 8)
	{
		vx_count = atoi(argv[1]);
		vx_size = atoi(argv[2]);

		voxel_count = Eigen::Vector3i(vx_count, vx_count, vx_count);
		voxel_size = Eigen::Vector3i(vx_size, vx_size, vx_size);

		ray_origin = Eigen::Vector3f(atof(argv[3]), atof(argv[4]), atof(argv[5]));
		ray_target = Eigen::Vector3f(atof(argv[6]), atof(argv[7]), atof(argv[8]));
		ray_direction = (ray_target - ray_origin).normalized();
	}

	std::vector<int> voxels_intersected;
	Timer t;
	t.start();
	raycast_volume<float>(ray_origin, ray_direction, voxel_count, voxel_size, voxels_intersected);
	t.print_interval("Raycasting volume       : ");

	std::cout << "Voxels Intersected: ";
	for (auto v : voxels_intersected)
		std::cout << v << ' ';
	std::cout << std::endl;

	return 0;
}

// Usage: ./Raycastingd.exe 3 1 1.5 1.5 -15 1.5 1.5 -10
int main(int argc, char **argv)
{
#if 0
	raycast_volume_test(argc, argv);

	Timer t;
	t.start();
	raycast_and_render_two_triangles(argc, argv);
	t.print_interval("Raycasting and render   : ");
#endif
	raycast_and_render_grid(argc, argv);

	return 0;
}
<commit_msg><commit_after>
#include <QApplication>
#include "QImageWidget.h"
#include "Raycasting.h"
#include "KinectSpecs.h"

#define DegToRad(angle_degrees) (angle_degrees * M_PI / 180.0)		// Converts degrees to radians.
#define RadToDeg(angle_radians) (angle_radians * 180.0 / M_PI)		// Converts radians to degrees.

static void multDirMatrix(const Eigen::Vector3f &src, const Eigen::Matrix4f &mat, Eigen::Vector3f &dst)
{
	float a, b, c;

	a = src[0] * mat(0, 0) + src[1] * mat(1, 0) + src[2] * mat(2, 0);
	b = src[0] * mat(0, 1) + src[1] * mat(1, 1) + src[2] * mat(2, 1);
	c = src[0] * mat(0, 2) + src[1] * mat(1, 2) + src[2] * mat(2, 2);

	dst.x() = a;
	dst.y() = b;
	dst.z() = c;
}

template <typename Type>
static Eigen::Matrix<Type, 3, 1> compute_normal(
	const Eigen::Matrix<Type, 3, 1>& p1,
	const Eigen::Matrix<Type, 3, 1>& p2,
	const Eigen::Matrix<Type, 3, 1>& p3)
{
	Eigen::Matrix<Type, 3, 1> u = p2 - p1;
	Eigen::Matrix<Type, 3, 1> v = p3 - p1;

	return v.cross(u).normalized();
}

template <typename Type>
static Eigen::Matrix<Type, 3, 1> reflect(const Eigen::Matrix<Type, 3, 1>& i, const Eigen::Matrix<Type, 3, 1>& n)
{
	return i - 2.0 * n * n.dot(i);
}

int raycast_and_render_grid(int argc, char* argv[])
{
	int vx_count = 8;
	int vx_size = 16;

	Eigen::Vector3i voxel_count(vx_count, vx_count, vx_count);
	Eigen::Vector3i voxel_size(vx_size, vx_size, vx_size);

	if (argc > 2)
	{
		vx_count = atoi(argv[1]);
		vx_size = atoi(argv[2]);

		voxel_count = Eigen::Vector3i(vx_count, vx_count, vx_count);
		voxel_size = Eigen::Vector3i(vx_size, vx_size, vx_size);
	}

	Eigen::Vector3i volume_size(voxel_count.x() * voxel_size.x(), voxel_count.y() * voxel_size.y(), voxel_count.z() * voxel_size.z());
	Eigen::Vector3f half_volume_size = volume_size.cast<float>() * 0.5f;
	const int total_voxels = voxel_count.x() * voxel_count.y() * voxel_count.z();

	std::cout << std::fixed
		<< "Voxel Count  : " << voxel_count.transpose() << std::endl
		<< "Voxel Size   : " << voxel_size.transpose() << std::endl
		<< "Volume Size  : " << volume_size.transpose() << std::endl
		<< "Total Voxels : " << total_voxels << std::endl;

	//
	// create the grid params and set a few voxels with different signals
	// in order to obtain zero crossings
	//
	std::vector<Eigen::Vector2f> tsdf(total_voxels, Eigen::Vector2f::Ones());
	//tsdf.at(13)[0] =
	//tsdf.at(22)[0] =
	//tsdf.at(18)[0] =
	//tsdf.at(26)[0] = -1.0f;
	tsdf.at(0)[0] = -1.0f;
	tsdf.at(tsdf.size() - 1)[0] = -1.0f;

	//
	// setup camera parameters
	//
	Eigen::Affine3f camera_to_world = Eigen::Affine3f::Identity();
	float cam_z = (-vx_count - 1) * vx_size;
	camera_to_world.translate(Eigen::Vector3f(half_volume_size.x(), half_volume_size.y(), cam_z));
	Eigen::Vector3f camera_pos = camera_to_world.matrix().col(3).head<3>();
	float scale = (float)tan(DegToRad(KINECT_V1_FOVY * 0.5f));
	float aspect_ratio = KINECT_V1_ASPECT_RATIO;

	//
	// setup image parameters
	//
	unsigned short image_width = KINECT_V1_COLOR_WIDTH / 10;
	unsigned short image_height = image_width / aspect_ratio;
	unsigned char* image_data = new unsigned char[image_width * image_height * 3]{0}; // rgb
	QImage image(image_data, image_width, image_height, QImage::Format_RGB888);

	//
	// for each pixel, trace a ray
	//
	for (int y = 0; y < image_height; ++y)
	{
		for (int x = 0; x < image_width; ++x)
		{
			// Convert from image space (in pixels) to screen space
			// Screen Space alon X axis = [-aspect ratio, aspect ratio]
			// Screen Space alon Y axis = [-1, 1]
			Eigen::Vector3f screen_coord(
				(2 * (x + 0.5f) / (float)image_width - 1) * aspect_ratio * scale,
				(1 - 2 * (y + 0.5f) / (float)image_height) * scale,
				1.0f);

			Eigen::Vector3f direction;
			multDirMatrix(screen_coord, camera_to_world.matrix(), direction);
			direction.normalize();

			std::vector<int> voxels_zero_crossing;
			if (raycast_tsdf_volume(camera_pos, direction, voxel_count, voxel_size, tsdf, voxels_zero_crossing) > 0)
			{
				if (voxels_zero_crossing.size() == 2)
				{
					image.setPixel(QPoint(x, y), qRgb(128, 128, 0));
				}
				else
				{
					image.setPixel(QPoint(x, y), qRgb(128, 0, 0));
				}
			}
		}
	}

	QApplication app(argc, argv);
	QImageWidget widget;
	widget.setImage(image);
	widget.show();

	return app.exec();
}

int raycast_and_render_two_triangles(int argc, char* argv[])
{
	Eigen::Affine3f camera_to_world = Eigen::Affine3f::Identity();
	camera_to_world.translate(Eigen::Vector3f(2, 2, 5));
	Eigen::Vector3f camera_pos = camera_to_world.matrix().col(3).head<3>();
	float scale = tan(DegToRad(60.f * 0.5f));
	float aspect_ratio = 1.7778f;
	unsigned short image_width = 710;
	unsigned short image_height = 400;
	unsigned char* image_data = new unsigned char[image_width * image_height * 3]{0}; // rgb
	QImage image(image_data, image_width, image_height, QImage::Format_RGB888);

	Eigen::Vector3f hit;
	Eigen::Vector3f v1(0.0f, -1.0f, -2.0f);
	Eigen::Vector3f v2(0.0f, 1.0f, -4.0f);
	Eigen::Vector3f v3(-1.0f, -1.0f, -3.0f);
	Eigen::Vector3f v4(0.0f, -1.0f, -2.0f);
	Eigen::Vector3f v5(0.0f, 1.0f, -4.0f);
	Eigen::Vector3f v6(1.0f, -1.0f, -3.0f);

	Eigen::Vector3f diff_color(1, 0, 0);
	Eigen::Vector3f spec_color(1, 1, 0);
	float spec_shininess = 1.0f;
	Eigen::Vector3f E(0, 0, -1);				// view direction
	Eigen::Vector3f L = Eigen::Vector3f(0.2, -1, -1).normalized();	// light direction
	Eigen::Vector3f N[2] = {
		compute_normal(v1, v2, v3),
		compute_normal(v4, v5, v6) };
	Eigen::Vector3f R[2] = {
		-reflect(L, N[0]).normalized(),
		-reflect(L, N[1]).normalized() };

	for (int y = 0; y < image_height; ++y)
	{
		for (int x = 0; x < image_width; ++x)
		{
			// Convert from image space (in pixels) to screen space
			// Screen Space alon X axis = [-aspect ratio, aspect ratio]
			// Screen Space alon Y axis = [-1, 1]
			Eigen::Vector3f screen_coord(
				(2 * (x + 0.5f) / (float)image_width - 1) * aspect_ratio * scale,
				(1 - 2 * (y + 0.5f) / (float)image_height) * scale,
				-1.0f);

			Eigen::Vector3f direction;
			multDirMatrix(screen_coord, camera_to_world.matrix(), direction);
			direction.normalize();

			bool intersec[2] = {
				triangle_intersection(camera_pos, direction, v1, v2, v3, hit),
				triangle_intersection(camera_pos, direction, v4, v5, v6, hit) };

			for (int i = 0; i < 2; ++i)
			{
				if (intersec[i])
				{
					Eigen::Vector3f diff = diff_color * std::fmax(N[i].dot(L), 0.0f);
					Eigen::Vector3f spec = spec_color * pow(std::fmax(R[i].dot(E), 0.0f), spec_shininess);
					Eigen::Vector3f color = eigen_clamp(diff + spec, 0.f, 1.f) * 255;
					image.setPixel(QPoint(x, y), qRgb(color.x(), color.y(), color.z()));
				}
			}
		}
	}

	QApplication app(argc, argv);
	QImageWidget widget;
	widget.setImage(image);
	widget.show();

	return app.exec();
}

int raycast_volume_test(int argc, char **argv)
{
	//int vx_count = 3;
	//int vx_size = 1;
	//int vx_count = 2;
	//int vx_size = 2;
	int vx_count = 3;
	int vx_size = 16;

	Eigen::Vector3i voxel_count(vx_count, vx_count, vx_count);
	Eigen::Vector3i voxel_size(vx_size, vx_size, vx_size);

	//Eigen::Vector3f ray_origin(0.5f, 0.5f, -1.0f);
	//Eigen::Vector3f ray_target(0.5f, 2.0f, 1.f);	// { 3, 6, 15, 24 }
	//Eigen::Vector3f ray_origin(2.f, 2.f, -2.0f);
	//Eigen::Vector3f ray_target(2.f, 2.f, 2.f);	// { 3, 7 }

	Eigen::Vector3f ray_origin(64.f, 64.f, -32.0f);
	Eigen::Vector3f ray_target(8.f, 8.f, 40.f);	// { 3, 7 }

	Eigen::Vector3f ray_direction = (ray_target - ray_origin).normalized();

	if (argc > 8)
	{
		vx_count = atoi(argv[1]);
		vx_size = atoi(argv[2]);

		voxel_count = Eigen::Vector3i(vx_count, vx_count, vx_count);
		voxel_size = Eigen::Vector3i(vx_size, vx_size, vx_size);

		ray_origin = Eigen::Vector3f(atof(argv[3]), atof(argv[4]), atof(argv[5]));
		ray_target = Eigen::Vector3f(atof(argv[6]), atof(argv[7]), atof(argv[8]));
		ray_direction = (ray_target - ray_origin).normalized();
	}

	std::vector<int> voxels_intersected;
	Timer t;
	t.start();
	raycast_volume<float>(ray_origin, ray_direction, voxel_count, voxel_size, voxels_intersected);
	t.print_interval("Raycasting volume       : ");

	std::cout << "Voxels Intersected: ";
	for (auto v : voxels_intersected)
		std::cout << v << ' ';
	std::cout << std::endl;

	return 0;
}

int main(int argc, char **argv)
{
#if 0
	// Usage: ./Raycastingd.exe vx_count vx_size cam_x y z target_x y z
	// Usage: ./Raycastingd.exe 3 1 1.5 1.5 -15 1.5 1.5 -10
	raycast_volume_test(argc, argv);
#endif

#if 0
	// Usage: ./Raycastingd.exe
	Timer t;
	t.start();
	raycast_and_render_two_triangles(argc, argv);
	t.print_interval("Raycasting and render   : ");
#endif

	// Usage: ./Raycastingd.exe vx_count vx_size
	// Usage: ./Raycastingd.exe 3 1
	raycast_and_render_grid(argc, argv);

	return 0;
}
<|endoftext|>


<commit_before>#include "RubyObject.h"
#include "common.h"
#include <vector>

#include <iostream>
using namespace std;

using namespace v8;

// TODO:
// - Where do we need to rb_rescue?
// - Modules?
// - Class inheritance/extending?

VALUE trueArg = Qtrue;
RubyObject::TplMap RubyObject::s_functionTemplates;

Local<Function> RubyObject::GetClass(VALUE klass)
{
  HandleScope scope;

  Persistent<FunctionTemplate> persistTpl;
  TplMap::iterator it = s_functionTemplates.find(klass);
  if (it == s_functionTemplates.end()) {
    log("Creating new class: " << rb_class2name(klass) << endl);

    Local<FunctionTemplate> tpl = FunctionTemplate::New(New, External::Wrap((void*)klass));
    tpl->SetClassName(String::NewSymbol(rb_class2name(klass)));
    tpl->InstanceTemplate()->SetInternalFieldCount(1);

    VALUE methods = rb_class_public_instance_methods(1, &trueArg, klass);
    for (int i = 0; i < RARRAY_LEN(methods); i++) {
      ID methodID = SYM2ID(rb_ary_entry(methods, i));
      Local<String> methodName = String::New(rb_id2name(methodID));

      Local<FunctionTemplate> methodTemplate =
        FunctionTemplate::New(CallMethod, External::Wrap((void*)methodID));
      tpl->PrototypeTemplate()->Set(methodName, methodTemplate->GetFunction());
    }

    persistTpl = s_functionTemplates[klass] = Persistent<FunctionTemplate>::New(tpl);
  }
  else {
    log("Getting existing class: " << rb_class2name(klass) << endl);

    persistTpl = it->second;
  }

  Local<Function> ctor = persistTpl->GetFunction();

  return scope.Close(ctor);
}

struct NewInstanceCaller
{
  NewInstanceCaller(std::vector<VALUE> &r, VALUE k) : rubyArgs(r), klass(k) {}
  VALUE operator()() const
  {
    return rb_class_new_instance(rubyArgs.size(), &rubyArgs[0], klass);
  }

  std::vector<VALUE>& rubyArgs;
  VALUE klass;
};

struct NewInstanceCaller2
{
  NewInstanceCaller2(std::vector<VALUE> &r, VALUE k, void* d) : rubyArgs(r), klass(k), data(d) {}
  VALUE operator()() const
  {
    VALUE obj = Data_Wrap_Struct(klass, NULL, NULL, data);
    rb_obj_call_init(obj, rubyArgs.size(), &rubyArgs[0]);
    return obj;
  }

  std::vector<VALUE>& rubyArgs;
  VALUE klass;
  void* data;
};

Handle<Value> RubyObject::New(const Arguments& args)
{
  HandleScope scope;

  if (args.IsConstructCall()) {
    VALUE klass = VALUE(External::Unwrap(args.Data()));

    // TODO: This has serious GC implications. Make weak? When can we delete the ptr?
    Persistent<Object>* owner;
    if (!args[0]->IsUndefined())
      owner = new Persistent<Object>(Persistent<Object>::New(args[0].As<Object>()));
    //DumpV8Props(*owner);
    //cout << "Owner: " << *String::Utf8Value(args[0]) << endl;

    Local<Array> v8Args = args[1].As<Array>();
    std::vector<VALUE> rubyArgs(v8Args->Length());
    for (uint32_t i = 0; i < v8Args->Length(); i++) {
      rubyArgs[i] = v8ToRuby(v8Args->Get(i));
    }

    log("Creating new " << rb_class2name(klass) << " with " << rubyArgs.size() << " args" << endl);

    VALUE ex;
    VALUE obj;
    if (args[0]->IsUndefined())
      obj = SafeRubyCall(NewInstanceCaller(rubyArgs, klass), ex);
    else
      obj = SafeRubyCall(NewInstanceCaller2(rubyArgs, klass, owner), ex);
    if (ex != Qnil) {
      ThrowException(rubyExToV8(ex));
      return scope.Close(Undefined());
    }

    // Wrap the obj immediately to prevent it from being garbage collected
    RubyObject *self = new RubyObject(obj);
    //self->m_owner = owner;
    self->Wrap(args.This());

    return scope.Close(args.This());
  }
  else {
    std::vector<Handle<Value> > argv(args.Length());
    for (int i = 0; i < args.Length(); i++) {
      argv[i] = args[i];
    }

    VALUE klass = VALUE(External::Unwrap(args.Data()));
    Local<Function> cons = RubyObject::GetClass(klass);

    //Local<Value> argv[argc] = { args[0], args[1], args[2] };
    //Local<Function> cons = args.Callee();
    return scope.Close(cons->NewInstance(args.Length(), &argv[0]));
  }
}

RubyObject::RubyObject(VALUE obj) : m_obj(obj)
{
  rb_gc_register_address(&m_obj);
}

RubyObject::~RubyObject()
{
  log("~RubyObject" << endl);
  rb_gc_unregister_address(&m_obj);
}

struct MethodCaller
{
  MethodCaller(VALUE o, VALUE m, const Arguments& args) :
    obj(o), methodID(m), rubyArgs(args.Length())
  {
    // TODO: Is this right? Is there a way to determine if a block is expected?
    if (args.Length() > 0 && args[args.Length()-1]->IsFunction()) {
      log("Got a func!" << endl);
      block = args[args.Length()-1].As<Function>();
      rubyArgs.resize(args.Length()-1);
    }

    for (size_t i = 0; i < rubyArgs.size(); i++) {
      rubyArgs[i] = v8ToRuby(args[i]);
    }
  }

  VALUE operator()() const
  {
    log("Calling method: " << rb_id2name(methodID) << " with " << rubyArgs.size() << " args");

    if (block.IsEmpty()) {
      log(endl);

      return rb_funcall2(obj, methodID, rubyArgs.size(), (VALUE*)&rubyArgs[0]);
    }
    else {
      log(" and a block" << endl);

      // TODO: Probably not available in Ruby < 1.9
      return rb_block_call(obj, methodID, rubyArgs.size(),
                           (VALUE*)&rubyArgs[0], RUBY_METHOD_FUNC(BlockFunc),
                           (VALUE)this);
    }
  }

  static VALUE BlockFunc(VALUE, VALUE data, int argc, const VALUE* rbArgv)
  {
    MethodCaller* self = reinterpret_cast<MethodCaller*>(data);

    return CallV8FromRuby(Context::GetCurrent()->Global(), self->block,
                          argc, rbArgv);
  }

  VALUE obj;
  VALUE methodID;
  std::vector<VALUE> rubyArgs;
  // TODO: Should this be persistent?
  Local<Function> block;
};

Handle<Value> RubyObject::CallMethod(const Arguments& args)
{
  HandleScope scope;

  RubyObject *self = node::ObjectWrap::Unwrap<RubyObject>(args.This());
  ID methodID = ID(External::Unwrap(args.Data()));

  //DumpV8Props(*self->m_owner);

  VALUE ex;
  VALUE res = SafeRubyCall(MethodCaller(self->m_obj, methodID, args), ex);
  if (ex != Qnil) {
    return scope.Close(ThrowException(rubyExToV8(ex)));
  }

  return scope.Close(rubyToV8(res));
}
<commit_msg>Dry it up<commit_after>#include "RubyObject.h"
#include "common.h"
#include <vector>

#include <iostream>
using namespace std;

using namespace v8;

// TODO:
// - Where do we need to rb_rescue?
// - Modules?
// - Class extending?

VALUE trueArg = Qtrue;
RubyObject::TplMap RubyObject::s_functionTemplates;

Local<Function> RubyObject::GetClass(VALUE klass)
{
  HandleScope scope;

  Persistent<FunctionTemplate> persistTpl;
  TplMap::iterator it = s_functionTemplates.find(klass);
  if (it == s_functionTemplates.end()) {
    log("Creating new class: " << rb_class2name(klass) << endl);

    Local<FunctionTemplate> tpl = FunctionTemplate::New(New, External::Wrap((void*)klass));
    tpl->SetClassName(String::NewSymbol(rb_class2name(klass)));
    tpl->InstanceTemplate()->SetInternalFieldCount(1);

    VALUE methods = rb_class_public_instance_methods(1, &trueArg, klass);
    for (int i = 0; i < RARRAY_LEN(methods); i++) {
      ID methodID = SYM2ID(rb_ary_entry(methods, i));
      Local<String> methodName = String::New(rb_id2name(methodID));

      Local<FunctionTemplate> methodTemplate =
        FunctionTemplate::New(CallMethod, External::Wrap((void*)methodID));
      tpl->PrototypeTemplate()->Set(methodName, methodTemplate->GetFunction());
    }

    persistTpl = s_functionTemplates[klass] = Persistent<FunctionTemplate>::New(tpl);
  }
  else {
    log("Getting existing class: " << rb_class2name(klass) << endl);

    persistTpl = it->second;
  }

  Local<Function> ctor = persistTpl->GetFunction();

  return scope.Close(ctor);
}

struct NewInstanceCaller
{
  NewInstanceCaller(std::vector<VALUE> &r, VALUE k, void* d) :
    rubyArgs(r), klass(k), data(d) {}

  VALUE operator()() const
  {
    if (data == NULL) {
      return rb_class_new_instance(rubyArgs.size(), &rubyArgs[0], klass);
    }
    else {
      VALUE obj = Data_Wrap_Struct(klass, NULL, NULL, data);
      rb_obj_call_init(obj, rubyArgs.size(), &rubyArgs[0]);
      return obj;
    }
  }

  std::vector<VALUE>& rubyArgs;
  VALUE klass;
  void* data;
};

Handle<Value> RubyObject::New(const Arguments& args)
{
  HandleScope scope;

  if (args.IsConstructCall()) {
    VALUE klass = VALUE(External::Unwrap(args.Data()));

    // TODO: This has serious GC implications. Make weak? When can we delete the ptr?
    Persistent<Object>* owner = NULL;
    if (!args[0]->IsUndefined())
      owner = new Persistent<Object>(Persistent<Object>::New(args[0].As<Object>()));

    Local<Array> v8Args = args[1].As<Array>();
    std::vector<VALUE> rubyArgs(v8Args->Length());
    for (uint32_t i = 0; i < v8Args->Length(); i++) {
      rubyArgs[i] = v8ToRuby(v8Args->Get(i));
    }

    log("Creating new " << rb_class2name(klass) << " with " << rubyArgs.size() << " args" << endl);

    VALUE ex;
    VALUE obj = SafeRubyCall(NewInstanceCaller(rubyArgs, klass, owner), ex);
    if (ex != Qnil) {
      ThrowException(rubyExToV8(ex));
      return scope.Close(Undefined());
    }

    // Wrap the obj immediately to prevent it from being garbage collected
    RubyObject *self = new RubyObject(obj);
    //self->m_owner = owner;
    self->Wrap(args.This());

    return scope.Close(args.This());
  }
  else {
    std::vector<Handle<Value> > argv(args.Length());
    for (int i = 0; i < args.Length(); i++) {
      argv[i] = args[i];
    }

    VALUE klass = VALUE(External::Unwrap(args.Data()));
    Local<Function> cons = RubyObject::GetClass(klass);

    //Local<Value> argv[argc] = { args[0], args[1], args[2] };
    //Local<Function> cons = args.Callee();
    return scope.Close(cons->NewInstance(args.Length(), &argv[0]));
  }
}

RubyObject::RubyObject(VALUE obj) : m_obj(obj)
{
  rb_gc_register_address(&m_obj);
}

RubyObject::~RubyObject()
{
  log("~RubyObject" << endl);
  rb_gc_unregister_address(&m_obj);
}

struct MethodCaller
{
  MethodCaller(VALUE o, VALUE m, const Arguments& args) :
    obj(o), methodID(m), rubyArgs(args.Length())
  {
    // TODO: Is this right? Is there a way to determine if a block is expected?
    if (args.Length() > 0 && args[args.Length()-1]->IsFunction()) {
      log("Got a func!" << endl);
      block = args[args.Length()-1].As<Function>();
      rubyArgs.resize(args.Length()-1);
    }

    for (size_t i = 0; i < rubyArgs.size(); i++) {
      rubyArgs[i] = v8ToRuby(args[i]);
    }
  }

  VALUE operator()() const
  {
    log("Calling method: " << rb_id2name(methodID) << " with " << rubyArgs.size() << " args");

    if (block.IsEmpty()) {
      log(endl);

      return rb_funcall2(obj, methodID, rubyArgs.size(), (VALUE*)&rubyArgs[0]);
    }
    else {
      log(" and a block" << endl);

      // TODO: Probably not available in Ruby < 1.9
      return rb_block_call(obj, methodID, rubyArgs.size(),
                           (VALUE*)&rubyArgs[0], RUBY_METHOD_FUNC(BlockFunc),
                           (VALUE)this);
    }
  }

  static VALUE BlockFunc(VALUE, VALUE data, int argc, const VALUE* rbArgv)
  {
    MethodCaller* self = reinterpret_cast<MethodCaller*>(data);

    return CallV8FromRuby(Context::GetCurrent()->Global(), self->block,
                          argc, rbArgv);
  }

  VALUE obj;
  VALUE methodID;
  std::vector<VALUE> rubyArgs;
  // TODO: Should this be persistent?
  Local<Function> block;
};

Handle<Value> RubyObject::CallMethod(const Arguments& args)
{
  HandleScope scope;

  RubyObject *self = node::ObjectWrap::Unwrap<RubyObject>(args.This());
  ID methodID = ID(External::Unwrap(args.Data()));

  //DumpV8Props(*self->m_owner);

  VALUE ex;
  VALUE res = SafeRubyCall(MethodCaller(self->m_obj, methodID, args), ex);
  if (ex != Qnil) {
    return scope.Close(ThrowException(rubyExToV8(ex)));
  }

  return scope.Close(rubyToV8(res));
}
<|endoftext|>