<commit_before>#include "plotwidget.h"
#include "plot.h"
#include "signalhandler.h"
#include "signaldata.h"
#include "setscaledialog.h"
#include "selectsignaldialog.h"
#include "signaldescription.h"
#include "pythonchannelsubscribercollection.h"

#include <qlabel.h>
#include <qlayout.h>
#include <QDoubleSpinBox>
#include <QMenu>
#include <QAction>
#include <QLabel>
#include <QInputDialog>
#include <QDialogButtonBox>
#include <QListWidget>
#include <QTimer>
#include <QPushButton>
#include <QColorDialog>

PlotWidget::PlotWidget(PythonChannelSubscriberCollection* subscribers, QWidget *parent):
    QWidget(parent),
    mSubscribers(subscribers)
{

  d_plot = new Plot(this);

  mColors << Qt::green
          << Qt::red
          << Qt::blue
          << Qt::cyan
          << Qt::magenta
          << Qt::darkYellow
          << QColor(139, 69, 19) // brown
          << Qt::darkCyan
          << Qt::darkGreen
          << Qt::darkMagenta
          << Qt::black;

  mTimeWindowSpin = new QDoubleSpinBox;
  mTimeWindowSpin->setSingleStep(0.1);
  mTimeWindowSpin->setMinimum(0.0);
  mTimeWindowSpin->setMaximum(60*5);

  QDoubleSpinBox* yScaleSpin = new QDoubleSpinBox;
  yScaleSpin->setSingleStep(0.1);

  QVBoxLayout* vLayout1 = new QVBoxLayout();

  //QPushButton* resetYScaleButton = new QPushButton("Reset Y scale");
  //vLayout1->addWidget(resetYScaleButton);

  QWidget* frameWidget = new QWidget;
  QHBoxLayout* frameLayout = new QHBoxLayout(frameWidget);
  frameWidget->setContentsMargins(0, 0, 0, 0);
  frameLayout->addWidget(new QLabel("Time Window [s]:"));
  frameLayout->addWidget(mTimeWindowSpin);
  vLayout1->addWidget(frameWidget);

  mSignalListWidget = new QListWidget(this);
  vLayout1->addWidget(mSignalListWidget);

  mSignalInfoLabel = new QLabel(this);
  vLayout1->addWidget(mSignalInfoLabel);
  vLayout1->addStretch(10);

  QHBoxLayout *layout = new QHBoxLayout(this);
  layout->addWidget(d_plot, 10);
  layout->addLayout(vLayout1);

  mTimeWindowSpin->setValue(d_plot->timeWindow());

  connect(mTimeWindowSpin, SIGNAL(valueChanged(double)),
          d_plot, SLOT(setTimeWindow(double)));

  connect(d_plot, SIGNAL(syncXAxisScale(double, double)),
          this, SIGNAL(syncXAxisScale(double, double)));

  //connect(yScaleSpin, SIGNAL(valueChanged(double)),
  //        d_plot, SLOT(setYScale(double)));
  //yScaleSpin->setValue(10.0);

  this->setContextMenuPolicy(Qt::CustomContextMenu);
  this->connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
      SLOT(onShowContextMenu(const QPoint&)));

  //mSignalListWidget->setDragDropMode(QAbstractItemView::DragDrop);
  //mSignalListWidget->setDragEnabled(true);
  //mSignalListWidget->setDefaultDropAction(Qt::MoveAction);
  mSignalListWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);

  mSignalListWidget->setContextMenuPolicy(Qt::CustomContextMenu);
  this->connect(mSignalListWidget, SIGNAL(customContextMenuRequested(const QPoint&)),
      SLOT(onShowSignalContextMenu(const QPoint&)));

  this->connect(mSignalListWidget, SIGNAL(itemChanged(QListWidgetItem *)), SLOT(onSignalListItemChanged(QListWidgetItem*)));

  QTimer* labelUpdateTimer = new QTimer(this);
  this->connect(labelUpdateTimer, SIGNAL(timeout()), SLOT(updateSignalInfoLabel()));
  labelUpdateTimer->start(100);
}

void PlotWidget::onShowContextMenu(const QPoint& pos)
{

  QPoint globalPos = this->mapToGlobal(pos);
  // for QAbstractScrollArea and derived classes you would use:
  // QPoint globalPos = myWidget->viewport()->mapToGlobal(pos);

  QMenu myMenu;
  myMenu.addAction("Add signal");
  myMenu.addSeparator();
  myMenu.addAction("Reset Y axis scale");
  myMenu.addAction("Set Y axis scale");
  myMenu.addSeparator();
  myMenu.addAction("Remove plot");

  QAction* selectedItem = myMenu.exec(globalPos);
  if (!selectedItem)
  {
    return;
  }

  QString selectedAction = selectedItem->text();

  if (selectedAction == "Remove plot")
  {
    emit this->removePlotRequested(this);
  }
  else if (selectedAction == "Add signal")
  {
    emit this->addSignalRequested(this);
  }
  else if (selectedAction == "Reset Y axis scale")
  {
    this->onResetYAxisScale();
  }
  else if (selectedAction == "Set Y axis scale")
  {

    SetScaleDialog dialog(this);
    QwtInterval axisInterval = d_plot->axisInterval(QwtPlot::yLeft);
    dialog.setUpper(axisInterval.maxValue());
    dialog.setLower(axisInterval.minValue());

    int result = dialog.exec();
    if (result == QDialog::Accepted)
    {
      this->setYAxisScale(dialog.lower(), dialog.upper());
    }
  }
}

QList<SignalHandler*> PlotWidget::signalHandlers()
{
  QList<SignalHandler*> handlers;
  for (int i = 0; i < mSignalListWidget->count(); ++i)
  {
    handlers.append(mSignals[mSignalListWidget->item(i)]);
  }

  return handlers;
}

void PlotWidget::onShowSignalContextMenu(const QPoint& pos)
{

  if (mSignals.empty())
  {
    return;
  }

  QPoint globalPos = mSignalListWidget->mapToGlobal(pos);
  // for QAbstractScrollArea and derived classes you would use:
  // QPoint globalPos = myWidget->viewport()->mapToGlobal(pos);

  QMenu myMenu;
  if (mSignalListWidget->selectedItems().size() == 1)
    {
    myMenu.addAction("Change color");
    myMenu.addSeparator();
    }

  myMenu.addAction("Remove signal");

  QAction* selectedItem = myMenu.exec(globalPos);
  if (!selectedItem)
  {
    return;
  }

  QString selectedAction = selectedItem->text();

  if (selectedAction == "Change color")
  {
    QListWidgetItem* signalItem = mSignalListWidget->currentItem();
    SignalHandler* signalHandler = signalItem->data(Qt::UserRole).value<SignalHandler*>();
    QColor initialColor = signalHandler->signalDescription()->mColor;
    QColor newColor = QColorDialog::getColor(initialColor, this, "Choose signal color");

    if (newColor.isValid())
    {
      signalHandler->signalDescription()->mColor = newColor;
      QPixmap pixmap(24, 24);
      pixmap.fill(newColor);
      signalItem->setIcon(QIcon(pixmap));
      d_plot->setSignalColor(signalHandler->signalData(), newColor);
    }

  }
  else if (selectedAction == "Remove signal")
  {

    QList<QListWidgetItem*> selectedItems = mSignalListWidget->selectedItems();
    foreach (QListWidgetItem*	selectedItem, selectedItems)
    {
      SignalHandler* signalHandler = this->signalForItem(selectedItem);

      mSubscribers->removeSignalHandler(signalHandler);

      d_plot->removeSignal(signalHandler->signalData());
      mSignals.remove(selectedItem);
      this->replot();

      delete selectedItem;
      delete signalHandler;
    }
  }

}

double PlotWidget::timeWindow() const
{
  return this->d_plot->timeWindow();
}

void PlotWidget::updateSignalInfoLabel()
{
  mSignalInfoLabel->setText(QString());

  QListWidgetItem* selectedItem = mSignalListWidget->currentItem();
  if (!selectedItem)
  {
    return;
  }

  SignalHandler* signalHandler = selectedItem->data(Qt::UserRole).value<SignalHandler*>();
  SignalData* signalData = signalHandler->signalData();

  QString signalValue = "No data";
  int numberOfValues = signalData->size();
  if (numberOfValues)
  {
    signalValue = QString::number(signalData->value(numberOfValues-1).y(), 'g', 6);
  }

  QString signalInfoText = QString("Freq:  %1  Val: %2").arg(QString::number(signalData->messageFrequency(), 'f', 1)).arg(signalValue);

  mSignalInfoLabel->setText(signalInfoText);
}

void PlotWidget::setEndTime(double endTime)
{
  d_plot->setEndTime(endTime);
}

void PlotWidget::setXAxisScale(double x0, double x1)
{
  d_plot->setAxisScale(QwtPlot::xBottom, x0, x1);
}

void PlotWidget::replot()
{
  d_plot->replot();
}

void PlotWidget::onResetYAxisScale()
{
  QRectF area;
  foreach (SignalHandler* signalHandler, mSignals.values())
  {
    if (this->signalIsVisible(signalHandler))
    {
      QRectF signalBounds = signalHandler->signalData()->computeBounds();

      if (!area.isValid())
      {
        area = signalBounds;
      }
      else
      {
        area = area.united(signalBounds);
      }
    }
  }

  if (!area.isValid())
  {
    area = QRectF(-1, -1, 2, 2);
  }

  this->setYAxisScale(area.top(), area.bottom());
}

void PlotWidget::setYAxisScale(double lower, double upper)
{
  d_plot->setAxisScale(QwtPlot::yLeft, lower, upper);
  this->replot();
}

void PlotWidget::onSignalListItemChanged(QListWidgetItem* item)
{
  SignalHandler* signalHandler = this->signalForItem(item);
  Qt::CheckState checkState = item->checkState();

  if (!item->isSelected())
  {
    mSignalListWidget->clearSelection();
    item->setSelected(true);
  }

  QList<QListWidgetItem*> selectedItems = mSignalListWidget->selectedItems();
  foreach (QListWidgetItem*	selectedItem, selectedItems)
  {
    SignalHandler* signalHandler = this->signalForItem(selectedItem);
    selectedItem->setCheckState(checkState);
    d_plot->setSignalVisible(signalHandler->signalData(), checkState == Qt::Checked);
  }
}

QListWidgetItem* PlotWidget::itemForSignal(SignalHandler* signalHandler)
{
  return mSignals.key(signalHandler);
}

SignalHandler* PlotWidget::signalForItem(QListWidgetItem* item)
{
  return mSignals.value(item);
}

bool PlotWidget::signalIsVisible(SignalHandler* signalHandler)
{
  if (!signalHandler)
  {
    return false;
  }

  return (this->itemForSignal(signalHandler)->checkState() == Qt::Checked);
}

void PlotWidget::setSignalVisibility(SignalHandler* signalHandler, bool visible)
{
  QListWidgetItem* item = this->itemForSignal(signalHandler);
  if (item)
  {
    item->setCheckState(visible ? Qt::Checked : Qt::Unchecked);
  }
}

void PlotWidget::start()
{
  d_plot->start();
}

void PlotWidget::stop()
{
  d_plot->stop();
}

void PlotWidget::clearHistory()
{
  foreach (SignalHandler* handler, this->signalHandlers())
  {
    handler->signalData()->clear();
  }

  d_plot->replot();
}

void PlotWidget::setBackgroundColor(QString color)
{
  d_plot->setBackgroundColor(color);
}

void PlotWidget::setPointSize(double pointSize)
{
  d_plot->setPointSize(pointSize);
}

void PlotWidget::setCurveStyle(QwtPlotCurve::CurveStyle style)
{
  d_plot->setCurveStyle(style);
}

void PlotWidget::setAlignMode(QString mode)
{
  if (mode != "center" && mode != "right")
  {
    printf("unsupported align mode: %s\n", qPrintable(mode));
    return;
  }

  d_plot->setAlignMode(mode == "center" ? Plot::CENTER : Plot::RIGHT);
}

