text:
/*
Copyright 2018 Thomas Spitzer <doxyqml@astade.de>
All rights reserved.

This software is a fork of the doxyqml tool written in python, by Aurélien Gâteau
(https://github.com/agateau/doxyqml)

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. 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 REGENTS 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 REGENTS 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 <stdio.h>
#include <argp.h>
#include <fstream>
#include <map>
#include <vector>
#include <string>
#include <iomanip>
#include <regex>
#include <fstream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/classic_position_iterator.hpp>
#include <boost/spirit/repository/include/qi_confix.hpp>
#include <boost/spirit/include/qi_lexeme.hpp>

#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/spirit/include/qi_action.hpp>

#include "CRootElement.h"
#include "CQmlObject.h"
#include "CMultilineComment.h"
#include "CSinglelineComment.h"
#include "CImport.h"
#include "CObjectDeclaration.h"
#include "CProperty.h"
#include "CSignal.h"
#include "CFunction.h"
#include "CNamespaceImport.h"

namespace classic = boost::spirit::classic;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

using boost::spirit::repository::confix;

/* This structure is used by main to communicate with parse_opt. */
struct Arguments
{
    Arguments(): debug(false) {}
    bool debug;
    std::string filename;
};

Arguments arguments;
doxyqml::CRootElement gRootObject;

void add_multiline_comment(const std::string& name, const boost::spirit::unused_type& it, bool& pass)
{
    doxyqml::CMultilineComment* p = new doxyqml::CMultilineComment(name);
    gRootObject.addChild(p);
}

void add_singleline_comment(const std::string& name, const boost::spirit::unused_type& it, bool& pass)
{
    doxyqml::CSinglelineComment* p = new doxyqml::CSinglelineComment(name);
    gRootObject.addChild(p);
}

void add_property(const std::string& name, const boost::spirit::unused_type& it, bool& pass)
{
    doxyqml::CProperty* p = new doxyqml::CProperty(name,false);
    gRootObject.addChild(p);
}

void add_subProperty(const std::string& name, const boost::spirit::unused_type& it, bool& pass)
{
    doxyqml::CProperty* p = new doxyqml::CProperty(name,true);
    gRootObject.addChild(p);
}

void add_signal(const std::string& name, const boost::spirit::unused_type& it, bool& pass)
{
    doxyqml::CSignal* p = new doxyqml::CSignal(name,false);
    gRootObject.addChild(p);
}

void add_subSignal(const std::string& name, const boost::spirit::unused_type& it, bool& pass)
{
    doxyqml::CSignal* p = new doxyqml::CSignal(name,true);
    gRootObject.addChild(p);
}

void add_function(const std::string& name, const boost::spirit::unused_type& it, bool& pass)
{
    doxyqml::CFunction* p = new doxyqml::CFunction(name,false);
    gRootObject.addChild(p);
}

void add_subFunction(const std::string& name, const boost::spirit::unused_type& it, bool& pass)
{
    doxyqml::CFunction* p = new doxyqml::CFunction(name,true);
    gRootObject.addChild(p);
}

void add_importline(const std::string& name, const boost::spirit::unused_type& it, bool& pass)
{
    doxyqml::CImport* p = new doxyqml::CImport(name);
    gRootObject.addChild(p);
}

void add_SubObject(const std::string& name, const boost::spirit::unused_type& it, bool& pass)
{
    doxyqml::CObjectDeclaration* o = new doxyqml::CObjectDeclaration(name);
    gRootObject.addSubObject(o);
}

void setBasename(const std::string& name, const boost::spirit::unused_type& it, bool& pass)
{
    gRootObject.setBaseClass(name);
    gRootObject.setMemberState();
}

void set_id(const std::string& name, const boost::spirit::unused_type& it, bool& pass)
{
    gRootObject.set_id(name);
}

void add_namespace(const std::string& name, const boost::spirit::unused_type& it, bool& pass)
{
    gRootObject.add_namespace(name);
}

std::string gNamespaceText;
void setNamespaceText(const std::string& name, const boost::spirit::unused_type& it, bool& pass)
{
    gNamespaceText = name;
}

std::string gNamespaceIdentifier;
void setNamespaceIdentifier(const std::string& name, const boost::spirit::unused_type& it, bool& pass)
{
    gNamespaceIdentifier = name;
}

void add_namespaceImport(const boost::spirit::unused_type& name, const boost::spirit::unused_type& it, bool& pass)
{
    doxyqml::CNamespaceImport* o = new doxyqml::CNamespaceImport(gNamespaceText, gNamespaceIdentifier);
    gRootObject.addChild(o);
}

template <typename Iterator>
struct qml_parser
  : qi::grammar<Iterator>
{
    qml_parser() : qml_parser::base_type(rootElements)
    {
        rootElements    =   *(topElement > space)
                        >>  topObjectDeclaration
                        >>  space
                        ;

        comment         =   multilineComment[add_multiline_comment]
                        |   singlelineComment[add_singleline_comment]
                        ;

        topElement      =   comment
                        |   namespaceImportLine[add_namespaceImport]
                        |   importLine[add_importline]
                        ;

        objectElement   =   comment
                        |   onCompletionHandler
                        |   (-(qi::lit("readonly") >> space) >> -(qi::lit("default") >> space) >> property[add_property])
                        |   signal[add_signal]
                        |   function[add_function]
                        |   objectDeclaration
                        |   idText
                        |   slot
                        |   propertySetting
                        |   structPropertySetting
                        ;

        subObjectElement   =   comment
                        |   onCompletionHandler
                        |   (-(qi::lit("readonly") >> space) >> -(qi::lit("default") >> space) >> property[add_subProperty])
                        |   signal[add_subSignal]
                        |   function[add_subFunction]
                        |   objectDeclaration
                        |   idText
                        |   slot
                        |   propertySetting
                        |   structPropertySetting
                        ;

        topObjectDeclaration    = uppercaseIdentifier[setBasename]
                                >>  *(qi::char_('.') >> uppercaseIdentifier[add_namespace])
                                > space
                                > *(qi::lit("on") > space > lowercaseIdentifier > space)
                                > qi::lit('{')
                                > space
                                > *(objectElement > space)
                                > qi::lit('}')
                                ;

        idText              =   "id:"
                            >>  space
                            >>  lowercaseIdentifier[set_id]
                            >>  space
                            >>  -qi::lit(';')
                            ;

        valueText           =   *(inCurlyBrackets | qi::lit('.') | (qi::char_ - qi::eol - qi::char_('}')))
                            ;

        propertySetting     =   *(uppercaseIdentifier >> qi::lit('.'))
                            >>  qualifiedIdentifier
                            >>  space
                            >>  qi::lit(':')
                            >>  space
                            >>  (arrayDeclare | objectDeclaration | valueText)
                            >>  space
                            >>  -qi::lit(';')
                            >> *(space >> qi::lit(':') >> tillEndOfLine)
                            ;

        structPropertySetting = lowercaseIdentifier
                            >>  space
                            >>  inCurlyBrackets
                            ;

        objectDeclaration   =   uppercaseIdentifier[add_SubObject]
                            >>  *(qi::char_('.') >> uppercaseIdentifier[add_namespace])
                            >>  space
                            >> *(qi::lit("on") > space > lowercaseIdentifier > space)
                            >>  qi::lit('{')
                            >>  space
                            >>  *(subObjectElement > space)
                            >>  qi::lit('}')
                            ;

        function            =   qi::lit("function")
                            >>  space
                            >>  -(lowercaseIdentifier >>  space)
                            >>  paramList
                            >>  space
                            >>  -(qi::lit("//") >> tillEndOfLine)
                            >>  space
                            >>  inCurlyBrackets
                            ;

        quotedText          =   confix("\"", "\"")[*((qi::char_ - "\"" - "\\") | ("\\" > qi::char_))];

        qualifiedIdentifier =   lowercaseIdentifier
                            >>  *(qi::lit('.') > lowercaseIdentifier)
                            ;

        someText            =   qi::lit(' ')
                            |   qi::lit('\n')
                            |   qi::lit('\t')
                            |   quotedText
                            |   inCurlyBrackets
                            |   qi::alnum
                            |   qi::char_("^,.;:_<>|~!*[]§$%&/()=?'-\\")
                            ;

        inCurlyBrackets     =   qi::lit('{')
                            >>  *someText
                            >>  qi::lit('}')
                            ;

        arrayDeclare        =   qi::lit('[')
                            >>  *(space >> objectDeclaration >> space >> qi::lit(','))
                            >>  -(space >> objectDeclaration)
                            >>  space
                            >>  qi::lit(']')
                            ;

        paramList           =   qi::char_('(')
                            >>  *(qi::char_ - ")")
                            >>  qi::char_(')')
                            ;

        slot                =   -qi::lit("Component.")
                            >>  lowercaseIdentifier
                            >>  space
                            >>  qi::lit(':')
                            >>  space
                            >>  (function | inCurlyBrackets)
                            ;

        onCompletionHandler =   (qi::lit("Component.onCompleted") | qi::lit("Component.onDestruction"))
                            >>  space
                            >>  qi::lit(':')
                            >>  space
                            >>  (inCurlyBrackets | *(qi::char_ - qi::eol - qi::char_('}')))
                            ;

        namespaceImportLine = qi::lit("import")
                            >>  space
                            >>  quotedText[setNamespaceText]
                            >>  space
                            >>  qi::lit("as")
                            >>  space
                            >>  uppercaseIdentifier[setNamespaceIdentifier]
                            ;

        property            = object_property | functionProperty | single_line_property;

        tillEndOfLine       =  *(qi::char_ - qi::eol);

        single_line_property  =  qi::lit("property")
                              >> *(qi::char_ - qi::lit(':') - qi::eol)
                              >> tillEndOfLine
                              >> *(space >> qi::lit(':') >> tillEndOfLine)
                              ;

        object_property     =   qi::lit("property")
                            >>  space
                            >>  uppercaseIdentifier
                            >>  qi::char_(" \t")
                            >>  space
                            >>  lowercaseIdentifier
                            >>  space
                            >>  qi::lit(':')
                            >>  space
                            >>  uppercaseIdentifier
                            >>  space
                            >>  inCurlyBrackets
                            ;

        functionProperty    =   qi::lit("property")
                            >>  space
                            >>  lowercaseIdentifier
                            >>  qi::char_(" \t")
                            >>  lowercaseIdentifier
                            >>  space
                            >>  qi::lit(':')
                            >>  space
                            >>  inCurlyBrackets
                            ;

        space = *(qi::lit(' ') | qi::lit('\n') | qi::lit('\t'));
        multilineComment = confix("/*", "*/")[*(qi::char_ - "*/")];
        singlelineComment = confix("//", qi::eol)[*(qi::char_ - qi::eol)];
        importLine = confix("import", qi::eol)[*(qi::char_ - qi::eol)];
        signal =  confix("signal", qi::eol)[*(qi::char_ - qi::eol)];
        uppercaseIdentifier = qi::char_("A-Z") > *qi::char_("_a-zA-Z0-9");
        lowercaseIdentifier = qi::char_("a-z") > *qi::char_("_a-zA-Z0-9");
    }

    qi::rule<Iterator, std::string()> multilineComment;
    qi::rule<Iterator, std::string()> singlelineComment;
    qi::rule<Iterator, std::string()> importLine;
    qi::rule<Iterator> namespaceImportLine;
    qi::rule<Iterator> tillEndOfLine;
    qi::rule<Iterator, std::string()> uppercaseIdentifier;
    qi::rule<Iterator, std::string()> lowercaseIdentifier;
    qi::rule<Iterator, std::string()> qualifiedIdentifier;

    qi::rule<Iterator> rootElements;
    qi::rule<Iterator, std::string()> topElement;
    qi::rule<Iterator> objectElement;
    qi::rule<Iterator> subObjectElement;
    qi::rule<Iterator> space;
    qi::rule<Iterator, std::string()> objectDeclaration;
    qi::rule<Iterator, std::string()> topObjectDeclaration;
    qi::rule<Iterator, std::string()> property;
    qi::rule<Iterator, std::string()> functionProperty;
    qi::rule<Iterator, std::string()> single_line_property;
    qi::rule<Iterator, std::string()> object_property;
    qi::rule<Iterator, std::string()> signal;
    qi::rule<Iterator, std::string()> quotedText;
    qi::rule<Iterator, std::string()> idText;
    qi::rule<Iterator, std::string()> valueText;
    qi::rule<Iterator> inCurlyBrackets;
    qi::rule<Iterator> arrayDeclare;
    qi::rule<Iterator> propertySetting;
    qi::rule<Iterator> structPropertySetting;
    qi::rule<Iterator> slot;
    qi::rule<Iterator, std::string()> paramList;
    qi::rule<Iterator, std::string()> function;
    qi::rule<Iterator, std::string()> someText;
    qi::rule<Iterator> comment;
    qi::rule<Iterator> onCompletionHandler;
};

