text:
// ======================================================================
/*!
 * \brief Model repository
 */
// ======================================================================

#include "Repository.h"
#include "MetaQueryFilters.h"
#include <boost/algorithm/string/join.hpp>
#include <boost/date_time/posix_time/posix_time_io.hpp>
#include <boost/tuple/tuple.hpp>
#include <macgyver/Exception.h>
#include <macgyver/StringConversion.h>
#include <newbase/NFmiFastQueryInfo.h>
#include <newbase/NFmiQueryData.h>
#include <spine/Convenience.h>
#include <spine/ParameterFactory.h>
#include <spine/TableFormatter.h>
#include <sstream>
#include <stdexcept>

namespace SmartMet
{
namespace Engine
{
namespace Querydata
{
// ----------------------------------------------------------------------
/*!
 * \brief Add a new producer configuration
 */
// ----------------------------------------------------------------------

void Repository::add(const ProducerConfig& config)
{
  try
  {
    itsProducerConfigs.insert(ProducerConfigs::value_type(config.producer, config));
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

// ----------------------------------------------------------------------
/*!
 * \brief Add a new model for the given producer
 */
// ----------------------------------------------------------------------

void Repository::add(const Producer& producer, SharedModel model)
{
  try
  {
    auto producer_model = itsProducers.find(producer);

    // Establish the model map for the producer

    bool ok;
    if (producer_model == itsProducers.end())
    {
      // Insert an empty map of models for a new producer
      boost::tie(producer_model, ok) =
          itsProducers.insert(Producers::value_type(producer, SharedModels()));

      if (!ok)
        throw Fmi::Exception(BCP, "Failed to add new model for producer '" + producer + "'!");
    }

    // And insert the model for the producer

    SharedModels& models = producer_model->second;

    SharedModels::iterator iter;

    boost::tie(iter, ok) = models.insert(std::make_pair(model->originTime(), model));

    if (!ok)
    {
      // The origin time must have matched. Choose the data with the
      // newer modification time.

      if (model->modificationTime() > iter->second->modificationTime())
      {
#if 0
        std::cerr << "QEngine: Replacing "
            << iter->second->path()
            << " by "
            << model->path()
            << " due to later modification time" << std::endl;
#endif
        // Replace old data with new one
        iter->second = model;
      }
      else
      {
        // This could happen for example during start up when newer data is read
        // before older data - we just ignore the old data
      }
    }
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

// ----------------------------------------------------------------------
/*!
 * \brief Get available origin times for the producer
 */
// ----------------------------------------------------------------------

OriginTimes Repository::originTimes(const Producer& producer) const
{
  try
  {
    OriginTimes times;

    const auto it = itsProducers.find(producer);
    if (it != itsProducers.end())
    {
      const SharedModels& models = it->second;

      for (const auto& time_model : models)
      {
        times.insert(time_model.first);
      }
    }
    return times;
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

// ----------------------------------------------------------------------
/*!
 * \brief Test if the producer name is known as done in get()
 */
// ----------------------------------------------------------------------

bool Repository::hasProducer(const Producer& producer) const
{
  try
  {
    const auto pos = itsProducerConfigs.find(producer);
    if (pos != itsProducerConfigs.end())
      return true;

    // Check aliases

    return std::any_of(itsProducerConfigs.cbegin(),
                       itsProducerConfigs.cend(),
                       [&producer](const ProducerConfigs::value_type& prod_config)
                       {
                         const auto& aliases = prod_config.second.aliases;
                         return (aliases.find(producer) != aliases.end());
                       });
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

// ----------------------------------------------------------------------
/*!
 * \brief Get newest data for the given producer
 */
// ----------------------------------------------------------------------

Q Repository::get(const Producer& producer) const
{
  try
  {
    // If the data is multifile return all of them instead of just the latest file

    const auto prod_config = itsProducerConfigs.find(producer);
    if (prod_config != itsProducerConfigs.end())
    {
      if (prod_config->second.ismultifile)
      {
        return getAll(producer);
      }
    }

    // Return the latest model only

    const auto producer_model = itsProducers.find(producer);

    if (producer_model == itsProducers.end())
    {
      throw Fmi::Exception(BCP,
                           "Repository get (1): No data available for producer '" + producer + "'!")
          .disableStackTrace();
    }

    const SharedModels& time_model = producer_model->second;

    if (time_model.empty())
    {
      throw Fmi::Exception(BCP,
                           "Repository get (2): No data available for producer '" + producer + "'!")
          .disableStackTrace();
    }

    // newest origintime is at the end
    auto last = --time_model.end();

    return boost::make_shared<QImpl>(last->second);
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

// ----------------------------------------------------------------------
/*!
 * \brief Get data for the given producer with given origintime
 */
// ----------------------------------------------------------------------

Q Repository::get(const Producer& producer, const OriginTime& origintime) const
{
  try
  {
    const auto producer_model = itsProducers.find(producer);

    if (producer_model == itsProducers.end())
    {
      throw Fmi::Exception(BCP,
                           "Repository get (3): No data available for producer '" + producer + "'!")
          .disableStackTrace();
    }

    const SharedModels& models = producer_model->second;

    if (models.empty())
      throw Fmi::Exception(BCP,
                           "Repository get (4): No data available for producer '" + producer + "'!")
          .disableStackTrace();

    SharedModels::const_iterator time_model;
    if (origintime.is_pos_infinity())
    {
      // newest origintime is at the end
      auto time_model = --models.end();
      return boost::make_shared<QImpl>(time_model->second);
    }
    if (origintime.is_neg_infinity())
    {
      // oldest origintime is at the beginning
      auto time_model = models.begin();
      return boost::make_shared<QImpl>(time_model->second);
    }

#if 1
    auto iter = models.find(origintime);
    if (iter != models.end())
      return boost::make_shared<QImpl>(iter->second);
#else
    // This was deprecated 27.4.2015 in favour of exact origintime requests

    // Find latest model with origintime <= given limit. This is potentially
    // slow if one is searching for very old radar data, but then again
    // one should use the radar data as a multifile instead
    for (auto iter = models.crbegin(); iter != models.crend(); ++iter)
      if (iter->first <= origintime)
        return boost::make_shared<QImpl>(iter->second);

#endif

    throw Fmi::Exception(BCP,
                         "Repository get: No data available for producer '" + producer +
                             "' with origintime == " + to_simple_string(origintime))
        .disableStackTrace();
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

// ----------------------------------------------------------------------
/*!
 * \brief Get all data for the given time period
 */
// ----------------------------------------------------------------------

Q Repository::getAll(const Producer& producer) const
{
  try
  {
    // Find the models
    const auto producer_model = itsProducers.find(producer);

    if (producer_model == itsProducers.end())
    {
      throw Fmi::Exception(
          BCP, "Repository getPeriod: No data available for producer '" + producer + "'")
          .disableStackTrace();
    }

    const SharedModels& models = producer_model->second;

    if (models.empty())
    {
      throw Fmi::Exception(
          BCP, "Repository getPeriod: No data available for producer '" + producer + "'")
          .disableStackTrace();
    }

    // Construct a vector of datas with similar grids only

    std::vector<SharedModel> okmodels;
    boost::optional<std::size_t> hash;

    for (const auto& otime_model : models)
    {
      auto tmphash = otime_model.second->gridHashValue();
      if (hash && *hash != tmphash)
        okmodels.clear();
      okmodels.push_back(otime_model.second);
      hash = tmphash;
    }

    // Construct a view of the data

    return boost::make_shared<QImpl>(okmodels);
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

// ----------------------------------------------------------------------
/*!
 * \brief Remove the specified model
 */
// ----------------------------------------------------------------------

void Repository::remove(const Producer& producer, const boost::filesystem::path& path)
{
  try
  {
    auto producer_model = itsProducers.find(producer);

    if (producer_model == itsProducers.end())
      throw Fmi::Exception(BCP,
                           "Repository remove: No data available for producer '" + producer + "'")
          .disableStackTrace();

    SharedModels& models = producer_model->second;

    if (models.empty())
      throw Fmi::Exception(BCP,
                           "Repository remove: No data available for producer '" + producer + "'")
          .disableStackTrace();

    for (auto time_model = models.begin(), end = models.end(); time_model != end; ++time_model)
    {
      if (time_model->second->path() == path)
      {
        if (itsVerbose)
          std::cout << boost::posix_time::second_clock::local_time() << " [qengine] Deleting "
                    << time_model->second->path() << std::endl;
        time_model->second->uncache();  // uncache validpoints
        models.erase(time_model);
        break;
      }
    }
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

// ----------------------------------------------------------------------
/*!
 * \brief Resize producer
 */
// ----------------------------------------------------------------------

void Repository::resize(const Producer& producer, std::size_t limit)
{
  try
  {
    auto producer_model = itsProducers.find(producer);

    if (producer_model == itsProducers.end())
      throw Fmi::Exception(BCP,
                           "Repository resize: no data available for producer '" + producer + "'")
          .disableStackTrace();

    SharedModels& models = producer_model->second;

    // Usually only the oldest (1) file is deleted, so
    // the speed of this erase loop is of no concern.
    // Typically we load a new file, and then delete
    // the oldest one. During the startup phase we may
    // have multiple deletions, but that is to be expected,
    // since we have to scan all the files for their origintimes.

    while (models.size() > limit)
    {
      if (itsVerbose)
        std::cout << boost::posix_time::second_clock::local_time()
                  << " [qengine] Resize removal of " << models.begin()->second->path() << std::endl;

      // the oldest file is the one first sorted by origintime
      models.begin()->second->uncache();  // uncache validpoints
      models.erase(models.begin());       // and erase the model
    }
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

// ----------------------------------------------------------------------
/*!
 * \brief Expire too old models
 */
// ----------------------------------------------------------------------

void Repository::expire(const Producer& producer, std::size_t max_age)
{
  // max_age is in seconds, and 0 implies no limit exists

  if (max_age == 0)
    return;

  auto now = boost::posix_time::second_clock::universal_time();
  auto time_limit = now - boost::posix_time::seconds(max_age);

  try
  {
    auto producer_model = itsProducers.find(producer);

    if (producer_model == itsProducers.end())
      return;

    SharedModels& models = producer_model->second;

    if (models.empty())
      return;

    for (auto time_model = models.begin(), end = models.end(); time_model != end;)
    {
      if (time_model->second->modificationTime() >= time_limit)
        ++time_model;
      else
      {
        if (itsVerbose)
          std::cout << boost::posix_time::second_clock::local_time() << " [qengine] Expiring "
                    << time_model->second->path() << std::endl;
        time_model->second->uncache();  // uncache validpoints
        models.erase(time_model++);
      }
    }
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Expiring model failed!");
  }
}

// ----------------------------------------------------------------------
/*!
 * \brief Match leveltypes
 *
 * Leveltype is OK if desired type is the same, or the desired
 * type is "" implying first match is OK.
 *
 */
// ----------------------------------------------------------------------

bool leveltype_ok(const std::string& modeltype, const std::string& wantedtype)
{
  try
  {
    if (wantedtype.empty())
      return true;
    return (modeltype == wantedtype);
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

// ----------------------------------------------------------------------
/*!
 * \brief Utility subroutine
 */
// ----------------------------------------------------------------------

bool Repository::contains(const Repository::SharedModels& models,
                          double lon,
                          double lat,
                          double maxdist,
                          const std::string& levelname) const
{
  try
  {
    if (models.empty())
      return false;

    SharedModel smodel = (--models.end())->second;
    const Model& model = *smodel;

    if (!leveltype_ok(model.levelName(), levelname))
      return false;

    auto qinfo = model.info();
    bool result = qinfo->IsInside(NFmiPoint(lon, lat), 1000 * maxdist);
    model.release(qinfo);

    return result;
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

// ----------------------------------------------------------------------
/*!
 * \brief Find the model containing the given point
 */
// ----------------------------------------------------------------------

Producer Repository::find(const ProducerList& producerlist,
                          const ProducerList& producerorder,
                          double lon,
                          double lat,
                          double maxdist,
                          bool usedatamaxdist,
                          const std::string& leveltype) const
{
  try
  {
    for (const Producer& producer : producerlist)
    {
      // Try primary names first
      const auto producer_model = itsProducers.find(producer);

      if (producer_model != itsProducers.end())
      {
        const auto prod_config = itsProducerConfigs.find(producer);
        // Use data maxdistance if allowed and it is set
        double chosenmaxdist =
            (usedatamaxdist && prod_config->second.maxdistance > 0 ? prod_config->second.maxdistance
                                                                   : maxdist);

        if (contains(producer_model->second, lon, lat, chosenmaxdist, leveltype))
          return producer;
      }
    }

    // Try aliases next in the given order

    for (const Producer& producer : producerorder)
    {
      const auto prod_config = itsProducerConfigs.find(producer);
      if (prod_config == itsProducerConfigs.end())
        continue;

      // Use data maxdistance if allowed and it is set
      double chosenmaxdist =
          (usedatamaxdist && prod_config->second.maxdistance > 0 ? prod_config->second.maxdistance
                                                                 : maxdist);

      const auto& aliases = prod_config->second.aliases;

      for (const Producer& alias : producerlist)
      {
        if (aliases.find(alias) != aliases.end())
        {
          const auto producer_model = itsProducers.find(producer);
          if (producer_model != itsProducers.end())
          {
            if (contains(producer_model->second, lon, lat, chosenmaxdist, leveltype))
              return producer;
          }
        }
      }
    }

    return Producer();
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

Repository::ContentTable Repository::getProducerInfo(const ProducerList& producerlist,
                                                     const std::string& timeFormat) const
{
  try
  {
    boost::shared_ptr<Spine::Table> resultTable(new Spine::Table);

    static Spine::TableFormatter::Names headers{"#",
                                                "Producer",
                                                "LastScanTime",
                                                "NextScanTime",
                                                "DataLoadTime",
                                                "NumberOfLoadedFiles",
                                                "aliases",
                                                "directory",
                                                "pattern",
                                                "forecast",
                                                "climatology",
                                                "fullgrid",
                                                "mmap",
                                                "type",
                                                "leveltype",
                                                "relative_uv",
                                                "refresh_interval_secs",
                                                "number_to_keep",
                                                "update_interval",
                                                "minimum_expires",
                                                "max_age",
                                                "maxdistance"};

    std::unique_ptr<Fmi::TimeFormatter> timeFormatter(Fmi::TimeFormatter::create(timeFormat));

    unsigned int row = 0;
    for (const auto& producer : producerlist)
    {
      if (producer.empty() || itsProducerConfigs.find(producer) == itsProducerConfigs.end())
        continue;

      const ProducerConfig thisConfig = itsProducerConfigs.find(producer)->second;

      int column = 0;

      // Row number
      resultTable->set(column, row, Fmi::to_string(row + 1));
      ++column;

      // Producer
      resultTable->set(column, row, producer);
      ++column;

      if (itsProducerStatus.find(producer) != itsProducerStatus.end())
      {
        const ProducerStatus& status = itsProducerStatus.at(producer);

        // Latest scan time
        resultTable->set(column, row, timeFormatter->format(status.latest_scan_time));
        ++column;

        // Next scan time
        resultTable->set(column, row, timeFormatter->format(status.next_scan_time));
        ++column;

        // Latest data load time
        resultTable->set(column, row, timeFormatter->format(status.latest_data_load_time));
        ++column;

        // Number of loaded files
        resultTable->set(column, row, Fmi::to_string(status.number_of_loaded_files));
        ++column;
      }
      else
      {
        // Latest scan time
        resultTable->set(column, row, "");
        ++column;

        // Next scan time
        resultTable->set(column, row, "");
        ++column;

        // Latest data load time
        resultTable->set(column, row, "");
        ++column;

        // Number of loaded files
        resultTable->set(column, row, "");
        ++column;
      }

      // Configuration
      resultTable->set(column, row, boost::algorithm::join(thisConfig.aliases, ", "));
      ++column;
      resultTable->set(column, row, std::string(thisConfig.directory.c_str()));
      ++column;
      resultTable->set(column, row, thisConfig.pattern_str);
      ++column;
      resultTable->set(column, row, Fmi::to_string(thisConfig.isforecast));
      ++column;
      resultTable->set(column, row, Fmi::to_string(thisConfig.isclimatology));
      ++column;
      resultTable->set(column, row, Fmi::to_string(thisConfig.isfullgrid));
      ++column;
      resultTable->set(column, row, Fmi::to_string(thisConfig.mmap));
      ++column;
      resultTable->set(column, row, thisConfig.type);
      ++column;
      resultTable->set(column, row, thisConfig.type);
      ++column;
      resultTable->set(column, row, Fmi::to_string(thisConfig.isrelativeuv));
      ++column;
      resultTable->set(column, row, Fmi::to_string(thisConfig.refresh_interval_secs));
      ++column;
      resultTable->set(column, row, Fmi::to_string(thisConfig.number_to_keep));
      ++column;
      resultTable->set(column, row, Fmi::to_string(thisConfig.update_interval));
      ++column;
      resultTable->set(column, row, Fmi::to_string(thisConfig.minimum_expires));
      ++column;
      resultTable->set(column, row, Fmi::to_string(thisConfig.max_age));
      ++column;
      resultTable->set(column, row, Fmi::to_string(thisConfig.maxdistance));

      row++;
    }

    return std::make_pair(resultTable, headers);
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

Repository::ContentTable Repository::getParameterInfo(const ProducerList& producerlist) const
{
  try
  {
    boost::shared_ptr<Spine::Table> resultTable(new Spine::Table);

    static Spine::TableFormatter::Names headers{"#", "ParamId", "ParamName", "Producers"};

    NFmiEnumConverter converter;
    using ParameterIdProducers = std::map<FmiParameterName, std::vector<std::string>>;

    ParameterIdProducers pip;
    for (const auto& producer : producerlist)
    {
      const auto producer_model = itsProducers.find(producer);
      if (producer_model == itsProducers.end() || producer_model->second.empty())
        continue;

      Q q = get(producer);
      q->resetParam();
      while (q->nextParam())
        pip[q->parameterName()].push_back(producer);
    }

    unsigned int row = 0;
    unsigned int parameter_no = 1;
    for (const auto& info : pip)
    {
      FmiParameterName param_id = info.first;

      auto parameter_no_str = Fmi::to_string(parameter_no);
      auto param_id_str = Fmi::to_string(param_id);
      auto param_name_str = converter.ToString(param_id);

      for (const auto& producer : info.second)
      {
        int column = 0;
        resultTable->set(column++, row, parameter_no_str);
        resultTable->set(column++, row, param_id_str);
        resultTable->set(column++, row, param_name_str);
        resultTable->set(column, row, producer);
        row++;
      }
      parameter_no++;
    }

    return std::make_pair(resultTable, headers);
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

Repository::ContentTable Repository::getRepoContents(const std::string& timeFormat,
                                                     const std::string& projectionFormat) const
{
  std::string producer;
  return getRepoContents(producer, timeFormat, projectionFormat);
}

#ifdef WGS84
Repository::ContentTable Repository::getRepoContents(const std::string& producer,
                                                     const std::string& timeFormat,
                                                     const std::string& projectionFormat) const
#else
Repository::ContentTable Repository::getRepoContents(
    const std::string& producer,
    const std::string& timeFormat,
    const std::string& /* projectionFormat */) const
#endif
{
  try
  {
    static const std::vector<std::string>& ContentTableHeaders =
        *new std::vector<std::string>{"Producer",
                                      "Aliases",
                                      "RI",
                                      "Path",
                                      "Parameters",
                                      "Descriptions",
                                      "Levels",
                                      "Projection",
                                      "OriginTime",
                                      "MinTime",
                                      "MaxTime",
                                      "LoadTime"};

    std::unique_ptr<Fmi::TimeFormatter> timeFormatter(Fmi::TimeFormatter::create(timeFormat));

    boost::shared_ptr<Spine::Table> resultTable(new Spine::Table);

    int row = 0;

    for (const auto& prodit : itsProducers)
    {
      // Skip all but the wanted producer
      if (!producer.empty() && producer != prodit.first)
        continue;

      const SharedModels& theseModels = prodit.second;

      const ProducerConfig thisConfig = itsProducerConfigs.find(prodit.first)->second;

      for (const auto& modit : theseModels)
      {
        auto model = modit.second;
        auto qi = model->info();

        // Time range
        qi->FirstTime();
        boost::posix_time::ptime time1 = qi->ValidTime();
        qi->LastTime();
        boost::posix_time::ptime time2 = qi->ValidTime();
        // File load time
        boost::posix_time::ptime time3 = model->loadTime();

        // Get the parameter list from querydatainfo
        std::list<std::string> params;
        std::list<std::string> descriptions;
        for (qi->ResetParam(); qi->NextParam(false);)
        {
          int paramID = boost::numeric_cast<int>(qi->Param().GetParamIdent());
          std::string paramName = Spine::ParameterFactory::instance().name(paramID);
          if (!paramName.empty())
            params.push_back(paramName);
          else
            params.emplace_back(Fmi::to_string(paramID));

          descriptions.emplace_back(qi->Param().GetParamName().CharPtr());
        }

        // Get the available levelvalues
        std::list<std::string> levels;
        for (qi->ResetLevel(); qi->NextLevel();)
        {
          float level = qi->Level()->LevelValue();
          if (level != kFloatMissing)
            levels.emplace_back(Fmi::to_string(level));
          else
            levels.emplace_back("-");
        }

        // Get projection string
        std::string projectionText;
        if (qi->Area() == nullptr)
          projectionText = "nan";
#ifdef WGS84
        else if (projectionFormat == "wkt")
          projectionText = qi->Area()->WKT();
        // Defaults to newbase form
        else
          projectionText = qi->Area()->ProjStr();
#else
        else
          projectionText = qi->Area()->WKT();
#endif
        // For nicer output in browsers we replace for example ",PROJCS" with ", PROJCS"
        boost::regex rex(",([A-Z])");
        projectionText = boost::regex_replace(projectionText, rex, ", $1");

        // Create the table

        int column = 0;

        // insert producer name
        resultTable->set(column, row, prodit.first);
        ++column;

        // Insert aliases
        std::string aliases = boost::algorithm::join(thisConfig.aliases, ", ");
        resultTable->set(column, row, aliases);
        ++column;

        // Insert refresh interval
        resultTable->set(column, row, Fmi::to_string(thisConfig.refresh_interval_secs));
        ++column;

        // insert model file path
        resultTable->set(column, row, modit.second->path().string());
        ++column;

        // Insert parameters
        std::string parameters = boost::algorithm::join(params, ", ");
        resultTable->set(column, row, parameters);
        ++column;

        // Insert parameter descriptions
        std::string descs = boost::algorithm::join(descriptions, ", ");
        resultTable->set(column, row, descs);
        ++column;

        // Insert levels
        std::string levs = boost::algorithm::join(levels, ", ");
        resultTable->set(column, row, levs);
        ++column;

        // Insert projection string
        resultTable->set(column, row, projectionText);
        ++column;

        // insert origin time
        resultTable->set(column, row, timeFormatter->format(modit.first));
        ++column;

        // Insert min time
        resultTable->set(column, row, timeFormatter->format(time1));
        ++column;

        // Insert max time
        resultTable->set(column, row, timeFormatter->format(time2));
        ++column;

        // Insert file laod time
        resultTable->set(column, row, timeFormatter->format(time3));
        ++column;

        ++row;
      }
    }

    // Insert headers

    Spine::TableFormatter::Names headers;

    for (const auto& p : ContentTableHeaders)
    {
      headers.push_back(p);
    }

    return std::make_pair(resultTable, headers);
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

std::list<MetaData> Repository::getRepoMetadata(const MetaQueryOptions& theOptions) const
{
  try
  {
    std::list<MetaData> propertyList;

    // Avoid processing all metadata if producer and possibly origintime too are known,
    // collecting all metadata may be quite slow

    if (theOptions.hasProducer())
    {
      if (theOptions.hasOriginTime())
        propertyList = getRepoMetadata(theOptions.getProducer(), theOptions.getOriginTime());
      else
        propertyList = getRepoMetadata(theOptions.getProducer());
    }
    else
      propertyList = getRepoMetadata();

    // Filter according to the given options. Producer and origintime filters
    // might have been used already, but at this point the tests fail quickly,
    // not worth optimizing.

    for (auto iter = propertyList.begin(); iter != propertyList.end();)
    {
      if (!filterProducer(*iter, theOptions))
      {
        propertyList.erase(iter++);
        continue;
      }
      if (!filterOriginTime(*iter, theOptions))
      {
        propertyList.erase(iter++);
        continue;
      }

      if (!filterFirstTime(*iter, theOptions))
      {
        propertyList.erase(iter++);
        continue;
      }

      if (!filterLastTime(*iter, theOptions))
      {
        propertyList.erase(iter++);
        continue;
      }

      if (!filterParameters(*iter, theOptions))
      {
        propertyList.erase(iter++);
        continue;
      }

      if (!filterLevelTypes(*iter, theOptions))
      {
        propertyList.erase(iter++);
        continue;
      }

      if (!filterLevelValues(*iter, theOptions))
      {
        propertyList.erase(iter++);
        continue;
      }

      if (!filterBoundingBox(*iter, theOptions))
      {
        propertyList.erase(iter++);
        continue;
      }

      ++iter;
    }

    return propertyList;
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

std::list<MetaData> Repository::getRepoMetadata(const std::string& producer) const
{
  try
  {
    std::list<MetaData> props;

    const auto producerpos = itsProducers.find(producer);
    if (producerpos == itsProducers.end())
      return props;

    const auto& models = producerpos->second;

    for (const auto& origintime_model : models)
    {
      QImpl q(origintime_model.second);
      props.push_back(q.metaData());
    }
    return props;
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

std::list<MetaData> Repository::getRepoMetadata(const std::string& producer,
                                                const boost::posix_time::ptime& origintime) const
{
  try
  {
    std::list<MetaData> props;

    const auto producerpos = itsProducers.find(producer);
    if (producerpos == itsProducers.end())
      return props;

    const auto& models = producerpos->second;
    const auto modelpos = models.find(origintime);

    if (modelpos == models.end())
      return props;

    QImpl q(modelpos->second);
    props.push_back(q.metaData());

    return props;
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

std::list<MetaData> Repository::getRepoMetadata() const
{
  try
  {
    std::list<MetaData> props;

    for (const auto& producer_models : itsProducers)
    {
      const auto& models = producer_models.second;

      for (const auto& origintime_model : models)
      {
        QImpl q(origintime_model.second);
        props.push_back(q.metaData());
      }
    }

    return props;
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

Repository::MetaObject Repository::getSynchroInfos() const
{
  try
  {
    Repository::MetaObject props;

    for (const auto& prodit : itsProducers)
    {
      const SharedModels& theseModels = prodit.second;

      const ProducerConfig thisConfig = itsProducerConfigs.find(prodit.first)->second;

      std::vector<bp::ptime> originTimes;

      for (const auto& modit : theseModels)
      {
        // Get querydata origintime

        originTimes.push_back(modit.first);
      }

      props.insert(std::make_pair(thisConfig.producer, originTimes));
    }

    return props;
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

SharedModel Repository::getModel(const Producer& producer,
                                 const boost::filesystem::path& path) const
{
  try
  {
    const auto producer_model = itsProducers.find(producer);

    if (producer_model == itsProducers.end())
      return {};

    const auto& models = producer_model->second;

    for (const auto& origintime_model : models)
    {
      const auto& model = origintime_model.second;
      if (model->path() == path)
        return model;
    }

    return {};
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

Repository::SharedModels Repository::getAllModels(const Producer& producer) const
{
  try
  {
    const auto producer_model = itsProducers.find(producer);

    if (producer_model == itsProducers.end())
      return SharedModels();

    return producer_model->second;
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

void Repository::updateProducerStatus(const std::string& producer,
                                      const boost::posix_time::ptime& scanTime,
                                      const boost::posix_time::ptime& nextScanTime)
{
  ProducerStatus& ps = itsProducerStatus[producer];
  ps.latest_scan_time = scanTime;
  ps.next_scan_time = nextScanTime;
}

void Repository::updateProducerStatus(const std::string& producer,
                                      const boost::posix_time::ptime& dataLoadTime,
                                      unsigned int nFiles)
{
  ProducerStatus& ps = itsProducerStatus[producer];
  ps.latest_data_load_time = dataLoadTime;
  ps.number_of_loaded_files = nFiles;
}

void Repository::verbose(bool flag)
{
  itsVerbose = flag;
}

}  // namespace Querydata
}  // namespace Engine
}  // namespace SmartMet

// ======================================================================

max_stars_repo_name: fmidev/smartmet-engine-querydata

max_issues_repo_name: fmidev/smartmet-engine-querydata

max_forks_repo_name: fmidev/smartmet-engine-querydata


text:
//
//  Copyright (C) 2012 Danny Havenith
//
//  Distributed under the Boost Software License, Version 1.0. (See
//  accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//

#include <vector>
#include <iostream>
#include <iterator>

#include <boost/config/warning_disable.hpp>

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/qi_binary.hpp>

#include "include/midi_parser.hpp"
#include "next_directive.hpp"
#include "midi_events_fusion.hpp"
#include "midi_file_fusion.hpp"

using namespace boost::spirit;
using namespace boost::spirit::qi;

/// Grammar for midi files.
/// This grammar can be used to parse midi files. It generates a midi_file struct from the contents of the file.
template<typename Iterator>
struct midi_parser: grammar< Iterator, midi_file()>
{
    midi_parser() :
        midi_parser::base_type( file),
            running_status(-1)
    {
        using boost::spirit::ascii::char_;
        using boost::phoenix::ref;
        using boost::phoenix::at_c;
        using boost::spirit::qi::rule;

        // a midi file consists of a header chunk followed by zero or more track chunks
        file
            %= header >> *track
            ;

        // a header chunk consist of the signature 'MThd' followed by the chunk size (6)
        // The three words of the header are: format, number of tracks and a time division value.
        header
            %= lit("MThd") >> big_dword(6) >> big_word >> big_word >> big_word
            ;

        // a track consists of the signature 'MTrk', followed by the chunk size (assigned to _a), followed by
        // timed midi events. The subrange directive is used to limit the parsing to only those bytes
        // that fall within the chunk (-size).
        track
            %= lit("MTrk") >>  omit[ big_dword[_a = _1]] >> next(_a)[+timed_event]
            ;

        // a 'timed event' consist of a time stamp (the time between this event and the previous one) and a midi event
        timed_event
            %= variable_length_quantity >> event
            ;

        // midi events are either sysex events, meta-events or 'channel events'.
        event
            %= sysex_event | meta_event | channel_event
            ;

        // a meta-event starts with 0xFF, followed by an event type, followed by a size indicator followed by the indicated amount of bytes.
        meta_event
            %= omit[char_('\xff')] >> byte_ >> omit[variable_length_quantity[ _a = _1]] >> repeat(_a)[byte_]
            ;

        // a sysex event starts with 0xF7 or 0xF0, followed by a size, followed by the indicated amount of bytes.
        sysex_event
            = (char_('\xf0') | char_('\xf7')) >> variable_length_quantity[ _a = _1] >> repeat(_a)[byte_]
            ;

        // a variable length quantity consist of zero or more bytes with the high bit set, followed by a single byte with a zero most significant bit.
        variable_length_quantity
            = eps[_val = 0] >> *high_byte[_val = (_val << 7) + (_1 & 0x7f)] >> low_byte[_val = (_val << 7) + _1]
            ;

        // channel events use a running status scheme, where the first byte of the event can be skipped if it is the same as the previous event.
        // if there's a high_byte, that will be the new event/channel and we store it in running_status.
        // if there isn't, we use the running status (the previously seen event).
        channel_event
            =  omit[-high_byte[ref(running_status) = _1]] >>
                    (
                        note_off_event
                    |   note_on_event
                    |   note_aftertouch_event
                    |   controller_event
                    |   program_change_event
                    |   channel_aftertouch_event
                    |   pitch_bend_event
                    )
                    [
                        at_c<1>(_val) = _1
                    ]
                    [
                        at_c<0>(_val) = ref(running_status) & 0x0f
                    ]
            ;

        // Now follow the rules for the channel events (note-on, note-off, aftertouch, etc.).
        // Note that the first byte of the event has already been read by the channel_event rule and stored in
        // running_status. That is why all these rules first check the running status in an epsilon parser. These epsilon
        // parsers act as a condition and should be read as "if ( (running_status & 0xf0) == some value) { parse the event } else { don't parse }
        note_on_event
            %=  eps( (ref(running_status) & 0xf0) == 0x90) >> byte_ >> byte_
            ;

        note_off_event
            %=  eps( (ref(running_status) & 0xf0) == 0x80) >> byte_ >> byte_
            ;

        note_aftertouch_event
            %=  eps( (ref(running_status) & 0xf0) == 0xa0) >> byte_ >> byte_
            ;

        controller_event
            %=  eps( (ref(running_status) & 0xf0) == 0xb0) >> byte_ >> byte_
            ;

        program_change_event
            %=  eps( (ref(running_status) & 0xf0) == 0xc0) >>  byte_
            ;

        channel_aftertouch_event
            %=  eps( (ref(running_status) & 0xf0) == 0xd0) >>  byte_
            ;

        // note how the pitch bend value is little endian
        pitch_bend_event
            %=  eps( (ref(running_status) & 0xf0) == 0xe0) >> little_word;

        // convenience rules to distinguish between low bytes (0-127) and high bytes (128-255).
        low_byte
            %= char_( '\x00', '\x7f')
            ;

        high_byte
            %= char_( '\x80', '\xff')
            ;
    }

    int running_status;

    rule<Iterator, unsigned char()      >           high_byte;
    rule<Iterator, unsigned char()      >           low_byte;
    rule<Iterator, midi_file()          >           file;
    rule<Iterator, midi_header()        >           header;
    rule<Iterator, midi_track(size_t)   >           track_data;
    rule<Iterator, events::timed_midi_event()>      timed_event;
    rule<Iterator, events::midi_event()        >           event;
    rule<Iterator, events::pitch_bend() >           pitch_bend_event;
    rule<Iterator, size_t()             >           variable_length_quantity;
    rule<Iterator, events::note_off()       >       note_off_event;
    rule<Iterator, events::note_on()        >       note_on_event;
    rule<Iterator, events::note_aftertouch()>       note_aftertouch_event;
    rule<Iterator, events::controller()     >       controller_event;
    rule<Iterator, events::program_change() >       program_change_event;
    rule<Iterator, events::channel_aftertouch()>    channel_aftertouch_event;
    rule<Iterator, midi_track(),            locals<size_t>  > track;
    rule<Iterator, events::sysex(),         locals<size_t>  > sysex_event;
    rule<Iterator, events::meta(),          locals<size_t>  > meta_event;
    rule<Iterator, events::channel_event(), locals<unsigned int>     > channel_event;
};

/// parse the midi file that the istream 'in' refers to and return the result in a midi_file structure
/// Note that on some platforms the input file must have been opened as binary.
bool parse_midifile( std::istream &in, midi_file &result)
{

    result.tracks.clear();

    // don't skip whitespaces.
    in.unsetf( std::ios_base::skipws);

    // copy the whole file into a string.
    typedef std::istreambuf_iterator<char> base_iterator;
    typedef std::vector<unsigned char> buffer_type;
    typedef buffer_type::iterator iterator;
    buffer_type buffer;
    buffer.assign( base_iterator(in), base_iterator());

    // parse the string
    midi_parser<iterator> parser;
    iterator first = buffer.begin();
    iterator last = buffer.end();

    boost::spirit::qi::parse( first, last, parser, result);

    return first == last;
}

ext: cpp

max_stars_repo_name: DannyHavenith/miditool

max_issues_repo_name: DannyHavenith/miditool

max_forks_repo_name: DannyHavenith/miditool


text:
/*
 Copyright 2011 Basho Technologies, Inc.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

#define BOOST_TEST_MODULE pbc_test
#include <boost/test/unit_test.hpp>
#include <riak_client/cxx/riak_client.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <algorithm>
#include <cstdio>

using std::string;

static const std::string TEST_BUCKET("riak-cxx-test");
static const std::string TEST_KEY("riak-cxx-test");

BOOST_AUTO_TEST_CASE (test_pbc_client)
{
    riak::client_ptr c = riak::new_client("127.0.0.1", "8087");
    bool ping = c->ping();
    BOOST_REQUIRE(ping);
    c->client_id(42);
    BOOST_REQUIRE(c->client_id() == 42);
}

BOOST_AUTO_TEST_CASE (test_set_bucket)
{
    riak::client_ptr c = riak::new_client("127.0.0.1", "8087");
    riak::bucket_properties properties;
    properties.allow_mult(true);
    properties.n_val(3);
    BOOST_REQUIRE(c->set_bucket(TEST_BUCKET, properties) == true);
}

BOOST_AUTO_TEST_CASE (test_fetch_bucket)
{
    riak::client_ptr c = riak::new_client("127.0.0.1", "8087");
    riak::bucket_properties result = c->fetch_bucket(TEST_BUCKET);
    BOOST_REQUIRE(result.allow_mult());
    BOOST_REQUIRE(result.n_val() == 3);
}

BOOST_AUTO_TEST_CASE (test_put)
{
    std::cout << riak::tss_client_id() << std::endl;
    riak::client_ptr c = riak::new_client("127.0.0.1", "8087");
    c->client_id(42);
    riak::store_params sp;
    sp.w(3).dw(3).return_body(true);
    riak::result_ptr fetch_result = c->fetch(TEST_BUCKET, TEST_KEY, 2);
    riak::object_ptr o;
    if (fetch_result->not_found())
    {
        o = riak::make_object(TEST_BUCKET, TEST_KEY, TEST_KEY);
        riak::link_vector v = o->update_content().links();
        v.push_back(riak::link("foo", "bar", "baz"));
        o->update_content().links(v);
    }
    else
        o = fetch_result->choose_sibling(0);
    riak::string_map usermeta(o->update_metadata().usermeta());
    usermeta["foo"] = "bar";
    riak::riak_metadata md(usermeta);
    o->update_metadata(md);
    riak::result_ptr r(c->store(o, sp));
    riak::object_ptr o2(r->choose_sibling(0));
}

BOOST_AUTO_TEST_CASE (test_fetch)
{
    riak::client_ptr c(riak::new_client("127.0.0.1", "8087"));
    riak::result_ptr fr(c->fetch(TEST_BUCKET, TEST_KEY, 3));
    BOOST_REQUIRE(fr->contents()[0].value() == TEST_KEY);
}

BOOST_AUTO_TEST_CASE (test_list_buckets)
{
    riak::client_ptr c = riak::new_client("127.0.0.1", "8087");
    riak::string_vector v = c->list_buckets();
    BOOST_REQUIRE(std::find(v.begin(), v.end(), TEST_BUCKET) != v.end());
}

BOOST_AUTO_TEST_CASE (test_list_keys)
{
    riak::client_ptr c = riak::new_client("127.0.0.1", "8087");
    riak::string_vector v = c->list_keys(TEST_BUCKET);
    BOOST_REQUIRE(v.size() > 0);
}

BOOST_AUTO_TEST_CASE (test_del)
{
    riak::client_ptr c = riak::new_client("127.0.0.1", "8087");
    riak::string_vector v = c->list_keys(TEST_BUCKET);
    for (riak::string_vector::size_type i=0;
         i < v.size(); ++i)
    {
        BOOST_REQUIRE(c->del(TEST_BUCKET, v[i], 3) == true);
    }
}

BOOST_AUTO_TEST_CASE (test_client)
{
    riak::cluster cluster;
    riak::client client(cluster.make_client());
    riak::basic_bucket<std::string> bucket = client.bucket<std::string>("bucket");
    bucket.del("foo").rw(2)();
    std::string value = bucket.fetch("foo").r(3)();
    BOOST_REQUIRE(value == "");
    value = bucket.store("foo", "bar")
        .r(2)
        .w(2)
        .dw(2)();
    value = bucket.fetch("foo").r(3)();
    BOOST_REQUIRE(value == "bar");
}

max_stars_repo_name: basho-labs/riak-cxx-client

max_issues_repo_name: basho-labs/riak-cxx-client

max_forks_repo_name: basho-labs/riak-cxx-client


text:
// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#include <boost/metaparse/v1/impl/back_inserter.hpp>

#include <boost/mpl/assert.hpp>
#include <boost/mpl/equal.hpp>
#include <boost/mpl/deque.hpp>

#include "test_case.hpp"

BOOST_METAPARSE_TEST_CASE(back_inserter)
{
  using boost::metaparse::v1::impl::back_inserter;

  using boost::mpl::equal;
  using boost::mpl::deque;

  // test_inserts_at_the_back
  BOOST_MPL_ASSERT((
    equal<deque<int, char>, back_inserter::apply<deque<int>, char>::type>
  ));
}


text:
/** @file
    @brief Implementation

    @date 2014

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>

*/

// Copyright 2014 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef __ANDROID__
#define OSVR_DEV_VERBOSE_DISABLE
#endif

// Internal Includes
#include <osvr/PluginHost/RegistrationContext.h>
#include <osvr/PluginHost/SearchPath.h>
#include <osvr/PluginHost/PathConfig.h>
#include "PluginSpecificRegistrationContextImpl.h"
#include <osvr/Util/Verbosity.h>

// Library/third-party includes
#include <libfunctionality/LoadPlugin.h>
#include <boost/filesystem.hpp>
#include <boost/range/adaptor/map.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include <boost/algorithm/string/predicate.hpp>

// Standard includes
#include <algorithm>
#include <iterator>

namespace osvr {
namespace pluginhost {
    RegistrationContext::RegistrationContext() {}

    RegistrationContext::~RegistrationContext() {
        // Reset the plugins in reverse order.
        for (auto &ptr : m_regMap | boost::adaptors::map_values |
                             boost::adaptors::reversed) {
            ptr.reset();
        }
    }

    static inline bool tryLoadingPlugin(libfunc::PluginHandle &plugin,
                                        std::string const &name,
                                        OSVR_PluginRegContext ctx,
                                        bool shouldRethrow = false) {
        OSVR_DEV_VERBOSE("Trying to load a plugin with the name " << name);
        try {
            plugin = libfunc::loadPluginByName(name, ctx);
            return true;
        } catch (std::runtime_error const &e) {
            OSVR_DEV_VERBOSE("Failed: " << e.what());
            if (shouldRethrow) {
                throw;
            }
            return false;
        } catch (...) {
            throw;
        }
    }

    void RegistrationContext::loadPlugin(std::string const &pluginName) {
        const std::string pluginPathName = pluginhost::findPlugin(pluginName);
        if (pluginPathName.empty()) {
            throw std::runtime_error("Could not find plugin named " +
                                     pluginName);
        }

        const std::string pluginPathNameNoExt =
            (boost::filesystem::path(pluginPathName).parent_path() /
             boost::filesystem::path(pluginPathName).stem()).generic_string();
        PluginRegPtr pluginReg(
            PluginSpecificRegistrationContext::create(pluginName));
        pluginReg->setParent(*this);

        libfunc::PluginHandle plugin;
        auto ctx = pluginReg->extractOpaquePointer();

        bool success = tryLoadingPlugin(plugin, pluginPathName, ctx) ||
                       tryLoadingPlugin(plugin, pluginPathNameNoExt, ctx, true);
        if (!success) {
            throw std::runtime_error(
                "Unusual error occurred trying to load plugin named " +
                pluginName);
        }

        pluginReg->takePluginHandle(plugin);
        adoptPluginRegistrationContext(pluginReg);
    }

    void RegistrationContext::loadPlugins() {
        // Build a list of all the plugins we can find
        auto pluginPaths = pluginhost::getPluginSearchPath();
        auto pluginPathNames =
            pluginhost::getAllFilesWithExt(pluginPaths, OSVR_PLUGIN_EXTENSION);

        // Load all of the non-.manualload plugins
        for (const auto &plugin : pluginPathNames) {
            OSVR_DEV_VERBOSE("Examining plugin '" << plugin << "'...");
            const std::string pluginBaseName = boost::filesystem::path(plugin)
                                                   .filename()
                                                   .stem()
                                                   .generic_string();
            if (boost::iends_with(pluginBaseName, OSVR_PLUGIN_IGNORE_SUFFIX)) {
                OSVR_DEV_VERBOSE(
                    "Ignoring manual-load plugin: " << pluginBaseName);
                continue;
            }

            try {
                loadPlugin(pluginBaseName);
                OSVR_DEV_VERBOSE(
                    "Successfully loaded plugin: " << pluginBaseName);
            } catch (const std::exception &e) {
                OSVR_DEV_VERBOSE("Failed to load plugin " << pluginBaseName
                                                          << ": " << e.what());
            } catch (...) {
                OSVR_DEV_VERBOSE("Failed to load plugin "
                                 << pluginBaseName << ": Unknown error.");
            }
        }
    }

    void RegistrationContext::adoptPluginRegistrationContext(PluginRegPtr ctx) {
        /// This set parent might be a duplicate, but won't be if the plugin reg
        /// ctx is not created by loadPlugin above.
        ctx->setParent(*this);

        m_regMap.insert(std::make_pair(ctx->getName(), ctx));
    }

    void RegistrationContext::triggerHardwareDetect() {
        for (auto &pluginPtr : m_regMap | boost::adaptors::map_values) {
            pluginPtr->triggerHardwareDetectCallbacks();
        }
    }

    void
    RegistrationContext::instantiateDriver(const std::string &pluginName,
                                           const std::string &driverName,
                                           const std::string &params) const {
        auto pluginIt = m_regMap.find(pluginName);
        if (pluginIt == end(m_regMap)) {
            throw std::runtime_error("Could not find plugin named " +
                                     pluginName);
        }
        pluginIt->second->instantiateDriver(driverName, params);
    }

    util::AnyMap &RegistrationContext::data() { return m_data; }

    util::AnyMap const &RegistrationContext::data() const { return m_data; }
} // namespace pluginhost
} // namespace osvr


text:
/* auc_test.cc
   Jeremy Barnes, 9 November 2009
   Copyright (c) 2009 Jeremy Barnes.  All rights reserved.

   Test for AUC functionality.
*/

#define BOOST_TEST_MAIN
#define BOOST_TEST_DYN_LINK

#include "jml/utils/info.h"
#include "jml/utils/environment.h"

#include <boost/test/unit_test.hpp>
#include <iostream>

#include "jml/stats/auc.h"

using namespace ML;
using namespace std;

using boost::unit_test::test_suite;

BOOST_AUTO_TEST_CASE( test1 )
{
}

ext: cc

max_stars_repo_name: etnrlz/rtbkit

max_issues_repo_name: TuanTranEngineer/rtbkit

max_forks_repo_name: TuanTranEngineer/rtbkit


text:
/*!
@file
Forward declares `boost::hana::mult`.

@copyright Louis Dionne 2013-2017
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
 */

#ifndef BOOST_HANA_FWD_MULT_HPP
#define BOOST_HANA_FWD_MULT_HPP

#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>

BOOST_HANA_NAMESPACE_BEGIN
    //! Associative operation of a `Ring`.
    //! @ingroup group-Ring
    //!
    //! @param x, y
    //! Two `Ring` elements to combine with the `Ring` binary operation.
    //!
    //!
    //! Cross-type version of the method
    //! --------------------------------
    //! The `mult` method is "overloaded" to handle distinct data types
    //! with certain properties. Specifically, `mult` is defined for
    //! _distinct_ data types `A` and `B` such that
    //! 1. `A` and `B` share a common data type `C`, as determined by the
    //!    `common` metafunction
    //! 2. `A`, `B` and `C` are all `Ring`s when taken individually
    //! 3. `to<C> : A -> B` and `to<C> : B -> C` are `Ring`-embeddings, as
    //!    determined by the `is_embedding` metafunction.
    //!
    //! The definition of `mult` for data types satisfying the above
    //! properties is obtained by setting
    //! @code
    //!     mult(x, y) = mult(to<C>(x), to<C>(y))
    //! @endcode
    //!
    //!
    //! Example
    //! -------
    //! @include example/mult.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
    constexpr auto mult = [](auto&& x, auto&& y) -> decltype(auto) {
        return tag-dispatched;
    };
#else
    template <typename T, typename U, typename = void>
    struct mult_impl : mult_impl<T, U, when<true>> { };

    struct mult_t {
        template <typename X, typename Y>
        constexpr decltype(auto) operator()(X&& x, Y&& y) const;
    };

    constexpr mult_t mult{};
#endif
BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_FWD_MULT_HPP

ext: hpp


text:
// copyright (c) 2010 satoshi nakamoto
// copyright (c) 2009-2014 the moorecoin core developers
// distributed under the mit software license, see the accompanying
// file copying or http://www.opensource.org/licenses/mit-license.php.

#include "amount.h"
#include "chainparams.h"
#include "consensus/consensus.h"
#include "consensus/validation.h"
#include "core_io.h"
#include "init.h"
#include "main.h"
#include "miner.h"
#include "net.h"
#include "pow.h"
#include "rpcserver.h"
#include "util.h"
#include "validationinterface.h"
#ifdef enable_wallet
#include "wallet/wallet.h"
#endif

#include <stdint.h>

#include <boost/assign/list_of.hpp>

#include "univalue/univalue.h"

using namespace std;

/**
 * return average network hashes per second based on the last 'lookup' blocks,
 * or from the last difficulty change if 'lookup' is nonpositive.
 * if 'height' is nonnegative, compute the estimate at the time when a given block was found.
 */
univalue getnetworkhashps(int lookup, int height) {
    cblockindex *pb = chainactive.tip();

    if (height >= 0 && height < chainactive.height())
        pb = chainactive[height];

    if (pb == null || !pb->nheight)
        return 0;

    // if lookup is -1, then use blocks since last difficulty change.
    if (lookup <= 0)
        lookup = pb->nheight % params().getconsensus().difficultyadjustmentinterval() + 1;

    // if lookup is larger than chain, then set it to chain length.
    if (lookup > pb->nheight)
        lookup = pb->nheight;

    cblockindex *pb0 = pb;
    int64_t mintime = pb0->getblocktime();
    int64_t maxtime = mintime;
    for (int i = 0; i < lookup; i++) {
        pb0 = pb0->pprev;
        int64_t time = pb0->getblocktime();
        mintime = std::min(time, mintime);
        maxtime = std::max(time, maxtime);
    }

    // in case there's a situation where mintime == maxtime, we don't want a divide by zero exception.
    if (mintime == maxtime)
        return 0;

    arith_uint256 workdiff = pb->nchainwork - pb0->nchainwork;
    int64_t timediff = maxtime - mintime;

    return (int64_t)(workdiff.getdouble() / timediff);
}

univalue getnetworkhashps(const univalue& params, bool fhelp)
{
    if (fhelp || params.size() > 2)
        throw runtime_error(
            "getnetworkhashps ( blocks height )\n"
            "\nreturns the estimated network hashes per second based on the last n blocks.\n"
            "pass in [blocks] to override # of blocks, -1 specifies since last difficulty change.\n"
            "pass in [height] to estimate the network speed at the time when a certain block was found.\n"
            "\narguments:\n"
            "1. blocks     (numeric, optional, default=120) the number of blocks, or -1 for blocks since last difficulty change.\n"
            "2. height     (numeric, optional, default=-1) to estimate at the time of the given height.\n"
            "\nresult:\n"
            "x             (numeric) hashes per second estimated\n"
            "\nexamples:\n"
            + helpexamplecli("getnetworkhashps", "")
            + helpexamplerpc("getnetworkhashps", "")
       );

    lock(cs_main);
    return getnetworkhashps(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
}

#ifdef enable_wallet
univalue getgenerate(const univalue& params, bool fhelp)
{
    if (fhelp || params.size() != 0)
        throw runtime_error(
            "getgenerate\n"
            "\nreturn if the server is set to generate coins or not. the default is false.\n"
            "it is set with the command line argument -gen (or moorecoin.conf setting gen)\n"
            "it can also be set with the setgenerate call.\n"
            "\nresult\n"
            "true|false      (boolean) if the server is set to generate coins or not\n"
            "\nexamples:\n"
            + helpexamplecli("getgenerate", "")
            + helpexamplerpc("getgenerate", "")
        );

    lock(cs_main);
    return getboolarg("-gen", false);
}

univalue generate(const univalue& params, bool fhelp)
{
    if (fhelp || params.size() < 1 || params.size() > 1)
        throw runtime_error(
            "generate numblocks\n"
            "\nmine blocks immediately (before the rpc call returns)\n"
            "\nnote: this function can only be used on the regtest network\n"
            "1. numblocks    (numeric) how many blocks are generated immediately.\n"
            "\nresult\n"
            "[ blockhashes ]     (array) hashes of blocks generated\n"
            "\nexamples:\n"
            "\ngenerate 11 blocks\n"
            + helpexamplecli("generate", "11")
        );

    if (pwalletmain == null)
        throw jsonrpcerror(rpc_method_not_found, "method not found (disabled)");
    if (!params().mineblocksondemand())
        throw jsonrpcerror(rpc_method_not_found, "this method can only be used on regtest");

    int nheightstart = 0;
    int nheightend = 0;
    int nheight = 0;
    int ngenerate = params[0].get_int();
    creservekey reservekey(pwalletmain);

    {   // don't keep cs_main locked
        lock(cs_main);
        nheightstart = chainactive.height();
        nheight = nheightstart;
        nheightend = nheightstart+ngenerate;
    }
    unsigned int nextranonce = 0;
    univalue blockhashes(univalue::varr);
    while (nheight < nheightend)
    {
        auto_ptr<cblocktemplate> pblocktemplate(createnewblockwithkey(reservekey));
        if (!pblocktemplate.get())
            throw jsonrpcerror(rpc_internal_error, "wallet keypool empty");
        cblock *pblock = &pblocktemplate->block;
        {
            lock(cs_main);
            incrementextranonce(pblock, chainactive.tip(), nextranonce);
        }
        while (!checkproofofwork(pblock->gethash(), pblock->nbits, params().getconsensus())) {
            // yes, there is a chance every nonce could fail to satisfy the -regtest
            // target -- 1 in 2^(2^32). that ain't gonna happen.
            ++pblock->nnonce;
        }
        cvalidationstate state;
        if (!processnewblock(state, null, pblock, true, null))
            throw jsonrpcerror(rpc_internal_error, "processnewblock, block not accepted");
        ++nheight;
        blockhashes.push_back(pblock->gethash().gethex());
    }
    return blockhashes;
}

univalue setgenerate(const univalue& params, bool fhelp)
{
    if (fhelp || params.size() < 1 || params.size() > 2)
        throw runtime_error(
            "setgenerate generate ( genproclimit )\n"
            "\nset 'generate' true or false to turn generation on or off.\n"
            "generation is limited to 'genproclimit' processors, -1 is unlimited.\n"
            "see the getgenerate call for the current setting.\n"
            "\narguments:\n"
            "1. generate         (boolean, required) set to true to turn on generation, off to turn off.\n"
            "2. genproclimit     (numeric, optional) set the processor limit for when generation is on. can be -1 for unlimited.\n"
            "\nexamples:\n"
            "\nset the generation on with a limit of one processor\n"
            + helpexamplecli("setgenerate", "true 1") +
            "\ncheck the setting\n"
            + helpexamplecli("getgenerate", "") +
            "\nturn off generation\n"
            + helpexamplecli("setgenerate", "false") +
            "\nusing json rpc\n"
            + helpexamplerpc("setgenerate", "true, 1")
        );

    if (pwalletmain == null)
        throw jsonrpcerror(rpc_method_not_found, "method not found (disabled)");
    if (params().mineblocksondemand())
        throw jsonrpcerror(rpc_method_not_found, "use the generate method instead of setgenerate on this network");

    bool fgenerate = true;
    if (params.size() > 0)
        fgenerate = params[0].get_bool();

    int ngenproclimit = -1;
    if (params.size() > 1)
    {
        ngenproclimit = params[1].get_int();
        if (ngenproclimit == 0)
            fgenerate = false;
    }

    mapargs["-gen"] = (fgenerate ? "1" : "0");
    mapargs ["-genproclimit"] = itostr(ngenproclimit);
    generatemoorecoins(fgenerate, pwalletmain, ngenproclimit);

    return nullunivalue;
}
#endif

univalue getmininginfo(const univalue& params, bool fhelp)
{
    if (fhelp || params.size() != 0)
        throw runtime_error(
            "getmininginfo\n"
            "\nreturns a json object containing mining-related information."
            "\nresult:\n"
            "{\n"
            "  \"blocks\": nnn,             (numeric) the current block\n"
            "  \"currentblocksize\": nnn,   (numeric) the last block size\n"
            "  \"currentblocktx\": nnn,     (numeric) the last block transaction\n"
            "  \"difficulty\": xxx.xxxxx    (numeric) the current difficulty\n"
            "  \"errors\": \"...\"          (string) current errors\n"
            "  \"generate\": true|false     (boolean) if the generation is on or off (see getgenerate or setgenerate calls)\n"
            "  \"genproclimit\": n          (numeric) the processor limit for generation. -1 if no generation. (see getgenerate or setgenerate calls)\n"
            "  \"pooledtx\": n              (numeric) the size of the mem pool\n"
            "  \"testnet\": true|false      (boolean) if using testnet or not\n"
            "  \"chain\": \"xxxx\",         (string) current network name as defined in bip70 (main, test, regtest)\n"
            "}\n"
            "\nexamples:\n"
            + helpexamplecli("getmininginfo", "")
            + helpexamplerpc("getmininginfo", "")
        );

    lock(cs_main);

    univalue obj(univalue::vobj);
    obj.push_back(pair("blocks",           (int)chainactive.height()));
    obj.push_back(pair("currentblocksize", (uint64_t)nlastblocksize));
    obj.push_back(pair("currentblocktx",   (uint64_t)nlastblocktx));
    obj.push_back(pair("difficulty",       (double)getdifficulty()));
    obj.push_back(pair("errors",           getwarnings("statusbar")));
    obj.push_back(pair("genproclimit",     (int)getarg("-genproclimit", -1)));
    obj.push_back(pair("networkhashps",    getnetworkhashps(params, false)));
    obj.push_back(pair("pooledtx",         (uint64_t)mempool.size()));
    obj.push_back(pair("testnet",          params().testnettobedeprecatedfieldrpc()));
    obj.push_back(pair("chain",            params().networkidstring()));
#ifdef enable_wallet
    obj.push_back(pair("generate",         getgenerate(params, false)));
#endif
    return obj;
}

// note: unlike wallet rpc (which use btc values), mining rpcs follow gbt (bip 22) in using satoshi amounts
univalue prioritisetransaction(const univalue& params, bool fhelp)
{
    if (fhelp || params.size() != 3)
        throw runtime_error(
            "prioritisetransaction <txid> <priority delta> <fee delta>\n"
            "accepts the transaction into mined blocks at a higher (or lower) priority\n"
            "\narguments:\n"
            "1. \"txid\"       (string, required) the transaction id.\n"
            "2. priority delta (numeric, required) the priority to add or subtract.\n"
            "                  the transaction selection algorithm considers the tx as it would have a higher priority.\n"
            "                  (priority of a transaction is calculated: coinage * value_in_satoshis / txsize) \n"
            "3. fee delta      (numeric, required) the fee value (in satoshis) to add (or subtract, if negative).\n"
            "                  the fee is not actually paid, only the algorithm for selecting transactions into a block\n"
            "                  considers the transaction as it would have paid a higher (or lower) fee.\n"
            "\nresult\n"
            "true              (boolean) returns true\n"
            "\nexamples:\n"
            + helpexamplecli("prioritisetransaction", "\"txid\" 0.0 10000")
            + helpexamplerpc("prioritisetransaction", "\"txid\", 0.0, 10000")
        );

    lock(cs_main);

    uint256 hash = parsehashstr(params[0].get_str(), "txid");
    camount namount = params[2].get_int64();

    mempool.prioritisetransaction(hash, params[0].get_str(), params[1].get_real(), namount);
    return true;
}

// note: assumes a conclusive result; if result is inconclusive, it must be handled by caller
static univalue bip22validationresult(const cvalidationstate& state)
{
    if (state.isvalid())
        return nullunivalue;

    std::string strrejectreason = state.getrejectreason();
    if (state.iserror())
        throw jsonrpcerror(rpc_verify_error, strrejectreason);
    if (state.isinvalid())
    {
        if (strrejectreason.empty())
            return "rejected";
        return strrejectreason;
    }
    // should be impossible
    return "valid?";
}

univalue getblocktemplate(const univalue& params, bool fhelp)
{
    if (fhelp || params.size() > 1)
        throw runtime_error(
            "getblocktemplate ( \"jsonrequestobject\" )\n"
            "\nif the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n"
            "it returns data needed to construct a block to work on.\n"
            "see https://en.moorecoin.it/wiki/bip_0022 for full specification.\n"

            "\narguments:\n"
            "1. \"jsonrequestobject\"       (string, optional) a json object in the following spec\n"
            "     {\n"
            "       \"mode\":\"template\"    (string, optional) this must be set to \"template\" or omitted\n"
            "       \"capabilities\":[       (array, optional) a list of strings\n"
            "           \"support\"           (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n"
            "           ,...\n"
            "         ]\n"
            "     }\n"
            "\n"

            "\nresult:\n"
            "{\n"
            "  \"version\" : n,                    (numeric) the block version\n"
            "  \"previousblockhash\" : \"xxxx\",    (string) the hash of current highest block\n"
            "  \"transactions\" : [                (array) contents of non-coinbase transactions that should be included in the next block\n"
            "      {\n"
            "         \"data\" : \"xxxx\",          (string) transaction data encoded in hexadecimal (byte-for-byte)\n"
            "         \"hash\" : \"xxxx\",          (string) hash/id encoded in little-endian hexadecimal\n"
            "         \"depends\" : [              (array) array of numbers \n"
            "             n                        (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n"
            "             ,...\n"
            "         ],\n"
            "         \"fee\": n,                   (numeric) difference in value between transaction inputs and outputs (in satoshis); for coinbase transactions, this is a negative number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients must not assume there isn't one\n"
            "         \"sigops\" : n,               (numeric) total number of sigops, as counted for purposes of block limits; if key is not present, sigop count is unknown and clients must not assume there aren't any\n"
            "         \"required\" : true|false     (boolean) if provided and true, this transaction must be in the final block\n"
            "      }\n"
            "      ,...\n"
            "  ],\n"
            "  \"coinbaseaux\" : {                  (json object) data that should be included in the coinbase's scriptsig content\n"
            "      \"flags\" : \"flags\"            (string) \n"
            "  },\n"
            "  \"coinbasevalue\" : n,               (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in satoshis)\n"
            "  \"coinbasetxn\" : { ... },           (json object) information for coinbase transaction\n"
            "  \"target\" : \"xxxx\",               (string) the hash target\n"
            "  \"mintime\" : xxx,                   (numeric) the minimum timestamp appropriate for next block time in seconds since epoch (jan 1 1970 gmt)\n"
            "  \"mutable\" : [                      (array of string) list of ways the block template may be changed \n"
            "     \"value\"                         (string) a way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n"
            "     ,...\n"
            "  ],\n"
            "  \"noncerange\" : \"00000000ffffffff\",   (string) a range of valid nonces\n"
            "  \"sigoplimit\" : n,                 (numeric) limit of sigops in blocks\n"
            "  \"sizelimit\" : n,                  (numeric) limit of block size\n"
            "  \"curtime\" : ttt,                  (numeric) current timestamp in seconds since epoch (jan 1 1970 gmt)\n"
            "  \"bits\" : \"xxx\",                 (string) compressed target of next block\n"
            "  \"height\" : n                      (numeric) the height of the next block\n"
            "}\n"

            "\nexamples:\n"
            + helpexamplecli("getblocktemplate", "")
            + helpexamplerpc("getblocktemplate", "")
         );

    lock(cs_main);

    std::string strmode = "template";
    univalue lpval = nullunivalue;
    if (params.size() > 0)
    {
        const univalue& oparam = params[0].get_obj();
        const univalue& modeval = find_value(oparam, "mode");
        if (modeval.isstr())
            strmode = modeval.get_str();
        else if (modeval.isnull())
        {
            /* do nothing */
        }
        else
            throw jsonrpcerror(rpc_invalid_parameter, "invalid mode");
        lpval = find_value(oparam, "longpollid");

        if (strmode == "proposal")
        {
            const univalue& dataval = find_value(oparam, "data");
            if (!dataval.isstr())
                throw jsonrpcerror(rpc_type_error, "missing data string key for proposal");

            cblock block;
            if (!decodehexblk(block, dataval.get_str()))
                throw jsonrpcerror(rpc_deserialization_error, "block decode failed");

            uint256 hash = block.gethash();
            blockmap::iterator mi = mapblockindex.find(hash);
            if (mi != mapblockindex.end()) {
                cblockindex *pindex = mi->second;
                if (pindex->isvalid(block_valid_scripts))
                    return "duplicate";
                if (pindex->nstatus & block_failed_mask)
                    return "duplicate-invalid";
                return "duplicate-inconclusive";
            }

            cblockindex* const pindexprev = chainactive.tip();
            // testblockvalidity only supports blocks built on the current tip
            if (block.hashprevblock != pindexprev->getblockhash())
                return "inconclusive-not-best-prevblk";
            cvalidationstate state;
            testblockvalidity(state, block, pindexprev, false, true);
            return bip22validationresult(state);
        }
    }

    if (strmode != "template")
        throw jsonrpcerror(rpc_invalid_parameter, "invalid mode");

    if (vnodes.empty())
        throw jsonrpcerror(rpc_client_not_connected, "moorecoin is not connected!");

    if (isinitialblockdownload())
        throw jsonrpcerror(rpc_client_in_initial_download, "moorecoin is downloading blocks...");

    static unsigned int ntransactionsupdatedlast;

    if (!lpval.isnull())
    {
        // wait to respond until either the best block changes, or a minute has passed and there are more transactions
        uint256 hashwatchedchain;
        boost::system_time checktxtime;
        unsigned int ntransactionsupdatedlastlp;

        if (lpval.isstr())
        {
            // format: <hashbestchain><ntransactionsupdatedlast>
            std::string lpstr = lpval.get_str();

            hashwatchedchain.sethex(lpstr.substr(0, 64));
            ntransactionsupdatedlastlp = atoi64(lpstr.substr(64));
        }
        else
        {
            // note: spec does not specify behaviour for non-string longpollid, but this makes testing easier
            hashwatchedchain = chainactive.tip()->getblockhash();
            ntransactionsupdatedlastlp = ntransactionsupdatedlast;
        }

        // release the wallet and main lock while waiting
        leave_critical_section(cs_main);
        {
            checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);

            boost::unique_lock<boost::mutex> lock(csbestblock);
            while (chainactive.tip()->getblockhash() == hashwatchedchain && isrpcrunning())
            {
                if (!cvblockchange.timed_wait(lock, checktxtime))
                {
                    // timeout: check transactions for update
                    if (mempool.gettransactionsupdated() != ntransactionsupdatedlastlp)
                        break;
                    checktxtime += boost::posix_time::seconds(10);
                }
            }
        }
        enter_critical_section(cs_main);

        if (!isrpcrunning())
            throw jsonrpcerror(rpc_client_not_connected, "shutting down");
        // todo: maybe recheck connections/ibd and (if something wrong) send an expires-immediately template to stop miners?
    }

    // update block
    static cblockindex* pindexprev;
    static int64_t nstart;
    static cblocktemplate* pblocktemplate;
    if (pindexprev != chainactive.tip() ||
        (mempool.gettransactionsupdated() != ntransactionsupdatedlast && gettime() - nstart > 5))
    {
        // clear pindexprev so future calls make a new block, despite any failures from here on
        pindexprev = null;

        // store the pindexbest used before createnewblock, to avoid races
        ntransactionsupdatedlast = mempool.gettransactionsupdated();
        cblockindex* pindexprevnew = chainactive.tip();
        nstart = gettime();

        // create new block
        if(pblocktemplate)
        {
            delete pblocktemplate;
            pblocktemplate = null;
        }
        cscript scriptdummy = cscript() << op_true;
        pblocktemplate = createnewblock(scriptdummy);
        if (!pblocktemplate)
            throw jsonrpcerror(rpc_out_of_memory, "out of memory");

        // need to update only after we know createnewblock succeeded
        pindexprev = pindexprevnew;
    }
    cblock* pblock = &pblocktemplate->block; // pointer for convenience

    // update ntime
    updatetime(pblock, params().getconsensus(), pindexprev);
    pblock->nnonce = 0;

    univalue acaps(univalue::varr); acaps.push_back("proposal");

    univalue transactions(univalue::varr);
    map<uint256, int64_t> settxindex;
    int i = 0;
    boost_foreach (const ctransaction& tx, pblock->vtx) {
        uint256 txhash = tx.gethash();
        settxindex[txhash] = i++;

        if (tx.iscoinbase())
            continue;

        univalue entry(univalue::vobj);

        entry.push_back(pair("data", encodehextx(tx)));

        entry.push_back(pair("hash", txhash.gethex()));

        univalue deps(univalue::varr);
        boost_foreach (const ctxin &in, tx.vin)
        {
            if (settxindex.count(in.prevout.hash))
                deps.push_back(settxindex[in.prevout.hash]);
        }
        entry.push_back(pair("depends", deps));

        int index_in_template = i - 1;
        entry.push_back(pair("fee", pblocktemplate->vtxfees[index_in_template]));
        entry.push_back(pair("sigops", pblocktemplate->vtxsigops[index_in_template]));

        transactions.push_back(entry);
    }

    univalue aux(univalue::vobj);
    aux.push_back(pair("flags", hexstr(coinbase_flags.begin(), coinbase_flags.end())));

    arith_uint256 hashtarget = arith_uint256().setcompact(pblock->nbits);

    static univalue amutable(univalue::varr);
    if (amutable.empty())
    {
        amutable.push_back("time");
        amutable.push_back("transactions");
        amutable.push_back("prevblock");
    }

    univalue result(univalue::vobj);
    result.push_back(pair("capabilities", acaps));
    result.push_back(pair("version", pblock->nversion));
    result.push_back(pair("previousblockhash", pblock->hashprevblock.gethex()));
    result.push_back(pair("transactions", transactions));
    result.push_back(pair("coinbaseaux", aux));
    result.push_back(pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nvalue));
    result.push_back(pair("longpollid", chainactive.tip()->getblockhash().gethex() + i64tostr(ntransactionsupdatedlast)));
    result.push_back(pair("target", hashtarget.gethex()));
    result.push_back(pair("mintime", (int64_t)pindexprev->getmediantimepast()+1));
    result.push_back(pair("mutable", amutable));
    result.push_back(pair("noncerange", "00000000ffffffff"));
    result.push_back(pair("sigoplimit", (int64_t)max_block_sigops));
    result.push_back(pair("sizelimit", (int64_t)max_block_size));
    result.push_back(pair("curtime", pblock->getblocktime()));
    result.push_back(pair("bits", strprintf("%08x", pblock->nbits)));
    result.push_back(pair("height", (int64_t)(pindexprev->nheight+1)));

    return result;
}

class submitblock_statecatcher : public cvalidationinterface
{
public:
    uint256 hash;
    bool found;
    cvalidationstate state;

    submitblock_statecatcher(const uint256 &hashin) : hash(hashin), found(false), state() {};

protected:
    virtual void blockchecked(const cblock& block, const cvalidationstate& statein) {
        if (block.gethash() != hash)
            return;
        found = true;
        state = statein;
    };
};

univalue submitblock(const univalue& params, bool fhelp)
{
    if (fhelp || params.size() < 1 || params.size() > 2)
        throw runtime_error(
            "submitblock \"hexdata\" ( \"jsonparametersobject\" )\n"
            "\nattempts to submit new block to network.\n"
            "the 'jsonparametersobject' parameter is currently ignored.\n"
            "see https://en.moorecoin.it/wiki/bip_0022 for full specification.\n"

            "\narguments\n"
            "1. \"hexdata\"    (string, required) the hex-encoded block data to submit\n"
            "2. \"jsonparametersobject\"     (string, optional) object of optional parameters\n"
            "    {\n"
            "      \"workid\" : \"id\"    (string, optional) if the server provided a workid, it must be included with submissions\n"
            "    }\n"
            "\nresult:\n"
            "\nexamples:\n"
            + helpexamplecli("submitblock", "\"mydata\"")
            + helpexamplerpc("submitblock", "\"mydata\"")
        );

    cblock block;
    if (!decodehexblk(block, params[0].get_str()))
        throw jsonrpcerror(rpc_deserialization_error, "block decode failed");

    uint256 hash = block.gethash();
    bool fblockpresent = false;
    {
        lock(cs_main);
        blockmap::iterator mi = mapblockindex.find(hash);
        if (mi != mapblockindex.end()) {
            cblockindex *pindex = mi->second;
            if (pindex->isvalid(block_valid_scripts))
                return "duplicate";
            if (pindex->nstatus & block_failed_mask)
                return "duplicate-invalid";
            // otherwise, we might only have the header - process the block before returning
            fblockpresent = true;
        }
    }

    cvalidationstate state;
    submitblock_statecatcher sc(block.gethash());
    registervalidationinterface(&sc);
    bool faccepted = processnewblock(state, null, &block, true, null);
    unregistervalidationinterface(&sc);
    if (fblockpresent)
    {
        if (faccepted && !sc.found)
            return "duplicate-inconclusive";
        return "duplicate";
    }
    if (faccepted)
    {
        if (!sc.found)
            return "inconclusive";
        state = sc.state;
    }
    return bip22validationresult(state);
}

univalue estimatefee(const univalue& params, bool fhelp)
{
    if (fhelp || params.size() != 1)
        throw runtime_error(
            "estimatefee nblocks\n"
            "\nestimates the approximate fee per kilobyte\n"
            "needed for a transaction to begin confirmation\n"
            "within nblocks blocks.\n"
            "\narguments:\n"
            "1. nblocks     (numeric)\n"
            "\nresult:\n"
            "n :    (numeric) estimated fee-per-kilobyte\n"
            "\n"
            "-1.0 is returned if not enough transactions and\n"
            "blocks have been observed to make an estimate.\n"
            "\nexample:\n"
            + helpexamplecli("estimatefee", "6")
            );

    rpctypecheck(params, boost::assign::list_of(univalue::vnum));

    int nblocks = params[0].get_int();
    if (nblocks < 1)
        nblocks = 1;

    cfeerate feerate = mempool.estimatefee(nblocks);
    if (feerate == cfeerate(0))
        return -1.0;

    return valuefromamount(feerate.getfeeperk());
}

univalue estimatepriority(const univalue& params, bool fhelp)
{
    if (fhelp || params.size() != 1)
        throw runtime_error(
            "estimatepriority nblocks\n"
            "\nestimates the approximate priority\n"
            "a zero-fee transaction needs to begin confirmation\n"
            "within nblocks blocks.\n"
            "\narguments:\n"
            "1. nblocks     (numeric)\n"
            "\nresult:\n"
            "n :    (numeric) estimated priority\n"
            "\n"
            "-1.0 is returned if not enough transactions and\n"
            "blocks have been observed to make an estimate.\n"
            "\nexample:\n"
            + helpexamplecli("estimatepriority", "6")
            );

    rpctypecheck(params, boost::assign::list_of(univalue::vnum));

    int nblocks = params[0].get_int();
    if (nblocks < 1)
        nblocks = 1;

    return mempool.estimatepriority(nblocks);
}

max_stars_repo_name: moorecoin/MooreCoinMiningAlgorithm

max_issues_repo_name: moorecoin/MooreCoinMiningAlgorithm

max_forks_repo_name: moorecoin/MooreCoinMiningAlgorithm


text:
//
// Created by Dmitri Bagaev on 2019-03-22.
//

#include "bayesian.h"

#define USE_NLOPT

#include <nlopt.hpp>

#include <boost/parameter/aux_/void.hpp>

#include <limbo/opt/nlopt_no_grad.hpp>
#include <Eigen/Core>
#include <limbo/kernel/exp.hpp>
#include <limbo/kernel/squared_exp_ard.hpp>
#include <limbo/mean/function_ard.hpp>
#include <limbo/model/gp.hpp>
#include <limbo/model/gp/kernel_lf_opt.hpp>
#include <limbo/tools.hpp>
#include <limbo/tools/macros.hpp>
#include <limbo/bayes_opt/bo_base.hpp>
#include <limbo/bayes_opt/boptimizer.hpp>
#include <limbo/model/gp/kernel_mean_lf_opt.hpp>
#include <limbo/model/multi_gp.hpp>
#include <limbo/acqui/gp_ucb.hpp>
#include <limbo/acqui/ei.hpp>

namespace INMOST {

    BayesianUniformDistribution::BayesianUniformDistribution() : distribution(0.0, 1.0) {
        int rank, size;

        MPI_Comm_rank(MPI_COMM_WORLD, &rank);
        MPI_Comm_size(MPI_COMM_WORLD, &size);

        unsigned int seed = static_cast<unsigned int>(time(NULL));

        if (rank == 0) {
            for (int i = 1; i < size; i++) {
                MPI_Send(&seed, 1, MPI_UNSIGNED, i, 0, MPI_COMM_WORLD);
            }
        } else {
            MPI_Status status;
            MPI_Recv(&seed, 1, MPI_UNSIGNED, 0, 0, MPI_COMM_WORLD, &status);
        }

        generator.seed(seed);
    }

    double BayesianUniformDistribution::next() {
        return distribution(generator);
    }

    unsigned int BayesianUniformDistribution::operator()(unsigned int n) {
        return static_cast<unsigned int>(next() * n);
    }

    unsigned int    BayesianOptimizer::DEFAULT_UNIQUE_POINTS_MAX_COUNT    = 7;
    unsigned int    BayesianOptimizer::DEFAULT_UNIQUE_POINTS_RANDOM_COUNT = 5;
    unsigned int    BayesianOptimizer::DEFAULT_INITIAL_ITERATIONS_COUNT   = 5;
    double          BayesianOptimizer::DEFAULT_INITIAL_ITERATIONS_RADIUS  = 0.2;
    double          BayesianOptimizer::DEFAULT_MAX_JUMP_BARRIER           = 0.1;

    BayesianOptimizer::BayesianOptimizer(const std::string &name, const OptimizationParameters &space, const OptimizerProperties &properties, std::size_t buffer_capacity) :
            OptimizerInterface(name, space, properties, buffer_capacity),
            unique_points_max_count(BayesianOptimizer::DEFAULT_UNIQUE_POINTS_MAX_COUNT),
            unique_points_random_count(BayesianOptimizer::DEFAULT_UNIQUE_POINTS_RANDOM_COUNT),
            initial_iterations_count(BayesianOptimizer::DEFAULT_INITIAL_ITERATIONS_COUNT),
            initial_iterations_radius(BayesianOptimizer::DEFAULT_INITIAL_ITERATIONS_RADIUS),
            max_jump_barrier(BayesianOptimizer::DEFAULT_MAX_JUMP_BARRIER) {

        if (this->HasProperty("unique_points_max_count")) {
            unique_points_max_count = static_cast<unsigned int>(std::atoi(this->GetProperty("unique_points_max_count").c_str()));
        }

        if (this->HasProperty("unique_points_random_count")) {
            unique_points_random_count = static_cast<unsigned int>(std::atoi(this->GetProperty("unique_points_random_count").c_str()));
        }

        if (this->HasProperty("initial_iterations_count")) {
            initial_iterations_count = static_cast<unsigned int>(std::atoi(this->GetProperty("initial_iterations_count").c_str()));
        }

        if (this->HasProperty("initial_iterations_radius")) {
            initial_iterations_radius = std::atof(this->GetProperty("initial_iterations_radius").c_str());
        }

        if (this->HasProperty("max_jump_barrier")) {
            max_jump_barrier = std::atof(this->GetProperty("max_jump_barrier").c_str());
        }

    }

    SuggestionChangedParameters BayesianOptimizer::AlgorithmMakeSuggestion() const {

        auto unique  = results.GetLastUniqueEntries(unique_points_max_count);
        auto entries = parameters.GetParameterEntries();

        std::vector<SuggestionChangedParameter> changed_parameters;

        if (unique.size() == 0) {

            std::size_t index = 0;
            std::for_each(entries.cbegin(), entries.cend(), [&index, &changed_parameters](const OptimizationParametersEntry &entry) {
                changed_parameters.emplace_back(SuggestionChangedParameter(index++, entry.first.GetDefaultValue()));
            });

            return changed_parameters;
        } else if (unique.size() < initial_iterations_count) {

            std::size_t index = 0;
            std::for_each(entries.cbegin(), entries.cend(), [&index, &changed_parameters, this, &unique](const OptimizationParametersEntry &entry) {
                auto parameter = entry.first;

                double min_bound = parameter.GetMinimalValue();
                double max_bound = parameter.GetMaximumValue();

                double r = random.next() * (max_bound - min_bound) * initial_iterations_radius;

                double next = entry.second + r * (2.0 * (unique.size() % 2) - 1.0);

                while (next < min_bound || next > max_bound) {
                    r    = random.next() * (max_bound - min_bound) * initial_iterations_radius;
                    next = entry.second + r * (2.0 * (unique.size() % 2) - 1.0);
                }

                changed_parameters.emplace_back(SuggestionChangedParameter(index++, next));
            });

            return changed_parameters;
        }

        std::random_shuffle(unique.begin() + 1, unique.end(), random);

        struct Params {
            struct kernel {
                // BO_PARAM(double, noise, 0.01); default
                // BO_PARAM(bool, optimize_noise, false); default
                BO_PARAM(double, noise, 0.01);

                BO_PARAM(bool, optimize_noise, false);
            };

            struct kernel_squared_exp_ard : public limbo::defaults::kernel_squared_exp_ard {
                // BO_PARAM(int, k, 0); default
                // BO_PARAM(double, sigma_sq, 1); default

                BO_PARAM(int, k, 4);

                BO_PARAM(double, sigma_sq, 0.2);
            };

            struct opt_rprop : public limbo::defaults::opt_rprop {
            };
            struct opt_nloptnograd : public limbo::defaults::opt_nloptnograd {
            };

            struct acqui_ucb {
                // BO_PARAM(double, alpha, 0.5); default

                BO_PARAM(double, alpha, 0.25);
            };

            struct acqui_gpucb : public limbo::defaults::acqui_gpucb {
            };
            struct acqui_ei : public limbo::defaults::acqui_ei {
            };
        };

        using Kernel2_t = limbo::kernel::SquaredExpARD<Params>;
        using Mean_t = limbo::mean::FunctionARD<Params, limbo::mean::Data<Params>>;
        using GP2_t = limbo::model::GP<Params, Kernel2_t, Mean_t, limbo::model::gp::KernelMeanLFOpt<Params>>;

        GP2_t gp_ard;

        std::vector<Eigen::VectorXd> samples;
        std::vector<Eigen::VectorXd> observations;

        std::for_each(unique.cbegin(), unique.cbegin() + std::min(static_cast<std::size_t>(unique_points_random_count), unique.size()), [this, &samples, &observations]
                (const OptimizationParameterResult &result) {
            Eigen::VectorXd sample(parameters.Size());

            int i = 0;
            std::for_each(result.GetPointsAfter().cbegin(), result.GetPointsAfter().cend(), [&i, &sample, this](const OptimizationParameterPoint &point) {
                auto parameter = parameters.GetParameter(static_cast<size_t>(i));

                double min_bound = parameter.GetMinimalValue();
                double max_bound = parameter.GetMaximumValue();

                double normalized = (parameter.ExtractValueFromPoint(point) - min_bound) / (max_bound - min_bound); // Normalize here to [0, 1]

                sample(i) = normalized;

                i += 1;
            });

            samples.push_back(sample);
            observations.push_back(limbo::tools::make_vector(-1.0 * result.GetMetricsAfter()));
        });

        double min_observation = (*std::min_element(observations.cbegin(), observations.cend(), [](const Eigen::VectorXd &l, const Eigen::VectorXd &r) {
            return l(0) < r(0);
        }))(0);

        double max_observation = (*std::max_element(observations.cbegin(), observations.cend(), [](const Eigen::VectorXd &l, const Eigen::VectorXd &r) {
            return l(0) < r(0);
        }))(0);

        std::transform(observations.cbegin(), observations.cend(), observations.begin(), [min_observation, max_observation](const Eigen::VectorXd &ob) {
            return limbo::tools::make_vector((ob(0) - min_observation) / ((10.0 / 6.0) * (max_observation - min_observation)) + 0.2); // Normalize here to [ 0.2, 0.8 ]
        });

        gp_ard.compute(samples, observations);
        gp_ard.optimize_hyperparams();

        using acquiopt_t = limbo::opt::NLOptNoGrad<Params, nlopt::GN_ISRES>;
        using acquisition_function_t = limbo::acqui::UCB<Params, GP2_t>;

        acquiopt_t             acquiopt;
        acquisition_function_t acqui(gp_ard, 0);

        auto afun               = limbo::FirstElem();
        auto acqui_optimization = [&](const Eigen::VectorXd &x, bool g) { return acqui(x, afun, g); };

        Eigen::VectorXd starting_point(parameters.Size());

        int i = 0;
        std::for_each(parameters.GetParameterEntries().cbegin(), parameters.GetParameterEntries().cend(), [&i, &starting_point](const OptimizationParametersEntry &entry) {

            auto parameter = entry.first;

            double min_bound = parameter.GetMinimalValue();
            double max_bound = parameter.GetMaximumValue();

            starting_point(i) = (entry.second - min_bound) / (max_bound - min_bound);

            i += 1;
        });

        Eigen::VectorXd new_sample = acquiopt(acqui_optimization, starting_point, true);

        for (int k = 0; k < parameters.Size(); ++k) {
            auto parameter = parameters.GetParameter(static_cast<size_t>(k));

            double min_bound = parameter.GetMinimalValue();
            double max_bound = parameter.GetMaximumValue();

            double barrier = max_jump_barrier;
            if (std::abs(new_sample(k) - starting_point(k)) > barrier) {
                new_sample(k) = starting_point(k) + barrier * (new_sample(k) - starting_point(k));
            }

            changed_parameters.emplace_back(SuggestionChangedParameter(k, (new_sample(k) * (max_bound - min_bound)) + min_bound));
        }

        return changed_parameters;
    }

    bool BayesianOptimizer::UpdateSpaceWithLatestResults() {
        const OptimizationParameterResult &last = results.at(0);

        if (last.IsGood() && (last.GetMetricsBefore() < 0.0 || (last.GetMetricsAfter() < last.GetMetricsBefore()))) {
            parameters.Update(last.GetChangedParameters(), last.GetMetricsAfter());
            return true;
        } else {
            return false;
        }
    }

    BayesianOptimizer::~BayesianOptimizer() {}

}

max_stars_repo_name: INM-RAS/INMOST

max_issues_repo_name: INMOST-DEV/INMOST

max_forks_repo_name: INM-RAS/INMOST