<commit_before>/* vim:set ts=4 sw=4 sts=4 et: */

#include <memory>
#include <sstream>
#include <igraph/cpp/graph.h>
#include <igraph/cpp/edge.h>
#include <igraph/cpp/vertex.h>
#include <igraph/cpp/vertex_selector.h>
#include <igraph/cpp/generators/degree_sequence.h>
#include <igraph/cpp/generators/erdos_renyi.h>
#include <netctrl/model.h>

#include "cmd_arguments.h"
#include "graph_util.h"
#include "logging.h"

using namespace igraph;
using namespace netctrl;

/// Helper function to split a string around a delimiter character
std::vector<std::string> &split(const std::string& s, char delim,
        std::vector<std::string>& elems) {
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

/// Helper function to split a string around a delimiter character
std::vector<std::string> split(const std::string& s, char delim) {
    std::vector<std::string> elems;
    return split(s, delim, elems);
}

class NetworkControllabilityApp {
private:
    /// Parsed command line arguments
    CommandLineArguments m_args;

    /// Graph being analyzed by the UI
    std::auto_ptr<Graph> m_pGraph;

    /// Controllability model being calculated on the graph
    std::auto_ptr<ControllabilityModel> m_pModel;

public:
    LOGGING_FUNCTION(debug, 2);
    LOGGING_FUNCTION(info, 1);
    LOGGING_FUNCTION(error, 0);

    /// Constructor
    NetworkControllabilityApp() : m_pGraph(0), m_pModel(0) {}

    /// Returns whether we are running in quiet mode
    bool isQuiet() {
        return m_args.verbosity < 1;
    }

    /// Returns whether we are running in verbose mode
    bool isVerbose() {
        return m_args.verbosity > 1;
    }

    /// Loads a graph from the given file
    /**
     * If the name of the file is "-", the file is assumed to be the
     * standard input.
     */
    std::auto_ptr<Graph> loadGraph(const std::string& filename, GraphFormat format) {
        std::auto_ptr<Graph> result;

        if (filename == "-") {
            // Loading graph from standard input
            if (format == GRAPH_FORMAT_AUTO)
                format = GRAPH_FORMAT_EDGELIST;
            result.reset(new Graph(GraphUtil::readGraph(stdin, format)));
        } else if (filename.find("://") != filename.npos) {
            // Generating graph from model
            size_t pos = filename.find("://");
            std::string model = filename.substr(0, pos);
            std::vector<std::string> params = split(filename.substr(pos+3), ',');

            if (model == "er") {
                // Erdos-Renyi network
                if (params.size() < 2) {
                    error("ER generator requires two or three arguments: number of nodes, "
                            "average degree and directedness (optional)");
                    return result;    // points to null
                }

                long int n = atoi(params[0].c_str());
                float k = atof(params[1].c_str());
                bool directed = true;
                if (params.size() >= 3) {
                    directed = atoi(params[2].c_str()) != 0;
                }
                return erdos_renyi_game_gnm(n, directed ? n*k : n*k/2.0,
                        directed, false);
            } else {
                error("Unknown graph generator: %s", model.c_str());
                return result;   // points to null
            }
        } else {
            // Loading graph from file
            result.reset(new Graph(GraphUtil::readGraph(filename, format)));
            result->setAttribute("filename", filename);
        }

        return result;
    }

    /// Runs the user interface
    int run(int argc, char** argv) {
        m_args.parse(argc, argv);

        info(">> loading graph: %s", m_args.inputFile.c_str());
        m_pGraph = loadGraph(m_args.inputFile, m_args.inputFormat);
        if (m_pGraph.get() == NULL)
            return 2;

        info(">> graph is %s and has %ld vertices and %ld edges",
             m_pGraph->isDirected() ? "directed" : "undirected",
             (long)m_pGraph->vcount(), (long)m_pGraph->ecount());

        switch (m_args.modelType) {
            case LIU_MODEL:
                m_pModel.reset(new LiuControllabilityModel(m_pGraph.get()));
                break;
            case SWITCHBOARD_MODEL:
                {
                    SwitchboardControllabilityModel* sbdModel;
                    sbdModel = new SwitchboardControllabilityModel(m_pGraph.get());
                    sbdModel->setControllabilityMeasure(
                            m_args.useEdgeMeasure ?
                            SwitchboardControllabilityModel::EDGE_MEASURE :
                            SwitchboardControllabilityModel::NODE_MEASURE
                    );
                    m_pModel.reset(sbdModel);
                }
                break;
        }

        switch (m_args.operationMode) {
            case MODE_CONTROL_PATHS:
                return runControlPaths();

            case MODE_DRIVER_NODES:
                return runDriverNodes();

            case MODE_GRAPH:
                return runGraph();

            case MODE_STATISTICS:
                return runStatistics();

            case MODE_SIGNIFICANCE:
                return runSignificance();

            default:
                return 1;
        }
    }

    /// Runs the control path calculation mode
    int runControlPaths() {
        info(">> calculating control paths");
        m_pModel->calculate();

        std::vector<ControlPath*> paths = m_pModel->controlPaths();
        info(">> found %d control path(s)", paths.size());
        for (std::vector<ControlPath*>::const_iterator it = paths.begin();
                it != paths.end(); it++) {
            std::cout << (*it)->toString() << '\n';
        }

        return 0;
    }

    /// Runs the driver node calculation mode
    int runDriverNodes() {
        info(">> calculating control paths and driver nodes");
        m_pModel->calculate();

        Vector driver_nodes = m_pModel->driverNodes();
        info(">> found %d driver node(s)", driver_nodes.size());
        for (Vector::const_iterator it = driver_nodes.begin(); it != driver_nodes.end(); it++) {
            any name(m_pGraph->vertex(*it).getAttribute("name", (long int)*it));
            if (name.type() == typeid(std::string)) {
                std::cout << name.as<std::string>() << '\n';
            } else {
                std::cout << name.as<long int>() << '\n';
            }
        }

        return 0;
    }

    /// Runs the annotated graph output mode
    int runGraph() {
        long int i, j, n;

        info(">> calculating control paths and driver nodes");
        m_pModel->calculate();

        Vector driver_nodes = m_pModel->driverNodes();
        std::vector<ControlPath*> paths = m_pModel->controlPaths();
        info(">> found %d driver node(s) and %d control path(s)",
                driver_nodes.size(), paths.size());

        info(">> classifying edges");
        std::vector<EdgeClass> edge_classes = m_pModel->edgeClasses();

        // Mark the driver nodes
        for (Vector::const_iterator it = driver_nodes.begin(); it != driver_nodes.end(); it++) {
            m_pGraph->vertex(*it).setAttribute("is_driver", true);
        }

        // Mark the edge types and path indices
        j = 0;
        for (std::vector<ControlPath*>::const_iterator it = paths.begin();
                it != paths.end(); it++, j++) {
            const igraph::Vector& vec = (*it)->edges(*m_pGraph.get());
            n = vec.size();
            for (i = 0; i < n; i++) {
                igraph::Edge edge = m_pGraph->edge(vec[i]);
                edge.setAttribute("path_type", (*it)->name());
                edge.setAttribute("path_indices", j);
                edge.setAttribute("path_order", i);
            }
        }

        // Mark the edge classes
        n = m_pGraph->ecount();
        for (i = 0; i < n; i++) {
            igraph::Edge edge = m_pGraph->edge(i);
            edge.setAttribute("edge_class", edgeClassToString(edge_classes[i]));
        }

        // Print the graph
        GraphUtil::writeGraph(stdout, (*m_pGraph.get()), m_args.outputFormat);
        return 0;
    }

    /// Runs the signficance calculation mode
    int runSignificance() {
        size_t observedDriverNodeCount;
        size_t numTrials = 100, i;
        float numNodes = m_pGraph->vcount();
        float controllability;
        Vector counts;

        info(">> calculating control paths and driver nodes");
        m_pModel->calculate();

        observedDriverNodeCount = m_pModel->driverNodes().size();
        controllability = m_pModel->controllability();

        info(">> found %d driver node(s)", observedDriverNodeCount);
        std::cout << "Observed\t" << controllability << '\n';

        // Testing Erdos-Renyi null model
        info(">> testing Erdos-Renyi null model");
        counts.clear();
        for (i = 0; i < numTrials; i++) {
            std::auto_ptr<Graph> graph = igraph::erdos_renyi_game_gnm(
                    numNodes, m_pGraph->ecount(),
                    m_pGraph->isDirected(), false);

            std::auto_ptr<ControllabilityModel> pModel(m_pModel->clone());
            pModel->setGraph(graph.get());
            pModel->calculate();

            counts.push_back(pModel->controllability());
        }
        counts.sort();
        std::cout << "ER\t" << counts.sum() / counts.size() << '\n';

        // Testing configuration model
        Vector inDegrees, outDegrees;
        m_pGraph->degree(&outDegrees, V(m_pGraph.get()), IGRAPH_OUT, true);
        m_pGraph->degree(&inDegrees,  V(m_pGraph.get()), IGRAPH_IN,  true);

        info(">> testing configuration model (preserving joint degree distribution)");
        counts.clear();
        for (i = 0; i < numTrials; i++) {
            std::auto_ptr<Graph> graph =
                igraph::degree_sequence_game(outDegrees, inDegrees,
                    IGRAPH_DEGSEQ_SIMPLE);

            std::auto_ptr<ControllabilityModel> pModel(m_pModel->clone());
            pModel->setGraph(graph.get());
            pModel->calculate();

            counts.push_back(pModel->controllability());
        }
        counts.sort();
        std::cout << "Configuration\t" << counts.sum() / counts.size() << '\n';

        // Testing configuration model
        info(">> testing configuration model (destroying joint degree distribution)");
        counts.clear();
        for (i = 0; i < numTrials; i++) {
            inDegrees.shuffle();
            outDegrees.shuffle();

            std::auto_ptr<Graph> graph =
                igraph::degree_sequence_game(outDegrees, inDegrees,
                    IGRAPH_DEGSEQ_SIMPLE);

            std::auto_ptr<ControllabilityModel> pModel(m_pModel->clone());
            pModel->setGraph(graph.get());
            pModel->calculate();

            counts.push_back(pModel->controllability());
        }
        counts.sort();
        std::cout << "Configuration_no_joint\t" << counts.sum() / counts.size() << '\n';

        return 0;
    }

    /// Runs the general statistics calculation mode
    int runStatistics() {
        float n = m_pGraph->vcount();
        float m = m_pGraph->ecount();
        long int num_driver;
        long int num_redundant = 0, num_ordinary = 0, num_critical = 0, num_distinguished = 0;

        info(">> calculating control paths and driver nodes");
        m_pModel->calculate();
        num_driver = m_pModel->driverNodes().size();

        info(">> classifying edges");
        std::vector<EdgeClass> edge_classes = m_pModel->edgeClasses();
        if (edge_classes.size() == m && !edge_classes.empty()) {
            for (long int i = 0; i < m; i++) {
                if (edge_classes[i] == EDGE_REDUNDANT)
                    num_redundant++;
                else if (edge_classes[i] == EDGE_ORDINARY)
                    num_ordinary++;
                else if (edge_classes[i] == EDGE_DISTINGUISHED)
                    num_distinguished++;
                else
                    num_critical++;
            }
        }

        info(">> order is as follows:");
        info(">> driver nodes; distinguished, redundant, ordinary, critical edges");

        std::cout << num_driver << ' '
                  << num_distinguished << ' '
                  << num_redundant << ' '
                  << num_ordinary << ' '
                  << num_critical << '\n';
        std::cout << num_driver / n << ' '
                  << num_distinguished / m << ' '
                  << num_redundant / m << ' '
                  << num_ordinary / m << ' '
                  << num_critical / m << '\n';

        return 0;
    }

};

int main(int argc, char** argv) {
    NetworkControllabilityApp app;

    igraph::AttributeHandler::attach();
    return app.run(argc, argv);
}

<commit_msg>added proper handling of "-o" option<commit_after>/* vim:set ts=4 sw=4 sts=4 et: */

#include <cstdio>
#include <fstream>
#include <memory>
#include <sstream>
#include <igraph/cpp/graph.h>
#include <igraph/cpp/edge.h>
#include <igraph/cpp/vertex.h>
#include <igraph/cpp/vertex_selector.h>
#include <igraph/cpp/generators/degree_sequence.h>
#include <igraph/cpp/generators/erdos_renyi.h>
#include <netctrl/model.h>

#include "cmd_arguments.h"
#include "graph_util.h"
#include "logging.h"

using namespace igraph;
using namespace netctrl;

/// Helper function to split a string around a delimiter character
std::vector<std::string> &split(const std::string& s, char delim,
        std::vector<std::string>& elems) {
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

/// Helper function to split a string around a delimiter character
std::vector<std::string> split(const std::string& s, char delim) {
    std::vector<std::string> elems;
    return split(s, delim, elems);
}

class NetworkControllabilityApp {
private:
    /// Parsed command line arguments
    CommandLineArguments m_args;

    /// The C-style output file object where the results will be written
    FILE* m_outputFileObject;

    /// Graph being analyzed by the UI
    std::auto_ptr<Graph> m_pGraph;

    /// Controllability model being calculated on the graph
    std::auto_ptr<ControllabilityModel> m_pModel;

    /// The C++-style output stream where the results will be written
    std::ostream* m_pOutputStream;

public:
    LOGGING_FUNCTION(debug, 2);
    LOGGING_FUNCTION(info, 1);
    LOGGING_FUNCTION(error, 0);

    /// Constructor
    NetworkControllabilityApp() : m_outputFileObject(0),
        m_pGraph(0), m_pModel(0), m_pOutputStream(0) {}

    /// Destructor
    ~NetworkControllabilityApp() {
        if (m_outputFileObject != 0 && m_outputFileObject != stdout) {
            fclose(m_outputFileObject);
        }

        if (m_pOutputStream != 0 && m_pOutputStream != &std::cout) {
            delete m_pOutputStream;
        }
    }

    /// Returns the C-style output file object where the results should be written
    FILE* getOutputFileObject() {
        if (m_outputFileObject == 0) {
            if (isWritingToStandardOutput()) {
                m_outputFileObject = stdout;
            } else {
                m_outputFileObject = fopen(m_args.outputFile.c_str(), "w");
                if (m_outputFileObject == 0) {
                    error("cannot open output file for writing: %s",
                            m_args.outputFile.c_str());
                    exit(3);
                }
            }
        }
        return m_outputFileObject;
    }

    /// Returns the C++-style output stream where the results should be written
    std::ostream& getOutputStream() {
        if (m_pOutputStream == 0) {
            if (isWritingToStandardOutput()) {
                m_pOutputStream = &std::cout;
            } else {
                m_pOutputStream = new std::ofstream(m_args.outputFile.c_str());
                if (m_pOutputStream->fail()) {
                    error("cannot open output file for writing: %s",
                            m_args.outputFile.c_str());
                    exit(3);
                }
            }
        }
        return *m_pOutputStream;
    }

    /// Returns whether we are writing to the standard output
    bool isWritingToStandardOutput() {
        return m_args.outputFile.empty() || m_args.outputFile == "-";
    }

    /// Returns whether we are running in quiet mode
    bool isQuiet() {
        return m_args.verbosity < 1;
    }

    /// Returns whether we are running in verbose mode
    bool isVerbose() {
        return m_args.verbosity > 1;
    }

    /// Loads a graph from the given file
    /**
     * If the name of the file is "-", the file is assumed to be the
     * standard input.
     */
    std::auto_ptr<Graph> loadGraph(const std::string& filename, GraphFormat format) {
        std::auto_ptr<Graph> result;

        if (filename == "-") {
            // Loading graph from standard input
            if (format == GRAPH_FORMAT_AUTO)
                format = GRAPH_FORMAT_EDGELIST;
            result.reset(new Graph(GraphUtil::readGraph(stdin, format)));
        } else if (filename.find("://") != filename.npos) {
            // Generating graph from model
            size_t pos = filename.find("://");
            std::string model = filename.substr(0, pos);
            std::vector<std::string> params = split(filename.substr(pos+3), ',');

            if (model == "er") {
                // Erdos-Renyi network
                if (params.size() < 2) {
                    error("ER generator requires two or three arguments: number of nodes, "
                            "average degree and directedness (optional)");
                    return result;    // points to null
                }

                long int n = atoi(params[0].c_str());
                float k = atof(params[1].c_str());
                bool directed = true;
                if (params.size() >= 3) {
                    directed = atoi(params[2].c_str()) != 0;
                }
                return erdos_renyi_game_gnm(n, directed ? n*k : n*k/2.0,
                        directed, false);
            } else {
                error("Unknown graph generator: %s", model.c_str());
                return result;   // points to null
            }
        } else {
            // Loading graph from file
            result.reset(new Graph(GraphUtil::readGraph(filename, format)));
            result->setAttribute("filename", filename);
        }

        return result;
    }

    /// Runs the user interface
    int run(int argc, char** argv) {
        int retval;

        m_args.parse(argc, argv);

        info(">> loading graph: %s", m_args.inputFile.c_str());
        m_pGraph = loadGraph(m_args.inputFile, m_args.inputFormat);
        if (m_pGraph.get() == NULL)
            return 2;

        info(">> graph is %s and has %ld vertices and %ld edges",
             m_pGraph->isDirected() ? "directed" : "undirected",
             (long)m_pGraph->vcount(), (long)m_pGraph->ecount());

        switch (m_args.modelType) {
            case LIU_MODEL:
                m_pModel.reset(new LiuControllabilityModel(m_pGraph.get()));
                break;
            case SWITCHBOARD_MODEL:
                {
                    SwitchboardControllabilityModel* sbdModel;
                    sbdModel = new SwitchboardControllabilityModel(m_pGraph.get());
                    sbdModel->setControllabilityMeasure(
                            m_args.useEdgeMeasure ?
                            SwitchboardControllabilityModel::EDGE_MEASURE :
                            SwitchboardControllabilityModel::NODE_MEASURE
                    );
                    m_pModel.reset(sbdModel);
                }
                break;
        }

        switch (m_args.operationMode) {
            case MODE_CONTROL_PATHS:
                retval = runControlPaths();
                break;

            case MODE_DRIVER_NODES:
                retval = runDriverNodes();
                break;

            case MODE_GRAPH:
                retval = runGraph();
                break;

            case MODE_STATISTICS:
                retval = runStatistics();
                break;

            case MODE_SIGNIFICANCE:
                retval = runSignificance();
                break;

            default:
                retval = 1;
        }

        if (!retval && !isWritingToStandardOutput()) {
            info(">> results were written to %s", m_args.outputFile.c_str());
        }

        return retval;
    }

    /// Runs the control path calculation mode
    int runControlPaths() {
        info(">> calculating control paths");
        m_pModel->calculate();

        std::vector<ControlPath*> paths = m_pModel->controlPaths();
        std::ostream& out = getOutputStream();

        info(">> found %d control path(s)", paths.size());
        for (std::vector<ControlPath*>::const_iterator it = paths.begin();
                it != paths.end(); it++) {
            out << (*it)->toString() << '\n';
        }

        return 0;
    }

    /// Runs the driver node calculation mode
    int runDriverNodes() {
        info(">> calculating control paths and driver nodes");
        m_pModel->calculate();

        Vector driver_nodes = m_pModel->driverNodes();
        std::ostream& out = getOutputStream();

        info(">> found %d driver node(s)", driver_nodes.size());
        for (Vector::const_iterator it = driver_nodes.begin(); it != driver_nodes.end(); it++) {
            any name(m_pGraph->vertex(*it).getAttribute("name", (long int)*it));
            if (name.type() == typeid(std::string)) {
                out << name.as<std::string>() << '\n';
            } else {
                out << name.as<long int>() << '\n';
            }
        }

        return 0;
    }

    /// Runs the annotated graph output mode
    int runGraph() {
        long int i, j, n;

        info(">> calculating control paths and driver nodes");
        m_pModel->calculate();

        Vector driver_nodes = m_pModel->driverNodes();
        std::vector<ControlPath*> paths = m_pModel->controlPaths();
        info(">> found %d driver node(s) and %d control path(s)",
                driver_nodes.size(), paths.size());

        info(">> classifying edges");
        std::vector<EdgeClass> edge_classes = m_pModel->edgeClasses();

        // Mark the driver nodes
        for (Vector::const_iterator it = driver_nodes.begin(); it != driver_nodes.end(); it++) {
            m_pGraph->vertex(*it).setAttribute("is_driver", true);
        }

        // Mark the edge types and path indices
        j = 0;
        for (std::vector<ControlPath*>::const_iterator it = paths.begin();
                it != paths.end(); it++, j++) {
            const igraph::Vector& vec = (*it)->edges(*m_pGraph.get());
            n = vec.size();
            for (i = 0; i < n; i++) {
                igraph::Edge edge = m_pGraph->edge(vec[i]);
                edge.setAttribute("path_type", (*it)->name());
                edge.setAttribute("path_indices", j);
                edge.setAttribute("path_order", i);
            }
        }

        // Mark the edge classes
        n = m_pGraph->ecount();
        for (i = 0; i < n; i++) {
            igraph::Edge edge = m_pGraph->edge(i);
            edge.setAttribute("edge_class", edgeClassToString(edge_classes[i]));
        }

        // Print the graph
        GraphUtil::writeGraph(getOutputFileObject(), (*m_pGraph.get()), m_args.outputFormat);

        return 0;
    }

    /// Runs the signficance calculation mode
    int runSignificance() {
        size_t observedDriverNodeCount;
        size_t numTrials = 100, i;
        float numNodes = m_pGraph->vcount();
        float controllability;
        Vector counts;
        std::ostream& out = getOutputStream();

        info(">> calculating control paths and driver nodes");
        m_pModel->calculate();

        observedDriverNodeCount = m_pModel->driverNodes().size();
        controllability = m_pModel->controllability();

        info(">> found %d driver node(s)", observedDriverNodeCount);
        out << "Observed\t" << controllability << '\n';

        // Testing Erdos-Renyi null model
        info(">> testing Erdos-Renyi null model");
        counts.clear();
        for (i = 0; i < numTrials; i++) {
            std::auto_ptr<Graph> graph = igraph::erdos_renyi_game_gnm(
                    numNodes, m_pGraph->ecount(),
                    m_pGraph->isDirected(), false);

            std::auto_ptr<ControllabilityModel> pModel(m_pModel->clone());
            pModel->setGraph(graph.get());
            pModel->calculate();

            counts.push_back(pModel->controllability());
        }
        counts.sort();
        out << "ER\t" << counts.sum() / counts.size() << '\n';

        // Testing configuration model
        Vector inDegrees, outDegrees;
        m_pGraph->degree(&outDegrees, V(m_pGraph.get()), IGRAPH_OUT, true);
        m_pGraph->degree(&inDegrees,  V(m_pGraph.get()), IGRAPH_IN,  true);

        info(">> testing configuration model (preserving joint degree distribution)");
        counts.clear();
        for (i = 0; i < numTrials; i++) {
            std::auto_ptr<Graph> graph =
                igraph::degree_sequence_game(outDegrees, inDegrees,
                    IGRAPH_DEGSEQ_SIMPLE);

            std::auto_ptr<ControllabilityModel> pModel(m_pModel->clone());
            pModel->setGraph(graph.get());
            pModel->calculate();

            counts.push_back(pModel->controllability());
        }
        counts.sort();
        out << "Configuration\t" << counts.sum() / counts.size() << '\n';

        // Testing configuration model
        info(">> testing configuration model (destroying joint degree distribution)");
        counts.clear();
        for (i = 0; i < numTrials; i++) {
            inDegrees.shuffle();
            outDegrees.shuffle();

            std::auto_ptr<Graph> graph =
                igraph::degree_sequence_game(outDegrees, inDegrees,
                    IGRAPH_DEGSEQ_SIMPLE);

            std::auto_ptr<ControllabilityModel> pModel(m_pModel->clone());
            pModel->setGraph(graph.get());
            pModel->calculate();

            counts.push_back(pModel->controllability());
        }
        counts.sort();
        out << "Configuration_no_joint\t" << counts.sum() / counts.size() << '\n';

        return 0;
    }

    /// Runs the general statistics calculation mode
    int runStatistics() {
        float n = m_pGraph->vcount();
        float m = m_pGraph->ecount();
        long int num_driver;
        long int num_redundant = 0, num_ordinary = 0, num_critical = 0, num_distinguished = 0;
        std::ostream& out = getOutputStream();

        info(">> calculating control paths and driver nodes");
        m_pModel->calculate();
        num_driver = m_pModel->driverNodes().size();

        info(">> classifying edges");
        std::vector<EdgeClass> edge_classes = m_pModel->edgeClasses();
        if (edge_classes.size() == m && !edge_classes.empty()) {
            for (long int i = 0; i < m; i++) {
                if (edge_classes[i] == EDGE_REDUNDANT)
                    num_redundant++;
                else if (edge_classes[i] == EDGE_ORDINARY)
                    num_ordinary++;
                else if (edge_classes[i] == EDGE_DISTINGUISHED)
                    num_distinguished++;
                else
                    num_critical++;
            }
        }

        info(">> order is as follows:");
        info(">> driver nodes; distinguished, redundant, ordinary, critical edges");

        out << num_driver << ' '
            << num_distinguished << ' '
            << num_redundant << ' '
            << num_ordinary << ' '
            << num_critical << '\n';
        out << num_driver / n << ' '
            << num_distinguished / m << ' '
            << num_redundant / m << ' '
            << num_ordinary / m << ' '
            << num_critical / m << '\n';

        return 0;
    }

};

int main(int argc, char** argv) {
    NetworkControllabilityApp app;

    igraph::AttributeHandler::attach();
    return app.run(argc, argv);
}

<|endoftext|>


<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Radu Serban
// =============================================================================
//
// M113 suspension subsystem.
//
// =============================================================================

#include "chrono_models/vehicle/m113a/M113a_RoadWheel.h"
#include "chrono_models/vehicle/m113a/M113a_Suspension.h"

namespace chrono {
namespace vehicle {
namespace m113 {

// -----------------------------------------------------------------------------
// Static variables
// -----------------------------------------------------------------------------
const double M113a_Suspension::m_arm_mass = 16.513;
const ChVector<> M113a_Suspension::m_arm_inertia(3.8, 0.08, 3.8);
const double M113a_Suspension::m_arm_radius = 0.019;

const double M113a_Suspension::m_torsion_a0 = 0;
const double M113a_Suspension::m_torsion_k = 9557;
const double M113a_Suspension::m_torsion_c = 191;
const double M113a_Suspension::m_torsion_t = 0;
const double M113a_Suspension::m_torsion_kstop = 350800;
const double M113a_Suspension::m_torsion_lowerstop = -7.0 / 180.0 * CH_C_PI;
const double M113a_Suspension::m_torsion_upperstop = 47.59 / 180.0 * CH_C_PI;

// -----------------------------------------------------------------------------
// M113 spring functor class - implements a (non)linear rotational spring
// -----------------------------------------------------------------------------
class M113a_SpringTorque : public ChLinkRSDA::TorqueFunctor {
public:
    M113a_SpringTorque(double k, double c, double t, double kstop, double lowerstop, double upperstop)
        : m_k(k), m_c(c), m_t(t), m_kstop(kstop), m_lowerstop(lowerstop), m_upperstop(upperstop) {}

    virtual double evaluate(double time, double angle, double vel, ChLinkRSDA* link) override {
        double force = m_t - m_k * angle - m_c * vel;

        //Apply bump stop spring rates if needed
        if (angle < m_lowerstop) {
            force -= m_kstop*(angle - m_lowerstop);
        }
        else if (angle > m_upperstop) {
            force -= m_kstop*(angle - m_upperstop);
        }

        return force;
    }

private:
    double m_k;
    double m_c;
    double m_t;
    double m_kstop;
    double m_lowerstop;
    double m_upperstop;
};

// -----------------------------------------------------------------------------
// M113 shock functor class - implements a (non)linear translational damper
// -----------------------------------------------------------------------------
class M113a_ShockForce : public ChLinkTSDA::ForceFunctor {
  public:
    M113a_ShockForce(){}

    virtual double evaluate(double time, double rest_length, double length, double vel, ChLinkTSDA* link) override {
        // Clip the velocity to within +/- 0.254 m/s [10 in/s]
        ChClampValue(vel, -0.254, 0.254);

        // Velocity is positive in extension.
        // Linear interpolate between 500lbf in extension at 10 in/s and
        // -2000lbf at -10in/s (converted to N)
        return vel >= 0 ? (-8756.341762 * vel) : (-35025.36705 * vel);
    }
};

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
M113a_Suspension::M113a_Suspension(const std::string& name, VehicleSide side, int index, bool has_shock)
    : ChLinearDamperRWAssembly(name, has_shock), m_side(side) {
    // Instantiate the force callback for the shock (damper).
    m_shock_forceCB = chrono_types::make_shared<M113a_ShockForce>();

    // Instantiate the torque callback for the spring.
    m_spring_torqueCB = chrono_types::make_shared<M113a_SpringTorque>(
        m_torsion_k, m_torsion_c, m_torsion_t, m_torsion_kstop, m_torsion_lowerstop, m_torsion_upperstop);

    // Create the associated road wheel.
    if (side == LEFT)
        m_road_wheel = chrono_types::make_shared<M113a_RoadWheelLeft>(index);
    else
        m_road_wheel = chrono_types::make_shared<M113a_RoadWheelRight>(index);
}

M113a_Suspension::~M113a_Suspension() {}

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
const ChVector<> M113a_Suspension::GetLocation(PointId which) {
    ChVector<> point;

    switch (which) {
        case ARM:
            point = ChVector<>(0.213, -0.12, 0.199);
            break;
        case ARM_WHEEL:
            point = ChVector<>(0, -0.12, 0);
            break;
        case ARM_CHASSIS:
            point = ChVector<>(0.232, -0.12, 0.217);
            break;
        case SHOCK_A:
            point = ChVector<>(0, -0.12, 0);
            break;
        case SHOCK_C:
            point = ChVector<>(0, -0.12, 1);
            break;
        default:
            point = ChVector<>(0, 0, 0);
            break;
    }

    if (m_side == RIGHT)
        point.y() *= -1;

    return point;
}

}  // end namespace m113
}  // end namespace vehicle
}  // end namespace chrono
<commit_msg>Update M113a model to reflect RSDA functor change<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Radu Serban
// =============================================================================
//
// M113 suspension subsystem.
//
// =============================================================================

#include "chrono_models/vehicle/m113a/M113a_RoadWheel.h"
#include "chrono_models/vehicle/m113a/M113a_Suspension.h"

namespace chrono {
namespace vehicle {
namespace m113 {

// -----------------------------------------------------------------------------
// Static variables
// -----------------------------------------------------------------------------
const double M113a_Suspension::m_arm_mass = 16.513;
const ChVector<> M113a_Suspension::m_arm_inertia(3.8, 0.08, 3.8);
const double M113a_Suspension::m_arm_radius = 0.019;

const double M113a_Suspension::m_torsion_a0 = 0;
const double M113a_Suspension::m_torsion_k = 9557;
const double M113a_Suspension::m_torsion_c = 191;
const double M113a_Suspension::m_torsion_t = 0;
const double M113a_Suspension::m_torsion_kstop = 350800;
const double M113a_Suspension::m_torsion_lowerstop = -7.0 / 180.0 * CH_C_PI;
const double M113a_Suspension::m_torsion_upperstop = 47.59 / 180.0 * CH_C_PI;

// -----------------------------------------------------------------------------
// M113 spring functor class - implements a (non)linear rotational spring
// -----------------------------------------------------------------------------
class M113a_SpringTorque : public ChLinkRSDA::TorqueFunctor {
public:
    M113a_SpringTorque(double k, double c, double t, double kstop, double lowerstop, double upperstop)
        : m_k(k), m_c(c), m_t(t), m_kstop(kstop), m_lowerstop(lowerstop), m_upperstop(upperstop) {}

    virtual double evaluate(double time, double angle, double vel, const ChLinkRSDA& link) override {
        double force = m_t - m_k * angle - m_c * vel;

        //Apply bump stop spring rates if needed
        if (angle < m_lowerstop) {
            force -= m_kstop*(angle - m_lowerstop);
        }
        else if (angle > m_upperstop) {
            force -= m_kstop*(angle - m_upperstop);
        }

        return force;
    }

private:
    double m_k;
    double m_c;
    double m_t;
    double m_kstop;
    double m_lowerstop;
    double m_upperstop;
};

// -----------------------------------------------------------------------------
// M113 shock functor class - implements a (non)linear translational damper
// -----------------------------------------------------------------------------
class M113a_ShockForce : public ChLinkTSDA::ForceFunctor {
  public:
    M113a_ShockForce(){}

    virtual double evaluate(double time, double rest_length, double length, double vel, ChLinkTSDA* link) override {
        // Clip the velocity to within +/- 0.254 m/s [10 in/s]
        ChClampValue(vel, -0.254, 0.254);

        // Velocity is positive in extension.
        // Linear interpolate between 500lbf in extension at 10 in/s and
        // -2000lbf at -10in/s (converted to N)
        return vel >= 0 ? (-8756.341762 * vel) : (-35025.36705 * vel);
    }
};

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
M113a_Suspension::M113a_Suspension(const std::string& name, VehicleSide side, int index, bool has_shock)
    : ChLinearDamperRWAssembly(name, has_shock), m_side(side) {
    // Instantiate the force callback for the shock (damper).
    m_shock_forceCB = chrono_types::make_shared<M113a_ShockForce>();

    // Instantiate the torque callback for the spring.
    m_spring_torqueCB = chrono_types::make_shared<M113a_SpringTorque>(
        m_torsion_k, m_torsion_c, m_torsion_t, m_torsion_kstop, m_torsion_lowerstop, m_torsion_upperstop);

    // Create the associated road wheel.
    if (side == LEFT)
        m_road_wheel = chrono_types::make_shared<M113a_RoadWheelLeft>(index);
    else
        m_road_wheel = chrono_types::make_shared<M113a_RoadWheelRight>(index);
}

M113a_Suspension::~M113a_Suspension() {}

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
const ChVector<> M113a_Suspension::GetLocation(PointId which) {
    ChVector<> point;

    switch (which) {
        case ARM:
            point = ChVector<>(0.213, -0.12, 0.199);
            break;
        case ARM_WHEEL:
            point = ChVector<>(0, -0.12, 0);
            break;
        case ARM_CHASSIS:
            point = ChVector<>(0.232, -0.12, 0.217);
            break;
        case SHOCK_A:
            point = ChVector<>(0, -0.12, 0);
            break;
        case SHOCK_C:
            point = ChVector<>(0, -0.12, 1);
            break;
        default:
            point = ChVector<>(0, 0, 0);
            break;
    }

    if (m_side == RIGHT)
        point.y() *= -1;

    return point;
}

}  // end namespace m113
}  // end namespace vehicle
}  // end namespace chrono
<|endoftext|>


<commit_before>// https://github.com/KubaO/stackoverflown/tree/master/questions/lineedit-frame-37831979
#include <QtWidgets>
#include <QtUiTools>

const char ui[] = R"EOF(
 <ui version="4.0">
  <class>Form</class>
  <widget class="QWidget" name="Form">
   <layout class="QFormLayout" name="formLayout">
    <item row="0" column="0">
     <widget class="QLabel" name="label">
      <property name="text">
       <string>TextLabel</string>
      </property>
     </widget>
    </item>
    <item row="0" column="1">
     <widget class="QLineEdit" name="lineEdit"/>
    </item>
   </layout>
  </widget>
  <resources/>
  <connections/>
 </ui>)EOF";

int main(int argc, char ** argv) {
   QApplication app{argc, argv};
   QBuffer buf;
   buf.setData(ui, sizeof(ui));
   auto w = QUiLoader().load(&buf);
   auto & layout = *static_cast<QFormLayout*>(w->layout());
   QLineEdit edit;
   layout.itemAt(0)->widget()->setMinimumHeight(50);
   layout.addRow("Edit here", &edit);
   edit.setMinimumHeight(100);
   layout.activate();
   w->show();
   return app.exec();
}
<commit_msg>Follow the updated question.<commit_after>// https://github.com/KubaO/stackoverflown/tree/master/questions/lineedit-frame-37831979
#include <QtWidgets>
#include <QtUiTools>

const char ui[] = R"EOF(
  <ui version="4.0">
   <class>DatasetWidget</class>
   <widget class="QWidget" name="DatasetWidget">
    <layout class="QVBoxLayout" name="verticalLayout">
     <item>
      <widget class="QLabel" name="lblCaptionDatensatz">
       <property name="text">
        <string>Datensatz:</string>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QLabel" name="lblDatensatz">
       <property name="text">
        <string>C-XXXX-XXX</string>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QLineEdit" name="leDescriptor">
       <property name="maxLength">
        <number>7</number>
       </property>
      </widget>
     </item>
     <item>
      <layout class="QFormLayout" name="formDisp"></layout>
     </item>
    </layout>
   </widget>
  <connections/>
  </ui>)EOF";

