<commit_before>/*

@Copyright Barrett Adair 2015-2018
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

*/

#ifndef BOOST_CLBL_TRTS_ADD_MEMBER_RVALUE_REFERENCE_HPP
#define BOOST_CLBL_TRTS_ADD_MEMBER_RVALUE_REFERENCE_HPP

#include <boost/callable_traits/detail/core.hpp>

namespace boost { namespace callable_traits {

//[ add_member_rvalue_reference_hpp
/*`
[section:ref_add_member_rvalue_reference add_member_rvalue_reference]
[heading Header]
``#include <boost/callable_traits/add_member_rvalue_reference.hpp>``
[heading Definition]
*/
//<-
#ifdef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS

template<typename T>
struct add_member_rvalue_reference_t {
    static_assert(std::is_same<T, detail::dummy>::value,
        "Reference member qualifiers are not supported by this configuration.");
};

#else
//->
template<typename T>
using add_member_rvalue_reference_t = //see below
//<-
#ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS

    detail::sfinae_try<
        typename detail::traits<T>::add_member_rvalue_reference,

        detail::fail_when_same<typename detail::traits<T>::add_member_rvalue_reference,
                detail::abominable_functions_not_supported_on_this_compiler,
            this_compiler_doesnt_support_abominable_function_types>,

        detail::fail_if_invalid<typename detail::traits<T>::add_member_rvalue_reference,
            member_qualifiers_are_illegal_for_this_type>>;
#else

    detail::try_but_fail_if_invalid<
        typename detail::traits<T>::add_member_rvalue_reference,
        member_qualifiers_are_illegal_for_this_type>;

#endif // #ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS
#endif // #ifdef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS

namespace detail {

    template<typename T, typename = std::false_type>
    struct add_member_rvalue_reference_impl {};

    template<typename T>
    struct add_member_rvalue_reference_impl <T, typename std::is_same<
        add_member_rvalue_reference_t<T>, detail::dummy>::type>
    {
        using type = add_member_rvalue_reference_t<T>;
    };
}
//->

template<typename T>
struct add_member_rvalue_reference
  : detail::add_member_rvalue_reference_impl<T> {};

//<-
}} // namespace boost::callable_traits
//->

/*`
[heading Constraints]
* `T` must be a function type or a member function pointer type
* If `T` is a pointer, it may not be cv/ref qualified

[heading Behavior]
* A substitution failure occurs if the constraints are violated.
* Adds a member rvalue reference qualifier (`&&`) to `T`, if not already present.
* If an lvalue reference qualifier is present, the lvalue reference qualifier remains (in accordance with reference collapsing rules).

[heading Input/Output Examples]
[table
    [[`T`]                              [`add_member_rvalue_reference_t<T>`]]
    [[`int()`]                          [`int() &&`]]
    [[`int(foo::*)()`]                  [`int(foo::*)() &&`]]
    [[`int(foo::*)() &`]                [`int(foo::*)() &`]]
    [[`int(foo::*)() &&`]               [`int(foo::*)() &&`]]
    [[`int(foo::*)() const`]            [`int(foo::*)() const &&`]]
    [[`int(foo::*)() transaction_safe`] [`int(foo::*)() && transaction_safe`]]
    [[`int`]                            [(substitution failure)]]
    [[`int (&)()`]                      [(substitution failure)]]
    [[`int (*)()`]                      [(substitution failure)]]
    [[`int foo::*`]                     [(substitution failure)]]
    [[`int (foo::* const)()`]           [(substitution failure)]]
]

[heading Example Program]
[import ../example/add_member_rvalue_reference.cpp]
[add_member_rvalue_reference]
[endsect][/section:ref_add_member_rvalue_reference]
*/
//]

#endif
<commit_msg>Delete add_member_rvalue_reference.hpp<commit_after><|endoftext|>


<commit_before>/**
 * File    : C.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-6-2 21:08:42
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <random> // random_device rd; mt19937 mt(rd());
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

ll N, D;
ll X[100010];
ll L[100010];
ll R[100010];
ll A[100010];
ll sum[100010];
ll cnt[100010];

int main()
{
  cin >> N >> D;
  for (auto i = 0; i < N; i++)
  {
    cin >> X[i];
  }
  for (auto i = 0; i < N; i++)
  {
    R[i] = i;
    L[i] = i;
  }
  ll l = 0, r = 0;
  while (r < N)
  {
    if (X[r] - X[l] <= D)
    {
      R[l] = r;
      r++;
    }
    else
    {
      l++;
    }
  }
  r = N - 1;
  while (l < N)
  {
    if (X[r] - X[l] <= D)
    {
      R[l] = r;
      l++;
    }
    else
    {
      l++;
    }
  }
  l = N - 1;
  while (l >= 0)
  {
    if (X[r] - X[l] <= D)
    {
      L[r] = l;
      l--;
    }
    else
    {
      r--;
    }
  }
  l = 0;
  while (r >= 0)
  {
    if (X[r] - X[l] <= D)
    {
      L[r] = l;
      r--;
    }
    else
    {
      r--;
    }
  }
  for (auto i = 0; i < N; i++)
  {
    A[i] = R[i] - i;
  }
  sum[0] = 0;
  for (auto i = 1; i <= N; i++)
  {
    sum[i] = sum[i - 1] + A[i - 1];
  }
  for (auto j = 0; j < N; j++)
  {
    ll n = R[j] - (L[j] - 1) - 1;
    cerr << "j = " << j << ", n = " << n << endl;
    cnt[j] = n * (n - 1) / 2;
    ll ext = sum[R[j] + 1] - sum[L[j]] - n;
    cerr << "ext = " << ext << endl;
    cnt[j] -= ext;
  }
  ll ans = 0;
  for (auto i = 0; i < N; i++)
  {
    ans += cnt[i];
  }
  cout << ans << endl;
}<commit_msg>tried C.cpp to 'C'<commit_after>/**
 * File    : C.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-6-2 21:08:42
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <random> // random_device rd; mt19937 mt(rd());
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

ll N, D;
ll X[100010];
ll L[100010];
ll R[100010];
ll A[100010];
ll sum[100010];
ll cnt[100010];

int main()
{
  cin >> N >> D;
  for (auto i = 0; i < N; i++)
  {
    cin >> X[i];
  }
  for (auto i = 0; i < N; i++)
  {
    R[i] = i;
    L[i] = i;
  }
  ll l = 0, r = 0;
  while (r < N)
  {
    if (X[r] - X[l] <= D)
    {
      R[l] = r;
      r++;
    }
    else
    {
      l++;
    }
  }
  r = N - 1;
  while (l < N)
  {
    if (X[r] - X[l] <= D)
    {
      R[l] = r;
      l++;
    }
    else
    {
      l++;
    }
  }
  l = N - 1;
  while (l >= 0)
  {
    if (X[r] - X[l] <= D)
    {
      L[r] = l;
      l--;
    }
    else
    {
      r--;
    }
  }
  l = 0;
  while (r >= 0)
  {
    if (X[r] - X[l] <= D)
    {
      L[r] = l;
      r--;
    }
    else
    {
      r--;
    }
  }
  for (auto i = 0; i < N; i++)
  {
    A[i] = R[i] - i;
  }
  sum[0] = 0;
  for (auto i = 1; i <= N; i++)
  {
    sum[i] = sum[i - 1] + A[i - 1];
    cerr << "sum[" << i << "] = " << sum[i] << endl;
  }
  for (auto j = 0; j < N; j++)
  {
    ll n = R[j] - (L[j] - 1) - 1;
    cerr << "j = " << j << ", n = " << n << endl;
    cnt[j] = n * (n - 1) / 2;
    ll ext = sum[R[j] + 1] - sum[L[j]] - n;
    cerr << "ext = " << ext << endl;
    cnt[j] -= ext;
  }
  ll ans = 0;
  for (auto i = 0; i < N; i++)
  {
    ans += cnt[i];
  }
  cout << ans << endl;
}<|endoftext|>


<commit_before><commit_msg>Edited comments.<commit_after><|endoftext|>


<commit_before>/******************************************************************************\

          This file is part of the C! library.  A.K.A the cbang library.

              Copyright (c) 2003-2015, Cauldron Development LLC
                 Copyright (c) 2003-2015, Stanford University
                             All rights reserved.

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

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

        You should have received a copy of the GNU Lesser General Public
        License along with the C! library.  If not, see
        <http://www.gnu.org/licenses/>.

        In addition, BSD licensing may be granted on a case by case basis
        by written permission from at least one of the copyright holders.
        You may request written permission by emailing the authors.

                For information regarding this software email:
                               Joseph Coffland
                        joseph@cauldrondevelopment.com

\******************************************************************************/

#ifdef _MSC_VER

#include "Win32EventLog.h"

#include <cbang/Exception.h>

#define WIN32_LEAN_AND_MEAN // Avoid including winsock.h
#include <windows.h>

using namespace cb;
using namespace std;

Win32EventLog::Win32EventLog(const std::string &source, const string &server) :
  source(source),
  handle(RegisterEventSource(server.empty() ? 0 : server.c_str(),
                             source.c_str())) {
  if (!handle) THROW("Failed to register WIN32 event source");
}

Win32EventLog::~Win32EventLog() {
  if (handle) DeregisterEventSource(handle);
}

void Win32EventLog::log(string &message, unsigned type, unsigned category,
                        unsigned id) const {
  LPCWSTR strs[2] = {(LPCWSTR)source.c_str(), (LPCWSTR)message.c_str()};
  ReportEvent(handle, (WORD)type, (WORD)category, (DWORD)id, 0, 2, 0, strs, 0);
}

#endif // _MSC_VER
<commit_msg>Not wide strings<commit_after>/******************************************************************************\

          This file is part of the C! library.  A.K.A the cbang library.

              Copyright (c) 2003-2015, Cauldron Development LLC
                 Copyright (c) 2003-2015, Stanford University
                             All rights reserved.

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

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

        You should have received a copy of the GNU Lesser General Public
        License along with the C! library.  If not, see
        <http://www.gnu.org/licenses/>.

        In addition, BSD licensing may be granted on a case by case basis
        by written permission from at least one of the copyright holders.
        You may request written permission by emailing the authors.

                For information regarding this software email:
                               Joseph Coffland
                        joseph@cauldrondevelopment.com

\******************************************************************************/

#ifdef _MSC_VER

#include "Win32EventLog.h"

#include <cbang/Exception.h>

#define WIN32_LEAN_AND_MEAN // Avoid including winsock.h
#include <windows.h>

using namespace cb;
using namespace std;

Win32EventLog::Win32EventLog(const std::string &source, const string &server) :
  source(source),
  handle(RegisterEventSource(server.empty() ? 0 : server.c_str(),
                             source.c_str())) {
  if (!handle) THROW("Failed to register WIN32 event source");
}

Win32EventLog::~Win32EventLog() {
  if (handle) DeregisterEventSource(handle);
}

void Win32EventLog::log(string &message, unsigned type, unsigned category,
                        unsigned id) const {
  LPCSTR strs[2] = {(LPCSTR)source.c_str(), (LPCSTR)message.c_str()};
  ReportEvent(handle, (WORD)type, (WORD)category, (DWORD)id, 0, 2, 0, strs, 0);
}

#endif // _MSC_VER
<|endoftext|>


<commit_before>// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "core_io.h"

#include "primitives/block.h"
#include "primitives/transaction.h"
#include "script/script.h"
#include "serialize.h"
#include "streams.h"
#include <univalue.h>
#include "util.h"
#include "utilstrencodings.h"
#include "version.h"

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/assign/list_of.hpp>

