text:
/*
 * Copyright (C) 2021 HERE Europe B.V.
 *
 * 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.
 *
 * SPDX-License-Identifier: Apache-2.0
 * License-Filename: LICENSE
 */

#include "TokenEndpointImpl.h"

#include <olp/authentication/SignInResult.h>
#include <olp/core/http/HttpStatusCode.h>
#include <olp/core/http/NetworkConstants.h>
#include <olp/core/http/NetworkUtils.h>
#include <olp/core/logging/Log.h>
#include <olp/core/thread/Atomic.h>
#include <rapidjson/document.h>
#include <rapidjson/istreamwrapper.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include "AuthenticationClientUtils.h"
#include "Constants.h"
#include "SignInResultImpl.h"

namespace olp {
namespace authentication {

namespace {
using TimeResponse = Response<time_t>;
using SignInResponse = Response<SignInResult>;
using RequestBodyData = client::OlpClient::RequestBodyType::element_type;

constexpr auto kApplicationJson = "application/json";
constexpr auto kOauthEndpoint = "/oauth2/token";
constexpr auto kTimestampEndpoint = "/timestamp";
constexpr auto kGrantType = "grantType";
constexpr auto kClientGrantType = "client_credentials";
constexpr auto kLogTag = "TokenEndpointImpl";
constexpr auto kErrorWrongTimestamp = 401204;

std::string GetBasePath(const std::string& base_string) {
  // Remove /oauth2/token from url to make sure only the base url is used
  auto new_base_string = base_string;
  auto pos = new_base_string.find(kOauthEndpoint);
  if (pos != std::string::npos) {
    new_base_string.erase(pos, std::strlen(kOauthEndpoint));
  }

  OLP_SDK_LOG_INFO_F(
      kLogTag,
      "GetBasePath: old_token_endpoint_url='%s', token_endpoint_url='%s'",
      base_string.c_str(), new_base_string.c_str());

  return new_base_string;
}

AuthenticationSettings ConvertSettings(Settings settings) {
  AuthenticationSettings auth_settings;
  auth_settings.network_proxy_settings =
      std::move(settings.network_proxy_settings);
  auth_settings.network_request_handler =
      std::move(settings.network_request_handler);
  auth_settings.token_endpoint_url = GetBasePath(settings.token_endpoint_url);
  auth_settings.use_system_time = settings.use_system_time;
  auth_settings.retry_settings = std::move(settings.retry_settings);

  // Ignore `settings.task_scheduler`. It can cause a deadlock on the sign in
  // when used from another task within `TaskScheduler` with 1 thread.

  return auth_settings;
}

bool HasWrongTimestamp(const SignInResult& result) {
  const auto& error_response = result.GetErrorResponse();
  const auto status = result.GetStatus();
  return status == http::HttpStatusCode::UNAUTHORIZED &&
         error_response.code == kErrorWrongTimestamp;
}

void RetryDelay(const client::RetrySettings& retry_settings, size_t retry) {
  std::this_thread::sleep_for(retry_settings.backdown_strategy(
      std::chrono::milliseconds(retry_settings.initial_backdown_period),
      retry));
}

TimeResponse ParseTimeResponse(std::stringstream& payload) {
  rapidjson::Document document;
  rapidjson::IStreamWrapper stream(payload);
  document.ParseStream(stream);

  if (!document.IsObject()) {
    return AuthenticationError(client::ErrorCode::InternalFailure,
                               "JSON document root is not an Object type");
  }

  const auto timestamp_it = document.FindMember("timestamp");
  if (timestamp_it == document.MemberEnd() || !timestamp_it->value.IsUint()) {
    return AuthenticationError(
        client::ErrorCode::InternalFailure,
        "JSON document must contain timestamp integer field");
  }

  return timestamp_it->value.GetUint();
}

std::string GenerateUid() {
  static thread::Atomic<boost::uuids::random_generator> generator;
  return generator.locked([](boost::uuids::random_generator& gen) {
    return boost::uuids::to_string(gen());
  });
}

client::OlpClient::RequestBodyType GenerateClientBody(
    const TokenRequest& token_request) {
  rapidjson::StringBuffer data;
  rapidjson::Writer<rapidjson::StringBuffer> writer(data);
  writer.StartObject();

  writer.Key(kGrantType);
  writer.String(kClientGrantType);

  auto expires_in =
      static_cast<unsigned int>(token_request.GetExpiresIn().count());
  if (expires_in > 0) {
    writer.Key(Constants::EXPIRES_IN);
    writer.Uint(expires_in);
  }

  writer.EndObject();
  auto content = data.GetString();
  return std::make_shared<RequestBodyData>(content, content + data.GetSize());
}
}  // namespace

TokenEndpointImpl::TokenEndpointImpl(Settings settings)
    : credentials_(std::move(settings.credentials)),
      settings_(ConvertSettings(std::move(settings))),
      auth_client_(settings_) {}

client::CancellationToken TokenEndpointImpl::RequestToken(
    const TokenRequest& token_request, const RequestTokenCallback& callback) {
  AuthenticationClient::SignInProperties properties;
  properties.expires_in = token_request.GetExpiresIn();
  return auth_client_.SignInClient(
      credentials_, properties,
      [callback](
          const AuthenticationClient::SignInClientResponse& sign_in_response) {
        if (!sign_in_response) {
          callback(sign_in_response.GetError());
          return;
        }

        const auto& sign_in_result = sign_in_response.GetResult();
        if (sign_in_result.GetAccessToken().empty()) {
          callback(client::ApiError{sign_in_result.GetStatus(),
                                    sign_in_result.GetFullMessage()});
          return;
        }

        callback(TokenResult{sign_in_result.GetAccessToken(),
                             sign_in_result.GetExpiresIn(),
                             http::HttpStatusCode::OK, ErrorResponse{}});
      });
}

std::future<TokenResponse> TokenEndpointImpl::RequestToken(
    client::CancellationToken& cancel_token,
    const TokenRequest& token_request) {
  auto promise = std::make_shared<std::promise<TokenResponse>>();
  cancel_token = RequestToken(token_request, [promise](TokenResponse response) {
    promise->set_value(std::move(response));
  });
  return promise->get_future();
}

TokenResponse TokenEndpointImpl::RequestToken(
    client::CancellationContext& context,
    const TokenRequest& token_request) const {
  auto sign_in_response = SignInClient(context, token_request);
  if (!sign_in_response) {
    return sign_in_response.GetError();
  }

  const auto& sign_in_result = sign_in_response.GetResult();
  if (sign_in_result.GetAccessToken().empty()) {
    auto message = sign_in_result.GetFullMessage();

    // Full message can be empty if an error occurred during response parsing.
    // Use message from an error response in this case.
    if (message.empty()) {
      message = sign_in_result.GetErrorResponse().message;
    }

    return client::ApiError{sign_in_result.GetStatus(), std::move(message)};
  }

  return TokenResult{sign_in_result.GetAccessToken(),
                     sign_in_result.GetExpiresIn(), http::HttpStatusCode::OK,
                     ErrorResponse{}};
}

SignInResponse TokenEndpointImpl::SignInClient(
    client::CancellationContext& context,
    const TokenRequest& token_request) const {
  if (!settings_.network_request_handler) {
    return client::ApiError::NetworkConnection("Cannot sign in while offline");
  }

  if (context.IsCancelled()) {
    return client::ApiError::Cancelled();
  }

  auto client = CreateOlpClient(settings_, boost::none, false);

  RequestTimer timer = CreateRequestTimer(client, context);

  const auto request_body = GenerateClientBody(token_request);

  SignInResult response;

  const auto& retry_settings = settings_.retry_settings;

  for (auto retry = 0; retry < retry_settings.max_attempts; ++retry) {
    if (context.IsCancelled()) {
      return client::ApiError::Cancelled();
    }

    auto auth_response = CallAuth(client, kOauthEndpoint, context, request_body,
                                  timer.GetRequestTime());
    const auto status = auth_response.status;
    if (status < 0) {
      // If a timeout occurred, the cancellation id done through the context.
      // So this case needs to be handled independently of context state.
      if (status != static_cast<int>(http::ErrorCode::TIMEOUT_ERROR) &&
          context.IsCancelled()) {
        return client::ApiError::Cancelled();
      }

      // Auth response message may be empty in case of unknown errors.
      // Fill in the message as a status string representation in this case.
      auto message = auth_response.response.str();
      if (message.empty()) {
        message = http::HttpErrorToString(status);
      }

      return client::ApiError(status, message);
    }

    response = ParseAuthResponse(status, auth_response.response);

    // The request ended up with `OK` status should not be retriggered even if
    // `retry_condition` is `true` for this `HttpResponse`.
    if (status == http::HttpStatusCode::OK) {
      break;
    }

    if (retry_settings.retry_condition(auth_response)) {
      RetryDelay(retry_settings, retry);
      continue;
    }

    // In case we can't authorize with system time, retry with the server
    // time from response headers (if available).
    if (HasWrongTimestamp(response)) {
      auto server_time = GetTimestampFromHeaders(auth_response.headers);
      if (server_time) {
        timer = RequestTimer(*server_time);
        continue;
      }
    }

    break;
  }

  return response;
}

SignInResult TokenEndpointImpl::ParseAuthResponse(
    int status, std::stringstream& auth_response) {
  auto document = std::make_shared<rapidjson::Document>();
  rapidjson::IStreamWrapper stream(auth_response);
  document->ParseStream(stream);
  return std::make_shared<SignInResultImpl>(
      status, http::HttpErrorToString(status), document);
}

client::HttpResponse TokenEndpointImpl::CallAuth(
    const client::OlpClient& client, const std::string& endpoint,
    client::CancellationContext& context,
    client::OlpClient::RequestBodyType body, std::time_t timestamp) const {
  const auto url = settings_.token_endpoint_url + endpoint;

  auto auth_header =
      GenerateAuthorizationHeader(credentials_, url, timestamp, GenerateUid());

  client::OlpClient::ParametersType headers = {
      {http::kAuthorizationHeader, std::move(auth_header)}};

  return client.CallApi(endpoint, "POST", {}, std::move(headers), {},
                        std::move(body), kApplicationJson, context);
}

TokenEndpointImpl::RequestTimer TokenEndpointImpl::CreateRequestTimer(
    const client::OlpClient& client,
    client::CancellationContext& context) const {
  if (settings_.use_system_time) {
    return RequestTimer();
  }

  auto server_time = GetTimeFromServer(context, client);
  if (!server_time) {
    return RequestTimer();
  }

  return RequestTimer(server_time.GetResult());
}

TimeResponse TokenEndpointImpl::GetTimeFromServer(
    client::CancellationContext& context,
    const client::OlpClient& client) const {
  auto http_result = client.CallApi(kTimestampEndpoint, "GET", {}, {}, {},
                                    nullptr, {}, context);

  if (http_result.status != http::HttpStatusCode::OK) {
    auto response = http_result.response.str();
    OLP_SDK_LOG_WARNING_F(
        kLogTag, "Failed to get time from server, status=%d, response='%s'",
        http_result.status, response.c_str());
    return AuthenticationError(http_result.status, http_result.response.str());
  }

  auto server_time = ParseTimeResponse(http_result.response);

  if (!server_time) {
    const auto& error = server_time.GetError();
    const auto& message = error.GetMessage();
    OLP_SDK_LOG_WARNING_F(kLogTag,
                          "Failed to decode time from server, message='%s'",
                          message.c_str());
  }

  return server_time;
}

TokenEndpointImpl::RequestTimer::RequestTimer()
    : timer_start_{std::chrono::steady_clock::now()},
      time_{std::chrono::system_clock::to_time_t(
          std::chrono::system_clock::now())} {}

TokenEndpointImpl::RequestTimer::RequestTimer(std::time_t server_time)
    : timer_start_{std::chrono::steady_clock::now()}, time_{server_time} {}

std::time_t TokenEndpointImpl::RequestTimer::GetRequestTime() const {
  const auto now = std::chrono::steady_clock::now();
  const auto time_since_start =
      std::chrono::duration_cast<std::chrono::seconds>(now - timer_start_);
  return time_ + time_since_start.count();
}

}  // namespace authentication
}  // namespace olp

max_stars_repo_name: fermeise/here-data-sdk-cpp

max_issues_repo_name: fermeise/here-data-sdk-cpp

max_forks_repo_name: fermeise/here-data-sdk-cpp


text:
/*
 * 		ELABORAZIONE DI DATI TRIDIMENSIONALI - 2014/2015
 *
 * 		Department of Information Engineering (DEI)
 *
 * 						University of Padova
 *
 *
 * This source was developed for the final course project as well as for the
 * competition organized by Loccioni Group.
 *
 *
 *  Created on: Apr 22, 2015
 *      Authors:
 *      	Alessandro Beltramin
 *      	Matteo Sartori
 *
 */

