<commit_before>#include "taginput.h"
#include <QDebug>
#include <QKeyEvent>
#include <QTextDocument>
#include <QTextBlock>
#include <QTextDocumentFragment>
#include <QHBoxLayout>
#include <QFrame>
#include <QLabel>
#include <QPushButton>
#include <QScrollArea>
#include <QScrollBar>
#include <QComboBox>

const int defaultMargins = 6;

//---------------------------------------------------------
// TagItem
//---------------------------------------------------------

TagItem::TagItem(QObject *parent)
    : QObject(parent)
    , m_unique(true)
{
}

TagItem::TagItem(const QString &tagName, QObject *parent)
    : QObject(parent)
    , m_tagName(tagName)
    , m_unique(true)
{
}

TagItem::TagItem(const QString &tagName, const QString &tagId, QObject *parent)
    : QObject(parent)
    , m_tagName(tagName)
    , m_id(tagId)
    , m_unique(true)
{
}

TagItem *TagItem::clone()
{
    TagItem *item = new TagItem(parent());
    item->setTagName(m_tagName);
    item->setId(m_id);
    item->setDescriptionText(m_descriptionText);
    return item;
}

QString TagItem::tagName() const
{
    return m_tagName;
}

void TagItem::setTagName(const QString &tagName)
{
    m_tagName = tagName;
}

QString TagItem::id() const
{
    return !m_id.isEmpty() ? m_id : m_tagName;
}

void TagItem::setId(const QString &id)
{
    m_id = id;
}

QString TagItem::descriptionText() const
{
    return !m_descriptionText.isEmpty() ? m_descriptionText : m_tagName;
}

void TagItem::setDescriptionText(const QString &descriptionText)
{
    m_descriptionText = descriptionText;
}

bool TagItem::unique() const
{
    return m_unique;
}

void TagItem::setUnique(bool unique)
{
    m_unique = unique;
}

//---------------------------------------------------------
// TagInput
//---------------------------------------------------------

TagInput::TagInput(QWidget *parent)
    : QScrollArea(parent)
    , m_dragStartOffset(0)
{
    initWidget();

#if 0
    append("test");
    append("hoge");
    append("a");
    append("ほげふが");
    append("ふふぉjのの");
    append("っっz");
    append("test5");
    append("hoge6");
    append("test7");
    append("hoge8");
#endif
}

void TagInput::initWidget()
{
    //connect(this, &QTextEdit::textChanged, this, &TagInput::updateTags);

    QFontMetrics fm = fontMetrics();
    setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Fixed);
    QMargins margin(contentsMargins().left() ? contentsMargins().left() : defaultMargins,
                    contentsMargins().top() ? contentsMargins().top() : defaultMargins,
                    contentsMargins().right() ? contentsMargins().right() : defaultMargins,
                    contentsMargins().bottom() ? contentsMargins().bottom() : defaultMargins
                );
    setContentsMargins(0, 0, 0, 0);

    setMaximumHeight(fm.height() + margin.top() + margin.bottom() + 4 * 2);

    setBackgroundRole(QPalette::Base);
    setFrameShadow(QFrame::Plain);
    setFrameShape(QFrame::StyledPanel);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setWidgetResizable(true);

    QWidget* base = new QWidget(this);
    base->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum);
    base->setLayout(m_layout = new QHBoxLayout(base));
    setWidget(base);

    m_layout->setSpacing(defaultMargins);
    m_layout->setContentsMargins(margin.left() ? margin.left() : defaultMargins,
                                 margin.top() ? margin.top() : defaultMargins,
                                 margin.right() ? margin.right() : defaultMargins,
                                 margin.bottom() ? margin.bottom() : defaultMargins
                              );

    // list and editor
    m_tagListWidget = new QComboBox(this);
    //m_tagListWidget->setEditable(true);
    m_tagListWidget->setFrame(false);
    m_layout->addWidget(m_tagListWidget);
    connect(m_tagListWidget, QOverload<int>::of(&QComboBox::currentIndexChanged),
            this, &TagInput::onTagListSelected);

    // spacer
    QWidget* spacer = new QWidget();
    spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
    m_layout->addWidget(spacer);
}

QFrame *TagInput::createTagItem(TagItem *item)
{
    // add widget
    QFrame *tagItem = new QFrame(this);
    tagItem->setObjectName(QStringLiteral("tag:%1").arg(item->id()));
    tagItem->setStyleSheet(QStringLiteral(
            "QFrame { border-radius: 5px; padding: 2px; border: none;"
                     "background: #19BC9C; color: #FFF; }"
        ));
    tagItem->setFrameShape(QFrame::StyledPanel);
    tagItem->setFrameShadow(QFrame::Raised);

    QLabel *tagLabel = new QLabel(tagItem);
    tagLabel->setObjectName(QStringLiteral("label"));
    QFontMetrics tagLabelFm = tagLabel->fontMetrics();
    QSizePolicy sizePolicyLabel(QSizePolicy::Preferred, QSizePolicy::Fixed);
    sizePolicyLabel.setHorizontalStretch(0);
    sizePolicyLabel.setVerticalStretch(0);
    tagLabel->setMaximumHeight(tagLabelFm.height());
    tagLabel->setSizePolicy(sizePolicyLabel);
    tagLabel->setContentsMargins(0, 0, 0, 0);
    tagLabel->setText(item->tagName());
    tagLabel->setStyleSheet(QStringLiteral("QFrame { border-radius: 0; border: none; background: #FFEEEE; color: #000; padding: 0; height: 1em; line-height: 1em; }"));
    tagLabel->setStyleSheet(QStringLiteral("QFrame { border-radius: 0; border: none; padding: 0; height: 1em; line-height: 1em; }"));

    QPushButton *tagRemoveButton = new QPushButton(tagItem);
    tagRemoveButton->setObjectName(QStringLiteral("removeButton"));
    QFontMetrics tagRemoveButtonFm = tagRemoveButton->fontMetrics();
    QSizePolicy sizePolicyRemoveButton(QSizePolicy::Fixed, QSizePolicy::Fixed);
    sizePolicyRemoveButton.setHorizontalStretch(0);
    sizePolicyRemoveButton.setVerticalStretch(0);
    //sizePolicy5.setHeightForWidth(tagRemove->sizePolicy().hasHeightForWidth());
    QFont fontRemoveButton = tagRemoveButton->font();
    fontRemoveButton.setBold(true);
    fontRemoveButton.setWeight(75);
    tagRemoveButton->setFont(fontRemoveButton);
    tagRemoveButton->setText("x");
    tagRemoveButton->setSizePolicy(sizePolicyRemoveButton);
    tagRemoveButton->setMouseTracking(true);
    tagRemoveButton->setFocusPolicy(Qt::NoFocus);
    tagRemoveButton->setContentsMargins(0, 0, 0, 0);
    tagRemoveButton->setMaximumWidth(tagRemoveButtonFm.width(tagRemoveButton->text()) + 6);
    tagRemoveButton->setMaximumHeight(tagRemoveButtonFm.height());
    tagRemoveButton->setStyleSheet(QStringLiteral(
           "QPushButton { margin: 0; padding: 0; border: none; color: #FFF; }"
           "QPushButton:pressed { border: none; background: #19BC9C; color: #F66;}"
        ));
    tagRemoveButton->setAttribute(Qt::WA_TransparentForMouseEvents, false);

    QRect rc = tagRemoveButtonFm.boundingRect("x");
    //qDebug() << "tagRemoveFm.w" << tagRemoveButtonFm.width("x") << tagRemoveButtonFm.height() << rc;

    QHBoxLayout *tagItemLayout = new QHBoxLayout(tagItem);
    tagItemLayout->setObjectName(QStringLiteral("layout"));
    tagItemLayout->setSpacing(3);
    tagItemLayout->setMargin(0);
    tagItemLayout->setContentsMargins(3, 0, 3, 0);
    tagItemLayout->addWidget(tagLabel);
    tagItemLayout->addWidget(tagRemoveButton);

    connect(tagRemoveButton, &QAbstractButton::clicked, this, &TagInput::onTagRemoveClick);

    return tagItem;
}

void TagInput::append(const QString &tag, const QString &tagId)
{
    append(new TagItem(tag, tagId, this));
}

void TagInput::append(TagItem *item)
{
    // check unique tag
    foreach (TagItem* ite, m_tags) {
        if (ite->id() == item->id() &&
            (ite->unique() || item->unique())) {
            return;
        }
    }

    // add tag list
    m_tags.append(item);

    // add tag widget
    QFrame *tagItem = createTagItem(item);
    m_layout->insertWidget(m_layout->count() - 2, tagItem);
}

void TagInput::removeById(const QString &tagId)
{
    foreach (TagItem* ite, m_tags) {
        if (tagId == ite->id()) {
            m_tagList.removeOne(ite);
            break;
        }
    }
}

void TagInput::appendList(const QString &tag, const QString &tagId)
{
    appendList(new TagItem(tag, tagId, this));
}

void TagInput::appendList(TagItem *item)
{
    // check unique tag
    foreach (TagItem* ite, m_tagList) {
        if (ite->id() == item->id()) {
            return;
        }
    }

    m_tagList.append(item);

    m_tagListWidget->blockSignals(true);
    m_tagListWidget->addItem(item->tagName(), item->id());
    m_tagListWidget->setCurrentIndex(-1);
    m_tagListWidget->blockSignals(false);
}

void TagInput::removeListById(const QString &tagId)
{
    foreach (TagItem* ite, m_tagList) {
        if (tagId == ite->id()) {
            m_tagList.removeOne(ite);
            break;
        }
    }

    int index = m_tagListWidget->findData(tagId);
    if (0 <= index) {
        m_tagListWidget->removeItem(index);
    }
}

void TagInput::mousePressEvent(QMouseEvent *event)
{
    m_dragStartPos = event->pos();
    m_dragStartOffset = horizontalScrollBar()->value();
    setCursor(Qt::SizeHorCursor);
//    qDebug() << "mousePressEvent" << m_dragStartPos;
}

void TagInput::mouseMoveEvent(QMouseEvent *event)
{
    if (m_dragStartOffset < 0) {
        return;
    }

    QPoint topLeft = viewport()->rect().topLeft();

    int offset = m_dragStartOffset - (event->pos().x() - m_dragStartPos.x());
    if (offset < 0) { offset = 0; }
    if (horizontalScrollBar()->maximum() <= offset) { offset = horizontalScrollBar()->maximum(); }

    horizontalScrollBar()->setValue(offset);
    widget()->move(topLeft.x() - offset, topLeft.y());

//    qDebug() << "mouseMoveEvent" << m_dragStartPos << event->pos() << (m_dragStartPos - event->pos());
}

void TagInput::mouseReleaseEvent(QMouseEvent *event)
{
    if (m_dragStartOffset < 0) {
        return;
    }

    QPoint topLeft = viewport()->rect().topLeft();

    int offset = m_dragStartOffset - (event->pos().x() - m_dragStartPos.x());
    if (offset < 0) { offset = 0; }
    if (horizontalScrollBar()->maximum() <= offset) { offset = horizontalScrollBar()->maximum(); }

    horizontalScrollBar()->setValue(offset);
    widget()->move(topLeft.x() - offset, topLeft.y());

    unsetCursor();

    m_dragStartOffset = -1;
//    qDebug() << "mouseReleaseEvent" << m_dragStartPos << event->pos() << (m_dragStartPos - event->pos());

}

void TagInput::onTagRemoveClick(bool checked)
{
    QPushButton *button = qobject_cast<QPushButton*>( sender() );
    QLabel *label = button->parentWidget()->findChild<QLabel*>();

    if (label) {
        qDebug() << label->text();
    }
}

void TagInput::onTagClick()
{

}

void TagInput::onTagListSelected(int index)
{
    if (index < 0 ||
        m_tagList.size() <= index) {
        return;
    }

    TagItem *item = m_tagList.at(index);
    TagItem *itemClone = item->clone();

    append(itemClone);

    m_tagListWidget->setCurrentIndex(-1);
}
<commit_msg>削除処理を実装<commit_after>#include "taginput.h"
#include <QDebug>
#include <QKeyEvent>
#include <QTextDocument>
#include <QTextBlock>
#include <QTextDocumentFragment>
#include <QHBoxLayout>
#include <QFrame>
#include <QLabel>
#include <QPushButton>
#include <QScrollArea>
#include <QScrollBar>
#include <QComboBox>

const int defaultMargins = 6;

//---------------------------------------------------------
// TagItem
//---------------------------------------------------------

TagItem::TagItem(QObject *parent)
    : QObject(parent)
    , m_unique(true)
{
}

TagItem::TagItem(const QString &tagName, QObject *parent)
    : QObject(parent)
    , m_tagName(tagName)
    , m_unique(true)
{
}

