<commit_before>#include <tuple>
#include "otc/otcli.h"
#include "otc/debug.h"
#include "otc/greedy_forest.h"
#include "otc/embedding.h"
#include "otc/embedded_tree.h"
using namespace otc;
std::unique_ptr<TreeMappedWithSplits> cloneTree(const TreeMappedWithSplits &);

template<typename T, typename U>
void updateAncestralPathOttIdSet(T * nd, const OttIdSet & oldEls, const OttIdSet newEls, std::map<const T *, NodeEmbedding<T, U> > & m);
template<typename T, typename U>
inline void updateAncestralPathOttIdSet(T * nd, const OttIdSet & oldEls, const OttIdSet newEls, std::map<const T *, NodeEmbedding<T, U> > & m) {
    for (auto anc : iter_anc(*nd)) {
         auto & ant = m.at(anc);
         ant.updateAllPathsOttIdSets(oldEls, newEls);
    }
}

//currently not copying names
std::unique_ptr<TreeMappedWithSplits> cloneTree(const TreeMappedWithSplits &tree) {
    TreeMappedWithSplits * rawTreePtr = new TreeMappedWithSplits();
    try {
        NodeWithSplits * newRoot = rawTreePtr->createRoot();
        auto r = tree.getRoot();
        assert(r->hasOttId());
        newRoot->setOttId(r->getOttId());
        std::map<const NodeWithSplits *, NodeWithSplits *> templateToNew;
        templateToNew[r]= newRoot;
        std::map<long, NodeWithSplits *> & newMap = rawTreePtr->getData().ottIdToNode;
        rawTreePtr->getData().desIdSetsContainInternals = tree.getData().desIdSetsContainInternals;
        for (auto nd : iter_pre_const(tree)) {
            auto p = nd->getParent();
            if (p == nullptr) {
                continue;
            }
            auto t2nIt = templateToNew.find(p);
            assert(t2nIt != templateToNew.end());
            auto ntp = t2nIt->second;
            auto nn = rawTreePtr->createChild(ntp);
            assert(templateToNew.find(nd) == templateToNew.end());
            templateToNew[nd] = nn;
            if (nd->hasOttId()) {
                nn->setOttId(nd->getOttId());
                newMap[nd->getOttId()] = nn;
            } else {
                assert(false);
            }
            nn->getData().desIds = nd->getData().desIds;
        }
    } catch (...) {
        delete rawTreePtr;
        throw;
    }
    return std::unique_ptr<TreeMappedWithSplits>(rawTreePtr);
}

class ScaffoldedSupertree
    : public TaxonomyDependentTreeProcessor<TreeMappedWithSplits>,
    public EmbeddedTree {
    public:
    int numErrors;
    OttIdSet tabooIds;
    std::map<std::unique_ptr<TreeMappedWithSplits>, std::size_t> inputTreesToIndex;
    std::vector<TreeMappedWithSplits *> treePtrByIndex;
    bool doReportAllContested;
    bool doConstructSupertree;
    std::list<long> idsListToReportOn;
    std::list<long> idListForDotExport;
    TreeMappedWithSplits * taxonomyAsSource;
    int currDotFileIndex;

    void resolveOrCollapse(NodeWithSplits * scaffoldNd, SupertreeContextWithSplits & sc) {
        auto & thr = taxoToEmbedding[scaffoldNd];
        if (thr.isContested()) {
            if (thr.highRankingTreesPreserveMonophyly(sc.numTrees)) {
                thr.resolveGivenContestedMonophyly(*scaffoldNd, sc);
            } else {
                thr.constructPhyloGraphAndCollapseIfNecessary(*scaffoldNd, sc);
            }
        } else {
            thr.resolveGivenUncontestedMonophyly(*scaffoldNd, sc);
        }
    }
    void constructSupertree() {
        const auto numTrees = treePtrByIndex.size();
        TreeMappedWithSplits * tax = taxonomy.get();
        SupertreeContextWithSplits sc{numTrees, taxoToEmbedding, *tax};
        writeNumberedDot(taxonomy->getRoot(), true, false);
        writeNumberedDot(taxonomy->getRoot(), true, true);
        LOG(DEBUG) << "Before supertree "; writeTreeAsNewick(std::cerr, *taxonomy); std::cerr << '\n';
        for (auto nd : iter_post_internal(*taxonomy)) {
            writeNumberedDot(nd, false, false);
            writeNumberedDot(nd, false, true);
            if (nd == taxonomy->getRoot()) ///TEMP!!!!
                resolveOrCollapse(nd, sc);
            LOG(DEBUG) << "After handling " << nd->getOttId(); writeTreeAsNewick(std::cerr, *taxonomy); std::cerr << '\n';
        }

    }

    void writeNumberedDot(NodeWithSplits * nd, bool entireSubtree, bool includeLastTree) {
        std::string fn = "ScaffSuperTree" + std::to_string(currDotFileIndex++) + ".dot";
        LOG(DEBUG) << "writing DOT file \"" << fn << "\"";
        std::ofstream out;
        out.open(fn);
        try {
            const auto & thr = taxoToEmbedding[nd];
            writeDOTExport(out, thr, nd, treePtrByIndex, entireSubtree, includeLastTree);
        } catch (...) {
            out.close();
            throw;
        }
        LOG(DEBUG) << "finished DOT file \"" << fn << "\"";
    }

    virtual ~ScaffoldedSupertree(){}
    ScaffoldedSupertree()
        :TaxonomyDependentTreeProcessor<TreeMappedWithSplits>(),
         numErrors(0),
         doReportAllContested(false),
         doConstructSupertree(false),
         taxonomyAsSource(nullptr),
         currDotFileIndex(0) {
    }

    void reportAllConflicting(std::ostream & out, bool verbose) {
        std::map<std::size_t, unsigned long> nodeMappingDegree;
        std::map<std::size_t, unsigned long> passThroughDegree;
        std::map<std::size_t, unsigned long> loopDegree;
        unsigned long totalContested = 0;
        unsigned long redundContested = 0;
        unsigned long totalNumNodes = 0;
        for (auto nd : iter_node_internal(*taxonomy)) {
            const auto & thr = taxoToEmbedding[nd];
            nodeMappingDegree[thr.getTotalNumNodeMappings()] += 1;
            passThroughDegree[thr.getTotalNumEdgeBelowTraversals()] += 1;
            loopDegree[thr.getTotalNumLoops()] += 1;
            totalNumNodes += 1;
            std::vector<NodeWithSplits *> aliasedBy = getNodesAliasedBy(nd, *taxonomy);
            if (thr.reportIfContested(out, nd, treePtrByIndex, aliasedBy, verbose)) {
                totalContested += 1;
                if (nd->getOutDegree() == 1) {
                    redundContested += 1;
                }
            }
        }
        unsigned long m = std::max(loopDegree.rbegin()->first, passThroughDegree.rbegin()->first);
        m = std::max(m, nodeMappingDegree.rbegin()->first);
        out << "Degree\tNodeMaps\tEdgeMaps\tLoops\n";
        for (unsigned long i = 0 ; i <= m; ++i) {
            out << i << '\t' << nodeMappingDegree[i]<< '\t' << passThroughDegree[i] << '\t' << loopDegree[i]<< '\n';
        }
        out << totalNumNodes << " internals\n" << totalContested << " contested\n" << (totalNumNodes - totalContested) << " uncontested\n";
        out << redundContested << " monotypic contested\n";
    }

    bool summarize(const OTCLI &otCLI) override {
        if (doConstructSupertree) {
            cloneTaxonomyAsASourceTree();
            constructSupertree();
            writeTreeAsNewick(otCLI.out, *taxonomy);
            otCLI.out << '\n';
        }
        std::ostream & out{otCLI.out};
        assert (taxonomy != nullptr);
        if (doReportAllContested) {
            reportAllConflicting(out, otCLI.verbose);
        } else {
            for (auto tr : idsListToReportOn) {
                auto nd = taxonomy->getData().getNodeForOttId(tr);
                if (nd == nullptr) {
                    throw OTCError(std::string("Unrecognized OTT ID in list of OTT IDs to report on: ") + std::to_string(tr));
                }
                const auto & thr = taxoToEmbedding[nd];
                std::vector<NodeWithSplits *> aliasedBy = getNodesAliasedBy(nd, *taxonomy);
                thr.reportIfContested(out, nd, treePtrByIndex, aliasedBy, otCLI.verbose);
            }
        }
        for (auto tr : idListForDotExport) {
            auto nd = taxonomy->getData().getNodeForOttId(tr);
            if (nd == nullptr) {
                throw OTCError(std::string("Unrecognized OTT ID in list of OTT IDs to export to DOT: ") + std::to_string(tr));
            }
            for (auto n : iter_pre_n_const(nd)) {
                const auto & thr = taxoToEmbedding[n];
                writeDOTExport(out, thr, n, treePtrByIndex, false, false);
            }
        }
        return true;
    }

    bool processTaxonomyTree(OTCLI & otCLI) override {
        TaxonomyDependentTreeProcessor<TreeMappedWithSplits>::processTaxonomyTree(otCLI);
        checkTreeInvariants(*taxonomy);
        suppressMonotypicTaxaPreserveDeepestDangle(*taxonomy);
        checkTreeInvariants(*taxonomy);
        for (auto nd : iter_node(*taxonomy)) {
            taxoToEmbedding.emplace(nd, NodeEmbeddingWithSplits{});
        }
        return true;
    }

    bool processSourceTree(OTCLI & otCLI, std::unique_ptr<TreeMappedWithSplits> treeup) override {
        assert(treeup != nullptr);
        assert(taxonomy != nullptr);
        // Store the tree pointer with a map to its index, and an alias for fast index->tree.
        std::size_t treeIndex = inputTreesToIndex.size();
        assert(treeIndex == treePtrByIndex.size());
        TreeMappedWithSplits * raw = treeup.get();
        inputTreesToIndex[std::move(treeup)] = treeIndex;
        treePtrByIndex.push_back(raw);
        // Store the tree's filename
        raw->setName(otCLI.currentFilename);
        embedNewTree(*taxonomy, *raw, treeIndex);
        otCLI.out << "# pathPairings = " << pathPairings.size() << '\n';
        return true;
    }

    bool cloneTaxonomyAsASourceTree() {
        assert(taxonomy != nullptr);
        assert(taxonomyAsSource == nullptr);
        std::unique_ptr<TreeMappedWithSplits> tree = std::move(cloneTree(*taxonomy));
        taxonomyAsSource = tree.get();
        std::size_t treeIndex = inputTreesToIndex.size();
        TreeMappedWithSplits * raw = tree.get();
        inputTreesToIndex[std::move(tree)] = treeIndex;
        treePtrByIndex.push_back(taxonomyAsSource);
        // Store the tree's filename
        raw->setName("TAXONOMY");
        threadTaxonomyClone(*taxonomy, *taxonomyAsSource, treeIndex);
        return true;
    }
};

bool handleReportAllFlag(OTCLI & otCLI, const std::string &);
bool handleReportOnNodesFlag(OTCLI & otCLI, const std::string &);
bool handleDotNodesFlag(OTCLI & otCLI, const std::string &narg);
bool handleSuperTreeFlag(OTCLI & otCLI, const std::string &narg);

