text:
#include <algorithm>
#include <string>
#include <functional>
#include <ostream>
#include <utility>
#include <vector>

#include <nlohmann/json.hpp>

#include <boost/date_time.hpp>
#include <boost/format.hpp>
#include <boost/optional.hpp>
#include <boost/filesystem.hpp>

#include <glog/logging.h>

#include <ortools/constraint_solver/routing.h>
#include <ortools/constraint_solver/routing_flags.h>
#include <boost/exception/diagnostic_information.hpp>

#include <osrm/match_parameters.hpp>
#include <osrm/nearest_parameters.hpp>
#include <osrm/route_parameters.hpp>
#include <osrm/table_parameters.hpp>
#include <osrm/trip_parameters.hpp>
#include <osrm/coordinate.hpp>
#include <osrm/engine_config.hpp>
#include <osrm/json_container.hpp>
#include <osrm/storage_config.hpp>
#include <osrm/osrm.hpp>
#include <boost/algorithm/string/join.hpp>

#include "util/aplication_error.h"
#include "util/error_code.h"
#include "problem.h"
#include "solution.h"

struct Visit {
    Visit(std::size_t location, const std::string &begin, const std::string &end, const std::string &duration)
            : Visit{location,
                    boost::posix_time::duration_from_string(begin),
                    boost::posix_time::duration_from_string(end),
                    boost::posix_time::duration_from_string(duration)} {}

    Visit(std::size_t location,
          boost::posix_time::time_duration begin,
          boost::posix_time::time_duration end,
          boost::posix_time::time_duration duration)
            : Location{location},
              Begin{std::move(begin)},
              End{std::move(end)},
              Duration{std::move(duration)} {}

    const std::size_t Location;
    const boost::posix_time::time_duration Begin;
    const boost::posix_time::time_duration End;
    const boost::posix_time::time_duration Duration;
};

std::ostream &operator<<(std::ostream &out, const Visit &visit) {
    out << boost::format("%1% [%2%,%3%] %4%")
           % visit.Location
           % visit.Begin
           % visit.End
           % visit.Duration;
    return out;
}

struct Break {
    Break(const std::string &start, const std::string &duration)
            : Break{boost::posix_time::duration_from_string(start),
                    boost::posix_time::duration_from_string(duration)} {}

    Break(boost::posix_time::time_duration start, boost::posix_time::time_duration duration)
            : Start{std::move(start)},
              Duration{std::move(duration)} {}

    const boost::posix_time::time_duration Start;
    const boost::posix_time::time_duration Duration;
};

struct Environment {
    static const std::string TIME_DIM;

    Environment(std::vector<Visit> visits,
                std::vector<std::vector<Break> > breaks,
                std::vector<std::vector<int64> > distances)
            : Depot{0},
              Visits(std::move(visits)),
              Breaks(std::move(breaks)),
              Distances(std::move(distances)) {}

    int64 distance(operations_research::RoutingNodeIndex from_node,
                   operations_research::RoutingNodeIndex to_node) const {
        if (from_node == Depot || to_node == Depot) {
            return 0;
        }

        const auto from = NodeToVisit(from_node).Location;
        const auto to = NodeToVisit(to_node).Location;
        return Distances.at(from).at(to);
    }

    int64 service_plus_distance(operations_research::RoutingNodeIndex from_node,
                                operations_research::RoutingNodeIndex to_node) const {
        if (from_node == Depot) {
            return 0;
        }

        const auto service_time = NodeToVisit(from_node).Duration.total_seconds();
        return service_time + distance(from_node, to_node);
    }

    const Visit &NodeToVisit(operations_research::RoutingNodeIndex node) const {
        return Visits.at(static_cast<std::size_t>(node.value() - 1));
    }

    const operations_research::RoutingNodeIndex Depot;
    const std::vector<Visit> Visits;
    const std::vector<std::vector<Break> > Breaks;
    const std::vector<std::vector<int64> > Distances;
};

const std::string Environment::TIME_DIM{"time"};

rows::Problem LoadReducedProblem(const std::string &problem_path) {
    boost::filesystem::path problem_file(boost::filesystem::canonical(problem_path));
    std::ifstream problem_stream;
    problem_stream.open(problem_file.c_str());
    if (!problem_stream.is_open()) {
        throw util::ApplicationError((boost::format("Failed to open the file: %1%") % problem_file).str(),
                                     util::ErrorCode::ERROR);
    }

    nlohmann::json problem_json;
    try {
        problem_stream >> problem_json;
    } catch (...) {
        throw util::ApplicationError((boost::format("Failed to open the file: %1%") % problem_file).str(),
                                     boost::current_exception_diagnostic_information(),
                                     util::ErrorCode::ERROR);
    }

    rows::Problem problem;
    try {
        rows::Problem::JsonLoader json_loader;
        problem = json_loader.Load(problem_json);
    } catch (const std::domain_error &ex) {
        throw util::ApplicationError(
                (boost::format("Failed to parse the file '%1%' due to error: '%2%'") % problem_file % ex.what()).str(),
                util::ErrorCode::ERROR);
    }

    const auto timespan_pair = problem.Timespan();
    if (timespan_pair.first.date() < timespan_pair.second.date()) {
        LOG(WARNING) << boost::format("Problem '%1%' contains records from several days. " \
                                              "The computed solution will be reduced to a single day: '%2%'")
                        % problem_file
                        % timespan_pair.first.date();
    }

    const auto problem_to_use = problem.Trim(timespan_pair.first, boost::posix_time::hours(24));
    DCHECK(problem_to_use.IsAdmissible());
    return problem_to_use;
}

int main(int argc, char *argv[]) {
    static const auto TIME_WINDOW = boost::posix_time::minutes(30);
    auto problem = LoadReducedProblem("/home/pmateusz/dev/cordia/problem.json");

    std::vector<rows::CalendarVisit> visits_to_schedule;
    std::copy(std::begin(problem.visits()),
              std::begin(problem.visits()) + 50,
              std::back_inserter(visits_to_schedule));

    auto current_index = 0;
    std::unordered_map<rows::Location, std::size_t> location_index;
    std::vector<rows::Location> locations;
    for (const auto &visit : visits_to_schedule) {
        const auto &location = visit.location().get();
        if (location_index.emplace(location, current_index).second) {
            locations.push_back(location);
            ++current_index;
        }
    }

    // initialize visits
    std::vector<Visit> visits;
    for (const auto &visit : visits_to_schedule) {
        const auto location_it = location_index.find(visit.location().get());
        CHECK(location_it != std::end(location_index));

        visits.emplace_back(location_it->second,
                            visit.datetime().time_of_day() - TIME_WINDOW,
                            visit.datetime().time_of_day() + TIME_WINDOW,
                            visit.duration());
    }

    // calculate distance matrix
    std::vector<int64> prototype(locations.size(), 0);
    std::vector<std::vector<int64> > distances(locations.size(), prototype);
    prototype.clear();

    osrm::EngineConfig config;
    config.storage_config = osrm::StorageConfig("/home/pmateusz/dev/cordia/data/scotland-latest.osrm");
    config.use_shared_memory = false;
    config.algorithm = osrm::EngineConfig::Algorithm::MLD;

    const osrm::OSRM engine{config};

    const auto get_distance = [&engine](rows::Location source,
                                        rows::Location destination) -> int64 {
        osrm::RouteParameters params;
        params.coordinates.emplace_back(source.longitude(), source.latitude());
        params.coordinates.emplace_back(destination.longitude(), destination.latitude());

        osrm::json::Object result;
        engine.Route(params, result);
        auto &routes = result.values["routes"].get<osrm::json::Array>();
        auto &route = routes.values.at(0).get<osrm::json::Object>();
        return static_cast<int64>(std::ceil(route.values["duration"].get<osrm::json::Number>().value));
    };

    const auto locations_size = locations.size();
    for (auto from_index = 0; from_index < locations_size; ++from_index) {
        for (auto to_index = 0; to_index < locations_size; ++to_index) {
            distances[from_index][to_index] = get_distance(locations[from_index], locations[to_index]);
        }
    }

    static const auto FIX_CUMULATIVE_TO_ZERO = true;
    static const auto MAX_TIME_SLACK = boost::posix_time::hours(24).total_seconds();
    static const auto CAPACITY = boost::posix_time::hours(24).total_seconds();

    boost::posix_time::ptime min_date_time = boost::posix_time::min_date_time;
    for (const auto &visit : visits_to_schedule) {
        min_date_time = std::min(min_date_time, boost::posix_time::ptime{visit.datetime().date()});
    }

    boost::posix_time::time_period time_horizon(min_date_time,
                                                min_date_time + boost::posix_time::seconds(MAX_TIME_SLACK));

    // initialize breaks
    std::vector<std::vector<Break> > breaks;
    for (const auto &carer_pair : problem.carers()) {
        DCHECK(carer_pair.second.empty() || carer_pair.second.size() == 1);

        std::vector<Break> local_breaks;
        for (const auto &local_break : carer_pair.second.front().Breaks(time_horizon)) {
            local_breaks.emplace_back(local_break.begin().time_of_day(), local_break.duration());
        }
        breaks.emplace_back(std::move(local_breaks));
    }

    const Environment data{visits, breaks, distances};

    operations_research::RoutingIndexManager index_manager(static_cast<int>(data.Visits.size() + 1),
                                                           static_cast<int>(data.Breaks.size()),
                                                           data.Depot);

    operations_research::RoutingModel model(index_manager);

    const auto transit_callback_handle = model.RegisterTransitCallback(
            [&data, &index_manager](int64 from_index, int64 to_index) -> int64 {
                return data.distance(index_manager.IndexToNode(from_index), index_manager.IndexToNode(to_index));
            });

    model.SetArcCostEvaluatorOfAllVehicles(transit_callback_handle);

    const auto service_time_callback_handle = model.RegisterTransitCallback(
            [&data, &index_manager](int64 from_index, int64 to_index) -> int64 {
                return data.service_plus_distance(index_manager.IndexToNode(from_index),
                                                  index_manager.IndexToNode(to_index));
            });
    model.AddDimension(service_time_callback_handle,
                       MAX_TIME_SLACK,
                       CAPACITY,
                       FIX_CUMULATIVE_TO_ZERO,
                       Environment::TIME_DIM);

    auto time_dimension = model.GetMutableDimension(Environment::TIME_DIM);

    for (auto visit_node = data.Depot + 1; visit_node < model.nodes(); ++visit_node) {
        const auto &visit = data.NodeToVisit(visit_node);
        const auto visit_index = index_manager.NodeToIndex(visit_node);

        time_dimension->CumulVar(visit_index)->SetRange(visit.Begin.total_seconds(), visit.End.total_seconds());
        model.AddVariableMinimizedByFinalizer(time_dimension->CumulVar(visit_index));
        model.AddToAssignment(time_dimension->SlackVar(visit_index));

        static const auto DROP_PENALTY = 1000000;
        model.AddDisjunction({visit_index}, DROP_PENALTY);
    }

    for (auto variable_index = 0; variable_index < model.Size(); ++variable_index) {
        model.AddVariableMinimizedByFinalizer(time_dimension->CumulVar(variable_index));
    }

    for (auto vehicle = 0; vehicle < model.vehicles(); ++vehicle) {
        std::vector<operations_research::IntervalVar *> break_intervals;
        auto break_index = 0;
        for (const auto &break_config : data.Breaks[vehicle]) {
            auto interval = model.solver()->MakeFixedInterval(break_config.Start.total_seconds(),
                                                              break_config.Duration.total_seconds(),
                                                              (boost::format("Break %1% of vehicle %2%")
                                                               % break_index
                                                               % vehicle).str());
            break_intervals.emplace_back(interval);
        }

        time_dimension->SetBreakIntervalsOfVehicle(std::move(break_intervals), vehicle, {});
        model.AddVariableMinimizedByFinalizer(time_dimension->CumulVar(model.Start(vehicle)));
        model.AddVariableMinimizedByFinalizer(time_dimension->CumulVar(model.End(vehicle)));
    }

    operations_research::RoutingSearchParameters parameters = operations_research::BuildSearchParametersFromFlags();
    parameters.set_first_solution_strategy(operations_research::FirstSolutionStrategy::PARALLEL_CHEAPEST_INSERTION);
//
//    static const auto USE_ADVANCED_SEARCH = false;
//    parameters.set_use_light_propagation(USE_ADVANCED_SEARCH);
//    parameters.mutable_local_search_operators()->set_use_path_lns(USE_ADVANCED_SEARCH);
//    parameters.mutable_local_search_operators()->set_use_inactive_lns(USE_ADVANCED_SEARCH);

    model.CloseModelWithParameters(parameters);

    const operations_research::Assignment *assignment = model.SolveWithParameters(parameters);

    if (nullptr == assignment) {
        LOG(ERROR) << "No solution found";
        return 1;
    }

    LOG(INFO) << model.solver()->DebugString();

    operations_research::Assignment assignment_check_copy{assignment};
    if (!model.solver()->CheckAssignment(&assignment_check_copy)) {
        LOG(ERROR) << "Solution failed validation checks";
        return 1;
    }

    std::vector<std::tuple<rows::Carer, rows::Diary, Visit, boost::posix_time::time_period, boost::posix_time::time_period> > schedule;
    const auto date = problem.visits().front().datetime().date();
    for (int vehicle = 0; vehicle < model.vehicles(); ++vehicle) {
        auto current_visit_index = model.Start(vehicle);
        const auto &carer_pair = problem.carers().at(static_cast<std::size_t>(vehicle));
        if (!model.IsEnd(assignment->Value(model.NextVar(current_visit_index)))) {
            current_visit_index = assignment->Value(model.NextVar(current_visit_index));
            while (!model.IsEnd(current_visit_index)) {
                const auto visit_node = index_manager.IndexToNode(current_visit_index);
                CHECK_NE(visit_node, data.Depot);

                const auto &visit = data.NodeToVisit(visit_node);
                const boost::posix_time::time_period min_period(
                        boost::posix_time::ptime(date, boost::posix_time::seconds(
                                assignment->Min(time_dimension->CumulVar(current_visit_index)))),
                        visit.Duration);
                const boost::posix_time::time_period max_period(
                        boost::posix_time::ptime(date, boost::posix_time::seconds(
                                assignment->Max(time_dimension->CumulVar(current_visit_index)))),
                        visit.Duration);

                schedule.emplace_back(carer_pair.first, carer_pair.second.front(), visit, min_period, max_period);

                current_visit_index = assignment->Value(model.NextVar(current_visit_index));
            }
        }
    }

    for (const auto &record : schedule) {
        const auto &diary = std::get<1>(record);
        const auto &min_period = std::get<3>(record);
        const auto &max_period = std::get<4>(record);

        for (const auto &event : diary.Breaks(time_horizon)) {
            const auto &event_period = event.period();
            const auto &min_intersection = event_period.intersection(min_period);
            const auto &max_intersection = event_period.intersection(max_period);

            LOG_IF(ERROR, !min_intersection.is_null()) << "Min intersection overlaps with break: " << event_period
                                                       << " intersection: " << min_intersection
                                                       << " carer: " << std::get<0>(record)
                                                       << " visit: " << std::get<2>(record);
            LOG_IF(ERROR, !max_intersection.is_null()) << "Max intersection overlaps with break: " << event_period
                                                       << " intersection: " << min_intersection
                                                       << " carer: " << std::get<0>(record)
                                                       << " visit: " << std::get<2>(record);
        }
    }

    for (const auto visit : data.Visits) {
        LOG(INFO) << boost::format("Visit %1% [%2%,%3%] %4%")
                     % visit.Location
                     % visit.Begin
                     % visit.End
                     % visit.Duration;
    }

    std::unordered_map<rows::Carer, std::size_t> carer_index;
    current_index = 0;
    for (const auto &carer_pair : problem.carers()) {
        CHECK(carer_index.emplace(carer_pair.first, current_index++).second);
    }

    std::unordered_set<rows::Carer> used_carers;
    for (const auto &record: schedule) {
        used_carers.insert(std::get<0>(record));
    }

    for (const auto &local_carer : used_carers) {
        const auto local_carer_index = carer_index[local_carer];
        LOG(INFO) << "Carer: " << local_carer_index << " breaks:";
        for (const auto &local_break : data.Breaks.at(local_carer_index)) {
            LOG(INFO) << boost::format("[%1%, %2%]")
                         % local_break.Start
                         % local_break.Duration;
        }
    }

    LOG(INFO) << "Distance matrix";
    for (const auto &row : data.Distances) {
        std::vector<std::string> text_row;
        std::transform(std::begin(row), std::end(row), std::back_inserter(text_row),
                       [](const int64 distance) -> std::string { return std::to_string(distance); });
        LOG(INFO) << boost::algorithm::join(text_row, ", ");
    }
}

