<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "docsumcontext.h"
#include <vespa/document/datatype/positiondatatype.h>
#include <vespa/searchlib/queryeval/begin_and_end_id.h>
#include <vespa/searchlib/attribute/iattributemanager.h>
#include <vespa/searchlib/common/location.h>
#include <vespa/searchlib/common/transport.h>
#include <vespa/vespalib/data/slime/slime.h>
#include <vespa/vespalib/util/stringfmt.h>

#include <vespa/log/log.h>
LOG_SETUP(".proton.docsummary.docsumcontext");

using document::PositionDataType;
using search::common::Location;
using vespalib::string;
using vespalib::slime::SymbolTable;
using vespalib::slime::NIX;
using vespalib::Memory;
using vespalib::slime::Cursor;
using vespalib::slime::Symbol;
using vespalib::slime::Inserter;
using vespalib::slime::ObjectSymbolInserter;
using vespalib::Slime;
using vespalib::make_string;
using namespace search;
using namespace search::attribute;
using namespace search::engine;
using namespace search::docsummary;

namespace proton {

using namespace matching;

namespace {

Memory DOCSUMS("docsums");
Memory DOCSUM("docsum");
Memory ERRORS("errors");
Memory TYPE("type");
Memory MESSAGE("message");
Memory DETAILS("details");
Memory TIMEOUT("timeout");

}

void
DocsumContext::initState()
{
    const DocsumRequest & req = _request;
    _docsumState._args.initFromDocsumRequest(req);
    _docsumState._args.SetQueryFlags(req.queryFlags & ~search::fs4transport::QFLAG_DROP_SORTDATA);
    _docsumState._docsumcnt = req.hits.size();

    _docsumState._docsumbuf = (_docsumState._docsumcnt > 0)
                              ? (uint32_t*)malloc(sizeof(uint32_t) * _docsumState._docsumcnt)
                              : nullptr;

    for (uint32_t i = 0; i < _docsumState._docsumcnt; i++) {
        _docsumState._docsumbuf[i] = req.hits[i].docid;
    }
}

DocsumReply::UP
DocsumContext::createReply()
{
    DocsumReply::UP reply(new DocsumReply());
    search::RawBuf buf(4096);
    _docsumWriter.InitState(_attrMgr, &_docsumState);
    reply->docsums.resize(_docsumState._docsumcnt);
    SymbolTable::UP symbols = std::make_unique<SymbolTable>();
    IDocsumWriter::ResolveClassInfo rci = _docsumWriter.resolveClassInfo(_docsumState._args.getResultClassName(), _docsumStore.getSummaryClassId());
    for (uint32_t i = 0; i < _docsumState._docsumcnt; ++i) {
        buf.reset();
        uint32_t docId = _docsumState._docsumbuf[i];
        reply->docsums[i].docid = docId;
        if (docId != search::endDocId && !rci.mustSkip) {
            Slime slime(Slime::Params(std::move(symbols)));
            vespalib::slime::SlimeInserter inserter(slime);
            if (_request.expired()) {
                inserter.insertString(make_string("Timed out with %ldus left.", _request.getTimeLeft().us()));
            } else {
                _docsumWriter.insertDocsum(rci, docId, &_docsumState, &_docsumStore, slime, inserter);
            }
            uint32_t docsumLen = (slime.get().type().getId() != NIX::ID)
                                   ? IDocsumWriter::slime2RawBuf(slime, buf)
                                   : 0;
            reply->docsums[i].setData(buf.GetDrainPos(), docsumLen);
            symbols = Slime::reclaimSymbols(std::move(slime));
        }
    }
    return reply;
}

namespace {

vespalib::Slime::Params
makeSlimeParams(size_t chunkSize) {
    Slime::Params params;
    params.setChunkSize(chunkSize);
    return params;
}

}

vespalib::Slime::UP
DocsumContext::createSlimeReply()
{
    _docsumWriter.InitState(_attrMgr, &_docsumState);
    const size_t estimatedChunkSize(std::min(0x200000ul, _docsumState._docsumcnt*0x400ul));
    vespalib::Slime::UP response(std::make_unique<vespalib::Slime>(makeSlimeParams(estimatedChunkSize)));
    Cursor & root = response->setObject();
    Cursor & array = root.setArray(DOCSUMS);
    const Symbol docsumSym = response->insert(DOCSUM);
    IDocsumWriter::ResolveClassInfo rci = _docsumWriter.resolveClassInfo(_docsumState._args.getResultClassName(),
                                                                         _docsumStore.getSummaryClassId());
    uint32_t i(0);
    for (i = 0; (i < _docsumState._docsumcnt) && !_request.expired(); ++i) {
        uint32_t docId = _docsumState._docsumbuf[i];
        Cursor & docSumC = array.addObject();
        ObjectSymbolInserter inserter(docSumC, docsumSym);
        if ((docId != search::endDocId) && !rci.mustSkip) {
            _docsumWriter.insertDocsum(rci, docId, &_docsumState, &_docsumStore, *response, inserter);
        }
    }
    if (i != _docsumState._docsumcnt) {
        const uint32_t numTimedOut = _docsumState._docsumcnt - 1;
        Cursor & errors = root.setArray(ERRORS);
        Cursor & timeout = errors.addObject();
        timeout.setString(TYPE, TIMEOUT);
        timeout.setString(MESSAGE, make_string("Timed out %d summaries with %ldus left.",
                                               numTimedOut, _request.getTimeLeft().us()));
    }
    return response;
}

DocsumContext::DocsumContext(const DocsumRequest & request, IDocsumWriter & docsumWriter,
                             IDocsumStore & docsumStore, const Matcher::SP & matcher,
                             ISearchContext & searchCtx, IAttributeContext & attrCtx,
                             search::IAttributeManager & attrMgr, SessionManager & sessionMgr) :
    _request(request),
    _docsumWriter(docsumWriter),
    _docsumStore(docsumStore),
    _matcher(matcher),
    _searchCtx(searchCtx),
    _attrCtx(attrCtx),
    _attrMgr(attrMgr),
    _docsumState(*this),
    _sessionMgr(sessionMgr)
{
    initState();
}

DocsumReply::UP
DocsumContext::getDocsums()
{
    if (_request.useRootSlime()) {
        return std::make_unique<DocsumReply>(createSlimeReply());
    }
    return createReply();
}

void
DocsumContext::FillSummaryFeatures(search::docsummary::GetDocsumsState * state, search::docsummary::IDocsumEnvironment *)
{
    assert(&_docsumState == state);
    if (_matcher->canProduceSummaryFeatures()) {
        state->_summaryFeatures = _matcher->getSummaryFeatures(_request, _searchCtx, _attrCtx, _sessionMgr);
    }
    state->_summaryFeaturesCached = false;
}

void
DocsumContext::FillRankFeatures(search::docsummary::GetDocsumsState * state, search::docsummary::IDocsumEnvironment *)
{
    assert(&_docsumState == state);
    // check if we are allowed to run
    if ((state->_args.GetQueryFlags() & search::fs4transport::QFLAG_DUMP_FEATURES) == 0) {
        return;
    }
    state->_rankFeatures = _matcher->getRankFeatures(_request, _searchCtx, _attrCtx, _sessionMgr);
}

namespace {
Location *getLocation(const string &loc_str, search::IAttributeManager &attrMgr)
{
    LOG(debug, "Filling document locations from location string: %s", loc_str.c_str());

    Location *loc = new Location;
    string location;
    string::size_type pos = loc_str.find(':');
    if (pos != string::npos) {
        string view = loc_str.substr(0, pos);
        AttributeGuard::UP vec = attrMgr.getAttribute(view);
        if (!vec->valid()) {
            view = PositionDataType::getZCurveFieldName(view);
            vec = attrMgr.getAttribute(view);
        }
        loc->setVecGuard(std::move(vec));
        location = loc_str.substr(pos + 1);
    } else {
        LOG(warning, "Location string lacks attribute vector specification. loc='%s'", loc_str.c_str());
        location = loc_str;
    }
    loc->parse(location);
    return loc;
}
}  // namespace

void
DocsumContext::ParseLocation(search::docsummary::GetDocsumsState *state)
{
    state->_parsedLocation.reset(getLocation(_request.location, _attrMgr));
}

} // namespace proton
<commit_msg>Even though visually similar, semantic similarity of '1' and 'i' are close to zero.<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "docsumcontext.h"
#include <vespa/document/datatype/positiondatatype.h>
#include <vespa/searchlib/queryeval/begin_and_end_id.h>
#include <vespa/searchlib/attribute/iattributemanager.h>
#include <vespa/searchlib/common/location.h>
#include <vespa/searchlib/common/transport.h>
#include <vespa/vespalib/data/slime/slime.h>
#include <vespa/vespalib/util/stringfmt.h>

#include <vespa/log/log.h>
LOG_SETUP(".proton.docsummary.docsumcontext");

using document::PositionDataType;
using search::common::Location;
using vespalib::string;
using vespalib::slime::SymbolTable;
using vespalib::slime::NIX;
using vespalib::Memory;
using vespalib::slime::Cursor;
using vespalib::slime::Symbol;
using vespalib::slime::Inserter;
using vespalib::slime::ObjectSymbolInserter;
using vespalib::Slime;
using vespalib::make_string;
using namespace search;
using namespace search::attribute;
using namespace search::engine;
using namespace search::docsummary;