using namespace std;

CScript ParseScript(std::string s)
{
    CScript result;

    static map<string, opcodetype> mapOpNames;

    if (mapOpNames.empty()) {
        for (int op = 0; op < FIRST_UNDEFINED_OP_VALUE; op++) {
            if (op < OP_PUSHDATA1)
                continue;

            const char* name = GetOpName((opcodetype)op);
            if (strcmp(name, "OP_UNKNOWN") == 0)
                continue;
            string strName(name);
            mapOpNames[strName] = (opcodetype)op;
            // Convenience: OP_ADD and just ADD are both recognized:
            boost::algorithm::replace_first(strName, "OP_", "");
            mapOpNames[strName] = (opcodetype)op;
        }
    }

    std::vector<std::string> words;
    boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"),
                            boost::algorithm::token_compress_on);

    size_t push_size = 0, next_push_size = 0;
    size_t script_size = 0;

    for (const auto &w : words) {
        if (w.empty()) {
            // Empty string, ignore. (boost::split given '' will return one
            // word)
            continue;
        }

        // Check that the expected number of byte where pushed.
        if (push_size && (result.size() - script_size) != push_size) {
            throw std::runtime_error(
                "Hex number doesn't match the number of bytes being pushed");
        }

        // Update script size.
        script_size = result.size();

        // Make sure we keep track of the size of push operations.
        push_size = next_push_size;
        next_push_size = 0;

        if (all(w, boost::algorithm::is_digit()) ||
            (boost::algorithm::starts_with(w, "-") &&
             all(std::string(w.begin() + 1, w.end()),
                 boost::algorithm::is_digit()))) {
            // Number
            int64_t n = atoi64(w);
            result << n;
            continue;
        }

        if (boost::algorithm::starts_with(w, "0x") &&
            (w.begin() + 2 != w.end())) {
            if (!IsHex(std::string(w.begin() + 2, w.end()))) {
                // Should only arrive here for improperly formatted hex values
                throw std::runtime_error("Hex numbers expected to be formatted "
                                         "in full-byte chunks (ex: 0x00 "
                                         "instead of 0x0)");
            }

            // Raw hex data, inserted NOT pushed onto stack:
            std::vector<uint8_t> raw =
                ParseHex(std::string(w.begin() + 2, w.end()));
            if (push_size && raw.size() != push_size) {
                throw std::runtime_error("Hex number doesn't match the "
                                         "number of bytes being pushed");
            }
            // If we have what looks like an immediate push, figure out its
            // size.
            if (!push_size && raw.size() == 1 && raw[0] < OP_PUSHDATA1) {
                next_push_size = raw[0];
            }

            result.insert(result.end(), raw.begin(), raw.end());
            continue;
        }

        if (w.size() >= 2 && boost::algorithm::starts_with(w, "'") &&
            boost::algorithm::ends_with(w, "'")) {
            // Single-quoted string, pushed as data. NOTE: this is poor-man's
            // parsing, spaces/tabs/newlines in single-quoted strings won't
            // work.
            std::vector<uint8_t> value(w.begin() + 1, w.end() - 1);
            result << value;
            continue;
        }

        if (mapOpNames.count(w)) {
            // opcode, e.g. OP_ADD or ADD:
            opcodetype op = mapOpNames[w];

            switch (op) {
                case OP_PUSHDATA1:
                    next_push_size = 1;
                    break;
                case OP_PUSHDATA2:
                    next_push_size = 2;
                    break;
                case OP_PUSHDATA4:
                    next_push_size = 4;
                    break;
                default:
                    break;
            }

            result << op;
            continue;
        }

        throw std::runtime_error("Error parsing script: " + s);
    }

    // Check that the expected number of byte where pushed.
    if (push_size && (result.size() - script_size) != push_size) {
        throw std::runtime_error(
            "Hex number doesn't match the number of bytes being pushed");
    }

    return result;
}

bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx)
{
    if (!IsHex(strHexTx))
        return false;

    vector<unsigned char> txData(ParseHex(strHexTx));
    CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
    try {
        ssData >> tx;
        if (!ssData.empty())
            return false;
    }
    catch (const std::exception&) {
        return false;
    }

    return true;
}

bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk)
{
    if (!IsHex(strHexBlk))
        return false;

    std::vector<unsigned char> blockData(ParseHex(strHexBlk));
    CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION);
    try {
        ssBlock >> block;
    }
    catch (const std::exception&) {
        return false;
    }

    return true;
}

uint256 ParseHashUV(const UniValue& v, const string& strName)
{
    string strHex;
    if (v.isStr())
        strHex = v.getValStr();
    return ParseHashStr(strHex, strName);  // Note: ParseHashStr("") throws a runtime_error
}

uint256 ParseHashStr(const std::string& strHex, const std::string& strName)
{
    if (!IsHex(strHex)) // Note: IsHex("") is false
        throw runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')");

    uint256 result;
    result.SetHex(strHex);
    return result;
}

vector<unsigned char> ParseHexUV(const UniValue& v, const string& strName)
{
    string strHex;
    if (v.isStr())
        strHex = v.getValStr();
    if (!IsHex(strHex))
        throw runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')");
    return ParseHex(strHex);
}
<commit_msg>Refactor ParseScript to deduplicate error checking.<commit_after>// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "core_io.h"

#include "primitives/block.h"
#include "primitives/transaction.h"
#include "script/script.h"
#include "serialize.h"
#include "streams.h"
#include <univalue.h>
#include "util.h"
#include "utilstrencodings.h"
#include "version.h"

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/assign/list_of.hpp>

using namespace std;

CScript ParseScript(std::string s)
{
    CScript result;

    static map<string, opcodetype> mapOpNames;

    if (mapOpNames.empty()) {
        for (int op = 0; op < FIRST_UNDEFINED_OP_VALUE; op++) {
            if (op < OP_PUSHDATA1)
                continue;

            const char* name = GetOpName((opcodetype)op);
            if (strcmp(name, "OP_UNKNOWN") == 0)
                continue;
            string strName(name);
            mapOpNames[strName] = (opcodetype)op;
            // Convenience: OP_ADD and just ADD are both recognized:
            boost::algorithm::replace_first(strName, "OP_", "");
            mapOpNames[strName] = (opcodetype)op;
        }
    }

    std::vector<std::string> words;
    boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"),
                            boost::algorithm::token_compress_on);

    size_t push_size = 0, next_push_size = 0;
    size_t script_size = 0;

    for (const auto &w : words) {
        if (w.empty()) {
            // Empty string, ignore. (boost::split given '' will return one
            // word)
            continue;
        }

        // Update script size.
        script_size = result.size();

        // Make sure we keep track of the size of push operations.
        push_size = next_push_size;
        next_push_size = 0;

        if (all(w, boost::algorithm::is_digit()) ||
            (boost::algorithm::starts_with(w, "-") &&
             all(std::string(w.begin() + 1, w.end()),
                 boost::algorithm::is_digit()))) {
            // Number
            int64_t n = atoi64(w);
            result << n;
            goto next;
        }

        if (boost::algorithm::starts_with(w, "0x") &&
            (w.begin() + 2 != w.end())) {
            if (!IsHex(std::string(w.begin() + 2, w.end()))) {
                // Should only arrive here for improperly formatted hex values
                throw std::runtime_error("Hex numbers expected to be formatted "
                                         "in full-byte chunks (ex: 0x00 "
                                         "instead of 0x0)");
            }

            // Raw hex data, inserted NOT pushed onto stack:
            std::vector<uint8_t> raw =
                ParseHex(std::string(w.begin() + 2, w.end()));
            // If we have what looks like an immediate push, figure out its
            // size.
            if (!push_size && raw.size() == 1 && raw[0] < OP_PUSHDATA1) {
                next_push_size = raw[0];
            }

            result.insert(result.end(), raw.begin(), raw.end());
            goto next;
        }

        if (w.size() >= 2 && boost::algorithm::starts_with(w, "'") &&
            boost::algorithm::ends_with(w, "'")) {
            // Single-quoted string, pushed as data. NOTE: this is poor-man's
            // parsing, spaces/tabs/newlines in single-quoted strings won't
            // work.
            std::vector<uint8_t> value(w.begin() + 1, w.end() - 1);
            result << value;
            goto next;
        }

        if (mapOpNames.count(w)) {
            // opcode, e.g. OP_ADD or ADD:
            opcodetype op = mapOpNames[w];

            switch (op) {
                case OP_PUSHDATA1:
                    next_push_size = 1;
                    break;
                case OP_PUSHDATA2:
                    next_push_size = 2;
                    break;
                case OP_PUSHDATA4:
                    next_push_size = 4;
                    break;
                default:
                    break;
            }

            result << op;
            goto next;
        }

        throw std::runtime_error("Error parsing script: " + s);

    next:
        size_t size_change = result.size() - script_size;
        if (push_size && size_change != push_size) {
            throw std::runtime_error("Wrong number of bytes being pushed.");
        }
    }

    return result;
}

bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx)
{
    if (!IsHex(strHexTx))
        return false;

    vector<unsigned char> txData(ParseHex(strHexTx));
    CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
    try {
        ssData >> tx;
        if (!ssData.empty())
            return false;
    }
    catch (const std::exception&) {
        return false;
    }

    return true;
}

bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk)
{
    if (!IsHex(strHexBlk))
        return false;

    std::vector<unsigned char> blockData(ParseHex(strHexBlk));
    CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION);
    try {
        ssBlock >> block;
    }
    catch (const std::exception&) {
        return false;
    }

    return true;
}

uint256 ParseHashUV(const UniValue& v, const string& strName)
{
    string strHex;
    if (v.isStr())
        strHex = v.getValStr();
    return ParseHashStr(strHex, strName);  // Note: ParseHashStr("") throws a runtime_error
}

uint256 ParseHashStr(const std::string& strHex, const std::string& strName)
{
    if (!IsHex(strHex)) // Note: IsHex("") is false
        throw runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')");

    uint256 result;
    result.SetHex(strHex);
    return result;
}

vector<unsigned char> ParseHexUV(const UniValue& v, const string& strName)
{
    string strHex;
    if (v.isStr())
        strHex = v.getValStr();
    if (!IsHex(strHex))
        throw runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')");
    return ParseHex(strHex);
}
<|endoftext|>


<commit_before>// Copyright (c) Wiesław Šoltés. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "StdAfx.h"
#include "BatchEncoder.h"
#include "Utilities.h"
#include "AboutDlg.h"
#include ".\aboutdlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

IMPLEMENT_DYNAMIC(CAboutDlg, CDialog)
CAboutDlg::CAboutDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CAboutDlg::IDD, pParent)
{

}

CAboutDlg::~CAboutDlg()
{

}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDOK, m_BtnOK);
    DDX_Control(pDX, IDC_STATIC_TEXT_APP_NAME, m_StcMainAppName);
    DDX_Control(pDX, IDC_STATIC_TEXT_WEBSITE, m_StcWebsite);
    DDX_Control(pDX, IDC_STATIC_TEXT_EMAIL, m_StcEmail);
    DDX_Control(pDX, IDC_STATIC_LICENSE, m_StcLicense);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
    ON_WM_CLOSE()
    ON_BN_CLICKED(IDOK, OnBnClickedOk)
END_MESSAGE_MAP()

