<commit_before>#include <iostream>
#include <seqan/sequence.h>
#include <seqan/file.h>

using namespace seqan;
// Function to print simple alignment between two sequences with the same length
template <typename TText1, typename TText2>
void printAlign(TText1 const & genomeFragment, TText2 const & read)
{
        std::cout <<  "Alignment " << std::endl;
        std::cout << "  genome : " << genomeFragment << std::endl;
        std::cout << "  read   : " << read << std::endl;
}
int main(int, char const **)
{
    // Build reads and genomes
    DnaString chr1 = "TATAATATTGCTATCGCGATATCGCTAGCTAGCTACGGATTATGCGCTCTGCGATATATCGCGCTAGATGTGCAGCTCGATCGAATGCACGTGTGTGCGATCGATTAGCGTCGATCATCGATCTATATTAGCGCGCGGTATCGGACGATCATATTAGCGGTCTAGCATTTAG";
    // Build List containing all reads
    typedef String<DnaString> DnaList;
    DnaList readList;
    resize(readList, 4);
    readList[0] = "TTGCTATCGCGATATCGCTAGCTAGCTACGGATTATGCGCTCTGCGATATATCGCGCT";
    readList[1] = "TCGATTAGCGTCGATCATCGATCTATATTAGCGCGCGGTATCGGACGATCATATTAGCGGTCTAGCATT";
    readList[2] = "AGCCTGCGTACGTTGCAGTGCGTGCGTAGACTGTTGCAAGCCGGGGGTTCATGTGCGCTGAAGCACACATGCACA";
    readList[3] = "CGTGCACTGCTGACGTCGTGGTTGTCACATCGTCGTGCGTGCGTACTGCTGCTGACA";
    // Append a second chromosome sequence fragment to chr1
    DnaString chr2 = "AGCCTGCGTACGTTGCAGTGCGTGCGTAGACTGTTGCAAGCCGGGGGTTCATGTGCGCTGAAGCACACATGCACACGTCTCTGTGTTCCGACGTGTGTCACGTGCACTGCTGACGTCGTGGTTGTCACATCGTCGTGCGTGCGTACTGCTGCTGACACATGCTGCTG";
    append(chr1, chr2);
    // Print readlist
    std::cout << " \n Read list: " << std::endl;
    for(unsigned i = 0; i < length(readList); ++i)
        std::cout << readList[i] << std::endl;
    // Assume we have mapped the 4 reads to chr1 (and chr2) and now have the mapping start positions (no gaps).
    // Store the start position in a String: 7, 100, 172, 272
    String<unsigned> alignPosList;
    resize(alignPosList, 4);
    alignPosList[0] = 7;
    alignPosList[1] = 100;
    alignPosList[2] = 172;
    alignPosList[3] = 272;
    // Print alignments using Segment
    std::cout << " \n Print alignment using Segment: " << std::endl;
    for(unsigned i = 0; i < length(readList); ++i)
    {
        // Begin and end position of a given alignment between the read and the genome
        unsigned beginPosition = alignPosList[i];
        unsigned endPosition = beginPosition + length(readList[i]);
        // Build infix
        Infix<DnaString>::Type genomeFragment = infix(chr1, beginPosition, endPosition);
        // Call of our function to print the simple alignment
        printAlign(genomeFragment, readList[i]);
    }

    // Iterators :)
    // Print alignments using Iterators: Do the same as above, but use Iterators to iterate over the read list.
    // First, use Standard Iterators.
    Iterator<DnaList>::Type it = begin(readList);
    Iterator<DnaList, Standard>::Type itEnd = end(readList); //same Iterator as above

    std::cout << " \n Print alignment using Standard Iterators: " << std::endl;
    for(; it != itEnd; goNext(it))
    {
        // Get the right index for alignPosList
        int i = position(it, readList);
        // Begin and end position of a given alignment between the read and the genome
        unsigned beginPosition = alignPosList[i];
        unsigned endPosition = beginPosition + length(value(it));
        // Build Infix
        Infix<DnaString>::Type genomeFragment = infix(chr1, beginPosition, endPosition);
        // Call of our function to print the simple alignment
        printAlign(genomeFragment, value(it));
    }

    // Now, use Rooted Iterators.
    Iterator<DnaList, Rooted>::Type it2 = begin(readList);
    std::cout << " \n Print alignment using Rooted Iterators: " << std::endl;
    for(; !atEnd(it2); goNext(it2))
    {
        int i = position(it2);
        // Begin and end position of a given alignment between the read and the genome
        unsigned beginPosition = alignPosList[i];
        unsigned endPosition = beginPosition + length(value(it2));
        // Build Infix
        Infix<DnaString>::Type genomeFragment = infix(bsChr1, beginPosition, endPosition);
        // Call of our function to print the simple alignment
        printAlign(genomeFragment, value(it2));
    }

    // StringSets
    // Build StringSet of readList: Build a StringSet of DnaQString and append the reads from readList.
    // Reuse the Rooted Iterator from above.
    StringSet<DnaString> readStringSet;
    goBegin(it2);
    for(; !atEnd(it2); goNext(it2))
        appendValue(readStringSet, value(it2));

    // Iterate over StringSet
    Iterator<DnaListSet, Rooted>::Type it3 = begin(readStringSet);

    std::cout << " \n Print alignment using Rooted Iterators: " << std::endl;
    for(; !atEnd(it3); goNext(it3))
        std::cout << value(it3) << std::endl;

    return 1;
}
<commit_msg>[DOC] Sequences/StringSets tutorial assignment4 demo cpp revised.<commit_after>#include <iostream>
#include <seqan/sequence.h>
#include <seqan/file.h>

using namespace seqan;
// Function to print simple alignment between two sequences with the same length
template <typename TText1, typename TText2>
void printAlign(TText1 const & genomeFragment, TText2 const & read)
{
        std::cout <<  "Alignment " << std::endl;
        std::cout << "  genome : " << genomeFragment << std::endl;
        std::cout << "  read   : " << read << std::endl;
}
int main(int, char const **)
{
    // Build reads and genomes
    DnaString chr1 = "TATAATATTGCTATCGCGATATCGCTAGCTAGCTACGGATTATGCGCTCTGCGATATATCGCGCTAGATGTGCAGCTCGATCGAATGCACGTGTGTGCGATCGATTAGCGTCGATCATCGATCTATATTAGCGCGCGGTATCGGACGATCATATTAGCGGTCTAGCATTTAG";
    // Build List containing all reads
    typedef String<DnaString> DnaList;
    DnaList readList;
    resize(readList, 4);
    readList[0] = "TTGCTATCGCGATATCGCTAGCTAGCTACGGATTATGCGCTCTGCGATATATCGCGCT";
    readList[1] = "TCGATTAGCGTCGATCATCGATCTATATTAGCGCGCGGTATCGGACGATCATATTAGCGGTCTAGCATT";
    readList[2] = "AGCCTGCGTACGTTGCAGTGCGTGCGTAGACTGTTGCAAGCCGGGGGTTCATGTGCGCTGAAGCACACATGCACA";
    readList[3] = "CGTGCACTGCTGACGTCGTGGTTGTCACATCGTCGTGCGTGCGTACTGCTGCTGACA";
    // Append a second chromosome sequence fragment to chr1
    DnaString chr2 = "AGCCTGCGTACGTTGCAGTGCGTGCGTAGACTGTTGCAAGCCGGGGGTTCATGTGCGCTGAAGCACACATGCACACGTCTCTGTGTTCCGACGTGTGTCACGTGCACTGCTGACGTCGTGGTTGTCACATCGTCGTGCGTGCGTACTGCTGCTGACACATGCTGCTG";
    append(chr1, chr2);
    // Print readlist
    std::cout << " \n Read list: " << std::endl;
    for(unsigned i = 0; i < length(readList); ++i)
        std::cout << readList[i] << std::endl;
    // Assume we have mapped the 4 reads to chr1 (and chr2) and now have the mapping start positions (no gaps).
    // Store the start position in a String: 7, 100, 172, 272
    String<unsigned> alignPosList;
    resize(alignPosList, 4);
    alignPosList[0] = 7;
    alignPosList[1] = 100;
    alignPosList[2] = 172;
    alignPosList[3] = 272;
    // Print alignments using Segment
    std::cout << " \n Print alignment using Segment: " << std::endl;
    for(unsigned i = 0; i < length(readList); ++i)
    {
        // Begin and end position of a given alignment between the read and the genome
        unsigned beginPosition = alignPosList[i];
        unsigned endPosition = beginPosition + length(readList[i]);
        // Build infix
        Infix<DnaString>::Type genomeFragment = infix(chr1, beginPosition, endPosition);
        // Call of our function to print the simple alignment
        printAlign(genomeFragment, readList[i]);
    }

    // Iterators :)
    // Print alignments using Iterators: Do the same as above, but use Iterators to iterate over the read list.
    // First, use Standard Iterators.
    Iterator<DnaList>::Type it = begin(readList);
    Iterator<DnaList, Standard>::Type itEnd = end(readList); //same Iterator as above

    std::cout << " \n Print alignment using Standard Iterators: " << std::endl;
    for(; it != itEnd; goNext(it))
    {
        // Get the right index for alignPosList
        int i = position(it, readList);
        // Begin and end position of a given alignment between the read and the genome
        unsigned beginPosition = alignPosList[i];
        unsigned endPosition = beginPosition + length(value(it));
        // Build Infix
        Infix<DnaString>::Type genomeFragment = infix(chr1, beginPosition, endPosition);
        // Call of our function to print the simple alignment
        printAlign(genomeFragment, value(it));
    }

    // Now, use Rooted Iterators.
    Iterator<DnaList, Rooted>::Type it2 = begin(readList);
    std::cout << " \n Print alignment using Rooted Iterators: " << std::endl;
    for(; !atEnd(it2); goNext(it2))
    {
        int i = position(it2);
        // Begin and end position of a given alignment between the read and the genome
        unsigned beginPosition = alignPosList[i];
        unsigned endPosition = beginPosition + length(value(it2));
        // Build Infix
        Infix<DnaString>::Type genomeFragment = infix(chr1, beginPosition, endPosition);
        // Call of our function to print the simple alignment
        printAlign(genomeFragment, value(it2));
    }

    // StringSets
    // Build StringSet of readList: Build a StringSet of DnaQString and append the reads from readList.
    // Reuse the Rooted Iterator from above.
    typedef StringSet<DnaString> DnaListSet;
    DnaListSet readStringSet;
    goBegin(it2);
    for(; !atEnd(it2); goNext(it2))
        appendValue(readStringSet, value(it2));

    // Iterate over StringSet
    Iterator<DnaListSet, Rooted>::Type it3 = begin(readStringSet);

    std::cout << " \n Print alignment using Rooted Iterators: " << std::endl;
    for(; !atEnd(it3); goNext(it3))
        std::cout << value(it3) << std::endl;

    return 1;
}
<|endoftext|>


