<commit_before>// Copyright 2014 Mike Tsao <mike@sowbug.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 <iostream>  // cerr

#include <algorithm>
#include <istream>
#include <sstream>

#include "base58.h"
#include "credentials.h"
#include "crypto.h"
#include "errors.h"
#include "node.h"
#include "node_factory.h"
#include "wallet.h"

Address::Address(const bytes_t& hash160, uint32_t child_num, bool is_public)
  : hash160_(hash160), child_num_(child_num), is_public_(is_public),
    balance_(0) {
}

Wallet::Wallet(Credentials& credentials)
  : credentials_(credentials), root_node_(NULL), child_node_(NULL) {
}

Wallet::~Wallet() {
  for (tx_hashes_to_txs_t::const_iterator i = tx_hashes_to_txs_.begin();
       i != tx_hashes_to_txs_.end();
       ++i) {
    delete i->second;
  }
  for (hash_to_address_t::const_iterator i = watched_addresses_.begin();
       i != watched_addresses_.end();
       ++i) {
    delete i->second;
  }
}

void Wallet::set_root_ext_keys(const bytes_t& ext_pub,
                               const bytes_t& ext_prv_enc) {
  root_ext_pub_ = ext_pub;
  root_ext_prv_enc_ = ext_prv_enc;
}

void Wallet::set_child_ext_keys(const bytes_t& ext_pub,
                                const bytes_t& ext_prv_enc) {
  child_ext_pub_ = ext_pub;
  child_ext_prv_enc_ = ext_prv_enc;
  watched_addresses_.clear();
  addresses_to_report_.clear();
}

bool Wallet::IsWalletLocked() const {
  if (credentials_.isLocked()) {
    std::cerr << "wallet is locked" << std::endl;
    return true;
  }
  return false;
}

bool Wallet::DeriveRootNode(const bytes_t& seed, bytes_t& ext_prv_enc) {
  if (IsWalletLocked()) {
    return false;
  }

  // If the caller passed in a zero-length seed, as a policy we're going to
  // error out. We don't want a user of this method to forget to supply
  // entropy and ship something that seems to work, but gives the same root
  // node to everyone.
  if (seed.empty()) {
    return false;
  }

  std::auto_ptr<Node> node(NodeFactory::CreateNodeFromSeed(seed));
  if (node.get()) {
    if (Crypto::Encrypt(credentials_.ephemeral_key(),
                        node->toSerialized(),
                        ext_prv_enc)) {
      set_root_ext_keys(node->toSerializedPublic(), ext_prv_enc);
      return true;
    }
  }
  return false;
}

bool Wallet::GenerateRootNode(bytes_t& ext_prv_enc) {
  if (IsWalletLocked()) {
    return false;
  }
  bytes_t seed(32, 0);
  if (!Crypto::GetRandomBytes(seed)) {
    return false;
  }
  return DeriveRootNode(seed, ext_prv_enc);
}

bool Wallet::ImportRootNode(const std::string& ext_prv_b58,
                            bytes_t& ext_prv_enc) {
  if (IsWalletLocked()) {
    return false;
  }
  const bytes_t ext_prv = Base58::fromBase58Check(ext_prv_b58);
  std::auto_ptr<Node> node(NodeFactory::CreateNodeFromExtended(ext_prv));
  if (node.get()) {
    if (Crypto::Encrypt(credentials_.ephemeral_key(),
                        ext_prv,
                        ext_prv_enc)) {
      // TODO: this should call RestoreNode instead. search for
      // all calls to this method & do same
      set_root_ext_keys(node->toSerializedPublic(), ext_prv_enc);
      return true;
    }
  }
  return false;
}

bool Wallet::DeriveChildNode(const std::string& path,
                             bool is_watch_only,
                             bytes_t& ext_prv_enc) {
  if (!is_watch_only && IsWalletLocked()) {
    return false;
  }
  if (!hasRootNode()) {
    std::cerr << "no root node" << std::endl;
    return false;
  }

  bool result = true;
  std::auto_ptr<Node> child_node(NodeFactory::
                                 DeriveChildNodeWithPath(*GetRootNode(),
                                                         path));
  if (child_node.get()) {
    const std::string ext_pub_b58 =
      Base58::toBase58Check(child_node->toSerializedPublic());
    if (!is_watch_only) {
      if (!Crypto::Encrypt(credentials_.ephemeral_key(),
                           child_node->toSerialized(),
                           ext_prv_enc)) {
        result = false;
      }
    }
    if (result) {
      bool is_root;
      RestoreNode(ext_pub_b58, ext_prv_enc, is_root);
    }
  }
  return result;
}

void Wallet::WatchAddress(const bytes_t& hash160,
                          uint32_t child_num,
                          bool is_public) {
  if (IsAddressWatched(hash160)) {
    return;
  }
  Address* address = new Address(hash160, child_num, is_public);
  watched_addresses_[hash160] = address;
  addresses_to_report_.insert(hash160);
}

bool Wallet::IsAddressWatched(const bytes_t& hash160) {
  return watched_addresses_.count(hash160) == 1;
}

void Wallet::UpdateAddressBalance(const bytes_t& hash160, uint64_t balance) {
  if (!IsAddressWatched(hash160)) {
    std::cerr << "oops, update address of unwatched address" << std::endl;
    return;
  }
  if (watched_addresses_[hash160]->balance() != balance) {
    watched_addresses_[hash160]->set_balance(balance);
    addresses_to_report_.insert(hash160);
  }
}

void Wallet::RestoreRootNode(const Node* /*node*/) {
  // Nothing to do!
}

void Wallet::RestoreChildNode(const Node* node) {
  uint32_t public_address_count = 8;
  uint32_t change_address_count = 8;
  for (uint32_t i = 0; i < public_address_count; ++i) {
    std::stringstream node_path;
    node_path << "m/0/" << i;  // external path
    std::auto_ptr<Node>
      address_node(NodeFactory::DeriveChildNodeWithPath(*node,
                                                        node_path.str()));
    if (address_node.get()) {
      WatchAddress(Base58::toHash160(address_node->public_key()), i, true);
    }
  }
  for (uint32_t i = 0; i < change_address_count; ++i) {
    std::stringstream node_path;
    node_path << "m/1/" << i;  // internal path
    std::auto_ptr<Node>
      address_node(NodeFactory::DeriveChildNodeWithPath(*node,
                                                        node_path.str()));
    if (address_node.get()) {
      WatchAddress(Base58::toHash160(address_node->public_key()), i, false);
    }
  }
}

bool Wallet::RestoreNode(const std::string& ext_pub_b58,
                         const bytes_t& ext_prv_enc,
                         bool& is_root) {
  const bytes_t ext_pub = Base58::fromBase58Check(ext_pub_b58);
  std::auto_ptr<Node> node;
  node.reset(NodeFactory::CreateNodeFromExtended(ext_pub));
  if (node.get()) {
    if (node->child_num() == 0) {
      if (ext_prv_enc.empty()) {
        return false;
      }
      is_root = true;
      set_root_ext_keys(ext_pub, ext_prv_enc);
      RestoreRootNode(node.get());
      GetRootNode();  // groan -- this regenerates the cached node
    } else {
      is_root = false;
      set_child_ext_keys(ext_pub, ext_prv_enc);
      RestoreChildNode(node.get());
      GetChildNode();  // groan -- this regenerates the cached node
    }
    return true;
  }
  return false;
}

Node* Wallet::GetRootNode() {
  if (!hasRootNode()) {
    return NULL;
  }

  if (credentials_.isLocked()) {
    root_node_.reset(NodeFactory::CreateNodeFromExtended(root_ext_pub_));
  } else {
    bytes_t ext_prv;
    if (Crypto::Decrypt(credentials_.ephemeral_key(),
                        root_ext_prv_enc_,
                        ext_prv)) {
      root_node_.reset(NodeFactory::CreateNodeFromExtended(ext_prv));
    } else {
      root_node_.reset();
    }
  }
  return root_node_.get();
}

Node* Wallet::GetChildNode() {
  if (!hasChildNode()) {
    return NULL;
  }

  if (credentials_.isLocked() || child_ext_prv_enc_.empty()) {
    child_node_.reset(NodeFactory::CreateNodeFromExtended(child_ext_pub_));
  } else {
    bytes_t ext_prv;
    if (Crypto::Decrypt(credentials_.ephemeral_key(),
                        child_ext_prv_enc_,
                        ext_prv)) {
      child_node_.reset(NodeFactory::CreateNodeFromExtended(ext_prv));
    } else {
      child_node_.reset();
    }
  }
  return child_node_.get();
}

static bool SortAddresses(const Address* a, const Address* b) {
  if (a->is_public() != b->is_public()) {
    return a->is_public() > b->is_public();
  }
  return a->child_num() < b->child_num();
}

bool Wallet::GetAddressStatusesToReport(Address::addresses_t& statuses) {
  for (std::set<bytes_t>::const_iterator i = addresses_to_report_.begin();
       i != addresses_to_report_.end();
       ++i) {
    statuses.push_back(watched_addresses_[*i]);
  }
  std::sort(statuses.begin(), statuses.end(), SortAddresses);
  addresses_to_report_.clear();
  return true;
}

bool Wallet::GetTxRequestsToReport(tx_requests_t& requests) {
  requests = tx_requests_;
  tx_requests_.clear();
  return true;
}

void Wallet::HandleTxStatus(const bytes_t& hash, uint32_t /*height*/) {
  tx_requests_.push_back(hash);
}

bool Wallet::DoesTxExist(const bytes_t& hash) {
  return tx_hashes_to_txs_.count(hash) == 1;
}

Transaction* Wallet::GetTx(const bytes_t& hash) {
  return tx_hashes_to_txs_[hash];
}

void Wallet::AddTx(Transaction* transaction) {
  // Stick it in the map.
  tx_hashes_to_txs_[transaction->hash()] = transaction;

  // Check every input to see which output it spends, and if we know
  // about that output, mark it spent.
  for (tx_hashes_to_txs_t::const_iterator i = tx_hashes_to_txs_.begin();
       i != tx_hashes_to_txs_.end();
       ++i) {
    for (tx_ins_t::const_iterator j = i->second->inputs().begin();
         j != i->second->inputs().end();
         ++j) {
      if (DoesTxExist(j->prev_txo_hash())) {
        Transaction* affected_tx = GetTx(j->prev_txo_hash());
        affected_tx->MarkOutputSpent(j->prev_txo_index());
      }
    }
  }
}

void Wallet::HandleTx(const bytes_t& tx_bytes) {
  std::istringstream is;
  const char* p = reinterpret_cast<const char*>(&tx_bytes[0]);
  is.rdbuf()->pubsetbuf(const_cast<char*>(p), tx_bytes.size());
  Transaction* tx = new Transaction(is);
  AddTx(tx);

  std::map<bytes_t, uint64_t> balances;
  for (hash_to_address_t::const_iterator i = watched_addresses_.begin();
       i != watched_addresses_.end();
       ++i) {
    balances[i->first] = 0;
  }

  for (tx_hashes_to_txs_t::const_iterator i = tx_hashes_to_txs_.begin();
       i != tx_hashes_to_txs_.end();
       ++i) {
    for (tx_outs_t::const_iterator j = i->second->outputs().begin();
         j != i->second->outputs().end();
         ++j) {
      const bytes_t hash160 = j->GetSigningAddress();
      if (IsAddressWatched(hash160)) {
        if (!j->is_spent()) {
          balances[hash160] += j->value();
        }
      }
    }
  }

  for (std::map<bytes_t, uint64_t>::const_iterator i = balances.begin();
       i != balances.end();
       ++i) {
    UpdateAddressBalance(i->first, i->second);
  }
}