#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <algorithm>
#include <cstdio>
#include <map>
#include <memory>

#include "Calibration.hpp"
#include "Inspection.hpp"
#include "Parameters.hpp"
#include "Pipeline.hpp"
#include "ResultConnector.hpp"

using namespace pinspect;

namespace po = boost::program_options;

static Pipeline pipeline;

static CalibrationSet dataset;

/**
 * Map of connector objects created on input to pass to various ProcessingStages.
 */
static std::vector<boost::any> inputConnectorList;

/**
 * Bind a name to each ProcessingStage objects.
 * It's used to set up links during pipeline constructions.
 */
static std::map<std::string, ProcessingInterface*> stageMap;

/**
 * Allocate processing stages associated with names.
 */
static void initializeStageMap() {
	stageMap.insert(
	{
		{"findGridLeft", new FindGridPattern("findGridLeft")},
		{"findGridRight",new FindGridPattern("findGridRight")},
		{"leftCamera", new SingleCalibration("leftCamera")},
		{"rightCamera", new SingleCalibration("rightCamera")},
		{"stereoCamera", new StereoCalibration("stereoCamera")},
		{"rectifyMaps", new RectifyCalibration("rectifyMaps")},
		{"rectification", new Rectification("rectification")},
		{"cornerDetection", new CornerDetection("cornerDetection")},
		{"gridFitting", new GridFitting("gridFitting")},
		{"refinement", new Refinement("refinement")},
		{"triangulation", new Triangulation("triangulation")},
		{"registration", new Registration("registration")}
	});
}

/**
 * Free memory.
 */
static void freeStageMap() {
	for(auto x : stageMap)
		delete x.second;
}

/**
 * Retrieve of ProcessingStages. It has to be generics because they are of
 * different type.
 */
template<typename T> static T* getStage(std::string s) {
	return static_cast<T*>(stageMap[s]);
}

/**
 * Allocate a new InputConnector object and @return a pointer to it.
 */
template<typename Type> static InputConnector<Type>* newInputConnector(Type x) {

	InputConnector<Type> newObj;
	newObj.putValue(x);
	inputConnectorList.push_back(boost::any(newObj));

	// this automatically returns a pointer to the underlying object
	return boost::any_cast<InputConnector<Type>>(&inputConnectorList.back());
}

/**
 * This is for reading specific command arguments and to setup input
 * connections. Then the stage is added to the pipeline object.
 */
static void setCalibration(po::variables_map vm) {

	std::string leftFormat = "";
	std::string rightFormat= "";

	if(!vm.count("left-format") || !vm.count("right-format")) {
		std::cout << "\n\nOptions --left-format and --right-format mandatory" << std::endl;
		std::cout << "\nExample: --left-format=datasetLoc/Leftimg#.jpg" << std::endl;
		std::cout << "Where the '#' stand for the ID of the image" << std::endl;
		std::exit(1);
	}

	leftFormat = vm["left-format"].as<std::string>();
	rightFormat = vm["right-format"].as<std::string>();

	dataset = buildCalibrationSetFromRegex(leftFormat, rightFormat);

	FindGridPattern *findLeft = getStage<FindGridPattern>("findGridLeft");
	findLeft->setInput(newInputConnector(dataset.getLeftList()));
	findLeft->setDataset(&dataset);

	FindGridPattern *findRight = getStage<FindGridPattern>("findGridRight");
	findRight->setInput(newInputConnector(dataset.getRightList()));
	findRight->setDataset(&dataset);

	SingleCalibration *calibLeft = getStage<SingleCalibration>("leftCamera");
	calibLeft->setInput(findLeft->getResultConnector());
	calibLeft->setDataset(&dataset);

	SingleCalibration *calibRight = getStage<SingleCalibration>("rightCamera");
	calibRight->setInput(findRight->getResultConnector());
	calibRight->setDataset(&dataset);

	StereoCalibration *stereo = getStage<StereoCalibration>("stereoCamera");
	stereo->setInput(findLeft->getResultConnector(), calibLeft->getResultConnector(),
			findRight->getResultConnector(), calibRight->getResultConnector());

	pipeline.addStage(findLeft).addStage(calibLeft);
	pipeline.addStage(findRight).addStage(calibRight);
	pipeline.addStage(stereo);
}

/**
 * @see setCalibration
 */
static void setRectifyMaps(po::variables_map vm) {

	RectifyCalibration *stage = getStage<RectifyCalibration>("rectifyMaps");
	stage->setInput(getStage<SingleCalibration>("leftCamera")->getResultConnector(),
			getStage<SingleCalibration>("rightCamera")->getResultConnector(),
			getStage<StereoCalibration>("stereoCamera")->getResultConnector());

	pipeline.addStage(stage);
}

/**
 * @see setCalibration
 */
static void setRectification(po::variables_map vm) {

	std::string leftImage = "";
	std::string rightImage= "";

	if (!vm.count("left-image") || !vm.count("right-image")) {
		std::cout << "\n\nOptions --left-image and --right-image mandatory" << std::endl;
		std::exit(1);
	}

	leftImage = vm["left-image"].as<std::string>();
	rightImage = vm["right-image"].as<std::string>();

	Rectification *stage = getStage<Rectification>("rectification");

	stage->setInput(newInputConnector(buildImagePair(leftImage, rightImage)),
			getStage<SingleCalibration>("leftCamera")->getResultConnector(),
			getStage<SingleCalibration>("rightCamera")->getResultConnector(),
			getStage<RectifyCalibration>("rectifyMaps")->getResultConnector());

	pipeline.addStage(stage);
}

/**
 * @see setCalibration
 */
static void setCornerDetection(po::variables_map vm) {

	CornerDetection *stage = getStage<CornerDetection>("cornerDetection");
	stage->setInput(getStage<Rectification>("rectification")->getResultConnector());
	pipeline.addStage(stage);
}

/**
 * @see setCalibration
 */
static void setGridFitting(po::variables_map vm) {

	GridFitting *stage = getStage<GridFitting>("gridFitting");
	stage->setInput(getStage<CornerDetection>("cornerDetection")->getResultConnector(),
			getStage<Rectification>("rectification")->getResultConnector());
	pipeline.addStage(stage);
}

/**
 * @see setCalibration
 */
static void setRefinement(po::variables_map vm) {

	Refinement *stage = getStage<Refinement>("refinement");
	stage->setInput(getStage<GridFitting>("gridFitting")->getResultConnector(),
			getStage<Rectification>("rectification")->getResultConnector());
	pipeline.addStage(stage);
}

/**
 * @see setCalibration
 */
static void setTriangulation(po::variables_map vm) {

	Triangulation *stage = getStage<Triangulation>("triangulation");
	stage->setInput(getStage<Refinement>("refinement")->getResultConnector(),
			getStage<RectifyCalibration>("rectifyMaps")->getResultConnector());
	pipeline.addStage(stage);
}

/**
 * @see setCalibration
 */
static void setRegistration(po::variables_map vm) {

	Registration *stage = getStage<Registration>("registration");
	stage->setInput(getStage<Triangulation>("triangulation")->getResultConnector());
	pipeline.addStage(stage);
}

typedef void (*commandHandler)(po::variables_map vm);

typedef std::pair<std::string, commandHandler> CommandPair;

typedef std::vector<CommandPair> CommandList;

/**
 * Represent commands with a description of which operation to perform.
 */
static std::vector<std::pair<std::string,std::string>> commandDescription = {
		{"calib", "perform calibration"},
		{"rectmap", "compute rectification maps"},
		{"rectify", "rectify input images"},
		{"cornerdet", "corner detection"},
		{"gridfit", "fitting the grid model"},
		{"refine", "pin position refinement"},
		{"triang", "triangulate and project in 3D"},
		{"regist", "model registration, compute errors"}
};

/**
 * Associate to each command name the static function to call to
 * create the ProcessingStage object specific for that command.
 */
static CommandList commandList = {
		{"calib", setCalibration},
		{"rectmap", setRectifyMaps},
		{"rectify", setRectification},
		{"cornerdet", setCornerDetection},
		{"gridfit", setGridFitting},
		{"refine", setRefinement},
		{"triang", setTriangulation},
		{"regist", setRegistration}
};

static void printCommands() {
	for(auto e : commandDescription)
		std::printf("   %s\t%s\n", e.first.c_str(), e.second.c_str());
}

/**
 * Decide how to build the pipeline while parsing command line arguments.
 * @param from decide where to start executing stage
 * @param to what stage to stop at.
 *
 * Every stage between from and to are added in the order decided statically by
 * @see commandList object.
 */
static void parseCommands(std::string from, std::string to, po::variables_map vm) {

	auto fromLambda = [from](CommandPair p){ return p.first == from; };
	auto toLambda   = [to](CommandPair p){ return p.first == to; };

	auto fromIt = std::find_if(commandList.begin(), commandList.end(), fromLambda);
	auto toIt = std::find_if(commandList.begin(), commandList.end(), toLambda);

	if(from == "start")
		fromIt = commandList.begin();
	if(to == "end")
		toIt = commandList.end() - 1;

	//boundary check
	if(fromIt == commandList.end())
		throw std::runtime_error("Invalid command '" + from + "'");

	if(fromIt > toIt)
		throw std::runtime_error("Invalid commands '" + from + "' '" + to + "'");

	if(toIt == commandList.end() && to.front() != '-')
		throw std::runtime_error("Invalid command '" + to + "'");
	else if(toIt == commandList.end())
		//we assume the user wants only one stage
		toIt = fromIt;

	std::cout << "Commands to execute: ";
	std::for_each(fromIt, toIt+1, [vm](CommandPair p) {
		std::cout << "'" << p.first << "' ";
		p.second(vm);
	});

	std::cout << std::endl;
}

std::string optionDescription = "\nUsage: pinspect [OPTIONS] FROM-CMD [TO-CMD]\n\nPrimary options";

int main(int argc, char *argv[]) {

	std::string paramsFilename = "parameters.xml";
	std::string resultsDirname = "results";
	std::string fromCommand = "";
	std::string toCommand = "";

	//boost object for describe program options.
	po::options_description desc(optionDescription);
	desc.add_options()
	    ("help,h", "produce help message")
			("print-params,p", "print set parameters")
	    ("parameters", po::value<std::string>(&paramsFilename), "set parameters file")
			("results", po::value<std::string>(&resultsDirname), "set results directory")
			("left-format", po::value<std::string>(),"left images form of the dataset")
			("right-format", po::value<std::string>(),"right images form of the dataset")
			("left-image,l", po::value<std::string>(), "left image to inspect")
			("right-image,r", po::value<std::string>(), "right image to inspect")
			("commands", po::value<std::vector<std::string>>(), "from command to command");

	po::positional_options_description p;
	p.add("commands", 2);

	//this actually parses argv
	po::variables_map vm;
	po::store(po::command_line_parser(argc, argv).positional(p).options(desc).run(),vm);
	po::notify(vm);

	if(vm.count("help")) {
		std::cout << desc << std::endl;
		std::cout << "Commands available:" << std::endl;
		printCommands();
		std::exit(1);
	}

	if(!vm.count("commands")) {
		std::cout << "Need to specify commands to execute" << std::endl;
		std::exit(1);
	}

	std::vector<std::string> commands = vm["commands"].as<std::vector<std::string>>();
	fromCommand = commands[0];
	toCommand   = commands[1];
	if(toCommand == "")
		toCommand = fromCommand;

	//initialize static members of ProcessignInterface
	//which are configurations common to all stages
	Parameters parameters = populateDefaultParameters(paramsFilename);
	if(vm.count("print-params"))
		parameters.print();
	ProcessingInterface::setParameters(parameters);
	ProcessingInterface::setOutputDirectory(resultsDirname + "/");
	//create if not existing
	boost::filesystem::create_directory(resultsDirname);

	initializeStageMap();

	try {
		parseCommands(fromCommand, toCommand, vm);
	}
	catch(std::runtime_error& e) {
		std::cout << e.what() << std::endl;
		std::cout << "Commands available:" << std::endl;
		printCommands();
		std::exit(1);
	}

	//this checks for missing inputs
	pipeline.checkStagesInput();

	auto start = std::chrono::steady_clock::now();
	pipeline.execute();

	auto end = std::chrono::steady_clock::now();
	auto diff = end - start;
	std::cout << "Total execution time: ";
	std::cout << std::chrono::duration<double, std::milli>(diff).count() << " ms"
			<< std::endl;

	freeStageMap();
	return 0;
}

ext: cpp

max_stars_repo_name: tteoz/pinspect

max_issues_repo_name: tteoz/pinspect

max_forks_repo_name: tteoz/pinspect


text:
#pragma once

#include "generator/feature_builder.hpp"
#include "generator/place_node.hpp"