<commit_before><commit_msg>SDL2: arrow keys on GamePad(#46)<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// CORE Update line 6

#include "addresstablemodel.h"

#include "guiutil.h"
#include "walletmodel.h"

#include "base58.h"
#include "wallet.h"

#include <QFont>
#include <QDebug>

const QString AddressTableModel::Send = "S";
const QString AddressTableModel::Receive = "R";

struct AddressTableEntry
{
    enum Type {
        Sending,
        Receiving,
        Hidden /* QSortFilterProxyModel will filter these out */
    };

    Type type;
    QString label;
    QString address;

    AddressTableEntry() {}
    AddressTableEntry(Type type, const QString &label, const QString &address):
        type(type), label(label), address(address) {}
};

struct AddressTableEntryLessThan
{
    bool operator()(const AddressTableEntry &a, const AddressTableEntry &b) const
    {
        return a.address < b.address;
    }
    bool operator()(const AddressTableEntry &a, const QString &b) const
    {
        return a.address < b;
    }
    bool operator()(const QString &a, const AddressTableEntry &b) const
    {
        return a < b.address;
    }
};

/* Determine address type from address purpose */
static AddressTableEntry::Type translateTransactionType(const QString &strPurpose, bool isMine)
{
    AddressTableEntry::Type addressType = AddressTableEntry::Hidden;
    // "refund" addresses aren't shown, and change addresses aren't in mapAddressBook at all.
    if (strPurpose == "send")
        addressType = AddressTableEntry::Sending;
    else if (strPurpose == "receive")
        addressType = AddressTableEntry::Receiving;
    else if (strPurpose == "unknown" || strPurpose == "") // if purpose not set, guess
        addressType = (isMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending);
    return addressType;
}

// Private implementation
class AddressTablePriv
{
public:
    CWallet *wallet;
    QList<AddressTableEntry> cachedAddressTable;
    AddressTableModel *parent;

    AddressTablePriv(CWallet *wallet, AddressTableModel *parent):
        wallet(wallet), parent(parent) {}

    void refreshAddressTable()
    {
        cachedAddressTable.clear();
        {
            LOCK(wallet->cs_wallet);
            BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, wallet->mapAddressBook)
            {
                const CBitcoinAddress& address = item.first;
                bool fMine = IsMine(*wallet, address.Get());
                AddressTableEntry::Type addressType = translateTransactionType(
                        QString::fromStdString(item.second.purpose), fMine);
                const std::string& strName = item.second.name;
                cachedAddressTable.append(AddressTableEntry(addressType,
                                  QString::fromStdString(strName),
                                  QString::fromStdString(address.ToString())));
            }
        }
        // qLowerBound() and qUpperBound() require our cachedAddressTable list to be sorted in asc order
        // Even though the map is already sorted this re-sorting step is needed because the originating map
        // is sorted by binary address, not by base58() address.
        qSort(cachedAddressTable.begin(), cachedAddressTable.end(), AddressTableEntryLessThan());
    }

    void updateEntry(const QString &address, const QString &label, bool isMine, const QString &purpose, int status)
    {
        // Find address / label in model
        QList<AddressTableEntry>::iterator lower = qLowerBound(
            cachedAddressTable.begin(), cachedAddressTable.end(), address, AddressTableEntryLessThan());
        QList<AddressTableEntry>::iterator upper = qUpperBound(
            cachedAddressTable.begin(), cachedAddressTable.end(), address, AddressTableEntryLessThan());
        int lowerIndex = (lower - cachedAddressTable.begin());
        int upperIndex = (upper - cachedAddressTable.begin());
        bool inModel = (lower != upper);
        AddressTableEntry::Type newEntryType = translateTransactionType(purpose, isMine);

        switch(status)
        {
        case CT_NEW:
            if(inModel)
            {
                qWarning() << "AddressTablePriv::updateEntry : Warning: Got CT_NEW, but entry is already in model";
                break;
            }
            parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex);
            cachedAddressTable.insert(lowerIndex, AddressTableEntry(newEntryType, label, address));
            parent->endInsertRows();
            break;
        case CT_UPDATED:
            if(!inModel)
            {
                qWarning() << "AddressTablePriv::updateEntry : Warning: Got CT_UPDATED, but entry is not in model";
                break;
            }
            lower->type = newEntryType;
            lower->label = label;
            parent->emitDataChanged(lowerIndex);
            break;
        case CT_DELETED:
            if(!inModel)
            {
                qWarning() << "AddressTablePriv::updateEntry : Warning: Got CT_DELETED, but entry is not in model";
                break;
            }
            parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1);
            cachedAddressTable.erase(lower, upper);
            parent->endRemoveRows();
            break;
        }
    }

    int size()
    {
        return cachedAddressTable.size();
    }

    AddressTableEntry *index(int idx)
    {
        if(idx >= 0 && idx < cachedAddressTable.size())
        {
            return &cachedAddressTable[idx];
        }
        else
        {
            return 0;
        }
    }
};

AddressTableModel::AddressTableModel(CWallet *wallet, WalletModel *parent) :
    QAbstractTableModel(parent),walletModel(parent),wallet(wallet),priv(0)
{
    columns << tr("Label") << tr("Address");
    priv = new AddressTablePriv(wallet, this);
    priv->refreshAddressTable();
}

AddressTableModel::~AddressTableModel()
{
    delete priv;
}

int AddressTableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return priv->size();
}

int AddressTableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return columns.length();
}

QVariant AddressTableModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();

    AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());

    if(role == Qt::DisplayRole || role == Qt::EditRole)
    {
        switch(index.column())
        {
        case Label:
            if(rec->label.isEmpty() && role == Qt::DisplayRole)
            {
                return tr("(no label)");
            }
            else
            {
                return rec->label;
            }
        case Address:
            return rec->address;
        }
    }
    else if (role == Qt::FontRole)
    {
        QFont font;
        if(index.column() == Address)
        {
            font = GUIUtil::bitcoinAddressFont();
        }
        return font;
    }
    else if (role == TypeRole)
    {
        switch(rec->type)
        {
        case AddressTableEntry::Sending:
            return Send;
        case AddressTableEntry::Receiving:
            return Receive;
        default: break;
        }
    }
    return QVariant();
}

bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if(!index.isValid())
        return false;
    AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());
    std::string strPurpose = (rec->type == AddressTableEntry::Sending ? "send" : "receive");
    editStatus = OK;

    if(role == Qt::EditRole)
    {
        LOCK(wallet->cs_wallet); /* For SetAddressBook / DelAddressBook */
        CTxDestination curAddress = CBitcoinAddress(rec->address.toStdString()).Get();
        if(index.column() == Label)
        {
            // Do nothing, if old label == new label
            if(rec->label == value.toString())
            {
                editStatus = NO_CHANGES;
                return false;
            }
            wallet->SetAddressBook(curAddress, value.toString().toStdString(), strPurpose);
        } else if(index.column() == Address) {
            CTxDestination newAddress = CBitcoinAddress(value.toString().toStdString()).Get();
            // Refuse to set invalid address, set error status and return false
            if(boost::get<CNoDestination>(&newAddress))
            {
                editStatus = INVALID_ADDRESS;
                return false;
            }
            // Do nothing, if old address == new address
            else if(newAddress == curAddress)
            {
                editStatus = NO_CHANGES;
                return false;
            }
            // Check for duplicate addresses to prevent accidental deletion of addresses, if you try
            // to paste an existing address over another address (with a different label)
            else if(wallet->mapAddressBook.count(newAddress))
            {
                editStatus = DUPLICATE_ADDRESS;
                return false;
            }
            // Double-check that we're not overwriting a receiving address
            else if(rec->type == AddressTableEntry::Sending)
            {
                // Remove old entry
                wallet->DelAddressBook(curAddress);
                // Add new entry with new address
                wallet->SetAddressBook(newAddress, rec->label.toStdString(), strPurpose);
            }
        }
        return true;
    }
    return false;
}

QVariant AddressTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(orientation == Qt::Horizontal)
    {
        if(role == Qt::DisplayRole && section < columns.size())
        {
            return columns[section];
        }
    }
    return QVariant();
}

Qt::ItemFlags AddressTableModel::flags(const QModelIndex &index) const
{
    if(!index.isValid())
        return 0;
    AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());

    Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
    // Can edit address and label for sending addresses,
    // and only label for receiving addresses.
    if(rec->type == AddressTableEntry::Sending ||
      (rec->type == AddressTableEntry::Receiving && index.column()==Label))
    {
        retval |= Qt::ItemIsEditable;
    }
    return retval;
}

QModelIndex AddressTableModel::index(int row, int column, const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    AddressTableEntry *data = priv->index(row);
    if(data)
    {
        return createIndex(row, column, priv->index(row));
    }
    else
    {
        return QModelIndex();
    }
}

void AddressTableModel::updateEntry(const QString &address,
        const QString &label, bool isMine, const QString &purpose, int status)
{
    // Update address book model from Bitcoin core
    priv->updateEntry(address, label, isMine, purpose, status);
}

QString AddressTableModel::addRow(const QString &type, const QString &label, const QString &address)
{
    std::string strLabel = label.toStdString();
    std::string strAddress = address.toStdString();

    editStatus = OK;

    if(type == Send)
    {
        if(!walletModel->validateAddress(address))
        {
            editStatus = INVALID_ADDRESS;
            return QString();
        }
        // Check for duplicate addresses
        {
            LOCK(wallet->cs_wallet);
            if(wallet->mapAddressBook.count(CBitcoinAddress(strAddress).Get()))
            {
                editStatus = DUPLICATE_ADDRESS;
                return QString();
            }
        }
    }
    else if(type == Receive)
    {
        // Generate a new address to associate with given label
        CPubKey newKey;
        if(!wallet->GetKeyFromPool(newKey))
        {
            WalletModel::UnlockContext ctx(walletModel->requestUnlock());
            if(!ctx.isValid())
            {
                // Unlock wallet failed or was cancelled
                editStatus = WALLET_UNLOCK_FAILURE;
                return QString();
            }
            if(!wallet->GetKeyFromPool(newKey))
            {
                editStatus = KEY_GENERATION_FAILURE;
                return QString();
            }
        }
        strAddress = CBitcoinAddress(newKey.GetID()).ToString();
    }
    else
    {
        return QString();
    }

    // Add entry
    {
        LOCK(wallet->cs_wallet);
        wallet->SetAddressBook(CBitcoinAddress(strAddress).Get(), strLabel,
                               (type == Send ? "send" : "receive"));
    }
    return QString::fromStdString(strAddress);
}

