<commit_before>/*
* Copyright (C) 2008-2011 J-P Nurmi jpnurmi@gmail.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*/

#include "messagehandler.h"
#include <qabstractsocket.h>
#include <ircsession.h>
#include <qvariant.h>
#include <qdebug.h>
#include <irc.h>

MessageHandler::MessageHandler(QObject* parent) : QObject(parent)
{
    d.session = 0;
    d.defaultReceiver = 0;
    d.currentReceiver = 0;
    setSession(qobject_cast<IrcSession*>(parent));
}

MessageHandler::~MessageHandler()
{
    d.defaultReceiver = 0;
    d.currentReceiver = 0;
    d.receivers.clear();
    d.channelUsers.clear();
    if (d.session && d.session->isActive())
        d.session->socket()->waitForDisconnected(500);
}

IrcSession* MessageHandler::session() const
{
    return d.session;
}

void MessageHandler::setSession(IrcSession* session)
{
    if (d.session != session)
    {
        if (d.session)
        {
            disconnect(d.session, SIGNAL(destroyed()), this, SLOT(onSessionDestroyed()));
            disconnect(d.session, SIGNAL(messageReceived(IrcMessage*)), this, SLOT(handleMessage(IrcMessage*)));
        }

        if (session)
        {
            connect(session, SIGNAL(destroyed()), this, SLOT(onSessionDestroyed()));
            connect(session, SIGNAL(messageReceived(IrcMessage*)), this, SLOT(handleMessage(IrcMessage*)));
        }

        d.session = session;
    }
}

QObject* MessageHandler::defaultReceiver() const
{
    return d.defaultReceiver;
}

void MessageHandler::setDefaultReceiver(QObject* receiver)
{
    d.defaultReceiver = receiver;
}

QObject* MessageHandler::currentReceiver() const
{
    return d.currentReceiver;
}

void MessageHandler::setCurrentReceiver(QObject* receiver)
{
    d.currentReceiver = receiver;
}

void MessageHandler::addReceiver(const QString& name, QObject* receiver)
{
    d.receivers.insert(name.toLower(), receiver);
}

QObject* MessageHandler::getReceiver(const QString& name) const
{
    return d.receivers.value(name.toLower());
}

void MessageHandler::removeReceiver(const QString& name)
{
    const QString lower = name.toLower();
    if (d.receivers.contains(lower))
    {
        d.receivers.remove(name.toLower());
        emit receiverToBeRemoved(name);
    }
}

void MessageHandler::handleMessage(IrcMessage* message)
{
    switch (message->type())
    {
    case IrcMessage::Invite:
        handleInviteMessage(static_cast<IrcInviteMessage*>(message));
        break;
    case IrcMessage::Join:
        handleJoinMessage(static_cast<IrcJoinMessage*>(message));
        break;
    case IrcMessage::Kick:
        handleKickMessage(static_cast<IrcKickMessage*>(message));
        break;
    case IrcMessage::Mode:
        handleModeMessage(static_cast<IrcModeMessage*>(message));
        break;
    case IrcMessage::Nick:
        handleNickMessage(static_cast<IrcNickMessage*>(message));
        break;
    case IrcMessage::Notice:
        handleNoticeMessage(static_cast<IrcNoticeMessage*>(message));
        break;
    case IrcMessage::Numeric:
        handleNumericMessage(static_cast<IrcNumericMessage*>(message));
        break;
    case IrcMessage::Part:
        handlePartMessage(static_cast<IrcPartMessage*>(message));
        break;
    case IrcMessage::Pong:
        handlePongMessage(static_cast<IrcPongMessage*>(message));
        break;
    case IrcMessage::Private:
        handlePrivateMessage(static_cast<IrcPrivateMessage*>(message));
        break;
    case IrcMessage::Quit:
        handleQuitMessage(static_cast<IrcQuitMessage*>(message));
        break;
    case IrcMessage::Topic:
        handleTopicMessage(static_cast<IrcTopicMessage*>(message));
        break;
    case IrcMessage::Unknown:
        handleUnknownMessage(static_cast<IrcMessage*>(message));
        break;
    default:
        break;
    }
}

void MessageHandler::handleInviteMessage(IrcInviteMessage* message)
{
    sendMessage(message, d.currentReceiver);
}

void MessageHandler::handleJoinMessage(IrcJoinMessage* message)
{
    sendMessage(message, message->channel());
    d.addChannelUser(message->channel(), message->sender().name());
}

void MessageHandler::handleKickMessage(IrcKickMessage* message)
{
    sendMessage(message, message->channel());
    d.removeChannelUser(message->channel(), message->user());
}

void MessageHandler::handleModeMessage(IrcModeMessage* message)
{
    if (message->sender().name() == message->target())
        sendMessage(message, d.defaultReceiver);
    else
        sendMessage(message, message->target());
}

void MessageHandler::handleNickMessage(IrcNickMessage* message)
{
    QString nick = message->sender().name().toLower();
    foreach (const QString& channel, d.userChannels(nick))
    {
        sendMessage(message, channel);
        d.removeChannelUser(channel, nick);
        d.addChannelUser(channel, message->nick());
    }
    foreach (const QString& receiver, d.receivers.keys())
    {
        if (!nick.compare(receiver, Qt::CaseInsensitive))
        {
            emit receiverToBeRenamed(receiver, message->nick());
            QObject* object = d.receivers.take(nick);
            d.receivers.insert(nick, object);
            sendMessage(message, object);
        }
    }
}

void MessageHandler::handleNoticeMessage(IrcNoticeMessage* message)
{
    sendMessage(message, d.currentReceiver);
}

void MessageHandler::handleNumericMessage(IrcNumericMessage* message)
{
    switch (message->code())
    {
    case Irc::RPL_ENDOFWHO:
    case Irc::RPL_WHOREPLY:
    case Irc::RPL_UNAWAY:
    case Irc::RPL_NOWAWAY:
    case Irc::RPL_AWAY:
    case Irc::RPL_WHOISOPERATOR:
    case Irc::RPL_WHOISHELPOP: // "is available for help"
    case Irc::RPL_WHOISSPECIAL: // "is identified to services"
    case Irc::RPL_WHOISHOST: // nick is connecting from <...>
    case Irc::RPL_WHOISSECURE: // nick is using a secure connection
    case Irc::RPL_WHOISUSER:
    case Irc::RPL_WHOISSERVER:
    case Irc::RPL_WHOISACCOUNT: // nick user is logged in as
    case Irc::RPL_WHOWASUSER:
    case Irc::RPL_WHOISIDLE:
    case Irc::RPL_WHOISCHANNELS:
    case Irc::RPL_ENDOFWHOIS:
    case Irc::RPL_INVITING:
    case Irc::RPL_VERSION:
    case Irc::RPL_TIME:
        sendMessage(message, d.currentReceiver);
        break;

    case Irc::RPL_ENDOFBANLIST:
    case Irc::RPL_ENDOFEXCEPTLIST:
    case Irc::RPL_ENDOFINFO:
    case Irc::RPL_ENDOFINVITELIST:
    case Irc::RPL_ENDOFLINKS:
    case Irc::RPL_ENDOFMOTD:
    case Irc::RPL_ENDOFSTATS:
    case Irc::RPL_ENDOFUSERS:
    case Irc::RPL_ENDOFWHOWAS:
        break; // ignore

    case Irc::RPL_ENDOFNAMES:
    case Irc::RPL_CHANNELMODEIS:
    case Irc::RPL_CHANNEL_URL:
    case Irc::RPL_CREATIONTIME:
    case Irc::RPL_NOTOPIC:
    case Irc::RPL_TOPIC:
    case Irc::RPL_TOPICWHOTIME:
        sendMessage(message, message->parameters().value(1));
        break;

    case Irc::RPL_NAMREPLY: {
        const int count = message->parameters().count();
        const QString channel = message->parameters().value(count - 2);
        const QStringList names = message->parameters().value(count - 1).split(" ", QString::SkipEmptyParts);
        foreach (QString name, names)
        {
            if (name.startsWith("@") || name.startsWith("+"))
                name.remove(0, 1);
            d.addChannelUser(channel, name);
        }
        sendMessage(message, channel);
        break;
        }

    default:
        sendMessage(message, d.defaultReceiver);
        break;
    }
}

void MessageHandler::handlePartMessage(IrcPartMessage* message)
{
    d.removeChannelUser(message->channel(), message->sender().name());
    if (message->sender().name() == d.session->nickName())
    {
        removeReceiver(message->channel());
        d.channelUsers.remove(message->channel().toLower());
    }
    else
    {
        sendMessage(message, message->channel());
    }
}

void MessageHandler::handlePongMessage(IrcPongMessage* message)
{
    sendMessage(message, d.currentReceiver);
}

void MessageHandler::handlePrivateMessage(IrcPrivateMessage* message)
{
    if (message->isRequest())
        sendMessage(message, d.currentReceiver);
    else if (message->target() == d.session->nickName())
        sendMessage(message, message->sender().name());
    else
        sendMessage(message, message->target());
}

void MessageHandler::handleQuitMessage(IrcQuitMessage* message)
{
    QString nick = message->sender().name();
    foreach (const QString& channel, d.userChannels(nick))
    {
        sendMessage(message, channel);
        d.removeChannelUser(channel, nick);
    }

    if (d.receivers.contains(nick.toLower()))
        sendMessage(message, nick);

    if (nick == d.session->nickName())
        removeReceiver(d.session->host());
}

void MessageHandler::handleTopicMessage(IrcTopicMessage* message)
{
    sendMessage(message, message->channel());
}

void MessageHandler::handleUnknownMessage(IrcMessage* message)
{
    sendMessage(message, d.defaultReceiver);
}

void MessageHandler::sendMessage(IrcMessage* message, QObject* receiver)
{
    QMetaObject::invokeMethod(receiver, "receiveMessage", Q_ARG(IrcMessage*, message));

    // if the receiver was a QML element, argument type would be QVariant(QObject*):
    // QMetaObject::invokeMethod(receiver, "receiveMessage", Q_ARG(QVariant, QVariant::fromValue((QObject*) message)));
}

void MessageHandler::sendMessage(IrcMessage* message, const QString& receiver)
{
    if (!d.receivers.contains(receiver.toLower()))
        emit receiverToBeAdded(receiver);
    QObject* object = getReceiver(receiver);
    Q_ASSERT(object);
    sendMessage(message, object);
}

void MessageHandler::onSessionDestroyed()
{
    setSession(0);
}

QStringList MessageHandler::Private::userChannels(const QString& user) const
{
    QStringList channels;
    QHash<QString, QSet<QString> >::const_iterator it;
    for (it = channelUsers.constBegin(); it != channelUsers.constEnd(); ++it)
        if (it.value().contains(user.toLower()))
            channels += it.key();
    return channels;
}

void MessageHandler::Private::addChannelUser(QString channel, const QString& user)
{
    channel = channel.toLower();
    if (!channelUsers.value(channel).contains(user.toLower()))
    {
        channelUsers[channel].insert(user.toLower());
        QObject* receiver = receivers.value(channel);
        if (receiver)
            QMetaObject::invokeMethod(receiver, "addUser", Q_ARG(QString, user));
    }
}

void MessageHandler::Private::removeChannelUser(QString channel, const QString& user)
{
    channel = channel.toLower();
    if (channelUsers.value(channel).contains(user.toLower()))
    {
        channelUsers[channel].remove(user.toLower());
        QObject* receiver = receivers.value(channel);
        if (receiver)
            QMetaObject::invokeMethod(receiver, "removeUser", Q_ARG(QString, user));
    }
}
<commit_msg>msg handler: make assert to a condition...<commit_after>/*
* Copyright (C) 2008-2011 J-P Nurmi jpnurmi@gmail.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*/

#include "messagehandler.h"
#include <qabstractsocket.h>
#include <ircsession.h>
#include <qvariant.h>
#include <qdebug.h>
#include <irc.h>

MessageHandler::MessageHandler(QObject* parent) : QObject(parent)
{
    d.session = 0;
    d.defaultReceiver = 0;
    d.currentReceiver = 0;
    setSession(qobject_cast<IrcSession*>(parent));
}

