<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "findinfiles.h"

#include <coreplugin/editormanager/editormanager.h>

#include <QtCore/QtDebug>
#include <QtCore/QSettings>
#include <QtCore/QDir>
#include <QtCore/QDirIterator>
#include <QtGui/QPushButton>
#include <QtGui/QFileDialog>
#include <QtGui/QHBoxLayout>
#include <QtGui/QVBoxLayout>

using namespace Find;
using namespace TextEditor;

FindInFiles::FindInFiles()
  : m_configWidget(0),
    m_directory(0)
{
}

QString FindInFiles::id() const
{
    return QLatin1String("Files on Disk");
}

QString FindInFiles::displayName() const
{
    return tr("Files on File System");
}

void FindInFiles::findAll(const QString &txt, Find::FindFlags findFlags)
{
    updateComboEntries(m_directory, true);
    BaseFileFind::findAll(txt, findFlags);
}

Utils::FileIterator *FindInFiles::files(const QStringList &nameFilters,
                                        const QVariant &additionalParameters) const
{
    return new Utils::SubDirFileIterator(QStringList() << additionalParameters.toString(),
                                         nameFilters,
                                         Core::EditorManager::instance()->defaultTextCodec());
}

QVariant FindInFiles::additionalParameters() const
{
    return qVariantFromValue(QDir::fromNativeSeparators(m_directory->currentText()));
}

QString FindInFiles::label() const
{
    const QChar slash = QLatin1Char('/');
    const QStringList &nonEmptyComponents = QDir::cleanPath(
                QFileInfo(QDir::fromNativeSeparators(m_directory->currentText())).absoluteFilePath())
            .split(slash, QString::SkipEmptyParts);
    return tr("Directory '%1':").arg(nonEmptyComponents.isEmpty() ? QString(slash) : nonEmptyComponents.last());
}

QString FindInFiles::toolTip() const
{
    //: %3 is filled by BaseFileFind::runNewSearch
    return tr("Path: %1\nFilter: %2\n%3")
            .arg(QDir::toNativeSeparators(QFileInfo(m_directory->currentText()).absoluteFilePath()))
            .arg(fileNameFilters().join(QLatin1String(",")));
}

QWidget *FindInFiles::createConfigWidget()
{
    if (!m_configWidget) {
        m_configWidget = new QWidget;
        QGridLayout * const gridLayout = new QGridLayout(m_configWidget);
        gridLayout->setMargin(0);
        m_configWidget->setLayout(gridLayout);

        QLabel *dirLabel = new QLabel(tr("Director&y:"));
        gridLayout->addWidget(dirLabel, 0, 0, Qt::AlignRight);
        m_directory = new QComboBox;
        m_directory->setEditable(true);
        m_directory->setMaxCount(30);
        m_directory->setMinimumContentsLength(10);
        m_directory->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
        m_directory->setInsertPolicy(QComboBox::InsertAtTop);
        m_directory->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
        m_directory->setModel(&m_directoryStrings);
        syncComboWithSettings(m_directory, m_directorySetting);
        dirLabel->setBuddy(m_directory);
        gridLayout->addWidget(m_directory, 0, 1);
        QPushButton *browseButton = new QPushButton(tr("&Browse..."));
        gridLayout->addWidget(browseButton, 0, 2);
        connect(browseButton, SIGNAL(clicked()), this, SLOT(openFileBrowser()));

        QLabel * const filePatternLabel = new QLabel(tr("Fi&le pattern:"));
        filePatternLabel->setMinimumWidth(80);
        filePatternLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
        filePatternLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
        QWidget *patternWidget = createPatternWidget();
        filePatternLabel->setBuddy(patternWidget);
        gridLayout->addWidget(filePatternLabel, 1, 0);
        gridLayout->addWidget(patternWidget, 1, 1, 1, 2);
        m_configWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    }
    return m_configWidget;
}

void FindInFiles::openFileBrowser()
{
    if (!m_directory)
        return;
    QString oldDir = m_directory->currentText();
    if (!QDir(oldDir).exists())
        oldDir.clear();
    QString dir = QFileDialog::getExistingDirectory(m_configWidget,
        tr("Directory to search"), oldDir);
    if (!dir.isEmpty())
        m_directory->setEditText(dir);
}

void FindInFiles::writeSettings(QSettings *settings)
{
    settings->beginGroup(QLatin1String("FindInFiles"));
    writeCommonSettings(settings);
    settings->setValue(QLatin1String("directories"), m_directoryStrings.stringList());
    if (m_directory)
        settings->setValue(QLatin1String("currentDirectory"), m_directory->currentText());
    settings->endGroup();
}

void FindInFiles::readSettings(QSettings *settings)
{
    settings->beginGroup(QLatin1String("FindInFiles"));
    readCommonSettings(settings, QLatin1String("*.cpp,*.h"));
    m_directoryStrings.setStringList(settings->value(QLatin1String("directories")).toStringList());
    m_directorySetting = settings->value(QLatin1String("currentDirectory")).toString();
    settings->endGroup();
    syncComboWithSettings(m_directory, m_directorySetting);
}

void FindInFiles::setDirectory(const QString &directory)
{
    syncComboWithSettings(m_directory, directory);
}

<commit_msg>Get native dir separators from "Find in Files" path chooser.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "findinfiles.h"

#include <coreplugin/editormanager/editormanager.h>

#include <QtCore/QtDebug>
#include <QtCore/QSettings>
#include <QtCore/QDir>
#include <QtCore/QDirIterator>
#include <QtGui/QPushButton>
#include <QtGui/QFileDialog>
#include <QtGui/QHBoxLayout>
#include <QtGui/QVBoxLayout>

using namespace Find;
using namespace TextEditor;

FindInFiles::FindInFiles()
  : m_configWidget(0),
    m_directory(0)
{
}

QString FindInFiles::id() const
{
    return QLatin1String("Files on Disk");
}

QString FindInFiles::displayName() const
{
    return tr("Files on File System");
}

void FindInFiles::findAll(const QString &txt, Find::FindFlags findFlags)
{
    updateComboEntries(m_directory, true);
    BaseFileFind::findAll(txt, findFlags);
}

Utils::FileIterator *FindInFiles::files(const QStringList &nameFilters,
                                        const QVariant &additionalParameters) const
{
    return new Utils::SubDirFileIterator(QStringList() << additionalParameters.toString(),
                                         nameFilters,
                                         Core::EditorManager::instance()->defaultTextCodec());
}

QVariant FindInFiles::additionalParameters() const
{
    return qVariantFromValue(QDir::fromNativeSeparators(m_directory->currentText()));
}

QString FindInFiles::label() const
{
    const QChar slash = QLatin1Char('/');
    const QStringList &nonEmptyComponents = QDir::cleanPath(
                QFileInfo(QDir::fromNativeSeparators(m_directory->currentText())).absoluteFilePath())
            .split(slash, QString::SkipEmptyParts);
    return tr("Directory '%1':").arg(nonEmptyComponents.isEmpty() ? QString(slash) : nonEmptyComponents.last());
}

QString FindInFiles::toolTip() const
{
    //: %3 is filled by BaseFileFind::runNewSearch
    return tr("Path: %1\nFilter: %2\n%3")
            .arg(QDir::toNativeSeparators(QFileInfo(m_directory->currentText()).absoluteFilePath()))
            .arg(fileNameFilters().join(QLatin1String(",")));
}

QWidget *FindInFiles::createConfigWidget()
{
    if (!m_configWidget) {
        m_configWidget = new QWidget;
        QGridLayout * const gridLayout = new QGridLayout(m_configWidget);
        gridLayout->setMargin(0);
        m_configWidget->setLayout(gridLayout);

        QLabel *dirLabel = new QLabel(tr("Director&y:"));
        gridLayout->addWidget(dirLabel, 0, 0, Qt::AlignRight);
        m_directory = new QComboBox;
        m_directory->setEditable(true);
        m_directory->setMaxCount(30);
        m_directory->setMinimumContentsLength(10);
        m_directory->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
        m_directory->setInsertPolicy(QComboBox::InsertAtTop);
        m_directory->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
        m_directory->setModel(&m_directoryStrings);
        syncComboWithSettings(m_directory, m_directorySetting);
        dirLabel->setBuddy(m_directory);
        gridLayout->addWidget(m_directory, 0, 1);
        QPushButton *browseButton = new QPushButton(tr("&Browse..."));
        gridLayout->addWidget(browseButton, 0, 2);
        connect(browseButton, SIGNAL(clicked()), this, SLOT(openFileBrowser()));

        QLabel * const filePatternLabel = new QLabel(tr("Fi&le pattern:"));
        filePatternLabel->setMinimumWidth(80);
        filePatternLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
        filePatternLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
        QWidget *patternWidget = createPatternWidget();
        filePatternLabel->setBuddy(patternWidget);
        gridLayout->addWidget(filePatternLabel, 1, 0);
        gridLayout->addWidget(patternWidget, 1, 1, 1, 2);
        m_configWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    }
    return m_configWidget;
}

void FindInFiles::openFileBrowser()
{
    if (!m_directory)
        return;
    QString oldDir = m_directory->currentText();
    if (!QDir(oldDir).exists())
        oldDir.clear();
    QString dir = QFileDialog::getExistingDirectory(m_configWidget,
        tr("Directory to search"), oldDir);
    if (!dir.isEmpty())
        m_directory->setEditText(QDir::toNativeSeparators(dir));
}

void FindInFiles::writeSettings(QSettings *settings)
{
    settings->beginGroup(QLatin1String("FindInFiles"));
    writeCommonSettings(settings);
    settings->setValue(QLatin1String("directories"), m_directoryStrings.stringList());
    if (m_directory)
        settings->setValue(QLatin1String("currentDirectory"), m_directory->currentText());
    settings->endGroup();
}

void FindInFiles::readSettings(QSettings *settings)
{
    settings->beginGroup(QLatin1String("FindInFiles"));
    readCommonSettings(settings, QLatin1String("*.cpp,*.h"));
    m_directoryStrings.setStringList(settings->value(QLatin1String("directories")).toStringList());
    m_directorySetting = settings->value(QLatin1String("currentDirectory")).toString();
    settings->endGroup();
    syncComboWithSettings(m_directory, m_directorySetting);
}

void FindInFiles::setDirectory(const QString &directory)
{
    syncComboWithSettings(m_directory, directory);
}

<|endoftext|>


<commit_before>#include "providers/ffz/FfzEmotes.hpp"

#include <QBuffer>
#include <QImageReader>
#include <QJsonArray>
#include <QJsonObject>
#include <QPainter>
#include <QString>

#include "common/NetworkRequest.hpp"
#include "common/Outcome.hpp"
#include "debug/Log.hpp"
#include "messages/Emote.hpp"
#include "messages/Image.hpp"