namespace proton {

using namespace matching;

namespace {

Memory DOCSUMS("docsums");
Memory DOCSUM("docsum");
Memory ERRORS("errors");
Memory TYPE("type");
Memory MESSAGE("message");
Memory DETAILS("details");
Memory TIMEOUT("timeout");

}

void
DocsumContext::initState()
{
    const DocsumRequest & req = _request;
    _docsumState._args.initFromDocsumRequest(req);
    _docsumState._args.SetQueryFlags(req.queryFlags & ~search::fs4transport::QFLAG_DROP_SORTDATA);
    _docsumState._docsumcnt = req.hits.size();

    _docsumState._docsumbuf = (_docsumState._docsumcnt > 0)
                              ? (uint32_t*)malloc(sizeof(uint32_t) * _docsumState._docsumcnt)
                              : nullptr;

    for (uint32_t i = 0; i < _docsumState._docsumcnt; i++) {
        _docsumState._docsumbuf[i] = req.hits[i].docid;
    }
}

DocsumReply::UP
DocsumContext::createReply()
{
    DocsumReply::UP reply(new DocsumReply());
    search::RawBuf buf(4096);
    _docsumWriter.InitState(_attrMgr, &_docsumState);
    reply->docsums.resize(_docsumState._docsumcnt);
    SymbolTable::UP symbols = std::make_unique<SymbolTable>();
    IDocsumWriter::ResolveClassInfo rci = _docsumWriter.resolveClassInfo(_docsumState._args.getResultClassName(), _docsumStore.getSummaryClassId());
    for (uint32_t i = 0; i < _docsumState._docsumcnt; ++i) {
        buf.reset();
        uint32_t docId = _docsumState._docsumbuf[i];
        reply->docsums[i].docid = docId;
        if (docId != search::endDocId && !rci.mustSkip) {
            Slime slime(Slime::Params(std::move(symbols)));
            vespalib::slime::SlimeInserter inserter(slime);
            if (_request.expired()) {
                inserter.insertString(make_string("Timed out with %ldus left.", _request.getTimeLeft().us()));
            } else {
                _docsumWriter.insertDocsum(rci, docId, &_docsumState, &_docsumStore, slime, inserter);
            }
            uint32_t docsumLen = (slime.get().type().getId() != NIX::ID)
                                   ? IDocsumWriter::slime2RawBuf(slime, buf)
                                   : 0;
            reply->docsums[i].setData(buf.GetDrainPos(), docsumLen);
            symbols = Slime::reclaimSymbols(std::move(slime));
        }
    }
    return reply;
}

namespace {

vespalib::Slime::Params
makeSlimeParams(size_t chunkSize) {
    Slime::Params params;
    params.setChunkSize(chunkSize);
    return params;
}

}

vespalib::Slime::UP
DocsumContext::createSlimeReply()
{
    _docsumWriter.InitState(_attrMgr, &_docsumState);
    const size_t estimatedChunkSize(std::min(0x200000ul, _docsumState._docsumcnt*0x400ul));
    vespalib::Slime::UP response(std::make_unique<vespalib::Slime>(makeSlimeParams(estimatedChunkSize)));
    Cursor & root = response->setObject();
    Cursor & array = root.setArray(DOCSUMS);
    const Symbol docsumSym = response->insert(DOCSUM);
    IDocsumWriter::ResolveClassInfo rci = _docsumWriter.resolveClassInfo(_docsumState._args.getResultClassName(),
                                                                         _docsumStore.getSummaryClassId());
    uint32_t i(0);
    for (i = 0; (i < _docsumState._docsumcnt) && !_request.expired(); ++i) {
        uint32_t docId = _docsumState._docsumbuf[i];
        Cursor & docSumC = array.addObject();
        ObjectSymbolInserter inserter(docSumC, docsumSym);
        if ((docId != search::endDocId) && !rci.mustSkip) {
            _docsumWriter.insertDocsum(rci, docId, &_docsumState, &_docsumStore, *response, inserter);
        }
    }
    if (i != _docsumState._docsumcnt) {
        const uint32_t numTimedOut = _docsumState._docsumcnt - i;
        Cursor & errors = root.setArray(ERRORS);
        Cursor & timeout = errors.addObject();
        timeout.setString(TYPE, TIMEOUT);
        timeout.setString(MESSAGE, make_string("Timed out %d summaries with %ldus left.",
                                               numTimedOut, _request.getTimeLeft().us()));
    }
    return response;
}

DocsumContext::DocsumContext(const DocsumRequest & request, IDocsumWriter & docsumWriter,
                             IDocsumStore & docsumStore, const Matcher::SP & matcher,
                             ISearchContext & searchCtx, IAttributeContext & attrCtx,
                             search::IAttributeManager & attrMgr, SessionManager & sessionMgr) :
    _request(request),
    _docsumWriter(docsumWriter),
    _docsumStore(docsumStore),
    _matcher(matcher),
    _searchCtx(searchCtx),
    _attrCtx(attrCtx),
    _attrMgr(attrMgr),
    _docsumState(*this),
    _sessionMgr(sessionMgr)
{
    initState();
}

DocsumReply::UP
DocsumContext::getDocsums()
{
    if (_request.useRootSlime()) {
        return std::make_unique<DocsumReply>(createSlimeReply());
    }
    return createReply();
}

void
DocsumContext::FillSummaryFeatures(search::docsummary::GetDocsumsState * state, search::docsummary::IDocsumEnvironment *)
{
    assert(&_docsumState == state);
    if (_matcher->canProduceSummaryFeatures()) {
        state->_summaryFeatures = _matcher->getSummaryFeatures(_request, _searchCtx, _attrCtx, _sessionMgr);
    }
    state->_summaryFeaturesCached = false;
}

void
DocsumContext::FillRankFeatures(search::docsummary::GetDocsumsState * state, search::docsummary::IDocsumEnvironment *)
{
    assert(&_docsumState == state);
    // check if we are allowed to run
    if ((state->_args.GetQueryFlags() & search::fs4transport::QFLAG_DUMP_FEATURES) == 0) {
        return;
    }
    state->_rankFeatures = _matcher->getRankFeatures(_request, _searchCtx, _attrCtx, _sessionMgr);
}

namespace {
Location *getLocation(const string &loc_str, search::IAttributeManager &attrMgr)
{
    LOG(debug, "Filling document locations from location string: %s", loc_str.c_str());

    Location *loc = new Location;
    string location;
    string::size_type pos = loc_str.find(':');
    if (pos != string::npos) {
        string view = loc_str.substr(0, pos);
        AttributeGuard::UP vec = attrMgr.getAttribute(view);
        if (!vec->valid()) {
            view = PositionDataType::getZCurveFieldName(view);
            vec = attrMgr.getAttribute(view);
        }
        loc->setVecGuard(std::move(vec));
        location = loc_str.substr(pos + 1);
    } else {
        LOG(warning, "Location string lacks attribute vector specification. loc='%s'", loc_str.c_str());
        location = loc_str;
    }
    loc->parse(location);
    return loc;
}
}  // namespace

void
DocsumContext::ParseLocation(search::docsummary::GetDocsumsState *state)
{
    state->_parsedLocation.reset(getLocation(_request.location, _attrMgr));
}

} // namespace proton
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, 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, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "devicesupport/deviceprocessesdialog.h"
#include "devicesupport/deviceprocesslist.h"
#include "kitchooser.h"
#include "kitinformation.h"

#include <utils/filterlineedit.h>
#include <utils/qtcassert.h>

#include <QDialogButtonBox>
#include <QFormLayout>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QPushButton>
#include <QSortFilterProxyModel>
#include <QSpacerItem>
#include <QTextBrowser>
#include <QTextDocument>
#include <QTreeView>
#include <QVBoxLayout>

using namespace Utils;

namespace ProjectExplorer {
namespace Internal {

///////////////////////////////////////////////////////////////////////
//
// ProcessListFilterModel
//
///////////////////////////////////////////////////////////////////////

class ProcessListFilterModel : public QSortFilterProxyModel
{
public:
    ProcessListFilterModel();
    bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
};

ProcessListFilterModel::ProcessListFilterModel()
{
    setFilterCaseSensitivity(Qt::CaseInsensitive);
    setDynamicSortFilter(true);
    setFilterKeyColumn(-1);
}

bool ProcessListFilterModel::lessThan(const QModelIndex &left,
    const QModelIndex &right) const
{
    const QString l = sourceModel()->data(left).toString();
    const QString r = sourceModel()->data(right).toString();
    if (left.column() == 0)
        return l.toInt() < r.toInt();
    return l < r;
}

///////////////////////////////////////////////////////////////////////
//
// DeviceProcessesDialogPrivate
//
///////////////////////////////////////////////////////////////////////

class DeviceProcessesDialogPrivate : public QObject
{
    Q_OBJECT

public:
    DeviceProcessesDialogPrivate(KitChooser *chooser, QWidget *parent);

public slots:
    void setDevice(const IDevice::ConstPtr &device);
    void updateProcessList();
    void updateDevice();
    void killProcess();
    void handleRemoteError(const QString &errorMsg);
    void handleProcessListUpdated();
    void handleProcessKilled();
    void updateButtons();
    DeviceProcess selectedProcess() const;

public:
    QWidget *q;
    DeviceProcessList *processList;
    ProcessListFilterModel proxyModel;
    QLabel *kitLabel;
    KitChooser *kitChooser;

    QTreeView *procView;
    QTextBrowser *errorText;
    FilterLineEdit *processFilterLineEdit;
    QPushButton *updateListButton;
    QPushButton *killProcessButton;
    QPushButton *acceptButton;
    QDialogButtonBox *buttonBox;
};

DeviceProcessesDialogPrivate::DeviceProcessesDialogPrivate(KitChooser *chooser, QWidget *parent)
    : q(parent)
    , kitLabel(new QLabel(DeviceProcessesDialog::tr("Kit:"), parent))
    , kitChooser(chooser)
    , acceptButton(0)
    , buttonBox(new QDialogButtonBox(parent))
{
    q->setWindowTitle(DeviceProcessesDialog::tr("List of Processes"));
    q->setWindowFlags(q->windowFlags() & ~Qt::WindowContextHelpButtonHint);
    q->setMinimumHeight(500);

    processList = 0;

    processFilterLineEdit = new FilterLineEdit(q);
    processFilterLineEdit->setPlaceholderText(DeviceProcessesDialog::tr("Filter"));
    processFilterLineEdit->setFocus(Qt::TabFocusReason);

    kitChooser->populate();

    procView = new QTreeView(q);
    procView->setModel(&proxyModel);
    procView->setSelectionBehavior(QAbstractItemView::SelectRows);
    procView->setSelectionMode(QAbstractItemView::SingleSelection);
    procView->setUniformRowHeights(true);
    procView->setRootIsDecorated(false);
    procView->setAlternatingRowColors(true);
    procView->setSortingEnabled(true);
    procView->header()->setDefaultSectionSize(100);
    procView->header()->setStretchLastSection(true);
    procView->sortByColumn(1, Qt::AscendingOrder);

    errorText = new QTextBrowser(q);

    updateListButton = new QPushButton(DeviceProcessesDialog::tr("&Update List"), q);
    killProcessButton = new QPushButton(DeviceProcessesDialog::tr("&Kill Process"), q);

    buttonBox->addButton(updateListButton, QDialogButtonBox::ActionRole);
    buttonBox->addButton(killProcessButton, QDialogButtonBox::ActionRole);

    QFormLayout *leftColumn = new QFormLayout();
    leftColumn->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
    leftColumn->addRow(kitLabel, kitChooser);
    leftColumn->addRow(DeviceProcessesDialog::tr("&Filter:"), processFilterLineEdit);

//    QVBoxLayout *rightColumn = new QVBoxLayout();
//    rightColumn->addWidget(updateListButton);
//    rightColumn->addWidget(killProcessButton);
//    rightColumn->addStretch();

//    QHBoxLayout *horizontalLayout = new QHBoxLayout();
//    horizontalLayout->addLayout(leftColumn);
//    horizontalLayout->addLayout(rightColumn);

    QVBoxLayout *mainLayout = new QVBoxLayout(q);
    mainLayout->addLayout(leftColumn);
    mainLayout->addWidget(procView);
    mainLayout->addWidget(errorText);
    mainLayout->addWidget(buttonBox);

//    QFrame *line = new QFrame(this);
//    line->setFrameShape(QFrame::HLine);
//    line->setFrameShadow(QFrame::Sunken);

    connect(processFilterLineEdit, SIGNAL(textChanged(QString)),
        &proxyModel, SLOT(setFilterRegExp(QString)));
    connect(procView->selectionModel(),
        SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
        SLOT(updateButtons()));
    connect(updateListButton, SIGNAL(clicked()), SLOT(updateProcessList()));
    connect(kitChooser, SIGNAL(currentIndexChanged(int)), SLOT(updateDevice()));
    connect(killProcessButton, SIGNAL(clicked()), SLOT(killProcess()));
    connect(&proxyModel, SIGNAL(layoutChanged()), SLOT(handleProcessListUpdated()));
    connect(buttonBox, SIGNAL(accepted()), q, SLOT(accept()));
    connect(buttonBox, SIGNAL(rejected()), q, SLOT(reject()));
}

void DeviceProcessesDialogPrivate::setDevice(const IDevice::ConstPtr &device)
{
    delete processList;

    processList = device->createProcessListModel();
    QTC_ASSERT(processList, return);
    proxyModel.setSourceModel(processList);

    connect(processList, SIGNAL(error(QString)),
        SLOT(handleRemoteError(QString)));
    connect(processList, SIGNAL(processListUpdated()),
        SLOT(handleProcessListUpdated()));
    connect(processList, SIGNAL(processKilled()),
        SLOT(handleProcessKilled()), Qt::QueuedConnection);

    updateButtons();
    updateProcessList();
}

void DeviceProcessesDialogPrivate::handleRemoteError(const QString &errorMsg)
{
    QMessageBox::critical(q, tr("Remote Error"), errorMsg);
    updateListButton->setEnabled(true);
    updateButtons();
}

void DeviceProcessesDialogPrivate::handleProcessListUpdated()
{
    updateListButton->setEnabled(true);
    procView->resizeColumnToContents(0);
    procView->resizeColumnToContents(1);
    updateButtons();
}

void DeviceProcessesDialogPrivate::updateProcessList()
{
    updateListButton->setEnabled(false);
    killProcessButton->setEnabled(false);
    if (processList)
        processList->update();
}

void DeviceProcessesDialogPrivate::killProcess()
{
    const QModelIndexList indexes = procView->selectionModel()->selectedIndexes();
    if (indexes.empty())
        return;
    updateListButton->setEnabled(false);
    killProcessButton->setEnabled(false);
    processList->killProcess(proxyModel.mapToSource(indexes.first()).row());
}

void DeviceProcessesDialogPrivate::updateDevice()
{
    setDevice(DeviceKitInformation::device(kitChooser->currentKit()));
}

void DeviceProcessesDialogPrivate::handleProcessKilled()
{
    updateProcessList();
}

void DeviceProcessesDialogPrivate::updateButtons()
{
    const bool hasSelection = procView->selectionModel()->hasSelection();
    if (acceptButton)
        acceptButton->setEnabled(hasSelection);
    killProcessButton->setEnabled(hasSelection);
    errorText->setVisible(!errorText->document()->isEmpty());
}

DeviceProcess DeviceProcessesDialogPrivate::selectedProcess() const
{
    const QModelIndexList indexes = procView->selectionModel()->selectedIndexes();
    if (indexes.empty())
        return DeviceProcess();
    return processList->at(proxyModel.mapToSource(indexes.first()).row());
}

} // namespace Internal

///////////////////////////////////////////////////////////////////////
//
// DeviceProcessesDialog
//
///////////////////////////////////////////////////////////////////////

/*!
     \class ProjectExplorer::DeviceProcessesDialog

     \brief Shows a list of processes.

     The dialog can be used as a
     \list
     \o Non-modal dialog showing a list of processes: Call addCloseButton()
        to add a 'Close' button.
     \o Modal dialog with an 'Accept' button to select a process: Call
        addAcceptButton() passing the label text. This will create a
        'Cancel' button as well.
     \endlist
*/

DeviceProcessesDialog::DeviceProcessesDialog(QWidget *parent)
    : QDialog(parent), d(new Internal::DeviceProcessesDialogPrivate(new KitChooser(this), this))
{
}

DeviceProcessesDialog::DeviceProcessesDialog(KitChooser *chooser, QWidget *parent)
    : QDialog(parent), d(new Internal::DeviceProcessesDialogPrivate(chooser, this))
{
}

DeviceProcessesDialog::~DeviceProcessesDialog()
{
    delete d;
}

void DeviceProcessesDialog::addAcceptButton(const QString &label)
{
    d->acceptButton = new QPushButton(label);
    d->buttonBox->addButton(d->acceptButton, QDialogButtonBox::AcceptRole);
    connect(d->procView, SIGNAL(doubleClicked(QModelIndex)),
            d->acceptButton, SLOT(animateClick()));
    d->buttonBox->addButton(QDialogButtonBox::Cancel);
}

void DeviceProcessesDialog::addCloseButton()
{
    d->buttonBox->addButton(QDialogButtonBox::Close);
}

void DeviceProcessesDialog::setKitVisible(bool v)
{
    d->kitLabel->setVisible(v);
    d->kitChooser->setVisible(v);
}

void DeviceProcessesDialog::setDevice(const IDevice::ConstPtr &device)
{
    setKitVisible(false);
    d->setDevice(device);
}

void DeviceProcessesDialog::showAllDevices()
{
    setKitVisible(true);
    d->updateDevice();
}

DeviceProcess DeviceProcessesDialog::currentProcess() const
{
    return d->selectedProcess();
}

KitChooser *DeviceProcessesDialog::kitChooser() const
{
    return d->kitChooser;
}

void DeviceProcessesDialog::logMessage(const QString &line)
{
    d->errorText->setVisible(true);
    d->errorText->append(line);
}

} // namespace ProjectExplorer