int main(int argc, char ** argv) {
   QApplication app{argc, argv};
   QBuffer buf;
   buf.setData(ui, sizeof(ui));
   auto w = QUiLoader().load(&buf);
   auto & layout = *w->findChild<QFormLayout*>("formDisp");
   QLineEdit edit1, edit2;
   layout.addRow("Edit1", &edit1);
   layout.addRow("Edit2", &edit2);
   edit1.setMinimumHeight(50);
   edit2.setMinimumHeight(100);
   w->show();
   return app.exec();
}
<|endoftext|>


<commit_before>/*
 * This file is a part of the open source stm32plus library.
 * Copyright (c) 2011,2012,2013,2014 Andy Brown <www.andybrown.me.uk>
 * Please see website for licensing terms.
 */

#include "config/stm32plus.h"
#include "config/timing.h"
#include "config/timer.h"
#include "config/usart.h"
#include "config/string.h"

using namespace stm32plus;

/**
 * This timer example demonstrates the use of the encoder feature. The STM32's timers understand
 * the phase relationship between two signals output by a rotary encoder and can translate those
 * rising and falling edges into up/down movements of a counter. All you need to do is to connect
 * up the two encoder output pins to channels 1 and 2 of a timer and then configure the timer to
 * operate in encoder mode. The timer's counter will then tick up and down as the encoder is operated.
 *
 * We will use timer 1 to receive the encoder inputs. We will subscribe to capture/compare interrupts
 * so that we get notified when the encoder is moved rather than having to poll for it. We will light
 * different LEDs depending on the direction that the encoder is turned and we will output the value
 * of the counter to the USART.
 *
 * We will also cater for the optional "index pin" that resets the counter to a known value when
 * its triggered. This should be connected to PA0. If you're simulating the encoder then you can
 * press the blue USER button on the F4 discovery board to trigger this.
 *
 * Some wiring is obviously required.
 *
 * If you have an encoder then wire the outputs to PA8, PA9 and remove the call to simulateSignals()
 * in the code. simulateSignals() allows you to validate your code before attaching your hardware.
 * To run in simulation mode you must wire PA2 => PA8 and PA3 => PA9. The simulator will pretend to
 * be an encoder and stimulate the encoder TI1 and TI2 inputs according to a known pattern. See the
 * file simulation_waveform.png for a logic-analyser capture of the simulation waveform.
 *
 * F4 Discovery board:
 *   This example will work out-of-the-box on the F4 discovery board. LEDs are on PD12, PD13. The
 *   USART TX/RX is on PB6/PB7 except on the F4 when it's on PD8/PD9 due to pin availability on
 *   the F4 discovery board.
 *
 * Compatible MCU:
 *   STM32F0
 *   STM32F1
 *   STM32F4
 *
 * Tested on devices:
 *   STM32F051R8T6
 *   STM32F100RBT6
 *   -STM32F103ZET6
 *   STM32F407VGT6
 */