namespace chatterino {
namespace {
    Url getEmoteLink(const QJsonObject &urls, const QString &emoteScale)
    {
        auto emote = urls.value(emoteScale);
        if (emote.isUndefined())
        {
            return {""};
        }

        assert(emote.isString());

        return {"https:" + emote.toString()};
    }
    void fillInEmoteData(const QJsonObject &urls, const EmoteName &name,
                         const QString &tooltip, Emote &emoteData)
    {
        auto url1x = getEmoteLink(urls, "1");
        auto url2x = getEmoteLink(urls, "2");
        auto url3x = getEmoteLink(urls, "4");

        //, code, tooltip
        emoteData.name = name;
        emoteData.images =
            ImageSet{Image::fromUrl(url1x, 1),
                     url2x.string.isEmpty() ? Image::getEmpty()
                                            : Image::fromUrl(url2x, 0.5),
                     url3x.string.isEmpty() ? Image::getEmpty()
                                            : Image::fromUrl(url3x, 0.25)};
        emoteData.tooltip = {tooltip};
    }
    EmotePtr cachedOrMake(Emote &&emote, const EmoteId &id)
    {
        static std::unordered_map<EmoteId, std::weak_ptr<const Emote>> cache;
        static std::mutex mutex;

        return cachedOrMakeEmotePtr(std::move(emote), cache, mutex, id);
    }
    std::pair<Outcome, EmoteMap> parseGlobalEmotes(
        const QJsonObject &jsonRoot, const EmoteMap &currentEmotes)
    {
        auto jsonSets = jsonRoot.value("sets").toObject();
        auto emotes = EmoteMap();

        for (auto jsonSet : jsonSets)
        {
            auto jsonEmotes = jsonSet.toObject().value("emoticons").toArray();

            for (auto jsonEmoteValue : jsonEmotes)
            {
                auto jsonEmote = jsonEmoteValue.toObject();

                auto name = EmoteName{jsonEmote.value("name").toString()};
                auto id = EmoteId{jsonEmote.value("id").toString()};
                auto urls = jsonEmote.value("urls").toObject();

                auto emote = Emote();
                fillInEmoteData(urls, name,
                                name.string + "
Global FFZ Emote", emote);
                emote.homePage =
                    Url{QString("https://www.frankerfacez.com/emoticon/%1-%2")
                            .arg(id.string)
                            .arg(name.string)};

                emotes[name] =
                    cachedOrMakeEmotePtr(std::move(emote), currentEmotes);
            }
        }

        return {Success, std::move(emotes)};
    }
    std::tuple<Outcome, EmoteMap, boost::optional<EmotePtr>>
        parseChannelResponse(const QJsonObject &jsonRoot)
    {
        boost::optional<EmotePtr> modBadge;

        // Parse mod badge
        auto room = jsonRoot.value("room").toObject();
        auto modUrls = room.value("mod_urls").toObject();
        if (!modUrls.isEmpty())
        {
            auto modBadge1x = getEmoteLink(modUrls, "1");
            auto modBadge2x = getEmoteLink(modUrls, "2");
            auto modBadge3x = getEmoteLink(modUrls, "4");

            auto modBadgeImageSet = ImageSet{
                Image::fromUrl(modBadge1x, 1),
                modBadge2x.string.isEmpty() ? Image::getEmpty()
                                            : Image::fromUrl(modBadge2x, 0.5),
                modBadge3x.string.isEmpty() ? Image::getEmpty()
                                            : Image::fromUrl(modBadge3x, 0.25),
            };

            modBadge = std::make_shared<Emote>(Emote{
                {""},
                modBadgeImageSet,
                Tooltip{"Twitch Channel Moderator"},
                modBadge1x,
            });
        }

        // Parse emotes
        auto jsonSets = jsonRoot.value("sets").toObject();
        auto emotes = EmoteMap();

        for (auto jsonSet : jsonSets)
        {
            auto jsonEmotes = jsonSet.toObject().value("emoticons").toArray();

            for (auto _jsonEmote : jsonEmotes)
            {
                auto jsonEmote = _jsonEmote.toObject();

                // margins
                auto id =
                    EmoteId{QString::number(jsonEmote.value("id").toInt())};
                auto name = EmoteName{jsonEmote.value("name").toString()};
                auto urls = jsonEmote.value("urls").toObject();

                Emote emote;
                fillInEmoteData(urls, name,
                                name.string + "
Channel FFZ Emote", emote);
                emote.homePage =
                    Url{QString("https://www.frankerfacez.com/emoticon/%1-%2")
                            .arg(id.string)
                            .arg(name.string)};

                emotes[name] = cachedOrMake(std::move(emote), id);
            }
        }

        return {Success, std::move(emotes), modBadge};
    }
}  // namespace

FfzEmotes::FfzEmotes()
    : global_(std::make_shared<EmoteMap>())
{
}

std::shared_ptr<const EmoteMap> FfzEmotes::emotes() const
{
    return this->global_.get();
}

boost::optional<EmotePtr> FfzEmotes::emote(const EmoteName &name) const
{
    auto emotes = this->global_.get();
    auto it = emotes->find(name);
    if (it != emotes->end())
        return it->second;
    return boost::none;
}

void FfzEmotes::loadEmotes()
{
    QString url("https://api.frankerfacez.com/v1/set/global");

    NetworkRequest(url)

        .timeout(30000)
        .onSuccess([this](auto result) -> Outcome {
            auto emotes = this->emotes();
            auto pair = parseGlobalEmotes(result.parseJson(), *emotes);
            if (pair.first)
                this->global_.set(
                    std::make_shared<EmoteMap>(std::move(pair.second)));
            return pair.first;
        })
        .execute();
}

void FfzEmotes::loadChannel(
    const QString &channelId, std::function<void(EmoteMap &&)> emoteCallback,
    std::function<void(boost::optional<EmotePtr>)> modBadgeCallback)
{
    log("[FFZEmotes] Reload FFZ Channel Emotes for channel {}\n", channelId);

    NetworkRequest("https://api.frankerfacez.com/v1/room/id/" + channelId)

        .timeout(20000)
        .onSuccess([emoteCallback = std::move(emoteCallback),
                    modBadgeCallback =
                        std::move(modBadgeCallback)](auto result) -> Outcome {
            auto [success, emoteMap, modBadge] =
                parseChannelResponse(result.parseJson());
            if (!success)
            {
                return success;
            }

            emoteCallback(std::move(emoteMap));
            modBadgeCallback(std::move(modBadge));

            return success;
        })
        .onError([channelId](int result) {
            if (result == 203)
            {
                // User does not have any FFZ emotes
                return true;
            }

            if (result == -2)
            {
                // TODO: Auto retry in case of a timeout, with a delay
                log("Fetching FFZ emotes for channel {} failed due to timeout",
                    channelId);
                return true;
            }

            log("Error fetching FFZ emotes for channel {}, error {}", channelId,
                result);

            return true;
        })
        .execute();
}

}  // namespace chatterino
<commit_msg>Remove more unused includes<commit_after>#include "providers/ffz/FfzEmotes.hpp"

#include <QJsonArray>

#include "common/NetworkRequest.hpp"
#include "common/Outcome.hpp"
#include "debug/Log.hpp"
#include "messages/Emote.hpp"
#include "messages/Image.hpp"

namespace chatterino {
namespace {
    Url getEmoteLink(const QJsonObject &urls, const QString &emoteScale)
    {
        auto emote = urls.value(emoteScale);
        if (emote.isUndefined())
        {
            return {""};
        }

        assert(emote.isString());

        return {"https:" + emote.toString()};
    }
    void fillInEmoteData(const QJsonObject &urls, const EmoteName &name,
                         const QString &tooltip, Emote &emoteData)
    {
        auto url1x = getEmoteLink(urls, "1");
        auto url2x = getEmoteLink(urls, "2");
        auto url3x = getEmoteLink(urls, "4");

        //, code, tooltip
        emoteData.name = name;
        emoteData.images =
            ImageSet{Image::fromUrl(url1x, 1),
                     url2x.string.isEmpty() ? Image::getEmpty()
                                            : Image::fromUrl(url2x, 0.5),
                     url3x.string.isEmpty() ? Image::getEmpty()
                                            : Image::fromUrl(url3x, 0.25)};
        emoteData.tooltip = {tooltip};
    }
    EmotePtr cachedOrMake(Emote &&emote, const EmoteId &id)
    {
        static std::unordered_map<EmoteId, std::weak_ptr<const Emote>> cache;
        static std::mutex mutex;

        return cachedOrMakeEmotePtr(std::move(emote), cache, mutex, id);
    }
    std::pair<Outcome, EmoteMap> parseGlobalEmotes(
        const QJsonObject &jsonRoot, const EmoteMap &currentEmotes)
    {
        auto jsonSets = jsonRoot.value("sets").toObject();
        auto emotes = EmoteMap();

        for (auto jsonSet : jsonSets)
        {
            auto jsonEmotes = jsonSet.toObject().value("emoticons").toArray();

            for (auto jsonEmoteValue : jsonEmotes)
            {
                auto jsonEmote = jsonEmoteValue.toObject();

                auto name = EmoteName{jsonEmote.value("name").toString()};
                auto id = EmoteId{jsonEmote.value("id").toString()};
                auto urls = jsonEmote.value("urls").toObject();

                auto emote = Emote();
                fillInEmoteData(urls, name,
                                name.string + "
Global FFZ Emote", emote);
                emote.homePage =
                    Url{QString("https://www.frankerfacez.com/emoticon/%1-%2")
                            .arg(id.string)
                            .arg(name.string)};

                emotes[name] =
                    cachedOrMakeEmotePtr(std::move(emote), currentEmotes);
            }
        }

        return {Success, std::move(emotes)};
    }
    std::tuple<Outcome, EmoteMap, boost::optional<EmotePtr>>
        parseChannelResponse(const QJsonObject &jsonRoot)
    {
        boost::optional<EmotePtr> modBadge;

        // Parse mod badge
        auto room = jsonRoot.value("room").toObject();
        auto modUrls = room.value("mod_urls").toObject();
        if (!modUrls.isEmpty())
        {
            auto modBadge1x = getEmoteLink(modUrls, "1");
            auto modBadge2x = getEmoteLink(modUrls, "2");
            auto modBadge3x = getEmoteLink(modUrls, "4");

            auto modBadgeImageSet = ImageSet{
                Image::fromUrl(modBadge1x, 1),
                modBadge2x.string.isEmpty() ? Image::getEmpty()
                                            : Image::fromUrl(modBadge2x, 0.5),
                modBadge3x.string.isEmpty() ? Image::getEmpty()
                                            : Image::fromUrl(modBadge3x, 0.25),
            };

            modBadge = std::make_shared<Emote>(Emote{
                {""},
                modBadgeImageSet,
                Tooltip{"Twitch Channel Moderator"},
                modBadge1x,
            });
        }

        // Parse emotes
        auto jsonSets = jsonRoot.value("sets").toObject();
        auto emotes = EmoteMap();

        for (auto jsonSet : jsonSets)
        {
            auto jsonEmotes = jsonSet.toObject().value("emoticons").toArray();

            for (auto _jsonEmote : jsonEmotes)
            {
                auto jsonEmote = _jsonEmote.toObject();

                // margins
                auto id =
                    EmoteId{QString::number(jsonEmote.value("id").toInt())};
                auto name = EmoteName{jsonEmote.value("name").toString()};
                auto urls = jsonEmote.value("urls").toObject();

                Emote emote;
                fillInEmoteData(urls, name,
                                name.string + "
Channel FFZ Emote", emote);
                emote.homePage =
                    Url{QString("https://www.frankerfacez.com/emoticon/%1-%2")
                            .arg(id.string)
                            .arg(name.string)};

                emotes[name] = cachedOrMake(std::move(emote), id);
            }
        }

        return {Success, std::move(emotes), modBadge};
    }
}  // namespace

FfzEmotes::FfzEmotes()
    : global_(std::make_shared<EmoteMap>())
{
}

std::shared_ptr<const EmoteMap> FfzEmotes::emotes() const
{
    return this->global_.get();
}

boost::optional<EmotePtr> FfzEmotes::emote(const EmoteName &name) const
{
    auto emotes = this->global_.get();
    auto it = emotes->find(name);
    if (it != emotes->end())
        return it->second;
    return boost::none;
}

void FfzEmotes::loadEmotes()
{
    QString url("https://api.frankerfacez.com/v1/set/global");

    NetworkRequest(url)

        .timeout(30000)
        .onSuccess([this](auto result) -> Outcome {
            auto emotes = this->emotes();
            auto pair = parseGlobalEmotes(result.parseJson(), *emotes);
            if (pair.first)
                this->global_.set(
                    std::make_shared<EmoteMap>(std::move(pair.second)));
            return pair.first;
        })
        .execute();
}

void FfzEmotes::loadChannel(
    const QString &channelId, std::function<void(EmoteMap &&)> emoteCallback,
    std::function<void(boost::optional<EmotePtr>)> modBadgeCallback)
{
    log("[FFZEmotes] Reload FFZ Channel Emotes for channel {}\n", channelId);

    NetworkRequest("https://api.frankerfacez.com/v1/room/id/" + channelId)

        .timeout(20000)
        .onSuccess([emoteCallback = std::move(emoteCallback),
                    modBadgeCallback =
                        std::move(modBadgeCallback)](auto result) -> Outcome {
            auto [success, emoteMap, modBadge] =
                parseChannelResponse(result.parseJson());
            if (!success)
            {
                return success;
            }

            emoteCallback(std::move(emoteMap));
            modBadgeCallback(std::move(modBadge));

            return success;
        })
        .onError([channelId](int result) {
            if (result == 203)
            {
                // User does not have any FFZ emotes
                return true;
            }

            if (result == -2)
            {
                // TODO: Auto retry in case of a timeout, with a delay
                log("Fetching FFZ emotes for channel {} failed due to timeout",
                    channelId);
                return true;
            }

            log("Error fetching FFZ emotes for channel {}, error {}", channelId,
                result);

            return true;
        })
        .execute();
}

}  // namespace chatterino
<|endoftext|>


<commit_before>#include "process_based_isolation_module.hpp"

#include "foreach.hpp"

using std::cerr;
using std::cout;
using std::endl;
using std::list;
using std::make_pair;
using std::ostringstream;
using std::pair;
using std::queue;
using std::string;
using std::vector;

using boost::lexical_cast;
using boost::unordered_map;
using boost::unordered_set;

using namespace nexus;
using namespace nexus::internal;
using namespace nexus::internal::slave;

ProcessBasedIsolationModule::ProcessBasedIsolationModule(Slave* slave)
{
  this->slave = slave;
  reaper = new Reaper(this);
  Process::spawn(reaper);
}

ProcessBasedIsolationModule::~ProcessBasedIsolationModule()
{
  // We want to wait until the reaper has completed because it
  // accesses 'this' in order to make callbacks ... deleting 'this'
  // could thus lead to a seg fault!
  Process::post(reaper->getPID(), SHUTDOWN_REAPER);
  Process::wait(reaper);
  delete reaper;
}

void ProcessBasedIsolationModule::frameworkAdded(Framework* framework)
{
  osPid[framework->id] = -1;
  framework->executorStatus = "No executor running";
}

void ProcessBasedIsolationModule::frameworkRemoved(Framework* framework)
{
  osPid.erase(framework->id);
}

void ProcessBasedIsolationModule::startExecutor(Framework* framework)
{
  LOG(INFO) << "Starting executor for framework " << framework->id << ": "
            << framework->executorInfo.uri;
  CHECK(osPid[framework->id] == -1);

  pid_t pid;
  if ((pid = fork()) == -1)
    PLOG(FATAL) << "Failed to fork to launch new executor";

  if (pid) {
    // In parent process
    LOG(INFO) << "Started executor, OS pid = " << pid;
    osPid[framework->id] = pid;
    framework->executorStatus = "PID: " + lexical_cast<string>(pid);
  } else {
    // In child process
    createExecutorLauncher(framework)->run();
  }
}

void ProcessBasedIsolationModule::killExecutor(Framework* fw)
{
  if (osPid[fw->id] != -1) {
    LOG(INFO) << "Sending SIGTERM to pid " << osPid[fw->id];
    kill(osPid[fw->id], SIGKILL);
    osPid[fw->id] = -1;
    fw->executorStatus = "No executor running";
    // TODO: Kill all of the process's descendants?
  }
}

void ProcessBasedIsolationModule::resourcesChanged(Framework* fw)
{
  // Do nothing; subclasses may override this.
}

ExecutorLauncher* ProcessBasedIsolationModule::createExecutorLauncher(Framework* fw)
{
  return new ExecutorLauncher(fw->id, fw->executorInfo.uri, fw->user,
			      slave->getWorkDirectory(fw->id),
			      slave->self(), !slave->local);
}

ProcessBasedIsolationModule::Reaper::Reaper(ProcessBasedIsolationModule* m)
  : module(m)
{}

void ProcessBasedIsolationModule::Reaper::operator () ()
{
  link(module->slave->getPID());
  while (true) {
    switch (receive(1)) {
    case PROCESS_TIMEOUT: {
      // Check whether any child process has exited
      pid_t pid;
      int status;
      if ((pid = waitpid((pid_t) -1, &status, WNOHANG)) > 0) {
	foreachpair (FrameworkID fid, pid_t& fwPid, module->osPid) {
	  if (fwPid == pid) {
	    module->osPid[fid] = -1;
	    module->slave->executorExited(fid, status);
	    break;
	  }
	}
      }
      break;
    }
    case SHUTDOWN_REAPER:
    case PROCESS_EXIT:
      return;
    }
  }
}

<commit_msg>Using sessions and doing process group killing in order to cleanup most descendants of an executor (this still will not cleanup any descendants that create their own process group or session, but hopefully that is unlikely, and if the organization is doing that then they probably really know what they are doing).<commit_after>#include "process_based_isolation_module.hpp"

#include "foreach.hpp"

using std::cerr;
using std::cout;
using std::endl;
using std::list;
using std::make_pair;
using std::ostringstream;
using std::pair;
using std::queue;
using std::string;
using std::vector;

using boost::lexical_cast;
using boost::unordered_map;
using boost::unordered_set;

using namespace nexus;
using namespace nexus::internal;
using namespace nexus::internal::slave;

ProcessBasedIsolationModule::ProcessBasedIsolationModule(Slave* slave)
{
  this->slave = slave;
  reaper = new Reaper(this);
  Process::spawn(reaper);
}

ProcessBasedIsolationModule::~ProcessBasedIsolationModule()
{
  // We want to wait until the reaper has completed because it
  // accesses 'this' in order to make callbacks ... deleting 'this'
  // could thus lead to a seg fault!
  Process::post(reaper->getPID(), SHUTDOWN_REAPER);
  Process::wait(reaper);
  delete reaper;
}

void ProcessBasedIsolationModule::frameworkAdded(Framework* framework)
{
  osPid[framework->id] = -1;
  framework->executorStatus = "No executor running";
}

void ProcessBasedIsolationModule::frameworkRemoved(Framework* framework)
{
  osPid.erase(framework->id);
}

void ProcessBasedIsolationModule::startExecutor(Framework* framework)
{
  LOG(INFO) << "Starting executor for framework " << framework->id << ": "
            << framework->executorInfo.uri;
  CHECK(osPid[framework->id] == -1);

  pid_t pid;
  if ((pid = fork()) == -1)
    PLOG(FATAL) << "Failed to fork to launch new executor";

  if (pid) {
    // In parent process, record the pid for killpg later.
    LOG(INFO) << "Started executor, OS pid = " << pid;
    osPid[framework->id] = pid;
    framework->executorStatus = "PID: " + lexical_cast<string>(pid);
  } else {
    // In child process, do setsid to make cleanup easier.
    if ((pid = setsid()) == -1)
      perror("setsid error");

    createExecutorLauncher(framework)->run();
  }
}

void ProcessBasedIsolationModule::killExecutor(Framework* fw)
{
  if (osPid[fw->id] != -1) {
    // TODO(benh): Consider sending a SIGTERM, then after so much time
    // if it still hasn't exited do a SIGKILL (can use a libprocess
    // process for this).
    LOG(INFO) << "Sending SIGKILL to gpid " << osPid[fw->id];
    killpg(osPid[fw->id], SIGKILL);
    osPid[fw->id] = -1;
    fw->executorStatus = "No executor running";
    // TODO(benh): Kill all of the process's descendants? Perhaps
    // create a new libprocess process that continually tries to kill
    // all the processes that are a descendant of the executor, trying
    // to kill the executor last ... maybe this is just too much of a
    // burden?
  }
}

void ProcessBasedIsolationModule::resourcesChanged(Framework* fw)
{
  // Do nothing; subclasses may override this.
}

ExecutorLauncher* ProcessBasedIsolationModule::createExecutorLauncher(Framework* fw)
{
  return new ExecutorLauncher(fw->id, fw->executorInfo.uri, fw->user,
			      slave->getWorkDirectory(fw->id),
			      slave->self(), !slave->local);
}

ProcessBasedIsolationModule::Reaper::Reaper(ProcessBasedIsolationModule* m)
  : module(m)
{}

void ProcessBasedIsolationModule::Reaper::operator () ()
{
  link(module->slave->getPID());
  while (true) {
    switch (receive(1)) {
    case PROCESS_TIMEOUT: {
      // Check whether any child process has exited
      pid_t pid;
      int status;
      if ((pid = waitpid((pid_t) -1, &status, WNOHANG)) > 0) {
	foreachpair (FrameworkID fid, pid_t& fwPid, module->osPid) {
	  if (fwPid == pid) {
	    module->osPid[fid] = -1;
	    module->slave->executorExited(fid, status);
	    break;
	  }
	}
      }
      break;
    }
    case SHUTDOWN_REAPER:
    case PROCESS_EXIT:
      return;
    }
  }
}

<|endoftext|>


<commit_before>
// Note - pyconfig.h must be included before condor_common to avoid
// re-definition warnings.
# include <pyconfig.h>

#include <string>

#include <classad/source.h>
#include <classad/sink.h>

#include "classad_wrapper.h"
#include "exprtree_wrapper.h"
#include "old_boost.h"

ExprTreeHolder::ExprTreeHolder(const std::string &str)
    : m_expr(NULL), m_owns(true)
{
    classad::ClassAdParser parser;
    classad::ExprTree *expr = NULL;
    if (!parser.ParseExpression(str, expr))
    {
        PyErr_SetString(PyExc_SyntaxError, "Unable to parse string into a ClassAd.");
        boost::python::throw_error_already_set();
    }
    m_expr = expr;
}

ExprTreeHolder::ExprTreeHolder(classad::ExprTree *expr, bool owns)
     : m_expr(expr), m_refcount(owns ? expr : NULL), m_owns(owns)
{
}

ExprTreeHolder::~ExprTreeHolder()
{
}

bool ExprTreeHolder::ShouldEvaluate() const
{
    return m_expr->GetKind() == classad::ExprTree::LITERAL_NODE ||
           m_expr->GetKind() == classad::ExprTree::CLASSAD_NODE;
}

boost::python::object ExprTreeHolder::Evaluate() const
{
    if (!m_expr)
    {
        PyErr_SetString(PyExc_RuntimeError, "Cannot operate on an invalid ExprTree");
        boost::python::throw_error_already_set();
    }
    classad::Value value;
    if (m_expr->GetParentScope())
    {
        if (!m_expr->Evaluate(value))
        {
            PyErr_SetString(PyExc_TypeError, "Unable to evaluate expression");
            boost::python::throw_error_already_set();
        }
    }
    else
    {
        classad::EvalState state;
        if (!m_expr->Evaluate(state, value))
        {
            PyErr_SetString(PyExc_TypeError, "Unable to evaluate expression");
            boost::python::throw_error_already_set();
        }
    }
    boost::python::object result;
    std::string strvalue;
    long long intvalue;
    bool boolvalue;
    double realvalue;
    classad::ClassAd *advalue = NULL;
    boost::shared_ptr<ClassAdWrapper> wrap;
    PyObject* obj;
    classad_shared_ptr<classad::ExprList> exprlist;
    switch (value.GetType())
    {
    case classad::Value::CLASSAD_VALUE:
        value.IsClassAdValue(advalue);
        wrap.reset(new ClassAdWrapper());
        wrap->CopyFrom(*advalue);
        result = boost::python::object(wrap);
        break;
    case classad::Value::BOOLEAN_VALUE:
        value.IsBooleanValue(boolvalue);
        obj = boolvalue ? Py_True : Py_False;
        result = boost::python::object(boost::python::handle<>(boost::python::borrowed(obj)));
        break;
    case classad::Value::STRING_VALUE:
        value.IsStringValue(strvalue);
        result = boost::python::str(strvalue);
        break;
    case classad::Value::ABSOLUTE_TIME_VALUE:
    case classad::Value::INTEGER_VALUE:
        value.IsIntegerValue(intvalue);
        result = boost::python::long_(intvalue);
        break;
    case classad::Value::RELATIVE_TIME_VALUE:
    case classad::Value::REAL_VALUE:
        value.IsRealValue(realvalue);
        result = boost::python::object(realvalue);
        break;
    case classad::Value::ERROR_VALUE:
        result = boost::python::object(classad::Value::ERROR_VALUE);
        break;
    case classad::Value::UNDEFINED_VALUE:
        result = boost::python::object(classad::Value::UNDEFINED_VALUE);
        break;
    case classad::Value::SLIST_VALUE:
    case classad::Value::LIST_VALUE:
        value.IsSListValue(exprlist);
        result = boost::python::list();
        for (classad::ExprList::const_iterator it = exprlist->begin(); it != exprlist->end(); it++)
        {
            classad::ExprTree *exprTree = (*it)->Copy();
            ExprTreeHolder exprHolder(exprTree, true);
            result.attr("append")(exprHolder);
        }
        break;
    default:
        PyErr_SetString(PyExc_TypeError, "Unknown ClassAd value type.");
        boost::python::throw_error_already_set();
    }
    return result;
}

boost::python::object ExprTreeHolder::getItem(ssize_t idx)
{
    if (m_expr->GetKind() != classad::ExprTree::EXPR_LIST_NODE)
    {
        PyErr_SetString(PyExc_TypeError, "ClassAd expression is not iterable");
        boost::python::throw_error_already_set();
    }
    std::vector<classad::ExprTree*> exprs;
    classad::ExprList *exprlist = static_cast<classad::ExprList*>(m_expr);
    if (idx >= exprlist->size())
    {
        PyErr_SetString(PyExc_IndexError, "list index out of range");
        boost::python::throw_error_already_set();
    }
    if (idx < 0)
    {
        if (idx < -exprlist->size())
        {
            PyErr_SetString(PyExc_IndexError, "list index out of range");
            boost::python::throw_error_already_set();
        }
        idx = exprlist->size() + idx;
    }
    exprlist->GetComponents(exprs);
    ExprTreeHolder holder(exprs[idx]);
    if (holder.ShouldEvaluate()) return holder.Evaluate();
    return boost::python::object(holder);
}

std::string ExprTreeHolder::toRepr()
{
    if (!m_expr)
    {
        PyErr_SetString(PyExc_RuntimeError, "Cannot operate on an invalid ExprTree");
        boost::python::throw_error_already_set();
    }
    classad::ClassAdUnParser up;
    std::string ad_str;
    up.Unparse(ad_str, m_expr);
    return ad_str;
}

std::string ExprTreeHolder::toString()
{
    if (!m_expr)
    {
        PyErr_SetString(PyExc_RuntimeError, "Cannot operate on an invalid ExprTree");
        boost::python::throw_error_already_set();
    }
    classad::PrettyPrint pp;
    std::string ad_str;
    pp.Unparse(ad_str, m_expr);
    return ad_str;
}

classad::ExprTree *ExprTreeHolder::get()
{
    if (!m_expr)
    {
        PyErr_SetString(PyExc_RuntimeError, "Cannot operate on an invalid ExprTree");
        boost::python::throw_error_already_set();
    }
    return m_expr->Copy();
}

AttrPairToSecond::result_type AttrPairToSecond::operator()(AttrPairToSecond::argument_type p) const
{
    ExprTreeHolder holder(p.second);
    if (holder.ShouldEvaluate())
    {
        return holder.Evaluate();
    }
    boost::python::object result(holder);
    return result;
}

AttrPair::result_type AttrPair::operator()(AttrPair::argument_type p) const
{
    ExprTreeHolder holder(p.second);
    boost::python::object result(holder);
    if (holder.ShouldEvaluate())
    {
        result = holder.Evaluate();
    }
    return boost::python::make_tuple<std::string, boost::python::object>(p.first, result);
}

boost::python::object ClassAdWrapper::LookupWrap(const std::string &attr) const
{
    classad::ExprTree * expr = Lookup(attr);
    if (!expr)
    {
        PyErr_SetString(PyExc_KeyError, attr.c_str());
        boost::python::throw_error_already_set();
    }
    ExprTreeHolder holder(expr);
    if (holder.ShouldEvaluate()) return EvaluateAttrObject(attr);
    return boost::python::object(holder);
}

boost::python::object ClassAdWrapper::get(const std::string attr, boost::python::object default_result) const
{
    classad::ExprTree * expr = Lookup(attr);
    if (!expr)
    {
        return default_result;
    }
    ExprTreeHolder holder(expr);
    if (holder.ShouldEvaluate()) return EvaluateAttrObject(attr);
    boost::python::object result(holder);
    return result;
}

boost::python::object ClassAdWrapper::setdefault(const std::string attr, boost::python::object default_result)
{
    classad::ExprTree *expr = Lookup(attr);
    if (!expr)
    {
        InsertAttrObject(attr, default_result);
        return default_result;
    }
    if (expr->GetKind() == classad::ExprTree::LITERAL_NODE) return EvaluateAttrObject(attr);
    ExprTreeHolder holder(expr);
    boost::python::object result(holder);
    return result;
}

ExprTreeHolder ClassAdWrapper::LookupExpr(const std::string &attr) const
{
    classad::ExprTree * expr = Lookup(attr);
    if (!expr)
    {
        PyErr_SetString(PyExc_KeyError, attr.c_str());
        boost::python::throw_error_already_set();
    }
    ExprTreeHolder holder(expr);
    return holder;
}

boost::python::object ClassAdWrapper::EvaluateAttrObject(const std::string &attr) const
{
    classad::ExprTree *expr;
    if (!(expr = Lookup(attr))) {
        PyErr_SetString(PyExc_KeyError, attr.c_str());
        boost::python::throw_error_already_set();
    }
    ExprTreeHolder holder(expr);
    return holder.Evaluate();
}

classad::ExprTree*
convert_python_to_exprtree(boost::python::object value)
{
    boost::python::extract<ExprTreeHolder&> expr_obj(value);
    if (expr_obj.check())
    {
        return expr_obj().get();
    }
    boost::python::extract<classad::Value::ValueType> value_enum_obj(value);
    if (value_enum_obj.check())
    {
        classad::Value::ValueType value_enum = value_enum_obj();
        classad::Value classad_value;
        if (value_enum == classad::Value::ERROR_VALUE)
        {
            classad_value.SetErrorValue();
            return classad::Literal::MakeLiteral(classad_value);
        }
        else if (value_enum == classad::Value::UNDEFINED_VALUE)
        {
            classad_value.SetUndefinedValue();
            return classad::Literal::MakeLiteral(classad_value);
        }
        PyErr_SetString(PyExc_ValueError, "Unknown ClassAd Value type.");
        boost::python::throw_error_already_set();
    }
    if (PyString_Check(value.ptr()))
    {
        std::string cppvalue = boost::python::extract<std::string>(value);
        classad::Value val; val.SetStringValue(cppvalue);
        return classad::Literal::MakeLiteral(val);
    }
    if (PyLong_Check(value.ptr()))
    {
        long long cppvalue = boost::python::extract<long long>(value);
        classad::Value val; val.SetIntegerValue(cppvalue);
        return classad::Literal::MakeLiteral(val);
    }
    if (PyInt_Check(value.ptr()))
    {
        long int cppvalue = boost::python::extract<long int>(value);
        classad::Value val; val.SetIntegerValue(cppvalue);
        return classad::Literal::MakeLiteral(val);
    }
    if (PyFloat_Check(value.ptr()))
    {
        double cppvalue = boost::python::extract<double>(value);
        classad::Value val; val.SetRealValue(cppvalue);
        return classad::Literal::MakeLiteral(val);
    }
    if (PyDict_Check(value.ptr()))
    {
        boost::python::dict dict = boost::python::extract<boost::python::dict>(value);
        return new ClassAdWrapper(dict);
    }
    PyObject *py_iter = PyObject_GetIter(value.ptr());
    if (py_iter)
    {
        boost::python::object iter = boost::python::object(boost::python::handle<>(py_iter));
        classad::ExprList *classad_list = new classad::ExprList();
        PyObject *obj;
        while ((obj = PyIter_Next(iter.ptr())))
        {
            boost::python::object o = boost::python::object(boost::python::handle<>(obj));
            classad_list->push_back(convert_python_to_exprtree(o));
        }
        return classad_list;
    }
    else
    {
        PyErr_Clear();
    }
    PyErr_SetString(PyExc_TypeError, "Unknown ClassAd value type.");
    boost::python::throw_error_already_set();
    return NULL;
}

void ClassAdWrapper::InsertAttrObject( const std::string &attr, boost::python::object value)
{
    ExprTree *result = convert_python_to_exprtree(value);
    if (!Insert(attr, result))
    {
        PyErr_SetString(PyExc_AttributeError, attr.c_str());
        boost::python::throw_error_already_set();
    }
    return;
}

std::string ClassAdWrapper::toRepr()
{
    classad::ClassAdUnParser up;
    std::string ad_str;
    up.Unparse(ad_str, this);
    return ad_str;
}

std::string ClassAdWrapper::toString()
{
    classad::PrettyPrint pp;
    std::string ad_str;
    pp.Unparse(ad_str, this);
    return ad_str;
}

std::string ClassAdWrapper::toOldString()
{
    classad::ClassAdUnParser pp;
    std::string ad_str;
    pp.SetOldClassAd(true);
    pp.Unparse(ad_str, this);
    return ad_str;
}

AttrKeyIter ClassAdWrapper::beginKeys()
{
    return AttrKeyIter(begin());
}

AttrKeyIter ClassAdWrapper::endKeys()
{
    return AttrKeyIter(end());
}

AttrValueIter ClassAdWrapper::beginValues()
{
    return AttrValueIter(begin());
}

AttrValueIter ClassAdWrapper::endValues()
{
    return AttrValueIter(end());
}

AttrItemIter ClassAdWrapper::beginItems()
{
    return AttrItemIter(begin());
}

AttrItemIter ClassAdWrapper::endItems()
{
    return AttrItemIter(end());
}

ClassAdWrapper::ClassAdWrapper() : classad::ClassAd() {}

ClassAdWrapper::ClassAdWrapper(const boost::python::dict dict)
{
    boost::python::list keys = dict.keys();
    ssize_t len = py_len(keys);
    for (ssize_t idx=0; idx<len; idx++)
    {
        std::string key = boost::python::extract<std::string>(keys[idx]);
        ExprTree *val = convert_python_to_exprtree(dict[keys[idx]]);
        if (!Insert(key, val))
        {
            PyErr_SetString(PyExc_ValueError, ("Unable to insert value into classad for key " + key).c_str());
            boost::python::throw_error_already_set();
        }
    }
}

ClassAdWrapper::ClassAdWrapper(const std::string &str)
{
    classad::ClassAdParser parser;
    classad::ClassAd *result = parser.ParseClassAd(str);
    if (!result)
    {
        PyErr_SetString(PyExc_SyntaxError, "Unable to parse string into a ClassAd.");
        boost::python::throw_error_already_set();
    }
    CopyFrom(*result);
    delete result;
}

ClassAdWrapper::~ClassAdWrapper()
{
}
<commit_msg>Fix handling of cached exprs and python booleans. #3353<commit_after>
// Note - pyconfig.h must be included before condor_common to avoid
// re-definition warnings.
# include <pyconfig.h>

#include <string>

#include <classad/source.h>
#include <classad/sink.h>
#include <classad/classadCache.h>

#include "classad_wrapper.h"
#include "exprtree_wrapper.h"
#include "old_boost.h"

ExprTreeHolder::ExprTreeHolder(const std::string &str)
    : m_expr(NULL), m_owns(true)
{
    classad::ClassAdParser parser;
    classad::ExprTree *expr = NULL;
    if (!parser.ParseExpression(str, expr))
    {
        PyErr_SetString(PyExc_SyntaxError, "Unable to parse string into a ClassAd.");
        boost::python::throw_error_already_set();
    }
    m_expr = expr;
}

ExprTreeHolder::ExprTreeHolder(classad::ExprTree *expr, bool owns)
     : m_expr(expr), m_refcount(owns ? expr : NULL), m_owns(owns)
{
}

ExprTreeHolder::~ExprTreeHolder()
{
}

bool ExprTreeHolder::ShouldEvaluate() const
{
    if (m_expr->GetKind() == classad::ExprTree::EXPR_ENVELOPE)
    {
        classad::CachedExprEnvelope *expr = static_cast<classad::CachedExprEnvelope*>(m_expr);
        return expr->get()->GetKind() == classad::ExprTree::LITERAL_NODE ||
               expr->get()->GetKind() == classad::ExprTree::CLASSAD_NODE;
    }
    return m_expr->GetKind() == classad::ExprTree::LITERAL_NODE ||
           m_expr->GetKind() == classad::ExprTree::CLASSAD_NODE;
}

boost::python::object ExprTreeHolder::Evaluate() const
{
    if (!m_expr)
    {
        PyErr_SetString(PyExc_RuntimeError, "Cannot operate on an invalid ExprTree");
        boost::python::throw_error_already_set();
    }
    classad::Value value;
    if (m_expr->GetParentScope())
    {
        if (!m_expr->Evaluate(value))
        {
            PyErr_SetString(PyExc_TypeError, "Unable to evaluate expression");
            boost::python::throw_error_already_set();
        }
    }
    else
    {
        classad::EvalState state;
        if (!m_expr->Evaluate(state, value))
        {
            PyErr_SetString(PyExc_TypeError, "Unable to evaluate expression");
            boost::python::throw_error_already_set();
        }
    }
    boost::python::object result;
    std::string strvalue;
    long long intvalue;
    bool boolvalue;
    double realvalue;
    classad::ClassAd *advalue = NULL;
    boost::shared_ptr<ClassAdWrapper> wrap;
    PyObject* obj;
    classad_shared_ptr<classad::ExprList> exprlist;
    switch (value.GetType())
    {
    case classad::Value::CLASSAD_VALUE:
        value.IsClassAdValue(advalue);
        wrap.reset(new ClassAdWrapper());
        wrap->CopyFrom(*advalue);
        result = boost::python::object(wrap);
        break;
    case classad::Value::BOOLEAN_VALUE:
        value.IsBooleanValue(boolvalue);
        obj = boolvalue ? Py_True : Py_False;
        result = boost::python::object(boost::python::handle<>(boost::python::borrowed(obj)));
        break;
    case classad::Value::STRING_VALUE:
        value.IsStringValue(strvalue);
        result = boost::python::str(strvalue);
        break;
    case classad::Value::ABSOLUTE_TIME_VALUE:
    case classad::Value::INTEGER_VALUE:
        value.IsIntegerValue(intvalue);
        result = boost::python::long_(intvalue);
        break;
    case classad::Value::RELATIVE_TIME_VALUE:
    case classad::Value::REAL_VALUE:
        value.IsRealValue(realvalue);
        result = boost::python::object(realvalue);
        break;
    case classad::Value::ERROR_VALUE:
        result = boost::python::object(classad::Value::ERROR_VALUE);
        break;
    case classad::Value::UNDEFINED_VALUE:
        result = boost::python::object(classad::Value::UNDEFINED_VALUE);
        break;
    case classad::Value::SLIST_VALUE:
    case classad::Value::LIST_VALUE:
        value.IsSListValue(exprlist);
        result = boost::python::list();
        for (classad::ExprList::const_iterator it = exprlist->begin(); it != exprlist->end(); it++)
        {
            classad::ExprTree *exprTree = (*it)->Copy();
            ExprTreeHolder exprHolder(exprTree, true);
            result.attr("append")(exprHolder);
        }
        break;
    default:
        PyErr_SetString(PyExc_TypeError, "Unknown ClassAd value type.");
        boost::python::throw_error_already_set();
    }
    return result;
}

boost::python::object ExprTreeHolder::getItem(ssize_t idx)
{
    if (m_expr->GetKind() != classad::ExprTree::EXPR_LIST_NODE)
    {
        PyErr_SetString(PyExc_TypeError, "ClassAd expression is not iterable");
        boost::python::throw_error_already_set();
    }
    std::vector<classad::ExprTree*> exprs;
    classad::ExprList *exprlist = static_cast<classad::ExprList*>(m_expr);
    if (idx >= exprlist->size())
    {
        PyErr_SetString(PyExc_IndexError, "list index out of range");
        boost::python::throw_error_already_set();
    }
    if (idx < 0)
    {
        if (idx < -exprlist->size())
        {
            PyErr_SetString(PyExc_IndexError, "list index out of range");
            boost::python::throw_error_already_set();
        }
        idx = exprlist->size() + idx;
    }
    exprlist->GetComponents(exprs);
    ExprTreeHolder holder(exprs[idx]);
    if (holder.ShouldEvaluate()) return holder.Evaluate();
    return boost::python::object(holder);
}

std::string ExprTreeHolder::toRepr()
{
    if (!m_expr)
    {
        PyErr_SetString(PyExc_RuntimeError, "Cannot operate on an invalid ExprTree");
        boost::python::throw_error_already_set();
    }
    classad::ClassAdUnParser up;
    std::string ad_str;
    up.Unparse(ad_str, m_expr);
    return ad_str;
}

std::string ExprTreeHolder::toString()
{
    if (!m_expr)
    {
        PyErr_SetString(PyExc_RuntimeError, "Cannot operate on an invalid ExprTree");
        boost::python::throw_error_already_set();
    }
    classad::PrettyPrint pp;
    std::string ad_str;
    pp.Unparse(ad_str, m_expr);
    return ad_str;
}

classad::ExprTree *ExprTreeHolder::get()
{
    if (!m_expr)
    {
        PyErr_SetString(PyExc_RuntimeError, "Cannot operate on an invalid ExprTree");
        boost::python::throw_error_already_set();
    }
    return m_expr->Copy();
}

AttrPairToSecond::result_type AttrPairToSecond::operator()(AttrPairToSecond::argument_type p) const
{
    ExprTreeHolder holder(p.second);
    if (holder.ShouldEvaluate())
    {
        return holder.Evaluate();
    }
    boost::python::object result(holder);
    return result;
}

AttrPair::result_type AttrPair::operator()(AttrPair::argument_type p) const
{
    ExprTreeHolder holder(p.second);
    boost::python::object result(holder);
    if (holder.ShouldEvaluate())
    {
        result = holder.Evaluate();
    }
    return boost::python::make_tuple<std::string, boost::python::object>(p.first, result);
}

boost::python::object ClassAdWrapper::LookupWrap(const std::string &attr) const
{
    classad::ExprTree * expr = Lookup(attr);
    if (!expr)
    {
        PyErr_SetString(PyExc_KeyError, attr.c_str());
        boost::python::throw_error_already_set();
    }
    ExprTreeHolder holder(expr);
    if (holder.ShouldEvaluate()) return EvaluateAttrObject(attr);
    return boost::python::object(holder);
}

boost::python::object ClassAdWrapper::get(const std::string attr, boost::python::object default_result) const
{
    classad::ExprTree * expr = Lookup(attr);
    if (!expr)
    {
        return default_result;
    }
    ExprTreeHolder holder(expr);
    if (holder.ShouldEvaluate()) return EvaluateAttrObject(attr);
    boost::python::object result(holder);
    return result;
}

boost::python::object ClassAdWrapper::setdefault(const std::string attr, boost::python::object default_result)
{
    classad::ExprTree *expr = Lookup(attr);
    if (!expr)
    {
        InsertAttrObject(attr, default_result);
        return default_result;
    }
    if (expr->GetKind() == classad::ExprTree::LITERAL_NODE) return EvaluateAttrObject(attr);
    ExprTreeHolder holder(expr);
    boost::python::object result(holder);
    return result;
}

ExprTreeHolder ClassAdWrapper::LookupExpr(const std::string &attr) const
{
    classad::ExprTree * expr = Lookup(attr);
    if (!expr)
    {
        PyErr_SetString(PyExc_KeyError, attr.c_str());
        boost::python::throw_error_already_set();
    }
    ExprTreeHolder holder(expr);
    return holder;
}

boost::python::object ClassAdWrapper::EvaluateAttrObject(const std::string &attr) const
{
    classad::ExprTree *expr;
    if (!(expr = Lookup(attr))) {
        PyErr_SetString(PyExc_KeyError, attr.c_str());
        boost::python::throw_error_already_set();
    }
    ExprTreeHolder holder(expr);
    return holder.Evaluate();
}

classad::ExprTree*
convert_python_to_exprtree(boost::python::object value)
{
    boost::python::extract<ExprTreeHolder&> expr_obj(value);
    if (expr_obj.check())
    {
        return expr_obj().get();
    }
    boost::python::extract<classad::Value::ValueType> value_enum_obj(value);
    if (value_enum_obj.check())
    {
        classad::Value::ValueType value_enum = value_enum_obj();
        classad::Value classad_value;
        if (value_enum == classad::Value::ERROR_VALUE)
        {
            classad_value.SetErrorValue();
            return classad::Literal::MakeLiteral(classad_value);
        }
        else if (value_enum == classad::Value::UNDEFINED_VALUE)
        {
            classad_value.SetUndefinedValue();
            return classad::Literal::MakeLiteral(classad_value);
        }
        PyErr_SetString(PyExc_ValueError, "Unknown ClassAd Value type.");
        boost::python::throw_error_already_set();
    }
    if (PyBool_Check(value.ptr()))
    {
        bool cppvalue = boost::python::extract<bool>(value);
        classad::Value val; val.SetBooleanValue(cppvalue);
        return classad::Literal::MakeLiteral(val);
    }
    if (PyString_Check(value.ptr()))
    {
        std::string cppvalue = boost::python::extract<std::string>(value);
        classad::Value val; val.SetStringValue(cppvalue);
        return classad::Literal::MakeLiteral(val);
    }
    if (PyLong_Check(value.ptr()))
    {
        long long cppvalue = boost::python::extract<long long>(value);
        classad::Value val; val.SetIntegerValue(cppvalue);
        return classad::Literal::MakeLiteral(val);
    }
    if (PyInt_Check(value.ptr()))
    {
        long int cppvalue = boost::python::extract<long int>(value);
        classad::Value val; val.SetIntegerValue(cppvalue);
        return classad::Literal::MakeLiteral(val);
    }
    if (PyFloat_Check(value.ptr()))
    {
        double cppvalue = boost::python::extract<double>(value);
        classad::Value val; val.SetRealValue(cppvalue);
        return classad::Literal::MakeLiteral(val);
    }
    if (PyDict_Check(value.ptr()))
    {
        boost::python::dict dict = boost::python::extract<boost::python::dict>(value);
        return new ClassAdWrapper(dict);
    }
    PyObject *py_iter = PyObject_GetIter(value.ptr());
    if (py_iter)
    {
        boost::python::object iter = boost::python::object(boost::python::handle<>(py_iter));
        classad::ExprList *classad_list = new classad::ExprList();
        PyObject *obj;
        while ((obj = PyIter_Next(iter.ptr())))
        {
            boost::python::object o = boost::python::object(boost::python::handle<>(obj));
            classad_list->push_back(convert_python_to_exprtree(o));
        }
        return classad_list;
    }
    else
    {
        PyErr_Clear();
    }
    PyErr_SetString(PyExc_TypeError, "Unknown ClassAd value type.");
    boost::python::throw_error_already_set();
    return NULL;
}

void ClassAdWrapper::InsertAttrObject( const std::string &attr, boost::python::object value)
{
    ExprTree *result = convert_python_to_exprtree(value);
    if (!Insert(attr, result))
    {
        PyErr_SetString(PyExc_AttributeError, attr.c_str());
        boost::python::throw_error_already_set();
    }
    return;
}

std::string ClassAdWrapper::toRepr()
{
    classad::ClassAdUnParser up;
    std::string ad_str;
    up.Unparse(ad_str, this);
    return ad_str;
}

std::string ClassAdWrapper::toString()
{
    classad::PrettyPrint pp;
    std::string ad_str;
    pp.Unparse(ad_str, this);
    return ad_str;
}

std::string ClassAdWrapper::toOldString()
{
    classad::ClassAdUnParser pp;
    std::string ad_str;
    pp.SetOldClassAd(true);
    pp.Unparse(ad_str, this);
    return ad_str;
}

AttrKeyIter ClassAdWrapper::beginKeys()
{
    return AttrKeyIter(begin());
}

AttrKeyIter ClassAdWrapper::endKeys()
{
    return AttrKeyIter(end());
}

AttrValueIter ClassAdWrapper::beginValues()
{
    return AttrValueIter(begin());
}

AttrValueIter ClassAdWrapper::endValues()
{
    return AttrValueIter(end());
}

AttrItemIter ClassAdWrapper::beginItems()
{
    return AttrItemIter(begin());
}

AttrItemIter ClassAdWrapper::endItems()
{
    return AttrItemIter(end());
}

ClassAdWrapper::ClassAdWrapper() : classad::ClassAd() {}

ClassAdWrapper::ClassAdWrapper(const boost::python::dict dict)
{
    boost::python::list keys = dict.keys();
    ssize_t len = py_len(keys);
    for (ssize_t idx=0; idx<len; idx++)
    {
        std::string key = boost::python::extract<std::string>(keys[idx]);
        ExprTree *val = convert_python_to_exprtree(dict[keys[idx]]);
        if (!Insert(key, val))
        {
            PyErr_SetString(PyExc_ValueError, ("Unable to insert value into classad for key " + key).c_str());
            boost::python::throw_error_already_set();
        }
    }
}

ClassAdWrapper::ClassAdWrapper(const std::string &str)
{
    classad::ClassAdParser parser;
    classad::ClassAd *result = parser.ParseClassAd(str);
    if (!result)
    {
        PyErr_SetString(PyExc_SyntaxError, "Unable to parse string into a ClassAd.");
        boost::python::throw_error_already_set();
    }
    CopyFrom(*result);
    delete result;
}

ClassAdWrapper::~ClassAdWrapper()
{
}
<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <std_msgs/String.h>
#include <qbot/NavCmd.h>
#include <qbot/SpcCmd.h>
#include <qbot/NavRes.h>
#include <qbot/SpcRes.h>
#include <qbot/NLPRes.h>
#include <qbot/GuiRes.h>
#include <qbot/CncStatus.h>

#include <iostream>  //declaring variables
#include <string>
#include <fstream>
#include <vector>

const int bufferSize = 1000;
uint8_t sys_state = 0;
std::vector<std::string> questions;

class Command_Node{
private:
	ros::Publisher navPub_;
	ros::Publisher spcPub_;
	ros::Publisher movenaoPub_;
	ros::Subscriber navSub_;
	//ros::Subscriber spcSub_;
	ros::Subscriber nlpSub_;
	ros::Subscriber guiSub_;
	uint8_t qnum;
	std::string response;
	//std::vector<std::string>& qnlist;

public:
	Command_Node(ros::NodeHandle& n){
		navPub_ = n.advertise<qbot::NavCmd>("/CNC_2_NAV", bufferSize);
		spcPub_ = n.advertise<qbot::SpcCmd>("/CNC_2_SPC", bufferSize);
		movenaoPub_ = n.advertise<std_msgs::String>("/posture", bufferSize);
		navSub_ = n.subscribe("/NAV_2_CNC", bufferSize, &Command_Node::navCallback, this);
		//spcSub_ = n.subscribe("/SPC_2_CNC", bufferSize, &Command_Node::spcCallback, this);
		nlpSub_ = n.subscribe("/NLP_2_CNC", bufferSize, &Command_Node::nlpCallback, this);
		guiSub_ = n.subscribe("/GUI_2_CNC", bufferSize, &Command_Node::guiCallback, this);

		qnum=0;

		// TODO: insert logic to enter starting parameters like bed ward etc

	}