bool handleReportAllFlag(OTCLI & otCLI, const std::string &) {
    ScaffoldedSupertree * proc = static_cast<ScaffoldedSupertree *>(otCLI.blob);
    assert(proc != nullptr);
    proc->doReportAllContested = true;
    return true;
}
bool handleSuperTreeFlag(OTCLI & otCLI, const std::string &) {
    ScaffoldedSupertree * proc = static_cast<ScaffoldedSupertree *>(otCLI.blob);
    assert(proc != nullptr);
    proc->doConstructSupertree = true;
    return true;
}

bool handleReportOnNodesFlag(OTCLI & otCLI, const std::string &narg) {
    ScaffoldedSupertree * proc = static_cast<ScaffoldedSupertree *>(otCLI.blob);
    assert(proc != nullptr);
    if (narg.empty()) {
        throw OTCError("Expecting a list of IDs after the -b argument.");
    }
    auto rs = split_string(narg, ',');
    for (auto word : rs) {
        auto ottId = ottIDFromName(word);
        if (ottId < 0) {
            throw OTCError(std::string("Expecting a list of IDs after the -b argument. Offending word: ") + word);
        }
        proc->idsListToReportOn.push_back(ottId);
    }
    return true;
}

bool handleDotNodesFlag(OTCLI & otCLI, const std::string &narg) {
    ScaffoldedSupertree * proc = static_cast<ScaffoldedSupertree *>(otCLI.blob);
    assert(proc != nullptr);
    if (narg.empty()) {
        throw OTCError("Expecting a list of IDs after the -d argument.");
    }
    auto rs = split_string(narg, ',');
    for (auto word : rs) {
        auto ottId = ottIDFromName(word);
        if (ottId < 0) {
            throw OTCError(std::string("Expecting a list of IDs after the -d argument. Offending word: ") + word);
        }
        proc->idListForDotExport.push_back(ottId);
    }
    return true;
}

int main(int argc, char *argv[]) {
    OTCLI otCLI("otcscaffoldedsupertree",
                "takes at least 2 newick file paths: a full taxonomy tree, and some number of input trees. Crashes or emits bogus output.",
                "taxonomy.tre inp1.tre inp2.tre");
    ScaffoldedSupertree proc;
    otCLI.addFlag('a',
                  "Write a report of all contested nodes",
                  handleReportAllFlag,
                  false);
    otCLI.addFlag('s',
                  "Compute a supertree",
                  handleSuperTreeFlag,
                  false);
    otCLI.addFlag('b',
                  "IDLIST should be a list of OTT IDs. A status report will be generated for those nodes",
                  handleReportOnNodesFlag,
                  true);
    otCLI.addFlag('d',
                  "IDLIST should be a list of OTT IDs. A DOT file of the nodes will be generated ",
                  handleDotNodesFlag,
                  true);
    return taxDependentTreeProcessingMain(otCLI, argc, argv, proc, 2, true);
}

<commit_msg>using the pretty graphs to debug means we can do the resolve step for every node<commit_after>#include <tuple>
#include "otc/otcli.h"
#include "otc/debug.h"
#include "otc/greedy_forest.h"
#include "otc/embedding.h"
#include "otc/embedded_tree.h"
using namespace otc;
std::unique_ptr<TreeMappedWithSplits> cloneTree(const TreeMappedWithSplits &);

template<typename T, typename U>
void updateAncestralPathOttIdSet(T * nd, const OttIdSet & oldEls, const OttIdSet newEls, std::map<const T *, NodeEmbedding<T, U> > & m);
template<typename T, typename U>
inline void updateAncestralPathOttIdSet(T * nd, const OttIdSet & oldEls, const OttIdSet newEls, std::map<const T *, NodeEmbedding<T, U> > & m) {
    for (auto anc : iter_anc(*nd)) {
         auto & ant = m.at(anc);
         ant.updateAllPathsOttIdSets(oldEls, newEls);
    }
}

//currently not copying names
std::unique_ptr<TreeMappedWithSplits> cloneTree(const TreeMappedWithSplits &tree) {
    TreeMappedWithSplits * rawTreePtr = new TreeMappedWithSplits();
    try {
        NodeWithSplits * newRoot = rawTreePtr->createRoot();
        auto r = tree.getRoot();
        assert(r->hasOttId());
        newRoot->setOttId(r->getOttId());
        std::map<const NodeWithSplits *, NodeWithSplits *> templateToNew;
        templateToNew[r]= newRoot;
        std::map<long, NodeWithSplits *> & newMap = rawTreePtr->getData().ottIdToNode;
        rawTreePtr->getData().desIdSetsContainInternals = tree.getData().desIdSetsContainInternals;
        for (auto nd : iter_pre_const(tree)) {
            auto p = nd->getParent();
            if (p == nullptr) {
                continue;
            }
            auto t2nIt = templateToNew.find(p);
            assert(t2nIt != templateToNew.end());
            auto ntp = t2nIt->second;
            auto nn = rawTreePtr->createChild(ntp);
            assert(templateToNew.find(nd) == templateToNew.end());
            templateToNew[nd] = nn;
            if (nd->hasOttId()) {
                nn->setOttId(nd->getOttId());
                newMap[nd->getOttId()] = nn;
            } else {
                assert(false);
            }
            nn->getData().desIds = nd->getData().desIds;
        }
    } catch (...) {
        delete rawTreePtr;
        throw;
    }
    return std::unique_ptr<TreeMappedWithSplits>(rawTreePtr);
}

class ScaffoldedSupertree
    : public TaxonomyDependentTreeProcessor<TreeMappedWithSplits>,
    public EmbeddedTree {
    public:
    int numErrors;
    OttIdSet tabooIds;
    std::map<std::unique_ptr<TreeMappedWithSplits>, std::size_t> inputTreesToIndex;
    std::vector<TreeMappedWithSplits *> treePtrByIndex;
    bool doReportAllContested;
    bool doConstructSupertree;
    std::list<long> idsListToReportOn;
    std::list<long> idListForDotExport;
    TreeMappedWithSplits * taxonomyAsSource;
    int currDotFileIndex;

    void resolveOrCollapse(NodeWithSplits * scaffoldNd, SupertreeContextWithSplits & sc) {
        auto & thr = taxoToEmbedding[scaffoldNd];
        if (thr.isContested()) {
            if (thr.highRankingTreesPreserveMonophyly(sc.numTrees)) {
                thr.resolveGivenContestedMonophyly(*scaffoldNd, sc);
            } else {
                thr.constructPhyloGraphAndCollapseIfNecessary(*scaffoldNd, sc);
            }
        } else {
            thr.resolveGivenUncontestedMonophyly(*scaffoldNd, sc);
        }
    }
    void constructSupertree() {
        const auto numTrees = treePtrByIndex.size();
        TreeMappedWithSplits * tax = taxonomy.get();
        SupertreeContextWithSplits sc{numTrees, taxoToEmbedding, *tax};
        writeNumberedDot(taxonomy->getRoot(), true, false);
        writeNumberedDot(taxonomy->getRoot(), true, true);
        LOG(DEBUG) << "Before supertree "; writeTreeAsNewick(std::cerr, *taxonomy); std::cerr << '\n';
        for (auto nd : iter_post_internal(*taxonomy)) {
            writeNumberedDot(nd, false, false);
            writeNumberedDot(nd, false, true);
            resolveOrCollapse(nd, sc);
            LOG(DEBUG) << "After handling " << nd->getOttId(); writeTreeAsNewick(std::cerr, *taxonomy); std::cerr << '\n';
            writeNumberedDot(taxonomy->getRoot(), true, false);
            writeNumberedDot(taxonomy->getRoot(), true, true);

        }

    }

    void writeNumberedDot(NodeWithSplits * nd, bool entireSubtree, bool includeLastTree) {
        std::string fn = "ScaffSuperTree" + std::to_string(currDotFileIndex++) + ".dot";
        LOG(DEBUG) << "writing DOT file \"" << fn << "\"";
        std::ofstream out;
        out.open(fn);
        try {
            const auto & thr = taxoToEmbedding[nd];
            writeDOTExport(out, thr, nd, treePtrByIndex, entireSubtree, includeLastTree);
        } catch (...) {
            out.close();
            throw;
        }
        LOG(DEBUG) << "finished DOT file \"" << fn << "\"";
    }

    virtual ~ScaffoldedSupertree(){}
    ScaffoldedSupertree()
        :TaxonomyDependentTreeProcessor<TreeMappedWithSplits>(),
         numErrors(0),
         doReportAllContested(false),
         doConstructSupertree(false),
         taxonomyAsSource(nullptr),
         currDotFileIndex(0) {
    }

    void reportAllConflicting(std::ostream & out, bool verbose) {
        std::map<std::size_t, unsigned long> nodeMappingDegree;
        std::map<std::size_t, unsigned long> passThroughDegree;
        std::map<std::size_t, unsigned long> loopDegree;
        unsigned long totalContested = 0;
        unsigned long redundContested = 0;
        unsigned long totalNumNodes = 0;
        for (auto nd : iter_node_internal(*taxonomy)) {
            const auto & thr = taxoToEmbedding[nd];
            nodeMappingDegree[thr.getTotalNumNodeMappings()] += 1;
            passThroughDegree[thr.getTotalNumEdgeBelowTraversals()] += 1;
            loopDegree[thr.getTotalNumLoops()] += 1;
            totalNumNodes += 1;
            std::vector<NodeWithSplits *> aliasedBy = getNodesAliasedBy(nd, *taxonomy);
            if (thr.reportIfContested(out, nd, treePtrByIndex, aliasedBy, verbose)) {
                totalContested += 1;
                if (nd->getOutDegree() == 1) {
                    redundContested += 1;
                }
            }
        }
        unsigned long m = std::max(loopDegree.rbegin()->first, passThroughDegree.rbegin()->first);
        m = std::max(m, nodeMappingDegree.rbegin()->first);
        out << "Degree\tNodeMaps\tEdgeMaps\tLoops\n";
        for (unsigned long i = 0 ; i <= m; ++i) {
            out << i << '\t' << nodeMappingDegree[i]<< '\t' << passThroughDegree[i] << '\t' << loopDegree[i]<< '\n';
        }
        out << totalNumNodes << " internals\n" << totalContested << " contested\n" << (totalNumNodes - totalContested) << " uncontested\n";
        out << redundContested << " monotypic contested\n";
    }

    bool summarize(const OTCLI &otCLI) override {
        if (doConstructSupertree) {
            cloneTaxonomyAsASourceTree();
            constructSupertree();
            writeTreeAsNewick(otCLI.out, *taxonomy);
            otCLI.out << '\n';
        }
        std::ostream & out{otCLI.out};
        assert (taxonomy != nullptr);
        if (doReportAllContested) {
            reportAllConflicting(out, otCLI.verbose);
        } else {
            for (auto tr : idsListToReportOn) {
                auto nd = taxonomy->getData().getNodeForOttId(tr);
                if (nd == nullptr) {
                    throw OTCError(std::string("Unrecognized OTT ID in list of OTT IDs to report on: ") + std::to_string(tr));
                }
                const auto & thr = taxoToEmbedding[nd];
                std::vector<NodeWithSplits *> aliasedBy = getNodesAliasedBy(nd, *taxonomy);
                thr.reportIfContested(out, nd, treePtrByIndex, aliasedBy, otCLI.verbose);
            }
        }
        for (auto tr : idListForDotExport) {
            auto nd = taxonomy->getData().getNodeForOttId(tr);
            if (nd == nullptr) {
                throw OTCError(std::string("Unrecognized OTT ID in list of OTT IDs to export to DOT: ") + std::to_string(tr));
            }
            for (auto n : iter_pre_n_const(nd)) {
                const auto & thr = taxoToEmbedding[n];
                writeDOTExport(out, thr, n, treePtrByIndex, false, false);
            }
        }
        return true;
    }

    bool processTaxonomyTree(OTCLI & otCLI) override {
        TaxonomyDependentTreeProcessor<TreeMappedWithSplits>::processTaxonomyTree(otCLI);
        checkTreeInvariants(*taxonomy);
        suppressMonotypicTaxaPreserveDeepestDangle(*taxonomy);
        checkTreeInvariants(*taxonomy);
        for (auto nd : iter_node(*taxonomy)) {
            taxoToEmbedding.emplace(nd, NodeEmbeddingWithSplits{});
        }
        return true;
    }

    bool processSourceTree(OTCLI & otCLI, std::unique_ptr<TreeMappedWithSplits> treeup) override {
        assert(treeup != nullptr);
        assert(taxonomy != nullptr);
        // Store the tree pointer with a map to its index, and an alias for fast index->tree.
        std::size_t treeIndex = inputTreesToIndex.size();
        assert(treeIndex == treePtrByIndex.size());
        TreeMappedWithSplits * raw = treeup.get();
        inputTreesToIndex[std::move(treeup)] = treeIndex;
        treePtrByIndex.push_back(raw);
        // Store the tree's filename
        raw->setName(otCLI.currentFilename);
        embedNewTree(*taxonomy, *raw, treeIndex);
        otCLI.out << "# pathPairings = " << pathPairings.size() << '\n';
        return true;
    }

    bool cloneTaxonomyAsASourceTree() {
        assert(taxonomy != nullptr);
        assert(taxonomyAsSource == nullptr);
        std::unique_ptr<TreeMappedWithSplits> tree = std::move(cloneTree(*taxonomy));
        taxonomyAsSource = tree.get();
        std::size_t treeIndex = inputTreesToIndex.size();
        TreeMappedWithSplits * raw = tree.get();
        inputTreesToIndex[std::move(tree)] = treeIndex;
        treePtrByIndex.push_back(taxonomyAsSource);
        // Store the tree's filename
        raw->setName("TAXONOMY");
        threadTaxonomyClone(*taxonomy, *taxonomyAsSource, treeIndex);
        return true;
    }
};

