<commit_before>#include "refinedepth.h"

using caffe::Blob;
using caffe::Net;

const int feature_num = 5; // y cr cb r c
const int w_ = 640;
const int h_ = 480;

RefineDepth::RefineDepth()
{
  int gpu_id = 0;
#ifdef CPU_ONLY
  printf("Setting up Caffe in CPU mode\n");
  caffe::Caffe::set_mode(caffe::Caffe::CPU);
#else
  caffe::Caffe::SetDevice(gpu_id);
  caffe::Caffe::set_mode(caffe::Caffe::GPU);
#endif
  char* drv_path_env = getenv("DRV");
  string drv_path_ = string(drv_path_env) + "/supplements/refine_depth/";
  string proto_file;
  proto_file = drv_path_ + "refine_depth.prototxt";

  if (!boost::filesystem::is_regular_file(proto_file))
    cerr << "Proto file " << proto_file << " not exist." << endl;
  net_.reset(new Net<float>(proto_file, caffe::TEST));
  setParams();
}

void RefineDepth::refineDepth(Mat rgb_in, Mat depth_in, Mat &depth_out)
{
  vector<float> depth_values_in;

  vector<vector<float> > features_in;
  vector<vector<float> > features_out;

  depth_values_in.resize(w_ * h_);
  features_in.resize(feature_num);
  features_out.resize(feature_num);

  for (size_t e = 0; e < feature_num; ++e) {
    features_in[e].resize(w_ * h_);
    features_out[e].resize(w_ * h_);
  }

  CHECK_EQ(rgb_in.size(), Size(w_, h_));
  CHECK_EQ(depth_in.size(), Size(w_, h_));

  cv::Mat yCrCb;
  cv::cvtColor(rgb_in, yCrCb, CV_BGR2YCrCb);

  for (size_t r = 0; r < h_; ++r) {
    for (size_t c = 0; c < w_; ++c) {
      float depth_val = depth_in.at<float>(r, c);
      if (depth_val == 0) {
        // In place where depth is not known, put its features to features_out
        features_out[0][r * w_ + c] = yCrCb.at<Vec3b>(r, c)[0];
        features_out[1][r * w_ + c] = yCrCb.at<Vec3b>(r, c)[1];
        features_out[2][r * w_ + c] = yCrCb.at<Vec3b>(r, c)[2];
        features_out[3][r * w_ + c] = r;
        features_out[4][r * w_ + c] = c;
      }
      else {
        features_in[0][r * w_ + c] = yCrCb.at<Vec3b>(r, c)[0];
        features_in[1][r * w_ + c] = yCrCb.at<Vec3b>(r, c)[1];
        features_in[2][r * w_ + c] = yCrCb.at<Vec3b>(r, c)[2];
        features_in[3][r * w_ + c] = r;
        features_in[4][r * w_ + c] = c;

        depth_values_in[r * w_ + c] = depth_val;
      }
    }
  }

  depth_out = Mat(h_, w_, CV_32FC1, Scalar(0.0));

  Mat depth_filled(h_, w_, CV_32FC1, Scalar(0.0));
  forward(depth_values_in, features_in, features_out, depth_filled);

  for (size_t r = 0; r < h_; ++r) {
    for (size_t c = 0; c < w_; ++c) {
      float depth_val = depth_in.at<float>(r, c);
      if (depth_val == 0) {
        depth_out.at<float>(r, c) = depth_filled.at<float>(r, c);
      }
      else {
        depth_out.at<float>(r, c) = depth_val;
      }
    }
  }
  namedWindow("Refined", WINDOW_NORMAL);
  imshow("Refined", depth_out);
  waitKey();
}

void RefineDepth::forward(vector<float> depth_in, vector<vector<float> > features_in,
                          vector<vector<float> > features_out, Mat &depth_out)
{
  wrapInputLayer(depth_in, features_in, features_out);
  net_->Forward();
  getOutput(depth_out);
}

void RefineDepth::setParams()
{
  const vector<boost::shared_ptr<Blob<float> > >& net_params = net_->params();
  boost::shared_ptr<Blob<float> > out_seg1 = net_params[0];
  float* out_seg1_data = out_seg1->mutable_cpu_data();
  // dim of out_seg1 param: 1 X 1 X 1 X 1
  out_seg1_data[0] = 1.0;

  boost::shared_ptr<Blob<float> > out_seg2 = net_params[2];
  float* out_seg2_data = out_seg2->mutable_cpu_data();
  // dim of out_seg1 param: 1 X 1 X 1 X 1
  out_seg2_data[0] = 1.0;

  boost::shared_ptr<Blob<float> > sp_out_seg1 = net_params[4];
  float* sp_out_seg1_data = sp_out_seg1->mutable_cpu_data();
  // dim of sp_out_seg1 param: 1 X 2 X 1 X 1
  sp_out_seg1_data[0] = 1.0; // This value only need be larger
  sp_out_seg1_data[1] = 0.0; // than this value
}

void RefineDepth::wrapInputLayer(vector<float> depth_in, vector<vector<float> > features_in,
                                 vector<vector<float> > features_out)
{
  // Input depth shape: num_pixel
  // Net shape: 1 1 1 num_pixel
  Blob<float>* input_unary = net_->input_blobs()[0];
  float* unary_data = input_unary->mutable_cpu_data();

  for (size_t e = 0; e < depth_in.size(); ++e) {
    *unary_data = depth_in[e];
    ++unary_data;
  }

  // Input in_features shape : feature_num_ num_pixel
  // Net shape : 1 feature_num_ 1 num_pixel
  Blob<float>* input_in_features = net_->input_blobs()[1];
  float* in_features_data = input_in_features->mutable_cpu_data();

  vector<float> in_features_c; // collection of data in in_features
  int sz = w_ * h_;
  for (size_t c = 0; c < feature_num; ++c) {
    for (size_t e = 0; e < sz; ++e) {
      in_features_c.push_back(features_in[c][e]);
    }
  }
  for (size_t e = 0; e < in_features_c.size(); ++e) {
    *in_features_data = in_features_c[e];
    ++in_features_data;
  }

  // Input out_features shape: feature_num_ num_pixel
  // Net shape : 1 feature_num_ 1 num_pixel
  Blob<float>* input_out_features = net_->input_blobs()[2];
  float* out_features_data = input_out_features->mutable_cpu_data();

  vector<float> out_features_c; // collection of data in out_features
  for (size_t c = 0; c < feature_num; ++c) {
    for (size_t e = 0; e < sz; ++e) {
      out_features_c.push_back(features_out[c][e]);
    }
  }
  for (size_t e = 0; e < out_features_c.size(); ++e) {
    *out_features_data = out_features_c[e];
    ++out_features_data;
  }

  // Scales1 1 feature_num_ 1 1
  Blob<float>* input_scales1 = net_->input_blobs()[3];
  float* scales1_data = input_scales1->mutable_cpu_data();
  // Scales2 1 feature_num_ 1 1
  Blob<float>* input_scales2 = net_->input_blobs()[4];
  float* scales2_data = input_scales2->mutable_cpu_data();

  float s1[] = {0.06, 0.2, 0.2, 0.02, 0.02};
  float s2[] = {0.09, 0.3, 0.3, 0.03, 0.03};
  vector<float> scales1(s1, s1 + sizeof(s1) / sizeof(float));
  for (size_t e = 0; e < feature_num; ++e) {
    *scales1_data = scales1[e];
    ++scales1_data;
  }
  vector<float> scales2(s2, s2 + sizeof(s2) / sizeof(float));
  for (size_t e = 0; e < feature_num; ++e) {
    *scales2_data = scales2[e];
    ++scales2_data;
  }
}

void RefineDepth::getOutput(Mat &depth_out)
{
  int num_elements = 1;
  const string out_depth_name = "out_depth1";
  const boost::shared_ptr<Blob<float> > out_depth_blob =
      net_->blob_by_name(out_depth_name.c_str());

  num_elements = 1;
  for (int i = 0; i < out_depth_blob->num_axes(); ++i) {
    const int elements_in_dim = out_depth_blob->shape(i);
    num_elements *= elements_in_dim;
  }

  vector<float> temp_depth;
  for (int n = 0; n < num_elements; ++n) {
    const float* out_depth_blob_data = out_depth_blob->cpu_data() + n;
    temp_depth.push_back(*out_depth_blob_data);
  }

  for (int i = 0; i < temp_depth.size(); ++i) {
    int r = i / w_;
    int c = i % w_;
    depth_out.at<float>(r, c) = float(temp_depth[i]);
  }
}

<commit_msg>refine the algorithm<commit_after>#include "refinedepth.h"

using caffe::Blob;
using caffe::Net;

const int feature_num = 5; // y cr cb r c
const int w_ = 640;
const int h_ = 480;

RefineDepth::RefineDepth()
{
  int gpu_id = 0;
#ifdef CPU_ONLY
  printf("Setting up Caffe in CPU mode\n");
  caffe::Caffe::set_mode(caffe::Caffe::CPU);
#else
  caffe::Caffe::SetDevice(gpu_id);
  caffe::Caffe::set_mode(caffe::Caffe::GPU);
#endif
  char* drv_path_env = getenv("DRV");
  string drv_path_ = string(drv_path_env) + "/supplements/refine_depth/";
  string proto_file;
  proto_file = drv_path_ + "refine_depth.prototxt";

  if (!boost::filesystem::is_regular_file(proto_file))
    cerr << "Proto file " << proto_file << " not exist." << endl;
  net_.reset(new Net<float>(proto_file, caffe::TEST));
  setParams();
}

void RefineDepth::refineDepth(Mat rgb_in, Mat depth_in, Mat &depth_out)
{
  vector<float> depth_values_in;

  vector<vector<float> > features_in;
  vector<vector<float> > features_out;

  depth_values_in.resize(w_ * h_);
  features_in.resize(feature_num);
  features_out.resize(feature_num);

  for (size_t e = 0; e < feature_num; ++e) {
    features_in[e].resize(w_ * h_);
    features_out[e].resize(w_ * h_);
  }

  CHECK_EQ(rgb_in.size(), Size(w_, h_));
  CHECK_EQ(depth_in.size(), Size(w_, h_));

  cv::Mat yCrCb;
  cv::cvtColor(rgb_in, yCrCb, CV_BGR2YCrCb);

  for (size_t r = 0; r < h_; ++r) {
    for (size_t c = 0; c < w_; ++c) {
      float depth_val = depth_in.at<float>(r, c);
      if (depth_val == 0) {
        // In place where depth is not known, put its features to features_out
        features_out[0][r * w_ + c] = yCrCb.at<Vec3b>(r, c)[0];
        features_out[1][r * w_ + c] = yCrCb.at<Vec3b>(r, c)[1];
        features_out[2][r * w_ + c] = yCrCb.at<Vec3b>(r, c)[2];
        features_out[3][r * w_ + c] = r;
        features_out[4][r * w_ + c] = c;
      }
      else {
        features_in[0][r * w_ + c] = yCrCb.at<Vec3b>(r, c)[0];
        features_in[1][r * w_ + c] = yCrCb.at<Vec3b>(r, c)[1];
        features_in[2][r * w_ + c] = yCrCb.at<Vec3b>(r, c)[2];
        features_in[3][r * w_ + c] = r;
        features_in[4][r * w_ + c] = c;

        depth_values_in[r * w_ + c] = depth_val;
      }
    }
  }

  depth_out = Mat(h_, w_, CV_32FC1, Scalar(0.0));

  Mat depth_filled(h_, w_, CV_32FC1, Scalar(0.0));
  forward(depth_values_in, features_in, features_out, depth_filled);

  for (size_t r = 0; r < h_; ++r) {
    for (size_t c = 0; c < w_; ++c) {
      float depth_val = depth_in.at<float>(r, c);
      if (depth_val == 0) {
        depth_out.at<float>(r, c) = depth_filled.at<float>(r, c);
      }
      else {
        depth_out.at<float>(r, c) = depth_val;
      }
    }
  }
  namedWindow("Refined", WINDOW_NORMAL);
  imshow("Refined", depth_out);
  waitKey(10);
}

