text:
#include "embeddedGraph.hpp"

#include <vector>
#include <set>

namespace coregraph {

EmbeddedGraph::EmbeddedGraph(vg::VG& graph, stPinchThreadSet* threadSet,
    std::map<int64_t, std::string>& threadSequences,
    std::function<int64_t(void)> getId, const std::string& name): graph(graph),
    threadSet(threadSet), name(name) {

    // We need to construct some embedding of xg nodes in a pinch graph.

    // We can't combine any two vg nodes onto the same thread, if either of them
    // has multiple edges on either side.

    // So, the algorithm:
    // Go through each vg node we haven't already placed
    // If the node has degree 1 on both ends, look left and right and compose a run of such nodes
    // Be careful because the run may be circular
    // Embed all the nodes onto a thread.
    // After doing that for all the nodes, turn all remaining nodes into their own threads.
    // For every edge, if it's not implicit, make an "NN" staple and attach the nodes it wants together.

    graph.for_each_node([&](vg::Node* node) {
#ifdef debug
        std::cerr << "Node: " << node->id() << ": " << node->sequence() << std::endl;
#endif
        // Add a thread
        int64_t threadName = getId();
        stPinchThread* thread = stPinchThreadSet_addThread(threadSet, threadName, 0, node->sequence().size());
        // Copy over its sequence
        threadSequences[threadName] = node->sequence();

        // TODO: for now just give every node its own thread.
        embedding[node->id()] = std::make_tuple(thread, 0, false);

    });

    graph.for_each_edge([&](vg::Edge* edge) {

        // Attach the nodes as specified by the edges

        // Make a 2-base staple sequence
        stPinchThread* thread = stPinchThreadSet_addThread(threadSet, getId(), 0, 2);

        // Unpack the tuples describing the embeddings, so we're holding thread,
        // offset, is-end-of-the-node-and-not-start tuples representing the two
        // sides to weld together.
        stPinchThread* thread1, *thread2;
        int64_t offset1, offset2;
        bool isEnd1, isEnd2; // These are basically !from_start and to_end

        std::tie(thread1, offset1, isEnd1) = embedding.at(edge->from());
        std::tie(thread2, offset2, isEnd2) = embedding.at(edge->to());

        // Adapt these to point to the sequence ends we want to weld together.
        // They start out pointing to the low ends, which are the starts if the
        // nodes are not embedded in reverse, and the ends otherwise.

        if(!edge->from_start()) {
            // Move the thread1 set to the end
            offset1 += (stPinchThread_getLength(thread1) - 1) * (isEnd1 ? -1 : 1);
            isEnd1 = !isEnd1;
        }

        if(edge->to_end()) {
            // Move the thread2 set to the end
            offset2 += (stPinchThread_getLength(thread2) - 1) * (isEnd2 ? -1 : 1);
            isEnd2 = !isEnd2;
        }

        // Do the welding. We're holding the ends looking outwards from the
        // join, so we need to flip the orientation of one of them. Also, pinch
        // graphs use 0 for the relatively backward orientation, so we invert
        // here. We still report the orientations the VG way.
#ifdef debug
        std::cerr << "Welding 0 on staple to " << offset1 << " on " << stPinchThread_getName(thread1) <<
            " in orientation " << (isEnd1 ? "forward" : "reverse") << std::endl;
#endif
        stPinchThread_pinch(thread, thread1, 0, offset1, 1, isEnd1);
#ifdef debug
        std::cerr << "Welding 1 on staple to " << offset2 << " on " << stPinchThread_getName(thread2) <<
            " in orientation " << (isEnd2 ? "reverse" : "forward") << std::endl;
#endif
        stPinchThread_pinch(thread, thread2, 1, offset2, 1, !isEnd2);
    });
}

/**
 * Return true if a mapping is a perfect match, and false if it isn't.
 */
bool mappingIsPerfectMatch(const vg::Mapping& mapping) {
    for (auto edit : mapping.edit()) {
        if (edit.from_length() != edit.to_length() || !edit.sequence().empty()) {
            // This edit isn't a perfect match
            return false;
        }
    }

    // If we get here, all the edits are perfect matches.
    // Note that Mappings with no edits at all are full-length perfect matches.
    return true;
}

bool EmbeddedGraph::isCoveredByPaths() {
    bool covered = true;

    graph.for_each_node([&](vg::Node* node) {
        if(!graph.paths.has_node_mapping(node)) {
            // We found a node that doesn't have a path on it.
            covered = false;
#ifdef debug
            std::cerr << "Node: " << node->id() << ": " << node->sequence() << " is uncovered by any path" << std::endl;
#endif

        }

    });

    // Return the flag we've been updating
    return covered;
}

/**
 * Return the (from) length of a Mapping, even if thgat Mapping has no edits
 * (and is implicitly a full-length perfect match). Requires the graph that the
 * Mapping is to.
 * TODO: put in a util file or something.
 */
int64_t mappingLength(const vg::Mapping& mapping, vg::VG& graph) {
    if(mapping.edit_size() == 0) {
        // There are no edits so we just use the (remaining) length of the node.

         if(mapping.is_reverse()) {
            // We take the part left of its offset. We don't even need the node.
            // But we account for the 0-based-ness of the coordinates.
            return mapping.position().offset() + 1;
        } else {
            // We take the part at and right of the offset
            int64_t nodeLength = graph.get_node(mapping.position().node_id())->sequence().size();
            return nodeLength - mapping.position().offset();
       }
    } else {
        // There are edits so just refer to them
        return vg::mapping_from_length(mapping);
    }
}

const std::string& EmbeddedGraph::getName() {
    return name;
}

size_t EmbeddedGraph::scanPath(std::list<vg::Mapping>& path) {

    size_t totalLength = 0;

    for(auto& mapping : path) {
        // Force it to be a perfect mapping
        assert(mappingIsPerfectMatch(mapping));

        // Calculate and incorporate its length
        totalLength += mappingLength(mapping, graph);
    }

    return totalLength;
}

void EmbeddedGraph::pinchWith(EmbeddedGraph& other) {
    // Look for common path names
    std::set<std::string> ourPaths;

    graph.paths.for_each([&](vg::Path& path) {
        ourPaths.insert(path.name());
    });
    std::set<std::string> sharedPaths;
    other.graph.paths.for_each([&](vg::Path& path) {
        std::string pathName = path.name();
        if(ourPaths.count(pathName)) {
            sharedPaths.insert(pathName);
        }
    });

    if(sharedPaths.size() == 0) {
        // Warn the user that no merging can happen.
        std::cerr << "WARNING: No shared paths exist to merge on!" << std::endl;
    }

    for(std::string pathName : sharedPaths) {
        // We zip along every shared path

        // Get the mappings
        std::list<vg::Mapping>& ourPath = graph.paths.get_path(pathName);
        std::list<vg::Mapping>& theirPath = other.graph.paths.get_path(pathName);

        // Go through each and make sure their lengths agree.
        std::cerr << "Checking " << pathName << " in " << name << " graph." << std::endl;
        size_t ourLength = scanPath(ourPath);
        std::cerr << "Checking " << pathName << " in " << other.name << " graph." << std::endl;
        size_t theirLength = other.scanPath(theirPath);

        if(ourLength != theirLength) {
            // These graphs disagree and we can't merge them without risking merging on an offset.
            std::cerr << "Path length mismatch for " << pathName << ": " << ourLength <<
                " in " << name << " vs. " << theirLength << " in " << other.name << std::endl;
            throw std::runtime_error("Path length mismatch");
        }

        std::cerr << "Processing path " << pathName << std::endl;

        // Do thje actual merge
        pinchOnPaths(ourPath, other, theirPath);
    }
}

void EmbeddedGraph::pinchOnPaths(std::list<vg::Mapping>& path, EmbeddedGraph& other,
    std::list<vg::Mapping>& otherPath) {

    // Make iterators to go through them together
    std::list<vg::Mapping>::iterator ourMapping = path.begin();
    std::list<vg::Mapping>::iterator theirMapping = otherPath.begin();

    // Keep track of where we are alogn each path, so we can get mapping
    // overlap
    int64_t ourPathBase = 0;
    int64_t theirPathBase = 0;

    while(ourMapping != path.end() && theirMapping != otherPath.end()) {
        // Go along the two paths.
#ifdef debug
        std::cerr << "At " << ourPathBase << " in graph 1, " << theirPathBase << " in graph 2." << std::endl;

        std::cerr << "Our mapping: " << pb2json(*ourMapping) << std::endl;
        std::cerr << "Their mapping: " << pb2json(*theirMapping) << std::endl;
#endif

        // Make sure the mappings are perfect matches
        assert(mappingIsPerfectMatch(*ourMapping));
        assert(mappingIsPerfectMatch(*theirMapping));

        // See how long our mapping is and how long their mapping is
        int64_t ourMappingLength = mappingLength(*ourMapping, graph);
        int64_t theirMappingLength = mappingLength(*theirMapping, other.graph);

#ifdef debug
        std::cerr << "Our mapping is " << ourMappingLength << " bases on node " << (*ourMapping).position().node_id() <<
            " offset " << (*ourMapping).position().offset() << " orientation " << (*ourMapping).is_reverse() << std::endl;
        std::cerr << "Their mapping is " << theirMappingLength << " bases on node " << (*theirMapping).position().node_id() <<
            " offset " << (*theirMapping).position().offset() << " orientation " << (*theirMapping).is_reverse() << std::endl;
#endif

        // See how much they overlap (start and length in each mapping)
        if(ourPathBase < theirPathBase + theirMappingLength &&
            theirPathBase < ourPathBase + ourMappingLength) {
            // The two ranges do overlap
            // Find their first base
            int64_t overlapStart = std::max(ourPathBase, theirPathBase);
            // And their past-the-end base
            int64_t overlapEnd = std::min(ourPathBase + ourMappingLength,
                theirPathBase + theirMappingLength);
            // How long soes that make the overlap?
            int64_t overlapLength = overlapEnd - overlapStart;

#ifdef debug
            std::cerr << "The mappings overlap for " << overlapLength << " bp" << std::endl;
#endif

            // Figure out where that overlapped region is in each graph
            // (start, length, and orientation in each mapping's node).
            // Start at the positions where the nodes start.
            stPinchThread* ourThread, *theirThread;
            int64_t ourOffset, theirOffset;
            bool ourIsReverse, theirIsReverse;

            std::tie(ourThread, ourOffset, ourIsReverse) = embedding.at((*ourMapping).position().node_id());
            std::tie(theirThread, theirOffset, theirIsReverse) = other.embedding.at((*theirMapping).position().node_id());

            // Advance by the offset in the node at which the mapping starts
            ourOffset += (*ourMapping).position().offset() * (ourIsReverse ? -1 : 1);
            theirOffset += (*theirMapping).position().offset() * (theirIsReverse ? -1 : 1);

            // Advance up to the start of the overlap, accounting for the
            // orientation of both the mapping in the node and the node in
            // the thread.
            ourOffset += (overlapStart - ourPathBase) * (ourIsReverse != (*ourMapping).is_reverse() ? -1 : 1);
            theirOffset += (overlapStart - theirPathBase) * (theirIsReverse != (*theirMapping).is_reverse() ? -1 : 1);

            // Pull back to the actual start of the overlap in thread
            // coordinates if it is going backward on the thread in question
            // from the mapping's start position. The -1 accounts for the
            // inclusiveness of the original end coordinate, and going to an
            // end-exclusive system.
            if(ourIsReverse != (*ourMapping).is_reverse()) {
                ourOffset -= overlapLength - 1;
            }
            if(theirIsReverse != (*theirMapping).is_reverse()) {
                theirOffset -= overlapLength - 1;
            }

            // Should we pinch the things relatively forward (0) or
            // relatively reverse (1)? Calculated by xor-ing all the flags
            // that could, by themselves, cause us to pinch in opposite
            // orientations.
            bool relativeOrientation = (ourIsReverse != (*ourMapping).is_reverse() !=
                theirIsReverse != (*theirMapping).is_reverse());

#ifdef debug
            std::cerr << "Pinch thread " << stPinchThread_getName(ourThread) << ":" << ourOffset << " and " <<
                stPinchThread_getName(theirThread) << ":" << theirOffset << " for " << overlapLength <<
                " bases in orientation " << (relativeOrientation ? "reverse" : "forward") << std::endl;
#endif

            // Pinch the threads, making sure to convert to pinch graph orientations, which are backward.
            stPinchThread_pinch(ourThread, theirThread, ourOffset, theirOffset, overlapLength, !relativeOrientation);

        }

        // Advance the mapping that ends first, or, if both end at the same place, advance both
        int64_t minNextBase = std::min(ourPathBase + ourMappingLength, theirPathBase + theirMappingLength);
        if(ourPathBase + ourMappingLength == minNextBase) {
            // We end first, so advance us
            ourPathBase = minNextBase;
            ++ourMapping;
#ifdef debug
            std::cerr << "Advanced in our thread" << std::endl;
#endif
        }
        if(theirPathBase + theirMappingLength == minNextBase) {
            // They end first, so advance them
            theirPathBase = minNextBase;
            ++theirMapping;
#ifdef debug
            std::cerr << "Advanced in their thread" << std::endl;
#endif
        }

        // If you hit the end of one path before the end of the other, complain

    }

    if((ourMapping == path.end()) != (theirMapping == otherPath.end())) {
        std::cerr << "We ran out of path in one graph and not in the other!" << std::endl;

        if(ourMapping != path.end()) {
            std::cerr << "We have a mapping" << std::endl;
            std::cerr << "Our mapping: " << pb2json(*ourMapping) << std::endl;
        }

        if(theirMapping != otherPath.end()) {
            std::cerr << "They have a mapping" << std::endl;
            std::cerr << "Their mapping: " << pb2json(*theirMapping) << std::endl;
        }

        // We should reach the end at the same time, but we didn't
        throw std::runtime_error("Ran out of mappings on one path before the other!");
    }

}

std::list<vg::Mapping> EmbeddedGraph::makeMinimalPath(
    std::string& kmer, std::list<vg::NodeTraversal>::iterator occurrence,
    int offset, std::list<vg::NodeTraversal>& path) {

    // Generate a path (std::list<vg::Mapping>) that describes only the
    // kmer.
    std::list<vg::Mapping> minimalPath;

    // How many bases of the kmer are yet to be accounted for?
    size_t remainingKmerLength = kmer.size();

    // What will the offset from where we enter the next node be? Will only
    // be nonzero on the first node.
    size_t nextOffset = offset;

    for(std::list<vg::NodeTraversal>::iterator i = occurrence; i != path.end() && remainingKmerLength > 0; ++i) {
        // For every node the kmer visits

        // Make a Mapping to this node
        vg::Mapping mapping;

        // How long is the node we're mapping to?
        size_t nodeLength = (*i).node->sequence().size();

        // Set the node ID we map to
        mapping.mutable_position()->set_node_id((*i).node->id());
        // Set the offset we map to
        mapping.mutable_position()->set_offset(nextOffset);
        if((*i).backward) {
            // Adjust so we actually come to the right side instead of the
            // left.
            mapping.set_is_reverse(true);

            // We need to correct the offset to count from the start of the
            // underlying, reversed node, instead of the start of the
            // traversal.
            mapping.mutable_position()->set_offset(nodeLength - nextOffset - 1);
        }

        // Populate the length of the mapping, in a single perfect match
        // edit.
        vg::Edit* edit = mapping.add_edit();

        if(remainingKmerLength >= (nodeLength - nextOffset)) {
            // We don't finish with this node. Map over all of it.
            edit->set_from_length(nodeLength - nextOffset);
            edit->set_to_length(nodeLength - nextOffset);

            // Update the remaining kmer length to account for how much we
            // used in this node.
            remainingKmerLength -= (nodeLength - nextOffset);
        } else {
            // We do finish in this node. Map over only the part we actually
            // cover.
            edit->set_from_length(remainingKmerLength);
            edit->set_to_length(remainingKmerLength);

            // We consumed the rest of the kmer length.
            remainingKmerLength = 0;
        }

        // Adjust the offset for the next iteration. It can only be nonzero
        // for the first node.
        nextOffset = 0;

        // Add the mapping to the path
        minimalPath.push_back(mapping);
    }

    // Spit back the minimal path we have constructed, with only the Mappings
    // covering the actual kmer sequence.
    return minimalPath;

}

bool EmbeddedGraph::paths_equal(std::list<vg::Mapping>& path1, std::list<vg::Mapping>& path2) {
    // We're going to structurally compare paths that we know are made by makeMinimalPath.
    // We therefore can look at only certain fields.

    if(path1.size() != path2.size()) {
        // They can't be equal if they differ in number of mappings.
        return false;
    }

    // Loop through the two paths in parallel. See
    // <http://stackoverflow.com/a/19933798>
    auto i = path1.begin();
    auto j = path2.begin();

    for(; i != path1.end() && j != path2.end(); ++i, ++j) {
        auto& mapping1 = *i;
        auto& mapping2 = *j;

        // Compare all the fields of the mappings

        if(mapping1.position().node_id() != mapping2.position().node_id()) {
            return false;
        }

        if(mapping1.position().offset() != mapping2.position().offset()) {
            return false;
        }

        if(mapping1.is_reverse() != mapping2.is_reverse()) {
            return false;
        }

        if(mapping1.edit_size() != mapping2.edit_size()) {
            return false;
        }

        for(int k = 0; k < mapping1.edit_size(); k++) {
            auto& edit1 = mapping1.edit(k);
            auto& edit2 = mapping2.edit(k);

            // Compare all the fields of each edit

            if(edit1.from_length() != edit2.from_length()) {
                return false;
            }

            if(edit1.to_length() != edit2.to_length()) {
                return false;
            }
        }
    }

    // If we get here, all the mappings match
    return true;
}

std::list<vg::Mapping> EmbeddedGraph::reverse_path(std::list<vg::Mapping> path) {
    // We need a function variable so we can supply a non-const reference.
    std::function<int64_t(int64_t)> getNodeLength = [&](int64_t nodeId) {
        // We need to be able to provide the sizes of nodes to do
        // this, and we get those sizes from our graph.
        return graph.get_node(nodeId)->sequence().size();
    };

    std::list<vg::Mapping> pathRev;
    for(auto& mapping : path) {
        // Reverse each mapping
        vg::Mapping reversed = vg::reverse_mapping(mapping, getNodeLength);

        // Put the mapping at the front of our new list (to reverse the order)
        pathRev.push_front(reversed);
    }

    return pathRev;
}

void EmbeddedGraph::pinchOnKmers(vg::Index& ourIndex, EmbeddedGraph& other,
    vg::Index& theirIndex, size_t kmerSize, size_t edgeMax) {

    // Actually good strategy:
    // Loop through the kmer instances in our index
    // For each first kmer instance followed by a different kmer (or for the last kmer instance if it's the first with its value)
    // Look it up in the other index and see if it's unique there too
    // If so, get the starting point
    // Search out a path that matches the kmer
    // Do the same to get the path in the other graph
    // Merge the paths together (make tow std::list<vg::Mapping> lists and use the path merge code)

    // Alternate easy startegy that I will use:

    // Keep track of the paths for unique kmers in our graph.
    // A kmer that occurs along multiple paths, but which the index still thinks is unique,
    std::map<std::string, std::list<vg::Mapping>> ourUniqueKmerPaths;
    // We need to protect it with a mutex
    std::mutex ourUniqueKmerPathsMutex;

    // And in the other graph
    std::map<std::string, std::list<vg::Mapping>> theirUniqueKmerPaths;
    // We need to protect it with a mutex
    std::mutex theirUniqueKmerPathsMutex;

    #ifdef debug
        std::cerr << "Looking for kmers of size " << kmerSize << "." << std::endl;
    #endif

    auto observeKmer = [this](std::string& kmer,
        std::list<vg::NodeTraversal>::iterator occurrence, int offset,
        std::list<vg::NodeTraversal>& path, vg::Index& index,
        std::map<std::string, std::list<vg::Mapping>>& uniqueKmerPaths,
        std::mutex& uniqueKmerPathsMutex) {

        // We receive each kmer, starting at the given offset from the left of
        // the given traversal, along the given path.

        // We will make sure it is unique in our graph, and then add it to our
        // table of unique kmers.

        if(index.approx_size_of_kmer_matches(kmer) > MAX_UNIQUE_KMER_BYTES) {
            // If its data takes up lots of space, it's not unique
            return;
        }

        // Count up how many times it occurs
        size_t kmerCount = 0;
        index.for_kmer_range(kmer, [&](std::string& key, std::string& value) {
            kmerCount++;
        });

        // Also include occurrences of the reverse complement
        index.for_kmer_range(vg::reverse_complement(kmer), [&](std::string& key, std::string& value) {
            kmerCount++;
        });

#ifdef debug
        #pragma omp critical(cerr)
        std::cerr << "Kmer " << kmer << " occurs " << kmerCount << " times in " << getName() << "." << std::endl;
#endif

        if(kmerCount > 1) {
            // It's not unique in our graph
            return;
        }

        // If we get here it occurs only in one place in our graph.
        // But does it occur on multiple paths?

        // Get the minimal path for the kmer
        std::list<vg::Mapping> minimalPath(makeMinimalPath(kmer, occurrence, offset, path));

        // Compute what it would look like as a reverse complement
        std::list<vg::Mapping> minimalPathRev = reverse_path(minimalPath);

        // Now we need to do serial access to the deduplication index
        std::lock_guard<std::mutex> guard(uniqueKmerPathsMutex);

        // Look up the kmer in the index
        auto kv = uniqueKmerPaths.find(kmer);

        // And the reverse version
        auto reverse_kv = uniqueKmerPaths.find(vg::reverse_complement(kmer));

        if(kv == uniqueKmerPaths.end()) {
            if(reverse_kv == uniqueKmerPaths.end()) {
                // It's not in there and neither is its reverse complement.
                // Add it with the path we just made.
                uniqueKmerPaths[kmer] = minimalPath;
#ifdef debug
                #pragma omp critical(cerr)
                std::cerr << "Found unique kmer " << kmer << "." << std::endl;
#endif
            } else {
                // The reverse complement is in but this kmer isn't.
                // Find the path the reverse complement is using.
                auto& oldPath = (*reverse_kv).second;

                if(oldPath.size() == 0) {
                    // If it's in there with an empty minimal path, it's already
                    // a dupe. Do nothing.
                } else if(paths_equal(oldPath, minimalPathRev)) {
                    // If it's in there with a nonempty minimal path and it
                    // matches the one for our reverse complement, do nothing.
                } else {
                    // If it's in there with a nonempty minimal path and it
                    // doesn't match the one we just made, empty its path to
                    // mark it as a duplicate.
                    oldPath.clear();

#ifdef debug
                    #pragma omp critical(cerr)
                    std::cerr << "Formerly unique kmer " << kmer << " is now RC-duplicated." << std::endl;
#endif

                }
            }
        } else {
            // This kmer is in.
            // Make a reference to the path used.
            auto& oldPath = (*kv).second;

            if(oldPath.size() == 0) {
                // If it's in there with an empty minimal path, it's already a
                // dupe. Do nothing.
            } else if(paths_equal(oldPath, minimalPath)) {
                // If it's in there with a nonempty minimal path and it matches
                // the one we just made, do nothing.
            } else {
                // If it's in there with a nonempty minimal path and it doesn't match
                // the one we just made, empty its path to mark it as a duplicate.
                oldPath.clear();

                if(reverse_kv != uniqueKmerPaths.end()) {
                    // The reverse complement is also in, so we need to
                    // clear it too.
                    (*reverse_kv).second.clear();
                }

#ifdef debug
                    #pragma omp critical(cerr)
                    std::cerr << "Formerly unique kmer " << kmer << " is now duplicated." << std::endl;
#endif
            }
        }

        // The lock guard automatically unlocks

    };

    // Enumerate kmers in one graph with for_each_kmer_parallel
    graph.for_each_kmer_parallel(kmerSize, edgeMax, [&](std::string& kmer,
        std::list<vg::NodeTraversal>::iterator occurrence, int offset,
        std::list<vg::NodeTraversal>& path, vg::VG& kmer_graph) {

        // We receive each kmer, starting at the given offset from the left of
        // the given traversal, along the given path.

        // Observe the kmer for us
        observeKmer(kmer, occurrence, offset, path, ourIndex, ourUniqueKmerPaths, ourUniqueKmerPathsMutex);

    }, true, false); // Accept duplicate kmers, but not kmers with negative offsets.

    // Do the same for the other graph
    other.graph.for_each_kmer_parallel(kmerSize, edgeMax, [&](std::string& kmer,
        std::list<vg::NodeTraversal>::iterator occurrence, int offset,
        std::list<vg::NodeTraversal>& path, vg::VG& kmer_graph) {

        // Observe the kmer for them
        observeKmer(kmer, occurrence, offset, path, theirIndex, theirUniqueKmerPaths, theirUniqueKmerPathsMutex);

    }, true, false); // Accept duplicate kmers, but not kmers with negative offsets.

    // How many shared unique kmers do we find?
    size_t sharedUniqueKmers = 0;

    // Then find the paths for corresponding kmers and merge on them.
    for(auto& kv : ourUniqueKmerPaths) {
        // For each kmer, path pair
        if(kv.second.empty()) {
            // This was really duplicated
            continue;
        }

        // Look up the forward and reverse versions
        auto theirMatch = theirUniqueKmerPaths.find(kv.first);
        auto theirReverseMatch = theirUniqueKmerPaths.find(vg::reverse_complement(kv.first));

        if(theirMatch != theirUniqueKmerPaths.end()) {
            // If the other graph has it, find out where
            auto& theirPath = (*theirMatch).second;

            if(theirPath.empty()) {
                // This was really duplicated
                continue;
            }

            // Merge on the paths
            pinchOnPaths(kv.second, other, theirPath);

#ifdef debug
            std::cerr << "Mutually unique kmer " << kv.first << " pinched on." << std::endl;
#endif
            sharedUniqueKmers++;

        } else if(theirReverseMatch != theirUniqueKmerPaths.end()) {
            // If the other graph has it reverse complemented, find out where
            auto& theirReversePath = (*theirReverseMatch).second;

            if(theirReversePath.empty()) {
                // This was really duplicated
                continue;
            }

            // Flip it to be forward relative to us.
            auto theirPath = other.reverse_path(theirReversePath);

            // Merge on the paths
            pinchOnPaths(kv.second, other, theirPath);

#ifdef debug
            std::cerr << "RC-mutually unique kmer " << kv.first << " pinched on." << std::endl;
#endif
            sharedUniqueKmers++;

        }

    }

    // Report to the user what happened.
    std::cerr << "Pinched on " << sharedUniqueKmers << " shared unique " << kmerSize << "-mers." << std::endl;

    if(sharedUniqueKmers == 0) {
        std::cerr << "WARNING: no kmer pinches performed!" << std::endl;
    }
}

}