#include "geometry/point2d.hpp"
#include "geometry/tree4d.hpp"

#include "base/geo_object_id.hpp"

#include <cstddef>
#include <string>
#include <unordered_map>
#include <vector>

#include <boost/geometry.hpp>
#include <boost/optional.hpp>

namespace generator_tests
{
class TestPopularityBuilder;
}  // namespace generator_tests

namespace generator
{
namespace popularity
{
// These are functions for generating a csv file for popularity.
// dataFilename - A path to data file
// dataDir - A path to the directory where the data files are located
// dataFilenames - Paths to data files
// cpuCount - A number of processes
// outFilename - A path where the csv file will be saved

// Csv format:
// Id;Parent id;Lat;Lon;Main type;Name
// 9223372036936022489;;42.996411;41.004747;leisure-park;Сквер им. И. А. Когония
// 9223372037297546235;;43.325002;40.224941;leisure-park;Приморский парк
// 9223372036933918763;;43.005177;41.022295;leisure-park;Сухумский ботанический сад
void BuildPopularitySrcFromData(std::string const & dataFilename, std::string const & outFilename);

void BuildPopularitySrcFromAllData(std::string const & dataDir, std::string const & outFilename,
                                   size_t cpuCount = 1);

void BuildPopularitySrcFromAllData(std::vector<std::string> const & dataFilenames, std::string const & outFilename,
                                   size_t cpuCount = 1);

class PopularityGeomPlace
{
public:
  explicit PopularityGeomPlace(feature::FeatureBuilder const & feature);

  bool Contains(PopularityGeomPlace const & smaller) const;
  bool Contains(m2::PointD const & point) const;
  feature::FeatureBuilder const & GetFeature() const { return m_feature; }
  double GetArea() const { return m_area; }
  base::GeoObjectId GetId() const { return m_id; }

private:
  using BoostPoint = boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>;
  using BoostPolygon = boost::geometry::model::polygon<BoostPoint>;

  base::GeoObjectId m_id;
  std::reference_wrapper<feature::FeatureBuilder const> m_feature;
  std::unique_ptr<BoostPolygon> m_polygon;
  double m_area;
};

struct PopularityLine
{
  base::GeoObjectId m_id;
  boost::optional<base::GeoObjectId> m_parent;
  m2::PointD m_center;
  std::string m_type;
  std::string m_name;
};

class PopularityBuilder
{
public:
  friend class generator_tests::TestPopularityBuilder;

  explicit PopularityBuilder(std::string const & dataFilename);

  std::vector<PopularityLine> Build() const;

private:
  using Node = PlaceNode<PopularityGeomPlace>;
  using Tree4d = m4::Tree<base::GeoObjectId>;
  using MapIdToNode = std::unordered_map<base::GeoObjectId, Node::Ptr>;

  static std::string GetType(feature::FeatureBuilder const & feature);
  static std::string GetFeatureName(feature::FeatureBuilder const & feature);
  static void FillLinesFromPointObjects(std::vector<feature::FeatureBuilder> const & pointObjs, MapIdToNode const & m,
                                        Tree4d const & tree, std::vector<PopularityLine> & lines);
  static boost::optional<base::GeoObjectId>
  FindPointParent(m2::PointD const & point, MapIdToNode const & m, Tree4d const & tree);
  static boost::optional<Node::Ptr>
  FindPopularityGeomPlaceParent(PopularityGeomPlace const & place, MapIdToNode const & m,
                                Tree4d const & tree);
  static MapIdToNode GetAreaMap(Node::PtrList const & nodes);
  static Tree4d MakeTree4d(Node::PtrList const & nodes);
  static void FillLineFromGeomObjectPtr(PopularityLine & line, Node::Ptr const & node);
  static void FillLinesFromGeomObjectPtrs(Node::PtrList const & nodes,
                                          std::vector<PopularityLine> & lines);
  static void LinkGeomPlaces(MapIdToNode const & m, Tree4d const & tree, Node::PtrList & nodes);
  static Node::PtrList MakeNodes(std::vector<feature::FeatureBuilder> const & features);

  std::string m_dataFilename;
};
}  // namespace popularity
}  // namespace generator

ext: hpp

max_stars_repo_name: vmihaylenko/omim

max_issues_repo_name: vmihaylenko/omim

max_forks_repo_name: vmihaylenko/omim


text:
/* this produces a git-calendar, like github or gitlab show for user activity.
 * See git-cal --help.
 *
 * Example scripts for .dotfiles:
 *
 * git-cal.bin --git-dir ~/.dotfiles/.git --work-tree=${HOME} "$@"
 * git-cal.bin --git-dir /home/.janek-git/.git --work-tree=/home/janek "$@"
 * git-cal.bin "$@"
 *
 */

#include "OptionsCal.hpp"
#include <boost/date_time/posix_time/posix_time.hpp>
#include "boost/date_time/c_local_time_adjustor.hpp"
#include <algorithm>
#include <sstream>
#include <codecvt>
#include <boost/optional.hpp>
#include <sys/ioctl.h>

// FIXME - duplicate with small changes from file moj-git-status.cpp. Should fix later.
std::string exec(const std::string& cmd) {
    std::array<char, 128> buffer;
    std::string result;
    auto pipe = popen(cmd.c_str(), "r"); // get rid of shared_ptr
    if (!pipe) { std::cerr << __PRETTY_FUNCTION__ << "pipe error" << "\n";exit(1); };
    while (!feof(pipe)) {
        if (fgets(buffer.data(), 128, pipe) != nullptr)
            result += buffer.data();
    }
    auto rc = pclose(pipe);
    if (rc == EXIT_SUCCESS) { // == 0
	return result;
    } else {
	std::cerr << __PRETTY_FUNCTION__ << "error: " << rc << "\n";
	exit(1);
    }
}

struct CommitInfo {
	boost::posix_time::ptime time;
	std::wstring author;
};

struct AuthorStreak {
	int count{0};
	// streaks are expressed in units of days_back
	std::set<int> streaks{};
};

typedef std::map<std::wstring,AuthorStreak> AuthorsCount;

struct DayInfo {
	int count;
	AuthorsCount authors;
};

std::pair<boost::optional<boost::posix_time::time_period> ,boost::optional<boost::posix_time::time_period> > calcStreak(const std::set<int>& streaks) {
	if(streaks.empty()) return {boost::none,boost::none};

// FIXME - duplicate from int main(), should fix this later
	auto        now_local_date = boost::posix_time::second_clock::local_time().date();
	// I need ptime, with truncated hours.
	boost::posix_time::ptime now_date_LOC{now_local_date};
// FIXME - end

	int cur_start{-1},cur_end{-1},lon_start{-1},lon_end{-1};//,tmp_start{-1},tmp_end{-1};

// This loop can be done better.
	std::vector<int> cal( *streaks.rbegin()+1 , 0);
	for(const auto& i : streaks) { cal[i] = 1; }
	for(size_t i=1 ; i<cal.size() ; ++i) { if((cal[i] != 0) and (cal[i-1] != 0)) cal[i] = cal[i-1]+1; }
	if(cal[0] != 0) {
		cur_end = 0;
		for(size_t i=1 ; i<cal.size() ; ++i) {
			if(cal[i] == 0) {
				cur_start = i-1;
				break;
			}
		}
	}
	int max = *std::max_element( cal.begin() , cal.end() );
	if(max >= 1) {
		for(size_t i=1 ; i<cal.size() ; ++i) {
			if(cal[i] == max) {
				lon_start = i;
				lon_end   = i-max+1;
			}
		}
	}

/* some other method but it has some error inside, for example yade Bruno commmits from year 2014.
	for(const auto& i : streaks_sorted) {
		if(tmp_start == -1) {
			tmp_end   = i;
			tmp_start = i;
		} else {
			if( std::abs(i - tmp_start) == 1) {
				tmp_start = i;
			} else {
				if(tmp_end   == 0) {
					cur_start = tmp_start;
					cur_end   = tmp_end;
				}
				if( std::abs(tmp_start - tmp_end) >= std::abs(lon_start - lon_end) ) {
					lon_start = tmp_start;
					lon_end   = tmp_end;
				}
				tmp_start = i;
				tmp_end   = i;
			}
		}
	}
	// oops start↔end got swapped, because numbers inside std::set<int> go back
	//std::swap(lon_end,lon_start);
	//std::swap(cur_end,cur_start);
*/

	boost::posix_time::ptime then1 = now_date_LOC - boost::posix_time::time_duration(boost::posix_time::hours(24*(lon_start  )));
	boost::posix_time::ptime then2 = now_date_LOC - boost::posix_time::time_duration(boost::posix_time::hours(24*(lon_end  -1)));
	boost::posix_time::ptime then3 = now_date_LOC - boost::posix_time::time_duration(boost::posix_time::hours(24*(cur_start  )));
	boost::posix_time::ptime then4 = now_date_LOC - boost::posix_time::time_duration(boost::posix_time::hours(24*(cur_end  -1)));
	boost::optional<boost::posix_time::time_period> ret1=boost::none; ret1=boost::optional<boost::posix_time::time_period>({then1 , then2});
	boost::optional<boost::posix_time::time_period> ret2=boost::none;
	if(cur_end   != -1) {
		ret2 = boost::optional<boost::posix_time::time_period>({ then3 , then4 });
	}
	return { ret1 , ret2 };
}

void printStreaks(const std::set<int>& streaks) {
	std::pair<boost::optional<boost::posix_time::time_period> ,boost::optional<boost::posix_time::time_period> > stt = calcStreak(streaks);
	if(stt.first) {
		std::cout << " Longest streak "<< std::ceil(double(stt.first.get().length().hours())/24.0)
		<< " days (" << stt.first.get().begin().date() << " " << stt.first.get().last().date() << ").";
		if(stt.second) {
			std::cout << " Current streak: " << std::ceil(double(stt.second.get().length().hours())/24.0) <<" days";
		}
	}
	std::cout << "\n";
}

void printAuthorSummary(const AuthorsCount& authors_count, size_t longest_author, const OptionsCal& opt) {
	std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; // FIXME - duplicate from int main(), because I am lazy
	std::vector<std::pair<std::wstring,AuthorStreak> > authors_count_sorted{};
	for(const auto& aa : authors_count) {
		authors_count_sorted.push_back({aa.first,aa.second});
	}
	std::sort(authors_count_sorted.begin(), authors_count_sorted.end() ,
		[](const std::pair<std::wstring,AuthorStreak>& a, const std::pair<std::wstring,AuthorStreak>& b)->bool { return a.second.count > b.second.count; });
	int printed=0;
	for(const auto& aa : authors_count_sorted) {
		std::string spaces{};
		int len=longest_author+1 - aa.first.size();
		while(--len>0) spaces+=" ";
		if(longest_author>3) {
			std::cout << spaces << converter.to_bytes(aa.first) << " : " << std::setw(4) << aa.second.count << " ";
		} else {
			std::cout << std::setw(4) << aa.second.count << " ";
		}
		std::cout << "total commits.";
		printStreaks(aa.second.streaks);
		if(++printed >= opt.print_authors) break;
	}
}

struct Dot {
	int q1{0},q2{0},q3{0};
	const std::string esc{char{27}}; // I would just use std::cout << "\e", but it is generating compiler warnings, so lets define the string with ESC inside.
	const std::vector<int> colors={ 237, 139, 40, 190, 1 };
	Dot(const std::vector<DayInfo>& cc) {
		std::vector<int> vv{};
		for(const auto& a:cc) { if(a.count != 0) vv.push_back(a.count); }
		std::sort(vv.begin(),vv.end());
		size_t s = vv.size();
//	std::cout << s << " ← size\n";
		if(s!=0) {
			q1=vv[s/4];
			q2=vv[s/2];
			q3=vv[3*s/4];
		} else {
			std::cerr << "Error: there are zero commits.\n";
			exit(1);
		}
//		std::cerr << vv[0] << " quartiles: " << q1 << " " << q2 << " " << q3 << "\n";
	};
	void print(int val , const boost::posix_time::ptime& then, const OptionsCal& opt) {
		int index=   val == 0  ? 0
			   : val <= q1 ? 1
			   : val <= q2 ? 2
			   : val <= q3 ? 3
				       : 4;
		if(opt.number_days) {
			int d = then.date().day();
			std::string s="";
			if(d<10) s=" ";
			std::cout << colStart(index)<< s << d <<colEnd();
		} else if(opt.number_commits) {
			int d = val;
			std::string s="";
			if(d<10) s=" ";
			std::cout << colStart(index)<< s << d <<colEnd();
		} else {
			put(index);
		}
	};
	void put(int index) {
		std::cout << colStart(index)<<"◼ "<<colEnd();
	};
	std::string colStart(int index) {
		return esc+"[38;5;"+(boost::lexical_cast<std::string>(colors[index]))+"m";
	}
	std::string colEnd() {
		return esc+"[0m";
	}
};