	void guiCallback(const qbot::GuiRes& guires){

		if(guires.cmdcode==100){
			qbot::NavCmd navcmd;
			navcmd.status = 0; // tell it to stop
			navPub_.publish(navcmd);

			qbot::SpcCmd spccmd;
			spccmd.question = "Hang on, something has gone wrong. Sorry about that.";
			spcPub_.publish(spccmd);

			ROS_INFO("QBot Emergency ABORT");
			sys_state = 100; // ALERT OPERATOR
		}
		else if(guires.cmdcode==101){
			ROS_INFO("QBot RESET");
			sys_state = 0;
			qnum = 0;

			std_msgs::String msg;
			msg.data = "Sit";
			movenaoPub_.publish(msg);
			ros::Duration(5).sleep();

		}
		else if(guires.cmdcode==1 && sys_state==0){
			ROS_INFO("QBot Activated");
			sys_state = 1;
		}

		// TODO: vvv confirm what triggers the introduction
		if((guires.cmdcode==200 && sys_state==11) || (guires.cmdcode==250) ){

			/*
		    std_msgs::String msg;
			msg.data = "Stand";
			movenaoPub_.publish(msg);

			ros::Duration(10).sleep();*/

			sys_state = 20; // 20: able to start question

			qbot::SpcCmd spccmd;
			spccmd.question = "Hello I am QBot, what is your name?";
			spcPub_.publish(spccmd);

			ROS_INFO("Introducing...\n");

		}

	}