MessageHandler::~MessageHandler()
{
    d.defaultReceiver = 0;
    d.currentReceiver = 0;
    d.receivers.clear();
    d.channelUsers.clear();
    if (d.session && d.session->isActive())
        d.session->socket()->waitForDisconnected(500);
}

IrcSession* MessageHandler::session() const
{
    return d.session;
}

void MessageHandler::setSession(IrcSession* session)
{
    if (d.session != session)
    {
        if (d.session)
        {
            disconnect(d.session, SIGNAL(destroyed()), this, SLOT(onSessionDestroyed()));
            disconnect(d.session, SIGNAL(messageReceived(IrcMessage*)), this, SLOT(handleMessage(IrcMessage*)));
        }

        if (session)
        {
            connect(session, SIGNAL(destroyed()), this, SLOT(onSessionDestroyed()));
            connect(session, SIGNAL(messageReceived(IrcMessage*)), this, SLOT(handleMessage(IrcMessage*)));
        }

        d.session = session;
    }
}

QObject* MessageHandler::defaultReceiver() const
{
    return d.defaultReceiver;
}

void MessageHandler::setDefaultReceiver(QObject* receiver)
{
    d.defaultReceiver = receiver;
}

QObject* MessageHandler::currentReceiver() const
{
    return d.currentReceiver;
}

void MessageHandler::setCurrentReceiver(QObject* receiver)
{
    d.currentReceiver = receiver;
}

void MessageHandler::addReceiver(const QString& name, QObject* receiver)
{
    d.receivers.insert(name.toLower(), receiver);
}

QObject* MessageHandler::getReceiver(const QString& name) const
{
    return d.receivers.value(name.toLower());
}

void MessageHandler::removeReceiver(const QString& name)
{
    const QString lower = name.toLower();
    if (d.receivers.contains(lower))
    {
        d.receivers.remove(name.toLower());
        emit receiverToBeRemoved(name);
    }
}

void MessageHandler::handleMessage(IrcMessage* message)
{
    switch (message->type())
    {
    case IrcMessage::Invite:
        handleInviteMessage(static_cast<IrcInviteMessage*>(message));
        break;
    case IrcMessage::Join:
        handleJoinMessage(static_cast<IrcJoinMessage*>(message));
        break;
    case IrcMessage::Kick:
        handleKickMessage(static_cast<IrcKickMessage*>(message));
        break;
    case IrcMessage::Mode:
        handleModeMessage(static_cast<IrcModeMessage*>(message));
        break;
    case IrcMessage::Nick:
        handleNickMessage(static_cast<IrcNickMessage*>(message));
        break;
    case IrcMessage::Notice:
        handleNoticeMessage(static_cast<IrcNoticeMessage*>(message));
        break;
    case IrcMessage::Numeric:
        handleNumericMessage(static_cast<IrcNumericMessage*>(message));
        break;
    case IrcMessage::Part:
        handlePartMessage(static_cast<IrcPartMessage*>(message));
        break;
    case IrcMessage::Pong:
        handlePongMessage(static_cast<IrcPongMessage*>(message));
        break;
    case IrcMessage::Private:
        handlePrivateMessage(static_cast<IrcPrivateMessage*>(message));
        break;
    case IrcMessage::Quit:
        handleQuitMessage(static_cast<IrcQuitMessage*>(message));
        break;
    case IrcMessage::Topic:
        handleTopicMessage(static_cast<IrcTopicMessage*>(message));
        break;
    case IrcMessage::Unknown:
        handleUnknownMessage(static_cast<IrcMessage*>(message));
        break;
    default:
        break;
    }
}

void MessageHandler::handleInviteMessage(IrcInviteMessage* message)
{
    sendMessage(message, d.currentReceiver);
}

void MessageHandler::handleJoinMessage(IrcJoinMessage* message)
{
    sendMessage(message, message->channel());
    d.addChannelUser(message->channel(), message->sender().name());
}

void MessageHandler::handleKickMessage(IrcKickMessage* message)
{
    sendMessage(message, message->channel());
    d.removeChannelUser(message->channel(), message->user());
}

void MessageHandler::handleModeMessage(IrcModeMessage* message)
{
    if (message->sender().name() == message->target())
        sendMessage(message, d.defaultReceiver);
    else
        sendMessage(message, message->target());
}

void MessageHandler::handleNickMessage(IrcNickMessage* message)
{
    QString nick = message->sender().name().toLower();
    foreach (const QString& channel, d.userChannels(nick))
    {
        sendMessage(message, channel);
        d.removeChannelUser(channel, nick);
        d.addChannelUser(channel, message->nick());
    }
    foreach (const QString& receiver, d.receivers.keys())
    {
        if (!nick.compare(receiver, Qt::CaseInsensitive))
        {
            emit receiverToBeRenamed(receiver, message->nick());
            QObject* object = d.receivers.take(nick);
            d.receivers.insert(nick, object);
            sendMessage(message, object);
        }
    }
}

void MessageHandler::handleNoticeMessage(IrcNoticeMessage* message)
{
    sendMessage(message, d.currentReceiver);
}

void MessageHandler::handleNumericMessage(IrcNumericMessage* message)
{
    switch (message->code())
    {
    case Irc::RPL_ENDOFWHO:
    case Irc::RPL_WHOREPLY:
    case Irc::RPL_UNAWAY:
    case Irc::RPL_NOWAWAY:
    case Irc::RPL_AWAY:
    case Irc::RPL_WHOISOPERATOR:
    case Irc::RPL_WHOISHELPOP: // "is available for help"
    case Irc::RPL_WHOISSPECIAL: // "is identified to services"
    case Irc::RPL_WHOISHOST: // nick is connecting from <...>
    case Irc::RPL_WHOISSECURE: // nick is using a secure connection
    case Irc::RPL_WHOISUSER:
    case Irc::RPL_WHOISSERVER:
    case Irc::RPL_WHOISACCOUNT: // nick user is logged in as
    case Irc::RPL_WHOWASUSER:
    case Irc::RPL_WHOISIDLE:
    case Irc::RPL_WHOISCHANNELS:
    case Irc::RPL_ENDOFWHOIS:
    case Irc::RPL_INVITING:
    case Irc::RPL_VERSION:
    case Irc::RPL_TIME:
        sendMessage(message, d.currentReceiver);
        break;

    case Irc::RPL_ENDOFBANLIST:
    case Irc::RPL_ENDOFEXCEPTLIST:
    case Irc::RPL_ENDOFINFO:
    case Irc::RPL_ENDOFINVITELIST:
    case Irc::RPL_ENDOFLINKS:
    case Irc::RPL_ENDOFMOTD:
    case Irc::RPL_ENDOFSTATS:
    case Irc::RPL_ENDOFUSERS:
    case Irc::RPL_ENDOFWHOWAS:
        break; // ignore

    case Irc::RPL_ENDOFNAMES:
    case Irc::RPL_CHANNELMODEIS:
    case Irc::RPL_CHANNEL_URL:
    case Irc::RPL_CREATIONTIME:
    case Irc::RPL_NOTOPIC:
    case Irc::RPL_TOPIC:
    case Irc::RPL_TOPICWHOTIME:
        sendMessage(message, message->parameters().value(1));
        break;

    case Irc::RPL_NAMREPLY: {
        const int count = message->parameters().count();
        const QString channel = message->parameters().value(count - 2);
        const QStringList names = message->parameters().value(count - 1).split(" ", QString::SkipEmptyParts);
        foreach (QString name, names)
        {
            if (name.startsWith("@") || name.startsWith("+"))
                name.remove(0, 1);
            d.addChannelUser(channel, name);
        }
        sendMessage(message, channel);
        break;
        }

    default:
        sendMessage(message, d.defaultReceiver);
        break;
    }
}

void MessageHandler::handlePartMessage(IrcPartMessage* message)
{
    d.removeChannelUser(message->channel(), message->sender().name());
    if (message->sender().name() == d.session->nickName())
    {
        removeReceiver(message->channel());
        d.channelUsers.remove(message->channel().toLower());
    }
    else
    {
        sendMessage(message, message->channel());
    }
}

void MessageHandler::handlePongMessage(IrcPongMessage* message)
{
    sendMessage(message, d.currentReceiver);
}

void MessageHandler::handlePrivateMessage(IrcPrivateMessage* message)
{
    if (message->isRequest())
        sendMessage(message, d.currentReceiver);
    else if (message->target() == d.session->nickName())
        sendMessage(message, message->sender().name());
    else
        sendMessage(message, message->target());
}

void MessageHandler::handleQuitMessage(IrcQuitMessage* message)
{
    QString nick = message->sender().name();
    foreach (const QString& channel, d.userChannels(nick))
    {
        sendMessage(message, channel);
        d.removeChannelUser(channel, nick);
    }

    if (d.receivers.contains(nick.toLower()))
        sendMessage(message, nick);

    if (nick == d.session->nickName())
        removeReceiver(d.session->host());
}

void MessageHandler::handleTopicMessage(IrcTopicMessage* message)
{
    sendMessage(message, message->channel());
}

void MessageHandler::handleUnknownMessage(IrcMessage* message)
{
    sendMessage(message, d.defaultReceiver);
}

void MessageHandler::sendMessage(IrcMessage* message, QObject* receiver)
{
    QMetaObject::invokeMethod(receiver, "receiveMessage", Q_ARG(IrcMessage*, message));

    // if the receiver was a QML element, argument type would be QVariant(QObject*):
    // QMetaObject::invokeMethod(receiver, "receiveMessage", Q_ARG(QVariant, QVariant::fromValue((QObject*) message)));
}

void MessageHandler::sendMessage(IrcMessage* message, const QString& receiver)
{
    if (!d.receivers.contains(receiver.toLower()))
        emit receiverToBeAdded(receiver);
    QObject* object = getReceiver(receiver);
    if (object)
        sendMessage(message, object);
}

void MessageHandler::onSessionDestroyed()
{
    setSession(0);
}

QStringList MessageHandler::Private::userChannels(const QString& user) const
{
    QStringList channels;
    QHash<QString, QSet<QString> >::const_iterator it;
    for (it = channelUsers.constBegin(); it != channelUsers.constEnd(); ++it)
        if (it.value().contains(user.toLower()))
            channels += it.key();
    return channels;
}

void MessageHandler::Private::addChannelUser(QString channel, const QString& user)
{
    channel = channel.toLower();
    if (!channelUsers.value(channel).contains(user.toLower()))
    {
        channelUsers[channel].insert(user.toLower());
        QObject* receiver = receivers.value(channel);
        if (receiver)
            QMetaObject::invokeMethod(receiver, "addUser", Q_ARG(QString, user));
    }
}

void MessageHandler::Private::removeChannelUser(QString channel, const QString& user)
{
    channel = channel.toLower();
    if (channelUsers.value(channel).contains(user.toLower()))
    {
        channelUsers[channel].remove(user.toLower());
        QObject* receiver = receivers.value(channel);
        if (receiver)
            QMetaObject::invokeMethod(receiver, "removeUser", Q_ARG(QString, user));
    }
}
<|endoftext|>


<commit_before>/* ux++ - ux implementation for C++ */

/* LICENSE - The MIT License (MIT)

Copyright (c) 2013 Tomona Nanase

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.
 */

#ifndef BASICWAVEFORM_HPP
#define	BASICWAVEFORM_HPP

#include <utility>
#include <list>
#include "StepWaveform.hpp"

namespace uxpp {

  /**
   * 矩形波を生成する波形ジェネレータクラスです。
   */
  class Square : public StepWaveform {
  public:
    // <editor-fold desc="-- Construnctors --">
    /**
     * 新しい Square クラスのインスタンスを初期化します。
     */
    Square();
    // </editor-fold>

    // <editor-fold desc="-- Methods --">
    /**
     * パラメータを指定してこの波形の設定値を変更します。
     * @param data1 整数パラメータ。
     * @param data2 実数パラメータ。
     */
    virtual void setParameter(int32_t data1, float data2) override;