void RefineDepth::forward(vector<float> depth_in, vector<vector<float> > features_in,
                          vector<vector<float> > features_out, Mat &depth_out)
{
  wrapInputLayer(depth_in, features_in, features_out);
  net_->Forward();
  getOutput(depth_out);
}

void RefineDepth::setParams()
{
  const vector<boost::shared_ptr<Blob<float> > >& net_params = net_->params();
  boost::shared_ptr<Blob<float> > out_seg1 = net_params[0];
  float* out_seg1_data = out_seg1->mutable_cpu_data();
  // dim of out_seg1 param: 1 X 1 X 1 X 1
  out_seg1_data[0] = 1.0;

  boost::shared_ptr<Blob<float> > out_seg2 = net_params[2];
  float* out_seg2_data = out_seg2->mutable_cpu_data();
  // dim of out_seg1 param: 1 X 1 X 1 X 1
  out_seg2_data[0] = 1.0;

  boost::shared_ptr<Blob<float> > sp_out_seg1 = net_params[4];
  float* sp_out_seg1_data = sp_out_seg1->mutable_cpu_data();
  // dim of sp_out_seg1 param: 1 X 2 X 1 X 1
  sp_out_seg1_data[0] = 1.0; // This value only need be larger
  sp_out_seg1_data[1] = 0.0; // than this value
}

void RefineDepth::wrapInputLayer(vector<float> depth_in, vector<vector<float> > features_in,
                                 vector<vector<float> > features_out)
{
  // Input depth shape: num_pixel
  // Net shape: 1 1 1 num_pixel
  Blob<float>* input_unary = net_->input_blobs()[0];
  float* unary_data = input_unary->mutable_cpu_data();

  for (size_t e = 0; e < depth_in.size(); ++e) {
    *unary_data = depth_in[e];
    ++unary_data;
  }

  // Input in_features shape : feature_num_ num_pixel
  // Net shape : 1 feature_num_ 1 num_pixel
  Blob<float>* input_in_features = net_->input_blobs()[1];
  float* in_features_data = input_in_features->mutable_cpu_data();

  vector<float> in_features_c; // collection of data in in_features
  int sz = w_ * h_;
  for (size_t c = 0; c < feature_num; ++c) {
    for (size_t e = 0; e < sz; ++e) {
      in_features_c.push_back(features_in[c][e]);
    }
  }
  for (size_t e = 0; e < in_features_c.size(); ++e) {
    *in_features_data = in_features_c[e];
    ++in_features_data;
  }

  // Input out_features shape: feature_num_ num_pixel
  // Net shape : 1 feature_num_ 1 num_pixel
  Blob<float>* input_out_features = net_->input_blobs()[2];
  float* out_features_data = input_out_features->mutable_cpu_data();

  vector<float> out_features_c; // collection of data in out_features
  for (size_t c = 0; c < feature_num; ++c) {
    for (size_t e = 0; e < sz; ++e) {
      out_features_c.push_back(features_out[c][e]);
    }
  }
  for (size_t e = 0; e < out_features_c.size(); ++e) {
    *out_features_data = out_features_c[e];
    ++out_features_data;
  }

  // Scales1 1 feature_num_ 1 1
  Blob<float>* input_scales1 = net_->input_blobs()[3];
  float* scales1_data = input_scales1->mutable_cpu_data();
  // Scales2 1 feature_num_ 1 1
  Blob<float>* input_scales2 = net_->input_blobs()[4];
  float* scales2_data = input_scales2->mutable_cpu_data();

  float s1[] = {0.06, 0.2, 0.2, 0.02, 0.02};
  float s2[] = {0.09, 0.3, 0.3, 0.03, 0.03};
  vector<float> scales1(s1, s1 + sizeof(s1) / sizeof(float));
  for (size_t e = 0; e < feature_num; ++e) {
    *scales1_data = scales1[e];
    ++scales1_data;
  }
  vector<float> scales2(s2, s2 + sizeof(s2) / sizeof(float));
  for (size_t e = 0; e < feature_num; ++e) {
    *scales2_data = scales2[e];
    ++scales2_data;
  }
}

void RefineDepth::getOutput(Mat &depth_out)
{
  int num_elements = 1;
  const string out_depth_name = "out_depth1";
  const boost::shared_ptr<Blob<float> > out_depth_blob =
      net_->blob_by_name(out_depth_name.c_str());

  num_elements = 1;
  for (int i = 0; i < out_depth_blob->num_axes(); ++i) {
    const int elements_in_dim = out_depth_blob->shape(i);
    num_elements *= elements_in_dim;
  }

  vector<float> temp_depth;
  for (int n = 0; n < num_elements; ++n) {
    const float* out_depth_blob_data = out_depth_blob->cpu_data() + n;
    temp_depth.push_back(*out_depth_blob_data);
  }

  for (int i = 0; i < temp_depth.size(); ++i) {
    int r = i / w_;
    int c = i % w_;
    depth_out.at<float>(r, c) = float(temp_depth[i]);
  }
}

<|endoftext|>


<commit_before>#pragma once

#include "generator/feature_merger.hpp"
#include "generator/generate_info.hpp"
#include "generator/popular_places_section_builder.hpp"

#include "search/utils.hpp"

#include "indexer/classificator.hpp"
#include "indexer/scales.hpp"

#include "coding/pointd_to_pointu.hpp"

#include "geometry/polygon.hpp"
#include "geometry/region2d.hpp"
#include "geometry/tree4d.hpp"

#include "base/logging.hpp"

#include <algorithm>
#include <cstdint>
#include <map>
#include <sstream>
#include <string>
#include <vector>

#include "defines.hpp"

namespace
{
class WaterBoundaryChecker
{
  uint32_t m_boundaryType;

  struct RegionTraits
  {
    m2::RectD const & LimitRect(m2::RegionD const & r) const { return r.GetRect(); }
  };
  m4::Tree<m2::RegionD, RegionTraits> m_tree;

  size_t m_totalFeatures = 0;
  size_t m_totalBorders = 0;
  size_t m_skippedBorders = 0;
  size_t m_selectedPolygons = 0;

public:
  WaterBoundaryChecker(feature::GenerateInfo const & info)
  {
    m_boundaryType = classif().GetTypeByPath({"boundary", "administrative"});
    LoadWaterGeometry(
        info.GetIntermediateFileName(WORLD_COASTS_FILE_NAME, RAW_GEOM_FILE_EXTENSION));
  }

  ~WaterBoundaryChecker()
  {
    LOG_SHORT(LINFO, ("Features checked:", m_totalFeatures, "borders checked:", m_totalBorders,
                "borders skipped:", m_skippedBorders, "selected polygons:", m_selectedPolygons));
  }

  void LoadWaterGeometry(std::string const & rawGeometryFileName)
  {
    LOG_SHORT(LINFO, ("Loading water geometry:", rawGeometryFileName));
    FileReader reader(rawGeometryFileName);
    ReaderSource<FileReader> file(reader);

    size_t total = 0;
    while (true)
    {
      uint64_t numGeometries = 0;
      file.Read(&numGeometries, sizeof(numGeometries));

      if (numGeometries == 0)
        break;

      ++total;

      for (size_t i = 0; i < numGeometries; ++i)
      {
        uint64_t numPoints = 0;
        file.Read(&numPoints, sizeof(numPoints));

        std::vector<m2::PointD> points(numPoints);
        file.Read(points.data(), sizeof(m2::PointD) * numPoints);
        m_tree.Add(m2::RegionD(move(points)));
      }
    }
    LOG_SHORT(LINFO, ("Load", total, "water geometries"));
  }

  bool IsBoundaries(FeatureBuilder1 const & fb)
  {
    ++m_totalFeatures;

    if (fb.FindType(m_boundaryType, 2) == ftype::GetEmptyValue())
      return false;

    ++m_totalBorders;

    return true;
  }

  enum class ProcessState
  {
    Initial,
    Water,
    Earth
  };

  void ProcessBoundary(FeatureBuilder1 const & boundary, std::vector<FeatureBuilder1> & parts)
  {
    auto const & line = boundary.GetGeometry().front();

    double constexpr kExtension = 0.01;
    ProcessState state = ProcessState::Initial;

    FeatureBuilder1::PointSeq points;

    for (size_t i = 0; i < line.size(); ++i)
    {
      m2::PointD const & p = line[i];
      m2::RectD r(p.x - kExtension, p.y - kExtension, p.x + kExtension, p.y + kExtension);
      size_t hits = 0;
      m_tree.ForEachInRect(r, [&](m2::RegionD const & rgn)
      {
        ++m_selectedPolygons;
        hits += rgn.Contains(p) ? 1 : 0;
      });

      bool inWater = (hits & 0x01) == 1;

      switch (state)
      {
      case ProcessState::Initial:
      {
        if (inWater)
        {
          state = ProcessState::Water;
        }
        else
        {
          points.push_back(p);
          state = ProcessState::Earth;
        }
        break;
      }
      case ProcessState::Water:
      {
        if (inWater)
        {
          // do nothing
        }
        else
        {
          points.push_back(p);
          state = ProcessState::Earth;
        }
        break;
      }
      case ProcessState::Earth:
      {
        if (inWater)
        {
          if (points.size() > 1)
          {
            parts.push_back(boundary);
            parts.back().ResetGeometry();
            for (auto const & pt : points)
              parts.back().AddPoint(pt);
          }
          points.clear();
          state = ProcessState::Water;
        }
        else
        {
          points.push_back(p);
        }
        break;
      }
      }
    }

    if (points.size() > 1)
    {
      parts.push_back(boundary);
      parts.back().ResetGeometry();
      for (auto const & pt : points)
        parts.back().AddPoint(pt);
    }

    if (parts.empty())
      m_skippedBorders++;
  }
};
} // namespace

/// Process FeatureBuilder1 for world map. Main functions:
/// - check for visibility in world map
/// - merge linear features
template <class FeatureOutT>
class WorldMapGenerator
{
  class EmitterImpl : public FeatureEmitterIFace
  {
    FeatureOutT m_output;
    std::map<uint32_t, size_t> m_mapTypes;

  public:
    explicit EmitterImpl(feature::GenerateInfo const & info)
      : m_output(info.GetTmpFileName(WORLD_FILE_NAME))
    {
      LOG_SHORT(LINFO, ("Output World file:", info.GetTmpFileName(WORLD_FILE_NAME)));
    }

    ~EmitterImpl() override
    {
      Classificator const & c = classif();

      std::stringstream ss;
      ss << std::endl;
      for (auto const & p : m_mapTypes)
        ss << c.GetReadableObjectName(p.first) << " : " <<  p.second << std::endl;
      LOG_SHORT(LINFO, ("World types:", ss.str()));
    }

    /// This function is called after merging linear features.
    void operator()(FeatureBuilder1 const & fb) override
    {
      // do additional check for suitable size of feature
      if (NeedPushToWorld(fb) &&
          scales::IsGoodForLevel(scales::GetUpperWorldScale(), fb.GetLimitRect()))
        PushSure(fb);
    }

    void CalcStatistics(FeatureBuilder1 const & fb)
    {
      for (uint32_t type : fb.GetTypes())
        ++m_mapTypes[type];
    }

    bool NeedPushToWorld(FeatureBuilder1 const & fb) const
    {
      // GetMinFeatureDrawScale also checks suitable size for AREA features
      return (scales::GetUpperWorldScale() >= fb.GetMinFeatureDrawScale());
    }

    void PushSure(FeatureBuilder1 const & fb) { m_output(fb); }
  };

  EmitterImpl m_worldBucket;
  FeatureTypesProcessor m_typesCorrector;
  FeatureMergeProcessor m_merger;
  WaterBoundaryChecker m_boundaryChecker;
  generator::PopularPlaces m_popularPlaces;

public:
  explicit WorldMapGenerator(feature::GenerateInfo const & info)
      : m_worldBucket(info),
        m_merger(POINT_COORD_BITS - (scales::GetUpperScale() - scales::GetUpperWorldScale()) / 2),
        m_boundaryChecker(info)
  {
    // Do not strip last types for given tags,
    // for example, do not cut 'admin_level' in  'boundary-administrative-XXX'.
    char const * arr1[][3] = {{"boundary", "administrative", "2"},
                              {"boundary", "administrative", "3"},
                              {"boundary", "administrative", "4"}};

    for (size_t i = 0; i < ARRAY_SIZE(arr1); ++i)
      m_typesCorrector.SetDontNormalizeType(arr1[i]);

    char const * arr2[] = {"boundary", "administrative", "4", "state"};
    m_typesCorrector.SetDontNormalizeType(arr2);

    if (!info.m_popularPlacesFilename.empty())
      generator::LoadPopularPlaces(info.m_popularPlacesFilename, m_popularPlaces);
    else
      LOG(LWARNING, ("popular_places_data option not set. Popular atractions will not be added to World.mwm"));
  }