class TimerEncoderTest {

  protected:

    /*
     * LED pins on port D
     */

    enum {
      LED1_PIN = 12,
      LED2_PIN = 13
    };

    /*
     * Set up the two LEDs that will show the direction of the counter (up/down)
     */

    GpioD<DefaultDigitalOutputFeature<LED1_PIN,LED2_PIN>> _leds;

    /*
     * Set up the timer that will be used to receive input from the encoder
     */

    Timer1<
       Timer1GpioFeature<               // TI1/TI2 are CH1_IN and CH2_IN, set them up
         TIMER_REMAP_NONE,              // the GPIO input will not be remapped
         TIM1_CH1_IN,                   // channel 1 = TI1
         TIM1_CH2_IN                    // channel 2 = TI2
       >,
       TimerEncoderFeature<             // we're using the quadrature encoder feature
         EncoderCounterEdge::Input1,    // count on TI1 edges with direction according to TI2
         EncoderPolarity::Rising,       // TI1 polarity
         EncoderPolarity::Rising        // TI2 polarity
       >,
       TimerChannel1Feature,            // we'll use channel 1 for CC interrupts
       Timer1InterruptFeature           // that means we need the interrupt feature
    > _timer;

    /*
     * Declare a USART to write out the counter value. TX/RX = PD8/PD9 for Usart3_Remap1 and
     * PB6/PB7 for Usart1_Remap1. The differences are down to which pins are available on the
     * F4 and F0 discovery boards.
     */

#if defined(STM32PLUS_F4)
    Usart3_Remap1<> _usart;
#else
    Usart1_Remap1<> _usart;
#endif