void PlotWidget::addSignal(const QMap<QString, QVariant>& signalSettings)
{
  SignalDescription desc;
  desc.mChannel = signalSettings.value("channel").toString();
  desc.mMessageType = signalSettings.value("messageType").toString();
  desc.mFieldName = signalSettings.value("fieldName").toString();
  desc.mArrayKeys = signalSettings.value("arrayKeys").toStringList();

  QList<QVariant> color = signalSettings.value("color").toList();
  if (color.size() == 3)
  {
    desc.mColor = QColor::fromRgb(color[0].toInt(), color[1].toInt(), color[2].toInt());
  }

  bool visible = signalSettings.value("visible", true).toBool();

  SignalHandler* signalHandler = SignalHandlerFactory::instance().createHandler(&desc);

  if (signalHandler)
  {
    //printf("adding signal: %s\n", qPrintable(signalHandler->description()));
  }
  else
  {
    printf("failed to create signal from signal settings.\n");
  }

  this->addSignal(signalHandler);
  this->setSignalVisibility(signalHandler, visible);
}

Q_DECLARE_METATYPE(SignalHandler*);

void PlotWidget::addSignal(SignalHandler* signalHandler)
{
  if (!signalHandler)
  {
    return;
  }

  QColor color = signalHandler->signalDescription()->mColor;
  if (!color.isValid())
  {
    int signalColorIndex = mSignals.size() % mColors.size();
    color = mColors[signalColorIndex];
    signalHandler->signalDescription()->mColor = color;
  }

  QString signalDescription = QString("%2 [%1]").arg(signalHandler->channel()).arg(signalHandler->description().split(".").back());
  QListWidgetItem* signalItem = new QListWidgetItem(signalDescription);
  signalItem->setToolTip(signalDescription);
  mSignalListWidget->addItem(signalItem);
  mSignals[signalItem] = signalHandler;

  mSubscribers->addSignalHandler(signalHandler);

  d_plot->addSignal(signalHandler->signalData(), color);

  QPixmap pixmap(24, 24);
  pixmap.fill(color);
  signalItem->setIcon(QIcon(pixmap));

  signalItem->setData(Qt::UserRole, qVariantFromValue(signalHandler));
  signalItem->setData(Qt::CheckStateRole, Qt::Checked);
}

void PlotWidget::setTimeWindow(double timeWindow)
{
  mTimeWindowSpin->setValue(timeWindow);
}

void PlotWidget::loadSettings(const QMap<QString, QVariant>& plotSettings)
{
  QList<QVariant> signalList = plotSettings.value("signals").toList();
  foreach (const QVariant& signalVariant, signalList)
  {
    this->addSignal(signalVariant.toMap());
  }

  double timeWindow = plotSettings.value("timeWindow", QVariant(10.0)).toDouble();
  double ymin = plotSettings.value("ymin", QVariant(-10.0)).toDouble();
  double ymax = plotSettings.value("ymax", QVariant(10.0)).toDouble();
  d_plot->setAxisScale(QwtPlot::yLeft, ymin, ymax);
  this->setTimeWindow(timeWindow);

  if (plotSettings.value("curveStyle", "dots") == "lines")
  {
    d_plot->setCurveStyle(QwtPlotCurve::Lines);
  }
}

QMap<QString, QVariant> PlotWidget::saveSettings()
{
  QMap<QString, QVariant> settings;

  settings["ymin"] = d_plot->axisInterval(QwtPlot::yLeft).minValue();
  settings["ymax"] = d_plot->axisInterval(QwtPlot::yLeft).maxValue();
  settings["timeWindow"] = d_plot->timeWindow();

  QList<QVariant> signalSettings;
  foreach (SignalHandler* signalHandler, this->signalHandlers())
  {
    signalSettings.append(this->saveSignalSettings(signalHandler));
  }

  settings["signals"] = signalSettings;
  return settings;
}

QMap<QString, QVariant> PlotWidget::saveSignalSettings(SignalHandler* signalHandler)
{
  QMap<QString, QVariant> settings;

  SignalDescription* signalDescription = signalHandler->signalDescription();

  settings["channel"] = signalDescription->mChannel;
  settings["messageType"] = signalDescription->mMessageType;
  settings["fieldName"] = signalDescription->mFieldName;
  settings["arrayKeys"] = QVariant(signalDescription->mArrayKeys);
  settings["visible"] = QVariant(this->itemForSignal(signalHandler)->checkState() == Qt::Checked);

  QList<QVariant> color;
  color << signalDescription->mColor.red() << signalDescription->mColor.green() << signalDescription->mColor.blue();
  settings["color"] = color;

  return settings;
}

<commit_msg>reorder default colors to follow red, green, blue<commit_after>#include "plotwidget.h"
#include "plot.h"
#include "signalhandler.h"
#include "signaldata.h"
#include "setscaledialog.h"
#include "selectsignaldialog.h"
#include "signaldescription.h"
#include "pythonchannelsubscribercollection.h"

#include <qlabel.h>
#include <qlayout.h>
#include <QDoubleSpinBox>
#include <QMenu>
#include <QAction>
#include <QLabel>
#include <QInputDialog>
#include <QDialogButtonBox>
#include <QListWidget>
#include <QTimer>
#include <QPushButton>
#include <QColorDialog>

PlotWidget::PlotWidget(PythonChannelSubscriberCollection* subscribers, QWidget *parent):
    QWidget(parent),
    mSubscribers(subscribers)
{

  d_plot = new Plot(this);

  mColors << Qt::red
          << Qt::green
          << Qt::blue
          << Qt::cyan
          << Qt::magenta
          << Qt::darkYellow
          << QColor(139, 69, 19) // brown
          << Qt::darkCyan
          << Qt::darkGreen
          << Qt::darkMagenta
          << Qt::black;

  mTimeWindowSpin = new QDoubleSpinBox;
  mTimeWindowSpin->setSingleStep(0.1);
  mTimeWindowSpin->setMinimum(0.0);
  mTimeWindowSpin->setMaximum(60*5);

  QDoubleSpinBox* yScaleSpin = new QDoubleSpinBox;
  yScaleSpin->setSingleStep(0.1);

  QVBoxLayout* vLayout1 = new QVBoxLayout();

  //QPushButton* resetYScaleButton = new QPushButton("Reset Y scale");
  //vLayout1->addWidget(resetYScaleButton);

  QWidget* frameWidget = new QWidget;
  QHBoxLayout* frameLayout = new QHBoxLayout(frameWidget);
  frameWidget->setContentsMargins(0, 0, 0, 0);
  frameLayout->addWidget(new QLabel("Time Window [s]:"));
  frameLayout->addWidget(mTimeWindowSpin);
  vLayout1->addWidget(frameWidget);

  mSignalListWidget = new QListWidget(this);
  vLayout1->addWidget(mSignalListWidget);

  mSignalInfoLabel = new QLabel(this);
  vLayout1->addWidget(mSignalInfoLabel);
  vLayout1->addStretch(10);

  QHBoxLayout *layout = new QHBoxLayout(this);
  layout->addWidget(d_plot, 10);
  layout->addLayout(vLayout1);

  mTimeWindowSpin->setValue(d_plot->timeWindow());

  connect(mTimeWindowSpin, SIGNAL(valueChanged(double)),
          d_plot, SLOT(setTimeWindow(double)));

  connect(d_plot, SIGNAL(syncXAxisScale(double, double)),
          this, SIGNAL(syncXAxisScale(double, double)));

  //connect(yScaleSpin, SIGNAL(valueChanged(double)),
  //        d_plot, SLOT(setYScale(double)));
  //yScaleSpin->setValue(10.0);

  this->setContextMenuPolicy(Qt::CustomContextMenu);
  this->connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
      SLOT(onShowContextMenu(const QPoint&)));

  //mSignalListWidget->setDragDropMode(QAbstractItemView::DragDrop);
  //mSignalListWidget->setDragEnabled(true);
  //mSignalListWidget->setDefaultDropAction(Qt::MoveAction);
  mSignalListWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);

  mSignalListWidget->setContextMenuPolicy(Qt::CustomContextMenu);
  this->connect(mSignalListWidget, SIGNAL(customContextMenuRequested(const QPoint&)),
      SLOT(onShowSignalContextMenu(const QPoint&)));

  this->connect(mSignalListWidget, SIGNAL(itemChanged(QListWidgetItem *)), SLOT(onSignalListItemChanged(QListWidgetItem*)));

  QTimer* labelUpdateTimer = new QTimer(this);
  this->connect(labelUpdateTimer, SIGNAL(timeout()), SLOT(updateSignalInfoLabel()));
  labelUpdateTimer->start(100);
}

void PlotWidget::onShowContextMenu(const QPoint& pos)
{

  QPoint globalPos = this->mapToGlobal(pos);
  // for QAbstractScrollArea and derived classes you would use:
  // QPoint globalPos = myWidget->viewport()->mapToGlobal(pos);

  QMenu myMenu;
  myMenu.addAction("Add signal");
  myMenu.addSeparator();
  myMenu.addAction("Reset Y axis scale");
  myMenu.addAction("Set Y axis scale");
  myMenu.addSeparator();
  myMenu.addAction("Remove plot");

  QAction* selectedItem = myMenu.exec(globalPos);
  if (!selectedItem)
  {
    return;
  }

  QString selectedAction = selectedItem->text();

  if (selectedAction == "Remove plot")
  {
    emit this->removePlotRequested(this);
  }
  else if (selectedAction == "Add signal")
  {
    emit this->addSignalRequested(this);
  }
  else if (selectedAction == "Reset Y axis scale")
  {
    this->onResetYAxisScale();
  }
  else if (selectedAction == "Set Y axis scale")
  {

    SetScaleDialog dialog(this);
    QwtInterval axisInterval = d_plot->axisInterval(QwtPlot::yLeft);
    dialog.setUpper(axisInterval.maxValue());
    dialog.setLower(axisInterval.minValue());

    int result = dialog.exec();
    if (result == QDialog::Accepted)
    {
      this->setYAxisScale(dialog.lower(), dialog.upper());
    }
  }
}

QList<SignalHandler*> PlotWidget::signalHandlers()
{
  QList<SignalHandler*> handlers;
  for (int i = 0; i < mSignalListWidget->count(); ++i)
  {
    handlers.append(mSignals[mSignalListWidget->item(i)]);
  }

  return handlers;
}

void PlotWidget::onShowSignalContextMenu(const QPoint& pos)
{

  if (mSignals.empty())
  {
    return;
  }

  QPoint globalPos = mSignalListWidget->mapToGlobal(pos);
  // for QAbstractScrollArea and derived classes you would use:
  // QPoint globalPos = myWidget->viewport()->mapToGlobal(pos);

  QMenu myMenu;
  if (mSignalListWidget->selectedItems().size() == 1)
    {
    myMenu.addAction("Change color");
    myMenu.addSeparator();
    }

  myMenu.addAction("Remove signal");

  QAction* selectedItem = myMenu.exec(globalPos);
  if (!selectedItem)
  {
    return;
  }

  QString selectedAction = selectedItem->text();

  if (selectedAction == "Change color")
  {
    QListWidgetItem* signalItem = mSignalListWidget->currentItem();
    SignalHandler* signalHandler = signalItem->data(Qt::UserRole).value<SignalHandler*>();
    QColor initialColor = signalHandler->signalDescription()->mColor;
    QColor newColor = QColorDialog::getColor(initialColor, this, "Choose signal color");

    if (newColor.isValid())
    {
      signalHandler->signalDescription()->mColor = newColor;
      QPixmap pixmap(24, 24);
      pixmap.fill(newColor);
      signalItem->setIcon(QIcon(pixmap));
      d_plot->setSignalColor(signalHandler->signalData(), newColor);
    }

  }
  else if (selectedAction == "Remove signal")
  {

    QList<QListWidgetItem*> selectedItems = mSignalListWidget->selectedItems();
    foreach (QListWidgetItem*	selectedItem, selectedItems)
    {
      SignalHandler* signalHandler = this->signalForItem(selectedItem);

      mSubscribers->removeSignalHandler(signalHandler);

      d_plot->removeSignal(signalHandler->signalData());
      mSignals.remove(selectedItem);
      this->replot();

      delete selectedItem;
      delete signalHandler;
    }
  }

}