bool handleReportAllFlag(OTCLI & otCLI, const std::string &);
bool handleReportOnNodesFlag(OTCLI & otCLI, const std::string &);
bool handleDotNodesFlag(OTCLI & otCLI, const std::string &narg);
bool handleSuperTreeFlag(OTCLI & otCLI, const std::string &narg);

bool handleReportAllFlag(OTCLI & otCLI, const std::string &) {
    ScaffoldedSupertree * proc = static_cast<ScaffoldedSupertree *>(otCLI.blob);
    assert(proc != nullptr);
    proc->doReportAllContested = true;
    return true;
}
bool handleSuperTreeFlag(OTCLI & otCLI, const std::string &) {
    ScaffoldedSupertree * proc = static_cast<ScaffoldedSupertree *>(otCLI.blob);
    assert(proc != nullptr);
    proc->doConstructSupertree = true;
    return true;
}

bool handleReportOnNodesFlag(OTCLI & otCLI, const std::string &narg) {
    ScaffoldedSupertree * proc = static_cast<ScaffoldedSupertree *>(otCLI.blob);
    assert(proc != nullptr);
    if (narg.empty()) {
        throw OTCError("Expecting a list of IDs after the -b argument.");
    }
    auto rs = split_string(narg, ',');
    for (auto word : rs) {
        auto ottId = ottIDFromName(word);
        if (ottId < 0) {
            throw OTCError(std::string("Expecting a list of IDs after the -b argument. Offending word: ") + word);
        }
        proc->idsListToReportOn.push_back(ottId);
    }
    return true;
}

bool handleDotNodesFlag(OTCLI & otCLI, const std::string &narg) {
    ScaffoldedSupertree * proc = static_cast<ScaffoldedSupertree *>(otCLI.blob);
    assert(proc != nullptr);
    if (narg.empty()) {
        throw OTCError("Expecting a list of IDs after the -d argument.");
    }
    auto rs = split_string(narg, ',');
    for (auto word : rs) {
        auto ottId = ottIDFromName(word);
        if (ottId < 0) {
            throw OTCError(std::string("Expecting a list of IDs after the -d argument. Offending word: ") + word);
        }
        proc->idListForDotExport.push_back(ottId);
    }
    return true;
}

int main(int argc, char *argv[]) {
    OTCLI otCLI("otcscaffoldedsupertree",
                "takes at least 2 newick file paths: a full taxonomy tree, and some number of input trees. Crashes or emits bogus output.",
                "taxonomy.tre inp1.tre inp2.tre");
    ScaffoldedSupertree proc;
    otCLI.addFlag('a',
                  "Write a report of all contested nodes",
                  handleReportAllFlag,
                  false);
    otCLI.addFlag('s',
                  "Compute a supertree",
                  handleSuperTreeFlag,
                  false);
    otCLI.addFlag('b',
                  "IDLIST should be a list of OTT IDs. A status report will be generated for those nodes",
                  handleReportOnNodesFlag,
                  true);
    otCLI.addFlag('d',
                  "IDLIST should be a list of OTT IDs. A DOT file of the nodes will be generated ",
                  handleDotNodesFlag,
                  true);
    return taxDependentTreeProcessingMain(otCLI, argc, argv, proc, 2, true);
}

<|endoftext|>


<commit_before>//===--- BracesAroundStatementsCheck.cpp - clang-tidy ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "BracesAroundStatementsCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Lex/Lexer.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace readability {
namespace {

tok::TokenKind getTokenKind(SourceLocation Loc, const SourceManager &SM,
                            const ASTContext *Context) {
  Token Tok;
  SourceLocation Beginning =
      Lexer::GetBeginningOfToken(Loc, SM, Context->getLangOpts());
  const bool Invalid =
      Lexer::getRawToken(Beginning, Tok, SM, Context->getLangOpts());
  assert(!Invalid && "Expected a valid token.");

  if (Invalid)
    return tok::NUM_TOKENS;

  return Tok.getKind();
}

SourceLocation forwardSkipWhitespaceAndComments(SourceLocation Loc,
                                                const SourceManager &SM,
                                                const ASTContext *Context) {
  assert(Loc.isValid());
  for (;;) {
    while (isWhitespace(*FullSourceLoc(Loc, SM).getCharacterData()))
      Loc = Loc.getLocWithOffset(1);

    tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
    if (TokKind == tok::NUM_TOKENS || TokKind != tok::comment)
      return Loc;

    // Fast-forward current token.
    Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
  }
}

SourceLocation findEndLocation(SourceLocation LastTokenLoc,
                               const SourceManager &SM,
                               const ASTContext *Context) {
  SourceLocation Loc = LastTokenLoc;
  // Loc points to the beginning of the last (non-comment non-ws) token
  // before end or ';'.
  assert(Loc.isValid());
  bool SkipEndWhitespaceAndComments = true;
  tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
  if (TokKind == tok::NUM_TOKENS || TokKind == tok::semi ||
      TokKind == tok::r_brace) {
    // If we are at ";" or "}", we found the last token. We could use as well
    // `if (isa<NullStmt>(S))`, but it wouldn't work for nested statements.
    SkipEndWhitespaceAndComments = false;
  }

  Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
  // Loc points past the last token before end or after ';'.

  if (SkipEndWhitespaceAndComments) {
    Loc = forwardSkipWhitespaceAndComments(Loc, SM, Context);
    tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
    if (TokKind == tok::semi)
      Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
  }

  for (;;) {
    assert(Loc.isValid());
    while (isHorizontalWhitespace(*FullSourceLoc(Loc, SM).getCharacterData()))
      Loc = Loc.getLocWithOffset(1);

    if (isVerticalWhitespace(*FullSourceLoc(Loc, SM).getCharacterData())) {
      // EOL, insert brace before.
      break;
    }
    tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
    if (TokKind != tok::comment) {
      // Non-comment token, insert brace before.
      break;
    }

    SourceLocation TokEndLoc =
        Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
    SourceRange TokRange(Loc, TokEndLoc);
    StringRef Comment = Lexer::getSourceText(
        CharSourceRange::getTokenRange(TokRange), SM, Context->getLangOpts());
    if (Comment.startswith("/*") && Comment.find('\n') != StringRef::npos) {
      // Multi-line block comment, insert brace before.
      break;
    }
    // else: Trailing comment, insert brace after the newline.

    // Fast-forward current token.
    Loc = TokEndLoc;
  }
  return Loc;
}

} // namespace

BracesAroundStatementsCheck::BracesAroundStatementsCheck(
    StringRef Name, ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context),
      // Always add braces by default.
      ShortStatementLines(Options.get("ShortStatementLines", 0U)) {}

void
BracesAroundStatementsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
  Options.store(Opts, "ShortStatementLines", ShortStatementLines);
}

void BracesAroundStatementsCheck::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(ifStmt().bind("if"), this);
  Finder->addMatcher(whileStmt().bind("while"), this);
  Finder->addMatcher(doStmt().bind("do"), this);
  Finder->addMatcher(forStmt().bind("for"), this);
  Finder->addMatcher(cxxForRangeStmt().bind("for-range"), this);
}

void
BracesAroundStatementsCheck::check(const MatchFinder::MatchResult &Result) {
  const SourceManager &SM = *Result.SourceManager;
  const ASTContext *Context = Result.Context;

  // Get location of closing parenthesis or 'do' to insert opening brace.
  if (auto S = Result.Nodes.getNodeAs<ForStmt>("for")) {
    checkStmt(Result, S->getBody(), S->getRParenLoc());
  } else if (auto S = Result.Nodes.getNodeAs<CXXForRangeStmt>("for-range")) {
    checkStmt(Result, S->getBody(), S->getRParenLoc());
  } else if (auto S = Result.Nodes.getNodeAs<DoStmt>("do")) {
    checkStmt(Result, S->getBody(), S->getDoLoc(), S->getWhileLoc());
  } else if (auto S = Result.Nodes.getNodeAs<WhileStmt>("while")) {
    SourceLocation StartLoc = findRParenLoc(S, SM, Context);
    if (StartLoc.isInvalid())
      return;
    checkStmt(Result, S->getBody(), StartLoc);
  } else if (auto S = Result.Nodes.getNodeAs<IfStmt>("if")) {
    SourceLocation StartLoc = findRParenLoc(S, SM, Context);
    if (StartLoc.isInvalid())
      return;
    if (ForceBracesStmts.erase(S))
      ForceBracesStmts.insert(S->getThen());
    bool BracedIf = checkStmt(Result, S->getThen(), StartLoc, S->getElseLoc());
    const Stmt *Else = S->getElse();
    if (Else && BracedIf)
      ForceBracesStmts.insert(Else);
    if (Else && !isa<IfStmt>(Else)) {
      // Omit 'else if' statements here, they will be handled directly.
      checkStmt(Result, Else, S->getElseLoc(), SourceLocation());
    }
  } else {
    llvm_unreachable("Invalid match");
  }
}