max_stars_repo_name: pmateusz/cordia

max_issues_repo_name: pmateusz/cordia

max_forks_repo_name: pmateusz/cordia


text:
#include "engine/guidance/verbosity_reduction.hpp"
#include "engine/guidance/collapsing_utility.hpp"

#include <boost/assert.hpp>
#include <iterator>

namespace osrm
{
namespace engine
{
namespace guidance
{
std::vector<RouteStep> suppressShortNameSegments(std::vector<RouteStep> steps)
{
    // guard against empty routes, even though they shouldn't happen
    if (steps.empty())
        return steps;

    // we remove only name changes that don't offer additional information
    const auto name_change_without_lanes = [](const RouteStep &step) {
        return hasTurnType(step, TurnType::NewName) && !hasLanes(step);
    };

    // check if the next step is not important enough to announce
    const auto can_be_extended_to = [](const RouteStep &step) {
        const auto is_not_arrive = !hasWaypointType(step);
        const auto is_silent = !hasTurnType(step) || hasTurnType(step, TurnType::Suppressed);

        return is_not_arrive && is_silent;
    };

    const auto suppress = [](RouteStep &from_step, RouteStep &onto_step) {
        from_step.ElongateBy(onto_step);
        onto_step.Invalidate();
    };

    // suppresses name segments that announce already known names or announce a name that will be
    // only available for a very short time
    const auto reduce_verbosity_if_possible = [suppress, can_be_extended_to](
        RouteStepIterator &current_turn_itr, RouteStepIterator &previous_turn_itr) {
        if (haveSameName(*previous_turn_itr, *current_turn_itr))
            suppress(*previous_turn_itr, *current_turn_itr);
        else
        {
            // remember the location of the name change so we can advance the previous turn
            const auto location_of_name_change = current_turn_itr;
            auto distance = current_turn_itr->distance;
            // sum up all distances that can be relevant to the name change
            while (can_be_extended_to(*(current_turn_itr + 1)) &&
                   distance < NAME_SEGMENT_CUTOFF_LENGTH)
            {
                ++current_turn_itr;
                distance += current_turn_itr->distance;
            }

            if (distance < NAME_SEGMENT_CUTOFF_LENGTH)
                suppress(*previous_turn_itr, *current_turn_itr);
            else
                previous_turn_itr = location_of_name_change;
        }
    };

    BOOST_ASSERT(!hasTurnType(steps.back()) && hasWaypointType(steps.back()));
    for (auto previous_turn_itr = steps.begin(), current_turn_itr = std::next(previous_turn_itr);
         !hasWaypointType(*current_turn_itr);
         ++current_turn_itr)
    {
        BOOST_ASSERT(hasTurnType(*current_turn_itr) &&
                     !hasTurnType(*current_turn_itr, TurnType::Suppressed));
        if (name_change_without_lanes(*current_turn_itr) &&
            haveSameMode(*previous_turn_itr, *current_turn_itr))
        {
            // check if the name can be reduced, also sets previous_turn_itr if update is necessary
            reduce_verbosity_if_possible(current_turn_itr, previous_turn_itr);
        }
        else
        {
            // remember the current (non-suppressed) item as a new start of a segment
            previous_turn_itr = current_turn_itr;
        }
    }
    return removeNoTurnInstructions(std::move(steps));
}

// `useLane` steps are only returned on `straight` maneuvers when there
// are surrounding lanes also tagged as `straight`. If there are no other `straight`
// lanes, it is not an ambiguous maneuver, and we can collapse the `useLane` step.
std::vector<RouteStep> collapseUseLane(std::vector<RouteStep> steps)
{
    const auto containsTag = [](const extractor::guidance::TurnLaneType::Mask mask,
                                const extractor::guidance::TurnLaneType::Mask tag) {
        return (mask & tag) != extractor::guidance::TurnLaneType::empty;
    };

    const auto canCollapseUseLane = [containsTag](const RouteStep &step) {
        // the lane description is given left to right, lanes are counted from the right.
        // Therefore we access the lane description using the reverse iterator

        auto right_most_lanes = step.LanesToTheRight();
        if (!right_most_lanes.empty() && containsTag(right_most_lanes.front(),
                                                     (extractor::guidance::TurnLaneType::straight |
                                                      extractor::guidance::TurnLaneType::none)))
            return false;

        auto left_most_lanes = step.LanesToTheLeft();
        if (!left_most_lanes.empty() && containsTag(left_most_lanes.back(),
                                                    (extractor::guidance::TurnLaneType::straight |
                                                     extractor::guidance::TurnLaneType::none)))
            return false;

        return true;
    };

    BOOST_ASSERT(steps.size() > 1);
    for (auto step_itr = steps.begin() + 1; step_itr != steps.end(); ++step_itr)
    {
        if (step_itr->maneuver.instruction.type == TurnType::UseLane &&
            canCollapseUseLane(*step_itr))
        {
            auto previous_turn_itr = findPreviousTurn(step_itr);
            if (haveSameMode(*previous_turn_itr, *step_itr))
            {
                previous_turn_itr->ElongateBy(*step_itr);
                step_itr->Invalidate();
            }
        }
    }
    return removeNoTurnInstructions(std::move(steps));
}

} // namespace guidance
} // namespace engine
} // namespace osrm

ext: cpp

max_stars_repo_name: mbeckem/msc

max_issues_repo_name: mbeckem/msc

max_forks_repo_name: mbeckem/msc


text:
/* Copyright (c) AIRBUS and its affiliates.
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
#ifndef SKDECIDE_BFWS_HH
#define SKDECIDE_BFWS_HH

// From paper: Best-First Width Search: Exploration and Exploitation in
// Classical Planning
//             by Nir Lipovetsky and Hector Geffner
//             in proceedings of AAAI 2017

#include <functional>
#include <memory>
#include <unordered_set>
#include <queue>
#include <list>
#include <chrono>

#include <boost/container_hash/hash.hpp>

#include "utils/associative_container_deducer.hh"
#include "utils/execution.hh"

namespace skdecide {

/** Use default hasher provided with domain's states */
template <typename Tdomain, typename Tfeature_vector> struct DomainStateHash {
  typedef typename Tdomain::State Key;

  template <typename Tnode> static const Key &get_key(const Tnode &n);

  struct Hash {
    std::size_t operator()(const Key &k) const;
  };

  struct Equal {
    bool operator()(const Key &k1, const Key &k2) const;
  };
};

/** Use state binary feature vector to hash states */
template <typename Tdomain, typename Tfeature_vector> struct StateFeatureHash {
  typedef Tfeature_vector Key;

  template <typename Tnode> static const Key &get_key(const Tnode &n);

  struct Hash {
    std::size_t operator()(const Key &k) const;
  };

  struct Equal {
    bool operator()(const Key &k1, const Key &k2) const;
  };
};

template <typename Tdomain, typename Tfeature_vector,
          template <typename...> class Thashing_policy = DomainStateHash,
          typename Texecution_policy = SequentialExecution>
class BFWSSolver {
public:
  typedef Tdomain Domain;
  typedef typename Domain::State State;
  typedef typename Domain::Action Action;
  typedef typename Domain::Value Value;
  typedef Tfeature_vector FeatureVector;
  typedef Thashing_policy<Domain, FeatureVector> HashingPolicy;
  typedef Texecution_policy ExecutionPolicy;

  BFWSSolver(
      Domain &domain,
      const std::function<std::unique_ptr<FeatureVector>(
          Domain &d, const State &s)> &state_features,
      const std::function<Value(Domain &, const State &)> &heuristic,
      const std::function<bool(Domain &, const State &)> &termination_checker,
      bool debug_logs = false);

  // clears the solver (clears the search graph, thus preventing from reusing
  // previous search results)
  void clear();

  // solves from state s
  void solve(const State &s);

  bool is_solution_defined_for(const State &s) const;
  const Action &get_best_action(const State &s) const;
  const double &get_best_value(const State &s) const;

private:
  Domain &_domain;
  std::function<std::unique_ptr<FeatureVector>(Domain &d, const State &s)>
      _state_features;
  std::function<Value(Domain &, const State &)> _heuristic;
  std::function<bool(Domain &, const State &)> _termination_checker;
  bool _debug_logs;
  ExecutionPolicy _execution_policy;

  typedef std::pair<std::size_t, typename FeatureVector::value_type> PairType;
  typedef std::unordered_map<
      double, std::unordered_set<PairType, boost::hash<PairType>>>
      PairMap;

  struct Node {
    State state;
    std::unique_ptr<FeatureVector> features;
    std::tuple<Node *, Action, double> best_parent;
    std::size_t novelty;
    double heuristic;
    double gscore;
    double fscore;
    Action *best_action; // computed only when constructing the solution path
                         // backward from the goal state
    bool solved; // set to true if on the solution path constructed backward
                 // from the goal state

    Node(const State &s, Domain &d,
         const std::function<std::unique_ptr<FeatureVector>(
             Domain &d, const State &s)> &state_features);

    struct Key {
      const typename HashingPolicy::Key &operator()(const Node &n) const;
    };
  };

  // we only compute novelty of 1 for complexity reasons and assign all other
  // novelties to +infty see paper "Best-First Width Search: Exploration and
  // Exploitation in Classical Planning" by Lipovetsky and Geffner
  std::size_t novelty(PairMap &heuristic_features_map,
                      const double &heuristic_value, Node &n) const;