bool Wallet::IsAddressUsed(const bytes_t& /*hash160*/) {
  return false;  // TODO(miket): implement
}

bytes_t Wallet::GetNextUnusedChangeAddress() {
  uint32_t i = 0;
  while (true) {
    std::stringstream node_path;
    node_path << "m/1/" << i++;  // internal path
    std::auto_ptr<Node> address_node(NodeFactory::
                                     DeriveChildNodeWithPath(*GetChildNode(),
                                                             node_path.str()));
    if (address_node.get()) {
      const bytes_t hash160 = Base58::toHash160(address_node->public_key());
      if (!IsAddressUsed(hash160)) {
        return hash160;
      }
    }
  }
}

bool Wallet::CreateTx(const tx_outs_t& recipients,
                      uint64_t fee,
                      bool should_sign,
                      bytes_t& tx) {
  if (should_sign && IsWalletLocked()) {
    return false;
  }
  TxOut change_txo(0, GetNextUnusedChangeAddress());

  Transaction transaction;
  int error_code = 0;
  tx = transaction.Sign(*GetChildNode(),  // TODO: should_sign
                        GetUnspentTxos(),
                        recipients,
                        change_txo,
                        fee,
                        error_code);
  if (error_code != ERROR_NONE) {
    std::cerr << "CreateTx failed: " << error_code << std::endl;
  }
  return error_code == ERROR_NONE;
}

tx_outs_t Wallet::GetUnspentTxos() {
  tx_outs_t unspent_txos;

  for (tx_hashes_to_txs_t::const_iterator i = tx_hashes_to_txs_.begin();
       i != tx_hashes_to_txs_.end();
       ++i) {
    for (tx_outs_t::const_iterator j = i->second->outputs().begin();
         j != i->second->outputs().end();
         ++j) {
      const bytes_t& address = j->GetSigningAddress();
      if (IsAddressWatched(address)) {
        if (!j->is_spent()) {
          unspent_txos.push_back(TxOut(j->value(), j->script(),
                                       j->tx_output_n(), i->first));
        }
      }
    }
  }
  return unspent_txos;
}
<commit_msg>Don't use zeroth child address.<commit_after>// Copyright 2014 Mike Tsao <mike@sowbug.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 <iostream>  // cerr

#include <algorithm>
#include <istream>
#include <sstream>

#include "base58.h"
#include "credentials.h"
#include "crypto.h"
#include "errors.h"
#include "node.h"
#include "node_factory.h"
#include "wallet.h"

Address::Address(const bytes_t& hash160, uint32_t child_num, bool is_public)
  : hash160_(hash160), child_num_(child_num), is_public_(is_public),
    balance_(0) {
}

Wallet::Wallet(Credentials& credentials)
  : credentials_(credentials), root_node_(NULL), child_node_(NULL) {
}

Wallet::~Wallet() {
  for (tx_hashes_to_txs_t::const_iterator i = tx_hashes_to_txs_.begin();
       i != tx_hashes_to_txs_.end();
       ++i) {
    delete i->second;
  }
  for (hash_to_address_t::const_iterator i = watched_addresses_.begin();
       i != watched_addresses_.end();
       ++i) {
    delete i->second;
  }
}

void Wallet::set_root_ext_keys(const bytes_t& ext_pub,
                               const bytes_t& ext_prv_enc) {
  root_ext_pub_ = ext_pub;
  root_ext_prv_enc_ = ext_prv_enc;
}

void Wallet::set_child_ext_keys(const bytes_t& ext_pub,
                                const bytes_t& ext_prv_enc) {
  child_ext_pub_ = ext_pub;
  child_ext_prv_enc_ = ext_prv_enc;
  watched_addresses_.clear();
  addresses_to_report_.clear();
}

bool Wallet::IsWalletLocked() const {
  if (credentials_.isLocked()) {
    std::cerr << "wallet is locked" << std::endl;
    return true;
  }
  return false;
}

bool Wallet::DeriveRootNode(const bytes_t& seed, bytes_t& ext_prv_enc) {
  if (IsWalletLocked()) {
    return false;
  }

  // If the caller passed in a zero-length seed, as a policy we're going to
  // error out. We don't want a user of this method to forget to supply
  // entropy and ship something that seems to work, but gives the same root
  // node to everyone.
  if (seed.empty()) {
    return false;
  }

  std::auto_ptr<Node> node(NodeFactory::CreateNodeFromSeed(seed));
  if (node.get()) {
    if (Crypto::Encrypt(credentials_.ephemeral_key(),
                        node->toSerialized(),
                        ext_prv_enc)) {
      set_root_ext_keys(node->toSerializedPublic(), ext_prv_enc);
      return true;
    }
  }
  return false;
}

bool Wallet::GenerateRootNode(bytes_t& ext_prv_enc) {
  if (IsWalletLocked()) {
    return false;
  }
  bytes_t seed(32, 0);
  if (!Crypto::GetRandomBytes(seed)) {
    return false;
  }
  return DeriveRootNode(seed, ext_prv_enc);
}

bool Wallet::ImportRootNode(const std::string& ext_prv_b58,
                            bytes_t& ext_prv_enc) {
  if (IsWalletLocked()) {
    return false;
  }
  const bytes_t ext_prv = Base58::fromBase58Check(ext_prv_b58);
  std::auto_ptr<Node> node(NodeFactory::CreateNodeFromExtended(ext_prv));
  if (node.get()) {
    if (Crypto::Encrypt(credentials_.ephemeral_key(),
                        ext_prv,
                        ext_prv_enc)) {
      // TODO: this should call RestoreNode instead. search for
      // all calls to this method & do same
      set_root_ext_keys(node->toSerializedPublic(), ext_prv_enc);
      return true;
    }
  }
  return false;
}

bool Wallet::DeriveChildNode(const std::string& path,
                             bool is_watch_only,
                             bytes_t& ext_prv_enc) {
  if (!is_watch_only && IsWalletLocked()) {
    return false;
  }
  if (!hasRootNode()) {
    std::cerr << "no root node" << std::endl;
    return false;
  }

  bool result = true;
  std::auto_ptr<Node> child_node(NodeFactory::
                                 DeriveChildNodeWithPath(*GetRootNode(),
                                                         path));
  if (child_node.get()) {
    const std::string ext_pub_b58 =
      Base58::toBase58Check(child_node->toSerializedPublic());
    if (!is_watch_only) {
      if (!Crypto::Encrypt(credentials_.ephemeral_key(),
                           child_node->toSerialized(),
                           ext_prv_enc)) {
        result = false;
      }
    }
    if (result) {
      bool is_root;
      RestoreNode(ext_pub_b58, ext_prv_enc, is_root);
    }
  }
  return result;
}

void Wallet::WatchAddress(const bytes_t& hash160,
                          uint32_t child_num,
                          bool is_public) {
  if (IsAddressWatched(hash160)) {
    return;
  }
  Address* address = new Address(hash160, child_num, is_public);
  watched_addresses_[hash160] = address;
  addresses_to_report_.insert(hash160);
}

bool Wallet::IsAddressWatched(const bytes_t& hash160) {
  return watched_addresses_.count(hash160) == 1;
}

void Wallet::UpdateAddressBalance(const bytes_t& hash160, uint64_t balance) {
  if (!IsAddressWatched(hash160)) {
    std::cerr << "oops, update address of unwatched address" << std::endl;
    return;
  }
  if (watched_addresses_[hash160]->balance() != balance) {
    watched_addresses_[hash160]->set_balance(balance);
    addresses_to_report_.insert(hash160);
  }
}

void Wallet::RestoreRootNode(const Node* /*node*/) {
  // Nothing to do!
}

void Wallet::RestoreChildNode(const Node* node) {
  uint32_t start = 1;
  uint32_t public_address_count = 8;
  uint32_t change_address_count = 8;
  for (uint32_t i = start; i < start + public_address_count; ++i) {
    std::stringstream node_path;
    node_path << "m/0/" << i;  // external path
    std::auto_ptr<Node>
      address_node(NodeFactory::DeriveChildNodeWithPath(*node,
                                                        node_path.str()));
    if (address_node.get()) {
      WatchAddress(Base58::toHash160(address_node->public_key()), i, true);
    }
  }
  for (uint32_t i = start; i < start + change_address_count; ++i) {
    std::stringstream node_path;
    node_path << "m/1/" << i;  // internal path
    std::auto_ptr<Node>
      address_node(NodeFactory::DeriveChildNodeWithPath(*node,
                                                        node_path.str()));
    if (address_node.get()) {
      WatchAddress(Base58::toHash160(address_node->public_key()), i, false);
    }
  }
}

bool Wallet::RestoreNode(const std::string& ext_pub_b58,
                         const bytes_t& ext_prv_enc,
                         bool& is_root) {
  const bytes_t ext_pub = Base58::fromBase58Check(ext_pub_b58);
  std::auto_ptr<Node> node;
  node.reset(NodeFactory::CreateNodeFromExtended(ext_pub));
  if (node.get()) {
    if (node->child_num() == 0) {
      if (ext_prv_enc.empty()) {
        return false;
      }
      is_root = true;
      set_root_ext_keys(ext_pub, ext_prv_enc);
      RestoreRootNode(node.get());
      GetRootNode();  // groan -- this regenerates the cached node
    } else {
      is_root = false;
      set_child_ext_keys(ext_pub, ext_prv_enc);
      RestoreChildNode(node.get());
      GetChildNode();  // groan -- this regenerates the cached node
    }
    return true;
  }
  return false;
}

Node* Wallet::GetRootNode() {
  if (!hasRootNode()) {
    return NULL;
  }

  if (credentials_.isLocked()) {
    root_node_.reset(NodeFactory::CreateNodeFromExtended(root_ext_pub_));
  } else {
    bytes_t ext_prv;
    if (Crypto::Decrypt(credentials_.ephemeral_key(),
                        root_ext_prv_enc_,
                        ext_prv)) {
      root_node_.reset(NodeFactory::CreateNodeFromExtended(ext_prv));
    } else {
      root_node_.reset();
    }
  }
  return root_node_.get();
}

Node* Wallet::GetChildNode() {
  if (!hasChildNode()) {
    return NULL;
  }

  if (credentials_.isLocked() || child_ext_prv_enc_.empty()) {
    child_node_.reset(NodeFactory::CreateNodeFromExtended(child_ext_pub_));
  } else {
    bytes_t ext_prv;
    if (Crypto::Decrypt(credentials_.ephemeral_key(),
                        child_ext_prv_enc_,
                        ext_prv)) {
      child_node_.reset(NodeFactory::CreateNodeFromExtended(ext_prv));
    } else {
      child_node_.reset();
    }
  }
  return child_node_.get();
}