/// Find location of right parenthesis closing condition
template <typename IfOrWhileStmt>
SourceLocation
BracesAroundStatementsCheck::findRParenLoc(const IfOrWhileStmt *S,
                                           const SourceManager &SM,
                                           const ASTContext *Context) {
  // Skip macros.
  if (S->getLocStart().isMacroID())
    return SourceLocation();

  static const char *const ErrorMessage =
      "cannot find location of closing parenthesis ')'";
  SourceLocation CondEndLoc = S->getCond()->getLocEnd();
  if (const DeclStmt *CondVar = S->getConditionVariableDeclStmt())
    CondEndLoc = CondVar->getLocEnd();

  assert(CondEndLoc.isValid());
  SourceLocation PastCondEndLoc =
      Lexer::getLocForEndOfToken(CondEndLoc, 0, SM, Context->getLangOpts());
  if (PastCondEndLoc.isInvalid()) {
    diag(CondEndLoc, ErrorMessage);
    return SourceLocation();
  }
  SourceLocation RParenLoc =
      forwardSkipWhitespaceAndComments(PastCondEndLoc, SM, Context);
  if (RParenLoc.isInvalid()) {
    diag(PastCondEndLoc, ErrorMessage);
    return SourceLocation();
  }
  tok::TokenKind TokKind = getTokenKind(RParenLoc, SM, Context);
  if (TokKind != tok::r_paren) {
    diag(RParenLoc, ErrorMessage);
    return SourceLocation();
  }
  return RParenLoc;
}

/// Determine if the statement needs braces around it, and add them if it does.
/// Returns true if braces where added.
bool BracesAroundStatementsCheck::checkStmt(
    const MatchFinder::MatchResult &Result, const Stmt *S,
    SourceLocation InitialLoc, SourceLocation EndLocHint) {
  // 1) If there's a corresponding "else" or "while", the check inserts "} "
  // right before that token.
  // 2) If there's a multi-line block comment starting on the same line after
  // the location we're inserting the closing brace at, or there's a non-comment
  // token, the check inserts "\n}" right before that token.
  // 3) Otherwise the check finds the end of line (possibly after some block or
  // line comments) and inserts "\n}" right before that EOL.
  if (!S || isa<CompoundStmt>(S)) {
    // Already inside braces.
    return false;
  }

  const SourceManager &SM = *Result.SourceManager;
  const ASTContext *Context = Result.Context;

  // Treat macros.
  CharSourceRange FileRange = Lexer::makeFileCharRange(
      CharSourceRange::getTokenRange(S->getSourceRange()), SM,
      Context->getLangOpts());
  if (FileRange.isInvalid())
    return false;

  // InitialLoc points at the last token before opening brace to be inserted.
  assert(InitialLoc.isValid());
  // Convert InitialLoc to file location, if it's on the same macro expansion
  // level as the start of the statement. We also need file locations for
  // Lexer::getLocForEndOfToken working properly.
  InitialLoc = Lexer::makeFileCharRange(
                   CharSourceRange::getCharRange(InitialLoc, S->getLocStart()),
                   SM, Context->getLangOpts())
                   .getBegin();
  if (InitialLoc.isInvalid())
    return false;
  SourceLocation StartLoc =
      Lexer::getLocForEndOfToken(InitialLoc, 0, SM, Context->getLangOpts());

  // StartLoc points at the location of the opening brace to be inserted.
  SourceLocation EndLoc;
  std::string ClosingInsertion;
  if (EndLocHint.isValid()) {
    EndLoc = EndLocHint;
    ClosingInsertion = "} ";
  } else {
    const auto FREnd = FileRange.getEnd().getLocWithOffset(-1);
    EndLoc = findEndLocation(FREnd, SM, Context);
    ClosingInsertion = "\n}";
  }

  assert(StartLoc.isValid());
  assert(EndLoc.isValid());
  // Don't require braces for statements spanning less than certain number of
  // lines.
  if (ShortStatementLines && !ForceBracesStmts.erase(S)) {
    unsigned StartLine = SM.getSpellingLineNumber(StartLoc);
    unsigned EndLine = SM.getSpellingLineNumber(EndLoc);
    if (EndLine - StartLine < ShortStatementLines)
      return false;
  }

  auto Diag = diag(StartLoc, "statement should be inside braces");
  Diag << FixItHint::CreateInsertion(StartLoc, " {")
       << FixItHint::CreateInsertion(EndLoc, ClosingInsertion);
  return true;
}

void BracesAroundStatementsCheck::onEndOfTranslationUnit() {
  ForceBracesStmts.clear();
}

} // namespace readability
} // namespace tidy
} // namespace clang
<commit_msg>[clang-tidy] Don't use diag() for debug output<commit_after>//===--- BracesAroundStatementsCheck.cpp - clang-tidy ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "BracesAroundStatementsCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Lex/Lexer.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace readability {
namespace {

tok::TokenKind getTokenKind(SourceLocation Loc, const SourceManager &SM,
                            const ASTContext *Context) {
  Token Tok;
  SourceLocation Beginning =
      Lexer::GetBeginningOfToken(Loc, SM, Context->getLangOpts());
  const bool Invalid =
      Lexer::getRawToken(Beginning, Tok, SM, Context->getLangOpts());
  assert(!Invalid && "Expected a valid token.");

  if (Invalid)
    return tok::NUM_TOKENS;

  return Tok.getKind();
}

SourceLocation forwardSkipWhitespaceAndComments(SourceLocation Loc,
                                                const SourceManager &SM,
                                                const ASTContext *Context) {
  assert(Loc.isValid());
  for (;;) {
    while (isWhitespace(*FullSourceLoc(Loc, SM).getCharacterData()))
      Loc = Loc.getLocWithOffset(1);

    tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
    if (TokKind == tok::NUM_TOKENS || TokKind != tok::comment)
      return Loc;

    // Fast-forward current token.
    Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
  }
}

SourceLocation findEndLocation(SourceLocation LastTokenLoc,
                               const SourceManager &SM,
                               const ASTContext *Context) {
  SourceLocation Loc = LastTokenLoc;
  // Loc points to the beginning of the last (non-comment non-ws) token
  // before end or ';'.
  assert(Loc.isValid());
  bool SkipEndWhitespaceAndComments = true;
  tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
  if (TokKind == tok::NUM_TOKENS || TokKind == tok::semi ||
      TokKind == tok::r_brace) {
    // If we are at ";" or "}", we found the last token. We could use as well
    // `if (isa<NullStmt>(S))`, but it wouldn't work for nested statements.
    SkipEndWhitespaceAndComments = false;
  }

  Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
  // Loc points past the last token before end or after ';'.

  if (SkipEndWhitespaceAndComments) {
    Loc = forwardSkipWhitespaceAndComments(Loc, SM, Context);
    tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
    if (TokKind == tok::semi)
      Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
  }

  for (;;) {
    assert(Loc.isValid());
    while (isHorizontalWhitespace(*FullSourceLoc(Loc, SM).getCharacterData()))
      Loc = Loc.getLocWithOffset(1);

    if (isVerticalWhitespace(*FullSourceLoc(Loc, SM).getCharacterData())) {
      // EOL, insert brace before.
      break;
    }
    tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
    if (TokKind != tok::comment) {
      // Non-comment token, insert brace before.
      break;
    }

    SourceLocation TokEndLoc =
        Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
    SourceRange TokRange(Loc, TokEndLoc);
    StringRef Comment = Lexer::getSourceText(
        CharSourceRange::getTokenRange(TokRange), SM, Context->getLangOpts());
    if (Comment.startswith("/*") && Comment.find('\n') != StringRef::npos) {
      // Multi-line block comment, insert brace before.
      break;
    }
    // else: Trailing comment, insert brace after the newline.

    // Fast-forward current token.
    Loc = TokEndLoc;
  }
  return Loc;
}

} // namespace

BracesAroundStatementsCheck::BracesAroundStatementsCheck(
    StringRef Name, ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context),
      // Always add braces by default.
      ShortStatementLines(Options.get("ShortStatementLines", 0U)) {}

void
BracesAroundStatementsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
  Options.store(Opts, "ShortStatementLines", ShortStatementLines);
}

void BracesAroundStatementsCheck::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(ifStmt().bind("if"), this);
  Finder->addMatcher(whileStmt().bind("while"), this);
  Finder->addMatcher(doStmt().bind("do"), this);
  Finder->addMatcher(forStmt().bind("for"), this);
  Finder->addMatcher(cxxForRangeStmt().bind("for-range"), this);
}

void
BracesAroundStatementsCheck::check(const MatchFinder::MatchResult &Result) {
  const SourceManager &SM = *Result.SourceManager;
  const ASTContext *Context = Result.Context;

  // Get location of closing parenthesis or 'do' to insert opening brace.
  if (auto S = Result.Nodes.getNodeAs<ForStmt>("for")) {
    checkStmt(Result, S->getBody(), S->getRParenLoc());
  } else if (auto S = Result.Nodes.getNodeAs<CXXForRangeStmt>("for-range")) {
    checkStmt(Result, S->getBody(), S->getRParenLoc());
  } else if (auto S = Result.Nodes.getNodeAs<DoStmt>("do")) {
    checkStmt(Result, S->getBody(), S->getDoLoc(), S->getWhileLoc());
  } else if (auto S = Result.Nodes.getNodeAs<WhileStmt>("while")) {
    SourceLocation StartLoc = findRParenLoc(S, SM, Context);
    if (StartLoc.isInvalid())
      return;
    checkStmt(Result, S->getBody(), StartLoc);
  } else if (auto S = Result.Nodes.getNodeAs<IfStmt>("if")) {
    SourceLocation StartLoc = findRParenLoc(S, SM, Context);
    if (StartLoc.isInvalid())
      return;
    if (ForceBracesStmts.erase(S))
      ForceBracesStmts.insert(S->getThen());
    bool BracedIf = checkStmt(Result, S->getThen(), StartLoc, S->getElseLoc());
    const Stmt *Else = S->getElse();
    if (Else && BracedIf)
      ForceBracesStmts.insert(Else);
    if (Else && !isa<IfStmt>(Else)) {
      // Omit 'else if' statements here, they will be handled directly.
      checkStmt(Result, Else, S->getElseLoc(), SourceLocation());
    }
  } else {
    llvm_unreachable("Invalid match");
  }
}

/// Find location of right parenthesis closing condition
template <typename IfOrWhileStmt>
SourceLocation
BracesAroundStatementsCheck::findRParenLoc(const IfOrWhileStmt *S,
                                           const SourceManager &SM,
                                           const ASTContext *Context) {
  // Skip macros.
  if (S->getLocStart().isMacroID())
    return SourceLocation();

  SourceLocation CondEndLoc = S->getCond()->getLocEnd();
  if (const DeclStmt *CondVar = S->getConditionVariableDeclStmt())
    CondEndLoc = CondVar->getLocEnd();

  assert(CondEndLoc.isValid());
  SourceLocation PastCondEndLoc =
      Lexer::getLocForEndOfToken(CondEndLoc, 0, SM, Context->getLangOpts());
  if (PastCondEndLoc.isInvalid())
    return SourceLocation();
  SourceLocation RParenLoc =
      forwardSkipWhitespaceAndComments(PastCondEndLoc, SM, Context);
  if (RParenLoc.isInvalid())
    return SourceLocation();
  tok::TokenKind TokKind = getTokenKind(RParenLoc, SM, Context);
  if (TokKind != tok::r_paren)
    return SourceLocation();
  return RParenLoc;
}