double PlotWidget::timeWindow() const
{
  return this->d_plot->timeWindow();
}

void PlotWidget::updateSignalInfoLabel()
{
  mSignalInfoLabel->setText(QString());

  QListWidgetItem* selectedItem = mSignalListWidget->currentItem();
  if (!selectedItem)
  {
    return;
  }

  SignalHandler* signalHandler = selectedItem->data(Qt::UserRole).value<SignalHandler*>();
  SignalData* signalData = signalHandler->signalData();

  QString signalValue = "No data";
  int numberOfValues = signalData->size();
  if (numberOfValues)
  {
    signalValue = QString::number(signalData->value(numberOfValues-1).y(), 'g', 6);
  }

  QString signalInfoText = QString("Freq:  %1  Val: %2").arg(QString::number(signalData->messageFrequency(), 'f', 1)).arg(signalValue);

  mSignalInfoLabel->setText(signalInfoText);
}

void PlotWidget::setEndTime(double endTime)
{
  d_plot->setEndTime(endTime);
}

void PlotWidget::setXAxisScale(double x0, double x1)
{
  d_plot->setAxisScale(QwtPlot::xBottom, x0, x1);
}

void PlotWidget::replot()
{
  d_plot->replot();
}

void PlotWidget::onResetYAxisScale()
{
  QRectF area;
  foreach (SignalHandler* signalHandler, mSignals.values())
  {
    if (this->signalIsVisible(signalHandler))
    {
      QRectF signalBounds = signalHandler->signalData()->computeBounds();

      if (!area.isValid())
      {
        area = signalBounds;
      }
      else
      {
        area = area.united(signalBounds);
      }
    }
  }

  if (!area.isValid())
  {
    area = QRectF(-1, -1, 2, 2);
  }

  this->setYAxisScale(area.top(), area.bottom());
}

void PlotWidget::setYAxisScale(double lower, double upper)
{
  d_plot->setAxisScale(QwtPlot::yLeft, lower, upper);
  this->replot();
}

void PlotWidget::onSignalListItemChanged(QListWidgetItem* item)
{
  SignalHandler* signalHandler = this->signalForItem(item);
  Qt::CheckState checkState = item->checkState();

  if (!item->isSelected())
  {
    mSignalListWidget->clearSelection();
    item->setSelected(true);
  }

  QList<QListWidgetItem*> selectedItems = mSignalListWidget->selectedItems();
  foreach (QListWidgetItem*	selectedItem, selectedItems)
  {
    SignalHandler* signalHandler = this->signalForItem(selectedItem);
    selectedItem->setCheckState(checkState);
    d_plot->setSignalVisible(signalHandler->signalData(), checkState == Qt::Checked);
  }
}

QListWidgetItem* PlotWidget::itemForSignal(SignalHandler* signalHandler)
{
  return mSignals.key(signalHandler);
}

SignalHandler* PlotWidget::signalForItem(QListWidgetItem* item)
{
  return mSignals.value(item);
}

bool PlotWidget::signalIsVisible(SignalHandler* signalHandler)
{
  if (!signalHandler)
  {
    return false;
  }

  return (this->itemForSignal(signalHandler)->checkState() == Qt::Checked);
}

void PlotWidget::setSignalVisibility(SignalHandler* signalHandler, bool visible)
{
  QListWidgetItem* item = this->itemForSignal(signalHandler);
  if (item)
  {
    item->setCheckState(visible ? Qt::Checked : Qt::Unchecked);
  }
}

void PlotWidget::start()
{
  d_plot->start();
}

void PlotWidget::stop()
{
  d_plot->stop();
}

void PlotWidget::clearHistory()
{
  foreach (SignalHandler* handler, this->signalHandlers())
  {
    handler->signalData()->clear();
  }

  d_plot->replot();
}

void PlotWidget::setBackgroundColor(QString color)
{
  d_plot->setBackgroundColor(color);
}

void PlotWidget::setPointSize(double pointSize)
{
  d_plot->setPointSize(pointSize);
}

void PlotWidget::setCurveStyle(QwtPlotCurve::CurveStyle style)
{
  d_plot->setCurveStyle(style);
}

void PlotWidget::setAlignMode(QString mode)
{
  if (mode != "center" && mode != "right")
  {
    printf("unsupported align mode: %s\n", qPrintable(mode));
    return;
  }

  d_plot->setAlignMode(mode == "center" ? Plot::CENTER : Plot::RIGHT);
}

void PlotWidget::addSignal(const QMap<QString, QVariant>& signalSettings)
{
  SignalDescription desc;
  desc.mChannel = signalSettings.value("channel").toString();
  desc.mMessageType = signalSettings.value("messageType").toString();
  desc.mFieldName = signalSettings.value("fieldName").toString();
  desc.mArrayKeys = signalSettings.value("arrayKeys").toStringList();

  QList<QVariant> color = signalSettings.value("color").toList();
  if (color.size() == 3)
  {
    desc.mColor = QColor::fromRgb(color[0].toInt(), color[1].toInt(), color[2].toInt());
  }

  bool visible = signalSettings.value("visible", true).toBool();

  SignalHandler* signalHandler = SignalHandlerFactory::instance().createHandler(&desc);

  if (signalHandler)
  {
    //printf("adding signal: %s\n", qPrintable(signalHandler->description()));
  }
  else
  {
    printf("failed to create signal from signal settings.\n");
  }

  this->addSignal(signalHandler);
  this->setSignalVisibility(signalHandler, visible);
}

Q_DECLARE_METATYPE(SignalHandler*);

void PlotWidget::addSignal(SignalHandler* signalHandler)
{
  if (!signalHandler)
  {
    return;
  }

  QColor color = signalHandler->signalDescription()->mColor;
  if (!color.isValid())
  {
    int signalColorIndex = mSignals.size() % mColors.size();
    color = mColors[signalColorIndex];
    signalHandler->signalDescription()->mColor = color;
  }

  QString signalDescription = QString("%2 [%1]").arg(signalHandler->channel()).arg(signalHandler->description().split(".").back());
  QListWidgetItem* signalItem = new QListWidgetItem(signalDescription);
  signalItem->setToolTip(signalDescription);
  mSignalListWidget->addItem(signalItem);
  mSignals[signalItem] = signalHandler;

  mSubscribers->addSignalHandler(signalHandler);

  d_plot->addSignal(signalHandler->signalData(), color);

  QPixmap pixmap(24, 24);
  pixmap.fill(color);
  signalItem->setIcon(QIcon(pixmap));

  signalItem->setData(Qt::UserRole, qVariantFromValue(signalHandler));
  signalItem->setData(Qt::CheckStateRole, Qt::Checked);
}

void PlotWidget::setTimeWindow(double timeWindow)
{
  mTimeWindowSpin->setValue(timeWindow);
}

void PlotWidget::loadSettings(const QMap<QString, QVariant>& plotSettings)
{
  QList<QVariant> signalList = plotSettings.value("signals").toList();
  foreach (const QVariant& signalVariant, signalList)
  {
    this->addSignal(signalVariant.toMap());
  }

  double timeWindow = plotSettings.value("timeWindow", QVariant(10.0)).toDouble();
  double ymin = plotSettings.value("ymin", QVariant(-10.0)).toDouble();
  double ymax = plotSettings.value("ymax", QVariant(10.0)).toDouble();
  d_plot->setAxisScale(QwtPlot::yLeft, ymin, ymax);
  this->setTimeWindow(timeWindow);

  if (plotSettings.value("curveStyle", "dots") == "lines")
  {
    d_plot->setCurveStyle(QwtPlotCurve::Lines);
  }
}

QMap<QString, QVariant> PlotWidget::saveSettings()
{
  QMap<QString, QVariant> settings;

  settings["ymin"] = d_plot->axisInterval(QwtPlot::yLeft).minValue();
  settings["ymax"] = d_plot->axisInterval(QwtPlot::yLeft).maxValue();
  settings["timeWindow"] = d_plot->timeWindow();

  QList<QVariant> signalSettings;
  foreach (SignalHandler* signalHandler, this->signalHandlers())
  {
    signalSettings.append(this->saveSignalSettings(signalHandler));
  }

  settings["signals"] = signalSettings;
  return settings;
}

QMap<QString, QVariant> PlotWidget::saveSignalSettings(SignalHandler* signalHandler)
{
  QMap<QString, QVariant> settings;

  SignalDescription* signalDescription = signalHandler->signalDescription();

  settings["channel"] = signalDescription->mChannel;
  settings["messageType"] = signalDescription->mMessageType;
  settings["fieldName"] = signalDescription->mFieldName;
  settings["arrayKeys"] = QVariant(signalDescription->mArrayKeys);
  settings["visible"] = QVariant(this->itemForSignal(signalHandler)->checkState() == Qt::Checked);

  QList<QVariant> color;
  color << signalDescription->mColor.red() << signalDescription->mColor.green() << signalDescription->mColor.blue();
  settings["color"] = color;

  return settings;
}

<|endoftext|>


<commit_before>//
// Copyright (c) 2014 CNRS
// Authors: Florent Lamiraux
//
// This file is part of hpp-core
// hpp-core is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// hpp-core is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-core  If not, see
// <http://www.gnu.org/licenses/>.

#include <boost/tuple/tuple.hpp>
#include <hpp/util/debug.hh>
#include <hpp/model/configuration.hh>
#include <hpp/model/device.hh>
#include <hpp/core/config-projector.hh>
#include <hpp/core/bi-rrt-planner.hh>
#include <hpp/core/node.hh>
#include <hpp/core/edge.hh>
#include <hpp/core/path.hh>
#include <hpp/core/path-validation.hh>
#include <hpp/core/problem.hh>
#include <hpp/core/roadmap.hh>
#include <hpp/core/steering-method.hh>
#include <hpp/core/basic-configuration-shooter.hh>

namespace hpp {
  namespace core {
    using model::displayConfig;

    BiRRTPlannerPtr_t BiRRTPlanner::createWithRoadmap
    (const Problem& problem, const RoadmapPtr_t& roadmap)
    {
      roadmap->clear();
      BiRRTPlanner* ptr = new BiRRTPlanner (problem, roadmap);
      return BiRRTPlannerPtr_t (ptr);
    }

    BiRRTPlannerPtr_t BiRRTPlanner::create (const Problem& problem)
    {
      BiRRTPlanner* ptr = new BiRRTPlanner (problem);
      return BiRRTPlannerPtr_t (ptr);
    }

    BiRRTPlanner::BiRRTPlanner (const Problem& problem):
      PathPlanner (problem),
      configurationShooter_ (problem.configurationShooter()),
      qProj_ (problem.robot ()->configSize ())
    {
    }

    BiRRTPlanner::BiRRTPlanner (const Problem& problem, const RoadmapPtr_t& roadmap):
      PathPlanner (problem, roadmap),
      configurationShooter_ (problem.configurationShooter()),
      qProj_ (problem.robot ()->configSize ())
    {
    }

    void BiRRTPlanner::init (const BiRRTPlannerWkPtr_t& weak)
    {
      PathPlanner::init (weak);
      weakPtr_ = weak;
    }

    namespace
    {
        PathPtr_t extendInternal (const SteeringMethodPtr_t& sm, Configuration_t& qProj_, const NodePtr_t& near,
                        const ConfigurationPtr_t& target, bool reverse=false)
        {
            const ConstraintSetPtr_t& constraints (sm->constraints ());
            if (constraints)
            {
                ConfigProjectorPtr_t configProjector (constraints->configProjector ());
                if (configProjector)
                {
                    configProjector->projectOnKernel (*(near->configuration ()), *target,
                            qProj_);
                }
                else
                {
                    qProj_ = *target;
                }
                if (constraints->apply (qProj_))
                {
                    return reverse ? (*sm) (qProj_, *(near->configuration ())) : (*sm) (*(near->configuration ()), qProj_);
                }
                else
                {
                    return PathPtr_t ();
                }
            }
            return reverse ? (*sm) (*target, *(near->configuration ())) : (*sm) (*(near->configuration ()), *target);
        }
    }