void calcCurrentWeek(int& current_week,const boost::posix_time::ptime& now_date_LOC, const OptionsCal& opt) {
	boost::posix_time::ptime year_start(boost::gregorian::date(now_date_LOC.date().year() , 1 , 1 ));
	current_week = 0;// weeks start with 0
	while(year_start < now_date_LOC) {
		year_start += boost::posix_time::time_duration(boost::posix_time::hours(24));
		if(     opt.start_with_sunday  and year_start.date().day_of_week() == 0) { ++current_week; };
		if((not opt.start_with_sunday) and year_start.date().day_of_week() == 1) { ++current_week; };
	}
}

void decrement(int& years_back, int& current_week, int& day_of_week, const OptionsCal& opt, int WEEKS, const boost::posix_time::ptime& now_date_LOC, int days_back) {
	if(opt.use_calendar_years) {
		boost::posix_time::ptime then = now_date_LOC - boost::posix_time::time_duration(boost::posix_time::hours(24 * days_back));
		//calcCurrentWeek(current_week , then , opt);
		day_of_week = then.date().day_of_week();
		if(not opt.start_with_sunday) { day_of_week = (day_of_week+6)%7;}
		int new_years_back  = now_date_LOC.date().year() - then.date().year();
		if(new_years_back != years_back) {
			calcCurrentWeek(current_week , then , opt);
			years_back = new_years_back;
		} else {
			if(day_of_week == 6) { --current_week; }
		}
	} else {
		--day_of_week;
		if(day_of_week==-1) {
			day_of_week = 6;
			current_week--;
			if(current_week==-1) {
				years_back++;
				current_week=WEEKS-1;
			}
		}
	}
}

int main(int argc, char** argv)
{
// FIXME - this int main() should be split into several functions inside a class, so that some variables are not duplicated: now_local_date, now_date_LOC, converter

// Parse command line options
	struct winsize ww; ioctl(0, TIOCGWINSZ, &ww);
	OptionsCal opt(argc,argv,ww.ws_col,15);
	if(opt.number_commits and opt.number_days) {
		std::cerr << "Bad invocation: `--number-days,-n`  and  `--number-commits,-c`  are mutually exclusive.\n";
		exit(1);
	}
	if(opt.include_emails and (opt.print_authors == 0)) {
		std::cerr << "Bad invocation: `--include-emails,-e` cannot work when `--print-authors,-N` == 0.\n";
		exit(1);
	}
// This line will print the options after parsing.
//	opt.print();
// Prepare for git invocation
	std::string gdir  = ""; if(opt.git_dir   != "") gdir  = " --git-dir "  +opt.git_dir;
	std::string wtree = ""; if(opt.work_tree != "") wtree = " --work-tree "+opt.work_tree;
	std::string author= ""; if(opt.author    != "") author= " --author='"   +opt.author+"'";
	std::string call  = "/usr/bin/git "+gdir+wtree;

// Calculate how many years passed since year 1975, also record present time `now` in UTC as well as in local clock. Will be used later too.
	boost::posix_time::ptime date1970(boost::gregorian::date(1970,1,1));
	auto        now            = boost::posix_time::second_clock::universal_time();
	auto        now_local      = boost::posix_time::second_clock::local_time();
	auto        now_local_date = now_local.date();
	boost::posix_time::ptime now_date_UTC{now.date()};
	boost::posix_time::ptime now_date_LOC{now_local_date};
	int         years_max      = (now - date1970).hours()/24/365.25 - 5; // FIXME : better use now.date().year() - 1975; why did I write it this way earlier??
	// if only_last_year then reset years_max to 1.
	if(opt.only_last_year) { years_max=1; }
// https://git-scm.com/docs/pretty-formats
// XXX: Thinking about adding the ability to count the number of lines in each commit, then for example filtering git-cal to show only commits within some range of committed lines.
//      so far I found the --numstat option
//      git log --no-merges --pretty=format:"%at %aE, %aN" --since="13 months" --numstat
//      also I found this to count number of lines, but it has mistakes:
//        git ls-files -z | xargs -0n1 git blame -w | ruby -n -e '$_ =~ /^.*\((.*?)\s[\d]{4}/; puts $1.strip' | sort -f | uniq -c | sort -n
// Prepare --pretty=format for git invocation
	std::string fmt="";
	if(opt.print_authors != 0) {
		fmt = " %aN";
		if(opt.include_emails) {
			fmt = " %aE, %aN";
		}
	}
// invoke git
	std::string git_cal_result = exec(call+" log --no-merges --pretty=format:\"%at"+fmt+"\" --since=\""+(boost::lexical_cast<std::string>(years_max))+" years\""+author);

// Parse git output and store it into commits
	size_t longest_author{0};
	size_t newlines = std::count(git_cal_result.begin(), git_cal_result.end(), '\n');
	std::vector<CommitInfo> commits;
	commits.reserve(newlines+10);
	std::string tmp;
	std::stringstream ss(git_cal_result);
	std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
	while(std::getline(ss,tmp,'\n')) {
		std::stringstream tt(tmp);
		time_t time{0};
		tt >> time;
		std::string aut{};
		std::getline(tt,aut,'\n');
		longest_author = std::max( aut.size() , longest_author );
		commits.push_back( { boost::posix_time::from_time_t( boost::lexical_cast<time_t>( time ) ) , converter.from_bytes(aut) } );
	}
// Make sure it is sorted. Git produces reverse sorted output, so this isn't maybe strictly necessary, it's just to make sure.
	std::sort(commits.rbegin() , commits.rend() , [](const CommitInfo& a, const CommitInfo& b)->bool { return a.time < b.time; } );
	auto start = commits.rbegin()->time;
// Round up the number of days to display on screen, so that it starts at a full year
	int WEEKS = 52 + 2*int(opt.use_calendar_years); // when use_calendar_years max is 54 weeks
	int days  = (now-start).hours()/24+1;
	int years = std::ceil(double(days)/(WEEKS*7));//(365.25));
	if(opt.use_calendar_years) {
		years = now_local_date.year() - start.date().year() + 1;
//		std::cerr << "years: " << years << "\n";
	}
	int day_of_week  = now_local_date.day_of_week();
	std::string weeknames=" M W F ";
	if(not opt.start_with_sunday) {
		day_of_week = (day_of_week+6)%7;
		weeknames="M W F S";
	}
	// the final calculation. Without this line the calendar printed on screen whould abruptly end upon the first commit, instead at the year's start.
	days=years*WEEKS*7 - (6-day_of_week);
	if(opt.use_calendar_years) {
		days = (now_date_LOC - boost::posix_time::ptime(boost::gregorian::date(start.date().year(),1,1))).hours()/24 + 1;
	}
// Calculate how many commits were done per day, also track each author separetely
	std::vector<DayInfo> count_per_day(days , {0,{}} );
	for(auto& that_commit_UTC : commits) {
//std::cerr << that_commit_UTC.time << " " << ( that_commit_UTC.time - diff_UTC_local ) << "\n";
//		int idx = ( now_date_UTC - boost::posix_time::ptime( that_commit_UTC.time                   .date()) ).hours()/24;
		// I need difference between dates with truncated hours, so that one second after midnight becomes full 24 hours.
		int idx = ( now_date_LOC - boost::posix_time::ptime((boost::date_time::c_local_adjustor<boost::posix_time::ptime>::utc_to_local(that_commit_UTC.time)).date()) ).hours()/24;
		if((idx >=0) and (idx < int(count_per_day.size()))) {
			count_per_day[ idx ].count += 1;
			count_per_day[ idx ].authors[that_commit_UTC.author].count += 1;
		}
	}

// The Dot class will print colored ◼ or commit counts or day of the month
	Dot dot(count_per_day);
/*
	std::cout << "today is: " << now_local_date.day_of_week()  << "\n";
	std::cout << "today is: " << now_local_date.month()  << "\n";
	std::cout << "today is: " << now_local_date.year()  << "\n";
*/
// Now fill the calendar matrix. Assume each year made of 52 weeks. The stored value is days_back since today. Also it refers to position in count_per_day[days_back]
	// ↓ year      ↓ week       ↓ day   days_back
	std::vector<std::vector<std::vector<int>>> calendar(years,std::vector<std::vector<int>>(WEEKS,std::vector<int>(7,-1))); // 3D matrix is constructed at the exactly needed size, filled with -1
	int current_week = WEEKS-1;
	if(opt.use_calendar_years) { calcCurrentWeek(current_week,now_date_LOC,opt); }
	int years_back   = 0;
	for(size_t i = 0 ; i<count_per_day.size() ; ++i) {
//std::cerr << "week: " << current_week << " years_back: " << years_back << "\n";
		assert(years_back   >=0 and years_back   < years);
		assert(current_week >=0 and current_week < WEEKS);
		assert(day_of_week  >=0 and day_of_week  < 7    );
		calendar[years_back][current_week][day_of_week] = i;
		decrement(years_back, current_week, day_of_week, opt, WEEKS, now_date_LOC , i+1);
	}

// Now print the calendar matrix on screen, calculate author contributions along the way for each year and sort them in authors_count
	ss.str("");
	std::set<int> total_streaks{};
	AuthorsCount total_authors_count{};
	for(int y = years-1 ; y>=0 ; --y) {
		bool just_printed=false;
		bool got_year=false;
		int prev_month=-1;
		AuthorsCount authors_count;
		std::string months_str("      ");// will write the Month names after these spaces
		std::string year_str(months_str);
		// This loop is only to construct the YEAR and MONTH lines
		for(int w=0 ; w<WEEKS ; ++w) {
			int days_back = calendar[y][w][0];
			if(days_back != -1) {
				boost::posix_time::ptime then = now_date_LOC - boost::posix_time::time_duration(boost::posix_time::hours(24*days_back));
				int new_month = then.date().month();
				if( (not got_year) and year_str.size() >= 56 ) {
					year_str.resize(56);
					// puts a year number above the month which is in the middle
					year_str += boost::lexical_cast<std::string>(then.date().year());
					got_year=true;
				}
				if((new_month != prev_month) and (not just_printed)) {
					ss << then.date().month();
					months_str += ss.str(); ss.str("");
					if(not got_year) year_str   += "   ";
					just_printed=true;
					prev_month=new_month;
				} else {
					if(just_printed) {
						months_str += " ";
						if(not got_year) year_str   += " ";
						just_printed=false;
					} else {
						months_str += "  ";
						if(not got_year) year_str   += "  ";
					}
				}
			} else {
				months_str += "  ";
				if(not got_year) year_str   += "  ";
			}
		}
		if(not got_year) {
			year_str.resize(56,' ');
			year_str += boost::lexical_cast<std::string>(now_date_LOC.date().year());
		}
		std::cout << year_str << "\n" << months_str << "\n";
		// This loop prints the actual colored ◼, and calculates commits
		for(int d=0 ; d<7 ; ++d) {
			std::cout << "    "<<weeknames[d]<<" ";
			for(int w=0 ; w<WEEKS ; ++w) {
				int days_back = calendar[y][w][d];
				if(days_back != -1) {
					assert(days_back >=0 and days_back<days);
					int val = count_per_day[days_back].count;
					for(const auto& aa : count_per_day[days_back].authors) {
						authors_count[aa.first].count += aa.second.count;
						authors_count[aa.first].streaks.insert(days_back);
						total_authors_count[aa.first].count += aa.second.count;
						total_authors_count[aa.first].streaks.insert(days_back);
						total_streaks.insert(days_back);
					}
					boost::posix_time::ptime then = now_date_LOC - boost::posix_time::time_duration(boost::posix_time::hours(24*days_back));
					dot.print(val,then,opt);
				} else {
					std::cout << "  ";
				}
			}
			std::cout << "\n";
		}
		// When whole year is printed, then print the summary for this year
		if(opt.print_authors != 0 or opt.print_streaks) {
			printAuthorSummary(authors_count , longest_author, opt);
		}
	}
	std::cout << "\n                                                                                Less ";
	dot.put(0);dot.put(1);dot.put(2);dot.put(3);dot.put(4);
	std::cout << " More\n";
	std::cout << std::setw(4) << commits.size() << " total commits since "<< start.date() <<".";
	printStreaks(total_streaks);
	std::cout << "\n";

	if(opt.print_authors != 0) {
		printAuthorSummary(total_authors_count , longest_author, opt);
	}
}

max_stars_repo_name: julee/zsh-git-cal-status-cpp

max_issues_repo_name: julee/zsh-git-cal-status-cpp

max_forks_repo_name: julee/zsh-git-cal-status-cpp


text:
#include <string>
#include <iostream>

#include <boost/filesystem.hpp>
#include <DesertIfaceBack.h>