  void operator()(FeatureBuilder1 fb)
  {
    auto const isPopularAttraction = IsPopularAttraction(fb);
    auto const isInternationalAirport =
        fb.HasType(classif().GetTypeByPath({"aeroway", "aerodrome", "international"}));
    auto const forcePushToWorld = isPopularAttraction || isInternationalAirport;

    if (!m_worldBucket.NeedPushToWorld(fb) && !forcePushToWorld)
      return;

    m_worldBucket.CalcStatistics(fb);

    if (!m_boundaryChecker.IsBoundaries(fb))
    {
      // Save original feature iff we need to force push it before PushFeature(fb) modifies fb.
      auto originalFeature = forcePushToWorld ? fb : FeatureBuilder1();

      if (PushFeature(fb) || !forcePushToWorld)
        return;

      // We push GEOM_POINT with all the same tags, names and center instead of GEOM_WAY/GEOM_AREA
      // because we do not need geometry for invisible features (just search index and placepage
      // data) and want to avoid size checks applied to areas.
      if (originalFeature.GetGeomType() != feature::GEOM_POINT)
        originalFeature.SetCenter(originalFeature.GetGeometryCenter());

      m_worldBucket.PushSure(originalFeature);
      return;
    }

    std::vector<FeatureBuilder1> boundaryParts;
    m_boundaryChecker.ProcessBoundary(fb, boundaryParts);
    for (auto & f : boundaryParts)
      PushFeature(f);
  }

  bool PushFeature(FeatureBuilder1 & fb)
  {
    switch (fb.GetGeomType())
    {
    case feature::GEOM_LINE:
    {
      MergedFeatureBuilder1 * p = m_typesCorrector(fb);
      if (p)
        m_merger(p);
      return false;
    }
    case feature::GEOM_AREA:
    {
      // This constant is set according to size statistics.
      // Added approx 4Mb of data to the World.mwm
      auto const & geometry = fb.GetOuterGeometry();
      if (GetPolygonArea(geometry.begin(), geometry.end()) < 0.01)
        return false;
    }
    default:
      break;
    }

    if (feature::PreprocessForWorldMap(fb))
    {
      m_worldBucket.PushSure(fb);
      return true;
    }

    return false;
  }

  void DoMerge() { m_merger.DoMerge(m_worldBucket); }

private:
  bool IsPopularAttraction(FeatureBuilder1 const & fb) const
  {
    if (fb.GetName().empty())
      return false;

    auto const attractionTypes =
        search::GetCategoryTypes("attractions", "en", GetDefaultCategories());
    ASSERT(is_sorted(attractionTypes.begin(), attractionTypes.end()), ());
    auto const & featureTypes = fb.GetTypes();
    if (!std::any_of(featureTypes.begin(), featureTypes.end(), [&attractionTypes](uint32_t t) {
          return binary_search(attractionTypes.begin(), attractionTypes.end(), t);
        }))
    {
      return false;
    }

    auto const it = m_popularPlaces.find(fb.GetMostGenericOsmId());
    if (it == m_popularPlaces.end())
      return false;

    // todo(@t.yan): adjust
    uint8_t const kPopularityThreshold = 40;
    if (it->second < kPopularityThreshold)
      return false;

    // todo(@t.yan): maybe check place has wikipedia link.
    return true;
  }
};

template <class FeatureOut>
class SimpleCountryMapGenerator
{
public:
  SimpleCountryMapGenerator(feature::GenerateInfo const & info) : m_bucket(info) {}

  void operator()(FeatureBuilder1 & fb)
  {
      m_bucket(fb);
  }

  FeatureOut & Parent() { return m_bucket; }

private:
  FeatureOut m_bucket;
};

template <class FeatureOut>
class CountryMapGenerator : public SimpleCountryMapGenerator<FeatureOut>
{
public:
  CountryMapGenerator(feature::GenerateInfo const & info) :
    SimpleCountryMapGenerator<FeatureOut>(info) {}

  void operator()(FeatureBuilder1 fb)
  {
    if (feature::PreprocessForCountryMap(fb))
      SimpleCountryMapGenerator<FeatureOut>::operator()(fb);
  }
};
<commit_msg>[generator][search] Adjust kPopularityThreshold for new data<commit_after>#pragma once

#include "generator/feature_merger.hpp"
#include "generator/generate_info.hpp"
#include "generator/popular_places_section_builder.hpp"

#include "search/utils.hpp"

#include "indexer/classificator.hpp"
#include "indexer/scales.hpp"

#include "coding/pointd_to_pointu.hpp"

#include "geometry/polygon.hpp"
#include "geometry/region2d.hpp"
#include "geometry/tree4d.hpp"

#include "base/logging.hpp"

#include <algorithm>
#include <cstdint>
#include <map>
#include <sstream>
#include <string>
#include <vector>

#include "defines.hpp"

namespace
{
class WaterBoundaryChecker
{
  uint32_t m_boundaryType;

  struct RegionTraits
  {
    m2::RectD const & LimitRect(m2::RegionD const & r) const { return r.GetRect(); }
  };
  m4::Tree<m2::RegionD, RegionTraits> m_tree;

  size_t m_totalFeatures = 0;
  size_t m_totalBorders = 0;
  size_t m_skippedBorders = 0;
  size_t m_selectedPolygons = 0;

public:
  WaterBoundaryChecker(feature::GenerateInfo const & info)
  {
    m_boundaryType = classif().GetTypeByPath({"boundary", "administrative"});
    LoadWaterGeometry(
        info.GetIntermediateFileName(WORLD_COASTS_FILE_NAME, RAW_GEOM_FILE_EXTENSION));
  }

  ~WaterBoundaryChecker()
  {
    LOG_SHORT(LINFO, ("Features checked:", m_totalFeatures, "borders checked:", m_totalBorders,
                "borders skipped:", m_skippedBorders, "selected polygons:", m_selectedPolygons));
  }

  void LoadWaterGeometry(std::string const & rawGeometryFileName)
  {
    LOG_SHORT(LINFO, ("Loading water geometry:", rawGeometryFileName));
    FileReader reader(rawGeometryFileName);
    ReaderSource<FileReader> file(reader);

    size_t total = 0;
    while (true)
    {
      uint64_t numGeometries = 0;
      file.Read(&numGeometries, sizeof(numGeometries));

      if (numGeometries == 0)
        break;

      ++total;

      for (size_t i = 0; i < numGeometries; ++i)
      {
        uint64_t numPoints = 0;
        file.Read(&numPoints, sizeof(numPoints));

        std::vector<m2::PointD> points(numPoints);
        file.Read(points.data(), sizeof(m2::PointD) * numPoints);
        m_tree.Add(m2::RegionD(move(points)));
      }
    }
    LOG_SHORT(LINFO, ("Load", total, "water geometries"));
  }

  bool IsBoundaries(FeatureBuilder1 const & fb)
  {
    ++m_totalFeatures;

    if (fb.FindType(m_boundaryType, 2) == ftype::GetEmptyValue())
      return false;

    ++m_totalBorders;

    return true;
  }

  enum class ProcessState
  {
    Initial,
    Water,
    Earth
  };

  void ProcessBoundary(FeatureBuilder1 const & boundary, std::vector<FeatureBuilder1> & parts)
  {
    auto const & line = boundary.GetGeometry().front();

    double constexpr kExtension = 0.01;
    ProcessState state = ProcessState::Initial;

    FeatureBuilder1::PointSeq points;

    for (size_t i = 0; i < line.size(); ++i)
    {
      m2::PointD const & p = line[i];
      m2::RectD r(p.x - kExtension, p.y - kExtension, p.x + kExtension, p.y + kExtension);
      size_t hits = 0;
      m_tree.ForEachInRect(r, [&](m2::RegionD const & rgn)
      {
        ++m_selectedPolygons;
        hits += rgn.Contains(p) ? 1 : 0;
      });

      bool inWater = (hits & 0x01) == 1;

      switch (state)
      {
      case ProcessState::Initial:
      {
        if (inWater)
        {
          state = ProcessState::Water;
        }
        else
        {
          points.push_back(p);
          state = ProcessState::Earth;
        }
        break;
      }
      case ProcessState::Water:
      {
        if (inWater)
        {
          // do nothing
        }
        else
        {
          points.push_back(p);
          state = ProcessState::Earth;
        }
        break;
      }
      case ProcessState::Earth:
      {
        if (inWater)
        {
          if (points.size() > 1)
          {
            parts.push_back(boundary);
            parts.back().ResetGeometry();
            for (auto const & pt : points)
              parts.back().AddPoint(pt);
          }
          points.clear();
          state = ProcessState::Water;
        }
        else
        {
          points.push_back(p);
        }
        break;
      }
      }
    }

    if (points.size() > 1)
    {
      parts.push_back(boundary);
      parts.back().ResetGeometry();
      for (auto const & pt : points)
        parts.back().AddPoint(pt);
    }

    if (parts.empty())
      m_skippedBorders++;
  }
};
} // namespace

/// Process FeatureBuilder1 for world map. Main functions:
/// - check for visibility in world map
/// - merge linear features
template <class FeatureOutT>
class WorldMapGenerator
{
  class EmitterImpl : public FeatureEmitterIFace
  {
    FeatureOutT m_output;
    std::map<uint32_t, size_t> m_mapTypes;

  public:
    explicit EmitterImpl(feature::GenerateInfo const & info)
      : m_output(info.GetTmpFileName(WORLD_FILE_NAME))
    {
      LOG_SHORT(LINFO, ("Output World file:", info.GetTmpFileName(WORLD_FILE_NAME)));
    }

    ~EmitterImpl() override
    {
      Classificator const & c = classif();

      std::stringstream ss;
      ss << std::endl;
      for (auto const & p : m_mapTypes)
        ss << c.GetReadableObjectName(p.first) << " : " <<  p.second << std::endl;
      LOG_SHORT(LINFO, ("World types:", ss.str()));
    }

    /// This function is called after merging linear features.
    void operator()(FeatureBuilder1 const & fb) override
    {
      // do additional check for suitable size of feature
      if (NeedPushToWorld(fb) &&
          scales::IsGoodForLevel(scales::GetUpperWorldScale(), fb.GetLimitRect()))
        PushSure(fb);
    }

    void CalcStatistics(FeatureBuilder1 const & fb)
    {
      for (uint32_t type : fb.GetTypes())
        ++m_mapTypes[type];
    }

    bool NeedPushToWorld(FeatureBuilder1 const & fb) const
    {
      // GetMinFeatureDrawScale also checks suitable size for AREA features
      return (scales::GetUpperWorldScale() >= fb.GetMinFeatureDrawScale());
    }

    void PushSure(FeatureBuilder1 const & fb) { m_output(fb); }
  };

  EmitterImpl m_worldBucket;
  FeatureTypesProcessor m_typesCorrector;
  FeatureMergeProcessor m_merger;
  WaterBoundaryChecker m_boundaryChecker;
  generator::PopularPlaces m_popularPlaces;

public:
  explicit WorldMapGenerator(feature::GenerateInfo const & info)
      : m_worldBucket(info),
        m_merger(POINT_COORD_BITS - (scales::GetUpperScale() - scales::GetUpperWorldScale()) / 2),
        m_boundaryChecker(info)
  {
    // Do not strip last types for given tags,
    // for example, do not cut 'admin_level' in  'boundary-administrative-XXX'.
    char const * arr1[][3] = {{"boundary", "administrative", "2"},
                              {"boundary", "administrative", "3"},
                              {"boundary", "administrative", "4"}};

    for (size_t i = 0; i < ARRAY_SIZE(arr1); ++i)
      m_typesCorrector.SetDontNormalizeType(arr1[i]);

    char const * arr2[] = {"boundary", "administrative", "4", "state"};
    m_typesCorrector.SetDontNormalizeType(arr2);

    if (!info.m_popularPlacesFilename.empty())
      generator::LoadPopularPlaces(info.m_popularPlacesFilename, m_popularPlaces);
    else
      LOG(LWARNING, ("popular_places_data option not set. Popular atractions will not be added to World.mwm"));
  }