    /// One step of extension.
    void BiRRTPlanner::startSolve()
    {
        PathPlanner::startSolve();
        startComponent_ = roadmap()->initNode()->connectedComponent();
        for(Nodes_t::const_iterator cit = roadmap()->goalNodes().begin();
            cit != roadmap()->goalNodes().end(); ++cit)
        {
            endComponents_.push_back((*cit)->connectedComponent());
        }
    }

    void BiRRTPlanner::oneStep ()
    {
        PathPtr_t validPath, path;
        PathValidationPtr_t pathValidation (problem ().pathValidation ());
        value_type distance;
        NodePtr_t near, reachedNodeFromStart;
        bool pathValidFromStart(false);
        ConfigurationPtr_t q_new;
        // first try to connect to start component
        ConfigurationPtr_t q_rand = configurationShooter_->shoot ();
        near = roadmap()->nearestNode (q_rand, startComponent_, distance);
        path = extendInternal (problem().steeringMethod(), qProj_, near, q_rand);
        if (path)
        {
            PathValidationReportPtr_t report;
            pathValidFromStart = pathValidation->validate (path, false, validPath, report);
            // Insert new path to q_near in roadmap
            value_type t_final = validPath->timeRange ().second;
            if (t_final != path->timeRange ().first)
            {
                q_new = ConfigurationPtr_t (new Configuration_t(validPath->end ()));
                reachedNodeFromStart = roadmap()->addNodeAndEdges(near, q_new, validPath);
            }
        }

        // now try to connect to end components
        for (std::vector<ConnectedComponentPtr_t>::const_iterator itcc =
           endComponents_.begin ();
         itcc != endComponents_.end (); ++itcc)
        {
            near = roadmap()->nearestNode (q_rand, *itcc, distance);
            path = extendInternal (problem().steeringMethod(), qProj_, near, q_rand, true);
            if (path)
            {
                PathValidationReportPtr_t report;
                if(pathValidation->validate (path, true, validPath, report) && pathValidFromStart)
                {
                    // we won, a path is found
                    roadmap()->addEdge(reachedNodeFromStart, near, validPath);
                    return;
                }
                else
                {
                    value_type t_final = validPath->timeRange ().second;
                    if (t_final != path->timeRange ().first)
                    {
                        ConfigurationPtr_t q_newEnd = ConfigurationPtr_t (new Configuration_t(validPath->initial()));
                        NodePtr_t newNode = roadmap()->addNode (q_newEnd);
                        roadmap()->addEdge(newNode, near, validPath);
                        // now try to connect both nodes
                        path = (*(problem().steeringMethod())) (*q_new, *q_newEnd);
                        if(path && pathValidation->validate (path, false, validPath, report))
                        {
                            roadmap()->addEdge (reachedNodeFromStart, newNode, path);
                            return;
                        }
                    }
                }
            }
        }
    }
  } // namespace core
} // namespace hpp
<commit_msg>step fails if no path found for starting connected component in rrt-connect<commit_after>//
// Copyright (c) 2014 CNRS
// Authors: Florent Lamiraux
//
// This file is part of hpp-core
// hpp-core is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// hpp-core is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-core  If not, see
// <http://www.gnu.org/licenses/>.

#include <boost/tuple/tuple.hpp>
#include <hpp/util/debug.hh>
#include <hpp/model/configuration.hh>
#include <hpp/model/device.hh>
#include <hpp/core/config-projector.hh>
#include <hpp/core/bi-rrt-planner.hh>
#include <hpp/core/node.hh>
#include <hpp/core/edge.hh>
#include <hpp/core/path.hh>
#include <hpp/core/path-validation.hh>
#include <hpp/core/problem.hh>
#include <hpp/core/roadmap.hh>
#include <hpp/core/steering-method.hh>
#include <hpp/core/basic-configuration-shooter.hh>

namespace hpp {
  namespace core {
    using model::displayConfig;

    BiRRTPlannerPtr_t BiRRTPlanner::createWithRoadmap
    (const Problem& problem, const RoadmapPtr_t& roadmap)
    {
      roadmap->clear();
      BiRRTPlanner* ptr = new BiRRTPlanner (problem, roadmap);
      return BiRRTPlannerPtr_t (ptr);
    }

    BiRRTPlannerPtr_t BiRRTPlanner::create (const Problem& problem)
    {
      BiRRTPlanner* ptr = new BiRRTPlanner (problem);
      return BiRRTPlannerPtr_t (ptr);
    }

    BiRRTPlanner::BiRRTPlanner (const Problem& problem):
      PathPlanner (problem),
      configurationShooter_ (problem.configurationShooter()),
      qProj_ (problem.robot ()->configSize ())
    {
    }

    BiRRTPlanner::BiRRTPlanner (const Problem& problem, const RoadmapPtr_t& roadmap):
      PathPlanner (problem, roadmap),
      configurationShooter_ (problem.configurationShooter()),
      qProj_ (problem.robot ()->configSize ())
    {
    }

    void BiRRTPlanner::init (const BiRRTPlannerWkPtr_t& weak)
    {
      PathPlanner::init (weak);
      weakPtr_ = weak;
    }

    namespace
    {
        PathPtr_t extendInternal (const SteeringMethodPtr_t& sm, Configuration_t& qProj_, const NodePtr_t& near,
                        const ConfigurationPtr_t& target, bool reverse=false)
        {
            const ConstraintSetPtr_t& constraints (sm->constraints ());
            if (constraints)
            {
                ConfigProjectorPtr_t configProjector (constraints->configProjector ());
                if (configProjector)
                {
                    configProjector->projectOnKernel (*(near->configuration ()), *target,
                            qProj_);
                }
                else
                {
                    qProj_ = *target;
                }
                if (constraints->apply (qProj_))
                {
                    return reverse ? (*sm) (qProj_, *(near->configuration ())) : (*sm) (*(near->configuration ()), qProj_);
                }
                else
                {
                    return PathPtr_t ();
                }
            }
            return reverse ? (*sm) (*target, *(near->configuration ())) : (*sm) (*(near->configuration ()), *target);
        }
    }

    /// One step of extension.
    void BiRRTPlanner::startSolve()
    {
        PathPlanner::startSolve();
        startComponent_ = roadmap()->initNode()->connectedComponent();
        for(Nodes_t::const_iterator cit = roadmap()->goalNodes().begin();
            cit != roadmap()->goalNodes().end(); ++cit)
        {
            endComponents_.push_back((*cit)->connectedComponent());
        }
    }

    void BiRRTPlanner::oneStep ()
    {
        PathPtr_t validPath, path;
        PathValidationPtr_t pathValidation (problem ().pathValidation ());
        value_type distance;
        NodePtr_t near, reachedNodeFromStart;
        bool pathValidFromStart(false);
        ConfigurationPtr_t q_new;
        // first try to connect to start component
        ConfigurationPtr_t q_rand = configurationShooter_->shoot ();
        near = roadmap()->nearestNode (q_rand, startComponent_, distance);
        path = extendInternal (problem().steeringMethod(), qProj_, near, q_rand);
        if (path)
        {
            PathValidationReportPtr_t report;
            pathValidFromStart = pathValidation->validate (path, false, validPath, report);
            // Insert new path to q_near in roadmap
            value_type t_final = validPath->timeRange ().second;
            if (t_final != path->timeRange ().first)
            {
                q_new = ConfigurationPtr_t (new Configuration_t(validPath->end ()));
                reachedNodeFromStart = roadmap()->addNodeAndEdges(near, q_new, validPath);
            }
            else return;
        }
        else return;

        // now try to connect to end components
        for (std::vector<ConnectedComponentPtr_t>::const_iterator itcc =
           endComponents_.begin ();
         itcc != endComponents_.end (); ++itcc)
        {
            near = roadmap()->nearestNode (q_rand, *itcc, distance);
            path = extendInternal (problem().steeringMethod(), qProj_, near, q_rand, true);
            if (path)
            {
                PathValidationReportPtr_t report;
                if(pathValidation->validate (path, true, validPath, report) && pathValidFromStart)
                {
                    // we won, a path is found
                    roadmap()->addEdge(reachedNodeFromStart, near, validPath);
                    return;
                }
                else
                {
                    value_type t_final = validPath->timeRange ().second;
                    if (t_final != path->timeRange ().first)
                    {
                        ConfigurationPtr_t q_newEnd = ConfigurationPtr_t (new Configuration_t(validPath->initial()));
                        NodePtr_t newNode = roadmap()->addNode (q_newEnd);
                        roadmap()->addEdge(newNode, near, validPath);
                        // now try to connect both nodes
                        path = (*(problem().steeringMethod())) (*q_new, *q_newEnd);
                        if(path && pathValidation->validate (path, false, validPath, report))
                        {
                            roadmap()->addEdge (reachedNodeFromStart, newNode, path);
                            return;
                        }
                    }
                }
            }
        }
    }
  } // namespace core
} // namespace hpp
<|endoftext|>


<commit_before>#include <iostream>
#include <time.h>
#include <ncurses.h>

#include "map/Level.h"
#include "map/filters/FloodFillFilter.h"
#include "map/filters/DrunkardsWalkFilter.h"
#include "map/filters/BSPFilter.h"

int main()
{
	initscr();
	noecho();

	//std::cout << "Default Level:" << std::endl;
	printw("Default Level:");
	Level walls(40, 80);
	//walls.printLevel();
	for(uint32_t x = 0; x < walls.getWidth(); x++)
	{
		for(uint32_t y = 0; y < walls.getHeight(); y++)
		{
			mvaddch(x+1, y, walls[x][y].getDisplay());
		}
	}
	std::cout << std::endl << std::endl;
	refresh();
	getch();
	endwin();

	std::cout << "Flood-filled room:" << std::endl;
	Level room(40, 80);
	FloodFillFilter fill;
	fill.setStart(1,1);
	fill.setEnd(room.getWidth()-2, room.getHeight()-2);
	fill.setTile(FloorTile);
	fill.apply(room);
	room.printLevel();
	std::cout << std::endl << std::endl;

	std::cout << "A drunkard's walk cave:" << std::endl;
	Level cave(40, 80);
	DrunkardsWalkFilter walk;
	walk.setSeed(time(NULL));
	walk.apply(cave);
	cave.printLevel();
	std::cout << std::endl << std::endl;

	std::cout << "A BSP dungeon:" << std::endl;
	Level dungeon(40, 80);
	BSPFilter bsp;
	bsp.setSeed(time(NULL));
	bsp.apply(dungeon);
	dungeon.printLevel();
	std::cout << std::endl << std::endl;

	//std::cout << "DungeonBSPGenerator:" << std::endl;
	//DungeonBSPGenerator dungeon;
	//dungeon.setSeed(time(NULL));
	//Level ldungeon(40, 80);
	//ldungeon.printLevel();
	//std::cout << std::endl << std::endl;

	return 0;
}
<commit_msg>TestLevel now uses the new Screen object.<commit_after>#include <iostream>
#include <time.h>
#include <ncurses.h>

#include "display/Screen.h"
#include "map/Level.h"
#include "map/filters/FloodFillFilter.h"
#include "map/filters/DrunkardsWalkFilter.h"
#include "map/filters/BSPFilter.h"