/// Determine if the statement needs braces around it, and add them if it does.
/// Returns true if braces where added.
bool BracesAroundStatementsCheck::checkStmt(
    const MatchFinder::MatchResult &Result, const Stmt *S,
    SourceLocation InitialLoc, SourceLocation EndLocHint) {
  // 1) If there's a corresponding "else" or "while", the check inserts "} "
  // right before that token.
  // 2) If there's a multi-line block comment starting on the same line after
  // the location we're inserting the closing brace at, or there's a non-comment
  // token, the check inserts "\n}" right before that token.
  // 3) Otherwise the check finds the end of line (possibly after some block or
  // line comments) and inserts "\n}" right before that EOL.
  if (!S || isa<CompoundStmt>(S)) {
    // Already inside braces.
    return false;
  }

  const SourceManager &SM = *Result.SourceManager;
  const ASTContext *Context = Result.Context;

  // Treat macros.
  CharSourceRange FileRange = Lexer::makeFileCharRange(
      CharSourceRange::getTokenRange(S->getSourceRange()), SM,
      Context->getLangOpts());
  if (FileRange.isInvalid())
    return false;

  // InitialLoc points at the last token before opening brace to be inserted.
  assert(InitialLoc.isValid());
  // Convert InitialLoc to file location, if it's on the same macro expansion
  // level as the start of the statement. We also need file locations for
  // Lexer::getLocForEndOfToken working properly.
  InitialLoc = Lexer::makeFileCharRange(
                   CharSourceRange::getCharRange(InitialLoc, S->getLocStart()),
                   SM, Context->getLangOpts())
                   .getBegin();
  if (InitialLoc.isInvalid())
    return false;
  SourceLocation StartLoc =
      Lexer::getLocForEndOfToken(InitialLoc, 0, SM, Context->getLangOpts());

  // StartLoc points at the location of the opening brace to be inserted.
  SourceLocation EndLoc;
  std::string ClosingInsertion;
  if (EndLocHint.isValid()) {
    EndLoc = EndLocHint;
    ClosingInsertion = "} ";
  } else {
    const auto FREnd = FileRange.getEnd().getLocWithOffset(-1);
    EndLoc = findEndLocation(FREnd, SM, Context);
    ClosingInsertion = "\n}";
  }

  assert(StartLoc.isValid());
  assert(EndLoc.isValid());
  // Don't require braces for statements spanning less than certain number of
  // lines.
  if (ShortStatementLines && !ForceBracesStmts.erase(S)) {
    unsigned StartLine = SM.getSpellingLineNumber(StartLoc);
    unsigned EndLine = SM.getSpellingLineNumber(EndLoc);
    if (EndLine - StartLine < ShortStatementLines)
      return false;
  }

  auto Diag = diag(StartLoc, "statement should be inside braces");
  Diag << FixItHint::CreateInsertion(StartLoc, " {")
       << FixItHint::CreateInsertion(EndLoc, ClosingInsertion);
  return true;
}

void BracesAroundStatementsCheck::onEndOfTranslationUnit() {
  ForceBracesStmts.clear();
}

} // namespace readability
} // namespace tidy
} // namespace clang
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/process_util.h"
#include "base/test/test_timeouts.h"
#include "chrome/browser/service/service_process_control.h"
#include "chrome/browser/service/service_process_control_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/service_process_util.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"

class ServiceProcessControlBrowserTest
    : public InProcessBrowserTest {
 public:
  ServiceProcessControlBrowserTest()
      : service_process_handle_(base::kNullProcessHandle) {
  }
  ~ServiceProcessControlBrowserTest() {
    base::CloseProcessHandle(service_process_handle_);
    service_process_handle_ = base::kNullProcessHandle;
    // Delete all instances of ServiceProcessControl.
    ServiceProcessControlManager::GetInstance()->Shutdown();
  }

#if defined(OS_MACOSX)
  virtual void TearDown() {
    // ForceServiceProcessShutdown removes the process from launchd on Mac.
    ForceServiceProcessShutdown("", 0);
  }
#endif  // OS_MACOSX

 protected:
  void LaunchServiceProcessControl() {
    ServiceProcessControl* process =
        ServiceProcessControlManager::GetInstance()->GetProcessControl(
            browser()->profile());
    process_ = process;

    // Launch the process asynchronously.
    process->Launch(
        NewRunnableMethod(
            this,
            &ServiceProcessControlBrowserTest::ProcessControlLaunched),
        NewRunnableMethod(
            this,
            &ServiceProcessControlBrowserTest::ProcessControlLaunchFailed));

    // Then run the message loop to keep things running.
    ui_test_utils::RunMessageLoop();
  }

  // Send a remoting host status request and wait reply from the service.
  void SendRequestAndWait() {
    process()->GetCloudPrintProxyStatus(NewCallback(
        this, &ServiceProcessControlBrowserTest::CloudPrintStatusCallback));
    ui_test_utils::RunMessageLoop();
  }

  void CloudPrintStatusCallback(
      bool enabled, std::string email) {
    MessageLoop::current()->Quit();
  }

  void Disconnect() {
    // This will delete all instances of ServiceProcessControl and close the IPC
    // connections.
    ServiceProcessControlManager::GetInstance()->Shutdown();
    process_ = NULL;
  }

  void WaitForShutdown() {
    EXPECT_TRUE(base::WaitForSingleProcess(
        service_process_handle_,
        TestTimeouts::wait_for_terminate_timeout_ms()));
  }

  void ProcessControlLaunched() {
    base::ProcessId service_pid;
    EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid));
    EXPECT_NE(static_cast<base::ProcessId>(0), service_pid);
    EXPECT_TRUE(base::OpenProcessHandleWithAccess(
        service_pid,
        base::kProcessAccessWaitForTermination,
        &service_process_handle_));
    // Quit the current message. Post a QuitTask instead of just calling Quit()
    // because this can get invoked in the context of a Launch() call and we
    // may not be in Run() yet.
    MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
  }

  void ProcessControlLaunchFailed() {
    ADD_FAILURE();
    // Quit the current message.
    MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
  }

  ServiceProcessControl* process() { return process_; }

 private:
  ServiceProcessControl* process_;
  base::ProcessHandle service_process_handle_;
};

// They way that the IPC is implemented only works on windows. This has to
// change when we implement a different scheme for IPC.
// Times out flakily, http://crbug.com/70076.
IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest,
                       DISABLED_LaunchAndIPC) {
  LaunchServiceProcessControl();

  // Make sure we are connected to the service process.
  EXPECT_TRUE(process()->is_connected());
  SendRequestAndWait();

  // And then shutdown the service process.
  EXPECT_TRUE(process()->Shutdown());
}

// This tests the case when a service process is launched when browser
// starts but we try to launch it again in the remoting setup dialog.
IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, LaunchTwice) {
  // Launch the service process the first time.
  LaunchServiceProcessControl();

  // Make sure we are connected to the service process.
  EXPECT_TRUE(process()->is_connected());
  SendRequestAndWait();

  // Launch the service process again.
  LaunchServiceProcessControl();
  EXPECT_TRUE(process()->is_connected());
  SendRequestAndWait();

  // And then shutdown the service process.
  EXPECT_TRUE(process()->Shutdown());
}

static void DecrementUntilZero(int* count) {
  (*count)--;
  if (!(*count))
    MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
}

// Invoke multiple Launch calls in succession and ensure that all the tasks
// get invoked.
IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, MultipleLaunchTasks) {
  ServiceProcessControl* process =
      ServiceProcessControlManager::GetInstance()->GetProcessControl(
          browser()->profile());
  int launch_count = 5;
  for (int i = 0; i < launch_count; i++) {
    // Launch the process asynchronously.
    process->Launch(
        NewRunnableFunction(&DecrementUntilZero, &launch_count),
        new MessageLoop::QuitTask());
  }
  // Then run the message loop to keep things running.
  ui_test_utils::RunMessageLoop();
  EXPECT_EQ(0, launch_count);
  // And then shutdown the service process.
  EXPECT_TRUE(process->Shutdown());
}

// Make sure using the same task for success and failure tasks works.
IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, SameLaunchTask) {
  ServiceProcessControl* process =
      ServiceProcessControlManager::GetInstance()->GetProcessControl(
          browser()->profile());
  int launch_count = 5;
  for (int i = 0; i < launch_count; i++) {
    // Launch the process asynchronously.
    Task * task = NewRunnableFunction(&DecrementUntilZero, &launch_count);
    process->Launch(task, task);
  }
  // Then run the message loop to keep things running.
  ui_test_utils::RunMessageLoop();
  EXPECT_EQ(0, launch_count);
  // And then shutdown the service process.
  EXPECT_TRUE(process->Shutdown());
}

// Tests whether disconnecting from the service IPC causes the service process
// to die.
IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, DieOnDisconnect) {
  // Launch the service process.
  LaunchServiceProcessControl();
  // Make sure we are connected to the service process.
  EXPECT_TRUE(process()->is_connected());
  Disconnect();
  WaitForShutdown();
}

//http://code.google.com/p/chromium/issues/detail?id=70793
IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest,
                       DISABLED_ForceShutdown) {
  // Launch the service process.
  LaunchServiceProcessControl();
  // Make sure we are connected to the service process.
  EXPECT_TRUE(process()->is_connected());
  base::ProcessId service_pid;
  EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid));
  EXPECT_NE(static_cast<base::ProcessId>(0), service_pid);
  chrome::VersionInfo version_info;
  ForceServiceProcessShutdown(version_info.Version(), service_pid);
  WaitForShutdown();
}

IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, CheckPid) {
  base::ProcessId service_pid;
  EXPECT_FALSE(GetServiceProcessData(NULL, &service_pid));
  // Launch the service process.
  LaunchServiceProcessControl();
  EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid));
  EXPECT_NE(static_cast<base::ProcessId>(0), service_pid);
}

DISABLE_RUNNABLE_METHOD_REFCOUNT(ServiceProcessControlBrowserTest);
<commit_msg>Mark CheckPid,DieOnDisconnect,LaunchTwice,MultipleLaunchTasks,SameLaunchTask as FAILS on mac.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/process_util.h"
#include "base/test/test_timeouts.h"
#include "chrome/browser/service/service_process_control.h"
#include "chrome/browser/service/service_process_control_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/service_process_util.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"