#include "deviceprocessesdialog.moc"
<commit_msg>Attach to Process: Fix crash<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, 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, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "devicesupport/deviceprocessesdialog.h"
#include "devicesupport/deviceprocesslist.h"
#include "kitchooser.h"
#include "kitinformation.h"

#include <utils/filterlineedit.h>
#include <utils/qtcassert.h>

#include <QDialogButtonBox>
#include <QFormLayout>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QPushButton>
#include <QSortFilterProxyModel>
#include <QSpacerItem>
#include <QTextBrowser>
#include <QTextDocument>
#include <QTreeView>
#include <QVBoxLayout>

using namespace Utils;

namespace ProjectExplorer {
namespace Internal {

///////////////////////////////////////////////////////////////////////
//
// ProcessListFilterModel
//
///////////////////////////////////////////////////////////////////////

class ProcessListFilterModel : public QSortFilterProxyModel
{
public:
    ProcessListFilterModel();
    bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
};

ProcessListFilterModel::ProcessListFilterModel()
{
    setFilterCaseSensitivity(Qt::CaseInsensitive);
    setDynamicSortFilter(true);
    setFilterKeyColumn(-1);
}

bool ProcessListFilterModel::lessThan(const QModelIndex &left,
    const QModelIndex &right) const
{
    const QString l = sourceModel()->data(left).toString();
    const QString r = sourceModel()->data(right).toString();
    if (left.column() == 0)
        return l.toInt() < r.toInt();
    return l < r;
}

///////////////////////////////////////////////////////////////////////
//
// DeviceProcessesDialogPrivate
//
///////////////////////////////////////////////////////////////////////

class DeviceProcessesDialogPrivate : public QObject
{
    Q_OBJECT

public:
    DeviceProcessesDialogPrivate(KitChooser *chooser, QWidget *parent);

public slots:
    void setDevice(const IDevice::ConstPtr &device);
    void updateProcessList();
    void updateDevice();
    void killProcess();
    void handleRemoteError(const QString &errorMsg);
    void handleProcessListUpdated();
    void handleProcessKilled();
    void updateButtons();
    DeviceProcess selectedProcess() const;

public:
    QWidget *q;
    DeviceProcessList *processList;
    ProcessListFilterModel proxyModel;
    QLabel *kitLabel;
    KitChooser *kitChooser;

    QTreeView *procView;
    QTextBrowser *errorText;
    FilterLineEdit *processFilterLineEdit;
    QPushButton *updateListButton;
    QPushButton *killProcessButton;
    QPushButton *acceptButton;
    QDialogButtonBox *buttonBox;
};

DeviceProcessesDialogPrivate::DeviceProcessesDialogPrivate(KitChooser *chooser, QWidget *parent)
    : q(parent)
    , kitLabel(new QLabel(DeviceProcessesDialog::tr("Kit:"), parent))
    , kitChooser(chooser)
    , acceptButton(0)
    , buttonBox(new QDialogButtonBox(parent))
{
    q->setWindowTitle(DeviceProcessesDialog::tr("List of Processes"));
    q->setWindowFlags(q->windowFlags() & ~Qt::WindowContextHelpButtonHint);
    q->setMinimumHeight(500);

    processList = 0;

    processFilterLineEdit = new FilterLineEdit(q);
    processFilterLineEdit->setPlaceholderText(DeviceProcessesDialog::tr("Filter"));
    processFilterLineEdit->setFocus(Qt::TabFocusReason);

    kitChooser->populate();

    procView = new QTreeView(q);
    procView->setModel(&proxyModel);
    procView->setSelectionBehavior(QAbstractItemView::SelectRows);
    procView->setSelectionMode(QAbstractItemView::SingleSelection);
    procView->setUniformRowHeights(true);
    procView->setRootIsDecorated(false);
    procView->setAlternatingRowColors(true);
    procView->setSortingEnabled(true);
    procView->header()->setDefaultSectionSize(100);
    procView->header()->setStretchLastSection(true);
    procView->sortByColumn(1, Qt::AscendingOrder);

    errorText = new QTextBrowser(q);

    updateListButton = new QPushButton(DeviceProcessesDialog::tr("&Update List"), q);
    killProcessButton = new QPushButton(DeviceProcessesDialog::tr("&Kill Process"), q);

    buttonBox->addButton(updateListButton, QDialogButtonBox::ActionRole);
    buttonBox->addButton(killProcessButton, QDialogButtonBox::ActionRole);

    QFormLayout *leftColumn = new QFormLayout();
    leftColumn->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
    leftColumn->addRow(kitLabel, kitChooser);
    leftColumn->addRow(DeviceProcessesDialog::tr("&Filter:"), processFilterLineEdit);

//    QVBoxLayout *rightColumn = new QVBoxLayout();
//    rightColumn->addWidget(updateListButton);
//    rightColumn->addWidget(killProcessButton);
//    rightColumn->addStretch();

//    QHBoxLayout *horizontalLayout = new QHBoxLayout();
//    horizontalLayout->addLayout(leftColumn);
//    horizontalLayout->addLayout(rightColumn);

    QVBoxLayout *mainLayout = new QVBoxLayout(q);
    mainLayout->addLayout(leftColumn);
    mainLayout->addWidget(procView);
    mainLayout->addWidget(errorText);
    mainLayout->addWidget(buttonBox);

//    QFrame *line = new QFrame(this);
//    line->setFrameShape(QFrame::HLine);
//    line->setFrameShadow(QFrame::Sunken);

    connect(processFilterLineEdit, SIGNAL(textChanged(QString)),
        &proxyModel, SLOT(setFilterRegExp(QString)));
    connect(procView->selectionModel(),
        SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
        SLOT(updateButtons()));
    connect(updateListButton, SIGNAL(clicked()), SLOT(updateProcessList()));
    connect(kitChooser, SIGNAL(currentIndexChanged(int)), SLOT(updateDevice()));
    connect(killProcessButton, SIGNAL(clicked()), SLOT(killProcess()));
    connect(&proxyModel, SIGNAL(layoutChanged()), SLOT(handleProcessListUpdated()));
    connect(buttonBox, SIGNAL(accepted()), q, SLOT(accept()));
    connect(buttonBox, SIGNAL(rejected()), q, SLOT(reject()));
}

void DeviceProcessesDialogPrivate::setDevice(const IDevice::ConstPtr &device)
{
    delete processList;
    processList = 0;
    proxyModel.setSourceModel(0);
    if (!device)
        return;

    processList = device->createProcessListModel();
    QTC_ASSERT(processList, return);
    proxyModel.setSourceModel(processList);

    connect(processList, SIGNAL(error(QString)),
        SLOT(handleRemoteError(QString)));
    connect(processList, SIGNAL(processListUpdated()),
        SLOT(handleProcessListUpdated()));
    connect(processList, SIGNAL(processKilled()),
        SLOT(handleProcessKilled()), Qt::QueuedConnection);

    updateButtons();
    updateProcessList();
}

void DeviceProcessesDialogPrivate::handleRemoteError(const QString &errorMsg)
{
    QMessageBox::critical(q, tr("Remote Error"), errorMsg);
    updateListButton->setEnabled(true);
    updateButtons();
}

void DeviceProcessesDialogPrivate::handleProcessListUpdated()
{
    updateListButton->setEnabled(true);
    procView->resizeColumnToContents(0);
    procView->resizeColumnToContents(1);
    updateButtons();
}

void DeviceProcessesDialogPrivate::updateProcessList()
{
    updateListButton->setEnabled(false);
    killProcessButton->setEnabled(false);
    if (processList)
        processList->update();
}

void DeviceProcessesDialogPrivate::killProcess()
{
    const QModelIndexList indexes = procView->selectionModel()->selectedIndexes();
    if (indexes.empty() || !processList)
        return;
    updateListButton->setEnabled(false);
    killProcessButton->setEnabled(false);
    processList->killProcess(proxyModel.mapToSource(indexes.first()).row());
}

void DeviceProcessesDialogPrivate::updateDevice()
{
    setDevice(DeviceKitInformation::device(kitChooser->currentKit()));
}

void DeviceProcessesDialogPrivate::handleProcessKilled()
{
    updateProcessList();
}

void DeviceProcessesDialogPrivate::updateButtons()
{
    const bool hasSelection = procView->selectionModel()->hasSelection();
    if (acceptButton)
        acceptButton->setEnabled(hasSelection);
    killProcessButton->setEnabled(hasSelection);
    errorText->setVisible(!errorText->document()->isEmpty());
}

DeviceProcess DeviceProcessesDialogPrivate::selectedProcess() const
{
    const QModelIndexList indexes = procView->selectionModel()->selectedIndexes();
    if (indexes.empty() || !processList)
        return DeviceProcess();
    return processList->at(proxyModel.mapToSource(indexes.first()).row());
}

} // namespace Internal

///////////////////////////////////////////////////////////////////////
//
// DeviceProcessesDialog
//
///////////////////////////////////////////////////////////////////////

/*!
     \class ProjectExplorer::DeviceProcessesDialog

     \brief Shows a list of processes.

     The dialog can be used as a
     \list
     \o Non-modal dialog showing a list of processes: Call addCloseButton()
        to add a 'Close' button.
     \o Modal dialog with an 'Accept' button to select a process: Call
        addAcceptButton() passing the label text. This will create a
        'Cancel' button as well.
     \endlist
*/

DeviceProcessesDialog::DeviceProcessesDialog(QWidget *parent)
    : QDialog(parent), d(new Internal::DeviceProcessesDialogPrivate(new KitChooser(this), this))
{
}

DeviceProcessesDialog::DeviceProcessesDialog(KitChooser *chooser, QWidget *parent)
    : QDialog(parent), d(new Internal::DeviceProcessesDialogPrivate(chooser, this))
{
}

DeviceProcessesDialog::~DeviceProcessesDialog()
{
    delete d;
}

void DeviceProcessesDialog::addAcceptButton(const QString &label)
{
    d->acceptButton = new QPushButton(label);
    d->buttonBox->addButton(d->acceptButton, QDialogButtonBox::AcceptRole);
    connect(d->procView, SIGNAL(doubleClicked(QModelIndex)),
            d->acceptButton, SLOT(animateClick()));
    d->buttonBox->addButton(QDialogButtonBox::Cancel);
}

void DeviceProcessesDialog::addCloseButton()
{
    d->buttonBox->addButton(QDialogButtonBox::Close);
}

void DeviceProcessesDialog::setKitVisible(bool v)
{
    d->kitLabel->setVisible(v);
    d->kitChooser->setVisible(v);
}

void DeviceProcessesDialog::setDevice(const IDevice::ConstPtr &device)
{
    setKitVisible(false);
    d->setDevice(device);
}

void DeviceProcessesDialog::showAllDevices()
{
    setKitVisible(true);
    d->updateDevice();
}

DeviceProcess DeviceProcessesDialog::currentProcess() const
{
    return d->selectedProcess();
}

KitChooser *DeviceProcessesDialog::kitChooser() const
{
    return d->kitChooser;
}

void DeviceProcessesDialog::logMessage(const QString &line)
{
    d->errorText->setVisible(true);
    d->errorText->append(line);
}

} // namespace ProjectExplorer