	void navCallback(const qbot::NavRes& navres){

		//if not navigating or not reached
		if(navres.status!=1 && sys_state==1){
			qbot::NavCmd navcmd;
			navcmd.status = 1; // tell it to move
			navcmd.floor = 1;
			navcmd.room = 10;
			navcmd.bed = 5;
			navPub_.publish(navcmd);
			ROS_INFO("Start Navigation...");
			sys_state = 10;
		}
		else if(sys_state==10){
			qbot::NavCmd navcmd;
			navcmd.status = 0; // tell it to stop
			navPub_.publish(navcmd);
			ROS_INFO("Stop Navigation...");

			sys_state = 11;
		}

	}

	void nlpCallback(const qbot::NLPRes& nlpres){

		if(sys_state==20){

		    sys_state = 21; // 21: Checking to start

			if(nlpres.res_type==0){
				response = nlpres.response;
				ROS_INFO("Reply: %s \n", response.c_str());

				qbot::SpcCmd spccmd;
				spccmd.question = "Nice to meet you " + response + ". Are you ready to start?";
				spcPub_.publish(spccmd);
				ROS_INFO("QBot: Nice to meet you [Name]" );
			}
			else{
				qbot::SpcCmd spccmd;
				spccmd.question = "Nice to meet you. Are you ready to start?";
				spcPub_.publish(spccmd);
				ROS_INFO("QBot: Nice to meet you" );
			}

		}
		else if(sys_state==21){
			if(nlpres.res_type==0){
				response = nlpres.response;
				ROS_INFO("Reply: %s \n", response.c_str());

				if(response.compare("yes") == 0){
				    sys_state = 22; // 22 In progress with questioning

					qbot::SpcCmd spccmd;
					spccmd.question = questions.at(qnum);
					spcPub_.publish(spccmd);
					ROS_INFO("QBot: %s ", questions[qnum].c_str());
				}
				else{
					qbot::SpcCmd spccmd;
					spccmd.question = "Are you ready to Start?";
					spcPub_.publish(spccmd);
					ROS_INFO("QBot: Are you ready to Start?" );
				}
			}
			else{
				qbot::SpcCmd spccmd;
				spccmd.question = "Are you ready to Start?";
				spcPub_.publish(spccmd);
				ROS_INFO("QBot: Are you ready to Start?" );
			}
		}
		else if(sys_state==22 && nlpres.res_type==0){
			response = nlpres.response;
			ROS_INFO("Reply: %s \n", response.c_str());

			qnum++;

			if(qnum < (int)questions.size()){
				qbot::SpcCmd spccmd;
				spccmd.question = questions.at(qnum);
				spcPub_.publish(spccmd);
				ROS_INFO("QBot: %s ", questions[qnum].c_str());
			}
			else sys_state=30; // finished
		}
		else if((nlpres.res_type==1||nlpres.res_type==2) && sys_state==22){
			response = nlpres.response;
			ROS_INFO("Reply: %s \n", response.c_str());

			// Got gibberish; ask same question again
			qbot::SpcCmd spccmd;
			spccmd.question = "Sorry I didn't catch that, " + questions.at(qnum);
			spcPub_.publish(spccmd);
			ROS_INFO("QBot: %s ", questions[qnum].c_str());
		}

		//Other responses
		if(nlpres.res_type==3){
			qbot::SpcCmd spccmd;
			spccmd.question = "Okay, we will take a short break";
			spcPub_.publish(spccmd);

			ROS_INFO("Taking break...\n");

			sys_state = 203; // 203: able to start question
		}
		if(nlpres.res_type==4){
			qbot::SpcCmd spccmd;
			spccmd.question = "Hang on, I will contact the nurse";
			spcPub_.publish(spccmd);

			ROS_INFO("Contact Nurse...\n");

			sys_state = 204; // 203: able to start question
		}

	}

};

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