class ServiceProcessControlBrowserTest
    : public InProcessBrowserTest {
 public:
  ServiceProcessControlBrowserTest()
      : service_process_handle_(base::kNullProcessHandle) {
  }
  ~ServiceProcessControlBrowserTest() {
    base::CloseProcessHandle(service_process_handle_);
    service_process_handle_ = base::kNullProcessHandle;
    // Delete all instances of ServiceProcessControl.
    ServiceProcessControlManager::GetInstance()->Shutdown();
  }

#if defined(OS_MACOSX)
  virtual void TearDown() {
    // ForceServiceProcessShutdown removes the process from launchd on Mac.
    ForceServiceProcessShutdown("", 0);
  }
#endif  // OS_MACOSX

 protected:
  void LaunchServiceProcessControl() {
    ServiceProcessControl* process =
        ServiceProcessControlManager::GetInstance()->GetProcessControl(
            browser()->profile());
    process_ = process;

    // Launch the process asynchronously.
    process->Launch(
        NewRunnableMethod(
            this,
            &ServiceProcessControlBrowserTest::ProcessControlLaunched),
        NewRunnableMethod(
            this,
            &ServiceProcessControlBrowserTest::ProcessControlLaunchFailed));

    // Then run the message loop to keep things running.
    ui_test_utils::RunMessageLoop();
  }

  // Send a remoting host status request and wait reply from the service.
  void SendRequestAndWait() {
    process()->GetCloudPrintProxyStatus(NewCallback(
        this, &ServiceProcessControlBrowserTest::CloudPrintStatusCallback));
    ui_test_utils::RunMessageLoop();
  }

  void CloudPrintStatusCallback(
      bool enabled, std::string email) {
    MessageLoop::current()->Quit();
  }

  void Disconnect() {
    // This will delete all instances of ServiceProcessControl and close the IPC
    // connections.
    ServiceProcessControlManager::GetInstance()->Shutdown();
    process_ = NULL;
  }

  void WaitForShutdown() {
    EXPECT_TRUE(base::WaitForSingleProcess(
        service_process_handle_,
        TestTimeouts::wait_for_terminate_timeout_ms()));
  }

  void ProcessControlLaunched() {
    base::ProcessId service_pid;
    EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid));
    EXPECT_NE(static_cast<base::ProcessId>(0), service_pid);
    EXPECT_TRUE(base::OpenProcessHandleWithAccess(
        service_pid,
        base::kProcessAccessWaitForTermination,
        &service_process_handle_));
    // Quit the current message. Post a QuitTask instead of just calling Quit()
    // because this can get invoked in the context of a Launch() call and we
    // may not be in Run() yet.
    MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
  }

  void ProcessControlLaunchFailed() {
    ADD_FAILURE();
    // Quit the current message.
    MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
  }

  ServiceProcessControl* process() { return process_; }

 private:
  ServiceProcessControl* process_;
  base::ProcessHandle service_process_handle_;
};

// They way that the IPC is implemented only works on windows. This has to
// change when we implement a different scheme for IPC.
// Times out flakily, http://crbug.com/70076.
IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest,
                       DISABLED_LaunchAndIPC) {
  LaunchServiceProcessControl();

  // Make sure we are connected to the service process.
  EXPECT_TRUE(process()->is_connected());
  SendRequestAndWait();

  // And then shutdown the service process.
  EXPECT_TRUE(process()->Shutdown());
}

// This tests the case when a service process is launched when browser
// starts but we try to launch it again in the remoting setup dialog.
// Fails on mac. http://crbug.com/75518
#if defined(OS_MACOSX)
#define MAYBE_LaunchTwice FAILS_LaunchTwice
#else
#define MAYBE_LaunchTwice LaunchTwice
#endif
IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, MAYBE_LaunchTwice) {
  // Launch the service process the first time.
  LaunchServiceProcessControl();

  // Make sure we are connected to the service process.
  EXPECT_TRUE(process()->is_connected());
  SendRequestAndWait();

  // Launch the service process again.
  LaunchServiceProcessControl();
  EXPECT_TRUE(process()->is_connected());
  SendRequestAndWait();

  // And then shutdown the service process.
  EXPECT_TRUE(process()->Shutdown());
}

static void DecrementUntilZero(int* count) {
  (*count)--;
  if (!(*count))
    MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
}

// Invoke multiple Launch calls in succession and ensure that all the tasks
// get invoked.
// Fails on mac. http://crbug.com/75518
#if defined(OS_MACOSX)
#define MAYBE_MultipleLaunchTasks FAILS_MultipleLaunchTasks
#else
#define MAYBE_MultipleLaunchTasks MultipleLaunchTasks
#endif
IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest,
                       MAYBE_MultipleLaunchTasks) {
  ServiceProcessControl* process =
      ServiceProcessControlManager::GetInstance()->GetProcessControl(
          browser()->profile());
  int launch_count = 5;
  for (int i = 0; i < launch_count; i++) {
    // Launch the process asynchronously.
    process->Launch(
        NewRunnableFunction(&DecrementUntilZero, &launch_count),
        new MessageLoop::QuitTask());
  }
  // Then run the message loop to keep things running.
  ui_test_utils::RunMessageLoop();
  EXPECT_EQ(0, launch_count);
  // And then shutdown the service process.
  EXPECT_TRUE(process->Shutdown());
}

// Make sure using the same task for success and failure tasks works.
// Fails on mac. http://crbug.com/75518
#if defined(OS_MACOSX)
#define MAYBE_SameLaunchTask FAILS_SameLaunchTask
#else
#define MAYBE_SameLaunchTask SameLaunchTask
#endif
IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, MAYBE_SameLaunchTask) {
  ServiceProcessControl* process =
      ServiceProcessControlManager::GetInstance()->GetProcessControl(
          browser()->profile());
  int launch_count = 5;
  for (int i = 0; i < launch_count; i++) {
    // Launch the process asynchronously.
    Task * task = NewRunnableFunction(&DecrementUntilZero, &launch_count);
    process->Launch(task, task);
  }
  // Then run the message loop to keep things running.
  ui_test_utils::RunMessageLoop();
  EXPECT_EQ(0, launch_count);
  // And then shutdown the service process.
  EXPECT_TRUE(process->Shutdown());
}

// Tests whether disconnecting from the service IPC causes the service process
// to die.
// Fails on mac. http://crbug.com/75518
#if defined(OS_MACOSX)
#define MAYBE_DieOnDisconnect FAILS_DieOnDisconnect
#else
#define MAYBE_DieOnDisconnect DieOnDisconnect
#endif
IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest,
                       MAYBE_DieOnDisconnect) {
  // Launch the service process.
  LaunchServiceProcessControl();
  // Make sure we are connected to the service process.
  EXPECT_TRUE(process()->is_connected());
  Disconnect();
  WaitForShutdown();
}

//http://code.google.com/p/chromium/issues/detail?id=70793
IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest,
                       DISABLED_ForceShutdown) {
  // Launch the service process.
  LaunchServiceProcessControl();
  // Make sure we are connected to the service process.
  EXPECT_TRUE(process()->is_connected());
  base::ProcessId service_pid;
  EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid));
  EXPECT_NE(static_cast<base::ProcessId>(0), service_pid);
  chrome::VersionInfo version_info;
  ForceServiceProcessShutdown(version_info.Version(), service_pid);
  WaitForShutdown();
}

// Fails on mac. http://crbug.com/75518
#if defined(OS_MACOSX)
#define MAYBE_CheckPid FAILS_CheckPid
#else
#define MAYBE_CheckPid CheckPid
#endif
IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, MAYBE_CheckPid) {
  base::ProcessId service_pid;
  EXPECT_FALSE(GetServiceProcessData(NULL, &service_pid));
  // Launch the service process.
  LaunchServiceProcessControl();
  EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid));
  EXPECT_NE(static_cast<base::ProcessId>(0), service_pid);
}

DISABLE_RUNNABLE_METHOD_REFCOUNT(ServiceProcessControlBrowserTest);
<|endoftext|>


<commit_before>#include <limits>
#include <boost/foreach.hpp>
#include "YankOpen.hpp"

using namespace std;
using namespace Geometry2d;

REGISTER_PLAY_CATEGORY(Gameplay::Plays::YankOpen, "Playing")

namespace Gameplay
{
	namespace Plays
	{
		REGISTER_CONFIGURABLE(YankOpen)
	}
}

ConfigDouble *Gameplay::Plays::YankOpen::_offense_hysteresis;
ConfigDouble *Gameplay::Plays::YankOpen::_support_backoff_thresh;
ConfigDouble *Gameplay::Plays::YankOpen::_mark_hysteresis_coeff;
ConfigDouble *Gameplay::Plays::YankOpen::_support_avoid_teammate_radius;
ConfigDouble *Gameplay::Plays::YankOpen::_support_avoid_shot;
ConfigDouble *Gameplay::Plays::YankOpen::_offense_support_ratio;
ConfigDouble *Gameplay::Plays::YankOpen::_defense_support_ratio;
ConfigBool *Gameplay::Plays::YankOpen::_useYank;

void Gameplay::Plays::YankOpen::createConfiguration(Configuration *cfg)
{
	_offense_hysteresis = new ConfigDouble(cfg, "YankOpen/Hystersis Coeff", 0.50);
	_support_backoff_thresh = new ConfigDouble(cfg, "YankOpen/Support Backoff Dist", 1.5);
	_mark_hysteresis_coeff = new ConfigDouble(cfg, "YankOpen/Mark Hystersis Coeff", 0.9);
	_support_avoid_teammate_radius = new ConfigDouble(cfg, "YankOpen/Support Avoid Teammate Dist", 0.5);
	_support_avoid_shot = new ConfigDouble(cfg, "YankOpen/Support Avoid Shot", 0.2);
	_offense_support_ratio = new ConfigDouble(cfg, "YankOpen/Offense Support Ratio", 0.7);
	_defense_support_ratio = new ConfigDouble(cfg, "YankOpen/Defense Support Ratio", 0.9);
	_useYank = new ConfigBool(cfg, "YankOpen/Use Yank", false);
}

Gameplay::Plays::YankOpen::YankOpen(GameplayModule *gameplay):
Play(gameplay),
_leftFullback(gameplay, Behaviors::Fullback::Left),
_rightFullback(gameplay, Behaviors::Fullback::Right),
_support(gameplay),
_strikerBump(gameplay),
_strikerFling(gameplay),
_strikerYank(gameplay)
{
	_leftFullback.otherFullbacks.insert(&_rightFullback);
	_rightFullback.otherFullbacks.insert(&_leftFullback);

	// use constant value of mark threshold for now
	_support.markLineThresh(1.0);

}

float Gameplay::Plays::YankOpen::score ( Gameplay::GameplayModule* gameplay )
{
	// only run if we are playing and not in a restart
	bool refApplicable = gameplay->state()->gameState.playing();
	return refApplicable ? 0 : INFINITY;
}