#include "ConfigKeeper.hpp"
#include "DesertBackSystem.hpp"

void usage( const std::string &programName );

int main( int argc, TCHAR *argv[] ) {

	try {

		if (  ConfigKeeper::getSingleton().getCount( "help" )  ) {
			usage( argv[0] );
			return 0;
		}

		if ( !ConfigKeeper::getSingleton().processCommandLineArguments( argc, argv ) ) {
			usage( argv[ 0 ] );
			return 1;
		}

		// Get the input file name
		if (  !ConfigKeeper::getSingleton().getCount( "compareFrom" )  ) {
			usage( argv[0] );
			return 1;
		}
		std::string compareFromFilename = ConfigKeeper::getSingleton().getStringValue( "compareFrom" );
		if (  !boost::filesystem::exists( compareFromFilename )  ) {
			std::cerr << "ERROR: Could not access file \"" << compareFromFilename << "\"." << std::endl << std::endl;
			return 2;
		}

		if (  !ConfigKeeper::getSingleton().getCount( "compareTo" )  ) {
			usage( argv[0] );
			return 1;
		}
		std::string compareToFilename = ConfigKeeper::getSingleton().getStringValue( "compareTo" );
		if (  !boost::filesystem::exists( compareToFilename )  ) {
			std::cerr << "ERROR: Could not access file \"" << compareToFilename << "\"." << std::endl << std::endl;
			return 2;
		}

		Udm::SmartDataNetwork compareFromSmartDataNetwork( DesertIfaceBack::diagram );
		compareFromSmartDataNetwork.OpenExisting( compareFromFilename, "DesertIfaceBack.xsd", Udm::CHANGES_LOST_DEFAULT );
		DesertIfaceBack::DesertBackSystem compareFromDesertBackSystem = DesertIfaceBack::DesertBackSystem::Cast( compareFromSmartDataNetwork.GetRootObject() );

		Udm::SmartDataNetwork compareToSmartDataNetwork( DesertIfaceBack::diagram );
		compareToSmartDataNetwork.OpenExisting( compareToFilename, "DesertIfaceBack.xsd", Udm::CHANGES_LOST_DEFAULT );
		DesertIfaceBack::DesertBackSystem compareToDesertBackSystem = DesertIfaceBack::DesertBackSystem::Cast( compareToSmartDataNetwork.GetRootObject() );

		return DesertBackSystem::compare( compareFromDesertBackSystem, compareToDesertBackSystem ) ? 0 : 1;

	} catch ( udm_exception &err ) {

		std::cerr << "The following UDM exception occurred:" << std::endl;
		std::cerr << err.what() << std::endl << std::endl;

	} catch ( std::exception &err ) {

		std::cerr << "The following std::exception occurred:" << std::endl;
		std::cerr << err.what() << std::endl << std::endl;

	} catch ( ... ) {

		std::cerr << "Unknown exception caught" << std::endl;
	}

	return 2;
}

void usage( const std::string &programName ) {
	std::cerr << "Usage:  " << programName << " <compareFrom> <compareTo>" << std::endl;
	std::cerr << programName << " compares <compareFrom> file and <compareTo> file to see if they contain identical DesertIfaceBack models." << std::endl << std::endl;
}

max_stars_repo_name: lefevre-fraser/openmeta-mms

max_issues_repo_name: lefevre-fraser/openmeta-mms

max_forks_repo_name: lefevre-fraser/openmeta-mms


text:
///
/// Copyright(c) 2018 Aimin Huang
/// Distributed under the MIT License (http://opensource.org/licenses/MIT)
///
#ifndef BinaryLogger_Header_Observer
#define BinaryLogger_Header_Observer

#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#include <vector>
#include <mutex>
//#include <boost/thread/shared_mutex.hpp>
#include <functional>
#include <cstdio> ////using std::remove function to remove a file / std::rename function to rename a file

#include <boost/mpl/bool.hpp>
#include <boost/filesystem.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
//#include <boost/date_time/posix_time/posix_time.hpp>

#include "binary_logger_util.h"

template<typename DataStruct>
class BinaryLogger
{
public:
	////online
    BinaryLogger(const std::string & name,const bool record_last, bool auto_write,
		std::ios_base::openmode mode = std::fstream::trunc,	const std::string & date = ""
		);
	~BinaryLogger();

    void append(const DataStruct &data);
	void append(const std::vector<DataStruct> &data);
	void readFromFirstCache(std::vector<DataStruct> & vData, const bool writeToFile =true );
    void readFromSecondCache(std::vector<DataStruct> & vData, unsigned int startpos, unsigned int deviation, unsigned int count = 0);
	void enableAutoWriteToSecondCache(bool);

	void autoWriteToSecondCache();

	////return value: False means empty file; true means non-empty file
	bool recover( const int dataStructsPerBlock );

	void appendLast(const std::vector<DataStruct> &vData  );
	void readLast( std::vector<DataStruct> &vData, const bool IsYdData=true );

public:
    const std::string m_logger_name;
private:
	const bool m_record_last;

	int m_data_structs_per_block;
	unsigned int m_data_written_count;
	bool m_auto_write;

	std::ios_base::openmode m_openmode;
	boost::gregorian::date m_date;

	std::string m_record_filename_txt;
	std::string m_last_filename_txt;

	std::string m_record_filename_bin;
	std::string m_last_filename_bin;

	std::fstream m_record_ofs;
	std::fstream m_last_ofs;
    std::vector<DataStruct> m_pending_data;

	std::mutex m_data_mutex;
    std::mutex m_file_mutex;
	std::mutex m_flag_mutex;

};

////online
template<typename DataStruct>
BinaryLogger<DataStruct>::BinaryLogger(const std::string & name, const bool record_last, bool auto_write,
		std::ios_base::openmode mode/* = std::fstream::trunc*/,		const std::string & date
		)
	:m_logger_name(name),m_record_last(record_last), m_data_structs_per_block(0),m_data_written_count(0),
	 m_auto_write(auto_write), m_openmode(mode)
{
	if( date.size() >=8 )
	{
		m_date = boost::gregorian::date_from_iso_string( date );
	}else{
		m_date = boost::gregorian::day_clock::local_day();
	}

	std::string t = boost::gregorian::to_iso_string( m_date );

	BinaryLoggerUtil::m_logger_filename_format.clear();
	BinaryLoggerUtil::m_logger_filename_format%name%"Record"%t%"bin";
	m_record_filename_bin = BinaryLoggerUtil::m_logger_filename_format.str();

	boost::filesystem::path cur_path( boost::filesystem::current_path() );
	std::cout<<"DataCenter Files Directory:"<<cur_path<<std::endl;

	cur_path /= m_record_filename_bin;
	m_record_filename_bin = cur_path.string();

	if( m_record_last )
	{
		BinaryLoggerUtil::m_logger_filename_format.clear();
		BinaryLoggerUtil::m_logger_filename_format%name%"Last"%t%"bin";
		m_last_filename_bin = BinaryLoggerUtil::m_logger_filename_format.str();

		cur_path = boost::filesystem::current_path() ;
		cur_path /= m_last_filename_bin;
		m_last_filename_bin = cur_path.string();
	}

//	if( ! boost::filesystem::exists( m_record_filename_bin.c_str() ) )
//	{
//		std::cout<<"The Record File:"<<m_record_filename_bin<<" Does Not Exist!"<<std::endl;
//	}

	if( ! BinaryLoggerUtil::open_bin_file(m_record_ofs, m_record_filename_bin,  m_openmode ) )
		std::cout<<"Could not open record file:"<<m_record_filename_bin<<std::endl;
//	if( !__open_bin_file(m_last_ofs, m_last_filename_bin ) )
//		std::cout<<"Could not open last file:"<<m_last_filename_bin<<std::endl;

	if( m_auto_write )
	{
		BinaryLoggerUtil::append( std::bind( &BinaryLogger<DataStruct>::autoWriteToSecondCache, this ) );
	}
};

template<typename DataStruct>
BinaryLogger<DataStruct>::~BinaryLogger()
{
	std::unique_lock<std::mutex> writeFileLock(m_file_mutex);
	if( !m_record_ofs.is_open() ) return;

	m_record_ofs.close();
	m_last_ofs.close();
};

template<typename DataStruct>
void BinaryLogger<DataStruct>::appendLast(const std::vector<DataStruct> &vData  ){

	if( m_record_last )
	{
		std::ofstream ofs( m_last_filename_bin.c_str(),  std::ios::out |std::ios::binary | std::ios::trunc );
		if( ofs.is_open()  ){
			for(auto it = vData.begin() ; it!= vData.end(); it++ ){
				ofs.write((const char *)&(*it), sizeof(DataStruct) );
				if( !ofs.good() ){
					std::cerr <<"In BinaryLogger: fail to write last record field to file:"<<m_last_filename_bin <<std::endl;
					break;
				}
			}
			ofs.close();
		}else{
			std::cout<<"===> Could not open file:"<<m_last_filename_bin<<std::endl;
		}
	}
}

////Read Yd Data
template<typename DataStruct>
void BinaryLogger<DataStruct>::readLast( std::vector<DataStruct> &vData, const bool IsYdData /*=true*/  ){

	if( m_record_last )
	{
		boost::gregorian::date tmpDate = m_date ;
		if( IsYdData )	tmpDate -=  boost::gregorian::days( tmpDate.day_of_week() == boost::date_time::Monday ? 3 : 1 );
		std::string t = boost::gregorian::to_iso_string( tmpDate );

		BinaryLoggerUtil::m_logger_filename_format.clear();
		BinaryLoggerUtil::m_logger_filename_format%m_logger_name%"Last"%t%"bin";
		t = BinaryLoggerUtil::m_logger_filename_format.str();

		boost::filesystem::path cur_path( boost::filesystem::current_path() );
		cur_path /= t;
		t = cur_path.string();

		if( boost::filesystem::exists( t.c_str() ) )
		{
			std::ifstream ofs( t.c_str(), std::ios::in  | std::ios::binary );
			if( ofs.is_open() ){
				DataStruct data;
				while (ofs.peek() != EOF ) {
					ofs.read( (char *)&data, sizeof(DataStruct));
					vData.push_back( data );
				}
				ofs.close();
			}
		}else{
			std::cout<<"===> The file:"<<t<<" does not exists!"<<std::endl;
		}
	}
}

////return value: False means empty file; true means non-empty file
template<typename DataStruct>
bool BinaryLogger<DataStruct>::recover(const int dataStructsPerBlock)
{
	std::unique_lock<std::mutex> writeFileLock(m_file_mutex);
	m_data_structs_per_block = dataStructsPerBlock;
//   if( !m_record_ofs.is_open() ) return false;
	bool emptyFile = false;
	long fileSize = BinaryLoggerUtil::filesize( m_record_filename_bin );
	if( fileSize > 0 ){
		m_data_written_count = fileSize/(sizeof(DataStruct)*dataStructsPerBlock);
		long reminder = fileSize%(sizeof(DataStruct)*dataStructsPerBlock);
		if( reminder > 0 ){
			////// Delete the un chunked data
			m_record_ofs.close();
			std::string tmp = m_record_filename_bin + ".tmp";
			int rc = std::rename( m_record_filename_bin.c_str(), tmp.c_str() );
			BinaryLoggerUtil::open_bin_file(m_record_ofs, m_record_filename_bin,  std::fstream::trunc );
			if( 0 == rc  )
			{
				std::ifstream ofs( tmp.c_str(), std::ios::in  | std::ios::binary );
				if( m_record_ofs.is_open() && ofs.is_open() ){
					long count = fileSize/(sizeof(DataStruct)*dataStructsPerBlock), i = 0;
					count *= dataStructsPerBlock;
					DataStruct data;
					while( i < count && ofs.peek() != EOF ){
						ofs.read( (char *)&data, sizeof(DataStruct));
						m_record_ofs.write((const char *)&data, sizeof(DataStruct) );
						if( !m_record_ofs.good() ){
							std::cerr <<"===> In BinaryLogger: fail to recover record field to file:"<<m_record_filename_bin <<std::endl;
							break;
						}
						i++;
					}
					if( i < count ){
						std::cerr<<"===> In BinaryLogger: fail to recover all record field to file:"<<m_record_filename_bin <<". Recovered: "<< i <<"/"<<count<<std::endl;
					}
					ofs.close();
					std::remove( tmp.c_str() );
				}else{
					emptyFile = true;
					std::cout<<"===> Recover Old Data Failed b/c could not open file:"<<m_record_filename_bin<<" or "<< tmp <<std::endl;
				}
			}else{
				emptyFile = true;
				std::cout<<"===> Recover Old Data Failed b/c could not rename file:"<<m_record_filename_bin<<std::endl;
			}
		}
	}else{
		emptyFile = true;
	}
	return emptyFile;
}