  struct NodeCompare {
    bool operator()(Node *&a, Node *&b) const;
  };

  typedef typename SetTypeDeducer<Node, HashingPolicy>::Set Graph;
  Graph _graph;
};

} // namespace skdecide

#endif // SKDECIDE_BFWS_HH

ext: hh

max_stars_repo_name: emilienDespres/scikit-decide

max_issues_repo_name: emilienDespres/scikit-decide

max_forks_repo_name: emilienDespres/scikit-decide


text:
#include "TargetVelPathPlanner.hpp"
#include <Configuration.hpp>
#include <boost/range/irange.hpp>
#include <cmath>
#include "EscapeObstaclesPathPlanner.hpp"
#include "TrapezoidalPath.hpp"

using namespace std;
using namespace Geometry2d;

namespace Planning {

REGISTER_CONFIGURABLE(TargetVelPathPlanner);

ConfigDouble* TargetVelPathPlanner::_targetVelChangeReplanThreshold;

void TargetVelPathPlanner::createConfiguration(Configuration* cfg) {
    _targetVelChangeReplanThreshold = new ConfigDouble(
        cfg, "TargetVelPathPlanner/velChangeReplanThreshold", 0.05,
        "If the target velocity changes by this much (in m/s), the planner is "
        "rerun.  Otherwise the previous path may be kept.");
}

Point TargetVelPathPlanner::calculateNonblockedPathEndpoint(
    Point start, Point dir, const ShapeSet& obstacles) const {
    dir = dir.normalized();

    // TODO(justbuchanan): handle dynamic obstacles (robots)

    float minDist = 0;
    // @maxDist is the diagonal distance across the floor - no robot can travel
    // a straightline distance further than this
    float maxDist =
        sqrtf(powf(Field_Dimensions::Current_Dimensions.FloorLength(), 2) +
              powf(Field_Dimensions::Current_Dimensions.FloorWidth(), 2));

    // We iteratively test different distances from the current point in the
    // direction of the target velocity.  We choose the furthest point away that
    // is non-blocked.  Searching for the furthest non-blocked distance is done
    // through binary search using std::loser_bound.  We use boost ranges to
    // represent a numeric range.  It only works with integers, so we prescale
    // by 100, giving us cm accuracy with the result.
    constexpr float rangeScaleFactor = 100;
    const auto scaledDistRange = boost::irange(
        (int)(minDist * rangeScaleFactor), (int)(maxDist * rangeScaleFactor));
    auto val = std::lower_bound(
        scaledDistRange.begin(), scaledDistRange.end(), obstacles,
        [start, dir, rangeScaleFactor](int scaledDist,
                                       const ShapeSet& obstacles) {
            Segment pathSegment(start,
                                start + dir * (scaledDist / rangeScaleFactor));
            // Returns true if a path of the given distance doesn't hit
            // obstacles
            return !obstacles.hit(pathSegment);
        });
    const float nonblockedPathLen = *val / rangeScaleFactor;

    return start + dir * nonblockedPathLen;
}

bool TargetVelPathPlanner::shouldReplan(const PlanRequest& planRequest) const {
    const Path* prevPath = planRequest.prevPath.get();
    const ShapeSet& obstacles = planRequest.obstacles;

    const WorldVelTargetCommand& command =
        static_cast<const WorldVelTargetCommand&>(*planRequest.motionCommand);

    if (SingleRobotPathPlanner::shouldReplan(planRequest)) return true;

    // See if obstacles have changed such that the end point is significantly
    // different
    const Point newEndpoint = calculateNonblockedPathEndpoint(
        prevPath->start().motion.pos, command.worldVel, obstacles);
    const float endChange = (newEndpoint - prevPath->end().motion.pos).mag();
    if (endChange > SingleRobotPathPlanner::goalChangeThreshold()) {
        return true;
    }

    // Replan if the maxSpeed of the previous path differs too much from the
    // command velocity

    if (auto trapezoidalPath = dynamic_cast<const TrapezoidalPath*>(prevPath)) {
        const float velChange =
            command.worldVel.mag() - trapezoidalPath->maxSpeed();
        if (velChange > *_targetVelChangeReplanThreshold) {
            return true;
        }
        return false;
    } else {
        throw std::runtime_error(
            "TargetVelPathPlanner expected a prevPath of type "
            "'TrapezoidalPath'");
    }
}

// TODO(justbuchanan): Paths aren't dynamically feasible sometimes because it
// doesn't account for initial velocity
std::unique_ptr<Path> TargetVelPathPlanner::run(PlanRequest& planRequest) {
    const MotionInstant& startInstant = planRequest.start;
    const MotionCommand& cmd = *planRequest.motionCommand;
    const auto& motionConstraints = planRequest.constraints.mot;
    const Geometry2d::ShapeSet& obstacles = planRequest.obstacles;
    std::unique_ptr<Path>& prevPath = planRequest.prevPath;

    // If the start point is in an obstacle, escape from it
    if (obstacles.hit(startInstant.pos)) {
        EscapeObstaclesPathPlanner escapePlanner;
        EmptyCommand emptyCommand;
        return escapePlanner.run(planRequest);
    }

    const WorldVelTargetCommand& command =
        static_cast<const WorldVelTargetCommand&>(cmd);

    if (shouldReplan(planRequest)) {
        // Choose the furthest endpoint we can that doesn't hit obstacles
        Point endpoint = calculateNonblockedPathEndpoint(
            startInstant.pos, command.worldVel, obstacles);
        MotionConstraints moddedConstraints = motionConstraints;
        moddedConstraints.maxSpeed = command.worldVel.mag();

        // Make a path from the start point in the direction of the target vel
        // that ends at the calculated endpoint
        auto path = std::unique_ptr<Path>(
            new TrapezoidalPath(startInstant.pos, startInstant.vel.mag(),
                                endpoint, 0, moddedConstraints));
        path->setStartTime(RJ::now());
        return std::move(path);
    } else {
        return std::move(prevPath);
    }
}

}  // namespace Planning


text: #include <boost/geometry/core/tag.hpp>

ext: hpp

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
/*
 * ip_address.hpp
 *
 *  Created on: Sep 2, 2015
 *      Author: zmij
 */

#ifndef LIB_PG_ASYNC_INCLUDE_TIP_DB_PG_IO_IP_ADDRESS_HPP_
#define LIB_PG_ASYNC_INCLUDE_TIP_DB_PG_IO_IP_ADDRESS_HPP_

#include <tip/db/pg/protocol_io_traits.hpp>
#include <tip/db/pg/asio_config.hpp>

#ifdef WITH_BOOST_ASIO
#include <boost/asio/ip/address.hpp>
#else
#include <asio/ip/address.hpp>
#endif

namespace tip {
namespace db {
namespace pg {
namespace io {

template < >
struct protocol_parser< ASIO_NAMESPACE::ip::address, TEXT_DATA_FORMAT > :
		detail::parser_base< ASIO_NAMESPACE::ip::address > {
	typedef detail::parser_base< ASIO_NAMESPACE::ip::address > base_type;
	typedef base_type::value_type value_type;

	protocol_parser(value_type& v) : base_type(v) {}

	size_t
	size() const
	{
		return base_type::value.to_string().size();
	}

	template < typename InputIterator >
	InputIterator
	operator()(InputIterator begin, InputIterator end)
	{
		typedef InputIterator iterator_type;
		typedef std::iterator_traits< iterator_type > iter_traits;
		typedef typename iter_traits::value_type iter_value_type;
		static_assert(std::is_same< iter_value_type, byte >::type::value,
				"Input iterator must be over a char container");
		std::string s(begin, end);
		asio_config::error_code ec;
		value_type tmp = value_type::from_string(s, ec);
		if (!ec) {
			base_type::value = tmp;
			return end;
		}
		return begin;
	}
};

namespace traits {

template < >
struct has_parser< ASIO_NAMESPACE::ip::address, TEXT_DATA_FORMAT > : std::true_type {};
//@{
template < >
struct pgcpp_data_mapping< oids::type::inet > :
		detail::data_mapping_base< oids::type::inet, boost::asio::ip::address > {};
template < >
struct cpppg_data_mapping< boost::asio::ip::address > :
		detail::data_mapping_base< oids::type::inet, boost::asio::ip::address > {};
//@}

}  // namespace traits

}  // namespace io
}  // namespace pg
}  // namespace db
}  // namespace tip

#endif /* LIB_PG_ASYNC_INCLUDE_TIP_DB_PG_IO_IP_ADDRESS_HPP_ */


text:
/*
 * Copyright (c) 2018, Sunanda Bose (Neel Basu) (neel.basu.z@gmail.com)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */

#include "tash/connection.h"
#include "tash/query.h"
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/asio/buffer.hpp>
#include <basen.hpp>

namespace http = boost::beast::http;

tash::connection::connection(const std::string& db, std::string host, unsigned int port, std::string user, std::string pass): _host(host), _port(port), _user(user), _pass(pass), _db(db), _resolver(_io){

}

tash::http_request_type tash::connection::url(boost::beast::http::verb method, std::string path) const{
    std::string b64_encoded_credentials;
    boost::trim_left_if(path, boost::is_any_of("/ "));
    tash::http_request_type request(method, "/"+path, 10);
    std::string credentials = (boost::format("%1%:%2%") % _user % _pass).str();
    bn::encode_b64(credentials.begin(), credentials.end(), back_inserter(b64_encoded_credentials));
    request.set(boost::beast::http::field::authorization, "Basic " + b64_encoded_credentials);
    return request;
}

tash::http_request_type tash::connection::db_url(boost::beast::http::verb method, std::string path) const{
    boost::trim_left_if(path, boost::is_any_of("/ "));
    return url(method, (boost::format("/_db/%1%/%2%") % _db % path).str());
}

tash::http_response_type tash::connection::query(const tash::http_request_type& request){
    boost::mutex::scoped_lock lock(_mutex);
    auto const results = _resolver.resolve(_host, boost::lexical_cast<std::string>(_port));
    boost::asio::ip::tcp::socket socket(_io);
    boost::asio::connect(socket, results.begin(), results.end());
    boost::beast::http::write(socket, request);
    boost::beast::flat_buffer buffer;
    tash::http_response_type res;
    boost::beast::http::read(socket, buffer, res);
    return res;
}

tash::http_response_type tash::connection::query(std::string path, boost::beast::http::verb method){
    tash::http_request_type request;
    if(boost::algorithm::starts_with(path, "/")){
        request = url(method, path);
    }else{
        request = db_url(method, path);
    }
    return query(request);
}

tash::http_response_type tash::connection::query(std::string path, const std::string& content, std::string type, boost::beast::http::verb method){
    tash::http_request_type request;
    if(boost::algorithm::starts_with(path, "/")){
        request = url(method, path);
    }else{
        request = db_url(method, path);
    }
    request.set(boost::beast::http::field::content_type, type);
    request.set(boost::beast::http::field::content_length, content.size());
    request.body() = content;
    return query(request);
}

tash::cursor tash::connection::aql(const std::string& q, int count, int batch){
    nlohmann::json document{
        {"query", q}
    };
    if(count != 0){
        document["count"] = count;
    }
    if(batch != 0){
        document["batchSize"] = batch;
    }
    tash::http_response_type response = query("_api/cursor", document.dump(), "application/json", boost::beast::http::verb::post);
    if(response.result() == http::status::ok || response.result() == http::status::accepted || response.result() == http::status::created){/* No Operation */}
    else{
        std::cout << "AQL Failed: " << q << std::endl;
        std::cout << "result: " << response.result() << std::endl;
        std::cout << response << std::endl;
    }
    tash::cursor cursor(*this);
    cursor.attach(response);
    return cursor;
}

boost::beast::http::status tash::connection::exists() {
    return query("_api/version").result();
}

tash::cursor::cursor(tash::connection& conn, const std::string& id): _conn(conn), _id(id){}
tash::cursor::cursor(tash::connection& conn): _conn(conn), _id(std::string()){}
tash::cursor::cursor(const tash::cursor& other): _conn(other._conn), _id(other._id), _has_more(other._has_more), _error(other._error), _count(other._count), _code(other._code), _results(other._results){}
tash::cursor::~cursor(){
     boost::mutex::scoped_lock lock(_mutex);
}

nlohmann::json tash::cursor::results() const{
    boost::mutex::scoped_lock lock(_mutex);
    return _results;
}

void tash::cursor::fetch(){
    // https://github.com/boostorg/beast/issues/819
    tash::http_response_type response = _conn.query("_api/cursor/"+_id, "", "application/json", boost::beast::http::verb::put);
    attach(response);
}

void tash::cursor::attach(const tash::http_response_type& response){
    boost::mutex::scoped_lock lock(_mutex);
    nlohmann::json json = nlohmann::json::parse(boost::beast::buffers_to_string(response.body().data()));
    _has_more = json.value("hasMore", false);
    _error    = json.value("error",   false);
    _count    = json.value("count",   0);
    _code     = json.value("code",    0);
    _results  = json["result"];
    if(_id.empty()){
        _id = json.value("id", std::string());
    }
}