int main()
{
	Screen screen;

	//std::cout << "Default Level:" << std::endl;
	printw("Default Level:");
	Level walls(40, 80);
	//walls.printLevel();
	for(uint32_t x = 0; x < walls.getWidth(); x++)
	{
		for(uint32_t y = 0; y < walls.getHeight(); y++)
		{
			mvaddch(x+1, y, walls[x][y].getDisplay());
		}
	}
	std::cout << std::endl << std::endl;
	refresh();
	getch();

	std::cout << "Flood-filled room:" << std::endl;
	Level room(40, 80);
	FloodFillFilter fill;
	fill.setStart(1,1);
	fill.setEnd(room.getWidth()-2, room.getHeight()-2);
	fill.setTile(FloorTile);
	fill.apply(room);
	room.printLevel();
	std::cout << std::endl << std::endl;

	std::cout << "A drunkard's walk cave:" << std::endl;
	Level cave(40, 80);
	DrunkardsWalkFilter walk;
	walk.setSeed(time(NULL));
	walk.apply(cave);
	cave.printLevel();
	std::cout << std::endl << std::endl;

	std::cout << "A BSP dungeon:" << std::endl;
	Level dungeon(40, 80);
	BSPFilter bsp;
	bsp.setSeed(time(NULL));
	bsp.apply(dungeon);
	dungeon.printLevel();
	std::cout << std::endl << std::endl;

	//std::cout << "DungeonBSPGenerator:" << std::endl;
	//DungeonBSPGenerator dungeon;
	//dungeon.setSeed(time(NULL));
	//Level ldungeon(40, 80);
	//ldungeon.printLevel();
	//std::cout << std::endl << std::endl;

	return 0;
}
<|endoftext|>


<commit_before>#include "common/LinkParser.hpp"

#include <QFile>
#include <QRegularExpression>
#include <QString>
#include <QTextStream>

namespace chatterino {

LinkParser::LinkParser(const QString &unparsedString)
{
    static QRegularExpression linkRegex = [] {
        QFile tldFile(":/tlds.txt");
        tldFile.open(QFile::ReadOnly);

        QTextStream t1(&tldFile);
        t1.setCodec("UTF-8");

        // Read the TLDs in and replace the newlines with pipes
        QString tldData = t1.readAll().replace("\n", "|");

        const QString urlRegExp =
            "^"
            // protocol identifier
            "(?:(?:https?|ftps?)://)?"
            // user:pass authentication
            "(?:\\S+(?::\\S*)?@)?"
            "(?:"
            // IP address dotted notation octets
            // excludes loopback network 0.0.0.0
            // excludes reserved space >= 224.0.0.0
            // excludes network & broacast addresses
            // (first & last IP address of each class)
            "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])"
            "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}"
            "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))"
            "|"
            // host name
            "(?:(?:[_a-z\\x{00a1}-\\x{ffff}0-9]-*)*[a-z\\x{00a1}-\\x{ffff}0-9]+)"
            // domain name
            "(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}0-9]-*)*[a-z\\x{00a1}-\\x{ffff}0-9]+)*"
            // TLD identifier
            //"(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}]{2,}))"
            "(?:[\\.](?:" +
            tldData +
            "))"
            "\\.?"
            ")"
            // port number
            "(?::\\d{2,5})?"
            // resource path
            "(?:[/?#]\\S*)?"
            "$";

        return QRegularExpression(urlRegExp, QRegularExpression::CaseInsensitiveOption);
    }();

    this->match_ = linkRegex.match(unparsedString);
}

}  // namespace chatterino
<commit_msg>fix link parser<commit_after>#include "common/LinkParser.hpp"

#include <QFile>
#include <QRegularExpression>
#include <QString>
#include <QTextStream>

namespace chatterino {

LinkParser::LinkParser(const QString &unparsedString)
{
    static QRegularExpression linkRegex = [] {
        static QRegularExpression newLineRegex("\r?\n");
        QFile tldFile(":/tlds.txt");
        tldFile.open(QFile::ReadOnly);

        QTextStream t1(&tldFile);
        t1.setCodec("UTF-8");

        // Read the TLDs in and replace the newlines with pipes
        QString tldData = t1.readAll().replace(newLineRegex, "|");

        const QString urlRegExp =
            "^"
            // protocol identifier
            "(?:(?:https?|ftps?)://)?"
            // user:pass authentication
            "(?:\\S+(?::\\S*)?@)?"
            "(?:"
            // IP address dotted notation octets
            // excludes loopback network 0.0.0.0
            // excludes reserved space >= 224.0.0.0
            // excludes network & broacast addresses
            // (first & last IP address of each class)
            "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])"
            "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}"
            "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))"
            "|"
            // host name
            "(?:(?:[_a-z\\x{00a1}-\\x{ffff}0-9]-*)*[a-z\\x{00a1}-\\x{ffff}0-9]+)"
            // domain name
            "(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}0-9]-*)*[a-z\\x{00a1}-\\x{ffff}0-9]+)*"
            // TLD identifier
            //"(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}]{2,}))"
            "(?:[\\.](?:" +
            tldData +
            "))"
            "\\.?"
            ")"
            // port number
            "(?::\\d{2,5})?"
            // resource path
            "(?:[/?#]\\S*)?"
            "$";

        return QRegularExpression(urlRegExp, QRegularExpression::CaseInsensitiveOption);
    }();

    this->match_ = linkRegex.match(unparsedString);
}

}  // namespace chatterino
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named LICENSE that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "ParseColor.h"

#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <string>
#include <stdio.h>

typedef struct {
  const char* name;
  const float value[4];
} ColorSet;

static const ColorSet colorSets[] = {
  { "red",	{1.0f, 0.0f, 0.0f, 1.0f}},
  { "blue",	{0.0f, 0.0f, 1.0f, 1.0f}},
  { "green",	{0.0f, 1.0f, 0.0f, 1.0f}},
  { "yellow",	{1.0f, 1.0f, 0.0f, 1.0f}},
  { "purple",	{1.0f, 0.0f, 1.0f, 1.0f}},
  { "purple",	{0.0f, 1.0f, 1.0f, 1.0f}},
  { "black",	{0.0f, 0.0f, 0.0f, 1.0f}},
  { "white",	{1.0f, 1.0f, 1.0f, 1.0f}},
  { "grey",	{0.5f, 0.5f, 0.5f, 1.0f}},
};
static const int colorCount = sizeof(colorSets) / sizeof(ColorSet);

bool parseColorStream(std::istream& input, float color[4])
{
  std::string line;
  std::getline(input, line);
  input.putback('\n');

  return parseColorString(line.c_str(), color);
}

