<commit_before>/** \brief  A MARC-21 filter uliity that replace URNs in 856u-fields with URLs
 *  \author Oliver Obenland (oliver.obenland@uni-tuebingen.de)
 *
 *  \copyright 2016,2017 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>
#include <string>
#include <vector>

#include "MarcReader.h"
#include "MarcRecord.h"
#include "MarcWriter.h"

void Usage() {
    std::cerr << "Usage: " << ::progname << " [-v|--verbose] marc_input marc_output\n";
    std::exit(EXIT_FAILURE);
}

inline bool IsHttpOrHttpsURL(const std::string &url_candidate) {
    return StringUtil::StartsWith(url_candidate, "http://") or StringUtil::StartsWith(url_candidate, "https://");
}

// Returns the number of extracted 856u subfields.
size_t ExtractAllHttpOrHttps856uSubfields(const MarcRecord &record, std::vector<std::string> * const _856u_urls) {
    std::vector<size_t> field_indices;
    if (record.getFieldIndices("856", &field_indices) == 0)
        return 0;

    for (const auto field_index : field_indices) {
        std::string _856u_subfield_value(record.extractFirstSubfield(field_index, 'u'));
        if (IsHttpOrHttpsURL(_856u_subfield_value))
            _856u_urls->emplace_back(_856u_subfield_value);
    }

    return _856u_urls->size();
}

// Returns true if "test_string" is the suffix of "url" after stripping off the schema and domain name as well as
// a single slash after the domain name.
bool IsSuffixOfURL(const std::string &url, const std::string &test_string) {
    const bool starts_with_http(StringUtil::StartsWith(url, "http://"));
    if (not starts_with_http and not StringUtil::StartsWith(url, "https://"))
        return false;

    size_t next_slash_pos;
    if (starts_with_http) {
        next_slash_pos = url.find('/', std::strlen("http://"));
        if (unlikely(next_slash_pos == std::string::npos))
            return false;
    } else { // We assume that "url" started with "https://"
        next_slash_pos = url.find('/', std::strlen("https://"));
        if (unlikely(next_slash_pos == std::string::npos))
            return false;
    }
    if (unlikely(next_slash_pos + 1 >= url.size()))
        return false; // We have no path component in our URL.

    return url.substr(next_slash_pos + 1) == test_string;
}

// Returns true if "test_string" is a proper suffix of any of the URLs contained in "urls".
bool IsSuffixOfAnyURL(const std::vector<std::string> &urls, const std::string &test_string) {
    for (const auto &url : urls) {
        if (IsSuffixOfURL(url, test_string))
            return true;
    }

    return false;
}

void NormaliseURLs(const bool verbose, MarcReader * const reader, MarcWriter * const writer) {
    unsigned count(0), modified_count(0), duplicate_skip_count(0);
    while (MarcRecord record = reader->read()) {
        ++count;

        std::vector<std::string> _856u_urls;
        ExtractAllHttpOrHttps856uSubfields(record, &_856u_urls);

        bool modified_record(false);
        std::unordered_set<std::string> already_seen_links;

        std::vector<size_t> erase_field_indices;
        for (size_t field_no(record.getFieldIndex("856")); record.getTag(field_no) == "856"; /* empty */) {
            Subfields _856_subfields(record.getSubfields(field_no));
            bool duplicate_link(false);
            if (_856_subfields.hasSubfield('u')) {
                const std::string u_subfield(StringUtil::Trim(_856_subfields.getFirstSubfieldValue('u')));

                if (IsHttpOrHttpsURL(u_subfield)) {
                    if (already_seen_links.find(u_subfield) == already_seen_links.cend())
                        already_seen_links.insert(u_subfield);
                    else
                        duplicate_link = true;
                } else if (IsSuffixOfAnyURL(_856u_urls, u_subfield) )
                    erase_field_indices.emplace_back(field_no);
                else {
                    std::string new_http_replacement_link;
                    if (StringUtil::StartsWith(u_subfield, "urn:"))
                        new_http_replacement_link = "https://nbn-resolving.org/" + u_subfield;
                    else if (StringUtil::StartsWith(u_subfield, "10900/"))
                        new_http_replacement_link = "https://publikationen.uni-tuebingen.de/xmlui/handle/"
                                                    + u_subfield;
                    else
                        new_http_replacement_link = "http://" + u_subfield;
                    if (already_seen_links.find(new_http_replacement_link) == already_seen_links.cend()) {
                        _856_subfields.replace('u', u_subfield, new_http_replacement_link);
                        if (verbose)
                            std::cout << "Replaced \"" << u_subfield << "\" with \"" << new_http_replacement_link
                                      << "\". (PPN: " << record.getControlNumber() << ")\n";
                        already_seen_links.insert(new_http_replacement_link);
                        modified_record = true;
                    } else
                        duplicate_link = true;
                }
            }

            if (not duplicate_link)
                ++field_no;
            else {
                ++duplicate_skip_count;
                if (verbose)
                    std::cout << "Skipping duplicate, control numbers is " << record.getControlNumber() << ".\n";
                record.deleteField(field_no);
                modified_record = true;
            }
        }

        if (not erase_field_indices.empty()) {
            // We need to remove fields starting from the end of the record.
            std::sort(erase_field_indices.begin(), erase_field_indices.end(), std::greater<size_t>());

            for (const size_t field_index : erase_field_indices)
                record.deleteField(field_index);

            modified_record = true;
        }

        if (modified_record)
            ++modified_count;

        writer->write(record);
    }

    std::cerr << "Read " << count << " records.\n";
    std::cerr << "Modified " << modified_count << " record(s).\n";
    std::cerr << "Skipped " << duplicate_skip_count << " duplicate links.\n";
}

int main(int argc, char **argv) {
    ::progname = argv[0];

    if (argc != 3 and argc != 4)
        Usage();

    bool verbose(std::strcmp("-v", argv[1]) == 0 or std::strcmp("--verbose", argv[1]) == 0);
    if (verbose)
        ++argv;
    std::unique_ptr <MarcReader> marc_reader(MarcReader::Factory(argv[1]));
    std::unique_ptr <MarcWriter> marc_writer(MarcWriter::Factory(argv[2]));
    try {
        NormaliseURLs(verbose, marc_reader.get(), marc_writer.get());
    } catch (const std::exception &x) {
        Error("caught exception: " + std::string(x.what()));
    }
}
<commit_msg>Hopefully more readable code.<commit_after>/** \brief  A MARC-21 filter uliity that replace URNs in 856u-fields with URLs
 *  \author Oliver Obenland (oliver.obenland@uni-tuebingen.de)
 *
 *  \copyright 2016,2017 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>
#include <string>
#include <vector>

#include "MarcReader.h"
#include "MarcRecord.h"
#include "MarcWriter.h"

void Usage() {
    std::cerr << "Usage: " << ::progname << " [-v|--verbose] marc_input marc_output\n";
    std::exit(EXIT_FAILURE);
}

inline bool IsHttpOrHttpsURL(const std::string &url_candidate) {
    return StringUtil::StartsWith(url_candidate, "http://") or StringUtil::StartsWith(url_candidate, "https://");
}

// Returns the number of extracted 856u subfields.
size_t ExtractAllHttpOrHttps856uSubfields(const MarcRecord &record, std::vector<std::string> * const _856u_urls) {
    std::vector<size_t> field_indices;
    if (record.getFieldIndices("856", &field_indices) == 0)
        return 0;

    for (const auto field_index : field_indices) {
        std::string _856u_subfield_value(record.extractFirstSubfield(field_index, 'u'));
        if (IsHttpOrHttpsURL(_856u_subfield_value))
            _856u_urls->emplace_back(_856u_subfield_value);
    }

    return _856u_urls->size();
}

// Returns true if "test_string" is the suffix of "url" after stripping off the schema and domain name as well as
// a single slash after the domain name.
bool IsSuffixOfURL(const std::string &url, const std::string &test_string) {
    const bool starts_with_http(StringUtil::StartsWith(url, "http://"));
    if (not starts_with_http and not StringUtil::StartsWith(url, "https://"))
        return false;

    const size_t next_slash_pos(url.find('/', starts_with_http ? std::strlen("http://") : std::strlen("https://")));
    if (unlikely(next_slash_pos == std::string::npos))
        return false;
    if (unlikely(next_slash_pos + 1 >= url.size()))
        return false; // We have no path component in our URL.

    return url.substr(next_slash_pos + 1) == test_string;
}

// Returns true if "test_string" is a proper suffix of any of the URLs contained in "urls".
bool IsSuffixOfAnyURL(const std::vector<std::string> &urls, const std::string &test_string) {
    for (const auto &url : urls) {
        if (IsSuffixOfURL(url, test_string))
            return true;
    }

    return false;
}

void NormaliseURLs(const bool verbose, MarcReader * const reader, MarcWriter * const writer) {
    unsigned count(0), modified_count(0), duplicate_skip_count(0);
    while (MarcRecord record = reader->read()) {
        ++count;

        std::vector<std::string> _856u_urls;
        ExtractAllHttpOrHttps856uSubfields(record, &_856u_urls);

        bool modified_record(false);
        std::unordered_set<std::string> already_seen_links;

        std::vector<size_t> erase_field_indices;
        for (size_t field_no(record.getFieldIndex("856")); record.getTag(field_no) == "856"; /* empty */) {
            Subfields _856_subfields(record.getSubfields(field_no));
            bool duplicate_link(false);
            if (_856_subfields.hasSubfield('u')) {
                const std::string u_subfield(StringUtil::Trim(_856_subfields.getFirstSubfieldValue('u')));

                if (IsHttpOrHttpsURL(u_subfield)) {
                    if (already_seen_links.find(u_subfield) == already_seen_links.cend())
                        already_seen_links.insert(u_subfield);
                    else
                        duplicate_link = true;
                } else if (IsSuffixOfAnyURL(_856u_urls, u_subfield) )
                    erase_field_indices.emplace_back(field_no);
                else {
                    std::string new_http_replacement_link;
                    if (StringUtil::StartsWith(u_subfield, "urn:"))
                        new_http_replacement_link = "https://nbn-resolving.org/" + u_subfield;
                    else if (StringUtil::StartsWith(u_subfield, "10900/"))
                        new_http_replacement_link = "https://publikationen.uni-tuebingen.de/xmlui/handle/"
                                                    + u_subfield;
                    else
                        new_http_replacement_link = "http://" + u_subfield;
                    if (already_seen_links.find(new_http_replacement_link) == already_seen_links.cend()) {
                        _856_subfields.replace('u', u_subfield, new_http_replacement_link);
                        if (verbose)
                            std::cout << "Replaced \"" << u_subfield << "\" with \"" << new_http_replacement_link
                                      << "\". (PPN: " << record.getControlNumber() << ")\n";
                        already_seen_links.insert(new_http_replacement_link);
                        modified_record = true;
                    } else
                        duplicate_link = true;
                }
            }

            if (not duplicate_link)
                ++field_no;
            else {
                ++duplicate_skip_count;
                if (verbose)
                    std::cout << "Skipping duplicate, control numbers is " << record.getControlNumber() << ".\n";
                record.deleteField(field_no);
                modified_record = true;
            }
        }

        if (not erase_field_indices.empty()) {
            // We need to remove fields starting from the end of the record.
            std::sort(erase_field_indices.begin(), erase_field_indices.end(), std::greater<size_t>());

            for (const size_t field_index : erase_field_indices)
                record.deleteField(field_index);

            modified_record = true;
        }

        if (modified_record)
            ++modified_count;

        writer->write(record);
    }

    std::cerr << "Read " << count << " records.\n";
    std::cerr << "Modified " << modified_count << " record(s).\n";
    std::cerr << "Skipped " << duplicate_skip_count << " duplicate links.\n";
}