template<typename DataStruct>
void BinaryLogger<DataStruct>::append(const DataStruct &data )
{
	std::unique_lock<std::mutex> writeFileLock(m_data_mutex);
	m_pending_data.push_back( data );
};

template<typename DataStruct>
void BinaryLogger<DataStruct>::append(const std::vector<DataStruct> &data )
{
	std::unique_lock<std::mutex> writeFileLock(m_data_mutex);
	m_pending_data.insert( m_pending_data.end(), data.begin(), data.end() );
};

template<typename DataStruct>
void BinaryLogger<DataStruct>::enableAutoWriteToSecondCache( bool auto_write )
{

	std::unique_lock<std::mutex> writeFileLock(m_flag_mutex);
	m_auto_write = auto_write;
};
template<typename DataStruct>
void BinaryLogger<DataStruct>::autoWriteToSecondCache()
{
	std::unique_lock<std::mutex> writeFileLock(m_flag_mutex);
	if( m_auto_write ){
		std::vector<DataStruct>  vData;
		this->readFromFirstCache( vData );
	}
};

template<typename DataStruct>
void BinaryLogger<DataStruct>::readFromFirstCache(std::vector<DataStruct> & vData, const bool writeToFile /*=true*/)
{
	unsigned int beg = vData.size();
	{
		std::unique_lock<std::mutex> writeFileLock(m_data_mutex);
		vData.reserve( vData.size() + m_pending_data.size() );
		vData.insert( vData.begin(), m_pending_data.begin(), m_pending_data.end() );
		if (writeToFile )m_pending_data.resize(0);
	}

	if( writeToFile ){
		std::unique_lock<std::mutex> writeFileLock(m_file_mutex);
		if( !m_record_ofs.is_open() ) return;
		m_record_ofs.seekp(0, std::ios_base::end);
//		for (auto it=vData.begin(); it!=vData.end(); it++) {
		unsigned int end = vData.size();
		for(unsigned int i = beg; i< end; i++){
			m_record_ofs.write((const char *)&( vData[i] ), sizeof(DataStruct) );
			if( !m_record_ofs.good() ){
				std::cerr <<"===> In BinaryLogger: fail to write record field to file:"<<m_record_filename_bin <<std::endl;
				break;
			}
			m_data_written_count++;
		}
		m_record_ofs.flush();
	}
};
template<typename DataStruct>
void BinaryLogger<DataStruct>::readFromSecondCache(std::vector<DataStruct> & vData, unsigned int startpos, unsigned int deviation, unsigned int count)
{
//	boost::unique_lock<boost::shared_mutex> writeFileLock(m_file_mutex);
	std::unique_lock<std::mutex> writeFileLock(m_file_mutex);
	if( !m_record_ofs.is_open() ) return;
//	long fileSize = BinaryLoggerUtil::filesize( m_record_filename_bin );
	if( m_data_written_count && deviation ){
		if( !count ){
			count = 1+m_data_written_count/deviation;
			vData.reserve( count  );
		}
		m_record_ofs.seekg(0);
		DataStruct data;
		m_record_ofs.seekg( startpos * sizeof(DataStruct), std::ios_base::cur );
		deviation--;                    ////reason: because the file pointer will move ahead after we read data
		if( deviation ){
			deviation *=sizeof(DataStruct);
			unsigned int i = 0;
			while (m_record_ofs.peek() != EOF && i < count ) {
				m_record_ofs.read( (char *)&data, sizeof(DataStruct));
				vData.push_back(data);
				m_record_ofs.seekg( deviation, std::ios_base::cur );
				i++;
			}
		}else{
			unsigned int i = 0;
			while (m_record_ofs.peek() != EOF && i < count) {
				m_record_ofs.read( (char *)&data, sizeof(DataStruct));
				vData.push_back(data);
				i++;
			}
		}
	//    std::cout<<"=====read data=== Key:"<<data.instrument_id<<std::endl;
		m_record_ofs.clear();
	}
};

/*
Helper must provide three method:
RtnFieldHeader
WriteFieldToFile
ReadFieldFromFile
and one public const variable
support_txt2bin
*/

template<typename DataStruct, class CHelper>
class BinaryLoggerOffline{
public:
	////offline
    BinaryLoggerOffline(const std::string & name,const bool record_last,
		CHelper helper,	const std::string & fmt = "csv", const std::string & date = ""
		);

	void txt2bin();
	void bin2txt();

public:
    const std::string m_logger_name;
private:
	const bool m_record_last;
	CHelper m_helper;

	boost::gregorian::date m_date;

	std::string m_record_filename_txt;
	std::string m_last_filename_txt;

	std::string m_record_filename_bin;
	std::string m_last_filename_bin;

	std::fstream m_record_ofs;
	std::fstream m_last_ofs;
};

////offline
template<typename DataStruct, class CHelper>
BinaryLoggerOffline<DataStruct, CHelper>::BinaryLoggerOffline(const std::string & name,const bool record_last,
									   CHelper helper,   const std::string & fmt,   const std::string & date
									   )
	:m_logger_name(name), m_record_last(record_last),m_helper(helper)
{
	if( date.size() >=8 )
	{
		m_date = boost::gregorian::date_from_iso_string( date );
	}else{
		m_date = boost::gregorian::day_clock::local_day();
	}

	std::string t = boost::gregorian::to_iso_string( m_date );

	BinaryLoggerUtil::m_logger_filename_format.clear();
	BinaryLoggerUtil::m_logger_filename_format%name%"Record"%t%fmt;
	m_record_filename_txt = BinaryLoggerUtil::m_logger_filename_format.str();
	BinaryLoggerUtil::m_logger_filename_format.clear();
	BinaryLoggerUtil::m_logger_filename_format%name%"Record"%t%"bin";
	m_record_filename_bin = BinaryLoggerUtil::m_logger_filename_format.str();

	boost::filesystem::path cur_path( boost::filesystem::current_path() );
	std::cout<<"DataCenter Files Directory:"<<cur_path<<std::endl;

	cur_path /= m_record_filename_bin;
	m_record_filename_bin = cur_path.string();

	cur_path = boost::filesystem::current_path();
	cur_path /= m_record_filename_txt;
	m_record_filename_txt = cur_path.string();

//	if( boost::mpl::bool_<m_record_last>::value )
	if( m_record_last )
	{
		BinaryLoggerUtil::m_logger_filename_format.clear();
		BinaryLoggerUtil::m_logger_filename_format%name%"Last"%t%fmt;
		m_last_filename_txt = BinaryLoggerUtil::m_logger_filename_format.str();
		BinaryLoggerUtil::m_logger_filename_format.clear();
		BinaryLoggerUtil::m_logger_filename_format%name%"Last"%t%"bin";
		m_last_filename_bin = BinaryLoggerUtil::m_logger_filename_format.str();

		cur_path = boost::filesystem::current_path() ;
		cur_path /= m_last_filename_bin;
		m_last_filename_bin = cur_path.string();

		cur_path = boost::filesystem::current_path();
		cur_path /= m_last_filename_txt;
		m_last_filename_txt = cur_path.string();
	}
};

template<typename DataStruct, class CHelper>
void BinaryLoggerOffline<DataStruct, CHelper>::txt2bin(){
	if( !m_helper.support_txt2bin ) return;
	if( boost::filesystem::exists( m_record_filename_txt.c_str() ) )
	{
		std::ifstream ofs( m_record_filename_txt.c_str(),  std::ios::in  );
		std::ofstream m_record_ofs( m_record_filename_bin.c_str(),  std::ios::out |std::ios::binary | std::ios::trunc );

		if( ofs.fail() || m_record_ofs.fail() )
		{
			std::cout<<"===> Can not open file:"<<m_record_filename_txt<<" or "<<m_record_filename_bin<<" <=============="<<std::endl;
			ofs.clear();	m_record_ofs.clear();
			return;
		}
		std::cout<<"===> Translating Txt File:"<<m_record_filename_txt<<std::endl;

		std::string line;
		std::getline( ofs, line);////discard header
		DataStruct data;
		while (std::getline(ofs, line))
		{
			std::istringstream iss(line);
			m_helper.ReadFieldFromFile(data, iss); ///////read data from file
			m_record_ofs.write((const char *)&(data), sizeof(DataStruct) );
		}
		ofs.close(); m_record_ofs.close();
	}else
	{
		std::cout<<"===> The file:"<<m_record_filename_txt<<" does not exists!"<<std::endl;
	}

	if( m_record_last )
	{
		if( boost::filesystem::exists( m_last_filename_txt.c_str() ) )
		{
			std::ifstream ofs( m_last_filename_txt.c_str(),  std::ios::in  );
			std::ofstream m_last_ofs( m_last_filename_bin.c_str(),  std::ios::out |std::ios::binary | std::ios::trunc );

			if( ofs.fail() || m_last_ofs.fail() )
			{
				std::cout<<"===> Can not open file:"<<m_last_filename_txt<<" or "<<m_last_filename_bin<<" <=============="<<std::endl;
				ofs.clear(); m_last_ofs.clear();
				return;
			}
			std::cout<<"===> Translating Txt File:"<<m_last_filename_txt<<std::endl;
			std::string line;
			std::getline( ofs, line);////discard header
			DataStruct data;
			while (std::getline(ofs, line))
			{
				std::istringstream iss(line);
				m_helper.ReadFieldFromFile(data, iss); ///////read data from file
				m_last_ofs.write((const char *)&(data), sizeof(DataStruct) );
			}
			ofs.close(); m_last_ofs.close();
		}else{
			std::cout<<"===> The file:"<<m_last_filename_txt<<" does not exists!"<<std::endl;
		}
	}
}

template<typename DataStruct, class CHelper>
void BinaryLoggerOffline<DataStruct, CHelper>::bin2txt(){
	if( boost::filesystem::exists( m_record_filename_bin.c_str() ) )
	{
		std::ifstream m_record_ofs( m_record_filename_bin.c_str(), std::ios::in  | std::ios::binary );
		std::ofstream ofs( m_record_filename_txt.c_str(), std::ios::out | std::ios::trunc);

		if( ofs.fail() || m_record_ofs.fail() )
		{
			std::cout<<"===> Can not open file:"<<m_record_filename_txt<<" or "<<m_record_filename_bin<<" <=============="<<std::endl;
			ofs.clear();
			return;
		}
		std::cout<<"===> Translating Bin File:"<<m_record_filename_bin<<std::endl;

		ofs<<m_helper.RtnFieldHeader()<<std::endl; ////write header

		m_record_ofs.seekg(0);
		DataStruct data;
		while (m_record_ofs.peek() != EOF ) {
			m_record_ofs.read( (char *)&data, sizeof(DataStruct));
			m_helper.WriteFieldToFile(data, ofs);
		}

		ofs.close(); m_record_ofs.close();
	}else{
		std::cout<<"===> The file:"<<m_record_filename_bin<<" does not exists!"<<std::endl;
	}

	if( m_record_last )
	{
		if( boost::filesystem::exists( m_last_filename_bin.c_str() ) )
		{
			std::ifstream m_last_ofs( m_last_filename_bin.c_str(), std::ios::in  | std::ios::binary );
			std::ofstream ofs( m_last_filename_txt.c_str(),  std::ios::out | std::ios::trunc );
			if( ofs.fail() || m_last_ofs.fail() )
			{
				std::cout<<"===> Can not open file:"<<m_last_filename_txt<<" or "<<m_last_filename_bin<<" <=============="<<std::endl;
				ofs.clear();m_last_ofs.clear();
				return;
			}
			std::cout<<"===> Translating Bin File:"<<m_last_filename_bin<<std::endl;
			ofs<<m_helper.RtnFieldHeader()<<std::endl;   ////write header
			DataStruct data;
			while (m_last_ofs.peek() != EOF ) {
				m_last_ofs.read( (char *)&data, sizeof(DataStruct));
				m_helper.WriteFieldToFile(data, ofs);
			}
			ofs.close(); m_last_ofs.close();
		}else{
			std::cout<<"===> The file:"<<m_last_filename_bin<<" does not exists!"<<std::endl;
		}
	}
}

#endif


text:
#include "CommonTools/Utils/interface/DynArray.h"
#include "DataFormats/ParticleFlowReco/interface/PFRecHit.h"
#include "DataFormats/ParticleFlowReco/interface/PFRecHitFwd.h"
#include "FWCore/Framework/interface/ConsumesCollector.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "FWCore/Utilities/interface/isFinite.h"
#include "RecoParticleFlow/PFClusterProducer/interface/CaloRecHitResolutionProvider.h"
#include "RecoParticleFlow/PFClusterProducer/interface/PFCPositionCalculatorBase.h"

#include "vdt/vdtMath.h"

#include <boost/iterator/function_output_iterator.hpp>

#include <cmath>
#include <iterator>
#include <memory>
#include <tuple>