    /**
     * 波形のパラメータをリセットします。
     */
    virtual void reset() override;
    // </editor-fold>

  private:
    // <editor-fold desc="-- Static Fields --">
    static std::list<std::pair<int8_t, std::vector<float >> > cache;
    // </editor-fold>

    // <editor-fold desc="-- Methods --">
    void generateStep(const float duty);
    // </editor-fold>
  };

  /**
   * 擬似三角波を生成する波形ジェネレータクラスです。
   */
  class Triangle : public StepWaveform {
  public:
    // <editor-fold desc="-- Construnctors --">
    /**
     * 新しい Triangle クラスのインスタンスを初期化します。
     */
    Triangle();
    // </editor-fold>

    // <editor-fold desc="-- Methods --">
    /**
     * パラメータを指定してこの波形の設定値を変更します。
     * @param data1 整数パラメータ。
     * @param data2 実数パラメータ。
     */
    virtual void setParameter(int32_t data1, float data2) override;

    /**
     * 波形のパラメータをリセットします。
     */
    virtual void reset() override;
    // </editor-fold>

  private:
    // <editor-fold desc="-- Static Fields --">
    static std::list<std::pair<int8_t, std::vector<float >> > cache;
    // </editor-fold>

    // <editor-fold desc="-- Methods --">
    void generateStep(const int step);
    // </editor-fold>
  };
}

#endif	/* BASICWAVEFORM_HPP */

<commit_msg>Revert "BasicWaveformのクラス群にoverrideキーワードを追加"<commit_after>/* ux++ - ux implementation for C++ */

/* LICENSE - The MIT License (MIT)

Copyright (c) 2013 Tomona Nanase

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.
 */

#ifndef BASICWAVEFORM_HPP
#define	BASICWAVEFORM_HPP

#include <utility>
#include <list>
#include "StepWaveform.hpp"

namespace uxpp {

  /**
   * 矩形波を生成する波形ジェネレータクラスです。
   */
  class Square : public StepWaveform {
  public:
    // <editor-fold desc="-- Construnctors --">
    /**
     * 新しい Square クラスのインスタンスを初期化します。
     */
    Square();
    // </editor-fold>

    // <editor-fold desc="-- Methods --">
    /**
     * パラメータを指定してこの波形の設定値を変更します。
     * @param data1 整数パラメータ。
     * @param data2 実数パラメータ。
     */
    virtual void setParameter(int32_t data1, float data2);

    /**
     * 波形のパラメータをリセットします。
     */
    virtual void reset();
    // </editor-fold>

  private:
    // <editor-fold desc="-- Static Fields --">
    static std::list<std::pair<int8_t, std::vector<float >> > cache;
    // </editor-fold>

    // <editor-fold desc="-- Methods --">
    void generateStep(const float duty);
    // </editor-fold>
  };

  /**
   * 擬似三角波を生成する波形ジェネレータクラスです。
   */
  class Triangle : public StepWaveform {
  public:
    // <editor-fold desc="-- Construnctors --">
    /**
     * 新しい Triangle クラスのインスタンスを初期化します。
     */
    Triangle();
    // </editor-fold>

    // <editor-fold desc="-- Methods --">
    /**
     * パラメータを指定してこの波形の設定値を変更します。
     * @param data1 整数パラメータ。
     * @param data2 実数パラメータ。
     */
    virtual void setParameter(int32_t data1, float data2);

    /**
     * 波形のパラメータをリセットします。
     */
    virtual void reset();
    // </editor-fold>

  private:
    // <editor-fold desc="-- Static Fields --">
    static std::list<std::pair<int8_t, std::vector<float >> > cache;
    // </editor-fold>

    // <editor-fold desc="-- Methods --">
    void generateStep(const int step);
    // </editor-fold>
  };
}

#endif	/* BASICWAVEFORM_HPP */

<|endoftext|>


<commit_before>/**
@file utility.hpp
@brief Utilities.

@author Tim Howard
@copyright 2013 Tim Howard under the MIT license;
see @ref index or the accompanying LICENSE file for full text.
*/

#ifndef BEARD_UTILITY_HPP_
#define BEARD_UTILITY_HPP_

#include <Beard/config.hpp>

#include <duct/utility.hpp>

namespace Beard {

// Forward declarations

/**
	@addtogroup etc
	@{
*/

using duct::make_const;
using duct::enum_cast;
using duct::enum_bitor;
using duct::enum_bitand;
using duct::enum_combine;
using duct::min_ce;
using duct::max_ce;

/** @} */ // end of doc-group etc

} // namespace Beard

#endif // BEARD_UTILITY_HPP_
<commit_msg>utility: imported duct::signed_cast() and duct::unsigned_cast().<commit_after>/**
@file utility.hpp
@brief Utilities.

@author Tim Howard
@copyright 2013 Tim Howard under the MIT license;
see @ref index or the accompanying LICENSE file for full text.
*/

#ifndef BEARD_UTILITY_HPP_
#define BEARD_UTILITY_HPP_

#include <Beard/config.hpp>

#include <duct/utility.hpp>

namespace Beard {

// Forward declarations

/**
	@addtogroup etc
	@{
*/

using duct::make_const;
using duct::signed_cast;
using duct::unsigned_cast;
using duct::enum_cast;
using duct::enum_bitor;
using duct::enum_bitand;
using duct::enum_combine;
using duct::min_ce;
using duct::max_ce;

/** @} */ // end of doc-group etc

} // namespace Beard

#endif // BEARD_UTILITY_HPP_
<|endoftext|>


<commit_before>// Copyright (C) 2012 Sami Kyöstilä

#include "Renderer.h"
#include "renderer/Image.h"

#include <glm/gtc/matrix_transform.hpp>
#include <string>
#include <iostream>
#include <iomanip>
#include <stdexcept>
#include <sstream>

#define ASSERT_GL() \
    do \
    { \
        GLenum status = glGetError(); \
        if (status) \
        { \
            std::ostringstream s; \
            s << "OpenGL error raised in " << __FILE__ << "() on line " << __LINE__ << ": " << std::setbase(16) << "0x" << status; \
            throw std::runtime_error(s.str()); \
        } \
    } while (0)