TagItem::TagItem(const QString &tagName, const QString &tagId, QObject *parent)
    : QObject(parent)
    , m_tagName(tagName)
    , m_id(tagId)
    , m_unique(true)
{
}

TagItem *TagItem::clone()
{
    TagItem *item = new TagItem(parent());
    item->setTagName(m_tagName);
    item->setId(m_id);
    item->setDescriptionText(m_descriptionText);
    return item;
}

QString TagItem::tagName() const
{
    return m_tagName;
}

void TagItem::setTagName(const QString &tagName)
{
    m_tagName = tagName;
}

QString TagItem::id() const
{
    return !m_id.isEmpty() ? m_id : m_tagName;
}

void TagItem::setId(const QString &id)
{
    m_id = id;
}

QString TagItem::descriptionText() const
{
    return !m_descriptionText.isEmpty() ? m_descriptionText : m_tagName;
}

void TagItem::setDescriptionText(const QString &descriptionText)
{
    m_descriptionText = descriptionText;
}

bool TagItem::unique() const
{
    return m_unique;
}

void TagItem::setUnique(bool unique)
{
    m_unique = unique;
}

//---------------------------------------------------------
// TagInput
//---------------------------------------------------------

TagInput::TagInput(QWidget *parent)
    : QScrollArea(parent)
    , m_dragStartOffset(0)
{
    initWidget();

#if 0
    append("test");
    append("hoge");
    append("a");
    append("ほげふが");
    append("ふふぉjのの");
    append("っっz");
    append("test5");
    append("hoge6");
    append("test7");
    append("hoge8");
#endif
}

void TagInput::initWidget()
{
    //connect(this, &QTextEdit::textChanged, this, &TagInput::updateTags);

    QFontMetrics fm = fontMetrics();
    setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Fixed);
    QMargins margin(contentsMargins().left() ? contentsMargins().left() : defaultMargins,
                    contentsMargins().top() ? contentsMargins().top() : defaultMargins,
                    contentsMargins().right() ? contentsMargins().right() : defaultMargins,
                    contentsMargins().bottom() ? contentsMargins().bottom() : defaultMargins
                );
    setContentsMargins(0, 0, 0, 0);

    setMaximumHeight(fm.height() + margin.top() + margin.bottom() + 4 * 2);

    setBackgroundRole(QPalette::Base);
    setFrameShadow(QFrame::Plain);
    setFrameShape(QFrame::StyledPanel);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setWidgetResizable(true);

    QWidget* base = new QWidget(this);
    base->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum);
    base->setLayout(m_layout = new QHBoxLayout(base));
    setWidget(base);

    m_layout->setSpacing(defaultMargins);
    m_layout->setContentsMargins(margin.left() ? margin.left() : defaultMargins,
                                 margin.top() ? margin.top() : defaultMargins,
                                 margin.right() ? margin.right() : defaultMargins,
                                 margin.bottom() ? margin.bottom() : defaultMargins
                              );

    // list and editor
    m_tagListWidget = new QComboBox(this);
    //m_tagListWidget->setEditable(true);
    m_tagListWidget->setFrame(false);
    m_layout->addWidget(m_tagListWidget);
    connect(m_tagListWidget, QOverload<int>::of(&QComboBox::currentIndexChanged),
            this, &TagInput::onTagListSelected);

    // spacer
    QWidget* spacer = new QWidget();
    spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
    m_layout->addWidget(spacer);
}

QFrame *TagInput::createTagItem(TagItem *item)
{
    // add widget
    QFrame *tagItem = new QFrame(this);
    tagItem->setObjectName(QStringLiteral("tag:%1").arg(item->id()));
    tagItem->setProperty("tagItem", QVariant::fromValue(static_cast<void *>( item )));
    tagItem->setStyleSheet(QStringLiteral(
            "QFrame { border-radius: 5px; padding: 2px; border: none;"
                     "background: #19BC9C; color: #FFF; }"
        ));
    tagItem->setFrameShape(QFrame::StyledPanel);
    tagItem->setFrameShadow(QFrame::Raised);

    QLabel *tagLabel = new QLabel(tagItem);
    tagLabel->setObjectName(QStringLiteral("label"));
    QFontMetrics tagLabelFm = tagLabel->fontMetrics();
    QSizePolicy sizePolicyLabel(QSizePolicy::Preferred, QSizePolicy::Fixed);
    sizePolicyLabel.setHorizontalStretch(0);
    sizePolicyLabel.setVerticalStretch(0);
    tagLabel->setMaximumHeight(tagLabelFm.height());
    tagLabel->setSizePolicy(sizePolicyLabel);
    tagLabel->setContentsMargins(0, 0, 0, 0);
    tagLabel->setText(item->tagName());
    tagLabel->setStyleSheet(QStringLiteral("QFrame { border-radius: 0; border: none; background: #FFEEEE; color: #000; padding: 0; height: 1em; line-height: 1em; }"));
    tagLabel->setStyleSheet(QStringLiteral("QFrame { border-radius: 0; border: none; padding: 0; height: 1em; line-height: 1em; }"));

    QPushButton *tagRemoveButton = new QPushButton(tagItem);
    tagRemoveButton->setObjectName(QStringLiteral("removeButton"));
    QFontMetrics tagRemoveButtonFm = tagRemoveButton->fontMetrics();
    QSizePolicy sizePolicyRemoveButton(QSizePolicy::Fixed, QSizePolicy::Fixed);
    sizePolicyRemoveButton.setHorizontalStretch(0);
    sizePolicyRemoveButton.setVerticalStretch(0);
    //sizePolicy5.setHeightForWidth(tagRemove->sizePolicy().hasHeightForWidth());
    QFont fontRemoveButton = tagRemoveButton->font();
    fontRemoveButton.setBold(true);
    fontRemoveButton.setWeight(75);
    tagRemoveButton->setFont(fontRemoveButton);
    tagRemoveButton->setText("x");
    tagRemoveButton->setSizePolicy(sizePolicyRemoveButton);
    tagRemoveButton->setMouseTracking(true);
    tagRemoveButton->setFocusPolicy(Qt::NoFocus);
    tagRemoveButton->setContentsMargins(0, 0, 0, 0);
    tagRemoveButton->setMaximumWidth(tagRemoveButtonFm.width(tagRemoveButton->text()) + 6);
    tagRemoveButton->setMaximumHeight(tagRemoveButtonFm.height());
    tagRemoveButton->setStyleSheet(QStringLiteral(
           "QPushButton { margin: 0; padding: 0; border: none; color: #FFF; }"
           "QPushButton:pressed { border: none; background: #19BC9C; color: #F66;}"
        ));
    tagRemoveButton->setAttribute(Qt::WA_TransparentForMouseEvents, false);

    QRect rc = tagRemoveButtonFm.boundingRect("x");
    //qDebug() << "tagRemoveFm.w" << tagRemoveButtonFm.width("x") << tagRemoveButtonFm.height() << rc;

    QHBoxLayout *tagItemLayout = new QHBoxLayout(tagItem);
    tagItemLayout->setObjectName(QStringLiteral("layout"));
    tagItemLayout->setSpacing(3);
    tagItemLayout->setMargin(0);
    tagItemLayout->setContentsMargins(3, 0, 3, 0);
    tagItemLayout->addWidget(tagLabel);
    tagItemLayout->addWidget(tagRemoveButton);

    connect(tagRemoveButton, &QAbstractButton::clicked, this, &TagInput::onTagRemoveClick);

    return tagItem;
}

void TagInput::append(const QString &tag, const QString &tagId)
{
    append(new TagItem(tag, tagId, this));
}

void TagInput::append(TagItem *item)
{
    // check unique tag
    foreach (TagItem* ite, m_tags) {
        if (ite->id() == item->id() &&
            (ite->unique() || item->unique())) {
            return;
        }
    }

    // add tag list
    m_tags.append(item);

    // add tag widget
    QFrame *tagItem = createTagItem(item);
    m_layout->insertWidget(m_layout->count() - 2, tagItem);
}

void TagInput::removeById(const QString &tagId)
{
    int tabOrder = -1;

    int index = 0;
    foreach (TagItem* ite, m_tags) {
        if (tagId == ite->id()) {
            m_tags.removeOne(ite);
            tabOrder = index;
            break;
        }
        ++index;
    }

    if (tabOrder < 0) {
        return;
    }

    if (QLayoutItem *item = m_layout->itemAt(tabOrder)) {
        QWidget *w = item->widget();
        m_layout->removeItem(item);
        delete w;
    }
}

void TagInput::appendList(const QString &tag, const QString &tagId)
{
    appendList(new TagItem(tag, tagId, this));
}

void TagInput::appendList(TagItem *item)
{
    // check unique tag
    foreach (TagItem* ite, m_tagList) {
        if (ite->id() == item->id()) {
            return;
        }
    }

    m_tagList.append(item);

    m_tagListWidget->blockSignals(true);
    m_tagListWidget->addItem(item->tagName(), item->id());
    m_tagListWidget->setCurrentIndex(-1);
    m_tagListWidget->blockSignals(false);
}

void TagInput::removeListById(const QString &tagId)
{
    foreach (TagItem* ite, m_tagList) {
        if (tagId == ite->id()) {
            m_tagList.removeOne(ite);
            break;
        }
    }

    int index = m_tagListWidget->findData(tagId);
    if (0 <= index) {
        m_tagListWidget->removeItem(index);
    }
}

void TagInput::mousePressEvent(QMouseEvent *event)
{
    m_dragStartPos = event->pos();
    m_dragStartOffset = horizontalScrollBar()->value();
    setCursor(Qt::SizeHorCursor);
//    qDebug() << "mousePressEvent" << m_dragStartPos;
}

void TagInput::mouseMoveEvent(QMouseEvent *event)
{
    if (m_dragStartOffset < 0) {
        return;
    }

    QPoint topLeft = viewport()->rect().topLeft();

    int offset = m_dragStartOffset - (event->pos().x() - m_dragStartPos.x());
    if (offset < 0) { offset = 0; }
    if (horizontalScrollBar()->maximum() <= offset) { offset = horizontalScrollBar()->maximum(); }

    horizontalScrollBar()->setValue(offset);
    widget()->move(topLeft.x() - offset, topLeft.y());

//    qDebug() << "mouseMoveEvent" << m_dragStartPos << event->pos() << (m_dragStartPos - event->pos());
}

void TagInput::mouseReleaseEvent(QMouseEvent *event)
{
    if (m_dragStartOffset < 0) {
        return;
    }

    QPoint topLeft = viewport()->rect().topLeft();

    int offset = m_dragStartOffset - (event->pos().x() - m_dragStartPos.x());
    if (offset < 0) { offset = 0; }
    if (horizontalScrollBar()->maximum() <= offset) { offset = horizontalScrollBar()->maximum(); }

    horizontalScrollBar()->setValue(offset);
    widget()->move(topLeft.x() - offset, topLeft.y());

    unsetCursor();

    m_dragStartOffset = -1;
//    qDebug() << "mouseReleaseEvent" << m_dragStartPos << event->pos() << (m_dragStartPos - event->pos());

}

void TagInput::onTagRemoveClick(bool checked)
{
    if (QPushButton *button = qobject_cast<QPushButton*>( sender() )) {
        if (QLabel *label = button->parentWidget()->findChild<QLabel*>()) {
            if (QFrame *tagItem = qobject_cast<QFrame*>(label->parentWidget())) {
                if (TagItem *item = static_cast<TagItem *>( tagItem->property("tagItem").value<void *>() )) {
                    qDebug() << label->text();
                    removeById(item->id());
                }
            }
        }
    }

#if 0
    int tagOrder = -1;
    for (int index = 0; index < m_layout->count(); ++index) {
        if (QLayoutItem *item = m_layout->itemAt(index)) {
            if (QFrame *tagItem_ = qobject_cast<QFrame*>(item->widget())) {
                if (tagItem_ == tagItem) {
                    tabOrder = index;
                    break;
                }
            }
        }
    }
#endif
}

void TagInput::onTagClick()
{

}

void TagInput::onTagListSelected(int index)
{
    if (index < 0 ||
        m_tagList.size() <= index) {
        return;
    }

    TagItem *item = m_tagList.at(index);
    TagItem *itemClone = item->clone();

    append(itemClone);

    m_tagListWidget->setCurrentIndex(-1);
}
<|endoftext|>


<commit_before>// @file AesopDemo.cpp
// @brief A small test application for the Aesop library.

#include <stdio.h>
#include <stdarg.h>

#include "AesopDemo.h"
#include "AesopObjects.h"
#include "AesopPredicates.h"
#include "AesopActionSet.h"
#include "AesopWorldState.h"
#include "AesopReverseAstar.h"

namespace ae = Aesop;