// wrap forward iterator with position iterator, to record the position
typedef classic::position_iterator2<boost::spirit::istream_iterator> pos_iterator_type;

bool load(const std::string& filename)
{
    try
    {
        // open file, disable skipping of whitespace
        std::ifstream in(filename.c_str());

        if (arguments.debug)
             std::cerr
                << "doxyqml: Parsing file: "
                << filename
                << std::endl;

        in.unsetf(std::ios::skipws);

        // wrap istream into iterator
        boost::spirit::istream_iterator begin(in);
        boost::spirit::istream_iterator end;

        pos_iterator_type position_begin(begin, end, filename.c_str());
        pos_iterator_type position_end;

        qml_parser<pos_iterator_type> p;  // create instance of parser
        gRootObject.setFilename(filename);

        qi::phrase_parse(position_begin, position_end, p, qi::space);

        if (position_begin != position_end)
            throw qi::expectation_failure<pos_iterator_type>(position_begin, position_end,boost::spirit::info("general error"));
    }

    catch(const qi::expectation_failure<pos_iterator_type> e)
    {
        const classic::file_position_base<std::string>& pos = e.first.get_position();
        std::cerr   << pos.file << ':'
                    << pos.line << ": error: "
                    << e.what_  << std::endl;
        return false;
    }

    return true;
}

const char *argp_program_version =
"doxyqml 2.3";

const char *argp_program_bug_address =
"<t.spitzer@astade.de>";

static struct argp_option options[] =
{
  {"debug", 'd', 0,            0, "Log debug info to stderr"},
  {0}
};

static error_t parse_opt (int key, char *arg, struct argp_state *state)
{
    Arguments* arguments = (Arguments*) state->input;

    switch (key)
    {
    case 'd':
        arguments->debug = true;
        break;
    case ARGP_KEY_ARG:
        if (state->arg_num >= 1)
            argp_usage (state);
        else
            arguments->filename = arg;
        break;
    case ARGP_KEY_END:
      if (state->arg_num < 1)
        /* Not enough arguments. */
        argp_usage (state);
      break;
    default:
        return ARGP_ERR_UNKNOWN;
    }
    return 0;
}

static char doc[] =
"doxyqml -- A program to convert qml to pseudo C++ for doxygen.\n"
"\n"
"doxyqml generates namespaces from filepath.\n"
"If you want to strip some path information\nyou can define an environment variable \"doxyqml_strip\"\n"
"If the variable is not defined,\n    \"/qml/\" is assumed\n"
"So a file \"/home/thomas/myProg/src/qml/main.qml\" results in a\n    classname: \"qml::main\"\n"
"if you use \"export doxyqml_strip=/myProg/\" it'll results in the\n    classname: \"myProg::qml::main\"\n"
"\n"
;

/* A description of the arguments we accept. */
static char args_doc[] = "qml_file";

static struct argp argp = {options, parse_opt, args_doc, doc};

int main (int argc, char **argv)
{
    /* Where the magic happens */
    argp_parse (&argp, argc, argv, 0, 0, &arguments);

    if (!arguments.filename.empty())
    {
        std::string qmldir(arguments.filename);
        size_t pos = qmldir.rfind('/');

        if (pos != std::string::npos)
        {
            qmldir.erase(pos);
            qmldir += "/qmldir";
        } else {
            qmldir = "qmldir";
        }

        std::ifstream qmldirText;
        qmldirText.open(qmldir.c_str());

        if (arguments.debug)
            printf("qmldir name is: %s\n", qmldir.c_str());

        if (qmldirText.good())
        {
            std::string line;
            std::regex e("^module\\s+((?:\\w|\\.)+)\\s*$"); // the pattern
            while (getline(qmldirText, line))
            {
                std::cmatch cm;
                bool match = regex_search(line.c_str(), cm, e);
                if (match)
                {
                    std::string s(cm[1]);
                    gRootObject.setNamespace(s);
                    if (arguments.debug)
                        printf("found namespace: %s\n", s.c_str());
                }
            }
        }

        qmldirText.close();

        load(arguments.filename);
    }
    gRootObject.print(false);
    return 0;
}

max_stars_repo_name: Thomas-Astade/doxyqml

max_issues_repo_name: Thomas-Astade/doxyqml

max_forks_repo_name: Thomas-Astade/doxyqml


text:
#include "gtest/gtest.h"
#include <Eigen/Dense>

#include <casadi/casadi.hpp>
#include <vector>

class Rosenbrock {
public:
    using var_t = Eigen::Vector2d;
    using gradient_t = Eigen::Vector2d;
    using hessian_t = Eigen::Matrix2d;

    casadi::Function m_f;
    casadi::Function m_grad;
    casadi::Function m_hess;

    Rosenbrock()
    {
        casadi::SX x = casadi::SX::sym("x", 2);
        const double a = 1;
        const double b = 100;

        casadi::SX z = 0;
        for (int i = 0; i < x.rows() - 1; i++) {
            z += pow(a - x(i), 2) + b * pow(x(i + 1) - pow(x(i), 2), 2);
        }

        casadi::SX f_sym = z;
        casadi::SX grad_sym = casadi::SX::gradient(f_sym, x);
        casadi::SX hess_sym = casadi::SX::jacobian(grad_sym, x);

        m_f = casadi::Function("f", {x}, {f_sym});
        m_grad = casadi::Function("g", {x}, {grad_sym});
        m_hess = casadi::Function("h", {x}, {hess_sym});
    }

    void operator()(const var_t& x, double& value)
    {
        std::vector<double> xv(x.size());
        var_t::Map(&xv[0]) = x;
        casadi::DM res;
        res = m_f({casadi::DM(xv)})[0];
        value = *casadi::DM::densify(res).nonzeros().data();
    }

    void gradient(const var_t& x, gradient_t& grad, double& value)
    {
        this->operator()(x, value);

        casadi::DM res;
        std::vector<double> xv(x.size());
        var_t::Map(&xv[0]) = x;

        res = m_grad({casadi::DM(xv)})[0];
        grad = gradient_t::Map(casadi::DM::densify(res).nonzeros().data());
    }

    void hessian(const var_t& x, hessian_t& hess, gradient_t& grad, double& value)
    {
        gradient(x, grad, value);

        casadi::DM res;
        std::vector<double> xv(x.size());
        var_t::Map(&xv[0]) = x;

        res = m_hess({casadi::DM(xv)})[0];
        hess = hessian_t::Map(casadi::DM::densify(res).nonzeros().data());
    }
};

class SimpleQP {
public:
    Eigen::Matrix2d H;
    Eigen::Vector2d h;
    Eigen::Vector2d l, u;

    SimpleQP()
    {
        H << 10, 0,
            0, 0.1;
        h << -1, -2;

        l << -1, -1;
        u << 1, 1;
    }

    void operator()(const Eigen::Vector2d& x, double& value)
    {
        value = 0.5 * x.dot(H * x) + h.dot(x);
    }

    void gradient(const Eigen::Vector2d& x, Eigen::Vector2d& grad, double& value)
    {
        this->operator()(x, value);
        grad << H * x + h;
    }

    void hessian(const Eigen::Vector2d& x,
                 Eigen::Matrix2d& hess,
                 Eigen::Vector2d& grad,
                 double& value)
    {
        gradient(x, grad, value);
        hess << H;
    }
};

TEST(TrustRegionTestCase, TestRosenbrock) {
    SimpleQP prob;
    // Rosenbrock prob;

    using Scalar = double;
    using var_t = Eigen::Vector2d;
    using gradient_t = Eigen::Vector2d;
    using hessian_t = Eigen::Matrix2d;

    var_t x0(0, 0);

    Scalar cost, trust_region;
    var_t x;
    hessian_t B;
    gradient_t g;
    Eigen::LLT<hessian_t> cholesky;

    const Scalar epsilon = 1e-4;
    const Scalar eta = 0; // 0 < eta < 10e-3
    const Scalar trust_region_max_radius = 1e3;
    x = x0;
    trust_region = 0.1;

    // Algorithm 6.2 Trust-Region Method
    int iter;
    for (iter = 0; iter < 100; iter++) {
        std::cout << "x " << x.transpose() << std::endl;

        prob.hessian(x, B, g, cost);
        var_t p, q, x_step;

        Scalar lambda = 0.1; // TODO: initial value?
        for (int i = 0; i < 3; i++) {
            // Algorithm 4.3 Trust Region Subproblem
            cholesky.compute(B + lambda * B.Identity());

            // TODO: what if B is indefinite?
            if (cholesky.info() != Eigen::Success) {
                lambda *= 2;
                continue;
            }

            p = cholesky.solve(-g);
            q = cholesky.matrixL().solve(p);
            // std::cout << "p " << p.transpose() << std::endl;
            // std::cout << "q " << p.transpose() << std::endl;
            lambda = lambda + p.dot(p) / q.dot(q) * (p.norm() - trust_region) / trust_region;

            // std::cout << "B\n" << B << std::endl;
            // std::cout << "B+\n" << (B + lambda * B.Identity()) << std::endl;

        }
        cholesky.compute(B + lambda * B.Identity());
        p = cholesky.solve(-g);

        std::cout << "g " << g.transpose() << std::endl;
        std::cout << "p " << p.transpose() << std::endl;

        x_step = x + p;

        Scalar ared, pred, rho;
        Scalar cost_step;
        gradient_t g_step;

        prob.gradient(x_step, g_step, cost_step);
        pred = -(g.dot(p) + 0.5 * p.dot(B * p));
        ared = cost - cost_step;
        rho = ared / pred;

        printf("rho %f\n", rho);

        if (rho > eta) {
            x = x + p;
        } else {
            printf("reject step\n");
            // reject step: x = x;
        }

        // trust region update
        if (rho < 0.1) {
            printf("shrink trust region, %f\n", trust_region);
            trust_region = 0.5 * trust_region;
        } else if (rho > 0.75) {
            if (p.norm() < 0.8 * trust_region) {
                // keep trust region
                printf("keep trust region\n");
            } else {
                trust_region = fmin(2.0 * trust_region, trust_region_max_radius);
                printf("increase trust region, %f\n", trust_region);
            }
        } else {
            // keep trust region
            printf("keep trust region\n");
        }

        // do SR1 or BFGS update
        // if (SR1 condition 6.26) {
        //     y = grad - grad_prev;
        //     SR1_update(B, p, y);
        // }

        if (g.lpNorm<Eigen::Infinity>() < epsilon) {
            break;
        }
    }
    std::cout << "x " << x.transpose() << std::endl;
    std::cout << "iter " << iter << std::endl;
}