  void operator()(FeatureBuilder1 fb)
  {
    auto const isPopularAttraction = IsPopularAttraction(fb);
    auto const isInternationalAirport =
        fb.HasType(classif().GetTypeByPath({"aeroway", "aerodrome", "international"}));
    auto const forcePushToWorld = isPopularAttraction || isInternationalAirport;

    if (!m_worldBucket.NeedPushToWorld(fb) && !forcePushToWorld)
      return;

    m_worldBucket.CalcStatistics(fb);

    if (!m_boundaryChecker.IsBoundaries(fb))
    {
      // Save original feature iff we need to force push it before PushFeature(fb) modifies fb.
      auto originalFeature = forcePushToWorld ? fb : FeatureBuilder1();

      if (PushFeature(fb) || !forcePushToWorld)
        return;

      // We push GEOM_POINT with all the same tags, names and center instead of GEOM_WAY/GEOM_AREA
      // because we do not need geometry for invisible features (just search index and placepage
      // data) and want to avoid size checks applied to areas.
      if (originalFeature.GetGeomType() != feature::GEOM_POINT)
        originalFeature.SetCenter(originalFeature.GetGeometryCenter());

      m_worldBucket.PushSure(originalFeature);
      return;
    }

    std::vector<FeatureBuilder1> boundaryParts;
    m_boundaryChecker.ProcessBoundary(fb, boundaryParts);
    for (auto & f : boundaryParts)
      PushFeature(f);
  }

  bool PushFeature(FeatureBuilder1 & fb)
  {
    switch (fb.GetGeomType())
    {
    case feature::GEOM_LINE:
    {
      MergedFeatureBuilder1 * p = m_typesCorrector(fb);
      if (p)
        m_merger(p);
      return false;
    }
    case feature::GEOM_AREA:
    {
      // This constant is set according to size statistics.
      // Added approx 4Mb of data to the World.mwm
      auto const & geometry = fb.GetOuterGeometry();
      if (GetPolygonArea(geometry.begin(), geometry.end()) < 0.01)
        return false;
    }
    default:
      break;
    }

    if (feature::PreprocessForWorldMap(fb))
    {
      m_worldBucket.PushSure(fb);
      return true;
    }

    return false;
  }

  void DoMerge() { m_merger.DoMerge(m_worldBucket); }

private:
  bool IsPopularAttraction(FeatureBuilder1 const & fb) const
  {
    if (fb.GetName().empty())
      return false;

    auto const attractionTypes =
        search::GetCategoryTypes("attractions", "en", GetDefaultCategories());
    ASSERT(is_sorted(attractionTypes.begin(), attractionTypes.end()), ());
    auto const & featureTypes = fb.GetTypes();
    if (!std::any_of(featureTypes.begin(), featureTypes.end(), [&attractionTypes](uint32_t t) {
          return binary_search(attractionTypes.begin(), attractionTypes.end(), t);
        }))
    {
      return false;
    }

    auto const it = m_popularPlaces.find(fb.GetMostGenericOsmId());
    if (it == m_popularPlaces.end())
      return false;

    // todo(@t.yan): adjust
    uint8_t const kPopularityThreshold = 20;
    if (it->second < kPopularityThreshold)
      return false;

    // todo(@t.yan): maybe check place has wikipedia link.
    return true;
  }
};

template <class FeatureOut>
class SimpleCountryMapGenerator
{
public:
  SimpleCountryMapGenerator(feature::GenerateInfo const & info) : m_bucket(info) {}

  void operator()(FeatureBuilder1 & fb)
  {
      m_bucket(fb);
  }

  FeatureOut & Parent() { return m_bucket; }

private:
  FeatureOut m_bucket;
};

template <class FeatureOut>
class CountryMapGenerator : public SimpleCountryMapGenerator<FeatureOut>
{
public:
  CountryMapGenerator(feature::GenerateInfo const & info) :
    SimpleCountryMapGenerator<FeatureOut>(info) {}

  void operator()(FeatureBuilder1 fb)
  {
    if (feature::PreprocessForCountryMap(fb))
      SimpleCountryMapGenerator<FeatureOut>::operator()(fb);
  }
};
<|endoftext|>


<commit_before>// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Utility/Debug.hpp>

template<typename T>
NzBoxf NzComputeVerticesAABB(const T* vertices, unsigned int vertexCount)
{
	NzBoxf aabb;
	if (vertexCount > 0)
	{
		aabb.Set(vertices->position.x, vertices->position.y, vertices->position.z, 0.f, 0.f, 0.f);
		vertices++;

		for (unsigned int i = 1; i < vertexCount; ++i)
		{
			aabb.ExtendTo(vertices->position);
			vertices++;
		}
	}
	else
		aabb.MakeZero();

	return aabb;
}

template<typename T>
void NzTransformVertices(T* vertices, unsigned int vertexCount, const NzMatrix4f& matrix)
{
	if (matrix.IsIdentity())
		return;

	NzVector3f scale = matrix.GetScale();

	for (unsigned int i = 0; i < vertexCount; ++i)
	{
		vertices->normal = matrix.Transform(vertices->normal, 0.f) / scale;
		vertices->position = matrix.Transform(vertices->position);
		vertices->tangent = matrix.Transform(vertices->tangent, 0.f) / scale;
		vertices++;
	}
}

#include <Nazara/Utility/DebugOff.hpp>
<commit_msg>Removed Identity test in TransformVertices<commit_after>// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Utility/Debug.hpp>

template<typename T>
NzBoxf NzComputeVerticesAABB(const T* vertices, unsigned int vertexCount)
{
	NzBoxf aabb;
	if (vertexCount > 0)
	{
		aabb.Set(vertices->position.x, vertices->position.y, vertices->position.z, 0.f, 0.f, 0.f);
		vertices++;

		for (unsigned int i = 1; i < vertexCount; ++i)
		{
			aabb.ExtendTo(vertices->position);
			vertices++;
		}
	}
	else
		aabb.MakeZero();

	return aabb;
}

template<typename T>
void NzTransformVertices(T* vertices, unsigned int vertexCount, const NzMatrix4f& matrix)
{
	NzVector3f scale = matrix.GetScale();

	for (unsigned int i = 0; i < vertexCount; ++i)
	{
		vertices->normal = matrix.Transform(vertices->normal, 0.f) / scale;
		vertices->position = matrix.Transform(vertices->position);
		vertices->tangent = matrix.Transform(vertices->tangent, 0.f) / scale;
		vertices++;
	}
}

#include <Nazara/Utility/DebugOff.hpp>
<|endoftext|>


<commit_before>/// ParameterGraph.hpp
/// Shaun Harker
/// 2015-05-24

#ifndef DSGRN_PARAMETERGRAPH_HPP
#define DSGRN_PARAMETERGRAPH_HPP

#ifndef INLINE_IF_HEADER_ONLY
#define INLINE_IF_HEADER_ONLY
#endif

#include "ParameterGraph.h"

INLINE_IF_HEADER_ONLY ParameterGraph::
ParameterGraph ( void ) {
  data_ . reset ( new ParameterGraph_ );
}

INLINE_IF_HEADER_ONLY ParameterGraph::
ParameterGraph ( Network const& network, std::string const& path ) {
  assign ( network, path );
}

INLINE_IF_HEADER_ONLY void ParameterGraph::
assign ( Network const& network, std::string const& path ) {
  data_ . reset ( new ParameterGraph_ );
  data_ -> network_ = network;
  data_ -> reorderings_ = 1;
  data_ -> fixedordersize_ = 1;
  // Load the network files one by one.
  uint64_t D = data_ -> network_ . size ();
  for ( uint64_t d = 0; d < D; ++ d ) {
    uint64_t n = data_ -> network_ . inputs ( d ) . size ();
    uint64_t m = data_ -> network_ . outputs ( d ) . size ();
    data_ -> order_place_values_ . push_back ( _factorial ( m ) );
    data_ -> reorderings_ *= data_ -> order_place_values_ . back ();
    std::vector<std::vector<uint64_t>> const& logic_struct = data_ -> network_ . logic ( d );
    std::stringstream ss;
    ss << path << "/" << n <<  "_" << m;
    for ( auto const& p : logic_struct ) ss <<  "_" << p.size();
    if ( data_ -> network_ . essential ( d ) ) ss << "_E";
    ss << ".dat";
    //std::cout << "Acquiring logic data in " << ss.str() << "\n";
    std::vector<std::string> hex_codes;
    std::ifstream infile ( ss.str() );
    if ( not infile . good () ) {
      throw std::runtime_error ( "Error: Could not find logic resource " + ss.str() + ".\n");
    }
    std::string line;
    while ( std::getline ( infile, line ) ) hex_codes . push_back ( line );
    infile . close ();
    data_ -> factors_ . push_back ( hex_codes );
    data_ -> logic_place_values_ . push_back ( hex_codes . size () );
    data_ -> fixedordersize_ *= hex_codes . size ();
    //std::cout << d << ": " << hex_codes . size () << " factorial(" << m << ")=" << _factorial ( m ) << "\n";
  }
  data_ -> size_ = data_ -> fixedordersize_ * data_ -> reorderings_;
}

INLINE_IF_HEADER_ONLY uint64_t ParameterGraph::
size ( void ) const {
  return data_ -> size_;
}

INLINE_IF_HEADER_ONLY Parameter ParameterGraph::
parameter ( uint64_t index ) const {
  //std::cout << data_ -> "ParameterGraph::parameter( " << index << " )\n";
  if ( index >= size () ) {
    throw std::runtime_error ( "ParameterGraph::parameter Index out of bounds");
  }
  uint64_t logic_index = index % data_ -> fixedordersize_;
  uint64_t order_index = index / data_ -> fixedordersize_;
  //std::cout << "Logic index = " << logic_index << "\n";
  //std::cout << "Order index = " << order_index << "\n";

  uint64_t D = data_ -> network_ . size ();
  std::vector<uint64_t> logic_indices;
  for ( uint64_t d = 0; d < D; ++ d ) {
    uint64_t i = logic_index % data_ -> logic_place_values_ [ d ];
    logic_index /= data_ -> logic_place_values_ [ d ];
    logic_indices . push_back ( i );
  }
  std::vector<uint64_t> order_indices;
  for ( uint64_t d = 0; d < D; ++ d ) {
    uint64_t i = order_index % data_ -> order_place_values_ [ d ];
    order_index /= data_ -> order_place_values_ [ d ];
    order_indices . push_back ( i );
  }
  std::vector<LogicParameter> logic;
  std::vector<OrderParameter> order;
  for ( uint64_t d = 0; d < D; ++ d ) {
    uint64_t n = data_ -> network_ . inputs ( d ) . size ();
    uint64_t m = data_ -> network_ . outputs ( d ) . size ();
    std::string hex_code = data_ -> factors_ [ d ] [ logic_indices[d] ];
    LogicParameter logic_param ( n, m, hex_code );
    OrderParameter order_param ( m, order_indices[d] );
    logic . push_back ( logic_param );
    order . push_back ( order_param );
  }
  Parameter result ( logic, order, data_ -> network_ );
  return result;
}