void printPlan(const ae::Plan &plan, const ae::ActionSet &actions)
{
   printf("The plan:\n");
   ae::Plan::const_iterator it;
   for(it = plan.begin(); it != plan.end(); it++)
   {
      printf("   %s", actions.repr(it->action).c_str());
      if(it->parameters.size())
      {
         ae::WorldState::paramlist::const_iterator pl;
         for(pl = it->parameters.begin(); pl != it->parameters.end(); pl++)
            printf(" %d", *pl);
      }
      putchar('\n');
   }
}

void complexTest()
{
}

void STRIPSTest()
{
}

void subSTRIPSTest()
{
   // --------------------
   // STEP 1. The Domain.
/*
   // 1.1. Define the types of objects that can exist.
   ae::NamedTypes types;
   types.add("object");
   ae::Types::typeID place = types.add("place");

   // 1.2. Create predicates that describe the physics of our problem.
   ae::AesopPredicates preds;

   // A physical object can be at a place
   preds.create("at");
   preds.parameter("place");
   preds.add();

   preds.create("box-at");
   preds.parameter("place");
   preds.add();

   preds.create("high");
   ae::Predicates::predicateID high = preds.add();

   // 1.3. Define actions we can use to modify the world state.
   ae::SingleParamActionSet actions;

   actions.create("move");
   actions.parameter(place);
   actions.add();

   actions.create("move-box");
   actions.parameter(place);
   actions.add();

   actions.create("climb-box");
   preds.effect(high);
   actions.add();

   // --------------------
   // STEP 2. The Problem.

   // 2.1. Create some objects.
   ae::Objects objects(types);
   objects.add("roomA", place);
   objects.add("roomB", place);
   objects.add("roomC", place);
*/
   // 2.2. Create initial and goal world states.
}

void simpleTest()
{
   // --------------------
   // STEP 1. The Domain.

   // 1.1. Create predicates that describe the physics of our problem.
   ae::SimplePredicates preds;

   enum {
      gunLoaded,
      gunEquipped,
      haveGun,
      haveMelee,
      meleeEquipped,
      inTurret,
      haveTarget,
      targetDead,
      NUMPREDS
   };

   // Define all predicates.
   preds.define(NUMPREDS);

   // 1.2. Create actions to modify the world state.
   ae::SimpleActionSet actions(preds);

   actions.create("attackRanged");
   actions.condition(haveTarget, true);
   actions.condition(gunLoaded, true);
   actions.condition(targetDead, false);
   actions.effect(targetDead, true);
   actions.effect(gunLoaded, false);
   actions.add();

   actions.create("attackMelee");
   actions.condition(haveTarget, true);
   actions.condition(targetDead, false);
   actions.condition(meleeEquipped, true);
   //actions.condition();
   actions.effect(targetDead, true);
   actions.add();

   actions.create("attackTurret");
   actions.condition(haveTarget, true);
   actions.condition(inTurret, true);
   actions.condition(targetDead, false);
   //actions.condition();
   actions.effect(targetDead, true);
   actions.add();

   actions.create("loadGun");
   actions.condition(gunEquipped, true);
   actions.condition(gunLoaded, false);
   actions.effect(gunLoaded, true);
   actions.add();

   actions.create("drawGun");
   actions.condition(haveGun, true);
   actions.condition(gunEquipped, false);
   actions.effect(gunEquipped, true);
   actions.add();

   actions.create("findGun");
   actions.condition(haveGun, false);
   actions.effect(haveGun, true);
   actions.add();

   actions.create("drawMelee");
   actions.condition(haveMelee, true);
   actions.condition(meleeEquipped, false);
   actions.effect(meleeEquipped, true);
   actions.add();

   actions.create("findMelee");
   actions.condition(haveMelee, false);
   actions.effect(haveMelee, true);
   actions.add();

   actions.create("findTurret");
   actions.condition(inTurret, false);
   actions.effect(inTurret, true);
   //actions.add();

   // --------------------
   // STEP 2. The Problem.

   // 2.1. Create initial and goal world states.
   ae::SimpleWorldState init(preds), goal(preds);

   init.set(haveTarget);

   goal.set(targetDead);

   // --------------------
   // STEP 3. The Solution.
   ae::Plan plan;
   ae::FileWriterContext context(*stdout);
   if(ae::ReverseAstarSolve(init, goal, actions, ae::NoObjects, plan, context))
      printPlan(plan, actions);
   else
      printf("No valid plan was found.\n");
}

int main(int argc, char **argv)
{
   simpleTest();
   return 0;
}
<commit_msg>Added a 'using namespace' to demo code.<commit_after>// @file AesopDemo.cpp
// @brief A small test application for the Aesop library.

#include <stdio.h>
#include <stdarg.h>

#include "AesopDemo.h"
#include "AesopObjects.h"
#include "AesopPredicates.h"
#include "AesopActionSet.h"
#include "AesopWorldState.h"
#include "AesopReverseAstar.h"

using namespace Aesop;

void printPlan(const Plan &plan, const ActionSet &actions)
{
   printf("The plan:\n");
   Plan::const_iterator it;
   for(it = plan.begin(); it != plan.end(); it++)
   {
      printf("   %s", actions.repr(it->action).c_str());
      if(it->parameters.size())
      {
         WorldState::paramlist::const_iterator pl;
         for(pl = it->parameters.begin(); pl != it->parameters.end(); pl++)
            printf(" %d", *pl);
      }
      putchar('\n');
   }
}

void complexTest()
{
}

void STRIPSTest()
{
}

void subSTRIPSTest()
{
   // --------------------
   // STEP 1. The Domain.
/*
   // 1.1. Define the types of objects that can exist.
   NamedTypes types;
   types.add("object");
   Types::typeID place = types.add("place");

   // 1.2. Create predicates that describe the physics of our problem.
   AesopPredicates preds;

   // A physical object can be at a place
   preds.create("at");
   preds.parameter("place");
   preds.add();

   preds.create("box-at");
   preds.parameter("place");
   preds.add();

   preds.create("high");
   Predicates::predicateID high = preds.add();

   // 1.3. Define actions we can use to modify the world state.
   SingleParamActionSet actions;

   actions.create("move");
   actions.parameter(place);
   actions.add();

   actions.create("move-box");
   actions.parameter(place);
   actions.add();

   actions.create("climb-box");
   preds.effect(high);
   actions.add();

   // --------------------
   // STEP 2. The Problem.

   // 2.1. Create some objects.
   Objects objects(types);
   objects.add("roomA", place);
   objects.add("roomB", place);
   objects.add("roomC", place);
*/
   // 2.2. Create initial and goal world states.
}

void simpleTest()
{
   // --------------------
   // STEP 1. The Domain.

   // 1.1. Create predicates that describe the physics of our problem.
   SimplePredicates preds;

   enum {
      gunLoaded,
      gunEquipped,
      haveGun,
      haveMelee,
      meleeEquipped,
      inTurret,
      haveTarget,
      targetDead,
      NUMPREDS
   };

   // Define all predicates.
   preds.define(NUMPREDS);

   // 1.2. Create actions to modify the world state.
   SimpleActionSet actions(preds);

   actions.create("attackRanged");
   actions.condition(haveTarget, true);
   actions.condition(gunLoaded, true);
   actions.condition(targetDead, false);
   actions.effect(targetDead, true);
   actions.effect(gunLoaded, false);
   actions.add();

   actions.create("attackMelee");
   actions.condition(haveTarget, true);
   actions.condition(targetDead, false);
   actions.condition(meleeEquipped, true);
   //actions.condition();
   actions.effect(targetDead, true);
   actions.add();

   actions.create("attackTurret");
   actions.condition(haveTarget, true);
   actions.condition(inTurret, true);
   actions.condition(targetDead, false);
   //actions.condition();
   actions.effect(targetDead, true);
   actions.add();

   actions.create("loadGun");
   actions.condition(gunEquipped, true);
   actions.condition(gunLoaded, false);
   actions.effect(gunLoaded, true);
   actions.add();

   actions.create("drawGun");
   actions.condition(haveGun, true);
   actions.condition(gunEquipped, false);
   actions.effect(gunEquipped, true);
   actions.add();

   actions.create("findGun");
   actions.condition(haveGun, false);
   actions.effect(haveGun, true);
   actions.add();

   actions.create("drawMelee");
   actions.condition(haveMelee, true);
   actions.condition(meleeEquipped, false);
   actions.effect(meleeEquipped, true);
   actions.add();

   actions.create("findMelee");
   actions.condition(haveMelee, false);
   actions.effect(haveMelee, true);
   actions.add();

   actions.create("findTurret");
   actions.condition(inTurret, false);
   actions.effect(inTurret, true);
   //actions.add();

   // --------------------
   // STEP 2. The Problem.

   // 2.1. Create initial and goal world states.
   SimpleWorldState init(preds), goal(preds);

   init.set(haveTarget);

   goal.set(targetDead);

   // --------------------
   // STEP 3. The Solution.
   Plan plan;
   FileWriterContext context(*stdout);
   if(ReverseAstarSolve(init, goal, actions, NoObjects, plan, context))
      printPlan(plan, actions);
   else
      printf("No valid plan was found.\n");
}

int main(int argc, char **argv)
{
   simpleTest();
   return 0;
}
<|endoftext|>


<commit_before>/*
 * Bayes++ the Bayesian Filtering Library
 * Copyright (c) 2004 Michael Stevens
 * See accompanying Bayes++.html for terms and conditions of use.
 *
 * $Header$
 */

/*
 * Good random numbers from Boost
 *  Provides a common class  for all random number requirements to test Bayes++
 */

#include <boost/random.hpp>

namespace Bayesian_filter_test
{

/*
 * Random numbers from Boost Random
 */

namespace
{
	// ISSUE variate_generator cannot be used without Partial template specialistion
	template<class Engine, class Distribution>
	class simple_generator
	{
	public:
		typedef typename Distribution::result_type result_type;
		simple_generator(Engine& e, Distribution& d)
			: _eng(e), _dist(d)
		{}
		result_type operator()()
		{	return _dist(_eng); }
	private:
		Engine& _eng;
		Distribution& _dist;
	};
}//namespace

class Boost_random
{
public:
	// ISSUE mt19937 is failing on x86_64
	//	typedef boost::mt19937 Boost_gen;
	typedef boost::ranlux3 Boost_gen;

	typedef Bayesian_filter_matrix::Float Float;
	typedef boost::uniform_01<Boost_gen, Float> UGen;
	Boost_random() : gen01(Boost_gen()), dist_normal()
	{}
	Bayesian_filter_matrix::Float normal(const Float mean, const Float sigma)
	{
		boost::normal_distribution<Float> dist(mean, sigma);
		simple_generator<UGen, boost::normal_distribution<Float> > gen(gen01, dist);
		return gen();
	}
	void normal(Bayesian_filter_matrix::DenseVec& v, const Float mean, const Float sigma)
	{
		boost::normal_distribution<Float> dist(mean, sigma);
		simple_generator<UGen, boost::normal_distribution<Float> > gen(gen01, dist);
		std::generate (v.begin(), v.end(), gen);
	}
	void normal(Bayesian_filter_matrix::DenseVec& v)
	{
		simple_generator<UGen, boost::normal_distribution<Float> > gen(gen01, dist_normal);
		std::generate (v.begin(), v.end(), gen);
	}
	void uniform_01(Bayesian_filter_matrix::DenseVec& v)
	{
		std::generate (v.begin(), v.end(), gen01);
	}
#ifdef BAYES_FILTER_GAPPY
	void normal(Bayesian_filter_matrix::Vec& v, const Float mean, const Float sigma)
	{
		boost::normal_distribution<Float> dist(mean, sigma);
		simple_generator<UGen, boost::normal_distribution<Float> > gen(gen01, dist);
		for (std::size_t i = 0, iend=v.size(); i < iend; ++i)
			v[i] = gen();
	}
	void normal(Bayesian_filter_matrix::Vec& v)
	{
		simple_generator<UGen, boost::normal_distribution<Float> > gen(gen01, dist_normal);
		for (std::size_t i = 0, iend=v.size(); i < iend; ++i)
			v[i] = gen();
	}
	void uniform_01(Bayesian_filter_matrix::Vec& v)
	{
		for (std::size_t i = 0, iend=v.size(); i < iend; ++i)
			v[i] = gen01();
	}
#endif
	void seed()
	{
		gen01.base().seed();
	}
private:
	UGen gen01;
	boost::normal_distribution<Float> dist_normal;
};

}//namespace
<commit_msg>mt19937 problem is GCC 3.3.3 specfic (may SuSE specific)<commit_after>/*
 * Bayes++ the Bayesian Filtering Library
 * Copyright (c) 2004 Michael Stevens
 * See accompanying Bayes++.html for terms and conditions of use.
 *
 * $Header$
 */

/*
 * Good random numbers from Boost
 *  Provides a common class  for all random number requirements to test Bayes++
 */

#include <boost/random.hpp>