tash::shell::shell(const std::string& db, std::string host, unsigned int port, std::string user, std::string pass): connection(db, host, port, user, pass){}
tash::shell& tash::shell::operator>>(nlohmann::json& res){
    res = results();
    return *this;
}

tash::collection::collection(tash::connection& conn, const std::string& name, type t): _conn(conn), _name(name), _type(t){}

boost::beast::http::status tash::connection::create(){
    nlohmann::json document = {
        {"name", _db}
    };
    tash::http_response_type response = query("/_api/database", document.dump());
    return response.result();
}

boost::beast::http::status tash::collection::exists(){
    tash::http_response_type response = _conn.query("_api/collection/"+_name);
    return response.result();
}

boost::beast::http::status tash::collection::create(){
    nlohmann::json document = {
        {"name", _name},
        {"type", _type}
    };
    tash::http_response_type response = _conn.query("_api/collection", document.dump());
    return response.result();
}

boost::beast::http::status tash::collection::add(const nlohmann::json& document){
    tash::http_response_type response = _conn.query("_api/document/"+_name, document.dump());
    return response.result();
}

boost::beast::http::status tash::collection::add(nlohmann::json& document){
    tash::http_response_type response = _conn.query("_api/document/"+_name, document.dump());
    nlohmann::json json = nlohmann::json::parse(boost::beast::buffers_to_string(response.body().data()));
    document = json;
    return response.result();
}

tash::http_response_type tash::collection::update(const std::string key, const nlohmann::json& document){
    return _conn.query((boost::format("_api/document/%1%/%2%") % _name % key).str(), document.dump(), "application/json", boost::beast::http::verb::patch);
}

tash::http_response_type tash::collection::replace(const std::string key, const nlohmann::json& document){
    return _conn.query((boost::format("_api/document/%1%/%2%") % _name % key).str(), document.dump(), "application/json", boost::beast::http::verb::put);
}

tash::http_response_type tash::collection::read(const std::string key){
    return _conn.query((boost::format("_api/document/%1%/%2%") % _name % key).str());
}

tash::http_response_type tash::collection::read(int limit, int skip){
    nlohmann::json document{
        {"collection", _name}
    };
    if(limit != 0){
        document["limit"] = limit;
    }
    if(skip != 0){
        document["skip"] = skip;
    }
    return _conn.query("_api/simple/all", document.dump(), "application/json", boost::beast::http::verb::put);
}

boost::beast::http::status tash::edge::add(const std::string& from, const std::string& to, nlohmann::json& document){
    document["_from"] = from;
    document["_to"]   = to;
    return tash::collection::add(document);
}

boost::beast::http::status tash::edge::add(const std::string& from, const std::string& to, const nlohmann::json& document){
    nlohmann::json request(document);
    request["_from"] = from;
    request["_to"]   = to;
    return tash::collection::add(request);
}

boost::beast::http::status tash::edge::add(const std::string& from, const std::string& to){
    return add(from, to, nlohmann::json());
}

nlohmann::json tash::collection::by_id(const std::string& id){
    tash::http_response_type response = _conn.query("_api/document/"+id);
    if(response.result() == boost::beast::http::status::ok){
        nlohmann::json json = nlohmann::json::parse(boost::beast::buffers_to_string(response.body().data()));
        return json;
    }
    return nlohmann::json(nullptr);
}

nlohmann::json tash::collection::by_key(const std::string& key){
    return by_id((boost::format("%1%/%2%") % _name % key).str());
}

max_stars_repo_name: neel/tash

max_issues_repo_name: neel/tash

max_forks_repo_name: neel/tash


text:
#include <iostream>
#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
#include "serialize.h"
#include "txdb.h"
#include "account.h"
#include "main.h"
using namespace std;

#define CHAIN_HEIGHT (nMaxCoinDay/nTargetSpacing)+10
#define VECTOR_SIZE 1000
#define random(x) (rand()%x)
vector<uint256> g_vHash[5];
class CFindIterByHash {
public:
	CFindIterByHash(uint256 hash) {
		m_hash = hash;
	}
	bool operator()(const CFund& fund) {
		return fund.uTxHash == m_hash;
	}

private:
	uint256 m_hash;

};

void GenerateRandomHash(vector<uint256>& vHash, uint64_t nSize = VECTOR_SIZE) {
	vHash.reserve(nSize);
	vector<unsigned char> vRandom;
	vRandom.reserve(32);

	//generate key hash
	for (int i = 0; i < nSize; i++) {
		CKey key;
		key.MakeNewKey(false);
		string str(key.begin(), key.end());
		vRandom.clear();
		vRandom.insert(vRandom.begin(), key.begin(), key.end());
		uint256 hash(vRandom);
		vHash.push_back(hash);
		//cout << hash.GetHex() << endl;
	}
}

void Init(CBlockIndex* pBlockIndex, CSecureAccount& account) {
	srand((unsigned) time(NULL));
	account.llValues = 100;
	pBlockIndex->nHeight = CHAIN_HEIGHT;
	chainActive.SetTip(pBlockIndex);
	BOOST_CHECK(NULL != chainActive.Tip());

	for (int i = 0; i < 5; i++) {
		GenerateRandomHash(g_vHash[i]);
	}

	for (int i = 0; i < VECTOR_SIZE; i++) {
		account.vRewardFund.push_back(CFund(REWARD_FUND, g_vHash[0].at(i), random(10), random(20)));
	}

	for (int i = 0; i < VECTOR_SIZE; i++) {
		account.vFreedomFund.push_back(CFund(FREEDOM_FUND, g_vHash[1].at(i), random(5), random(20)));
	}

	for (int i = 0; i < VECTOR_SIZE; i++) {
		account.vInputFreeze.push_back(
				CFund(INPUT_FREEZD_FUND, g_vHash[2].at(i), random(10), CHAIN_HEIGHT - 10 + random(30)));
	}

	for (int i = 0; i < VECTOR_SIZE; i++) {
		account.vOutputFreeze.push_back(
				CFund(OUTPUT_FREEZD_FUND, g_vHash[3].at(i), random(10), CHAIN_HEIGHT - 10 + random(30)));
	}

	for (int i = 0; i < VECTOR_SIZE; i++) {
		account.vSelfFreeze.push_back(
				CFund(SELF_FREEZD_FUND, g_vHash[4].at(i), random(10), CHAIN_HEIGHT - 10 + random(30)));
	}
}

bool IsEqual(const vector<CFund>& vSrc, const vector<CFund>& vDest) {
	if (vSrc.size() != vDest.size()) {
		return false;
	}

	for (vector<CFund>::const_iterator it = vDest.begin(); it != vDest.end(); it++) {
		if (vSrc.end() == find(vSrc.begin(), vSrc.end(), *it)) {
			return false;
		}
	}

	return true;
}
struct CTxTest {
	CBlockIndex block;
	CSecureAccount accOperate;
	CSecureAccount accBeforOperate;

	CTxTest() {
		::Init(&block, accOperate);
		accBeforOperate = accOperate;
	}

	void CheckAccountEqual() {
		BOOST_CHECK(IsEqual(accBeforOperate.vRewardFund, accOperate.vRewardFund));
		BOOST_CHECK(IsEqual(accBeforOperate.vFreedomFund, accOperate.vFreedomFund));
		BOOST_CHECK(IsEqual(accBeforOperate.vInputFreeze, accOperate.vInputFreeze));
		BOOST_CHECK(IsEqual(accBeforOperate.vOutputFreeze, accOperate.vOutputFreeze));
		BOOST_CHECK(IsEqual(accBeforOperate.vSelfFreeze, accOperate.vSelfFreeze));
		BOOST_CHECK(accBeforOperate.llValues == accOperate.llValues);
	}

	uint64_t GetTotalValue(const vector<CFund>& vFund) {
		uint64_t nSum = 0;
		for (vector<CFund>::const_iterator it = vFund.begin(); it != vFund.end(); it++) {
			nSum += it->value;
		}

		return nSum;
	}

	void FillSpecificAndRandData(vector<uint256>& vHashCopy, vector<CFund>& vSpecificFund) {
		for (vector<CFund>::iterator it = vSpecificFund.begin(); it != vSpecificFund.end(); it++) {
			vHashCopy.push_back(it->uTxHash);
		}

		//insert 100 data that not in the specific vector
		vector<uint256> vRandomHash;
		GenerateRandomHash(vRandomHash, VECTOR_SIZE / 10);
		vHashCopy.insert(vHashCopy.end(), vRandomHash.begin(), vRandomHash.end());
		random_shuffle(vHashCopy.begin(), vHashCopy.end());
	}

	void CheckInOut(OperType emType) {
		BOOST_CHECK(emType == MINUS_OUTPUT || emType == MINUS_INPUT);
		accOperate.CompactAccount(CHAIN_HEIGHT);

		vector<CFund>& vFund = emType == MINUS_OUTPUT ? accOperate.vOutputFreeze : accOperate.vInputFreeze;
		vector<uint256> vHashCopy;
		FillSpecificAndRandData(vHashCopy, vFund);

		//start test random data
		int nExecBranchCount[3] = { 0 };
		uint64_t nOperaeValue = 0;
		int nCount = 0;
		for (vector<uint256>::iterator it = vHashCopy.begin(); it != vHashCopy.end(); it++) {
			nOperaeValue = 0;
			uint64_t nRandomValue = random(10);
			CFund fund(OUTPUT_FREEZD_FUND, *it, nRandomValue, random(20));
			vector<CFund>::iterator iter = find_if(vFund.begin(), vFund.end(), CFindIterByHash(*it));

			if (vFund.end() == iter) {
				//can't find the specific fund by *it,so operatreAccount should return false
				BOOST_CHECK(!accOperate.OperateAccount(emType, fund, &nOperaeValue));
				nExecBranchCount[0]++;
				continue;
			}

			uint64_t nOldVectorValue = GetTotalValue(vFund);
			uint64_t nOldIterValue = iter->value;
			if (nRandomValue > iter->value) {
				BOOST_CHECK(!accOperate.OperateAccount(emType, fund, &nOperaeValue));
				BOOST_CHECK(GetTotalValue(vFund) + nOldIterValue == nOldVectorValue);
				BOOST_CHECK(nOldIterValue == nOperaeValue);
				nExecBranchCount[1]++;
			} else {
				BOOST_CHECK(accOperate.OperateAccount(emType, fund, &nOperaeValue));
				BOOST_CHECK(GetTotalValue(vFund) + nRandomValue == nOldVectorValue);
				BOOST_CHECK(nRandomValue == nOperaeValue);
				nExecBranchCount[2]++;
			}
		}

		for (int i = 0; i < sizeof(nExecBranchCount) / sizeof(nExecBranchCount[0]); i++) {
			//cout << "execute branch " << i << " times is " << nExecBranchCount[i] << endl;
		}
		accOperate.UndoOperateAccount(accOperate.accountOperLog);
		CheckAccountEqual();
	}

	void CheckInOutFree(OperType emType) {
		BOOST_CHECK(emType == MINUS_OUTPUT_OR_FREE || emType == MINUS_INPUT_OR_FREE);
		accOperate.CompactAccount(CHAIN_HEIGHT);

		vector<CFund>& vFund = emType == MINUS_OUTPUT_OR_FREE ? accOperate.vOutputFreeze : accOperate.vInputFreeze;
		vector<uint256> vHashCopy;
		FillSpecificAndRandData(vHashCopy, vFund);

		int nExecBranchCount[4] = { 0 };
		uint64_t nOperaeValue = 0;
		int nCount = 0;
		for (vector<uint256>::iterator it = vHashCopy.begin(); it != vHashCopy.end(); it++) {
			nOperaeValue = 0;
			uint64_t nRandomValue = random(200);
			CFund fund(OUTPUT_FREEZD_FUND, *it, nRandomValue, random(20));
			vector<CFund>::iterator iter = find_if(vFund.begin(), vFund.end(), CFindIterByHash(*it));

			if (vFund.end() == iter) {
				//can't find the specific fund by *it,so operatreAccount should return false
				BOOST_CHECK(!accOperate.OperateAccount(emType, fund, &nOperaeValue));
				nExecBranchCount[0]++;
				continue;
			}

			uint64_t nOldVectorValue = GetTotalValue(vFund);
			uint64_t nOldIterValue = iter->value;
			if (iter->value >= nRandomValue) {
				BOOST_CHECK(accOperate.OperateAccount(emType, fund, &nOperaeValue));
				BOOST_CHECK(GetTotalValue(vFund) + nRandomValue == nOldVectorValue);
				BOOST_CHECK(nRandomValue == nOperaeValue);
				nExecBranchCount[1]++;
			} else {
				uint64_t nOldFree = GetTotalValue(accOperate.vFreedomFund) + accOperate.llValues;
				if (iter->value + nOldFree >= nRandomValue) {
					BOOST_CHECK(accOperate.OperateAccount(emType, fund, &nOperaeValue));
					BOOST_CHECK(
							nOldVectorValue + nOldFree - nRandomValue
									== GetTotalValue(accOperate.vFreedomFund) + accOperate.llValues
											+ GetTotalValue(vFund));
					BOOST_CHECK(nRandomValue == nOperaeValue);
					nExecBranchCount[2]++;
				} else {
					BOOST_CHECK(!accOperate.OperateAccount(emType, fund, &nOperaeValue));
					BOOST_CHECK(!GetTotalValue(accOperate.vFreedomFund) && !accOperate.llValues);
					BOOST_CHECK(nOldVectorValue + nOldFree - nOperaeValue == GetTotalValue(vFund));
					nExecBranchCount[3]++;
				}
			}
		}

		for (int i = 0; i < sizeof(nExecBranchCount) / sizeof(nExecBranchCount[0]); i++) {
			//cout << "execute branch " << i << " times is " << nExecBranchCount[i] << endl;
		}
		accOperate.UndoOperateAccount(accOperate.accountOperLog);
		CheckAccountEqual();
	}