#define ASSERT_GL_EXTENSION(EXTNAME) \
    do \
    { \
        if (!(GLEW_ ## EXTNAME)) \
        { \
            std::ostringstream s; \
            s << "OpenGL extension " #EXTNAME " not supported"; \
            throw std::runtime_error(s.str()); \
        } \
    } while (0)

namespace gl
{

template <void (*F)(GLsizei, const GLuint*)>
class GLDeleter
{
public:
    typedef GLuint pointer;

    void operator()(GLuint id)
    {
        if (id)
            F(1, &id);
    }
};

class GLShaderDeleter
{
public:
    typedef GLuint pointer;

    void operator()(GLuint id)
    {
        if (id)
            glDeleteShader(id);
    }
};

class GLProgramDeleter
{
public:
    typedef GLuint pointer;

    void operator()(GLuint id)
    {
        if (id)
            glDeleteProgram(id);
    }
};

class GLFramebufferDeleter
{
public:
    typedef GLuint pointer;

    void operator()(GLuint id)
    {
        if (id)
            glDeleteFramebuffers(1, &id);
    }
};

typedef std::unique_ptr<GLuint, GLDeleter<glDeleteTextures>> Texture;
static Texture createTexture(GLenum target, int levels, GLenum internalFormat, int width, int height)
{
    GLuint id;
    glGenTextures(1, &id);
    glBindTexture(target, id);
    glTexStorage2D(target, levels, internalFormat, width, height);
    return Texture(id);
}

typedef std::unique_ptr<GLuint, GLShaderDeleter> Shader;
typedef std::unique_ptr<GLuint, GLProgramDeleter> Program;
typedef std::unique_ptr<GLuint, GLFramebufferDeleter> Framebuffer;

static bool compileShader(GLuint id, const std::string& source)
{
    const char* s[] =
    {
        source.c_str()
    };

    glShaderSource(id, 1, s, NULL);
    glCompileShader(id);

    std::string infoLog;
    GLint length;
    glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
    if (length > 0) {
        std::unique_ptr<char[]> logData(new char[length]);
        glGetShaderInfoLog(id, length, &length, logData.get());
        infoLog = logData.get();
    }

    GLint status;
    glGetShaderiv(id, GL_COMPILE_STATUS, &status);
    if (status != GL_TRUE)
    {
        std::cerr << "Shader compilation failed: " << infoLog << std::endl;
        return false;
    }
    return true;
}

static bool compileProgram(GLuint id, const std::string& vertSource, const std::string& fragSource)
{
    Shader vertShader(glCreateShader(GL_VERTEX_SHADER));
    Shader fragShader(glCreateShader(GL_FRAGMENT_SHADER));

    if (!compileShader(vertShader.get(), vertSource) || !compileShader(fragShader.get(), fragSource))
        return false;

    glAttachShader(id, vertShader.get());
    glAttachShader(id, fragShader.get());
    glLinkProgram(id);

    std::string infoLog;
    GLint length;
    glGetProgramiv(id, GL_INFO_LOG_LENGTH, &length);
    if (length > 0) {
        std::unique_ptr<char[]> logData(new char[length]);
        glGetShaderInfoLog(id, length, &length, logData.get());
        infoLog = logData.get();
    }

    GLint status;
    glGetProgramiv(id, GL_LINK_STATUS, &status);
    if (status != GL_TRUE)
    {
        std::cerr << "Program linking failed: " << infoLog << std::endl;
        return false;
    }
    return true;
}

#define SHADER(X) #X

static const char initVertShader[] = SHADER(
    void main()
    {
        gl_Position = vec4(0.0, 0.8, 1.0, 1.0);
    }
);

static const char initFragShader[] = SHADER(
    void main()
    {
        gl_FragColor = vec4(0.0, 0.8, 1.0, 1.0);
    }
);

Renderer::Renderer(const scene::Scene& scene)
{
}

void Renderer::render(Image& image, int xOffset, int yOffset, int width, int height) const
{
    // Each ray has:
    // - origin
    // - direction
    // - weight
    // - color
    //
    // 1. Generate initial set of rays from camera
    // 2. Repeat:
    // - Intersect all rays
    // - Generate new rays based on shading

    Texture originTexture = createTexture(GL_TEXTURE_2D, 1, GL_RGB32F, image.width, image.height);
    Texture directionTexture = createTexture(GL_TEXTURE_2D, 1, GL_RGB32F, image.width, image.height);
    Texture distanceTexture = createTexture(GL_TEXTURE_2D, 1, GL_R32F, image.width, image.height);
    ASSERT_GL();

    //Program initProgram(glCreateProgram());
    //compileProgram(initProgram.get(), initVertShader, initFragShader);
    //ASSERT_GL();

/*
    GLuint init
    glGenFramebuffers(1, &m_fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, preview->m_fbo);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                           GL_TEXTURE_2D, preview->m_texture, 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
*/
    glClearColor(1, .5, 0, 1);
    glClear(GL_COLOR_BUFFER_BIT);

    glPixelStorei(GL_PACK_ROW_LENGTH, image.width);
    glReadPixels(xOffset, yOffset, width, height, GL_BGRA, GL_UNSIGNED_BYTE, image.pixels.get());
    glPixelStorei(GL_PACK_ROW_LENGTH, 0);

#if 0
    const Camera& camera = m_scene->camera;

    const glm::vec4 viewport(0, 0, 1, 1);
    glm::vec3 p1 = glm::unProject(glm::vec3(0.f, 0.f, 0.f), camera.transform, camera.projection, viewport);
    glm::vec3 p2 = glm::unProject(glm::vec3(1.f, 0.f, 0.f), camera.transform, camera.projection, viewport);
    glm::vec3 p3 = glm::unProject(glm::vec3(0.f, 1.f, 0.f), camera.transform, camera.projection, viewport);
    glm::vec3 origin(glm::inverse(camera.transform) * glm::vec4(0.f, 0.f, 0.f, 1.f));

    std::unique_ptr<glm::vec4[]> radianceMap(new glm::vec4[width * height]);

    int samples = 1;
    for (int pass = 1;; pass++)
    {
        if (m_observer && !m_observer(pass, samples, xOffset, yOffset, width, height))
            return;
    }
#endif
}

}
<commit_msg>First GL program running<commit_after>// Copyright (C) 2012 Sami Kyöstilä

#include "Renderer.h"
#include "renderer/Image.h"

#include <glm/gtc/matrix_transform.hpp>
#include <list>
#include <string>
#include <iostream>
#include <iomanip>
#include <stdexcept>
#include <sstream>

#define ASSERT_GL() \
    do \
    { \
        GLenum status = glGetError(); \
        if (status) \
        { \
            std::ostringstream s; \
            s << "OpenGL error raised in " << __FILE__ << "() on line " << __LINE__ << ": " << std::setbase(16) << "0x" << status; \
            throw std::runtime_error(s.str()); \
        } \
    } while (0)

#define ASSERT_GL_EXTENSION(EXTNAME) \
    do \
    { \
        if (!(GLEW_ ## EXTNAME)) \
        { \
            std::ostringstream s; \
            s << "OpenGL extension " #EXTNAME " not supported"; \
            throw std::runtime_error(s.str()); \
        } \
    } while (0)

namespace gl
{

template <void (*F)(GLsizei, const GLuint*)>
class GLDeleter
{
public:
    typedef GLuint pointer;

    void operator()(GLuint id)
    {
        if (id)
            F(1, &id);
    }
};

class GLShaderDeleter
{
public:
    typedef GLuint pointer;

    void operator()(GLuint id)
    {
        if (id)
            glDeleteShader(id);
    }
};

class GLProgramDeleter
{
public:
    typedef GLuint pointer;

    void operator()(GLuint id)
    {
        if (id)
            glDeleteProgram(id);
    }
};

class GLFramebufferDeleter
{
public:
    typedef GLuint pointer;

    void operator()(GLuint id)
    {
        if (id)
            glDeleteFramebuffers(1, &id);
    }
};

class GLBufferDeleter
{
public:
    typedef GLuint pointer;

    void operator()(GLuint id)
    {
        if (id)
            glDeleteBuffers(1, &id);
    }
};

typedef std::unique_ptr<GLuint, GLDeleter<glDeleteTextures>> Texture;
static Texture createTexture(GLenum target, int levels, GLenum internalFormat, int width, int height)
{
    GLuint id;
    glGenTextures(1, &id);
    glBindTexture(target, id);
    glTexStorage2D(target, levels, internalFormat, width, height);
    return Texture(id);
}

typedef std::unique_ptr<GLuint, GLShaderDeleter> Shader;
typedef std::unique_ptr<GLuint, GLProgramDeleter> Program;
typedef std::unique_ptr<GLuint, GLFramebufferDeleter> Framebuffer;

typedef std::unique_ptr<GLuint, GLBufferDeleter> Buffer;
static Buffer createBuffer(GLenum target, size_t size, const void* data, GLenum usage)
{
    GLuint id;
    glGenBuffers(1, &id);
    glBindBuffer(target, id);
    glBufferData(target, size, data, usage);
    return Buffer(id);
}

static bool compileShader(GLuint id, const std::string& source)
{
    const char* s[] =
    {
        source.c_str()
    };

    glShaderSource(id, 1, s, NULL);
    glCompileShader(id);

    std::string infoLog;
    GLint length = 0;
    glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
    if (length > 0) {
        std::unique_ptr<char[]> logData(new char[length]);
        glGetShaderInfoLog(id, length, &length, logData.get());
        infoLog = logData.get();
    }

    GLint status;
    glGetShaderiv(id, GL_COMPILE_STATUS, &status);
    if (status != GL_TRUE)
    {
        std::cerr << "Shader compilation failed: " << infoLog << std::endl;
        return false;
    }
    return true;
}

static bool compileProgram(GLuint id, const std::string& vertSource, const std::string& fragSource,
                           const std::list<std::string>& attributes)
{
    Shader vertShader(glCreateShader(GL_VERTEX_SHADER));
    Shader fragShader(glCreateShader(GL_FRAGMENT_SHADER));

    if (!compileShader(vertShader.get(), vertSource) || !compileShader(fragShader.get(), fragSource))
        return false;

    glAttachShader(id, vertShader.get());
    glAttachShader(id, fragShader.get());

    int n = 0;
    for (const std::string& attribute: attributes)
        glBindAttribLocation(id, n++, attribute.c_str());
    glLinkProgram(id);

    std::string infoLog;
    GLint length = 0;
    glGetProgramiv(id, GL_INFO_LOG_LENGTH, &length);
    if (length > 0) {
        std::unique_ptr<char[]> logData(new char[length]);
        glGetProgramInfoLog(id, length, &length, logData.get());
        infoLog = logData.get();
    }

    GLint status;
    glGetProgramiv(id, GL_LINK_STATUS, &status);
    if (status != GL_TRUE)
    {
        std::cerr << "Program linking failed: " << infoLog << std::endl;
        return false;
    }
    ASSERT_GL();
    return true;
}

#define SHADER(X) #X

static const char initVertShader[] = SHADER(
    attribute vec4 position;

    void main()
    {
        gl_Position = position;
    }
);

static const char initFragShader[] = SHADER(
    void main()
    {
        gl_FragColor = vec4(0.0, 0.8, 1.0, 1.0);
    }
);

Renderer::Renderer(const scene::Scene& scene)
{
}

void Renderer::render(Image& image, int xOffset, int yOffset, int width, int height) const
{
    // Each ray has:
    // - origin
    // - direction
    // - weight
    // - color
    //
    // 1. Generate initial set of rays from camera
    // 2. Repeat:
    // - Intersect all rays
    // - Generate new rays based on shading

    Texture originTexture = createTexture(GL_TEXTURE_2D, 1, GL_RGB32F, image.width, image.height);
    Texture directionTexture = createTexture(GL_TEXTURE_2D, 1, GL_RGB32F, image.width, image.height);
    Texture distanceTexture = createTexture(GL_TEXTURE_2D, 1, GL_R32F, image.width, image.height);
    ASSERT_GL();

    const float quadVertices[] = {
        -1, -1, 0, 1,
        1, -1, 0, 1,
        -1, 1, 0, 1,
        1, 1, 0, 1,
    };
    Buffer quadBuffer = createBuffer(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW);
    ASSERT_GL();

    Program initProgram(glCreateProgram());
    compileProgram(initProgram.get(), initVertShader, initFragShader, {"position"});
    ASSERT_GL();

    glUseProgram(initProgram.get());
    glBindBuffer(GL_ARRAY_BUFFER, quadBuffer.get());
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(0);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    glUseProgram(0);
/*
    GLuint init
    glGenFramebuffers(1, &m_fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, preview->m_fbo);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                           GL_TEXTURE_2D, preview->m_texture, 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
*/
    //glClearColor(1, .5, 0, 1);
    //glClear(GL_COLOR_BUFFER_BIT);

    glPixelStorei(GL_PACK_ROW_LENGTH, image.width);
    glReadPixels(xOffset, yOffset, width, height, GL_BGRA, GL_UNSIGNED_BYTE, image.pixels.get());
    glPixelStorei(GL_PACK_ROW_LENGTH, 0);

#if 0
    const Camera& camera = m_scene->camera;

    const glm::vec4 viewport(0, 0, 1, 1);
    glm::vec3 p1 = glm::unProject(glm::vec3(0.f, 0.f, 0.f), camera.transform, camera.projection, viewport);
    glm::vec3 p2 = glm::unProject(glm::vec3(1.f, 0.f, 0.f), camera.transform, camera.projection, viewport);
    glm::vec3 p3 = glm::unProject(glm::vec3(0.f, 1.f, 0.f), camera.transform, camera.projection, viewport);
    glm::vec3 origin(glm::inverse(camera.transform) * glm::vec4(0.f, 0.f, 0.f, 1.f));

    std::unique_ptr<glm::vec4[]> radianceMap(new glm::vec4[width * height]);

    int samples = 1;
    for (int pass = 1;; pass++)
    {
        if (m_observer && !m_observer(pass, samples, xOffset, yOffset, width, height))
            return;
    }
#endif
}

}
<|endoftext|>


<commit_before>#include "xchainer/routines/connection.h"

#include <cstdint>
#include <vector>

#include <nonstd/optional.hpp>

#include "xchainer/array.h"
#include "xchainer/constant.h"
#include "xchainer/device.h"
#include "xchainer/error.h"
#include "xchainer/routines/math.h"
#include "xchainer/stack_vector.h"

namespace xchainer {
namespace internal {

int64_t GetConvOutDim(int64_t in_dim, int64_t kernel_size, int64_t stride, int64_t pad, bool cover_all) {
    if (cover_all) {
        return (in_dim + pad * 2 - kernel_size + stride - 1) / stride + 1;
    }
    return (in_dim + pad * 2 - kernel_size) / stride + 1;
}

int64_t GetConvTransposeOutDim(int64_t in_dim, int64_t kernel_size, int64_t stride, int64_t pad, bool cover_all) {
    if (cover_all) {
        return stride * (in_dim - 1) + kernel_size - stride + 1 - 2 * pad;
    }
    return stride * (in_dim - 1) + kernel_size - 2 * pad;
}

}  // namespace internal

namespace {

Array ConvGradW(
        Dtype w_dtype,
        const Shape& w_shape,
        const Array& x,
        const Array& gy,
        const StackVector<int64_t, kMaxNdim>& stride,
        const StackVector<int64_t, kMaxNdim>& pad,
        bool cover_all) {
    assert(w_shape.ndim() > 2);
    assert(x.ndim() == w_shape.ndim());
    assert(gy.ndim() == w_shape.ndim());
    assert(stride.size() == static_cast<size_t>(w_shape.ndim() - 2));
    assert(pad.size() == static_cast<size_t>(w_shape.ndim() - 2));
    Array out = x.device().ConvGradWeight(w_dtype, w_shape, x, gy, stride, pad, cover_all);

    auto x_backward_function =
            [ x_shape = x.shape(), gy, stride, pad ](const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient)->Array {
        StackVector<int64_t, kMaxNdim> out_size{x_shape.begin() + 2, x_shape.end()};
        assert(out_size.size() == stride.size());
        return ConvTranspose(gy.AsConstant(graph_ids_to_stop_gradient), gout, nonstd::nullopt, stride, pad, out_size);
    };
    auto gy_backward_function = [x, stride, pad, cover_all](
                                        const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient) -> Array {
        return Conv(x.AsConstant(graph_ids_to_stop_gradient), gout, nonstd::nullopt, stride, pad, cover_all);
    };
    internal::SetUpOpNodes("conv-grad-weight", {x, gy}, out, {x_backward_function, gy_backward_function});

    return out;
}

void ConvCheckNdim(
        const Array& x, const Array& w, const StackVector<int64_t, kMaxNdim>& stride, const StackVector<int64_t, kMaxNdim>& pad) {
    if (w.ndim() != x.ndim()) {
        throw DimensionError{"Mismatched number of dimensions between input ", x.ndim(), " and weights ", w.ndim(), "."};
    }
    int8_t ndim = x.ndim() - 2;  // Number of spacial dimensions
    if (ndim < 0) {
        throw DimensionError{"Number of spacial dimensions must be greater than or equal to 0"};
    }
    if (static_cast<int8_t>(stride.size()) != ndim) {
        throw DimensionError{"Wrong numbers of strides ", stride.size(), " for input with ", x.ndim(), " dimensions."};
    }
    if (static_cast<int8_t>(pad.size()) != ndim) {
        throw DimensionError{"Wrong numbers of paddings ", pad.size(), " for input with ", x.ndim(), " dimensions."};
    }
}

}  // namespace

Array Conv(
        const Array& x,
        const Array& w,
        const nonstd::optional<Array>& b,
        const StackVector<int64_t, kMaxNdim>& stride,
        const StackVector<int64_t, kMaxNdim>& pad,
        bool cover_all) {
    ConvCheckNdim(x, w, stride, pad);
    if (w.shape()[1] != x.shape()[1]) {
        throw DimensionError{"Mismatched number of input channels in input ", x.shape(), " and weights ", w.shape(), "."};
    }
    if (b.has_value() && (b->ndim() != 1 || b->shape()[0] != w.shape()[0])) {
        throw DimensionError{"Mismatched bias shape ", b->shape(), " for weights ", w.shape(), "."};
    }

    Array out = x.device().Conv(x, w, b, stride, pad, cover_all);
    auto x_backward_function =
            [ x_shape = x.shape(), w, stride, pad ](const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient)->Array {
        StackVector<int64_t, kMaxNdim> out_size{x_shape.begin() + 2, x_shape.end()};
        return ConvTranspose(gout, w.AsConstant(graph_ids_to_stop_gradient), nonstd::nullopt, stride, pad, out_size);
    };
    auto w_backward_function = [ w_dtype = w.dtype(), w_shape = w.shape(), x, stride, pad, cover_all ](
                                       const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient)
                                       ->Array {
        return ConvGradW(w_dtype, w_shape, x.AsConstant(graph_ids_to_stop_gradient), gout, stride, pad, cover_all);
    };
    if (b.has_value()) {
        auto b_backward_function = [](const Array& gout, const std::vector<GraphId>&) -> Array {
            Axes axis{0};
            for (int8_t i = 2; i < gout.ndim(); ++i) {
                axis.emplace_back(int64_t{i});
            }
            return Sum(gout, axis, false);
        };
        internal::SetUpOpNodes("conv", {x, w, *b}, out, {x_backward_function, w_backward_function, b_backward_function});
    } else {
        internal::SetUpOpNodes("conv", {x, w}, out, {x_backward_function, w_backward_function});
    }
    return out;
}

Array ConvTranspose(
        const Array& x,
        const Array& w,
        const nonstd::optional<Array>& b,
        const StackVector<int64_t, kMaxNdim>& stride,
        const StackVector<int64_t, kMaxNdim>& pad,
        const nonstd::optional<StackVector<int64_t, kMaxNdim>>& out_size) {
    ConvCheckNdim(x, w, stride, pad);
    if (x.shape()[1] != w.shape()[0]) {
        throw DimensionError{"Mismatched number of input channels in input ", x.shape(), " and weights ", w.shape(), "."};
    }
    if (b.has_value() && (b->ndim() != 1 || b->shape()[0] != w.shape()[1])) {
        throw DimensionError{"Mismatched bias shape ", b->shape(), " for weights ", w.shape(), "."};
    }
    int8_t ndim = x.ndim() - 2;  // Number of spacial dimensions
    Shape in_dims{x.shape().begin() + 2, x.shape().end()};
    Shape kernel_size{w.shape().begin() + 2, w.shape().end()};

    bool cover_all = false;
    bool cover_all_determined = false;

    // Compute out_size if not specified
    StackVector<int64_t, kMaxNdim> real_out_size;
    if (out_size.has_value()) {
        real_out_size = *out_size;
    } else {
        cover_all_determined = true;
        for (int8_t i = 0; i < ndim; ++i) {
            real_out_size.emplace_back(internal::GetConvTransposeOutDim(in_dims[i], kernel_size[i], stride[i], pad[i], cover_all));
            std::cout << internal::GetConvTransposeOutDim(in_dims[i], kernel_size[i], stride[i], pad[i], cover_all) << std::endl;
        }
    }
    for (int64_t size : real_out_size) {
        if (size < 0) {
            throw DimensionError{"All output sizes must be positive"};
        }
    }

    // Compute transposed convolution
    Array out = x.device().ConvTranspose(x, w, b, stride, pad, real_out_size);

    // Detect cover_all
    // TODO(niboshi): This logic is only required if x belongs to some graph.
    if (!cover_all_determined) {
        for (int8_t i = 0; i < ndim; ++i) {
            if (in_dims[i] != internal::GetConvOutDim(real_out_size[i], kernel_size[i], stride[i], pad[i], false)) {
                cover_all = true;
                break;
            }
        }
        cover_all_determined = true;

        // Check detected cover_all is consistent
        for (int8_t i = 0; i < ndim; ++i) {
            if (in_dims[i] != internal::GetConvOutDim(real_out_size[i], kernel_size[i], stride[i], pad[i], cover_all)) {
                throw DimensionError{"Output dims ", Shape{real_out_size.begin(), real_out_size.end()}, " are inconsistent."};
            }
        }
    }

    auto x_backward_function =
            [ x_shape = x.shape(), w, stride, pad, cover_all ](const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient)
                    ->Array {
        return Conv(gout, w.AsConstant(graph_ids_to_stop_gradient), nonstd::nullopt, stride, pad, cover_all);
    };
    auto w_backward_function = [ w_dtype = w.dtype(), w_shape = w.shape(), x, stride, pad, cover_all ](
                                       const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient)
                                       ->Array {
        return ConvGradW(w_dtype, w_shape, gout, x.AsConstant(graph_ids_to_stop_gradient), stride, pad, cover_all);
    };
    if (b.has_value()) {
        auto b_backward_function = [](const Array& gout, const std::vector<GraphId>&) -> Array {
            Axes axis{0};
            for (int8_t i = 2; i < gout.ndim(); ++i) {
                axis.emplace_back(int64_t{i});
            }
            return Sum(gout, axis, false);
        };
        internal::SetUpOpNodes("conv_transpose", {x, w, *b}, out, {x_backward_function, w_backward_function, b_backward_function});
    } else {
        internal::SetUpOpNodes("conv_transpose", {x, w}, out, {x_backward_function, w_backward_function});
    }
    return out;
}

}  // namespace xchainer
<commit_msg>remove debug print<commit_after>#include "xchainer/routines/connection.h"

#include <cstdint>
#include <vector>

#include <nonstd/optional.hpp>

#include "xchainer/array.h"
#include "xchainer/constant.h"
#include "xchainer/device.h"
#include "xchainer/error.h"
#include "xchainer/routines/math.h"
#include "xchainer/stack_vector.h"

namespace xchainer {
namespace internal {

int64_t GetConvOutDim(int64_t in_dim, int64_t kernel_size, int64_t stride, int64_t pad, bool cover_all) {
    if (cover_all) {
        return (in_dim + pad * 2 - kernel_size + stride - 1) / stride + 1;
    }
    return (in_dim + pad * 2 - kernel_size) / stride + 1;
}

int64_t GetConvTransposeOutDim(int64_t in_dim, int64_t kernel_size, int64_t stride, int64_t pad, bool cover_all) {
    if (cover_all) {
        return stride * (in_dim - 1) + kernel_size - stride + 1 - 2 * pad;
    }
    return stride * (in_dim - 1) + kernel_size - 2 * pad;
}

}  // namespace internal

namespace {

Array ConvGradW(
        Dtype w_dtype,
        const Shape& w_shape,
        const Array& x,
        const Array& gy,
        const StackVector<int64_t, kMaxNdim>& stride,
        const StackVector<int64_t, kMaxNdim>& pad,
        bool cover_all) {
    assert(w_shape.ndim() > 2);
    assert(x.ndim() == w_shape.ndim());
    assert(gy.ndim() == w_shape.ndim());
    assert(stride.size() == static_cast<size_t>(w_shape.ndim() - 2));
    assert(pad.size() == static_cast<size_t>(w_shape.ndim() - 2));
    Array out = x.device().ConvGradWeight(w_dtype, w_shape, x, gy, stride, pad, cover_all);

    auto x_backward_function =
            [ x_shape = x.shape(), gy, stride, pad ](const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient)->Array {
        StackVector<int64_t, kMaxNdim> out_size{x_shape.begin() + 2, x_shape.end()};
        assert(out_size.size() == stride.size());
        return ConvTranspose(gy.AsConstant(graph_ids_to_stop_gradient), gout, nonstd::nullopt, stride, pad, out_size);
    };
    auto gy_backward_function = [x, stride, pad, cover_all](
                                        const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient) -> Array {
        return Conv(x.AsConstant(graph_ids_to_stop_gradient), gout, nonstd::nullopt, stride, pad, cover_all);
    };
    internal::SetUpOpNodes("conv-grad-weight", {x, gy}, out, {x_backward_function, gy_backward_function});

    return out;
}

void ConvCheckNdim(
        const Array& x, const Array& w, const StackVector<int64_t, kMaxNdim>& stride, const StackVector<int64_t, kMaxNdim>& pad) {
    if (w.ndim() != x.ndim()) {
        throw DimensionError{"Mismatched number of dimensions between input ", x.ndim(), " and weights ", w.ndim(), "."};
    }
    int8_t ndim = x.ndim() - 2;  // Number of spacial dimensions
    if (ndim < 0) {
        throw DimensionError{"Number of spacial dimensions must be greater than or equal to 0"};
    }
    if (static_cast<int8_t>(stride.size()) != ndim) {
        throw DimensionError{"Wrong numbers of strides ", stride.size(), " for input with ", x.ndim(), " dimensions."};
    }
    if (static_cast<int8_t>(pad.size()) != ndim) {
        throw DimensionError{"Wrong numbers of paddings ", pad.size(), " for input with ", x.ndim(), " dimensions."};
    }
}

}  // namespace

Array Conv(
        const Array& x,
        const Array& w,
        const nonstd::optional<Array>& b,
        const StackVector<int64_t, kMaxNdim>& stride,
        const StackVector<int64_t, kMaxNdim>& pad,
        bool cover_all) {
    ConvCheckNdim(x, w, stride, pad);
    if (w.shape()[1] != x.shape()[1]) {
        throw DimensionError{"Mismatched number of input channels in input ", x.shape(), " and weights ", w.shape(), "."};
    }
    if (b.has_value() && (b->ndim() != 1 || b->shape()[0] != w.shape()[0])) {
        throw DimensionError{"Mismatched bias shape ", b->shape(), " for weights ", w.shape(), "."};
    }

    Array out = x.device().Conv(x, w, b, stride, pad, cover_all);
    auto x_backward_function =
            [ x_shape = x.shape(), w, stride, pad ](const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient)->Array {
        StackVector<int64_t, kMaxNdim> out_size{x_shape.begin() + 2, x_shape.end()};
        return ConvTranspose(gout, w.AsConstant(graph_ids_to_stop_gradient), nonstd::nullopt, stride, pad, out_size);
    };
    auto w_backward_function = [ w_dtype = w.dtype(), w_shape = w.shape(), x, stride, pad, cover_all ](
                                       const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient)
                                       ->Array {
        return ConvGradW(w_dtype, w_shape, x.AsConstant(graph_ids_to_stop_gradient), gout, stride, pad, cover_all);
    };
    if (b.has_value()) {
        auto b_backward_function = [](const Array& gout, const std::vector<GraphId>&) -> Array {
            Axes axis{0};
            for (int8_t i = 2; i < gout.ndim(); ++i) {
                axis.emplace_back(int64_t{i});
            }
            return Sum(gout, axis, false);
        };
        internal::SetUpOpNodes("conv", {x, w, *b}, out, {x_backward_function, w_backward_function, b_backward_function});
    } else {
        internal::SetUpOpNodes("conv", {x, w}, out, {x_backward_function, w_backward_function});
    }
    return out;
}

Array ConvTranspose(
        const Array& x,
        const Array& w,
        const nonstd::optional<Array>& b,
        const StackVector<int64_t, kMaxNdim>& stride,
        const StackVector<int64_t, kMaxNdim>& pad,
        const nonstd::optional<StackVector<int64_t, kMaxNdim>>& out_size) {
    ConvCheckNdim(x, w, stride, pad);
    if (x.shape()[1] != w.shape()[0]) {
        throw DimensionError{"Mismatched number of input channels in input ", x.shape(), " and weights ", w.shape(), "."};
    }
    if (b.has_value() && (b->ndim() != 1 || b->shape()[0] != w.shape()[1])) {
        throw DimensionError{"Mismatched bias shape ", b->shape(), " for weights ", w.shape(), "."};
    }
    int8_t ndim = x.ndim() - 2;  // Number of spacial dimensions
    Shape in_dims{x.shape().begin() + 2, x.shape().end()};
    Shape kernel_size{w.shape().begin() + 2, w.shape().end()};

    bool cover_all = false;
    bool cover_all_determined = false;

    // Compute out_size if not specified
    StackVector<int64_t, kMaxNdim> real_out_size;
    if (out_size.has_value()) {
        real_out_size = *out_size;
    } else {
        cover_all_determined = true;
        for (int8_t i = 0; i < ndim; ++i) {
            real_out_size.emplace_back(internal::GetConvTransposeOutDim(in_dims[i], kernel_size[i], stride[i], pad[i], cover_all));
        }
    }
    for (int64_t size : real_out_size) {
        if (size < 0) {
            throw DimensionError{"All output sizes must be positive"};
        }
    }

    // Compute transposed convolution
    Array out = x.device().ConvTranspose(x, w, b, stride, pad, real_out_size);

    // Detect cover_all
    // TODO(niboshi): This logic is only required if x belongs to some graph.
    if (!cover_all_determined) {
        for (int8_t i = 0; i < ndim; ++i) {
            if (in_dims[i] != internal::GetConvOutDim(real_out_size[i], kernel_size[i], stride[i], pad[i], false)) {
                cover_all = true;
                break;
            }
        }
        cover_all_determined = true;

        // Check detected cover_all is consistent
        for (int8_t i = 0; i < ndim; ++i) {
            if (in_dims[i] != internal::GetConvOutDim(real_out_size[i], kernel_size[i], stride[i], pad[i], cover_all)) {
                throw DimensionError{"Output dims ", Shape{real_out_size.begin(), real_out_size.end()}, " are inconsistent."};
            }
        }
    }

    auto x_backward_function =
            [ x_shape = x.shape(), w, stride, pad, cover_all ](const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient)
                    ->Array {
        return Conv(gout, w.AsConstant(graph_ids_to_stop_gradient), nonstd::nullopt, stride, pad, cover_all);
    };
    auto w_backward_function = [ w_dtype = w.dtype(), w_shape = w.shape(), x, stride, pad, cover_all ](
                                       const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient)
                                       ->Array {
        return ConvGradW(w_dtype, w_shape, gout, x.AsConstant(graph_ids_to_stop_gradient), stride, pad, cover_all);
    };
    if (b.has_value()) {
        auto b_backward_function = [](const Array& gout, const std::vector<GraphId>&) -> Array {
            Axes axis{0};
            for (int8_t i = 2; i < gout.ndim(); ++i) {
                axis.emplace_back(int64_t{i});
            }
            return Sum(gout, axis, false);
        };
        internal::SetUpOpNodes("conv_transpose", {x, w, *b}, out, {x_backward_function, w_backward_function, b_backward_function});
    } else {
        internal::SetUpOpNodes("conv_transpose", {x, w}, out, {x_backward_function, w_backward_function});
    }
    return out;
}

}  // namespace xchainer
<|endoftext|>


<commit_before>#define _IRR_STATIC_LIB_
#include <irrlicht.h>
#include "../source/Irrlicht/COpenGLExtensionHandler.h"

#include "../source/Irrlicht/CGeometryCreator.h"
#include "../source/Irrlicht/CBAWMeshWriter.h"
#include <SVertexManipulator.h>

using namespace irr;
using namespace core;

bool quit = false;
//!Same As Last Example
class MyEventReceiver : public IEventReceiver
{
public:

	MyEventReceiver()
	{
	}

	bool OnEvent(const SEvent& event)
	{
        if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown)
        {
            switch (event.KeyInput.Key)
            {
            case irr::KEY_KEY_Q: // switch wire frame mode
                quit = true;
                return true;
            default:
                break;
            }
        }

		return false;
	}

private:
};

class SimpleCallBack : public video::IShaderConstantSetCallBack
{
    int32_t mvpUniformLocation;
    int32_t cameraDirUniformLocation;
    int32_t texUniformLocation[4];
    video::E_SHADER_CONSTANT_TYPE mvpUniformType;
    video::E_SHADER_CONSTANT_TYPE cameraDirUniformType;
    video::E_SHADER_CONSTANT_TYPE texUniformType[4];
public:
    SimpleCallBack() : cameraDirUniformLocation(-1), cameraDirUniformType(video::ESCT_FLOAT_VEC3) {}

    virtual void PostLink(video::IMaterialRendererServices* services, const video::E_MATERIAL_TYPE& materialType, const core::vector<video::SConstantLocationNamePair>& constants)
    {
        for (size_t i=0; i<constants.size(); i++)
        {
            if (constants[i].name=="MVP")
            {
                mvpUniformLocation = constants[i].location;
                mvpUniformType = constants[i].type;
            }
            else if (constants[i].name=="cameraPos")
            {
                cameraDirUniformLocation = constants[i].location;
                cameraDirUniformType = constants[i].type;
            }
        }
    }

    virtual void OnSetConstants(video::IMaterialRendererServices* services, int32_t userData)
    {
        core::vectorSIMDf modelSpaceCamPos;
        modelSpaceCamPos.set(services->getVideoDriver()->getTransform(video::E4X3TS_WORLD_VIEW_INVERSE).getTranslation());
        services->setShaderConstant(&modelSpaceCamPos,cameraDirUniformLocation,cameraDirUniformType,1);
        services->setShaderConstant(services->getVideoDriver()->getTransform(video::EPTS_PROJ_VIEW_WORLD).pointer(),mvpUniformLocation,mvpUniformType,1);
    }

    virtual void OnUnsetMaterial() {}
};

int main()
{
    srand(time(0));
	// create device with full flexibility over creation parameters
	// you can add more parameters if desired, check irr::SIrrlichtCreationParameters
	irr::SIrrlichtCreationParameters params;
	params.Bits = 24; //may have to set to 32bit for some platforms
	params.ZBufferBits = 24; //we'd like 32bit here
	params.DriverType = video::EDT_OPENGL; //! Only Well functioning driver, software renderer left for sake of 2D image drawing
	params.WindowSize = dimension2d<uint32_t>(1280, 720);
	params.Fullscreen = false;
	params.Vsync = true; //! If supported by target platform
	params.Doublebuffer = true;
	params.Stencilbuffer = false; //! This will not even be a choice soon
	IrrlichtDevice* device = createDeviceEx(params);

	if (device == 0)
		return 1; // could not create selected driver.

	video::IVideoDriver* driver = device->getVideoDriver();

    SimpleCallBack* cb = new SimpleCallBack();
    video::E_MATERIAL_TYPE newMaterialType = (video::E_MATERIAL_TYPE)driver->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles("../mesh.vert",
                                                        "","","", //! No Geometry or Tessellation Shaders
                                                        "../mesh.frag",
                                                        3,video::EMT_SOLID, //! 3 vertices per primitive (this is tessellation shader relevant only
                                                        cb, //! Our Shader Callback
                                                        0); //! No custom user data
    cb->drop();

	scene::ISceneManager* smgr = device->getSceneManager();
	driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);
	scene::ICameraSceneNode* camera =
		smgr->addCameraSceneNodeFPS(0,100.0f,0.01f);
	camera->setPosition(core::vector3df(-4,0,0));
	camera->setTarget(core::vector3df(0,0,0));
	camera->setNearValue(0.01f);
	camera->setFarValue(100.0f);
    smgr->setActiveCamera(camera);
	device->getCursorControl()->setVisible(false);
	MyEventReceiver receiver;
	device->setEventReceiver(&receiver);

	io::IFileSystem* fs = device->getFileSystem();

	// from Criss:
	// here i'm testing baw mesh writer and loader
	// (import from .stl/.obj, then export to .baw, then import from .baw :D)
	// Seems to work for those two simple meshes, but need more testing!

    asset::IAssetManager& am = device->getAssetManager();

	//! Test Loading of Obj
    asset::IAssetLoader::SAssetLoadParams lparams;
    scene::ICPUMesh* cpumesh = static_cast<scene::ICPUMesh*>(device->getAssetManager().getAsset("../../media/extrusionLogo_TEST_fixed.stl", lparams));
	// export mesh
    scene::CBAWMeshWriter::WriteProperties bawprops;
    asset::IAssetWriter::SAssetWriteParams wparams(cpumesh, asset::EWF_COMPRESSED, 0.f, 0, nullptr, &bawprops);
    device->getAssetManager().writeAsset("extrusionLogo_TEST_fixed.baw", wparams);
	// end export

	// import .baw mesh (test)
    cpumesh = static_cast<scene::ICPUMesh*>(device->getAssetManager().getAsset("extrusionLogo_TEST_fixed.baw", lparams));
	// end import

    if (cpumesh)
    {
        scene::IGPUMesh* gpumesh = driver->getGPUObjectsFromAssets(&cpumesh, (&cpumesh)+1)[0];
        smgr->getMeshCache()->removeMesh(cpumesh);
        smgr->addMeshSceneNode(gpumesh)->setMaterialType(newMaterialType);
        gpumesh->drop();
    }

    cpumesh = static_cast<scene::ICPUMesh*>(device->getAssetManager().getAsset("../../media/cow.obj", lparams));
	// export mesh
    wparams.rootAsset = cpumesh;
    device->getAssetManager().writeAsset("cow.baw", wparams);
	// end export

	// import .baw mesh (test)
	cpumesh = static_cast<scene::ICPUMesh*>(device->getAssetManager().getAsset("cow.baw", lparams));
	// end import

    if (cpumesh)
    {
        scene::IGPUMesh* gpumesh = driver->getGPUObjectsFromAssets(&cpumesh, (&cpumesh)+1)[0];
        smgr->getMeshCache()->removeMesh(cpumesh);
        smgr->addMeshSceneNode(gpumesh,0,-1,core::vector3df(3.f,1.f,0.f))->setMaterialType(newMaterialType);
        gpumesh->drop();
    }

	uint64_t lastFPSTime = 0;

	while(!quit && device->run())
	//if (device->isWindowActive())
	{
		driver->beginScene(true, true, video::SColor(255,0,0,255) );

        //! This animates (moves) the camera and sets the transforms
        //! Also draws the meshbuffer
        smgr->drawAll();

		driver->endScene();

		// display frames per second in window title
		uint64_t time = device->getTimer()->getRealTime();
		if (time-lastFPSTime > 1000)
		{
			std::wostringstream sstr;
			sstr << L"Builtin Nodes Demo - Irrlicht Engine FPS:" << driver->getFPS() << " PrimitvesDrawn:" << driver->getPrimitiveCountDrawn();

			device->setWindowCaption(sstr.str().c_str());
			lastFPSTime = time;
		}
	}

    //create a screenshot
	video::IImage* screenshot = driver->createImage(video::EF_B8G8R8A8_UNORM,params.WindowSize);
    glReadPixels(0,0, params.WindowSize.Width,params.WindowSize.Height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, screenshot->getData());
    video::CImageData* img = new video::CImageData(screenshot);
    screenshot->drop();
	//driver->writeImageToFile(screenshot,"./screenshot.png");
    wparams.rootAsset = img;
    wparams.userData = nullptr;
    device->getAssetManager().writeAsset("screenshot.png", wparams);
    img->drop();
	device->sleep(3000);

	device->drop();

	return 0;
}
<commit_msg>Updated meshloaders example once more<commit_after>#define _IRR_STATIC_LIB_
#include <irrlicht.h>
#include "../source/Irrlicht/COpenGLExtensionHandler.h"

#include "../source/Irrlicht/CGeometryCreator.h"
#include "../source/Irrlicht/CBAWMeshWriter.h"
#include <SVertexManipulator.h>

using namespace irr;
using namespace core;

bool quit = false;
//!Same As Last Example
class MyEventReceiver : public IEventReceiver
{
public:

	MyEventReceiver()
	{
	}

	bool OnEvent(const SEvent& event)
	{
        if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown)
        {
            switch (event.KeyInput.Key)
            {
            case irr::KEY_KEY_Q: // switch wire frame mode
                quit = true;
                return true;
            default:
                break;
            }
        }

		return false;
	}

private:
};

class SimpleCallBack : public video::IShaderConstantSetCallBack
{
    int32_t mvpUniformLocation;
    int32_t cameraDirUniformLocation;
    int32_t texUniformLocation[4];
    video::E_SHADER_CONSTANT_TYPE mvpUniformType;
    video::E_SHADER_CONSTANT_TYPE cameraDirUniformType;
    video::E_SHADER_CONSTANT_TYPE texUniformType[4];
public:
    SimpleCallBack() : cameraDirUniformLocation(-1), cameraDirUniformType(video::ESCT_FLOAT_VEC3) {}

    virtual void PostLink(video::IMaterialRendererServices* services, const video::E_MATERIAL_TYPE& materialType, const core::vector<video::SConstantLocationNamePair>& constants)
    {
        for (size_t i=0; i<constants.size(); i++)
        {
            if (constants[i].name=="MVP")
            {
                mvpUniformLocation = constants[i].location;
                mvpUniformType = constants[i].type;
            }
            else if (constants[i].name=="cameraPos")
            {
                cameraDirUniformLocation = constants[i].location;
                cameraDirUniformType = constants[i].type;
            }
        }
    }

    virtual void OnSetConstants(video::IMaterialRendererServices* services, int32_t userData)
    {
        core::vectorSIMDf modelSpaceCamPos;
        modelSpaceCamPos.set(services->getVideoDriver()->getTransform(video::E4X3TS_WORLD_VIEW_INVERSE).getTranslation());
        services->setShaderConstant(&modelSpaceCamPos,cameraDirUniformLocation,cameraDirUniformType,1);
        services->setShaderConstant(services->getVideoDriver()->getTransform(video::EPTS_PROJ_VIEW_WORLD).pointer(),mvpUniformLocation,mvpUniformType,1);
    }

    virtual void OnUnsetMaterial() {}
};

int main()
{
    srand(time(0));
	// create device with full flexibility over creation parameters
	// you can add more parameters if desired, check irr::SIrrlichtCreationParameters
	irr::SIrrlichtCreationParameters params;
	params.Bits = 24; //may have to set to 32bit for some platforms
	params.ZBufferBits = 24; //we'd like 32bit here
	params.DriverType = video::EDT_OPENGL; //! Only Well functioning driver, software renderer left for sake of 2D image drawing
	params.WindowSize = dimension2d<uint32_t>(1280, 720);
	params.Fullscreen = false;
	params.Vsync = true; //! If supported by target platform
	params.Doublebuffer = true;
	params.Stencilbuffer = false; //! This will not even be a choice soon
	IrrlichtDevice* device = createDeviceEx(params);

	if (device == 0)
		return 1; // could not create selected driver.

	video::IVideoDriver* driver = device->getVideoDriver();

    SimpleCallBack* cb = new SimpleCallBack();
    video::E_MATERIAL_TYPE newMaterialType = (video::E_MATERIAL_TYPE)driver->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles("../mesh.vert",
                                                        "","","", //! No Geometry or Tessellation Shaders
                                                        "../mesh.frag",
                                                        3,video::EMT_SOLID, //! 3 vertices per primitive (this is tessellation shader relevant only
                                                        cb, //! Our Shader Callback
                                                        0); //! No custom user data
    cb->drop();

	scene::ISceneManager* smgr = device->getSceneManager();
	driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);
	scene::ICameraSceneNode* camera =
		smgr->addCameraSceneNodeFPS(0,100.0f,0.01f);
	camera->setPosition(core::vector3df(-4,0,0));
	camera->setTarget(core::vector3df(0,0,0));
	camera->setNearValue(0.01f);
	camera->setFarValue(100.0f);
    smgr->setActiveCamera(camera);
	device->getCursorControl()->setVisible(false);
	MyEventReceiver receiver;
	device->setEventReceiver(&receiver);

	io::IFileSystem* fs = device->getFileSystem();

	// from Criss:
	// here i'm testing baw mesh writer and loader
	// (import from .stl/.obj, then export to .baw, then import from .baw :D)
	// Seems to work for those two simple meshes, but need more testing!

    asset::IAssetManager& am = device->getAssetManager();

	//! Test Loading of Obj
    asset::IAssetLoader::SAssetLoadParams lparams;
    asset::ICPUMesh* cpumesh = static_cast<asset::ICPUMesh*>(device->getAssetManager().getAsset("../../media/extrusionLogo_TEST_fixed.stl", lparams));
	// export mesh
    scene::CBAWMeshWriter::WriteProperties bawprops;
    asset::IAssetWriter::SAssetWriteParams wparams(cpumesh, asset::EWF_COMPRESSED, 0.f, 0, nullptr, &bawprops);
    device->getAssetManager().writeAsset("extrusionLogo_TEST_fixed.baw", wparams);
	// end export

	// import .baw mesh (test)
    cpumesh = static_cast<asset::ICPUMesh*>(device->getAssetManager().getAsset("extrusionLogo_TEST_fixed.baw", lparams));
	// end import

    if (cpumesh)
    {
        scene::IGPUMesh* gpumesh = driver->getGPUObjectsFromAssets(&cpumesh, (&cpumesh)+1)[0];
        smgr->getMeshCache()->removeMesh(cpumesh);
        smgr->addMeshSceneNode(gpumesh)->setMaterialType(newMaterialType);
        gpumesh->drop();
    }

    cpumesh = static_cast<asset::ICPUMesh*>(device->getAssetManager().getAsset("../../media/cow.obj", lparams));
	// export mesh
    wparams.rootAsset = cpumesh;
    device->getAssetManager().writeAsset("cow.baw", wparams);
	// end export

	// import .baw mesh (test)
	cpumesh = static_cast<asset::ICPUMesh*>(device->getAssetManager().getAsset("cow.baw", lparams));
	// end import

    if (cpumesh)
    {
        scene::IGPUMesh* gpumesh = driver->getGPUObjectsFromAssets(&cpumesh, (&cpumesh)+1)[0];
        smgr->getMeshCache()->removeMesh(cpumesh);
        smgr->addMeshSceneNode(gpumesh,0,-1,core::vector3df(3.f,1.f,0.f))->setMaterialType(newMaterialType);
        gpumesh->drop();
    }

	uint64_t lastFPSTime = 0;

	while(!quit && device->run())
	//if (device->isWindowActive())
	{
		driver->beginScene(true, true, video::SColor(255,0,0,255) );

        //! This animates (moves) the camera and sets the transforms
        //! Also draws the meshbuffer
        smgr->drawAll();

		driver->endScene();

		// display frames per second in window title
		uint64_t time = device->getTimer()->getRealTime();
		if (time-lastFPSTime > 1000)
		{
			std::wostringstream sstr;
			sstr << L"Builtin Nodes Demo - Irrlicht Engine FPS:" << driver->getFPS() << " PrimitvesDrawn:" << driver->getPrimitiveCountDrawn();

			device->setWindowCaption(sstr.str().c_str());
			lastFPSTime = time;
		}
	}

    //create a screenshot
	video::IImage* screenshot = driver->createImage(video::EF_B8G8R8A8_UNORM,params.WindowSize);
    glReadPixels(0,0, params.WindowSize.Width,params.WindowSize.Height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, screenshot->getData());
    video::CImageData* img = new video::CImageData(screenshot);
    screenshot->drop();
	//driver->writeImageToFile(screenshot,"./screenshot.png");
    wparams.rootAsset = img;
    wparams.userData = nullptr;
    device->getAssetManager().writeAsset("screenshot.png", wparams);
    img->drop();
	device->sleep(3000);

	device->drop();

	return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: AViews.cxx,v $
 *
 *  $Revision: 1.16 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 02:16:55 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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 library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"
#ifndef _CONNECTIVITY_ADO_VIEWS_HXX_
#include "ado/AViews.hxx"
#endif
#ifndef _CONNECTIVITY_ADO_VIEW_HXX_
#include "ado/AView.hxx"
#endif
#ifndef _CONNECTIVITY_ADO_TABLES_HXX_
#include "ado/ATables.hxx"
#endif
#ifndef _CONNECTIVITY_ADO_CATALOG_HXX_
#include "ado/ACatalog.hxx"
#endif
#ifndef _CONNECTIVITY_ADO_BCONNECTION_HXX_
#include "ado/AConnection.hxx"
#endif
#ifndef _CONNECTIVITY_ADO_AWRAPADO_HXX_
#include "ado/Awrapado.hxx"
#endif
#ifndef CONNECTIVITY_CONNECTION_HXX
#include "TConnection.hxx"
#endif
#ifndef _COMPHELPER_TYPES_HXX_
#include <comphelper/types.hxx>
#endif
#ifndef _DBHELPER_DBEXCEPTION_HXX_
#include <connectivity/dbexception.hxx>
#endif

using namespace ::comphelper;

using namespace connectivity;
using namespace connectivity::ado;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::beans;
using namespace com::sun::star::sdbc;
using namespace com::sun::star::container;

sdbcx::ObjectType OViews::createObject(const ::rtl::OUString& _rName)
{
    OAdoView* pView = new OAdoView(isCaseSensitive(),m_aCollection.GetItem(_rName));
    pView->setNew(sal_False);
    return pView;
}
// -------------------------------------------------------------------------
void OViews::impl_refresh(  ) throw(RuntimeException)
{
    m_aCollection.Refresh();
}
// -------------------------------------------------------------------------
Reference< XPropertySet > OViews::createDescriptor()
{
    return new OAdoView(isCaseSensitive());
}

// -------------------------------------------------------------------------
// XAppend
sdbcx::ObjectType OViews::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor )
{
    OAdoView* pView = NULL;
    if ( !getImplementation( pView, descriptor ) || pView == NULL )
        ::dbtools::throwGenericSQLException(
            ::rtl::OUString::createFromAscii( "Could not create view: invalid object descriptor." ),
            static_cast<XTypeProvider*>(this)
        );

    WpADOCommand aCommand;
    aCommand.Create();
    if ( !aCommand.IsValid() )
        ::dbtools::throwGenericSQLException(
            ::rtl::OUString::createFromAscii( "Could not create view: no command object." ),
            static_cast<XTypeProvider*>(this)
        );

    ::rtl::OUString sName( _rForName );
    aCommand.put_Name(sName);
    aCommand.put_CommandText(getString(descriptor->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_COMMAND))));
    ADOViews* pViews = (ADOViews*)m_aCollection;
    if(FAILED(pViews->Append(OLEString(sName),aCommand)))
        ADOS::ThrowException(*m_pCatalog->getConnection()->getConnection(),static_cast<XTypeProvider*>(this));

    OTables* pTables = static_cast<OTables*>(static_cast<OCatalog&>(m_rParent).getPrivateTables());
    if ( pTables )
        pTables->appendNew(sName);

    return createObject( _rForName );
}
// -------------------------------------------------------------------------
// XDrop
void OViews::dropObject(sal_Int32 /*_nPos*/,const ::rtl::OUString _sElementName)
{
    if(!m_aCollection.Delete(_sElementName))
        ADOS::ThrowException(*m_pCatalog->getConnection()->getConnection(),static_cast<XTypeProvider*>(this));
}
// -------------------------------------------------------------------------