#include "deviceprocessesdialog.moc"
<|endoftext|>


<commit_before>#ifndef MOBS_HPP
#define MOBS_HPP

#include <iostream>

class Mob
{
public:
  mob(std::string, std::string std::string, int, int, int, int);

  void setName(std::string);
  void setArea(std::string);
  void setSkill(std::string);

  void setLevel(int);
  void setEXP(int);
  void setHP(int);
  void setMaxHealth(int);

  void setDamage();
  void setEXP();

  std::string getName;
  std::string getArea;

  int getLevel();
  int getEXP();
  int getHP();
  int getMaxHealth();
  int getDamage();
  int getEXP();

private:
  std::string mobName;
  std::string mobArea;
  int mobLevel;
  int mobHealth;
  int mobMaxHealth;
  int mobDamage;
  int mobEXP;
};

#endif

<commit_msg>Update mob.hpp<commit_after>#ifndef MOB_HPP
#define MOB_HPP

#include <iostream>

class Mob
{
public:
  mob(std::string, std::string std::string, int, int, int, int);

  void setName(std::string);
  void setArea(std::string);
  void setSkill(std::string);

  void setLevel(int);
  void setEXP(int);
  void setHP(int);
  void setMaxHealth(int);

  void setDamage();
  void setEXP();

  std::string getName;
  std::string getArea;

  int getLevel();
  int getEXP();
  int getHP();
  int getMaxHealth();
  int getDamage();
  int getEXP();

private:
  std::string mobName;
  std::string mobArea;
  int mobLevel;
  int mobHealth;
  int mobMaxHealth;
  int mobDamage;
  int mobEXP;
};

#endif

<|endoftext|>


<commit_before>#include <iostream>
#include <ref/utils/StructuralContext.hpp>
#include "company.hpp"

using namespace ref;
using namespace example;
using namespace std;

const char * options =
    "node ["
    " fontname = \"Bitstream Vera Sans\""
    " fontsize = 8"
    " shape = \"record\""
    "]";
const char * reference_options =
    "edge ["
    " fontname = \"Bitstream Vera Sans\""
    " fontsize = 8"
    "]";
const char * inherit_options =
    "edge[dir=back, arrowtail=empty]";

std::ostream& line()
{
    return cout << endl << "    ";
}

int main(int argc, char **argv)
{
    auto companyDesc =
        example::Company::getClassDescriptorInstance();
    const StructuralContext ctx(companyDesc);

    cout << "digraph " << companyDesc->getName();
    cout << endl << "{" << endl;
    line() << options << endl;

    const auto& allClasses = ctx.getAllClasses();

    // Attributes
    for (auto desc: allClasses)
    {
        line() << desc->getName() << " [";
        line() << "    label = \"{" << desc->getName() << "|";

        for (auto feature : desc->getFeatureDescriptors())
        {
            if (ctx.isReference(feature)) continue;

            cout << feature->getName() << " : "
                 << feature->getTypeDescriptor()->getFqn() << "\\l";
        }

        cout << "}\"";
        line() << "]";
    }
    cout << endl;

    // References
    line() << reference_options << endl;

    for (auto desc: allClasses)
    {
        const auto& references = ctx.getOutgoingReferences(desc);
        for (const auto& ref : references)
        {
            line() << ref.classDesc->getName() << "->"
                   << ref.referencedClassDesc->getName();
        }
    }
    cout << endl;

    // Parent classes
    line() << inherit_options << endl;

    for (auto desc: allClasses)
    {
        if (auto parent = desc->getParentClassDescriptor())
        {
            line() << parent->getName() << "->" << desc->getName();
        }
    }

    cout << endl << "}" << endl;

    return 0;
}
<commit_msg>Add labels for references<commit_after>#include <iostream>
#include <ref/utils/StructuralContext.hpp>
#include "company.hpp"

using namespace ref;
using namespace example;
using namespace std;

const char * options =
    "node ["
    " fontname = \"Bitstream Vera Sans\""
    " fontsize = 8"
    " shape = \"record\""
    "]";
const char * reference_options =
    "edge ["
    " fontname = \"Bitstream Vera Sans\""
    " fontsize = 8"
    "]";
const char * inherit_options =
    "edge[dir=back, arrowtail=empty]";

std::ostream& line()
{
    return cout << endl << "    ";
}

int main(int argc, char **argv)
{
    auto companyDesc =
        example::Company::getClassDescriptorInstance();
    const StructuralContext ctx(companyDesc);

    cout << "digraph " << companyDesc->getName();
    cout << endl << "{" << endl;
    line() << options << endl;

    const auto& allClasses = ctx.getAllClasses();

    // Attributes
    for (auto desc: allClasses)
    {
        line() << desc->getName() << " [";
        line() << "    label = \"{" << desc->getName() << "|";

        for (auto feature : desc->getFeatureDescriptors())
        {
            if (ctx.isReference(feature)) continue;

            cout << feature->getName() << " : "
                 << feature->getTypeDescriptor()->getFqn() << "\\l";
        }

        cout << "}\"";
        line() << "]";
    }
    cout << endl;

    // References
    line() << reference_options << endl;

    for (auto desc: allClasses)
    {
        const auto& references = ctx.getOutgoingReferences(desc);
        for (const auto& ref : references)
        {
            line() << ref.classDesc->getName() << "->"
                   << ref.referencedClassDesc->getName() << " [ label = \""
                   << ref.featureDesc->getName() << "\" ];";
        }
    }
    cout << endl;

    // Parent classes
    line() << inherit_options << endl;

    for (auto desc: allClasses)
    {
        if (auto parent = desc->getParentClassDescriptor())
        {
            line() << parent->getName() << "->" << desc->getName();
        }
    }

    cout << endl << "}" << endl;

    return 0;
}
<|endoftext|>


<commit_before>/**
 * @file
 */
#include "bi/primitive/encode.hpp"

#include "boost/algorithm/string.hpp"

#include <iomanip>
#include <locale>
#include <codecvt>

std::string bi::encode32(const std::string& in) {
  std::string out;
  out.resize((in.length() + 4) / 5 * 7);

  unsigned long num, i1, i2, j;
  for (i1 = 0, i2 = 0; i1 < in.length(); i1 += 5, i2 += 7) {
    num = 0;
    for (j = 0; j < 5; ++j) {
      num <<= 7;
      if (i1 + j < in.length()) {
        num |= in[i1 + j] & 0x7F;
      }
    }
    for (j = 0; j < 7; ++j) {
      out[i2 + 6 - j] = encode32(num & 0x1F);
      num >>= 5;
    }
  }
  return out;
}

std::string bi::decode32(const std::string& in) {
  std::string out;
  out.resize((in.length() + 6) / 7 * 5);

  unsigned long num, i1, i2, j;
  for (i1 = 0, i2 = 0; i1 < in.length(); i1 += 7, i2 += 5) {
    num = 0;
    for (j = 0; j < 7; ++j) {
      num <<= 5;
      if (i1 + j < in.length()) {
        num |= decode32(in[i1 + j]) & 0x1F;
      }
    }
    for (j = 0; j < 5; ++j) {
      out[i2 + 4 - j] = num & 0x7F;
      num >>= 7;
    }
  }
  return out;
}

unsigned char bi::encode32(const unsigned char c) {
  /* pre-condition */
  assert(c < 32u);

  unsigned char d = c + ((c < 26u) ? 'a' : '0' - 26u);

  /* post-condition */
  assert((d >= 'a' && d <= 'z') || (d >= '0' && d <= '5'));

  return d;
}

unsigned char bi::decode32(const unsigned char c) {
  /* pre-condition */
  assert((c >= 'a' && c <= 'z') || (c >= '0' && c <= '5'));

  unsigned char d = c - ((c >= 'a') ? 'a' : '0' - 26u);

  /* post-condition */
  assert(d < 32u);

  return d;
}

bool bi::isTranslatable(const std::string& op) {
  static std::unordered_set<std::string> ops;
  static bool init = false;
  if (!init) {
    ops.insert("+");
    ops.insert("-");
    ops.insert("*");
    ops.insert("/");
    ops.insert("<");
    ops.insert(">");
    ops.insert("<=");
    ops.insert(">=");
    ops.insert("==");
    ops.insert("!=");
    ops.insert("!");
    ops.insert("||");
    ops.insert("&&");

    init = true;
  }
  return ops.find(op) != ops.end();
}

std::string bi::nice(const std::string& name) {
  /* translations */
  static std::regex reg;
  static std::unordered_map<std::string,std::string> ops;
  static bool init = false;
  if (!init) {
    ops["<-"] = "assign_";
    ops["<~"] = "left_tilde_";
    ops["~>"] = "right_tilde_";
    ops["~"] = "tilde_";
    ops[".."] = "range_";
    ops["+"] = "add_";
    ops["-"] = "subtract_";
    ops["*"] = "multiply_";
    ops["/"] = "divide_";
    ops["<"] = "lt_";
    ops[">"] = "gt_";
    ops["<="] = "le_";
    ops[">="] = "ge_";
    ops["=="] = "eq_";
    ops["!="] = "ne_";
    ops["!"] = "not_";
    ops["||"] = "or_";
    ops["&&"] = "and_";

    init = true;
  }

  /* translate operators */
  std::string str = name;
  if (ops.find(name) != ops.end()) {
    str = ops[name];
  }

  /* translate prime (apostrophe at end of name) */
  boost::replace_last(str, "'", "_prime_");

  return str;
}

std::string bi::internalise(const std::string& name) {
  return escape_unicode(nice(name));
}

std::string bi::escape_unicode(const std::string& str) {
  /* ideally we would write the UTF-8 encoded character (works with clang at
   * least), next best would be a \u0000 universal character name (works with
   * gcc at least), but failing that (Intel compiler) we just write _u0000 as
   * the name */
  std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> converter;
  std::u16string wstr = converter.from_bytes(str);
  std::stringstream buf;
  for (wchar_t c : wstr) {
    if (c < 127) {
      buf << (char)c;
    } else {
      buf << "_u" << std::setfill('0') << std::setw(4) << c;
    }
  }
  return buf.str();
}

std::string bi::detailed(const std::string& str) {
  std::regex reg(" *\n *\\* ?");
  std::stringstream buf;
  std::smatch match;
  std::string str1 = str;
  while (std::regex_search(str1, match, reg)) {
    buf << match.prefix() << '\n';
    str1 = match.suffix();
  }
  buf << str1;
  str1 = buf.str();
  boost::trim(str1);

  return str1;
}

std::string bi::brief(const std::string& str) {
  std::regex reg(".*?[\\.\\?\\!]");
  std::stringstream buf;
  std::smatch match;
  std::string str1 = one_line(str);
  if (std::regex_search(str1, match, reg)) {
    return one_line(match.str());
  } else {
    return "";
  }
}

std::string bi::one_line(const std::string& str) {
  std::string str1 = detailed(str);
  boost::replace_all(str1, "\n", " ");
  return str1;
}