bool AddressTableModel::removeRows(int row, int count, const QModelIndex &parent)
{
    Q_UNUSED(parent);
    AddressTableEntry *rec = priv->index(row);
    if(count != 1 || !rec || rec->type == AddressTableEntry::Receiving)
    {
        // Can only remove one row at a time, and cannot remove rows not in model.
        // Also refuse to remove receiving addresses.
        return false;
    }
    {
        LOCK(wallet->cs_wallet);
        wallet->DelAddressBook(CBitcoinAddress(rec->address.toStdString()).Get());
    }
    return true;
}

/* Look up label for address in address book, if not found return empty string.
 */
QString AddressTableModel::labelForAddress(const QString &address) const
{
    {
        LOCK(wallet->cs_wallet);
        CBitcoinAddress address_parsed(address.toStdString());
        std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(address_parsed.Get());
        if (mi != wallet->mapAddressBook.end())
        {
            return QString::fromStdString(mi->second.name);
        }
    }
    return QString();
}

int AddressTableModel::lookupAddress(const QString &address) const
{
    QModelIndexList lst = match(index(0, Address, QModelIndex()),
                                Qt::EditRole, address, 1, Qt::MatchExactly);
    if(lst.isEmpty())
    {
        return -1;
    }
    else
    {
        return lst.at(0).row();
    }
}

void AddressTableModel::emitDataChanged(int idx)
{
    emit dataChanged(index(idx, 0, QModelIndex()), index(idx, columns.length()-1, QModelIndex()));
}
<commit_msg>Update addresstablemodel.cpp<commit_after>// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// CORE Update line 6

#include "addresstablemodel.h"

#include "guiutil.h"
#include "walletmodel.h"

#include "base58.h"
#include "wallet.h"

#include <QFont>
#include <QDebug>

const QString AddressTableModel::Send = "S";
const QString AddressTableModel::Receive = "R";

struct AddressTableEntry
{
    enum Type {
        Sending,
        Receiving,
        Hidden /* QSortFilterProxyModel will filter these out */
    };

    Type type;
    QString label;
    QString address;

    AddressTableEntry() {}
    AddressTableEntry(Type type, const QString &label, const QString &address):
        type(type), label(label), address(address) {}
};

struct AddressTableEntryLessThan
{
    bool operator()(const AddressTableEntry &a, const AddressTableEntry &b) const
    {
        return a.address < b.address;
    }
    bool operator()(const AddressTableEntry &a, const QString &b) const
    {
        return a.address < b;
    }
    bool operator()(const QString &a, const AddressTableEntry &b) const
    {
        return a < b.address;
    }
};

/* Determine address type from address purpose */
static AddressTableEntry::Type translateTransactionType(const QString &strPurpose, bool isMine)
{
    AddressTableEntry::Type addressType = AddressTableEntry::Hidden;
    // "refund" addresses aren't shown, and change addresses aren't in mapAddressBook at all.
    if (strPurpose == "send")
        addressType = AddressTableEntry::Sending;
    else if (strPurpose == "receive")
        addressType = AddressTableEntry::Receiving;
    else if (strPurpose == "unknown" || strPurpose == "") // if purpose not set, guess
        addressType = (isMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending);
    return addressType;
}

// Private implementation
class AddressTablePriv
{
public:
    CWallet *wallet;
    QList<AddressTableEntry> cachedAddressTable;
    AddressTableModel *parent;

    AddressTablePriv(CWallet *wallet, AddressTableModel *parent):
        wallet(wallet), parent(parent) {}

    void refreshAddressTable()
    {
        cachedAddressTable.clear();
        {
            LOCK(wallet->cs_wallet);
            BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, wallet->mapAddressBook)
            {
                const CBitcoinAddress& address = item.first;
                bool fMine = IsMine(*wallet, address.Get());
                AddressTableEntry::Type addressType = translateTransactionType(
                        QString::fromStdString(item.second.purpose), fMine);
                const std::string& strName = item.second.name;
                cachedAddressTable.append(AddressTableEntry(addressType,
                                  QString::fromStdString(strName),
                                  QString::fromStdString(address.ToString())));
            }
        }
        // qLowerBound() and qUpperBound() require our cachedAddressTable list to be sorted in asc order
        // Even though the map is already sorted this re-sorting step is needed because the originating map
        // is sorted by binary address, not by base58() address.
        qSort(cachedAddressTable.begin(), cachedAddressTable.end(), AddressTableEntryLessThan());
    }

    void updateEntry(const QString &address, const QString &label, bool isMine, const QString &purpose, int status)
    {
        // Find address / label in model
        QList<AddressTableEntry>::iterator lower = qLowerBound(
            cachedAddressTable.begin(), cachedAddressTable.end(), address, AddressTableEntryLessThan());
        QList<AddressTableEntry>::iterator upper = qUpperBound(
            cachedAddressTable.begin(), cachedAddressTable.end(), address, AddressTableEntryLessThan());
        int lowerIndex = (lower - cachedAddressTable.begin());
        int upperIndex = (upper - cachedAddressTable.begin());
        bool inModel = (lower != upper);
        AddressTableEntry::Type newEntryType = translateTransactionType(purpose, isMine);

        switch(status)
        {
        case CT_NEW:
            if(inModel)
            {
                qWarning() << "AddressTablePriv::updateEntry : Warning: Got CT_NEW, but entry is already in model";
                break;
            }
            parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex);
            cachedAddressTable.insert(lowerIndex, AddressTableEntry(newEntryType, label, address));
            parent->endInsertRows();
            break;
        case CT_UPDATED:
            if(!inModel)
            {
                qWarning() << "AddressTablePriv::updateEntry : Warning: Got CT_UPDATED, but entry is not in model";
                break;
            }
            lower->type = newEntryType;
            lower->label = label;
            parent->emitDataChanged(lowerIndex);
            break;
        case CT_DELETED:
            if(!inModel)
            {
                qWarning() << "AddressTablePriv::updateEntry : Warning: Got CT_DELETED, but entry is not in model";
                break;
            }
            parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1);
            cachedAddressTable.erase(lower, upper);
            parent->endRemoveRows();
            break;
        }
    }

    int size()
    {
        return cachedAddressTable.size();
    }

    AddressTableEntry *index(int idx)
    {
        if(idx >= 0 && idx < cachedAddressTable.size())
        {
            return &cachedAddressTable[idx];
        }
        else
        {
            return 0;
        }
    }
};

AddressTableModel::AddressTableModel(CWallet *wallet, WalletModel *parent) :
    QAbstractTableModel(parent),walletModel(parent),wallet(wallet),priv(0)
{
    columns << tr("Label") << tr("Address");
    priv = new AddressTablePriv(wallet, this);
    priv->refreshAddressTable();
}

AddressTableModel::~AddressTableModel()
{
    delete priv;
}

int AddressTableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return priv->size();
}

int AddressTableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return columns.length();
}

QVariant AddressTableModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();

    AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());

    if(role == Qt::DisplayRole || role == Qt::EditRole)
    {
        switch(index.column())
        {
        case Label:
            if(rec->label.isEmpty() && role == Qt::DisplayRole)
            {
                return tr("(no label)");
            }
            else
            {
                return rec->label;
            }
        case Address:
            return rec->address;
        }
    }
    else if (role == Qt::FontRole)
    {
        QFont font;
        if(index.column() == Address)
        {
            font = GUIUtil::bitcoinAddressFont();
        }
        return font;
    }
    else if (role == TypeRole)
    {
        switch(rec->type)
        {
        case AddressTableEntry::Sending:
            return Send;
        case AddressTableEntry::Receiving:
            return Receive;
        default: break;
        }
    }
    return QVariant();
}

bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if(!index.isValid())
        return false;
    AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());
    std::string strPurpose = (rec->type == AddressTableEntry::Sending ? "send" : "receive");
    editStatus = OK;

    if(role == Qt::EditRole)
    {
        LOCK(wallet->cs_wallet); /* For SetAddressBook / DelAddressBook */
        CTxDestination curAddress = CBitcoinAddress(rec->address.toStdString()).Get();
        if(index.column() == Label)
        {
            // Do nothing, if old label == new label
            if(rec->label == value.toString())
            {
                editStatus = NO_CHANGES;
                return false;
            }
            wallet->SetAddressBook(curAddress, value.toString().toStdString(), strPurpose);
        } else if(index.column() == Address) {
            CTxDestination newAddress = CBitcoinAddress(value.toString().toStdString()).Get();
            // Refuse to set invalid address, set error status and return false
            if(boost::get<CNoDestination>(&newAddress))
            {
                editStatus = INVALID_ADDRESS;
                return false;
            }
            // Do nothing, if old address == new address
            else if(newAddress == curAddress)
            {
                editStatus = NO_CHANGES;
                return false;
            }
            // Check for duplicate addresses to prevent accidental deletion of addresses, if you try
            // to paste an existing address over another address (with a different label)
            else if(wallet->mapAddressBook.count(newAddress))
            {
                editStatus = DUPLICATE_ADDRESS;
                return false;
            }
            // Double-check that we're not overwriting a receiving address
            else if(rec->type == AddressTableEntry::Sending)
            {
                // Remove old entry
                wallet->DelAddressBook(curAddress);
                // Add new entry with new address
                wallet->SetAddressBook(newAddress, rec->label.toStdString(), strPurpose);
            }
        }
        return true;
    }
    return false;
}

QVariant AddressTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(orientation == Qt::Horizontal)
    {
        if(role == Qt::DisplayRole && section < columns.size())
        {
            return columns[section];
        }
    }
    return QVariant();
}

Qt::ItemFlags AddressTableModel::flags(const QModelIndex &index) const
{
    if(!index.isValid())
        return 0;
    AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());

    Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
    // Can edit address and label for sending addresses,
    // and only label for receiving addresses.
    if(rec->type == AddressTableEntry::Sending ||
      (rec->type == AddressTableEntry::Receiving && index.column()==Label))
    {
        retval |= Qt::ItemIsEditable;
    }
    return retval;
}

QModelIndex AddressTableModel::index(int row, int column, const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    AddressTableEntry *data = priv->index(row);
    if(data)
    {
        return createIndex(row, column, priv->index(row));
    }
    else
    {
        return QModelIndex();
    }
}

void AddressTableModel::updateEntry(const QString &address,
        const QString &label, bool isMine, const QString &purpose, int status)
{
    // Update address book model from Bitcoin core
    priv->updateEntry(address, label, isMine, purpose, status);
}