<commit_msg>INTEGRATION: CWS changefileheader (1.16.216); FILE MERGED 2008/04/01 15:08:38 thb 1.16.216.3: #i85898# Stripping all external header guards 2008/04/01 10:52:50 thb 1.16.216.2: #i85898# Stripping all external header guards 2008/03/28 15:23:27 rt 1.16.216.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: AViews.cxx,v $
 * $Revision: 1.17 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"
#include "ado/AViews.hxx"
#include "ado/AView.hxx"
#include "ado/ATables.hxx"
#include "ado/ACatalog.hxx"
#ifndef _CONNECTIVITY_ADO_BCONNECTION_HXX_
#include "ado/AConnection.hxx"
#endif
#include "ado/Awrapado.hxx"
#include "TConnection.hxx"
#include <comphelper/types.hxx>
#include <connectivity/dbexception.hxx>

using namespace ::comphelper;

using namespace connectivity;
using namespace connectivity::ado;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::beans;
using namespace com::sun::star::sdbc;
using namespace com::sun::star::container;

sdbcx::ObjectType OViews::createObject(const ::rtl::OUString& _rName)
{
    OAdoView* pView = new OAdoView(isCaseSensitive(),m_aCollection.GetItem(_rName));
    pView->setNew(sal_False);
    return pView;
}
// -------------------------------------------------------------------------
void OViews::impl_refresh(  ) throw(RuntimeException)
{
    m_aCollection.Refresh();
}
// -------------------------------------------------------------------------
Reference< XPropertySet > OViews::createDescriptor()
{
    return new OAdoView(isCaseSensitive());
}