bool Gameplay::Plays::YankOpen::run()
{
	// handle assignments
	set<OurRobot *> available = _gameplay->playRobots();

	// project the ball forward (dampened)
	const float proj_time = 0.75; // seconds to project
	const float dampen_factor = 0.9; // accounts for slowing over time
	Geometry2d::Point ballProj = ball().pos + ball().vel * proj_time * dampen_factor;

	// defense first - get closest to goal to choose sides properly
	assignNearest(_leftFullback.robot, available, Geometry2d::Point(-Field_GoalWidth/2, 0.0));
	assignNearest(_rightFullback.robot, available, Geometry2d::Point(Field_GoalWidth/2, 0.0));

	// determine whether to change offense players
	bool forward_reset = false;
	if (_strikerYank.robot && _support.robot &&
			_support.robot->pos.distTo(ballProj) < *_offense_hysteresis * _strikerYank.robot->pos.distTo(ballProj)) {
		_strikerBump.robot = NULL;
		_strikerYank.robot = NULL;
		_strikerFling.robot = NULL;
		_strikerBump.restart();
		_strikerYank.restart();
		_strikerFling.restart();
		_support.robot = NULL;
		forward_reset = true;
	}

	// choose offense, we want closest robot to ball to be striker
	// FIXME: need to assign more carefully to ensure that there is a robot available to kick
	if (assignNearest(_strikerYank.robot, available, ballProj))
	{
		_strikerBump.robot = _strikerYank.robot;
		_strikerFling.robot = _strikerYank.robot;
	}
//	assignNearest(_support.robot, available, ballProj);

	// find the nearest opponent to the striker
	OpponentRobot* closestRobotToStriker = 0;
	float closestDistToStriker = numeric_limits<float>::infinity();
	if (_strikerYank.robot) {
		BOOST_FOREACH(OpponentRobot* opp, state()->opp) {
			if (opp) {
				float d = opp->pos.distTo(_strikerYank.robot->pos);
				if (d < closestDistToStriker) {
					closestDistToStriker = d;
					closestRobotToStriker = opp;
				}
			}
		}
	}
	bool striker_engaged = _strikerYank.robot && closestDistToStriker < *_support_backoff_thresh;

	// pick as a mark target the furthest back opposing robot
	// and adjust mark ratio based on field position
	OpponentRobot* bestOpp = NULL;
	float bestDist = numeric_limits<float>::infinity();
	float cur_dist = (_support.markRobot()) ? _support.markRobot()->pos.distTo(ballProj) : numeric_limits<float>::infinity();

	size_t nrOppClose = 0;
	BOOST_FOREACH(OpponentRobot* opp, state()->opp)
	{
		const float oppPos = opp->pos.y;
		if (opp && opp->visible && oppPos > 0.1 && !(striker_engaged && opp == closestRobotToStriker)) {
			if (oppPos < bestDist) {
				bestDist = opp->pos.y;
				bestOpp = opp;
			}
			if (oppPos < Field_Length/2) {
				++nrOppClose;
			}
		}
	}
	if (!bestOpp && _support.robot) {
		_support.robot->addText("No mark target");
	}

	// use hysteresis for changing of the robot
	if (bestOpp && bestOpp->visible && (forward_reset || bestDist < cur_dist * *_mark_hysteresis_coeff))
		_support.markRobot(bestOpp);

	// if we are further away, we can mark further from robot
	if (ballProj.y > Field_Length/2.0 && nrOppClose)
		_support.ratio(*_offense_support_ratio);
	else
		_support.ratio(*_defense_support_ratio);

	// adjust obstacles on markers
	if (_strikerYank.robot && _support.robot) {
		unsigned striker = _strikerYank.robot->shell();
		_support.robot->avoidTeammateRadius(striker, *_support_avoid_teammate_radius);
	}

	// manually reset any kickers so they keep kicking
	if (_strikerYank.done())
	{
		_strikerYank.restart();
	}

	if (_strikerBump.done())
	{
		_strikerBump.restart();
	}

	if (_strikerFling.done())
	{
		_strikerFling.restart();
	}

	// execute behaviors
//	if (_striker.robot) _striker.run(); // TODO: choose which one to run
	if (*_useYank && _strikerYank.robot) _strikerYank.run();
	if (!*_useYank && _strikerBump.robot) _strikerBump.run();
	if (_support.robot) _support.run();
	if (_leftFullback.robot) _leftFullback.run();
	if (_rightFullback.robot) _rightFullback.run();

	return true;
}
<commit_msg> sldkfjs<commit_after>#include <limits>
#include <boost/foreach.hpp>
#include "YankOpen.hpp"

using namespace std;
using namespace Geometry2d;

REGISTER_PLAY_CATEGORY(Gameplay::Plays::YankOpen, "Playing")

namespace Gameplay
{
	namespace Plays
	{
		REGISTER_CONFIGURABLE(YankOpen)
	}
}

ConfigDouble *Gameplay::Plays::YankOpen::_offense_hysteresis;
ConfigDouble *Gameplay::Plays::YankOpen::_support_backoff_thresh;
ConfigDouble *Gameplay::Plays::YankOpen::_mark_hysteresis_coeff;
ConfigDouble *Gameplay::Plays::YankOpen::_support_avoid_teammate_radius;
ConfigDouble *Gameplay::Plays::YankOpen::_support_avoid_shot;
ConfigDouble *Gameplay::Plays::YankOpen::_offense_support_ratio;
ConfigDouble *Gameplay::Plays::YankOpen::_defense_support_ratio;
ConfigBool *Gameplay::Plays::YankOpen::_useYank;

void Gameplay::Plays::YankOpen::createConfiguration(Configuration *cfg)
{
	_offense_hysteresis = new ConfigDouble(cfg, "YankOpen/Hystersis Coeff", 0.50);
	_support_backoff_thresh = new ConfigDouble(cfg, "YankOpen/Support Backoff Dist", 1.5);
	_mark_hysteresis_coeff = new ConfigDouble(cfg, "YankOpen/Mark Hystersis Coeff", 0.9);
	_support_avoid_teammate_radius = new ConfigDouble(cfg, "YankOpen/Support Avoid Teammate Dist", 0.5);
	_support_avoid_shot = new ConfigDouble(cfg, "YankOpen/Support Avoid Shot", 0.2);
	_offense_support_ratio = new ConfigDouble(cfg, "YankOpen/Offense Support Ratio", 0.7);
	_defense_support_ratio = new ConfigDouble(cfg, "YankOpen/Defense Support Ratio", 0.9);
	_useYank = new ConfigBool(cfg, "YankOpen/Use Yank", false);
}

Gameplay::Plays::YankOpen::YankOpen(GameplayModule *gameplay):
Play(gameplay),
_leftFullback(gameplay, Behaviors::Fullback::Left),
_rightFullback(gameplay, Behaviors::Fullback::Right),
_support(gameplay),
_strikerBump(gameplay),
_strikerFling(gameplay),
_strikerYank(gameplay)
{
	_leftFullback.otherFullbacks.insert(&_rightFullback);
	_rightFullback.otherFullbacks.insert(&_leftFullback);

	// use constant value of mark threshold for now
	_support.markLineThresh(1.0);

}

float Gameplay::Plays::YankOpen::score ( Gameplay::GameplayModule* gameplay )
{
	// only run if we are playing and not in a restart
	bool refApplicable = gameplay->state()->gameState.playing();
	return refApplicable ? 0 : INFINITY;
}

bool Gameplay::Plays::YankOpen::run()
{
	// handle assignments
	set<OurRobot *> available = _gameplay->playRobots();

	// project the ball forward (dampened)
	const float proj_time = 0.75; // seconds to project
	const float dampen_factor = 0.9; // accounts for slowing over time
	Geometry2d::Point ballProj = ball().pos + ball().vel * proj_time * dampen_factor;

	// determine whether to change offense players
	bool forward_reset = false;
//	if (_strikerYank.robot && //_support.robot &&
//			_support.robot->pos.distTo(ballProj) < *_offense_hysteresis * _strikerYank.robot->pos.distTo(ballProj)) {
//		_strikerBump.robot = NULL;
//		_strikerYank.robot = NULL;
//		_strikerFling.robot = NULL;
//		_strikerBump.restart();
//		_strikerYank.restart();
//		_strikerFling.restart();
//		_support.robot = NULL;
//		forward_reset = true;
//	}

	// choose offense, we want closest robot to ball to be striker
	// FIXME: need to assign more carefully to ensure that there is a robot available to kick
	if (assignNearest(_strikerYank.robot, available, ballProj))
	{
		_strikerBump.robot = _strikerYank.robot;
		_strikerFling.robot = _strikerYank.robot;
	}
//	assignNearest(_support.robot, available, ballProj);

	// find the nearest opponent to the striker
	OpponentRobot* closestRobotToStriker = 0;
	float closestDistToStriker = numeric_limits<float>::infinity();
	if (_strikerYank.robot) {
		BOOST_FOREACH(OpponentRobot* opp, state()->opp) {
			if (opp) {
				float d = opp->pos.distTo(_strikerYank.robot->pos);
				if (d < closestDistToStriker) {
					closestDistToStriker = d;
					closestRobotToStriker = opp;
				}
			}
		}
	}
	bool striker_engaged = _strikerYank.robot && closestDistToStriker < *_support_backoff_thresh;

	// defense first - get closest to goal to choose sides properly
	assignNearest(_leftFullback.robot, available, Geometry2d::Point(-Field_GoalWidth/2, 0.0));
	assignNearest(_rightFullback.robot, available, Geometry2d::Point(Field_GoalWidth/2, 0.0));

	// pick as a mark target the furthest back opposing robot
	// and adjust mark ratio based on field position
	OpponentRobot* bestOpp = NULL;
	float bestDist = numeric_limits<float>::infinity();
	float cur_dist = (_support.markRobot()) ? _support.markRobot()->pos.distTo(ballProj) : numeric_limits<float>::infinity();

	size_t nrOppClose = 0;
	BOOST_FOREACH(OpponentRobot* opp, state()->opp)
	{
		const float oppPos = opp->pos.y;
		if (opp && opp->visible && oppPos > 0.1 && !(striker_engaged && opp == closestRobotToStriker)) {
			if (oppPos < bestDist) {
				bestDist = opp->pos.y;
				bestOpp = opp;
			}
			if (oppPos < Field_Length/2) {
				++nrOppClose;
			}
		}
	}
	if (!bestOpp && _support.robot) {
		_support.robot->addText("No mark target");
	}

	// use hysteresis for changing of the robot
	if (bestOpp && bestOpp->visible && (forward_reset || bestDist < cur_dist * *_mark_hysteresis_coeff))
		_support.markRobot(bestOpp);

	// if we are further away, we can mark further from robot
	if (ballProj.y > Field_Length/2.0 && nrOppClose)
		_support.ratio(*_offense_support_ratio);
	else
		_support.ratio(*_defense_support_ratio);

	// adjust obstacles on markers
	if (_strikerYank.robot && _support.robot) {
		unsigned striker = _strikerYank.robot->shell();
		_support.robot->avoidTeammateRadius(striker, *_support_avoid_teammate_radius);
	}

	// manually reset any kickers so they keep kicking
	if (_strikerYank.done())
	{
		_strikerYank.restart();
	}

	if (_strikerBump.done())
	{
		_strikerBump.restart();
	}

	if (_strikerFling.done())
	{
		_strikerFling.restart();
	}

	// execute behaviors
//	if (_striker.robot) _striker.run(); // TODO: choose which one to run
	if (*_useYank && _strikerYank.robot) _strikerYank.run();
	if (!*_useYank && _strikerBump.robot) _strikerBump.run();
	if (_support.robot) _support.run();
	if (_leftFullback.robot) _leftFullback.run();
	if (_rightFullback.robot) _rightFullback.run();

	return true;
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/crypto_module_password_dialog_view.h"

#include "base/basictypes.h"
#include "base/bind.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/ui/views/window.h"
#include "googleurl/src/gurl.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/controls/button/text_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/layout/layout_constants.h"
#include "ui/views/widget/widget.h"

int kInputPasswordMinWidth = 8;

namespace browser {

// CryptoModulePasswordDialogView
////////////////////////////////////////////////////////////////////////////////
CryptoModulePasswordDialogView::CryptoModulePasswordDialogView(
    const std::string& slot_name,
    browser::CryptoModulePasswordReason reason,
    const std::string& server,
    const base::Callback<void(const char*)>& callback)
    : callback_(callback) {
  Init(server, slot_name, reason);
}

CryptoModulePasswordDialogView::~CryptoModulePasswordDialogView() {
}

void CryptoModulePasswordDialogView::Init(
    const std::string& server,
    const std::string& slot_name,
    browser::CryptoModulePasswordReason reason) {
  // Select an appropriate text for the reason.
  std::string text;
  const string16& server16 = UTF8ToUTF16(server);
  const string16& slot16 = UTF8ToUTF16(slot_name);
  switch (reason) {
    case browser::kCryptoModulePasswordKeygen:
      text = l10n_util::GetStringFUTF8(
          IDS_CRYPTO_MODULE_AUTH_DIALOG_TEXT_KEYGEN, slot16, server16);
      break;
    case browser::kCryptoModulePasswordCertEnrollment:
      text = l10n_util::GetStringFUTF8(
          IDS_CRYPTO_MODULE_AUTH_DIALOG_TEXT_CERT_ENROLLMENT, slot16, server16);
      break;
    case browser::kCryptoModulePasswordClientAuth:
      text = l10n_util::GetStringFUTF8(
          IDS_CRYPTO_MODULE_AUTH_DIALOG_TEXT_CLIENT_AUTH, slot16, server16);
      break;
    case browser::kCryptoModulePasswordListCerts:
      text = l10n_util::GetStringFUTF8(
          IDS_CRYPTO_MODULE_AUTH_DIALOG_TEXT_LIST_CERTS, slot16);
      break;
    case browser::kCryptoModulePasswordCertImport:
      text = l10n_util::GetStringFUTF8(
          IDS_CRYPTO_MODULE_AUTH_DIALOG_TEXT_CERT_IMPORT, slot16);
      break;
    case browser::kCryptoModulePasswordCertExport:
      text = l10n_util::GetStringFUTF8(
          IDS_CRYPTO_MODULE_AUTH_DIALOG_TEXT_CERT_EXPORT, slot16);
      break;
    default:
      NOTREACHED();
  }
  reason_label_ = new views::Label(UTF8ToUTF16(text));
  reason_label_->SetMultiLine(true);

  password_label_ = new views::Label(l10n_util::GetStringUTF16(
      IDS_CRYPTO_MODULE_AUTH_DIALOG_PASSWORD_FIELD));

  password_entry_ = new views::Textfield(views::Textfield::STYLE_OBSCURED);
  password_entry_->SetController(this);

  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
  SetLayoutManager(layout);

  views::ColumnSet* reason_column_set = layout->AddColumnSet(0);
  reason_column_set->AddColumn(
      views::GridLayout::LEADING, views::GridLayout::LEADING, 1,
      views::GridLayout::USE_PREF, 0, 0);

  views::ColumnSet* column_set = layout->AddColumnSet(1);
  column_set->AddColumn(views::GridLayout::LEADING,
                        views::GridLayout::LEADING, 0,
                        views::GridLayout::USE_PREF, 0, 0);
  column_set->AddPaddingColumn(
      0, views::kUnrelatedControlLargeHorizontalSpacing);
  column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
                        views::GridLayout::USE_PREF, 0, 0);

  layout->StartRow(0, 0);
  layout->AddView(reason_label_);
  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);

  layout->StartRow(0, 1);
  layout->AddView(password_label_);
  layout->AddView(password_entry_);
}