text:
require 'httparty'

class Bitly
  include HTTParty
  base_uri 'api.bit.ly/v3'
  format :json

  # :query => {:login :domain :url :apiKey}
  def self.shorten(query={})
    result = get('/shorten', :query => query)
  end
end

redpajama_set_name: RedPajamaGithub


text:
package hrv.band.app.ui.presenter;

import android.net.Uri;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import hrv.band.app.R;
import hrv.band.app.ui.view.activity.IWebView;

import static hrv.band.app.ui.view.activity.web.WebsiteUrls.GOOGLE_FORMS_HOST_URL;
import static hrv.band.app.ui.view.activity.web.WebsiteUrls.HRVBAND_HOST_URL;
import static hrv.band.app.ui.view.activity.web.WebsiteUrls.SURVEY_URL;
import static hrv.band.app.ui.view.activity.web.WebsiteUrls.WEBSITE_ABOUT_URL;
import static hrv.band.app.ui.view.activity.web.WebsiteUrls.WEBSITE_FAQ_URL;
import static hrv.band.app.ui.view.activity.web.WebsiteUrls.WEBSITE_PARAMETER_URL;
import static hrv.band.app.ui.view.activity.web.WebsiteUrls.WEBSITE_PRIVACY_URL;
import static hrv.band.app.ui.view.activity.web.WebsiteUrls.WEBSITE_URL;