    UsartPollingOutputStream _outputStream;

    /*
     * Declare the EXTI input (PA0) that should be connected to the encoder's index
     * pin if it has one. A rising edge on this pin resets the counter to a known value
     */

    GpioA<DefaultDigitalInputFeature<0> > _indexPin;
    Exti0 _exti;

    /*
     * The last value received from the counter
     */

    uint16_t _lastValue;

  public:

    /*
     * Constructor, call the member variable constructors where needed
     */

    TimerEncoderTest() :
      _usart(57600),
      _outputStream(_usart),
      _exti(EXTI_Mode_Interrupt,EXTI_Trigger_Rising,_indexPin[0]) {
    }

    /*
     * Run the test
     */

    void run() {

      /*
       * Set ourselves up as a subscriber for interrupts raised by the timer class.
       */

      _timer.TimerInterruptEventSender.insertSubscriber(
          TimerInterruptEventSourceSlot::bind(this,&TimerEncoderTest::onInterrupt)
        );

      /*
       * Initialise the counter for the encoder to have a range of 0..65535 and arrange
       * for automatic management of the index pin (resets to 30000)
       */

      _timer.initialiseEncoderCounter(65535);
      _timer.manageEncoderReset(_exti,30000);

      /*
       * Initialise the capture and subscribe to the interrupts
       */

      _timer.initCapture();
      _timer.enableInterrupts(TIM_IT_CC1);

      /*
       * Initialise the starting value for the counter to 30000
       */

      _timer.setCounter(_lastValue=30000);

      /*
       * Enable the timer
       */

      _timer.enablePeripheral();

      /*
       * Go into an infinite loop simulating the encoder signals. If you've got a real
       * encoder then delete the simulateSignals() and delay() calls and just go into
       * an infinite loop.
       */

      for(;;) {
        simulateSignals();
        MillisecondTimer::delay(1000);
      }
    }