QString AddressTableModel::addRow(const QString &type, const QString &label, const QString &address)
{
    std::string strLabel = label.toStdString();
    std::string strAddress = address.toStdString();

    editStatus = OK;

    if(type == Send)
    {
        if(!walletModel->validateAddress(address))
        {
            editStatus = INVALID_ADDRESS;
            return QString();
        }
        // Check for duplicate addresses
        {
            LOCK(wallet->cs_wallet);
            if(wallet->mapAddressBook.count(CBitcoinAddress(strAddress).Get()))
            {
                editStatus = DUPLICATE_ADDRESS;
                return QString();
            }
        }
    }
    else if(type == Receive)
    {
        // Generate a new address to associate with given label
        CPubKey newKey;
        if(!wallet->GetKeyFromPool(newKey))
        {
            WalletModel::UnlockContext ctx(walletModel->requestUnlock());
            if(!ctx.isValid())
            {
                // Unlock wallet failed or was cancelled
                editStatus = WALLET_UNLOCK_FAILURE;
                return QString();
            }
            if(!wallet->GetKeyFromPool(newKey))
            {
                editStatus = KEY_GENERATION_FAILURE;
                return QString();
            }
        }
        strAddress = CBitcoinAddress(newKey.GetID()).ToString();
    }
    else
    {
        return QString();
    }

    // Add entry
    {
        LOCK(wallet->cs_wallet);
        wallet->SetAddressBook(CBitcoinAddress(strAddress).Get(), strLabel,
                               (type == Send ? "send" : "receive"));
    }
    return QString::fromStdString(strAddress);
}

bool AddressTableModel::removeRows(int row, int count, const QModelIndex &parent)
{
    Q_UNUSED(parent);
    AddressTableEntry *rec = priv->index(row);
    if(count != 1 || !rec || rec->type == AddressTableEntry::Receiving)
    {
        // Can only remove one row at a time, and cannot remove rows not in model.
        // Also refuse to remove receiving addresses.
        return false;
    }
    {
        LOCK(wallet->cs_wallet);
        wallet->DelAddressBook(CBitcoinAddress(rec->address.toStdString()).Get());
    }
    return true;
}

/* Look up label for address in address book, if not found return empty string.
 */
QString AddressTableModel::labelForAddress(const QString &address) const
{
    {
        LOCK(wallet->cs_wallet);
        CBitcoinAddress address_parsed(address.toStdString());
        std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(address_parsed.Get());
        if (mi != wallet->mapAddressBook.end())
        {
            return QString::fromStdString(mi->second.name);
        }
    }
    return QString();
}

int AddressTableModel::lookupAddress(const QString &address) const
{
    QModelIndexList lst = match(index(0, Address, QModelIndex()),
                                Qt::EditRole, address, 1, Qt::MatchExactly);
    if(lst.isEmpty())
    {
        return -1;
    }
    else
    {
        return lst.at(0).row();
    }
}

void AddressTableModel::emitDataChanged(int idx)
{
    emit dataChanged(index(idx, 0, QModelIndex()), index(idx, columns.length()-1, QModelIndex()));
}

<|endoftext|>


<commit_before>#include "transactionrecord.h"

#include "wallet.h"
#include "base58.h"

std::string GetTxProject(uint256 hash, int& out_blocknumber, int& out_blocktype, double& out_rac);
std::string RoundToString(double d, int place);
double DoubleFromAmount(int64_t amount);

bool IsLockTimeWithinMinutes(int64_t locktime, int minutes);

/* Return positive answer if transaction should be shown in list. */
bool TransactionRecord::showTransaction(const CWalletTx &wtx)
{

	std::string ShowOrphans = GetArg("-showorphans", "false");
	if (ShowOrphans=="false" && !wtx.IsInMainChain()) return false;
	//R Halford - Discard Orphans after Y mins:
	if (wtx.IsCoinStake())
	{
		if (!wtx.IsInMainChain())
		{
			//Orphaned tx
			if (ShowOrphans=="true"  && IsLockTimeWithinMinutes(wtx.nTimeReceived,15))
			{
				return true;
			}
			else
			{
				return false;
			}
		}
    }

    if (wtx.IsCoinBase())
    {
        // Ensures we show generated coins / mined transactions at depth 1
        if (!wtx.IsInMainChain())
        {
            return false;
        }
    }
    return true;
}

	int64_t GetMyValueOut(const CWallet *wallet,const CWalletTx &wtx)
    {
        int64_t nValueOut = 0;
        BOOST_FOREACH(const CTxOut& txout, wtx.vout)
        {
	       if (wallet->IsMine(txout))
		   {
				nValueOut += txout.nValue;
		   }
        }
        return nValueOut;
    }

/*
 * Decompose CWallet transaction to model transaction records.
 */
QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
{
    QList<TransactionRecord> parts;
    int64_t nTime = wtx.GetTxTime();
    int64_t nCredit = wtx.GetCredit(true);
    int64_t nDebit = wtx.GetDebit();
    int64_t nNet = nCredit - nDebit;
    uint256 hash = wtx.GetHash(), hashPrev = 0;
    std::map<std::string, std::string> mapValue = wtx.mapValue;

    if (nNet > 0 || wtx.IsCoinBase() || wtx.IsCoinStake())
    {
        //
        // Credit - Calculate Net from CryptoLottery Rob Halford - 4-3-2015-1
        //
        BOOST_FOREACH(const CTxOut& txout, wtx.vout)
        {
            if(wallet->IsMine(txout))
            {
                TransactionRecord sub(hash, nTime);
                CTxDestination address;
                sub.idx = parts.size(); // sequence number
                sub.credit = txout.nValue;
                if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
                {
                    // Received by Bitcoin Address
                    sub.type = TransactionRecord::RecvWithAddress;
                    sub.address = CBitcoinAddress(address).ToString();
                }
                else
                {
                    // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction
                    sub.type = TransactionRecord::RecvFromOther;
                    sub.address = mapValue["from"];
                }
                if (wtx.IsCoinBase())
                {
                    // Generated (proof-of-work)
                    sub.type = TransactionRecord::Generated;
                }
                if (wtx.IsCoinStake())
                {
                    // Generated (proof-of-stake)
			        if (hashPrev == hash)
                        continue; // last coinstake output

					if (wtx.vout.size()==2)
					{
						//Standard POR CoinStake
						sub.type = TransactionRecord::Generated;
						sub.credit = nNet > 0 ? nNet : wtx.GetValueOut() - nDebit;
						hashPrev = hash;
					}
					else
					{
						//CryptoLottery - CoinStake - 4-3-2015
						sub.type = TransactionRecord::Generated;
						if (nDebit == 0)
						{
							sub.credit = GetMyValueOut(wallet,wtx);
							sub.RemoteFlag = 1;
						}
						else
						{
							sub.credit = nNet > 0 ? nNet : GetMyValueOut(wallet,wtx) - nDebit;
						}

						hashPrev = hash;

					}
                }

                parts.append(sub);
            }
        }
    }
    else
    {
        bool fAllFromMe = true;
        BOOST_FOREACH(const CTxIn& txin, wtx.vin)
            fAllFromMe = fAllFromMe && wallet->IsMine(txin);

        bool fAllToMe = true;
        BOOST_FOREACH(const CTxOut& txout, wtx.vout)
            fAllToMe = fAllToMe && wallet->IsMine(txout);

        if (fAllFromMe && fAllToMe)
        {
            // Payment to self
            int64_t nChange = wtx.GetChange();

            parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "",
                            -(nDebit - nChange), nCredit - nChange));
        }
        else if (fAllFromMe)
        {
            //
            // Debit
            //
            int64_t nTxFee = nDebit - wtx.GetValueOut();

            for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
            {
                const CTxOut& txout = wtx.vout[nOut];
                TransactionRecord sub(hash, nTime);
                sub.idx = parts.size();

                if(wallet->IsMine(txout))
                {
                    // Ignore parts sent to self, as this is usually the change
                    // from a transaction sent back to our own address.
                    continue;
                }

                CTxDestination address;
                if (ExtractDestination(txout.scriptPubKey, address))
                {
                    // Sent to Bitcoin Address
                    sub.type = TransactionRecord::SendToAddress;
                    sub.address = CBitcoinAddress(address).ToString();
                }
                else
                {
                    // Sent to IP, or other non-address transaction like OP_EVAL
                    sub.type = TransactionRecord::SendToOther;
                    sub.address = mapValue["to"];
                }

                int64_t nValue = txout.nValue;
                /* Add fee to first output */
                if (nTxFee > 0)
                {
                    nValue += nTxFee;
                    nTxFee = 0;
                }
                sub.debit = -nValue;

                parts.append(sub);
            }
        }
        else
        {
            //
            // Mixed debit transaction, can't break down payees
            //
            parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0));
        }
    }

    return parts;
}

void TransactionRecord::updateStatus(const CWalletTx &wtx)
{
    AssertLockHeld(cs_main);
    // Determine transaction status

    // Find the block the tx is in
    CBlockIndex* pindex = NULL;
    std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(wtx.hashBlock);
    if (mi != mapBlockIndex.end())
        pindex = (*mi).second;

    // Sort order, unrecorded transactions sort to the top
    status.sortKey = strprintf("%010d-%01d-%010u-%03d",
        (pindex ? pindex->nHeight : std::numeric_limits<int>::max()),
        (wtx.IsCoinBase() ? 1 : 0),
        wtx.nTimeReceived,
        idx);
    status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0);
    status.depth = wtx.GetDepthInMainChain();
    status.cur_num_blocks = nBestHeight;

    if (!IsFinalTx(wtx, nBestHeight + 1))
    {
        if (wtx.nLockTime < LOCKTIME_THRESHOLD)
        {
            status.status = TransactionStatus::OpenUntilBlock;
            status.open_for = wtx.nLockTime - nBestHeight;
        }
        else
        {
            status.status = TransactionStatus::OpenUntilDate;
            status.open_for = wtx.nLockTime;
        }
    }

    // For generated transactions, determine maturity
    else if(type == TransactionRecord::Generated)
    {
        if (wtx.GetBlocksToMaturity() > 0)
        {
            status.status = TransactionStatus::Immature;

            if (wtx.IsInMainChain())
            {
                status.matures_in = wtx.GetBlocksToMaturity();

                // Check if the block was requested by anyone
                if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
                    status.status = TransactionStatus::MaturesWarning;
            }
            else
            {
                status.status = TransactionStatus::NotAccepted;
            }
        }
        else
        {
            status.status = TransactionStatus::Confirmed;
        }
    }
    else
    {
        if (status.depth < 0)
        {
            status.status = TransactionStatus::Conflicted;
        }
        else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
        {
            status.status = TransactionStatus::Offline;
        }
        else if (status.depth == 0)
        {
            status.status = TransactionStatus::Unconfirmed;
        }
        else if (status.depth < RecommendedNumConfirmations)
        {
            status.status = TransactionStatus::Confirming;
        }
        else
        {
            status.status = TransactionStatus::Confirmed;
        }
    }
}

bool TransactionRecord::statusUpdateNeeded()
{
    AssertLockHeld(cs_main);
    return status.cur_num_blocks != nBestHeight;
}

std::string TransactionRecord::getTxID()
{
    return hash.ToString() + strprintf("-%03d", idx);
}