public class WebPresenter implements IWebPresenter {

    private IWebView webView;
    private WebViewClient webViewClient;

    public WebPresenter(IWebView webView) {
        this.webView = webView;
        this.webViewClient = new AppWebViewClient();
    }

    @Override
    public void loadUrl(int urlId) {
        switch (urlId) {

            case R.id.web_nav_home:
                webView.loadUrl(WEBSITE_URL);
                break;
            case R.id.web_nav_background:
                webView.loadUrl(WEBSITE_PARAMETER_URL);
                break;
            case R.id.web_nav_faq:
                webView.loadUrl(WEBSITE_FAQ_URL);
                break;
            case R.id.web_nav_privacy:
                webView.loadUrl(WEBSITE_PRIVACY_URL);
                break;
            case R.id.web_nav_about:
                webView.loadUrl(WEBSITE_ABOUT_URL);
                break;
            case R.id.web_nav_survey:
                webView.loadUrl(SURVEY_URL);
                break;
            default: webView.loadUrl(WEBSITE_URL);
        }
    }

    @Override
    public WebViewClient getWebViewClient() {
        return webViewClient;
    }

    /**
     * Checks if the url belongs to the app website. If not it asks the user to open his browser
     * app.
     */
    private class AppWebViewClient extends WebViewClient {
        @Override @SuppressWarnings("deprecation")
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            if(Uri.parse(url).getHost().startsWith(HRVBAND_HOST_URL)) {
                return false;
            }
            if (Uri.parse(url).getHost().startsWith(GOOGLE_FORMS_HOST_URL)) {
                return false;
            }
            webView.openBrowserIntent(url);
            return true;
        }
    }
}


text:
package com.github.davidmoten.rx2;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

import org.junit.Test;

import com.github.davidmoten.junit.Asserts;
import com.github.davidmoten.rx2.util.ZippedEntry;

import io.reactivex.Flowable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;

public class BytesTest {

    @Test
    public void testUnzip() {
        List<String> list = Bytes.unzip(new File("src/test/resources/test.zip"))
                .concatMap(new Function<ZippedEntry, Flowable<String>>() {

                    @Override
                    public Flowable<String> apply(ZippedEntry entry) {
                        return Flowable.just(entry.getName()).concatWith(Strings.from(entry.getInputStream()));
                    }
                }).toList().blockingGet();
        assertEquals(Arrays.asList("document1.txt", "hello there", "document2.txt", "how are you going?"), list);
    }

    @Test
    public void testUnzipPartial() {
        InputStream is = BytesTest.class.getResourceAsStream("/test.zip");
        assertNotNull(is);
        List<String> list = Bytes.unzip(is).concatMap(new Function<ZippedEntry, Flowable<String>>() {

            @Override
            public Flowable<String> apply(ZippedEntry entry) {
                try {
                    return Flowable.just((char) entry.getInputStream().read() + "");
                } catch (IOException e) {
                    return Flowable.error(e);
                }
            }
        }).toList().blockingGet();
        assertEquals(Arrays.asList("h", "h"), list);
    }