    /*
     * Simulate the signals that an encoder might make. This requires you to make the following
     * wiring: PA2 => PA8. PA3 => PA9. TI1 and TI2 will be generated on PA0/PA1 following the
     * pattern in AN4013 Figure 8. This will simulate 4 up counts and then 4 down counts.
     */

    void simulateSignals() {

      static const bool ti[][2]={
          { false, false },
          { true,  false },         // +1
          { true,  true },
          { false, true },          // +1
          { false, false },
          { true,  false },         // +1
          { true,  true },
          { false, true },          // +1
          { false, false },
          { true,  false },         // reversal
          { false, false },
          { true,  false },
          { false, false },         // -1
          { false, true },
          { true,  true },          // -1
          { true,  false },
          { false, false },         // -1
          { false, true },
          { true,  true },          // -1
          { true,  false },
          { false, false },
          { false, true },          // reversal
          { false, false },
          { false, true },
          { false, false },
          { false, true },
          { false, false }
      };

      enum { TI1 = 2, TI2 = 3 };
      GpioA<DefaultDigitalOutputFeature<TI1,TI2> > simpins;

      uint8_t i;

      // run through the steps allowing 10ms between each one

      for(i=0;i<sizeof(ti)/sizeof(ti[0]);i++) {

        simpins[TI1].setState(ti[i][0]);
        simpins[TI2].setState(ti[i][1]);

        MillisecondTimer::delay(10);
      }
    }

    /*
     * Subscriber callback function. This is called when the CC1 interrupt that we've
     * enabled is fired. Don't do much in here and be aware of re-entrancy issues.
     */

    void onInterrupt(TimerEventType tet,uint8_t /* timerNumber */) {

      uint16_t currentValue;

      /*
       * Not likely to be anything else but anyway...
       */

      if(tet!=TimerEventType::EVENT_COMPARE1)
        return;

      /*
       * A positive change will light LED1, a negative change will light LED2
       */

      currentValue=_timer.getCounter();
      if(currentValue>_lastValue || _lastValue-currentValue>30000) {

        // current > last or there's been a wrap (i.e. silly difference between last and current)

        _leds[LED1_PIN].set();
        _leds[LED2_PIN].reset();
      }
      else {
        _leds[LED1_PIN].reset();
        _leds[LED2_PIN].set();
      }

      /*
       * Write out the current value to the USART if it's connected
       */

      _outputStream << StringUtil::Ascii(currentValue) << "\r\n";
      _lastValue=currentValue;
    }
};

/*
 * Main entry point
 */

int main() {

  MillisecondTimer::initialise();

  TimerEncoderTest test;
  test.run();

  // not reached
  return 0;
}
<commit_msg>tested on f1hd<commit_after>/*
 * This file is a part of the open source stm32plus library.
 * Copyright (c) 2011,2012,2013,2014 Andy Brown <www.andybrown.me.uk>
 * Please see website for licensing terms.
 */