INLINE_IF_HEADER_ONLY uint64_t ParameterGraph::
index ( Parameter const& p ) const {
//   throw std::runtime_error ( "Feature not implemented" );  // TODO

  std::vector<LogicParameter> logic = p . logic ( );
  std::vector<OrderParameter> order = p . order ( );

  /// Construct Logic indices
  std::vector<uint64_t> logic_indices;
  uint64_t D = data_ -> network_ . size ();
  for ( uint64_t d = 0; d< D; ++d ) {
      std::string hexcode = logic [ d ] . hex ( );
      /// If factors_ was a different container, we could use find instead
      /// find the hex code within factors_ for the appropriate node
      uint64_t hexsize = data_ -> factors_ [ d ] . size ( );
      for ( uint64_t i = 0; i < hexsize; ++i ) {
          if ( hexcode == data_ -> factors_ [ d ] [ i ] ) {
              logic_indices . push_back ( i );
          }
      }
  }
  // debug
  std::cout << "\nLogic indices:\n";
  for ( uint64_t d = 0; d< D; ++d ) std::cout << logic_indices[d] << " ";
  std::cout << "\n";
  // end debug

  /// Construct Order indices
  std::vector<uint64_t> order_indices;
  for ( uint64_t d = 0; d < D; ++ d ) {
      order_indices . push_back ( order[d].index() );
  }
  // debug
  std::cout << "\nOrder indices:\n";
  for ( uint64_t d = 0; d< D; ++d ) std::cout << order_indices[d] << " ";
  std::cout << "\n";
  // end debug

  // Debug
  std::cout << "\n\n";
  std::cout << "Logic_place_values : ";
  for ( uint64_t d = 0; d< D; ++d ) std::cout << data_ -> logic_place_values_[d] << " ";
  std::cout << "\n";
  std::cout << "Order_place_values : ";
  for ( uint64_t d = 0; d< D; ++d ) std::cout << data_ -> order_place_values_[d] << " ";
  std::cout << "\n";
  std::cout << "Fixed order size : " << data_ -> fixedordersize_;
  std::cout << "\n\n";
  // end debug

  /// Find logic_index and order_index, in general
  /// notation :
  /// Logic_place_values : lpv
  /// logics_indices : lis
  ///
  /// For the logic index L :
  /// A[n] = m_n * lpv[n] + lis[n] for n > 1, and m_n are unknown integers.
  /// L = m_0 * lpv[0] + lis[0] for n = 0
  /// with
  ///     A[n] = floor( A[n-1] / lpv[n-1] ) and A[0] = L
  ///

/// BELOW WAS INCOMPLETE TEST FOR 2 NODES NETWORKS
  // /// Return : m * Q + R
  // auto getInteger = []( const uint64_t &m, const uint64_t &Q, const uint64_t &R ) -> uint64_t {
  //     return m * Q + R;
  // };
  //
  // typedef std::vector<uint64_t> Interval;
  //
  // /// Return interval of the form : [ m*n*k+m*a, m*n*k+m*a+m )
  // auto getInterval = [](uint64_t &k, uint64_t &m, uint64_t &n, uint64_t &a ) -> Interval  {
  //     return Interval { m*n*k+m*a,m*n*k+m*a+m };
  // };
  //
  // auto insideInterval = [](uint64_t &n, Interval &interval) -> bool {
  //   return n>=interval[0] && n<=interval[1];
  // };
  //
  // // List all the subintervals for logic_index and store the potential good values for logic index
  // std::cout << "\n\nList of all subintervals for logic index\n";
  // std::vector<Interval> intervals; // needed just for debug
  // std::vector<uint64_t> logicindexvalues;
  // for ( uint64_t R = 0; R<data_->reorderings_; ++R ) {
  //     Interval interval = getInterval( R,
  //                                      data_ -> logic_place_values_[0],
  //                                      data_ -> logic_place_values_[1],
  //                                      logic_indices[1] );
  //     std::cout << "[ " << interval[0] << ", " << interval[1] << " ]\n";
  //     intervals . push_back ( interval );
  //     /// check for good values inside the interval
  //     uint64_t myvalue = getInteger(data_ -> logic_place_values_[0],
  //                                   R*data_ -> logic_place_values_[1]+logic_indices[1],
  //                                   logic_indices[0]);
  //     std::cout << "value=" << myvalue << " ";
  //     if ( insideInterval(myvalue,interval) ) {
  //         std::cout << "is good\n";
  //         logicindexvalues . push_back ( myvalue );
  //     } else {
  //         std::cout << "is bad\n";
  //     }
  // }
  // // List all the subintervals for order_index and store the potential good values for order index

/// END INCOMPLETE TEST 2 NODES NETWORK

  return 0;

}

INLINE_IF_HEADER_ONLY std::vector<uint64_t> ParameterGraph::
adjacencies ( uint64_t index ) const {
  throw std::runtime_error ( "Feature not implemented" );   //TODO
}

INLINE_IF_HEADER_ONLY Network const ParameterGraph::
network ( void ) const {
  return data_ -> network_;
}

INLINE_IF_HEADER_ONLY std::ostream& operator << ( std::ostream& stream, ParameterGraph const& pg ) {
  stream <<  "(ParameterGraph: "<< pg.size() << " parameters, "
         << pg.network().size() << " nodes)";
  return stream;
}

INLINE_IF_HEADER_ONLY uint64_t ParameterGraph::
fixedordersize ( void ) const {
  return data_ -> fixedordersize_;
}

INLINE_IF_HEADER_ONLY uint64_t ParameterGraph::
reorderings ( void ) const {
  return data_ -> reorderings_;
}