    @Test
    public void testUnzipCheckEntryFields() {
        Bytes.unzip(new File("src/test/resources/test.zip")) //
                .filter(new Predicate<ZippedEntry>() {

                    @Override
                    public boolean test(ZippedEntry entry) {
                        return entry.getName().equals("document2.txt");
                    }
                }).doOnNext(new Consumer<ZippedEntry>() {
                    @Override
                    public void accept(ZippedEntry e) throws Exception {
                        assertEquals(1091476648, e.getCrc());
                        assertNull(e.getComment());
                        assertEquals(18, e.getCompressedSize());
                        assertEquals(18, e.getSize());
                        assertEquals(0, e.getMethod());
                        assertEquals("document2.txt", e.getName());
                        assertTrue(e.getTime() > 0);
                        assertNotNull(e.getExtra());
                    }
                }).test().assertNoErrors().assertComplete();
    }

    @Test
    public void testUnzipExtractSpecificFile() {
        List<String> list = Bytes.unzip(new File("src/test/resources/test.zip")).filter(new Predicate<ZippedEntry>() {

            @Override
            public boolean test(ZippedEntry entry) {
                return entry.getName().equals("document2.txt");
            }
        }).concatMap(new Function<ZippedEntry, Flowable<String>>() {

            @Override
            public Flowable<String> apply(ZippedEntry entry) {
                return Strings.from(entry.getInputStream());
            }
        }).toList().blockingGet();
        assertEquals(Arrays.asList("how are you going?"), list);
    }

    @Test
    public void isUtilClass() {
        Asserts.assertIsUtilityClass(Bytes.class);
    }

    @Test
    public void testBytesFromFileLowBufferSize() throws IOException {
        File file = new File("target/testFromFile");
        file.delete();
        FileOutputStream out = new FileOutputStream(file);
        out.write("abcdefg".getBytes());
        out.close();
        final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        Bytes //
                .from(file, 4) //
                .doOnNext(new Consumer<byte[]>() {
                    @Override
                    public void accept(byte[] b) {
                        try {
                            bytes.write(b);
                        } catch (IOException e) {
                            throw new RuntimeException();
                        }
                    }
                }).subscribe();
        bytes.close();
        assertArrayEquals("abcdefg".getBytes(), bytes.toByteArray());
    }

    @Test
    public void testBytesFromFileWhenDoesNotExist() {
        Bytes.from(new File("target/" + UUID.randomUUID())) //
                .test() //
                .assertError(FileNotFoundException.class);
    }

    @Test
    public void testBytesFromInputStreamDefaultBufferSize() {
        String s = "hello there";
        Bytes.from(new ByteArrayInputStream(s.getBytes(Strings.UTF_8))) //
                .to(Bytes.collect()) //
                .map(new Function<byte[], String>() {

                    @Override
                    public String apply(byte[] b) throws Exception {
                        return new String(b, Strings.UTF_8);
                    }
                }) //
                .test().assertValue("hello there") //
                .assertComplete();
    }

    @Test
    public void testBytesFromFileDefaultBufferSize() throws IOException {
        File file = new File("target/testFromFile");
        file.delete();
        FileOutputStream out = new FileOutputStream(file);
        out.write("abcdefg".getBytes());
        out.close();
        final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        Bytes //
                .from(file) //
                .doOnNext(new Consumer<byte[]>() {
                    @Override
                    public void accept(byte[] b) {
                        try {
                            bytes.write(b);
                        } catch (IOException e) {
                            throw new RuntimeException();
                        }
                    }
                }).subscribe();
        bytes.close();
        assertArrayEquals("abcdefg".getBytes(), bytes.toByteArray());
    }

    @Test
    public void testCollect() {
        byte[] a = { 1, 2, 3 };
        byte[] b = { 4, 5, 6 };
        byte[] result = Flowable //
                .just(a, b) //
                .to(Bytes.collect()).blockingGet();
        assertTrue(Arrays.equals(new byte[] { 1, 2, 3, 4, 5, 6 }, result));
    }

    @Test
    public void testCollectWithEmpty() {
        byte[] a = { 1, 2, 3 };
        byte[] b = {};
        byte[] result = Flowable //
                .just(a, b) //
                .to(Bytes.collect()).blockingGet();
        assertTrue(Arrays.equals(new byte[] { 1, 2, 3 }, result));
    }

    @Test
    public void testCollectWithEmpties() {
        byte[] a = {};
        byte[] b = {};
        byte[] result = Flowable //
                .just(a, b) //
                .to(Bytes.collect()).blockingGet();
        assertTrue(Arrays.equals(new byte[] {}, result));
    }

}


text:
import {TypeaheadDirective}from './typeahead.directive';

export class TypeaheadOptions {
	public placement: string;
	public animation: boolean;
	public typeaheadRef: TypeaheadDirective;

	public constructor(options: TypeaheadOptions) {
		Object.assign(this, options);
	}
}


text:
<?php
require_once __DIR__.'/bootstrap.php';

use Api\Application;

$app = new Application(['em' => $em]);


text:
package org.deviceconnect.android.deviceplugin.chromecast;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import com.google.android.gms.cast.Cast;
import com.google.android.gms.cast.CastDevice;
import com.google.android.gms.cast.MediaInfo;
import com.google.android.gms.cast.MediaStatus;
import com.google.android.gms.cast.RemoteMediaPlayer.MediaChannelResult;
import com.google.android.gms.common.api.Status;

import org.deviceconnect.android.deviceplugin.chromecast.core.ChromeCastApplication;
import org.deviceconnect.android.deviceplugin.chromecast.core.ChromeCastDiscovery;
import org.deviceconnect.android.deviceplugin.chromecast.core.ChromeCastHttpServer;
import org.deviceconnect.android.deviceplugin.chromecast.core.ChromeCastMediaPlayer;
import org.deviceconnect.android.deviceplugin.chromecast.core.ChromeCastMessage;
import org.deviceconnect.android.deviceplugin.chromecast.profile.ChromeCastCanvasProfile;
import org.deviceconnect.android.deviceplugin.chromecast.profile.ChromeCastMediaPlayerProfile;
import org.deviceconnect.android.deviceplugin.chromecast.profile.ChromeCastNotificationProfile;
import org.deviceconnect.android.deviceplugin.chromecast.profile.ChromeCastServiceDiscoveryProfile;
import org.deviceconnect.android.deviceplugin.chromecast.profile.ChromeCastSystemProfile;
import org.deviceconnect.android.event.Event;
import org.deviceconnect.android.event.EventManager;
import org.deviceconnect.android.event.cache.db.DBCacheController;
import org.deviceconnect.android.message.DConnectMessageService;
import org.deviceconnect.android.message.MessageUtils;
import org.deviceconnect.android.profile.MediaPlayerProfile;
import org.deviceconnect.android.profile.ServiceDiscoveryProfile;
import org.deviceconnect.android.profile.ServiceInformationProfile;
import org.deviceconnect.android.profile.SystemProfile;
import org.deviceconnect.message.DConnectMessage;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * メッセージサービス (Chromecast).
 * <p>
 * Chromecastデバイスプラグインのサービス
 * </p>
 * @author NTT DOCOMO, INC.
 */