namespace Bayesian_filter_test
{

/*
 * Random numbers from Boost Random
 */

namespace
{
	// ISSUE variate_generator cannot be used without Partial template specialistion
	template<class Engine, class Distribution>
	class simple_generator
	{
	public:
		typedef typename Distribution::result_type result_type;
		simple_generator(Engine& e, Distribution& d)
			: _eng(e), _dist(d)
		{}
		result_type operator()()
		{	return _dist(_eng); }
	private:
		Engine& _eng;
		Distribution& _dist;
	};
}//namespace

class Boost_random
{
public:
	// ISSUE mt19937 results incorrect on x86_64 GCC version 3.3.3 (SuSE Linux)
	typedef boost::mt19937 Boost_gen;

	typedef Bayesian_filter_matrix::Float Float;
	typedef boost::uniform_01<Boost_gen, Float> UGen;
	Boost_random() : gen01(Boost_gen()), dist_normal()
	{}
	Bayesian_filter_matrix::Float normal(const Float mean, const Float sigma)
	{
		boost::normal_distribution<Float> dist(mean, sigma);
		simple_generator<UGen, boost::normal_distribution<Float> > gen(gen01, dist);
		return gen();
	}
	void normal(Bayesian_filter_matrix::DenseVec& v, const Float mean, const Float sigma)
	{
		boost::normal_distribution<Float> dist(mean, sigma);
		simple_generator<UGen, boost::normal_distribution<Float> > gen(gen01, dist);
		std::generate (v.begin(), v.end(), gen);
	}
	void normal(Bayesian_filter_matrix::DenseVec& v)
	{
		simple_generator<UGen, boost::normal_distribution<Float> > gen(gen01, dist_normal);
		std::generate (v.begin(), v.end(), gen);
	}
	void uniform_01(Bayesian_filter_matrix::DenseVec& v)
	{
		std::generate (v.begin(), v.end(), gen01);
	}
#ifdef BAYES_FILTER_GAPPY
	void normal(Bayesian_filter_matrix::Vec& v, const Float mean, const Float sigma)
	{
		boost::normal_distribution<Float> dist(mean, sigma);
		simple_generator<UGen, boost::normal_distribution<Float> > gen(gen01, dist);
		for (std::size_t i = 0, iend=v.size(); i < iend; ++i)
			v[i] = gen();
	}
	void normal(Bayesian_filter_matrix::Vec& v)
	{
		simple_generator<UGen, boost::normal_distribution<Float> > gen(gen01, dist_normal);
		for (std::size_t i = 0, iend=v.size(); i < iend; ++i)
			v[i] = gen();
	}
	void uniform_01(Bayesian_filter_matrix::Vec& v)
	{
		for (std::size_t i = 0, iend=v.size(); i < iend; ++i)
			v[i] = gen01();
	}
#endif
	void seed()
	{
		gen01.base().seed();
	}
private:
	UGen gen01;
	boost::normal_distribution<Float> dist_normal;
};

}//namespace
<|endoftext|>


<commit_before>#include "NumbersGame.h"
#include "SimpleAudioEngine.h"

USING_NS_CC;
NumbersGame::NumbersGame() : _fishPool(20)
{
}
Scene* NumbersGame::createScene()
{
    auto scene = Scene::create();
    auto layer = NumbersGame::create();
    scene->addChild(layer);
    return scene;
}

// on "init" you need to initialize your instance
bool NumbersGame::init()
{
    if ( !Layer::init() )
    {
        return false;
    }

    _screenSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    _score = 0;
    _hook_has_fish = false;
    //create game screen elements
    createGameScreen();
    //create object pools
    createPools();
    //create CCActions
    createActions();

    auto listener = EventListenerTouchOneByOne::create();
    listener->onTouchBegan = CC_CALLBACK_2(NumbersGame::onTouchBegan, this);
    listener->onTouchEnded = CC_CALLBACK_2(NumbersGame::onTouchEnded, this);
    this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);

    this->schedule(schedule_selector(NumbersGame::update));
    return true;
}

void NumbersGame::createGameScreen () {
    Sprite * bg = Sprite::create("bg.png");
    bg->setPosition(Vec2(_screenSize.width * 0.5f, _screenSize.height * 0.5f));
    this->addChild(bg, kBackground);

    SpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("sprites.plist");
    _gameBatchNode = SpriteBatchNode::create("sprites.png", 100);

    this->addChild(_gameBatchNode, kForeground);

    _hook = Sprite::create("hook.png");
    _hook->setScale(0.1);
    _hook->setPosition(Vec2(_screenSize.width * 0.5f, _hook->getBoundingBox().size.height * 0.5));
    this->addChild(_hook, kMiddleground);

    _scoreDisplay = LabelTTF::create();
    _scoreDisplay->setFontName("fonts/font.ttf");
    _scoreDisplay->setAnchorPoint(Vec2(1,0.5));
    _scoreDisplay->setFontSize(20);
    _scoreDisplay->setPosition(Vec2(_screenSize.width * 0.9f, _screenSize.height * 0.94f));
    _scoreDisplay->setString("0");
    this->addChild(_scoreDisplay,kForeground);

    _scoreDisplayLarge = LabelTTF::create();
    _scoreDisplayLarge->setFontSize(300);
    _scoreDisplayLarge->setFontName("fonts/font.ttf");
    _scoreDisplayLarge->setPosition(Vec2(_screenSize.width * 0.5f, _screenSize.height * 0.5f));
    _scoreDisplayLarge->setScale(0.2);
    _scoreDisplayLarge->setString("0");
    _scoreDisplayLarge->setVisible(false);
    this->addChild(_scoreDisplayLarge,kForeground);

    ParticleSystemQuad* p = ParticleSystemQuad::create("bubbles.plist");
    p->setScale(0.);
    this->addChild(p,kForeground);
}
void NumbersGame::createPools () {
    Sprite * sprite;
    int i,output;

    _fishPoolIndex = 0;
    for (i = 0; i < _fishPool.capacity(); i++) {
        output = 1 + (rand() % (int)(6 - 2));
        auto name = CCString::createWithFormat("fish_%i.png", output);
        sprite = Sprite::createWithSpriteFrameName(name->_string);
        sprite->setVisible(false);
        sprite->setScale(0.2);
        _gameBatchNode->addChild(sprite, kMiddleground);
        _fishPool.pushBack(sprite);
    }
}
void NumbersGame::createActions () {

}
void NumbersGame::update (float dt) {
    if (!_running) return;

    _fishTimer += dt;
    if (_fishTimer > _fishInterval) {
        _fishTimer = 0;
        this->resetFish();
    }

    if(_hook_has_fish) return;

    if (_hook_pull){
        _hook->setPosition(_hook->getPositionX(),_hook->getPositionY() + 5);
        if(_hook->getPositionY() > _screenSize.height - _hook->getBoundingBox().size.height /2)
            _hook->setPositionY( _screenSize.height - _hook->getBoundingBox().size.height /2);

        for (auto fish: this->_fishPool)
        {
            if(fish->getBoundingBox().intersectsRect(_hook->getBoundingBox()))
            {
                fish->stopAllActions();
                _hook_has_fish = true;
                _hook_pull = false;

                auto fishing = MoveTo::create(
                    ( (_screenSize.height - _hook->getPositionY()) * 0.002)
                    , Vec2(_hook->getPositionX(),_screenSize.height));
                auto rotate = RotateTo::create(0.2,90);
                fish->runAction(
                 CCSequence::create(
                    fishing->clone(),
                    CCCallFuncN::create(this, callfuncN_selector(NumbersGame::fishingDone)),
                    NULL)
                );
                fish->runAction(rotate);
                _hook->runAction(fishing);
                _hook->setVisible(false);
            }
        }
    }else{
        _hook->setPosition(_hook->getPositionX(),_hook->getPositionY() - 3);
        if(_hook->getPositionY() < _hook->getBoundingBox().size.height /2)
            _hook->setPositionY( _hook->getBoundingBox().size.height /2);
    }
}
bool NumbersGame::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event * event){
    if (!_running) _running = true;
    _hook_pull = true;
    return true;
}
void NumbersGame::onTouchEnded(cocos2d::Touch *touch, cocos2d::Event * event){
    _hook_pull = false;
}

void NumbersGame::resetFish(){
    Sprite * fish = (Sprite *) _fishPool.at(_fishPoolIndex);
    _fishPoolIndex++;
    if (_fishPoolIndex == _fishPool.size())   _fishPoolIndex = 0;

    int meteor_y = rand() % (int) (_screenSize.height * 0.8f) + _screenSize.height * 0.1f;

    fish->stopAllActions();

    fish->setPosition(Vec2(_screenSize.width + fish->getBoundingBox().size.width * 0.5,meteor_y));
    auto swim = MoveTo::create(_fishSpeed, Vec2(0-fish->getBoundingBox().size.width * 0.5,meteor_y));

    fish->setVisible ( true );
    fish->runAction(swim);
}

void NumbersGame::fishingDone (Node* pSender) {
    pSender->setVisible(false);
    pSender->setRotation(0);
    pSender->setPosition(0,0);
    _score++;
    auto name = CCString::createWithFormat("%i", _score);
    _scoreDisplay->setString(name->_string);
    _scoreDisplayLarge->setString(name->_string);
    _scoreDisplayLarge->setVisible(true);

    char numstr[21]; // enough to hold all numbers up to 64-bits
    std::sprintf(numstr, "%i", _score);
    std::string result__ = numstr + std::string("_.wav");
    const char * audio_file = result__.c_str();
    if(_score < 11)
        CocosDenshion::SimpleAudioEngine::getInstance()->playEffect(audio_file);

    _scoreDisplayLarge->runAction(CCSequence::create(
        EaseBackOut::create(ScaleTo::create(4,1)),
        CCCallFuncN::create(this, callfuncN_selector(NumbersGame::bigScoreDone)),
        NULL)
    );
}
void NumbersGame::bigScoreDone (Node* pSender) {
    pSender->setScale(0.2);
    pSender->setVisible(false);
    _hook_has_fish = false;
    _hook->setVisible(true);
}<commit_msg>position particles<commit_after>#include "NumbersGame.h"
#include "SimpleAudioEngine.h"

USING_NS_CC;
NumbersGame::NumbersGame() : _fishPool(20)
{
}
Scene* NumbersGame::createScene()
{
    auto scene = Scene::create();
    auto layer = NumbersGame::create();
    scene->addChild(layer);
    return scene;
}

// on "init" you need to initialize your instance
bool NumbersGame::init()
{
    if ( !Layer::init() )
    {
        return false;
    }

    _screenSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    _score = 0;
    _hook_has_fish = false;
    //create game screen elements
    createGameScreen();
    //create object pools
    createPools();
    //create CCActions
    createActions();

    auto listener = EventListenerTouchOneByOne::create();
    listener->onTouchBegan = CC_CALLBACK_2(NumbersGame::onTouchBegan, this);
    listener->onTouchEnded = CC_CALLBACK_2(NumbersGame::onTouchEnded, this);
    this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);

    this->schedule(schedule_selector(NumbersGame::update));
    return true;
}