	void CheckInOutFreeSelf(OperType emType) {
		BOOST_CHECK(emType == MINUS_OUTPUT_OR_FREE_OR_SELF || emType == MINUS_INPUT_OR_FREE_OR_SELF);
		accOperate.CompactAccount(CHAIN_HEIGHT);

		vector<CFund>& vFund =
				emType == MINUS_OUTPUT_OR_FREE_OR_SELF ? accOperate.vOutputFreeze : accOperate.vInputFreeze;
		vector<uint256> vHashCopy;
		FillSpecificAndRandData(vHashCopy, vFund);

		int nExecBranchCount[5] = { 0 };
		uint64_t nOperaeValue = 0;
		int nCount = 0;
		for (vector<uint256>::iterator it = vHashCopy.begin(); it != vHashCopy.end(); it++) {
			nOperaeValue = 0;
			uint64_t nRandomValue = random(70);
			CFund fund(OUTPUT_FREEZD_FUND, *it, nRandomValue, random(20));
			vector<CFund>::iterator iter = find_if(vFund.begin(), vFund.end(), CFindIterByHash(*it));

			if (vFund.end() == iter) {
				//can't find the specific fund by *it,so operatreAccount should return false
				BOOST_CHECK(!accOperate.OperateAccount(emType, fund, &nOperaeValue));
				nExecBranchCount[0]++;
				continue;
			}

			uint64_t nOldVectorValue = GetTotalValue(vFund);
			uint64_t nIterValue = iter->value;
			if (nIterValue >= nRandomValue) {
				BOOST_CHECK(accOperate.OperateAccount(emType, fund, &nOperaeValue));
				BOOST_CHECK(GetTotalValue(vFund) + nRandomValue == nOldVectorValue);
				BOOST_CHECK(nRandomValue == nOperaeValue);
				nExecBranchCount[1]++;
			} else {
				uint64_t nOldTotalFree = GetTotalValue(accOperate.vFreedomFund) + accOperate.llValues;
				if (nIterValue + nOldTotalFree >= nRandomValue) {
					BOOST_CHECK(accOperate.OperateAccount(emType, fund, &nOperaeValue));
					BOOST_CHECK(
							nOldVectorValue + nOldTotalFree - nRandomValue
									== GetTotalValue(accOperate.vFreedomFund) + accOperate.llValues
											+ GetTotalValue(vFund));
					BOOST_CHECK(nRandomValue == nOperaeValue);
					nExecBranchCount[2]++;
				} else {
					uint64_t nOldSelfValue = GetTotalValue(accOperate.vSelfFreeze);
					if (nIterValue + nOldTotalFree + nOldSelfValue >= nRandomValue) {
						BOOST_CHECK(accOperate.OperateAccount(emType, fund, &nOperaeValue));
						uint64_t nSum = GetTotalValue(vFund) + accOperate.llValues
								+ GetTotalValue(accOperate.vFreedomFund) + GetTotalValue(accOperate.vSelfFreeze);
						BOOST_CHECK(nOldVectorValue + nOldTotalFree + nOldSelfValue - nRandomValue == nSum);
						BOOST_CHECK(nOperaeValue == nRandomValue);
						nExecBranchCount[3]++;
					} else {
						BOOST_CHECK(!accOperate.OperateAccount(emType, fund, &nOperaeValue));
						BOOST_CHECK(!GetTotalValue(accOperate.vFreedomFund) && !accOperate.llValues);
						BOOST_CHECK(!GetTotalValue(accOperate.vSelfFreeze));

						BOOST_CHECK(
								nOldVectorValue + nOldTotalFree + nOldSelfValue - nOperaeValue == GetTotalValue(vFund));
						nExecBranchCount[4]++;
					}
				}
			}
		}

		for (int i = 0; i < sizeof(nExecBranchCount) / sizeof(nExecBranchCount[0]); i++) {
			//cout<<"execute branch "<<i<<" times is "<<nExecBranchCount[i]<<endl;
		}

		accOperate.UndoOperateAccount(accOperate.accountOperLog);
		CheckAccountEqual();
	}

	void CheckFreeSelf() {

	}
};

BOOST_FIXTURE_TEST_SUITE(tx_tests,CTxTest)

#if 0

BOOST_FIXTURE_TEST_CASE(tx_add_free,CTxTest) {
	//invalid data
	CFund fund(NULL_FUNDTYPE, g_vHash[0].at(0), 1, CHAIN_HEIGHT + 1);
	BOOST_CHECK(!accOperate.OperateAccount(ADD_FREE, fund));
	fund.nFundType = FREEDOM_FUND;
	fund.value = MAX_MONEY;
	BOOST_CHECK(!accOperate.OperateAccount(ADD_FREE, fund));

	vector<uint256> vReward;
	vector<uint256> vFree;
	GenerateRandomHash(vReward);
	GenerateRandomHash(vFree);
	accOperate.CompactAccount(10);
	for (int i = 0; i < VECTOR_SIZE; i++) {
		uint64_t nOld = GetTotalValue(accOperate.vRewardFund);
		uint64_t randValue = random(10);
		CFund fundReward(REWARD_FUND, vReward.at(i), randValue, CHAIN_HEIGHT + 1);
		BOOST_CHECK(accOperate.OperateAccount(ADD_FREE, fundReward));
		BOOST_CHECK(GetTotalValue(accOperate.vRewardFund) == nOld + randValue);

		nOld = GetTotalValue(accOperate.vFreedomFund);
		CFund fundFree(FREEDOM_FUND, vFree.at(i), randValue, CHAIN_HEIGHT + 1);
		BOOST_CHECK(accOperate.OperateAccount(ADD_FREE, fundFree));
		BOOST_CHECK(GetTotalValue(accOperate.vFreedomFund) == nOld + randValue);
	}

	accOperate.UndoOperateAccount(accOperate.accountOperLog);
	CheckAccountEqual();
}

BOOST_FIXTURE_TEST_CASE(tx_minus_free,CTxTest) {
	accOperate.CompactAccount(CHAIN_HEIGHT);
	for (int i = 0; i < VECTOR_SIZE; i++) {
		uint64_t nOldVectorSum = GetTotalValue(accOperate.vFreedomFund);
		uint64_t nOldValue = accOperate.llValues;
		uint64_t randValue = random(30);
		uint64_t nOperateValue = 0;
		CFund fund(REWARD_FUND, 0, randValue, random(20));

		if (nOldVectorSum && nOldVectorSum >= randValue) {
			nOperateValue = 0;
			BOOST_CHECK(accOperate.OperateAccount(MINUS_FREE, fund, &nOperateValue));
			BOOST_CHECK(GetTotalValue(accOperate.vFreedomFund) == nOldVectorSum - randValue);
			BOOST_CHECK(nOperateValue == randValue);
		} else {
			if (accOperate.llValues + nOldVectorSum >= randValue) {
				nOperateValue = 0;
				BOOST_CHECK(accOperate.OperateAccount(MINUS_FREE, fund, &nOperateValue));
				BOOST_CHECK(
						GetTotalValue(accOperate.vFreedomFund) + accOperate.llValues
						== nOldValue + nOldVectorSum - randValue);
				BOOST_CHECK(nOperateValue == randValue);
			} else {
				nOperateValue = 0;
				accOperate.OperateAccount(MINUS_FREE, fund, &nOperateValue);
				BOOST_CHECK(!GetTotalValue(accOperate.vFreedomFund) && !accOperate.llValues);
				BOOST_CHECK(nOperateValue == nOldValue + nOldVectorSum);
			}
		}
	}

	accOperate.UndoOperateAccount(accOperate.accountOperLog);
	CheckAccountEqual();
}

BOOST_FIXTURE_TEST_CASE(tx_add_self,CTxTest) {
	//invalid data
	CFund fundInvalid(NULL_FUNDTYPE, g_vHash[0].at(0), 1, CHAIN_HEIGHT + 1);
	BOOST_CHECK(!accOperate.OperateAccount(ADD_SELF_FREEZD, fundInvalid));
	fundInvalid.nFundType = 0;
	BOOST_CHECK(!accOperate.OperateAccount(ADD_SELF_FREEZD, fundInvalid));
	fundInvalid.nFundType = FREEDOM_FUND;
	fundInvalid.value = MAX_MONEY;
	BOOST_CHECK(!accOperate.OperateAccount(ADD_SELF_FREEZD, fundInvalid));

	//random test
	vector<uint256> vSelf;
	GenerateRandomHash(vSelf);

	accOperate.CompactAccount(CHAIN_HEIGHT);
	for (int i = 0; i < VECTOR_SIZE; i++) {
		uint64_t nOldVectorSum = GetTotalValue(accOperate.vFreedomFund);
		uint64_t nOldValue = accOperate.llValues;
		uint64_t randValue = random(30);
		uint64_t nOperateValue = 0;
		uint64_t nOldSelfValue = GetTotalValue(accOperate.vSelfFreeze);
		CFund fund(SELF_FREEZD_FUND, vSelf.at(i), randValue, CHAIN_HEIGHT + 1);

		if (nOldVectorSum && nOldVectorSum >= randValue) {
			nOperateValue = 0;
			BOOST_CHECK(accOperate.OperateAccount(ADD_SELF_FREEZD, fund, &nOperateValue));
			BOOST_CHECK(GetTotalValue(accOperate.vFreedomFund) == nOldVectorSum - randValue);
			BOOST_CHECK(nOperateValue == randValue);

			BOOST_CHECK(nOldSelfValue + randValue == GetTotalValue(accOperate.vSelfFreeze));
		} else {
			if (accOperate.llValues + nOldVectorSum >= randValue) {
				nOperateValue = 0;
				BOOST_CHECK(accOperate.OperateAccount(ADD_SELF_FREEZD, fund, &nOperateValue));
				BOOST_CHECK(
						GetTotalValue(accOperate.vFreedomFund) + accOperate.llValues
						== nOldValue + nOldVectorSum - randValue);
				BOOST_CHECK(nOperateValue == randValue);

				BOOST_CHECK(nOldSelfValue + randValue == GetTotalValue(accOperate.vSelfFreeze));
			} else {
				nOperateValue = 0;
				accOperate.OperateAccount(ADD_SELF_FREEZD, fund, &nOperateValue);
				BOOST_CHECK(!GetTotalValue(accOperate.vFreedomFund) && !accOperate.llValues);
				BOOST_CHECK(nOperateValue == nOldValue + nOldVectorSum);
			}
		}
	}

	accOperate.UndoOperateAccount(accOperate.accountOperLog);
	CheckAccountEqual();
}

BOOST_FIXTURE_TEST_CASE(tx_add_input,CTxTest) {
	vector<uint256> vSelf;
	GenerateRandomHash(vSelf);
	accOperate.CompactAccount(CHAIN_HEIGHT);

	//invalid param check
	CFund fundvalid(INPUT_FREEZD_FUND, vSelf.at(0), 1, CHAIN_HEIGHT + 1);
	CFund fundInvalid1(fundvalid);
	fundInvalid1.nFundType = 0;
	BOOST_CHECK(!accOperate.OperateAccount(ADD_INPUT_FREEZD, fundInvalid1));
	fundInvalid1.nFundType = NULL_OPERTYPE;
	BOOST_CHECK(!accOperate.OperateAccount(ADD_INPUT_FREEZD, fundInvalid1));

	CFund fundInvalid2(fundvalid);
	fundInvalid2.uTxHash = uint256(0);
	BOOST_CHECK(!accOperate.OperateAccount(ADD_INPUT_FREEZD, fundInvalid2));

//	CFund fundInvalid3(fundvalid);
//	fundInvalid3.nHeight = 0;
//	BOOST_CHECK(!accOperate.OperateAccount(ADD_INPUT_FREEZD, fundInvalid3));

//random check
	for (int i = 0; i < VECTOR_SIZE; i++) {
		uint64_t nOldInput = GetTotalValue(accOperate.vInputFreeze);
		uint64_t randValue = random(10);
		CFund fund(INPUT_FREEZD_FUND, vSelf.at(i), randValue, CHAIN_HEIGHT + 1);
		BOOST_CHECK(accOperate.OperateAccount(ADD_INPUT_FREEZD, fund));
		BOOST_CHECK(GetTotalValue(accOperate.vInputFreeze) == nOldInput + randValue);
	}

	accOperate.UndoOperateAccount(accOperate.accountOperLog);
	CheckAccountEqual();
}