public class ChromeCastService extends DConnectMessageService implements
        ChromeCastDiscovery.Callbacks,
        ChromeCastMediaPlayer.Callbacks,
        ChromeCastMessage.Callbacks,
        ChromeCastApplication.Result {
    /**
     * Chromecastのサーバポート.
     */
    private static final int SERVER_PORT = 38088;

    /** Chromecast Discovery. */
    private ChromeCastDiscovery mDiscovery;
    /** Chromecast Application. */
    private ChromeCastApplication mApplication;
    /** Chromecast MediaPlayer. */
    private ChromeCastMediaPlayer mMediaPlayer;
    /** Chromecast Message. */
    private ChromeCastMessage mMessage;
    /** ChromecastHttpServer. */
    private ChromeCastHttpServer mServer;
    /** ChromecastMediaPlayerProfile. */
    private ChromeCastMediaPlayerProfile mMediaPlayerProfile;
    /** StatusChange時のServiceId. */
    private String mServiceIdOnStatusChange = null;
    /** StatusChange時のSessionKey. */
    private String mSessionKeyOnStatusChange = null;
    /** MediaPlayerのステータスアップデートフラグ. */
    private boolean mEnableCastMediaPlayerStatusUpdate = false;
    /** Async Response Array List. */
    private ArrayList<Callback> mAsyncResponse = new ArrayList<Callback>();

    /**
     * ChromeCastが接続完了してからレスポンスを返すためのCallbackを返す.
     * @author NTT DOCOMO, INC.
     */
    public interface Callback {
        /**
         * レスポンス.
         */
        void onResponse();
    }

    @Override
    public void onCreate() {
        super.onCreate();

        String appId = getString(R.string.application_id);
        String appMsgUrn = getString(R.string.application_message_urn);

        int portCount = 0;
        while (portCount < 500) { // Portを決定する
            try {
                mServer = new ChromeCastHttpServer("0.0.0.0", SERVER_PORT + portCount);
                mServer.start();
                break;
            } catch (IOException e) {
                portCount++;
            }
        }

        mDiscovery = new ChromeCastDiscovery(this, appId);
        mDiscovery.setCallbacks(this);
        mDiscovery.registerEvent();
        mApplication = new ChromeCastApplication(this, appId);
        mApplication.setResult(this);
        mMediaPlayer = new ChromeCastMediaPlayer(mApplication);
        mMediaPlayer.setCallbacks(this);
        mMessage = new ChromeCastMessage(mApplication, appMsgUrn);
        mMessage.setCallbacks(this);

        EventManager.INSTANCE.setController(new DBCacheController(this));
        addProfile(new ChromeCastCanvasProfile());
        addProfile(new ChromeCastNotificationProfile());
        mMediaPlayerProfile = new ChromeCastMediaPlayerProfile();
        addProfile(mMediaPlayerProfile);
    }

    @Override
    public void onDestroy() {
        mServer.stop();
        if (mApplication != null) {
            mApplication.teardown();
        }
        super.onDestroy();
    }

    @Override
    protected SystemProfile getSystemProfile() {
        return new ChromeCastSystemProfile();
    }

    @Override
    protected ServiceInformationProfile getServiceInformationProfile() {
        return new ServiceInformationProfile(this) { };
    }

    @Override
    protected ServiceDiscoveryProfile getServiceDiscoveryProfile() {
        return new ChromeCastServiceDiscoveryProfile(this);
    }

    @Override
    public void onCastDeviceUpdate(final ArrayList<String> devices) {
        if (devices.size() == 0) {
            if (BuildConfig.DEBUG) {
                Log.d("ChromeCastDiscovery", "size:0");
            }
            if (mApplication != null) {
                mApplication.teardown();
            }
            if (mDiscovery != null) {
                mDiscovery.unregisterEvent();
            }
        }
    }

    @Override
    public void onCastDeviceSelected(final CastDevice selectedDevice) {
        CastDevice currentDevice = mApplication.getSelectedDevice();
        if (currentDevice != null) {
            if (!currentDevice.getDeviceId().equals(selectedDevice.getDeviceId())) {
                mApplication.setSelectedDevice(selectedDevice);
                mApplication.reconnect();
            } else {
                mApplication.connect();
            }
        } else {
            mApplication.setSelectedDevice(selectedDevice);
            mApplication.connect();
        }
    }

    @Override
    public void onCastDeviceUnselected() {
        mApplication.reconnect();
    }

    /**
     * Connected By Selected ChromeCast.
     * @param serviceId Service Identifier
     * @param callback Asynchronous Response
     */
    public synchronized void connectChromeCast(final String serviceId,
                                  final Callback callback) {
        if (mDiscovery.getSelectedDevice() != null) {
            if (mDiscovery.getSelectedDevice().getFriendlyName().equals(serviceId)
                    && !mApplication.getGoogleApiClient().isConnecting()) {
                mApplication.connect();
                // Whether application that had been started before whether other apps
                if ((Cast.CastApi.getApplicationStatus(mApplication.getGoogleApiClient())
                    .equals(""))) {
                    for (int i = 0; i < mAsyncResponse.size(); i++) {
                        Callback call = mAsyncResponse.remove(i);
                        call.onResponse();
                    }
                    callback.onResponse();
                } else  {
                    mAsyncResponse.add(callback);
                }
                return;
            } else {
                // Request in connection queuing
                mAsyncResponse.add(callback);
                return;
            }
        }
        mAsyncResponse.add(callback);
        mDiscovery.setRouteName(serviceId);
    }
    /**
     * ChromeCastDiscoveryを返す.
     * @return  ChromeCastDiscovery
     */
    public ChromeCastDiscovery getChromeCastDiscovery() {
        return mDiscovery;
    }
    /**
     * ChromeCastApplicationを返す.
     * @return  ChromeCastApplication
     */
    public ChromeCastApplication getChromeCastApplication() {
        return mApplication;
     }
    /**
     * ChromeCastMediaPlayerを返す.
     * @return  ChromeCastMediaPlayer
     */
    public ChromeCastMediaPlayer getChromeCastMediaPlayer() {
        return mMediaPlayer;
    }
    /**
     * ChromeCastMessageを返す.
     * @return  ChromeCastMessage
     */
    public ChromeCastMessage getChromeCastMessage() {
        return mMessage;
    }
    /**
     * ChromeCastHttpServerを返す.
     * @return  ChromeCastHttpServer
     */
    public ChromeCastHttpServer getChromeCastHttpServer() {
        return mServer;
    }

    /**
     * StatusChange通知を有効にする.
     *
     * @param response レスポンス
     * @param serviceId デバイスを識別するID
     * @param sessionKey イベントを識別するKey
     */
    public void registerOnStatusChange(final Intent response, final String serviceId, final String sessionKey) {
        mServiceIdOnStatusChange = serviceId;
        mSessionKeyOnStatusChange = sessionKey;
        mEnableCastMediaPlayerStatusUpdate = true;
        response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
        response.putExtra(DConnectMessage.EXTRA_VALUE, "Register OnStatusChange event");
        sendBroadcast(response);
    }

    /**
     * StatusChange通知を無効にする.
     *
     * @param response レスポンス
     */
    public void unregisterOnStatusChange(final Intent response) {
        mServiceIdOnStatusChange = null;
        mSessionKeyOnStatusChange = null;
        mEnableCastMediaPlayerStatusUpdate = false;
        response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
        response.putExtra(DConnectMessage.EXTRA_VALUE, "Unregister OnStatusChange event");
        sendBroadcast(response);
    }

    @Override
    public void onChromeCastMediaPlayerStatusUpdate(final MediaStatus status) {
        MediaInfo info = status.getMediaInfo();
        String playStatusString = mMediaPlayerProfile.getPlayStatus(status.getPlayerState());

        if (mEnableCastMediaPlayerStatusUpdate) {
            List<Event> events = EventManager.INSTANCE.getEventList(mServiceIdOnStatusChange,
                    MediaPlayerProfile.PROFILE_NAME, null,
                    MediaPlayerProfile.ATTRIBUTE_ON_STATUS_CHANGE);

            for (int i = 0; i < events.size(); i++) {
                Event event = events.get(i);
                if (event.getSessionKey().equals(mSessionKeyOnStatusChange)) {
                    Intent intent = EventManager.createEventMessage(event);
                    MediaPlayerProfile.setAttribute(intent,
                            MediaPlayerProfile.ATTRIBUTE_ON_STATUS_CHANGE);
                    Bundle mediaPlayer = new Bundle();
                    MediaPlayerProfile.setStatus(mediaPlayer, playStatusString);
                    if (info != null) {
                        MediaPlayerProfile.setMediaId(mediaPlayer, info.getContentId());
                        MediaPlayerProfile.setMIMEType(mediaPlayer, info.getContentType());
                    } else {
                        MediaPlayerProfile.setMediaId(mediaPlayer, "");
                        MediaPlayerProfile.setMIMEType(mediaPlayer, "");
                    }
                    MediaPlayerProfile.setPos(mediaPlayer, (int) status.getStreamPosition() / 1000);
                    MediaPlayerProfile.setVolume(mediaPlayer, status.getStreamVolume());
                    MediaPlayerProfile.setMediaPlayer(intent, mediaPlayer);
                    getContext().sendBroadcast(intent);
                }
            }
        }
    }

    /**
     * ステータスに基づいて、レスポンスする.
     * @param response レスポンス
     * @param result Chromecastからの状態
     * @param message Chromecastの状態
     */
    private void onChromeCastResult(final Intent response, final Status result, final String message) {
        if (result == null) {
            MessageUtils.setIllegalDeviceStateError(response, message);
            sendBroadcast(response);
        } else {
            if (result.isSuccess()) {
                response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
            } else {
                if (message == null) {
                    MessageUtils.setIllegalDeviceStateError(response);
                } else {
                    MessageUtils.setIllegalDeviceStateError(response, message + " is error");
                }
            }
            sendBroadcast(response);
        }
    }
    @Override
    public void onChromeCastMediaPlayerResult(final Intent response,
                        final MediaChannelResult result, final String message) {
        if (result == null) {
            MessageUtils.setIllegalDeviceStateError(response, message);
            sendBroadcast(response);
        } else {
            onChromeCastResult(response, result.getStatus(), message);
        }
    }

    @Override
    public synchronized void onChromeCastConnected() {
        for (int i = 0; i < mAsyncResponse.size(); i++) {
            Callback callback = mAsyncResponse.remove(i);
            callback.onResponse();
        }
    }

    @Override
    public void onChromeCastMessageResult(final Intent response, final Status result, final String message) {
        onChromeCastResult(response, result, message);
    }
}


text:
//
//  FXW_AptBtn.h
//  AptLandlord
//
//  Created by kenshin on 2017/7/28.
//  Copyright © 2017年 m2mKey. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface FXW_AptBtn : UIView

/**
 唯一初始化方法

 @param frame       frame width = 140 height = 50 这两个参数值写死
 @param title       按钮名字
 @param imgName     图片名字
 @return            FXW_AptBtn实例
 */
-(instancetype)initWithFrame:(CGRect)frame title:(NSString *)title imgName:(NSString *)imgName;

typedef void (^FXW_AptBtnBlock)(FXW_AptBtn *cuObj);

- (void)click:(FXW_AptBtnBlock)block;

@end


text:
class ChromeAppViewAsh;
struct MetroViewerHostMsg_SaveAsDialogParams;

namespace base {
class FilePath;
}

// Base class for the file pickers.
class FilePickerSessionBase {
 public:
  // Creates a file picker for open_file_name.
  explicit FilePickerSessionBase(ChromeAppViewAsh* app_view,
                                 const string16& title,
                                 const string16& filter,
                                 const string16& default_path);

  virtual ~FilePickerSessionBase() {
  }

  // Runs the picker, returns true on success.
  bool Run();

  const string16& result() const {
    return result_;
  }

  bool success() const {
    return success_;
  }

 protected:
  // Creates, configures and starts a file picker.
  // If the HRESULT returned is a failure code the file picker has not started,
  // so no callbacks should be expected.
  virtual HRESULT StartFilePicker() = 0;

  // True iff a file picker has successfully finished.
  bool success_;

  // The title of the file picker.
  string16 title_;

  // The file type filter.
  string16 filter_;

  // The starting directory/file name.
  string16 default_path_;

  // Pointer to the ChromeAppViewAsh instance. We notify the ChromeAppViewAsh
  // instance when the file open/save operations complete.
  ChromeAppViewAsh* app_view_;

  string16 result_;

 private:
  // Initiate a file picker, must be called on the main metro thread.
  // Returns true on success.
  bool DoFilePicker();

  DISALLOW_COPY_AND_ASSIGN(FilePickerSessionBase);
};

// Provides functionality to display the open file/multiple open file pickers
// metro dialog.
class OpenFilePickerSession : public FilePickerSessionBase {
 public:
  explicit OpenFilePickerSession(ChromeAppViewAsh* app_view,
                                 const string16& title,
                                 const string16& filter,
                                 const string16& default_path,
                                 bool allow_multi_select);

  const std::vector<base::FilePath>& filenames() const {
    return filenames_;
  }

  const bool allow_multi_select() const {
    return allow_multi_select_;
  }

 private:
  virtual HRESULT StartFilePicker() OVERRIDE;

  typedef winfoundtn::IAsyncOperation<winstorage::StorageFile*>
      SingleFileAsyncOp;
  typedef winfoundtn::Collections::IVectorView<
      winstorage::StorageFile*> StorageFileVectorCollection;
  typedef winfoundtn::IAsyncOperation<StorageFileVectorCollection*>
      MultiFileAsyncOp;

  // Called asynchronously when a single file picker is done.
  HRESULT SinglePickerDone(SingleFileAsyncOp* async, AsyncStatus status);

  // Called asynchronously when a multi file picker is done.
  HRESULT MultiPickerDone(MultiFileAsyncOp* async, AsyncStatus status);

  // Composes a multi-file result string suitable for returning to a
  // from a storage file collection.
  static HRESULT ComposeMultiFileResult(StorageFileVectorCollection* files,
                                        string16* result);