class Basic2DGenericPFlowPositionCalc : public PFCPositionCalculatorBase {
public:
  Basic2DGenericPFlowPositionCalc(const edm::ParameterSet& conf, edm::ConsumesCollector& cc)
      : PFCPositionCalculatorBase(conf, cc),
        _posCalcNCrystals(conf.getParameter<int>("posCalcNCrystals")),
        _minAllowedNorm(conf.getParameter<double>("minAllowedNormalization")) {
    std::vector<int> detectorEnum;
    std::vector<int> depths;
    std::vector<double> logWeightDenom;
    std::vector<float> logWeightDenomInv;

    if (conf.exists("logWeightDenominatorByDetector")) {
      const std::vector<edm::ParameterSet>& logWeightDenominatorByDetectorPSet =
          conf.getParameterSetVector("logWeightDenominatorByDetector");

      for (const auto& pset : logWeightDenominatorByDetectorPSet) {
        if (!pset.exists("detector")) {
          throw cms::Exception("logWeightDenominatorByDetectorPSet") << "logWeightDenominator : detector not specified";
        }

        const std::string& det = pset.getParameter<std::string>("detector");

        if (det == std::string("HCAL_BARREL1") || det == std::string("HCAL_ENDCAP")) {
          std::vector<int> depthsT = pset.getParameter<std::vector<int> >("depths");
          std::vector<double> logWeightDenomT = pset.getParameter<std::vector<double> >("logWeightDenominator");
          if (logWeightDenomT.size() != depthsT.size()) {
            throw cms::Exception("logWeightDenominator") << "logWeightDenominator mismatch with the numbers of depths";
          }
          for (unsigned int i = 0; i < depthsT.size(); ++i) {
            if (det == std::string("HCAL_BARREL1"))
              detectorEnum.push_back(1);
            if (det == std::string("HCAL_ENDCAP"))
              detectorEnum.push_back(2);
            depths.push_back(depthsT[i]);
            logWeightDenom.push_back(logWeightDenomT[i]);
          }
        }
      }
    } else {
      detectorEnum.push_back(0);
      depths.push_back(0);
      logWeightDenom.push_back(conf.getParameter<double>("logWeightDenominator"));
    }

    for (unsigned int i = 0; i < depths.size(); ++i) {
      logWeightDenomInv.push_back(1. / logWeightDenom[i]);
    }

    //    _logWeightDenom = std::make_pair(depths,logWeightDenomInv);
    _logWeightDenom = std::make_tuple(detectorEnum, depths, logWeightDenomInv);

    _timeResolutionCalcBarrel.reset(nullptr);
    if (conf.exists("timeResolutionCalcBarrel")) {
      const edm::ParameterSet& timeResConf = conf.getParameterSet("timeResolutionCalcBarrel");
      _timeResolutionCalcBarrel = std::make_unique<CaloRecHitResolutionProvider>(timeResConf);
    }
    _timeResolutionCalcEndcap.reset(nullptr);
    if (conf.exists("timeResolutionCalcEndcap")) {
      const edm::ParameterSet& timeResConf = conf.getParameterSet("timeResolutionCalcEndcap");
      _timeResolutionCalcEndcap = std::make_unique<CaloRecHitResolutionProvider>(timeResConf);
    }

    switch (_posCalcNCrystals) {
      case 5:
      case 9:
      case -1:
        break;
      default:
        edm::LogError("Basic2DGenericPFlowPositionCalc") << "posCalcNCrystals not valid";
        assert(0);  // bug
    }
  }

  Basic2DGenericPFlowPositionCalc(const Basic2DGenericPFlowPositionCalc&) = delete;
  Basic2DGenericPFlowPositionCalc& operator=(const Basic2DGenericPFlowPositionCalc&) = delete;

  void calculateAndSetPosition(reco::PFCluster&) override;
  void calculateAndSetPositions(reco::PFClusterCollection&) override;

private:
  const int _posCalcNCrystals;
  std::tuple<std::vector<int>, std::vector<int>, std::vector<float> > _logWeightDenom;
  const float _minAllowedNorm;

  std::unique_ptr<CaloRecHitResolutionProvider> _timeResolutionCalcBarrel;
  std::unique_ptr<CaloRecHitResolutionProvider> _timeResolutionCalcEndcap;

  void calculateAndSetPositionActual(reco::PFCluster&) const;
};

DEFINE_EDM_PLUGIN(PFCPositionCalculatorFactory, Basic2DGenericPFlowPositionCalc, "Basic2DGenericPFlowPositionCalc");

namespace {
  inline bool isBarrel(int cell_layer) {
    return (cell_layer == PFLayer::HCAL_BARREL1 || cell_layer == PFLayer::HCAL_BARREL2 ||
            cell_layer == PFLayer::ECAL_BARREL);
  }
}  // namespace

void Basic2DGenericPFlowPositionCalc::calculateAndSetPosition(reco::PFCluster& cluster) {
  calculateAndSetPositionActual(cluster);
}

void Basic2DGenericPFlowPositionCalc::calculateAndSetPositions(reco::PFClusterCollection& clusters) {
  for (reco::PFCluster& cluster : clusters) {
    calculateAndSetPositionActual(cluster);
  }
}

void Basic2DGenericPFlowPositionCalc::calculateAndSetPositionActual(reco::PFCluster& cluster) const {
  if (!cluster.seed()) {
    throw cms::Exception("ClusterWithNoSeed") << " Found a cluster with no seed: " << cluster;
  }
  double cl_energy = 0;
  double cl_time = 0;
  double cl_timeweight = 0.0;
  double max_e = 0.0;
  PFLayer::Layer max_e_layer = PFLayer::NONE;
  // find the seed and max layer and also calculate time
  //Michalis : Even if we dont use timing in clustering here we should fill
  //the time information for the cluster. This should use the timing resolution(1/E)
  //so the weight should be fraction*E^2
  //calculate a simplistic depth now. The log weighted will be done
  //in different stage

  auto const recHitCollection =
      &(*cluster.recHitFractions()[0].recHitRef()) - cluster.recHitFractions()[0].recHitRef().key();
  auto nhits = cluster.recHitFractions().size();
  struct LHit {
    reco::PFRecHit const* hit;
    float energy;
    float fraction;
  };
  declareDynArray(LHit, nhits, hits);
  for (auto i = 0U; i < nhits; ++i) {
    auto const& hf = cluster.recHitFractions()[i];
    auto k = hf.recHitRef().key();
    auto p = recHitCollection + k;
    hits[i] = {p, (*p).energy(), float(hf.fraction())};
  }

  bool resGiven = bool(_timeResolutionCalcBarrel) & bool(_timeResolutionCalcEndcap);
  LHit mySeed = {};
  for (auto const& rhf : hits) {
    const reco::PFRecHit& refhit = *rhf.hit;
    if (refhit.detId() == cluster.seed())
      mySeed = rhf;
    const auto rh_fraction = rhf.fraction;
    const auto rh_rawenergy = rhf.energy;
    const auto rh_energy = rh_rawenergy * rh_fraction;
#ifdef PF_DEBUG
    if UNLIKELY (edm::isNotFinite(rh_energy)) {
      throw cms::Exception("PFClusterAlgo") << "rechit " << refhit.detId() << " has a NaN energy... "
                                            << "The input of the particle flow clustering seems to be corrupted.";
    }
#endif
    cl_energy += rh_energy;
    // If time resolution is given, calculated weighted average
    if (resGiven) {
      double res2 = 1.e-4;
      int cell_layer = (int)refhit.layer();
      res2 = isBarrel(cell_layer) ? 1. / _timeResolutionCalcBarrel->timeResolution2(rh_rawenergy)
                                  : 1. / _timeResolutionCalcEndcap->timeResolution2(rh_rawenergy);
      cl_time += rh_fraction * refhit.time() * res2;
      cl_timeweight += rh_fraction * res2;
    } else {  // assume resolution = 1/E**2
      const double rh_rawenergy2 = rh_rawenergy * rh_rawenergy;
      cl_timeweight += rh_rawenergy2 * rh_fraction;
      cl_time += rh_rawenergy2 * rh_fraction * refhit.time();
    }

    if (rh_energy > max_e) {
      max_e = rh_energy;
      max_e_layer = refhit.layer();
    }
  }

  cluster.setEnergy(cl_energy);
  cluster.setTime(cl_time / cl_timeweight);
  if (resGiven) {
    cluster.setTimeError(std::sqrt(1.0f / float(cl_timeweight)));
  }
  cluster.setLayer(max_e_layer);

  // calculate the position
  double depth = 0.0;
  double position_norm = 0.0;
  double x(0.0), y(0.0), z(0.0);
  if (nullptr != mySeed.hit) {
    auto seedNeighbours = mySeed.hit->neighbours();
    switch (_posCalcNCrystals) {
      case 5:
        seedNeighbours = mySeed.hit->neighbours4();
        break;
      case 9:
        seedNeighbours = mySeed.hit->neighbours8();
        break;
      default:
        break;
    }

    auto compute = [&](LHit const& rhf) {
      const reco::PFRecHit& refhit = *rhf.hit;

      int cell_layer = (int)refhit.layer();
      float threshold = 0;

      for (unsigned int j = 0; j < (std::get<2>(_logWeightDenom)).size(); ++j) {
        // barrel is detecor type1
        int detectorEnum = std::get<0>(_logWeightDenom)[j];
        int depth = std::get<1>(_logWeightDenom)[j];

        if ((cell_layer == PFLayer::HCAL_BARREL1 && detectorEnum == 1 && refhit.depth() == depth) ||
            (cell_layer == PFLayer::HCAL_ENDCAP && detectorEnum == 2 && refhit.depth() == depth) || detectorEnum == 0)
          threshold = std::get<2>(_logWeightDenom)[j];
      }

      const auto rh_energy = rhf.energy * rhf.fraction;
      const auto norm =
          (rhf.fraction < _minFractionInCalc ? 0.0f : std::max(0.0f, vdt::fast_logf(rh_energy * threshold)));
      const auto rhpos_xyz = refhit.position() * norm;
      x += rhpos_xyz.x();
      y += rhpos_xyz.y();
      z += rhpos_xyz.z();
      depth += refhit.depth() * norm;
      position_norm += norm;
    };

    if (_posCalcNCrystals != -1)  // sorted to make neighbour search faster (maybe)
      std::sort(hits.begin(), hits.end(), [](LHit const& a, LHit const& b) { return a.hit < b.hit; });

    if (_posCalcNCrystals == -1)
      for (auto const& rhf : hits)
        compute(rhf);
    else {  // only seed and its neighbours
      compute(mySeed);
      // search seedNeighbours to find energy fraction in cluster (sic)
      unInitDynArray(reco::PFRecHit const*, seedNeighbours.size(), nei);
      for (auto k : seedNeighbours) {
        nei.push_back(recHitCollection + k);
      }
      std::sort(nei.begin(), nei.end());
      struct LHitLess {
        auto operator()(LHit const& a, reco::PFRecHit const* b) const { return a.hit < b; }
        auto operator()(reco::PFRecHit const* b, LHit const& a) const { return b < a.hit; }
      };
      std::set_intersection(
          hits.begin(), hits.end(), nei.begin(), nei.end(), boost::make_function_output_iterator(compute), LHitLess());
    }
  } else {
    throw cms::Exception("Basic2DGenerticPFlowPositionCalc")
        << "Cluster seed hit is null, something is wrong with PFlow RecHit!";
  }

  if (position_norm < _minAllowedNorm) {
    edm::LogError("WeirdClusterNormalization") << "PFCluster too far from seeding cell: set position to (0,0,0).";
    cluster.setPosition(math::XYZPoint(0, 0, 0));
    cluster.calculatePositionREP();
  } else {
    const double norm_inverse = 1.0 / position_norm;
    x *= norm_inverse;
    y *= norm_inverse;
    z *= norm_inverse;
    depth *= norm_inverse;
    cluster.setPosition(math::XYZPoint(x, y, z));
    cluster.setDepth(depth);
    cluster.calculatePositionREP();
  }
}

ext: cc

max_stars_repo_name: Purva-Chaudhari/cmssw

max_issues_repo_name: Purva-Chaudhari/cmssw

max_forks_repo_name: Purva-Chaudhari/cmssw


text:
// Copyright (c) 2014-2018 LG Electronics, 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.
//
// SPDX-License-Identifier: Apache-2.0

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <wait.h>
#include <boost/algorithm/string.hpp>
#include <string>
#include <fstream>
#include <iostream>

#include "Logging.h"
#include "util/Platform.h"
#include "util/Logger.hpp"

bool Platform::isFileExist(const string &path)
{
    if (access(path.c_str(), 0) != -1) {
        return true;
    }
    return false;
}