#include "config/stm32plus.h"
#include "config/timing.h"
#include "config/timer.h"
#include "config/usart.h"
#include "config/string.h"

using namespace stm32plus;

/**
 * This timer example demonstrates the use of the encoder feature. The STM32's timers understand
 * the phase relationship between two signals output by a rotary encoder and can translate those
 * rising and falling edges into up/down movements of a counter. All you need to do is to connect
 * up the two encoder output pins to channels 1 and 2 of a timer and then configure the timer to
 * operate in encoder mode. The timer's counter will then tick up and down as the encoder is operated.
 *
 * We will use timer 1 to receive the encoder inputs. We will subscribe to capture/compare interrupts
 * so that we get notified when the encoder is moved rather than having to poll for it. We will light
 * different LEDs depending on the direction that the encoder is turned and we will output the value
 * of the counter to the USART.
 *
 * We will also cater for the optional "index pin" that resets the counter to a known value when
 * its triggered. This should be connected to PA0. If you're simulating the encoder then you can
 * press the blue USER button on the F4 discovery board to trigger this.
 *
 * Some wiring is obviously required.
 *
 * If you have an encoder then wire the outputs to PA8, PA9 and remove the call to simulateSignals()
 * in the code. simulateSignals() allows you to validate your code before attaching your hardware.
 * To run in simulation mode you must wire PA2 => PA8 and PA3 => PA9. The simulator will pretend to
 * be an encoder and stimulate the encoder TI1 and TI2 inputs according to a known pattern. See the
 * file simulation_waveform.png for a logic-analyser capture of the simulation waveform.
 *
 * F4 Discovery board:
 *   This example will work out-of-the-box on the F4 discovery board. LEDs are on PD12, PD13. The
 *   USART TX/RX is on PB6/PB7 except on the F4 when it's on PD8/PD9 due to pin availability on
 *   the F4 discovery board.
 *
 * Compatible MCU:
 *   STM32F0
 *   STM32F1
 *   STM32F4
 *
 * Tested on devices:
 *   STM32F051R8T6
 *   STM32F100RBT6
 *   STM32F103ZET6
 *   STM32F407VGT6
 */

class TimerEncoderTest {

  protected:

    /*
     * LED pins on port D
     */

    enum {
      LED1_PIN = 12,
      LED2_PIN = 13
    };

    /*
     * Set up the two LEDs that will show the direction of the counter (up/down)
     */

    GpioD<DefaultDigitalOutputFeature<LED1_PIN,LED2_PIN>> _leds;

    /*
     * Set up the timer that will be used to receive input from the encoder
     */

    Timer1<
       Timer1GpioFeature<               // TI1/TI2 are CH1_IN and CH2_IN, set them up
         TIMER_REMAP_NONE,              // the GPIO input will not be remapped
         TIM1_CH1_IN,                   // channel 1 = TI1
         TIM1_CH2_IN                    // channel 2 = TI2
       >,
       TimerEncoderFeature<             // we're using the quadrature encoder feature
         EncoderCounterEdge::Input1,    // count on TI1 edges with direction according to TI2
         EncoderPolarity::Rising,       // TI1 polarity
         EncoderPolarity::Rising        // TI2 polarity
       >,
       TimerChannel1Feature,            // we'll use channel 1 for CC interrupts
       Timer1InterruptFeature           // that means we need the interrupt feature
    > _timer;

    /*
     * Declare a USART to write out the counter value. TX/RX = PD8/PD9 for Usart3_Remap1 and
     * PB6/PB7 for Usart1_Remap1. The differences are down to which pins are available on the
     * F4 and F0 discovery boards.
     */

#if defined(STM32PLUS_F4)
    Usart3_Remap1<> _usart;
#else
    Usart1_Remap1<> _usart;
#endif

    UsartPollingOutputStream _outputStream;

    /*
     * Declare the EXTI input (PA0) that should be connected to the encoder's index
     * pin if it has one. A rising edge on this pin resets the counter to a known value
     */

    GpioA<DefaultDigitalInputFeature<0> > _indexPin;
    Exti0 _exti;

    /*
     * The last value received from the counter
     */

    uint16_t _lastValue;

  public:

    /*
     * Constructor, call the member variable constructors where needed
     */

    TimerEncoderTest() :
      _usart(57600),
      _outputStream(_usart),
      _exti(EXTI_Mode_Interrupt,EXTI_Trigger_Rising,_indexPin[0]) {
    }

    /*
     * Run the test
     */

    void run() {

      /*
       * Set ourselves up as a subscriber for interrupts raised by the timer class.
       */

      _timer.TimerInterruptEventSender.insertSubscriber(
          TimerInterruptEventSourceSlot::bind(this,&TimerEncoderTest::onInterrupt)
        );

      /*
       * Initialise the counter for the encoder to have a range of 0..65535 and arrange
       * for automatic management of the index pin (resets to 30000)
       */

      _timer.initialiseEncoderCounter(65535);
      _timer.manageEncoderReset(_exti,30000);

      /*
       * Initialise the capture and subscribe to the interrupts
       */

      _timer.initCapture();
      _timer.enableInterrupts(TIM_IT_CC1);

      /*
       * Initialise the starting value for the counter to 30000
       */

      _timer.setCounter(_lastValue=30000);

      /*
       * Enable the timer
       */

      _timer.enablePeripheral();

      /*
       * Go into an infinite loop simulating the encoder signals. If you've got a real
       * encoder then delete the simulateSignals() and delay() calls and just go into
       * an infinite loop.
       */

      for(;;) {
        simulateSignals();
        MillisecondTimer::delay(1000);
      }
    }

    /*
     * Simulate the signals that an encoder might make. This requires you to make the following
     * wiring: PA2 => PA8. PA3 => PA9. TI1 and TI2 will be generated on PA0/PA1 following the
     * pattern in AN4013 Figure 8. This will simulate 4 up counts and then 4 down counts.
     */

    void simulateSignals() {

      static const bool ti[][2]={
          { false, false },
          { true,  false },         // +1
          { true,  true },
          { false, true },          // +1
          { false, false },
          { true,  false },         // +1
          { true,  true },
          { false, true },          // +1
          { false, false },
          { true,  false },         // reversal
          { false, false },
          { true,  false },
          { false, false },         // -1
          { false, true },
          { true,  true },          // -1
          { true,  false },
          { false, false },         // -1
          { false, true },
          { true,  true },          // -1
          { true,  false },
          { false, false },
          { false, true },          // reversal
          { false, false },
          { false, true },
          { false, false },
          { false, true },
          { false, false }
      };

      enum { TI1 = 2, TI2 = 3 };
      GpioA<DefaultDigitalOutputFeature<TI1,TI2> > simpins;

      uint8_t i;

      // run through the steps allowing 10ms between each one

      for(i=0;i<sizeof(ti)/sizeof(ti[0]);i++) {

        simpins[TI1].setState(ti[i][0]);
        simpins[TI2].setState(ti[i][1]);

        MillisecondTimer::delay(10);
      }
    }

    /*
     * Subscriber callback function. This is called when the CC1 interrupt that we've
     * enabled is fired. Don't do much in here and be aware of re-entrancy issues.
     */

    void onInterrupt(TimerEventType tet,uint8_t /* timerNumber */) {

      uint16_t currentValue;

      /*
       * Not likely to be anything else but anyway...
       */

      if(tet!=TimerEventType::EVENT_COMPARE1)
        return;

      /*
       * A positive change will light LED1, a negative change will light LED2
       */

      currentValue=_timer.getCounter();
      if(currentValue>_lastValue || _lastValue-currentValue>30000) {

        // current > last or there's been a wrap (i.e. silly difference between last and current)

        _leds[LED1_PIN].set();
        _leds[LED2_PIN].reset();
      }
      else {
        _leds[LED1_PIN].reset();
        _leds[LED2_PIN].set();
      }

      /*
       * Write out the current value to the USART if it's connected
       */

      _outputStream << StringUtil::Ascii(currentValue) << "\r\n";
      _lastValue=currentValue;
    }
};

/*
 * Main entry point
 */

int main() {

  MillisecondTimer::initialise();

  TimerEncoderTest test;
  test.run();

  // not reached
  return 0;
}
<|endoftext|>


<commit_before>/* Copyright (c) 2010 - 2021 Advanced Micro Devices, Inc.

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE. */

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 3343
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<commit_msg>SWDEV-2 - Change OpenCL version number from  3343 to 3344<commit_after>/* Copyright (c) 2010 - 2021 Advanced Micro Devices, Inc.

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE. */

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 3344
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<|endoftext|>


<commit_before>/* Copyright (c) 2010-present Advanced Micro Devices, Inc.

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE. */

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 3132
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<commit_msg>SWDEV-2 - Change OpenCL version number from  3132 to 3133<commit_after>/* Copyright (c) 2010-present Advanced Micro Devices, Inc.

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE. */

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 3133
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<|endoftext|>


<commit_before>/* Copyright (c) 2010-present Advanced Micro Devices, Inc.

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE. */

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 3102
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<commit_msg>SWDEV-2 - Change OpenCL version number from  3102 to 3103<commit_after>/* Copyright (c) 2010-present Advanced Micro Devices, Inc.

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE. */

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 3103
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<|endoftext|>