<commit_msg>3.4.0.8b<commit_after>#include "transactionrecord.h"

#include "wallet.h"
#include "base58.h"

std::string GetTxProject(uint256 hash, int& out_blocknumber, int& out_blocktype, double& out_rac);
std::string RoundToString(double d, int place);
double DoubleFromAmount(int64_t amount);

bool IsLockTimeWithinMinutes(int64_t locktime, int minutes);

bool IsSmartContractForDPOR(const CWalletTx &wtx)
{
   bool result = false;
   QList<TransactionRecord> parts;
   int64_t nTime = wtx.GetTxTime();
   uint256 hash = wtx.GetHash(), hashPrev = 0;

   for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
   {
                const CTxOut& txout = wtx.vout[nOut];
                TransactionRecord sub(hash, nTime);
                sub.idx = parts.size();

                CTxDestination address;
                if (ExtractDestination(txout.scriptPubKey, address))
                {
                    sub.type = TransactionRecord::SendToAddress;
                    sub.address = CBitcoinAddress(address).ToString();
					int64_t nDebit = wtx.GetDebit();
				    if (nDebit=.00001 && sub.address =="S67nL4vELWwdDVzjgtEP4MxryarTZ9a8GB")
					{
						return true;
					}
                }

   }
   return false;
}

/* Return positive answer if transaction should be shown in list. */
bool TransactionRecord::showTransaction(const CWalletTx &wtx)
{

	std::string ShowOrphans = GetArg("-showorphans", "false");
	if (ShowOrphans=="false" && !wtx.IsInMainChain()) return false;
	if (IsSmartContractForDPOR(wtx)) return false;
	//R Halford - Discard Orphans after Y mins:
	if (wtx.IsCoinStake())
	{
		if (!wtx.IsInMainChain())
		{
			//Orphaned tx
			if (ShowOrphans=="true"  && IsLockTimeWithinMinutes(wtx.nTimeReceived,15))
			{
				return true;
			}
			else
			{
				return false;
			}
		}
    }

    if (wtx.IsCoinBase())
    {
        // Ensures we show generated coins / mined transactions at depth 1
        if (!wtx.IsInMainChain())
        {
            return false;
        }
    }
    return true;
}

	int64_t GetMyValueOut(const CWallet *wallet,const CWalletTx &wtx)
    {
        int64_t nValueOut = 0;
        BOOST_FOREACH(const CTxOut& txout, wtx.vout)
        {
	       if (wallet->IsMine(txout))
		   {
				nValueOut += txout.nValue;
		   }
        }
        return nValueOut;
    }

/*
 * Decompose CWallet transaction to model transaction records.
 */
QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
{
    QList<TransactionRecord> parts;
    int64_t nTime = wtx.GetTxTime();
    int64_t nCredit = wtx.GetCredit(true);
    int64_t nDebit = wtx.GetDebit();
    int64_t nNet = nCredit - nDebit;
    uint256 hash = wtx.GetHash(), hashPrev = 0;
    std::map<std::string, std::string> mapValue = wtx.mapValue;

    if (nNet > 0 || wtx.IsCoinBase() || wtx.IsCoinStake())
    {
        //
        // Credit - Calculate Net from CryptoLottery Rob Halford - 4-3-2015-1
        //
        BOOST_FOREACH(const CTxOut& txout, wtx.vout)
        {
            if(wallet->IsMine(txout))
            {
                TransactionRecord sub(hash, nTime);
                CTxDestination address;
                sub.idx = parts.size(); // sequence number
                sub.credit = txout.nValue;
                if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
                {
                    // Received by Bitcoin Address
                    sub.type = TransactionRecord::RecvWithAddress;
                    sub.address = CBitcoinAddress(address).ToString();
                }
                else
                {
                    // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction
                    sub.type = TransactionRecord::RecvFromOther;
                    sub.address = mapValue["from"];
                }
                if (wtx.IsCoinBase())
                {
                    // Generated (proof-of-work)
                    sub.type = TransactionRecord::Generated;
                }
                if (wtx.IsCoinStake())
                {
                    // Generated (proof-of-stake)
			        if (hashPrev == hash)
                        continue; // last coinstake output

					if (wtx.vout.size()==2)
					{
						//Standard POR CoinStake
						sub.type = TransactionRecord::Generated;
						sub.credit = nNet > 0 ? nNet : wtx.GetValueOut() - nDebit;
						hashPrev = hash;
					}
					else
					{
						//CryptoLottery - CoinStake - 4-3-2015
						sub.type = TransactionRecord::Generated;
						if (nDebit == 0)
						{
							sub.credit = GetMyValueOut(wallet,wtx);
							sub.RemoteFlag = 1;
						}
						else
						{
							sub.credit = nNet > 0 ? nNet : GetMyValueOut(wallet,wtx) - nDebit;
						}

						hashPrev = hash;

					}
                }

                parts.append(sub);
            }
        }
    }
    else
    {
        bool fAllFromMe = true;
        BOOST_FOREACH(const CTxIn& txin, wtx.vin)
            fAllFromMe = fAllFromMe && wallet->IsMine(txin);

        bool fAllToMe = true;
        BOOST_FOREACH(const CTxOut& txout, wtx.vout)
            fAllToMe = fAllToMe && wallet->IsMine(txout);

        if (fAllFromMe && fAllToMe)
        {
            // Payment to self
            int64_t nChange = wtx.GetChange();

            parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "",
                            -(nDebit - nChange), nCredit - nChange));
        }
        else if (fAllFromMe)
        {
            //
            // Debit
            //
            int64_t nTxFee = nDebit - wtx.GetValueOut();

            for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
            {
                const CTxOut& txout = wtx.vout[nOut];
                TransactionRecord sub(hash, nTime);
                sub.idx = parts.size();

                if(wallet->IsMine(txout))
                {
                    // Ignore parts sent to self, as this is usually the change
                    // from a transaction sent back to our own address.
                    continue;
                }

                CTxDestination address;
                if (ExtractDestination(txout.scriptPubKey, address))
                {
                    // Sent to Bitcoin Address
                    sub.type = TransactionRecord::SendToAddress;
                    sub.address = CBitcoinAddress(address).ToString();
                }
                else
                {
                    // Sent to IP, or other non-address transaction like OP_EVAL
                    sub.type = TransactionRecord::SendToOther;
                    sub.address = mapValue["to"];
                }

                int64_t nValue = txout.nValue;
                /* Add fee to first output */
                if (nTxFee > 0)
                {
                    nValue += nTxFee;
                    nTxFee = 0;
                }
                sub.debit = -nValue;

                parts.append(sub);
            }
        }
        else
        {
            //
            // Mixed debit transaction, can't break down payees
            //
            parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0));
        }
    }

    return parts;
}

void TransactionRecord::updateStatus(const CWalletTx &wtx)
{
    AssertLockHeld(cs_main);
    // Determine transaction status

    // Find the block the tx is in
    CBlockIndex* pindex = NULL;
    std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(wtx.hashBlock);
    if (mi != mapBlockIndex.end())
        pindex = (*mi).second;

    // Sort order, unrecorded transactions sort to the top
    status.sortKey = strprintf("%010d-%01d-%010u-%03d",
        (pindex ? pindex->nHeight : std::numeric_limits<int>::max()),
        (wtx.IsCoinBase() ? 1 : 0),
        wtx.nTimeReceived,
        idx);
    status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0);
    status.depth = wtx.GetDepthInMainChain();
    status.cur_num_blocks = nBestHeight;

    if (!IsFinalTx(wtx, nBestHeight + 1))
    {
        if (wtx.nLockTime < LOCKTIME_THRESHOLD)
        {
            status.status = TransactionStatus::OpenUntilBlock;
            status.open_for = wtx.nLockTime - nBestHeight;
        }
        else
        {
            status.status = TransactionStatus::OpenUntilDate;
            status.open_for = wtx.nLockTime;
        }
    }

    // For generated transactions, determine maturity
    else if(type == TransactionRecord::Generated)
    {
        if (wtx.GetBlocksToMaturity() > 0)
        {
            status.status = TransactionStatus::Immature;

            if (wtx.IsInMainChain())
            {
                status.matures_in = wtx.GetBlocksToMaturity();

                // Check if the block was requested by anyone
                if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
                    status.status = TransactionStatus::MaturesWarning;
            }
            else
            {
                status.status = TransactionStatus::NotAccepted;
            }
        }
        else
        {
            status.status = TransactionStatus::Confirmed;
        }
    }
    else
    {
        if (status.depth < 0)
        {
            status.status = TransactionStatus::Conflicted;
        }
        else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
        {
            status.status = TransactionStatus::Offline;
        }
        else if (status.depth == 0)
        {
            status.status = TransactionStatus::Unconfirmed;
        }
        else if (status.depth < RecommendedNumConfirmations)
        {
            status.status = TransactionStatus::Confirming;
        }
        else
        {
            status.status = TransactionStatus::Confirmed;
        }
    }
}

bool TransactionRecord::statusUpdateNeeded()
{
    AssertLockHeld(cs_main);
    return status.cur_num_blocks != nBestHeight;
}

std::string TransactionRecord::getTxID()
{
    return hash.ToString() + strprintf("-%03d", idx);
}

<|endoftext|>


<commit_before>// Time:  O(nlogn)
// Space: O(1)

class Solution {
public:
    int splitArray(vector<int>& nums, int m) {
        int left = 0, right = 0;
        for (const auto& num : nums) {
            left = max(left, num);
            right += num;
        }

        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (canSplit(nums, m, mid)) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }

private:
    bool canSplit(vector<int>& nums, int m, int sum) {
        int cnt = 1;
        int curr_sum = 0;
        for (const auto& num : nums) {
            curr_sum += num;
            if (curr_sum > sum) {
                curr_sum = num;
                ++cnt;
            }
        }
        return cnt <= m;
    }
};
<commit_msg>Update split-array-largest-sum.cpp<commit_after>// Time:  O(nlogn)
// Space: O(1)