BOOL CAboutDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    m_StcMainAppName.SetBold(true);
    m_StcWebsite.SetBold(false);
    m_StcEmail.SetBold(false);
    m_StcLicense.SetBold(false);

    m_StcMainAppName.SetWindowText(MAIN_APP_NAME_VER);
    m_StcWebsite.SetWindowText(MAIN_APP_WEBSITE);
    m_StcWebsite.SetTargetUrl(MAIN_APP_WEBSITE);

    CString szEmail;
    szEmail.Format(_T("mailto:%s"), MAIN_APP_EMAIL);
    m_StcEmail.SetWindowText(MAIN_APP_EMAIL);
    m_StcEmail.SetTargetUrl(szEmail);

    return TRUE;
}

void CAboutDlg::OnOK()
{
    CDialog::OnOK();
}

void CAboutDlg::OnCancel()
{
    CDialog::OnCancel();
}

void CAboutDlg::OnClose()
{
    CDialog::OnClose();
}

void CAboutDlg::OnBnClickedOk()
{
    OnOK();
}
<commit_msg>Update AboutDlg.cpp<commit_after>// Copyright (c) Wiesław Šoltés. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "..\StdAfx.h"
#include "..\BatchEncoder.h"
#include "..\utilities\Utilities.h"
#include "AboutDlg.h"
#include ".\aboutdlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

IMPLEMENT_DYNAMIC(CAboutDlg, CDialog)
CAboutDlg::CAboutDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CAboutDlg::IDD, pParent)
{

}

CAboutDlg::~CAboutDlg()
{

}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDOK, m_BtnOK);
    DDX_Control(pDX, IDC_STATIC_TEXT_APP_NAME, m_StcMainAppName);
    DDX_Control(pDX, IDC_STATIC_TEXT_WEBSITE, m_StcWebsite);
    DDX_Control(pDX, IDC_STATIC_TEXT_EMAIL, m_StcEmail);
    DDX_Control(pDX, IDC_STATIC_LICENSE, m_StcLicense);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
    ON_WM_CLOSE()
    ON_BN_CLICKED(IDOK, OnBnClickedOk)
END_MESSAGE_MAP()

BOOL CAboutDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    m_StcMainAppName.SetBold(true);
    m_StcWebsite.SetBold(false);
    m_StcEmail.SetBold(false);
    m_StcLicense.SetBold(false);

    m_StcMainAppName.SetWindowText(MAIN_APP_NAME_VER);
    m_StcWebsite.SetWindowText(MAIN_APP_WEBSITE);
    m_StcWebsite.SetTargetUrl(MAIN_APP_WEBSITE);

    CString szEmail;
    szEmail.Format(_T("mailto:%s"), MAIN_APP_EMAIL);
    m_StcEmail.SetWindowText(MAIN_APP_EMAIL);
    m_StcEmail.SetTargetUrl(szEmail);

    return TRUE;
}

void CAboutDlg::OnOK()
{
    CDialog::OnOK();
}

void CAboutDlg::OnCancel()
{
    CDialog::OnCancel();
}

void CAboutDlg::OnClose()
{
    CDialog::OnClose();
}

void CAboutDlg::OnBnClickedOk()
{
    OnOK();
}
<|endoftext|>


<commit_before>/**
 * File    : E.cpp
 * Author  : Kazune Takahashi
 * Created : 12/22/2018, 9:09:29 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

class BIT
{ // index starts at 1.
public:
  int N;
  ll *data;

  BIT(int n) : N(n)
  {
    data = new ll[N + 1];
    for (auto i = 1; i <= N; ++i)
    {
      data[i] = 0;
    }
  }

  ~BIT()
  {
    delete[] data;
  }

  ll sum(int i)
  { // [1, i]
    ll s = 0;
    while (i > 0)
    {
      s += data[i];
      i -= i & -i;
    }
    return s;
  }

  ll sum(int a, int b)
  { // [a, b)
    return sum(b - 1) - sum(a - 1);
  }

  void add(int i, ll x)
  {
    while (i <= N)
    {
      data[i] += x;
      i += i & -i;
    }
  }

  void add(int i)
  {
    add(i, 1);
  }
};

ll calc(ll x, ll y)
{
  if (x > y)
  {
    ll res = 0;
    ll mult = 1;
    while (x > y * mult)
    {
      res += 2;
      mult *= 4;
    }
    return res;
  }
  else
  {
    ll res = 0;
    ll mult = 1;
    while (x * (mult * 4) >= y)
    {
      res -= 2;
      mult *= 4;
    }
    return res;
  }
}

int N;
ll A[200010];
ll X[200010];
ll imos_X[200010];
ll ans_X[200010];

ll B[200010];
ll Y[200010];
ll imos_Y[200010];
ll ans_Y[200010];

typedef tuple<ll, int> T;

int main()
{
  cin >> N;
  for (auto i = 0; i < N; i++)
  {
    cin >> A[i];
  }
  X[0] = 0;
  for (auto i = 1; i < N; i++)
  {
    X[i] = calc(A[i - 1], A[i]);
  }
  imos_X[0] = 0;
  for (auto i = 1; i < N; i++)
  {
    imos_X[i] = X[i] + imos_X[i - 1];
    cerr << "imos_X[" << i << "] = " << imos_X[i] << endl;
  }
  vector<T> V;
  BIT bit_X = BIT(N);
  BIT bit_cnt_X = BIT(N);
  for (auto i = 0; i < N; i++)
  {
    V.push_back(T(imos_X[i], i));
  }
  sort(V.begin(), V.end());
  reverse(V.begin(), V.end());
  for (auto i = 0; i < N; i++)
  {
    ll M = get<0>(V[i]);
    int ind = get<1>(V[i]) + 1;
    bit_X.add(ind, M);
    bit_cnt_X.add(ind);
    ans_X[ind - 1] = bit_X.sum(ind, N + 1) - M * bit_cnt_X.sum(ind, N + 1);
  }
  for (auto i = 0; i < N; i++)
  {
    B[i] = A[i];
  }
  reverse(B, B + N);
  Y[0] = 0;
  for (auto i = 1; i < N; i++)
  {
    Y[i] = calc(B[i - 1], B[i]);
  }
  imos_Y[0] = 0;
  for (auto i = 1; i < N; i++)
  {
    imos_Y[i] = Y[i] + imos_Y[i - 1];
  }
  V.clear();
  BIT bit_Y = BIT(N);
  BIT bit_cnt_Y = BIT(N);
  for (auto i = 0; i < N; i++)
  {
    V.push_back(T(imos_Y[i], i));
  }
  sort(V.begin(), V.end());
  reverse(V.begin(), V.end());
  for (auto i = 0; i < N; i++)
  {
    ll M = get<0>(V[i]);
    int ind = get<1>(V[i]) + 1;
    bit_Y.add(ind, M);
    bit_cnt_Y.add(ind);
    ans_Y[ind - 1] = bit_Y.sum(ind, N + 1) - M * bit_cnt_Y.sum(ind, N + 1);
  }
  reverse(ans_Y, ans_Y + N);
  ll ans = 10000000000000000;
  for (auto i = 0; i <= N; i++)
  {
    ll t_ans = i;
    cerr << "i = " << i << endl;
    if (i < N)
    {
      t_ans += ans_X[i];
      cerr << "ans_X[" << i << "] = " << ans_X[i] << endl;
    }
    if (i > 0)
    {
      t_ans += ans_Y[i - 1];
      cerr << "ans_Y[" << i - 1 << "] = " << ans_Y[i - 1] << endl;
    }
    ans = min(t_ans, ans);
  }
  cout << ans << endl;
}<commit_msg>tried E.cpp to 'E'<commit_after>/**
 * File    : E.cpp
 * Author  : Kazune Takahashi
 * Created : 12/22/2018, 9:09:29 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

class BIT
{ // index starts at 1.
public:
  int N;
  ll *data;

  BIT(int n) : N(n)
  {
    data = new ll[N + 1];
    for (auto i = 1; i <= N; ++i)
    {
      data[i] = 0;
    }
  }

  ~BIT()
  {
    delete[] data;
  }

  ll sum(int i)
  { // [1, i]
    ll s = 0;
    while (i > 0)
    {
      s += data[i];
      i -= i & -i;
    }
    return s;
  }

  ll sum(int a, int b)
  { // [a, b)
    return sum(b - 1) - sum(a - 1);
  }

  void add(int i, ll x)
  {
    while (i <= N)
    {
      data[i] += x;
      i += i & -i;
    }
  }

  void add(int i)
  {
    add(i, 1);
  }
};

ll calc(ll x, ll y)
{
  if (x > y)
  {
    ll res = 0;
    ll mult = 1;
    while (x > y * mult)
    {
      res += 2;
      mult *= 4;
    }
    return res;
  }
  else
  {
    ll res = 0;
    ll mult = 1;
    while (x * (mult * 4) <= y)
    {
      res -= 2;
      mult *= 4;
    }
    return res;
  }
}

int N;
ll A[200010];
ll X[200010];
ll imos_X[200010];
ll ans_X[200010];

ll B[200010];
ll Y[200010];
ll imos_Y[200010];
ll ans_Y[200010];

typedef tuple<ll, int> T;

int main()
{
  cin >> N;
  for (auto i = 0; i < N; i++)
  {
    cin >> A[i];
  }
  X[0] = 0;
  for (auto i = 1; i < N; i++)
  {
    X[i] = calc(A[i - 1], A[i]);
  }
  imos_X[0] = 0;
  for (auto i = 1; i < N; i++)
  {
    imos_X[i] = X[i] + imos_X[i - 1];
    cerr << "imos_X[" << i << "] = " << imos_X[i] << endl;
  }
  vector<T> V;
  BIT bit_X = BIT(N);
  BIT bit_cnt_X = BIT(N);
  for (auto i = 0; i < N; i++)
  {
    V.push_back(T(imos_X[i], i));
  }
  sort(V.begin(), V.end());
  reverse(V.begin(), V.end());
  for (auto i = 0; i < N; i++)
  {
    ll M = get<0>(V[i]);
    int ind = get<1>(V[i]) + 1;
    bit_X.add(ind, M);
    bit_cnt_X.add(ind);
    ans_X[ind - 1] = bit_X.sum(ind, N + 1) - M * bit_cnt_X.sum(ind, N + 1);
  }
  for (auto i = 0; i < N; i++)
  {
    B[i] = A[i];
  }
  reverse(B, B + N);
  Y[0] = 0;
  for (auto i = 1; i < N; i++)
  {
    Y[i] = calc(B[i - 1], B[i]);
  }
  imos_Y[0] = 0;
  for (auto i = 1; i < N; i++)
  {
    imos_Y[i] = Y[i] + imos_Y[i - 1];
  }
  V.clear();
  BIT bit_Y = BIT(N);
  BIT bit_cnt_Y = BIT(N);
  for (auto i = 0; i < N; i++)
  {
    V.push_back(T(imos_Y[i], i));
  }
  sort(V.begin(), V.end());
  reverse(V.begin(), V.end());
  for (auto i = 0; i < N; i++)
  {
    ll M = get<0>(V[i]);
    int ind = get<1>(V[i]) + 1;
    bit_Y.add(ind, M);
    bit_cnt_Y.add(ind);
    ans_Y[ind - 1] = bit_Y.sum(ind, N + 1) - M * bit_cnt_Y.sum(ind, N + 1);
  }
  reverse(ans_Y, ans_Y + N);
  ll ans = 10000000000000000;
  for (auto i = 0; i <= N; i++)
  {
    ll t_ans = i;
    cerr << "i = " << i << endl;
    if (i < N)
    {
      t_ans += ans_X[i];
      cerr << "ans_X[" << i << "] = " << ans_X[i] << endl;
    }
    if (i > 0)
    {
      t_ans += ans_Y[i - 1];
      cerr << "ans_Y[" << i - 1 << "] = " << ans_Y[i - 1] << endl;
    }
    ans = min(t_ans, ans);
  }
  cout << ans << endl;
}<|endoftext|>


<commit_before>#include "qxtstdio.h"
#include <cstdio>
#include <QSocketNotifier>

/**
\class QxtStdio QxtStdio

\ingroup core

\brief QIODevice support for stdin and stdout

including readyRead() signal
note that when using this class, the buffer for stdin will be disabled, and NOT reenabled on destruction

perfect as a counter part for QProcess
*/