// -------------------------------------------------------------------------
// XAppend
sdbcx::ObjectType OViews::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor )
{
    OAdoView* pView = NULL;
    if ( !getImplementation( pView, descriptor ) || pView == NULL )
        ::dbtools::throwGenericSQLException(
            ::rtl::OUString::createFromAscii( "Could not create view: invalid object descriptor." ),
            static_cast<XTypeProvider*>(this)
        );

    WpADOCommand aCommand;
    aCommand.Create();
    if ( !aCommand.IsValid() )
        ::dbtools::throwGenericSQLException(
            ::rtl::OUString::createFromAscii( "Could not create view: no command object." ),
            static_cast<XTypeProvider*>(this)
        );

    ::rtl::OUString sName( _rForName );
    aCommand.put_Name(sName);
    aCommand.put_CommandText(getString(descriptor->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_COMMAND))));
    ADOViews* pViews = (ADOViews*)m_aCollection;
    if(FAILED(pViews->Append(OLEString(sName),aCommand)))
        ADOS::ThrowException(*m_pCatalog->getConnection()->getConnection(),static_cast<XTypeProvider*>(this));

    OTables* pTables = static_cast<OTables*>(static_cast<OCatalog&>(m_rParent).getPrivateTables());
    if ( pTables )
        pTables->appendNew(sName);

    return createObject( _rForName );
}
// -------------------------------------------------------------------------
// XDrop
void OViews::dropObject(sal_Int32 /*_nPos*/,const ::rtl::OUString _sElementName)
{
    if(!m_aCollection.Delete(_sElementName))
        ADOS::ThrowException(*m_pCatalog->getConnection()->getConnection(),static_cast<XTypeProvider*>(this));
}
// -------------------------------------------------------------------------