static bool SortAddresses(const Address* a, const Address* b) {
  if (a->is_public() != b->is_public()) {
    return a->is_public() > b->is_public();
  }
  return a->child_num() < b->child_num();
}

bool Wallet::GetAddressStatusesToReport(Address::addresses_t& statuses) {
  for (std::set<bytes_t>::const_iterator i = addresses_to_report_.begin();
       i != addresses_to_report_.end();
       ++i) {
    statuses.push_back(watched_addresses_[*i]);
  }
  std::sort(statuses.begin(), statuses.end(), SortAddresses);
  addresses_to_report_.clear();
  return true;
}

bool Wallet::GetTxRequestsToReport(tx_requests_t& requests) {
  requests = tx_requests_;
  tx_requests_.clear();
  return true;
}

void Wallet::HandleTxStatus(const bytes_t& hash, uint32_t /*height*/) {
  tx_requests_.push_back(hash);
}

bool Wallet::DoesTxExist(const bytes_t& hash) {
  return tx_hashes_to_txs_.count(hash) == 1;
}

Transaction* Wallet::GetTx(const bytes_t& hash) {
  return tx_hashes_to_txs_[hash];
}

void Wallet::AddTx(Transaction* transaction) {
  // Stick it in the map.
  tx_hashes_to_txs_[transaction->hash()] = transaction;

  // Check every input to see which output it spends, and if we know
  // about that output, mark it spent.
  for (tx_hashes_to_txs_t::const_iterator i = tx_hashes_to_txs_.begin();
       i != tx_hashes_to_txs_.end();
       ++i) {
    for (tx_ins_t::const_iterator j = i->second->inputs().begin();
         j != i->second->inputs().end();
         ++j) {
      if (DoesTxExist(j->prev_txo_hash())) {
        Transaction* affected_tx = GetTx(j->prev_txo_hash());
        affected_tx->MarkOutputSpent(j->prev_txo_index());
      }
    }
  }
}

void Wallet::HandleTx(const bytes_t& tx_bytes) {
  std::istringstream is;
  const char* p = reinterpret_cast<const char*>(&tx_bytes[0]);
  is.rdbuf()->pubsetbuf(const_cast<char*>(p), tx_bytes.size());
  Transaction* tx = new Transaction(is);
  AddTx(tx);

  std::map<bytes_t, uint64_t> balances;
  for (hash_to_address_t::const_iterator i = watched_addresses_.begin();
       i != watched_addresses_.end();
       ++i) {
    balances[i->first] = 0;
  }

  for (tx_hashes_to_txs_t::const_iterator i = tx_hashes_to_txs_.begin();
       i != tx_hashes_to_txs_.end();
       ++i) {
    for (tx_outs_t::const_iterator j = i->second->outputs().begin();
         j != i->second->outputs().end();
         ++j) {
      const bytes_t hash160 = j->GetSigningAddress();
      if (IsAddressWatched(hash160)) {
        if (!j->is_spent()) {
          balances[hash160] += j->value();
        }
      }
    }
  }

  for (std::map<bytes_t, uint64_t>::const_iterator i = balances.begin();
       i != balances.end();
       ++i) {
    UpdateAddressBalance(i->first, i->second);
  }
}

bool Wallet::IsAddressUsed(const bytes_t& /*hash160*/) {
  return false;  // TODO(miket): implement
}

bytes_t Wallet::GetNextUnusedChangeAddress() {
  uint32_t i = 0;
  while (true) {
    std::stringstream node_path;
    node_path << "m/1/" << i++;  // internal path
    std::auto_ptr<Node> address_node(NodeFactory::
                                     DeriveChildNodeWithPath(*GetChildNode(),
                                                             node_path.str()));
    if (address_node.get()) {
      const bytes_t hash160 = Base58::toHash160(address_node->public_key());
      if (!IsAddressUsed(hash160)) {
        return hash160;
      }
    }
  }
}

bool Wallet::CreateTx(const tx_outs_t& recipients,
                      uint64_t fee,
                      bool should_sign,
                      bytes_t& tx) {
  if (should_sign && IsWalletLocked()) {
    return false;
  }
  TxOut change_txo(0, GetNextUnusedChangeAddress());

  Transaction transaction;
  int error_code = 0;
  tx = transaction.Sign(*GetChildNode(),  // TODO: should_sign
                        GetUnspentTxos(),
                        recipients,
                        change_txo,
                        fee,
                        error_code);
  if (error_code != ERROR_NONE) {
    std::cerr << "CreateTx failed: " << error_code << std::endl;
  }
  return error_code == ERROR_NONE;
}

tx_outs_t Wallet::GetUnspentTxos() {
  tx_outs_t unspent_txos;

  for (tx_hashes_to_txs_t::const_iterator i = tx_hashes_to_txs_.begin();
       i != tx_hashes_to_txs_.end();
       ++i) {
    for (tx_outs_t::const_iterator j = i->second->outputs().begin();
         j != i->second->outputs().end();
         ++j) {
      const bytes_t& address = j->GetSigningAddress();
      if (IsAddressWatched(address)) {
        if (!j->is_spent()) {
          unspent_txos.push_back(TxOut(j->value(), j->script(),
                                       j->tx_output_n(), i->first));
        }
      }
    }
  }
  return unspent_txos;
}
<|endoftext|>


<commit_before>#include "stdafx.h"

#include "OpenGLPlotter.h"
#include "utilShader.h"

#include <GL/glew.h>
#include <GL/glfw.h>

#include <boost/filesystem.hpp>
#include <boost/scoped_array.hpp>
#include <boost/foreach.hpp>

OpenGLPlotter::OpenGLPlotter(unsigned int numNeurons, unsigned int index, float dt)
    : _numNeurons(numNeurons),
    _index(index),
    _dt(dt),
    _graphsize(1000),
    _V(std::deque<float>()),
    _sAMPA(std::deque<float>()),
    _xNMDA(std::deque<float>()),
    _sNMDA(std::deque<float>()),
    _graph(std::unique_ptr<point[]>(new point[1000]))
{
    auto pathVertexShader = boost::filesystem3::path(CL_SOURCE_DIR);
    pathVertexShader /= "/vertexShader.glsl";
    auto pathFragmentShader = boost::filesystem3::path(CL_SOURCE_DIR);
    pathFragmentShader /= "/fragmentShader.glsl";

    if(!glfwInit())
    {
        throw;
    };

    if(!glfwOpenWindow(800, 600, 0, 0, 0, 0, 0, 0, GLFW_WINDOW))
    {
        throw;
    };

    //enable vsync
    glfwSwapInterval(1);

    GLenum glew_status = glewInit();
    if (GLEW_OK != glew_status) {
        //fprintf(stderr, "Error: %s\n", glewGetErrorString(glew_status));
        throw glew_status;
    }

    if (!GLEW_VERSION_2_0) {
        //fprintf(stderr, "No support for OpenGL 2.0 found\n");
        throw;
    }

    GLint link_ok = GL_FALSE;

    GLuint vs, fs;
    if((vs = create_shader(pathVertexShader.string().c_str(), GL_VERTEX_SHADER)) == 0)
        throw;
    if((fs = create_shader(pathFragmentShader.string().c_str(), GL_FRAGMENT_SHADER)) == 0)
        throw;

    _program = glCreateProgram();
    glAttachShader(_program, vs);
    glAttachShader(_program, fs);
    glLinkProgram(_program);
    glGetProgramiv(_program, GL_LINK_STATUS, &link_ok);
    if (!link_ok) {
        //fprintf(stderr, "glLinkProgram:");
        //print_log(program);
        //return 0;
        throw;
    }

    const char* attribute_name;
    attribute_name = "coord2d";
    _attribute_coord2d = glGetAttribLocation(_program, attribute_name);
    if (_attribute_coord2d == -1) {
        throw;
        /*fprintf(stderr, "Could not bind attribute %s\n", attribute_name);
        return 0;*/
    }

    const char* uniform_name;
    uniform_name = "color";
    _uniform_color = glGetUniformLocation(_program, uniform_name);
    if (_uniform_color == -1) {
        fprintf(stderr, "Could not bind uniform %s\n", uniform_name);
        throw;
    }

//    /* Enable blending */
//    glEnable(GL_BLEND);
//    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    // Create the vertex buffer object
    glGenBuffers(1, &_vbo);

    for(unsigned int i = 0; i < _graphsize - 1; ++i)
    {
        _V.push_back(-100);
        _sAMPA.push_back(-100);
        _sNMDA.push_back(-100);
        _xNMDA.push_back(-100);
    }
}

OpenGLPlotter::~OpenGLPlotter()
{
    //glfwTerminate();
}

void OpenGLPlotter::step(const state *curState, const unsigned int t, std::unique_ptr<float[]> const& sumFootprintAMPA, std::unique_ptr<float[]> const& sumFootprintNMDA, std::unique_ptr<float[]> const& sumFootprintGABAA)
{
    static const unsigned int interval = 10;

    _V.push_back(curState[_index].V);
    _sAMPA.push_back(curState[_index].s_AMPA);
    _sNMDA.push_back(curState[_index].s_NMDA);
    _xNMDA.push_back(curState[_index].x_NMDA);
    int size = _V.size();

    if((size >= _graphsize) && (t % interval == 0))
    {
        glUseProgram(_program);

        glClearColor(0.0, 0.0, 0.0, 0.0);
        glClear(GL_COLOR_BUFFER_BIT);

        /* Draw using the vertices in our vertex buffer object */
        glBindBuffer(GL_ARRAY_BUFFER, _vbo);

        for(int i=0; i < static_cast<int>(_graphsize); ++i)
        {
            _graph[i].x = (i - (static_cast<int>(_graphsize)/2)) / (size/2.0);
            _graph[i].y = _sAMPA[i] - 1;
        }

        // Tell OpenGL to copy our array to the buffer object
        glBufferData(GL_ARRAY_BUFFER, size * sizeof(point), _graph.get(), GL_DYNAMIC_DRAW);

        glEnableVertexAttribArray(_attribute_coord2d);
        glVertexAttribPointer(
            _attribute_coord2d,   // attribute
            2,                   // number of elements per vertex, here (x,y)
            GL_FLOAT,            // the type of each element
            GL_FALSE,            // take our values as-is
            0,                   // no space between values
            0                    // use the vertex buffer object
            );

        glUniform4f(_uniform_color, 0, 0, 1, 1);
        glDrawArrays(GL_LINE_STRIP, 0, size);

        for(int i=0; i < static_cast<int>(_graphsize); ++i)
        {
            _graph[i].x = (i - (static_cast<int>(_graphsize)/2)) / (size/2.0);
            _graph[i].y = _sNMDA[i] - 1;
        }

        // Tell OpenGL to copy our array to the buffer object
        glBufferData(GL_ARRAY_BUFFER, size * sizeof(point), _graph.get(), GL_DYNAMIC_DRAW);

        glEnableVertexAttribArray(_attribute_coord2d);
        glVertexAttribPointer(
            _attribute_coord2d,   // attribute
            2,                   // number of elements per vertex, here (x,y)
            GL_FLOAT,            // the type of each element
            GL_FALSE,            // take our values as-is
            0,                   // no space between values
            0                    // use the vertex buffer object
            );

        glUniform4f(_uniform_color, 0, 1, 0, 1);
        glDrawArrays(GL_LINE_STRIP, 0, size);

        for(int i=0; i < static_cast<int>(_graphsize); ++i)
        {
            _graph[i].x = (i - (static_cast<int>(_graphsize)/2)) / (size/2.0);
            _graph[i].y = _xNMDA[i] - 1;
        }

        // Tell OpenGL to copy our array to the buffer object
        glBufferData(GL_ARRAY_BUFFER, size * sizeof(point), _graph.get(), GL_DYNAMIC_DRAW);

        glEnableVertexAttribArray(_attribute_coord2d);
        glVertexAttribPointer(
            _attribute_coord2d,   // attribute
            2,                   // number of elements per vertex, here (x,y)
            GL_FLOAT,            // the type of each element
            GL_FALSE,            // take our values as-is
            0,                   // no space between values
            0                    // use the vertex buffer object
            );

        glUniform4f(_uniform_color, 0, 0.5, 0.5, 1);
        glDrawArrays(GL_LINE_STRIP, 0, size);

        for(int i=0; i < static_cast<int>(_graphsize); ++i)
        {
            _graph[i].x = (i - (static_cast<int>(_graphsize)/2)) / (size/2.0);
            _graph[i].y = _V[i] / 80.0 + 0.2;
        }

        // Tell OpenGL to copy our array to the buffer object
        glBufferData(GL_ARRAY_BUFFER, size * sizeof(point), _graph.get(), GL_DYNAMIC_DRAW);

        glEnableVertexAttribArray(_attribute_coord2d);
        glVertexAttribPointer(
            _attribute_coord2d,   // attribute
            2,                   // number of elements per vertex, here (x,y)
            GL_FLOAT,            // the type of each element
            GL_FALSE,            // take our values as-is
            0,                   // no space between values
            0                    // use the vertex buffer object
            );

        //glUniform1f(uniform_sprite, 0);
        glUniform4f(_uniform_color, 1, 0, 0, 1);
        glDrawArrays(GL_LINE_STRIP, 0, size);

        /* Stop using the vertex buffer object */
        glDisableVertexAttribArray(_attribute_coord2d);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glfwSwapBuffers();

        for(unsigned int j = 0; j < interval; ++j)
        {
            _V.pop_front();
            _sAMPA.pop_front();
            _sNMDA.pop_front();
            _xNMDA.pop_front();
        }
    }
}