std::string bi::anchor(const std::string& name) {
  std::string str = name;
  boost::to_lower(str);
  boost::replace_all(str, " ", "-");
  boost::replace_all(str, "_", "-");
  return str;
}

std::string bi::quote(const std::string& str, const std::string& indent) {
  std::string result = indent + str;
  boost::replace_all(result, "\n", std::string("\n") + indent);
  return result;
}
<commit_msg>Fixed C++ code generation for more than one prime at the end of a name.<commit_after>/**
 * @file
 */
#include "bi/primitive/encode.hpp"

#include "boost/algorithm/string.hpp"

#include <iomanip>
#include <locale>
#include <codecvt>

std::string bi::encode32(const std::string& in) {
  std::string out;
  out.resize((in.length() + 4) / 5 * 7);

  unsigned long num, i1, i2, j;
  for (i1 = 0, i2 = 0; i1 < in.length(); i1 += 5, i2 += 7) {
    num = 0;
    for (j = 0; j < 5; ++j) {
      num <<= 7;
      if (i1 + j < in.length()) {
        num |= in[i1 + j] & 0x7F;
      }
    }
    for (j = 0; j < 7; ++j) {
      out[i2 + 6 - j] = encode32(num & 0x1F);
      num >>= 5;
    }
  }
  return out;
}

std::string bi::decode32(const std::string& in) {
  std::string out;
  out.resize((in.length() + 6) / 7 * 5);

  unsigned long num, i1, i2, j;
  for (i1 = 0, i2 = 0; i1 < in.length(); i1 += 7, i2 += 5) {
    num = 0;
    for (j = 0; j < 7; ++j) {
      num <<= 5;
      if (i1 + j < in.length()) {
        num |= decode32(in[i1 + j]) & 0x1F;
      }
    }
    for (j = 0; j < 5; ++j) {
      out[i2 + 4 - j] = num & 0x7F;
      num >>= 7;
    }
  }
  return out;
}

unsigned char bi::encode32(const unsigned char c) {
  /* pre-condition */
  assert(c < 32u);

  unsigned char d = c + ((c < 26u) ? 'a' : '0' - 26u);

  /* post-condition */
  assert((d >= 'a' && d <= 'z') || (d >= '0' && d <= '5'));

  return d;
}

unsigned char bi::decode32(const unsigned char c) {
  /* pre-condition */
  assert((c >= 'a' && c <= 'z') || (c >= '0' && c <= '5'));

  unsigned char d = c - ((c >= 'a') ? 'a' : '0' - 26u);

  /* post-condition */
  assert(d < 32u);

  return d;
}

bool bi::isTranslatable(const std::string& op) {
  static std::unordered_set<std::string> ops;
  static bool init = false;
  if (!init) {
    ops.insert("+");
    ops.insert("-");
    ops.insert("*");
    ops.insert("/");
    ops.insert("<");
    ops.insert(">");
    ops.insert("<=");
    ops.insert(">=");
    ops.insert("==");
    ops.insert("!=");
    ops.insert("!");
    ops.insert("||");
    ops.insert("&&");

    init = true;
  }
  return ops.find(op) != ops.end();
}

std::string bi::nice(const std::string& name) {
  /* translations */
  static std::regex reg;
  static std::unordered_map<std::string,std::string> ops;
  static bool init = false;
  if (!init) {
    ops["<-"] = "assign_";
    ops["<~"] = "left_tilde_";
    ops["~>"] = "right_tilde_";
    ops["~"] = "tilde_";
    ops[".."] = "range_";
    ops["+"] = "add_";
    ops["-"] = "subtract_";
    ops["*"] = "multiply_";
    ops["/"] = "divide_";
    ops["<"] = "lt_";
    ops[">"] = "gt_";
    ops["<="] = "le_";
    ops[">="] = "ge_";
    ops["=="] = "eq_";
    ops["!="] = "ne_";
    ops["!"] = "not_";
    ops["||"] = "or_";
    ops["&&"] = "and_";

    init = true;
  }

  /* translate operators */
  std::string str = name;
  if (ops.find(name) != ops.end()) {
    str = ops[name];
  }

  /* translate prime (apostrophe at end of name) */
  boost::replace_all(str, "'", "_prime_");

  return str;
}

std::string bi::internalise(const std::string& name) {
  return escape_unicode(nice(name));
}

std::string bi::escape_unicode(const std::string& str) {
  /* ideally we would write the UTF-8 encoded character (works with clang at
   * least), next best would be a \u0000 universal character name (works with
   * gcc at least), but failing that (Intel compiler) we just write _u0000 as
   * the name */
  std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> converter;
  std::u16string wstr = converter.from_bytes(str);
  std::stringstream buf;
  for (wchar_t c : wstr) {
    if (c < 127) {
      buf << (char)c;
    } else {
      buf << "_u" << std::setfill('0') << std::setw(4) << c;
    }
  }
  return buf.str();
}

std::string bi::detailed(const std::string& str) {
  std::regex reg(" *\n *\\* ?");
  std::stringstream buf;
  std::smatch match;
  std::string str1 = str;
  while (std::regex_search(str1, match, reg)) {
    buf << match.prefix() << '\n';
    str1 = match.suffix();
  }
  buf << str1;
  str1 = buf.str();
  boost::trim(str1);

  return str1;
}

std::string bi::brief(const std::string& str) {
  std::regex reg(".*?[\\.\\?\\!]");
  std::stringstream buf;
  std::smatch match;
  std::string str1 = one_line(str);
  if (std::regex_search(str1, match, reg)) {
    return one_line(match.str());
  } else {
    return "";
  }
}

std::string bi::one_line(const std::string& str) {
  std::string str1 = detailed(str);
  boost::replace_all(str1, "\n", " ");
  return str1;
}

std::string bi::anchor(const std::string& name) {
  std::string str = name;
  boost::to_lower(str);
  boost::replace_all(str, " ", "-");
  boost::replace_all(str, "_", "-");
  return str;
}

std::string bi::quote(const std::string& str, const std::string& indent) {
  std::string result = indent + str;
  boost::replace_all(result, "\n", std::string("\n") + indent);
  return result;
}
<|endoftext|>


<commit_before>#pragma once
#ifndef WTL_CLUSTER_HPP_
#define WTL_CLUSTER_HPP_

#include "random.hpp"

#include <valarray>
#include <vector>
#include <limits>

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////
namespace wtl { namespace cluster {
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////

template <class ValArray>
double euclidean_distance(ValArray&& v) {
    return std::sqrt((v * v).sum());
}

template <class T, class URBG>
class PAM {
  public:
    PAM(const std::vector<std::valarray<T>>& points, size_t k, URBG&& engine, size_t max_iteration)
    : points_(points), labels_(points.size()) {
        const auto n = points_.size();
        const auto indices = wtl::sample(points.size(), k, engine);
        medoids_.assign(indices.begin(), indices.end());
        for (size_t step=0; step<max_iteration; ++step) {
            for (size_t i=0; i<n; ++i) {
                labels_[i] = classify(i);
            }
            auto prev_medoids = medoids_;
            for (size_t i=0; i<k; ++i) {
                medoids_[i] = select_medoid(i);
            }
            if (medoids_ == prev_medoids) break;
        }
    }

    const auto& points() const noexcept {return points_;}
    const auto& labels() const noexcept {return labels_;}
    const auto& medoids() const noexcept {return medoids_;}

  private:
    size_t classify(size_t i) const {
        const auto& x = points_[i];
        double min_dist = std::numeric_limits<double>::max();
        size_t best_cluster = std::numeric_limits<size_t>::max();
        for (size_t cluster=0; cluster<medoids_.size(); ++cluster) {
            const auto dist = euclidean_distance(x - points_[medoids_[cluster]]);
            if (dist < min_dist) {
                min_dist = dist;
                best_cluster = cluster;
            }
        }
        return best_cluster;
    }

    size_t select_medoid(size_t cluster) const {
        const size_t n = points_.size();
        double min_dist = std::numeric_limits<double>::max();
        size_t medoid_idx = std::numeric_limits<size_t>::max();
        for (size_t i=0; i<n; ++i) {
            if (labels_[i] != cluster) continue;
            double dist = 0.0;
            for (size_t j=0; j<n; ++j) {
                if (labels_[j] != cluster) continue;
                dist += euclidean_distance(points_[i] - points_[j]);
            }
            if (dist < min_dist) {
                min_dist = dist;
                medoid_idx = i;
            }
        }
        return medoid_idx;
    }

    const std::vector<std::valarray<T>>& points_;
    std::vector<size_t> labels_;
    std::vector<size_t> medoids_;
};

template <class T, class URBG> inline
auto pam(const T& points, size_t k, URBG&& engine, size_t max_iteration=10ul) {
    return PAM<typename T::value_type::value_type, URBG>(points, k, std::forward<URBG>(engine), max_iteration);
}

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////
}} // namespace wtl::cluster
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////

#endif // WTL_CLUSTER_HPP_
<commit_msg>:art: cluster.hpp: Generalize coordinate type<commit_after>#pragma once
#ifndef WTL_CLUSTER_HPP_
#define WTL_CLUSTER_HPP_

#include "random.hpp"

#include <vector>
#include <limits>

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////
namespace wtl { namespace cluster {
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////

template <class ValArray>
double euclidean_distance(ValArray&& v) {
    return std::sqrt((v * v).sum());
}

template <class T, class URBG>
class PAM {
  public:
    PAM(const std::vector<T>& points, size_t k, URBG&& engine, size_t max_iteration)
    : points_(points), labels_(points.size()) {
        const auto n = points_.size();
        const auto indices = wtl::sample(points.size(), k, engine);
        medoids_.assign(indices.begin(), indices.end());
        for (size_t step=0; step<max_iteration; ++step) {
            for (size_t i=0; i<n; ++i) {
                labels_[i] = classify(i);
            }
            auto prev_medoids = medoids_;
            for (size_t i=0; i<k; ++i) {
                medoids_[i] = select_medoid(i);
            }
            if (medoids_ == prev_medoids) break;
        }
    }

    const auto& points() const noexcept {return points_;}
    const auto& labels() const noexcept {return labels_;}
    const auto& medoids() const noexcept {return medoids_;}

  private:
    size_t classify(size_t i) const {
        const auto& x = points_[i];
        double min_dist = std::numeric_limits<double>::max();
        size_t best_cluster = std::numeric_limits<size_t>::max();
        for (size_t cluster=0; cluster<medoids_.size(); ++cluster) {
            const auto dist = euclidean_distance(x - points_[medoids_[cluster]]);
            if (dist < min_dist) {
                min_dist = dist;
                best_cluster = cluster;
            }
        }
        return best_cluster;
    }

    size_t select_medoid(size_t cluster) const {
        const size_t n = points_.size();
        double min_dist = std::numeric_limits<double>::max();
        size_t medoid_idx = std::numeric_limits<size_t>::max();
        for (size_t i=0; i<n; ++i) {
            if (labels_[i] != cluster) continue;
            double dist = 0.0;
            for (size_t j=0; j<n; ++j) {
                if (labels_[j] != cluster) continue;
                dist += euclidean_distance(points_[i] - points_[j]);
            }
            if (dist < min_dist) {
                min_dist = dist;
                medoid_idx = i;
            }
        }
        return medoid_idx;
    }

    const std::vector<T>& points_;
    std::vector<size_t> labels_;
    std::vector<size_t> medoids_;
};

template <class T, class URBG> inline
auto pam(const T& points, size_t k, URBG&& engine, size_t max_iteration=10ul) {
    return PAM<typename T::value_type, URBG>(points, k, std::forward<URBG>(engine), max_iteration);
}

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////
}} // namespace wtl::cluster
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////

#endif // WTL_CLUSTER_HPP_
<|endoftext|>


<commit_before>// Copyright 2015-2020 Elviss Strazdins. All rights reserved.

#ifndef OUZEL_UTILS_THREAD_HPP
#define OUZEL_UTILS_THREAD_HPP

#include <system_error>
#include <thread>
#if defined(_WIN32)
#  pragma push_macro("WIN32_LEAN_AND_MEAN")
#  pragma push_macro("NOMINMAX")
#  ifndef WIN32_LEAN_AND_MEAN
#    define WIN32_LEAN_AND_MEAN
#  endif
#  ifndef NOMINMAX
#    define NOMINMAX
#  endif
#  include <Windows.h>
#  pragma pop_macro("WIN32_LEAN_AND_MEAN")
#  pragma pop_macro("NOMINMAX")
#elif defined(__unix__) || defined(__APPLE__)
#  include <pthread.h>
#endif