 private:
  // True if the multi file picker is to be displayed.
  bool allow_multi_select_;
  // If multi select is true then this member contains the list of filenames
  // to be returned back.
  std::vector<base::FilePath> filenames_;

  DISALLOW_COPY_AND_ASSIGN(OpenFilePickerSession);
};

// Provides functionality to display the save file picker.
class SaveFilePickerSession : public FilePickerSessionBase {
 public:
  explicit SaveFilePickerSession(
      ChromeAppViewAsh* app_view,
      const MetroViewerHostMsg_SaveAsDialogParams& params);

  int SaveFilePickerSession::filter_index() const;

 private:
  virtual HRESULT StartFilePicker() OVERRIDE;

  typedef winfoundtn::IAsyncOperation<winstorage::StorageFile*>
      SaveFileAsyncOp;

  // Called asynchronously when the save file picker is done.
  HRESULT FilePickerDone(SaveFileAsyncOp* async, AsyncStatus status);

  int filter_index_;

  DISALLOW_COPY_AND_ASSIGN(SaveFilePickerSession);
};

// Provides functionality to display the folder picker.
class FolderPickerSession : public FilePickerSessionBase {
 public:
  explicit FolderPickerSession(ChromeAppViewAsh* app_view,
                               const string16& title);

 private:
  virtual HRESULT StartFilePicker() OVERRIDE;

  typedef winfoundtn::IAsyncOperation<winstorage::StorageFolder*>
      FolderPickerAsyncOp;

  // Called asynchronously when the folder picker is done.
  HRESULT FolderPickerDone(FolderPickerAsyncOp* async, AsyncStatus status);

  DISALLOW_COPY_AND_ASSIGN(FolderPickerSession);
};

#endif  // CHROME_BROWSER_UI_METRO_DRIVER_FILE_PICKER_ASH_H_


text:
from collections import defaultdict
import inspect

import normalize.exc as exc

PROPERTY_TYPES = dict()

# Duck typing kwargs... for picking the right Property sub-class to instantiate
# based on the kwargs used in the Property() constructor
DUCKWARGS = defaultdict(set)

# a test for whether a value passed to 'default' is sufficient to qualify the
# attribute for v1 upgrade
def looks_like_v1_none(value):
    return not value and value.__hash__ and not callable(value)

def has(selfie, self, args, kwargs):
    """This is called 'has' but is called indirectly.  Each Property sub-class
    is installed with this function which replaces their __new__.

    It is called 'has', because it runs during property declaration, processes
    the arguments and is responsible for returning an appropriate Property
    subclass.  As such it is identical to the 'has' function in Perl's Moose.
    The API does not use the word, but the semantics are the same.

    It is responsible for picking which sub-class of 'self' to invoke.
    Unlike Moose, it will not dynamically create property types; if a type
    does not exist it will be a hard error.

    This function should *only* be concerned with picking the appropriate
    object type, because unlike in Perl, python cannot re-bless objects from
    one class to another.
    """
    if args:
        raise exc.PositionalArgumentsProhibited()
    extra_traits = set(kwargs.pop('traits', tuple()))

    safe_unless_ro = self.__safe_unless_ro__ or any(
        x in kwargs for x in ("required", "isa", "check")
    )
    # detect initializer arguments only supported by a subclass and add
    # them to extra_traits
    for argname in kwargs:
        if argname not in self.all_duckwargs:
            # initializer does not support this arg.  Do any subclasses?
            implies_traits = set()
            for traits, proptype in DUCKWARGS[argname]:
                if isinstance(proptype, type(self)):
                    implies_traits.add(traits)
                    if proptype.__safe_unless_ro__:
                        safe_unless_ro = True
            if len(implies_traits) > 1:
                raise exc.AmbiguousPropertyTraitArg(
                    trait_arg=argname,
                    could_be=" ".join(
                        sorted(x.__name__ for x in implies_traits)
                    ),
                    matched_traits=implies_traits,
                )
            elif not implies_traits:
                raise exc.PropertyArgumentNotKnown(
                    badkwarg=argname,
                    badkwarg_value=kwargs[argname],
                    proptypename=self.__name__,
                    proptype=self,
                )
            else:
                extra_traits.update(list(implies_traits)[0])

    all_traits = set(self.traits) | extra_traits

    if "unsafe" in all_traits and "safe" not in all_traits:
        all_traits.remove("unsafe")
    elif "ro" not in all_traits and safe_unless_ro:
        all_traits.add("safe")

    if "v1" not in all_traits:
        if 'default' in kwargs and looks_like_v1_none(kwargs['default']):
            all_traits.add("v1")
            if 'safe' not in all_traits:
                all_traits.add("safe")

    trait_set_key = tuple(sorted(all_traits))

    if trait_set_key not in PROPERTY_TYPES:
        create_property_type_from_traits(trait_set_key)
    property_type = PROPERTY_TYPES[trait_set_key]
    if not isinstance(property_type, type(self)):
        raise exc.PropertyTypeMismatch(
            selected=type(property_type).__name__,
            base=type(self).__name__,
        )

    return super(selfie, self).__new__(property_type)

def _merge_camel_case_names(base_name, new_name):
    import re
    name_parts = re.sub(
        r'([a-z\d])([A-Z])', lambda m: "%s,%s" % m.groups(), base_name,
    ).split(",")

    other_parts = list(
        x for x in re.sub(
            r'([a-z\d])([A-Z])', lambda m: "%s,%s" % m.groups(), new_name,
        ).split(",") if x not in name_parts
    )

    return "".join(other_parts + name_parts)

def create_property_type_from_traits(trait_set):
    """Takes an iterable of trait names, and tries to compose a property type
    from that.  Raises an exception if this is not possible.  Extra traits not
    requested are not acceptable.

    If this automatic generation doesn't work for you for some reason, then
    compose your property types manually.

    The details of this composition should not be relied upon; it may change in
    future releases.  However, a given normalize version should behave
    consistently for multiple runs, given the same starting sets of properties,
    the composition order will be the same every time.
    """
    wanted_traits = set(trait_set)
    stock_types = dict(
        (k, v) for k, v in PROPERTY_TYPES.items() if
        set(k).issubset(wanted_traits)
    )

    traits_available = set()
    for key in stock_types.keys():
        traits_available.update(key)

    missing_traits = wanted_traits - traits_available
    if missing_traits:
        raise exc.PropertyTypeMixinNotPossible(
            traitlist=repr(trait_set),
            missing=repr(tuple(sorted(missing_traits))),
        )

    made_types = []
    # mix together property types, until we have made the right type.
    while trait_set not in PROPERTY_TYPES:

        # be somewhat deterministic: always start with types which provide the
        # 'first' trait on the list
        start_with = set(
            k for k in stock_types.keys() if k and k[0] == trait_set[0]
        )

        # prefer extending already composed trait sets, by only adding to the
        # longest ones
        longest = max(len(x) for x in start_with)
        made_type = False

        for base in sorted(start_with):
            if len(base) != longest:
                continue

            # pick a type to join on which reduces the short-fall as much as
            # possible.
            shortfall = len(wanted_traits) - len(base)
            mix_in = None
            for other in sorted(stock_types.keys()):
                # skip mixes that will fail; this means that the type on the
                # list is a trait subset of 'base'
                mixed_traits = tuple(sorted(set(base) | set(other)))
                if mixed_traits in PROPERTY_TYPES:
                    continue

                this_shortfall = len(wanted_traits - (set(base) | set(other)))
                if this_shortfall < shortfall:
                    mix_in = other
                    mixed_in_product = mixed_traits
                    shortfall = this_shortfall
                    if shortfall == 0:
                        break

            if mix_in:
                base_type = PROPERTY_TYPES[base]
                other_type = PROPERTY_TYPES[other]
                new_name = _merge_camel_case_names(
                    base_type.__name__, other_type.__name__,
                )
                new_type = type(new_name, (base_type, other_type), {})
                stock_types[mixed_in_product] = new_type
                made_types.append(new_type)
                made_type = True

        if not made_type:
            raise exc.PropertyTypeMixinFailure(
                traitlist=repr(trait_set),
                newtypelist=", ".join(
                    "%r (%s)" % (x.traits, x.__name__) for x in made_types
                )
            )

class MetaProperty(type):
    """MetaClass for the various Property types, which allows for
    composing the various Property mix-ins, depending on options
    selected.
    """
    def __new__(mcs, name, bases, attrs):
        """This __new__ method is called when new property trait combinations
        are created."""
        selfie = [None, attrs.get('default_kwargs', {})]

        def _has(self, *args, **kwargs):
            mixed_kwargs = dict(selfie[1])
            mixed_kwargs.update(kwargs)
            return has(selfie[0], self, args, mixed_kwargs)

        attrs['__new__'] = _has
        duckwargs = set()
        if '__init__' in attrs:
            new_kwargs = inspect.getargspec(attrs['__init__']).args
            if new_kwargs:
                duckwargs.update(new_kwargs)
        traits = set()
        trait = attrs.get('__trait__', None)
        if trait:
            traits.add(trait)
        all_duckwargs = set(duckwargs)
        for base in bases:
            if hasattr(base, "traits"):
                traits.update(base.traits)
            if hasattr(base, "all_duckwargs"):
                all_duckwargs.update(base.all_duckwargs)
        traits = tuple(sorted(traits))
        if traits in PROPERTY_TYPES:
            raise exc.PropertyTypeClash(
                newtype=name,
                oldtype=PROPERTY_TYPES[traits].__name__,
                traitlist=repr(traits),
            )
        attrs['traits'] = traits
        attrs['duckwargs'] = duckwargs
        attrs['all_duckwargs'] = all_duckwargs
        self = super(MetaProperty, mcs).__new__(mcs, name, bases, attrs)
        PROPERTY_TYPES[self.traits] = self
        selfie[0] = self
        if trait:
            for kwarg in duckwargs:
                DUCKWARGS[kwarg].add((traits, self))
        return self


text:
/**
 * Bugs Overlay View
 * @author Williams Medina <williams.medinaa@gmail.com>
 */
'use strict'

const _ = require('lodash')

class BugsOverlayView {

  constructor (editor, range) {
    let marker = editor.markBufferRange(range)
    this.panelView = document.createElement('atom-bugs-overlay')
    this.panelView.className = 'native-key-bindings'
    this.panelView.innerHTML = 'loading...'
    this.decorator = editor.decorateMarker(marker, {
      type: 'overlay',
      class: 'bugs-evaluate-expression',
      item: this.panelView,
      position: 'tail'
    })
  }

  static label (type, label) {
    return `<span class="bugs-label-${type} bugs-label">${label}</span>`
  }