<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <functional>
#include <ctime>

#define _USE_MATH_DEFINES   1
#include <complex>

#define GRAPH_NODETYPE  2
#include "graph.hpp"
#include "parser.hpp"
#include "bstree.hpp"

#define elapsed_secs(begin, end) ((double)(end - begin) / CLOCKS_PER_SEC)

class city_searcher
{
    struct graphelement
    {
        const std::string data;
        graphelement(const std::string &city_name) : data(city_name) {}
    };
    graph<graphelement> g;
    binary_search_tree *bst;

    static double degtorad(const double deg)
    {
        return (double)(deg * M_PI / (double)180);
    }

    static double radtodeg(const double rad)
    {
        return (double)(rad * (double)180 / M_PI);
    }

    static double calc_distance(const double lat1, const double lon1, const double lat2, const double lon2)
    {
        double theta = lon1 - lon2;

        double dist = sin(degtorad(lat1)) * sin(degtorad(lat2))
                    + cos(degtorad(lat1)) * cos(degtorad(lat2)) * cos(degtorad(theta));
        dist = acos(dist);
        dist = radtodeg(dist);
        dist = dist * 60 * 1.1515;
        dist = dist * 1.609344; /* mile to km */
        dist = dist * 1000.00; /* km to m */

        return dist;
    }

public:
    city_searcher(void) : g(35000, [] (const graphelement &a, const graphelement &b) -> bool { return a.data == b.data; }), bst(new binary_search_tree()) {}