void NumbersGame::createGameScreen () {
    Sprite * bg = Sprite::create("bg.png");
    bg->setPosition(Vec2(_screenSize.width * 0.5f, _screenSize.height * 0.5f));
    this->addChild(bg, kBackground);

    SpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("sprites.plist");
    _gameBatchNode = SpriteBatchNode::create("sprites.png", 100);

    this->addChild(_gameBatchNode, kForeground);

    _hook = Sprite::create("hook.png");
    _hook->setScale(0.1);
    _hook->setPosition(Vec2(_screenSize.width * 0.5f, _hook->getBoundingBox().size.height * 0.5));
    this->addChild(_hook, kMiddleground);

    _scoreDisplay = LabelTTF::create();
    _scoreDisplay->setFontName("fonts/font.ttf");
    _scoreDisplay->setAnchorPoint(Vec2(1,0.5));
    _scoreDisplay->setFontSize(20);
    _scoreDisplay->setPosition(Vec2(_screenSize.width * 0.9f, _screenSize.height * 0.94f));
    _scoreDisplay->setString("0");
    this->addChild(_scoreDisplay,kForeground);

    _scoreDisplayLarge = LabelTTF::create();
    _scoreDisplayLarge->setFontSize(300);
    _scoreDisplayLarge->setFontName("fonts/font.ttf");
    _scoreDisplayLarge->setPosition(Vec2(_screenSize.width * 0.5f, _screenSize.height * 0.5f));
    _scoreDisplayLarge->setScale(0.2);
    _scoreDisplayLarge->setString("0");
    _scoreDisplayLarge->setVisible(false);
    this->addChild(_scoreDisplayLarge,kForeground);

    ParticleSystemQuad* p1 = ParticleSystemQuad::create("bubbles.plist");
    p1->setPosition(Vec2(_screenSize.width * 0.86f, _screenSize.height * 0.1f));
    p1->setScale(0.1);
    p1->setLife(0.6);
    this->addChild(p1,kForeground);

    ParticleSystemQuad* p2 = ParticleSystemQuad::create("bubbles.plist");
    p2->setPosition(Vec2(_screenSize.width * 0.9f, _screenSize.height * 0.125f));
    p2->setScale(0.1);
    p2->setLife(0.6);
    this->addChild(p2,kMiddleground);
}
void NumbersGame::createPools () {
    Sprite * sprite;
    int i,output;

    _fishPoolIndex = 0;
    for (i = 0; i < _fishPool.capacity(); i++) {
        output = 1 + (rand() % (int)(6 - 2));
        auto name = CCString::createWithFormat("fish_%i.png", output);
        sprite = Sprite::createWithSpriteFrameName(name->_string);
        sprite->setVisible(false);
        sprite->setScale(0.2);
        _gameBatchNode->addChild(sprite, kMiddleground);
        _fishPool.pushBack(sprite);
    }
}
void NumbersGame::createActions () {

}
void NumbersGame::update (float dt) {
    if (!_running) return;

    _fishTimer += dt;
    if (_fishTimer > _fishInterval) {
        _fishTimer = 0;
        this->resetFish();
    }

    if(_hook_has_fish) return;

    if (_hook_pull){
        _hook->setPosition(_hook->getPositionX(),_hook->getPositionY() + 5);
        if(_hook->getPositionY() > _screenSize.height - _hook->getBoundingBox().size.height /2)
            _hook->setPositionY( _screenSize.height - _hook->getBoundingBox().size.height /2);

        for (auto fish: this->_fishPool)
        {
            if(fish->getBoundingBox().intersectsRect(_hook->getBoundingBox()))
            {
                fish->stopAllActions();
                _hook_has_fish = true;
                _hook_pull = false;

                auto fishing = MoveTo::create(
                    ( (_screenSize.height - _hook->getPositionY()) * 0.002)
                    , Vec2(_hook->getPositionX(),_screenSize.height));
                auto rotate = RotateTo::create(0.2,90);
                fish->runAction(
                 CCSequence::create(
                    fishing->clone(),
                    CCCallFuncN::create(this, callfuncN_selector(NumbersGame::fishingDone)),
                    NULL)
                );
                fish->runAction(rotate);
                _hook->runAction(fishing);
                _hook->setVisible(false);
            }
        }
    }else{
        _hook->setPosition(_hook->getPositionX(),_hook->getPositionY() - 3);
        if(_hook->getPositionY() < _hook->getBoundingBox().size.height /2)
            _hook->setPositionY( _hook->getBoundingBox().size.height /2);
    }
}
bool NumbersGame::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event * event){
    if (!_running) _running = true;
    _hook_pull = true;
    return true;
}
void NumbersGame::onTouchEnded(cocos2d::Touch *touch, cocos2d::Event * event){
    _hook_pull = false;
}

void NumbersGame::resetFish(){
    Sprite * fish = (Sprite *) _fishPool.at(_fishPoolIndex);
    _fishPoolIndex++;
    if (_fishPoolIndex == _fishPool.size())   _fishPoolIndex = 0;

    int meteor_y = rand() % (int) (_screenSize.height * 0.8f) + _screenSize.height * 0.1f;

    fish->stopAllActions();

    fish->setPosition(Vec2(_screenSize.width + fish->getBoundingBox().size.width * 0.5,meteor_y));
    auto swim = MoveTo::create(_fishSpeed, Vec2(0-fish->getBoundingBox().size.width * 0.5,meteor_y));

    fish->setVisible ( true );
    fish->runAction(swim);
}

void NumbersGame::fishingDone (Node* pSender) {
    pSender->setVisible(false);
    pSender->setRotation(0);
    pSender->setPosition(0,0);
    _score++;
    auto name = CCString::createWithFormat("%i", _score);
    _scoreDisplay->setString(name->_string);
    _scoreDisplayLarge->setString(name->_string);
    _scoreDisplayLarge->setVisible(true);

    char numstr[21]; // enough to hold all numbers up to 64-bits
    std::sprintf(numstr, "%i", _score);
    std::string result__ = numstr + std::string("_.wav");
    const char * audio_file = result__.c_str();
    if(_score < 11)
        CocosDenshion::SimpleAudioEngine::getInstance()->playEffect(audio_file);

    _scoreDisplayLarge->runAction(CCSequence::create(
        EaseBackOut::create(ScaleTo::create(4,1)),
        CCCallFuncN::create(this, callfuncN_selector(NumbersGame::bigScoreDone)),
        NULL)
    );
}
void NumbersGame::bigScoreDone (Node* pSender) {
    pSender->setScale(0.2);
    pSender->setVisible(false);
    _hook_has_fish = false;
    _hook->setVisible(true);
}<|endoftext|>


<commit_before>
/*
  Copyright 1995 The University of Rhode Island and The Massachusetts
  Institute of Technology

  Portions of this software were developed by the Graduate School of
  Oceanography (GSO) at the University of Rhode Island (URI) in collaboration
  with The Massachusetts Institute of Technology (MIT).

  Access and use of this software shall impose the following obligations and
  understandings on the user. The user is granted the right, without any fee
  or cost, to use, copy, modify, alter, enhance and distribute this software,
  and any derivative works thereof, and its supporting documentation for any
  purpose whatsoever, provided that this entire notice appears in all copies
  of the software, derivative works and supporting documentation.  Further,
  the user agrees to credit URI/MIT in any publications that result from the
  use of this software or in any product that includes this software. The
  names URI, MIT and/or GSO, however, may not be used in any advertising or
  publicity to endorse or promote any products or commercial entity unless
  specific written permission is obtained from URI/MIT. The user also
  understands that URI/MIT is not obligated to provide the user with any
  support, consulting, training or assistance of any kind with regard to the
  use, operation and performance of this software nor to provide the user
  with any updates, revisions, new versions or "bug fixes".

  THIS SOFTWARE IS PROVIDED BY URI/MIT "AS IS" AND ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
  EVENT SHALL URI/MIT BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS
  ACTION, ARISING OUT OF OR IN CONNECTION WITH THE ACCESS, USE OR PERFORMANCE
  OF THIS SOFTWARE.
*/

// Implementation for the class Structure
//
// jhrg 9/14/94

// $Log: Structure.cc,v $
// Revision 1.19  1996/02/02 00:31:13  jimg
// Merge changes for DODS-1.1.0 into DODS-2.x
//
// Revision 1.18  1995/12/09  01:07:00  jimg
// Added changes so that relational operators will work properly for all the
// datatypes (including Sequences). The relational ops are evaluated in
// DDS::eval_constraint() after being parsed by DDS::parse_constraint().
//
// Revision 1.17  1995/12/06  21:56:32  jimg
// Added `constrained' flag to print_decl.
// Removed third parameter of read.
// Modified print_decl() to print only those parts of a dataset that are
// selected when `constrained' is true.
//
// Revision 1.16  1995/10/23  23:21:04  jimg
// Added _send_p and _read_p fields (and their accessors) along with the
// virtual mfuncs set_send_p() and set_read_p().
//
// Revision 1.15  1995/08/26  00:31:49  jimg
// Removed code enclosed in #ifdef NEVER #endif.
//
// Revision 1.14  1995/08/23  00:11:08  jimg
// Changed old, deprecated member functions to new ones.
// Switched from String representation of type to enum.
//
// Revision 1.13.2.1  1995/09/14 20:58:13  jimg
// Moved some loop index variables out of the loop statement.
//
// Revision 1.13  1995/07/09  21:29:06  jimg
// Added copyright notice.
//
// Revision 1.12  1995/05/10  15:34:06  jimg
// Failed to change `config.h' to `config_dap.h' in these files.
//
// Revision 1.11  1995/05/10  13:45:31  jimg
// Changed the name of the configuration header file from `config.h' to
// `config_dap.h' so that other libraries could have header files which were
// installed in the DODS include directory without overwriting this one. Each
// config header should follow the convention config_<name>.h.
//
// Revision 1.10  1995/03/16  17:29:12  jimg
// Added include config_dap.h to top of include list.
// Added TRACE_NEW switched dbnew includes.
// Fixed bug in read_val() where **val was passed incorrectly to
// subordinate read_val() calls.
//
// Revision 1.9  1995/03/04  14:34:51  jimg
// Major modifications to the transmission and representation of values:
// Added card() virtual function which is true for classes that
// contain cardinal types (byte, int float, string).
// Changed the representation of Str from the C rep to a C++
// class represenation.
// Chnaged read_val and store_val so that they take and return
// types that are stored by the object (e.g., inthe case of Str
// an URL, read_val returns a C++ String object).
// Modified Array representations so that arrays of card()
// objects are just that - no more storing strings, ... as
// C would store them.
// Arrays of non cardinal types are arrays of the DODS objects (e.g.,
// an array of a structure is represented as an array of Structure
// objects).
//
// Revision 1.8  1995/02/10  02:22:59  jimg
// Added DBMALLOC includes and switch to code which uses malloc/free.
// Private and protected symbols now start with `_'.
// Added new accessors for name and type fields of BaseType; the old ones
// will be removed in a future release.
// Added the store_val() mfunc. It stores the given value in the object's
// internal buffer.
// Made both List and Str handle their values via pointers to memory.
// Fixed read_val().
// Made serialize/deserialize handle all malloc/free calls (even in those
// cases where xdr initiates the allocation).
// Fixed print_val().
//
// Revision 1.7  1995/01/19  20:05:24  jimg
// ptr_duplicate() mfunc is now abstract virtual.
// Array, ... Grid duplicate mfuncs were modified to take pointers, not
// referenves.
//
// Revision 1.6  1995/01/11  15:54:49  jimg
// Added modifications necessary for BaseType's static XDR pointers. This
// was mostly a name change from xdrin/out to _xdrin/out.
// Removed the two FILE pointers from ctors, since those are now set with
// functions which are friends of BaseType.
//
// Revision 1.5  1994/12/16  15:16:39  dan
// Modified Structure class removing inheritance from class CtorType
// and directly inheriting from class BaseType to alloc calling
// BaseType's constructor directly.
//
// Revision 1.4  1994/11/22  14:06:10  jimg
// Added code for data transmission to parts of the type hierarchy. Not
// complete yet.
// Fixed erros in type hierarchy headers (typos, incorrect comments, ...).
//
// Revision 1.3  1994/10/17  23:34:47  jimg
// Added code to print_decl so that variable declarations are pretty
// printed.
// Added private mfunc duplicate().
// Added ptr_duplicate().
// Added Copy ctor, dtor and operator=.
//
// Revision 1.2  1994/09/23  14:45:26  jimg
// Added mfunc check_semantics().
// Added sanity checking on the variable list (is it empty?).
//

#ifdef _GNUG_
#pragma implementation
#endif

#include "config_dap.h"

#include <string.h>
#include <stdlib.h>
#include <assert.h>

#include "Structure.h"
#include "DDS.h"
#include "util.h"

#ifdef TRACE_NEW
#include "trace_new.h"
#endif

void
Structure::_duplicate(const Structure &s)
{
#ifdef NEVER
    set_name(s.name());
    set_type(s.type());

    Structure &cs = (Structure &)s; // cast away const
#endif

    BaseType::_duplicate(s);

    Structure &cs = (Structure &)s; // cast away const

    for (Pix p = cs._vars.first(); p; cs._vars.next(p))
	_vars.append(cs._vars(p)->ptr_duplicate());
}

Structure::Structure(const String &n) : BaseType(n, structure_t)
{
}

Structure::Structure(const Structure &rhs)
{
    _duplicate(rhs);
}

Structure::~Structure()
{
    for (Pix p = _vars.first(); p; _vars.next(p))
	delete _vars(p);
}

const Structure &
Structure::operator=(const Structure &rhs)
{
    if (this == &rhs)
	return *this;

    _duplicate(rhs);

    return *this;
}

void
Structure::set_send_p(bool state)
{
    for (Pix p = _vars.first(); p; _vars.next(p))
	_vars(p)->set_send_p(state);

    BaseType::set_send_p(state);
}

void
Structure::set_read_p(bool state)
{
    for (Pix p = _vars.first(); p; _vars.next(p))
	_vars(p)->set_read_p(state);

    BaseType::set_read_p(state);
}

// NB: Part p defaults to nil for this class

void
Structure::add_var(BaseType *bt, Part p)
{
    _vars.append(bt);
}

unsigned int
Structure::width()
{
    return sizeof(Structure);
}

bool
Structure::serialize(const String &dataset, DDS &dds, bool flush)
{
    bool status = true;

    if (!read_p())		// only read if not read already
	status = read(dataset);

    if (status && !dds.eval_constraint()) // if the constraint is false, return
	return status;

    if (!status)
	return false;

    for (Pix p = first_var(); p; next_var(p))
	if (var(p)->send_p()
	    && !(status = var(p)->serialize(dataset, dds, false)))
	    break;

    if (status && flush)
	status = expunge();

    return status;
}