void OpenGLPlotter::plot()
{
    glfwTerminate();
    //getchar();
}
<commit_msg>set viewport for opengl plot<commit_after>#include "stdafx.h"

#include "OpenGLPlotter.h"
#include "utilShader.h"

#include <GL/glew.h>
#include <GL/glfw.h>

#include <boost/filesystem.hpp>
#include <boost/scoped_array.hpp>
#include <boost/foreach.hpp>

OpenGLPlotter::OpenGLPlotter(unsigned int numNeurons, unsigned int index, float dt)
    : _numNeurons(numNeurons),
    _index(index),
    _dt(dt),
    _graphsize(1000),
    _V(std::deque<float>()),
    _sAMPA(std::deque<float>()),
    _xNMDA(std::deque<float>()),
    _sNMDA(std::deque<float>()),
    _graph(std::unique_ptr<point[]>(new point[1000]))
{
    auto pathVertexShader = boost::filesystem3::path(CL_SOURCE_DIR);
    pathVertexShader /= "/vertexShader.glsl";
    auto pathFragmentShader = boost::filesystem3::path(CL_SOURCE_DIR);
    pathFragmentShader /= "/fragmentShader.glsl";

    if(!glfwInit())
    {
        throw;
    };

    if(!glfwOpenWindow(800, 600, 0, 0, 0, 0, 0, 0, GLFW_WINDOW))
    {
        throw;
    };

    //enable vsync
    glfwSwapInterval(1);

    GLenum glew_status = glewInit();
    if (GLEW_OK != glew_status) {
        //fprintf(stderr, "Error: %s\n", glewGetErrorString(glew_status));
        throw glew_status;
    }

    if (!GLEW_VERSION_2_0) {
        //fprintf(stderr, "No support for OpenGL 2.0 found\n");
        throw;
    }

    GLint link_ok = GL_FALSE;

    GLuint vs, fs;
    if((vs = create_shader(pathVertexShader.string().c_str(), GL_VERTEX_SHADER)) == 0)
        throw;
    if((fs = create_shader(pathFragmentShader.string().c_str(), GL_FRAGMENT_SHADER)) == 0)
        throw;

    _program = glCreateProgram();
    glAttachShader(_program, vs);
    glAttachShader(_program, fs);
    glLinkProgram(_program);
    glGetProgramiv(_program, GL_LINK_STATUS, &link_ok);
    if (!link_ok) {
        //fprintf(stderr, "glLinkProgram:");
        //print_log(program);
        //return 0;
        throw;
    }

    const char* attribute_name;
    attribute_name = "coord2d";
    _attribute_coord2d = glGetAttribLocation(_program, attribute_name);
    if (_attribute_coord2d == -1) {
        throw;
        /*fprintf(stderr, "Could not bind attribute %s\n", attribute_name);
        return 0;*/
    }

    const char* uniform_name;
    uniform_name = "color";
    _uniform_color = glGetUniformLocation(_program, uniform_name);
    if (_uniform_color == -1) {
        fprintf(stderr, "Could not bind uniform %s\n", uniform_name);
        throw;
    }

    glViewport(0, 0, _graphsize, 500);

//    /* Enable blending */
//    glEnable(GL_BLEND);
//    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    // Create the vertex buffer object
    glGenBuffers(1, &_vbo);

    //for(unsigned int i = 0; i < _graphsize - 1; ++i)
    //{
    //    _V.push_back(-100);
    //    _sAMPA.push_back(-100);
    //    _sNMDA.push_back(-100);
    //    _xNMDA.push_back(-100);
    //}
}

OpenGLPlotter::~OpenGLPlotter()
{
    //glfwTerminate();
}

void OpenGLPlotter::step(const state *curState, const unsigned int t, std::unique_ptr<float[]> const& sumFootprintAMPA, std::unique_ptr<float[]> const& sumFootprintNMDA, std::unique_ptr<float[]> const& sumFootprintGABAA)
{
    static const unsigned int interval = 10;

    _V.push_back(curState[_index].V);
    _sAMPA.push_back(curState[_index].s_AMPA);
    _sNMDA.push_back(curState[_index].s_NMDA);
    _xNMDA.push_back(curState[_index].x_NMDA);
    int size = _V.size();

    if(t % interval == 0)
    {
        glUseProgram(_program);

        glClearColor(255.0, 255.0, 255.0, 0.0);
        glClear(GL_COLOR_BUFFER_BIT);

        /* Draw using the vertices in our vertex buffer object */
        glBindBuffer(GL_ARRAY_BUFFER, _vbo);

        for(int i=0; i < size; ++i)
        {
            _graph[i].x = (i - (static_cast<int>(_graphsize)/2)) / (size/2.0);
            _graph[i].y = _sAMPA[size-i-1] - 1;
        }

        // Tell OpenGL to copy our array to the buffer object
        glBufferData(GL_ARRAY_BUFFER, size * sizeof(point), _graph.get(), GL_DYNAMIC_DRAW);

        glEnableVertexAttribArray(_attribute_coord2d);
        glVertexAttribPointer(
            _attribute_coord2d,   // attribute
            2,                   // number of elements per vertex, here (x,y)
            GL_FLOAT,            // the type of each element
            GL_FALSE,            // take our values as-is
            0,                   // no space between values
            0                    // use the vertex buffer object
            );

        glUniform4f(_uniform_color, 0, 0, 1, 1);
        glDrawArrays(GL_LINE_STRIP, 0, size);

        for(int i=0; i < size; ++i)
        {
            _graph[i].x = (i - (static_cast<int>(_graphsize)/2)) / (size/2.0);
            _graph[i].y = _sNMDA[size-i-1] - 1;
        }

        // Tell OpenGL to copy our array to the buffer object
        glBufferData(GL_ARRAY_BUFFER, size * sizeof(point), _graph.get(), GL_DYNAMIC_DRAW);

        glEnableVertexAttribArray(_attribute_coord2d);
        glVertexAttribPointer(
            _attribute_coord2d,   // attribute
            2,                   // number of elements per vertex, here (x,y)
            GL_FLOAT,            // the type of each element
            GL_FALSE,            // take our values as-is
            0,                   // no space between values
            0                    // use the vertex buffer object
            );

        glUniform4f(_uniform_color, 0, 1, 0, 1);
        glDrawArrays(GL_LINE_STRIP, 0, size);

        for(int i=0; i < size; ++i)
        {
            _graph[i].x = (i - (static_cast<int>(_graphsize)/2)) / (size/2.0);
            _graph[i].y = _xNMDA[size-i-1] - 1;
        }

        // Tell OpenGL to copy our array to the buffer object
        glBufferData(GL_ARRAY_BUFFER, size * sizeof(point), _graph.get(), GL_DYNAMIC_DRAW);

        glEnableVertexAttribArray(_attribute_coord2d);
        glVertexAttribPointer(
            _attribute_coord2d,   // attribute
            2,                   // number of elements per vertex, here (x,y)
            GL_FLOAT,            // the type of each element
            GL_FALSE,            // take our values as-is
            0,                   // no space between values
            0                    // use the vertex buffer object
            );

        glUniform4f(_uniform_color, 0, 0.5, 0.5, 1);
        glDrawArrays(GL_LINE_STRIP, 0, size);

        for(int i=0; i < size; ++i)
        {
            _graph[i].x = (i - (static_cast<int>(_graphsize)/2)) / (size/2.0);
            _graph[i].y = _V[size-i-1] / 80.0 + 0.2;
        }

        // Tell OpenGL to copy our array to the buffer object
        glBufferData(GL_ARRAY_BUFFER, size * sizeof(point), _graph.get(), GL_DYNAMIC_DRAW);

        glEnableVertexAttribArray(_attribute_coord2d);
        glVertexAttribPointer(
            _attribute_coord2d,   // attribute
            2,                   // number of elements per vertex, here (x,y)
            GL_FLOAT,            // the type of each element
            GL_FALSE,            // take our values as-is
            0,                   // no space between values
            0                    // use the vertex buffer object
            );

        //glUniform1f(uniform_sprite, 0);
        glUniform4f(_uniform_color, 1, 0, 0, 1);
        glDrawArrays(GL_LINE_STRIP, 0, size);

        /* Stop using the vertex buffer object */
        glDisableVertexAttribArray(_attribute_coord2d);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glfwSwapBuffers();
        if(size >= _graphsize)
        {
            for(unsigned int j = 0; j < interval; ++j)
            {
                _V.pop_front();
                _sAMPA.pop_front();
                _sNMDA.pop_front();
                _xNMDA.pop_front();
            }
        }
    }
}

void OpenGLPlotter::plot()
{
    glfwTerminate();
    //getchar();
}
<|endoftext|>


<commit_before>/*
 * irods_environment_properties.cpp
 *
 */