namespace ouzel
{
    class Thread final
    {
    public:
        Thread() noexcept = default;

        Thread(const Thread&) = delete;
        Thread(Thread&& other) noexcept: t(std::move(other.t)) {}

        Thread(const std::thread&) = delete;
        Thread(std::thread&& other) noexcept: t(std::move(other)) {}

        Thread& operator=(const Thread&) = delete;
        Thread& operator=(Thread&& other) noexcept
        {
            t = std::move(other.t);
            return *this;
        }

        Thread& operator=(const std::thread&) = delete;
        Thread& operator=(std::thread&& other) noexcept
        {
            t = std::move(other);
            return *this;
        }

        template <typename Callable, typename... Args>
        explicit Thread(Callable&& f, Args&&... args):
            t(std::forward<Callable>(f), std::forward<Args>(args)...)
        {
        }

        ~Thread()
        {
            if (t.joinable()) t.join();
        }

        auto isJoinable() const { return t.joinable(); }
        auto getId() const noexcept { return t.get_id(); }
        auto getNativeHandle() { return t.native_handle(); }

        void join()
        {
            t.join();
        }

        void setPriority(float priority, bool realtime)
        {
#if defined(_MSC_VER)
            static_cast<void>(realtime);
            static constexpr int priorities[] = {
                THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL,
                THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL
            };

            if (!SetThreadPriority(t.native_handle(), priorities[static_cast<std::size_t>((priority + 1.0F) * 6.0F / 2.0F)]))
                throw std::system_error(GetLastError(), std::system_category(), "Failed to set thread name");
#else
            if (priority < 0.0F) priority = 0.0F;

            const int policy = realtime ? SCHED_RR : SCHED_OTHER;

            const int minPriority = sched_get_priority_min(policy);
            if (minPriority == -1)
                throw std::system_error(errno, std::system_category(), "Failed to get thread min priority");
            const int maxPriority = sched_get_priority_max(policy);
            if (maxPriority == -1)
                throw std::system_error(errno, std::system_category(), "Failed to get thread max priority");

            sched_param param;
            param.sched_priority = static_cast<int>(priority * (maxPriority - minPriority)) + minPriority;
            const int error = pthread_setschedparam(t.native_handle(), policy, &param);
            if (error != 0)
                throw std::system_error(error, std::system_category(), "Failed to set thread priority");
#endif
        }

        static void setCurrentThreadName(const std::string& name)
        {
#if defined(_MSC_VER)
            constexpr DWORD MS_VC_EXCEPTION = 0x406D1388;
#  pragma pack(push,8)
            typedef struct tagTHREADNAME_INFO
            {
                DWORD dwType; // Must be 0x1000.
                LPCSTR szName; // Pointer to name (in user addr space).
                DWORD dwThreadID; // Thread ID (-1=caller thread).
                DWORD dwFlags; // Reserved for future use, must be zero.
            } THREADNAME_INFO;
#  pragma pack(pop)

            THREADNAME_INFO info;
            info.dwType = 0x1000;
            info.szName = name.c_str();
            info.dwThreadID = static_cast<DWORD>(-1);
            info.dwFlags = 0;

            const DWORD numberOfArguments = sizeof(info) / sizeof(ULONG_PTR);
            ULONG_PTR arguments[numberOfArguments];
            std::memcpy(arguments, &info, sizeof(info));

            __try
            {
                RaiseException(MS_VC_EXCEPTION, 0, numberOfArguments, arguments);
            }
            __except (EXCEPTION_EXECUTE_HANDLER)
            {
            }
#else
#  ifdef __APPLE__
            const int error = pthread_setname_np(name.c_str());
            if (error != 0)
                throw std::system_error(error, std::system_category(), "Failed to set thread name");
#  elif defined(__linux__)
            const int error = pthread_setname_np(pthread_self(), name.c_str());
            if (error != 0)
                throw std::system_error(error, std::system_category(), "Failed to set thread name");
#  endif
#endif
        }

    private:
        std::thread t;
    };
}

#endif // OUZEL_UTILS_THREAD_HPP
<commit_msg>Make isJoinable noexcept<commit_after>// Copyright 2015-2020 Elviss Strazdins. All rights reserved.

#ifndef OUZEL_UTILS_THREAD_HPP
#define OUZEL_UTILS_THREAD_HPP

#include <system_error>
#include <thread>
#if defined(_WIN32)
#  pragma push_macro("WIN32_LEAN_AND_MEAN")
#  pragma push_macro("NOMINMAX")
#  ifndef WIN32_LEAN_AND_MEAN
#    define WIN32_LEAN_AND_MEAN
#  endif
#  ifndef NOMINMAX
#    define NOMINMAX
#  endif
#  include <Windows.h>
#  pragma pop_macro("WIN32_LEAN_AND_MEAN")
#  pragma pop_macro("NOMINMAX")
#elif defined(__unix__) || defined(__APPLE__)
#  include <pthread.h>
#endif

namespace ouzel
{
    class Thread final
    {
    public:
        Thread() noexcept = default;

        Thread(const Thread&) = delete;
        Thread(Thread&& other) noexcept: t(std::move(other.t)) {}

        Thread(const std::thread&) = delete;
        Thread(std::thread&& other) noexcept: t(std::move(other)) {}

        Thread& operator=(const Thread&) = delete;
        Thread& operator=(Thread&& other) noexcept
        {
            t = std::move(other.t);
            return *this;
        }

        Thread& operator=(const std::thread&) = delete;
        Thread& operator=(std::thread&& other) noexcept
        {
            t = std::move(other);
            return *this;
        }

        template <typename Callable, typename... Args>
        explicit Thread(Callable&& f, Args&&... args):
            t(std::forward<Callable>(f), std::forward<Args>(args)...)
        {
        }

        ~Thread()
        {
            if (t.joinable()) t.join();
        }

        auto isJoinable() const noexcept { return t.joinable(); }
        auto getId() const noexcept { return t.get_id(); }
        auto getNativeHandle() { return t.native_handle(); }

        void join()
        {
            t.join();
        }

        void setPriority(float priority, bool realtime)
        {
#if defined(_MSC_VER)
            static_cast<void>(realtime);
            static constexpr int priorities[] = {
                THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL,
                THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL
            };

            if (!SetThreadPriority(t.native_handle(), priorities[static_cast<std::size_t>((priority + 1.0F) * 6.0F / 2.0F)]))
                throw std::system_error(GetLastError(), std::system_category(), "Failed to set thread name");
#else
            if (priority < 0.0F) priority = 0.0F;

            const int policy = realtime ? SCHED_RR : SCHED_OTHER;

            const int minPriority = sched_get_priority_min(policy);
            if (minPriority == -1)
                throw std::system_error(errno, std::system_category(), "Failed to get thread min priority");
            const int maxPriority = sched_get_priority_max(policy);
            if (maxPriority == -1)
                throw std::system_error(errno, std::system_category(), "Failed to get thread max priority");

            sched_param param;
            param.sched_priority = static_cast<int>(priority * (maxPriority - minPriority)) + minPriority;
            const int error = pthread_setschedparam(t.native_handle(), policy, &param);
            if (error != 0)
                throw std::system_error(error, std::system_category(), "Failed to set thread priority");
#endif
        }

        static void setCurrentThreadName(const std::string& name)
        {
#if defined(_MSC_VER)
            constexpr DWORD MS_VC_EXCEPTION = 0x406D1388;
#  pragma pack(push,8)
            typedef struct tagTHREADNAME_INFO
            {
                DWORD dwType; // Must be 0x1000.
                LPCSTR szName; // Pointer to name (in user addr space).
                DWORD dwThreadID; // Thread ID (-1=caller thread).
                DWORD dwFlags; // Reserved for future use, must be zero.
            } THREADNAME_INFO;
#  pragma pack(pop)

            THREADNAME_INFO info;
            info.dwType = 0x1000;
            info.szName = name.c_str();
            info.dwThreadID = static_cast<DWORD>(-1);
            info.dwFlags = 0;

            const DWORD numberOfArguments = sizeof(info) / sizeof(ULONG_PTR);
            ULONG_PTR arguments[numberOfArguments];
            std::memcpy(arguments, &info, sizeof(info));

            __try
            {
                RaiseException(MS_VC_EXCEPTION, 0, numberOfArguments, arguments);
            }
            __except (EXCEPTION_EXECUTE_HANDLER)
            {
            }
#else
#  ifdef __APPLE__
            const int error = pthread_setname_np(name.c_str());
            if (error != 0)
                throw std::system_error(error, std::system_category(), "Failed to set thread name");
#  elif defined(__linux__)
            const int error = pthread_setname_np(pthread_self(), name.c_str());
            if (error != 0)
                throw std::system_error(error, std::system_category(), "Failed to set thread name");
#  endif
#endif
        }

    private:
        std::thread t;
    };
}

#endif // OUZEL_UTILS_THREAD_HPP
<|endoftext|>


<commit_before>#include <iostream>
#include "LoadImageModule.hpp"

using namespace std;
using namespace uipf;

// executes the Module
/*
input 		is a std::map of input resources, the names are described in the module meta description
params 		is a std::map of input paramaeters, the names are described in the module meta description
ouput 		is a std::map of output resources, the names are described in the module meta description
context 	is a container providing access to the current environment, allowing to open windows, write to logger etc...
*/
void LoadImageModule::run(map<string, Data*>& input, map<string, string> params, map<string, Data*>& output, Context context) const
{
	cout << "Dummy Module has been executed with the following params:";
	cout << endl;

	map<string, string>::iterator it = params.begin();
	for( ; it!=params.end(); ++it) {
		cout << "    " << it->first << " - " << it->second << endl;
	}

}

std::string LoadImageModule::name() const
{
	return "loadImage";
}
<commit_msg>fixed typo<commit_after>#include <iostream>
#include "LoadImageModule.hpp"

using namespace std;
using namespace uipf;

// executes the Module
/*
input 		is a std::map of input resources, the names are described in the module meta description
params 		is a std::map of input paramaeters, the names are described in the module meta description
ouput 		is a std::map of output resources, the names are described in the module meta description
context 	is a container providing access to the current environment, allowing to open windows, write to logger etc...
*/
void LoadImageModule::run(map<string, Data*>& input, map<string, string> params, map<string, Data*>& output, Context context) const
{
	cout << "LoadImage Module has been executed with the following params:";
	cout << endl;

	map<string, string>::iterator it = params.begin();
	for( ; it!=params.end(); ++it) {
		cout << "    " << it->first << " - " << it->second << endl;
	}

}

std::string LoadImageModule::name() const
{
	return "loadImage";
}
<|endoftext|>


<commit_before>/*
 *  caosVar.cpp
 *  openc2e
 *
 *  Created by Bryan Donlan on Thu Mar 10 2005.
 *  Copyright (c) 2005-2006 Alyssa Milburn and Bryan Donlan. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 */

#define IN_CAOSVAR_CPP

#include "caosVar.h"

#include <iostream>
#include <sstream>
#include <boost/format.hpp>

#ifdef DONT_INLINE_CAOSVAR_ACCESSORS
#error meh, copy the stuff out of caosVar.h and drop it here
#endif

using boost::str;

static inline std::string stringify(double x) {
	std::ostringstream o;
	if (!(o << x)) throw "stringify() failed";
	return o.str();
}

std::string caosVar::dump() const {
	switch(getType()) {
		case STRING:
			return str(boost::format("String \"%s\" ") % getString());
			break;
		case INTEGER:
			return str(boost::format("Int %d ") % getInt());
			break;
		case FLOAT:
			return str(boost::format("Float %f ") % getFloat());
			break;
		case AGENT:
			return str(boost::format("Agent %p ") % (Agent *)getAgent().get());
			break;
		case VECTOR:
			return str(boost::format("Vector (%f, %f)") % getVector().x % getVector().y);
			break;
		default:
			return "[bad caosVar!] ";
			break;
	};
}

bool caosVar::operator == (const caosVar &v) const {
	// todo: should be able to compare int and float, apparently
	if (this->hasInt() && v.hasInt()) {
		return this->getInt() == v.getInt();
	} else if (this->hasDecimal() && v.hasDecimal()) {
		return this->getFloat() == v.getFloat();
	} else if (this->hasString() && v.hasString()) {
		return this->getString() == v.getString();
	} else if (this->hasAgent() && v.hasAgent()) {
		return this->getAgent() == v.getAgent();
	} else if (this->hasVector() && v.hasVector()) {
		return this->getVector() == v.getVector();
	}

	throw caosException(std::string("caosVar operator == couldn't compare ") + this->dump() + "and " + v.dump());
}