bool
Structure::deserialize(bool reuse)
{
  bool status;

    for (Pix p = first_var(); p; next_var(p)) {
	status = var(p)->deserialize(reuse);
	if (!status)
	  break;
    }

    return status;
}

// This mfunc assumes that val contains values for all the elements of the
// strucuture in the order those elements are declared.

unsigned int
Structure::val2buf(void *val, bool reuse)
{
    return sizeof(Structure);
}

unsigned int
Structure::buf2val(void **val)
{
    return sizeof(Structure);
}

BaseType *
Structure::var(const String &name)
{
    for (Pix p = _vars.first(); p; _vars.next(p))
	if (_vars(p)->name() == name)
	    return _vars(p);

    return 0;
}

Pix
Structure::first_var()
{
    return _vars.first();
}

void
Structure::next_var(Pix &p)
{
    if (!_vars.empty() && p)
	_vars.next(p);
}

BaseType *
Structure::var(Pix p)
{
    if (!_vars.empty() && p)
	return _vars(p);
    else
      return NULL;
}

void
Structure::print_decl(ostream &os, String space, bool print_semi,
		      bool constraint_info, bool constrained)
{
    if (constrained && !send_p())
	return;

    os << space << type_name() << " {" << endl;
    for (Pix p = _vars.first(); p; _vars.next(p))
	_vars(p)->print_decl(os, space + "    ", true, constraint_info,
			     constrained);
    os << space << "} " << name();

    if (constraint_info) {
	if (send_p())
	    cout << ": Send True";
	else
	    cout << ": Send False";
    }

    if (print_semi)
	os << ";" << endl;
}

// print the values of the contained variables

void
Structure::print_val(ostream &os, String space, bool print_decl_p)
{
    if (print_decl_p) {
	print_decl(os, space, false);
	os << " = ";
    }

    os << "{ ";
    for (Pix p = _vars.first(); p; _vars.next(p), p && os << ", ") {
	_vars(p)->print_val(os, "", false);
    }
    os << " }";

    if (print_decl_p)
	os << ";" << endl;
}

bool
Structure::check_semantics(bool all)
{
    if (!BaseType::check_semantics())
	return false;

    if (!unique(_vars, (const char *)name(), (const char *)type_name()))
	return false;

    if (all)
	for (Pix p = _vars.first(); p; _vars.next(p))
	    if (!_vars(p)->check_semantics(true))
		return false;

    return true;
}

<commit_msg>Added ce_eval to serailize member function. Added debugging information to _duplicate member function.<commit_after>
/*
  Copyright 1995 The University of Rhode Island and The Massachusetts
  Institute of Technology

  Portions of this software were developed by the Graduate School of
  Oceanography (GSO) at the University of Rhode Island (URI) in collaboration
  with The Massachusetts Institute of Technology (MIT).

  Access and use of this software shall impose the following obligations and
  understandings on the user. The user is granted the right, without any fee
  or cost, to use, copy, modify, alter, enhance and distribute this software,
  and any derivative works thereof, and its supporting documentation for any
  purpose whatsoever, provided that this entire notice appears in all copies
  of the software, derivative works and supporting documentation.  Further,
  the user agrees to credit URI/MIT in any publications that result from the
  use of this software or in any product that includes this software. The
  names URI, MIT and/or GSO, however, may not be used in any advertising or
  publicity to endorse or promote any products or commercial entity unless
  specific written permission is obtained from URI/MIT. The user also
  understands that URI/MIT is not obligated to provide the user with any
  support, consulting, training or assistance of any kind with regard to the
  use, operation and performance of this software nor to provide the user
  with any updates, revisions, new versions or "bug fixes".

  THIS SOFTWARE IS PROVIDED BY URI/MIT "AS IS" AND ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
  EVENT SHALL URI/MIT BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS
  ACTION, ARISING OUT OF OR IN CONNECTION WITH THE ACCESS, USE OR PERFORMANCE
  OF THIS SOFTWARE.
*/

// Implementation for the class Structure
//
// jhrg 9/14/94

// $Log: Structure.cc,v $
// Revision 1.20  1996/03/05 17:36:12  jimg
// Added ce_eval to serailize member function.
// Added debugging information to _duplicate member function.
//
// Revision 1.19  1996/02/02 00:31:13  jimg
// Merge changes for DODS-1.1.0 into DODS-2.x
//
// Revision 1.18  1995/12/09  01:07:00  jimg
// Added changes so that relational operators will work properly for all the
// datatypes (including Sequences). The relational ops are evaluated in
// DDS::eval_constraint() after being parsed by DDS::parse_constraint().
//
// Revision 1.17  1995/12/06  21:56:32  jimg
// Added `constrained' flag to print_decl.
// Removed third parameter of read.
// Modified print_decl() to print only those parts of a dataset that are
// selected when `constrained' is true.
//
// Revision 1.16  1995/10/23  23:21:04  jimg
// Added _send_p and _read_p fields (and their accessors) along with the
// virtual mfuncs set_send_p() and set_read_p().
//
// Revision 1.15  1995/08/26  00:31:49  jimg
// Removed code enclosed in #ifdef NEVER #endif.
//
// Revision 1.14  1995/08/23  00:11:08  jimg
// Changed old, deprecated member functions to new ones.
// Switched from String representation of type to enum.
//
// Revision 1.13.2.1  1995/09/14 20:58:13  jimg
// Moved some loop index variables out of the loop statement.
//
// Revision 1.13  1995/07/09  21:29:06  jimg
// Added copyright notice.
//
// Revision 1.12  1995/05/10  15:34:06  jimg
// Failed to change `config.h' to `config_dap.h' in these files.
//
// Revision 1.11  1995/05/10  13:45:31  jimg
// Changed the name of the configuration header file from `config.h' to
// `config_dap.h' so that other libraries could have header files which were
// installed in the DODS include directory without overwriting this one. Each
// config header should follow the convention config_<name>.h.
//
// Revision 1.10  1995/03/16  17:29:12  jimg
// Added include config_dap.h to top of include list.
// Added TRACE_NEW switched dbnew includes.
// Fixed bug in read_val() where **val was passed incorrectly to
// subordinate read_val() calls.
//
// Revision 1.9  1995/03/04  14:34:51  jimg
// Major modifications to the transmission and representation of values:
// Added card() virtual function which is true for classes that
// contain cardinal types (byte, int float, string).
// Changed the representation of Str from the C rep to a C++
// class represenation.
// Chnaged read_val and store_val so that they take and return
// types that are stored by the object (e.g., inthe case of Str
// an URL, read_val returns a C++ String object).
// Modified Array representations so that arrays of card()
// objects are just that - no more storing strings, ... as
// C would store them.
// Arrays of non cardinal types are arrays of the DODS objects (e.g.,
// an array of a structure is represented as an array of Structure
// objects).
//
// Revision 1.8  1995/02/10  02:22:59  jimg
// Added DBMALLOC includes and switch to code which uses malloc/free.
// Private and protected symbols now start with `_'.
// Added new accessors for name and type fields of BaseType; the old ones
// will be removed in a future release.
// Added the store_val() mfunc. It stores the given value in the object's
// internal buffer.
// Made both List and Str handle their values via pointers to memory.
// Fixed read_val().
// Made serialize/deserialize handle all malloc/free calls (even in those
// cases where xdr initiates the allocation).
// Fixed print_val().
//
// Revision 1.7  1995/01/19  20:05:24  jimg
// ptr_duplicate() mfunc is now abstract virtual.
// Array, ... Grid duplicate mfuncs were modified to take pointers, not
// referenves.
//
// Revision 1.6  1995/01/11  15:54:49  jimg
// Added modifications necessary for BaseType's static XDR pointers. This
// was mostly a name change from xdrin/out to _xdrin/out.
// Removed the two FILE pointers from ctors, since those are now set with
// functions which are friends of BaseType.
//
// Revision 1.5  1994/12/16  15:16:39  dan
// Modified Structure class removing inheritance from class CtorType
// and directly inheriting from class BaseType to alloc calling
// BaseType's constructor directly.
//
// Revision 1.4  1994/11/22  14:06:10  jimg
// Added code for data transmission to parts of the type hierarchy. Not
// complete yet.
// Fixed erros in type hierarchy headers (typos, incorrect comments, ...).
//
// Revision 1.3  1994/10/17  23:34:47  jimg
// Added code to print_decl so that variable declarations are pretty
// printed.
// Added private mfunc duplicate().
// Added ptr_duplicate().
// Added Copy ctor, dtor and operator=.
//
// Revision 1.2  1994/09/23  14:45:26  jimg
// Added mfunc check_semantics().
// Added sanity checking on the variable list (is it empty?).
//

#ifdef _GNUG_
#pragma implementation
#endif

#include "config_dap.h"

#include <string.h>
#include <stdlib.h>
#include <assert.h>

#include "Structure.h"
#include "DDS.h"
#include "util.h"
#include "debug.h"

#ifdef TRACE_NEW
#include "trace_new.h"
#endif

void
Structure::_duplicate(const Structure &s)
{
    BaseType::_duplicate(s);

    Structure &cs = (Structure &)s; // cast away const

    DBG(cerr << "Copying strucutre: " << name() << endl);

    for (Pix p = cs._vars.first(); p; cs._vars.next(p)) {
	DBG(cerr << "Copying field: " << cs.name() << endl);
	_vars.append(cs._vars(p)->ptr_duplicate());
    }
}

Structure::Structure(const String &n) : BaseType(n, structure_t)
{
}

Structure::Structure(const Structure &rhs)
{
    _duplicate(rhs);
}

Structure::~Structure()
{
    for (Pix p = _vars.first(); p; _vars.next(p))
	delete _vars(p);
}

const Structure &
Structure::operator=(const Structure &rhs)
{
    if (this == &rhs)
	return *this;

    _duplicate(rhs);

    return *this;
}

void
Structure::set_send_p(bool state)
{
    for (Pix p = _vars.first(); p; _vars.next(p))
	_vars(p)->set_send_p(state);

    BaseType::set_send_p(state);
}

void
Structure::set_read_p(bool state)
{
    for (Pix p = _vars.first(); p; _vars.next(p))
	_vars(p)->set_read_p(state);

    BaseType::set_read_p(state);
}

// NB: Part p defaults to nil for this class

void
Structure::add_var(BaseType *bt, Part p)
{
    _vars.append(bt);
}

unsigned int
Structure::width()
{
    return sizeof(Structure);
}

// Returns: false if an error was detected, true otherwise.
// NB: this means that serialize() returns true when the CE evaluates to
// false. This bug might be fixed using exceptions.

bool
Structure::serialize(const String &dataset, DDS &dds, bool ce_eval, bool flush)
{
    bool status = true;

    if (!read_p() && !read(dataset))
	return false;

    if (ce_eval && !dds.eval_selection(dataset))
	return true;

    for (Pix p = first_var(); p; next_var(p))
	if (var(p)->send_p()
	    && !(status = var(p)->serialize(dataset, dds, false, false)))
	    break;

    // flush the stream *even* if status is false, but preserve the value of
    // status if it's false.
    if (flush)
	status = status && expunge();

    return status;
}

bool
Structure::deserialize(bool reuse)
{
  bool status;

    for (Pix p = first_var(); p; next_var(p)) {
	status = var(p)->deserialize(reuse);
	if (!status)
	  break;
    }

    return status;
}

// This mfunc assumes that val contains values for all the elements of the
// strucuture in the order those elements are declared.

unsigned int
Structure::val2buf(void *val, bool reuse)
{
    return sizeof(Structure);
}

unsigned int
Structure::buf2val(void **val)
{
    return sizeof(Structure);
}

BaseType *
Structure::var(const String &name)
{
    for (Pix p = _vars.first(); p; _vars.next(p))
	if (_vars(p)->name() == name)
	    return _vars(p);

    return 0;
}

Pix
Structure::first_var()
{
    return _vars.first();
}

void
Structure::next_var(Pix &p)
{
    if (!_vars.empty() && p)
	_vars.next(p);
}

BaseType *
Structure::var(Pix p)
{
    if (!_vars.empty() && p)
	return _vars(p);
    else
      return NULL;
}

void
Structure::print_decl(ostream &os, String space, bool print_semi,
		      bool constraint_info, bool constrained)
{
    if (constrained && !send_p())
	return;

    os << space << type_name() << " {" << endl;
    for (Pix p = _vars.first(); p; _vars.next(p))
	_vars(p)->print_decl(os, space + "    ", true, constraint_info,
			     constrained);
    os << space << "} " << name();

    if (constraint_info) {
	if (send_p())
	    cout << ": Send True";
	else
	    cout << ": Send False";
    }

    if (print_semi)
	os << ";" << endl;
}

// print the values of the contained variables