BOOST_FIXTURE_TEST_CASE(tx_minus_free_to_output,CTxTest) {
	accOperate.CompactAccount(CHAIN_HEIGHT);
	vector<CFund> vFreeCopy(accOperate.vFreedomFund);

	for (vector<CFund>::iterator it = vFreeCopy.begin(); it != vFreeCopy.end(); it++) {
		size_t nOldFreeSize = accOperate.vFreedomFund.size();
		uint64_t nOldFreeValue = GetTotalValue(accOperate.vFreedomFund);
		size_t nOldOutputSize = accOperate.vOutputFreeze.size();
		uint64_t nOldOutputValue = GetTotalValue(accOperate.vOutputFreeze);
		uint64_t nChangeValue = it->value;

		BOOST_CHECK(accOperate.OperateAccount(MINUS_FREE_TO_OUTPUT, *it));

		BOOST_CHECK(nOldFreeValue - nChangeValue == GetTotalValue(accOperate.vFreedomFund));
		BOOST_CHECK(nOldOutputValue + nChangeValue == GetTotalValue(accOperate.vOutputFreeze));

		BOOST_CHECK(
				((nOldFreeSize == accOperate.vFreedomFund.size() + 1)
						&& nOldOutputSize + 1 == accOperate.vOutputFreeze.size())
				|| (nOldFreeSize == accOperate.vFreedomFund.size()
						&& nOldOutputSize == accOperate.vOutputFreeze.size()));
	}

	accOperate.UndoOperateAccount(accOperate.accountOperLog);
	CheckAccountEqual();
}

BOOST_FIXTURE_TEST_CASE(tx_minus_free_or_self,CTxTest) {
	accOperate.CompactAccount(CHAIN_HEIGHT);
	for (int i = 0; i < VECTOR_SIZE; i++) {
		uint64_t nOldTotalFree = GetTotalValue(accOperate.vFreedomFund)+accOperate.llValues;
		uint64_t nOldSelf = GetTotalValue(accOperate.vSelfFreeze);
		uint64_t randValue = random(30);
		uint64_t nOperateValue = 0;
		CFund fund(REWARD_FUND, 0, randValue, random(20));

		if (nOldTotalFree >= randValue) {
			nOperateValue = 0;
			BOOST_CHECK(accOperate.OperateAccount(MINUS_FREE_OR_SELF, fund, &nOperateValue));
			BOOST_CHECK(GetTotalValue(accOperate.vFreedomFund)+accOperate.llValues == nOldTotalFree - randValue);
			BOOST_CHECK(nOperateValue == randValue);
		} else {
			if (nOldTotalFree + nOldSelf >= randValue) {
				nOperateValue = 0;
				BOOST_CHECK(accOperate.OperateAccount(MINUS_FREE_OR_SELF, fund, &nOperateValue));
				BOOST_CHECK(GetTotalValue(accOperate.vFreedomFund) + accOperate.llValues+
						GetTotalValue(accOperate.vSelfFreeze)== nOldTotalFree + nOldSelf - randValue);
				BOOST_CHECK(nOperateValue == randValue);
			} else {
				nOperateValue = 0;
				accOperate.OperateAccount(MINUS_FREE_OR_SELF, fund, &nOperateValue);
				BOOST_CHECK(!GetTotalValue(accOperate.vFreedomFund) && !accOperate.llValues);
				BOOST_CHECK(nOperateValue == nOldSelf + nOldTotalFree);
			}
		}
	}

	accOperate.UndoOperateAccount(accOperate.accountOperLog);
	CheckAccountEqual();
}

BOOST_FIXTURE_TEST_CASE(tx_minus_output,CTxTest) {
//	accOperate.CompactAccount(CHAIN_HEIGHT);
//	vector<uint256> vOutputHashCopy;
//	for(vector<CFund>::iterator it = accOperate.vOutputFreeze.begin();it !=accOperate.vOutputFreeze.end();it++)
//	{
//		vOutputHashCopy.push_back(it->uTxHash);
//	}
//
//	//insert 100 data that not in the specific vector
//	vector<uint256> vRandomHash;
//	GenerateRandomHash(vRandomHash,100);
//	vOutputHashCopy.insert(vOutputHashCopy.end(),vRandomHash.begin(),vRandomHash.end() );
//	random_shuffle(vOutputHashCopy.begin(),vOutputHashCopy.end() );
//
//	//start test random data
//	uint64_t nOperaeValue = 0;
//	int nCount = 0;
//	for (vector<uint256>::iterator it = vOutputHashCopy.begin();it !=vOutputHashCopy.end();it++)
//	{
//		nOperaeValue = 0;
//		uint64_t nRandomValue = random(10);
//		CFund fund(OUTPUT_FREEZD_FUND, *it, nRandomValue, random(20));
//		vector<CFund>::iterator iter = find_if(accOperate.vOutputFreeze.begin(),accOperate.vOutputFreeze.end(),
//				CFindIterByHash(*it) );
//
//		if(accOperate.vOutputFreeze.end() == iter){
//			//can't find the specific fund by *it,so operatreAccount should return false
//			BOOST_CHECK(!accOperate.OperateAccount(MINUS_OUTPUT, fund,&nOperaeValue) );
//			continue;
//		}
//
//		uint64_t nOldOutputValue = GetTotalValue(accOperate.vOutputFreeze);
//		uint64_t nOldIterValue = iter->value;
//		if(nRandomValue>iter->value)
//		{
//			BOOST_CHECK(!accOperate.OperateAccount(MINUS_OUTPUT, fund,&nOperaeValue) );
//			BOOST_CHECK(GetTotalValue(accOperate.vOutputFreeze) + nOldIterValue == nOldOutputValue);
//			BOOST_CHECK(nOldIterValue == nOperaeValue);
//		}
//		else
//		{
//			BOOST_CHECK(accOperate.OperateAccount(MINUS_OUTPUT, fund,&nOperaeValue) );
//			BOOST_CHECK(GetTotalValue(accOperate.vOutputFreeze) + nRandomValue == nOldOutputValue);
//			BOOST_CHECK(nRandomValue == nOperaeValue);
//		}
//	}
//
//	accOperate.UndoOperateAccount(accOperate.accountOperLog);
//	CheckAccountEqual();

	CheckInOut(MINUS_OUTPUT);
}

BOOST_FIXTURE_TEST_CASE(tx_minus_input,CTxTest) {
	CheckInOut(MINUS_INPUT);
}

BOOST_FIXTURE_TEST_CASE(tx_minus_output_free,CTxTest) {
	CheckInOutFree(MINUS_OUTPUT_OR_FREE);
}

BOOST_FIXTURE_TEST_CASE(tx_minus_input_free,CTxTest) {
	CheckInOutFree(MINUS_INPUT_OR_FREE);
}

BOOST_FIXTURE_TEST_CASE(tx_minus_input_free_self,CTxTest) {
	CheckInOutFreeSelf(MINUS_INPUT_OR_FREE_OR_SELF);
}

BOOST_FIXTURE_TEST_CASE(tx_minus_output_free_self,CTxTest) {
	CheckInOutFreeSelf(MINUS_OUTPUT_OR_FREE_OR_SELF);
}

#else
BOOST_AUTO_TEST_CASE(xxxx) {
	BOOST_ERROR("ERROR:THE SUITE NEED TO MODIFY!");
}
#endif

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: SoyPay/soypay

max_issues_repo_name: SoyPay/soypay

max_forks_repo_name: SoyPay/soypay


text:
// ORIGINAL SOURCE: https://github.com/lltcggie/waifu2x-caffe
// This file is a modification translated to english.
// source.cpp -- 20 / 05 / 2020 --- waifu2x_caffe.ipynb

#include <stdio.h>
#include <algorithm>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <functional>
#include <boost/tokenizer.hpp>
#include <boost/tokenizer.hpp>
#include <glog/logging.h>
#include <codecvt>
#include "../common/waifu2x.h"

#if defined(UNICODE) && defined(_WIN32)
#define WIN_UNICODE
#include <Windows.h>
#include <tclapw/CmdLine.h>
#include <io.h>
#include <fcntl.h>
using namespace TCLAPW;
typedef std::wstring tstring;
typedef wchar_t TCHAR;
#ifndef TEXT
#define TEXT(x) L##x
#endif
#define totlower towlower
#define to_tstring std::to_wstring
#define tprintf wprintf
#define CHAR_STR_FORMAT L"%S"

const tstring& path_to_tstring(const boost::filesystem::path &p)
{
	return p.wstring();
}
#else
#include <tclap/CmdLine.h>
using namespace TCLAP;
typedef std::string tstring;
typedef char TCHAR;
#ifndef TEXT
#define TEXT(x) x
#endif
#define totlower tolower
#define to_tstring std::to_string
#define tprintf printf
#define CHAR_STR_FORMAT "%s"

const tstring& path_to_tstring(const boost::filesystem::path &p)
{
	return p.string();
}
#endif

// http://stackoverflow.com/questions/10167382/boostfilesystem-get-relative-path
boost::filesystem::path relativePath(const boost::filesystem::path &path, const boost::filesystem::path &relative_to)
{
	// create absolute paths
	boost::filesystem::path p = boost::filesystem::absolute(path);
	boost::filesystem::path r = boost::filesystem::absolute(relative_to);

	// if root paths are different, return absolute path
	if (p.root_path() != r.root_path())
		return p;

	// initialize relative path
	boost::filesystem::path result;

	// find out where the two paths diverge
	boost::filesystem::path::const_iterator itr_path = p.begin();
	boost::filesystem::path::const_iterator itr_relative_to = r.begin();
	while (*itr_path == *itr_relative_to && itr_path != p.end() && itr_relative_to != r.end()) {
		++itr_path;
		++itr_relative_to;
	}

	// add "../" for each remaining token in relative_to
	if (itr_relative_to != r.end()) {
		++itr_relative_to;
		while (itr_relative_to != r.end()) {
			result /= "..";
			++itr_relative_to;
		}
	}

	// add remaining path
	while (itr_path != p.end()) {
		result /= *itr_path;
		++itr_path;
	}

	return result;
}

