コード例 #1
0
ファイル: ImageNode.cpp プロジェクト: ming-hai/libavg
glm::vec2 ImageNode::toCanvasPos(const glm::vec2& pos)
{
    OffscreenCanvasPtr pCanvas = m_pGPUImage->getCanvas();
    AVG_ASSERT(pCanvas);
    glm::vec2 containerPos = getRelPos(pos);
    glm::vec2 nodeSize(getSize());
    glm::vec2 canvasSize(pCanvas->getSize());
    return glm::vec2(containerPos.x*(canvasSize.x/nodeSize.x),
            containerPos.y*(canvasSize.y/nodeSize.y));
}
コード例 #2
0
ファイル: ImageNode.cpp プロジェクト: ming-hai/libavg
void ImageNode::getElementsByPos(const glm::vec2& pos, vector<NodePtr>& pElements)
{
    if (reactsToMouseEvents()) {
        OffscreenCanvasPtr pCanvas = m_pGPUImage->getCanvas();
        if (pCanvas && pCanvas->getHandleEvents()) {
            glm::vec2 nodeSize(getSize());
            glm::vec2 canvasSize(pCanvas->getSize());
            glm::vec2 localPos(pos.x*(canvasSize.x/nodeSize.x), 
                    pos.y*(canvasSize.y/nodeSize.y));
            pCanvas->getRootNode()->getElementsByPos(localPos, pElements);
        }
        RasterNode::getElementsByPos(pos, pElements);
    }
}
コード例 #3
0
ファイル: testApp.cpp プロジェクト: pleekMan/fileNavigator_00
//--------------------------------------------------------------
void testApp::setup(){
    
    cout << "-------------------oo" << endl;
    cout << "-------------------oo" << endl;
    
    ofSetFrameRate(30);
    ofSetVerticalSync(true);
    //ofEnableAlphaBlending();
    //ofEnableSmoothing();
    //ofSetCircleResolution(32);
    ofBackground(0);
    ofSetBackgroundAuto(true);
    
    //DirectoryUtils dirUtil;
    
    ofDirectory dir("");

    dir.listDir();
    

    cout << "FileCount: " << dir.numFiles() << endl;
    cout << "FilePath: " << dir.getPath(0) << endl;
    cout << "FilePath: " << dir.getAbsolutePath() << endl;
    cout << " " << endl;
    
    ofVec2f nodePos(10,50);
    ofVec2f nodeSize(200,17);
    
    for (int i = 0; i < dir.numFiles(); i++) {
        string filePath = dir.getAbsolutePath() + "/" + dir.getPath(i);
        files.push_back(filePath);
        cout << files[i] << endl;
        
        nodes.push_back(Node(nodePos, nodeSize, filePath));
        nodePos += ofVec2f(0,20);
        
    }

}
コード例 #4
0
std::pair< size_t, size_t > WHtreeProcesser::pruneTree( float condition, size_t safeSize, const HTPROC_MODE pruneType )
{
    if( safeSize == 0 )
    {
        safeSize = m_tree.getNumLeaves(); // any cluster no matter what size may be pruned if he meets the conditions
    }

    if( pruneType == HTPR_SIZERATIO )
    {
        if( condition < 2 )
            throw std::runtime_error( "ERROR @ WHtreeProcesser::pruneTree(): size pruning ratio must be equal or greater than 2" );
    }
    else if( pruneType == HTPR_JOINSIZE )
    {
        condition = std::floor( condition );
        if( condition < safeSize )
            throw std::runtime_error(
                            "ERROR @ WHtreeProcesser::pruneTree(): size pruning lower boundary must be smaller than greater boundary" );
    }
    else if( pruneType == HTPR_JOINLEVEL )
    {
        if( condition <= 0 || condition >= 1 )
        {
            throw std::runtime_error( "ERROR @ WHtreeProcesser::pruneTree(): condition is out of boundaries" );
        }
        if( safeSize >= m_tree.getNumLeaves() )
        {
            throw std::runtime_error(
                     "ERROR @ WHtreeProcesser::pruneTree(): when pruning by distance level a safe size smaller than the roi size must be entered" );
        }
    }

    size_t prunedLeaves( 0 ), prunedNodes( 0 );

    // loop through all leaves and set them to prune if they match discardidng conditions
    for( std::vector< WHnode >::iterator leavesIter( m_tree.m_leaves.begin() ); leavesIter != m_tree.m_leaves.end(); ++leavesIter )
    {
        size_t parentID( leavesIter->getParent().second );
        size_t parentLevel( m_tree.getNode( parentID ).getDistLevel() );

        if( ( pruneType == HTPR_JOINLEVEL ) && ( parentLevel > condition ) )
        {
            leavesIter->setFlag( true );
        }
        else if( ( pruneType == HTPR_SIZERATIO ) || ( pruneType == HTPR_JOINSIZE ) )
        {
            size_t biggerSize( 0 );
            std::vector< nodeID_t > kids( m_tree.getNode( parentID ).getChildren() );
            for( size_t i = 0; i < kids.size(); ++i )
            {
                size_t brotherSize( m_tree.getNode( kids[i] ).getSize() );
                if( brotherSize > biggerSize )
                {
                    biggerSize = brotherSize;
                }
            }
            if( biggerSize > condition )
            {
                leavesIter->setFlag( true );
            }
        }
    }

    // loop through all nodes and set them to prune if they match discarding conditions
    for( std::vector< WHnode >::iterator nodesIter( m_tree.m_nodes.begin() ); nodesIter != m_tree.m_nodes.end() - 1; ++nodesIter )
    { // dont check last node
        size_t parentID( nodesIter->getParent().second );
        size_t nodeSize( nodesIter->getSize() );
        size_t parentLevel( m_tree.getNode( parentID ).getDistLevel() );
        bool pruneBranch( false );

        if( nodeSize < safeSize )
        {
            if( ( pruneType == HTPR_JOINLEVEL ) && ( parentLevel > condition ) )
            {
                pruneBranch = true;
            }
            else if( ( pruneType == HTPR_SIZERATIO ) || ( pruneType == HTPR_JOINSIZE ) )
            {
                size_t biggerSize( 0 );
                std::vector< nodeID_t > kids( m_tree.getNode( parentID ).getChildren() );
                for( size_t i = 0; i < kids.size(); ++i )
                {
                    if( kids[i] == nodesIter->getFullID() )
                    {
                        continue;
                    }
                    size_t brotherSize( m_tree.getNode( kids[i] ).getSize() );
                    if( brotherSize > biggerSize )
                    {
                        biggerSize = brotherSize;
                    }
                }

                if( ( pruneType == HTPR_SIZERATIO ) && ( biggerSize > ( nodeSize * condition ) ) )
                {
                    pruneBranch = true;
                }

                if( ( pruneType == HTPR_JOINSIZE ) && ( biggerSize >=  condition ) )
                {
                    pruneBranch = true;
                }
            }
        }

        if( pruneBranch )
        {
            std::list< nodeID_t > worklist;
            worklist.push_back( nodesIter->getFullID() );
            while( !worklist.empty() )
            {
                WHnode* currentNode( m_tree.fetchNode( worklist.front() ) );
                worklist.pop_front();
                // if current node has already been pruned we continue with the next iteration
                if( currentNode->isFlagged() )
                {
                    continue;
                }
                currentNode->setFlag( true );
                std::vector< nodeID_t > currentKids( currentNode->getChildren() );
                worklist.insert( worklist.end(), currentKids.begin(), currentKids.end() );
            }
        }
    }

    // count total pruned leaves
    for( std::vector< WHnode >::iterator leavesIter( m_tree.m_leaves.begin() ); leavesIter != m_tree.m_leaves.end(); ++leavesIter )
    {
        if( leavesIter->isFlagged() )
        {
            ++prunedLeaves;
        }
    }

    // count total pruned nodes
    for( std::vector< WHnode >::iterator nodesIter( m_tree.m_nodes.begin() ); nodesIter != m_tree.m_nodes.end() - 1; ++nodesIter )
    {
        if( nodesIter->isFlagged() )
            ++prunedNodes;
    }

    if( pruneType == HTPR_SIZERATIO )
    {
        m_tree.m_treeName += ( "_prunedR" + string_utils::toString( safeSize ) + ":" + string_utils::toString( condition ) );
    }
    else if( pruneType == HTPR_JOINSIZE )
    {
        m_tree.m_treeName += ( "_prunedS" + string_utils::toString( condition ) + ":" + string_utils::toString( safeSize ) );
    }
    else if( pruneType == HTPR_JOINLEVEL )
    {
        m_tree.m_treeName += ( "_prunedL" + string_utils::toString( safeSize ) + ":" + string_utils::toString( condition ) );
    }

    std::pair< size_t, size_t > pruned( m_tree.cleanup() );

    pruned.second += m_tree.debinarize();

    return pruned;
} // end "pruneTree()" -----------------------------------------------------------------
コード例 #5
0
void CLWSamplingInfEngine::Estimate(CEvidence * pEstimate)
{
	if( pEstimate == NULL ) return;
	if( m_bNormalized == false ) NormalizeWeight();

	int i, j, k, offset;

	int  iNodes   = pEstimate->GetNumberObsNodes ();
	const int* obsNodes = pEstimate->GetAllObsNodes();
	const CNodeType *const* pNodeTypes = pEstimate->GetNodeTypes();
	
	int totalNodeSize =0;
	intVector nodeSize(iNodes);
	for( j = 0, totalNodeSize = 0; j < iNodes; j++)
	{
		nodeSize[j] = pNodeTypes[j]->GetNodeSize();
		totalNodeSize += nodeSize[j];
	}
	
	floatVector pFloatValue;
	pFloatValue.resize(totalNodeSize, 0);
		
	for( j = 0, offset = 0; j < iNodes; j++)
	{
		if( pNodeTypes[j]->IsDiscrete())  
		{
			for( i = 0; i < m_particleCount; i++)
			{
				Value* pValue = (m_currentEvVec[i])->GetValue(obsNodes[j]);

				// for discrete value type
				pFloatValue[offset + pValue->GetInt()] = pFloatValue[offset + pValue->GetInt()] + m_particleWeight[i];
			}
		}
		else
		{
			for( i = 0; i < m_particleCount; i++)
			{
				Value* pValue = (m_currentEvVec[i])->GetValue(obsNodes[j]);

				// for continuous value type
				for( k =0; k < nodeSize[j]; k++)
				{
					pFloatValue[offset + k] = pFloatValue[offset + k] + m_particleWeight[i] * (pValue+k)->GetFlt();
				}
			}
		}
		offset += nodeSize[j];
	}

	// set pFloatValue data to pEstimate
	for( j = 0, offset = 0; j < iNodes; j++)
	{
		Value* pValue = pEstimate->GetValue(obsNodes[j]);
		
		if( pNodeTypes[j]->IsDiscrete())  
		{
			float maxweight = -99; int itmax = 0;
			for( k =0; k < nodeSize[j]; k++)
			{
				if(maxweight < pFloatValue[offset + k])
				{
					maxweight = pFloatValue[offset + k];
					itmax = k;
				}
				pValue->SetInt(itmax);
			}
		}
		else
		{
			for( k =0; k < nodeSize[j]; k++)
				(pValue+k)->SetFlt( pFloatValue[offset + k] );
		}

		offset += nodeSize[j];
	}
}
コード例 #6
0
TER PathCursor::reverseLiquidityForAccount () const
{
    TER terResult = tesSUCCESS;
    auto const lastNodeIndex = nodeSize () - 1;
    auto const isFinalNode = (nodeIndex_ == lastNodeIndex);

    // 0 quality means none has yet been determined.
    std::uint64_t uRateMax = 0;

    // Current is allowed to redeem to next.
    const bool previousNodeIsAccount = !nodeIndex_ ||
            previousNode().isAccount();

    const bool nextNodeIsAccount = isFinalNode || nextNode().isAccount();

    AccountID const& previousAccountID = previousNodeIsAccount
        ? previousNode().account_ : node().account_;
    AccountID const& nextAccountID = nextNodeIsAccount ? nextNode().account_
        : node().account_;   // Offers are always issue.

    // This is the quality from from the previous node to this one.
    auto const qualityIn
         = (nodeIndex_ != 0)
            ? quality_in (view(),
                node().account_,
                previousAccountID,
                node().issue_.currency)
            : parityRate;

    // And this is the quality from the next one to this one.
    auto const qualityOut
        = (nodeIndex_ != lastNodeIndex)
            ? quality_out (view(),
                node().account_,
                nextAccountID,
                node().issue_.currency)
            : parityRate;

    // For previousNodeIsAccount:
    // Previous account is already owed.
    const STAmount saPrvOwed = (previousNodeIsAccount && nodeIndex_ != 0)
        ? creditBalance (view(),
            node().account_,
            previousAccountID,
            node().issue_.currency)
        : STAmount (node().issue_);

    // The limit amount that the previous account may owe.
    const STAmount saPrvLimit = (previousNodeIsAccount && nodeIndex_ != 0)
        ? creditLimit (view(),
            node().account_,
            previousAccountID,
            node().issue_.currency)
        : STAmount (node().issue_);

    // Next account is owed.
    const STAmount saNxtOwed = (nextNodeIsAccount && nodeIndex_ != lastNodeIndex)
        ? creditBalance (view(),
            node().account_,
            nextAccountID,
            node().issue_.currency)
        : STAmount (node().issue_);

    JLOG (j_.trace())
        << "reverseLiquidityForAccount>"
        << " nodeIndex_=" << nodeIndex_ << "/" << lastNodeIndex
        << " previousAccountID=" << previousAccountID
        << " node.account_=" << node().account_
        << " nextAccountID=" << nextAccountID
        << " currency=" << node().issue_.currency
        << " qualityIn=" << qualityIn
        << " qualityOut=" << qualityOut
        << " saPrvOwed=" << saPrvOwed
        << " saPrvLimit=" << saPrvLimit;

    // Requests are computed to be the maximum flow possible.
    // Previous can redeem the owed IOUs it holds.
    const STAmount saPrvRedeemReq  = (saPrvOwed > beast::zero)
        ? saPrvOwed
        : STAmount (saPrvOwed.issue ());

    // Previous can issue up to limit minus whatever portion of limit already
    // used (not including redeemable amount) - another "maximum flow".
    const STAmount saPrvIssueReq = (saPrvOwed < beast::zero)
        ? saPrvLimit + saPrvOwed : saPrvLimit;

    // Precompute these values in case we have an order book.
    auto deliverCurrency = previousNode().saRevDeliver.getCurrency ();
    const STAmount saPrvDeliverReq (
        {deliverCurrency, previousNode().saRevDeliver.getIssuer ()}, -1);
    // -1 means unlimited delivery.

    // Set to zero, because we're trying to hit the previous node.
    auto saCurRedeemAct = node().saRevRedeem.zeroed();

    // Track the amount we actually redeem.
    auto saCurIssueAct = node().saRevIssue.zeroed();

    // For !nextNodeIsAccount
    auto saCurDeliverAct  = node().saRevDeliver.zeroed();

    JLOG (j_.trace())
        << "reverseLiquidityForAccount:"
        << " saPrvRedeemReq:" << saPrvRedeemReq
        << " saPrvIssueReq:" << saPrvIssueReq
        << " previousNode.saRevDeliver:" << previousNode().saRevDeliver
        << " saPrvDeliverReq:" << saPrvDeliverReq
        << " node.saRevRedeem:" << node().saRevRedeem
        << " node.saRevIssue:" << node().saRevIssue
        << " saNxtOwed:" << saNxtOwed;

    // VFALCO-FIXME this generates errors
    //JLOG (j_.trace()) << pathState_.getJson ();

    // Current redeem req can't be more than IOUs on hand.
    assert (!node().saRevRedeem || -saNxtOwed >= node().saRevRedeem);
    assert (!node().saRevIssue  // If not issuing, fine.
            || saNxtOwed >= beast::zero
            // saNxtOwed >= 0: Sender not holding next IOUs, saNxtOwed < 0:
            // Sender holding next IOUs.
            || -saNxtOwed == node().saRevRedeem);
    // If issue req, then redeem req must consume all owed.

    if (nodeIndex_ == 0)
    {
        // ^ --> ACCOUNT -->  account|offer
        // Nothing to do, there is no previous to adjust.
        //
        // TODO(tom): we could have skipped all that setup and just left
        // or even just never call this whole routine on nodeIndex_ = 0!
    }

    // The next four cases correspond to the table at the bottom of this Wiki
    // page section: https://ripple.com/wiki/Transit_Fees#Implementation
    else if (previousNodeIsAccount && nextNodeIsAccount)
    {
        if (isFinalNode)
        {
            // account --> ACCOUNT --> $
            // Overall deliverable.
            const STAmount saCurWantedReq = std::min (
                pathState_.outReq() - pathState_.outAct(),
                saPrvLimit + saPrvOwed);
            auto saCurWantedAct = saCurWantedReq.zeroed ();

            JLOG (j_.trace())
                << "reverseLiquidityForAccount: account --> "
                << "ACCOUNT --> $ :"
                << " saCurWantedReq=" << saCurWantedReq;

            // Calculate redeem
            if (saPrvRedeemReq) // Previous has IOUs to redeem.
            {
                // Redeem your own IOUs at 1:1

                saCurWantedAct = std::min (saPrvRedeemReq, saCurWantedReq);
                previousNode().saRevRedeem = saCurWantedAct;

                uRateMax = STAmount::uRateOne;

                JLOG (j_.trace())
                    << "reverseLiquidityForAccount: Redeem at 1:1"
                    << " saPrvRedeemReq=" << saPrvRedeemReq
                    << " (available) previousNode.saRevRedeem="
                    << previousNode().saRevRedeem
                    << " uRateMax="
                    << amountFromQuality (uRateMax).getText ();
            }
            else
            {
                previousNode().saRevRedeem.clear (saPrvRedeemReq);
            }

            // Calculate issuing.
            previousNode().saRevIssue.clear (saPrvIssueReq);

            if (saCurWantedReq != saCurWantedAct // Need more.
                && saPrvIssueReq)  // Will accept IOUs from previous.
            {
                // Rate: quality in : 1.0

                // If we previously redeemed and this has a poorer rate, this
                // won't be included the current increment.
                rippleLiquidity (
                    rippleCalc_,
                    qualityIn,
                    parityRate,
                    saPrvIssueReq,
                    saCurWantedReq,
                    previousNode().saRevIssue,
                    saCurWantedAct,
                    uRateMax);

                JLOG (j_.trace())
                    << "reverseLiquidityForAccount: Issuing: Rate: "
                    << "quality in : 1.0"
                    << " previousNode.saRevIssue:" << previousNode().saRevIssue
                    << " saCurWantedAct:" << saCurWantedAct;
            }

            if (!saCurWantedAct)
            {
                // Must have processed something.
                terResult   = tecPATH_DRY;
            }
        }
        else
        {
            // Not final node.
            // account --> ACCOUNT --> account
            previousNode().saRevRedeem.clear (saPrvRedeemReq);
            previousNode().saRevIssue.clear (saPrvIssueReq);

            // redeem (part 1) -> redeem
            if (node().saRevRedeem
                // Next wants IOUs redeemed from current account.
                && saPrvRedeemReq)
                // Previous has IOUs to redeem to the current account.
            {
                // TODO(tom): add English.
                // Rate : 1.0 : quality out - we must accept our own IOUs
                // as 1:1.
                rippleLiquidity (
                    rippleCalc_,
                    parityRate,
                    qualityOut,
                    saPrvRedeemReq,
                    node().saRevRedeem,
                    previousNode().saRevRedeem,
                    saCurRedeemAct,
                    uRateMax);

                JLOG (j_.trace())
                    << "reverseLiquidityForAccount: "
                    << "Rate : 1.0 : quality out"
                    << " previousNode.saRevRedeem:" << previousNode().saRevRedeem
                    << " saCurRedeemAct:" << saCurRedeemAct;
            }

            // issue (part 1) -> redeem
            if (node().saRevRedeem != saCurRedeemAct
                // The current node has more IOUs to redeem.
                && previousNode().saRevRedeem == saPrvRedeemReq)
                // The previous node has no IOUs to redeem remaining, so issues.
            {
                // Rate: quality in : quality out
                rippleLiquidity (
                    rippleCalc_,
                    qualityIn,
                    qualityOut,
                    saPrvIssueReq,
                    node().saRevRedeem,
                    previousNode().saRevIssue,
                    saCurRedeemAct,
                    uRateMax);

                JLOG (j_.trace())
                    << "reverseLiquidityForAccount: "
                    << "Rate: quality in : quality out:"
                    << " previousNode.saRevIssue:" << previousNode().saRevIssue
                    << " saCurRedeemAct:" << saCurRedeemAct;
            }

            // redeem (part 2) -> issue.
            if (node().saRevIssue   // Next wants IOUs issued.
                // TODO(tom): this condition seems redundant.
                && saCurRedeemAct == node().saRevRedeem
                // Can only issue if completed redeeming.
                && previousNode().saRevRedeem != saPrvRedeemReq)
                // Did not complete redeeming previous IOUs.
            {
                // Rate : 1.0 : transfer_rate
                rippleLiquidity (
                    rippleCalc_,
                    parityRate,
                    transferRate (view(), node().account_),
                    saPrvRedeemReq,
                    node().saRevIssue,
                    previousNode().saRevRedeem,
                    saCurIssueAct,
                    uRateMax);

                JLOG (j_.debug())
                    << "reverseLiquidityForAccount: "
                    << "Rate : 1.0 : transfer_rate:"
                    << " previousNode.saRevRedeem:" << previousNode().saRevRedeem
                    << " saCurIssueAct:" << saCurIssueAct;
            }

            // issue (part 2) -> issue
            if (node().saRevIssue != saCurIssueAct
                // Need wants more IOUs issued.
                && saCurRedeemAct == node().saRevRedeem
                // Can only issue if completed redeeming.
                && saPrvRedeemReq == previousNode().saRevRedeem
                // Previously redeemed all owed IOUs.
                && saPrvIssueReq)
                // Previous can issue.
            {
                // Rate: quality in : 1.0
                rippleLiquidity (
                    rippleCalc_,
                    qualityIn,
                    parityRate,
                    saPrvIssueReq,
                    node().saRevIssue,
                    previousNode().saRevIssue,
                    saCurIssueAct,
                    uRateMax);

                JLOG (j_.trace())
                    << "reverseLiquidityForAccount: "
                    << "Rate: quality in : 1.0:"
                    << " previousNode.saRevIssue:" << previousNode().saRevIssue
                    << " saCurIssueAct:" << saCurIssueAct;
            }

            if (!saCurRedeemAct && !saCurIssueAct)
            {
                // Did not make progress.
                terResult = tecPATH_DRY;
            }

            JLOG (j_.trace())
                << "reverseLiquidityForAccount: "
                << "^|account --> ACCOUNT --> account :"
                << " node.saRevRedeem:" << node().saRevRedeem
                << " node.saRevIssue:" << node().saRevIssue
                << " saPrvOwed:" << saPrvOwed
                << " saCurRedeemAct:" << saCurRedeemAct
                << " saCurIssueAct:" << saCurIssueAct;
        }
    }
    else if (previousNodeIsAccount && !nextNodeIsAccount)
    {
        // account --> ACCOUNT --> offer
        // Note: deliver is always issue as ACCOUNT is the issuer for the offer
        // input.
        JLOG (j_.trace())
            << "reverseLiquidityForAccount: "
            << "account --> ACCOUNT --> offer";

        previousNode().saRevRedeem.clear (saPrvRedeemReq);
        previousNode().saRevIssue.clear (saPrvIssueReq);

        // We have three cases: the nxt offer can be owned by current account,
        // previous account or some third party account.
        //
        // Also, the current account may or may not have a redeemable balance
        // with the account for the next offer, so we don't yet know if we're
        // redeeming or issuing.
        //
        // TODO(tom): Make sure deliver was cleared, or check actual is zero.
        // redeem -> deliver/issue.
        if (saPrvOwed > beast::zero                    // Previous has IOUs to redeem.
            && node().saRevDeliver)                 // Need some issued.
        {
            // Rate : 1.0 : transfer_rate
            rippleLiquidity (
                rippleCalc_,
                parityRate,
                transferRate (view(), node().account_),
                saPrvRedeemReq,
                node().saRevDeliver,
                previousNode().saRevRedeem,
                saCurDeliverAct,
                uRateMax);
        }

        // issue -> deliver/issue
        if (saPrvRedeemReq == previousNode().saRevRedeem
            // Previously redeemed all owed.
            && node().saRevDeliver != saCurDeliverAct)  // Still need some issued.
        {
            // Rate: quality in : 1.0
            rippleLiquidity (
                rippleCalc_,
                qualityIn,
                parityRate,
                saPrvIssueReq,
                node().saRevDeliver,
                previousNode().saRevIssue,
                saCurDeliverAct,
                uRateMax);
        }

        if (!saCurDeliverAct)
        {
            // Must want something.
            terResult   = tecPATH_DRY;
        }

        JLOG (j_.trace())
            << "reverseLiquidityForAccount: "
            << " node.saRevDeliver:" << node().saRevDeliver
            << " saCurDeliverAct:" << saCurDeliverAct
            << " saPrvOwed:" << saPrvOwed;
    }
    else if (!previousNodeIsAccount && nextNodeIsAccount)
    {
        if (isFinalNode)
        {
            // offer --> ACCOUNT --> $
            // Previous is an offer, no limit: redeem own IOUs.
            //
            // This is the final node; we can't look to the right to get values;
            // we have to go up to get the out value for the entire path state.
            STAmount const& saCurWantedReq  =
                    pathState_.outReq() - pathState_.outAct();
            STAmount saCurWantedAct = saCurWantedReq.zeroed();

            JLOG (j_.trace())
                << "reverseLiquidityForAccount: "
                << "offer --> ACCOUNT --> $ :"
                << " saCurWantedReq:" << saCurWantedReq
                << " saOutAct:" << pathState_.outAct()
                << " saOutReq:" << pathState_.outReq();

            if (saCurWantedReq <= beast::zero)
            {
                assert(false);
                JLOG (j_.fatal()) << "CurWantReq was not positive";
                return tefEXCEPTION;
            }

            // The previous node is an offer; we are receiving our own currency.

            // The previous order book's entries might hold our issuances; might
            // not hold our issuances; might be our own offer.
            //
            // Assume the worst case, the case which costs the most to go
            // through, which is that it is not our own offer or our own
            // issuances.  Later on the forward pass we may be able to do
            // better.
            //
            // TODO: this comment applies generally to this section - move it up
            // to a document.

            // Rate: quality in : 1.0
            rippleLiquidity (
                rippleCalc_,
                qualityIn,
                parityRate,
                saPrvDeliverReq,
                saCurWantedReq,
                previousNode().saRevDeliver,
                saCurWantedAct,
                uRateMax);

            if (!saCurWantedAct)
            {
                // Must have processed something.
                terResult   = tecPATH_DRY;
            }

            JLOG (j_.trace())
                << "reverseLiquidityForAccount:"
                << " previousNode().saRevDeliver:" << previousNode().saRevDeliver
                << " saPrvDeliverReq:" << saPrvDeliverReq
                << " saCurWantedAct:" << saCurWantedAct
                << " saCurWantedReq:" << saCurWantedReq;
        }
        else
        {
            // offer --> ACCOUNT --> account
            // Note: offer is always delivering(redeeming) as account is issuer.
            JLOG (j_.trace())
                << "reverseLiquidityForAccount: "
                << "offer --> ACCOUNT --> account :"
                << " node.saRevRedeem:" << node().saRevRedeem
                << " node.saRevIssue:" << node().saRevIssue;

            // deliver -> redeem
            // TODO(tom): now we have more checking in nodeRipple, these checks
            // might be redundant.
            if (node().saRevRedeem)  // Next wants us to redeem.
            {
                // cur holds IOUs from the account to the right, the nxt
                // account.  If someone is making the current account get rid of
                // the nxt account's IOUs, then charge the input for quality
                // out.
                //
                // Rate : 1.0 : quality out
                rippleLiquidity (
                    rippleCalc_,
                    parityRate,
                    qualityOut,
                    saPrvDeliverReq,
                    node().saRevRedeem,
                    previousNode().saRevDeliver,
                    saCurRedeemAct,
                    uRateMax);
            }

            // deliver -> issue.
            if (node().saRevRedeem == saCurRedeemAct
                // Can only issue if previously redeemed all.
                && node().saRevIssue)
                // Need some issued.
            {
                // Rate : 1.0 : transfer_rate
                rippleLiquidity (
                    rippleCalc_,
                    parityRate,
                    transferRate (view(), node().account_),
                    saPrvDeliverReq,
                    node().saRevIssue,
                    previousNode().saRevDeliver,
                    saCurIssueAct,
                    uRateMax);
            }

            JLOG (j_.trace())
                << "reverseLiquidityForAccount:"
                << " saCurRedeemAct:" << saCurRedeemAct
                << " node.saRevRedeem:" << node().saRevRedeem
                << " previousNode.saRevDeliver:" << previousNode().saRevDeliver
                << " node.saRevIssue:" << node().saRevIssue;

            if (!previousNode().saRevDeliver)
            {
                // Must want something.
                terResult   = tecPATH_DRY;
            }
        }
    }
    else
    {
        // offer --> ACCOUNT --> offer
        // deliver/redeem -> deliver/issue.
        JLOG (j_.trace())
            << "reverseLiquidityForAccount: offer --> ACCOUNT --> offer";

        // Rate : 1.0 : transfer_rate
        rippleLiquidity (
            rippleCalc_,
            parityRate,
            transferRate (view(), node().account_),
            saPrvDeliverReq,
            node().saRevDeliver,
            previousNode().saRevDeliver,
            saCurDeliverAct,
            uRateMax);

        if (!saCurDeliverAct)
        {
            // Must want something.
            terResult   = tecPATH_DRY;
        }
    }

    return terResult;
}