int main(int argc, char **argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

ext: cpp


text:
//  GetCurrentProcess.hpp  --------------------------------------------------------------//

//  Copyright 2010 Vicente J. Botet Escriba

//  Distributed under the Boost Software License, Version 1.0.
//  See http://www.boost.org/LICENSE_1_0.txt

#ifndef BOOST_DETAIL_WINAPI_GETCURRENTPROCESS_HPP
#define BOOST_DETAIL_WINAPI_GETCURRENTPROCESS_HPP

#include <boost/detail/winapi/basic_types.hpp>

#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif

namespace boost {
namespace detail {
namespace winapi {
#if defined( BOOST_USE_WINDOWS_H )
    using ::GetCurrentProcess;
#else
    extern "C" __declspec(dllimport) HANDLE_ WINAPI GetCurrentProcess();
#endif
}
}
}
#endif // BOOST_DETAIL_WINAPI_GETCURRENTPROCESS_HPP

ext: hpp

max_stars_repo_name: multi-os-engine/cinder-natj-binding

max_issues_repo_name: wujf/mongo

max_forks_repo_name: wujf/mongo


text:
/*
	Copyright (C) 2003-2013 by David White <davewx7@gmail.com>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <boost/regex.hpp>
#include <iostream>
#include <math.h>
#include <sstream>
#include <set>

#include "asserts.hpp"
#include "foreach.hpp"
#include "formatter.hpp"
#include "formula.hpp"
#include "formula_callable.hpp"
#include "formula_function.hpp"
#include "json_parser.hpp"
#include "level_solid_map.hpp"
#include "multi_tile_pattern.hpp"
#include "point_map.hpp"
#include "preferences.hpp"
#include "random.hpp"
#include "string_utils.hpp"
#include "thread.hpp"
#include "tile_map.hpp"
#include "variant_utils.hpp"

namespace {

PREF_INT(tile_pattern_search_border, 1, "How many extra tiles to search for patterns");

const std::map<std::string, int>& str_to_zorder() {
	static std::map<std::string, int>* instance = NULL;
	if(!instance) {
		instance = new std::map<std::string, int>;
		variant node = json::parse_from_file("data/zorder.cfg");

		foreach(variant::map_pair p, node.as_map()) {
			(*instance)[p.first.as_string()] = p.second.as_int();
		}
	}

	return *instance;
}

const std::map<int, variant>& zorder_to_str() {
	static std::map<int, variant>* instance = NULL;
	if(!instance) {
		instance = new std::map<int, variant>;
		variant node = json::parse_from_file("data/zorder.cfg");

		foreach(variant::map_pair p, node.as_map()) {
			ASSERT_LOG(instance->count(p.second.as_int()) == 0, "Multiple zorders map to same value: " << p.second.as_int());

			(*instance)[p.second.as_int()] = p.first;
		}
	}

	return *instance;
}

}

int parse_zorder(const variant& v, variant default_val)
{
	if(v.is_null() && !default_val.is_null()) {
		return parse_zorder(default_val);
	}

	if(v.is_int()) {
		return v.as_int();
	}

	const std::string& str = v.as_string();
	ASSERT_LOG(str_to_zorder().count(str), "Invalid zorder id: " << v.as_string() << ": " << v.debug_location());
	return str_to_zorder().find(str)->second;
}

variant write_zorder(int zorder)
{
	if(zorder_to_str().count(zorder)) {
		return zorder_to_str().find(zorder)->second;
	}

	return variant(zorder);
}

int get_named_zorder(const std::string& key, int default_value)
{
	std::map<std::string, int>::const_iterator itor = str_to_zorder().find(key);
	if(itor == str_to_zorder().end()) {
		return default_value;
	}

	return itor->second;
}

namespace {

typedef std::map<const boost::regex*, bool> regex_match_map;
std::map<boost::array<char, 4>, regex_match_map> re_matches;

bool match_regex(boost::array<char, 4> str, const boost::regex* re) {
	if(reinterpret_cast<intptr_t>(re)&1) {
		//the low bit in the re pointer is set, meaning this is an inverted
		//match.
		return !match_regex(str, reinterpret_cast<const boost::regex*>(reinterpret_cast<intptr_t>(re)-1));
	}

	std::map<const boost::regex*, bool>& m = re_matches[str];
	std::map<const boost::regex*, bool>::const_iterator i = m.find(re);
	if(i != m.end()) {
		return i->second;
	}

	const bool match = boost::regex_match(str.data(), str.data() + strlen(str.data()), *re);
	m[re] = match;
	return match;
}

struct is_whitespace {
	bool operator()(char c) const { return util::c_isspace(c); }
};

}

struct tile_pattern {
	explicit tile_pattern(variant node, const std::string& id)
	  : tile_id(id),
	    tile(new level_object(node, id.c_str())), reverse(node["reverse"].as_bool(true)),
	    empty(node["empty"].as_bool(false)),
		filter_formula(game_logic::formula::create_optional_formula(node["filter"]))
	{
		variations.push_back(tile);

		pattern_str = node["pattern"].as_string();
		std::string pattern_str = node["pattern"].as_string();
		pattern_str.erase(std::remove_if(pattern_str.begin(), pattern_str.end(), is_whitespace()), pattern_str.end());

		static std::vector<std::string> patterns;
		patterns.clear();
		util::split(pattern_str, patterns, ',', 0);

		assert(!patterns.empty());

		//the main pattern is always the very middle one.
		int main_tile = patterns.size()/2;

		int width = node["pattern_width"].as_int(sqrt(static_cast<float>(patterns.size())));
		assert(width != 0);
		int height = patterns.size()/width;

		int top = -height/2;
		int left = -width/2;

		//pattern with size 12 is a special case
		if(patterns.size() == 12 && !node.has_key("pattern_width")) {
			width = 3;
			height = 4;
			top = -1;
			left = -1;
			main_tile = 4;
		}

		current_tile_pattern = &get_regex_from_pool(patterns[main_tile].empty() ? "^$" : patterns[main_tile]);

		for(int n = 0; n != patterns.size(); ++n) {
			if(n == main_tile) {
				continue;
			}

			const int x = left + n%width;
			const int y = top + n/width;
			surrounding_tiles.push_back(surrounding_tile(x, y, patterns[n]));
		}

		foreach(variant var, node["variation"].as_list()) {
			variations.push_back(level_object_ptr(new level_object(var, tile_id.c_str())));
		}

		foreach(variant var, node["tile"].as_list()) {
			added_tile t;
			level_object_ptr new_object(new level_object(var, tile_id.c_str()));

			t.object = new_object.get();
			t.zorder = parse_zorder(var["zorder"]);
			added_tiles.push_back(t);

		}
	}

	std::string tile_id;
	const boost::regex* current_tile_pattern;

	struct surrounding_tile {
		surrounding_tile(int x, int y, const std::string& s)
		  : xoffset(x), yoffset(y), pattern(&get_regex_from_pool(s))
		{}
		int xoffset;
		int yoffset;
		const boost::regex* pattern;
	};

	std::vector<surrounding_tile> surrounding_tiles;

	std::string pattern_str;
	level_object_ptr tile;
	std::vector<level_object_ptr> variations;
	bool reverse;
	bool empty;

	struct added_tile {
		level_object_ptr object;
		int zorder;
	};

	std::vector<added_tile> added_tiles;

	game_logic::const_formula_ptr filter_formula;
};

namespace {

std::vector<tile_pattern> patterns;
int current_patterns_version = 0;

class filter_callable : public game_logic::formula_callable {
	const tile_map& m_;
	int x_, y_;
public:
	filter_callable(const tile_map& m, int x, int y) : m_(m), x_(x), y_(y)
	{}

	variant get_value(const std::string& key) const {
		if(key == "tiles") {
			return variant(&m_);
		} else if(key == "x") {
			return variant(x_);
		} else if(key == "y") {
			return variant(y_);
		} else {
			return variant();
		}
	}
};

using namespace game_logic;

class tile_at_function : public function_expression {
public:
	explicit tile_at_function(const args_list& args)
	  : function_expression("tile_at", args, 2)
	{}

private:
	variant execute(const formula_callable& variables) const {
		variant v = args()[0]->evaluate(variables);
		tile_map* m = v.convert_to<tile_map>();
		return variant(m->get_tile(args()[1]->evaluate(variables).as_int(),
		                           args()[2]->evaluate(variables).as_int()));
	}
};

class tile_map_function_symbol_table : public function_symbol_table
{
public:
	expression_ptr create_function(
	           const std::string& fn, const std::vector<expression_ptr>& args, const_formula_callable_definition_ptr callable_def) const {
		if(fn == "tile_at") {
			return expression_ptr(new tile_at_function(args));
		} else {
			return function_symbol_table::create_function(fn, args, callable_def);
		}
	}
};

std::map<std::string, std::vector<std::string> > files_index;
std::set<std::string> files_loaded;

}

void tile_map::load_all()
{
	for(std::map<std::string, std::vector<std::string> >::const_iterator i = files_index.begin(); i != files_index.end(); ++i) {
		foreach(const std::string& s, i->second) {
			load(s, i->first);
		}
	}
}

void tile_map::load(const std::string& fname, const std::string& tile_id)
{
	if(files_loaded.count(fname)) {
		return;
	}

	files_loaded.insert(fname);

	variant node = json::parse_from_file("data/tiles/" + fname);

	palette_scope palette_setter(parse_variant_list_or_csv_string(node["palettes"]));

	foreach(variant pattern, node["tile_pattern"].as_list()) {
		patterns.push_back(tile_pattern(pattern, tile_id));
	}

	multi_tile_pattern::load(node, tile_id);

	++current_patterns_version;
}

const std::vector<std::string>& tile_map::get_files(const std::string& tile_id)
{
	if(files_index.count(tile_id)) {
		return files_index.find(tile_id)->second;
	} else {
		static const std::vector<std::string> empty;
		return empty;
	}
}

void tile_map::init(variant node)
{
	files_index.clear();

	foreach(const variant_pair& value, node.as_map()) {
		files_index[value.first.as_string()] = util::split(value.second.as_string());
	}

	patterns.clear();
	files_loaded.clear();

	multi_tile_pattern::init(node);

	++current_patterns_version;
}

#ifndef NO_EDITOR
namespace {
std::set<tile_map*>& all_tile_maps() {
	static std::set<tile_map*>* all = new std::set<tile_map*>;
	return *all;
}
threading::mutex& all_tile_maps_mutex() {
	static threading::mutex* m = new threading::mutex;
	return *m;
}

void create_tile_map(tile_map* t) {
	threading::lock l(all_tile_maps_mutex());
	all_tile_maps().insert(t);
}
void destroy_tile_map(tile_map* t) {
	threading::lock l(all_tile_maps_mutex());
	all_tile_maps().erase(t);
}
std::set<tile_map*> copy_tile_maps() {
	threading::lock l(all_tile_maps_mutex());
	std::set<tile_map*> result = all_tile_maps();
	return result;
}
}

void tile_map::prepare_rebuild_all()
{
	const std::set<tile_map*> maps = copy_tile_maps();
	foreach(tile_map* m, maps) {
		m->node_ = m->write();
	}
}

void tile_map::rebuild_all()
{
	const std::set<tile_map*> maps = copy_tile_maps();
	foreach(tile_map* m, maps) {
		*m = tile_map(m->node_);
	}
}
#endif

tile_map::tile_map() : xpos_(0), ypos_(0), x_speed_(100), y_speed_(100), zorder_(0), patterns_version_(-1)
{
#ifndef NO_EDITOR
	create_tile_map(this);
#endif

	//turn off reference counting
	add_ref();

	//make an entry for the empty string.
	pattern_index_.push_back(pattern_index_entry());
	pattern_index_.back().matching_patterns.push_back(&get_regex_from_pool(""));
}

tile_map::tile_map(variant node)
  : xpos_(node["x"].as_int()), ypos_(node["y"].as_int()),
	x_speed_(node["x_speed"].as_int(100)), y_speed_(node["y_speed"].as_int(100)),
    zorder_(parse_zorder(node["zorder"]))

#ifndef NO_EDITOR
	, node_(node)
#endif
{
#ifndef NO_EDITOR
	create_tile_map(this);
#endif

	//turn off reference counting
	add_ref();

	const std::string& unique_tiles = node["unique_tiles"].as_string_default();
	foreach(const std::string& tile, util::split(unique_tiles)) {
		const std::vector<std::string>& files = files_index[tile];
		foreach(const std::string& file, files) {
			load(file, tile);
		}
	}

	//make an entry for the empty string.
	pattern_index_.push_back(pattern_index_entry());
	pattern_index_.back().matching_patterns.push_back(&get_regex_from_pool(""));

	{
	const std::string& tiles_str = node["tiles"].as_string();
	std::vector<std::string> lines;
	lines.reserve(std::count(tiles_str.begin(), tiles_str.end(), '\n')+1);

	util::split(tiles_str, lines, '\n', 0);
	foreach(const std::string& line, lines) {
		map_.resize(map_.size()+1);

		std::vector<tile_string> items;
		const char* ptr = line.c_str();
		bool found_end = line.empty();
		while(!found_end) {
			const char* end = strchr(ptr, ',');
			if(end == NULL) {
				end = line.c_str() + line.size();
				found_end = true;
			}

			//We want to copy [ptr,end) to tile_string. First strip the spaces.
			while(ptr != end && util::c_isspace(*ptr)) {
				++ptr;
			}

			while(end != ptr && util::c_isspace(*(end-1))) {
				--end;
			}

			ASSERT_LOG(end - ptr <= 4, "TILE PATTERN IS TOO LONG: " << std::string(ptr, end));

			tile_string tile;
			std::fill(tile.begin(), tile.end(), '\0');
			std::copy(ptr, end, tile.begin());
			items.push_back(tile);

			if(!found_end) {
				ptr = end + 1;
			}
		}

		foreach(const tile_string& str, items) {
			int index_entry = 0;
			foreach(const pattern_index_entry& e, pattern_index_) {
				if(strcmp(e.str.data(), str.data()) == 0) {
					break;
				}

				++index_entry;
			}

			if(index_entry == pattern_index_.size()) {
				pattern_index_.push_back(pattern_index_entry());
				pattern_index_.back().str = str;
			}

			map_.back().push_back(index_entry);
		}
	}

	build_patterns();

	}
}

tile_map::tile_map(const tile_map& o)
{
#ifndef NO_EDITOR
	create_tile_map(this);
#endif

	add_ref();
	*this = o;
}

tile_map::~tile_map()
{
#ifndef NO_EDITOR
	destroy_tile_map(this);
#endif
}

void tile_map::build_patterns()
{
	std::vector<const boost::regex*> all_regexes;

	patterns_version_ = current_patterns_version;
	const int begin_time = SDL_GetTicks();
	patterns_.clear();
	foreach(const tile_pattern& p, patterns) {
		std::vector<const boost::regex*> re;
		std::vector<const boost::regex*> accepted_re;
		if(!p.current_tile_pattern->empty()) {
			re.push_back(p.current_tile_pattern);
		}

		foreach(const tile_pattern::surrounding_tile& t, p.surrounding_tiles) {
			re.push_back(t.pattern);
		}

		int matches = 0;
		foreach(pattern_index_entry& e, pattern_index_) {
			foreach(const boost::regex*& regex, re) {
				if(regex && match_regex(e.str, regex)) {
					accepted_re.push_back(regex);
					regex = NULL;
					++matches;
					if(matches == re.size()) {
						break;
					}
				}
			}

			if(matches == re.size()) {
				break;
			}
		}

		if(matches == re.size()) {
			all_regexes.insert(all_regexes.end(), accepted_re.begin(), accepted_re.end());
			patterns_.push_back(&p);
		}
	}

	foreach(const multi_tile_pattern& p, multi_tile_pattern::get_all()) {
		std::vector<const boost::regex*> re;
		std::vector<const boost::regex*> accepted_re;

		re.reserve(p.width()*p.height());
		for(int x = 0; x < p.width(); ++x) {
			for(int y = 0; y < p.height(); ++y) {
				re.push_back(p.tile_at(x, y).re);
			}
		}

		int matches = 0;
		foreach(pattern_index_entry& e, pattern_index_) {
			foreach(const boost::regex*& regex, re) {
				if(regex && match_regex(e.str, regex)) {
					accepted_re.push_back(regex);
					regex = NULL;
					++matches;
					if(matches == re.size()) {
						break;
					}
				}
			}

			if(matches == re.size()) {
				break;
			}
		}

		if(matches == re.size()) {
			all_regexes.insert(all_regexes.end(), accepted_re.begin(), accepted_re.end());
			multi_patterns_.push_back(&p);
		}
	}

	std::sort(all_regexes.begin(), all_regexes.end());
	all_regexes.erase(std::unique(all_regexes.begin(), all_regexes.end()), all_regexes.end());

	foreach(pattern_index_entry& e, pattern_index_) {
		e.matching_patterns.clear();

		foreach(const boost::regex* re, all_regexes) {
			if(match_regex(e.str, re)) {
				e.matching_patterns.push_back(re);
			}
		}
	}

	const int end_time = SDL_GetTicks();
	static int total_time = 0;
	total_time += (end_time - begin_time);
}

const std::vector<const tile_pattern*>& tile_map::get_patterns() const
{
	if(patterns_version_ != current_patterns_version) {
		const_cast<tile_map*>(this)->build_patterns();
	}

	return patterns_;
}

variant tile_map::write() const
{
	variant_builder res;
	res.add("x", xpos_);
	res.add("y", ypos_);
	res.add("x_speed", x_speed_);
	res.add("y_speed", y_speed_);
	res.add("zorder", write_zorder(zorder_));

	std::vector<boost::array<char, 4> > unique_tiles;
	std::ostringstream tiles;
	bool first = true;
	foreach(const std::vector<int>& row, map_) {

		//cut off any empty cells at the end.
		int size = row.size();
		while(size > 2 && *pattern_index_[row[size-1]].str.data() == 0) {
			--size;
		}

		if(!first) {
			tiles << "\n";
		}

		first = false;
		for(int i = 0; i != size; ++i) {
			if(i) {
				tiles << ",";
			}
			tiles << pattern_index_[row[i]].str.data();
			unique_tiles.push_back(pattern_index_[row[i]].str);
		}

		if(row.empty()) {
			tiles << ",";
		}
	}

	std::sort(unique_tiles.begin(), unique_tiles.end());
	unique_tiles.erase(std::unique(unique_tiles.begin(), unique_tiles.end()), unique_tiles.end());
	std::ostringstream unique_str;
	for(int n = 0; n != unique_tiles.size(); ++n) {
		if(n != 0) {
			unique_str << ",";
		}

		unique_str << unique_tiles[n].data();
	}

	res.add("unique_tiles", unique_str.str());

	std::ostringstream variations;
	foreach(const std::vector<int>& row, variations_) {
		variations << "\n";
		for(int i = 0; i != row.size(); ++i) {
			if(i) {
				variations << ",";
			}
			variations << row[i];
		}

		if(row.empty()) {
			variations << ",";
		}
	}

	res.add("tiles", tiles.str());
	res.add("variations", variations.str());
	return res.build();
}

const char* tile_map::get_tile_from_pixel_pos(int xpos, int ypos) const
{
	const int x = (xpos - xpos_)/TileSize;
	const int y = (ypos - ypos_)/TileSize;
	return get_tile(y, x);
}

const char* tile_map::get_tile(int y, int x) const
{
	if(x < 0 || y < 0 || y >= map_.size() || x >= map_[y].size()) {
		return "";
	}

	return pattern_index_[map_[y][x]].str.data();
}

const tile_map::pattern_index_entry& tile_map::get_tile_entry(int y, int x) const
{
	if(x < 0 || y < 0 || y >= map_.size() || x >= map_[y].size()) {
		return pattern_index_.front();
	}

	return pattern_index_[map_[y][x]];
}

namespace {
struct cstr_less {
	bool operator()(const char* a, const char* b) const {
		return strcmp(a, b) < 0;
	}
};

typedef std::map<const char*, std::vector<const tile_pattern*>, cstr_less> tile_pattern_cache_map;
struct tile_pattern_cache {
	tile_pattern_cache_map cache;
};

}

int tile_map::get_variations(int x, int y) const
{
	x -= xpos_/TileSize;
	y -= ypos_/TileSize;
	tile_pattern_cache cache;
	bool face_right = false;
	const tile_pattern* p = get_matching_pattern(x, y, cache, &face_right);
	if(p == NULL) {
		return 0;
	}

	return p->variations.size();
}

int tile_map::variation(int x, int y) const
{
	if(x < 0 || y < 0 || y >= variations_.size() || x >= variations_[y].size()) {
		return 0;
	}

	return variations_[y][x];
}

void tile_map::flip_variation(int x, int y, int delta)
{
	const int variations = get_variations(x, y);
	if(variations <= 1) {
		return;
	}

	x -= xpos_/TileSize;
	y -= ypos_/TileSize;

	if(y >= variations_.size()) {
		variations_.resize(y + 1);
	}

	std::vector<int>& row = variations_[y];
	if(x >= row.size()) {
		row.resize(x + 1);
	}

	row[x] += delta;
	while(row[x] < 0) {
		row[x] += variations;
	}

	while(row[x] >= variations) {
		row[x] = row[x]%variations;
	}
}

void tile_map::prepare_for_copy_to_worker_thread()
{
#ifndef NO_EDITOR
	node_ = variant();
#endif
}

namespace {

//This function is a random hash. It takes an (x,y) position as well as a
//zorder, and then a 'n' integer which is used to identify the number of the
//pattern. The idea is that for the same input it always gives the same output,
//but the output appears random, and there is a complete avalanche effect --
//i.e. any change in the input results in a completely different output.
//
//The function returns a number in the range [0,99].
int random_hash(int x, int y, int z, int n)
{
	//The implementation is simply four arrays of hard coded random numbers.
	//We index our input into each of the arrays, summing the results and
	//returning. This does have the implication that
	//random_hash(x,y,z,n) == random_hash(x+k,y,z,n) where k is the size
	//of the array. However, this should be acceptable.
	static const unsigned int x_rng[] = {31,29,62,59,14,2,64,50,17,74,72,47,69,92,89,79,5,21,36,83,81,35,58,44,88,5,51,4,23,54,87,39,44,52,86,6,95,23,72,77,48,97,38,20,45,58,86,8,80,7,65,0,17,85,84,11,68,19,63,30,32,57,62,70,50,47,41,0,39,24,14,6,18,45,56,54,77,61,2,68,92,20,93,68,66,24,5,29,61,48,5,64,39,91,20,69,39,59,96,33,81,63,49,98,48,28,80,96,34,20,65,84,19,87,43,4,54,21,35,54,66,28,42,22,62,13,59,42,17,66,67,67,55,65,20,68,75,62,58,69,95,50,34,46,56,57,71,79,80,47,56,31,35,55,95,60,12,76,53,52,94,90,72,37,8,58,9,70,5,89,61,27,28,51,38,58,60,46,25,86,46,0,73,7,66,91,13,92,78,58,28,2,56,3,70,81,19,98,50,50,4,0,57,49,36,4,51,78,10,7,26,44,28,43,53,56,53,13,6,71,95,36,87,49,62,63,30,45,75,41,59,51,77,0,72,28,24,25,35,4,4,56,87,23,25,21,4,58,57,19,4,97,78,31,38,80,};
	static const unsigned int y_rng[] = {91,80,42,50,40,7,82,67,81,3,54,31,74,49,30,98,49,93,7,62,10,4,67,93,28,53,74,20,36,62,54,64,60,33,85,31,31,6,22,2,29,16,63,46,83,78,2,11,18,39,62,56,36,56,0,39,26,45,72,46,11,4,49,13,24,40,47,51,17,99,80,64,27,21,20,4,1,37,33,25,9,87,87,36,44,4,77,72,23,73,76,47,28,41,94,69,48,81,82,0,41,7,90,75,4,37,8,86,64,14,1,89,91,0,29,44,35,36,78,89,40,86,19,5,39,52,24,42,44,74,71,96,78,29,54,72,35,96,86,11,49,96,90,79,79,70,50,36,15,50,34,31,86,99,77,97,19,15,32,54,58,87,79,85,49,71,91,78,98,64,18,82,55,66,39,35,86,63,87,41,25,73,79,99,43,2,29,16,53,42,43,26,45,45,95,70,35,75,55,73,58,62,45,86,46,90,12,10,72,88,29,77,10,8,92,72,22,3,1,49,5,51,41,86,65,66,95,23,60,87,64,86,55,30,48,76,21,76,43,52,52,23,40,64,69,43,69,97,34,39,18,87,46,8,96,50,};
	static const unsigned int z_rng[] = {91,80,42,50,40,7,82,67,81,3,54,31,74,49,30,98,49,93,7,62,10,4,67,93,28,53,74,20,36,62,54,64,60,33,85,31,31,6,22,2,29,16,63,46,83,78,2,11,18,39,62,56,36,56,0,39,26,45,72,46,11,4,49,13,24,40,47,51,17,99,80,64,27,21,20,4,1,37,33,25,9,87,87,36,44,4,77,72,23,73,76,47,28,41,94,69,48,81,82,0,41,7,90,75,4,37,8,86,64,14,1,89,91,0,29,44,35,36,78,89,40,86,19,5,39,52,24,42,44,74,71,96,78,29,54,72,35,96,86,11,49,96,90,79,79,70,50,36,15,50,34,31,86,99,77,97,19,15,32,54,58,87,79,85,49,71,91,78,98,64,18,82,55,66,39,35,86,63,87,41,25,73,79,99,43,2,29,16,53,42,43,26,45,45,95,70,35,75,55,73,58,62,45,86,46,90,12,10,72,88,29,77,10,8,92,72,22,3,1,49,5,51,41,86,65,66,95,23,60,87,64,86,55,30,48,76,21,76,43,52,52,23,40,64,69,43,69,97,34,39,18,87,46,8,96,50,};
	static const unsigned int n_rng[] = {28,61,82,84,31,6,65,20,50,87,22,52,92,28,39,81,54,48,21,10,5,45,32,62,51,46,60,65,11,67,59,50,48,73,42,40,30,88,33,59,88,33,32,7,15,74,38,6,0,76,66,29,32,40,22,62,62,39,17,24,64,75,35,75,99,57,43,98,6,16,63,72,62,39,10,48,48,82,88,94,26,79,49,98,4,40,8,54,67,85,81,66,69,46,27,76,45,68,76,49,94,59,21,74,26,36,97,34,22,98,84,33,7,17,43,56,75,51,32,74,23,67,29,43,32,89,28,50,11,37,30,2,81,6,4,83,99,7,76,46,32,12,3,33,83,19,0,47,19,32,59,97,92,71,45,93,5,55,53,99,77,96,49,90,16,98,99,6,22,14,5,47,10,49,42,61,7,33,21,84,68,19,22,47,28,8,87,66,65,74,21,21,50,70,64,97,29,54,96,94,42,18,88,79,72,66,93,92,3,93,22,62,73,63,69,27,35,45,27,1,88,23,78,10,61,26,70,67,11,43,16,43,99,42,39,43,89,3,84,90,65,49,67,71,60,45,38,95,32,27,7,30,77,75,24,46,};

	return (
	  x_rng[x%(sizeof(x_rng)/sizeof(*x_rng))] +
	  y_rng[y%(sizeof(y_rng)/sizeof(*y_rng))] +
	  z_rng[z%(sizeof(z_rng)/sizeof(*z_rng))] +
	  n_rng[n%(sizeof(n_rng)/sizeof(*n_rng))]);
}

}

void tile_map::apply_matching_multi_pattern(int& x, int y,
  const multi_tile_pattern& pattern,
  point_map<level_object*>& mapping,
  std::map<point_zorder, level_object*>& different_zorder_mapping) const
{

	if(pattern.chance() < 100 && random_hash(x, y, zorder_, 0)%100 > pattern.chance()) {
		return;
	}

	bool match = true;
	for(int n = 0; n != pattern.try_order().size() && match; ++n) {
		const int xpos = pattern.try_order()[n].loc.x;
		const int ypos = pattern.try_order()[n].loc.y;

		const pattern_index_entry& entry = get_tile_entry(y + ypos, x + xpos);
		if(std::find(entry.matching_patterns.begin(), entry.matching_patterns.end(), pattern.tile_at(xpos, ypos).re) == entry.matching_patterns.end()) {
			//the regex doesn't match
			match = false;

			//because this didn't match, we can skip over all patterns that
			//have the same pattern repeating.
			x += pattern.try_order()[n].run_length;
			break;
		}

		if(pattern.tile_at(xpos, ypos).tiles.empty() == false && mapping.get(point(x + xpos, y + ypos))) {
			//there is already another pattern filling this tile.
			match = false;
			break;
		}
	}

	if(match) {
		const int hash = random_hash(x, y, zorder_, 0);
		const multi_tile_pattern& chosen_pattern = pattern.choose_random_alternative(hash);
		for(int xpos = 0; xpos < chosen_pattern.width() && match; ++xpos) {
			for(int ypos = 0; ypos < chosen_pattern.height() && match; ++ypos) {
				const multi_tile_pattern::tile_info& info = chosen_pattern.tile_at(xpos, ypos);
				foreach(const multi_tile_pattern::tile_entry& entry, info.tiles) {
					level_object* ob = entry.tile.get();
					if(ob) {
						if(entry.zorder == INT_MIN || entry.zorder == zorder_) {
							mapping.insert(point(x + xpos, y + ypos), ob);
						} else {
							different_zorder_mapping[point_zorder(point(x + xpos, y + ypos), entry.zorder)] = ob;
						}
					}
				}
			}
		}
	}
}

void tile_map::build_tiles(std::vector<level_tile>* tiles, const rect* r) const
{
	const int begin_time = SDL_GetTicks();
	//std::cerr << "build tiles... " << patterns_.size() << "/" << patterns.size() << "\n";
	int width = 0;
	foreach(const std::vector<int>& row, map_) {
		if(row.size() > width) {
			width = row.size();
		}
	}

	point_map<level_object*> multi_pattern_matches;
	std::map<point_zorder, level_object*> different_zorder_multi_pattern_matches;

	//std::cerr << "MULTIPATTERNS: " << multi_patterns_.size() << "/" << multi_tile_pattern::get_all().size() << "\n";
	foreach(const multi_tile_pattern* p, multi_patterns_) {
		for(int y = -p->height(); y < static_cast<int>(map_.size()) + p->height(); ++y) {
			const int ypos = ypos_ + y*TileSize;

			if(r && ypos < r->y() || r && ypos > r->y2()) {
				continue;
			}

			for(int x = -p->width(); x < width + p->width(); ++x) {
				apply_matching_multi_pattern(x, y, *p, multi_pattern_matches, different_zorder_multi_pattern_matches);
			}
		}
	}

	//add all tiles in different zorders to our own.
	for(std::map<point_zorder, level_object*>::const_iterator i = different_zorder_multi_pattern_matches.begin(); i != different_zorder_multi_pattern_matches.end(); ++i) {
		const level_object* obj = i->second;
		const int x = i->first.first.x;
		const int y = i->first.first.y;

		const int xpos = xpos_ + x*TileSize;
		const int ypos = ypos_ + y*TileSize;

		level_tile t;
		t.x = xpos;
		t.y = ypos;
		t.layer_from = zorder_;
		t.zorder = i->first.second;
		t.object = i->second;
		t.face_right = false;
		tiles->push_back(t);
	}

	tile_pattern_cache cache;

	int ntiles = 0;
	for(int y = -g_tile_pattern_search_border; y < static_cast<int>(map_.size()) + g_tile_pattern_search_border; ++y) {
		const int ypos = ypos_ + y*TileSize;

		if(r && ypos < r->y() || r && ypos > r->y2()) {
			continue;
		}

		for(int x = -g_tile_pattern_search_border; x < width + g_tile_pattern_search_border; ++x) {
			const int xpos = xpos_ + x*TileSize;

			const level_object* obj = multi_pattern_matches.get(point(x, y));
			if(obj) {
				level_tile t;
				t.x = xpos;
				t.y = ypos;
				t.layer_from = zorder_;
				t.zorder = zorder_;
				t.object = obj;
				t.face_right = false;
				tiles->push_back(t);
				continue;
			}

			bool face_right = true;
			const tile_pattern* p = get_matching_pattern(x, y, cache, &face_right);
			if(p == NULL) {
				continue;
			}

			if(r && xpos < r->x() || r && xpos > r->x2()) {
				continue;
			}

			++ntiles;

			level_tile t;
			t.x = xpos;
			t.y = ypos;
			t.layer_from = zorder_;
			t.zorder = zorder_;

			int variation_num = variation(x, y);
			if(variation_num >= p->variations.size()) {
				variation_num = 0;
			}
			assert(p->variations[variation_num]);
			t.object = p->variations[variation_num].get();
			t.face_right = face_right;
			if(t.object->flipped()) {
				t.face_right = !t.face_right;
			}
			tiles->push_back(t);

			foreach(const tile_pattern::added_tile& a, p->added_tiles) {
				//std::cerr << "added_tile\n";
				level_tile t;
				t.x = xpos;
				t.y = ypos;
				t.layer_from = zorder_;
				t.zorder = zorder_;
				if(a.zorder) {
					t.zorder = a.zorder;
				}
				t.object = a.object.get();
				t.face_right = face_right;
				if(t.object->flipped()) {
					t.face_right = !t.face_right;
				}

				tiles->push_back(t);
			}
		}
	}
	//std::cerr << "done build tiles: " << ntiles << " " << (SDL_GetTicks() - begin_time) << "\n";
}

const tile_pattern* tile_map::get_matching_pattern(int x, int y, tile_pattern_cache& cache, bool* face_right) const
{

	if (!*get_tile(y, x) &&
	    !*get_tile(y-1, x) &&
		!*get_tile(y+1, x) &&
		!*get_tile(y, x-1) &&
		!*get_tile(y, x+1)) {
		return NULL;
	}

	const int xpos = xpos_ + x*TileSize;

	filter_callable callable(*this, x, y);

	const char* current_tile = get_tile(y,x);

	//we build a cache of all of the patterns which have some chance of
	//matching the current tile.
	tile_pattern_cache_map::iterator itor = cache.cache.find(current_tile);
	if(itor == cache.cache.end()) {
		itor = cache.cache.insert(std::pair<const char*,std::vector<const tile_pattern*> >(current_tile, std::vector<const tile_pattern*>())).first;
		foreach(const tile_pattern* p, get_patterns()) {
			if(!p->current_tile_pattern->empty() && !boost::regex_match(current_tile, current_tile + strlen(current_tile), *p->current_tile_pattern)) {
				continue;
			}

			itor->second.push_back(&*p);
		}
	}

	const std::vector<const tile_pattern*>& matching_patterns = itor->second;

	foreach(const tile_pattern* ptr, matching_patterns) {
		const tile_pattern& p = *ptr;
		if(p.filter_formula && p.filter_formula->execute(callable).as_bool() == false) {
			continue;
		}

		bool match = true;
		foreach(const tile_pattern::surrounding_tile& t, p.surrounding_tiles) {
			const pattern_index_entry& entry = get_tile_entry(y + t.yoffset, x + t.xoffset);
			if(std::find(entry.matching_patterns.begin(), entry.matching_patterns.end(), t.pattern) == entry.matching_patterns.end()) {
				match = false;
				break;
			}
		}

		if(match) {
			if(p.empty) {
				return NULL;
			}

			*face_right = false;
			return &p;
		}

		if(p.reverse) {
			match = true;

			foreach(const tile_pattern::surrounding_tile& t, p.surrounding_tiles) {
				const pattern_index_entry& entry = get_tile_entry(y + t.yoffset, x - t.xoffset);
				if(std::find(entry.matching_patterns.begin(), entry.matching_patterns.end(), t.pattern) == entry.matching_patterns.end()) {
					match = false;
					break;
				}
			}
		}

		if(match) {
			if(p.empty) {
				return NULL;
			}

			*face_right = true;
			return &p;
		}
	}

	return NULL;
}

bool tile_map::set_tile(int xpos, int ypos, const std::string& str)
{
	if(str.empty() && (xpos < xpos_ || ypos < ypos_)) {
		return false;
	}

	tile_string empty_tile;
	std::fill(empty_tile.begin(), empty_tile.end(), '\0');
	if(xpos < xpos_) {
		const int add_tiles = abs((xpos - xpos_)/TileSize);
		std::vector<int> insert(add_tiles, get_pattern_index_entry(empty_tile));
		foreach(std::vector<int>& row, map_) {
			row.insert(row.begin(), insert.begin(), insert.end());
		}

		xpos_ = xpos;
	}

	while(ypos < ypos_) {
		map_.insert(map_.begin(), std::vector<int>());
		ypos_ -= TileSize;
	}

	const int x = (xpos - xpos_)/TileSize;
	const int y = (ypos - ypos_)/TileSize;
	assert(x >= 0);
	assert(y >= 0);
	if(map_.size() <= y) {
		map_.resize(y + 1);
	}

	std::vector<int>& row = map_[y];

	tile_string tstr;
	memset(&tstr[0], 0, tstr.size());
	std::string::const_iterator end = str.end();
	if(str.size() > 3) {
		end = str.begin() + 3;
	}

	std::copy(str.begin(), end, tstr.begin());

	const int index = get_pattern_index_entry(tstr);
	if(row.size() > x && row[x] == index) {
		return false;
	}

	const int empty_index = get_pattern_index_entry(empty_tile);
	while(row.size() <= x) {
		row.push_back(empty_index);
	}

	row[x] = index;

	// clear out variations info
	if (y < variations_.size() && x < variations_[y].size()) {
		variations_[y][x] = 0;
	}
	return true;
}

int tile_map::get_pattern_index_entry(const tile_string& str) {
	int index = 0;
	foreach(pattern_index_entry& e, pattern_index_) {
		if(strcmp(e.str.data(), str.data()) == 0) {
			return index;
		}
		++index;
	}

	pattern_index_.push_back(pattern_index_entry());
	pattern_index_.back().str = str;
	build_patterns();
	return index;
}

max_stars_repo_name: sweetkristas/anura

max_issues_repo_name: sweetkristas/anura

max_forks_repo_name: sweetkristas/anura


text:
#pragma once

#include <string>

#include <boost/variant.hpp>

#include "blackhole/attribute.hpp"
#include "blackhole/detail/config/underlying.hpp"
#include "blackhole/expression/helper.hpp"
#include "blackhole/filter.hpp"

namespace blackhole {

namespace expression {

template<typename T>
class has_attribute_visitor : public boost::static_visitor<bool>{
public:
    bool operator()(const T&) const {
        return true;
    }

    template<typename Other>
    bool operator()(const Other&) const {
        return false;
    }
};

template<typename T>
struct has_attr_action_t : public aux::LogicMixin<has_attr_action_t<T>> {
    typedef typename blackhole::aux::underlying_type<T>::type underlying_type;

    const std::string name;

    has_attr_action_t(const std::string& name) : name(name) {}

    bool operator()(const attribute::set_view_t& attributes) const {
        static has_attribute_visitor<underlying_type> visitor;

        if (auto attribute = attributes.find(name)) {
            return boost::apply_visitor(visitor, attribute->value);
        }

        return false;
    }
};

// For dynamic attributes.
template<typename T>
has_attr_action_t<T> has_attr(const std::string& name) {
    return has_attr_action_t<T>(name);
}

// For static attributes.
template<typename T>
has_attr_action_t<typename T::type> has_attr(const T&) {
    return has_attr<typename T::type>(std::string(T::name()));
}

} // namespace expression

} // namespace blackhole

max_stars_repo_name: tomzhang/blackhole

max_issues_repo_name: tomzhang/blackhole

max_forks_repo_name: tomzhang/blackhole


text:
//
// Copyright (c) 2021 Richard Hodges (hodges.r@gmail.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef NEW_YEAR_2021_CONFIG_HPP
#define NEW_YEAR_2021_CONFIG_HPP

#include <boost/asio.hpp>
#include <boost/asio/experimental/as_single.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/ssl.hpp>
#include <boost/variant2/variant.hpp>

using boost::variant2::monostate;
using boost::variant2::variant;

namespace asio  = boost::asio;
namespace ssl   = boost::asio::ssl;
namespace beast = boost::beast;

using boost::system::error_code;
using boost::system::system_error;

namespace net
{
using namespace asio;

using io_executor = io_context::executor_type;

#ifdef MULTI_THREADED

using io_strand = strand< io_executor >;

inline io_strand
new_strand(io_executor const &src)
{
    return net::make_strand(src);
}

inline io_strand
new_strand(io_strand const &src)
{
    return new_strand(src.get_inner_executor());
}

#else

using io_strand = io_context::executor_type;

inline io_strand
new_strand(io_executor const &src)
{
    return src;
}

#endif

inline io_executor
to_io_executor(any_io_executor const &src)
{
    if (auto e = src.target< io_context::executor_type >())
    {
        return *e;
    }
    else if (auto s = src.target< strand< io_context::executor_type > >())
    {
        return s->get_inner_executor();
    }
    else
    {
        assert(!"unknown executor type");
        std::abort();
    }
}
}   // namespace net
#endif   // NEW_YEAR_2021_CONFIG_HPP


text:
/*
	Copyright (C) 2003-2014 by David White <davewx7@gmail.com>

	This software is provided 'as-is', without any express or implied
	warranty. In no event will the authors be held liable for any damages
	arising from the use of this software.

	Permission is granted to anyone to use this software for any purpose,
	including commercial applications, and to alter it and redistribute it
	freely, subject to the following restrictions:

	   1. The origin of this software must not be misrepresented; you must not
	   claim that you wrote the original software. If you use this software
	   in a product, an acknowledgement in the product documentation would be
	   appreciated but is not required.

	   2. Altered source versions must be plainly marked as such, and must not be
	   misrepresented as being the original software.

	   3. This notice may not be removed or altered from any source
	   distribution.
*/

#pragma once

#include <set>
#include <string>
#include <vector>

#include <boost/uuid/uuid.hpp>

#include "formula.hpp"
#include "formula_callable_definition.hpp"
#include "variant.hpp"
#include "wml_formula_callable.hpp"

#ifdef USE_LUA
#include "lua_iface.hpp"
#endif

namespace game_logic
{
	class FormulaClass;

	FormulaCallableDefinitionPtr get_class_definition(const std::string& name);

	bool is_class_derived_from(const std::string& derived, const std::string& base);

	class FormulaObject : public game_logic::WmlSerializableFormulaCallable
	{
		static void visitVariantsInternal(const variant& v, const std::function<void (variant)>& fn, std::vector<FormulaObject*>* seen);
		static void visitVariantsInternal(const variant& v, const std::function<void (FormulaObject*)>& fn, std::vector<FormulaObject*>* seen);
	public:
		static void visitVariants(const variant& v, const std::function<void (variant)>& fn);
		static void visitVariantObjects(const variant& v, const std::function<void (FormulaObject*)>& fn);
		static void mapObjectIntoDifferentTree(variant& v, const std::map<FormulaObject*, FormulaObject*>& mapping, std::set<FormulaObject*>& seen);

		void update(FormulaObject& updated);

		static variant deepClone(variant v);
		static variant deepClone(variant v, std::map<FormulaObject*,FormulaObject*>& mapping);

		static void deepDestroy(variant v);
		static void deepDestroy(variant v, std::set<FormulaObject*>& seen);

		static variant generateDiff(variant a, variant b);
		void applyDiff(variant delta);

		static void reloadClasses();
		static void loadAllClasses();
		static void tryLoadClass(const std::string& name);

		static ffl::IntrusivePtr<FormulaObject> create(const std::string& type, variant args=variant());

		bool isA(const std::string& class_name) const;
		const std::string& getClassName() const;

		//construct with data representing private/internal represenation.
		explicit FormulaObject(variant data);
		virtual ~FormulaObject();

		ffl::IntrusivePtr<FormulaObject> clone() const;

		void validate() const;

		std::string write_id() const;

		void surrenderReferences(GarbageCollector* collector) override;
		std::string debugObjectName() const override;

		variant_type_ptr getPropertySetType(const std::string& key) const;

		bool getConstantValue(const std::string& id, variant* result) const override;

#if defined(USE_LUA)
		const ffl::IntrusivePtr<lua::LuaContext> & get_lua_context() const {
			return lua_ptr_;
		}
#endif
	private:
		//construct with type and constructor parameters.
		//Don't call directly, use create() instead.
		explicit FormulaObject(const std::string& type, variant args=variant());
		void callConstructors(variant args);

		variant serializeToWml() const override;

		variant getValue(const std::string& key) const override;
		variant getValueBySlot(int slot) const override;
		void setValue(const std::string& key, const variant& value) override;
		void setValueBySlot(int slot, const variant& value) override;

		void getInputs(std::vector<FormulaInput>* inputs) const override;

		bool new_in_update_;
		bool orphaned_;

		ffl::IntrusivePtr<game_logic::FormulaCallable> builtin_base_;

		//overrides of the class's read-only properties.
		std::vector<FormulaPtr> property_overrides_;

		std::vector<variant> variables_;

		ffl::IntrusivePtr<const FormulaClass> class_;

		// for lua integration
#if defined(USE_LUA)
		void init_lua();
		ffl::IntrusivePtr<lua::LuaContext> lua_ptr_;
#endif

		variant tmp_value_;

		//if this is non-zero, then private_data_ will be exposed via getValue.
		mutable int private_data_;
	};

	typedef ffl::IntrusivePtr<FormulaObject> FormulaObjectPtr;

	bool formula_class_valid(const std::string& type);

	FormulaCallableDefinitionPtr get_library_definition();
	FormulaCallablePtr get_library_object();

	bool can_load_library_instance(const std::string& id);
	FormulaCallablePtr get_library_instance(const std::string& id);

#if defined(USE_LUA)
	class formula_class_unit_test_helper {
	public:
		formula_class_unit_test_helper();
		~formula_class_unit_test_helper();
		void add_class_defn(const std::string & name, const variant & node);
		//friend void TEST_lua_in_ffl_objects();
	};
#endif
}

max_stars_repo_name: gamobink/anura

max_issues_repo_name: gamobink/anura

max_forks_repo_name: gamobink/anura


text:
//  (C) Copyright Raffi Enficiaud 2015
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//
//  See http://www.boost.org/libs/test for the library home page.
//
//  Tests some compilation troubleshooting issues with the windows headers (eg min/max macros)
// ***************************************************************************

#define BOOST_TEST_MODULE test_windows_headers

#include <boost/config.hpp>
#ifdef BOOST_WINDOWS
#include <windows.h>
#endif

#include <boost/test/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp> // Extra test tool for FP comparison.

BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES( test, 2 )

BOOST_AUTO_TEST_CASE( test )
{
    // produces an error
    BOOST_TEST(1 == 0);

    // this is added in order to compile floating point relative code as well
    // which might have trouble compiling if system headers are included (as for
    // boost.thread, eg. for std::min).
    BOOST_CHECK_CLOSE(1.1, 1.2, 1e-5);
}


text:
/*
 Copyright (C) 2016 Quaternion Risk Management Ltd
 All rights reserved.

 This file is part of ORE, a free-software/open-source library
 for transparent pricing and risk analysis - http://opensourcerisk.org

 ORE is free software: you can redistribute it and/or modify it
 under the terms of the Modified BSD License.  You should have received a
 copy of the license along with this program.
 The license is also available online at <http://opensourcerisk.org>

 This program is distributed on the basis that it will form a useful
 contribution to risk analytics and model standardisation, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
*/

#include <boost/algorithm/string.hpp>
#include <ored/configuration/swaptionvolcurveconfig.hpp>
#include <ored/utilities/indexparser.hpp>
#include <ored/utilities/parsers.hpp>
#include <ored/utilities/to_string.hpp>
#include <ql/errors.hpp>

namespace ore {
namespace data {

std::ostream& operator<<(std::ostream& out, SwaptionVolatilityCurveConfig::VolatilityType t) {
    switch (t) {
    case SwaptionVolatilityCurveConfig::VolatilityType::Lognormal:
        return out << "RATE_LNVOL";
    case SwaptionVolatilityCurveConfig::VolatilityType::Normal:
        return out << "RATE_NVOL";
    case SwaptionVolatilityCurveConfig::VolatilityType::ShiftedLognormal:
        return out << "RATE_SLNVOL";
    default:
        QL_FAIL("unknown VolatilityType(" << Integer(t) << ")");
    }
}

SwaptionVolatilityCurveConfig::SwaptionVolatilityCurveConfig(
    const string& curveID, const string& curveDescription, const Dimension& dimension,
    const VolatilityType& volatilityType, const bool extrapolate, const bool flatExtrapolation,
    const vector<Period>& optionTenors, const vector<Period>& swapTenors, const DayCounter& dayCounter,
    const Calendar& calendar, const BusinessDayConvention& businessDayConvention, const string& shortSwapIndexBase,
    const string& swapIndexBase, const vector<Period>& smileOptionTenors, const vector<Period>& smileSwapTenors,
    const vector<Real>& smileSpreads)
    : CurveConfig(curveID, curveDescription), dimension_(dimension), volatilityType_(volatilityType),
      extrapolate_(extrapolate), flatExtrapolation_(flatExtrapolation), optionTenors_(optionTenors),
      swapTenors_(swapTenors), dayCounter_(dayCounter), calendar_(calendar),
      businessDayConvention_(businessDayConvention), shortSwapIndexBase_(shortSwapIndexBase),
      swapIndexBase_(swapIndexBase), smileOptionTenors_(smileOptionTenors), smileSwapTenors_(smileSwapTenors),
      smileSpreads_(smileSpreads) {

    QL_REQUIRE(dimension == Dimension::ATM || dimension == Dimension::Smile, "Invalid dimension");

    if (dimension != Dimension::Smile) {
        QL_REQUIRE(smileOptionTenors.size() == 0 && smileSwapTenors.size() == 0 && smileSpreads.size() == 0,
                   "Smile tenors/strikes/spreads should only be set when dim=Smile");
    }
}

const vector<string>& SwaptionVolatilityCurveConfig::quotes() {

    if (quotes_.size() == 0) {
        std::vector<string> tokens;
        split(tokens, swapIndexBase_, boost::is_any_of("-"));

        Currency ccy = parseCurrency(tokens[0]);

        std::stringstream ssBase;
        ssBase << "SWAPTION/" << volatilityType_ << "/" << ccy.code() << "/";
        string base = ssBase.str();

        if (dimension_ == Dimension::ATM) {
            for (auto o : optionTenors_) {
                for (auto s : swapTenors_) {
                    std::stringstream ss;
                    ss << base << to_string(o) << "/" << to_string(s) << "/ATM";
                    quotes_.push_back(ss.str());
                }
            }

        } else {
            for (auto o : smileOptionTenors_) {
                for (auto s : smileSwapTenors_) {
                    for (auto sp : smileSpreads_) {
                        std::stringstream ss;
                        ss << base << to_string(o) << "/" << to_string(s) << "/Smile/" << to_string(sp);
                        quotes_.push_back(ss.str());
                    }
                }
            }
        }
    }
    return quotes_;
}

void SwaptionVolatilityCurveConfig::fromXML(XMLNode* node) {
    XMLUtils::checkNode(node, "SwaptionVolatility");

    curveID_ = XMLUtils::getChildValue(node, "CurveId", true);
    curveDescription_ = XMLUtils::getChildValue(node, "CurveDescription", true);

    string dim = XMLUtils::getChildValue(node, "Dimension", true);
    if (dim == "ATM") {
        dimension_ = Dimension::ATM;
    } else if (dim == "Smile") {
        dimension_ = Dimension::Smile;
    } else {
        QL_FAIL("Dimension " << dim << " not recognized");
    }

    string volType = XMLUtils::getChildValue(node, "VolatilityType", true);
    if (volType == "Normal") {
        volatilityType_ = VolatilityType::Normal;
    } else if (volType == "Lognormal") {
        volatilityType_ = VolatilityType::Lognormal;
    } else if (volType == "ShiftedLognormal") {
        volatilityType_ = VolatilityType::ShiftedLognormal;
    } else {
        QL_FAIL("Volatility type " << volType << " not recognized");
    }

    string extr = XMLUtils::getChildValue(node, "Extrapolation", true);
    extrapolate_ = true;
    flatExtrapolation_ = true;
    if (extr == "Linear") {
        flatExtrapolation_ = false;
    } else if (extr == "Flat") {
        flatExtrapolation_ = true;
    } else if (extr == "None") {
        extrapolate_ = false;
    } else {
        QL_FAIL("Extrapolation " << extr << " not recognized");
    }

    optionTenors_ = XMLUtils::getChildrenValuesAsPeriods(node, "OptionTenors", true);
    swapTenors_ = XMLUtils::getChildrenValuesAsPeriods(node, "SwapTenors", true);

    string cal = XMLUtils::getChildValue(node, "Calendar", true);
    calendar_ = parseCalendar(cal);

    string dc = XMLUtils::getChildValue(node, "DayCounter", true);
    dayCounter_ = parseDayCounter(dc);

    string bdc = XMLUtils::getChildValue(node, "BusinessDayConvention", true);
    businessDayConvention_ = parseBusinessDayConvention(bdc);

    shortSwapIndexBase_ = XMLUtils::getChildValue(node, "ShortSwapIndexBase", true);
    swapIndexBase_ = XMLUtils::getChildValue(node, "SwapIndexBase", true);

    // optional smile stuff
    smileOptionTenors_ = XMLUtils::getChildrenValuesAsPeriods(node, "SmileOptionTenors");
    smileSwapTenors_ = XMLUtils::getChildrenValuesAsPeriods(node, "SmileSwapTenors");
    smileSpreads_ = XMLUtils::getChildrenValuesAsDoublesCompact(node, "SmileSpreads");
}

XMLNode* SwaptionVolatilityCurveConfig::toXML(XMLDocument& doc) {
    XMLNode* node = doc.allocNode("SwaptionVolatility");

    XMLUtils::addChild(doc, node, "CurveId", curveID_);
    XMLUtils::addChild(doc, node, "CurveDescription", curveDescription_);

    if (dimension_ == Dimension::ATM) {
        XMLUtils::addChild(doc, node, "Dimension", "ATM");
    } else if (dimension_ == Dimension::Smile) {
        XMLUtils::addChild(doc, node, "Dimension", "Smile");
    } else {
        QL_FAIL("Unkown Dimension in SwaptionVolatilityCurveConfig::toXML()");
    }

    if (volatilityType_ == VolatilityType::Normal) {
        XMLUtils::addChild(doc, node, "VolatilityType", "Normal");
    } else if (volatilityType_ == VolatilityType::Lognormal) {
        XMLUtils::addChild(doc, node, "VolatilityType", "Lognormal");
    } else if (volatilityType_ == VolatilityType::ShiftedLognormal) {
        XMLUtils::addChild(doc, node, "VolatilityType", "ShiftedLognormal");
    } else {
        QL_FAIL("Unknown VolatilityType in SwaptionVolatilityCurveConfig::toXML()");
    }

    string extr_str = flatExtrapolation_ ? "Flat" : "Linear";
    if (!extrapolate_)
        extr_str = "None";
    XMLUtils::addChild(doc, node, "Extrapolation", extr_str);

    XMLUtils::addGenericChildAsList(doc, node, "OptionTenors", optionTenors_);
    XMLUtils::addGenericChildAsList(doc, node, "SwapTenors", swapTenors_);
    XMLUtils::addChild(doc, node, "Calendar", to_string(calendar_));
    XMLUtils::addChild(doc, node, "DayCounter", to_string(dayCounter_));
    XMLUtils::addChild(doc, node, "BusinessDayConvention", to_string(businessDayConvention_));
    XMLUtils::addChild(doc, node, "ShortSwapIndexBase", shortSwapIndexBase_);
    XMLUtils::addChild(doc, node, "SwapIndexBase", swapIndexBase_);

    if (dimension_ == Dimension::Smile) {
        XMLUtils::addGenericChildAsList(doc, node, "SmileOptionTenors", smileOptionTenors_);
        XMLUtils::addGenericChildAsList(doc, node, "SmileSwapTenors", smileSwapTenors_);
        XMLUtils::addGenericChildAsList(doc, node, "SmileSpreads", smileSpreads_);
    }

    return node;
}
} // namespace data
} // namespace ore

max_stars_repo_name: mrslezak/Engine

max_issues_repo_name: mrslezak/Engine

max_forks_repo_name: mrslezak/Engine


text:
#ifndef STAN_MATH_PRIM_MAT_PROB_ORDERED_LOGISTIC_LPMF_HPP
#define STAN_MATH_PRIM_MAT_PROB_ORDERED_LOGISTIC_LPMF_HPP

#include <boost/random/uniform_01.hpp>
#include <boost/random/variate_generator.hpp>
#include <stan/math/prim/scal/fun/inv_logit.hpp>
#include <stan/math/prim/scal/fun/log1m.hpp>
#include <stan/math/prim/scal/fun/log1m_exp.hpp>
#include <stan/math/prim/scal/fun/log1p_exp.hpp>
#include <stan/math/prim/scal/err/check_bounded.hpp>
#include <stan/math/prim/scal/err/check_finite.hpp>
#include <stan/math/prim/scal/err/check_greater.hpp>
#include <stan/math/prim/scal/err/check_less.hpp>
#include <stan/math/prim/scal/err/check_less_or_equal.hpp>
#include <stan/math/prim/scal/err/check_nonnegative.hpp>
#include <stan/math/prim/scal/err/check_positive.hpp>
#include <stan/math/prim/scal/fun/constants.hpp>
#include <stan/math/prim/mat/prob/categorical_rng.hpp>
#include <stan/math/prim/scal/meta/include_summand.hpp>

namespace stan {
  namespace math {

    template <typename T>
    inline T log_inv_logit_diff(const T& alpha, const T& beta) {
      using std::exp;
      return beta + log1m_exp(alpha - beta) - log1p_exp(alpha)
        - log1p_exp(beta);
    }

    /**
     * Returns the (natural) log probability of the specified integer
     * outcome given the continuous location and specified cutpoints
     * in an ordered logistic model.
     *
     * <p>Typically the continous location
     * will be the dot product of a vector of regression coefficients
     * and a vector of predictors for the outcome.
     *
     * @tparam propto True if calculating up to a proportion.
     * @tparam T_loc Location type.
     * @tparam T_cut Cut-point type.
     * @param y Outcome.
     * @param lambda Location.
     * @param c Positive increasing vector of cutpoints.
     * @return Log probability of outcome given location and
     * cutpoints.

     * @throw std::domain_error If the outcome is not between 1 and
     * the number of cutpoints plus 2; if the cutpoint vector is
     * empty; if the cutpoint vector contains a non-positive,
     * non-finite value; or if the cutpoint vector is not sorted in
     * ascending order.
     */
    template <bool propto, typename T_lambda, typename T_cut>
    typename boost::math::tools::promote_args<T_lambda, T_cut>::type
    ordered_logistic_lpmf(int y, const T_lambda& lambda,
                         const Eigen::Matrix<T_cut, Eigen::Dynamic, 1>& c) {
      using std::exp;
      using std::log;

      static const char* function("ordered_logistic");

      int K = c.size() + 1;

      check_bounded(function, "Random variable", y, 1, K);
      check_finite(function, "Location parameter", lambda);
      check_greater(function, "Size of cut points parameter", c.size(), 0);
      for (int i = 1; i < c.size(); ++i)
        check_greater(function, "Cut points parameter", c(i), c(i - 1));

      check_finite(function, "Cut points parameter", c(c.size()-1));
      check_finite(function, "Cut points parameter", c(0));

      // log(1 - inv_logit(lambda))
      if (y == 1)
        return -log1p_exp(lambda - c(0));

      // log(inv_logit(lambda - c(K-3)));
      if (y == K) {
        return -log1p_exp(c(K-2) - lambda);
      }

      // if (2 < y < K) { ... }
      // log(inv_logit(lambda - c(y-2)) - inv_logit(lambda - c(y-1)))
      return log_inv_logit_diff(c(y-2) - lambda,
                                c(y-1) - lambda);
    }

    template <typename T_lambda, typename T_cut>
    typename boost::math::tools::promote_args<T_lambda, T_cut>::type
    ordered_logistic_lpmf(int y, const T_lambda& lambda,
                         const Eigen::Matrix<T_cut, Eigen::Dynamic, 1>& c) {
      return ordered_logistic_lpmf<false>(y, lambda, c);
    }

  }
}
#endif

max_stars_repo_name: yizhang-cae/torsten

max_issues_repo_name: yizhang-cae/torsten

max_forks_repo_name: yizhang-cae/torsten


text:
// MS WARNINGS MACRO
#define _SCL_SECURE_NO_WARNINGS

// Macro: Program Settings
#define ENABLE_NETWORK_IO 1
#define ENABLE_SAVE_IMAGE 0

#include <iostream>
#include <deque>
#include <utility>
#include <boost/noncopyable.hpp>
#include <boost/optional.hpp>
#include <boost/program_options.hpp>
#include <boost/timer/timer.hpp>
#include <boost/range/algorithm.hpp>
#include "data_type.hpp"
#include "image_comparator.hpp"
#include "ppm_reader.hpp"
#include "splitter.hpp"
#include "slide_algorithm/algorithm.hpp"
#include "slide_algorithm/algorithm_2.hpp"
#include "slide_algorithm/truncater.hpp"
#include "slide_algorithm/charles.hpp"
#include "gui.hpp"
#include "network.hpp"
#include "test_tool.hpp"

#include <image_algorithm/yrange2.hpp>
#include <image_algorithm/yrange5.hpp>
#include <image_algorithm/genetic.hpp>
#include <image_algorithm/Murakami.hpp>

class position_manager : boost::noncopyable
{
public:
    typedef question_data position_type;

    position_manager() = default;
    virtual ~position_manager() = default;

    template<class T>
    void add(T && pos, bool const auto__ = false)
    {
        std::lock_guard<std::mutex> lock(mutex_);
        items_.push_back(std::forward<T>(pos));
        auto_.push_back(auto__);
    }

    std::pair<position_type,bool> get()
    {
        std::lock_guard<std::mutex> lock(mutex_);
        auto res = items_.front(); auto res_b = auto_.front();
        items_.pop_front();
        auto_.pop_front();
        return std::make_pair(res, res_b);
    }

    bool empty()
    {
        return items_.empty();
    }

private:
    std::mutex mutex_;
    std::deque<position_type> items_;
    std::deque<bool>          auto_;
};

class analyzer : boost::noncopyable
{
public:
    explicit analyzer(
        boost::shared_ptr<network::client> const& network_client,
        int const problem_id, std::string const& player_id,
        bool const is_auto, bool const is_blur
#if ENABLE_SAVE_IMAGE
        ,std::string const& dir_path = "./saved_image"
#endif
        )
        : client_(network_client), problem_id_(problem_id), player_id_(player_id)
        , is_auto_(is_auto), is_blur_(is_blur)
#if ENABLE_SAVE_IMAGE
        , dir_path_(dir_path)
#endif
    {
    }
    virtual ~analyzer() = default;

    void operator() (position_manager& manager)
    {
        splitter sp;

        // 問題文の入手
        raw_data_ = get_raw_question();
        data_     = get_skelton_question(raw_data_);

        // 2次元画像に分割
        split_image_ = sp.split_image(raw_data_);

        // compare用の画像を作成
        auto const arranged_split = is_blur_ ? sp.split_image_gaussianblur(split_image_) : split_image_;
        auto const image_comp    = comparator_   .image_comp(raw_data_, arranged_split);
		auto const image_comp_dx = comparator_dx_.image_comp(raw_data_, arranged_split);

        // 原画像推測部
        yrange2 yrange2_(raw_data_, image_comp);
        Murakami murakami_(raw_data_, image_comp,true);

        // GUI Threadの起動
        gui::manager gui_thread(
            [this, &manager](std::vector<std::vector<point_type>> const& data)
            {
                // 回答としてマーク -> 回答ジョブに追加
                auto clone = data_.clone();
                clone.block = data;
                manager.add(convert_block(clone));
            });

        // YRange2 -> YRange5 Thread
        boost::thread y_thread(
            [&, this]()
            {
                // YRange2
                auto yrange2_resolve = yrange2_();
                if (!yrange2_resolve.empty())
		        {
                    // Shoot
                    if(is_auto_)
                    {
                        is_auto_ = false;

                        std::cout << "Yrange2 Auto" << std::endl;
                        auto clone = data_.clone();
                        clone.block = yrange2_resolve[0].points;
                        manager.add(convert_block(clone), true);
                    }

                    // GUI
			        for (int y2 = yrange2_resolve.size() - 1; y2 >= 0; --y2)
			        {
                        gui_thread.push_back(
                            boost::bind(gui::make_mansort_window, split_image_, yrange2_resolve.at(y2).points, "yrange2")
                            );
			        }
		        }

                // YRange5
				if (raw_data_.split_num.first > 3 || raw_data_.split_num.second > 3){
					auto yrange5_resolve = yrange5(raw_data_, image_comp)(yrange2_.sorted_matrix());
					if (!yrange5_resolve.empty())
					{
						// Shoot
						if(is_auto_)
						{
							is_auto_ = false;

                            std::cout << "Yrange5 Auto" << std::endl;
							auto clone = data_.clone();
							clone.block = yrange5_resolve[0].points;
							manager.add(convert_block(clone), true);
						}

						// GUI
						for (int y5 = yrange5_resolve.size() - 1; y5 >= 0; --y5)
						{
							gui_thread.push_back(
								boost::bind(gui::make_mansort_window, split_image_, yrange5_resolve.at(y5).points, "yrange5")
								);
						}
					}
				}
            });

        // Murakami Thread
        boost::thread m_thread(
            [&]()
            {
                // Murakami
		    	std::cout << "村上モード" << std::endl;
                auto murakami_resolve = murakami_()[0].points;
				std::vector<std::vector<point_type>> murakami_dx_resolve, murakami_w_resolve, murakami_dx_w_resolve;
				if (!murakami_resolve.empty())
				{
					if(is_auto_)
					{
						is_auto_ = false;

                        std::cout << "Murakami Auto" << std::endl;
						auto clone = data_.clone();
						clone.block = murakami_resolve;
						manager.add(convert_block(clone), true);
					}
					gui_thread.push_back(boost::bind(gui::make_mansort_window, split_image_, murakami_resolve, "Murakami"));
                }
				if (murakami_resolve.empty()){
					std::cout << "デラックス村上モード" << std::endl;
					Murakami murakami_dx(raw_data_, image_comp_dx, true);
					murakami_dx_resolve = murakami_dx()[0].points;
					if (!murakami_dx_resolve.empty())gui_thread.push_back(boost::bind(gui::make_mansort_window, split_image_, murakami_dx_resolve, "Murakami_dx"));
					if (murakami_dx_resolve.empty()){
						std::cout << "W村上モード" << std::endl;
						Murakami murakami_w(raw_data_, image_comp, false);
						murakami_w_resolve = murakami_w()[0].points;
						if (!murakami_w_resolve.empty())gui_thread.push_back(boost::bind(gui::make_mansort_window, split_image_, murakami_w_resolve, "Murakami_w"));
						if (murakami_w_resolve.empty()){
							std::cout << "デラックスW村上モード" << std::endl;
							Murakami murakami_dx_w(raw_data_, image_comp_dx, false);
							murakami_dx_w_resolve = murakami_w()[0].points;
							if (!murakami_dx_w_resolve.empty())gui_thread.push_back(boost::bind(gui::make_mansort_window, split_image_, murakami_dx_w_resolve, "Murakami_dx_w"));
						}
					}
				}
            });

        gui_thread.push_back(
            boost::bind(gui::make_mansort_window, split_image_, "Yor are the sorter!!! Sort this!")
            );

        // 各Threadの待機
        y_thread.join();
        m_thread.join();
        gui_thread.wait_all_window();
    }

    int calc_cost(answer_type const& ans) const
    {
        int cost = (timer_.elapsed().wall / 1000000000) * 100;
        cost += ans.list.size() * data_.cost_select;
        boost::for_each(
            ans.list,
            [&,this](answer_atom const& move)
            {
                cost += move.actions.size() * data_.cost_change;
            });

        return cost;
    }

    std::string submit(answer_type const& ans, bool is_auto = false) const
    {
        std::lock_guard<std::mutex> lock(submit_mutex_);
        int const cost = calc_cost(ans);

	if(is_auto)
	{
            auto submit_result = client_->submit(problem_id_, player_id_, ans);
            return submit_result.get();
	}

        char input;
        std::cout << "★Submit: Cost = " << cost << " [Y/n]★";
        std::cin.get(input);

        if(input == '\n' || input == 'y' || input == 'Y')
        {
            auto submit_result = client_->submit(problem_id_, player_id_, ans);
            return submit_result.get();
        }

        return std::string();
    }

private:
    question_raw_data get_raw_question() const
    {
#if ENABLE_NETWORK_IO
        // ネットワーク通信から
        std::string const data = client_->get_problem(problem_id_).get();
        timer_.start();
#if ENABLE_SAVE_IMAGE
        std::ofstream ofs((boost::format("%s/prob%02d.ppm") % dir_path_ % problem_id_).str(), std::ios::binary);
        ofs << data;
        ofs.close();
#endif
        return ppm_reader().from_data(data);
#else
        // ファイルから
        std::string const path("prob01.ppm");
        timer_.start();
        return ppm_reader().from_file(path);
#endif
    }

    question_data get_skelton_question(question_raw_data const& raw) const
    {
        question_data formed = {
            problem_id_,
            player_id_,
            raw.split_num,
            raw.selectable_num,
            raw.cost.first,
            raw.cost.second,
            std::vector<std::vector<point_type>>()
        };

        return formed;
    }

    question_data convert_block(question_data const& data) const
    {
        auto res = data.clone();

        for(int i = 0; i < data.size.second; ++i)
        {
            for(int j = 0; j < data.size.first; ++j)
            {
                auto const& target = data.block[i][j];
                res.block[target.y][target.x] = point_type{j, i};
		}
        }

        return res;
    }

    int const problem_id_;
    std::string const player_id_;
    bool is_auto_;
    bool const is_blur_;

    question_raw_data raw_data_;
    question_data         data_;
    split_image_type  split_image_;
	split_image_type  split_image_gaussianblur;

    mutable boost::shared_ptr<network::client> client_;
    image_comparator    comparator_;
	image_comparator_dx comparator_dx_;

    // 送信用mutex
    mutable boost::timer::cpu_timer timer_;
    mutable std::mutex submit_mutex_;

#if ENABLE_SAVE_IMAGE
    mutable std::string dir_path_;
#endif
};

void submit_func(question_data question, analyzer const& analyze, bool is_auto)
{
    algorithm algo;
    truncater talgo;

    algorithm_2 algo2;
	charles algo3;

    boost::optional<answer_type> algo_answer;
    boost::optional<answer_type> talgo_answer;
    boost::optional<answer_type> answer;

    auto algo_thread = boost::thread(
        [&algo, &algo_answer, &question]() {
            algo.reset(question);
            algo_answer = algo.get();
        }
    );

    auto talgo_thread = boost::thread(
        [&talgo, &talgo_answer, &question]() {
            talgo.reset(question);
            talgo_answer = talgo.get();
        }
    );

    algo_thread.join();
    talgo_thread.join();

    int algo_score = algo_answer->get_score(question.cost_select, question.cost_change);
    int talgo_score = talgo_answer->get_score(question.cost_select, question.cost_change);
    if (algo_score < talgo_score) {
        answer = algo_answer;
    } else {
        answer = talgo_answer;
    }

    if(answer) // 解が見つかった
    {
#if ENABLE_NETWORK_IO
        // TODO: 前より良くなったら提出など(普通にいらないかも．提出前に目grepしてるわけだし)
		std::cout << "Submit! Wait 5 sec" << std::endl;

        std::string result;

        result = analyze.submit(answer.get(), is_auto);
        std::cout << "Submit Result: " << result << std::endl;

        if(result.find("ACCEPTED") == std::string::npos)
        {
            std::cout << "Submit Result is not \"ACCEPTED\"" << std::endl;
            return;
        }

	// FIXME: 汚いしセグフォする//セグフォはしなくなったらしい
	int wrong_number = std::stoi(result.substr(result.find(" ")));
	if (wrong_number == 0)
	{
		algo2.reset(question);
		auto const answer = algo2.get();
		if (algo2.overlimitcheck()){
			if (answer)
			{
				result = analyze.submit(answer.get());
				std::cout << "Submit Result: " << result << std::endl;
				std::cout << "勝った！" << std::endl;
			}
		}
		else{
			std::cout << "algo2は答えを返しませんでした" << std::endl;
		}

		algo3.reset(question);
		auto const answer2 = algo3.get();
		if (algo3.overlimitcheck()){
			if (answer2)
			{
				result = analyze.submit(answer2.get());
				std::cout << "Submit Result 2 : " << result << std::endl;
				std::cout << "さらに勝った！" << std::endl;
			}
		}
		else{
			std::cout << "algo3は答えを返しませんでした" << std::endl;
		}
	}
#else
        test_tool::emulator emu(question);
        auto result = emu.start(answer.get());
        std::cout << "Wrong: " << result.wrong << std::endl;
        std::cout << "Cost : " << result.cost  << std::endl;
        std::cout << "---" << std::endl;
#endif
    }
}

int main(int const argc, char const* argv[])
{
    std::string server_addr;
	int         problemid = 0;
    auto const  token = "1";//"3935105806";
    bool        is_auto;
    bool        is_blur;
    std::string url_format;
#if ENABLE_SAVE_IMAGE
    std::string save_dir;
#endif

    try
    {
        namespace po = boost::program_options;
        po::options_description opt("option");
        opt.add_options()
            ("help,h"    , "produce help message")
            ("auto,a"    , "auto submit flag")
            ("blur,b"    , "gaussian blur to image")
#if ENABLE_SAVE_IMAGE
            ("save_dir"  , po::value<std::string>(&save_dir)   , "(require)set image dir to save")
#endif
#if ENABLE_NETWORK_IO
            ("prob_format,f", po::value<std::string>(&url_format)->default_value("/problem/prob%02d.ppm"), "set problem format(ex. /problem/prob%02d.ppm)")
            ("server,s"  , po::value<std::string>(&server_addr), "(require)set server ip address")
            ("problem,p" , po::value<int>(&problemid)          , "(require)set problem_id")
#endif
            ;

        po::variables_map argmap;
        po::store(po::parse_command_line(argc, argv, opt), argmap);
        po::notify(argmap);

#if ENABLE_NETWORK_IO
        if(argmap.count("help") || !argmap.count("server") || !argmap.count("problem"))
#else
        if(argmap.count("help"))
#endif
        {
            std::cout << opt << std::endl;
            return 0;
        }

        is_auto = argmap.count("auto");
        is_blur = argmap.count("blur");
    }
    catch(boost::program_options::error_with_option_name const& e)
    {
        std::cout << e.what() << std::endl;
        std::exit(-1);
    }

    auto             network_client = boost::make_shared<network::client>(server_addr, url_format/*, submit_path*/);

#if ENABLE_SAVE_IMAGE
    if(save_dir.empty()) save_dir = "./saved_image";
    analyzer         analyze(network_client, problemid, token, is_auto, is_blur, save_dir);
#else
    analyzer         analyze(network_client, problemid, token, is_auto, is_blur);
#endif
    position_manager manager;

    boost::thread thread(boost::bind(&analyzer::operator(), &analyze, std::ref(manager)));
    boost::thread_group submit_threads;

    while(thread.joinable())
    {
        if(!manager.empty())
        {
            auto question = manager.get();

            // 手順探索部
            submit_threads.create_thread(
                boost::bind(submit_func, question.first, boost::ref(analyze), question.second)
                );
        }
    }

    thread.join();
    submit_threads.join_all();

    return 0;
}