#include "irods_environment_properties.hpp"
#include "irods_get_full_path_for_config_file.hpp"

#include "rods.h"
#include "irods_log.hpp"
#include "irods_lookup_table.hpp"
#include "irods_home_directory.hpp"
#include "readServerConfig.hpp"

#include <string>
#include <algorithm>
#include <fstream>

#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;

#define BUF_LEN 500

namespace irods {

    const std::string environment_properties::LEGACY_ENV_FILE = "/.irods/.irodsEnv";
    const std::string environment_properties::JSON_ENV_FILE   = "/.irods/irods_environment.json";

// Access method for singleton
    environment_properties& environment_properties::getInstance() {
        static environment_properties instance;
        return instance;
    }

    error environment_properties::capture_if_needed() {
        error result = SUCCESS();
        if ( !captured_ ) {
            result = capture();
        }
        return result;
    }

    environment_properties::environment_properties() :
        captured_( false ) {

        legacy_key_map_[ "irodsUserName" ]                = CFG_IRODS_USER_NAME_KW;
        legacy_key_map_[ "irodsHost" ]                    = CFG_IRODS_HOST_KW;
        legacy_key_map_[ "irodsPort" ]                    = CFG_IRODS_PORT_KW;
        legacy_key_map_[ "xmsgHost" ]                     = CFG_IRODS_XMSG_HOST_KW;
        legacy_key_map_[ "xmsgPort" ]                     = CFG_IRODS_XMSG_PORT_KW;
        legacy_key_map_[ "irodsHome" ]                    = CFG_IRODS_HOME_KW;
        legacy_key_map_[ "irodsCwd" ]                     = CFG_IRODS_CWD_KW;
        legacy_key_map_[ "irodsAuthScheme" ]              = CFG_IRODS_AUTHENTICATION_SCHEME_KW;
        legacy_key_map_[ "irodsDefResource" ]             = CFG_IRODS_DEFAULT_RESOURCE_KW;
        legacy_key_map_[ "irodsZone" ]                    = CFG_IRODS_ZONE_KW;
        legacy_key_map_[ "irodsServerDn" ]                = CFG_IRODS_GSI_SERVER_DN_KW;
        legacy_key_map_[ "irodsLogLevel" ]                = CFG_IRODS_LOG_LEVEL_KW;
        legacy_key_map_[ "irodsAuthFileName" ]            = CFG_IRODS_AUTHENTICATION_FILE_KW;
        legacy_key_map_[ "irodsDebug" ]                   = CFG_IRODS_DEBUG_KW;
        legacy_key_map_[ "irodsClientServerPolicy" ]      = CFG_IRODS_CLIENT_SERVER_POLICY_KW;
        legacy_key_map_[ "irodsClientServerNegotiation" ] = CFG_IRODS_CLIENT_SERVER_NEGOTIATION_KW;
        legacy_key_map_[ "irodsEncryptionKeySize" ]       = CFG_IRODS_ENCRYPTION_KEY_SIZE_KW;
        legacy_key_map_[ "irodsEncryptionSaltSize" ]      = CFG_IRODS_ENCRYPTION_SALT_SIZE_KW;
        legacy_key_map_[ "irodsEncryptionNumHashRounds" ] = CFG_IRODS_ENCRYPTION_NUM_HASH_ROUNDS_KW;
        legacy_key_map_[ "irodsEncryptionAlgorithm" ]     = CFG_IRODS_ENCRYPTION_ALGORITHM_KW;
        legacy_key_map_[ "irodsDefaultHashScheme" ]       = CFG_IRODS_DEFAULT_HASH_SCHEME_KW;
        legacy_key_map_[ "irodsMatchHashPolicy" ]         = CFG_IRODS_MATCH_HASH_POLICY_KW;

    } // ctor

    error environment_properties::get_json_environment_file(
        std::string& _env_file,
        std::string& _session_file ) {
        // capture parent process id for use in creation of 'session'
        // file which contains the cwd for a given session.  this cwd
        // is only updated by the icd command which writes a new irods
        // CFG_IRODS_CWD_KW to the session dir which repaves the existing
        // one in the original irodsEnv file.
        std::stringstream ppid_str; ppid_str << getppid();

        // if a json version exists, then attempt to capture
        // that
        std::string json_file( IRODS_HOME_DIRECTORY );
        std::string json_session_file( IRODS_HOME_DIRECTORY );
        std::string env_var = to_env( CFG_IRODS_ENVIRONMENT_FILE_KW );
        char* irods_env = getenv(
                              to_env(
                                  CFG_IRODS_ENVIRONMENT_FILE_KW ).c_str() );
        if ( irods_env && strlen( irods_env ) > 0 ) {
            json_file = irods_env;
            // "cwd" is used in this case instead of the ppid given the
            // assumption that scripts will set the env file var to allow
            // for more complex interactions possibly yielding complex pid
            // hierarchies.  this routes all references to the same session
            // for this given use case
            json_session_file = json_file + ".cwd";

        }
        else {
            char* home_dir = getenv( "HOME" );
            // if home env exists, prefer that for run in place
            // or use of existing irods service accound
            if ( home_dir ) {
                json_file = home_dir;
            }

            json_file += JSON_ENV_FILE;
            json_session_file = json_file + "." + ppid_str.str();

        }

        _env_file     = json_file;
        _session_file = json_session_file;

        return SUCCESS();

    } // get_json_environment_file

    error environment_properties::get_legacy_environment_file(
        std::string& _env_file,
        std::string& _session_file ) {
        printf(
            "get_legacy_environment_file - use of legacy configuration is deprecated\n" );
        // capture parent process id for use in creation of 'session'
        // file which contains the cwd for a given session.  this cwd
        // is only updated by the icd command which writes a new irods
        // CFG_IRODS_CWD_KW to the session dir which repaves the existing
        // one in the original irodsEnv file.
        std::stringstream ppid_str; ppid_str << getppid();

        std::string legacy_file( IRODS_HOME_DIRECTORY );
        std::string legacy_session_file( IRODS_HOME_DIRECTORY );
        char* irods_env = getenv(
                              to_env(
                                  CFG_IRODS_ENVIRONMENT_FILE_KW ).c_str() );
        if ( irods_env && strlen( irods_env ) != 0 ) {
            legacy_file = irods_env;

            // "cwd" is used in this case instead of the ppid given the
            // assumption that scripts will set the env file var to allow
            // for more complex interactions possibly yielding complex pid
            // hierarchies.  this routes all references to the same session
            // for this given use case
            legacy_session_file = legacy_file + ".cwd";

        }
        else {
            char* home_dir = getenv( "HOME" );
            // if home env exists, prefer that for run in place
            // or use of existing irods service accound
            if ( home_dir ) {
                legacy_file = home_dir;
            }

            legacy_file += LEGACY_ENV_FILE;
            legacy_session_file = legacy_file + "." + ppid_str.str();

        }

        _env_file     = legacy_file;
        _session_file = legacy_session_file;

        return SUCCESS();

    } // get_legacy_environment_file

    error environment_properties::capture() {
        std::string json_file, json_session_file;
        error ret = get_json_environment_file(
                        json_file,
                        json_session_file );

        bool do_parse_legacy = false;
        if ( ret.ok() ) {
            if ( fs::exists( json_file ) ) {
                ret = capture_json( json_file );
                if ( !ret.ok() ) {
                    irods::log( ret );
                    do_parse_legacy = true;
                }
                else {
                    config_props_.set< std::string >(
                        CFG_IRODS_ENVIRONMENT_FILE_KW,
                        json_file );
                    ret = capture_json( json_session_file );
                    if ( !ret.ok() ) {
                        // debug - irods::log( PASS( ret ) );
                    }
                    config_props_.set< std::string >(
                        CFG_IRODS_SESSION_ENVIRONMENT_FILE_KW,
                        json_session_file );
                }
            }
            else {
                do_parse_legacy = true;
            }
        }
        else {
            do_parse_legacy = true;
        }

        if ( do_parse_legacy ) {
            std::string legacy_file, legacy_session_file;
            ret = get_legacy_environment_file(
                      legacy_file,
                      legacy_session_file );
            if ( ret.ok() ) {
                ret = capture_legacy( legacy_file );
                if ( !ret.ok() ) {
                    // debug - irods::log( PASS( ret ) );
                } else {
                    config_props_.set< std::string >(
                        CFG_IRODS_ENVIRONMENT_FILE_KW,
                        legacy_file );
                }

                // session file ( written by icd ) already moved
                // to json
                ret = capture_json( legacy_session_file );
                if ( !ret.ok() ) {
                    // debug - irods::log( PASS( ret ) );
                }

                config_props_.set< std::string >(
                    CFG_IRODS_SESSION_ENVIRONMENT_FILE_KW,
                    legacy_session_file );

            }
            else {
                // debug - irods::log( PASS( ret ) );

            }

        } // do parse legacy

        // set the captured flag so we no its already
        // been captured
        captured_ = true;
        return SUCCESS();

    } // capture

    error environment_properties::capture_json(
        const std::string& _fn ) {
        error ret = config_props_.load( _fn );
        return ret;

    } // capture_json