INLINE_IF_HEADER_ONLY uint64_t ParameterGraph::
_factorial ( uint64_t m ) const {
  static const std::vector<uint64_t> table =
    { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
  if ( m < 10 ) return table [ m ]; else return m * _factorial ( m - 1 );
}

#endif
<commit_msg>[WIP] debug index method for 2 nodes network<commit_after>/// ParameterGraph.hpp
/// Shaun Harker
/// 2015-05-24

#ifndef DSGRN_PARAMETERGRAPH_HPP
#define DSGRN_PARAMETERGRAPH_HPP

#ifndef INLINE_IF_HEADER_ONLY
#define INLINE_IF_HEADER_ONLY
#endif

#include "ParameterGraph.h"

INLINE_IF_HEADER_ONLY ParameterGraph::
ParameterGraph ( void ) {
  data_ . reset ( new ParameterGraph_ );
}

INLINE_IF_HEADER_ONLY ParameterGraph::
ParameterGraph ( Network const& network, std::string const& path ) {
  assign ( network, path );
}

INLINE_IF_HEADER_ONLY void ParameterGraph::
assign ( Network const& network, std::string const& path ) {
  data_ . reset ( new ParameterGraph_ );
  data_ -> network_ = network;
  data_ -> reorderings_ = 1;
  data_ -> fixedordersize_ = 1;
  // Load the network files one by one.
  uint64_t D = data_ -> network_ . size ();
  for ( uint64_t d = 0; d < D; ++ d ) {
    uint64_t n = data_ -> network_ . inputs ( d ) . size ();
    uint64_t m = data_ -> network_ . outputs ( d ) . size ();
    data_ -> order_place_values_ . push_back ( _factorial ( m ) );
    data_ -> reorderings_ *= data_ -> order_place_values_ . back ();
    std::vector<std::vector<uint64_t>> const& logic_struct = data_ -> network_ . logic ( d );
    std::stringstream ss;
    ss << path << "/" << n <<  "_" << m;
    for ( auto const& p : logic_struct ) ss <<  "_" << p.size();
    if ( data_ -> network_ . essential ( d ) ) ss << "_E";
    ss << ".dat";
    //std::cout << "Acquiring logic data in " << ss.str() << "\n";
    std::vector<std::string> hex_codes;
    std::ifstream infile ( ss.str() );
    if ( not infile . good () ) {
      throw std::runtime_error ( "Error: Could not find logic resource " + ss.str() + ".\n");
    }
    std::string line;
    while ( std::getline ( infile, line ) ) hex_codes . push_back ( line );
    infile . close ();
    data_ -> factors_ . push_back ( hex_codes );
    data_ -> logic_place_values_ . push_back ( hex_codes . size () );
    data_ -> fixedordersize_ *= hex_codes . size ();
    //std::cout << d << ": " << hex_codes . size () << " factorial(" << m << ")=" << _factorial ( m ) << "\n";
  }
  data_ -> size_ = data_ -> fixedordersize_ * data_ -> reorderings_;
}

INLINE_IF_HEADER_ONLY uint64_t ParameterGraph::
size ( void ) const {
  return data_ -> size_;
}

INLINE_IF_HEADER_ONLY Parameter ParameterGraph::
parameter ( uint64_t index ) const {
  //std::cout << data_ -> "ParameterGraph::parameter( " << index << " )\n";
  if ( index >= size () ) {
    throw std::runtime_error ( "ParameterGraph::parameter Index out of bounds");
  }
  uint64_t logic_index = index % data_ -> fixedordersize_;
  uint64_t order_index = index / data_ -> fixedordersize_;
  //std::cout << "Logic index = " << logic_index << "\n";
  //std::cout << "Order index = " << order_index << "\n";

  uint64_t D = data_ -> network_ . size ();
  std::vector<uint64_t> logic_indices;
  for ( uint64_t d = 0; d < D; ++ d ) {
    uint64_t i = logic_index % data_ -> logic_place_values_ [ d ];
    logic_index /= data_ -> logic_place_values_ [ d ];
    logic_indices . push_back ( i );
  }
  std::vector<uint64_t> order_indices;
  for ( uint64_t d = 0; d < D; ++ d ) {
    uint64_t i = order_index % data_ -> order_place_values_ [ d ];
    order_index /= data_ -> order_place_values_ [ d ];
    order_indices . push_back ( i );
  }
  std::vector<LogicParameter> logic;
  std::vector<OrderParameter> order;
  for ( uint64_t d = 0; d < D; ++ d ) {
    uint64_t n = data_ -> network_ . inputs ( d ) . size ();
    uint64_t m = data_ -> network_ . outputs ( d ) . size ();
    std::string hex_code = data_ -> factors_ [ d ] [ logic_indices[d] ];
    LogicParameter logic_param ( n, m, hex_code );
    OrderParameter order_param ( m, order_indices[d] );
    logic . push_back ( logic_param );
    order . push_back ( order_param );
  }
  Parameter result ( logic, order, data_ -> network_ );
  return result;
}

INLINE_IF_HEADER_ONLY uint64_t ParameterGraph::
index ( Parameter const& p ) const {
//   throw std::runtime_error ( "Feature not implemented" );  // TODO

  std::vector<LogicParameter> logic = p . logic ( );
  std::vector<OrderParameter> order = p . order ( );

  /// Construct Logic indices
  std::vector<uint64_t> logic_indices;
  uint64_t D = data_ -> network_ . size ();
  for ( uint64_t d = 0; d< D; ++d ) {
      std::string hexcode = logic [ d ] . hex ( );
      /// If factors_ was a different container, we could use find instead
      /// find the hex code within factors_ for the appropriate node
      uint64_t hexsize = data_ -> factors_ [ d ] . size ( );
      for ( uint64_t i = 0; i < hexsize; ++i ) {
          if ( hexcode == data_ -> factors_ [ d ] [ i ] ) {
              logic_indices . push_back ( i );
          }
      }
  }
  // debug
  std::cout << "\nLogic indices:\n";
  for ( uint64_t d = 0; d< D; ++d ) std::cout << logic_indices[d] << " ";
  std::cout << "\n";
  // end debug

  /// Construct Order indices
  std::vector<uint64_t> order_indices;
  for ( uint64_t d = 0; d < D; ++ d ) {
      order_indices . push_back ( order[d].index() );
  }
  // debug
  std::cout << "\nOrder indices:\n";
  for ( uint64_t d = 0; d< D; ++d ) std::cout << order_indices[d] << " ";
  std::cout << "\n";
  // end debug

  // Debug
  std::cout << "\n\n";
  std::cout << "Logic_place_values : ";
  for ( uint64_t d = 0; d< D; ++d ) std::cout << data_ -> logic_place_values_[d] << " ";
  std::cout << "\n";
  std::cout << "Order_place_values : ";
  for ( uint64_t d = 0; d< D; ++d ) std::cout << data_ -> order_place_values_[d] << " ";
  std::cout << "\n";
  std::cout << "Fixed order size : " << data_ -> fixedordersize_;
  std::cout << "\n";
  std::cout << "reorderings : " << data_ -> reorderings_;
  std::cout << "\n\n";
  // end debug

  /// Find logic_index and order_index, in general
  /// notation :
  /// Logic_place_values : lpv
  /// logics_indices : lis
  ///
  /// For the logic index L :
  /// A[n] = m_n * lpv[n] + lis[n] ,m_n are unknown integers.
  /// L = m_0 * lpv[0] + lis[0] for n = 0
  /// with
  ///     A[n] = floor( A[n-1] / lpv[n-1] ) and A[0] = L
  ///
  /// By using the floor function at the step n, we have :
  ///
  /// lpv[n-1]*( m_n * lpv[n] + lis[n] ) <= A[n-1] < lpv[n-1]*( m_n * lpv[n] + lis[n] + 1 )
  ///
  /// so A[n-1] is a set of intervals of the form
  ///     I_{n-1} = [ a_{n-1}, b_{n-1} )   for various m_n (positive integers)
  ///     with
  ///         a_{n-1} = lpv[n-1]*( m_n * lpv[n] + lis[n] )
  ///         b_{n-1} = lpv[n-1]*( m_n * lpv[n] + lis[n] + 1 ) = a_{n-1} + lpv[n-1]
  ///
  ///

  /// and according to the step n-1
  ///
  /// A[n-1] = m_{n-1} * lpv[n-1] + lis[n-1]
  ///
  /// Find all m_{n-1} such that A[n-1] is in the set I_{n-1}
  /// (hmmmm no)
  /// ...

  ///=========================
  /// Using only A[0] and A[1]

  /// A[0] = m_0 * lpv[0] + lis[0]  : GOAL : Find m_0

  /// A[1] = m_1 * lpv[1] + lis[1]
  ///        lpv[0]*( m_1 * lpv[1] + lis[1] ) <= A[0] < lpv[0]*( m_1 * lpv[1] + lis[1] + 1 )
  ///
  /// Find the set of intervals {I_1}

/// BELOW WAS INCOMPLETE TEST FOR 2 NODES NETWORKS
  /// Return : m * Q + R
  auto getInteger = []( const uint64_t &m, const uint64_t &Q, const uint64_t &R ) -> uint64_t {
      return m * Q + R;
  };

  typedef std::vector<uint64_t> Interval;

  /// Return interval of the form : [ m*n*k+m*a, m*n*k+m*a+m )
  auto getInterval = [](uint64_t &k, uint64_t &m, uint64_t &n, uint64_t &a ) -> Interval  {
      return Interval { m*n*k+m*a,m*n*k+m*a+m };
  };

  auto insideInterval = [](uint64_t &n, Interval &interval) -> bool {
    return n>=interval[0] && n<=interval[1];
  };

  // List all the subintervals for logic_index and store the potential good values for logic index
  std::cout << "\n\nList of all subintervals for logic index\n";
  std::vector<Interval> intervals; // needed just for debug
  std::vector<uint64_t> logicindexvalues;
  for ( uint64_t R = 0; R<data_->reorderings_; ++R ) {
      Interval interval = getInterval( R,
                                       data_ -> logic_place_values_[0],
                                       data_ -> logic_place_values_[1],
                                       logic_indices[1] );
      std::cout << "[ " << interval[0] << ", " << interval[1] << " ]\n";
      // intervals . push_back ( interval );
      /// check for good values inside the interval
      uint64_t myvalue = getInteger(data_ -> logic_place_values_[0],
                                    R*data_ -> logic_place_values_[1]+logic_indices[1],
                                    logic_indices[0]);
      std::cout << "value=" << myvalue << " ";
      if ( insideInterval(myvalue,interval) ) {
          std::cout << "is good\n";
          logicindexvalues . push_back ( myvalue );
      } else {
          std::cout << "is bad\n";
      }
  }
  // List all the subintervals for order_index and store the potential good values for order index
  std::vector<uint64_t> orderindexvalues;
  for ( uint64_t R = 0; R<data_->reorderings_; ++R ) {
      Interval interval = getInterval( R,
                                       data_ -> order_place_values_[0],
                                       data_ -> order_place_values_[1],
                                       order_indices[1] );
      std::cout << "[ " << interval[0] << ", " << interval[1] << " ]\n";
      // intervals . push_back ( interval );
      /// check for good values inside the interval
      uint64_t myvalue = getInteger(data_ -> order_place_values_[0],
                                    R*data_ -> order_place_values_[1]+order_indices[1],
                                    order_indices[0]);
      std::cout << "value=" << myvalue << " ";
      if ( insideInterval(myvalue,interval) ) {
          std::cout << "is good\n";
          orderindexvalues . push_back ( myvalue );
      } else {
          std::cout << "is bad\n";
      }
  }

  // Find which pair of logicindexvalues and orderindexvalues is correct
  for ( uint64_t L : logicindexvalues ) {
    for ( uint64_t O : orderindexvalues ) {
      uint64_t myindex = O * data_ -> fixedordersize_ + L;

      if ( myindex < size() ) {
        std::cout << "Found a good pair (L,O)=( " << L << ", " << O << " ) with index : " << myindex << "\n";
      }

    }
  }

/// END INCOMPLETE TEST 2 NODES NETWORK

  return 0;

}

INLINE_IF_HEADER_ONLY std::vector<uint64_t> ParameterGraph::
adjacencies ( uint64_t index ) const {
  throw std::runtime_error ( "Feature not implemented" );   //TODO
}

INLINE_IF_HEADER_ONLY Network const ParameterGraph::
network ( void ) const {
  return data_ -> network_;
}

INLINE_IF_HEADER_ONLY std::ostream& operator << ( std::ostream& stream, ParameterGraph const& pg ) {
  stream <<  "(ParameterGraph: "<< pg.size() << " parameters, "
         << pg.network().size() << " nodes)";
  return stream;
}

INLINE_IF_HEADER_ONLY uint64_t ParameterGraph::
fixedordersize ( void ) const {
  return data_ -> fixedordersize_;
}

INLINE_IF_HEADER_ONLY uint64_t ParameterGraph::
reorderings ( void ) const {
  return data_ -> reorderings_;
}

INLINE_IF_HEADER_ONLY uint64_t ParameterGraph::
_factorial ( uint64_t m ) const {
  static const std::vector<uint64_t> table =
    { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
  if ( m < 10 ) return table [ m ]; else return m * _factorial ( m - 1 );
}

#endif
<|endoftext|>


<commit_before>/*  Copyright (C) 2009  Adenilson Cavalcanti <savagobr@yahoo.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; by version 2 of the License or (at your
 *  choice) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "gcalresource.h"
#include "settings.h"
#include "settingsadaptor.h"

#include <QtDBus/QDBusConnection>
#include <QDate>
#include <kabc/addressee.h>
#include <kabc/phonenumber.h>
#include <kabc/key.h>
#include <kabc/errorhandler.h>
#include <kcal/event.h>
#include <kdatetime.h>
#include <qstring.h>
#include <KWindowSystem>
#include <akonadi/changerecorder.h>
#include <akonadi/itemfetchscope.h>
#include <KUrl>

extern "C" {
#include <gcalendar.h>
#include <gcal_status.h>
}

using namespace Akonadi;

GCalResource::GCalResource( const QString &id )
	: ResourceBase(id)
{
	new SettingsAdaptor( Settings::self() );
	QDBusConnection::sessionBus().registerObject(
		QLatin1String( "/Settings" ), Settings::self(),
		QDBusConnection::ExportAdaptors );

	changeRecorder()->itemFetchScope().fetchFullPayload();

    if (!(gcal = gcal_new(GCALENDAR)))
		exit(1);
    gcal_set_store_xml(gcal, 1);
    all_events.length = 0;
    all_events.entries = NULL;
}

GCalResource::~GCalResource()
{
    gcal_cleanup_events(&all_events);
    pending.clear();
    deleted.clear();
}

void GCalResource::retrieveTimestamp(QString &timestamp)
{
	timestamp = Settings::self()->timestamp();
}

void GCalResource::saveTimestamp(QString &timestamp)
{
    Settings::self()->setTimestamp(timestamp);
    Settings::self()->writeConfig();
}

void GCalResource::retrieveCollections()
{
    if(!authenticated) {
		kError() << "No authentication for Google Calendar available";
                const QString message = i18nc("@info: status",
					      "Not yet authenticated for "
					      "use of Google Calendar");

        emit error(message);

        emit status(Broken, message);
        return;
    }

    Collection c;
    c.setParent(Collection::root());
    c.setRemoteId("google-calendar");
    c.setName(name());

    QStringList mimeTypes;
    mimeTypes << "text/calendar";
    c.setContentMimeTypes(mimeTypes);

    Collection::List list;
    list << c;
    collectionsRetrieved(list);
}

void GCalResource::retrieveItems( const Akonadi::Collection &collection )
{
    Q_UNUSED(collection);
    Item::List items;
    int result;
	gcal_event_t event;
	QString timestamp;
	QByteArray t_byte;

	kError() << "\n............. retrieveItems ...........\n";
	if (!authenticated) {
		kError() << "No authentication for Google calendar available";
		const QString message = i18nc("@info:status",
					      "Not yet authenticated for"
					      " use of Google calendar");
		emit error(message);
		emit status(Broken, message);
		return;
	}

	/* Query by updated */
	retrieveTimestamp(timestamp);
	t_byte = timestamp.toLocal8Bit();
	if (t_byte.length() > TIMESTAMP_SIZE) {
		//TODO: implement getUpdated
		//result = getUpdated(t_byte.data());
		return;
	}
	kError() << "First retrieve";

	if ((result = gcal_get_events(gcal, &all_events)))
		exit(1);

	/* GCalendar returns last updated entry as first element */
	event = gcal_event_element(&all_events, 0);
	if (!event) {
		kError() << "Failed to retrieve last updated event.";
		const QString message = i18nc("@info:status",
					      "Failed getting last updated"
					      " event");
		emit error(message);
		emit status(Broken, message);
		return;

	}

	timestamp = gcal_event_get_updated(event);
	saveTimestamp(timestamp);

	/* Each google entry has a unique ID and edit_url */
	for (size_t i = 0; i < all_events.length; ++i) {
		Item item(QLatin1String("text/calendar"));
		KCal::Event kevent;
		QString temp;
		event = gcal_event_element(&all_events, i);

		temp = gcal_event_get_title(event);
		kevent.setSummary(temp);

		temp = gcal_event_get_where(event);
		kevent.setLocation(temp);

		temp = gcal_event_get_status(event);
		KCal::Incidence::Status status;
		if (gcal_event_is_deleted(event))
			status = KCal::Incidence::StatusCanceled;
		else
			status = KCal::Incidence::StatusConfirmed;
		kevent.setStatus(status);

		temp = gcal_event_get_content(event);
		kevent.setDescription(temp);

		/* TODO: there must exit an easier way */
		QDate start, end;
		temp = gcal_event_get_start(event);
		start.fromString(temp, Qt::ISODate);
		temp = gcal_event_get_end(event);
		end.fromString(temp, Qt::ISODate);
		KDateTime time_start(start), time_end(end);
		kevent.setDtStart(time_start);
		kevent.setDtEnd(time_end);

	}
}

bool GCalResource::retrieveItem( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED(parts);
	Q_UNUSED(item);
	return true;
}

void GCalResource::aboutToQuit()
{
	// TODO: any cleanup you need to do while there is still an active
	// event loop. The resource will terminate after this method returns
}

void GCalResource::doSetOnline(bool online)
{
	Q_UNUSED(online);
}

int GCalResource::getUpdated(char *timestamp)
{
	Q_UNUSED(timestamp);

	return -1;
}

void GCalResource::configure( WId windowId )
{
	Q_UNUSED(windowId);

}

void GCalResource::itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection )
{
	Q_UNUSED(collection);
	Q_UNUSED(item);
}

void GCalResource::itemChanged( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED(parts);
	Q_UNUSED(item);
}

void GCalResource::itemRemoved( const Akonadi::Item &item )
{
	Q_UNUSED(item);
}

AKONADI_RESOURCE_MAIN( GCalResource )