int main(int argc, char** argv)
{
#ifdef WIN_UNICODE
	//switch the console to UTF-16 mode
	_setmode(_fileno(stdout), _O_U16TEXT);
#endif

	Waifu2x::init_liblary(argc, argv);

	// Do not save non-error logs of Caffe
	google::SetLogDestination(google::GLOG_INFO, "");
	google::SetLogDestination(google::GLOG_WARNING, "");

	// Output Caffe's error log to 'error_log_~'.
	google::SetLogDestination(google::GLOG_ERROR, "error_log_");
	google::SetLogDestination(google::GLOG_FATAL, "error_log_");

	// definition of command line arguments
	CmdLine cmd(TEXT("waifu2x reimplementation using Caffe"), ' ', TEXT("1.0.0"));

	ValueArg<tstring> cmdInputFile(TEXT("i"), TEXT("input_path"),
		TEXT("path to input image file"), true, TEXT(""),
		TEXT("string"), cmd);

	ValueArg<tstring> cmdOutputFile(TEXT("o"), TEXT("output_path"),
		TEXT("path to output image file (when input_path is folder, output_path must be folder)"), false,
		TEXT("(auto)"), TEXT("string"), cmd);

	ValueArg<tstring> cmdInputFileExt(TEXT("l"), TEXT("input_extention_list"),
		TEXT("extention to input image file when input_path is folder"), false, TEXT("png:jpg:jpeg:tif:tiff:bmp:tga"),
		TEXT("string"), cmd);

	ValueArg<tstring> cmdOutputFileExt(TEXT("e"), TEXT("output_extention"),
		TEXT("extention to output image file when output_path is (auto) or input_path is folder"), false,
		TEXT("png"), TEXT("string"), cmd);

	std::vector<tstring> cmdModeConstraintV;
	cmdModeConstraintV.push_back(TEXT("noise"));
	cmdModeConstraintV.push_back(TEXT("scale"));
	cmdModeConstraintV.push_back(TEXT("noise_scale"));
	cmdModeConstraintV.push_back(TEXT("auto_scale"));
	ValuesConstraint<tstring> cmdModeConstraint(cmdModeConstraintV);
	ValueArg<tstring> cmdMode(TEXT("m"), TEXT("mode"), TEXT("image processing mode"),
		false, TEXT("noise_scale"), &cmdModeConstraint, cmd);

	std::vector<int> cmdNRLConstraintV;
	cmdNRLConstraintV.push_back(0);
	cmdNRLConstraintV.push_back(1);
	cmdNRLConstraintV.push_back(2);
	cmdNRLConstraintV.push_back(3);
	ValuesConstraint<int> cmdNRLConstraint(cmdNRLConstraintV);
	ValueArg<int> cmdNRLevel(TEXT("n"), TEXT("noise_level"), TEXT("noise reduction level"),
		false, 0, &cmdNRLConstraint, cmd);

	ValueArg<double> cmdScaleRatio(TEXT("s"), TEXT("scale_ratio"),
		TEXT("custom scale ratio"), false, 2.0, TEXT("double"), cmd);

	ValueArg<double> cmdScaleWidth(TEXT("w"), TEXT("scale_width"),
		TEXT("custom scale width"), false, 0, TEXT("double"), cmd);

	ValueArg<double> cmdScaleHeight(TEXT("h"), TEXT("scale_height"),
		TEXT("custom scale height"), false, 0, TEXT("double"), cmd);

	ValueArg<tstring> cmdModelPath(TEXT(""), TEXT("model_dir"),
		TEXT("path to custom model directory (don't append last / )"), false,
		TEXT("models/cunet"), TEXT("string"), cmd);

	std::vector<tstring> cmdProcessConstraintV;
	cmdProcessConstraintV.push_back(TEXT("cpu"));
	cmdProcessConstraintV.push_back(TEXT("gpu"));
	cmdProcessConstraintV.push_back(TEXT("cudnn"));
	ValuesConstraint<tstring> cmdProcessConstraint(cmdProcessConstraintV);
	ValueArg<tstring> cmdProcess(TEXT("p"), TEXT("process"), TEXT("process mode"),
		false, TEXT("gpu"), &cmdProcessConstraint, cmd);

	ValueArg<int> cmdOutputQuality(TEXT("q"), TEXT("output_quality"),
		TEXT("output image quality"), false,
		-1, TEXT("int"), cmd);

	ValueArg<int> cmdOutputDepth(TEXT("d"), TEXT("output_depth"),
		TEXT("output image chaneel depth bit"), false,
		8, TEXT("int"), cmd);

	ValueArg<int> cmdCropSizeFile(TEXT("c"), TEXT("crop_size"),
		TEXT("input image split size"), false,
		128, TEXT("int"), cmd);

	ValueArg<int> cmdCropWidth(TEXT(""), TEXT("crop_w"),
		TEXT("input image split size(width)"), false,
		128, TEXT("int"), cmd);

	ValueArg<int> cmdCropHeight(TEXT(""), TEXT("crop_h"),
		TEXT("input image split size(height)"), false,
		128, TEXT("int"), cmd);

	ValueArg<int> cmdBatchSizeFile(TEXT("b"), TEXT("batch_size"),
		TEXT("input batch size"), false,
		1, TEXT("int"), cmd);

	ValueArg<int> cmdGPUNoFile(TEXT(""), TEXT("gpu"),
		TEXT("gpu device no"), false,
		0, TEXT("int"), cmd);

	std::vector<int> cmdTTAConstraintV;
	cmdTTAConstraintV.push_back(0);
	cmdTTAConstraintV.push_back(1);
	ValuesConstraint<int> cmdTTAConstraint(cmdTTAConstraintV);
	ValueArg<int> cmdTTALevel(TEXT("t"), TEXT("tta"), TEXT("8x slower and slightly high quality"),
		false, 0, &cmdTTAConstraint, cmd);

	// definition of command line argument : end

	Arg::enableIgnoreMismatched();

	// parse command line arguments
	try
	{
#ifdef WIN_UNICODE
		int nArgs = 0;
		LPTSTR *lplpszArgs = CommandLineToArgvW(GetCommandLine(), &nArgs);
		cmd.parse(nArgs, lplpszArgs);
		LocalFree(lplpszArgs);
#else
		cmd.parse(argc, argv);
#endif
	}
	catch (std::exception &e)
	{
		tprintf(TEXT("ERROR: ") CHAR_STR_FORMAT TEXT("\n"), e.what());
		return 1;
	}

	boost::optional<double> ScaleRatio;
	boost::optional<int> ScaleWidth;
	boost::optional<int> ScaleHeight;

	int crop_w = cmdCropSizeFile.getValue();
	int crop_h = cmdCropSizeFile.getValue();

	if (cmdCropWidth.isSet())
		crop_w = cmdCropWidth.getValue();

	if (cmdCropHeight.isSet())
		crop_h = cmdCropHeight.getValue();

	if (cmdScaleWidth.getValue() > 0)
		ScaleWidth = cmdScaleWidth.getValue();
	if (cmdScaleHeight.getValue() > 0)
		ScaleHeight = cmdScaleHeight.getValue();

	if (cmdScaleWidth.getValue() == 0 && cmdScaleHeight.getValue() == 0)
		ScaleRatio = cmdScaleRatio.getValue();

	const boost::filesystem::path input_path(boost::filesystem::absolute((cmdInputFile.getValue())));

	tstring outputExt = cmdOutputFileExt.getValue();
	if (outputExt.length() > 0 && outputExt[0] != TEXT('.'))
		outputExt = TEXT(".") + outputExt;

	const std::string ModelName = Waifu2x::GetModelName(cmdModelPath.getValue());

	tstring tModelName;

#ifdef WIN_UNICODE
	{
		std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> cv;
		tModelName = cv.from_bytes(ModelName);
	}
#else
	tModelName = ModelName;
#endif

	const bool use_tta = cmdTTALevel.getValue() == 1;

	std::vector<std::pair<tstring, tstring>> file_paths;
	if (boost::filesystem::is_directory(input_path)) // Batch conversion of image files under the directory if input_path is a folder
	{
		boost::filesystem::path output_path;

		if (cmdOutputFile.getValue() == TEXT("(auto)"))
		{
			// If it is "test", it should be like "test_noise_scale(Level1)(x2.000000)".

			tstring addstr(TEXT("("));
			addstr += tModelName;
			addstr += TEXT(")");

			const tstring &mode = cmdMode.getValue();

			addstr += TEXT("(") + mode + TEXT(")");

			if (mode.find(TEXT("noise")) != mode.npos || mode.find(TEXT("auto_scale")) != mode.npos)
				addstr += TEXT("(Level") + to_tstring(cmdNRLevel.getValue()) + TEXT(")");

			if (use_tta)
				addstr += TEXT("(tta)");
			if (mode.find(TEXT("scale")) != mode.npos)
			{
				if(ScaleRatio)
					addstr += TEXT("(x") + to_tstring(*ScaleRatio) + TEXT(")");
				else if (ScaleWidth && ScaleHeight)
					addstr += TEXT("(") + to_tstring(*ScaleWidth) + TEXT("x") + to_tstring(*ScaleHeight) + TEXT(")");
				else if (ScaleWidth)
					addstr += TEXT("(width ") + to_tstring(*ScaleWidth) + TEXT(")");
				else if (ScaleHeight)
					addstr += TEXT("(height ") + to_tstring(*ScaleHeight) + TEXT(")");
			}

			if (cmdOutputDepth.getValue() != 8)
				addstr += TEXT("(") + to_tstring(cmdOutputDepth.getValue()) + TEXT("bit)");

			output_path = input_path.branch_path() / (path_to_tstring(input_path.stem()) + addstr);
		}
		else
			output_path = cmdOutputFile.getValue();

		output_path = boost::filesystem::absolute(output_path);

		if (!boost::filesystem::exists(output_path))
		{
			if (!boost::filesystem::create_directory(output_path))
			{
				tprintf(TEXT("Error: Failed to create output folder '%s'.\n"), path_to_tstring(output_path).c_str());
				return 1;
			}
		}

		std::vector<tstring> extList;
		{
			// Turn input_extention_list into an array of strings

			typedef boost::char_separator<TCHAR> char_separator;
			typedef boost::tokenizer<char_separator, tstring::const_iterator, tstring> tokenizer;

			char_separator sep(TEXT(":"), TEXT(""), boost::drop_empty_tokens);
			tokenizer tokens(cmdInputFileExt.getValue(), sep);

			for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter)
			{
				tstring ext(*tok_iter);
				std::transform(ext.begin(), ext.end(), ext.begin(), totlower);
				extList.push_back(TEXT(".") + ext);
			}
		}

		// Acquire the input and output path of the image to be converted
		const auto func = [&extList, &input_path, &output_path, &outputExt, &file_paths](const boost::filesystem::path &path)
		{
			BOOST_FOREACH(const boost::filesystem::path& p, std::make_pair(boost::filesystem::recursive_directory_iterator(path),
				boost::filesystem::recursive_directory_iterator()))
			{
				if (boost::filesystem::is_directory(p))
				{
					const auto out_relative = relativePath(p, input_path);
					const auto out_absolute = output_path / out_relative;

					if (!boost::filesystem::exists(out_absolute))
					{
						if (!boost::filesystem::create_directory(out_absolute))
						{
							tprintf(TEXT("Error: creation of the output folder '%s' failed.\n"), path_to_tstring(out_absolute).c_str());
							return false;
						}
					}
				}
				else
				{
					tstring ext(path_to_tstring(p.extension()));
					std::transform(ext.begin(), ext.end(), ext.begin(), totlower);
					if (std::find(extList.begin(), extList.end(), ext) != extList.end())
					{
						const auto out_relative = relativePath(p, input_path);
						const auto out_absolute = output_path / out_relative;

						const auto out = path_to_tstring(out_absolute.branch_path() / out_absolute.stem()) + outputExt;

						file_paths.emplace_back(path_to_tstring(p), out);
					}
				}
			}

			return true;
		};

		if (!func(input_path))
			return 1;
	}
	else
	{
		tstring outputFileName = cmdOutputFile.getValue();

		if (outputFileName == TEXT("(auto)"))
		{
			// If it is "miku_small.png", it should be like "miku_small(noise_scale)(Level1)(x2.000000).png".

			outputFileName = cmdInputFile.getValue();
			const auto tailDot = outputFileName.find_last_of('.');
			outputFileName.erase(tailDot, outputFileName.length());

			tstring addstr(TEXT("("));
			addstr += tModelName;
			addstr += TEXT(")");

			const tstring &mode = cmdMode.getValue();

			addstr += TEXT("(") + mode + TEXT(")");

			if (mode.find(TEXT("noise")) != mode.npos || mode.find(TEXT("auto_scale")) != mode.npos)
				addstr += TEXT("(Level") + to_tstring(cmdNRLevel.getValue()) + TEXT(")");

			if (use_tta)
				addstr += TEXT("(tta)");
			if (mode.find(TEXT("scale")) != mode.npos)
			{
				if (ScaleRatio)
					addstr += TEXT("(x") + to_tstring(*ScaleRatio) + TEXT(")");
				else if (ScaleWidth && ScaleHeight)
					addstr += TEXT("(") + to_tstring(*ScaleWidth) + TEXT("x") + to_tstring(*ScaleHeight) + TEXT(")");
				else if (ScaleWidth)
					addstr += TEXT("(width ") + to_tstring(*ScaleWidth) + TEXT(")");
				else
					addstr += TEXT("(height ") + to_tstring(*ScaleHeight) + TEXT(")");
			}

			if (cmdOutputDepth.getValue() != 8)
				addstr += TEXT("(") + to_tstring(cmdOutputDepth.getValue()) + TEXT("bit)");

			outputFileName += addstr + outputExt;
		}

		file_paths.emplace_back(cmdInputFile.getValue(), outputFileName);
	}

	Waifu2x::eWaifu2xModelType mode;
	if (cmdMode.getValue() == TEXT("noise"))
		mode = Waifu2x::eWaifu2xModelTypeNoise;
	else if (cmdMode.getValue() == TEXT("scale"))
		mode = Waifu2x::eWaifu2xModelTypeScale;
	else if (cmdMode.getValue() == TEXT("noise_scale"))
		mode = Waifu2x::eWaifu2xModelTypeNoiseScale;
	else if (cmdMode.getValue() == TEXT("auto_scale"))
		mode = Waifu2x::eWaifu2xModelTypeAutoScale;

	Waifu2x::eWaifu2xError ret;
	Waifu2x w;

#ifdef WIN_UNICODE
	std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> cv;
	const std::string sProcess = cv.to_bytes(cmdProcess.getValue());
#else
	const std::string sProcess = cmdProcess.getValue();
#endif

	ret = w.Init(mode, cmdNRLevel.getValue(), cmdModelPath.getValue(), sProcess, cmdGPUNoFile.getValue());
	switch (ret)
	{
	case Waifu2x::eWaifu2xError_InvalidParameter:
		tprintf(TEXT("Error: Invalid parameter.\n"));
		return 1;
	case Waifu2x::eWaifu2xError_FailedOpenModelFile:
		tprintf(TEXT("Error: Model file could not be opened.\n"));
		return 1;
	case Waifu2x::eWaifu2xError_FailedParseModelFile:
		tprintf(TEXT("Error: The model file is corrupt.\n"));
		return 1;
	case Waifu2x::eWaifu2xError_FailedConstructModel:
		tprintf(TEXT("Error: Network build failed.\n"));
		return 1;
	}

	bool isError = false;
	for (const auto &p : file_paths)
	{
		const Waifu2x::eWaifu2xError ret = w.waifu2x(p.first, p.second, ScaleRatio, ScaleWidth, ScaleHeight, nullptr,
			crop_w, crop_h,
			cmdOutputQuality.getValue() == -1 ? boost::optional<int>() : cmdOutputQuality.getValue(), cmdOutputDepth.getValue(), use_tta, cmdBatchSizeFile.getValue());
		if (ret != Waifu2x::eWaifu2xError_OK)
		{
			switch (ret)
			{
			case Waifu2x::eWaifu2xError_InvalidParameter:
				tprintf(TEXT("Error: Invalid parameter.\n"));
				break;
			case Waifu2x::eWaifu2xError_FailedOpenInputFile:
				tprintf(TEXT("Error: Input image '%s' could not be opened.\n"), p.first.c_str());
				break;
			case Waifu2x::eWaifu2xError_FailedOpenOutputFile:
				tprintf(TEXT("Error: Output image '%s' could not be written to.\n"), p.second.c_str());
				break;
			case Waifu2x::eWaifu2xError_FailedProcessCaffe:
				tprintf(TEXT("Error: Interpolation failed.\n"));
				break;
			}

			isError = true;
		}
	}

	if (isError)
	{
		tprintf(TEXT("We have a file that failed to convert.\n"));
		return 1;
	}

	tprintf(TEXT("The conversion has been successful.\n"));

	Waifu2x::quit_liblary();

	return 0;
}