	std::string line;
	std::ofstream outfile;
    std::ifstream infile("/home/human/catkin_ws/src/qbot/src/questions.txt");

    if(infile.is_open())
    {
    	while(!infile.eof())
    	{
    		std::getline(infile, line);
    		questions.push_back(line);
    	}
    }
    else{
    	std::cout << "Unable to open file" << std::endl;
    	exit(1);
    }

    infile.close();

    std::cout << "Size of questions: " << questions.size() << std::endl;

	ros::init(argc, argv, "command_module");
	ros::NodeHandle n;

	Command_Node cmdnode(n);
	ROS_INFO("Command Node Started");

	ros::Publisher cncPub_ = n.advertise<qbot::CncStatus>("/CNC_STATUS", bufferSize);
	ros::Rate loop_rate(10);

	while(ros::ok()){

		qbot::CncStatus cncstatus;
		cncstatus.sys_state = sys_state;
		cncPub_.publish(cncstatus);

		ros::spinOnce();

		loop_rate.sleep();
	}
	return 0;
}

<commit_msg>Sze: Update CNC outro<commit_after>#include <ros/ros.h>
#include <std_msgs/String.h>
#include <qbot/NavCmd.h>
#include <qbot/SpcCmd.h>
#include <qbot/NavRes.h>
#include <qbot/SpcRes.h>
#include <qbot/NLPRes.h>
#include <qbot/GuiRes.h>
#include <qbot/CncStatus.h>

#include <iostream>  //declaring variables
#include <string>
#include <fstream>
#include <vector>

const int bufferSize = 1000;
uint8_t sys_state = 0;
std::vector<std::string> questions;

class Command_Node{
private:
	ros::Publisher navPub_;
	ros::Publisher spcPub_;
	ros::Publisher movenaoPub_;
	ros::Subscriber navSub_;
	//ros::Subscriber spcSub_;
	ros::Subscriber nlpSub_;
	ros::Subscriber guiSub_;
	uint8_t qnum;
	std::string response;
	std::ofstream outfile;
	//std::vector<std::string>& qnlist;

public:
	Command_Node(ros::NodeHandle& n){
		navPub_ = n.advertise<qbot::NavCmd>("/CNC_2_NAV", bufferSize);
		spcPub_ = n.advertise<qbot::SpcCmd>("/CNC_2_SPC", bufferSize);
		movenaoPub_ = n.advertise<std_msgs::String>("/posture", bufferSize);
		navSub_ = n.subscribe("/NAV_2_CNC", bufferSize, &Command_Node::navCallback, this);
		//spcSub_ = n.subscribe("/SPC_2_CNC", bufferSize, &Command_Node::spcCallback, this);
		nlpSub_ = n.subscribe("/NLP_2_CNC", bufferSize, &Command_Node::nlpCallback, this);
		guiSub_ = n.subscribe("/GUI_2_CNC", bufferSize, &Command_Node::guiCallback, this);

		qnum=0;

		outfile.open("PatientResponses01.txt");

		// TODO: insert logic to enter starting parameters like bed ward etc

	}