#include "gcalresource.moc"
<commit_msg>Removing unused function call.<commit_after>/*  Copyright (C) 2009  Adenilson Cavalcanti <savagobr@yahoo.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; by version 2 of the License or (at your
 *  choice) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "gcalresource.h"
#include "settings.h"
#include "settingsadaptor.h"

#include <QtDBus/QDBusConnection>
#include <QDate>
#include <kabc/addressee.h>
#include <kabc/phonenumber.h>
#include <kabc/key.h>
#include <kabc/errorhandler.h>
#include <kcal/event.h>
#include <kdatetime.h>
#include <qstring.h>
#include <KWindowSystem>
#include <akonadi/changerecorder.h>
#include <akonadi/itemfetchscope.h>
#include <KUrl>

extern "C" {
#include <gcalendar.h>
#include <gcal_status.h>
}

using namespace Akonadi;

GCalResource::GCalResource( const QString &id )
	: ResourceBase(id)
{
	new SettingsAdaptor( Settings::self() );
	QDBusConnection::sessionBus().registerObject(
		QLatin1String( "/Settings" ), Settings::self(),
		QDBusConnection::ExportAdaptors );

	changeRecorder()->itemFetchScope().fetchFullPayload();

    if (!(gcal = gcal_new(GCALENDAR)))
		exit(1);
    gcal_set_store_xml(gcal, 1);
    all_events.length = 0;
    all_events.entries = NULL;
}

GCalResource::~GCalResource()
{
    gcal_cleanup_events(&all_events);
    pending.clear();
    deleted.clear();
}

void GCalResource::retrieveTimestamp(QString &timestamp)
{
	timestamp = Settings::self()->timestamp();
}

void GCalResource::saveTimestamp(QString &timestamp)
{
    Settings::self()->setTimestamp(timestamp);
    Settings::self()->writeConfig();
}

void GCalResource::retrieveCollections()
{
    if(!authenticated) {
		kError() << "No authentication for Google Calendar available";
                const QString message = i18nc("@info: status",
					      "Not yet authenticated for "
					      "use of Google Calendar");

        emit error(message);

        emit status(Broken, message);
        return;
    }

    Collection c;
    c.setParent(Collection::root());
    c.setRemoteId("google-calendar");
    c.setName(name());

    QStringList mimeTypes;
    mimeTypes << "text/calendar";
    c.setContentMimeTypes(mimeTypes);

    Collection::List list;
    list << c;
    collectionsRetrieved(list);
}

void GCalResource::retrieveItems( const Akonadi::Collection &collection )
{
    Q_UNUSED(collection);
    Item::List items;
    int result;
	gcal_event_t event;
	QString timestamp;
	QByteArray t_byte;

	kError() << "\n............. retrieveItems ...........\n";
	if (!authenticated) {
		kError() << "No authentication for Google calendar available";
		const QString message = i18nc("@info:status",
					      "Not yet authenticated for"
					      " use of Google calendar");
		emit error(message);
		emit status(Broken, message);
		return;
	}

	/* Query by updated */
	retrieveTimestamp(timestamp);
	t_byte = timestamp.toLocal8Bit();
	if (t_byte.length() > TIMESTAMP_SIZE) {
		//TODO: implement getUpdated
		//result = getUpdated(t_byte.data());
		return;
	}
	kError() << "First retrieve";

	if ((result = gcal_get_events(gcal, &all_events)))
		exit(1);

	/* GCalendar returns last updated entry as first element */
	event = gcal_event_element(&all_events, 0);
	if (!event) {
		kError() << "Failed to retrieve last updated event.";
		const QString message = i18nc("@info:status",
					      "Failed getting last updated"
					      " event");
		emit error(message);
		emit status(Broken, message);
		return;

	}

	timestamp = gcal_event_get_updated(event);
	saveTimestamp(timestamp);

	/* Each google entry has a unique ID and edit_url */
	for (size_t i = 0; i < all_events.length; ++i) {
		Item item(QLatin1String("text/calendar"));
		KCal::Event kevent;
		QString temp;
		event = gcal_event_element(&all_events, i);

		temp = gcal_event_get_title(event);
		kevent.setSummary(temp);

		temp = gcal_event_get_where(event);
		kevent.setLocation(temp);

		KCal::Incidence::Status status;
		if (gcal_event_is_deleted(event))
			status = KCal::Incidence::StatusCanceled;
		else
			status = KCal::Incidence::StatusConfirmed;
		kevent.setStatus(status);

		temp = gcal_event_get_content(event);
		kevent.setDescription(temp);

		/* TODO: there must exit an easier way */
		QDate start, end;
		temp = gcal_event_get_start(event);
		start.fromString(temp, Qt::ISODate);
		temp = gcal_event_get_end(event);
		end.fromString(temp, Qt::ISODate);
		KDateTime time_start(start), time_end(end);
		kevent.setDtStart(time_start);
		kevent.setDtEnd(time_end);

	}
}

bool GCalResource::retrieveItem( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED(parts);
	Q_UNUSED(item);
	return true;
}

void GCalResource::aboutToQuit()
{
	// TODO: any cleanup you need to do while there is still an active
	// event loop. The resource will terminate after this method returns
}

void GCalResource::doSetOnline(bool online)
{
	Q_UNUSED(online);
}

int GCalResource::getUpdated(char *timestamp)
{
	Q_UNUSED(timestamp);

	return -1;
}

void GCalResource::configure( WId windowId )
{
	Q_UNUSED(windowId);

}

void GCalResource::itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection )
{
	Q_UNUSED(collection);
	Q_UNUSED(item);
}

void GCalResource::itemChanged( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED(parts);
	Q_UNUSED(item);
}

void GCalResource::itemRemoved( const Akonadi::Item &item )
{
	Q_UNUSED(item);
}

AKONADI_RESOURCE_MAIN( GCalResource )

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


<commit_before>#ifndef CLAMMBON_SORT_GENETIC_HPP
#define CLAMMBON_SORT_GENETIC_HPP

#include <algorithm>
#include <iomanip> // std::setwのみ
#include <random>
#include <boost/range/algorithm.hpp>

int constexpr PARENT_NUM = 10;
int constexpr CHILDREN_NUM = 100;

class genetic
{
private:
    typedef std::vector<std::vector<std::vector<std::vector<direction_type<uint64_t>>>>> compared_type;

	struct children_t { std::vector<int> children_gene; unsigned int assessment;};//子供の遺伝子と評価値
	std::vector<children_t> children_;//子供の遺伝子と評価値の配列

    question_raw_data *data_;
    compared_type *comp_;

    // std::mt19937_64ほど高級なもの要る？
    mutable std::mt19937 mt_;

    void shuffle(std::vector<int>& arr) const
    {
        std::uniform_int_distribution<int> distribution(0, arr.size()-1);

        for(int i = 0; i < arr.size(); ++i)
        {
            int j = distribution(mt_);
            std::swap(arr[i], arr[j]);
        }
    }

    void shuffle_all()
    {
        for(auto it = children_.begin(); it != children_.end(); ++it)
        {
            shuffle(it->children_gene);
        }
    }

    unsigned int assess(std::vector<int> const& arr) const
    {
        auto const sepx = data_->split_num.first;
        auto const sepy = data_->split_num.second;

        unsigned int ass = 0;
        for(int i = 0; i < arr.size(); ++i)
        {
            if(i + 1 < arr.size())
            {
                if(arr[i] == arr[i + 1])
                {
                    std::cout << "!!!" << arr[i] << arr[i + 1] << std::endl;
                }
                ass += (*comp_)[arr[i] / sepx][arr[i] % sepx][arr[i + 1] / sepx][arr[i + 1] % sepx].right;
            }
            if(i + sepy < arr.size())
            {
                if(arr[i] == arr[i + sepy])
                {
                    std::cout << "???" << arr[i] << arr[i + sepy] << std::endl;
                }
                ass += (*comp_)[arr[i] / sepx][arr[i] % sepx][arr[i + sepy] / sepx][arr[i + sepy] % sepx].right;
            }
        }
        return ass;
    }

    void assess_all()
    {
        for(auto it = children_.begin(); it != children_.end(); ++it)
        {
            //for(int i = 0; i < split_total; ++i)
            //{
            //    std::cout << it->children_gene[i] << " - ";
            //}
            it->assessment = assess(it->children_gene);
		    //std::cout << "     " << it->assessment << std::endl;
        }
    }

    std::vector<std::vector<int>> select_parent(std::vector<int>& top10)
    {
        top10.assign(PARENT_NUM, 0);

        std::vector<int> childred_copy;
        childred_copy.reserve(children_.size());

        boost::transform(
            children_, std::back_inserter(childred_copy),
            [](children_t const& base){ return base.assessment; }
            );
        boost::sort(childred_copy);
        //boost::for_each(childred_copy, [](int const base){ std::cout << base << std::endl; });

        for(int i=0; i<top10.size(); ++i)
        {
            for(int j=0; j<CHILDREN_NUM; ++j)
            {
                if(childred_copy.at(i) == children_[j].assessment)
                {
                    top10[i] = j;
                }
            }
        }

        auto const split_total = data_->split_num.first * data_->split_num.second;
        std::vector<std::vector<int>> parent_gene(PARENT_NUM, std::vector<int>(split_total, 0));

        //親遺伝子配列にいいやつTop10を突っ込む
        for(int i=0; i<top10.size(); ++i)
        {
            for(int j=0; j<split_total; ++j)
            {
                parent_gene[i][j] = children_[top10[i]].children_gene[j];
            }
        }

        std::cout << "番号  " << "評価" << std::endl;
        for(auto const& elem : top10)
        {
            std::cout << elem << "   " << children_[elem].assessment << std::endl;
        }

        return parent_gene;
    }

    void cross_over(std::vector<std::vector<int>> const& parent_gene)
    {
        auto const split_width  = data_->split_num.first;
        auto const split_height = data_->split_num.second;
        auto const split_total  = split_width * split_height;

        std::uniform_int_distribution<int> parent_dist(0, PARENT_NUM - 1);
        std::uniform_int_distribution<int> mutate_dist(0, 4 - 1);
        std::uniform_int_distribution<int> split_dist(0, split_total - 1);

        for(int i=0; i<CHILDREN_NUM; i+=2)
        {
            auto const& pra1 = parent_gene[parent_dist(mt_)];
            auto const& pra2 = parent_gene[parent_dist(mt_)];
            auto      & child1 = children_[i  ].children_gene;
            auto      & child2 = children_[i+1].children_gene;

            //std::cout << "par1 ";
            //boost::for_each(pra1, [](int const elem){ std::cout << elem << "*"; });
            //std::cout << std::endl;
            //
            //std::cout << "par2 ";
            //boost::for_each(pra2, [](int const elem){ std::cout << elem << "*"; });
            //std::cout << std::endl;

            child1.assign(child1.size(), -1);
            child2.assign(child2.size(), -1);

            int select_gene = split_dist(mt_);
            //std::cout << "  s" << select_gene;
            while(child1[select_gene] != pra1[select_gene])
            {
			    child1[select_gene] = pra1[select_gene];
			    child2[select_gene] = pra2[select_gene];

                for(int i=0; i<split_total; ++i)
                {
                    if(child2[select_gene] == pra1[i])
                    {
                        select_gene = i;
                    }
                }
                //std::cout << "  s" << select_gene;
            }

            for(int i=0; i<split_total; ++i)
            {
                if(child1[i] == -1)
                {
				    child1[i] = pra2[i];
				    child2[i] = pra1[i];
                }
            }

            for(int n = parent_dist(mt_); n < 10; ++n) //このループ数をいじらないと収束しなかったりすぐに収束してしまったり
            {
                if(mutate_dist(mt_) == 0) //ここの確率で突然変異率を変化させる
                {
                    int rand1 = split_dist(mt_);
                    int rand2 = split_dist(mt_);
                    std::swap(child1[rand1], child1[rand2]);
                    //std::cout << "rand1" << std::endl;
                }
                if(mutate_dist(mt_) == 0) //ここの確率で突然変異率を変化させる
                {
                    int rand1 = split_dist(mt_);
                    int rand2 = split_dist(mt_);
                    std::swap(child2[rand1], child2[rand2]);
				    //std::cout << "rand2" << std::endl;
                }
            }

            //std::cout << std::endl;
            //std::cout << "chi1 ";
            //boost::for_each(child1, [](int const elem){ std::cout << elem << "+"; });
            //
            //std::cout << std::endl;
            //std::cout << "chi2 ";
            //boost::for_each(child2, [](int const elem){ std::cout << elem << "+"; });
            //
            //std::cout << std::endl;
        }
    }

public:
    // 泣きのポインタ渡し
    genetic(question_raw_data *data, compared_type *comp)
        : data_(data), comp_(comp)
    {
        //メルセンヌ・ツイスタの初期化
        std::random_device rd;
        std::vector<std::uint_least64_t> random_seed(10);
        boost::generate(random_seed, std::ref(rd));
        mt_.seed(std::seed_seq(random_seed.cbegin(), random_seed.cend()));
    }
    virtual ~genetic() = default;