  static header (type, label, title) {
    let lbl = BugsOverlayView.label(type, label)
    return `<strong class="pull-right">${title || ''}</strong> ${lbl}`
  }

  static inspect (data, {fromSource} = {}) {
    let inspector = document.createElement('atom-bugs-inspector')
    let header = document.createElement('atom-bugs-inspector-header')
    let content = document.createElement('atom-bugs-inspector-body')
    inspector.appendChild(header)
    inspector.appendChild(content)
    content.setAttribute('tabindex', -1)
    if (data.get) {
      data.get().then((res) => {
        header.innerHTML = BugsOverlayView.header(res.type, res.className, fromSource)
        BugsOverlayView.setProperties(content, { withData: res })
      })
    } else {
      header.innerHTML = BugsOverlayView.header(data.type, data.className, fromSource)
      content.innerHTML = data.value
    }
    return inspector
  }

  static setProperties (content, {withData} = {}) {
    _.forEach(withData.value, (prop, name) => {
      let property = document.createElement('atom-bugs-inspector-property')
      let label = BugsOverlayView.label(prop.type, prop.className ? prop.className[0] : '-')
      let inspectable = prop.get
      property.innerHTML = `${label}<strong>${name}</strong>: ${inspectable ? prop.className : prop.value}`
      content.appendChild(property)
      if (inspectable) {
        let properties = document.createElement('atom-bugs-inspector-property')
        let render = false
        let icon = document.createElement('i')
        icon.className = 'bugs-icon-plus-square-o'
        property.appendChild(icon)
        property.style.cursor = 'pointer'
        properties.classList.add('hide')
        content.appendChild(properties)
        property.addEventListener('click', (e) => {
          e.stopPropagation()
          if (!render) {
            render = true
            prop.get().then((res) => {
              BugsOverlayView.setProperties(properties, { withData: res })
            })
          }
          if (properties.classList.contains('hide')) {
            properties.classList.remove('hide')
            icon.className = 'bugs-icon-minus-square-o'
          } else {
            properties.classList.add('hide')
            icon.className = 'bugs-icon-plus-square-o'
          }
        })
      }
    })
  }

  show (value, options) {
    setTimeout(() => {
      this.panelView.innerHTML = ''
      let visor = BugsOverlayView.inspect(value, options)
      this.panelView.appendChild(visor)
    }, 0)
  }

  destroy () {
    // destroy
    this.panelView = null
    this.decorator.destroy()
  }
}

module.exports = BugsOverlayView


text:
package org.alienideology.jcord.internal.object.guild;

import org.alienideology.jcord.Identity;
import org.alienideology.jcord.handle.guild.IGuild;
import org.alienideology.jcord.handle.guild.IGuildVoiceState;
import org.alienideology.jcord.handle.guild.IMember;
import org.alienideology.jcord.handle.guild.IRole;
import org.alienideology.jcord.handle.managers.IMemberManager;
import org.alienideology.jcord.handle.modifiers.IMemberModifier;
import org.alienideology.jcord.handle.permission.Permission;
import org.alienideology.jcord.handle.user.IUser;
import org.alienideology.jcord.internal.object.DiscordObject;
import org.alienideology.jcord.internal.object.VoiceState;
import org.alienideology.jcord.internal.object.managers.MemberManager;
import org.alienideology.jcord.internal.object.modifiers.MemberModifier;
import org.jetbrains.annotations.Nullable;

import java.time.OffsetDateTime;
import java.util.*;

/**
 * @author AlienIdeology
 */
public final class Member extends DiscordObject implements IMember {

    private final IGuild guild;

    private final IUser user;
    private String nickname;
    private OffsetDateTime joinedDate;
    private GuildVoiceState voiceState;

    private List<IRole> roles;
    private List<Permission> permissions;

    private final MemberManager manager;
    private final MemberModifier modifier;

    public Member(Identity identity, IGuild guild, IUser user) {
        super(identity);
        this.guild = guild;
        this.user = user;
        this.voiceState = new GuildVoiceState(identity, this, new VoiceState(identity, user));
        this.manager = new MemberManager(this);
        this.modifier = new MemberModifier(this);
    }

    @Override
    public IMemberManager getManager() {
        return manager;
    }

    @Override
    public IMemberModifier getModifier() {
        return modifier;
    }

    @Override
    public boolean hasAllPermissions(Collection<Permission> permissions) {
        for (Permission perm : permissions) {
            if (!this.permissions.contains(perm))
                return false;
        }
        return true;
    }

    @Override
    public boolean hasPermissions(boolean checkAdmin, Collection<Permission> permissions) {
        if (checkAdmin) {
            if (this.permissions.contains(Permission.ADMINISTRATOR) || isOwner()) return true;
        }
        for (Permission perm : permissions) {
            if (this.permissions.contains(perm))
                return true;
        }
        return false;
    }

    @Override
    public IGuild getGuild() {
        return guild;
    }

    @Override
    public IUser getUser() {
        return user;
    }

    @Override
    @Nullable
    public String getNickname() {
        return nickname;
    }

    @Override
    public OffsetDateTime getJoinedDate() {
        return joinedDate;
    }

    @Override
    public IGuildVoiceState getVoiceState() {
        return voiceState;
    }

    @Override
    public IRole getHighestRole() {
        return roles.isEmpty() ? null : roles.get(0);
    }

    @Override
    @Nullable
    public IRole getRole(String id) {
        for (IRole role : roles) {
            if (role.getId().equals(id))
                return role;
        }
        return null;
    }

    @Override
    public List<IRole> getRoles() {
        return Collections.unmodifiableList(roles);
    }

    @Override
    public List<Permission> getPermissions() {
        return Collections.unmodifiableList(permissions);
    }

    @Override
    public String getId() {
        return user.getId();
    }

    @Override
    public boolean equals(Object obj) {
        return (obj instanceof Member) && user.equals(((Member) obj).getUser()) && guild.equals(((Member) obj).getGuild());
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + guild.hashCode();
        result = 31 * result + user.hashCode();
        return result;
    }

    @Override
    public String toString() {
        return "Member{" +
                "guild=" + guild +
                ", user=" + user +
                '}';
    }

    public Member setNickname(String nickname) {
        this.nickname = nickname;
        return this;
    }

    public Member setJoinedDate(String joinedDate) {
        this.joinedDate = OffsetDateTime.parse(joinedDate);
        return this;
    }

    public Member setVoiceState(GuildVoiceState voiceState) {
        this.voiceState = voiceState;
        return this;
    }

    public Member setMuted(boolean muted) {
        this.voiceState.setMuted(muted);
        return this;
    }

    public Member setDeafened(boolean deafened) {
        this.voiceState.setDeafened(deafened);
        return this;
    }

    public Member setRoles(List<IRole> roles) {
        this.roles = roles;
        this.roles.sort((o1, o2) -> -1 * o1.compareTo(o2));
        this.permissions = initPermissions();
        return this;
    }

    public List<Permission> initPermissions() {
        Set<Permission> allPerms = new TreeSet<>();
        for (IRole role : roles) {
            allPerms.addAll(role.getPermissions());
        }
        List<Permission> permissions = new ArrayList<>();
        permissions.addAll(allPerms);
        return permissions;
    }

    public Member addRole(Role role) {
        if (!roles.contains(role))
            roles.add(role);
        return this;
    }

    public Member removeRoles(Collection<IRole> roles) {
        this.roles.removeAll(roles);
        return this;
    }

}


text:
module OpenEvaluation
  class Contact < ActiveRecord::Base
    self.table_name = "openeval_contacts"
    attr_accessible :evaluation, :evaluation_id, :contact_info,
    :email_feedback, :contact_by_phone, :phone_number, :contact_by_video,
    :video_account_info, :interested_in_feedback_session

    belongs_to :evaluation
    has_one :user, through: :evaluation

    after_create :set_evaluation_milestone

    def set_evaluation_milestone
      if self.evaluation
        evaluation.update_attribute(:contact_info_added_at, DateTime.current)
        UserMailer.contact_info_created_email(self).deliver
      end
    end
  end
end


text:
layout: post
status: publish
published: true
title: Módulos
author: Carlos Picca
author_login: carlos
author_email: carlospicca@gmail.com
wordpress_id: 1394
wordpress_url: http://codehero.co/?p=1394
date: 2013-07-12 07:14:59.000000000 -04:30
serie: Python desde Cero
dificultad: Novato
duracion: 25
description: Curso en el cual aprenderemos Python desde Cero. En esta clase, estudiaremos como crear módulos y como importarlos en tus aplicaciones.
categories:
- Cursos
- Python
tags:
- Python
- Módulos
- datetime
- math
- urllib2
---

Bienvenidos una vez más a Python desde Cero, curso en el cual aprendemos a programar sin conocimiento alguno. En el capítulo anterior, te enseñe como crear y usar funciones dentro de Python. Si eres nuevo en este curso, te recomiendo que le eches un vistazo al capítulo anterior para que te pongas en contexto (Capítulo 3)

Hoy, vamos a aprender a desarrollar nuestros propios módulos, como importarlos en nuestras aplicaciones y a como usar los que ya vienen incorporados con el lenguaje.

Módulos

Los módulos en Python son grupos de funciones alojadas dentro de un archivo .py.

Como observamos en capítulos anteriores, uno no puede desarrollar una aplicación compleja sin organizar nuestro código en funciones, y mientras que nuestro programa continua creciendo cada vez más y más, vamos a necesitar una manera para organizarlo a un nivel que no se vuelva engorroso de mantener, es ahí donde viene a la mano los módulos. Con ellos podemos organizar un grupo de funciones como si fueran un conjunto de herramientas las cuales podemos hacer uso de ellas cada vez que las necesitemos.

Los módulos son bastante fáciles de crear, ya que son scripts sencillos de Python. Vemos como crear un módulo:

Vamos a necesitar abrir un nuevo archivo en un editor de texto o en un IDE de tu preferencia. Para que el curso tenga sentido, voy a continuar con el ejemplo que utilizamos en el ultimo capítulo, crear un carrito de compra (ecommerce). Solo que esta vez vamos a calcular el impuesto de un articulo en especifico dado su precio.

```python
def calcularImpuesto(precio, impuesto):
   precioNuevo = precio / 100 * (100 + impuesto)
   return precioNuevo
```

Observemos que fue sencillo de realizar, lo que hicimos fue definir una función llamada calcularImpuesto la cual toma dos argumentos precio y impuesto, para luego calcular y retornar el valor total del articulo.