bool caosVar::operator > (const caosVar &v) const {
	if (this->hasDecimal() && v.hasDecimal()) {
		return this->getFloat() > v.getFloat();
	} else if (this->hasString() && v.hasString()) {
		return this->getString() > v.getString();
	} else if (this->hasVector() && v.hasVector()) {
		// XXX this is totally arbitrary
		const Vector<float> &v1 = this->getVector();
		const Vector<float> &v2 = v.getVector();
		if (v1.x > v2.x)
			return true;
		else if (v1.x < v2.x)
			return false;
		else if (v1.y > v2.y)
			return true;
		else return false;
	}

	throw caosException(std::string("caosVar operator > couldn't compare ") + this->dump() + "and " + v.dump());
}

bool caosVar::operator < (const caosVar &v) const {
	if (this->hasDecimal() && v.hasDecimal()) {
		return this->getFloat() < v.getFloat();
	} else if (this->hasString() && v.hasString()) {
		return this->getString() < v.getString();
	} else if (this->hasVector() && v.hasVector()) {
		return (*this != v) && !(*this > v);
	}

	throw caosException(std::string("caosVar operator < couldn't compare ") + this->dump() + "and " + v.dump());
}

/* vim: set noet: */
<commit_msg>allow comparing agents to zero in C1/C2<commit_after>/*
 *  caosVar.cpp
 *  openc2e
 *
 *  Created by Bryan Donlan on Thu Mar 10 2005.
 *  Copyright (c) 2005-2006 Alyssa Milburn and Bryan Donlan. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 */

#define IN_CAOSVAR_CPP

#include "caosVar.h"
#include "Engine.h" // version

#include <iostream>
#include <sstream>
#include <boost/format.hpp>

#ifdef DONT_INLINE_CAOSVAR_ACCESSORS
#error meh, copy the stuff out of caosVar.h and drop it here
#endif

using boost::str;

static inline std::string stringify(double x) {
	std::ostringstream o;
	if (!(o << x)) throw "stringify() failed";
	return o.str();
}

std::string caosVar::dump() const {
	switch(getType()) {
		case STRING:
			return str(boost::format("String \"%s\" ") % getString());
			break;
		case INTEGER:
			return str(boost::format("Int %d ") % getInt());
			break;
		case FLOAT:
			return str(boost::format("Float %f ") % getFloat());
			break;
		case AGENT:
			return str(boost::format("Agent %p ") % (Agent *)getAgent().get());
			break;
		case VECTOR:
			return str(boost::format("Vector (%f, %f)") % getVector().x % getVector().y);
			break;
		default:
			return "[bad caosVar!] ";
			break;
	};
}

bool caosVar::operator == (const caosVar &v) const {
	// todo: should be able to compare int and float, apparently
	if (this->hasInt() && v.hasInt()) {
		return this->getInt() == v.getInt();
	} else if (this->hasDecimal() && v.hasDecimal()) {
		return this->getFloat() == v.getFloat();
	} else if (this->hasString() && v.hasString()) {
		return this->getString() == v.getString();
	} else if (this->hasAgent() && v.hasAgent()) {
		return this->getAgent() == v.getAgent();
	} else if (this->hasVector() && v.hasVector()) {
		return this->getVector() == v.getVector();
	} else if (engine.version < 3) {
		// C1/C2 allow you to compare an agent to zero, since agents are integers..
		// TODO: do this for >/< too?

		if (this->hasInt() && this->getInt() == 0 && v.hasAgent()) {
			return v.getAgent();
		} else if (v.hasInt() && v.getInt() == 0 && this->hasAgent()) {
			return this->getAgent();
		}
	}

	throw caosException(std::string("caosVar operator == couldn't compare ") + this->dump() + "and " + v.dump());
}

bool caosVar::operator > (const caosVar &v) const {
	if (this->hasDecimal() && v.hasDecimal()) {
		return this->getFloat() > v.getFloat();
	} else if (this->hasString() && v.hasString()) {
		return this->getString() > v.getString();
	} else if (this->hasVector() && v.hasVector()) {
		// XXX this is totally arbitrary
		const Vector<float> &v1 = this->getVector();
		const Vector<float> &v2 = v.getVector();
		if (v1.x > v2.x)
			return true;
		else if (v1.x < v2.x)
			return false;
		else if (v1.y > v2.y)
			return true;
		else return false;
	}

	throw caosException(std::string("caosVar operator > couldn't compare ") + this->dump() + "and " + v.dump());
}

bool caosVar::operator < (const caosVar &v) const {
	if (this->hasDecimal() && v.hasDecimal()) {
		return this->getFloat() < v.getFloat();
	} else if (this->hasString() && v.hasString()) {
		return this->getString() < v.getString();
	} else if (this->hasVector() && v.hasVector()) {
		return (*this != v) && !(*this > v);
	}

	throw caosException(std::string("caosVar operator < couldn't compare ") + this->dump() + "and " + v.dump());
}

/* vim: set noet: */
<|endoftext|>


<commit_before>//========= Copyright Valve Corporation ============//
//
// hydra_monitor.cpp : Interacts with driver_hydra to provide overlay instructions at startup
//

#include "stdafx.h"
#include "hydra_monitor.h"
#include <openvr.h>

#include <set>
#include <chrono>
#include <thread>
#include <sstream>

const std::chrono::milliseconds k_MonitorInterval( 50 );

class CHydraMonitor
{
public:
	CHydraMonitor( const std::string & path )
		: m_strOverlayImagePath( path )
		, m_OverlayHandle( vr::k_ulOverlayHandleInvalid )
		, m_eCurrentOverlay( k_eNone )
	{}

	~CHydraMonitor() {}

	void Run()
	{
		if ( Init() )
		{
			MainLoop();
		}

		Shutdown();
	}

protected:

	enum EOverlayToDisplay { k_eNone, k_ePointAtBaseForHemisphereTracking, k_eHoldAtShouldersForCoordinateAlignment };

	bool Init()
	{
		// Start as "background" application.  This prevents vrserver from being started
		// on our behalf, and prevents us from keeping vrserver alive when everything else
		// exits.  This is very important because we're spawning from a driver, and any
		// class besides "background" would keep vrserver running forever
		vr::EVRInitError eVRInitError;
		vr::VR_Init( &eVRInitError, vr::VRApplication_Background );
		if ( !vr::VRSystem() || eVRInitError != vr::VRInitError_None )
			return false;

		// Keep track of which devices use driver_hydra
		for ( int i = 0; i < vr::k_unMaxTrackedDeviceCount; ++i )
		{
			UpdateTrackedDevice( i );
		}

		return true;
	}

	void MainLoop()
	{
		while ( true )
		{
			std::this_thread::sleep_for( k_MonitorInterval );

#if defined( WIN32 )
			MSG msg = { 0 };
			while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
			{
				TranslateMessage( &msg );
				DispatchMessage( &msg );
			}

			if ( msg.message == WM_QUIT )
				break;
#endif

			// Display instructions for user if we find any devices that need them
			ShowOverlay( BestOverlayForHydraDevices() );

			vr::VREvent_t Event;
			while ( vr::VRSystem()->PollNextEvent( &Event, sizeof( Event ) ) )
			{
				switch ( Event.eventType )
				{
				case vr::VREvent_Quit:
					exit( 0 );
					// NOTREAHED

				case vr::VREvent_TrackedDeviceActivated:
				case vr::VREvent_TrackedDeviceUpdated:
					UpdateTrackedDevice( Event.trackedDeviceIndex );
					break;

				case vr::VREvent_VendorSpecific_Reserved_Start + 0:
					// User has made the "align" gesture.  The driver can't see the HMD
					// coordinates, so we forward those from our client view.
					if ( IsHydraDevice( Event.trackedDeviceIndex ) )
					{
						TriggerRealignCoordinates( Event );
					}
					break;
				}
			}
		}
	}

	/** Create and show an overlay nailed to the user's face */
	bool ShowOverlay( EOverlayToDisplay eOverlay )
	{
		if ( m_eCurrentOverlay == eOverlay && m_OverlayHandle != vr::k_ulOverlayHandleInvalid )
			return true;

		// Hiding or changing, so destroy old overlay
		HideOverlay();

		if ( eOverlay == k_eNone )
		{
			m_eCurrentOverlay = eOverlay;
			return true;
		}

		// Compositor must be initialized to create overlays
		if ( !vr::VRCompositor() )
			return false;

		vr::EVROverlayError eOverlayError = vr::VROverlay()->CreateOverlay( "hydra_monitor", "Hydra Monitor", &m_OverlayHandle );
		if ( eOverlayError != vr::VROverlayError_None )
			return false;

		vr::HmdMatrix34_t matInFrontOfHead;
		memset( &matInFrontOfHead, 0, sizeof( matInFrontOfHead ) );
		float scale = 1.4f;
		matInFrontOfHead.m[0][0] = matInFrontOfHead.m[1][1] = matInFrontOfHead.m[2][2] = scale;
		matInFrontOfHead.m[2][3] = -2.0f;
		eOverlayError = vr::VROverlay()->SetOverlayTransformTrackedDeviceRelative( m_OverlayHandle,	vr::k_unTrackedDeviceIndex_Hmd,	&matInFrontOfHead );
		if ( eOverlayError != vr::VROverlayError_None )
			return false;

		std::string image;
		switch ( eOverlay )
		{
		case k_ePointAtBaseForHemisphereTracking:
			image = m_strOverlayImagePath + "need_hemisphere_tracking.png";
			break;

		case k_eHoldAtShouldersForCoordinateAlignment:
			image = m_strOverlayImagePath + "need_alignment_gesture.png";
			break;

		default:
			HideOverlay();
			return false;
		}

		eOverlayError = vr::VROverlay()->SetOverlayFromFile( m_OverlayHandle, image.c_str() );
		if ( eOverlayError != vr::VROverlayError_None )
			return false;

		eOverlayError = vr::VROverlay()->ShowOverlay( m_OverlayHandle );
		if ( eOverlayError != vr::VROverlayError_None )
			return false;

		m_eCurrentOverlay = eOverlay;

		return true;
	}

	void HideOverlay()
	{
		if ( m_OverlayHandle == vr::k_ulOverlayHandleInvalid )
			return;

		vr::VRCompositor();  // Required to call overlays...
		vr::VROverlay()->HideOverlay( m_OverlayHandle );
		vr::VROverlay()->DestroyOverlay( m_OverlayHandle );
		m_OverlayHandle = vr::k_ulOverlayHandleInvalid;
	}

	/** Send a message to the driver with the HMD coordinates (which are not available to the server side) */
	bool TriggerRealignCoordinates( const vr::VREvent_t & Event )
	{
		vr::TrackedDevicePose_t hmdPose;
		vr::VRSystem()->GetDeviceToAbsoluteTrackingPose( vr::TrackingUniverseRawAndUncalibrated, -Event.eventAgeSeconds, &hmdPose, 1 );
		if ( !hmdPose.bPoseIsValid )
			return false;

		std::ostringstream ss;
		char rgchReplyBuf[256];

		ss << "hydra:realign_coordinates";
		for ( int i = 0; i < 3; ++i )
		{
			for ( int j = 0; j < 4; ++j )
			{
				ss << " " << hmdPose.mDeviceToAbsoluteTracking.m[i][j];
			}
		}
		vr::VRSystem()->DriverDebugRequest( Event.trackedDeviceIndex, ss.str().c_str(), rgchReplyBuf, sizeof( rgchReplyBuf ) );
		return true;
	}

	void Shutdown()
	{
		vr::VR_Shutdown();
	}

	/** Keep track of which devices are using driver_hydra */
	void UpdateTrackedDevice( uint32_t unTrackedDeviceIndex )
	{
		char rgchTrackingSystemName[vr::k_unTrackingStringSize];
		vr::ETrackedPropertyError eError;

		uint32_t size = vr::VRSystem()->GetStringTrackedDeviceProperty( unTrackedDeviceIndex, vr::Prop_TrackingSystemName_String, rgchTrackingSystemName, sizeof( rgchTrackingSystemName ), &eError );
		if ( eError == vr::TrackedProp_Success )
		{
			if ( strcmp( rgchTrackingSystemName, "hydra" ) == 0 )
			{
				m_setHydraDevices.insert( unTrackedDeviceIndex );
			}
		}
	}