QxtStdio::QxtStdio(QObject * parent):QIODevice(parent)
	{
	setvbuf ( stdin , NULL , _IONBF , 0 );
	setOpenMode (QIODevice::ReadWrite);
	notify = new QSocketNotifier ( fileno(stdin),QSocketNotifier::Read,this );
	connect(notify, SIGNAL(activated(int)),this,SLOT(activated(int)));
	}

qint64 QxtStdio::readData ( char * data, qint64 maxSize )
	{
	qint64 i=0;
	for (;i<maxSize;i++)
		{
		if (inbuffer.isEmpty())
			break;
		(*data++)=inbuffer.dequeue();
		}
	return i;
	}
qint64 QxtStdio::writeData ( const char * data, qint64 maxSize )
	{
	qint64 i=0;
	for (;i<maxSize;i++)
		{
		char c=*data++;
		if (putchar(c)!=c)
			break;
		}
// 	emit(bytesWritten (i)); ///FIXME: acording to the docs this may not be recoursive. how do i prevent that?
	return i;
	}

bool QxtStdio::isSequential () const
	{
	return true;
	}

qint64 QxtStdio::bytesAvailable () const
	{
	return inbuffer.count();
	}

void QxtStdio::activated(int )
	{
	inbuffer.enqueue(getchar());
 	emit(readyRead ());
	}

<commit_msg>reason unknown, but this fixes stdout<commit_after>#include "qxtstdio.h"
#include <cstdio>
#include <QSocketNotifier>

/**
\class QxtStdio QxtStdio

\ingroup core

\brief QIODevice support for stdin and stdout

including readyRead() signal
note that when using this class, the buffers for stdin/stdout will be disabled, and NOT reenabled on destruction

perfect as a counter part for QProcess
*/

QxtStdio::QxtStdio(QObject * parent):QIODevice(parent)
	{
	setvbuf ( stdin , NULL , _IONBF , 0 );
	setvbuf ( stdout , NULL , _IONBF , 0 );

	setOpenMode (QIODevice::ReadWrite);
	notify = new QSocketNotifier ( fileno(stdin),QSocketNotifier::Read,this );
	connect(notify, SIGNAL(activated(int)),this,SLOT(activated(int)));
	}

qint64 QxtStdio::readData ( char * data, qint64 maxSize )
	{
	qint64 i=0;
	for (;i<maxSize;i++)
		{
		if (inbuffer.isEmpty())
			break;
		(*data++)=inbuffer.dequeue();
		}
	return i;
	}
qint64 QxtStdio::writeData ( const char * data, qint64 maxSize )
	{
	qDebug("write %i,%s",maxSize,data);
	qint64 i=0;
	for (;i<maxSize;i++)
		{
		char c=*data++;
		putchar(c);

///FIXME: why the heck is that not working... the C99 standard says it should...
// 		if (putchar(c)!=c)
// 			break;

		}
	qDebug("written %i,%s",i,data);
// 	emit(bytesWritten (i)); ///FIXME: acording to the docs this may not be recoursive. how do i prevent that?
	return i;
	}

bool QxtStdio::isSequential () const
	{
	return true;
	}

qint64 QxtStdio::bytesAvailable () const
	{
	return inbuffer.count();
	}

void QxtStdio::activated(int )
	{
	inbuffer.enqueue(getchar());
 	emit(readyRead ());
	}

<|endoftext|>


<commit_before>/*
 The MIT License (MIT)

 Copyright (c) [2016] [BTC.COM]

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */
#include "EthConsensus.h"

#include <algorithm>

EthConsensus::Chain EthConsensus::getChain(std::string chainStr) {
    // toupper
    std::transform(chainStr.begin(), chainStr.end(), chainStr.begin(), ::toupper);

    if (chainStr == "CLASSIC") {
        return Chain::CLASSIC;
    }
    else if (chainStr == "FOUNDATION") {
        return Chain::FOUNDATION;
    }
    else {
        return Chain::UNKNOWN;
    }
}

std::string EthConsensus::getChainStr(const Chain chain) {
    switch (chain) {
    case Chain::CLASSIC:
        return "CLASSIC";
    case Chain::FOUNDATION:
        return "FOUNDATION";
    case Chain::UNKNOWN:
        return "UNKNOWN";
    }
    // should not be here
    return "UNKNOWN";
}

// The "static" block reward for the winning block.
    // Uncle block rewards are not included.
int64_t EthConsensus::getStaticBlockReward(int nHeight, Chain chain) {
    switch (chain) {
    case Chain::CLASSIC:
        return getStaticBlockRewardClassic(nHeight);
    case Chain::FOUNDATION:
        return getStaticBlockRewardFoundation(nHeight);
    case Chain::UNKNOWN:
        return 0;
    }
    // should not be here
    return 0;
}

// static block rewards of Ethereum Classic Main Network
// The implementation followed ECIP-1017:
// https://github.com/ethereumproject/ECIPs/blob/master/ECIPs/ECIP-1017.md
int64_t EthConsensus::getStaticBlockRewardClassic(int nHeight) {
    const int64_t blockEra = (nHeight - 1) / 5000000 + 1;

    // The blockEra is 2 in 2018.
    // Avoid calculations by giving the result directly.
    if (blockEra == 2) {
        return 4e+18;
    }

    int64_t reward = 5e+18;

    for (int i=1; i<blockEra; i++) {
        // ECIP-1017: all rewards will be reduced at a constant rate of 20% upon entering a new Era.
        // reward *= 0.8 (avoid converts to float)
        reward = reward * 8 / 10;
    }

    return reward;
}

// static block rewards of Ethereum Main Network
int64_t EthConsensus::getStaticBlockRewardFoundation(int /*nHeight*/) {
  // Ethereum Main Network has a static block reward (3 Ether) at current.
  // And it seems does not have a clear block reward policy for the long-term.
  return 3e+18;
}

double EthConsensus::getUncleBlockRewardRatio(int nHeight, Chain chain) {
    switch (chain) {
    case Chain::CLASSIC:
        return getUncleBlockRewardRatioClassic(nHeight);
    case Chain::FOUNDATION:
        return getUncleBlockRewardRatioFoundation(nHeight);
    case Chain::UNKNOWN:
        return 0.0;
    }
    // should not be here
    return 0.0;
}

// uncle block reward radio of Ethereum Classic Main Network
// The implementation followed ECIP-1017:
// https://github.com/ethereumproject/ECIPs/blob/master/ECIPs/ECIP-1017.md
double EthConsensus::getUncleBlockRewardRatioClassic(int nHeight) {
    // Assume that there is only one height lower than the main chain block

    const int64_t blockEra = (nHeight - 1) / 5000000 + 1;

    if (blockEra == 1) {
        // The blockEra 1 is special
        return 7.0 / 8.0;
    }
    else if (blockEra == 2) {
        // The blockEra is 2 in 2018.
        // Avoid calculations by giving the result directly.
        return 1.0 / 32.0;
    }

    double radio = 1.0 / 32.0;

    for (int i=2; i<blockEra; i++) {
        // ECIP-1017: all rewards will be reduced at a constant rate of 20% upon entering a new Era.
        radio *= 0.8;
    }

    return radio;
}