	void guiCallback(const qbot::GuiRes& guires){

		if(guires.cmdcode==100){
			qbot::NavCmd navcmd;
			navcmd.status = 0; // tell it to stop
			navPub_.publish(navcmd);

			qbot::SpcCmd spccmd;
			spccmd.question = "Hang on, something has gone wrong. Sorry about that.";
			spcPub_.publish(spccmd);

			ROS_INFO("QBot Emergency ABORT");
			sys_state = 100; // ALERT OPERATOR
		}
		else if(guires.cmdcode==101){
			ROS_INFO("QBot RESET");
			sys_state = 0;
			qnum = 0;

			std_msgs::String msg;
			msg.data = "Sit";
			movenaoPub_.publish(msg);
			ros::Duration(5).sleep();

		}
		else if(guires.cmdcode==1 && sys_state==0){
			ROS_INFO("QBot Activated");
			sys_state = 1;
		}

		// TODO: vvv confirm what triggers the introduction
		if((guires.cmdcode==200 && sys_state==11) || (guires.cmdcode==250) ){

			/*
		    std_msgs::String msg;
			msg.data = "Stand";
			movenaoPub_.publish(msg);

			ros::Duration(10).sleep();*/

			sys_state = 20; // 20: able to start question

			qbot::SpcCmd spccmd;
			spccmd.question = "Hello I am QBot, what is your name?";
			spcPub_.publish(spccmd);

			ROS_INFO("Introducing...\n");

		}

	}

	void navCallback(const qbot::NavRes& navres){

		//if not navigating or not reached
		if(navres.status!=1 && sys_state==1){
			qbot::NavCmd navcmd;
			navcmd.status = 1; // tell it to move
			navcmd.floor = 1;
			navcmd.room = 10;
			navcmd.bed = 5;
			navPub_.publish(navcmd);
			ROS_INFO("Start Navigation...");
			sys_state = 10;
		}
		else if(sys_state==10){
			qbot::NavCmd navcmd;
			navcmd.status = 0; // tell it to stop
			navPub_.publish(navcmd);
			ROS_INFO("Stop Navigation...");

			sys_state = 11;
		}

	}

	void nlpCallback(const qbot::NLPRes& nlpres){

		if(sys_state==20){

		    sys_state = 21; // 21: Checking to start

			if(nlpres.res_type==0){
				response = nlpres.response;
				ROS_INFO("Reply: %s \n", response.c_str());

				qbot::SpcCmd spccmd;
				spccmd.question = "Nice to meet you " + response + ". Are you ready to start?";
				spcPub_.publish(spccmd);
				ROS_INFO("QBot: Nice to meet you [Name]" );
			}
			else{
				qbot::SpcCmd spccmd;
				spccmd.question = "Nice to meet you. Are you ready to start?";
				spcPub_.publish(spccmd);
				ROS_INFO("QBot: Nice to meet you" );
			}

		}
		else if(sys_state==21){
			if(nlpres.res_type==0){
				response = nlpres.response;
				ROS_INFO("Reply: %s \n", response.c_str());

				if(response.compare("yes") == 0){
				    sys_state = 22; // 22 In progress with questioning

					qbot::SpcCmd spccmd;
					spccmd.question = questions.at(qnum);
					spcPub_.publish(spccmd);
					ROS_INFO("QBot: %s ", questions[qnum].c_str());
				}
				else{
					qbot::SpcCmd spccmd;
					spccmd.question = "Are you ready to Start?";
					spcPub_.publish(spccmd);
					ROS_INFO("QBot: Are you ready to Start?" );
				}
			}
			else{
				qbot::SpcCmd spccmd;
				spccmd.question = "Are you ready to Start?";
				spcPub_.publish(spccmd);
				ROS_INFO("QBot: Are you ready to Start?" );
			}
		}
		else if(sys_state==22 && nlpres.res_type==0){
			response = nlpres.response;
			ROS_INFO("Reply: %s \n", response.c_str());

			qnum++;

			outfile << qnum << ") " << response << std::endl;

			if(qnum < (int)questions.size()){
				qbot::SpcCmd spccmd;
				spccmd.question = questions.at(qnum);
				spcPub_.publish(spccmd);
				ROS_INFO("QBot: %s ", questions[qnum].c_str());
			}
			else{
			    outfile << "-----===== END =====-----" << std::endl;
			    outfile.close();

			    sys_state=30; // finished

			    qbot::SpcCmd spccmd;
				spccmd.question = "Thank you for your time. QBot out.";
				spcPub_.publish(spccmd);
				ROS_INFO("QBot: Thank you for your time. QBot out." );
			}
		}
		else if((nlpres.res_type==1||nlpres.res_type==2) && sys_state==22){
			response = nlpres.response;
			ROS_INFO("Reply: %s \n", response.c_str());

			// Got gibberish; ask same question again
			qbot::SpcCmd spccmd;
			spccmd.question = "Sorry I didn't catch that, " + questions.at(qnum);
			spcPub_.publish(spccmd);
			ROS_INFO("QBot: %s ", questions[qnum].c_str());
		}

		//Other responses
		if(nlpres.res_type==3){
			qbot::SpcCmd spccmd;
			spccmd.question = "Okay, we will take a short break";
			spcPub_.publish(spccmd);

			ROS_INFO("Taking break...\n");

			sys_state = 203; // 203: able to start question
		}
		if(nlpres.res_type==4){
			qbot::SpcCmd spccmd;
			spccmd.question = "Hang on, I will contact the nurse";
			spcPub_.publish(spccmd);

			ROS_INFO("Contact Nurse...\n");

			sys_state = 204; // 203: able to start question
		}

	}

};

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