    error environment_properties::capture_legacy(
        const std::string& _fn ) {

        std::ifstream in_file(
            _fn.c_str(),
            std::ios::in );
        if ( !in_file.is_open() ) {
            std::string msg( "failed to open legacy file [" );
            msg += _fn;
            msg += "]";
            return ERROR( SYS_INVALID_FILE_PATH, msg );
        }

        std::string line;
        while ( getline( in_file, line ) ) {
            // left trim whitespace
            line.erase(
                line.begin(),
                std::find_if(
                    line.begin(),
                    line.end(),
                    std::not1(
                        std::ptr_fun<int, int>(
                            std::isspace ) ) ) );
            // skip comments
            if ( '#' == line[0] ) {
                continue;
            }

            std::vector< std::string > toks;
            try {
                boost::split(
                    toks,
                    line,
                    boost::is_any_of( "\t " ),
                    boost::token_compress_on );
            }
            catch ( boost::exception& ) {
                rodsLog( LOG_ERROR, "boost::split failed on line [%s]", line.c_str() );
                continue;
            }
            if ( toks.size() != 2 ||
                    toks[0].empty()  ||
                    toks[1].empty() ) {
                rodsLog(
                    LOG_NOTICE,
                    "environment_properties :: invalid line [%s]",
                    line.c_str() );
                continue;
            }

            std::string& key = toks[0];
            if ( legacy_key_map_.has_entry( key ) ) {
                key = legacy_key_map_[ key ];

            } //if has entry

            std::string& val = toks[1];

            char front = *( val.begin() );
            if ( '"'  == front ||
                    '\'' == front ) {
                val.erase( 0, 1 );
            }

            char back = *( val.rbegin() );
            if ( '"'  == back ||
                    '\'' == back ) {
                val.erase( val.size() - 1 );
            }

            error ret;
            if ( CFG_IRODS_PORT_KW                        == key ||
                 CFG_IRODS_XMSG_PORT_KW                   == key ||
                 CFG_IRODS_LOG_LEVEL_KW                   == key ||
                 CFG_IRODS_ENCRYPTION_KEY_SIZE_KW         == key ||
                 CFG_IRODS_ENCRYPTION_SALT_SIZE_KW        == key ||
                 CFG_IRODS_ENCRYPTION_NUM_HASH_ROUNDS_KW  == key ) {
                try {
                    int i_val = boost::lexical_cast< int >( val );
                    ret = config_props_.set< int >( key, i_val );
                }
                catch ( ... ) {
                    rodsLog(
                        LOG_ERROR,
                        "environment_properties :: lexical_cast failed for [%s]-[%s]",
                        key.c_str(),
                        val.c_str() );
                }
            }
            else {
                ret = config_props_.set <
                      std::string > (
                          key,
                          val );
            }
            if ( !ret.ok() ) {
                irods::log( PASS( ret ) );
            }

        } // while

        in_file.close();

        return SUCCESS();

    } // environment_properties::capture_legacy

} // namespace irods
<commit_msg>[#2686] move deprecation warning to more appropriate location<commit_after>/*
 * irods_environment_properties.cpp
 *
 */

#include "irods_environment_properties.hpp"
#include "irods_get_full_path_for_config_file.hpp"

#include "rods.h"
#include "irods_log.hpp"
#include "irods_lookup_table.hpp"
#include "irods_home_directory.hpp"
#include "readServerConfig.hpp"

#include <string>
#include <algorithm>
#include <fstream>

#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;

#define BUF_LEN 500

namespace irods {

    const std::string environment_properties::LEGACY_ENV_FILE = "/.irods/.irodsEnv";
    const std::string environment_properties::JSON_ENV_FILE   = "/.irods/irods_environment.json";

// Access method for singleton
    environment_properties& environment_properties::getInstance() {
        static environment_properties instance;
        return instance;
    }

    error environment_properties::capture_if_needed() {
        error result = SUCCESS();
        if ( !captured_ ) {
            result = capture();
        }
        return result;
    }

    environment_properties::environment_properties() :
        captured_( false ) {

        legacy_key_map_[ "irodsUserName" ]                = CFG_IRODS_USER_NAME_KW;
        legacy_key_map_[ "irodsHost" ]                    = CFG_IRODS_HOST_KW;
        legacy_key_map_[ "irodsPort" ]                    = CFG_IRODS_PORT_KW;
        legacy_key_map_[ "xmsgHost" ]                     = CFG_IRODS_XMSG_HOST_KW;
        legacy_key_map_[ "xmsgPort" ]                     = CFG_IRODS_XMSG_PORT_KW;
        legacy_key_map_[ "irodsHome" ]                    = CFG_IRODS_HOME_KW;
        legacy_key_map_[ "irodsCwd" ]                     = CFG_IRODS_CWD_KW;
        legacy_key_map_[ "irodsAuthScheme" ]              = CFG_IRODS_AUTHENTICATION_SCHEME_KW;
        legacy_key_map_[ "irodsDefResource" ]             = CFG_IRODS_DEFAULT_RESOURCE_KW;
        legacy_key_map_[ "irodsZone" ]                    = CFG_IRODS_ZONE_KW;
        legacy_key_map_[ "irodsServerDn" ]                = CFG_IRODS_GSI_SERVER_DN_KW;
        legacy_key_map_[ "irodsLogLevel" ]                = CFG_IRODS_LOG_LEVEL_KW;
        legacy_key_map_[ "irodsAuthFileName" ]            = CFG_IRODS_AUTHENTICATION_FILE_KW;
        legacy_key_map_[ "irodsDebug" ]                   = CFG_IRODS_DEBUG_KW;
        legacy_key_map_[ "irodsClientServerPolicy" ]      = CFG_IRODS_CLIENT_SERVER_POLICY_KW;
        legacy_key_map_[ "irodsClientServerNegotiation" ] = CFG_IRODS_CLIENT_SERVER_NEGOTIATION_KW;
        legacy_key_map_[ "irodsEncryptionKeySize" ]       = CFG_IRODS_ENCRYPTION_KEY_SIZE_KW;
        legacy_key_map_[ "irodsEncryptionSaltSize" ]      = CFG_IRODS_ENCRYPTION_SALT_SIZE_KW;
        legacy_key_map_[ "irodsEncryptionNumHashRounds" ] = CFG_IRODS_ENCRYPTION_NUM_HASH_ROUNDS_KW;
        legacy_key_map_[ "irodsEncryptionAlgorithm" ]     = CFG_IRODS_ENCRYPTION_ALGORITHM_KW;
        legacy_key_map_[ "irodsDefaultHashScheme" ]       = CFG_IRODS_DEFAULT_HASH_SCHEME_KW;
        legacy_key_map_[ "irodsMatchHashPolicy" ]         = CFG_IRODS_MATCH_HASH_POLICY_KW;

    } // ctor

    error environment_properties::get_json_environment_file(
        std::string& _env_file,
        std::string& _session_file ) {
        // capture parent process id for use in creation of 'session'
        // file which contains the cwd for a given session.  this cwd
        // is only updated by the icd command which writes a new irods
        // CFG_IRODS_CWD_KW to the session dir which repaves the existing
        // one in the original irodsEnv file.
        std::stringstream ppid_str; ppid_str << getppid();

        // if a json version exists, then attempt to capture
        // that
        std::string json_file( IRODS_HOME_DIRECTORY );
        std::string json_session_file( IRODS_HOME_DIRECTORY );
        std::string env_var = to_env( CFG_IRODS_ENVIRONMENT_FILE_KW );
        char* irods_env = getenv(
                              to_env(
                                  CFG_IRODS_ENVIRONMENT_FILE_KW ).c_str() );
        if ( irods_env && strlen( irods_env ) > 0 ) {
            json_file = irods_env;
            // "cwd" is used in this case instead of the ppid given the
            // assumption that scripts will set the env file var to allow
            // for more complex interactions possibly yielding complex pid
            // hierarchies.  this routes all references to the same session
            // for this given use case
            json_session_file = json_file + ".cwd";

        }
        else {
            char* home_dir = getenv( "HOME" );
            // if home env exists, prefer that for run in place
            // or use of existing irods service accound
            if ( home_dir ) {
                json_file = home_dir;
            }

            json_file += JSON_ENV_FILE;
            json_session_file = json_file + "." + ppid_str.str();

        }

        _env_file     = json_file;
        _session_file = json_session_file;

        return SUCCESS();

    } // get_json_environment_file

    error environment_properties::get_legacy_environment_file(
        std::string& _env_file,
        std::string& _session_file ) {
        // capture parent process id for use in creation of 'session'
        // file which contains the cwd for a given session.  this cwd
        // is only updated by the icd command which writes a new irods
        // CFG_IRODS_CWD_KW to the session dir which repaves the existing
        // one in the original irodsEnv file.
        std::stringstream ppid_str; ppid_str << getppid();

        std::string legacy_file( IRODS_HOME_DIRECTORY );
        std::string legacy_session_file( IRODS_HOME_DIRECTORY );
        char* irods_env = getenv(
                              to_env(
                                  CFG_IRODS_ENVIRONMENT_FILE_KW ).c_str() );
        if ( irods_env && strlen( irods_env ) != 0 ) {
            legacy_file = irods_env;

            // "cwd" is used in this case instead of the ppid given the
            // assumption that scripts will set the env file var to allow
            // for more complex interactions possibly yielding complex pid
            // hierarchies.  this routes all references to the same session
            // for this given use case
            legacy_session_file = legacy_file + ".cwd";

        }
        else {
            char* home_dir = getenv( "HOME" );
            // if home env exists, prefer that for run in place
            // or use of existing irods service accound
            if ( home_dir ) {
                legacy_file = home_dir;
            }

            legacy_file += LEGACY_ENV_FILE;
            legacy_session_file = legacy_file + "." + ppid_str.str();

        }

        _env_file     = legacy_file;
        _session_file = legacy_session_file;

        if( fs::exists( legacy_file ) ) {
            std::cout << "Warning: use of legacy configuration is deprecated." << std::endl;
        }

        return SUCCESS();

    } // get_legacy_environment_file

    error environment_properties::capture() {
        std::string json_file, json_session_file;
        error ret = get_json_environment_file(
                        json_file,
                        json_session_file );

        bool do_parse_legacy = false;
        if ( ret.ok() ) {
            if ( fs::exists( json_file ) ) {
                ret = capture_json( json_file );
                if ( !ret.ok() ) {
                    irods::log( ret );
                    do_parse_legacy = true;
                }
                else {
                    config_props_.set< std::string >(
                        CFG_IRODS_ENVIRONMENT_FILE_KW,
                        json_file );
                    ret = capture_json( json_session_file );
                    if ( !ret.ok() ) {
                        // debug - irods::log( PASS( ret ) );
                    }
                    config_props_.set< std::string >(
                        CFG_IRODS_SESSION_ENVIRONMENT_FILE_KW,
                        json_session_file );
                }
            }
            else {
                do_parse_legacy = true;
            }
        }
        else {
            do_parse_legacy = true;
        }

        if ( do_parse_legacy ) {
            std::string legacy_file, legacy_session_file;
            ret = get_legacy_environment_file(
                      legacy_file,
                      legacy_session_file );
            if ( ret.ok() ) {
                ret = capture_legacy( legacy_file );
                if ( !ret.ok() ) {
                    // debug - irods::log( PASS( ret ) );
                } else {
                    config_props_.set< std::string >(
                        CFG_IRODS_ENVIRONMENT_FILE_KW,
                        legacy_file );
                }

                // session file ( written by icd ) already moved
                // to json
                ret = capture_json( legacy_session_file );
                if ( !ret.ok() ) {
                    // debug - irods::log( PASS( ret ) );
                }

                config_props_.set< std::string >(
                    CFG_IRODS_SESSION_ENVIRONMENT_FILE_KW,
                    legacy_session_file );

            }
            else {
                // debug - irods::log( PASS( ret ) );

            }

        } // do parse legacy

        // set the captured flag so we no its already
        // been captured
        captured_ = true;
        return SUCCESS();

    } // capture

    error environment_properties::capture_json(
        const std::string& _fn ) {
        error ret = config_props_.load( _fn );
        return ret;

    } // capture_json

    error environment_properties::capture_legacy(
        const std::string& _fn ) {

        std::ifstream in_file(
            _fn.c_str(),
            std::ios::in );
        if ( !in_file.is_open() ) {
            std::string msg( "failed to open legacy file [" );
            msg += _fn;
            msg += "]";
            return ERROR( SYS_INVALID_FILE_PATH, msg );
        }

        std::string line;
        while ( getline( in_file, line ) ) {
            // left trim whitespace
            line.erase(
                line.begin(),
                std::find_if(
                    line.begin(),
                    line.end(),
                    std::not1(
                        std::ptr_fun<int, int>(
                            std::isspace ) ) ) );
            // skip comments
            if ( '#' == line[0] ) {
                continue;
            }

            std::vector< std::string > toks;
            try {
                boost::split(
                    toks,
                    line,
                    boost::is_any_of( "\t " ),
                    boost::token_compress_on );
            }
            catch ( boost::exception& ) {
                rodsLog( LOG_ERROR, "boost::split failed on line [%s]", line.c_str() );
                continue;
            }
            if ( toks.size() != 2 ||
                    toks[0].empty()  ||
                    toks[1].empty() ) {
                rodsLog(
                    LOG_NOTICE,
                    "environment_properties :: invalid line [%s]",
                    line.c_str() );
                continue;
            }

            std::string& key = toks[0];
            if ( legacy_key_map_.has_entry( key ) ) {
                key = legacy_key_map_[ key ];

            } //if has entry

            std::string& val = toks[1];

            char front = *( val.begin() );
            if ( '"'  == front ||
                    '\'' == front ) {
                val.erase( 0, 1 );
            }

            char back = *( val.rbegin() );
            if ( '"'  == back ||
                    '\'' == back ) {
                val.erase( val.size() - 1 );
            }

            error ret;
            if ( CFG_IRODS_PORT_KW                        == key ||
                 CFG_IRODS_XMSG_PORT_KW                   == key ||
                 CFG_IRODS_LOG_LEVEL_KW                   == key ||
                 CFG_IRODS_ENCRYPTION_KEY_SIZE_KW         == key ||
                 CFG_IRODS_ENCRYPTION_SALT_SIZE_KW        == key ||
                 CFG_IRODS_ENCRYPTION_NUM_HASH_ROUNDS_KW  == key ) {
                try {
                    int i_val = boost::lexical_cast< int >( val );
                    ret = config_props_.set< int >( key, i_val );
                }
                catch ( ... ) {
                    rodsLog(
                        LOG_ERROR,
                        "environment_properties :: lexical_cast failed for [%s]-[%s]",
                        key.c_str(),
                        val.c_str() );
                }
            }
            else {
                ret = config_props_.set <
                      std::string > (
                          key,
                          val );
            }
            if ( !ret.ok() ) {
                irods::log( PASS( ret ) );
            }

        } // while

        in_file.close();

        return SUCCESS();

    } // environment_properties::capture_legacy

} // namespace irods
<|endoftext|>


<commit_before>#include "SmoothControl.h"

void SmoothControl::getTrajectory(igvc_msgs::velocity_pair& vel, nav_msgs::Path& trajectory,
        Eigen::Vector3d cur_pos, Eigen::Vector3d target, Eigen::Vector2d egocentric_heading)
{
  double dt = rollOutTime / 10;
  for (int i = 0; i < 15; i++)
  {
    Eigen::Vector3d action;
    getAction(action, cur_pos, target, egocentric_heading);
    action[2] = dt;

    if (i == 0)
    {
      vel.left_velocity = action[0] - action[1] * axle_length / 2;
      vel.right_velocity = action[0] + action[1] * axle_length / 2;
    }

    Eigen::Vector3d end_pos;
    getResult(end_pos, egocentric_heading, cur_pos, action);

    if (i == 0)
    {
      geometry_msgs::PoseStamped start;
      start.pose.position.x = cur_pos[0];
      start.pose.position.y = cur_pos[1];
      trajectory.poses.push_back(start);
    }

    geometry_msgs::PoseStamped pose;
    pose.pose.position.x = end_pos[0];
    pose.pose.position.y = end_pos[1];
    trajectory.poses.push_back(pose);
    cur_pos = end_pos;
  }
}

void SmoothControl::getAction(Eigen::Vector3d& result, Eigen::Vector3d cur_pos,
        Eigen::Vector3d target, Eigen::Vector2d egocentric_heading)
{
  /**
  Computes the radius of curvature to obtain a new angular velocity value.

  */
  double delta = egocentric_heading[0], theta = egocentric_heading[1];

  // adjust both angles to lie between -PI and PI
  fitToPolar(delta);
  fitToPolar(theta);

  // calculate the radius of curvature, K
  double d = sqrt(pow(target[0] - cur_pos[0], 2) + pow(target[1] - cur_pos[1], 2));
  double K = k2 * (delta - atan(-k1 * theta));
  K += (1 + (k1 / (1 + pow(k1 * theta, 2)))) * sin(delta);
  K /= -d;

  // calculate angular velocity using radius of curvature
  double w = K * v;
  result[0] = v;
  result[1] = w;
}

void SmoothControl::getResult(Eigen::Vector3d& result, Eigen::Vector2d& egocentric_heading,
        Eigen::Vector3d cur_pos, Eigen::Vector3d action)
{
  /**
  Obtains the resultant pose given the current velocity and angular velocity command.
  */
  double v = action[0];
  double w = action[1];
  double dt = action[2];

  if (std::abs(w) > 1e-10)
  {
    double R = v / w;
    double ICCx = cur_pos[0] - (R * sin(cur_pos[2]));
    double ICCy = cur_pos[1] + (R * cos(cur_pos[2]));
    using namespace Eigen;
    Matrix3d T;
    double wdt = w * dt;
    T << cos(wdt), -sin(wdt), 0, sin(wdt), cos(wdt), 0, 0, 0, 1;
    Vector3d a(cur_pos[0] - ICCx, cur_pos[1] - ICCy, cur_pos[2]);
    Vector3d b = T * a;
    Vector3d c = b + Vector3d(ICCx, ICCy, wdt);
    egocentric_heading[0] += wdt; // update delta

    result[0] = c[0];
    result[1] = c[1];
    result[2] = c[2];

    fitToPolar(result[2]);
  }
  else
  {
    result[0] = cur_pos[0] + (cos(cur_pos[2]) * v * dt);
    result[1] = cur_pos[1] + (sin(cur_pos[2]) * v * dt);
    result[2] = cur_pos[2];
  }
}

void SmoothControl::fitToPolar(double& angle) {
    /**
    Adjust angle to lie within the polar range [-PI, PI]
    */
    while (angle > M_PI)
      angle -= 2 * M_PI;
    while (angle < -M_PI)
      angle += 2 * M_PI;
}
<commit_msg>beautify<commit_after>#include "SmoothControl.h"

void SmoothControl::getTrajectory(igvc_msgs::velocity_pair& vel, nav_msgs::Path& trajectory,
        Eigen::Vector3d cur_pos, Eigen::Vector3d target, Eigen::Vector2d egocentric_heading)
{
  double dt = rollOutTime / 10;
  for (int i = 0; i < 15; i++)
  {
    Eigen::Vector3d action;
    getAction(action, cur_pos, target, egocentric_heading);
    action[2] = dt;

    if (i == 0)
    {
      vel.left_velocity = action[0] - action[1] * axle_length / 2;
      vel.right_velocity = action[0] + action[1] * axle_length / 2;
    }

    Eigen::Vector3d end_pos;
    getResult(end_pos, egocentric_heading, cur_pos, action);

    if (i == 0)
    {
      geometry_msgs::PoseStamped start;
      start.pose.position.x = cur_pos[0];
      start.pose.position.y = cur_pos[1];
      trajectory.poses.push_back(start);
    }

    geometry_msgs::PoseStamped pose;
    pose.pose.position.x = end_pos[0];
    pose.pose.position.y = end_pos[1];
    trajectory.poses.push_back(pose);
    cur_pos = end_pos;
  }
}

void SmoothControl::getAction(Eigen::Vector3d& result, Eigen::Vector3d cur_pos,
        Eigen::Vector3d target, Eigen::Vector2d egocentric_heading)
{
  /**
  Computes the radius of curvature to obtain a new angular velocity value.
  */

  // get egocentric polar coordinates for delta and theta
  double delta = egocentric_heading[0], theta = egocentric_heading[1];

  // adjust both angles to lie between -PI and PI
  fitToPolar(delta);
  fitToPolar(theta);

  // calculate the radius of curvature, K
  double d = sqrt(pow(target[0] - cur_pos[0], 2) + pow(target[1] - cur_pos[1], 2));
  double K = k2 * (delta - atan(-k1 * theta));
  K += (1 + (k1 / (1 + pow(k1 * theta, 2)))) * sin(delta);
  K /= -d;

  // calculate angular velocity using radius of curvature
  double w = K * v;
  result[0] = v;
  result[1] = w;
}

void SmoothControl::getResult(Eigen::Vector3d& result, Eigen::Vector2d& egocentric_heading,
        Eigen::Vector3d cur_pos, Eigen::Vector3d action)
{
  /**
  Obtains the resultant pose given the current velocity and angular velocity command.
  Makes extensive use of differential drive odometry equations to calculate resultant
  pose

  Source: http://www8.cs.umu.se/kurser/5DV122/HT13/material/Hellstrom-ForwardKinematics.pdf
  */
  double v = action[0];
  double w = action[1];
  double dt = action[2];

  if (std::abs(w) > 1e-10)
  {
    // calculate instantaneous center of curvature
    double R = v / w;
    double ICCx = cur_pos[0] - (R * sin(cur_pos[2]));
    double ICCy = cur_pos[1] + (R * cos(cur_pos[2]));

    using namespace Eigen;
    Matrix3d T;
    double wdt = w * dt;
    T << cos(wdt), -sin(wdt), 0, sin(wdt), cos(wdt), 0, 0, 0, 1;
    Vector3d a(cur_pos[0] - ICCx, cur_pos[1] - ICCy, cur_pos[2]);
    Vector3d b = T * a;
    Vector3d c = b + Vector3d(ICCx, ICCy, wdt);

    egocentric_heading[0] += wdt; // update delta

    result[0] = c[0];
    result[1] = c[1];
    result[2] = c[2];

    fitToPolar(result[2]);
  }
  else
  {
    result[0] = cur_pos[0] + (cos(cur_pos[2]) * v * dt);
    result[1] = cur_pos[1] + (sin(cur_pos[2]) * v * dt);
    result[2] = cur_pos[2];
  }
}

void SmoothControl::fitToPolar(double& angle) {
    /**
    Adjust angle to lie within the polar range [-PI, PI]
    */
    while (angle > M_PI)
      angle -= 2 * M_PI;
    while (angle < -M_PI)
      angle += 2 * M_PI;
}
<|endoftext|>


<commit_before>#ifndef GCN_OPENGLALLEGROIMAGELOADER_HPP
#define GCN_OPENGLALLEGROIMAGELOADER_HPP

#include <allegro.h>
#include <alleggl.h>

#include <guichan/imageloader.hpp>
#include <guichan/exception.hpp>
#include <guichan/opengl/openglimage.hpp>

namespace gcn
{
    /**
     * OpenGL ImageLoader that loads images with Allegro.
     */
    class OpenGLAllegroImageLoader : public ImageLoader
    {
    public:

        // Inherited from ImageLoader

        virtual Image* load(const std::string& filename,
                            bool convertToDisplayFormat = true)

        {
            BITMAP *bmp = load_bitmap(filename.c_str(), NULL);

            if (bmp == NULL)
            {
                throw GCN_EXCEPTION(
                        std::string("Unable to load image file: ") + filename);
            }

            int bitmapBpp = bitmap_color_depth(bmp);

            // As a BITMAP without an alpha channel in Allegro has
            // all it's alpha values set to zero we have to check
            // if the BITMAP has an alpha channel. If no alpha channel
            // exists then we need to change the alpha values to 255
            // before creating the OpenGL image.
            bool hasAlphaChannel = false;
            int x, y;
            for (y = 0; y < bmp->h; y++)
            {
                for (x = 0; x < bmp->w; x++)
                {
                    int pixel = getpixel(bmp, x, y);
                    if (geta_depth(bitmapBpp, pixel) != 0)
                    {
                        hasAlphaChannel = true;
                    }
                }
            }

            unsigned int pixels[bmp->w * bmp->h];

            for (y = 0; y < bmp->h; y++)
            {
                for (x = 0; x < bmp->w; x++)
                {
                    int pixel = getpixel(bmp,x, y);

                    if (!hasAlphaChannel)
                    {
                        pixels[x + y * bmp->w] = pixel | 0xff000000;
                    }
                    else
                    {
                        pixels[x + y * bmp->w] = pixel;
                    }
                }
            }

            OpenGLImage *image = new OpenGLImage(pixels,
                                                 bmp->w,
                                                 bmp->h,
                                                 convertToDisplayFormat);

            destroy_bitmap(bmp);

            return image;
        }
    };
}

#endif // end GCN_OPENGLALLEGROIMAGELOADER_HPP
<commit_msg>Compile error in VC 8 has been fixed.<commit_after>#ifndef GCN_OPENGLALLEGROIMAGELOADER_HPP
#define GCN_OPENGLALLEGROIMAGELOADER_HPP

#include <allegro.h>
#include <alleggl.h>
#if defined (_WIN32)
// Sometimes windows.h defines DELETE which causes a compilation
// error in a Guichan header.
#if defined (DELETE)
#undef DELETE
#endif
#endif

#include <guichan/imageloader.hpp>
#include <guichan/exception.hpp>
#include <guichan/opengl/openglimage.hpp>

namespace gcn
{
    /**
     * OpenGL ImageLoader that loads images with Allegro.
     */
    class OpenGLAllegroImageLoader : public ImageLoader
    {
    public:

        // Inherited from ImageLoader

        virtual Image* load(const std::string& filename,
                            bool convertToDisplayFormat = true)

        {
            BITMAP *bmp = load_bitmap(filename.c_str(), NULL);

            if (bmp == NULL)
            {
                throw GCN_EXCEPTION(
                        std::string("Unable to load image file: ") + filename);
            }

            int bitmapBpp = bitmap_color_depth(bmp);

            // As a BITMAP without an alpha channel in Allegro has
            // all it's alpha values set to zero we have to check
            // if the BITMAP has an alpha channel. If no alpha channel
            // exists then we need to change the alpha values to 255
            // before creating the OpenGL image.
            bool hasAlphaChannel = false;
            int x, y;
            for (y = 0; y < bmp->h; y++)
            {
                for (x = 0; x < bmp->w; x++)
                {
                    int pixel = getpixel(bmp, x, y);
                    if (geta_depth(bitmapBpp, pixel) != 0)
                    {
                        hasAlphaChannel = true;
                    }
                }
            }

            unsigned int *pixels = new unsigned int[bmp->w * bmp->h];

            for (y = 0; y < bmp->h; y++)
            {
                for (x = 0; x < bmp->w; x++)
                {
                    int pixel = getpixel(bmp,x, y);

                    if (!hasAlphaChannel)
                    {
                        pixels[x + y * bmp->w] = pixel | 0xff000000;
                    }
                    else
                    {
                        pixels[x + y * bmp->w] = pixel;
                    }
                }
            }

            OpenGLImage *image = new OpenGLImage(pixels,
                                                 bmp->w,
                                                 bmp->h,
                                                 convertToDisplayFormat);

            destroy_bitmap(bmp);

            return image;
        }
    };
}

#endif // end GCN_OPENGLALLEGROIMAGELOADER_HPP
<|endoftext|>


<commit_before>#include "moduleBase.h"

class Module {
	public:
		Module(std::tr1::unordered_map<std::string, Channel>& channels, Socket& botSocket);
		virtual void onChannelMsg(std::string channel, char target, std::string nick, std::string message) = 0;
		virtual void onUserMsg(std::string nick, std::string message) = 0;
		virtual void onChannelNotice(std::string channel, char target, std::string nick, std::string message) = 0;
		virtual void onUserNotice(std::string nick, std::string message) = 0;
		virtual void onChannelCTCP(std::string channel, std::string nick, std::string type, std::string params) = 0;
		virtual void onUserCTCP(std::string nick, std::string type, std::string params) = 0;
		virtual void onChannelCTCPReply(std::string channel, std::string nick, std::string type, std::string data) = 0;
		virtual void onUserCTCPReply(std::string nick, std::string type, std::string data) = 0;
		virtual void onChannelJoin(std::string channel, std::string hostmask) = 0;
		virtual void onChannelPart(std::string channel, std::string hostmask, std::string reason) = 0;
		virtual void onUserQuit(std::string hostmask, std::string reason) = 0;
		virtual void onChannelKick(std::string channel, std::string kicker, std::string kickee, std::string reason) = 0;
		virtual void onOutMessage(std::string target, std::string message) = 0;
		virtual void onOutNotice(std::string target, std::string message) = 0;
	protected:
		std::tr1::unordered_map<std::string, Channel> *channelList;
		Socket* bot_socket;
		void sendPrivMsg(std::string target, std::string message);
		void sendNotice(std::string target, std::string message);
		void sendCTCP(std::string target, std::string type, std::string params = "");
		void sendCTCPReply(std::string target, std::string type, std::string data = "");
		void joinChannel(std::string channel, std::string key = "");
		void partChannel(std::string channel, std::string reason);
		void kickChannelUser(std::string channel, std::string nick, std::string reason);
		std::vector<std::string> splitBySpace(std::string line);
};

Module::Module(std::tr1::unordered_map<std::string, Channel>& channels, Socket& botSocket) {
	channelList = &channels;
	bot_socket = &botSocket;
}

void Module::sendPrivMsg(std::string target, std::string message) {
	bot_socket->sendMsg("PRIVMSG " + target + " :" + message);
}

void Module::sendNotice(std::string target, std::string message) {
	bot_socket->sendMsg("NOTICE " + target + " :" + message);
}

void Module::sendCTCP(std::string target, std::string type, std::string params) {
	if (params != "")
		bot_socket->sendMsg("PRIVMSG " + target + " :" + (char)1 + type + " " + params + (char)1);
	else
		bot_socket->sendMsg("PRIVMSG " + target + " :" + (char)1 + type + (char)1);
}

void Module::sendCTCPReply(std::string target, std::string type, std::string data) {
	if (data != "")
		bot_socket->sendMsg("NOTICE " + target + " :" + (char)1 + type + " " + data + (char)1);
	else
		bot_socket->sendMsg("NOTICE " + target + " :" + (char)1 + type + (char)1);
}

void Module::joinChannel(std::string channel, std::string key) {
	bot_socket->sendMsg("JOIN " + channel + " " + key);
}

void Module::partChannel(std::string channel, std::string reason) {
	bot_socket->sendMsg("PART " + channel + " :" + reason);
}

void Module::kickChannelUser(std::string channel, std::string nick, std::string reason) {
	bot_socket->sendMsg("KICK " + channel + " " + nick + " :" + reason);
}

std::vector<std::string> splitBySpace(std::string line) {
	std::vector<std::string> split;
	std::string temp = "";
	for (unsigned int i = 0; i < line.size(); i++) {
		if (line[i] == ' ') {
			split.push_back(temp);
			temp = "";
		} else
			temp += line[i];
	}
	return split;
}<commit_msg>Comment out most of the module base definitions while I rejig stuff.<commit_after>#include "moduleBase.h"

class Module {
	public:
		Module(std::tr1::unordered_map<std::string, Channel>& channels, Socket& botSocket);
		virtual void onChannelMsg(std::string channel, char target, std::string nick, std::string message) = 0;
		virtual void onUserMsg(std::string nick, std::string message) = 0;
		virtual void onChannelNotice(std::string channel, char target, std::string nick, std::string message) = 0;
		virtual void onUserNotice(std::string nick, std::string message) = 0;
		virtual void onChannelCTCP(std::string channel, std::string nick, std::string type, std::string params) = 0;
		virtual void onUserCTCP(std::string nick, std::string type, std::string params) = 0;
		virtual void onChannelCTCPReply(std::string channel, std::string nick, std::string type, std::string data) = 0;
		virtual void onUserCTCPReply(std::string nick, std::string type, std::string data) = 0;
		virtual void onChannelJoin(std::string channel, std::string hostmask) = 0;
		virtual void onChannelPart(std::string channel, std::string hostmask, std::string reason) = 0;
		virtual void onUserQuit(std::string hostmask, std::string reason) = 0;
		virtual void onChannelKick(std::string channel, std::string kicker, std::string kickee, std::string reason) = 0;
		virtual void onOutMessage(std::string target, std::string message) = 0;
		virtual void onOutNotice(std::string target, std::string message) = 0;
	protected:
		std::tr1::unordered_map<std::string, Channel> *channelList;
		Socket* bot_socket;
		void sendPrivMsg(std::string target, std::string message);
		void sendNotice(std::string target, std::string message);
		void sendCTCP(std::string target, std::string type, std::string params = "");
		void sendCTCPReply(std::string target, std::string type, std::string data = "");
		void joinChannel(std::string channel, std::string key = "");
		void partChannel(std::string channel, std::string reason);
		void kickChannelUser(std::string channel, std::string nick, std::string reason);
		std::vector<std::string> splitBySpace(std::string line);
};

Module::Module(std::tr1::unordered_map<std::string, Channel>& channels, Socket& botSocket) {
	channelList = &channels;
	bot_socket = &botSocket;
}

/*void Module::sendPrivMsg(std::string target, std::string message) {
	bot_socket->sendMsg("PRIVMSG " + target + " :" + message);
}

void Module::sendNotice(std::string target, std::string message) {
	bot_socket->sendMsg("NOTICE " + target + " :" + message);
}

void Module::sendCTCP(std::string target, std::string type, std::string params) {
	if (params != "")
		bot_socket->sendMsg("PRIVMSG " + target + " :" + (char)1 + type + " " + params + (char)1);
	else
		bot_socket->sendMsg("PRIVMSG " + target + " :" + (char)1 + type + (char)1);
}

void Module::sendCTCPReply(std::string target, std::string type, std::string data) {
	if (data != "")
		bot_socket->sendMsg("NOTICE " + target + " :" + (char)1 + type + " " + data + (char)1);
	else
		bot_socket->sendMsg("NOTICE " + target + " :" + (char)1 + type + (char)1);
}

void Module::joinChannel(std::string channel, std::string key) {
	bot_socket->sendMsg("JOIN " + channel + " " + key);
}

void Module::partChannel(std::string channel, std::string reason) {
	bot_socket->sendMsg("PART " + channel + " :" + reason);
}

void Module::kickChannelUser(std::string channel, std::string nick, std::string reason) {
	bot_socket->sendMsg("KICK " + channel + " " + nick + " :" + reason);
} */

std::vector<std::string> splitBySpace(std::string line) {
	std::vector<std::string> split;
	std::string temp = "";
	for (unsigned int i = 0; i < line.size(); i++) {
		if (line[i] == ' ') {
			split.push_back(temp);
			temp = "";
		} else
			temp += line[i];
	}
	return split;
}<|endoftext|>