double EthConsensus::getUncleBlockRewardRatioFoundation(int /*nHeight*/) {
    // Assume that there is only one height lower than the main chain block
    return 7.0 / 8.0;
}
<commit_msg>Ethereum lsConstantinople fork at block 7080000 on Mainnet (#222)<commit_after>/*
 The MIT License (MIT)

 Copyright (c) [2016] [BTC.COM]

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */
#include "EthConsensus.h"

#include <algorithm>

EthConsensus::Chain EthConsensus::getChain(std::string chainStr) {
    // toupper
    std::transform(chainStr.begin(), chainStr.end(), chainStr.begin(), ::toupper);

    if (chainStr == "CLASSIC") {
        return Chain::CLASSIC;
    }
    else if (chainStr == "FOUNDATION") {
        return Chain::FOUNDATION;
    }
    else {
        return Chain::UNKNOWN;
    }
}

std::string EthConsensus::getChainStr(const Chain chain) {
    switch (chain) {
    case Chain::CLASSIC:
        return "CLASSIC";
    case Chain::FOUNDATION:
        return "FOUNDATION";
    case Chain::UNKNOWN:
        return "UNKNOWN";
    }
    // should not be here
    return "UNKNOWN";
}

// The "static" block reward for the winning block.
    // Uncle block rewards are not included.
int64_t EthConsensus::getStaticBlockReward(int nHeight, Chain chain) {
    switch (chain) {
    case Chain::CLASSIC:
        return getStaticBlockRewardClassic(nHeight);
    case Chain::FOUNDATION:
        return getStaticBlockRewardFoundation(nHeight);
    case Chain::UNKNOWN:
        return 0;
    }
    // should not be here
    return 0;
}

// static block rewards of Ethereum Classic Main Network
// The implementation followed ECIP-1017:
// https://github.com/ethereumproject/ECIPs/blob/master/ECIPs/ECIP-1017.md
int64_t EthConsensus::getStaticBlockRewardClassic(int nHeight) {
    const int64_t blockEra = (nHeight - 1) / 5000000 + 1;

    // The blockEra is 2 in 2018.
    // Avoid calculations by giving the result directly.
    if (blockEra == 2) {
        return 4e+18;
    }

    int64_t reward = 5e+18;

    for (int i=1; i<blockEra; i++) {
        // ECIP-1017: all rewards will be reduced at a constant rate of 20% upon entering a new Era.
        // reward *= 0.8 (avoid converts to float)
        reward = reward * 8 / 10;
    }

    return reward;
}

// static block rewards of Ethereum Main Network
int64_t EthConsensus::getStaticBlockRewardFoundation(int nHeight) {
 // Constantinople fork at block 7080000 on Mainnet.
  if (nHeight >= 7080000) {
    return 2e+18;
  }
  // Ethereum Main Network has a static block reward (3 Ether) before height 7080000.
  return 3e+18;
}

double EthConsensus::getUncleBlockRewardRatio(int nHeight, Chain chain) {
    switch (chain) {
    case Chain::CLASSIC:
        return getUncleBlockRewardRatioClassic(nHeight);
    case Chain::FOUNDATION:
        return getUncleBlockRewardRatioFoundation(nHeight);
    case Chain::UNKNOWN:
        return 0.0;
    }
    // should not be here
    return 0.0;
}

// uncle block reward radio of Ethereum Classic Main Network
// The implementation followed ECIP-1017:
// https://github.com/ethereumproject/ECIPs/blob/master/ECIPs/ECIP-1017.md
double EthConsensus::getUncleBlockRewardRatioClassic(int nHeight) {
    // Assume that there is only one height lower than the main chain block

    const int64_t blockEra = (nHeight - 1) / 5000000 + 1;

    if (blockEra == 1) {
        // The blockEra 1 is special
        return 7.0 / 8.0;
    }
    else if (blockEra == 2) {
        // The blockEra is 2 in 2018.
        // Avoid calculations by giving the result directly.
        return 1.0 / 32.0;
    }

    double radio = 1.0 / 32.0;

    for (int i=2; i<blockEra; i++) {
        // ECIP-1017: all rewards will be reduced at a constant rate of 20% upon entering a new Era.
        radio *= 0.8;
    }

    return radio;
}

double EthConsensus::getUncleBlockRewardRatioFoundation(int /*nHeight*/) {
    // Assume that there is only one height lower than the main chain block
    return 7.0 / 8.0;
}
<|endoftext|>


<commit_before>#include <cstring>
#include <set>
#include <map>
#include <functional>
#include <queue>

#include <unistd.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/stat.h>

#include "judge.h"

#include "global.h"

#define BSIZ (1 << 18)

using namespace std;

typedef function<char(char, char*, char*, Settings&)> Script;
struct QueueData;

static map<string, Script> scripts;
static queue<QueueData*> jqueue;
static pthread_mutex_t judger_mutex = PTHREAD_MUTEX_INITIALIZER;

static bool instance_exists(char problem, int i) {
  FILE* fp = fopen(stringf("problems/%c.in%d", problem, i).c_str(), "r");
  if (!fp) return false;
  fclose(fp);
  return true;
}

static string judge(
  int id, const string& team, const string& fno,
  const string& path, const string& fn, Settings& settings
) {
  // build attempt
  Attempt att;
  att.id = id;
  strcpy(att.team, team.c_str());
  att.problem = fno[0]-'A';
  char run = scripts[fno.substr(1, fno.size())](
    fno[0], (char*)path.c_str(), (char*)fn.c_str(), settings
  );
  if (run != AC) {
    att.verdict = run;
  }
  else {
    att.verdict = AC;
    for (int i = 1; instance_exists(fno[0], i) && att.verdict == AC; i++) {
      int status = system(
        "diff -wB %s%c.out%d problems/%c.sol%d",
        path.c_str(), fno[0], i, fno[0], i
      );
      if (WEXITSTATUS(status)) att.verdict = WA;
      else {
        status = system(
          "diff %s%c.out%d problems/%c.sol%d",
          path.c_str(), fno[0], i, fno[0], i
        );
        if (WEXITSTATUS(status)) att.verdict = PE;
      }
    }
  }
  att.when = time(nullptr);

  // save attempt info
  Global::lock_att_file();
  if (Global::alive()) {
    FILE* fp = fopen("attempts.bin", "ab");
    fwrite(&att, sizeof att, 1, fp);
    fclose(fp);
  }
  Global::unlock_att_file();

  // return verdict
  static string verdict[] = {"AC", "CE", "RTE", "TLE", "WA", "PE"};
  return
    att.when < settings.noverdict ?
    verdict[int(att.verdict)] :
    "The judge is hiding verdicts!"
  ;
}

struct QueueData {
  int id;
  string team;
  string fno;
  string path;
  string fn;
  Settings settings;
  string verdict;
  bool done;
  QueueData() : done(false) {}
  void push() {
    pthread_mutex_lock(&judger_mutex);
    jqueue.push(this);
    pthread_mutex_unlock(&judger_mutex);
    while (Global::alive() && !done) usleep(25000);
  }
  void judge() {
    verdict = ::judge(id, team, fno, path, fn, settings);
    done = true;
  }
};

static bool valid_filename(Settings& settings, const string& fn) {
  return
    ('A' <= fn[0]) && (fn[0] <= ('A' + int(settings.problems.size())-1)) &&
    (scripts.find(fn.substr(1, fn.size())) != scripts.end())
  ;
}

static int genid() {
  FILE* fp = fopen("nextid.bin", "rb");
  int current, next;
  if (!fp) current = 1, next = 2;
  else {
    fread(&current, sizeof current, 1, fp);
    fclose(fp);
    next = current + 1;
  }
  fp = fopen("nextid.bin", "wb");
  fwrite(&next, sizeof next, 1, fp);
  fclose(fp);
  return current;
}

static __suseconds_t dt(const timeval& start) {
  timeval end;
  gettimeofday(&end, nullptr);
  return
    (end.tv_sec*1000000 + end.tv_usec)-
    (start.tv_sec*1000000 + start.tv_usec)
  ;
}
static char run(
  int s,
  const string& exec_cmd,
  char problem,
  const string& output_path
) {
  __suseconds_t us = s*1000000;

  timeval start;
  gettimeofday(&start, nullptr);

  pid_t proc = fork();
  if (!proc) {
    // TODO lose root permissions
    setpgid(0, 0); // create new process group rooted at proc
    for (int i = 1; instance_exists(problem, i); i++) {
      int status = system(
        "%s < problems/%c.in%d > %s%c.out%d",
        exec_cmd.c_str(),
        problem, i,
        output_path.c_str(), problem, i
      );
      int exit_code = WEXITSTATUS(status);
      if (exit_code) exit(exit_code);
    }
    exit(0);
  }

  int status;
  while (waitpid(proc, &status, WNOHANG) != proc) {
    if (dt(start) > us) {
      kill(-proc, SIGKILL); // the minus kills the whole group rooted at proc
      waitpid(proc, &status, 0); // FIXME reap correctly
      return TLE;
    }
    usleep(10000);
  }
  if (WEXITSTATUS(status)) return RTE;
  return AC;
}
static void load_scripts() {
  scripts[".c"] = [](char p, char* path, char* fn, Settings& settings) {
    int status = system("gcc -std=c11 %s -o %s%c -lm", fn, path, p);
    if (WEXITSTATUS(status)) return char(CE);
    return run(
      settings.problems[p-'A'],
      stringf("%s%c", path, p),
      p,
      path
    );
  };
  scripts[".cpp"] = [](char p, char* path, char* fn, Settings& settings) {
    int status = system("g++ -std=c++1y %s -o %s%c", fn, path, p);
    if (WEXITSTATUS(status)) return char(CE);
    return run(
      settings.problems[p-'A'],
      stringf("%s%c", path, p),
      p,
      path
    );
  };
  scripts[".java"] = [](char p, char* path, char* fn, Settings& settings) {
    int status = system("javac %s", fn);
    if (WEXITSTATUS(status)) return char(CE);
    return run(
      settings.problems[p-'A'],
      stringf("java -cp %s %c", path, p),
      p,
      path
    );
  };
  scripts[".py"] = [](char p, char* path, char* fn, Settings& settings) {
    return run(
      settings.problems[p-'A'],
      stringf("python %s", fn),
      p,
      path
    );
  };
  scripts[".py3"] = [](char p, char* path, char* fn, Settings& settings) {
    return run(
      settings.problems[p-'A'],
      stringf("python3 %s", fn),
      p,
      path
    );
  };
}

static void* judger(void*) {
  while (Global::alive()) {
    pthread_mutex_lock(&judger_mutex);
    if (jqueue.empty()) {
      pthread_mutex_unlock(&judger_mutex);
      usleep(25000);
      continue;
    }
    QueueData* qd = jqueue.front(); jqueue.pop();
    pthread_mutex_unlock(&judger_mutex);
    qd->judge();
  }
  return nullptr;
}

namespace Judge {

void fire() {
  load_scripts();
  Global::fire(judger);
}

void attempt(
  int sd,
  const string& teamname, const string& team,
  const string& file_name, int file_size
) {
  Settings settings;

  // check time
  time_t now = time(nullptr);
  if (now < settings.begin || settings.end <= now) {
    ignoresd(sd);
    write(sd, "The contest is not running.", 27);
    return;
  }

  // check file name
  if (!valid_filename(settings, file_name)) {
    ignoresd(sd);
    write(sd, "Invalid file name!", 18);
    return;
  }

  // check file size
  if (file_size > BSIZ) {
    string resp =
      "Files with more than "+to<string>(BSIZ)+" bytes are not allowed!"
    ;
    ignoresd(sd);
    write(sd, resp.c_str(), resp.size());
    return;
  }

  // read data
  char* buf = new char[BSIZ];
  for (int i = 0, fs = file_size; fs > 0;) {
    int rb = read(sd, &buf[i], fs);
    if (rb < 0) {
      write(sd, "Incomplete request!", 19);
      delete[] buf;
      return;
    }
    fs -= rb;
    i += rb;
  }

  // generate id
  Global::lock_nextid_file();
  if (!Global::alive()) {
    Global::unlock_nextid_file();
    delete[] buf;
    return;
  }
  int id = genid();
  Global::unlock_nextid_file();

  // save file
  string fn = "attempts/";
  mkdir(fn.c_str(), 0777);
  fn += (team+"/");
  mkdir(fn.c_str(), 0777);
  fn += file_name[0]; fn += "/";
  mkdir(fn.c_str(), 0777);
  fn += (to<string>(id)+"/");
  mkdir(fn.c_str(), 0777);
  string path = "./"+fn;
  fn += file_name;
  FILE* fp = fopen(fn.c_str(), "wb");
  fwrite(buf, file_size, 1, fp);
  fclose(fp);
  delete[] buf;

  // respond
  string response = "Attempt "+to<string>(id)+": ";
  QueueData qd;
  qd.id = id;
  qd.team = teamname;
  qd.fno = file_name;
  qd.path = path;
  qd.fn = fn;
  qd.settings = settings;
  qd.push();
  response += qd.verdict;
  write(sd, response.c_str(), response.size());
}

} // namespace Judge
<commit_msg>Removing FIXME<commit_after>#include <cstring>
#include <set>
#include <map>
#include <functional>
#include <queue>

#include <unistd.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/stat.h>

#include "judge.h"

#include "global.h"

#define BSIZ (1 << 18)

using namespace std;

typedef function<char(char, char*, char*, Settings&)> Script;
struct QueueData;

static map<string, Script> scripts;
static queue<QueueData*> jqueue;
static pthread_mutex_t judger_mutex = PTHREAD_MUTEX_INITIALIZER;

static bool instance_exists(char problem, int i) {
  FILE* fp = fopen(stringf("problems/%c.in%d", problem, i).c_str(), "r");
  if (!fp) return false;
  fclose(fp);
  return true;
}

static string judge(
  int id, const string& team, const string& fno,
  const string& path, const string& fn, Settings& settings
) {
  // build attempt
  Attempt att;
  att.id = id;
  strcpy(att.team, team.c_str());
  att.problem = fno[0]-'A';
  char run = scripts[fno.substr(1, fno.size())](
    fno[0], (char*)path.c_str(), (char*)fn.c_str(), settings
  );
  if (run != AC) {
    att.verdict = run;
  }
  else {
    att.verdict = AC;
    for (int i = 1; instance_exists(fno[0], i) && att.verdict == AC; i++) {
      int status = system(
        "diff -wB %s%c.out%d problems/%c.sol%d",
        path.c_str(), fno[0], i, fno[0], i
      );
      if (WEXITSTATUS(status)) att.verdict = WA;
      else {
        status = system(
          "diff %s%c.out%d problems/%c.sol%d",
          path.c_str(), fno[0], i, fno[0], i
        );
        if (WEXITSTATUS(status)) att.verdict = PE;
      }
    }
  }
  att.when = time(nullptr);

  // save attempt info
  Global::lock_att_file();
  if (Global::alive()) {
    FILE* fp = fopen("attempts.bin", "ab");
    fwrite(&att, sizeof att, 1, fp);
    fclose(fp);
  }
  Global::unlock_att_file();

  // return verdict
  static string verdict[] = {"AC", "CE", "RTE", "TLE", "WA", "PE"};
  return
    att.when < settings.noverdict ?
    verdict[int(att.verdict)] :
    "The judge is hiding verdicts!"
  ;
}

struct QueueData {
  int id;
  string team;
  string fno;
  string path;
  string fn;
  Settings settings;
  string verdict;
  bool done;
  QueueData() : done(false) {}
  void push() {
    pthread_mutex_lock(&judger_mutex);
    jqueue.push(this);
    pthread_mutex_unlock(&judger_mutex);
    while (Global::alive() && !done) usleep(25000);
  }
  void judge() {
    verdict = ::judge(id, team, fno, path, fn, settings);
    done = true;
  }
};

static bool valid_filename(Settings& settings, const string& fn) {
  return
    ('A' <= fn[0]) && (fn[0] <= ('A' + int(settings.problems.size())-1)) &&
    (scripts.find(fn.substr(1, fn.size())) != scripts.end())
  ;
}

static int genid() {
  FILE* fp = fopen("nextid.bin", "rb");
  int current, next;
  if (!fp) current = 1, next = 2;
  else {
    fread(&current, sizeof current, 1, fp);
    fclose(fp);
    next = current + 1;
  }
  fp = fopen("nextid.bin", "wb");
  fwrite(&next, sizeof next, 1, fp);
  fclose(fp);
  return current;
}

static __suseconds_t dt(const timeval& start) {
  timeval end;
  gettimeofday(&end, nullptr);
  return
    (end.tv_sec*1000000 + end.tv_usec)-
    (start.tv_sec*1000000 + start.tv_usec)
  ;
}
static char run(
  int s,
  const string& exec_cmd,
  char problem,
  const string& output_path
) {
  __suseconds_t us = s*1000000;

  timeval start;
  gettimeofday(&start, nullptr);

  pid_t proc = fork();
  if (!proc) {
    // TODO lose root permissions
    setpgid(0, 0); // create new process group rooted at proc
    for (int i = 1; instance_exists(problem, i); i++) {
      int status = system(
        "%s < problems/%c.in%d > %s%c.out%d",
        exec_cmd.c_str(),
        problem, i,
        output_path.c_str(), problem, i
      );
      int exit_code = WEXITSTATUS(status);
      if (exit_code) exit(exit_code);
    }
    exit(0);
  }

  int status;
  while (waitpid(proc, &status, WNOHANG) != proc) {
    if (dt(start) > us) {
      kill(-proc, SIGKILL); // the minus kills the whole group rooted at proc
      waitpid(proc, &status, 0);
      return TLE;
    }
    usleep(10000);
  }
  if (WEXITSTATUS(status)) return RTE;
  return AC;
}
static void load_scripts() {
  scripts[".c"] = [](char p, char* path, char* fn, Settings& settings) {
    int status = system("gcc -std=c11 %s -o %s%c -lm", fn, path, p);
    if (WEXITSTATUS(status)) return char(CE);
    return run(
      settings.problems[p-'A'],
      stringf("%s%c", path, p),
      p,
      path
    );
  };
  scripts[".cpp"] = [](char p, char* path, char* fn, Settings& settings) {
    int status = system("g++ -std=c++1y %s -o %s%c", fn, path, p);
    if (WEXITSTATUS(status)) return char(CE);
    return run(
      settings.problems[p-'A'],
      stringf("%s%c", path, p),
      p,
      path
    );
  };
  scripts[".java"] = [](char p, char* path, char* fn, Settings& settings) {
    int status = system("javac %s", fn);
    if (WEXITSTATUS(status)) return char(CE);
    return run(
      settings.problems[p-'A'],
      stringf("java -cp %s %c", path, p),
      p,
      path
    );
  };
  scripts[".py"] = [](char p, char* path, char* fn, Settings& settings) {
    return run(
      settings.problems[p-'A'],
      stringf("python %s", fn),
      p,
      path
    );
  };
  scripts[".py3"] = [](char p, char* path, char* fn, Settings& settings) {
    return run(
      settings.problems[p-'A'],
      stringf("python3 %s", fn),
      p,
      path
    );
  };
}

static void* judger(void*) {
  while (Global::alive()) {
    pthread_mutex_lock(&judger_mutex);
    if (jqueue.empty()) {
      pthread_mutex_unlock(&judger_mutex);
      usleep(25000);
      continue;
    }
    QueueData* qd = jqueue.front(); jqueue.pop();
    pthread_mutex_unlock(&judger_mutex);
    qd->judge();
  }
  return nullptr;
}

namespace Judge {

void fire() {
  load_scripts();
  Global::fire(judger);
}

void attempt(
  int sd,
  const string& teamname, const string& team,
  const string& file_name, int file_size
) {
  Settings settings;

  // check time
  time_t now = time(nullptr);
  if (now < settings.begin || settings.end <= now) {
    ignoresd(sd);
    write(sd, "The contest is not running.", 27);
    return;
  }

  // check file name
  if (!valid_filename(settings, file_name)) {
    ignoresd(sd);
    write(sd, "Invalid file name!", 18);
    return;
  }

  // check file size
  if (file_size > BSIZ) {
    string resp =
      "Files with more than "+to<string>(BSIZ)+" bytes are not allowed!"
    ;
    ignoresd(sd);
    write(sd, resp.c_str(), resp.size());
    return;
  }

  // read data
  char* buf = new char[BSIZ];
  for (int i = 0, fs = file_size; fs > 0;) {
    int rb = read(sd, &buf[i], fs);
    if (rb < 0) {
      write(sd, "Incomplete request!", 19);
      delete[] buf;
      return;
    }
    fs -= rb;
    i += rb;
  }

  // generate id
  Global::lock_nextid_file();
  if (!Global::alive()) {
    Global::unlock_nextid_file();
    delete[] buf;
    return;
  }
  int id = genid();
  Global::unlock_nextid_file();

  // save file
  string fn = "attempts/";
  mkdir(fn.c_str(), 0777);
  fn += (team+"/");
  mkdir(fn.c_str(), 0777);
  fn += file_name[0]; fn += "/";
  mkdir(fn.c_str(), 0777);
  fn += (to<string>(id)+"/");
  mkdir(fn.c_str(), 0777);
  string path = "./"+fn;
  fn += file_name;
  FILE* fp = fopen(fn.c_str(), "wb");
  fwrite(buf, file_size, 1, fp);
  fclose(fp);
  delete[] buf;

  // respond
  string response = "Attempt "+to<string>(id)+": ";
  QueueData qd;
  qd.id = id;
  qd.team = teamname;
  qd.fno = file_name;
  qd.path = path;
  qd.fn = fn;
  qd.settings = settings;
  qd.push();
  response += qd.verdict;
  write(sd, response.c_str(), response.size());
}

} // namespace Judge
<|endoftext|>


<commit_before>#include "core/renderer.h"
#include "structs/model.h"
#include "core/renderer_openGL.h"
#include "core/logger.h"
using namespace flare;

Renderer* Renderer::s_instance = nullptr;

Renderer::Renderer() :
	m_api( GraphicsAPI::Unknown ) {

}

Renderer::~Renderer() {

}

Renderer* Renderer::GetInstance() {
	if( s_instance == nullptr ) {
		s_instance = new Renderer_OpenGL();
	}
	return s_instance;
}

void Renderer::Render() {
	const auto size = m_renderQueue.size();
	for( int i = 0; i < size; ++i ) {
		m_renderQueue[i]->Render();
	}
}

void Renderer::AddToQueue( Model* a_model ) {
	m_renderQueue.push_back( a_model );
}<commit_msg>fix warning<commit_after>#include "core/renderer.h"
#include "structs/model.h"
#include "core/renderer_openGL.h"
#include "core/logger.h"
using namespace flare;

Renderer* Renderer::s_instance = nullptr;

Renderer::Renderer() :
	m_api( GraphicsAPI::Unknown ) {

}

Renderer::~Renderer() {

}

Renderer* Renderer::GetInstance() {
	if( s_instance == nullptr ) {
		s_instance = new Renderer_OpenGL();
	}
	return s_instance;
}

void Renderer::Render() {
	const int size = m_renderQueue.size();
	for( int i = 0; i < size; ++i ) {
		m_renderQueue[i]->Render();
	}
}

void Renderer::AddToQueue( Model* a_model ) {
	m_renderQueue.push_back( a_model );
}<|endoftext|>


<commit_before>#include "cnn/nodes.h"
#include "cnn/cnn.h"
#include "cnn/training.h"
#include "cnn/gpu-ops.h"
#include "cnn/expr.h"
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/algorithm/string.hpp>

#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <utility>
#include <sstream>
#include <random>

using namespace std;
using namespace cnn;
using namespace cnn::expr;

typedef pair<cnn::real, cnn::real> Datum;

const unsigned num_children = 2;
struct Workload {
  pid_t pid;
  unsigned start;
  unsigned end;
  int pipe[2];
};

struct ModelParameters {
  Parameters* m;
  Parameters* b;
};

void BuildComputationGraph(ComputationGraph& cg, ModelParameters& model_parameters, cnn::real* x_value, cnn::real* y_value) {
  Expression m = parameter(cg, model_parameters.m);
  Expression b = parameter(cg, model_parameters.b);

  Expression x = input(cg, x_value);
  Expression y_star = input(cg, y_value);
  Expression y = m * x + b;
  Expression loss = squared_distance(y, y_star);
}

vector<Datum> ReadData(string filename) {
  vector<Datum> data;
  ifstream fs(filename);
  string line;
  while (getline(fs, line)) {
    if (line.size() > 0 && line[0] == '#') {
      continue;
    }
    vector<string> parts;
    boost::split(parts, line, boost::is_any_of("\t"));
    data.push_back(make_pair(atof(parts[0].c_str()), atof(parts[1].c_str())));
  }
  return data;
}

unsigned SpawnChildren(vector<Workload>& workloads) {
  assert (workloads.size() == num_children);
  pid_t pid;
  unsigned cid;
  for (cid = 0; cid < num_children; ++cid) {
    pid = fork();
    if (pid == -1) {
      cerr << "Fork failed. Exiting ...";
      return 1;
    }
    else if (pid == 0) {
      // children shouldn't continue looping
      break;
    }
    workloads[cid].pid = pid;
  }
  return cid;
}

int RunChild(unsigned cid, ComputationGraph& cg, Trainer* trainer, vector<Workload>& workloads,
    const vector<Datum>& data, cnn::real& x_value, cnn::real& y_value, ModelParameters& model_params) {
  assert (cid >= 0 && cid < num_children);
  unsigned start = workloads[cid].start;
  unsigned end = workloads[cid].end;
  assert (start < end);
  assert (end <= data.size());

  cnn::real loss = 0;
  for (auto it = data.begin() + start; it != data.begin() + end; ++it) {
    auto p = *it;
    x_value = get<0>(p);
    y_value = get<1>(p);
    loss += as_scalar(cg.forward());
    cg.backward();
    trainer->update(1.0);
  }
  loss /= (end - start);

  cnn::real m_end = as_scalar(model_params.m->values);
  cnn::real b_end = as_scalar(model_params.b->values);

  write(workloads[cid].pipe[1], (char*)&m_end, sizeof(cnn::real));
  write(workloads[cid].pipe[1], (char*)&b_end, sizeof(cnn::real));
  write(workloads[cid].pipe[1], (char*)&loss, sizeof(cnn::real));
  return 0;
}

void RunParent(unsigned iter, vector<Workload>& workloads, ModelParameters& model_params, Trainer* trainer) {
  vector<cnn::real> m_values;
  vector<cnn::real> b_values;
  vector<cnn::real> loss_values;
  for(unsigned cid = 0; cid < num_children; ++cid) {
    cnn::real m, b, loss;
    read(workloads[cid].pipe[0], (char*)&m, sizeof(cnn::real));
    read(workloads[cid].pipe[0], (char*)&b, sizeof(cnn::real));
    read(workloads[cid].pipe[0], (char*)&loss, sizeof(cnn::real));
    m_values.push_back(m);
    b_values.push_back(b);
    loss_values.push_back(loss);
    wait(NULL);
  }

  cnn::real m = 0.0;
  cnn::real b = 0.0;
  cnn::real loss = 0.0;
  for (unsigned i = 0; i < m_values.size(); ++i) {
    m += m_values[i];
    b += b_values[i];
    loss += loss_values[i];
  }
  m /= m_values.size();
  b /= b_values.size();

  // Update parameters to use the new m and b values
  TensorTools::SetElements(model_params.m->values, {m});
  TensorTools::SetElements(model_params.b->values, {b});
  trainer->update_epoch();
  cerr << iter << "\t" << "loss = " << loss << "\tm = " << m << "\tb = " << b << endl;
}

int main(int argc, char** argv) {
  cnn::Initialize(argc, argv);

  if (argc < 2) {
    cerr << "Usage: " << argv[0] << " data.txt" << endl;
    cerr << "Where data.txt contains tab-delimited pairs of floats." << endl;
    return 1;
  }
  vector<Datum> data = ReadData(argv[1]);
  vector<Workload> workloads(num_children);

  Model model;
  AdamTrainer sgd(&model, 0.0);

  ComputationGraph cg;
  cnn::real x_value, y_value;
  Parameters* m_param = model.add_parameters({1, 1});
  Parameters* b_param = model.add_parameters({1});
  ModelParameters model_params = {m_param, b_param};
  BuildComputationGraph(cg, model_params, &x_value, &y_value);

  for (unsigned cid = 0; cid < num_children; cid++) {
    unsigned start = (unsigned)(1.0 * cid / num_children * data.size() + 0.5);
    unsigned end = (unsigned)(1.0 * (cid + 1) / num_children * data.size() + 0.5);
    workloads[cid].start = start;
    workloads[cid].end = end;
    pipe(workloads[cid].pipe);
  }

  // train the parameters
  for (unsigned iter = 0; true; ++iter) {
    random_shuffle(data.begin(), data.end());
    unsigned cid = SpawnChildren(workloads);

    if (cid < num_children) {
      return RunChild(cid, cg, &sgd, workloads, data, x_value, y_value, model_params);
    }
    else {
      RunParent(iter, workloads, model_params, &sgd);
    }
  }
}

<commit_msg>more minor cleanup<commit_after>#include "cnn/cnn.h"
#include "cnn/training.h"
#include "cnn/expr.h"
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/algorithm/string.hpp>

#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <utility>
#include <sstream>
#include <random>

using namespace std;
using namespace cnn;
using namespace cnn::expr;

typedef pair<cnn::real, cnn::real> Datum;
const unsigned num_children = 2;

cnn::real ReadReal(int pipe) {
  cnn::real v;
  read(pipe, &v, sizeof(cnn::real));
  return v;
}

void WriteReal(int pipe, cnn::real v) {
  write(pipe, &v, sizeof(cnn::real));
}

cnn::real Mean(const vector<cnn::real>& values) {
  return accumulate(values.begin(), values.end(), 0.0) / values.size();
}

struct Workload {
  pid_t pid;
  unsigned start;
  unsigned end;
  int pipe[2];
};

struct ModelParameters {
  Parameters* m;
  Parameters* b;
};

void BuildComputationGraph(ComputationGraph& cg, ModelParameters& model_parameters, cnn::real* x_value, cnn::real* y_value) {
  Expression m = parameter(cg, model_parameters.m);
  Expression b = parameter(cg, model_parameters.b);

  Expression x = input(cg, x_value);
  Expression y_star = input(cg, y_value);
  Expression y = m * x + b;
  Expression loss = squared_distance(y, y_star);
}

vector<Datum> ReadData(string filename) {
  vector<Datum> data;
  ifstream fs(filename);
  string line;
  while (getline(fs, line)) {
    if (line.size() > 0 && line[0] == '#') {
      continue;
    }
    vector<string> parts;
    boost::split(parts, line, boost::is_any_of("\t"));
    data.push_back(make_pair(atof(parts[0].c_str()), atof(parts[1].c_str())));
  }
  return data;
}

unsigned SpawnChildren(vector<Workload>& workloads) {
  assert (workloads.size() == num_children);
  pid_t pid;
  unsigned cid;
  for (cid = 0; cid < num_children; ++cid) {
    pid = fork();
    if (pid == -1) {
      cerr << "Fork failed. Exiting ...";
      return 1;
    }
    else if (pid == 0) {
      // children shouldn't continue looping
      break;
    }
    workloads[cid].pid = pid;
  }
  return cid;
}

int RunChild(unsigned cid, ComputationGraph& cg, Trainer* trainer, vector<Workload>& workloads,
    const vector<Datum>& data, cnn::real& x_value, cnn::real& y_value, ModelParameters& model_params) {
  assert (cid >= 0 && cid < num_children);
  unsigned start = workloads[cid].start;
  unsigned end = workloads[cid].end;
  assert (start < end);
  assert (end <= data.size());

  cnn::real loss = 0;
  for (auto it = data.begin() + start; it != data.begin() + end; ++it) {
    auto p = *it;
    x_value = get<0>(p);
    y_value = get<1>(p);
    loss += as_scalar(cg.forward());
    cg.backward();
    trainer->update(1.0);
  }
  loss /= (end - start);

  cnn::real m_end = as_scalar(model_params.m->values);
  cnn::real b_end = as_scalar(model_params.b->values);

  write(workloads[cid].pipe[1], (char*)&m_end, sizeof(cnn::real));
  write(workloads[cid].pipe[1], (char*)&b_end, sizeof(cnn::real));
  write(workloads[cid].pipe[1], (char*)&loss, sizeof(cnn::real));
  return 0;
}

void RunParent(unsigned iter, vector<Workload>& workloads, ModelParameters& model_params, Trainer* trainer) {
  vector<cnn::real> m_values;
  vector<cnn::real> b_values;
  vector<cnn::real> loss_values;
  for(unsigned cid = 0; cid < num_children; ++cid) {
    cnn::real m = ReadReal(workloads[cid].pipe[0]);
    cnn::real b = ReadReal(workloads[cid].pipe[0]);
    cnn::real loss = ReadReal(workloads[cid].pipe[0]);
    m_values.push_back(m);
    b_values.push_back(b);
    loss_values.push_back(loss);
    wait(NULL);
  }

  cnn::real m = Mean(m_values);
  cnn::real b = 0.0;
  cnn::real loss = 0.0;
  for (unsigned i = 0; i < m_values.size(); ++i) {
    b += b_values[i];
    loss += loss_values[i];
  }

  b /= b_values.size();

  // Update parameters to use the new m and b values
  TensorTools::SetElements(model_params.m->values, {m});
  TensorTools::SetElements(model_params.b->values, {b});
  trainer->update_epoch();
  cerr << iter << "\t" << "loss = " << loss << "\tm = " << m << "\tb = " << b << endl;
}

int main(int argc, char** argv) {
  cnn::Initialize(argc, argv);

  if (argc < 2) {
    cerr << "Usage: " << argv[0] << " data.txt" << endl;
    cerr << "Where data.txt contains tab-delimited pairs of floats." << endl;
    return 1;
  }
  vector<Datum> data = ReadData(argv[1]);
  vector<Workload> workloads(num_children);

  Model model;
  AdamTrainer sgd(&model, 0.0);

  ComputationGraph cg;
  cnn::real x_value, y_value;
  Parameters* m_param = model.add_parameters({1, 1});
  Parameters* b_param = model.add_parameters({1});
  ModelParameters model_params = {m_param, b_param};
  BuildComputationGraph(cg, model_params, &x_value, &y_value);

  for (unsigned cid = 0; cid < num_children; cid++) {
    unsigned start = (unsigned)(1.0 * cid / num_children * data.size() + 0.5);
    unsigned end = (unsigned)(1.0 * (cid + 1) / num_children * data.size() + 0.5);
    workloads[cid].start = start;
    workloads[cid].end = end;
    pipe(workloads[cid].pipe);
  }

  // train the parameters
  for (unsigned iter = 0; true; ++iter) {
    random_shuffle(data.begin(), data.end());
    unsigned cid = SpawnChildren(workloads);

    if (cid < num_children) {
      return RunChild(cid, cg, &sgd, workloads, data, x_value, y_value, model_params);
    }
    else {
      RunParent(iter, workloads, model_params, &sgd);
    }
  }
}

<|endoftext|>


<commit_before>/* * * * * * * * * * * * * * * *
* YHGenomics Inc.
* Author     : yang shubo
* Date       : 2015-10-22
* Description:
* * * * * * * * * * * * * * * */

#ifndef NETWORK_DATA_BUILDER_H_
#define NETWORK_DATA_BUILDER_H_

#include "Macros.h"
#include <memory.h>

// in some cases two tcp message will be combined into one or chopped
// this class will solve the problem
class CircleBuffer
{
public:

    CircleBuffer()
    {
        this->circle_buffer_ = new char[this->buffer_length_];

        this->available_len_ = this->buffer_length_;
        this->used_len_ = 0;
    }

    ~CircleBuffer()
    {
        if ( this->circle_buffer_ != nullptr )
        {
            delete this->circle_buffer_;
            this->circle_buffer_ = nullptr;
        }
    }

    virtual bool push( const char* data, int len )
    {
        if ( available_length() < len )
        {
            throw "[CircleBuffer.cpp] not enough buffer";
        }

        if ( tail_ + len > this->buffer_length_ )
        {
            char* ptail = this->circle_buffer_ + this->tail_;
            int delta_len = this->buffer_length_ - tail_;
            memcpy( ptail, data, delta_len );
            memcpy( this->circle_buffer_, data + delta_len, len - delta_len );
        }
        else
        {
            char* ptail = this->circle_buffer_ + this->tail_;

            memcpy( ptail, data, len );
        }

        this->tail_ = ( this->tail_ + len ) % this->buffer_length_;

        this->used_len_ += len;

        this->available_len_ = this->buffer_length_ - this->used_len_;

        return true;
    }

    virtual char* pop( int len )
    {
        if ( len > this->used_length() )
        {
            return nullptr;
        }

        char* result = new char[len];
        int result_pos = 0;
        char* phead = this->circle_buffer_ + this->head_;

        // there are two pices data
        // one is at end of circle buffer
        // antoher is at front of circle buffer
        if ( ( this->head_ + len ) > this->buffer_length_ )
        {
            int end_len = this->buffer_length_ - this->head_;
            memcpy( result, phead + result_pos, end_len );
            result_pos += this->buffer_length_ - this->head_;
            memcpy( result + result_pos, this->circle_buffer_, ( len - end_len ) );
        }
        // circle buffer contains all data inside
        else
        {
            memcpy( result, phead + result_pos, len );
        }

        this->head_ = ( this->head_ + len ) % this->buffer_length_;

        this->used_len_ -= len;

        this->available_len_ = this->buffer_length_ - this->used_len_;

        return result;
    }

    int length() { return this->buffer_length_; };
    int used_length() { return this->used_len_; };
    int available_length() { return this->available_len_; };

    int tail_ = 0;
    int head_ = 0;

private:

    CircleBuffer( CircleBuffer & ) = delete;
    CircleBuffer( CircleBuffer && ) = delete;
    CircleBuffer operator=( CircleBuffer ) = delete;

    int used_len_ = 0;
    int available_len_ = 0;

    const int buffer_length_ = CIRCLE_BUFFER_SIZE;

    char* circle_buffer_ = nullptr;
};

#endif // !NETWORK_DATA_BUILDER_H_
<commit_msg>fixed a bug<commit_after>/* * * * * * * * * * * * * * * *
* YHGenomics Inc.
* Author     : yang shubo
* Date       : 2015-10-22
* Description:
* * * * * * * * * * * * * * * */

#ifndef NETWORK_DATA_BUILDER_H_
#define NETWORK_DATA_BUILDER_H_

#include "Macros.h"
#include <memory.h>

// in some cases two tcp message will be combined into one or chopped
// this class will solve the problem
class CircleBuffer
{
public:

    CircleBuffer()
    {
        this->circle_buffer_ = new char[this->buffer_length_];

        this->available_len_ = this->buffer_length_;
        this->used_len_ = 0;
    }

    ~CircleBuffer()
    {
        if ( this->circle_buffer_ != nullptr )
        {
            delete this->circle_buffer_;
            this->circle_buffer_ = nullptr;
        }
    }

    virtual bool push( const char* data, int len )
    {
        if ( available_length() < len )
        {
            throw "[CircleBuffer.cpp] not enough buffer";
        }

        if ( ( tail_ + len ) > this->buffer_length_ )
        {
            char* ptail = this->circle_buffer_ + this->tail_;
            int delta_len = this->buffer_length_ - tail_;
            memcpy( ptail, data, delta_len );
            memcpy( this->circle_buffer_, data + delta_len, len - delta_len );
        }
        else
        {
            char* ptail = this->circle_buffer_ + this->tail_;

            memcpy( ptail, data, len );
        }

        this->tail_ = ( this->tail_ + len ) % this->buffer_length_;

        this->used_len_ += len;

        this->available_len_ = this->buffer_length_ - this->used_len_;

        return true;
    }

    virtual char* pop( int len )
    {
        if ( len > this->used_length() )
        {
            return nullptr;
        }

        char* result = new char[len];
        int result_pos = 0;
        char* phead = this->circle_buffer_ + this->head_;

        // there are two pices data
        // one is at end of circle buffer
        // antoher is at front of circle buffer
        if ( ( this->head_ + len ) > this->buffer_length_ )
        {
            int end_len = this->buffer_length_ - this->head_;
            memcpy( result, phead + result_pos, end_len );
            result_pos += this->buffer_length_ - this->head_;
            memcpy( result + result_pos, this->circle_buffer_, ( len - end_len ) );
        }
        // circle buffer contains all data inside
        else
        {
            memcpy( result, phead + result_pos, len );
        }

        this->head_ = ( this->head_ + len ) % this->buffer_length_;

        this->used_len_ -= len;

        this->available_len_ = this->buffer_length_ - this->used_len_;

        return result;
    }

    int length() { return this->buffer_length_; };
    int used_length() { return this->used_len_; };
    int available_length() { return this->available_len_; };

    int tail_ = 0;
    int head_ = 0;

private:

    CircleBuffer( CircleBuffer & ) = delete;
    CircleBuffer( CircleBuffer && ) = delete;
    CircleBuffer operator=( CircleBuffer ) = delete;

    int used_len_ = 0;
    int available_len_ = 0;

    const int buffer_length_ = CIRCLE_BUFFER_SIZE;

    char* circle_buffer_ = nullptr;
};

#endif // !NETWORK_DATA_BUILDER_H_
<|endoftext|>


<commit_before>/* This file is part of Mapnik (c++ mapping toolkit)
 * Copyright (C) 2005 Artem Pavlenko
 *
 * Mapnik 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 any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//$Id: layer.cpp 17 2005-03-08 23:58:43Z pavlenko $

#include <string>
#include "ptr.hpp"
#include "style.hpp"
#include "datasource.hpp"
#include "datasource_cache.hpp"
#include "layer.hpp"

namespace mapnik
{
    using namespace std;

    Layer::Layer(const Parameters& params)
        :params_(params),
	 minZoom_(0),
	 maxZoom_(std::numeric_limits<double>::max()),
	 active_(true),
	 selectable_(false),
	 selection_style_("default_selection")
    {

        try
        {
            name_=params_.get("name");
            //volatile datasource_cache* factory=datasource_cache::instance();
            //ds_=factory->create(params_);
	    ds_=datasource_cache::instance()->create(params_);

        }
        catch (...)
        {
            throw;
        }
    }

    Layer::Layer(const Layer& rhs)
        :params_(rhs.params_),
	 name_(rhs.name_),
	 minZoom_(rhs.minZoom_),
	 maxZoom_(rhs.maxZoom_),
	 active_(rhs.active_),
	 selectable_(rhs.selectable_),
	 ds_(rhs.ds_),
	 styles_(rhs.styles_),
	 selection_style_(rhs.selection_style_) {}

    Layer& Layer::operator=(const Layer& rhs)
    {
        Layer tmp(rhs);
        swap(tmp);
        return *this;
    }

    bool Layer::operator==(Layer const& other) const
    {
	return (this == &other);
    }

    void Layer::swap(const Layer& rhs)
    {
        params_=rhs.params_;
        name_=rhs.name_;
        minZoom_=rhs.minZoom_;
        maxZoom_=rhs.maxZoom_;
        active_=rhs.active_;
        selectable_=rhs.selectable_;
        ds_=rhs.ds_;
        styles_=rhs.styles_;
	selection_style_=rhs.selection_style_;
    }

    Layer::~Layer() {}

    Parameters const& Layer::params() const
    {
        return params_;
    }

    const string& Layer::name() const
    {
        return name_;
    }

    void Layer::add_style(std::string const& stylename)
    {
        styles_.push_back(stylename);
    }

    std::vector<std::string> const& Layer::styles() const
    {
        return styles_;
    }

    void Layer::setMinZoom(double minZoom)
    {
        minZoom_=minZoom;
    }

    void Layer::setMaxZoom(double maxZoom)
    {
        maxZoom_=maxZoom;
    }

    double Layer::getMinZoom() const
    {
        return minZoom_;
    }

    double Layer::getMaxZoom() const
    {
        return maxZoom_;
    }

    void Layer::setActive(bool active)
    {
        active_=active;
    }

    bool Layer::isActive() const
    {
        return active_;
    }

    bool Layer::isVisible(double scale) const
    {
        return isActive() && scale>=minZoom_ && scale<maxZoom_;
    }

    void Layer::setSelectable(bool selectable)
    {
        selectable_=selectable;
    }

    bool Layer::isSelectable() const
    {
        return selectable_;
    }

    const datasource_p& Layer::datasource() const
    {
        return ds_;
    }

    const Envelope<double>& Layer::envelope() const
    {
        return ds_->envelope();
    }

    void Layer::selection_style(const std::string& name)
    {
	selection_style_=name;
    }

    const std::string& Layer::selection_style() const
    {
	return selection_style_;
    }

    void Layer::add_to_selection(ref_ptr<Feature>& feature) const
    {
	selection_.push_back(feature);
    }

    vector<ref_ptr<Feature> >& Layer::selection() const
    {
	return selection_;
    }

    void Layer::clear_selection() const
    {
	selection_.clear();
    }
}
<commit_msg>check datasource in envelope method<commit_after>/* This file is part of Mapnik (c++ mapping toolkit)
 * Copyright (C) 2005 Artem Pavlenko
 *
 * Mapnik 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 any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//$Id: layer.cpp 17 2005-03-08 23:58:43Z pavlenko $

#include <string>
#include "ptr.hpp"
#include "style.hpp"
#include "datasource.hpp"
#include "datasource_cache.hpp"
#include "layer.hpp"

namespace mapnik
{
    using namespace std;

    Layer::Layer(const Parameters& params)
        :params_(params),
	 minZoom_(0),
	 maxZoom_(std::numeric_limits<double>::max()),
	 active_(true),
	 selectable_(false),
	 selection_style_("default_selection")
    {

        try
        {
            name_=params_.get("name");
            //volatile datasource_cache* factory=datasource_cache::instance();
            //ds_=factory->create(params_);
	    ds_=datasource_cache::instance()->create(params_);

        }
        catch (...)
        {
            throw;
        }
    }

    Layer::Layer(const Layer& rhs)
        :params_(rhs.params_),
	 name_(rhs.name_),
	 minZoom_(rhs.minZoom_),
	 maxZoom_(rhs.maxZoom_),
	 active_(rhs.active_),
	 selectable_(rhs.selectable_),
	 ds_(rhs.ds_),
	 styles_(rhs.styles_),
	 selection_style_(rhs.selection_style_) {}

    Layer& Layer::operator=(const Layer& rhs)
    {
        Layer tmp(rhs);
        swap(tmp);
        return *this;
    }

    bool Layer::operator==(Layer const& other) const
    {
	return (this == &other);
    }

    void Layer::swap(const Layer& rhs)
    {
        params_=rhs.params_;
        name_=rhs.name_;
        minZoom_=rhs.minZoom_;
        maxZoom_=rhs.maxZoom_;
        active_=rhs.active_;
        selectable_=rhs.selectable_;
        ds_=rhs.ds_;
        styles_=rhs.styles_;
	selection_style_=rhs.selection_style_;
    }

    Layer::~Layer() {}

    Parameters const& Layer::params() const
    {
        return params_;
    }

    const string& Layer::name() const
    {
        return name_;
    }

    void Layer::add_style(std::string const& stylename)
    {
        styles_.push_back(stylename);
    }

    std::vector<std::string> const& Layer::styles() const
    {
        return styles_;
    }

    void Layer::setMinZoom(double minZoom)
    {
        minZoom_=minZoom;
    }

    void Layer::setMaxZoom(double maxZoom)
    {
        maxZoom_=maxZoom;
    }

    double Layer::getMinZoom() const
    {
        return minZoom_;
    }

    double Layer::getMaxZoom() const
    {
        return maxZoom_;
    }

    void Layer::setActive(bool active)
    {
        active_=active;
    }

    bool Layer::isActive() const
    {
        return active_;
    }

    bool Layer::isVisible(double scale) const
    {
        return isActive() && scale>=minZoom_ && scale<maxZoom_;
    }

    void Layer::setSelectable(bool selectable)
    {
        selectable_=selectable;
    }

    bool Layer::isSelectable() const
    {
        return selectable_;
    }

    const datasource_p& Layer::datasource() const
    {
        return ds_;
    }

    const Envelope<double>& Layer::envelope() const
    {
	if (ds_)
	    return ds_->envelope();
	return Envelope<double>();
    }

    void Layer::selection_style(const std::string& name)
    {
	selection_style_=name;
    }

    const std::string& Layer::selection_style() const
    {
	return selection_style_;
    }

    void Layer::add_to_selection(ref_ptr<Feature>& feature) const
    {
	selection_.push_back(feature);
    }

    vector<ref_ptr<Feature> >& Layer::selection() const
    {
	return selection_;
    }

    void Layer::clear_selection() const
    {
	selection_.clear();
    }
}
<|endoftext|>