class Solution {
public:
    int splitArray(vector<int>& nums, int m) {
        int left = 0, right = 0;
        for (const auto& num : nums) {
            left = max(left, num);
            right += num;
        }

        while (left <= right) {
            const auto mid = left + (right - left) / 2;
            if (canSplit(nums, m, mid)) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }

private:
    bool canSplit(vector<int>& nums, int m, int sum) {
        int cnt = 1, curr_sum = 0;
        for (const auto& num : nums) {
            curr_sum += num;
            if (curr_sum > sum) {
                curr_sum = num;
                ++cnt;
            }
        }
        return cnt <= m;
    }
};
<|endoftext|>


<commit_before>#include "potholedetector.h"
#include <opencv2/video/video.hpp>
#include <sensor_msgs/image_encodings.h>
#include <pcl_ros/point_cloud.h>
#include <camera_info_manager/camera_info_manager.h>
#include <math.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>

using namespace std;
using namespace cv;
using namespace pcl;

cv_bridge::CvImagePtr cv_ptr;
typedef pcl::PointCloud<pcl::PointXYZ> PCLCloud;

const int maxRadius = 150;
const int minRadius = 20;

// Set 1 to disable
const int minWhiteThreshold = 255 * 0.30;
const int maxWhiteThreshold = 255 * 1;

const int sizeThreshold = 200;

void PotholeDetector::img_callback(const sensor_msgs::ImageConstPtr& msg) {
    cv_ptr = cv_bridge::toCvCopy(msg, "");
    Mat orig = cv_ptr->image.clone();
    src = cv_ptr->image.clone();

    //Crops the image (removes sky)
    int topCrop = src.rows / 2 - 100;
    cv::Rect myROI(0, topCrop, src.cols, src.rows - topCrop);
    src = src(myROI);

    cvtColor(src, src_gray, CV_BGR2GRAY);

    //Find the mean and stddev of the grayscale image in order to do adaptive thresholding
    Mat mean;
    Mat stddev;
    meanStdDev(src_gray, mean, stddev);

    double thresh = mean.at<double>(0,0) + (stddev.at<double>(0,0) * 2);
    if(thresh > 254) {
        thresh = 254;
    }

    threshold(src_gray, src_gray, thresh, 255, THRESH_BINARY);

    GaussianBlur(src_gray, src_gray, Size(gaussian_size, gaussian_size), 2, 2);

    vector<Vec3f> circles;

    // TODO tune circle radii for actual potholes
    HoughCircles(src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows / 8, 50, 10, minRadius, maxRadius);

    Mat cloudMat = Mat::zeros(orig.rows, orig.cols, CV_32F);
    /// Put the circles into a matrix
    for( size_t i = 0; i < circles.size(); i++ ) {
        Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
        int radius = cvRound(circles[i][2]);

        // If the circle is too close to the top / bottom edges, filter
        if (center.y <= 100 || center.y >= src_gray.rows - 100) {
            continue;
        }

        // If the circle is too close to the left / right edges, filter
        if (center.x <= 200 || center.x >= src_gray.cols - 200) {
            continue;
        }

        int cropSize = (100 / (double) src_gray.rows) * center.y;
        //Get a matrix around circle center
        cv::Rect myROI(center.x - (cropSize * 2), center.y - cropSize, cropSize * 4, cropSize * 2);
        Mat roi = src_gray(myROI);

        // If the sum of all the pixels in the rectangle is less than sumThreshold
        // Then this circle is not encompassing mostly white pixels
        const int sumThreshold = (cropSize * cropSize * 8);
        double sum = cv::sum(roi)[0];
        if (sum < sumThreshold * minWhiteThreshold || sum > sumThreshold * maxWhiteThreshold) {
            continue;
        }

        //circle(cloudMat, center, radius, Scalar(255), 1, 8, 0);
        rectangle(src, myROI, Scalar(255), 2, 8, 0);
        cerr << "" + to_string(cropSize) + " " + to_string(radius) << endl;
        circle(src, center, radius, Scalar(255), 2, 8, 0);

        Point offset(center.x - (cropSize * 2), center.y - cropSize);
        vector<vector<Point>> contours;
        findContours(roi, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE, Point((center.x - (cropSize * 2)), center.y - cropSize));

        // Filter false positives - small contours and cone stripes
        for (vector<vector<Point>>::iterator it = contours.begin(); it != contours.end(); ++it) {
            vector<Point> curCont = *it;
            if (curCont.size() <= sizeThreshold) {
                contours.erase(it);
                --it;
            }
        }

        drawContours(src, contours, -1, Scalar(20, 236, 27), 3, 8);
    }

    cvtColor(src_gray, src_gray, CV_GRAY2BGR);

    cv_bridge::CvImage out_msg;
    out_msg.header   = msg->header;
    out_msg.encoding = msg->encoding;
    out_msg.image    = src;

    cv_ptr->image = src;
    _pothole_filt_img.publish(cv_ptr->toImageMsg());
    _pothole_thres.publish(out_msg.toImageMsg());
    cloud = toPointCloud(cloudMat);
    _pothole_cloud.publish(cloud);
}

PotholeDetector::PotholeDetector(ros::NodeHandle &handle)
    : gaussian_size(7),
      _it(handle),
      tf_listener(handle) {
    _src_img = _it.subscribe("/stereo/right/image_raw", 1, &PotholeDetector::img_callback, this);
    _pothole_filt_img = _it.advertise("/pothole_filt_img", 1);
    _pothole_thres = _it.advertise("/pothole_thres", 1);
    _pothole_cloud = handle.advertise<PCLCloud>("/pothole_cloud", 100);
}

// FIXME does not take into account distance from groud to camera
PointCloud<PointXYZ>::Ptr PotholeDetector::toPointCloud(Mat src) {
    PointCloud<PointXYZ>::Ptr cloud(new PointCloud<PointXYZ>);
    for(int r = 0; r < src.rows; r++) {
        float *row = src.ptr<float>(r);
        for(int c = 0; c < src.cols; c++) {
            if(row[c] > 0) {
                cloud->points.push_back(PointXYZ(r, c, 0));
            }
        }
    }
	cloud->header.frame_id = "base_footprint";
	return cloud;
}
<commit_msg>Changed initial sampling and white thresholding code. Need to work on detetecting false positives in the grass.<commit_after>#include "potholedetector.h"
#include <opencv2/video/video.hpp>
#include <sensor_msgs/image_encodings.h>
#include <pcl_ros/point_cloud.h>
#include <camera_info_manager/camera_info_manager.h>
#include <math.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>

using namespace std;
using namespace cv;
using namespace pcl;

cv_bridge::CvImagePtr cv_ptr;
typedef pcl::PointCloud<pcl::PointXYZ> PCLCloud;

const int maxRadius = 50;
const int minRadius = 10;

// Set 1 to disable
const int minWhiteThreshold = 255 * 0.60;
const int maxWhiteThreshold = 255 * 1;
const int whiteSampleRadius = 30;

const int sizeThreshold = 200;

const int lightROrange = 230;
const int lightGOrange = 180;
const int lightBOrange = 180;
const int darkROrange = 140;
const int darkGOrange = 50;
const int darkBOrange = 40;

int getDiff(int a, int b) {
    return abs(a - b);
}

void PotholeDetector::img_callback(const sensor_msgs::ImageConstPtr& msg) {
    cv_ptr = cv_bridge::toCvCopy(msg, "");
    Mat orig = cv_ptr->image.clone();
    src = cv_ptr->image.clone();

    //Crops the image (removes sky)
    int topCrop = src.rows / 2 - 100;
    cv::Rect myROI(0, topCrop, src.cols, src.rows - topCrop);
    src = src(myROI);

    cvtColor(src, src_gray, CV_BGR2GRAY);

    //Find the mean and stddev of the grayscale image in order to do adaptive thresholding
    Mat mean;
    Mat stddev;
    meanStdDev(src_gray, mean, stddev);

    double thresh = mean.at<double>(0,0) + (stddev.at<double>(0,0) * 2);
    if(thresh > 254) {
        thresh = 254;
    }

    threshold(src_gray, src_gray, thresh, 255, THRESH_BINARY);

    GaussianBlur(src_gray, src_gray, Size(gaussian_size, gaussian_size), 2, 2);

    vector<Vec3f> circles;

    // TODO tune circle radii for actual potholes
    HoughCircles(src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows / 8, 50, 10, minRadius, maxRadius);

    Mat cloudMat = Mat::zeros(orig.rows, orig.cols, CV_32F);
    /// Put the circles into a matrix
    for( size_t i = 0; i < circles.size(); i++ ) {
        Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
        int radius = cvRound(circles[i][2]);

        // If the circle is too close to the top / bottom edges, filter
        if (center.y <= 100 || center.y >= src_gray.rows - 100) {
            continue;
        }

        // If the circle is too close to the left / right edges, filter
        if (center.x <= 100 || center.x >= src_gray.cols - 100) {
            continue;
        }

        int cropSize = (125 / (double) src_gray.rows) * center.y;

        int xStart = center.x - (cropSize * 2);
        if (xStart < 0) {
            xStart = 0;
        }
        int yStart = center.y - cropSize;
        if (yStart < 0) {
            yStart = 0;
        }
        int xWidth = cropSize * 4;
        if (xWidth + xStart > src_gray.cols) {
            xWidth = src_gray.cols - xStart;
        }
        int yHeight = cropSize * 2;
        if (yHeight + yStart > src_gray.rows) {
            yHeight = src_gray.rows - yStart;
        }

        //Get a matrix around circle center
        cv::Rect myROI(xStart, yStart, xWidth, yHeight);
        Mat roi = src_gray(myROI);

        // If the sum of all the pixels in the rectangle is less than sumThreshold
        // Then this circle is not encompassing mostly white pixels
        const int sumThreshold = whiteSampleRadius * whiteSampleRadius * (double) 3.141592 * 3;
        double sum = 0;
        for (int i = -whiteSampleRadius; i <= whiteSampleRadius; i++) {
            for (int j = -whiteSampleRadius; j <= whiteSampleRadius; j++) {
                if (i * i + j * j <= whiteSampleRadius * whiteSampleRadius) {
                    Vec3b currentPixel = src.at<Vec3b>(j + center.y, i + center.x);
                    sum += currentPixel[0] + currentPixel[1] + currentPixel[2];
                }
            }
        }
        Point sampleCenter(center.x, center.y);

        if (sum < sumThreshold * minWhiteThreshold || sum > sumThreshold * maxWhiteThreshold) {
            continue;
        }

        //circle(cloudMat, center, radius, Scalar(255), 1, 8, 0);
        rectangle(src, myROI, Scalar(255), 2, 8, 0);
        circle(src, sampleCenter, whiteSampleRadius, Scalar(255), 1, 8, 0);
        circle(src, center, radius, Scalar(255), 2, 8, 0);

        Point offset(center.x - (cropSize * 2), center.y - cropSize);
        vector<vector<Point>> contours;
        findContours(roi, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE, Point((center.x - (cropSize * 2)), center.y - cropSize));

        // Filter false positives - small contours
        /*
        for (vector<vector<Point>>::iterator it = contours.begin(); it != contours.end(); ++it) {
            vector<Point> curCont = *it;
            if (curCont.size() <= sizeThreshold) {
                contours.erase(it);
                --it;
            }
        } */

        // Filter false positives - small contours and cone stripes
        for (vector<vector<Point>>::iterator it = contours.begin(); it != contours.end(); ++it) {
            if ((*it).size() > sizeThreshold) {
                // Find center in x frame
                int minY = src_gray.rows;
                int minX = src_gray.cols;
                int maxY = 0;
                int maxX = 0;
                for (Point p : *it) {
                    int x = p.x;
                    if (x > maxX) {
                        maxX = x;
                    }
                    if (x < minX) {
                        minX = x;
                    }
                }
                int centerX = (minX + maxX) / 2;
                int realMinY = src_gray.rows;
                int realMaxY;

                // Find centers of top and bottom edges
                for (Point p : *it) {
                    int x = p.x;
                    int y = p.y;
                    if (x == centerX && y > maxY) {
                        maxY = y;
                    }
                    if (x == centerX && y < minY) {
                        minY = y;
                    }

                    if (y > realMaxY) {
                        realMaxY = y;
                    }
                    if (y < realMinY) {
                        realMinY = y;
                    }
                }

                int realCenterY = (realMinY + realMaxY) / 2;

                // Check if contour is within bounds of image
                if (minY - 35 >= 0) {
                    // Average rgb values above and below the contour
                    int blueAbove = 0;
                    int greenAbove = 0;
                    int redAbove = 0;
                    int blueBelow = 0;
                    int greenBelow = 0;
                    int redBelow = 0;
                    Vec3b currentPixel;
                    for (int j = 5; j < 36; j++) {
                        currentPixel = src.at<Vec3b>(minY - j, centerX);
                        blueAbove += currentPixel[0];
                        greenAbove += currentPixel[1];
                        redAbove += currentPixel[2];
                        currentPixel[0] = 0;
                        currentPixel[1] = 0;
                        currentPixel[2] = 0;
                        src.at<Vec3b>(minY - j, centerX) = currentPixel;
                        currentPixel = src.at<Vec3b>(maxY + j, centerX);
                        blueBelow += currentPixel[0];
                        greenBelow += currentPixel[1];
                        redBelow += currentPixel[2];
                        currentPixel[0] = 0;
                        currentPixel[1] = 0;
                        currentPixel[2] = 0;
                        src.at<Vec3b>(maxY + j, centerX) = currentPixel;
                    }
                    blueAbove /= 30;
                    greenAbove /= 30;
                    redAbove /= 30;
                    blueBelow /= 30;
                    greenBelow /= 30;
                    redBelow /= 30;

                    if (redAbove > greenAbove + 50 && redAbove > blueAbove + 50 && redBelow > greenBelow + 50 && redBelow > blueBelow + 50) {
                        contours.erase(it);
                        --it;
                    } else {
                        // Delete if the contour itself is orange
                        Vec3b intensity = src.at<Vec3b>((minY + maxY) / 2, centerX);
                        uchar blue = intensity.val[0];
                        uchar green = intensity.val[1];
                        uchar red = intensity.val[2];
                        if ((getDiff(red, darkROrange) < 50 && getDiff(green, darkGOrange) < 50
                                && getDiff(blue, darkBOrange) < 50)
                                || (getDiff(red, lightROrange) < 50 && getDiff(green, lightGOrange) < 50
                                && getDiff(blue, lightBOrange) < 50)) {
                            contours.erase(it);
                            --it;
                        } else {
                            cerr << to_string(maxX - minX) + " " + to_string(maxY - minY) << endl;
                            int xDist = maxX - minX;
                            int yDist = realMaxY - realMinY;
                            if (xDist < yDist * 1.9 || xDist > yDist * 3.1) {
                                contours.erase(it);
                                --it;
                            }
                        }
                    }

                    // // Filter out contours with orange above and below
                    // // If above is light or dark orange and below is light or dark
                    // if (((getDiff(redAbove, darkROrange) < 50
                    //         && getDiff(greenAbove, darkGOrange) < 50
                    //         && getDiff(blueAbove, darkBOrange) < 50)
                    //         || (getDiff(redAbove, lightROrange) < 50
                    //         && getDiff(greenAbove, lightGOrange) < 50
                    //         && getDiff(blueAbove, lightBOrange) < 50))
                    //     && ((getDiff(redBelow, darkROrange) < 50
                    //         && getDiff(greenBelow, darkGOrange) < 50
                    //         && getDiff(blueBelow, darkBOrange) < 50)
                    //         || (getDiff(redBelow, lightROrange) < 50
                    //         && getDiff(greenBelow, lightGOrange) < 50
                    //         && getDiff(blueBelow, lightBOrange) < 50))) {
                    //     // Delete contour
                    //     contours.erase(it);
                    //     --it;
                    // } else {
                    //     cerr << "" + to_string(blueAbove) + ", " + to_string(greenAbove) + ", " + to_string(redAbove) + "     " + to_string(blueBelow) + ", " + to_string(greenBelow) + ", " + to_string(redBelow)  << endl;
                    // }
                } else {
                    contours.erase(it);
                    --it;
                }
            } else {
                contours.erase(it);
                --it;
            }
        }

        drawContours(src, contours, -1, Scalar(20, 236, 27), 3, 8);
    }

    cvtColor(src_gray, src_gray, CV_GRAY2BGR);

    cv_bridge::CvImage out_msg;
    out_msg.header   = msg->header;
    out_msg.encoding = msg->encoding;
    out_msg.image    = src;

    cv_ptr->image = src;
    _pothole_filt_img.publish(cv_ptr->toImageMsg());
    _pothole_thres.publish(out_msg.toImageMsg());
    cloud = toPointCloud(cloudMat);
    _pothole_cloud.publish(cloud);
}

PotholeDetector::PotholeDetector(ros::NodeHandle &handle)
    : gaussian_size(7),
      _it(handle),
      tf_listener(handle) {
    _src_img = _it.subscribe("/stereo/right/image_raw", 1, &PotholeDetector::img_callback, this);
    _pothole_filt_img = _it.advertise("/pothole_filt_img", 1);
    _pothole_thres = _it.advertise("/pothole_thres", 1);
    _pothole_cloud = handle.advertise<PCLCloud>("/pothole_cloud", 100);
}

// FIXME does not take into account distance from groud to camera
PointCloud<PointXYZ>::Ptr PotholeDetector::toPointCloud(Mat src) {
    PointCloud<PointXYZ>::Ptr cloud(new PointCloud<PointXYZ>);
    for(int r = 0; r < src.rows; r++) {
        float *row = src.ptr<float>(r);
        for(int c = 0; c < src.cols; c++) {
            if(row[c] > 0) {
                cloud->points.push_back(PointXYZ(r, c, 0));
            }
        }
    }
	cloud->header.frame_id = "base_footprint";
	return cloud;
}
<|endoftext|>


<commit_before>#ifndef HMLIB_LATTICES_POINTACCESSITERATOR_INC
#define HMLIB_LATTICES_POINTACCESSITERATOR_INC 100
#
#include<iterator>
namespace hmLib {
	template<typename lattice_type_, typename point_iterator_, typename point_iterator_category_ = typename std::iterator_traits<point_iterator_>::iterator_category>
	struct point_access_iterator {};
	template<typename lattice_type_, typename point_iterator_>
	struct point_access_iterator<lattice_type_, point_iterator_, std::input_iterator_tag> {
	private:
		using this_type = point_access_iterator<lattice_type_, point_iterator_, std::input_iterator_tag>;
		using lattice_type = lattice_type_;
		using lattice_reference = lattice_type&;
		using point_iterator = point_iterator_;
	public:
		using value_type = typename std::iterator_traits<base_iterator>::value_type;
		using difference_type = typename std::iterator_traits<base_iterator>::difference_type;
		using reference = typename std::iterator_traits<base_iterator>::reference;
		using pointer = typename std::iterator_traits<base_iterator>::pointer;
		using iterator_category = std::input_iterator_tag;
	private:
		lattice_type Lattice;
		point_iterator IItr;
	public://constructer
		point_access_iterator() = default;
		point_access_iterator(base_iterator Beg_, index_iterator_ IItr_):Beg(Beg_), IItr(IItr_) {}
		template<typename other_iterator_, typename std::enable_if<std::is_convertible<base_iterator, other_iterator_>::value&&!std::is_same<base_iterator, other_iterator_>::value>::type *& = hmLib::utility::enabler>
		point_access_iterator(const point_access_iterator<other_iterator_, index_iterator_>& Other) : Beg(Other.Beg), IItr(Other.IItr) {}
		template<typename other_iterator_, typename std::enable_if<std::is_convertible<base_iterator, other_iterator_>::value&&!std::is_same<base_iterator, other_iterator_>::value>::type *& = hmLib::utility::enabler>
		this_type& operator=(const point_access_iterator<other_iterator_, index_iterator_>& Other) {
			Beg = Other.Beg;
			IItr = Other.IItr;
			return *this;
		}
	public:
		reference operator*()const { return Beg[*IItr]; }
		pointer operator->()const { return &Beg[*IItr]; }
		this_type& operator++() {
			++IItr;
			return *this;
		}
		this_type operator++(int) {
			this_type Ans = *this;
			operator++();
			return Ans;
		}
		base_iterator base()const { return Beg+(*IItr); }
		auto index()const { return *IItr; }
		friend bool operator==(const this_type& v1, const this_type& v2) {
			return v1.IItr == v2.IItr;
		}
		friend bool operator!=(const this_type& v1, const this_type& v2) {
			return v1.IItr != v2.IItr;
		}
	};
	template<typename random_access_iterator_, typename index_iterator_>
	struct index_access_iterator<random_access_iterator_, index_iterator_, std::forward_iterator_tag> {
	private:
		static_assert(std::is_same<typename std::iterator_traits<random_access_iterator_>::iterator_category, std::random_access_iterator_tag>::value, "index_iterator can use only for random_access_iterator");
		using this_type = index_access_iterator<random_access_iterator_, index_iterator_, std::forward_iterator_tag>;
		using base_iterator = random_access_iterator_;
		using index_iterator = index_iterator_;
	public:
		using value_type = typename std::iterator_traits<base_iterator>::value_type;
		using difference_type = typename std::iterator_traits<base_iterator>::difference_type;
		using reference = typename std::iterator_traits<base_iterator>::reference;
		using pointer = typename std::iterator_traits<base_iterator>::pointer;
		using iterator_category = std::forward_iterator_tag;
	private:
		base_iterator Beg;
		index_iterator IItr;
	public://constructer
		index_access_iterator() = default;
		index_access_iterator(base_iterator Beg_, index_iterator_ IItr_):Beg(Beg_), IItr(IItr_) {}
		template<typename other_iterator_, typename std::enable_if<std::is_convertible<base_iterator, other_iterator_>::value&&!std::is_same<base_iterator, other_iterator_>::value>::type *& = hmLib::utility::enabler>
		index_access_iterator(const index_access_iterator<other_iterator_, index_iterator_>& Other) : Beg(Other.Beg), IItr(Other.IItr) {}
		template<typename other_iterator_, typename std::enable_if<std::is_convertible<base_iterator, other_iterator_>::value&&!std::is_same<base_iterator, other_iterator_>::value>::type *& = hmLib::utility::enabler>
		this_type& operator=(const index_access_iterator<other_iterator_, index_iterator_>& Other) {
			Beg = Other.Beg;
			IItr = Other.IItr;
			return *this;
		}
	public:
		reference operator*()const { return Beg[*IItr]; }
		pointer operator->()const { return &Beg[*IItr]; }
		this_type& operator++() {
			++IItr;
			return *this;
		}
		this_type operator++(int) {
			this_type Ans = *this;
			operator++();
			return Ans;
		}
		base_iterator base() { return Beg+(*IItr); }
		auto index()const { return *IItr; }
		friend bool operator==(const this_type& v1, const this_type& v2) {
			return v1.IItr == v2.IItr;
		}
		friend bool operator!=(const this_type& v1, const this_type& v2) {
			return v1.IItr != v2.IItr;
		}
	};
	template<typename random_access_iterator_, typename index_iterator_>
	struct index_access_iterator<random_access_iterator_, index_iterator_, std::bidirectional_iterator_tag> {
	private:
		static_assert(std::is_same<typename std::iterator_traits<random_access_iterator_>::iterator_category, std::random_access_iterator_tag>::value, "index_iterator can use only for random_access_iterator");
		using this_type = index_access_iterator<random_access_iterator_, index_iterator_, std::bidirectional_iterator_tag>;
		using base_iterator = random_access_iterator_;
		using index_iterator = index_iterator_;
	public:
		using value_type = typename std::iterator_traits<base_iterator>::value_type;
		using difference_type = typename std::iterator_traits<base_iterator>::difference_type;
		using reference = typename std::iterator_traits<base_iterator>::reference;
		using pointer = typename std::iterator_traits<base_iterator>::pointer;
		using iterator_category = std::bidirectional_iterator_tag;
	private:
		base_iterator Beg;
		index_iterator IItr;
	public://constructer
		index_access_iterator() = default;
		index_access_iterator(base_iterator Beg_, index_iterator_ IItr_):Beg(Beg_), IItr(IItr_) {}
		template<typename other_iterator_, typename std::enable_if<std::is_convertible<base_iterator, other_iterator_>::value&&!std::is_same<base_iterator, other_iterator_>::value>::type *& = hmLib::utility::enabler>
		index_access_iterator(const index_access_iterator<other_iterator_, index_iterator_>& Other) : Beg(Other.Beg), IItr(Other.IItr) {}
		template<typename other_iterator_, typename std::enable_if<std::is_convertible<base_iterator, other_iterator_>::value&&!std::is_same<base_iterator, other_iterator_>::value>::type *& = hmLib::utility::enabler>
		this_type& operator=(const index_access_iterator<other_iterator_, index_iterator_>& Other) {
			Beg = Other.Beg;
			IItr = Other.IItr;
			return *this;
		}
	public:
		reference operator*()const { return Beg[*IItr]; }
		pointer operator->()const { return &Beg[*IItr]; }
		this_type& operator++() {
			++IItr;
			return *this;
		}
		this_type operator++(int) {
			this_type Ans = *this;
			operator++();
			return Ans;
		}
		this_type& operator--() {
			--IItr;
			return *this;
		}
		this_type operator--(int) {
			this_type Ans = *this;
			operator--();
			return Ans;
		}
		base_iterator base()const { return Beg+(*IItr); }
		auto index()const { return *IItr; }
		friend bool operator==(const this_type& v1, const this_type& v2) {
			return v1.IItr == v2.IItr;
		}
		friend bool operator!=(const this_type& v1, const this_type& v2) {
			return v1.IItr != v2.IItr;
		}
	};
	template<typename random_access_iterator_, typename index_iterator_>
	struct index_access_iterator<random_access_iterator_, index_iterator_, std::random_access_iterator_tag> {
	private:
		static_assert(std::is_same<typename std::iterator_traits<random_access_iterator_>::iterator_category, std::random_access_iterator_tag>::value, "index_iterator can use only for random_access_iterator");
		using this_type = index_access_iterator<random_access_iterator_, index_iterator_, std::random_access_iterator_tag>;
		using base_iterator = random_access_iterator_;
		using index_iterator = index_iterator_;
	public:
		using value_type = typename std::iterator_traits<base_iterator>::value_type;
		using difference_type = typename std::iterator_traits<base_iterator>::difference_type;
		using reference = typename std::iterator_traits<base_iterator>::reference;
		using pointer = typename std::iterator_traits<base_iterator>::pointer;
		using iterator_category = std::random_access_iterator_tag;
	private:
		base_iterator Beg;
		index_iterator IItr;
	public://constructer
		index_access_iterator() = default;
		index_access_iterator(base_iterator Beg_, index_iterator_ IItr_):Beg(Beg_), IItr(IItr_) {}
		template<typename other_iterator_, typename std::enable_if<std::is_convertible<base_iterator, other_iterator_>::value&&!std::is_same<base_iterator, other_iterator_>::value>::type *& = hmLib::utility::enabler>
		index_access_iterator(const index_access_iterator<other_iterator_, index_iterator_>& Other) : Beg(Other.Beg), IItr(Other.IItr) {}
		template<typename other_iterator_, typename std::enable_if<std::is_convertible<base_iterator, other_iterator_>::value&&!std::is_same<base_iterator, other_iterator_>::value>::type *& = hmLib::utility::enabler>
		this_type& operator=(const index_access_iterator<other_iterator_, index_iterator_>& Other) {
			Beg = Other.Beg;
			IItr = Other.IItr;
			return *this;
		}
	public:
		reference operator*()const { return Beg[*IItr]; }
		pointer operator->()const { return &Beg[*IItr]; }
		reference operator[](difference_type d) { return Beg[IItr[d]]; }
		this_type& operator++() {
			++IItr;
			return *this;
		}
		this_type operator++(int) {
			this_type Ans = *this;
			operator++();
			return Ans;
		}
		this_type& operator--() {
			--IItr;
			return *this;
		}
		this_type operator--(int) {
			this_type Ans = *this;
			operator--();
			return Ans;
		}
		this_type& operator+=(difference_type d) {
			IItr = +d;
			return *this;
		}
		this_type& operator-=(difference_type d) {
			IItr = -d;
			return *this;
		}
		friend this_type operator+(const this_type& itr, difference_type d) {
			this_type ans = itr;
			ans += d;
			return ans;
		}
		friend this_type operator+(difference_type d, const this_type& itr) {
			return operator+(itr, d);
		}
		friend this_type operator-(const this_type& itr, difference_type d) {
			this_type ans = itr;
			ans -= d;
			return ans;
		}
		friend difference_type operator-(const this_type& itr1, const this_type& itr2) {
			return itr1.IItr - itr2.IItr;
		}
		base_iterator base()const { return Beg+(*IItr); }
		auto index()const { return *IItr; }
		friend bool operator==(const this_type& v1, const this_type& v2) {
			return v1.IItr == v2.IItr;
		}
		friend bool operator!=(const this_type& v1, const this_type& v2) {
			return v1.IItr != v2.IItr;
		}
		friend bool operator>(const this_type& v1, const this_type& v2) {
			return v1.IItr > v2.IItr;
		}
		friend bool operator<(const this_type& v1, const this_type& v2) {
			return v1.IItr < v2.IItr;
		}
		friend bool operator>=(const this_type& v1, const this_type& v2) {
			return v1.IItr >= v2.IItr;
		}
		friend bool operator<=(const this_type& v1, const this_type& v2) {
			return v1.IItr <= v2.IItr;
		}
	};