int main(int argc, char **argv) {
    ::progname = argv[0];

    if (argc != 3 and argc != 4)
        Usage();

    bool verbose(std::strcmp("-v", argv[1]) == 0 or std::strcmp("--verbose", argv[1]) == 0);
    if (verbose)
        ++argv;
    std::unique_ptr <MarcReader> marc_reader(MarcReader::Factory(argv[1]));
    std::unique_ptr <MarcWriter> marc_writer(MarcWriter::Factory(argv[2]));
    try {
        NormaliseURLs(verbose, marc_reader.get(), marc_writer.get());
    } catch (const std::exception &x) {
        Error("caught exception: " + std::string(x.what()));
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2010-2014 Jeremy Lainé
 * Contact: https://github.com/jlaine/qdjango
 *
 * This file is part of the QDjango Library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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
 * Lesser General Public License for more details.
 */

#include <QDebug>
#include <QStringList>

#include "QDjango.h"
#include "QDjangoModel.h"
#include "QDjangoQuerySet.h"

/** Construct a new QDjangoModel.
 *
 * \param parent
 */
QDjangoModel::QDjangoModel(QObject *parent)
    : QObject(parent)
{
}

/** Returns the primary key for this QDjangoModel.
 */
QVariant QDjangoModel::pk() const
{
    const QDjangoMetaModel metaModel = QDjango::metaModel(metaObject()->className());
    return property(metaModel.primaryKey());
}

/** Sets the primary key for this QDjangoModel.
 *
 * \param pk
 */
void QDjangoModel::setPk(const QVariant &pk)
{
    const QDjangoMetaModel metaModel = QDjango::metaModel(metaObject()->className());
    setProperty(metaModel.primaryKey(), pk);
}

/** Retrieves the QDjangoModel pointed to by the given foreign-key.
 *
 * \param name
 */
QObject *QDjangoModel::foreignKey(const char *name) const
{
    const QDjangoMetaModel metaModel = QDjango::metaModel(metaObject()->className());
    return metaModel.foreignKey(this, name);
}

/** Sets the QDjangoModel pointed to by the given foreign-key.
 *
 * \param name
 * \param value
 *
 * \note The current QDjangoModel will take ownership of the given \c value.
 */
void QDjangoModel::setForeignKey(const char *name, QObject *value)
{
    const QDjangoMetaModel metaModel = QDjango::metaModel(metaObject()->className());
    metaModel.setForeignKey(this, name, value);
}

/** Deletes the QDjangoModel from the database.
 *
 * \return true if deletion succeeded, false otherwise
 */
bool QDjangoModel::remove()
{
    const QDjangoMetaModel metaModel = QDjango::metaModel(metaObject()->className());
    return metaModel.remove(this);
}

/** Saves the QDjangoModel to the database.
 *
 * \return true if saving succeeded, false otherwise
 */
bool QDjangoModel::save()
{
    const QDjangoMetaModel metaModel = QDjango::metaModel(metaObject()->className());
    return metaModel.save(this);
}

/** Returns a string representation of the model instance.
 */
QString QDjangoModel::toString() const
{
    const QDjangoMetaModel metaModel = QDjango::metaModel(metaObject()->className());
    const QByteArray pkName = metaModel.primaryKey();
    return QString::fromLatin1("%1(%2=%3)").arg(QString::fromLatin1(metaObject()->className()), QString::fromLatin1(pkName), property(pkName).toString());
}

<commit_msg>fix docs for setForeignKey (closes: #42)<commit_after>/*
 * Copyright (C) 2010-2014 Jeremy Lainé
 * Contact: https://github.com/jlaine/qdjango
 *
 * This file is part of the QDjango Library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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
 * Lesser General Public License for more details.
 */

#include <QDebug>
#include <QStringList>

#include "QDjango.h"
#include "QDjangoModel.h"
#include "QDjangoQuerySet.h"

/** Construct a new QDjangoModel.
 *
 * \param parent
 */
QDjangoModel::QDjangoModel(QObject *parent)
    : QObject(parent)
{
}

/** Returns the primary key for this QDjangoModel.
 */
QVariant QDjangoModel::pk() const
{
    const QDjangoMetaModel metaModel = QDjango::metaModel(metaObject()->className());
    return property(metaModel.primaryKey());
}

/** Sets the primary key for this QDjangoModel.
 *
 * \param pk
 */
void QDjangoModel::setPk(const QVariant &pk)
{
    const QDjangoMetaModel metaModel = QDjango::metaModel(metaObject()->className());
    setProperty(metaModel.primaryKey(), pk);
}

/** Retrieves the QDjangoModel pointed to by the given foreign-key.
 *
 * \param name
 */
QObject *QDjangoModel::foreignKey(const char *name) const
{
    const QDjangoMetaModel metaModel = QDjango::metaModel(metaObject()->className());
    return metaModel.foreignKey(this, name);
}

/** Sets the QDjangoModel pointed to by the given foreign-key.
 *
 * \param name
 * \param value
 *
 * \note The QDjangoModel will not take ownership of the given \c value.
 */
void QDjangoModel::setForeignKey(const char *name, QObject *value)
{
    const QDjangoMetaModel metaModel = QDjango::metaModel(metaObject()->className());
    metaModel.setForeignKey(this, name, value);
}

/** Deletes the QDjangoModel from the database.
 *
 * \return true if deletion succeeded, false otherwise
 */
bool QDjangoModel::remove()
{
    const QDjangoMetaModel metaModel = QDjango::metaModel(metaObject()->className());
    return metaModel.remove(this);
}

/** Saves the QDjangoModel to the database.
 *
 * \return true if saving succeeded, false otherwise
 */
bool QDjangoModel::save()
{
    const QDjangoMetaModel metaModel = QDjango::metaModel(metaObject()->className());
    return metaModel.save(this);
}

/** Returns a string representation of the model instance.
 */
QString QDjangoModel::toString() const
{
    const QDjangoMetaModel metaModel = QDjango::metaModel(metaObject()->className());
    const QByteArray pkName = metaModel.primaryKey();
    return QString::fromLatin1("%1(%2=%3)").arg(QString::fromLatin1(metaObject()->className()), QString::fromLatin1(pkName), property(pkName).toString());
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Zubax, zubax.com
 * Please refer to the file LICENSE for terms and conditions.
 * Author: Pavel Kirienko <pavel.kirienko@zubax.com>
 */

#pragma once

#include <unordered_map>
#include <ros/ros.h>
#include <std_msgs/Float64MultiArray.h>
#include <std_msgs/Float64.h>
#include <eigen3/Eigen/Eigen>

namespace zubax_posekf
{

class DebugPublisher
{
    static constexpr unsigned QueueSize = 10;

    ros::NodeHandle node_;
    std::unordered_map<std::string, ros::Publisher> pubs_;

    template <typename Message>
    ros::Publisher& getPublisher(const std::string& name)
    {
        auto pub = pubs_.find(name);
        if (pub == pubs_.end())
        {
            (void)pubs_.insert({name, node_.advertise<Message>(name, QueueSize)});
            pub = pubs_.find(name);
            ROS_INFO("Debug publisher: New topic '%s' of type '%s'",
                     name.c_str(), ros::message_traits::DataType<Message>::value());
        }
        ROS_ASSERT(pub != pubs_.end());
        return pub->second;
    }

public:
    DebugPublisher(const std::string& ros_ns = "debug")
        : node_(ros_ns)
    { }

    template <class Message>
    void publishROSMessage(const std::string& name, const Message& msg)
    {
        getPublisher<Message>(name).publish(msg);
    }

    template <typename Derived>
    void publish(const std::string& name, const Eigen::MatrixBase<Derived>& matrix)
    {
        std_msgs::Float64MultiArray msg;

        msg.layout.dim.resize(2);
        msg.layout.dim[0].stride = static_cast<unsigned>(matrix.rows() * matrix.cols());
        msg.layout.dim[0].size   = static_cast<unsigned>(matrix.rows());
        msg.layout.dim[1].stride = static_cast<unsigned>(matrix.cols());
        msg.layout.dim[1].size   = static_cast<unsigned>(matrix.cols());
        msg.data.resize(static_cast<unsigned>(matrix.size()));

        {
            unsigned write_idx = 0;
            for (int row_idx = 0; row_idx < matrix.rows(); row_idx++)
            {
                // We can't access the matrix elements directly via coeff() in a generic way
                const auto row = matrix.row(row_idx);
                for (int col_idx = 0; col_idx < matrix.cols(); col_idx++)
                {
                    msg.data[write_idx++] = static_cast<double>(row[col_idx]);
                }
            }
        }

        publishROSMessage(name, msg);
    }

    void publish(const std::string& name, const double scalar)
    {
        std_msgs::Float64 msg;
        msg.data = scalar;
        publishROSMessage(name, msg);
    }
};

}
<commit_msg>Improved debug publisher<commit_after>/*
 * Copyright (c) 2014 Zubax, zubax.com
 * Please refer to the file LICENSE for terms and conditions.
 * Author: Pavel Kirienko <pavel.kirienko@zubax.com>
 */

#pragma once

#include <unordered_map>
#include <ros/ros.h>
#include <std_msgs/Float64MultiArray.h>
#include <geometry_msgs/Vector3.h>
#include <std_msgs/Float64.h>
#include <eigen3/Eigen/Eigen>

namespace zubax_posekf
{

class DebugPublisher
{
    static constexpr unsigned QueueSize = 10;

    ros::NodeHandle node_;
    std::unordered_map<std::string, ros::Publisher> pubs_;

    template <typename Message>
    ros::Publisher& getPublisher(const std::string& name)
    {
        auto pub = pubs_.find(name);
        if (pub == pubs_.end())
        {
            (void)pubs_.insert({name, node_.advertise<Message>(name, QueueSize)});
            pub = pubs_.find(name);
            ROS_INFO("Debug publisher: New topic '%s' of type '%s'",
                     name.c_str(), ros::message_traits::DataType<Message>::value());
        }
        ROS_ASSERT(pub != pubs_.end());
        return pub->second;
    }

public:
    DebugPublisher(const std::string& ros_ns = "debug")
        : node_(ros_ns)
    { }

    template <class Message>
    void publishROSMessage(const std::string& name, const Message& msg)
    {
        getPublisher<Message>(name).publish(msg);
    }

    template <typename Derived>
    void publish(const std::string& name, const Eigen::MatrixBase<Derived>& matrix)
    {
        std_msgs::Float64MultiArray msg;

        msg.layout.dim.resize(2);
        msg.layout.dim[0].stride = static_cast<unsigned>(matrix.rows() * matrix.cols());
        msg.layout.dim[0].size   = static_cast<unsigned>(matrix.rows());
        msg.layout.dim[1].stride = static_cast<unsigned>(matrix.cols());
        msg.layout.dim[1].size   = static_cast<unsigned>(matrix.cols());
        msg.data.resize(static_cast<unsigned>(matrix.size()));

        {
            unsigned write_idx = 0;
            for (int row_idx = 0; row_idx < matrix.rows(); row_idx++)
            {
                // We can't access the matrix elements directly via coeff() in a generic way
                const auto row = matrix.row(row_idx);
                for (int col_idx = 0; col_idx < matrix.cols(); col_idx++)
                {
                    msg.data[write_idx++] = static_cast<double>(row[col_idx]);
                }
            }
        }

        publishROSMessage(name, msg);
    }

    template <typename Scalar, int Options>
    void publish(const std::string& name, const Eigen::Matrix<Scalar, 3, 1, Options>& vector)
    {
        geometry_msgs::Vector3 msg;
        msg.x = vector[0];
        msg.y = vector[1];
        msg.z = vector[2];
        publishROSMessage(name, msg);
    }

    void publish(const std::string& name, const double scalar)
    {
        std_msgs::Float64 msg;
        msg.data = scalar;
        publishROSMessage(name, msg);
    }
};

}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include "stx/protobuf/msg.h"
#include "docdb/DocumentDB.h"

using namespace stx;

namespace cm {

DocumentDB::DocumentDB(const String& path) {
  mdb::MDBOptions mdb_opts;
  mdb_opts.data_filename = "docdb.db",
  mdb_opts.lock_filename = "docdb.db.lck";
  mdb_opts.duplicate_keys = false;

  db_ = mdb::MDB::open(path, mdb_opts);
}

void DocumentDB::listDocuments(
    const String& db_namespace,
    const String& userid,
    Function<bool (const Document& doc)> fn) const {
  auto namespace_prefix = db_namespace + "~d~";

  Buffer key;
  Buffer value;

  auto txn = db_->startTransaction(true);
  txn->autoAbort();

  auto cursor = txn->getCursor();
  key.append(namespace_prefix);
  if (!cursor->getFirstOrGreater(&key, &value)) {
    return;
  }

  do {
    if (!StringUtil::beginsWith(key.toString(), namespace_prefix)) {
      break;
    }

    auto doc = msg::decode<Document>(value);
    if (isDocumentReadableForUser(doc, userid)) {
      continue;
    }

    if (!fn(doc)) {
      break;
    }
  } while (cursor->getNext(&key, &value));

  cursor->close();
}

void DocumentDB::createDocument(
    const String& db_namespace,
    const Document& document) {
  auto db_key = StringUtil::format("$0~d~$1", db_namespace, document.uuid());
  auto buf = msg::encode(document);

  auto txn = db_->startTransaction(false);
  txn->autoAbort();
  txn->insert(db_key.data(), db_key.size(), buf->data(), buf->size());
  txn->commit();
}

bool DocumentDB::fetchDocument(
    const String& db_namespace,
    const String& userid,
    const SHA1Hash& uuid,
    Document* document) {
  auto db_key = StringUtil::format("$0~d~$1", db_namespace, uuid.toString());

  void* data;
  size_t data_size;
  auto txn = db_->startTransaction(true);
  txn->autoAbort();

  if (txn->get(db_key.data(), db_key.size(), &data, &data_size)) {
    auto doc = msg::decode<Document>(data, data_size);

    if (isDocumentReadableForUser(doc, userid)) {
      *document = doc;
    } else {
      RAISE(kAccessDeniedError, "access denied");
    }

    return true;
  } else {
    return false;
  }
}

void DocumentDB::updateDocument(
      const String& db_namespace,
      const SHA1Hash& uuid,
      Function<void (Document* doc)> fn) {
  auto db_key = StringUtil::format("$0~d~$1", db_namespace, uuid.toString());

  auto txn = db_->startTransaction(false);
  txn->autoAbort();

  void* data;
  size_t data_size;
  if (!txn->get(db_key.data(), db_key.size(), &data, &data_size)) {
    RAISE(kNotFoundError, "document not found");
  }

  auto doc = msg::decode<Document>(data, data_size);
  fn(&doc);

  auto doc_buf = msg::encode<Document>(doc);
  txn->update(db_key.data(), db_key.size(), doc_buf->data(), doc_buf->size());
  txn->commit();
}

void DocumentDB::updateDocumentContent(
    const String& db_namespace,
    const String& userid,
    const SHA1Hash& uuid,
    const String& content) {
  updateDocument(
    db_namespace,
    uuid,
    [&userid, &content] (Document* doc) {
    if (!isDocumentWritableForUser(*doc, userid)) {
      RAISE(kAccessDeniedError, "access denied");
    }

    doc->set_content(content);
  });
}

void DocumentDB::updateDocumentName(
    const String& db_namespace,
    const String& userid,
    const SHA1Hash& uuid,
    const String& name) {
  updateDocument(
    db_namespace,
    uuid,
    [&userid, &name] (Document* doc) {
    if (!isDocumentWritableForUser(*doc, userid)) {
      RAISE(kAccessDeniedError, "access denied");
    }

    doc->set_name(name);
  });
}

void DocumentDB::updateDocumentACLPolicy(
    const String& db_namespace,
    const String& userid,
    const SHA1Hash& uuid,
    DocumentACLPolicy policy) {
  updateDocument(
    db_namespace,
    uuid,
    [&userid, &policy] (Document* doc) {
    if (!isDocumentWritableForUser(*doc, userid)) {
      RAISE(kAccessDeniedError, "access denied");
    }

    doc->set_acl_policy(policy);
  });
}

//void createDocument(
//    const String& db_namespace,
//    const Document& document);
//
//void updateDocument(
//    const String& db_namespace,
//    const Document& document);
//
//bool findDocument(
//    const String& db_namespace,
//    const SHA1Hash& uuid,
//    Document* document);

} // namespace cm

<commit_msg>fix...<commit_after>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include "stx/protobuf/msg.h"
#include "docdb/DocumentDB.h"

using namespace stx;

namespace cm {

DocumentDB::DocumentDB(const String& path) {
  mdb::MDBOptions mdb_opts;
  mdb_opts.data_filename = "docdb.db",
  mdb_opts.lock_filename = "docdb.db.lck";
  mdb_opts.duplicate_keys = false;

  db_ = mdb::MDB::open(path, mdb_opts);
}

void DocumentDB::listDocuments(
    const String& db_namespace,
    const String& userid,
    Function<bool (const Document& doc)> fn) const {
  auto namespace_prefix = db_namespace + "~d~";

  Buffer key;
  Buffer value;

  auto txn = db_->startTransaction(true);
  txn->autoAbort();

  auto cursor = txn->getCursor();
  key.append(namespace_prefix);
  if (!cursor->getFirstOrGreater(&key, &value)) {
    return;
  }

  do {
    if (!StringUtil::beginsWith(key.toString(), namespace_prefix)) {
      break;
    }

    auto doc = msg::decode<Document>(value);
    if (!isDocumentReadableForUser(doc, userid)) {
      continue;
    }

    if (!fn(doc)) {
      break;
    }
  } while (cursor->getNext(&key, &value));

  cursor->close();
}

void DocumentDB::createDocument(
    const String& db_namespace,
    const Document& document) {
  auto db_key = StringUtil::format("$0~d~$1", db_namespace, document.uuid());
  auto buf = msg::encode(document);

  auto txn = db_->startTransaction(false);
  txn->autoAbort();
  txn->insert(db_key.data(), db_key.size(), buf->data(), buf->size());
  txn->commit();
}

bool DocumentDB::fetchDocument(
    const String& db_namespace,
    const String& userid,
    const SHA1Hash& uuid,
    Document* document) {
  auto db_key = StringUtil::format("$0~d~$1", db_namespace, uuid.toString());

  void* data;
  size_t data_size;
  auto txn = db_->startTransaction(true);
  txn->autoAbort();

  if (txn->get(db_key.data(), db_key.size(), &data, &data_size)) {
    auto doc = msg::decode<Document>(data, data_size);

    if (isDocumentReadableForUser(doc, userid)) {
      *document = doc;
    } else {
      RAISE(kAccessDeniedError, "access denied");
    }

    return true;
  } else {
    return false;
  }
}

void DocumentDB::updateDocument(
      const String& db_namespace,
      const SHA1Hash& uuid,
      Function<void (Document* doc)> fn) {
  auto db_key = StringUtil::format("$0~d~$1", db_namespace, uuid.toString());

  auto txn = db_->startTransaction(false);
  txn->autoAbort();

  void* data;
  size_t data_size;
  if (!txn->get(db_key.data(), db_key.size(), &data, &data_size)) {
    RAISE(kNotFoundError, "document not found");
  }

  auto doc = msg::decode<Document>(data, data_size);
  fn(&doc);

  auto doc_buf = msg::encode<Document>(doc);
  txn->update(db_key.data(), db_key.size(), doc_buf->data(), doc_buf->size());
  txn->commit();
}

void DocumentDB::updateDocumentContent(
    const String& db_namespace,
    const String& userid,
    const SHA1Hash& uuid,
    const String& content) {
  updateDocument(
    db_namespace,
    uuid,
    [&userid, &content] (Document* doc) {
    if (!isDocumentWritableForUser(*doc, userid)) {
      RAISE(kAccessDeniedError, "access denied");
    }

    doc->set_content(content);
  });
}

void DocumentDB::updateDocumentName(
    const String& db_namespace,
    const String& userid,
    const SHA1Hash& uuid,
    const String& name) {
  updateDocument(
    db_namespace,
    uuid,
    [&userid, &name] (Document* doc) {
    if (!isDocumentWritableForUser(*doc, userid)) {
      RAISE(kAccessDeniedError, "access denied");
    }

    doc->set_name(name);
  });
}

void DocumentDB::updateDocumentACLPolicy(
    const String& db_namespace,
    const String& userid,
    const SHA1Hash& uuid,
    DocumentACLPolicy policy) {
  updateDocument(
    db_namespace,
    uuid,
    [&userid, &policy] (Document* doc) {
    if (!isDocumentWritableForUser(*doc, userid)) {
      RAISE(kAccessDeniedError, "access denied");
    }

    doc->set_acl_policy(policy);
  });
}

//void createDocument(
//    const String& db_namespace,
//    const Document& document);
//
//void updateDocument(
//    const String& db_namespace,
//    const Document& document);
//
//bool findDocument(
//    const String& db_namespace,
//    const SHA1Hash& uuid,
//    Document* document);

} // namespace cm

<|endoftext|>


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

#include "webkit/tools/test_shell/drag_delegate.h"

#include <atltypes.h>

#include "webkit/api/public/WebPoint.h"
#include "webkit/glue/webview.h"

using WebKit::WebPoint;

namespace {

void GetCursorPositions(HWND hwnd, CPoint* client, CPoint* screen) {
  // GetCursorPos will fail if the input desktop isn't the current desktop.
  // See http://b/1173534. (0,0) is wrong, but better than uninitialized.
  if (!GetCursorPos(screen))
    screen->SetPoint(0, 0);

  *client = *screen;
  ScreenToClient(hwnd, client);
}

}  // anonymous namespace

void TestDragDelegate::OnDragSourceCancel() {
  OnDragSourceDrop();
}

void TestDragDelegate::OnDragSourceDrop() {
  CPoint client;
  CPoint screen;
  GetCursorPositions(source_hwnd_, &client, &screen);
  webview_->DragSourceEndedAt(WebPoint(client.x, client.y),
                              WebPoint(screen.x, screen.y));
}

void TestDragDelegate::OnDragSourceMove() {
  CPoint client;
  CPoint screen;
  GetCursorPositions(source_hwnd_, &client, &screen);
  webview_->DragSourceMovedTo(WebPoint(client.x, client.y),
                              WebPoint(screen.x, screen.y));
}
<commit_msg>Convert usage of CPoint to gfx::Point.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/tools/test_shell/drag_delegate.h"

#include "webkit/api/public/WebPoint.h"
#include "webkit/glue/webview.h"

using WebKit::WebPoint;

namespace {

void GetCursorPositions(HWND hwnd, gfx::Point* client, gfx::Point* screen) {
  // GetCursorPos will fail if the input desktop isn't the current desktop.
  // See http://b/1173534. (0,0) is wrong, but better than uninitialized.
  POINT pos;
  if (!GetCursorPos(&pos)) {
    pos.x = 0;
    pos.y = 0;
  }

  *screen = gfx::Point(pos);
  ScreenToClient(hwnd, &pos);
  *client = gfx::Point(pos);
}

}  // anonymous namespace

void TestDragDelegate::OnDragSourceCancel() {
  OnDragSourceDrop();
}

void TestDragDelegate::OnDragSourceDrop() {
  gfx::Point client;
  gfx::Point screen;
  GetCursorPositions(source_hwnd_, &client, &screen);
  webview_->DragSourceEndedAt(client, screen);
}

void TestDragDelegate::OnDragSourceMove() {
  gfx::Point client;
  gfx::Point screen;
  GetCursorPositions(source_hwnd_, &client, &screen);
  webview_->DragSourceMovedTo(client, screen);
}
<|endoftext|>


<commit_before>// Copyright 2010-2013 Google
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string>
#include "base/integral_types.h"
#include "base/logging.h"
#include "base/hash.h"
#include "base/map_util.h"
#include "flatzinc2/model.h"
#include "flatzinc2/sat_constraint.h"
#include "flatzinc2/solver.h"
#include "constraint_solver/constraint_solver.h"
#include "util/string_array.h"

DECLARE_bool(logging);
DECLARE_bool(verbose_logging);
DEFINE_bool(use_sat, true, "Use a sat solver for propagating on booleans.");

namespace operations_research {
IntExpr* FzSolver::GetExpression(const FzArgument& arg) {
  switch (arg.type) {
    case FzArgument::INT_VALUE: { return solver_.MakeIntConst(arg.Value()); }
    case FzArgument::INT_VAR_REF: { return Extract(arg.variables[0]); }
    default: {
      LOG(FATAL) << "Cannot extract " << arg.DebugString() << " as a variable";
      return nullptr;
    }
  }
}

std::vector<IntVar*> FzSolver::GetVariableArray(const FzArgument& arg) {
  std::vector<IntVar*> result;
  if (arg.type == FzArgument::INT_VAR_REF_ARRAY) {
    result.resize(arg.variables.size());
    for (int i = 0; i < arg.variables.size(); ++i) {
      result[i] = Extract(arg.variables[i])->Var();
    }
  } else if (arg.type == FzArgument::INT_LIST) {
    result.resize(arg.values.size());
    for (int i = 0; i < arg.values.size(); ++i) {
      result[i] = solver_.MakeIntConst(arg.values[i]);
    }
  } else {
    LOG(FATAL) << "Cannot extract " << arg.DebugString()
               << " as a variable array";
  }
  return result;
}

IntExpr* FzSolver::Extract(FzIntegerVariable* var) {
  IntExpr* result = FindPtrOrNull(extrated_map_, var);
  if (result != nullptr) {
    return result;
  }
  if (var->domain.values.size() == 1) {
    result = solver_.MakeIntConst(var->domain.values.back());
  } else if (var->domain.is_interval && var->domain.values.empty()) {
    result = solver_.MakeIntVar(kint32min, kint32max, var->name);
  } else if (var->domain.is_interval) {
    result = solver_.MakeIntVar(var->domain.values[0], var->domain.values[1],
                                var->name);
  } else {
    result = solver_.MakeIntVar(var->domain.values, var->name);
  }
  FZVLOG << "Extract " << var->DebugString() << " into "
         << result->DebugString() << FZENDL;
  extrated_map_[var] = result;
  return result;
}

void FzSolver::SetExtracted(FzIntegerVariable* var, IntExpr* expr) {
  CHECK(!ContainsKey(extrated_map_, var));
  extrated_map_[var] = expr;
}

// The format is fixed in the flatzinc specification.
std::string FzSolver::SolutionString(const FzOnSolutionOutput& output) {
  if (output.variable != nullptr) {
    return StringPrintf("%s = %" GG_LL_FORMAT "d;", output.name.c_str(),
                        Extract(output.variable)->Var()->Value());
  } else {
    const int bound_size = output.bounds.size();
    std::string result =
        StringPrintf("%s = array%dd(", output.name.c_str(), bound_size);
    for (int i = 0; i < bound_size; ++i) {
      result.append(
          StringPrintf("%" GG_LL_FORMAT "d..%" GG_LL_FORMAT "d, ",
                       output.bounds[i].min_value, output.bounds[i].max_value));
    }
    result.append("[");
    for (int i = 0; i < output.flat_variables.size(); ++i) {
      result.append(
          StringPrintf("%" GG_LL_FORMAT "d",
                       Extract(output.flat_variables[i])->Var()->Value()));
      if (i != output.flat_variables.size() - 1) {
        result.append(", ");
      }
    }
    result.append("]);");
    return result;
  }
  return "";
}

namespace {
struct ConstraintWithIo {
  FzConstraint* ct;
  int index;
  hash_set<FzIntegerVariable*> required;

  ConstraintWithIo(FzConstraint* cte, int i,
                   const hash_set<FzIntegerVariable*>& defined)
      : ct(cte), index(i) {
    // Collect required variables.
    for (const FzArgument& arg : ct->arguments) {
      for (FzIntegerVariable* const var : arg.variables) {
        if (ContainsKey(defined, var)) {
          required.insert(var);
        }
      }
    }
    // Remove the target_variable as it always appears in the constraint.
    if (ct->target_variable != nullptr) {
      required.erase(ct->target_variable);
    }
  }
};

int ComputeWeight(const ConstraintWithIo& ctio) {
  if (ctio.required.empty()) return 0;
  if (ctio.ct->target_variable != nullptr) return 1;
  return 2;
}

// Comparator to sort constraints based on numbers of required
// elements and index. Reverse sorting to put elements to remove at the end.
struct ConstraintWithIoComparator {
  bool operator()(ConstraintWithIo* a, ConstraintWithIo* b) const {
    const int a_weight = ComputeWeight(*a);
    const int b_weight = ComputeWeight(*b);
    return a_weight > b_weight ||
           (a_weight == b_weight && a_weight != 1 && a->index > b->index) ||
           (a_weight == b_weight && a_weight == 1 &&
            ContainsKey(a->required, b->ct->target_variable));
  }
};
}  // namespace

bool FzSolver::Extract() {
  // Create the sat solver.
  if (FLAGS_use_sat) {
    FZLOG << "  - Use sat" << FZENDL;
    sat_ = MakeSatPropagator(&solver_);
    solver_.AddConstraint(reinterpret_cast<Constraint*>(sat_));
  } else {
    sat_ = nullptr;
  }
  // Build statistics.
  statistics_.BuildStatistics();
  // Extract variables.
  hash_set<FzIntegerVariable*> defined_variables;
  for (FzIntegerVariable* const var : model_.variables()) {
    if (var->defining_constraint == nullptr && var->active) {
      Extract(var);
    } else {
      FZVLOG << "Skip " << var->DebugString() << FZENDL;
      if (var->defining_constraint != nullptr) {
        FZVLOG << "  - defined by " << var->defining_constraint->DebugString()
               << FZENDL;
      }
      defined_variables.insert(var);
    }
  }
  // Parse model to store info.
  for (FzConstraint* const ct : model_.constraints()) {
    if (ct->type == "all_different_int") {
      StoreAllDifferent(ct->Arg(0).variables);
    }
  }
  // Sort constraints such that defined variables are created before the
  // extraction of the constraints that use them.
  int index = 0;
  std::vector<ConstraintWithIo*> to_sort;
  std::vector<FzConstraint*> sorted;
  hash_map<const FzIntegerVariable*, std::vector<ConstraintWithIo*>>
      dependencies;
  for (FzConstraint* ct : model_.constraints()) {
    if (ct != nullptr && ct->active) {
      ConstraintWithIo* const ctio =
          new ConstraintWithIo(ct, index++, defined_variables);
      to_sort.push_back(ctio);
      for (FzIntegerVariable* const var : ctio->required) {
        dependencies[var].push_back(ctio);
      }
    }
  }
  // Sort a first time.
  std::sort(to_sort.begin(), to_sort.end(), ConstraintWithIoComparator());
  // Topological sort.
  while (!to_sort.empty()) {
    if (!to_sort.back()->required.empty()) {
      // Sort again.
      std::sort(to_sort.begin(), to_sort.end(), ConstraintWithIoComparator());
    }
    ConstraintWithIo* const ctio = to_sort.back();
    to_sort.pop_back();
    FZVLOG << "Pop " << ctio->ct->DebugString() << FZENDL;
    CHECK(ctio->required.empty());
    // TODO(user): Implement recovery mode.
    sorted.push_back(ctio->ct);
    FzIntegerVariable* const var = ctio->ct->target_variable;
    if (var != nullptr && ContainsKey(dependencies, var)) {
      for (ConstraintWithIo* const to_clean : dependencies[var]) {
        to_clean->required.erase(var);
      }
    }
    delete ctio;
  }
  for (FzConstraint* const ct : sorted) {
    ExtractConstraint(ct);
  }
  // Add domain constraints to created extressions.
  for (FzIntegerVariable* const var : model_.variables()) {
    if (var->defining_constraint != nullptr && var->active) {
      const FzDomain& domain = var->domain;
      IntExpr* const expr = Extract(var);
      if (expr->IsVar() && domain.is_interval && !domain.values.empty() &&
          (expr->Min() < domain.values[0] || expr->Max() > domain.values[1])) {
        FZVLOG << "Reduce variable domain of " << expr->DebugString()
               << " from " << domain.DebugString() << FZENDL;
        expr->Var()->SetRange(domain.values[0], domain.values[1]);
      } else if (expr->IsVar() && !domain.is_interval) {
        FZVLOG << "Reduce variable domain of " << expr->DebugString()
               << " from " << domain.DebugString() << FZENDL;
        expr->Var()->SetValues(domain.values);
      } else if (domain.is_interval && !domain.values.empty() &&
                 (expr->Min() < domain.values[0] ||
                  expr->Max() > domain.values[1])) {
        FZVLOG << "Add domain constraint " << domain.DebugString() << " onto "
               << expr->DebugString() << FZENDL;
        solver_.AddConstraint(solver_.MakeBetweenCt(
            expr->Var(), domain.values[0], domain.values[1]));
      } else if (!domain.is_interval) {
        FZVLOG << "Add domain constraint " << domain.DebugString() << " onto "
               << expr->DebugString() << FZENDL;
        solver_.AddConstraint(solver_.MakeMemberCt(expr->Var(), domain.values));
      }
    }
  }

  return true;
}

// ----- Alldiff info support -----

void FzSolver::StoreAllDifferent(const std::vector<FzIntegerVariable*>& diffs) {
  std::vector<FzIntegerVariable*> local(diffs);
  std::sort(local.begin(), local.end());
  FZVLOG << "Store AllDifferent info for [" << JoinDebugStringPtr(diffs, ", ")
         << "]" << FZENDL;
  alldiffs_[local.front()].push_back(local);
}

namespace {
template <class T>
bool EqualVector(const std::vector<T>& v1, const std::vector<T>& v2) {
  if (v1.size() != v2.size()) return false;
  for (int i = 0; i < v1.size(); ++i) {
    if (v1[i] != v2[i]) return false;
  }
  return true;
}
}  // namespace

bool FzSolver::IsAllDifferent(
    const std::vector<FzIntegerVariable*>& diffs) const {
  std::vector<FzIntegerVariable*> local(diffs);
  std::sort(local.begin(), local.end());
  const FzIntegerVariable* const start = local.front();
  if (!ContainsKey(alldiffs_, start)) return false;
  const std::vector<std::vector<FzIntegerVariable*>>& stored =
      FindOrDie(alldiffs_, start);
  for (const std::vector<FzIntegerVariable*>& one_diff : stored) {
    if (EqualVector(local, one_diff)) {
      return true;
    }
  }
  return false;
}
}  // namespace operations_research
<commit_msg>work on constraint sorting<commit_after>// Copyright 2010-2013 Google
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string>
#include "base/integral_types.h"
#include "base/logging.h"
#include "base/hash.h"
#include "base/map_util.h"
#include "flatzinc2/model.h"
#include "flatzinc2/sat_constraint.h"
#include "flatzinc2/solver.h"
#include "constraint_solver/constraint_solver.h"
#include "util/string_array.h"

DECLARE_bool(logging);
DECLARE_bool(verbose_logging);
DEFINE_bool(use_sat, true, "Use a sat solver for propagating on booleans.");

namespace operations_research {
IntExpr* FzSolver::GetExpression(const FzArgument& arg) {
  switch (arg.type) {
    case FzArgument::INT_VALUE: { return solver_.MakeIntConst(arg.Value()); }
    case FzArgument::INT_VAR_REF: { return Extract(arg.variables[0]); }
    default: {
      LOG(FATAL) << "Cannot extract " << arg.DebugString() << " as a variable";
      return nullptr;
    }
  }
}

std::vector<IntVar*> FzSolver::GetVariableArray(const FzArgument& arg) {
  std::vector<IntVar*> result;
  if (arg.type == FzArgument::INT_VAR_REF_ARRAY) {
    result.resize(arg.variables.size());
    for (int i = 0; i < arg.variables.size(); ++i) {
      result[i] = Extract(arg.variables[i])->Var();
    }
  } else if (arg.type == FzArgument::INT_LIST) {
    result.resize(arg.values.size());
    for (int i = 0; i < arg.values.size(); ++i) {
      result[i] = solver_.MakeIntConst(arg.values[i]);
    }
  } else {
    LOG(FATAL) << "Cannot extract " << arg.DebugString()
               << " as a variable array";
  }
  return result;
}

IntExpr* FzSolver::Extract(FzIntegerVariable* var) {
  IntExpr* result = FindPtrOrNull(extrated_map_, var);
  if (result != nullptr) {
    return result;
  }
  if (var->domain.values.size() == 1) {
    result = solver_.MakeIntConst(var->domain.values.back());
  } else if (var->domain.is_interval && var->domain.values.empty()) {
    result = solver_.MakeIntVar(kint32min, kint32max, var->name);
  } else if (var->domain.is_interval) {
    result = solver_.MakeIntVar(var->domain.values[0], var->domain.values[1],
                                var->name);
  } else {
    result = solver_.MakeIntVar(var->domain.values, var->name);
  }
  FZVLOG << "Extract " << var->DebugString() << " into "
         << result->DebugString() << FZENDL;
  extrated_map_[var] = result;
  return result;
}

void FzSolver::SetExtracted(FzIntegerVariable* var, IntExpr* expr) {
  CHECK(!ContainsKey(extrated_map_, var));
  extrated_map_[var] = expr;
}

// The format is fixed in the flatzinc specification.
std::string FzSolver::SolutionString(const FzOnSolutionOutput& output) {
  if (output.variable != nullptr) {
    return StringPrintf("%s = %" GG_LL_FORMAT "d;", output.name.c_str(),
                        Extract(output.variable)->Var()->Value());
  } else {
    const int bound_size = output.bounds.size();
    std::string result =
        StringPrintf("%s = array%dd(", output.name.c_str(), bound_size);
    for (int i = 0; i < bound_size; ++i) {
      result.append(
          StringPrintf("%" GG_LL_FORMAT "d..%" GG_LL_FORMAT "d, ",
                       output.bounds[i].min_value, output.bounds[i].max_value));
    }
    result.append("[");
    for (int i = 0; i < output.flat_variables.size(); ++i) {
      result.append(
          StringPrintf("%" GG_LL_FORMAT "d",
                       Extract(output.flat_variables[i])->Var()->Value()));
      if (i != output.flat_variables.size() - 1) {
        result.append(", ");
      }
    }
    result.append("]);");
    return result;
  }
  return "";
}

namespace {
struct ConstraintWithIo {
  FzConstraint* ct;
  int index;
  hash_set<FzIntegerVariable*> required;

  ConstraintWithIo(FzConstraint* cte, int i,
                   const hash_set<FzIntegerVariable*>& defined)
      : ct(cte), index(i) {
    // Collect required variables.
    for (const FzArgument& arg : ct->arguments) {
      for (FzIntegerVariable* const var : arg.variables) {
        if (var != cte->target_variable && ContainsKey(defined, var)) {
          required.insert(var);
        }
      }
    }
  }
};

int ComputeWeight(const ConstraintWithIo& ctio) {
  if (ctio.required.empty()) return 0;
  if (ctio.ct->target_variable != nullptr) return 1;
  return 2;
}

// Comparator to sort constraints based on numbers of required
// elements and index. Reverse sorting to put elements to remove at the end.
struct ConstraintWithIoComparator {
  bool operator()(ConstraintWithIo* a, ConstraintWithIo* b) const {
    const int a_weight = ComputeWeight(*a);
    const int b_weight = ComputeWeight(*b);
    return a_weight > b_weight ||
           (a_weight == b_weight && a_weight != 1 && a->index > b->index) ||
           (a_weight == b_weight && a_weight == 1 &&
            ContainsKey(a->required, b->ct->target_variable));
  }
};
}  // namespace

bool FzSolver::Extract() {
  // Create the sat solver.
  if (FLAGS_use_sat) {
    FZLOG << "  - Use sat" << FZENDL;
    sat_ = MakeSatPropagator(&solver_);
    solver_.AddConstraint(reinterpret_cast<Constraint*>(sat_));
  } else {
    sat_ = nullptr;
  }
  // Build statistics.
  statistics_.BuildStatistics();
  // Extract variables.
  hash_set<FzIntegerVariable*> defined_variables;
  for (FzIntegerVariable* const var : model_.variables()) {
    if (var->defining_constraint == nullptr && var->active) {
      Extract(var);
    } else {
      FZVLOG << "Skip " << var->DebugString() << FZENDL;
      if (var->defining_constraint != nullptr) {
        FZVLOG << "  - defined by " << var->defining_constraint->DebugString()
               << FZENDL;
      }
      defined_variables.insert(var);
    }
  }
  // Parse model to store info.
  for (FzConstraint* const ct : model_.constraints()) {
    if (ct->type == "all_different_int") {
      StoreAllDifferent(ct->Arg(0).variables);
    }
  }
  // Sort constraints such that defined variables are created before the
  // extraction of the constraints that use them.
  int index = 0;
  std::vector<ConstraintWithIo*> to_sort;
  std::vector<FzConstraint*> sorted;
  hash_map<const FzIntegerVariable*, std::vector<ConstraintWithIo*>>
      dependencies;
  for (FzConstraint* ct : model_.constraints()) {
    if (ct != nullptr && ct->active) {
      ConstraintWithIo* const ctio =
          new ConstraintWithIo(ct, index++, defined_variables);
      to_sort.push_back(ctio);
      for (FzIntegerVariable* const var : ctio->required) {
        dependencies[var].push_back(ctio);
      }
    }
  }
  // Sort a first time.
  std::sort(to_sort.begin(), to_sort.end(), ConstraintWithIoComparator());
  // Topological sort.
  while (!to_sort.empty()) {
    if (!to_sort.back()->required.empty()) {
      // Sort again.
      std::sort(to_sort.begin(), to_sort.end(), ConstraintWithIoComparator());
    }
    ConstraintWithIo* const ctio = to_sort.back();
    to_sort.pop_back();
    FZVLOG << "Pop " << ctio->ct->DebugString() << FZENDL;
    CHECK(ctio->required.empty());
    // TODO(user): Implement recovery mode.
    sorted.push_back(ctio->ct);
    FzIntegerVariable* const var = ctio->ct->target_variable;
    if (var != nullptr && ContainsKey(dependencies, var)) {
      for (ConstraintWithIo* const to_clean : dependencies[var]) {
        to_clean->required.erase(var);
      }
    }
    delete ctio;
  }
  for (FzConstraint* const ct : sorted) {
    ExtractConstraint(ct);
  }
  // Add domain constraints to created extressions.
  for (FzIntegerVariable* const var : model_.variables()) {
    if (var->defining_constraint != nullptr && var->active) {
      const FzDomain& domain = var->domain;
      IntExpr* const expr = Extract(var);
      if (expr->IsVar() && domain.is_interval && !domain.values.empty() &&
          (expr->Min() < domain.values[0] || expr->Max() > domain.values[1])) {
        FZVLOG << "Reduce variable domain of " << expr->DebugString()
               << " from " << domain.DebugString() << FZENDL;
        expr->Var()->SetRange(domain.values[0], domain.values[1]);
      } else if (expr->IsVar() && !domain.is_interval) {
        FZVLOG << "Reduce variable domain of " << expr->DebugString()
               << " from " << domain.DebugString() << FZENDL;
        expr->Var()->SetValues(domain.values);
      } else if (domain.is_interval && !domain.values.empty() &&
                 (expr->Min() < domain.values[0] ||
                  expr->Max() > domain.values[1])) {
        FZVLOG << "Add domain constraint " << domain.DebugString() << " onto "
               << expr->DebugString() << FZENDL;
        solver_.AddConstraint(solver_.MakeBetweenCt(
            expr->Var(), domain.values[0], domain.values[1]));
      } else if (!domain.is_interval) {
        FZVLOG << "Add domain constraint " << domain.DebugString() << " onto "
               << expr->DebugString() << FZENDL;
        solver_.AddConstraint(solver_.MakeMemberCt(expr->Var(), domain.values));
      }
    }
  }

  return true;
}

// ----- Alldiff info support -----

void FzSolver::StoreAllDifferent(const std::vector<FzIntegerVariable*>& diffs) {
  std::vector<FzIntegerVariable*> local(diffs);
  std::sort(local.begin(), local.end());
  FZVLOG << "Store AllDifferent info for [" << JoinDebugStringPtr(diffs, ", ")
         << "]" << FZENDL;
  alldiffs_[local.front()].push_back(local);
}

namespace {
template <class T>
bool EqualVector(const std::vector<T>& v1, const std::vector<T>& v2) {
  if (v1.size() != v2.size()) return false;
  for (int i = 0; i < v1.size(); ++i) {
    if (v1[i] != v2[i]) return false;
  }
  return true;
}
}  // namespace

bool FzSolver::IsAllDifferent(
    const std::vector<FzIntegerVariable*>& diffs) const {
  std::vector<FzIntegerVariable*> local(diffs);
  std::sort(local.begin(), local.end());
  const FzIntegerVariable* const start = local.front();
  if (!ContainsKey(alldiffs_, start)) return false;
  const std::vector<std::vector<FzIntegerVariable*>>& stored =
      FindOrDie(alldiffs_, start);
  for (const std::vector<FzIntegerVariable*>& one_diff : stored) {
    if (EqualVector(local, one_diff)) {
      return true;
    }
  }
  return false;
}
}  // namespace operations_research
<|endoftext|>


<commit_before>/********************************************************************* *\
 * INTEL CORPORATION PROPRIETARY INFORMATION
 * This software is supplied under the terms of a license agreement or
 * nondisclosure agreement with Intel Corporation and may not be copied
 * or disclosed except in accordance with the terms of that agreement.
 * Copyright (C) 2014 Intel Corporation. All Rights Reserved.
 ********************************************************************* */

/*
 mm -C ~/Projects/ospray/bin/ && ~/Projects/ospray/bin/streamLineView ~/models/NASA/B-field-sun/ext/*pnt ~/models/NASA/B-field-sun/original/temp\=6400k.sv   --renderer obj --1k -vp 0.897989 0.588022 -0.800192 -vi 0.0106688 -0.212129 -0.029311 -vu 0 1 0
*/

#undef NDEBUG
// viewer widget
#include "../../apps/util/glut3D/glut3D.h"
// ospray, for rendering
#include "ospray/ospray.h"
// embree
#include "common/sys/filename.h"

namespace ospray {
  using std::cout;
  using std::endl;

  const char *rendererType = "raycast_eyelight";
  bool doShadows = 1;

  OSPModel model = NULL;

  void error(const std::string &err)
  {
    cout << "ospray::ospDVR fatal error : " << err << endl;
    cout << endl;
    cout << "Proper usage: " << endl;
    cout << "  ./streamLineView <file1.pnt> <file2.pnt> ....<fileN.sv>" << std::endl;
    cout << "or" << endl;
    cout << "  ./streamLineView <listOfPntFiles.pntlist> ...." << std::endl;
    cout << endl;
    exit(1);
  }

  using ospray::glut3D::Glut3DWidget;

  struct Triangles {
    std::vector<vec3fa> vertex;
    std::vector<vec3fa> color; // vertex color, from sv's 'v' value
    std::vector<vec3i>  index;

    struct SVVertex {
      float v;
      vec3f pos; //float x,y,z;
    };

    struct SVTriangle {
      SVVertex vertex[3];
    };

    vec3f lerpf(float x, float x0,float x1,vec3f y0, vec3f y1)
    {
      float f = (x-x0)/(x1-x0);
      return f*y1+(1-f)*y0;
    }
    vec3f colorOf(const float f)
    {
      if (f < .5f)
        return vec3f(lerpf(f, 0.f,.5f,vec3f(0),vec3f(0,1,0)));
      else
        return vec3f(lerpf(f, .5f,1.f,vec3f(0,1,0),vec3f(1,0,0)));
    }
    void parseSV(const embree::FileName &fn)
    {
      FILE *file = fopen(fn.str().c_str(),"rb");
      if (!file) return;
      SVTriangle triangle;
      while (fread(&triangle,sizeof(triangle),1,file)) {
        index.push_back(vec3i(0,1,2)+vec3i(vertex.size()));
        vertex.push_back(vec3fa(triangle.vertex[0].pos));
        vertex.push_back(vec3fa(triangle.vertex[1].pos));
        vertex.push_back(vec3fa(triangle.vertex[2].pos));
        color.push_back(colorOf(triangle.vertex[0].v));
        color.push_back(colorOf(triangle.vertex[1].v));
        color.push_back(colorOf(triangle.vertex[2].v));
      }
      fclose(file);
    }
  };

  struct StreamLines {
    std::vector<vec3fa> vertex;
    std::vector<int>    index;
    float radius;

    StreamLines() : radius(0.001f) {};

    void parsePNT(const embree::FileName &fn)
    {
      FILE *file = fopen(fn.c_str(),"r");
      if (!file) {
        cout << "WARNING: could not open file " << fn << endl;
        return;
      }
      vec3fa pnt;
      static size_t totalSegments = 0;
      size_t segments = 0;
      // cout << "parsing file " << fn << ":" << std::flush;
      int rc = fscanf(file,"%f %f %f\n",&pnt.x,&pnt.y,&pnt.z);
      vertex.push_back(pnt);
      Assert(rc == 3);
      while ((rc = fscanf(file,"%f %f %f\n",&pnt.x,&pnt.y,&pnt.z)) == 3) {
        index.push_back(vertex.size()-1);
        vertex.push_back(pnt);
        segments++;
      }
      totalSegments += segments;
      // cout << " " << segments << " segments (" << totalSegments << " total)" << endl;
      fclose(file);
    }
    void parsePNTlist(const embree::FileName &fn)
    {
      FILE *file = fopen(fn.c_str(),"r");
      Assert(file);
      for (char line[10000]; fgets(line,10000,file) && !feof(file); ) {
        char *eol = strstr(line,"\n"); if (eol) *eol = 0;
        parsePNT(line);
      }
      fclose(file);
    }

    void parse(const embree::FileName &fn)
    {
      if (fn.ext() == "pnt")
        parsePNT(fn);
      else if (fn.ext() == "pntlist") {
        FILE *file = fopen(fn.c_str(),"r");
        Assert(file);
        for (char line[10000]; fgets(line,10000,file) && !feof(file); ) {
          char *eol = strstr(line,"\n"); if (eol) *eol = 0;
          parsePNT(line);
        }
        fclose(file);
      } else
        throw std::runtime_error("unknown input file format "+fn.str());
    }
    box3f getBounds() const
    {
      box3f bounds = embree::empty;
      for (int i=0;i<vertex.size();i++)
        bounds.extend(vertex[i]);
      return bounds;
    }
  };

  struct StreamLineViewer : public Glut3DWidget {
    /*! construct volume from file name and dimensions \see volview_notes_on_volume_interface */
    StreamLineViewer(StreamLines *sl, Triangles *tris)
      : Glut3DWidget(Glut3DWidget::FRAMEBUFFER_NONE),
        fb(NULL), renderer(NULL),
        sl(sl), tris(tris)
    {
      camera = ospNewCamera("perspective");
      Assert2(camera,"could not create camera");
      ospSet3f(camera,"pos",-1,1,-1);
      ospSet3f(camera,"dir",+1,-1,+1);
      ospCommit(camera);
      ospCommit(camera);

      renderer = ospNewRenderer(rendererType);

      OSPMaterial mat = ospNewMaterial(renderer,"default");
      if (mat) {
        ospSet3f(mat,"kd",.7,.7,.7); // OBJ renderer, default ...
        ospCommit(mat);
      }

      if (std::string(rendererType) == "obj") {
        OSPLight topLight = ospNewLight(renderer,"DirectionalLight");
        if (topLight) {
          ospSet3f(topLight,"direction",-1,-2,1);
          ospSet3f(topLight,"color",1,1,1);
          ospCommit(topLight);
          OSPData lights = ospNewData(1,OSP_OBJECT,&topLight);
          ospCommit(lights);
          ospSetData(renderer,"directionalLights",lights);
        }
      }

      ospCommit(renderer);

      model = ospNewModel();
      {
        OSPGeometry geom = ospNewGeometry("streamlines");
        Assert(geom);
        OSPData vertex = ospNewData(sl->vertex.size(),OSP_vec3fa,&sl->vertex[0]);
        OSPData index  = ospNewData(sl->index.size(),OSP_uint32,&sl->index[0]);
        ospSetParam(geom,"vertex",vertex);
        ospSetParam(geom,"index",index);
        ospSet1f(geom,"radius",sl->radius);
        if (mat)
          ospSetMaterial(geom,mat);
        ospCommit(geom);
        ospAddGeometry(model,geom);
      }

      if (tris && !tris->index.empty()) {
        OSPGeometry geom = ospNewTriangleMesh();
        Assert(geom);
        OSPData vertex = ospNewData(tris->vertex.size(),OSP_vec3fa,&tris->vertex[0]);
        OSPData index  = ospNewData(tris->index.size(),OSP_vec3i,&tris->index[0]);
        OSPData color  = ospNewData(tris->color.size(),OSP_vec3fa,&tris->color[0]);
        ospSetParam(geom,"vertex",vertex);
        ospSetParam(geom,"index",index);
        ospSetParam(geom,"vertex.color",color);
        ospSetMaterial(geom,mat);
        ospCommit(geom);
        ospAddGeometry(model,geom);
      }

      ospCommit(model);

      Assert2(renderer,"could not create renderer");
      ospSetParam(renderer,"world",model);
      ospSetParam(renderer,"camera",camera);
      ospCommit(renderer);

    };
    virtual void reshape(const ospray::vec2i &newSize)
    {
      Glut3DWidget::reshape(newSize);
      if (fb) ospFreeFrameBuffer(fb);
      fb = ospNewFrameBuffer(newSize,OSP_RGBA_I8,OSP_FB_COLOR|OSP_FB_ACCUM);
      ospSetf(camera,"aspect",viewPort.aspect);
      ospCommit(camera);
    }

    virtual void keypress(char key, const vec2f where)
    {
      switch (key) {
      case 'S':
        doShadows = !doShadows;
        cout << "Switching shadows " << (doShadows?"ON":"OFF") << endl;
        ospSet1i(renderer,"shadowsEnabled",doShadows);
        ospCommit(renderer);
        ospFrameBufferClear(fb,OSP_FB_ACCUM);
        break;
      default:
        Glut3DWidget::keypress(key,where);
      }
    }
    virtual void display()
    {
      if (!fb || !renderer) return;

      if (viewPort.modified) {
        Assert2(camera,"ospray camera is null");

        ospSetVec3f(camera,"pos",viewPort.from);
        ospSetVec3f(camera,"dir",viewPort.at-viewPort.from);
        ospSetVec3f(camera,"up",viewPort.up);
        ospSetf(camera,"aspect",viewPort.aspect);
        ospCommit(camera);
        viewPort.modified = false;
        ospFrameBufferClear(fb,OSP_FB_ACCUM);
      }

      fps.startRender();
      ospRenderFrame(fb,renderer,OSP_FB_COLOR|OSP_FB_ACCUM
                     );
      fps.doneRender();

      ucharFB = (unsigned int *)ospMapFrameBuffer(fb);
      frameBufferMode = Glut3DWidget::FRAMEBUFFER_UCHAR;
      Glut3DWidget::display();

      ospUnmapFrameBuffer(ucharFB,fb);

      char title[1000];

      sprintf(title,"OSPRay StreamLines test viewer (%f fps)",
              fps.getFPS());
      setTitle(title);
      forceRedraw();
    }

    OSPFrameBuffer fb;
    OSPRenderer    renderer;
    OSPCamera      camera;
    int            resampleSize;
    ospray::glut3D::FPSCounter fps;
    StreamLines *sl;
    Triangles *tris;
  };

  void ospDVRMain(int &ac, const char **&av)
  {
    StreamLines *streamLines = new StreamLines;
    Triangles   *triangles = new Triangles;
    for (int i=1;i<ac;i++) {
      std::string arg = av[i];
      if (arg[0] != '-') {
        const embree::FileName fn = arg;
        if (fn.ext() == "pnt")
          streamLines->parsePNT(fn);
        else if (fn.ext() == "pntlist")
          streamLines->parsePNTlist(fn);
        else if (fn.ext() == "sv")
          triangles->parseSV(fn);
        else
          throw std::runtime_error("unknown file format "+fn.str());
      } else if (arg == "--module") {
	ospLoadModule(av[++i]);
      } else if (arg == "--renderer") {
        rendererType = av[++i];
      } else if (arg == "--radius") {
        streamLines->radius = atof(av[++i]);
      } else
        throw std::runtime_error("unknown parameter "+arg);
    }
    // -------------------------------------------------------
    // create viewer window
    // -------------------------------------------------------
    StreamLineViewer window(streamLines,triangles);
    window.create("ospDVR: OSPRay miniature stream line viewer");
    printf("Viewer created. Press 'Q' to quit.\n");
    window.setWorldBounds(streamLines->getBounds());
    ospray::glut3D::runGLUT();
  }
}

int main(int ac, const char **av)
{
  ospInit(&ac,av);
  ospray::glut3D::initGLUT(&ac,av);
  ospray::ospDVRMain(ac,av);
}
<commit_msg>adding XML exporter for stream line data<commit_after>/********************************************************************* *\
 * INTEL CORPORATION PROPRIETARY INFORMATION
 * This software is supplied under the terms of a license agreement or
 * nondisclosure agreement with Intel Corporation and may not be copied
 * or disclosed except in accordance with the terms of that agreement.
 * Copyright (C) 2014 Intel Corporation. All Rights Reserved.
 ********************************************************************* */

/*
 mm -C ~/Projects/ospray/bin/ && ~/Projects/ospray/bin/streamLineView ~/models/NASA/B-field-sun/ext/*pnt ~/models/NASA/B-field-sun/original/temp\=6400k.sv   --renderer obj --1k -vp 0.897989 0.588022 -0.800192 -vi 0.0106688 -0.212129 -0.029311 -vu 0 1 0
*/

#undef NDEBUG
// viewer widget
#include "../../apps/util/glut3D/glut3D.h"
// ospray, for rendering
#include "ospray/ospray.h"
// embree
#include "common/sys/filename.h"

namespace ospray {
  using std::cout;
  using std::endl;

  const char *rendererType = "raycast_eyelight";
  bool doShadows = 1;

  OSPModel model = NULL;

  void error(const std::string &err)
  {
    cout << "ospray::ospDVR fatal error : " << err << endl;
    cout << endl;
    cout << "Proper usage: " << endl;
    cout << "  ./streamLineView <file1.pnt> <file2.pnt> ....<fileN.sv>" << std::endl;
    cout << "or" << endl;
    cout << "  ./streamLineView <listOfPntFiles.pntlist> ...." << std::endl;
    cout << endl;
    exit(1);
  }

  using ospray::glut3D::Glut3DWidget;

  struct Triangles {
    std::vector<vec3fa> vertex;
    std::vector<vec3fa> color; // vertex color, from sv's 'v' value
    std::vector<vec3i>  index;

    struct SVVertex {
      float v;
      vec3f pos; //float x,y,z;
    };

    struct SVTriangle {
      SVVertex vertex[3];
    };

    vec3f lerpf(float x, float x0,float x1,vec3f y0, vec3f y1)
    {
      float f = (x-x0)/(x1-x0);
      return f*y1+(1-f)*y0;
    }
    vec3f colorOf(const float f)
    {
      if (f < .5f)
        return vec3f(lerpf(f, 0.f,.5f,vec3f(0),vec3f(0,1,0)));
      else
        return vec3f(lerpf(f, .5f,1.f,vec3f(0,1,0),vec3f(1,0,0)));
    }
    void parseSV(const embree::FileName &fn)
    {
      FILE *file = fopen(fn.str().c_str(),"rb");
      if (!file) return;
      SVTriangle triangle;
      while (fread(&triangle,sizeof(triangle),1,file)) {
        index.push_back(vec3i(0,1,2)+vec3i(vertex.size()));
        vertex.push_back(vec3fa(triangle.vertex[0].pos));
        vertex.push_back(vec3fa(triangle.vertex[1].pos));
        vertex.push_back(vec3fa(triangle.vertex[2].pos));
        color.push_back(colorOf(triangle.vertex[0].v));
        color.push_back(colorOf(triangle.vertex[1].v));
        color.push_back(colorOf(triangle.vertex[2].v));
      }
      fclose(file);
    }
  };

  struct StreamLines {
    std::vector<vec3fa> vertex;
    std::vector<int>    index;
    float radius;

    StreamLines() : radius(0.001f) {};

    void parsePNT(const embree::FileName &fn)
    {
      FILE *file = fopen(fn.c_str(),"r");
      if (!file) {
        cout << "WARNING: could not open file " << fn << endl;
        return;
      }
      vec3fa pnt;
      static size_t totalSegments = 0;
      size_t segments = 0;
      // cout << "parsing file " << fn << ":" << std::flush;
      int rc = fscanf(file,"%f %f %f\n",&pnt.x,&pnt.y,&pnt.z);
      vertex.push_back(pnt);
      Assert(rc == 3);
      while ((rc = fscanf(file,"%f %f %f\n",&pnt.x,&pnt.y,&pnt.z)) == 3) {
        index.push_back(vertex.size()-1);
        vertex.push_back(pnt);
        segments++;
      }
      totalSegments += segments;
      // cout << " " << segments << " segments (" << totalSegments << " total)" << endl;
      fclose(file);
    }
    void parsePNTlist(const embree::FileName &fn)
    {
      FILE *file = fopen(fn.c_str(),"r");
      Assert(file);
      for (char line[10000]; fgets(line,10000,file) && !feof(file); ) {
        char *eol = strstr(line,"\n"); if (eol) *eol = 0;
        parsePNT(line);
      }
      fclose(file);
    }

    void parse(const embree::FileName &fn)
    {
      if (fn.ext() == "pnt")
        parsePNT(fn);
      else if (fn.ext() == "pntlist") {
        FILE *file = fopen(fn.c_str(),"r");
        Assert(file);
        for (char line[10000]; fgets(line,10000,file) && !feof(file); ) {
          char *eol = strstr(line,"\n"); if (eol) *eol = 0;
          parsePNT(line);
        }
        fclose(file);
      } else
        throw std::runtime_error("unknown input file format "+fn.str());
    }
    box3f getBounds() const
    {
      box3f bounds = embree::empty;
      for (int i=0;i<vertex.size();i++)
        bounds.extend(vertex[i]);
      return bounds;
    }
  };

  void writeToXML(StreamLines *sl, Triangles *tris)
  {
    FILE *file = fopen("/tmp/streamlines.xml","w");
    fprintf(file,"<?xml?>\n");
    fprintf(file,"<ospray version=\"0.5.0\">\n");
    fprintf(file,"</ospray>\n");
    fclose(file);
  }

  struct StreamLineViewer : public Glut3DWidget {
    /*! construct volume from file name and dimensions \see volview_notes_on_volume_interface */
    StreamLineViewer(StreamLines *sl, Triangles *tris)
      : Glut3DWidget(Glut3DWidget::FRAMEBUFFER_NONE),
        fb(NULL), renderer(NULL),
        sl(sl), tris(tris)
    {
      camera = ospNewCamera("perspective");
      Assert2(camera,"could not create camera");
      ospSet3f(camera,"pos",-1,1,-1);
      ospSet3f(camera,"dir",+1,-1,+1);
      ospCommit(camera);
      ospCommit(camera);

      renderer = ospNewRenderer(rendererType);

      OSPMaterial mat = ospNewMaterial(renderer,"default");
      if (mat) {
        ospSet3f(mat,"kd",.7,.7,.7); // OBJ renderer, default ...
        ospCommit(mat);
      }

      if (std::string(rendererType) == "obj") {
        OSPLight topLight = ospNewLight(renderer,"DirectionalLight");
        if (topLight) {
          ospSet3f(topLight,"direction",-1,-2,1);
          ospSet3f(topLight,"color",1,1,1);
          ospCommit(topLight);
          OSPData lights = ospNewData(1,OSP_OBJECT,&topLight);
          ospCommit(lights);
          ospSetData(renderer,"directionalLights",lights);
        }
      }

      ospCommit(renderer);

      model = ospNewModel();
      {
        OSPGeometry geom = ospNewGeometry("streamlines");
        Assert(geom);
        OSPData vertex = ospNewData(sl->vertex.size(),OSP_vec3fa,&sl->vertex[0]);
        OSPData index  = ospNewData(sl->index.size(),OSP_uint32,&sl->index[0]);
        ospSetParam(geom,"vertex",vertex);
        ospSetParam(geom,"index",index);
        ospSet1f(geom,"radius",sl->radius);
        if (mat)
          ospSetMaterial(geom,mat);
        ospCommit(geom);
        ospAddGeometry(model,geom);
      }

      if (tris && !tris->index.empty()) {
        OSPGeometry geom = ospNewTriangleMesh();
        Assert(geom);
        OSPData vertex = ospNewData(tris->vertex.size(),OSP_vec3fa,&tris->vertex[0]);
        OSPData index  = ospNewData(tris->index.size(),OSP_vec3i,&tris->index[0]);
        OSPData color  = ospNewData(tris->color.size(),OSP_vec3fa,&tris->color[0]);
        ospSetParam(geom,"vertex",vertex);
        ospSetParam(geom,"index",index);
        ospSetParam(geom,"vertex.color",color);
        ospSetMaterial(geom,mat);
        ospCommit(geom);
        ospAddGeometry(model,geom);
      }

      ospCommit(model);

      Assert2(renderer,"could not create renderer");
      ospSetParam(renderer,"world",model);
      ospSetParam(renderer,"camera",camera);
      ospCommit(renderer);

    };
    virtual void reshape(const ospray::vec2i &newSize)
    {
      Glut3DWidget::reshape(newSize);
      if (fb) ospFreeFrameBuffer(fb);
      fb = ospNewFrameBuffer(newSize,OSP_RGBA_I8,OSP_FB_COLOR|OSP_FB_ACCUM);
      ospSetf(camera,"aspect",viewPort.aspect);
      ospCommit(camera);
    }

    virtual void keypress(char key, const vec2f where)
    {
      switch (key) {
      case 'S':
        doShadows = !doShadows;
        cout << "Switching shadows " << (doShadows?"ON":"OFF") << endl;
        ospSet1i(renderer,"shadowsEnabled",doShadows);
        ospCommit(renderer);
        ospFrameBufferClear(fb,OSP_FB_ACCUM);
        break;
      default:
        Glut3DWidget::keypress(key,where);
      }
    }
    virtual void display()
    {
      if (!fb || !renderer) return;

      if (viewPort.modified) {
        Assert2(camera,"ospray camera is null");

        ospSetVec3f(camera,"pos",viewPort.from);
        ospSetVec3f(camera,"dir",viewPort.at-viewPort.from);
        ospSetVec3f(camera,"up",viewPort.up);
        ospSetf(camera,"aspect",viewPort.aspect);
        ospCommit(camera);
        viewPort.modified = false;
        ospFrameBufferClear(fb,OSP_FB_ACCUM);
      }

      fps.startRender();
      ospRenderFrame(fb,renderer,OSP_FB_COLOR|OSP_FB_ACCUM
                     );
      fps.doneRender();

      ucharFB = (unsigned int *)ospMapFrameBuffer(fb);
      frameBufferMode = Glut3DWidget::FRAMEBUFFER_UCHAR;
      Glut3DWidget::display();

      ospUnmapFrameBuffer(ucharFB,fb);

      char title[1000];

      sprintf(title,"OSPRay StreamLines test viewer (%f fps)",
              fps.getFPS());
      setTitle(title);
      forceRedraw();
    }

    OSPFrameBuffer fb;
    OSPRenderer    renderer;
    OSPCamera      camera;
    int            resampleSize;
    ospray::glut3D::FPSCounter fps;
    StreamLines *sl;
    Triangles *tris;
  };

  void ospDVRMain(int &ac, const char **&av)
  {
    StreamLines *streamLines = new StreamLines;
    Triangles   *triangles = new Triangles;
    for (int i=1;i<ac;i++) {
      std::string arg = av[i];
      if (arg[0] != '-') {
        const embree::FileName fn = arg;
        if (fn.ext() == "pnt")
          streamLines->parsePNT(fn);
        else if (fn.ext() == "pntlist")
          streamLines->parsePNTlist(fn);
        else if (fn.ext() == "sv")
          triangles->parseSV(fn);
        else
          throw std::runtime_error("unknown file format "+fn.str());
      } else if (arg == "--module") {
	ospLoadModule(av[++i]);
      } else if (arg == "--renderer") {
        rendererType = av[++i];
      } else if (arg == "--radius") {
        streamLines->radius = atof(av[++i]);
      } else
        throw std::runtime_error("unknown parameter "+arg);
    }
    // -------------------------------------------------------
    // create viewer window
    // -------------------------------------------------------
#if 1
    writeToXML(streamLines,triangles);
#endif
    StreamLineViewer window(streamLines,triangles);
    window.create("ospDVR: OSPRay miniature stream line viewer");
    printf("Viewer created. Press 'Q' to quit.\n");
    window.setWorldBounds(streamLines->getBounds());
    ospray::glut3D::runGLUT();
  }
}

int main(int ac, const char **av)
{
  ospInit(&ac,av);
  ospray::glut3D::initGLUT(&ac,av);
  ospray::ospDVRMain(ac,av);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2020 LcfTrans authors
 * This file is released under the MIT License
 * http://opensource.org/licenses/MIT
 */

#include <cstring>
#include <fstream>
#include <iostream>

#include "translation.h"
#include "utils.h"

#ifdef _WIN32
#include "dirent_win.h"
#else
#include <dirent.h>
#endif

#define DATABASE_FILE "rpg_rt.ldb"
#define MAPTREE_FILE "rpg_rt.lmt"
#define INI_FILE "rpg_rt.ini"

void DumpLdb(const std::string& filename);
void DumpLmu(const std::string& filename);
void DumpLmt(const std::string& filename);

static int print_help(char** argv) {
	std::cerr << "lcftrans - Translate RPG Maker 2000/2003 projects\n";
	std::cerr << "Usage: " << argv[0] << " [OPTION...] DIRECTORY [ENCODING]\n";
	std::cerr << "Required options (one of):\n";
	std::cerr << "  -c, --create  Create a new translation\n";
	std::cerr << "  -u, --update  Update an existing translation\n";
	std::cerr << "\n";
	std::cerr << "Optional options:\n";
	std::cerr << "  -h, --help    This usage message\n";
	std::cerr << "  -o, --output  Output directory (default: working directory)\n";
	return 2;
}

std::string encoding;
std::string outdir = ".";
std::vector<std::pair<std::string, std::string>> outdir_files;
bool update = false;

int main(int argc, char** argv) {
	std::string indir;
	bool create = false;

	if (argc <= 1) {
		return print_help(argv);
	}

	/* parse command line arguments */
	for (int i = 1; i < argc; ++i) {
		std::string arg = argv[i];

		if ((arg == "--help") || (arg == "-h")) {
			return print_help(argv);
		} else if ((arg == "--output") || (arg == "-o")) {
			if (i + 1 < argc) {
				outdir = argv[i + 1];
				++i;
			}
		} else if ((arg == "--create") || (arg == "-c")) {
			if (update) {
				return print_help(argv);
			}
			create = true;
		} else if ((arg == "--update") || (arg == "-u")) {
			if (create) {
				return print_help(argv);
			}
			update = true;
		} else {
			indir = arg;
			if (i+1 < argc) {
				encoding = argv[i+1];
			}
			break;
		}
	}

	if (indir.empty() || (!update && !create)) {
		return print_help(argv);
	}

	DIR *dirHandle;
	struct dirent* dirEntry;

	dirHandle = opendir(outdir.c_str());
	if (!dirHandle) {
		std::cerr << "Can not access output directory " << outdir << "\n";
		return 1;
	}
	if (update) {
		while (nullptr != (dirEntry = readdir(dirHandle))) {
			outdir_files.emplace_back(dirEntry->d_name, Utils::LowerCase(dirEntry->d_name));
		}
	}

	closedir(dirHandle);

	dirHandle = opendir(indir.c_str());

	if (dirHandle) {
		while (nullptr != (dirEntry = readdir(dirHandle))) {
			std::string name = dirEntry->d_name;
			std::string lname = Utils::LowerCase(name);

			auto full_path = [&]() {
				return indir + "/" + name;
			};

			if (lname == DATABASE_FILE) {
				std::cout << "Parsing Database " << name << std::endl;
				DumpLdb(full_path());
			} else if (lname == MAPTREE_FILE) {
				std::cout << "Parsing Maptree " << name << std::endl;
				DumpLmt(full_path());
			} else if (Utils::HasExt(lname, ".lmu")) {
				std::cout << "Parsing Map " << name << std::endl;
				DumpLmu(full_path());
			}
		}
		closedir(dirHandle);
	} else {
		std::cerr << "Failed reading dir " << indir << "\n";
		return 1;
	}

	return 0;
}

static std::string get_outdir_file(const std::string& file) {
	for (const auto& f : outdir_files) {
		if (f.second == file) {
			return f.first;
		}
	}
	return "";
}

void DumpLdb(const std::string& filename) {
	TranslationLdb t = Translation::fromLDB(filename, encoding);

	auto dump = [](Translation& ti, const std::string& poname) {
		if (update) {
			std::string po = get_outdir_file(Utils::LowerCase(poname + ".po"));
			if (!po.empty()) {
				Translation pot;
				pot = Translation::fromPO(outdir + "/" + po);
				auto stale = ti.Merge(pot);
				if (!stale.getEntries().empty()) {
					std::cout << " " << stale.getEntries().size() << " strings are stale\n";
					std::ofstream outfile(outdir + "/" + poname + ".stale.po");
					stale.write(outfile);
				}
			}
		}

		std::ofstream outfile(outdir + "/" + poname + ".po");
		ti.write(outfile);
	};

	std::cout << " " << t.terms.getEntries().size() << " strings\n";
	dump(t.terms, "RPG_RT.ldb");

	std::cout << " " << t.common_events.getEntries().size() << " strings in Common Events\n";
	dump(t.common_events, "RPG_RT.ldb.common");

	std::cout << " " << t.battle_events.getEntries().size() << " strings in Battle Events\n";
	dump(t.terms, "RPG_RT.ldb.battle");
}

void DumpLmuLmtInner(const std::string& filename, Translation& t, const std::string& poname) {
	Translation pot;

	if (t.getEntries().empty()) {
		std::cout << " Skipped... No strings found.\n";
		return;
	}

	std::cout << " " << t.getEntries().size() << " strings\n";

	if (update) {
		std::string po = get_outdir_file(Utils::LowerCase(poname + ".po"));
		if (!po.empty()) {
			if (poname == "Map0001") {
				int a;
			}

			pot = Translation::fromPO(outdir + "/" + po);
			auto stale = t.Merge(pot);
			if (!stale.getEntries().empty()) {
				std::cout << " " << stale.getEntries().size() << " strings are stale\n";
				std::ofstream outfile(outdir + "/" + poname + ".stale.po");
				stale.write(outfile);
			}
		}
	}

	std::ofstream outfile(outdir + "/" + poname + ".po");

	t.write(outfile);
}

void DumpLmu(const std::string& filename) {
	Translation t = Translation::fromLMU(filename, encoding);
	DumpLmuLmtInner(filename, t, Utils::GetFilename(filename));
}

void DumpLmt(const std::string& filename) {
	Translation t = Translation::fromLMT(filename, encoding);
	DumpLmuLmtInner(filename, t, "RPG_RT.lmt");
}

<commit_msg>LcfTrans: Grammar :)<commit_after>/*
 * Copyright (c) 2020 LcfTrans authors
 * This file is released under the MIT License
 * http://opensource.org/licenses/MIT
 */

#include <cstring>
#include <fstream>
#include <iostream>

#include "translation.h"
#include "utils.h"

#ifdef _WIN32
#include "dirent_win.h"
#else
#include <dirent.h>
#endif

#define DATABASE_FILE "rpg_rt.ldb"
#define MAPTREE_FILE "rpg_rt.lmt"
#define INI_FILE "rpg_rt.ini"

void DumpLdb(const std::string& filename);
void DumpLmu(const std::string& filename);
void DumpLmt(const std::string& filename);

static int print_help(char** argv) {
	std::cerr << "lcftrans - Translate RPG Maker 2000/2003 projects\n";
	std::cerr << "Usage: " << argv[0] << " [OPTION...] DIRECTORY [ENCODING]\n";
	std::cerr << "Required options (one of):\n";
	std::cerr << "  -c, --create  Create a new translation\n";
	std::cerr << "  -u, --update  Update an existing translation\n";
	std::cerr << "\n";
	std::cerr << "Optional options:\n";
	std::cerr << "  -h, --help    This usage message\n";
	std::cerr << "  -o, --output  Output directory (default: working directory)\n";
	return 2;
}

std::string encoding;
std::string outdir = ".";
std::vector<std::pair<std::string, std::string>> outdir_files;
bool update = false;

int main(int argc, char** argv) {
	std::string indir;
	bool create = false;

	if (argc <= 1) {
		return print_help(argv);
	}

	/* parse command line arguments */
	for (int i = 1; i < argc; ++i) {
		std::string arg = argv[i];

		if ((arg == "--help") || (arg == "-h")) {
			return print_help(argv);
		} else if ((arg == "--output") || (arg == "-o")) {
			if (i + 1 < argc) {
				outdir = argv[i + 1];
				++i;
			}
		} else if ((arg == "--create") || (arg == "-c")) {
			if (update) {
				return print_help(argv);
			}
			create = true;
		} else if ((arg == "--update") || (arg == "-u")) {
			if (create) {
				return print_help(argv);
			}
			update = true;
		} else {
			indir = arg;
			if (i+1 < argc) {
				encoding = argv[i+1];
			}
			break;
		}
	}

	if (indir.empty() || (!update && !create)) {
		return print_help(argv);
	}

	DIR *dirHandle;
	struct dirent* dirEntry;

	dirHandle = opendir(outdir.c_str());
	if (!dirHandle) {
		std::cerr << "Can not access output directory " << outdir << "\n";
		return 1;
	}
	if (update) {
		while (nullptr != (dirEntry = readdir(dirHandle))) {
			outdir_files.emplace_back(dirEntry->d_name, Utils::LowerCase(dirEntry->d_name));
		}
	}

	closedir(dirHandle);

	dirHandle = opendir(indir.c_str());

	if (dirHandle) {
		while (nullptr != (dirEntry = readdir(dirHandle))) {
			std::string name = dirEntry->d_name;
			std::string lname = Utils::LowerCase(name);

			auto full_path = [&]() {
				return indir + "/" + name;
			};

			if (lname == DATABASE_FILE) {
				std::cout << "Parsing Database " << name << std::endl;
				DumpLdb(full_path());
			} else if (lname == MAPTREE_FILE) {
				std::cout << "Parsing Maptree " << name << std::endl;
				DumpLmt(full_path());
			} else if (Utils::HasExt(lname, ".lmu")) {
				std::cout << "Parsing Map " << name << std::endl;
				DumpLmu(full_path());
			}
		}
		closedir(dirHandle);
	} else {
		std::cerr << "Failed reading dir " << indir << "\n";
		return 1;
	}

	return 0;
}

static std::string get_outdir_file(const std::string& file) {
	for (const auto& f : outdir_files) {
		if (f.second == file) {
			return f.first;
		}
	}
	return "";
}

void DumpLdb(const std::string& filename) {
	TranslationLdb t = Translation::fromLDB(filename, encoding);

	auto dump = [](Translation& ti, const std::string& poname) {
		if (update) {
			std::string po = get_outdir_file(Utils::LowerCase(poname + ".po"));
			if (!po.empty()) {
				Translation pot;
				pot = Translation::fromPO(outdir + "/" + po);
				auto stale = ti.Merge(pot);
				if (!stale.getEntries().empty()) {
					std::string term = stale.getEntries().size() == 1 ? " term is " : " terms are ";

					std::cout << " " << stale.getEntries().size() << term << "stale\n";
					std::ofstream outfile(outdir + "/" + poname + ".stale.po");
					stale.write(outfile);
				}
			}
		}

		std::ofstream outfile(outdir + "/" + poname + ".po");
		ti.write(outfile);
	};

	auto term = [](const Translation& t) {
		return std::to_string(t.getEntries().size()) + " " + (t.getEntries().size() == 1 ? "term " : "terms ");
	};

	std::cout << " " << term(t.terms) << "in the database\n";
	dump(t.terms, "RPG_RT.ldb");

	std::cout << " " << term(t.common_events) << "in Common Events\n";
	dump(t.common_events, "RPG_RT.ldb.common");

	std::cout << " " << term(t.battle_events) << "in Battle Events\n";
	dump(t.battle_events, "RPG_RT.ldb.battle");
}

void DumpLmuLmtInner(const std::string& filename, Translation& t, const std::string& poname) {
	Translation pot;

	if (t.getEntries().empty()) {
		std::cout << " Skipped. No terms found.\n";
		return;
	}

	std::cout << " " << t.getEntries().size() << " term" << (t.getEntries().size() == 1 ? "" : "s") << "\n";

	if (update) {
		std::string po = get_outdir_file(Utils::LowerCase(poname + ".po"));
		if (!po.empty()) {
			if (poname == "Map0001") {
				int a;
			}

			pot = Translation::fromPO(outdir + "/" + po);
			auto stale = t.Merge(pot);
			if (!stale.getEntries().empty()) {
				std::string term = stale.getEntries().size() == 1 ? " term is " : " terms are ";
				std::cout << " " << stale.getEntries().size() << term << "stale\n";
				std::ofstream outfile(outdir + "/" + poname + ".stale.po");
				stale.write(outfile);
			}
		}
	}

	std::ofstream outfile(outdir + "/" + poname + ".po");

	t.write(outfile);
}

void DumpLmu(const std::string& filename) {
	Translation t = Translation::fromLMU(filename, encoding);
	DumpLmuLmtInner(filename, t, Utils::GetFilename(filename));
}

void DumpLmt(const std::string& filename) {
	Translation t = Translation::fromLMT(filename, encoding);
	DumpLmuLmtInner(filename, t, "RPG_RT.lmt");
}

<|endoftext|>