    int sort()
    {
        auto const split_total = data_->split_num.first * data_->split_num.second;

        // children_の初期化
        {
            //連番リスト(0~split_total-1)の作製
            std::vector<int> tmp_vector;
            tmp_vector.reserve(split_total);
            for(int i = 0; i < split_total; ++i) tmp_vector.push_back(i);

            //連番リストでchildren_を初期化
            children_.assign(CHILDREN_NUM, {tmp_vector, 0});
        }

        shuffle_all();
        assess_all();

        int top;
        std::vector<int> top10(PARENT_NUM);
        std::vector<int> toppers(1000);
        for(int i = 0; i < toppers.size(); ++i)
        {
            for(int j = 0; j < 10000; ++j)
            {
                auto const parent_gene = select_parent(top10);
                top = children_.at(top10[0]).assessment;

                cross_over(parent_gene);
                assess_all();

			    std::cout << "最上位遺伝子";
			    for (int i = 0; i < split_total; i++)
                {
				    std::cout << std::setw(3) << parent_gene[0][i]; //unspecified(std::setw)
			    }

                std::cout << "番号" << top10[0] << std::endl;

                int const base = top10[0]; // VCのための苦肉の策
                if(
                    std::all_of(
                        top10.begin(), top10.end(),
                        [base](int const elem){ return base == elem; }
                        //[base = top10[0]](int const elem){ return base == elem; }
                    )
                )
                {
                    //Top10の遺伝子がすべて同じものになったら収束したと判断する
                    break;
                }
                std::cout << "世代=" << j << "ループ" << i << std::endl;

            }
            toppers[i] = top;

            shuffle_all();
        }

	    int toptop = std::numeric_limits<int>::max();
	    int topnum = 0;
	    for(auto const elem : toppers)
        {
            if(elem < toptop)
            {
                toptop = elem;
                topnum = 0;
            }
            else if(elem == toptop)
            {
                ++topnum;
            }
		    std::cout << elem << std::endl;
        }
	    std::cout << "最適値" << toptop << "数" << topnum << std::endl;
    }

};

#endif
<commit_msg>g++/clangに対応<commit_after>#ifndef CLAMMBON_SORT_GENETIC_HPP
#define CLAMMBON_SORT_GENETIC_HPP

#include <iostream>
#include <algorithm>
#include <functional>
#include <iomanip> // std::setwのみ
#include <random>
#include <boost/range/algorithm.hpp>

int constexpr PARENT_NUM = 10;
int constexpr CHILDREN_NUM = 100;

class genetic
{
private:
    typedef std::vector<std::vector<std::vector<std::vector<direction_type<uint64_t>>>>> compared_type;

	struct children_t { std::vector<int> children_gene; unsigned int assessment;};//子供の遺伝子と評価値
	std::vector<children_t> children_;//子供の遺伝子と評価値の配列

    question_raw_data *data_;
    compared_type *comp_;

    // std::mt19937_64ほど高級なもの要る？
    mutable std::mt19937 mt_;

    void shuffle(std::vector<int>& arr) const
    {
        std::uniform_int_distribution<int> distribution(0, arr.size()-1);

        for(int i = 0; i < arr.size(); ++i)
        {
            int j = distribution(mt_);
            std::swap(arr[i], arr[j]);
        }
    }

    void shuffle_all()
    {
        for(auto it = children_.begin(); it != children_.end(); ++it)
        {
            shuffle(it->children_gene);
        }
    }

    unsigned int assess(std::vector<int> const& arr) const
    {
        auto const sepx = data_->split_num.first;
        auto const sepy = data_->split_num.second;

        unsigned int ass = 0;
        for(int i = 0; i < arr.size(); ++i)
        {
            if(i + 1 < arr.size())
            {
                if(arr[i] == arr[i + 1])
                {
                    std::cout << "!!!" << arr[i] << arr[i + 1] << std::endl;
                }
                ass += (*comp_)[arr[i] / sepx][arr[i] % sepx][arr[i + 1] / sepx][arr[i + 1] % sepx].right;
            }
            if(i + sepy < arr.size())
            {
                if(arr[i] == arr[i + sepy])
                {
                    std::cout << "???" << arr[i] << arr[i + sepy] << std::endl;
                }
                ass += (*comp_)[arr[i] / sepx][arr[i] % sepx][arr[i + sepy] / sepx][arr[i + sepy] % sepx].right;
            }
        }
        return ass;
    }

    void assess_all()
    {
        for(auto it = children_.begin(); it != children_.end(); ++it)
        {
            //for(int i = 0; i < split_total; ++i)
            //{
            //    std::cout << it->children_gene[i] << " - ";
            //}
            it->assessment = assess(it->children_gene);
		    //std::cout << "     " << it->assessment << std::endl;
        }
    }

    std::vector<std::vector<int>> select_parent(std::vector<int>& top10)
    {
        top10.assign(PARENT_NUM, 0);

        std::vector<int> childred_copy;
        childred_copy.reserve(children_.size());

        boost::transform(
            children_, std::back_inserter(childred_copy),
            [](children_t const& base){ return base.assessment; }
            );
        boost::sort(childred_copy);
        //boost::for_each(childred_copy, [](int const base){ std::cout << base << std::endl; });

        for(int i=0; i<top10.size(); ++i)
        {
            for(int j=0; j<CHILDREN_NUM; ++j)
            {
                if(childred_copy.at(i) == children_[j].assessment)
                {
                    top10[i] = j;
                }
            }
        }

        auto const split_total = data_->split_num.first * data_->split_num.second;
        std::vector<std::vector<int>> parent_gene(PARENT_NUM, std::vector<int>(split_total, 0));

        //親遺伝子配列にいいやつTop10を突っ込む
        for(int i=0; i<top10.size(); ++i)
        {
            for(int j=0; j<split_total; ++j)
            {
                parent_gene[i][j] = children_[top10[i]].children_gene[j];
            }
        }

        std::cout << "番号  " << "評価" << std::endl;
        for(auto const& elem : top10)
        {
            std::cout << elem << "   " << children_[elem].assessment << std::endl;
        }

        return parent_gene;
    }

    void cross_over(std::vector<std::vector<int>> const& parent_gene)
    {
        auto const split_width  = data_->split_num.first;
        auto const split_height = data_->split_num.second;
        auto const split_total  = split_width * split_height;

        std::uniform_int_distribution<int> parent_dist(0, PARENT_NUM - 1);
        std::uniform_int_distribution<int> mutate_dist(0, 4 - 1);
        std::uniform_int_distribution<int> split_dist(0, split_total - 1);

        for(int i=0; i<CHILDREN_NUM; i+=2)
        {
            auto const& pra1 = parent_gene[parent_dist(mt_)];
            auto const& pra2 = parent_gene[parent_dist(mt_)];
            auto      & child1 = children_[i  ].children_gene;
            auto      & child2 = children_[i+1].children_gene;

            //std::cout << "par1 ";
            //boost::for_each(pra1, [](int const elem){ std::cout << elem << "*"; });
            //std::cout << std::endl;
            //
            //std::cout << "par2 ";
            //boost::for_each(pra2, [](int const elem){ std::cout << elem << "*"; });
            //std::cout << std::endl;

            child1.assign(child1.size(), -1);
            child2.assign(child2.size(), -1);

            int select_gene = split_dist(mt_);
            //std::cout << "  s" << select_gene;
            while(child1[select_gene] != pra1[select_gene])
            {
			    child1[select_gene] = pra1[select_gene];
			    child2[select_gene] = pra2[select_gene];

                for(int i=0; i<split_total; ++i)
                {
                    if(child2[select_gene] == pra1[i])
                    {
                        select_gene = i;
                    }
                }
                //std::cout << "  s" << select_gene;
            }

            for(int i=0; i<split_total; ++i)
            {
                if(child1[i] == -1)
                {
				    child1[i] = pra2[i];
				    child2[i] = pra1[i];
                }
            }

            for(int n = parent_dist(mt_); n < 10; ++n) //このループ数をいじらないと収束しなかったりすぐに収束してしまったり
            {
                if(mutate_dist(mt_) == 0) //ここの確率で突然変異率を変化させる
                {
                    int rand1 = split_dist(mt_);
                    int rand2 = split_dist(mt_);
                    std::swap(child1[rand1], child1[rand2]);
                    //std::cout << "rand1" << std::endl;
                }
                if(mutate_dist(mt_) == 0) //ここの確率で突然変異率を変化させる
                {
                    int rand1 = split_dist(mt_);
                    int rand2 = split_dist(mt_);
                    std::swap(child2[rand1], child2[rand2]);
				    //std::cout << "rand2" << std::endl;
                }
            }

            //std::cout << std::endl;
            //std::cout << "chi1 ";
            //boost::for_each(child1, [](int const elem){ std::cout << elem << "+"; });
            //
            //std::cout << std::endl;
            //std::cout << "chi2 ";
            //boost::for_each(child2, [](int const elem){ std::cout << elem << "+"; });
            //
            //std::cout << std::endl;
        }
    }

public:
    // 泣きのポインタ渡し
    genetic(question_raw_data *data, compared_type *comp)
        : data_(data), comp_(comp)
    {
        //メルセンヌ・ツイスタの初期化
        std::random_device rd;
        std::vector<std::uint_least64_t> random_seed(10);
        boost::generate(random_seed, std::ref(rd));

        std::seed_seq seed(random_seed.cbegin(), random_seed.cend());
        mt_.seed(seed);
    }
    virtual ~genetic() = default;

    int sort()
    {
        auto const split_total = data_->split_num.first * data_->split_num.second;

        // children_の初期化
        {
            //連番リスト(0~split_total-1)の作製
            std::vector<int> tmp_vector;
            tmp_vector.reserve(split_total);
            for(int i = 0; i < split_total; ++i) tmp_vector.push_back(i);

            //連番リストでchildren_を初期化
            children_.assign(CHILDREN_NUM, {tmp_vector, 0});
        }

        shuffle_all();
        assess_all();

        int top;
        std::vector<int> top10(PARENT_NUM);
        std::vector<int> toppers(1000);
        for(int i = 0; i < toppers.size(); ++i)
        {
            for(int j = 0; j < 10000; ++j)
            {
                auto const parent_gene = select_parent(top10);
                top = children_.at(top10[0]).assessment;

                cross_over(parent_gene);
                assess_all();

			    std::cout << "最上位遺伝子";
			    for (int i = 0; i < split_total; i++)
                {
				    std::cout << std::setw(3) << parent_gene[0][i]; //unspecified(std::setw)
			    }

                std::cout << "番号" << top10[0] << std::endl;

                int const base = top10[0]; // VCのための苦肉の策
                if(
                    std::all_of(
                        top10.begin(), top10.end(),
                        [base](int const elem){ return base == elem; }
                        //[base = top10[0]](int const elem){ return base == elem; }
                    )
                )
                {
                    //Top10の遺伝子がすべて同じものになったら収束したと判断する
                    break;
                }
                std::cout << "世代=" << j << "ループ" << i << std::endl;

            }
            toppers[i] = top;

            shuffle_all();
        }

	    int toptop = std::numeric_limits<int>::max();
	    int topnum = 0;
	    for(auto const elem : toppers)
        {
            if(elem < toptop)
            {
                toptop = elem;
                topnum = 0;
            }
            else if(elem == toptop)
            {
                ++topnum;
            }
		    std::cout << elem << std::endl;
        }
	    std::cout << "最適値" << toptop << "数" << topnum << std::endl;
    }

};

#endif
<|endoftext|>