Para que este código sea o cumpla como un módulo en Python, lo único que tenemos que hacer es guardarlo con la extensión .py en el mismo directorio donde residen nuestros otros scripts de la aplicación. Vamos a guardar el archivo con el siguiente nombre: finanzas.py y así nuestro módulo será el módulo de finanzas.

¿Cómo importar un módulo?

Para usar los módulos existen dos posibilidades, podemos usar la palabra clave import o la palabra clave from. import es la manera más simple y más coman de usar, ya que que importa todas las funcionalidades existentes dentro del archivo .py en donde este alojado ese módulo. Veamos como importar el ejemplo anterior en donde teníamos el módulo de finanzas (finanzas.py):

```python
import finanzas
```

Observemos que para importar el módulo no hizo falta escribir la extensión del archivo. Una vez que Python interprete esta linea de código podemos tener a nuestra disposición la función calcularImpuesto que definimos anteriormente.

La otra manera es usando la palabra clave from, la cual importará única y exclusivamente la función que uno le pasa como parámetro, es decir, imaginemos que tenemos un módulo que posee miles y miles de funciones, para que importar todas esas funciones dentro de nuestro script si solo vamos a necesitar una, es en este caso donde viene a la mano el from. Una de las prácticas más recomendadas dentro de Python es hacer uso de la palabra from cuando se esta trabajando con módulos, ya que salva tiempo de procesamiento y recursos de la máquina en cuestión.

Veamos como importar una funcionalidad del módulo de finanzas:

```python
from finanzas import calcularImpuesto
```

Observemos que necesitamos especificar de que módulo queremos obtener nuestra función con from + MÓDULO y luego la función que queremos importar import + FUNCIÓN. En nuestro caso, del módulo de finanzas importa la función calcularImpuesto.

También puedes importar varias funciones a la vez, solo necesitas separarlas por comas.

```python
from finanzas import calcularImpuesto, calcularDescuento
```

Incluso puedes importar todas las funciones usando un wildcard

```python
from finanzas import *
```

Después de importar los módulos, la manera de usar las funciones es la siguiente: el nombre del módulo, seguido de un punto, seguido del nombre de la función a usar. Veamos un ejemplo:

```python
import finanzas
print finanzas.calcularImpuesto(100, 5)
```

Si corremos el script, debería imprimir 105. Una prueba sencilla, pero significa que nuestro módulo funcionó a la perfección!

Módulos Incorporados

Existen miles de módulos incorporados dentro de Python. Debido a que el rango es extenso, es imposible cubrirlos todos dentro de este curso, por lo que solo me voy basar en los más útiles. Si quieres conocer más sobre los módulos incorporados en Python te invito a que le eches un vistazo a la página oficial donde encontrarás toda la documentación necesaria. Veamos cuales son esos módulos:

math

os

datetime

urllib2

math

El módulo de math nos provee el acceso a funciones y constantes matemáticas. Veamos unos ejemplos:

```python
import math

math.pi #Pi, 3.14...
math.e  #Número de Euler, 2.71...

math.degrees(2)  #2 radianes = 114.59 grados
math.radians(60) #60 grados = 1.04 radianes

math.sin(2)    #Seno de 2 radianes
math.cos(0.5)  #Coseno de 0.5 radianes
math.tan(0.23) #Tangente de 0.23 radianes

math.factorial(5) #1 * 2 * 3 * 4 * 5 = 120
math.sqrt(49)   #Raíz cuadrada de 49 = 7
```

Existe miles de funciones dentro de este módulo te invito a que las revises todas aquí.

datetime

Si necesitas trabajar con fechas y tiempos, entonces el módulo datetime es el indicado para ti. Veamos un ejemplo con los usos más comunes:

```python
import datetime
from datetime import date
import time

time.time() #Retorna el número de segundos desde el 1 de enero de 1970 (Unix Epoch)

date.fromtimestamp(123456789)   #Convierte número de segundos en un objeto tipo date
date.fromtimestamp(time.time()) #Podemos combinar las funciones time y fromtimestamp para representar el tiempo actual

currentDate = date.fromtimestamp(time.time()) #Creamos una variable con la representación del tiempo actual
currentDate.strftime("%d/%m/%y") #Le coloca el siguiente formato a la fecha DD/MM/YY

currentDate.isoformat() #Le coloca el formato estándar ISO a esa fecha
```

Existe miles de funciones dentro de este módulo te invito a que las revises todas aquí.

os

Este módulo te permite trabajar con el sistema operativo en el cual Python este ejecutándose, ya sea Windows, Mac o Linux. Nos enfocaremos en la funcionalidad path ya que es la más común. Path nos permite manipular y encontrar propiedades de los archivos y carpetas que existen en el sistema. Vemos unos ejemplos:

```python
from os import path

path.exists("/Users/Picca") #Cheque si un directorio existe

path.getatime("/Users") #Retorna la fecha en la cual ese directorio fue accedido por ultima vez
path.getmtime("/Users") #Retorna la fecha en la cual ese directorio fue modificado por ultima vez

path.getsize("/Users/Picca/Desktop/boot") #Retorna el tamaño en bytes de ese archivo

path.join("C:", "Users") #Retorna la siguiente dirección "C:/Users"
```

Existe miles de funciones dentro de este módulo te invito a que las revises todas aquí.

urllib2

Este módulo permite interactuar con la web. La función más común es la urlopen la cual nos permite descargar una página o un archivo que exista en la web. Veamos unos ejemplos:

```python
import urllib2
urllib2.urlopen("http://codehero.co")
```

Este scritp descargará el HTML de la pagina web codehero.co.

```python
import urllib2
urllib2.urlopen("http://codehero.co").read(100)
```

Al igual que en el ejemplo anterior, se descargará el HTML de codehero.co pero ahora solo nos devolverá los primeros 100 caracteres. Para así después poder extraer los trozos que nos sean necesarios.

Existe miles de funciones dentro de este módulo te invito a que las revises todas aquí.

Conclusión

En esta lección, aprendimos como crear módulos en Python, como importarlos en nuestros programas, y como usar los módulos que vienen incorporados en el lenguaje. Te invito a que practiques y crees tus propios módulos ya que lo mejor de todo es que los puedes reutilizar en diferentes aplicaciones que estés desarrollando. Si tienes alguna pregunta, yo estaré feliz de responderte en los comentarios, además espero que te unas y le eches un vistazo a todo el resto de este curso. Te espero la próxima semana!


text:
var request = require('../..')
  , express = require('express')
  , assert = require('better-assert')
  , app = express()
  , url = require('url');

app.get('/', function(req, res){
  res.send(400, 'invalid json');
});

app.listen(8888);

describe('res.toError()', function(){
  it('should return an Error', function(done){
    request
    .get('http://localhost:8888/')
    .end(function(res){
      var err = res.toError();
      assert(err.status == 400);
      assert(err.message == 'got 400 response');
      done();
    });
  })
})


text:
  ## package_source_push_managed(<package handle> ) -> <uri string>
  ##
  ## returns a valid uri if the package was pushed successfully
  ## else returns null
  ##
  ## expects a this object to be defined which contains directory and source_name
  ## --reference flag indicates that the content will not be copied into the the package source
  ##             the already existing package dir will be used
  ## --content-dir <dir> flag indicates where the package content will reside
  ## --package-dir <dir> flag indicates parent dir of content of package
  ## --force     flag indicates that existing package should be overwritten
  function(package_source_push_managed)
    if("${ARGN}" MATCHES "(.*);=>;?(.*)")
        set(source_args "${CMAKE_MATCH_1}")
        set(args "${CMAKE_MATCH_2}")
    else()
        set(source_args ${ARGN})
        set(args)
    endif()
    list_pop_front(source_args)
    ans(source)

    list_extract_labelled_value(source_args --content-dir)
    ans(content_dir)

    list_extract_labelled_value(source_args --package-dir)
    ans(package_dir)

    list_extract_flag(args --force)
    ans(force)

    this_get(directory)

    list_pop_front(source_args)
    ans(uri)

    uri_coerce(uri)

    assign(package_handle = source.resolve(${uri}))

    if(NOT package_handle)
      error("could not resolve ${source_args} to a package handle")
      return()
    endif()

    package_handle_hash("${package_handle}")
    ans(hash)

    set(managed_dir "${directory}/${hash}")

    if(EXISTS "${managed_dir}" AND NOT force)
      error("package (${hash}) already exists ")
      return()
    endif()

    if(NOT content_dir)
      if(NOT package_dir)
        this_get(package_dir)
      endif()
      if(package_dir)
        assign(id = package_handle.package_descriptor.id)
        assign(version = package_handle.package_descriptor.version)

        path("${package_dir}/${id}")
        ans(content_dir)
        if(EXISTS "${content_dir}")
          path("${package_dir}/${id}@${version}")
          ans(content_dir)
          if(EXISTS "${content_dir}")
            path("${package_dir}/${hash}")
          endif()
        endif()
      else()
        set(content_dir "${managed_dir}/content")
      endif()
    else()
      path_qualify(content_dir)
    endif()

    assign(package_handle = source.pull("${uri}" ${source_args} "${content_dir}"))
    if(NOT package_handle)
      error("failed to pull {uri.uri} to {content_dir}")
      return()
    endif()
    assign(!package_handle.managed_descriptor.hash = hash)
    assign(!package_handle.managed_descriptor.managed_dir = managed_dir)
    assign(!package_handle.managed_descriptor.remote_source_name = source.source_name)
    assign(!package_handle.managed_descriptor.remote_uri = uri.uri)
    assign(!package_handle.working_dir = '${managed_dir}/workspace')

    qm_write("${managed_dir}/package_handle.qm" "${package_handle}")

    return_ref(package_handle)

  endfunction()


text:
/*
---
name: {%= name %}
description: {%= description %}.
license: {%= licenses.join(', ') %} license{%= licenses.length === 1 ? '' : 's' %}.
authors:
 - {%= author_name %}
requires:
provides: {%= name %}
...
*/

var {%= name %} = new Class({

	// Put your code here

	initialize: function() {

	}

});


text:
package com.example.jaein.unitaxi;

import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;

public class u01_Intro_Activity extends AppCompatActivity {

    Handler handler_intro;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_u01_intro);

        handler_intro = new Handler();
        handler_intro.postDelayed(run_into, 3000);
    }

    Runnable run_into = new Runnable() {
        @Override
        public void run() {
            Intent i_Login = new Intent(u01_Intro_Activity.this, u02_Login_Activity.class);
            startActivity(i_Login);
            finish();
            overridePendingTransition(android.R.anim.fade_in,android.R.anim.fade_out);
        }
    };

    @Override
    public void onBackPressed() {
        super.onBackPressed();
    }
}