views::View* CryptoModulePasswordDialogView::GetInitiallyFocusedView() {
  return password_entry_;
}
ui::ModalType CryptoModulePasswordDialogView::GetModalType() const {
  return ui::MODAL_TYPE_WINDOW;
}
views::View* CryptoModulePasswordDialogView::GetContentsView() {
  return this;
}

string16 CryptoModulePasswordDialogView::GetDialogButtonLabel(
    ui::DialogButton button) const {
  return l10n_util::GetStringUTF16(button == ui::DIALOG_BUTTON_OK ?
      IDS_CRYPTO_MODULE_AUTH_DIALOG_OK_BUTTON_LABEL : IDS_CANCEL);
}

bool CryptoModulePasswordDialogView::Accept() {
  callback_.Run(UTF16ToUTF8(password_entry_->text()).c_str());
  const string16 empty;
  password_entry_->SetText(empty);
  return true;
}

bool CryptoModulePasswordDialogView::Cancel() {
  callback_.Run(static_cast<const char*>(NULL));
  const string16 empty;
  password_entry_->SetText(empty);
  return true;
}

bool CryptoModulePasswordDialogView::HandleKeyEvent(
    views::Textfield* sender,
    const views::KeyEvent& keystroke) {
  return false;
}

void CryptoModulePasswordDialogView::ContentsChanged(
    views::Textfield* sender,
    const string16& new_contents) {
}

string16 CryptoModulePasswordDialogView::GetWindowTitle() const {
  return l10n_util::GetStringUTF16(IDS_CRYPTO_MODULE_AUTH_DIALOG_TITLE);
}

void ShowCryptoModulePasswordDialog(
    const std::string& slot_name,
    bool retry,
    CryptoModulePasswordReason reason,
    const std::string& server,
    const CryptoModulePasswordCallback& callback) {
  CryptoModulePasswordDialogView* dialog =
      new CryptoModulePasswordDialogView(slot_name, reason, server, callback);
  views::Widget::CreateWindowWithParent(dialog, NULL)->Show();
}

}  // namespace browser
<commit_msg>views: Create crypto dialog with Widget::CreateWindow() function.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/crypto_module_password_dialog_view.h"

#include "base/basictypes.h"
#include "base/bind.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/ui/views/window.h"
#include "googleurl/src/gurl.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/controls/button/text_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/layout/layout_constants.h"
#include "ui/views/widget/widget.h"

int kInputPasswordMinWidth = 8;

namespace browser {

// CryptoModulePasswordDialogView
////////////////////////////////////////////////////////////////////////////////
CryptoModulePasswordDialogView::CryptoModulePasswordDialogView(
    const std::string& slot_name,
    browser::CryptoModulePasswordReason reason,
    const std::string& server,
    const base::Callback<void(const char*)>& callback)
    : callback_(callback) {
  Init(server, slot_name, reason);
}

CryptoModulePasswordDialogView::~CryptoModulePasswordDialogView() {
}

void CryptoModulePasswordDialogView::Init(
    const std::string& server,
    const std::string& slot_name,
    browser::CryptoModulePasswordReason reason) {
  // Select an appropriate text for the reason.
  std::string text;
  const string16& server16 = UTF8ToUTF16(server);
  const string16& slot16 = UTF8ToUTF16(slot_name);
  switch (reason) {
    case browser::kCryptoModulePasswordKeygen:
      text = l10n_util::GetStringFUTF8(
          IDS_CRYPTO_MODULE_AUTH_DIALOG_TEXT_KEYGEN, slot16, server16);
      break;
    case browser::kCryptoModulePasswordCertEnrollment:
      text = l10n_util::GetStringFUTF8(
          IDS_CRYPTO_MODULE_AUTH_DIALOG_TEXT_CERT_ENROLLMENT, slot16, server16);
      break;
    case browser::kCryptoModulePasswordClientAuth:
      text = l10n_util::GetStringFUTF8(
          IDS_CRYPTO_MODULE_AUTH_DIALOG_TEXT_CLIENT_AUTH, slot16, server16);
      break;
    case browser::kCryptoModulePasswordListCerts:
      text = l10n_util::GetStringFUTF8(
          IDS_CRYPTO_MODULE_AUTH_DIALOG_TEXT_LIST_CERTS, slot16);
      break;
    case browser::kCryptoModulePasswordCertImport:
      text = l10n_util::GetStringFUTF8(
          IDS_CRYPTO_MODULE_AUTH_DIALOG_TEXT_CERT_IMPORT, slot16);
      break;
    case browser::kCryptoModulePasswordCertExport:
      text = l10n_util::GetStringFUTF8(
          IDS_CRYPTO_MODULE_AUTH_DIALOG_TEXT_CERT_EXPORT, slot16);
      break;
    default:
      NOTREACHED();
  }
  reason_label_ = new views::Label(UTF8ToUTF16(text));
  reason_label_->SetMultiLine(true);

  password_label_ = new views::Label(l10n_util::GetStringUTF16(
      IDS_CRYPTO_MODULE_AUTH_DIALOG_PASSWORD_FIELD));

  password_entry_ = new views::Textfield(views::Textfield::STYLE_OBSCURED);
  password_entry_->SetController(this);

  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
  SetLayoutManager(layout);

  views::ColumnSet* reason_column_set = layout->AddColumnSet(0);
  reason_column_set->AddColumn(
      views::GridLayout::LEADING, views::GridLayout::LEADING, 1,
      views::GridLayout::USE_PREF, 0, 0);

  views::ColumnSet* column_set = layout->AddColumnSet(1);
  column_set->AddColumn(views::GridLayout::LEADING,
                        views::GridLayout::LEADING, 0,
                        views::GridLayout::USE_PREF, 0, 0);
  column_set->AddPaddingColumn(
      0, views::kUnrelatedControlLargeHorizontalSpacing);
  column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
                        views::GridLayout::USE_PREF, 0, 0);

  layout->StartRow(0, 0);
  layout->AddView(reason_label_);
  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);

  layout->StartRow(0, 1);
  layout->AddView(password_label_);
  layout->AddView(password_entry_);
}

views::View* CryptoModulePasswordDialogView::GetInitiallyFocusedView() {
  return password_entry_;
}
ui::ModalType CryptoModulePasswordDialogView::GetModalType() const {
  return ui::MODAL_TYPE_WINDOW;
}
views::View* CryptoModulePasswordDialogView::GetContentsView() {
  return this;
}

string16 CryptoModulePasswordDialogView::GetDialogButtonLabel(
    ui::DialogButton button) const {
  return l10n_util::GetStringUTF16(button == ui::DIALOG_BUTTON_OK ?
      IDS_CRYPTO_MODULE_AUTH_DIALOG_OK_BUTTON_LABEL : IDS_CANCEL);
}

bool CryptoModulePasswordDialogView::Accept() {
  callback_.Run(UTF16ToUTF8(password_entry_->text()).c_str());
  const string16 empty;
  password_entry_->SetText(empty);
  return true;
}

bool CryptoModulePasswordDialogView::Cancel() {
  callback_.Run(static_cast<const char*>(NULL));
  const string16 empty;
  password_entry_->SetText(empty);
  return true;
}

bool CryptoModulePasswordDialogView::HandleKeyEvent(
    views::Textfield* sender,
    const views::KeyEvent& keystroke) {
  return false;
}

void CryptoModulePasswordDialogView::ContentsChanged(
    views::Textfield* sender,
    const string16& new_contents) {
}

string16 CryptoModulePasswordDialogView::GetWindowTitle() const {
  return l10n_util::GetStringUTF16(IDS_CRYPTO_MODULE_AUTH_DIALOG_TITLE);
}

void ShowCryptoModulePasswordDialog(
    const std::string& slot_name,
    bool retry,
    CryptoModulePasswordReason reason,
    const std::string& server,
    const CryptoModulePasswordCallback& callback) {
  CryptoModulePasswordDialogView* dialog =
      new CryptoModulePasswordDialogView(slot_name, reason, server, callback);
  views::Widget::CreateWindow(dialog)->Show();
}

}  // namespace browser
<|endoftext|>