void
Structure::print_val(ostream &os, String space, bool print_decl_p)
{
    if (print_decl_p) {
	print_decl(os, space, false);
	os << " = ";
    }

    os << "{ ";
    for (Pix p = _vars.first(); p; _vars.next(p), p && os << ", ") {
	_vars(p)->print_val(os, "", false);
    }
    os << " }";

    if (print_decl_p)
	os << ";" << endl;
}

bool
Structure::check_semantics(bool all)
{
    if (!BaseType::check_semantics())
	return false;

    if (!unique(_vars, (const char *)name(), (const char *)type_name()))
	return false;

    if (all)
	for (Pix p = _vars.first(); p; _vars.next(p))
	    if (!_vars(p)->check_semantics(true))
		return false;

    return true;
}

<|endoftext|>


<commit_before>/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
 *  Main authors:
 *     Guido Tack <tack@gecode.org>
 *
 *  Copyright:
 *     Guido Tack, 2007
 *
 *  Last modified:
 *     $Date: 2010-07-02 19:18:43 +1000 (Fri, 02 Jul 2010) $ by $Author: tack $
 *     $Revision: 11149 $
 *
 *  This file is part of Gecode, the generic constraint
 *  development environment:
 *     http://www.gecode.org
 *
 *  Permission is hereby granted, free of charge, to any person obtaining
 *  a copy of this software and associated documentation files (the
 *  "Software"), to deal in the Software without restriction, including
 *  without limitation the rights to use, copy, modify, merge, publish,
 *  distribute, sublicense, and/or sell copies of the Software, and to
 *  permit persons to whom the Software is furnished to do so, subject to
 *  the following conditions:
 *
 *  The above copyright notice and this permission notice shall be
 *  included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#include "base/stringprintf.h"
#include "flatzinc/flatzinc.h"

#include <vector>
#include <string>
using namespace std;

namespace operations_research {

FlatZincModel::FlatZincModel(void)
    : int_var_count(-1),
      bool_var_count(-1),
      set_var_count(-1),
      objective_variable_(-1),
      solve_annotations_(NULL),
      solver_("FlatZincSolver"),
      objective_(NULL),
      output_(NULL) {}

void FlatZincModel::Init(int intVars, int boolVars, int setVars) {
  int_var_count = 0;
  integer_variables_.resize(intVars);
  integer_variables_introduced.resize(intVars);
  integer_variables_boolalias.resize(intVars);
  bool_var_count = 0;
  boolean_variables_.resize(boolVars);
  boolean_variables_introduced.resize(boolVars);
  set_var_count = 0;
  // sv = std::vector<SetVar>(setVars);
  // sv_introduced = std::vector<bool>(setVars);
}

void FlatZincModel::NewIntVar(const std::string& name, IntVarSpec* const vs) {
  if (vs->alias) {
    integer_variables_[int_var_count++] = integer_variables_[vs->i];
  } else {
    AST::SetLit* domain = vs->domain.some();
    if (domain == NULL) {
      integer_variables_[int_var_count++] =
          solver_.MakeIntVar(kint32min, kint32max, name);
    } else if (domain->interval) {
      integer_variables_[int_var_count++] =
          solver_.MakeIntVar(domain->min, domain->max, name);
    } else {
      integer_variables_[int_var_count++] = solver_.MakeIntVar(domain->s, name);
    }
    VLOG(1) << "Create IntVar: "
            << integer_variables_[int_var_count - 1]->DebugString();
  }
  integer_variables_introduced[int_var_count - 1] = vs->introduced;
  integer_variables_boolalias[int_var_count - 1] = -1;
}

void FlatZincModel::AliasBool2Int(int iv, int bv) {
  integer_variables_boolalias[iv] = bv;
}

int FlatZincModel::AliasBool2Int(int iv) {
  return integer_variables_boolalias[iv];
}

void FlatZincModel::NewBoolVar(const std::string& name, BoolVarSpec* const vs) {
  if (vs->alias) {
    boolean_variables_[bool_var_count++] = boolean_variables_[vs->i];
  } else {
    boolean_variables_[bool_var_count++] = solver_.MakeBoolVar(name);
    VLOG(1) << "Create BoolVar: "
            << boolean_variables_[bool_var_count - 1]->DebugString();
  }
  boolean_variables_introduced[bool_var_count-1] = vs->introduced;
}

// void FlatZincModel::newSetVar(SetVarSpec* vs) {
//   if (vs->alias) {
//     sv[set_var_count++] = sv[vs->i];
//   } else {
//     LOG(FATAL) << "SetVar not supported";
//     sv[set_var_count++] = SetVar();
//   }
//   sv_introduced[set_var_count-1] = vs->introduced;
// }

void FlattenAnnotations(AST::Array* const annotations,
                        std::vector<AST::Node*>& out) {
  for (unsigned int i=0; i < annotations->a.size(); i++) {
    if (annotations->a[i]->isCall("seq_search")) {
      AST::Call* c = annotations->a[i]->getCall();
      if (c->args->isArray()) {
        FlattenAnnotations(c->args->getArray(), out);
      } else {
        out.push_back(c->args);
      }
    } else {
      out.push_back(annotations->a[i]);
    }
  }
}

void FlatZincModel::CreateDecisionBuilders(bool ignore_unknown,
                                           bool ignore_annotations) {
  AST::Node* annotations = solve_annotations_;
  if (annotations && !ignore_annotations) {
    std::vector<AST::Node*> flat_annotations;
    if (annotations->isArray()) {
      FlattenAnnotations(annotations->getArray(), flat_annotations);
    } else {
      flat_annotations.push_back(annotations);
    }

    for (unsigned int i=0; i < flat_annotations.size(); i++) {
      try {
        AST::Call *call = flat_annotations[i]->getCall("int_search");
        AST::Array *args = call->getArgs(4);
        AST::Array *vars = args->a[0]->getArray();
        std::vector<IntVar*> int_vars;
        for (int i = 0; i < vars->a.size(); ++i) {
          int_vars.push_back(integer_variables_[vars->a[i]->getIntVar()]);
        }
        builders_.push_back(solver_.MakePhase(int_vars,
                                              Solver::CHOOSE_FIRST_UNBOUND,
                                              Solver::ASSIGN_MIN_VALUE));
      } catch (AST::TypeError& e) {
        (void) e;
        try {
          AST::Call *call = flat_annotations[i]->getCall("bool_search");
          AST::Array *args = call->getArgs(4);
          AST::Array *vars = args->a[0]->getArray();
          std::vector<IntVar*> int_vars;
          for (int i = 0; i < vars->a.size(); ++i) {
            int_vars.push_back(boolean_variables_[vars->a[i]->getBoolVar()]);
          }
          builders_.push_back(solver_.MakePhase(int_vars,
                                                Solver::CHOOSE_FIRST_UNBOUND,
                                                Solver::ASSIGN_MAX_VALUE));
        } catch (AST::TypeError& e) {
          (void) e;
          try {
            AST::Call *call = flat_annotations[i]->getCall("set_search");
            AST::Array *args = call->getArgs(4);
            AST::Array *vars = args->a[0]->getArray();
            LOG(FATAL) << "Search on set variables not supported";
          } catch (AST::TypeError& e) {
            (void) e;
            if (!ignore_unknown) {
              LOG(WARNING) << "Warning, ignored search annotation: "
                           << flat_annotations[i]->DebugString();
            }
          }
        }
      }
      VLOG(1) << "Adding decision builder = "
              << builders_.back()->DebugString();
    }
  } else {
    std::vector<IntVar*> primary_integer_variables;
    std::vector<IntVar*> secondary_integer_variables;
    std::vector<SequenceVar*> sequence_variables;
    std::vector<IntervalVar*> interval_variables;
    solver_.CollectDecisionVariables(&primary_integer_variables,
                                     &secondary_integer_variables,
                                     &sequence_variables,
                                     &interval_variables);
    builders_.push_back(solver_.MakePhase(primary_integer_variables,
                                          Solver::CHOOSE_FIRST_UNBOUND,
                                          Solver::ASSIGN_MIN_VALUE));
    VLOG(1) << "Decision builder = " << builders_.back()->DebugString();
  }
}

void FlatZincModel::Satisfy(AST::Array* const annotations) {
  method_ = SAT;
  solve_annotations_ = annotations;
}

void FlatZincModel::Minimize(int var, AST::Array* const annotations) {
  method_ = MIN;
  objective_variable_ = var;
  solve_annotations_ = annotations;
  // Branch on optimization variable to ensure that it is given a value.
  AST::Array* args = new AST::Array(4);
  args->a[0] = new AST::Array(new AST::IntVar(objective_variable_));
  args->a[1] = new AST::Atom("input_order");
  args->a[2] = new AST::Atom("indomain_min");
  args->a[3] = new AST::Atom("complete");
  AST::Call* c = new AST::Call("int_search", args);
  if (!solve_annotations_) {
    solve_annotations_ = new AST::Array(c);
  } else {
    solve_annotations_->a.push_back(c);
  }
  objective_ = solver_.MakeMinimize(integer_variables_[objective_variable_], 1);
}

void FlatZincModel::Maximize(int var, AST::Array* const annotations) {
  method_ = MAX;
  objective_variable_ = var;
  solve_annotations_ = annotations;
  // Branch on optimization variable to ensure that it is given a value.
  AST::Array* args = new AST::Array(4);
  args->a[0] = new AST::Array(new AST::IntVar(objective_variable_));
  args->a[1] = new AST::Atom("input_order");
  args->a[2] = new AST::Atom("indomain_min");
  args->a[3] = new AST::Atom("complete");
  AST::Call* c = new AST::Call("int_search", args);
  if (!solve_annotations_) {
    solve_annotations_ = new AST::Array(c);
  } else {
    solve_annotations_->a.push_back(c);
  }
  objective_ = solver_.MakeMaximize(integer_variables_[objective_variable_], 1);
}

FlatZincModel::~FlatZincModel(void) {
  delete solve_annotations_;
  delete output_;
}

void FlatZincModel::Solve(int solve_frequency,
                          bool use_log,
                          bool all_solutions,
                          bool ignore_annotations,
                          int num_solutions) {
  CreateDecisionBuilders(false, ignore_annotations);
  if (all_solutions && num_solutions == 0) {
    num_solutions = kint32max;
  }
  std::vector<SearchMonitor*> monitors;
  switch (method_) {
    case MIN:
    case MAX: {
      SearchMonitor* const log = use_log ?
          solver_.MakeSearchLog(solve_frequency, objective_) :
          NULL;
      monitors.push_back(log);
      monitors.push_back(objective_);
      break;
    }
    case SAT: {
      SearchMonitor* const log = use_log ?
          solver_.MakeSearchLog(solve_frequency) :
          NULL;
      monitors.push_back(log);
      break;
    }
  }

  int count = 0;
  solver_.NewSearch(solver_.Compose(builders_), monitors);
  while (solver_.NextSolution()) {
    if (output_ != NULL) {
      for (unsigned int i = 0; i < output_->a.size(); i++) {
        std::cout << DebugString(output_->a[i]);
      }
      std::cout << "----------" << std::endl;
    }
    count++;
    if (num_solutions > 0 && count >= num_solutions) {
      break;
    }
  }
  solver_.EndSearch();
}

void FlatZincModel::InitOutput(AST::Array* const output) {
  output_ = output;
}

string FlatZincModel::DebugString(AST::Node* const ai) const {
  string output;
  int k;
  if (ai->isArray()) {
    AST::Array* aia = ai->getArray();
    int size = aia->a.size();
    output += "[";
    for (int j = 0; j < size; j++) {
      output += DebugString(aia->a[j]);
      if (j < size - 1) {
        output += ", ";
      }
    }
    output += "]";
  } else if (ai->isInt(k)) {
    output += StringPrintf("%d", k);
  } else if (ai->isIntVar()) {
    IntVar* const var = integer_variables_[ai->getIntVar()];
    output += StringPrintf("%d", var->Value());
  } else if (ai->isBoolVar()) {
    IntVar* const var = boolean_variables_[ai->getBoolVar()];
    output += var->Value() ? "true" : "false";
  } else if (ai->isSetVar()) {
    LOG(FATAL) << "Set variables not implemented";
  } else if (ai->isBool()) {
    output += (ai->getBool() ? "true" : "false");
  } else if (ai->isSet()) {
    AST::SetLit* s = ai->getSet();
    if (s->interval) {
      output += StringPrintf("%d..%d", s->min, s->max);
    } else {
      output += "{";
      for (unsigned int i=0; i<s->s.size(); i++) {
        output += StringPrintf("%d%s",
                               s->s[i],
                               (i < s->s.size()-1 ? ", " : "}"));
      }
    }
  } else if (ai->isString()) {
    string s = ai->getString();
    for (unsigned int i = 0; i < s.size(); i++) {
      if (s[i] == '\\' && i < s.size() - 1) {
        switch (s[i+1]) {
          case 'n': output += "\n"; break;
          case '\\': output += "\\"; break;
          case 't': output += "\t"; break;
          default: {
            output += "\\";
            output += s[i+1];
          }
        }
        i++;
      } else {
        output += s[i];
      }
    }
  }
  return output;
}
}