	/** If any Hydra devices need automatic hemisphere tracking enabled, prompt the user to do that.
	 * Otherwise, if any devices do not know how to transform into the global coordinate system, show
	 * instructions for that. */
	EOverlayToDisplay BestOverlayForHydraDevices()
	{
		bool bNeedCoordinateAlignment = false;
		vr::TrackedDevicePose_t poses[vr::k_unMaxTrackedDeviceCount];

		// The "raw and uncalibrated" universe gives us coordinates in the HMD's native tracking space.
		// Adjustments like room setup and seated zero position will be applied equally to the HMD and
		// the coordinates we return, so the "raw" space is what we want our driver to match.
		vr::VRSystem()->GetDeviceToAbsoluteTrackingPose( vr::TrackingUniverseRawAndUncalibrated, 0, poses, vr::k_unMaxTrackedDeviceCount );
		for ( auto it = m_setHydraDevices.begin(); it != m_setHydraDevices.end(); ++it )
		{
			if ( poses[*it].bDeviceIsConnected )
			{
				switch ( poses[*it].eTrackingResult )
				{
				case vr::TrackingResult_Uninitialized:
					// Getting all devices to have hemisphere tracking is high priority
					return k_ePointAtBaseForHemisphereTracking;

				case vr::TrackingResult_Calibrating_InProgress:
					bNeedCoordinateAlignment = true;
					break;
				}
			}
		}

		if ( bNeedCoordinateAlignment )
			return k_eHoldAtShouldersForCoordinateAlignment;

		return k_eNone;
	}

	bool IsHydraDevice( uint32_t unTrackedDeviceIndex )
	{
		return ( m_setHydraDevices.count( unTrackedDeviceIndex ) != 0 );
	}

private:
	std::string m_strOverlayImagePath;
	vr::VROverlayHandle_t m_OverlayHandle;
	EOverlayToDisplay m_eCurrentOverlay;
	std::set<uint32_t> m_setHydraDevices;
};

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

	// Find resource path
	HMODULE hModule = GetModuleHandleA( NULL );
	char path[MAX_PATH];
	GetModuleFileNameA( hModule, path, MAX_PATH );

	char *snip = strstr( path, "\\bin\\" );
	if ( snip )
	{
		*snip = '\0';
	}

	std::string resources = std::string( path ) + "\\resources\\overlays\\";

	CHydraMonitor HydraMonitor( resources );

	HydraMonitor.Run();
}

<commit_msg>removed unavailable constant<commit_after>//========= Copyright Valve Corporation ============//
//
// hydra_monitor.cpp : Interacts with driver_hydra to provide overlay instructions at startup
//

#include "stdafx.h"
#include "hydra_monitor.h"
#include <openvr.h>

#include <set>
#include <chrono>
#include <thread>
#include <sstream>

const std::chrono::milliseconds k_MonitorInterval( 50 );

class CHydraMonitor
{
public:
	CHydraMonitor( const std::string & path )
		: m_strOverlayImagePath( path )
		, m_OverlayHandle( vr::k_ulOverlayHandleInvalid )
		, m_eCurrentOverlay( k_eNone )
	{}

	~CHydraMonitor() {}

	void Run()
	{
		if ( Init() )
		{
			MainLoop();
		}

		Shutdown();
	}

protected:

	enum EOverlayToDisplay { k_eNone, k_ePointAtBaseForHemisphereTracking, k_eHoldAtShouldersForCoordinateAlignment };

	bool Init()
	{
		// Start as "background" application.  This prevents vrserver from being started
		// on our behalf, and prevents us from keeping vrserver alive when everything else
		// exits.  This is very important because we're spawning from a driver, and any
		// class besides "background" would keep vrserver running forever
		vr::EVRInitError eVRInitError;
		vr::VR_Init( &eVRInitError, vr::VRApplication_Background );
		if ( !vr::VRSystem() || eVRInitError != vr::VRInitError_None )
			return false;

		// Keep track of which devices use driver_hydra
		for ( int i = 0; i < vr::k_unMaxTrackedDeviceCount; ++i )
		{
			UpdateTrackedDevice( i );
		}

		return true;
	}

	void MainLoop()
	{
		while ( true )
		{
			std::this_thread::sleep_for( k_MonitorInterval );

#if defined( WIN32 )
			MSG msg = { 0 };
			while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
			{
				TranslateMessage( &msg );
				DispatchMessage( &msg );
			}

			if ( msg.message == WM_QUIT )
				break;
#endif

			// Display instructions for user if we find any devices that need them
			ShowOverlay( BestOverlayForHydraDevices() );

			vr::VREvent_t Event;
			while ( vr::VRSystem()->PollNextEvent( &Event, sizeof( Event ) ) )
			{
				switch ( Event.eventType )
				{
				case vr::VREvent_Quit:
					exit( 0 );
					// NOTREAHED

				case vr::VREvent_TrackedDeviceActivated:
				case vr::VREvent_TrackedDeviceUpdated:
					UpdateTrackedDevice( Event.trackedDeviceIndex );
					break;

				case vr::VREvent_VendorSpecific_Reserved_Start + 0:
					// User has made the "align" gesture.  The driver can't see the HMD
					// coordinates, so we forward those from our client view.
					if ( IsHydraDevice( Event.trackedDeviceIndex ) )
					{
						TriggerRealignCoordinates( Event );
					}
					break;
				}
			}
		}
	}

	/** Create and show an overlay nailed to the user's face */
	bool ShowOverlay( EOverlayToDisplay eOverlay )
	{
		if ( m_eCurrentOverlay == eOverlay && m_OverlayHandle != vr::k_ulOverlayHandleInvalid )
			return true;

		// Hiding or changing, so destroy old overlay
		HideOverlay();

		if ( eOverlay == k_eNone )
		{
			m_eCurrentOverlay = eOverlay;
			return true;
		}

		// Compositor must be initialized to create overlays
		if ( !vr::VRCompositor() )
			return false;

		vr::EVROverlayError eOverlayError = vr::VROverlay()->CreateOverlay( "hydra_monitor", "Hydra Monitor", &m_OverlayHandle );
		if ( eOverlayError != vr::VROverlayError_None )
			return false;

		vr::HmdMatrix34_t matInFrontOfHead;
		memset( &matInFrontOfHead, 0, sizeof( matInFrontOfHead ) );
		float scale = 1.4f;
		matInFrontOfHead.m[0][0] = matInFrontOfHead.m[1][1] = matInFrontOfHead.m[2][2] = scale;
		matInFrontOfHead.m[2][3] = -2.0f;
		eOverlayError = vr::VROverlay()->SetOverlayTransformTrackedDeviceRelative( m_OverlayHandle,	vr::k_unTrackedDeviceIndex_Hmd,	&matInFrontOfHead );
		if ( eOverlayError != vr::VROverlayError_None )
			return false;

		std::string image;
		switch ( eOverlay )
		{
		case k_ePointAtBaseForHemisphereTracking:
			image = m_strOverlayImagePath + "need_hemisphere_tracking.png";
			break;

		case k_eHoldAtShouldersForCoordinateAlignment:
			image = m_strOverlayImagePath + "need_alignment_gesture.png";
			break;

		default:
			HideOverlay();
			return false;
		}

		eOverlayError = vr::VROverlay()->SetOverlayFromFile( m_OverlayHandle, image.c_str() );
		if ( eOverlayError != vr::VROverlayError_None )
			return false;

		eOverlayError = vr::VROverlay()->ShowOverlay( m_OverlayHandle );
		if ( eOverlayError != vr::VROverlayError_None )
			return false;

		m_eCurrentOverlay = eOverlay;

		return true;
	}

	void HideOverlay()
	{
		if ( m_OverlayHandle == vr::k_ulOverlayHandleInvalid )
			return;

		vr::VRCompositor();  // Required to call overlays...
		vr::VROverlay()->HideOverlay( m_OverlayHandle );
		vr::VROverlay()->DestroyOverlay( m_OverlayHandle );
		m_OverlayHandle = vr::k_ulOverlayHandleInvalid;
	}

	/** Send a message to the driver with the HMD coordinates (which are not available to the server side) */
	bool TriggerRealignCoordinates( const vr::VREvent_t & Event )
	{
		vr::TrackedDevicePose_t hmdPose;
		vr::VRSystem()->GetDeviceToAbsoluteTrackingPose( vr::TrackingUniverseRawAndUncalibrated, -Event.eventAgeSeconds, &hmdPose, 1 );
		if ( !hmdPose.bPoseIsValid )
			return false;

		std::ostringstream ss;
		char rgchReplyBuf[256];

		ss << "hydra:realign_coordinates";
		for ( int i = 0; i < 3; ++i )
		{
			for ( int j = 0; j < 4; ++j )
			{
				ss << " " << hmdPose.mDeviceToAbsoluteTracking.m[i][j];
			}
		}
		vr::VRSystem()->DriverDebugRequest( Event.trackedDeviceIndex, ss.str().c_str(), rgchReplyBuf, sizeof( rgchReplyBuf ) );
		return true;
	}

	void Shutdown()
	{
		vr::VR_Shutdown();
	}

	/** Keep track of which devices are using driver_hydra */
	void UpdateTrackedDevice( uint32_t unTrackedDeviceIndex )
	{
		char rgchTrackingSystemName[32]; //was vr::k_unTrackingStringSize
		vr::ETrackedPropertyError eError;

		uint32_t size = vr::VRSystem()->GetStringTrackedDeviceProperty( unTrackedDeviceIndex, vr::Prop_TrackingSystemName_String, rgchTrackingSystemName, sizeof( rgchTrackingSystemName ), &eError );
		if ( eError == vr::TrackedProp_Success )
		{
			if ( strcmp( rgchTrackingSystemName, "hydra" ) == 0 )
			{
				m_setHydraDevices.insert( unTrackedDeviceIndex );
			}
		}
	}

	/** If any Hydra devices need automatic hemisphere tracking enabled, prompt the user to do that.
	 * Otherwise, if any devices do not know how to transform into the global coordinate system, show
	 * instructions for that. */
	EOverlayToDisplay BestOverlayForHydraDevices()
	{
		bool bNeedCoordinateAlignment = false;
		vr::TrackedDevicePose_t poses[vr::k_unMaxTrackedDeviceCount];

		// The "raw and uncalibrated" universe gives us coordinates in the HMD's native tracking space.
		// Adjustments like room setup and seated zero position will be applied equally to the HMD and
		// the coordinates we return, so the "raw" space is what we want our driver to match.
		vr::VRSystem()->GetDeviceToAbsoluteTrackingPose( vr::TrackingUniverseRawAndUncalibrated, 0, poses, vr::k_unMaxTrackedDeviceCount );
		for ( auto it = m_setHydraDevices.begin(); it != m_setHydraDevices.end(); ++it )
		{
			if ( poses[*it].bDeviceIsConnected )
			{
				switch ( poses[*it].eTrackingResult )
				{
				case vr::TrackingResult_Uninitialized:
					// Getting all devices to have hemisphere tracking is high priority
					return k_ePointAtBaseForHemisphereTracking;

				case vr::TrackingResult_Calibrating_InProgress:
					bNeedCoordinateAlignment = true;
					break;
				}
			}
		}

		if ( bNeedCoordinateAlignment )
			return k_eHoldAtShouldersForCoordinateAlignment;

		return k_eNone;
	}

	bool IsHydraDevice( uint32_t unTrackedDeviceIndex )
	{
		return ( m_setHydraDevices.count( unTrackedDeviceIndex ) != 0 );
	}

private:
	std::string m_strOverlayImagePath;
	vr::VROverlayHandle_t m_OverlayHandle;
	EOverlayToDisplay m_eCurrentOverlay;
	std::set<uint32_t> m_setHydraDevices;
};

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

	// Find resource path
	HMODULE hModule = GetModuleHandleA( NULL );
	char path[MAX_PATH];
	GetModuleFileNameA( hModule, path, MAX_PATH );

	char *snip = strstr( path, "\\bin\\" );
	if ( snip )
	{
		*snip = '\0';
	}

	std::string resources = std::string( path ) + "\\resources\\overlays\\";

	CHydraMonitor HydraMonitor( resources );

	HydraMonitor.Run();
}

<|endoftext|>