	std::string line;

    std::ifstream infile("/home/human/catkin_ws/src/qbot/src/questions.txt");

    if(infile.is_open())
    {
    	while(!infile.eof())
    	{
    		std::getline(infile, line);
    		questions.push_back(line);
    	}
    }
    else{
    	std::cout << "Unable to open file" << std::endl;
    	exit(1);
    }

    infile.close();

    std::cout << "Size of questions: " << questions.size() << std::endl;

	ros::init(argc, argv, "command_module");
	ros::NodeHandle n;

	Command_Node cmdnode(n);
	ROS_INFO("Command Node Started");

	ros::Publisher cncPub_ = n.advertise<qbot::CncStatus>("/CNC_STATUS", bufferSize);
	ros::Rate loop_rate(10);

	while(ros::ok()){

		qbot::CncStatus cncstatus;
		cncstatus.sys_state = sys_state;
		cncPub_.publish(cncstatus);

		ros::spinOnce();

		loop_rate.sleep();
	}
	return 0;
}

<|endoftext|>


<commit_before>// Example STEP-NC Program using C++/CLI
// ========================================
//
// This sample C++ project calls the STEP-NC Machine Programming API
// using the .NET interface with C++/CLI calls.  The program creates a
// small machining program with a few toolpath moves.
//
// The project creates a command line program that writes test.stpnc.
// You can find more examples and other programming documentation at:
//
//	http://www.steptools.com/support/stepnc_docs/
//
#include "MtConnector.h"
using namespace System;

using namespace System::Xml;
using namespace System::Collections::Generic;

//array<int>^ CurrentPos(String ^xml)
List<array<double>^> ^  coordinates(String ^fileName,bool convert_to_inches){
//create instance of the xml reader

	XmlDocument ^doc = gcnew XmlDocument();
	doc->Load(fileName);
	XmlNode ^root = doc->DocumentElement;

		XmlNamespaceManager ^nsmgr = gcnew XmlNamespaceManager(doc->NameTable);
		nsmgr->AddNamespace("base", root->NamespaceURI);

		List<array<double>^> ^Lst = gcnew List<array<double>^>();
		String ^str;
		XmlNodeList^ pathList = root->SelectNodes("//base:PathPosition", nsmgr);

		array<double> ^coor;
		for (int i=0;i<pathList->Count;i++){
			XmlNode^ temp=pathList->Item(i);
			str=temp->InnerText;
			if(str!="UNAVAILABLE"){
			//Console::WriteLine(str);
			array<String^>^ arr;
			arr=str->Split(' ');
			coor=gcnew array<double>(3);
			try
			{
			coor[0]=Convert::ToDouble(arr[0]);
			coor[1]=Convert::ToDouble(arr[1]);
			coor[2]=Convert::ToDouble(arr[2]);
			if(convert_to_inches){
			coor[0]=coor[0]*0.0393701;
			coor[1]=coor[1]*0.0393701;
			coor[2]=coor[2]*0.0393701;

			}
			//Console::WriteLine(arr[0]);
			//Console::WriteLine(coor[0]);
			Lst->Add((array<double> ^)coor->Clone());
			}
			catch (Exception^ e){
			Console::WriteLine(e);

			}
			}

		}
return Lst;
}

void PullFromServer(MtConnector ^ mt){

STEPNCLib::AptStepMaker ^ apt = gcnew STEPNCLib::AptStepMaker();

	////////////////////////
   STEPNCLib::Finder ^find = gcnew STEPNCLib::Finder();
   apt->Inches();

   apt->Open238 ("hardmoldy_ext.stpnc");
    find->Open238 ("hardmoldy_ext.stpnc");
	//feat->OpenSpecificWorkpiece("test_with_rawpiece2.stpnc","HardModly_design.stp");

    int wp_id = find->GetMainWorkplan();
	Console::WriteLine("Main Workplan name %S\n", (find->GetExecutableName(wp_id)));

    // add a new workplan at the end of the project
    apt->NestWorkplanAfter("Workplan for new results", find->GetWorkplanExecutableCount(wp_id) + 1, wp_id);

    // Starting first workingstep in new plan

    // Create a trivial STEP-NC file
    apt->Workingstep("Extension 1");

    // Create a trivial STEP-NC file
    apt->PartNo ("test part");
	 apt->Rawpiece ("HardMoldy_stock.stp");
    long raw_id = apt->GetCurrentRawpiece ();
	 apt->DefineTool(0.25, 5.0, 1.0, 2.0, 3.0, 4.0, 5.0);
    apt->PutWorkpiecePlacement (raw_id, 0, 0, 0, 0, 0, -1, 1, 0, 0);
	apt->GeometryForToolNumber ("Iscar_2.stp", 1);
    apt->LoadTool (1);
     apt->SpindleSpeed (300);
    apt->Feedrate (30);

		apt->GoToXYZ("point0", 0,0,200);
		apt->GoToXYZ("point0", 0,0,200);

   String ^str;
	array<double>^ coor;
	for (int i=0;i<100;i++){
		//Console::WriteLine(i);
	coor=mt->getPos();
	if(coor!=nullptr){

		str= gcnew String(String::Format("point {0} ",i));
		Console::WriteLine(str);
        Console::WriteLine(coor[0]);

		apt->GoToXYZ(str, coor[0]*0.0393701, coor[1]*0.0393701, coor[2]*0.0393701);
	}
	}

    apt->SaveAsModules("hardmoldy_extended");
	Console::WriteLine("done");
	String ^readIn =Console::ReadLine();

}

void appendToFile(String^ file_name,String^ new_file_name,bool convert_to_inches){
	List<array<double>^> ^coor_List= coordinates(file_name,convert_to_inches);
    // Create a trivial STEP-NC file
	Console::WriteLine("Got Position Data From File");
    STEPNCLib::AptStepMaker ^ apt = gcnew STEPNCLib::AptStepMaker();

	////////////////////////
   STEPNCLib::Finder ^find = gcnew STEPNCLib::Finder();

	    //	    APT.Open238("new_hardmoldy.stpnc");
	    //	    Find.Open238("new_hardmoldy.stpnc");
	    apt->Open238("hardmoldy_ext.stpnc");
	    apt->Open238("hardmoldy_ext.stpnc");

	    long wp_id = find->GetMainWorkplan();
	    Console::WriteLine("Main Workplan name " + find->GetExecutableName(wp_id));

	    // add a new workplan at the end of the project
	    apt->NestWorkplanAfter("Workplan for MTConnect results", find->GetWorkplanExecutableCount(wp_id) + 1, wp_id);

	    // Starting first workingstep in new plan
	    apt->Workingstep("testing");

//////////////////////////
    //apt->PartNo("test part");
    //apt->DefineTool(0.25, 5.0, 1.0, 2.0, 3.0, 4.0, 5.0);
	//apt->GeometryForToolNumber ("Iscar_2.stp", 1);

		//String^ boeingTool=find->GetToolNumberAsNumber()
		Console::WriteLine("is tool defined {0}",apt->IsToolDefined(1));
			apt->LoadTool(1);
    apt->SpindleSpeed (300);
    apt->Feedrate (30);
	String ^str;
	array<double>^ coor;
	for (int i=0;i<coor_List->Count;i++){
		coor=coor_List[i];

		str=String::Format("point {0} ",i+1);
		//Console::WriteLine(str);
		//Console::WriteLine(" {0} {1} {2}",coor[0],coor[1],coor[2]);

		apt->GoToXYZ(str, coor[0], coor[1], coor[2]);

	}

	apt->SaveAsModules(new_file_name);
	Console::WriteLine("done");

}

long long GetWorkplan(String^name,STEPNCLib::AptStepMaker ^ apt, STEPNCLib::Finder ^find){

long long wp_id = find->GetMainWorkplan();
String^ str=nullptr;

str=find->GetExecutableName (wp_id);
	if(str!=nullptr){
		Console::WriteLine("Workplan name: %s\n", str);
		List<long long>^nestedPlans =find->GetWorkplanExecutableAll (wp_id);
		for each (long long x in nestedPlans){
		str=find->GetExecutableName (x);
	if(str!=nullptr){
		Console::WriteLine("Workplan name: %s\n", str);}

	if(str==name){
		return x;
		}

		}

	}

}

List<array<double>^> ^ GetRapidToolPaths()
{

}

*/
int main(int argc, char * argv[])
{

	MtConnector ^ mt;
	mt=gcnew MtConnector();
	//mt->startPush("http://okuma-matata:5000/sample?count=1000&interval=10&path=//Path/DataItems/DataItem[@id=\"Mp1LPathPos\"]");
	//http://agent.mtconnect.org/VMC-3Axis/sample?count=1000&interval=10&path=//Path/DataItems/DataItem[@category=\"SAMPLE\"]"
	//http://okuma-matata:5000/sample?count=1000&interval=10

	//mt->getRequest("http://okuma-matata:5000/sample?count=1000&interval=10&path=//Path/DataItems/DataItem[@id=\"Mp1LPathPos\"]");
	//PullFromServer(mt);
    appendToFile("moldy_data_iteration_2.xml","moldy.stpnc",true);

	String ^readIn =Console::ReadLine();
	return 0;
}

<commit_msg>//Began algorithm to patch segments of position data where the path changes for Feed to Rapid or Rapid to Feed<commit_after>// Example STEP-NC Program using C++/CLI
// ========================================
//
// This sample C++ project calls the STEP-NC Machine Programming API
// using the .NET interface with C++/CLI calls.  The program creates a
// small machining program with a few toolpath moves.
//
// The project creates a command line program that writes test.stpnc.
// You can find more examples and other programming documentation at:
//
//	http://www.steptools.com/support/stepnc_docs/
//
#include "MtConnector.h"
using namespace System;

using namespace System::Xml;
using namespace System::Collections::Generic;

//array<int>^ CurrentPos(String ^xml)
List<array<double>^> ^  coordinates(String ^fileName,bool convert_to_inches){
//create instance of the xml reader

	XmlDocument ^doc = gcnew XmlDocument();
	doc->Load(fileName);
	XmlNode ^root = doc->DocumentElement;

		XmlNamespaceManager ^nsmgr = gcnew XmlNamespaceManager(doc->NameTable);
		nsmgr->AddNamespace("base", root->NamespaceURI);

		List<array<double>^> ^Lst = gcnew List<array<double>^>();
		String ^str;
		XmlNodeList^ pathList = root->SelectNodes("//base:PathPosition", nsmgr);

		array<double> ^coor;
		for (int i=0;i<pathList->Count;i++){
			XmlNode^ temp=pathList->Item(i);
			str=temp->InnerText;
			if(str!="UNAVAILABLE"){
			//Console::WriteLine(str);
			array<String^>^ arr;
			arr=str->Split(' ');
			coor=gcnew array<double>(3);
			try
			{
			coor[0]=Convert::ToDouble(arr[0]);
			coor[1]=Convert::ToDouble(arr[1]);
			coor[2]=Convert::ToDouble(arr[2]);
			if(convert_to_inches){
			coor[0]=coor[0]*0.0393701;
			coor[1]=coor[1]*0.0393701;
			coor[2]=coor[2]*0.0393701;

			}
			//Console::WriteLine(arr[0]);
			//Console::WriteLine(coor[0]);
			Lst->Add((array<double> ^)coor->Clone());
			}
			catch (Exception^ e){
			Console::WriteLine(e);

			}
			}

		}
return Lst;
}

void PullFromServer(MtConnector ^ mt){

STEPNCLib::AptStepMaker ^ apt = gcnew STEPNCLib::AptStepMaker();

	////////////////////////
   STEPNCLib::Finder ^find = gcnew STEPNCLib::Finder();
   apt->Inches();

   apt->Open238 ("hardmoldy_ext.stpnc");
    find->Open238 ("hardmoldy_ext.stpnc");
	//feat->OpenSpecificWorkpiece("test_with_rawpiece2.stpnc","HardModly_design.stp");

    int wp_id = find->GetMainWorkplan();
	Console::WriteLine("Main Workplan name %S\n", (find->GetExecutableName(wp_id)));

    // add a new workplan at the end of the project
    apt->NestWorkplanAfter("Workplan for new results", find->GetWorkplanExecutableCount(wp_id) + 1, wp_id);

    // Starting first workingstep in new plan

    // Create a trivial STEP-NC file
    apt->Workingstep("Extension 1");

    // Create a trivial STEP-NC file
    apt->PartNo ("test part");
	 apt->Rawpiece ("HardMoldy_stock.stp");
    long raw_id = apt->GetCurrentRawpiece ();
	 apt->DefineTool(0.25, 5.0, 1.0, 2.0, 3.0, 4.0, 5.0);
    apt->PutWorkpiecePlacement (raw_id, 0, 0, 0, 0, 0, -1, 1, 0, 0);
	apt->GeometryForToolNumber ("Iscar_2.stp", 1);
    apt->LoadTool (1);
     apt->SpindleSpeed (300);
    apt->Feedrate (30);

		apt->GoToXYZ("point0", 0,0,200);
		apt->GoToXYZ("point0", 0,0,200);

   String ^str;
	array<double>^ coor;
	for (int i=0;i<100;i++){
		//Console::WriteLine(i);
	coor=mt->getPos();
	if(coor!=nullptr){

		str= gcnew String(String::Format("point {0} ",i));
		Console::WriteLine(str);
        Console::WriteLine(coor[0]);

		apt->GoToXYZ(str, coor[0]*0.0393701, coor[1]*0.0393701, coor[2]*0.0393701);
	}
	}

    apt->SaveAsModules("hardmoldy_extended");
	Console::WriteLine("done");
	String ^readIn =Console::ReadLine();

}

void appendToFile(String^ file_name,String^ original,String^ new_file_name,bool convert_to_inches){
	List<array<double>^> ^coor_List= coordinates(file_name,convert_to_inches);
    // Create a trivial STEP-NC file
	Console::WriteLine("Got Position Data From File");
    STEPNCLib::AptStepMaker ^ apt = gcnew STEPNCLib::AptStepMaker();

	////////////////////////
   STEPNCLib::Finder ^find = gcnew STEPNCLib::Finder();

	    //	    APT.Open238("new_hardmoldy.stpnc");
	    //	    Find.Open238("new_hardmoldy.stpnc");
	    apt->Open238(original);
	    apt->Open238(original);

	    long wp_id = find->GetMainWorkplan();
	    Console::WriteLine("Main Workplan name " + find->GetExecutableName(wp_id));

	    // add a new workplan at the end of the project
	    apt->NestWorkplanAfter("Workplan for MTConnect results", find->GetWorkplanExecutableCount(wp_id) + 1, wp_id);

	    // Starting first workingstep in new plan
	    apt->Workingstep("testing");

//////////////////////////
    //apt->PartNo("test part");
    //apt->DefineTool(0.25, 5.0, 1.0, 2.0, 3.0, 4.0, 5.0);
	//apt->GeometryForToolNumber ("Iscar_2.stp", 1);

		//String^ boeingTool=find->GetToolNumberAsNumber()
		Console::WriteLine("is tool defined {0}",apt->IsToolDefined(1));
			apt->LoadTool(1);
    apt->SpindleSpeed (300);
    apt->Feedrate (30);
	String ^str;
	array<double>^ coor;
	for (int i=0;i<coor_List->Count;i++){
		coor=coor_List[i];

		str=String::Format("point {0} ",i+1);
		//Console::WriteLine(str);
		//Console::WriteLine(" {0} {1} {2}",coor[0],coor[1],coor[2]);

		apt->GoToXYZ(str, coor[0], coor[1], coor[2]);

	}

	apt->SaveAsModules(new_file_name);
	Console::WriteLine("done");

}
long long getWorkPlanByPath(array<String^>^ nameList,STEPNCLib::Finder ^find){
	long long root=find->GetMainWorkplan();
	bool found=false;
	List<long long>^tempList=gcnew List<long long>();
	tempList->Add(root);
	for (int i=0;i<nameList->Length;i++){
		found=false;
		for each(long long x in tempList){
			if(find->IsProgramStructure(x)){
			if(find->GetExecutableName(x)==nameList[i]){
				Console::WriteLine(find->GetExecutableName(x));
			root =x;
			tempList=find->GetNestedExecutableAll(root);
			found=true;
			break;
			}
			}

		}
		if(found==false){
		return -1;
		}

	}
	Console::WriteLine(find->GetExecutableName(root));
	return root;
}

long long getWorkPlanByName(String^ name,STEPNCLib::Finder ^find,long long root){

	if (find->IsProgramStructure(root)){
		List<long long>^nestedPlans =find->GetNestedExecutableAll (root);
		for each (long long x in nestedPlans){

				if(find->IsProgramStructure(x)){
					Console::WriteLine(find->GetExecutableName(x));
					if(name==find->GetExecutableName(x)){
						return x;
					}else{
						getWorkPlanByName(name,find,x);

					}

				}

		}

	}

}
long long GetWorkplan(String^name,STEPNCLib::AptStepMaker ^ apt, STEPNCLib::Finder ^find){

long long wp_id = find->GetMainWorkplan();
Console::WriteLine("main workplan id is {0}",wp_id);
String^ str=nullptr;

str=find->GetExecutableName(wp_id);
long long temp_id=wp_id;

	if(str!=nullptr){
		Console::WriteLine("Workplan name: {0}\n", str);
		List<long long>^nestedPlans =find->GetNestedExecutableAll (wp_id);
		for each (long long x in nestedPlans){
			str=find->GetExecutableName(x);
			if(str!=nullptr){
		Console::WriteLine("Workplan name: {0}\n", str);}

			List<long long>^nestedExecutables=find->GetNestedExecutableAll (x);
		for each (long long y in nestedExecutables){
			str=find->GetExecutableName(y);

	if(str!=nullptr){
		Console::WriteLine("Executable name: {0}\n", str);
	if(str==name){
		return y;
		}
	}

		}
		}

	}

}
//recursively get all enabled worksteps
void getAllWorksteps(long long root,STEPNCLib::Finder ^find,List<long long>^ wsList){
	if (find->IsProgramStructure(root)){
		List<long long>^nestedPlans =find->GetNestedExecutableAllEnabled (root);
		for each (long long x in nestedPlans){

				if(find->IsProgramStructure(x))
					{
						getAllWorksteps(x,find,wsList);

					}
				else if (find->IsWorkingstep(x)&&find->IsEnabled(x)){
					wsList->Add(x);
				}

				}

		}

	}
List<array<double>^> ^  coordinatesWithTime(String ^fileName,bool convert_to_inches){
//create instance of the xml reader

	XmlDocument ^doc = gcnew XmlDocument();
	doc->Load(fileName);
	XmlNode ^root = doc->DocumentElement;

		XmlNamespaceManager ^nsmgr = gcnew XmlNamespaceManager(doc->NameTable);
		nsmgr->AddNamespace("base", root->NamespaceURI);

		List<array<double>^> ^Lst = gcnew List<array<double>^>();
		String ^str;
		XmlNodeList^ pathList = root->SelectNodes("//base:PathPosition", nsmgr);
		DateTime  tempTime= DateTime();

		DateTime  tempTime2= DateTime();
		array<double> ^coor;
		bool firstTimeStamp=true;
		for (int i=0;i<pathList->Count;i++){
			XmlNode^ temp=pathList->Item(i);
			str=temp->InnerText;
			if(str!="UNAVAILABLE"){

			//Console::WriteLine(str);
			array<String^>^ arr;
			arr=str->Split(' ');
			coor=gcnew array<double>(4);
			if(firstTimeStamp){
					tempTime.Parse(temp->Attributes["timestamp"]->Value);
				coor[3]=0;

			}else{
			tempTime2.Parse(temp->Attributes["timestamp"]->Value);
			System::TimeSpan diff=(tempTime2.Subtract(tempTime));
			coor[3]=diff.TotalSeconds;
			tempTime=tempTime2;

			}

			try
			{
			coor[0]=Convert::ToDouble(arr[0]);
			coor[1]=Convert::ToDouble(arr[1]);
			coor[2]=Convert::ToDouble(arr[2]);
			if(convert_to_inches){
			coor[0]=coor[0]*0.0393701;
			coor[1]=coor[1]*0.0393701;
			coor[2]=coor[2]*0.0393701;

			}
			//Console::WriteLine(arr[0]);
			//Console::WriteLine(coor[0]);
			Lst->Add((array<double> ^)coor->Clone());
			}
			catch (Exception^ e){
			Console::WriteLine(e);

			}
			}

		}
return Lst;
}

//return list of transitions Feed->rapid,rapid to feed
//each array has two curve ids of (F,R)or (R,F)
//third element of array indicates type of transition 0 F->R 1 R->F
List<array<long long>^> ^ GetRapidToolPaths(long long workplan, STEPNCLib::Finder ^find)
{
	List<long long> ^wsList=gcnew List<long long>();
	List<long long>^pathList=gcnew List<long long>();
	List<long long>^tempPathList=nullptr;
	List<array<long long>^> ^ rapidToolPaths=gcnew List<array<long long>^>();

	getAllWorksteps(workplan,find,wsList);
	for each(long long x in wsList ){

		pathList->AddRange(find->GetWorkingstepPathAll(x));

	}
	bool currentPathIsRapid=false;
	array<long long>^ tempTrans;
	if(pathList->Count>0){currentPathIsRapid=find->GetPathRapid(pathList[0]);}
	for( int i=1;i<pathList->Count;i++){
		if(find->GetPathRapid(i)!=currentPathIsRapid){
			tempTrans=gcnew array<long long>(3);
				tempTrans[0]=pathList[i-1];
			tempTrans[1]=pathList[i];
			if(currentPathIsRapid){
			tempTrans[1]=1;
			}else
			{tempTrans[1]=0;}
			rapidToolPaths->Add(tempTrans);

		}
		currentPathIsRapid=find->GetPathRapid(pathList[i]);

	}

	//GetPathPolylinePointAll/Count/Next()

	return rapidToolPaths;
}
double actualFeedRate(array<double>^ coor1,array<double>^ coor2){
	double dx=coor1[0]-coor2[0];
	double dy=coor1[1]-coor2[1];
	double dz=coor1[2]-coor2[2];
	Math::Pow(dx,2)+Math::Pow()

}
void appendPatchWorkPlan(String^file,String^ path,bool toInches ){
	//assume all units are inches or inches per sec
	double max_feed=12.3/60;//inches per sec
List<array<double>^> ^coorList=	coordinatesWithTime(file,toInches);

STEPNCLib::AptStepMaker ^ apt = gcnew STEPNCLib::AptStepMaker();
array<String^>^ nameList=path->Split('/');
	////////////////////////
   STEPNCLib::Finder ^find = gcnew STEPNCLib::Finder();
   apt->Inches();

   apt->Open238 ("hardmoldy_ext.stpnc");
   find->Open238 ("hardmoldy_ext.stpnc");
	long long id= getWorkPlanByPath(nameList,find);
List<array<long long>^> ^transitionPaths= GetRapidToolPaths(id, find);

//begin the extended version of the stpnc file

 long wp_id = find->GetMainWorkplan();
	    Console::WriteLine("Main Workplan name " + find->GetExecutableName(wp_id));

	    // add a new workplan at the end of the project
	    apt->NestWorkplanAfter("Workplan for MTConnect results", find->GetWorkplanExecutableCount(wp_id) + 1, wp_id);

	    // Starting first workingstep in new plan
	    apt->Workingstep("testing");

//////////////////////////
    //apt->PartNo("test part");
    //apt->DefineTool(0.25, 5.0, 1.0, 2.0, 3.0, 4.0, 5.0);
	//apt->GeometryForToolNumber ("Iscar_2.stp", 1);

		//String^ boeingTool=find->GetToolNumberAsNumber()
		Console::WriteLine("is tool defined {0}",apt->IsToolDefined(1));
			apt->LoadTool(1);
    apt->SpindleSpeed (300);
    apt->Feedrate (30);
	String ^str;
	array<double>^ coor1;
	array<double>^coor2;
	for (int i=1;i<coorList->Count;i++){
		coor1=coorList[i-1];
		coor2=coorList[i];

		str=String::Format("point {0} ",i+1);
		//Console::WriteLine(str);
		//Console::WriteLine(" {0} {1} {2}",coor[0],coor[1],coor[2]);

		apt->GoToXYZ(str, coor[0], coor[1], coor[2]);

	}

	apt->SaveAsModules(new_file_name);
	Console::WriteLine("done");

}

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

	MtConnector ^ mt;
	mt=gcnew MtConnector();
	//mt->startPush("http://okuma-matata:5000/sample?count=1000&interval=10&path=//Path/DataItems/DataItem[@id=\"Mp1LPathPos\"]");
	//http://agent.mtconnect.org/VMC-3Axis/sample?count=1000&interval=10&path=//Path/DataItems/DataItem[@category=\"SAMPLE\"]"
	//http://okuma-matata:5000/sample?count=1000&interval=10

	//mt->getRequest("http://okuma-matata:5000/sample?count=1000&interval=10&path=//Path/DataItems/DataItem[@id=\"Mp1LPathPos\"]");
	//PullFromServer(mt);
  // appendToFile("iteration3_10_ms.xml","hardmoldy_ext.stpnc","moldy.stpnc",true);
	appendPatchWorkPlan("HARDMOLDY/Profiling/Boeing",true);
	String ^readIn =Console::ReadLine();
	return 0;
}

<|endoftext|>