// STATISTICS: flatzinc-any
<commit_msg>revamp parsing...<commit_after>/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
 *  Main authors:
 *     Guido Tack <tack@gecode.org>
 *
 *  Copyright:
 *     Guido Tack, 2007
 *
 *  Last modified:
 *     $Date: 2010-07-02 19:18:43 +1000 (Fri, 02 Jul 2010) $ by $Author: tack $
 *     $Revision: 11149 $
 *
 *  This file is part of Gecode, the generic constraint
 *  development environment:
 *     http://www.gecode.org
 *
 *  Permission is hereby granted, free of charge, to any person obtaining
 *  a copy of this software and associated documentation files (the
 *  "Software"), to deal in the Software without restriction, including
 *  without limitation the rights to use, copy, modify, merge, publish,
 *  distribute, sublicense, and/or sell copies of the Software, and to
 *  permit persons to whom the Software is furnished to do so, subject to
 *  the following conditions:
 *
 *  The above copyright notice and this permission notice shall be
 *  included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#include "base/stringprintf.h"
#include "flatzinc/flatzinc.h"

#include <vector>
#include <string>
using namespace std;

namespace operations_research {

FlatZincModel::FlatZincModel(void)
    : int_var_count(-1),
      bool_var_count(-1),
      set_var_count(-1),
      objective_variable_(-1),
      solve_annotations_(NULL),
      solver_("FlatZincSolver"),
      objective_(NULL),
      output_(NULL) {}

void FlatZincModel::Init(int intVars, int boolVars, int setVars) {
  int_var_count = 0;
  integer_variables_.resize(intVars);
  integer_variables_introduced.resize(intVars);
  integer_variables_boolalias.resize(intVars);
  bool_var_count = 0;
  boolean_variables_.resize(boolVars);
  boolean_variables_introduced.resize(boolVars);
  set_var_count = 0;
  // sv = std::vector<SetVar>(setVars);
  // sv_introduced = std::vector<bool>(setVars);
}

void FlatZincModel::NewIntVar(const std::string& name, IntVarSpec* const vs) {
  if (vs->alias) {
    integer_variables_[int_var_count++] = integer_variables_[vs->i];
  } else {
    AST::SetLit* domain = vs->domain.some();
    if (domain == NULL) {
      integer_variables_[int_var_count++] =
          solver_.MakeIntVar(kint32min, kint32max, name);
    } else if (domain->interval) {
      integer_variables_[int_var_count++] =
          solver_.MakeIntVar(domain->min, domain->max, name);
    } else {
      integer_variables_[int_var_count++] = solver_.MakeIntVar(domain->s, name);
    }
    VLOG(1) << "Create IntVar: "
            << integer_variables_[int_var_count - 1]->DebugString();
  }
  integer_variables_introduced[int_var_count - 1] = vs->introduced;
  integer_variables_boolalias[int_var_count - 1] = -1;
}

void FlatZincModel::AliasBool2Int(int iv, int bv) {
  integer_variables_boolalias[iv] = bv;
}

int FlatZincModel::AliasBool2Int(int iv) {
  return integer_variables_boolalias[iv];
}

void FlatZincModel::NewBoolVar(const std::string& name, BoolVarSpec* const vs) {
  if (vs->alias) {
    boolean_variables_[bool_var_count++] = boolean_variables_[vs->i];
  } else {
    boolean_variables_[bool_var_count++] = solver_.MakeBoolVar(name);
    VLOG(1) << "Create BoolVar: "
            << boolean_variables_[bool_var_count - 1]->DebugString();
  }
  boolean_variables_introduced[bool_var_count-1] = vs->introduced;
}

// void FlatZincModel::newSetVar(SetVarSpec* vs) {
//   if (vs->alias) {
//     sv[set_var_count++] = sv[vs->i];
//   } else {
//     LOG(FATAL) << "SetVar not supported";
//     sv[set_var_count++] = SetVar();
//   }
//   sv_introduced[set_var_count-1] = vs->introduced;
// }

void FlattenAnnotations(AST::Array* const annotations,
                        std::vector<AST::Node*>& out) {
  for (unsigned int i=0; i < annotations->a.size(); i++) {
    if (annotations->a[i]->isCall("seq_search")) {
      AST::Call* c = annotations->a[i]->getCall();
      if (c->args->isArray()) {
        FlattenAnnotations(c->args->getArray(), out);
      } else {
        out.push_back(c->args);
      }
    } else {
      out.push_back(annotations->a[i]);
    }
  }
}

void FlatZincModel::CreateDecisionBuilders(bool ignore_unknown,
                                           bool ignore_annotations) {
  AST::Node* annotations = solve_annotations_;
  if (annotations && !ignore_annotations) {
    std::vector<AST::Node*> flat_annotations;
    if (annotations->isArray()) {
      FlattenAnnotations(annotations->getArray(), flat_annotations);
    } else {
      flat_annotations.push_back(annotations);
    }

    for (unsigned int i=0; i < flat_annotations.size(); i++) {
      try {
        AST::Call *call = flat_annotations[i]->getCall("int_search");
        AST::Array *args = call->getArgs(4);
        AST::Array *vars = args->a[0]->getArray();
        std::vector<IntVar*> int_vars;
        for (int i = 0; i < vars->a.size(); ++i) {
          int_vars.push_back(integer_variables_[vars->a[i]->getIntVar()]);
        }
        builders_.push_back(solver_.MakePhase(int_vars,
                                              Solver::CHOOSE_FIRST_UNBOUND,
                                              Solver::ASSIGN_MIN_VALUE));
      } catch (AST::TypeError& e) {
        (void) e;
        try {
          AST::Call *call = flat_annotations[i]->getCall("bool_search");
          AST::Array *args = call->getArgs(4);
          AST::Array *vars = args->a[0]->getArray();
          std::vector<IntVar*> int_vars;
          for (int i = 0; i < vars->a.size(); ++i) {
            int_vars.push_back(boolean_variables_[vars->a[i]->getBoolVar()]);
          }
          builders_.push_back(solver_.MakePhase(int_vars,
                                                Solver::CHOOSE_FIRST_UNBOUND,
                                                Solver::ASSIGN_MAX_VALUE));
        } catch (AST::TypeError& e) {
          (void) e;
          try {
            AST::Call *call = flat_annotations[i]->getCall("set_search");
            AST::Array *args = call->getArgs(4);
            AST::Array *vars = args->a[0]->getArray();
            LOG(FATAL) << "Search on set variables not supported";
          } catch (AST::TypeError& e) {
            (void) e;
            if (!ignore_unknown) {
              LOG(WARNING) << "Warning, ignored search annotation: "
                           << flat_annotations[i]->DebugString();
            }
          }
        }
      }
      VLOG(1) << "Adding decision builder = "
              << builders_.back()->DebugString();
    }
  } else {
    std::vector<IntVar*> primary_integer_variables;
    std::vector<IntVar*> secondary_integer_variables;
    std::vector<SequenceVar*> sequence_variables;
    std::vector<IntervalVar*> interval_variables;
    solver_.CollectDecisionVariables(&primary_integer_variables,
                                     &secondary_integer_variables,
                                     &sequence_variables,
                                     &interval_variables);
    builders_.push_back(solver_.MakePhase(primary_integer_variables,
                                          Solver::CHOOSE_FIRST_UNBOUND,
                                          Solver::ASSIGN_MIN_VALUE));
    VLOG(1) << "Decision builder = " << builders_.back()->DebugString();
  }
}

void FlatZincModel::Satisfy(AST::Array* const annotations) {
  method_ = SAT;
  solve_annotations_ = annotations;
}

void FlatZincModel::Minimize(int var, AST::Array* const annotations) {
  method_ = MIN;
  objective_variable_ = var;
  solve_annotations_ = annotations;
  // Branch on optimization variable to ensure that it is given a value.
  AST::Array* args = new AST::Array(4);
  args->a[0] = new AST::Array(new AST::IntVar(objective_variable_));
  args->a[1] = new AST::Atom("input_order");
  args->a[2] = new AST::Atom("indomain_min");
  args->a[3] = new AST::Atom("complete");
  AST::Call* c = new AST::Call("int_search", args);
  if (!solve_annotations_) {
    solve_annotations_ = new AST::Array(c);
  } else {
    solve_annotations_->a.push_back(c);
  }
  objective_ = solver_.MakeMinimize(integer_variables_[objective_variable_], 1);
}

void FlatZincModel::Maximize(int var, AST::Array* const annotations) {
  method_ = MAX;
  objective_variable_ = var;
  solve_annotations_ = annotations;
  // Branch on optimization variable to ensure that it is given a value.
  AST::Array* args = new AST::Array(4);
  args->a[0] = new AST::Array(new AST::IntVar(objective_variable_));
  args->a[1] = new AST::Atom("input_order");
  args->a[2] = new AST::Atom("indomain_min");
  args->a[3] = new AST::Atom("complete");
  AST::Call* c = new AST::Call("int_search", args);
  if (!solve_annotations_) {
    solve_annotations_ = new AST::Array(c);
  } else {
    solve_annotations_->a.push_back(c);
  }
  objective_ = solver_.MakeMaximize(integer_variables_[objective_variable_], 1);
}

FlatZincModel::~FlatZincModel(void) {
  delete solve_annotations_;
  delete output_;
}

void FlatZincModel::Solve(int solve_frequency,
                          bool use_log,
                          bool all_solutions,
                          bool ignore_annotations,
                          int num_solutions) {
  CreateDecisionBuilders(false, ignore_annotations);
  if (all_solutions && num_solutions == 0) {
    num_solutions = kint32max;
  } else if (objective_ == NULL) {
    num_solutions = 1;
  }
  std::vector<SearchMonitor*> monitors;
  switch (method_) {
    case MIN:
    case MAX: {
      SearchMonitor* const log = use_log ?
          solver_.MakeSearchLog(solve_frequency, objective_) :
          NULL;
      monitors.push_back(log);
      monitors.push_back(objective_);
      break;
    }
    case SAT: {
      SearchMonitor* const log = use_log ?
          solver_.MakeSearchLog(solve_frequency) :
          NULL;
      monitors.push_back(log);
      break;
    }
  }

  int count = 0;
  solver_.NewSearch(solver_.Compose(builders_), monitors);
  while (solver_.NextSolution()) {
    if (output_ != NULL) {
      for (unsigned int i = 0; i < output_->a.size(); i++) {
        std::cout << DebugString(output_->a[i]);
      }
      std::cout << "----------" << std::endl;
    }
    count++;
    if (num_solutions > 0 && count >= num_solutions) {
      break;
    }
  }
  solver_.EndSearch();
}

void FlatZincModel::InitOutput(AST::Array* const output) {
  output_ = output;
}

string FlatZincModel::DebugString(AST::Node* const ai) const {
  string output;
  int k;
  if (ai->isArray()) {
    AST::Array* aia = ai->getArray();
    int size = aia->a.size();
    output += "[";
    for (int j = 0; j < size; j++) {
      output += DebugString(aia->a[j]);
      if (j < size - 1) {
        output += ", ";
      }
    }
    output += "]";
  } else if (ai->isInt(k)) {
    output += StringPrintf("%d", k);
  } else if (ai->isIntVar()) {
    IntVar* const var = integer_variables_[ai->getIntVar()];
    output += StringPrintf("%d", var->Value());
  } else if (ai->isBoolVar()) {
    IntVar* const var = boolean_variables_[ai->getBoolVar()];
    output += var->Value() ? "true" : "false";
  } else if (ai->isSetVar()) {
    LOG(FATAL) << "Set variables not implemented";
  } else if (ai->isBool()) {
    output += (ai->getBool() ? "true" : "false");
  } else if (ai->isSet()) {
    AST::SetLit* s = ai->getSet();
    if (s->interval) {
      output += StringPrintf("%d..%d", s->min, s->max);
    } else {
      output += "{";
      for (unsigned int i=0; i<s->s.size(); i++) {
        output += StringPrintf("%d%s",
                               s->s[i],
                               (i < s->s.size()-1 ? ", " : "}"));
      }
    }
  } else if (ai->isString()) {
    string s = ai->getString();
    for (unsigned int i = 0; i < s.size(); i++) {
      if (s[i] == '\\' && i < s.size() - 1) {
        switch (s[i+1]) {
          case 'n': output += "\n"; break;
          case '\\': output += "\\"; break;
          case 't': output += "\t"; break;
          default: {
            output += "\\";
            output += s[i+1];
          }
        }
        i++;
      } else {
        output += s[i];
      }
    }
  }
  return output;
}
}

// STATISTICS: flatzinc-any
<|endoftext|>