bool parseColorString(const char* str, float color[4])
{
  int i;
  const float white[4] = { 1.0f, 1.0f, 1.0f, 1.0f };

  // set to opaque white
  memcpy (color, white, sizeof(float[4]));

  // strip leading space
  while ((*str != '\0') && isspace(*str)) {
    str++;
  }

  // no string
  if (*str == '\0') {
    return false;
  }

  // #FF2343A9 format
  if (*str == '#') {
    // FIXME - complete this ?
    return false;
  }

  // numeric format (either 3 or 4 floating point values)
  else if (((*str >= '0') && (*str <= '9'))
           || (*str == '.')
           || (*str == '+')
           || (*str == '-')) {
    int count;
    float tmp[4];
    count = sscanf(str, "%f %f %f %f", &tmp[0], &tmp[1], &tmp[2], &tmp[3]);
    if (count < 3) {
      return false;
    } else {
      memcpy (color, tmp, count * sizeof(float));
      return true;
    }
  }

  // text string format  ("red 0.2" format is accepted for alpha values)
  else {
    for (i = 0; i < colorCount; i++) {
      int len = strlen (colorSets[i].name);
      const char* end = str + len;
      if ((strncasecmp (colorSets[i].name, str, len) == 0)
          && ((*end == '\0') || isspace(*end))) {
        memcpy (color, colorSets[i].value, sizeof(float[3]));

        int count;
        float alpha;
        count = sscanf (str + len, "%f", &alpha);
        if (count > 0) {
          color[3] = alpha;
        }

        return true;
      }
    }
  }

  return false;
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>compile on vc!<commit_after>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named LICENSE that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "common.h"

#include "ParseColor.h"

#include <ctype.h>
#include <string.h>
#include <string>
#include <stdio.h>

typedef struct {
  const char* name;
  const float value[4];
} ColorSet;

static const ColorSet colorSets[] = {
  { "red",	{1.0f, 0.0f, 0.0f, 1.0f}},
  { "blue",	{0.0f, 0.0f, 1.0f, 1.0f}},
  { "green",	{0.0f, 1.0f, 0.0f, 1.0f}},
  { "yellow",	{1.0f, 1.0f, 0.0f, 1.0f}},
  { "purple",	{1.0f, 0.0f, 1.0f, 1.0f}},
  { "purple",	{0.0f, 1.0f, 1.0f, 1.0f}},
  { "black",	{0.0f, 0.0f, 0.0f, 1.0f}},
  { "white",	{1.0f, 1.0f, 1.0f, 1.0f}},
  { "grey",	{0.5f, 0.5f, 0.5f, 1.0f}},
};
static const int colorCount = sizeof(colorSets) / sizeof(ColorSet);

bool parseColorStream(std::istream& input, float color[4])
{
  std::string line;
  std::getline(input, line);
  input.putback('\n');

  return parseColorString(line.c_str(), color);
}

bool parseColorString(const char* str, float color[4])
{
  int i;
  const float white[4] = { 1.0f, 1.0f, 1.0f, 1.0f };

  // set to opaque white
  memcpy (color, white, sizeof(float[4]));

  // strip leading space
  while ((*str != '\0') && isspace(*str)) {
    str++;
  }

  // no string
  if (*str == '\0') {
    return false;
  }

  // #FF2343A9 format
  if (*str == '#') {
    // FIXME - complete this ?
    return false;
  }

  // numeric format (either 3 or 4 floating point values)
  else if (((*str >= '0') && (*str <= '9'))
           || (*str == '.')
           || (*str == '+')
           || (*str == '-')) {
    int count;
    float tmp[4];
    count = sscanf(str, "%f %f %f %f", &tmp[0], &tmp[1], &tmp[2], &tmp[3]);
    if (count < 3) {
      return false;
    } else {
      memcpy (color, tmp, count * sizeof(float));
      return true;
    }
  }

  // text string format  ("red 0.2" format is accepted for alpha values)
  else {
    for (i = 0; i < colorCount; i++) {
      int len = strlen (colorSets[i].name);
      const char* end = str + len;
      if ((strncasecmp (colorSets[i].name, str, len) == 0)
          && ((*end == '\0') || isspace(*end))) {
        memcpy (color, colorSets[i].value, sizeof(float[3]));

        int count;
        float alpha;
        count = sscanf (str + len, "%f", &alpha);
        if (count > 0) {
          color[3] = alpha;
        }

        return true;
      }
    }
  }

  return false;
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// materialization_executor.cpp
//
// Identification: src/backend/executor/materialization_executor.cpp
//
// Copyright (c) 2015, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "backend/executor/materialization_executor.h"

#include <cassert>
#include <memory>
#include <utility>

#include "backend/planner/materialization_plan.h"
#include "backend/executor/logical_tile.h"
#include "backend/executor/logical_tile_factory.h"
#include "backend/storage/tile.h"
#include "backend/storage/data_table.h"

namespace peloton {
namespace executor {

// Row-oriented materialization
void MaterializeRowAtAtATime(LogicalTile *source_tile,
                             const std::unordered_map<oid_t, oid_t> &old_to_new_cols,
                             const std::unordered_map<storage::Tile *, std::vector<oid_t>> &tile_to_cols,
                             storage::Tile *dest_tile);

// Column-oriented materialization
void MaterializeColumnAtATime(LogicalTile *source_tile,
                              const std::unordered_map<oid_t, oid_t> &old_to_new_cols,
                              const std::unordered_map<storage::Tile *, std::vector<oid_t>> &tile_to_cols,
                              storage::Tile *dest_tile);

/**
 * @brief Constructor for the materialization executor.
 * @param node Materialization node corresponding to this executor.
 */
MaterializationExecutor::MaterializationExecutor(
    const planner::AbstractPlan *node, ExecutorContext *executor_context)
: AbstractExecutor(node, executor_context) {}

/**
 * @brief Nothing to init at the moment.
 * @return true on success, false otherwise.
 */
bool MaterializationExecutor::DInit() {
  assert(children_.size() == 1);

  return true;
}

/**
 * @brief Generates map from each base tile to columns originally from that
 *        base tile to be materialized.
 * @param column_ids Ids of columns to be materialized.
 * @param source_tile Logical tile that contains mapping from columns to
 *        base tiles.
 * @param tile_to_cols Map to be populated with mappings from tile to columns.
 *
 * We generate this mapping so that we can materialize columns tile by tile for
 * efficiency reasons.
 */
void MaterializationExecutor::GenerateTileToColMap(
    const std::unordered_map<oid_t, oid_t> &old_to_new_cols,
    LogicalTile *source_tile,
    std::unordered_map<storage::Tile *, std::vector<oid_t>> &
    cols_in_physical_tile) {
  for (const auto &kv : old_to_new_cols) {
    oid_t col = kv.first;

    // figure out base physical tile for column in logical tile
    storage::Tile *base_tile = source_tile->GetBaseTile(col);

    std::vector<oid_t> &cols_from_tile = cols_in_physical_tile[base_tile];
    cols_from_tile.push_back(col);
  }
}

/**
 * @brief Does the actual copying of data into the new physical tile.
 * @param source_tile Source tile to copy data from.
 * @param tile_to_cols Map from base tile to columns in that tile
 *        to be materialized.
 * @param dest_tile New tile to copy data into.
 */
void MaterializationExecutor::MaterializeByTiles(
    LogicalTile *source_tile,
    const std::unordered_map<oid_t, oid_t> &old_to_new_cols,
    const std::unordered_map<storage::Tile *, std::vector<oid_t>> &tile_to_cols,
    storage::Tile *dest_tile) {

  auto dest_tile_column_count = dest_tile->GetColumnCount();
  // TODO: Make this a parameter
  oid_t column_count_threshold = 20;
  bool row_wise_materialization = true;

  if(peloton_layout == LAYOUT_HYBRID &&
      dest_tile_column_count < column_count_threshold)
    row_wise_materialization = false;

  // Materialize as needed
  if(row_wise_materialization == true) {
    MaterializeRowAtAtATime(source_tile, old_to_new_cols, tile_to_cols, dest_tile);
  }
  else {
    MaterializeColumnAtATime(source_tile, old_to_new_cols, tile_to_cols, dest_tile);
  }

}

void MaterializeRowAtAtATime(LogicalTile *source_tile,
                             const std::unordered_map<oid_t, oid_t> &old_to_new_cols,
                             const std::unordered_map<storage::Tile *, std::vector<oid_t>> &tile_to_cols,
                             storage::Tile *dest_tile) {

  ///////////////////////////
  // EACH PHYSICAL TILE
  ///////////////////////////
  // Copy over all data from each base tile.
  for (const auto &kv : tile_to_cols) {
    const std::vector<oid_t> &old_column_ids = kv.second;

    auto &schema = source_tile->GetSchema();
    oid_t new_tuple_id = 0;

    auto& column_position_lists = source_tile->GetPositionLists();

    // Get old column information
    std::vector<oid_t> old_column_position_idxs;
    std::vector<size_t> old_column_offsets;
    std::vector<ValueType> old_column_types;
    std::vector<bool> old_is_inlineds;
    std::vector<storage::Tile*> old_tiles;

    // Get new column information
    std::vector<size_t> new_column_offsets;
    std::vector<bool> new_is_inlineds;
    std::vector<size_t> new_column_lengths;

    // Amortize schema lookups once per column
    for (oid_t old_col_id : old_column_ids) {
      auto& column_info = schema[old_col_id];

      // Get the position list
      old_column_position_idxs.push_back(column_info.position_list_idx);

      // Get old column information
      storage::Tile *old_tile = column_info.base_tile;
      old_tiles.push_back(old_tile);
      auto old_schema = old_tile->GetSchema();
      oid_t old_column_id = column_info.origin_column_id;
      const size_t old_column_offset = old_schema->GetOffset(old_column_id);
      old_column_offsets.push_back(old_column_offset);
      const ValueType old_column_type = old_schema->GetType(old_column_id);
      old_column_types.push_back(old_column_type);
      const bool old_is_inlined = old_schema->IsInlined(old_column_id);
      old_is_inlineds.push_back(old_is_inlined);

      // Old to new column mapping
      auto it = old_to_new_cols.find(old_col_id);
      assert(it != old_to_new_cols.end());

      // Get new column information
      oid_t new_column_id = it->second;
      auto new_schema = dest_tile->GetSchema();
      const size_t new_column_offset = new_schema->GetOffset(new_column_id);
      new_column_offsets.push_back(new_column_offset);
      const bool new_is_inlined = new_schema->IsInlined(new_column_id);
      new_is_inlineds.push_back(new_is_inlined);
      const size_t new_column_length = new_schema->GetAppropriateLength(new_column_id);
      new_column_lengths.push_back(new_column_length);
    }

    assert(new_column_offsets.size() == old_column_ids.size());

    ///////////////////////////
    // EACH TUPLE
    ///////////////////////////
    // Copy all values in the tuple to the physical tile
    // This uses fast getter and setter functions
    for (oid_t old_tuple_id : *source_tile) {

      ///////////////////////////
      // EACH COLUMN
      ///////////////////////////
      // Go over each column in given base physical tile
      oid_t col_itr = 0;

      for (oid_t old_col_id : old_column_position_idxs) {

        auto& column_position_list = column_position_lists[old_col_id];

        oid_t base_tuple_id = column_position_list[old_tuple_id];

        auto value = old_tiles[col_itr]->GetValueFast(base_tuple_id,
                                                      old_column_offsets[col_itr],
                                                      old_column_types[col_itr],
                                                      old_is_inlineds[col_itr]);

        LOG_TRACE("Old Tuple : %u Column : %u \n", old_tuple_id, old_col_id);
        LOG_TRACE("New Tuple : %u Column : %u \n", new_tuple_id, new_column_id);

        dest_tile->SetValueFast(value, new_tuple_id,
                                new_column_offsets[col_itr],
                                new_is_inlineds[col_itr],
                                new_column_lengths[col_itr]);

        // Go to next column
        col_itr++;
      }

      // Go to next tuple
      new_tuple_id++;
    }

  }

}

void MaterializeColumnAtATime(LogicalTile *source_tile,
                              const std::unordered_map<oid_t, oid_t> &old_to_new_cols,
                              const std::unordered_map<storage::Tile *, std::vector<oid_t>> &tile_to_cols,
                              storage::Tile *dest_tile) {

  ///////////////////////////
  // EACH PHYSICAL TILE
  ///////////////////////////
  // Copy over all data from each base tile.
  for (const auto &kv : tile_to_cols) {
    const std::vector<oid_t> &old_column_ids = kv.second;

    ///////////////////////////
    // EACH COLUMN
    ///////////////////////////
    // Go over each column in given base physical tile
    for (oid_t old_col_id : old_column_ids) {
      auto &column_info = source_tile->GetColumnInfo(old_col_id);

      // Amortize schema lookups once per column
      storage::Tile *old_tile = column_info.base_tile;
      auto old_schema = old_tile->GetSchema();

      // Get old column information
      oid_t old_column_id = column_info.origin_column_id;
      const size_t old_column_offset = old_schema->GetOffset(old_column_id);
      const ValueType old_column_type = old_schema->GetType(old_column_id);
      const bool old_is_inlined = old_schema->IsInlined(old_column_id);

      // Old to new column mapping
      auto it = old_to_new_cols.find(old_col_id);
      assert(it != old_to_new_cols.end());

      // Get new column information
      oid_t new_column_id = it->second;
      auto new_schema = dest_tile->GetSchema();
      const size_t new_column_offset = new_schema->GetOffset(new_column_id);
      const bool new_is_inlined = new_schema->IsInlined(new_column_id);
      const size_t new_column_length = new_schema->GetAppropriateLength(new_column_id);

      // Get the position list
      auto& column_position_list = source_tile->GetPositionList(column_info.position_list_idx);
      oid_t new_tuple_id = 0;

      // Copy all values in the column to the physical tile
      // This uses fast getter and setter functions
      ///////////////////////////
      // EACH TUPLE
      ///////////////////////////
      for (oid_t old_tuple_id : *source_tile) {
        oid_t base_tuple_id = column_position_list[old_tuple_id];
        auto value = old_tile->GetValueFast(base_tuple_id,
                                            old_column_offset,
                                            old_column_type,
                                            old_is_inlined);

        LOG_TRACE("Old Tuple : %u Column : %u \n", old_tuple_id, old_col_id);
        LOG_TRACE("New Tuple : %u Column : %u \n", new_tuple_id, new_column_id);

        dest_tile->SetValueFast(value, new_tuple_id,
                                new_column_offset,
                                new_is_inlined,
                                new_column_length);

        // Go to next tuple
        new_tuple_id++;
      }

    }

  }

}

std::unordered_map<oid_t, oid_t> MaterializationExecutor::BuildIdentityMapping(
    const catalog::Schema *schema) {
  std::unordered_map<oid_t, oid_t> old_to_new_cols;
  oid_t column_count = schema->GetColumnCount();
  for (oid_t col = 0; col < column_count; col++) {
    old_to_new_cols[col] = col;
  }

  return old_to_new_cols;
}

/**
 * @brief Create a physical tile for the given logical tile
 * @param source_tile Source tile from which the physical tile is created
 * @return a logical tile wrapper for the created physical tile
 */
LogicalTile *MaterializationExecutor::Physify(LogicalTile *source_tile) {
  std::unique_ptr<catalog::Schema> source_tile_schema(
      source_tile->GetPhysicalSchema());
  const int num_tuples = source_tile->GetTupleCount();
  const catalog::Schema *output_schema;
  std::unordered_map<oid_t, oid_t> old_to_new_cols;
  auto node = GetRawNode();

  // Create a default identity mapping node if we did not get one
  if (node == nullptr) {
    assert(source_tile_schema.get());
    output_schema = source_tile_schema.get();

    old_to_new_cols = BuildIdentityMapping(output_schema);
  }
  // Else use the mapping in the given plan node
  else {
    const planner::MaterializationPlan &node =
        GetPlanNode<planner::MaterializationPlan>();
    if (node.GetSchema()) {
      output_schema = node.GetSchema();
      old_to_new_cols = node.old_to_new_cols();
    } else {
      output_schema = source_tile_schema.get();
      old_to_new_cols = BuildIdentityMapping(output_schema);
    }
  }

  // Generate mappings.
  std::unordered_map<storage::Tile *, std::vector<oid_t>> tile_to_cols;
  GenerateTileToColMap(old_to_new_cols, source_tile, tile_to_cols);

  // Create new physical tile.
  std::unique_ptr<storage::Tile> dest_tile(
      storage::TileFactory::GetTempTile(*output_schema, num_tuples));

  // Proceed to materialize logical tile by physical tile at a time.
  MaterializeByTiles(source_tile, old_to_new_cols, tile_to_cols,
                     dest_tile.get());

  // Wrap physical tile in logical tile.
  return LogicalTileFactory::WrapTiles({dest_tile.release()});
}

/**
 * @brief Creates materialized physical tile from logical tile and wraps it
 *        in a new logical tile.
 *
 * @return true on success, false otherwise.
 */
bool MaterializationExecutor::DExecute() {
  // Retrieve child tile.
  const bool success = children_[0]->Execute();
  if (!success) {
    return false;
  }

  std::unique_ptr<LogicalTile> source_tile(children_[0]->GetOutput());
  LogicalTile *output_tile = nullptr;

  // Check the number of tuples in input logical tile
  // If none, then just return false
  const int num_tuples = source_tile->GetTupleCount();
  if (num_tuples == 0) {
    return false;
  }

  auto node = GetRawNode();
  bool physify_flag = true;  // by default, we create a physical tile

  if (node != nullptr) {
    const planner::MaterializationPlan &node =
        GetPlanNode<planner::MaterializationPlan>();
    physify_flag = node.GetPhysifyFlag();
  }

  if (physify_flag) {
    /* create a physical tile and a logical tile wrapper to be the output */
    output_tile = Physify(source_tile.get());
  } else {
    /* just pass thru the underlying logical tile */
    output_tile = source_tile.release();
  }

  SetOutput(output_tile);

  return true;
}

}  // namespace executor
}  // namespace peloton
<commit_msg>Restore mat<commit_after>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// materialization_executor.cpp
//
// Identification: src/backend/executor/materialization_executor.cpp
//
// Copyright (c) 2015, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "backend/executor/materialization_executor.h"

#include <cassert>
#include <memory>
#include <utility>

#include "backend/planner/materialization_plan.h"
#include "backend/executor/logical_tile.h"
#include "backend/executor/logical_tile_factory.h"
#include "backend/storage/tile.h"
#include "backend/storage/data_table.h"

namespace peloton {
namespace executor {

// Row-oriented materialization
void MaterializeRowAtAtATime(LogicalTile *source_tile,
                             const std::unordered_map<oid_t, oid_t> &old_to_new_cols,
                             const std::unordered_map<storage::Tile *, std::vector<oid_t>> &tile_to_cols,
                             storage::Tile *dest_tile);

// Column-oriented materialization
void MaterializeColumnAtATime(LogicalTile *source_tile,
                              const std::unordered_map<oid_t, oid_t> &old_to_new_cols,
                              const std::unordered_map<storage::Tile *, std::vector<oid_t>> &tile_to_cols,
                              storage::Tile *dest_tile);

/**
 * @brief Constructor for the materialization executor.
 * @param node Materialization node corresponding to this executor.
 */
MaterializationExecutor::MaterializationExecutor(
    const planner::AbstractPlan *node, ExecutorContext *executor_context)
: AbstractExecutor(node, executor_context) {}

/**
 * @brief Nothing to init at the moment.
 * @return true on success, false otherwise.
 */
bool MaterializationExecutor::DInit() {
  assert(children_.size() == 1);

  return true;
}

/**
 * @brief Generates map from each base tile to columns originally from that
 *        base tile to be materialized.
 * @param column_ids Ids of columns to be materialized.
 * @param source_tile Logical tile that contains mapping from columns to
 *        base tiles.
 * @param tile_to_cols Map to be populated with mappings from tile to columns.
 *
 * We generate this mapping so that we can materialize columns tile by tile for
 * efficiency reasons.
 */
void MaterializationExecutor::GenerateTileToColMap(
    const std::unordered_map<oid_t, oid_t> &old_to_new_cols,
    LogicalTile *source_tile,
    std::unordered_map<storage::Tile *, std::vector<oid_t>> &
    cols_in_physical_tile) {
  for (const auto &kv : old_to_new_cols) {
    oid_t col = kv.first;

    // figure out base physical tile for column in logical tile
    storage::Tile *base_tile = source_tile->GetBaseTile(col);

    std::vector<oid_t> &cols_from_tile = cols_in_physical_tile[base_tile];
    cols_from_tile.push_back(col);
  }
}

/**
 * @brief Does the actual copying of data into the new physical tile.
 * @param source_tile Source tile to copy data from.
 * @param tile_to_cols Map from base tile to columns in that tile
 *        to be materialized.
 * @param dest_tile New tile to copy data into.
 */
void MaterializationExecutor::MaterializeByTiles(
    LogicalTile *source_tile,
    const std::unordered_map<oid_t, oid_t> &old_to_new_cols,
    const std::unordered_map<storage::Tile *, std::vector<oid_t>> &tile_to_cols,
    storage::Tile *dest_tile) {

  auto dest_tile_column_count = dest_tile->GetColumnCount();
  // TODO: Make this a parameter
  oid_t column_count_threshold = 20;
  bool row_wise_materialization = true;

  if(peloton_layout == LAYOUT_COLUMN)
      row_wise_materialization = false;

  if(peloton_layout == LAYOUT_HYBRID &&
      dest_tile_column_count < column_count_threshold)
    row_wise_materialization = false;

  // Materialize as needed
  if(row_wise_materialization == true) {
    MaterializeRowAtAtATime(source_tile, old_to_new_cols, tile_to_cols, dest_tile);
  }
  else {
    MaterializeColumnAtATime(source_tile, old_to_new_cols, tile_to_cols, dest_tile);
  }

}

void MaterializeRowAtAtATime(LogicalTile *source_tile,
                             const std::unordered_map<oid_t, oid_t> &old_to_new_cols,
                             const std::unordered_map<storage::Tile *, std::vector<oid_t>> &tile_to_cols,
                             storage::Tile *dest_tile) {

  ///////////////////////////
  // EACH PHYSICAL TILE
  ///////////////////////////
  // Copy over all data from each base tile.
  for (const auto &kv : tile_to_cols) {
    const std::vector<oid_t> &old_column_ids = kv.second;

    auto &schema = source_tile->GetSchema();
    oid_t new_tuple_id = 0;

    auto& column_position_lists = source_tile->GetPositionLists();

    // Get old column information
    std::vector<oid_t> old_column_position_idxs;
    std::vector<size_t> old_column_offsets;
    std::vector<ValueType> old_column_types;
    std::vector<bool> old_is_inlineds;
    std::vector<storage::Tile*> old_tiles;

    // Get new column information
    std::vector<size_t> new_column_offsets;
    std::vector<bool> new_is_inlineds;
    std::vector<size_t> new_column_lengths;

    // Amortize schema lookups once per column
    for (oid_t old_col_id : old_column_ids) {
      auto& column_info = schema[old_col_id];

      // Get the position list
      old_column_position_idxs.push_back(column_info.position_list_idx);

      // Get old column information
      storage::Tile *old_tile = column_info.base_tile;
      old_tiles.push_back(old_tile);
      auto old_schema = old_tile->GetSchema();
      oid_t old_column_id = column_info.origin_column_id;
      const size_t old_column_offset = old_schema->GetOffset(old_column_id);
      old_column_offsets.push_back(old_column_offset);
      const ValueType old_column_type = old_schema->GetType(old_column_id);
      old_column_types.push_back(old_column_type);
      const bool old_is_inlined = old_schema->IsInlined(old_column_id);
      old_is_inlineds.push_back(old_is_inlined);

      // Old to new column mapping
      auto it = old_to_new_cols.find(old_col_id);
      assert(it != old_to_new_cols.end());

      // Get new column information
      oid_t new_column_id = it->second;
      auto new_schema = dest_tile->GetSchema();
      const size_t new_column_offset = new_schema->GetOffset(new_column_id);
      new_column_offsets.push_back(new_column_offset);
      const bool new_is_inlined = new_schema->IsInlined(new_column_id);
      new_is_inlineds.push_back(new_is_inlined);
      const size_t new_column_length = new_schema->GetAppropriateLength(new_column_id);
      new_column_lengths.push_back(new_column_length);
    }

    assert(new_column_offsets.size() == old_column_ids.size());

    ///////////////////////////
    // EACH TUPLE
    ///////////////////////////
    // Copy all values in the tuple to the physical tile
    // This uses fast getter and setter functions
    for (oid_t old_tuple_id : *source_tile) {

      ///////////////////////////
      // EACH COLUMN
      ///////////////////////////
      // Go over each column in given base physical tile
      oid_t col_itr = 0;

      for (oid_t old_col_id : old_column_position_idxs) {

        auto& column_position_list = column_position_lists[old_col_id];

        oid_t base_tuple_id = column_position_list[old_tuple_id];

        auto value = old_tiles[col_itr]->GetValueFast(base_tuple_id,
                                                      old_column_offsets[col_itr],
                                                      old_column_types[col_itr],
                                                      old_is_inlineds[col_itr]);

        LOG_TRACE("Old Tuple : %u Column : %u \n", old_tuple_id, old_col_id);
        LOG_TRACE("New Tuple : %u Column : %u \n", new_tuple_id, new_column_id);

        dest_tile->SetValueFast(value, new_tuple_id,
                                new_column_offsets[col_itr],
                                new_is_inlineds[col_itr],
                                new_column_lengths[col_itr]);

        // Go to next column
        col_itr++;
      }

      // Go to next tuple
      new_tuple_id++;
    }

  }

}

void MaterializeColumnAtATime(LogicalTile *source_tile,
                              const std::unordered_map<oid_t, oid_t> &old_to_new_cols,
                              const std::unordered_map<storage::Tile *, std::vector<oid_t>> &tile_to_cols,
                              storage::Tile *dest_tile) {

  ///////////////////////////
  // EACH PHYSICAL TILE
  ///////////////////////////
  // Copy over all data from each base tile.
  for (const auto &kv : tile_to_cols) {
    const std::vector<oid_t> &old_column_ids = kv.second;

    ///////////////////////////
    // EACH COLUMN
    ///////////////////////////
    // Go over each column in given base physical tile
    for (oid_t old_col_id : old_column_ids) {
      auto &column_info = source_tile->GetColumnInfo(old_col_id);

      // Amortize schema lookups once per column
      storage::Tile *old_tile = column_info.base_tile;
      auto old_schema = old_tile->GetSchema();

      // Get old column information
      oid_t old_column_id = column_info.origin_column_id;
      const size_t old_column_offset = old_schema->GetOffset(old_column_id);
      const ValueType old_column_type = old_schema->GetType(old_column_id);
      const bool old_is_inlined = old_schema->IsInlined(old_column_id);

      // Old to new column mapping
      auto it = old_to_new_cols.find(old_col_id);
      assert(it != old_to_new_cols.end());

      // Get new column information
      oid_t new_column_id = it->second;
      auto new_schema = dest_tile->GetSchema();
      const size_t new_column_offset = new_schema->GetOffset(new_column_id);
      const bool new_is_inlined = new_schema->IsInlined(new_column_id);
      const size_t new_column_length = new_schema->GetAppropriateLength(new_column_id);

      // Get the position list
      auto& column_position_list = source_tile->GetPositionList(column_info.position_list_idx);
      oid_t new_tuple_id = 0;

      // Copy all values in the column to the physical tile
      // This uses fast getter and setter functions
      ///////////////////////////
      // EACH TUPLE
      ///////////////////////////
      for (oid_t old_tuple_id : *source_tile) {
        oid_t base_tuple_id = column_position_list[old_tuple_id];
        auto value = old_tile->GetValueFast(base_tuple_id,
                                            old_column_offset,
                                            old_column_type,
                                            old_is_inlined);

        LOG_TRACE("Old Tuple : %u Column : %u \n", old_tuple_id, old_col_id);
        LOG_TRACE("New Tuple : %u Column : %u \n", new_tuple_id, new_column_id);

        dest_tile->SetValueFast(value, new_tuple_id,
                                new_column_offset,
                                new_is_inlined,
                                new_column_length);

        // Go to next tuple
        new_tuple_id++;
      }

    }

  }

}

std::unordered_map<oid_t, oid_t> MaterializationExecutor::BuildIdentityMapping(
    const catalog::Schema *schema) {
  std::unordered_map<oid_t, oid_t> old_to_new_cols;
  oid_t column_count = schema->GetColumnCount();
  for (oid_t col = 0; col < column_count; col++) {
    old_to_new_cols[col] = col;
  }

  return old_to_new_cols;
}

/**
 * @brief Create a physical tile for the given logical tile
 * @param source_tile Source tile from which the physical tile is created
 * @return a logical tile wrapper for the created physical tile
 */
LogicalTile *MaterializationExecutor::Physify(LogicalTile *source_tile) {
  std::unique_ptr<catalog::Schema> source_tile_schema(
      source_tile->GetPhysicalSchema());
  const int num_tuples = source_tile->GetTupleCount();
  const catalog::Schema *output_schema;
  std::unordered_map<oid_t, oid_t> old_to_new_cols;
  auto node = GetRawNode();

  // Create a default identity mapping node if we did not get one
  if (node == nullptr) {
    assert(source_tile_schema.get());
    output_schema = source_tile_schema.get();

    old_to_new_cols = BuildIdentityMapping(output_schema);
  }
  // Else use the mapping in the given plan node
  else {
    const planner::MaterializationPlan &node =
        GetPlanNode<planner::MaterializationPlan>();
    if (node.GetSchema()) {
      output_schema = node.GetSchema();
      old_to_new_cols = node.old_to_new_cols();
    } else {
      output_schema = source_tile_schema.get();
      old_to_new_cols = BuildIdentityMapping(output_schema);
    }
  }

  // Generate mappings.
  std::unordered_map<storage::Tile *, std::vector<oid_t>> tile_to_cols;
  GenerateTileToColMap(old_to_new_cols, source_tile, tile_to_cols);

  // Create new physical tile.
  std::unique_ptr<storage::Tile> dest_tile(
      storage::TileFactory::GetTempTile(*output_schema, num_tuples));

  // Proceed to materialize logical tile by physical tile at a time.
  MaterializeByTiles(source_tile, old_to_new_cols, tile_to_cols,
                     dest_tile.get());

  // Wrap physical tile in logical tile.
  return LogicalTileFactory::WrapTiles({dest_tile.release()});
}

/**
 * @brief Creates materialized physical tile from logical tile and wraps it
 *        in a new logical tile.
 *
 * @return true on success, false otherwise.
 */
bool MaterializationExecutor::DExecute() {
  // Retrieve child tile.
  const bool success = children_[0]->Execute();
  if (!success) {
    return false;
  }

  std::unique_ptr<LogicalTile> source_tile(children_[0]->GetOutput());
  LogicalTile *output_tile = nullptr;

  // Check the number of tuples in input logical tile
  // If none, then just return false
  const int num_tuples = source_tile->GetTupleCount();
  if (num_tuples == 0) {
    return false;
  }

  auto node = GetRawNode();
  bool physify_flag = true;  // by default, we create a physical tile

  if (node != nullptr) {
    const planner::MaterializationPlan &node =
        GetPlanNode<planner::MaterializationPlan>();
    physify_flag = node.GetPhysifyFlag();
  }

  if (physify_flag) {
    /* create a physical tile and a logical tile wrapper to be the output */
    output_tile = Physify(source_tile.get());
  } else {
    /* just pass thru the underlying logical tile */
    output_tile = source_tile.release();
  }

  SetOutput(output_tile);

  return true;
}

}  // namespace executor
}  // namespace peloton
<|endoftext|>


<commit_before>#include <allegro.h>
#include "allegro-joystick.h"

void AllegroJoystick::poll(){
    ::poll_joystick();
}

JoystickInput AllegroJoystick::readAll(){
    JoystickInput input;
    JOYSTICK_INFO * info = &joy[0];
    switch(info->num_buttons > 4 ? 4 : info->num_buttons){
        case 4: input.button4 = info->button[3].b;
        case 3: input.button3 = info->button[2].b;
        case 2: input.button2 = info->button[1].b;
        case 1: input.button1 = info->button[0].b;
        case 0: {
            break;
        }
    }
    if (info->num_sticks > 0){
        if (info->stick[0].num_axis > 0){
            int position = info->stick[0].axis[0].pos;
            if (position < 0){
                input.left = true;
            } else if (position > 0){
                input.right = true;
            }
        }
        if (info->stick[0].num_axis > 1){
            int position = info->stick[0].axis[1].pos;
            if (position < 0){
                input.up = true;
            } else if (position > 0){
                input.down = true;
            }
        }
    }
    return input;
}

bool AllegroJoystick::pressed(){
    JoystickInput input = readAll();
    return input.up || input.down || input.left || input.right ||
           input.button1 || input.button2 || input.button3 || input.button4;
}

AllegroJoystick::~AllegroJoystick(){
}

AllegroJoystick::AllegroJoystick(){
}
<commit_msg>read all joystick sticks<commit_after>#include <allegro.h>
#include "allegro-joystick.h"

void AllegroJoystick::poll(){
    ::poll_joystick();
}

JoystickInput AllegroJoystick::readAll(){
    JoystickInput input;
    JOYSTICK_INFO * info = &joy[0];
    switch(info->num_buttons > 4 ? 4 : info->num_buttons){
        case 4: input.button4 = info->button[3].b;
        case 3: input.button3 = info->button[2].b;
        case 2: input.button2 = info->button[1].b;
        case 1: input.button1 = info->button[0].b;
        case 0: {
            break;
        }
    }

    for (int stick = 0; stick < info->num_sticks; stick++){
        if (info->stick[stick].num_axis > 0){
            int position = info->stick[stick].axis[0].pos;
            if (position < 0){
                input.left = true;
            } else if (position > 0){
                input.right = true;
            }
        }
        if (info->stick[stick].num_axis > 1){
            int position = info->stick[stick].axis[1].pos;
            if (position < 0){
                input.up = true;
            } else if (position > 0){
                input.down = true;
            }
        }
    }

    return input;
}

bool AllegroJoystick::pressed(){
    JoystickInput input = readAll();
    return input.up || input.down || input.left || input.right ||
           input.button1 || input.button2 || input.button3 || input.button4;
}

AllegroJoystick::~AllegroJoystick(){
}

AllegroJoystick::AllegroJoystick(){
}
<|endoftext|>


<commit_before><commit_msg>Changed example_basic to use black background<commit_after><|endoftext|>


<commit_before>#include <stdint.h>
#include <deque>
#include <iostream>
#include <rte_rwlock.h>

#define BUFFER_SIZE 256

namespace moonsniff {

	struct ms_entry {
		uint64_t timestamp;
		bool valid = false;
	};

	std::deque<uint64_t> latencies;

	ms_entry hit_list[UINT16_MAX];
	rte_rwlock_t mutex[UINT16_MAX];

	uint32_t hits = 0;
	uint32_t misses = 0;
	uint32_t inval_ts = 0; // computed latency is invalid, e.g. negative

	static uint32_t getHits(){ return hits; }
	static uint32_t getMisses(){ return misses; }
	static uint32_t getInvalidTS(){ return inval_ts; }

	static void init(){
		for(uint32_t i = 0; i < UINT16_MAX; ++i){
			rte_rwlock_init(&mutex[i]);
		}
	}

	static void add_entry(uint16_t identification, uint64_t timestamp){
		rte_rwlock_write_lock(&mutex[identification]);
		//std::cout << "timestamp: " << timestamp << " for identification: " << identification << "\n";
		hit_list[identification].valid = true;
		hit_list[identification].timestamp = timestamp;
		//std::cout << "finished adding" << "\n";
		rte_rwlock_write_unlock(&mutex[identification]);
	}

	static void test_for(uint16_t identification, uint64_t timestamp){
		rte_rwlock_write_lock(&mutex[identification]);
		if( hit_list[identification].valid == true ){
			++hits;
			//latencies.push_back(timestamp - hit_list[identification].timestamp);
			if( timestamp > hit_list[identification].timestamp){
				uint64_t difference = timestamp - hit_list[identification].timestamp;
				if( difference < 1e9){
					latencies.push_back(difference);
				}else{
					++inval_ts;
				}
			}else{
				++inval_ts;
			}

			//std::cout << "new: " << timestamp << "\n";
			//std::cout << "old: " << hit_list[identification].timestamp << "\n";
			//std::cout << "difference: " << (timestamp - hit_list[identification].timestamp)/1e6 << " ms\n";
			hit_list[identification].valid = false;
		} else {
			++misses;
		}
		rte_rwlock_write_unlock(&mutex[identification]);
	}

	static uint64_t average_latency(){
		uint64_t size = 0;
		uint64_t sum = 0;
		for(auto it = latencies.cbegin(); it != latencies.cend(); ++it){
			sum += *it;
			++size;
		}
		std::cout << "sum: " << sum << ", length: " << latencies.size() << ", size: " << size << "\n";
		return sum/size;
	}
}

extern "C" {
	void ms_add_entry(uint16_t identification, uint64_t timestamp){
		moonsniff::add_entry(identification, timestamp);
	}

	void ms_test_for(uint16_t identification, uint64_t timestamp){
		moonsniff::test_for(identification, timestamp);
	}

	uint64_t ms_average_latency(){
		return moonsniff::average_latency();
	}

	void ms_init(){ moonsniff::init(); }
	uint32_t ms_get_hits(){ return moonsniff::getHits(); }
	uint32_t ms_get_misses(){ return moonsniff::getMisses(); }
	uint32_t ms_get_invalid_timestamps(){ return moonsniff::getInvalidTS();}

}
<commit_msg>write latencies to file instead of dequeue<commit_after>#include <stdint.h>
#include <deque>
#include <iostream>
#include <fstream>
#include <rte_rwlock.h>

#define BUFFER_SIZE 256

namespace moonsniff {

	struct ms_entry {
		uint64_t timestamp;
		bool valid = false;
	};

	std::deque<uint64_t> latencies;
	std::ofstream file;

	ms_entry hit_list[UINT16_MAX];
	rte_rwlock_t mutex[UINT16_MAX];

	uint32_t hits = 0;
	uint32_t misses = 0;
	uint32_t inval_ts = 0; // computed latency is invalid, e.g. negative

	static uint32_t getHits(){ return hits; }
	static uint32_t getMisses(){ return misses; }
	static uint32_t getInvalidTS(){ return inval_ts; }

	static void init(){
		for(uint32_t i = 0; i < UINT16_MAX; ++i){
			rte_rwlock_init(&mutex[i]);
		}
		file.open("latencies.csv");
		file << "timestamp pre, timestamp post\n";
	}

	static void add_entry(uint16_t identification, uint64_t timestamp){
		rte_rwlock_write_lock(&mutex[identification]);
		//std::cout << "timestamp: " << timestamp << " for identification: " << identification << "\n";
		hit_list[identification].valid = true;
		hit_list[identification].timestamp = timestamp;
		//std::cout << "finished adding" << "\n";
		rte_rwlock_write_unlock(&mutex[identification]);
	}

	static void test_for(uint16_t identification, uint64_t timestamp){
		rte_rwlock_write_lock(&mutex[identification]);
		if( hit_list[identification].valid == true ){
			++hits;
			//latencies.push_back(timestamp - hit_list[identification].timestamp);
//			if( timestamp > hit_list[identification].timestamp){
//				uint64_t difference = timestamp - hit_list[identification].timestamp;
//				if( difference < 1e9){
//					latencies.push_back(difference);
//				}else{
//					++inval_ts;
//				}
//			}else{
//				++inval_ts;
//			}
			file << hit_list[identification].timestamp << ", " << timestamp << "\n";

			//std::cout << "new: " << timestamp << "\n";
			//std::cout << "old: " << hit_list[identification].timestamp << "\n";
			//std::cout << "difference: " << (timestamp - hit_list[identification].timestamp)/1e6 << " ms\n";
			hit_list[identification].valid = false;
		} else {
			++misses;
		}
		rte_rwlock_write_unlock(&mutex[identification]);
	}

	static uint64_t average_latency(){
		file.close();
		uint64_t size = 0;
		uint64_t sum = 0;
		for(auto it = latencies.cbegin(); it != latencies.cend(); ++it){
			sum += *it;
			++size;
		}
		std::cout << "sum: " << sum << ", length: " << latencies.size() << ", size: " << size << "\n";
		return sum/size;
	}
}

extern "C" {
	void ms_add_entry(uint16_t identification, uint64_t timestamp){
		moonsniff::add_entry(identification, timestamp);
	}

	void ms_test_for(uint16_t identification, uint64_t timestamp){
		moonsniff::test_for(identification, timestamp);
	}

	uint64_t ms_average_latency(){
		return moonsniff::average_latency();
	}

	void ms_init(){ moonsniff::init(); }
	uint32_t ms_get_hits(){ return moonsniff::getHits(); }
	uint32_t ms_get_misses(){ return moonsniff::getMisses(); }
	uint32_t ms_get_invalid_timestamps(){ return moonsniff::getInvalidTS();}

}
<|endoftext|>