bool Platform::isDirExist(const string &path)
{
    if (g_file_test(path.c_str(), G_FILE_TEST_IS_DIR)) {
        return true;
    }
    return false;
}

bool Platform::canWriteFile(const string &path)
{
    FILE *fp = NULL;
    if(!(fp = fopen(path.c_str(), "w+"))) {
        return false;
    }

    fclose(fp);
    return true;
}

string Platform::readFile(const string &filename)
{
    string file;

    if (isDirExist(filename))
        return file;
    else if (!isFileExist(filename))
        return file;
    std::ifstream stream(filename);
    file.assign((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
    boost::trim(file);

    return file;
}

bool Platform::writeFile(const string &filename, const string &content)
{
    ofstream out(filename);
    out << content;
    out.close();
    return true;
}

bool Platform::copyFile(const string &from, const string &to)
{
    if (!Platform::isFileExist(from)) {
        return false;
    }
    string content = readFile(from);
    return writeFile(to, content);
}

bool Platform::deleteFile(const string &filename)
{
    if (filename.empty()) {
        return false;
    }

    if (!::remove(filename.c_str())) {
        Logger::debug(LOG_PREPIX_FORMAT "'%s' file deleted successfully.",
                      LOG_PREPIX_ARGS, filename.c_str());
        return true;
    }

    Logger::debug(LOG_PREPIX_FORMAT "Unable to delete file (%s)", LOG_PREPIX_ARGS, filename.c_str());
    return false;
}

string Platform::executeCommand(const string &command, const string firstArg, const string secondArg)
{
    string console = "";
    string newCommand = command + " " + firstArg + " " + secondArg;

    if (!executeCommand(newCommand, console)) {
        return console;
    }
    return console;
}

bool Platform::executeCommand(const string &command, string &console)
{
    FILE *file;
    char buff[256];

    if (!(file = popen(command.c_str(), "r"))){
        return false;
    }

    console.clear();
    Logger::info(MSGID_CONFIGDSERVICE,
                 LOG_PREPIX_FORMAT "Execute command (%s)",
                 LOG_PREPIX_ARGS, command.c_str());
    while(fgets(buff, sizeof(buff), file)!=NULL){
        console += buff;
    }
    boost::trim(console);
    pclose(file);
    return true;
}

string Platform::concatPaths(string parent, string child)
{
    trim(parent);
    trim(child);
    if (parent.find_last_of('/') == parent.length() - 1) {
        parent.erase(parent.size() - 1, 1);
    }
    if (child.find_first_of('/') == 0) {
        child.erase(0, 1);
    }

    if (parent.empty())
        parent = "/" + child;
    else if (!child.empty())
        parent.append("/").append(child);
    return parent;
}

string& Platform::extractFileName(string &fileName, string &name, string &extension)
{
    name = fileName;
    extension.clear();

    int lastIndex = fileName.find_last_of('.');
    if (lastIndex < 0)
        return fileName;

    name = fileName.substr(0, lastIndex);
    extension = fileName.substr(lastIndex + 1);
    return fileName;
}

string& Platform::trim(string& str)
{
    size_t first = str.find_first_not_of(' ');
    if (string::npos == first)
    {
        return str;
    }
    size_t last = str.find_last_not_of(' ');
    str = str.substr(first, (last - first + 1));
    return str;
}

string Platform::timeStr()
{
    char buffer[64];
    sprintf(buffer, "%u", (unsigned)time(NULL));
    return buffer;
}

max_stars_repo_name: webosce/configd

max_issues_repo_name: webosce/configd

max_forks_repo_name: webosce/configd


text:
#include <fstream>
#include <boost/program_options.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/filesystem.hpp>
#include <Common/config.h>
//#include <Common/Util/util.h>
#include <yaml-cpp/yaml.h>

namespace bpt = boost::property_tree;
namespace bpo = boost::program_options;
namespace fs = boost::filesystem;

namespace EliteQuant {
	CConfig* CConfig::pinstance_ = nullptr;
	mutex CConfig::instancelock_;

	CConfig::CConfig() {
		readConfig();
	}

	CConfig& CConfig::instance() {
		if (pinstance_ == nullptr) {
			std::lock_guard<mutex> g(instancelock_);
			if (pinstance_ == nullptr) {
				pinstance_ = new CConfig();
			}
		}
		return *pinstance_;
	}

	void CConfig::readConfig()
	{
#ifdef _DEBUG
		std::printf("Current path is : %s\n", boost::filesystem::current_path().string().c_str());
#endif
		string path = boost::filesystem::current_path().string() + "/config.yaml";
		YAML::Node config = YAML::LoadFile(path);

		_config_dir = boost::filesystem::current_path().string();
		_log_dir = config["log_dir"].as<std::string>();
		_data_dir = config["data_dir"].as<std::string>();
		boost::filesystem::path log_path(logDir());
		boost::filesystem::create_directory(log_path);
		boost::filesystem::path data_path(dataDir());
		boost::filesystem::create_directory(data_path);

		const string msgq = config["msgq"].as<std::string>();
		if (msgq == "zmq")
			_msgq = MSGQ::ZMQ;
		else if (msgq == "kafka")
			_msgq = MSGQ::KAFKA;
		else
			_msgq = MSGQ::NANOMSG;

		const string broker = config["broker"].as<std::string>();
		if (broker == "IB")
			_broker = BROKERS::IB;
		else if (broker == "CTP")
			_broker = BROKERS::CTP;
		else if (broker == "GOOGLE")
			_broker = BROKERS::GOOGLE;
		else if (broker == "SINA")
			_broker = BROKERS::SINA;
		else
			_broker = BROKERS::PAPER;

		account = config["account"].as<std::string>();
		ib_port = config["ibport"].as<long>();
		ctp_broker_id = config["ctp_broker_id"].as<std::string>();
		ctp_user_id = config["ctp_user_id"].as<std::string>();
		ctp_password = config["ctp_password"].as<std::string>();
		ctp_data_address = config["ctp_md_address"].as<std::string>();
		ctp_broker_address = config["ctp_td_address"].as<std::string>();
		const std::vector<string> tickers = config["tickers"].as<std::vector<string>>();
		for (auto s : tickers)
		{
			securities.push_back(s);
		}
	}

	string CConfig::configDir()
	{
		//return boost::filesystem::current_path().string();
		return _config_dir;
	}

	string CConfig::logDir()
	{
		//boost::filesystem::path full_path = boost::filesystem::current_path() / "log";
		//return full_path.string();
		return _log_dir;
	}

	string CConfig::dataDir()
	{
		//boost::filesystem::path full_path = boost::filesystem::current_path() / "data";
		//return full_path.string();
		return _data_dir;
	}
}


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

#include "coins.h"
#include "random.h"
#include "uint256.h"
#include "test/test_dzcoin.h"

#include <vector>
#include <map>

#include <boost/test/unit_test.hpp>

namespace
{
class ccoinsviewtest : public ccoinsview
{
    uint256 hashbestblock_;
    std::map<uint256, ccoins> map_;

public:
    bool getcoins(const uint256& txid, ccoins& coins) const
    {
        std::map<uint256, ccoins>::const_iterator it = map_.find(txid);
        if (it == map_.end()) {
            return false;
        }
        coins = it->second;
        if (coins.ispruned() && insecure_rand() % 2 == 0) {
            // randomly return false in case of an empty entry.
            return false;
        }
        return true;
    }

    bool havecoins(const uint256& txid) const
    {
        ccoins coins;
        return getcoins(txid, coins);
    }

    uint256 getbestblock() const { return hashbestblock_; }

    bool batchwrite(ccoinsmap& mapcoins, const uint256& hashblock)
    {
        for (ccoinsmap::iterator it = mapcoins.begin(); it != mapcoins.end(); ) {
            map_[it->first] = it->second.coins;
            if (it->second.coins.ispruned() && insecure_rand() % 3 == 0) {
                // randomly delete empty entries on write.
                map_.erase(it->first);
            }
            mapcoins.erase(it++);
        }
        mapcoins.clear();
        hashbestblock_ = hashblock;
        return true;
    }

    bool getstats(ccoinsstats& stats) const { return false; }
};

class ccoinsviewcachetest : public ccoinsviewcache
{
public:
    ccoinsviewcachetest(ccoinsview* base) : ccoinsviewcache(base) {}

    void selftest() const
    {
        // manually recompute the dynamic usage of the whole data, and compare it.
        size_t ret = memusage::dynamicusage(cachecoins);
        for (ccoinsmap::iterator it = cachecoins.begin(); it != cachecoins.end(); it++) {
            ret += memusage::dynamicusage(it->second.coins);
        }
        boost_check_equal(memusage::dynamicusage(*this), ret);
    }

};

}

boost_fixture_test_suite(coins_tests, basictestingsetup)

static const unsigned int num_simulation_iterations = 40000;

// this is a large randomized insert/remove simulation test on a variable-size
// stack of caches on top of ccoinsviewtest.
//
// it will randomly create/update/delete ccoins entries to a tip of caches, with
// txids picked from a limited list of random 256-bit hashes. occasionally, a
// new tip is added to the stack of caches, or the tip is flushed and removed.
//
// during the process, booleans are kept to make sure that the randomized
// operation hits all branches.
boost_auto_test_case(coins_cache_simulation_test)
{
    // various coverage trackers.
    bool removed_all_caches = false;
    bool reached_4_caches = false;
    bool added_an_entry = false;
    bool removed_an_entry = false;
    bool updated_an_entry = false;
    bool found_an_entry = false;
    bool missed_an_entry = false;

    // a simple map to track what we expect the cache stack to represent.
    std::map<uint256, ccoins> result;

    // the cache stack.
    ccoinsviewtest base; // a ccoinsviewtest at the bottom.
    std::vector<ccoinsviewcachetest*> stack; // a stack of ccoinsviewcaches on top.
    stack.push_back(new ccoinsviewcachetest(&base)); // start with one cache.

    // use a limited set of random transaction ids, so we do test overwriting entries.
    std::vector<uint256> txids;
    txids.resize(num_simulation_iterations / 8);
    for (unsigned int i = 0; i < txids.size(); i++) {
        txids[i] = getrandhash();
    }

    for (unsigned int i = 0; i < num_simulation_iterations; i++) {
        // do a random modification.
        {
            uint256 txid = txids[insecure_rand() % txids.size()]; // txid we're going to modify in this iteration.
            ccoins& coins = result[txid];
            ccoinsmodifier entry = stack.back()->modifycoins(txid);
            boost_check(coins == *entry);
            if (insecure_rand() % 5 == 0 || coins.ispruned()) {
                if (coins.ispruned()) {
                    added_an_entry = true;
                } else {
                    updated_an_entry = true;
                }
                coins.nversion = insecure_rand();
                coins.vout.resize(1);
                coins.vout[0].nvalue = insecure_rand();
                *entry = coins;
            } else {
                coins.clear();
                entry->clear();
                removed_an_entry = true;
            }
        }

        // once every 1000 iterations and at the end, verify the full cache.
        if (insecure_rand() % 1000 == 1 || i == num_simulation_iterations - 1) {
            for (std::map<uint256, ccoins>::iterator it = result.begin(); it != result.end(); it++) {
                const ccoins* coins = stack.back()->accesscoins(it->first);
                if (coins) {
                    boost_check(*coins == it->second);
                    found_an_entry = true;
                } else {
                    boost_check(it->second.ispruned());
                    missed_an_entry = true;
                }
            }
            boost_foreach(const ccoinsviewcachetest *test, stack) {
                test->selftest();
            }
        }

        if (insecure_rand() % 100 == 0) {
            // every 100 iterations, change the cache stack.
            if (stack.size() > 0 && insecure_rand() % 2 == 0) {
                stack.back()->flush();
                delete stack.back();
                stack.pop_back();
            }
            if (stack.size() == 0 || (stack.size() < 4 && insecure_rand() % 2)) {
                ccoinsview* tip = &base;
                if (stack.size() > 0) {
                    tip = stack.back();
                } else {
                    removed_all_caches = true;
                }
                stack.push_back(new ccoinsviewcachetest(tip));
                if (stack.size() == 4) {
                    reached_4_caches = true;
                }
            }
        }
    }

    // clean up the stack.
    while (stack.size() > 0) {
        delete stack.back();
        stack.pop_back();
    }

    // verify coverage.
    boost_check(removed_all_caches);
    boost_check(reached_4_caches);
    boost_check(added_an_entry);
    boost_check(removed_an_entry);
    boost_check(updated_an_entry);
    boost_check(found_an_entry);
    boost_check(missed_an_entry);
}

boost_auto_test_suite_end()

max_stars_repo_name: dzcoin/DzCoinMiningAlgorithm

max_issues_repo_name: dzcoin/DzCoinMiningAlgorithm

max_forks_repo_name: dzcoin/DzCoinMiningAlgorithm