    int load(const int argc, const char *argv[])
    {
        /***************************
         * CHECK IF IS FILE EXISTS *
         ***************************/
        if(argc < 2)
        {
            fprintf(stdout, "Warning: Resource file not loaded.\nUsage: %s [path_of_file]\n", argv[0]);
            return 1;
        }

        parser fp;
        if(fp.open(argv[1]) != true)
        {
            fprintf(stdout, "Error: File '%s' not found.\n", argv[1]);
            return 2;
        }

        clock_t begin, end;
        double elapsed_secs = 0;

        /***************************
         * READ FILE               *
         ***************************/
        std::cout << "Step 1 of 2: Read a file, add to the vertex of the graph, add to the BST (together) . . . ";
        begin = clock();

        fp.parse(
            [&] (const std::string &line)
            {
                std::string arr[5];
                fp.divide_by_delimiter(arr, line, 5, '\t');
                /*
                    arr[0] = StateAbb
                    arr[1] = PlaceName
                    arr[2] = longitude
                    arr[3] = latitude
                    arr[4] = DistancetoCapitalCity_km
                */

                std::string city_name = arr[1];
                double longitude, latitude;
                try
                {
                    longitude = stod(arr[2]);
                    latitude = stod(arr[3]);
                }
                catch(const std::invalid_argument &e)
                {
                    return; /* Invalid line, so we should not add this line */
                }

                /* Add to graph */
                int key = g.add_vertex(graphelement(arr[1]));
                if(key == -1) /* Duplicate city name */
                {
                    char *temp = new char[5]();
                    for(int i = 2; ; ++i) /* suffix start with #2 */
                    {
                        std::snprintf(temp, 5, "%d", i);
                        if((key = g.add_vertex(graphelement(std::string(city_name + " #" + temp)))) != -1)
                        {
                            city_name = city_name + " #" + temp;
                            break;
                        }
                    }
                    delete temp;
                }

                /* Add to BST */
                bstelement *element = new bstelement(city_name, key, longitude, latitude);
                bst->add(element);
            }
        );

        end = clock();
        std::cout << "Finished (" << elapsed_secs(begin, end) << "sec)" << std::endl;
        bst->printall();

        std::cout << "Step 2 of 2: Add the edges to each vertex . . . ";
        begin = clock();

        double lat1, lon1, lat2, lon2;
        bst->traverse_level_order(
            [&] (bstnode *node)
            {
                bst->binary_search_tree::traverse_level_order(
                    [&] (bstnode *n)
                    {
                        if(10000 >= calc_distance(node->element->latitude,
                                                  node->element->longitude,
                                                  n->element->latitude,
                                                  n->element->longitude))
                        {
                            g.add_edge(node->element->value, n->element->value);
                            g.add_edge(n->element->value, node->element->value);
                        }
                    }
                );
            }
        );

        end = clock();
        std::cout << "Finished (" << elapsed_secs(begin, end) << "sec)" << std::endl;
        g.print();
    }

    void prompt(void)
    {
        while(true)
        {
            std::string city_name, hop;
            std::cout << "City name: "; std::getline(std::cin, city_name);
            std::cout << "Hop: "; std::getline(std::cin, hop);

            bstnode *n = bst->get_node_by_key(city_name);
            if(n == NULL)
                std::cout << "Error: City name '" << city_name << "' not found." << std::endl;
            else
            {
                int city_code = n->element->value;
                g.traverse(city_code, atoi(hop.c_str()));
            }
        }
    }
};
<commit_msg>Remove traversal printing<commit_after>#include <iostream>
#include <string>
#include <functional>
#include <ctime>

#define _USE_MATH_DEFINES   1
#include <complex>

#define GRAPH_NODETYPE  2
#include "graph.hpp"
#include "parser.hpp"
#include "bstree.hpp"

#define elapsed_secs(begin, end) ((double)(end - begin) / CLOCKS_PER_SEC)

class city_searcher
{
    struct graphelement
    {
        const std::string data;
        graphelement(const std::string &city_name) : data(city_name) {}
    };
    graph<graphelement> g;
    binary_search_tree *bst;

    static double degtorad(const double deg)
    {
        return (double)(deg * M_PI / (double)180);
    }

    static double radtodeg(const double rad)
    {
        return (double)(rad * (double)180 / M_PI);
    }

    static double calc_distance(const double lat1, const double lon1, const double lat2, const double lon2)
    {
        double theta = lon1 - lon2;

        double dist = sin(degtorad(lat1)) * sin(degtorad(lat2))
                    + cos(degtorad(lat1)) * cos(degtorad(lat2)) * cos(degtorad(theta));
        dist = acos(dist);
        dist = radtodeg(dist);
        dist = dist * 60 * 1.1515;
        dist = dist * 1.609344; /* mile to km */
        dist = dist * 1000.00; /* km to m */

        return dist;
    }

public:
    city_searcher(void) : g(35000, [] (const graphelement &a, const graphelement &b) -> bool { return a.data == b.data; }), bst(new binary_search_tree()) {}

    int load(const int argc, const char *argv[])
    {
        /***************************
         * CHECK IF IS FILE EXISTS *
         ***************************/
        if(argc < 2)
        {
            fprintf(stdout, "Warning: Resource file not loaded.\nUsage: %s [path_of_file]\n", argv[0]);
            return 1;
        }

        parser fp;
        if(fp.open(argv[1]) != true)
        {
            fprintf(stdout, "Error: File '%s' not found.\n", argv[1]);
            return 2;
        }

        clock_t begin, end;
        double elapsed_secs = 0;

        /***************************
         * READ FILE               *
         ***************************/
        std::cout << "Step 1 of 2: Read a file, add to the vertex of the graph, add to the BST (together) . . . ";
        begin = clock();

        fp.parse(
            [&] (const std::string &line)
            {
                std::string arr[5];
                fp.divide_by_delimiter(arr, line, 5, '\t');
                /*
                    arr[0] = StateAbb
                    arr[1] = PlaceName
                    arr[2] = longitude
                    arr[3] = latitude
                    arr[4] = DistancetoCapitalCity_km
                */

                std::string city_name = arr[1];
                double longitude, latitude;
                try
                {
                    longitude = stod(arr[2]);
                    latitude = stod(arr[3]);
                }
                catch(const std::invalid_argument &e)
                {
                    return; /* Invalid line, so we should not add this line */
                }

                /* Add to graph */
                int key = g.add_vertex(graphelement(arr[1]));
                if(key == -1) /* Duplicate city name */
                {
                    char *temp = new char[5]();
                    for(int i = 2; ; ++i) /* suffix start with #2 */
                    {
                        std::snprintf(temp, 5, "%d", i);
                        if((key = g.add_vertex(graphelement(std::string(city_name + " #" + temp)))) != -1)
                        {
                            city_name = city_name + " #" + temp;
                            break;
                        }
                    }
                    delete temp;
                }

                /* Add to BST */
                bstelement *element = new bstelement(city_name, key, longitude, latitude);
                bst->add(element);
            }
        );

        end = clock();
        std::cout << "Finished (" << elapsed_secs(begin, end) << "sec)" << std::endl;
        //bst->printall();

        std::cout << "Step 2 of 2: Add the edges to each vertex . . . ";
        begin = clock();

        double lat1, lon1, lat2, lon2;
        bst->traverse_level_order(
            [&] (bstnode *node)
            {
                bst->binary_search_tree::traverse_level_order(
                    [&] (bstnode *n)
                    {
                        if(10000 >= calc_distance(node->element->latitude,
                                                  node->element->longitude,
                                                  n->element->latitude,
                                                  n->element->longitude))
                        {
                            g.add_edge(node->element->value, n->element->value);
                            g.add_edge(n->element->value, node->element->value);
                        }
                    }
                );
            }
        );

        end = clock();
        std::cout << "Finished (" << elapsed_secs(begin, end) << "sec)" << std::endl;
        //g.print();
    }

    void prompt(void)
    {
        while(true)
        {
            std::string city_name, hop;
            std::cout << "City name: "; std::getline(std::cin, city_name);
            std::cout << "Hop: "; std::getline(std::cin, hop);

            bstnode *n = bst->get_node_by_key(city_name);
            if(n == NULL)
                std::cout << "Error: City name '" << city_name << "' not found." << std::endl;
            else
            {
                int city_code = n->element->value;
                g.traverse(city_code, atoi(hop.c_str()));
            }
        }
    }
};
<|endoftext|>