<commit_before>#include "rotation_copying_system.h"
#include <Box2D\Dynamics\b2Body.h>

#include "game/transcendental/entity_id.h"
#include "augs/graphics/renderer.h"

#include "game/components/physics_component.h"
#include "game/components/special_physics_component.h"
#include "game/components/gun_component.h"
#include "game/detail/inventory_slot_id.h"
#include "game/detail/inventory_slot.h"
#include "game/detail/inventory_utils.h"

#include "augs/ensure.h"

#include "game/components/rotation_copying_component.h"
#include "game/components/transform_component.h"

#include "augs/misc/timer.h"

#include "game/transcendental/entity_handle.h"
#include "game/transcendental/step.h"
#include "game/transcendental/cosmos.h"

using namespace augs;

float colinearize_AB(const vec2 O_center_of_rotation, vec2 A_rifle_center, vec2 B_barrel, vec2 C_crosshair) {
	auto crosshair_vector = C_crosshair - O_center_of_rotation;
	auto barrel_vector = B_barrel - O_center_of_rotation;

	if (crosshair_vector.is_epsilon(1.f))
		crosshair_vector.set(1, 0);

	if (crosshair_vector.length() < barrel_vector.length() + 1.f)
		return crosshair_vector.degrees();

	C_crosshair = O_center_of_rotation + crosshair_vector;

	const float oc_radius = crosshair_vector.length();

	const auto intersection = circle_ray_intersection(B_barrel, A_rifle_center, O_center_of_rotation, oc_radius);
	const bool has_intersection = intersection.first;

	ensure(has_intersection);

	const auto G = intersection.second;
	const auto CG = C_crosshair - G;
	const auto AG = A_rifle_center - G;

	const auto final_angle = 2 * (CG.degrees() - AG.degrees());

	if (augs::renderer::get_current().debug_draw_colinearization) {
		auto& ln = augs::renderer::get_current().logic_lines;

		ln.draw_cyan(O_center_of_rotation, C_crosshair);
		ln.draw_red(O_center_of_rotation, A_rifle_center);
		ln.draw_red(O_center_of_rotation, B_barrel);
		ln.draw_yellow(O_center_of_rotation, G);

		ln.draw_green(G, A_rifle_center);
		ln.draw_green(G, C_crosshair);

		A_rifle_center.rotate(final_angle, O_center_of_rotation);
		B_barrel.rotate(final_angle, O_center_of_rotation);

		ln.draw_red(O_center_of_rotation, A_rifle_center);
		ln.draw_red(O_center_of_rotation, B_barrel);

		ln.draw(A_rifle_center - (B_barrel - A_rifle_center) * 100, B_barrel + (B_barrel - A_rifle_center)*100);
	}

	return final_angle;
}

float rotation_copying_system::resolve_rotation_copying_value(const const_entity_handle it) const {
	auto& rotation_copying = it.get<components::rotation_copying>();
	auto& cosmos = it.get_cosmos();
	const auto target = cosmos[rotation_copying.target];

	if (target.dead())
		return 0.f;

	float new_angle = 0.f;

	if (rotation_copying.look_mode == components::rotation_copying::look_type::ROTATION) {
		new_angle = target.logic_transform().rotation;
	}
	else if (rotation_copying.look_mode == components::rotation_copying::look_type::POSITION) {
		const auto& target_transform = target.logic_transform();

		const auto diff = target_transform.pos - position(it);

		if (diff.is_epsilon(1.f))
			new_angle = 0.f;
		else
			new_angle = diff.degrees();

		if (rotation_copying.colinearize_item_in_hand) {
			auto hand = it.map_primary_action_to_secondary_hand_if_primary_empty(0);

			if (hand.has_items()) {
				const auto subject_item = hand.get_items_inside()[0];

				const auto* maybe_gun = subject_item.find<components::gun>();

				if (maybe_gun) {
					const auto rifle_transform = subject_item.logic_transform();
					auto rifle_center = rifle_transform.pos;
					auto barrel = maybe_gun->calculate_barrel_transform(rifle_transform).pos;
					const auto mc = position(it);

					rifle_center.rotate(-rotation(it), mc);
					barrel.rotate(-rotation(it), mc);

					auto crosshair_vector = target_transform.pos - mc;

					new_angle = colinearize_AB(mc, rifle_center, barrel, target_transform.pos);
				}
			}
		}
	}
	else {
		if (target.has<components::physics>()) {
			const auto target_physics = target.get<components::physics>();

			vec2 direction;

			if (rotation_copying.look_mode == components::rotation_copying::look_type::VELOCITY)
				direction = vec2(target_physics.velocity());

			if (direction.non_zero())
				new_angle = direction.degrees();
		}
	}

	if (rotation_copying.easing_mode == components::rotation_copying::easing_type::EXPONENTIAL) {
		ensure(0);
		//float averaging_constant = static_cast<float>(
		//	pow(rotation_copying.smoothing_average_factor, rotation_copying.averages_per_sec * delta_seconds())
		//	);
		//
		//rotation_copying.last_rotation_interpolant = (rotation_copying.last_rotation_interpolant * averaging_constant + new_rotation * (1.0f - averaging_constant)).normalize();
		//rotation_copying.last_value = rotation_copying.last_rotation_interpolant.degrees();
	}
	else if (rotation_copying.easing_mode == components::rotation_copying::easing_type::NONE) {

	}

	return new_angle;
}

void rotation_copying_system::update_rotations(cosmos& cosmos) const {
	for (const auto it : cosmos.get(processing_subjects::WITH_ROTATION_COPYING)) {
		const auto& rotation_copying = it.get<components::rotation_copying>();

		if (rotation_copying.update_value) {
			if (it.has<components::physics>()) {
				auto target_angle = resolve_rotation_copying_value(it);
				auto& phys = it.get<components::physics>();

				phys.set_transform({ phys.get_position(), target_angle });
				phys.set_angular_velocity(0);
			}
			else {
				it.get<components::transform>().rotation = resolve_rotation_copying_value(it);
			}
		}
	}
}<commit_msg>usage of guns_wielded<commit_after>#include "rotation_copying_system.h"
#include <Box2D\Dynamics\b2Body.h>

#include "game/transcendental/entity_id.h"
#include "augs/graphics/renderer.h"

#include "game/components/physics_component.h"
#include "game/components/special_physics_component.h"
#include "game/components/gun_component.h"
#include "game/detail/inventory_slot_id.h"
#include "game/detail/inventory_slot.h"
#include "game/detail/inventory_utils.h"

#include "augs/ensure.h"

#include "game/components/rotation_copying_component.h"
#include "game/components/transform_component.h"

#include "augs/misc/timer.h"

#include "game/transcendental/entity_handle.h"
#include "game/transcendental/step.h"
#include "game/transcendental/cosmos.h"

using namespace augs;

float colinearize_AB(const vec2 O_center_of_rotation, vec2 A_rifle_center, vec2 B_barrel, vec2 C_crosshair) {
	auto crosshair_vector = C_crosshair - O_center_of_rotation;
	auto barrel_vector = B_barrel - O_center_of_rotation;

	if (crosshair_vector.is_epsilon(1.f))
		crosshair_vector.set(1, 0);

	if (crosshair_vector.length() < barrel_vector.length() + 1.f)
		return crosshair_vector.degrees();

	C_crosshair = O_center_of_rotation + crosshair_vector;

	const float oc_radius = crosshair_vector.length();

	const auto intersection = circle_ray_intersection(B_barrel, A_rifle_center, O_center_of_rotation, oc_radius);
	const bool has_intersection = intersection.first;

	ensure(has_intersection);

	const auto G = intersection.second;
	const auto CG = C_crosshair - G;
	const auto AG = A_rifle_center - G;

	const auto final_angle = 2 * (CG.degrees() - AG.degrees());

	if (augs::renderer::get_current().debug_draw_colinearization) {
		auto& ln = augs::renderer::get_current().logic_lines;

		ln.draw_cyan(O_center_of_rotation, C_crosshair);
		ln.draw_red(O_center_of_rotation, A_rifle_center);
		ln.draw_red(O_center_of_rotation, B_barrel);
		ln.draw_yellow(O_center_of_rotation, G);

		ln.draw_green(G, A_rifle_center);
		ln.draw_green(G, C_crosshair);

		A_rifle_center.rotate(final_angle, O_center_of_rotation);
		B_barrel.rotate(final_angle, O_center_of_rotation);

		ln.draw_red(O_center_of_rotation, A_rifle_center);
		ln.draw_red(O_center_of_rotation, B_barrel);

		ln.draw(A_rifle_center - (B_barrel - A_rifle_center) * 100, B_barrel + (B_barrel - A_rifle_center)*100);
	}

	return final_angle;
}