	template<typename lattice_type_, typename point_iterator_>
	struct point_access_iterator {
	};
}
#
#endif
<commit_msg>Remove old point_access iterator.hpp<commit_after><|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkTestFriendTemplatedFunction.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

/*
   This file tests the syntax that the compiler supports for declaring
   templated functions as friends of a templated class.
*/

//
// Here is our templated function
//
template <class T>
T compose( const T & a, const T & b )
{ return a + b; }

//
// Here is our templated class
//
template <class T>
class WantToHaveFriend
{
public:

  typedef WantToHaveFriend Self;

  Self operator+(const Self & other) const
    {
    Self result;
    result.x = this->x + other.x;
    return result;
    }

  WantToHaveFriend()
    {
    x = 0;
    }

  void DoNothing() const
    {
    // of course... do nothing.
    }

//
//  Here are the variants that some compilers use
//

#ifdef TRY_COMPILE_FRIEND_WITH_NULL_TEMPLATE_STRING
  friend Self compose(const Self &, const Self &);
#endif

#ifdef TRY_COMPILE_FRIEND_WITH_EMPTY_TEMPLATE_BRACKETS
  friend Self compose<>(const Self &, const Self &);
#endif

#ifdef TRY_COMPILE_FRIEND_WITH_TEMPLATE_ARGUMENTS
  friend Self compose<Self>(const Self &, const Self &);
#endif

private:
   int x;
};

int main()
{
  typedef WantToHaveFriend<int>  FriendlyType;

  FriendlyType foo1;
  FriendlyType foo2;
  FriendlyType foo3;

  foo1 = compose( foo2, foo3 );

  foo1.DoNothing();

  return 0;
}

<commit_msg>ENH: Creating a code example similar to what is found in itk_hashmap and itk_hashtable.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkTestFriendTemplatedFunction.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

/*
   This file tests the syntax that the compiler supports for declaring
   templated functions as friends of a templated class.
*/

//
// Here is our templated function, forward declared
//
template <class T> class WantToHaveFriend;

template <class T>
bool operator==( const WantToHaveFriend<T> & a, const  WantToHaveFriend<T> & b );

//
// Here is our templated class
//
template <class T>
class WantToHaveFriend
{
public:

  typedef WantToHaveFriend Self;

  WantToHaveFriend()
    {
    x = 0;
    }

  void DoNothing() const
    {
    // of course... do nothing.
    }

//
//  Here are the variants that some compilers use
//

#ifdef TRY_COMPILE_FRIEND_WITH_NULL_TEMPLATE_STRING
  friend bool operator==(const Self &, const Self &);
#endif

#ifdef TRY_COMPILE_FRIEND_WITH_EMPTY_TEMPLATE_BRACKETS
  friend bool operator==<>(const Self &, const Self &);
#endif

#ifdef TRY_COMPILE_FRIEND_WITH_TEMPLATE_ARGUMENTS
  friend bool operator==<Self>(const Self &, const Self &);
#endif

private:
   int x;
};

template <class T>
bool operator==( const WantToHaveFriend<T> & a, const  WantToHaveFriend<T> & b )
{ return a.x == b.x; }

int main()
{
  typedef WantToHaveFriend<int>  FriendlyType;

  FriendlyType foo1;
  FriendlyType foo2;

  bool result = ( foo1 == foo2 );

  if( result )
    {
    return 1;
    }

  return 0;
}

<|endoftext|>