text:
#pragma once
#include <cmath>
#include <cstdarg>
#include <limits>
#include <vector>
#include <list>
#include <string>
#include <sstream>
#include <boost/algorithm/string.hpp>
#include <algorithm>
#include <iostream>
#include <random>
#include <ctime>

namespace kt84 {

namespace util {
    template <typename T> inline T lexical_cast(const std::string& str) {
        T ret;
        std::stringstream ss;
        ss.str(str);
        ss >> ret;
        return ret;
    }
    template <typename T> inline void append_str(std::string& str, const T& value) {
        std::stringstream ss;
        ss << str << value;
        str = ss.str();
    }
    template <typename T> inline T& incr_mod(T& value, const T& mod) { return value = (value + 1) % mod; }
    template <typename T> inline T& decr_mod(T& value, const T& mod) { return value = (value + mod - 1) % mod; }
    inline bool ensure_filename_extension(std::string& filename, const std::string& extension_including_period) {
        auto n = extension_including_period.size();
        if (!boost::iequals(filename.substr(filename.size() - n, n), extension_including_period)) {
            filename += extension_including_period;
            return false;
        }
        return true;
    }
    inline void flip_bool(bool& b) { b = !b; }
    template <typename T> inline void update_if_bigger (T& val_current, const T& val_new) { if (val_current < val_new) val_current = val_new; }
    template <typename T> inline void update_if_smaller(T& val_current, const T& val_new) { if (val_current > val_new) val_current = val_new; }
    template <typename T> inline T clamp(const T& value, const T& range_min, const T& range_max) { return std::max<T>(std::min<T>(value, range_max), range_min); }
    inline double asin_clamped(double sine)   { return std::asin(clamp(sine  , -1.0, 1.0)); };
    inline double acos_clamped(double cosine) { return std::acos(clamp(cosine, -1.0, 1.0)); };
    inline double pi() { return std::acos(-1); }
    inline double dbl_max() { return std::numeric_limits<double>::max(); }
    inline int    int_max() { return std::numeric_limits<int   >::max(); }
    template <typename T> inline T squared(const T& value) { return value * value; }
    template <typename T> inline T cubed(const T& value) { return value * value * value; }
    template <typename T> inline T normalize(const T& value, const T& value_min, const T& value_max) { return (value - value_min) / (value_max - value_min); }

    // max/min of more than two inputs. this is already possible in C++11 using initializer lists, but unfortunately it's still unsupported in VC11.
    template <typename T> inline T max(const T& arg0, const T& arg1, const T& arg2) { return std::max<T>(std::max<T>(arg0, arg1), arg2); }
    template <typename T> inline T min(const T& arg0, const T& arg1, const T& arg2) { return std::min<T>(std::min<T>(arg0, arg1), arg2); }
    template <typename T> inline T max(const T& arg0, const T& arg1, const T& arg2, const T& arg3) { return std::max<T>(max(arg0, arg1, arg2), arg3); }
    template <typename T> inline T min(const T& arg0, const T& arg1, const T& arg2, const T& arg3) { return std::min<T>(min(arg0, arg1, arg2), arg3); }
    template <typename T> inline T max(const T& arg0, const T& arg1, const T& arg2, const T& arg3, const T& arg4) { return std::max<T>(max(arg0, arg1, arg2, arg3), arg4); }
    template <typename T> inline T min(const T& arg0, const T& arg1, const T& arg2, const T& arg3, const T& arg4) { return std::min<T>(min(arg0, arg1, arg2, arg3), arg4); }

    // not so great with va_arg, but just for convenience...
    template <typename T>
    inline std::vector<T> make_vector(int size, ...) {
        va_list args;
        va_start(args, size);
        std::vector<T> result;
        result.reserve(size);
        for (int i = 0; i < size; ++i)
            result.push_back(va_arg(args, T));
        va_end(args);
        return result;
    }
    template <typename T>
    inline std::list<T> make_list(int size, ...) {
        va_list args;
        va_start(args, size);
        std::list<T> result;
        for (int i = 0; i < size; ++i)
            result.push_back(va_arg(args, T));
        va_end(args);
        return result;
    }
    template <typename T>
    inline T simple_prompt(const std::string& name) {
        T value;
        std::cout << name << ":";
        std::cin >> value;
        return value;
    }
    template <typename T>
    inline T simple_prompt_array(const std::string& name, int n) {
        T value;
        std::cout << name << ":";
        for (int i = 0; i < n; ++i)
            std::cin >> value[i];
        return value;
    }
    template <typename T>
    inline T simple_prompt(const std::string& name, const T& current_value) {
        T value;
        std::cout << name << " (current=" << current_value << "):";
        std::cin >> value;
        return value;
    }
    template <typename T>
    inline void swap_pair(std::pair<T, T>& p) { std::swap(p.first, p.second); }
    template <typename T>
    inline bool is_pair_equal(const std::pair<T, T>& p1, const std::pair<T, T>& p2) {       // compare p1 and p2 while ignoring ordering
        return p1.first == p2.first  && p1.second == p2.second ||
               p1.first == p2.second && p1.second == p2.first;
    }
    inline std::mt19937& random_engine() {
        static std::mt19937 engine(static_cast<unsigned int>(std::time(nullptr)));
        return engine;
    }
    template <typename T>
    T random_real(T range_min, T range_max) {   // range: [min, max)
        static std::uniform_real_distribution<T> dist(0, 1);       // range: [0, 1)
        T t = dist(random_engine());
        return (1 - t) * range_min + t * range_max;
    }
    inline double random_double(double range_min, double range_max) { return random_real<double>(range_min, range_max); }
    inline float  random_float (float  range_min, float  range_max) { return random_real<float >(range_min, range_max); }
    template <typename T>
    T random_integral(T range_min, T range_max) {               // range: [min, max]
        return range_min + static_cast<T>(random_double(0, 1) * (range_max - range_min + 1));
    }
    inline int  random_int (int  range_min, int  range_max ) { return random_integral<int > (range_min, range_max); }
    inline int  random_long(long range_min, long range_max ) { return random_integral<long> (range_min, range_max); }
    inline void srand(unsigned long seed) {
        random_engine().seed(seed);
    }
    template <typename T1, typename T2>
    inline void unfold_pair(const std::pair<T1, T2>& p, T1& val1, T2& val2) { val1 = p.first; val2 = p.second; }
    template <typename TEnum, typename TInt>
    inline TEnum add_enum(const TEnum& e, TInt n) { return static_cast<TEnum>(static_cast<TInt>(e) + n); }
    template <typename Value, typename IStream>
    Value query_istream(IStream& stream) {
        Value value;
        stream >> value;
        return value;
    }
}

}

max_stars_repo_name: honoriocassiano/skbar

max_issues_repo_name: honoriocassiano/skbar

max_forks_repo_name: honoriocassiano/skbar


text:
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2013-2018 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 */

#include "prefix-announcement.hpp"
#include "encoding/tlv-nfd.hpp"

#include <boost/lexical_cast.hpp>

namespace ndn {

static const name::Component KEYWORD_PA_COMP = "20025041"_block;

PrefixAnnouncement::PrefixAnnouncement() = default;

PrefixAnnouncement::PrefixAnnouncement(Data data)
  : m_data(std::move(data))
{
  if (m_data->getContentType() != tlv::ContentType_PrefixAnn) {
    BOOST_THROW_EXCEPTION(Error("Data is not a prefix announcement: ContentType is " +
                                boost::lexical_cast<std::string>(m_data->getContentType())));
  }

  const Name& dataName = m_data->getName();
  if (dataName.size() < 3 || dataName[-3] != KEYWORD_PA_COMP ||
      !dataName[-2].isVersion() || !dataName[-1].isSegment()) {
    BOOST_THROW_EXCEPTION(Error("Data is not a prefix announcement: wrong name structure"));
  }
  m_announcedName = dataName.getPrefix(-3);

  const Block& payload = m_data->getContent();
  payload.parse();

  m_expiration = time::milliseconds(readNonNegativeInteger(payload.get(tlv::nfd::ExpirationPeriod)));

  auto validityElement = payload.find(tlv::ValidityPeriod);
  if (validityElement != payload.elements_end()) {
    m_validity.emplace(*validityElement);
  }

  for (const Block& element : payload.elements()) {
    if (element.type() != tlv::nfd::ExpirationPeriod && element.type() != tlv::ValidityPeriod &&
        tlv::isCriticalType(element.type())) {
      BOOST_THROW_EXCEPTION(Error("unrecognized element of critical type " +
                                  to_string(element.type())));
    }
  }
}

const Data&
PrefixAnnouncement::toData(KeyChain& keyChain, const ndn::security::SigningInfo& si,
                           optional<uint64_t> version) const
{
  if (!m_data) {
    Name dataName = m_announcedName;
    dataName.append(KEYWORD_PA_COMP);
    dataName.appendVersion(version.value_or(time::toUnixTimestamp(time::system_clock::now()).count()));
    dataName.appendSegment(0);
    m_data.emplace(dataName);
    m_data->setContentType(tlv::ContentType_PrefixAnn);

    Block content(tlv::Content);
    content.push_back(makeNonNegativeIntegerBlock(tlv::nfd::ExpirationPeriod,
                                                  m_expiration.count()));
    if (m_validity) {
      content.push_back(m_validity->wireEncode());
    }
    content.encode();
    m_data->setContent(content);

    keyChain.sign(*m_data, si);
  }
  return *m_data;
}

PrefixAnnouncement&
PrefixAnnouncement::setAnnouncedName(Name name)
{
  m_data.reset();
  m_announcedName = std::move(name);
  return *this;
}

PrefixAnnouncement&
PrefixAnnouncement::setExpiration(time::milliseconds expiration)
{
  if (expiration < 0_ms) {
    BOOST_THROW_EXCEPTION(std::invalid_argument("expiration period is negative"));
  }
  m_data.reset();
  m_expiration = expiration;
  return *this;
}

PrefixAnnouncement&
PrefixAnnouncement::setValidityPeriod(optional<security::ValidityPeriod> validity)
{
  m_data.reset();
  m_validity = std::move(validity);
  return *this;
}

bool
operator==(const PrefixAnnouncement& lhs, const PrefixAnnouncement& rhs)
{
  return lhs.getAnnouncedName() == rhs.getAnnouncedName() &&
         lhs.getExpiration() == rhs.getExpiration() &&
         lhs.getValidityPeriod() == rhs.getValidityPeriod();
}

std::ostream&
operator<<(std::ostream& os, const PrefixAnnouncement& pa)
{
  os << pa.getAnnouncedName() << " expires=" << pa.getExpiration();
  if (pa.getValidityPeriod()) {
    os << " validity=" << *pa.getValidityPeriod();
  }
  return os;
}

} // namespace ndn


text:
// Copyright (c) 2014, Ruslan Baratov
// All rights reserved.

#include <leathers/push>
#include <leathers/assign-base-inaccessible>
#include <leathers/behavior-change>
#include <leathers/c++98-compat-pedantic>
#include <leathers/c++98-compat>
#include <leathers/catch-semantic-changed>
#include <leathers/copy-ctor-could-not-be-generated>
#include <leathers/deprecated-declarations>
#include <leathers/deprecated>
#include <leathers/disabled-macro-expansion>
#include <leathers/documentation-unknown-command>
#include <leathers/documentation>
#include <leathers/extra-semi>
#include <leathers/layout-changed>
#include <leathers/padded>
#include <leathers/shadow>
#include <leathers/sign-conversion>
#include <leathers/static-ctor-not-thread-safe>
#include <leathers/switch-enum>
#include <leathers/undef>
#include <leathers/unused-parameter>
#include <leathers/weak-vtables>
#include <leathers/automatic-inline>
#if !defined(SHOW_WARNINGS)
# include <leathers/force-not-inlined>
#endif

#include <boost/xpressive/xpressive.hpp>

int main() {
  using namespace boost::xpressive;
  sregex pat1 = "foo" >> +space >> "bar";
}

#include <leathers/pop>

max_stars_repo_name: nojhan/leathers

max_issues_repo_name: nojhan/leathers

max_forks_repo_name: nojhan/leathers


text: #include <boost/hana/union.hpp>