float rotation_copying_system::resolve_rotation_copying_value(const const_entity_handle it) const {
	auto& rotation_copying = it.get<components::rotation_copying>();
	auto& cosmos = it.get_cosmos();
	const auto target = cosmos[rotation_copying.target];

	if (target.dead())
		return 0.f;

	float new_angle = 0.f;

	if (rotation_copying.look_mode == components::rotation_copying::look_type::ROTATION) {
		new_angle = target.logic_transform().rotation;
	}
	else if (rotation_copying.look_mode == components::rotation_copying::look_type::POSITION) {
		const auto& target_transform = target.logic_transform();

		const auto diff = target_transform.pos - position(it);

		if (diff.is_epsilon(1.f))
			new_angle = 0.f;
		else
			new_angle = diff.degrees();

		if (rotation_copying.colinearize_item_in_hand) {
			auto guns = it.guns_wielded();

			if (guns.size() > 0) {
				const auto subject_item = guns[0];

				const auto& gun = subject_item.get<components::gun>();

				const auto rifle_transform = subject_item.logic_transform();
				auto rifle_center = rifle_transform.pos;
				auto barrel = gun.calculate_barrel_transform(rifle_transform).pos;
				const auto mc = position(it);

				rifle_center.rotate(-rotation(it), mc);
				barrel.rotate(-rotation(it), mc);

				auto crosshair_vector = target_transform.pos - mc;

				new_angle = colinearize_AB(mc, rifle_center, barrel, target_transform.pos);
			}
		}
	}
	else {
		if (target.has<components::physics>()) {
			const auto target_physics = target.get<components::physics>();

			vec2 direction;

			if (rotation_copying.look_mode == components::rotation_copying::look_type::VELOCITY)
				direction = vec2(target_physics.velocity());

			if (direction.non_zero())
				new_angle = direction.degrees();
		}
	}

	if (rotation_copying.easing_mode == components::rotation_copying::easing_type::EXPONENTIAL) {
		ensure(0);
		//float averaging_constant = static_cast<float>(
		//	pow(rotation_copying.smoothing_average_factor, rotation_copying.averages_per_sec * delta_seconds())
		//	);
		//
		//rotation_copying.last_rotation_interpolant = (rotation_copying.last_rotation_interpolant * averaging_constant + new_rotation * (1.0f - averaging_constant)).normalize();
		//rotation_copying.last_value = rotation_copying.last_rotation_interpolant.degrees();
	}
	else if (rotation_copying.easing_mode == components::rotation_copying::easing_type::NONE) {

	}

	return new_angle;
}

void rotation_copying_system::update_rotations(cosmos& cosmos) const {
	for (const auto it : cosmos.get(processing_subjects::WITH_ROTATION_COPYING)) {
		const auto& rotation_copying = it.get<components::rotation_copying>();

		if (rotation_copying.update_value) {
			if (it.has<components::physics>()) {
				auto target_angle = resolve_rotation_copying_value(it);
				auto& phys = it.get<components::physics>();

				phys.set_transform({ phys.get_position(), target_angle });
				phys.set_angular_velocity(0);
			}
			else {
				it.get<components::transform>().rotation = resolve_rotation_copying_value(it);
			}
		}
	}
}<|endoftext|>


<commit_before><commit_msg>Fix bug & optimize completion<commit_after><|endoftext|>


<commit_before>/*
  This file is part of the KDE PIM project.

  Copyright (C) 2009 Martin Koller <kollix@aon.at>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License version 2 as published by the Free Software Foundation.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include <qtest_kde.h>
#include "testdateparser.h"

#include <mimelib/datetime.h>

#include <QList>
#include <QByteArray>

//---------------------------------------------------------------------

QTEST_KDEMAIN( TestDateParser, NoGUI )

//---------------------------------------------------------------------

void TestDateParser::testParsing()
{
  QList<QByteArray> dates;

  // first of a pair is string to parse (local time),
  // second is the same in ISO-8601 format (YYYY-MM-DDTHH:MM:SS) UTC
  // non-RFC2822 dates
  dates << "Mon Dec 15 11:04:05 PST 2003"      << "2003-12-15T19:04:05";
  dates << "Tue, Feb 04, 2003 00:01:20 +0000"  << "2003-02-04T00:01:20";
  dates << "Tue, Feb 04, 2003 10:01:20 -0220"  << "2003-02-04T12:21:20";
  dates << "Tue Feb 04, 2003 00:01:20 +0000"   << "2003-02-04T00:01:20";
  dates << "Fri Oct 14 09:21:49 CEST 2005"     << "2005-10-14T07:21:49";
  dates << "Tue Mar 23 18:00:02 2004"          << "2004-03-23T18:00:02";

  QByteArray date;
  for (int i = 0; i < dates.count(); i += 2)
  {
    DwDateTime dwt(dates[i].constData());
    dwt.Parse();

    QDateTime test;
    test.setTime_t(dwt.AsUnixTime());

    QDateTime iso;
    iso = QDateTime::fromString(dates[i+1], Qt::ISODate);
    iso.setTimeSpec(Qt::UTC);
    //qDebug() << test << iso;
    QVERIFY2(test == iso, dates[i]);
  }
}

//---------------------------------------------------------------------
<commit_msg>Add unit test for bug 207766, but it doesn't fail.<commit_after>/*
  This file is part of the KDE PIM project.

  Copyright (C) 2009 Martin Koller <kollix@aon.at>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License version 2 as published by the Free Software Foundation.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include <qtest_kde.h>
#include "testdateparser.h"

#include <mimelib/datetime.h>

#include <QList>
#include <QByteArray>

//---------------------------------------------------------------------

QTEST_KDEMAIN( TestDateParser, NoGUI )

//---------------------------------------------------------------------

void TestDateParser::testParsing()
{
  QList<QByteArray> dates;

  // first of a pair is string to parse (local time),
  // second is the same in ISO-8601 format (YYYY-MM-DDTHH:MM:SS) UTC
  // non-RFC2822 dates
  dates << "Mon Dec 15 11:04:05 PST 2003"      << "2003-12-15T19:04:05";
  dates << "Tue, Feb 04, 2003 00:01:20 +0000"  << "2003-02-04T00:01:20";
  dates << "Tue, Feb 04, 2003 10:01:20 -0220"  << "2003-02-04T12:21:20";
  dates << "Fri, 18 Sep 2009 04:44:55 -0400"   << "2009-09-18T08:44:55";
  dates << "Tue Feb 04, 2003 00:01:20 +0000"   << "2003-02-04T00:01:20";
  dates << "Fri Oct 14 09:21:49 CEST 2005"     << "2005-10-14T07:21:49";
  dates << "Tue Mar 23 18:00:02 2004"          << "2004-03-23T18:00:02";

  QByteArray date;
  for (int i = 0; i < dates.count(); i += 2)
  {
    DwDateTime dwt(dates[i].constData());
    dwt.Parse();

    QDateTime test;
    test.setTime_t(dwt.AsUnixTime());

    QDateTime iso;
    iso = QDateTime::fromString(dates[i+1], Qt::ISODate);
    iso.setTimeSpec(Qt::UTC);
    //qDebug() << test << iso;
    QVERIFY2(test == iso, dates[i]);
  }
}

//---------------------------------------------------------------------
<|endoftext|>


<commit_before>#include <stdio.h>
#include <vector>
#define OK 1
#define ERROR 0
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
#define ElemType int

int main()
{
	std::vector<ElemType> v;
	int a, i;
	ElemType e, x;
	if(v)    // 判断顺序表是否创建成功
	{
		printf("A Sequence List Has Created.\n");
	}
	while(1)
	{
		printf("1:Insert element\n2:Delete element\n3:Load all elements\n0:Exit\nPlease choose:\n");
		scanf("%d",&a);
		switch(a)
		{
			case 1: scanf("%d%d",&i,&x);
					vector<ElemType>::iterator I = v.begin();
					if(v.insert(I,i,x)) printf("Insert Error!\n"); // 判断i值是否合法，请填空
					else printf("The Element %d is Successfully Inserted!\n", x);
					break;
			case 2: scanf("%d",&i);
					vector<ElemType>::iterator I = v.begin();
					I=I+i;

					if(v.erase(I)) printf("Delete Error!\n"); // 判断i值是否合法，请填空
					else printf("The Element %d is Successfully Deleted!\n", e);
					break;
			case 3:
			vector<ElemType>::iterator tempIterator;
			for( tempIterator = v.begin(); tempIterator != v.end(); tempIterator++ )
    				cout << *tempIterator;
    		cout << endl;
					break;
			case 0: return 1;
		}
	}
}<commit_msg>update uoj8576<commit_after>#include <stdio.h>
#include <vector>
#define OK 1
#define ERROR 0
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
#define ElemType int

int main()
{
	std::vector<ElemType> v;
	int a, i;
	ElemType e, x;
	if(v.empty())    // 判断顺序表是否创建成功
	{
		printf("A Sequence List Has Created.\n");
	}
	while(1)
	{
		printf("1:Insert element\n2:Delete element\n3:Load all elements\n0:Exit\nPlease choose:\n");
		scanf("%d",&a);
		switch(a)
		{
			case 1: scanf("%d%d",&i,&x);
					vector<ElemType>::iterator I = v.begin();
					if(v.insert(I,i,x)) printf("Insert Error!\n"); // 判断i值是否合法，请填空
					else printf("The Element %d is Successfully Inserted!\n", x);
					break;
			case 2: scanf("%d",&i);
					vector<ElemType>::iterator I = v.begin();
					I=I+i;

					if(v.erase(I)) printf("Delete Error!\n"); // 判断i值是否合法，请填空
					else printf("The Element %d is Successfully Deleted!\n", e);
					break;
			case 3:
			vector<ElemType>::iterator tempIterator;
			for( tempIterator = v.begin(); tempIterator != v.end(); tempIterator++ )
    				cout << *tempIterator;
    		cout << endl;
					break;
			case 0: return 1;
		}
	}
}<|endoftext|>