<commit_before>/*
 *  This file is part of Poedit (https://poedit.net)
 *
 *  Copyright (C) 2015-2016 Vaclav Slavik
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 *
 */

#include "customcontrols.h"

#include "concurrency.h"
#include "errors.h"
#include "hidpi.h"

#include <wx/app.h>
#include <wx/clipbrd.h>
#include <wx/menu.h>
#include <wx/settings.h>
#include <wx/sizer.h>
#include <wx/weakref.h>
#include <wx/wupdlock.h>

#if wxCHECK_VERSION(3,1,0)
    #include <wx/activityindicator.h>
#else
    #include "wx_backports/activityindicator.h"
#endif

#include <unicode/brkiter.h>
#ifdef __WXGTK__
#include <gtk/gtk.h>
#endif

#include "str_helpers.h"
#include "unicode_helpers.h"

#include <memory>

namespace
{

wxString WrapTextAtWidth(const wxString& text_, int width, Language lang, wxWindow *wnd)
{
    if (text_.empty())
        return text_;

#ifdef BIDI_NEEDS_DIRECTION_ON_EACH_LINE
    wchar_t directionMark = 0;
    if (bidi::is_direction_mark(*text_.begin()))
        directionMark = *text_.begin();
#endif

    auto text = str::to_icu(text_);

    static std::unique_ptr<icu::BreakIterator> iter;
    if (!iter)
    {
        UErrorCode err = U_ZERO_ERROR;
        iter.reset(icu::BreakIterator::createLineInstance(lang.IsValid() ? lang.ToIcu() : icu::Locale(), err));
        if (!iter)
            iter.reset(icu::BreakIterator::createLineInstance(icu::Locale::getEnglish(), err));
    }

    iter->setText(text);

    wxString out;
    out.reserve(text_.length() + 10);

    int32_t lineStart = 0;
    wxString previousSubstr;

    for (int32_t pos = iter->next(); pos != icu::BreakIterator::DONE; pos = iter->next())
    {
        auto substr = str::to_wx(text.tempSubStringBetween(lineStart, pos));

        if (wnd->GetTextExtent(substr).x > width)
        {
            auto previousPos = iter->previous();
            if (previousPos == lineStart || previousPos == icu::BreakIterator::DONE)
            {
                // line is too large but we can't break it, so have no choice but not to wrap
                out += substr;
                lineStart = pos;
            }
            else
            {
                // need to wrap at previous linebreak position
                out += previousSubstr;
                lineStart = previousPos;
            }

            out += '\n';
#ifdef BIDI_NEEDS_DIRECTION_ON_EACH_LINE
            if (directionMark)
                out += directionMark;
#endif

            previousSubstr.clear();
        }
        else if (pos > 0 && text[pos-1] == '\n') // forced line feed
        {
            out += substr;
            lineStart = pos;
            previousSubstr.clear();
        }
        else
        {
            previousSubstr = substr;
        }
    }

    if (!previousSubstr.empty())
    {
        out += previousSubstr;
    }

    if (out.Last() == '\n')
        out.RemoveLast();

    return out;
}

} // anonymous namespace

AutoWrappingText::AutoWrappingText(wxWindow *parent, const wxString& label)
    : wxStaticText(parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE),
      m_text(label),
      m_wrapWidth(-1)
{
    m_text.Replace("\n", " ");

    SetInitialSize(wxSize(10,10));
    Bind(wxEVT_SIZE, &AutoWrappingText::OnSize, this);
}

void AutoWrappingText::SetLanguage(Language lang)
{
    m_language = lang;
    SetAlignment(m_language.Direction());
}

void AutoWrappingText::SetAlignment(TextDirection dir)
{
    // a quirk of wx API: if the current locale is RTL, the meaning of L and R is reversed
    // for alignments
    bool isRTL = (dir == TextDirection::RTL);
    if (GetLayoutDirection() == wxLayout_RightToLeft)
        isRTL = !isRTL;

    const int align = isRTL ? wxALIGN_RIGHT : wxALIGN_LEFT;
    if (HasFlag(align))
        return;
    SetWindowStyleFlag(wxST_NO_AUTORESIZE | align);
}

void AutoWrappingText::SetAndWrapLabel(const wxString& label)
{
    m_text = bidi::platform_mark_direction(label);
    if (!m_language.IsValid())
        SetAlignment(bidi::get_base_direction(m_text));

    wxWindowUpdateLocker lock(this);
    m_wrapWidth = GetSize().x;
    SetLabelText(WrapTextAtWidth(label, m_wrapWidth, m_language, this));

    InvalidateBestSize();
    SetMinSize(wxDefaultSize);
    SetMinSize(GetBestSize());
}

void AutoWrappingText::OnSize(wxSizeEvent& e)
{
    e.Skip();
    int w = wxMax(0, e.GetSize().x - PX(4));
    if (w == m_wrapWidth)
        return;

    wxWindowUpdateLocker lock(this);

    m_wrapWidth = w;
    SetLabel(WrapTextAtWidth(m_text, w, m_language, this));

    InvalidateBestSize();
    SetMinSize(wxDefaultSize);
    SetMinSize(GetBestSize());
}

SelectableAutoWrappingText::SelectableAutoWrappingText(wxWindow *parent, const wxString& label)
    : AutoWrappingText(parent, label)
{
#if defined(__WXOSX__)
    NSTextField *view = (NSTextField*)GetHandle();
    [view setSelectable:YES];
#elif defined(__WXGTK__)
    GtkLabel *view = GTK_LABEL(GetHandle());
    gtk_label_set_selectable(view, TRUE);
#else
    // at least allow copying
    static wxWindowID idCopy = wxNewId();
    Bind(wxEVT_CONTEXT_MENU, [=](wxContextMenuEvent&){
        wxMenu *menu = new wxMenu();
        menu->Append(idCopy, _("&Copy"));
        PopupMenu(menu);
    });
    Bind(wxEVT_MENU, [=](wxCommandEvent&){
        wxClipboardLocker lock;
        wxClipboard::Get()->SetData(new wxTextDataObject(m_text));
    }, idCopy);
#endif
}

ExplanationLabel::ExplanationLabel(wxWindow *parent, const wxString& label)
    : AutoWrappingText(parent, label)
{
#if defined(__WXOSX__)
    SetWindowVariant(wxWINDOW_VARIANT_SMALL);
#elif defined(__WXGTK__)
    #if wxCHECK_VERSION(3,1,0)
        SetWindowVariant(wxWINDOW_VARIANT_SMALL);
    #else
        SetFont(GetFont().Smaller());
    #endif
#endif
#ifndef __WXGTK__
    SetForegroundColour(GetTextColor());
#endif
}

wxColour ExplanationLabel::GetTextColor()
{
#if defined(__WXOSX__)
    return wxColour("#777777");
#elif defined(__WXGTK__)
    return wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
#else
    return wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT);
#endif
}

SecondaryLabel::SecondaryLabel(wxWindow *parent, const wxString& label)
    : wxStaticText(parent, wxID_ANY, label)
{
#if defined(__WXOSX__)
    SetWindowVariant(wxWINDOW_VARIANT_SMALL);
#elif defined(__WXGTK__)
    #if wxCHECK_VERSION(3,1,0)
        SetWindowVariant(wxWINDOW_VARIANT_SMALL);
    #else
        SetFont(GetFont().Smaller());
    #endif
#endif
#ifndef __WXGTK__
    SetForegroundColour(GetTextColor());
#endif
}

LearnMoreLink::LearnMoreLink(wxWindow *parent, const wxString& url, wxString label, wxWindowID winid)
{
    if (label.empty())
    {
#ifdef __WXMSW__
        label = _("Learn more");
#else
        label = _("Learn More");
#endif
    }

    wxHyperlinkCtrl::Create(parent, winid, label, url);
    SetNormalColour("#2F79BE");
    SetVisitedColour("#2F79BE");
    SetHoverColour("#3D8DD5");

#ifdef __WXOSX__
    SetWindowVariant(wxWINDOW_VARIANT_SMALL);
    SetFont(GetFont().Underlined());
#endif
}

wxObject *LearnMoreLinkXmlHandler::DoCreateResource()
{
    auto w = new LearnMoreLink(m_parentAsWindow, GetText("url"), GetText("label"), GetID());
    w->SetName(GetName());
    SetupWindow(w);
    return w;
}

bool LearnMoreLinkXmlHandler::CanHandle(wxXmlNode *node)
{
    return IsOfClass(node, "LearnMoreLink");
}

ActivityIndicator::ActivityIndicator(wxWindow *parent)
    : wxWindow(parent, wxID_ANY), m_running(false)
{
    auto sizer = new wxBoxSizer(wxHORIZONTAL);
    SetSizer(sizer);

    m_spinner = new wxActivityIndicator(this, wxID_ANY);
    m_spinner->SetWindowVariant(wxWINDOW_VARIANT_SMALL);
    m_label = new wxStaticText(this, wxID_ANY, "");
#ifdef __WXOSX__
    m_label->SetWindowVariant(wxWINDOW_VARIANT_SMALL);
#endif

    sizer->Add(m_spinner, wxSizerFlags().Center().Border(wxRIGHT, PX(4)));
    sizer->Add(m_label, wxSizerFlags(1).Center());

    HandleError = on_main_thread_for_window<std::exception_ptr>(this, [=](std::exception_ptr e){
        StopWithError(DescribeException(e));
    });
}

void ActivityIndicator::Start(const wxString& msg)
{
    m_running = true;

    m_label->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
    m_label->SetLabel(msg);

    auto sizer = GetSizer();
    sizer->Show(m_spinner);
    sizer->Show(m_label, !msg.empty());
    Layout();

    m_spinner->Start();
}

void ActivityIndicator::Stop()
{
    m_running = false;

    m_spinner->Stop();
    m_label->SetLabel("");

    auto sizer = GetSizer();
    sizer->Hide(m_spinner);
    sizer->Hide(m_label);
    Layout();
}

void ActivityIndicator::StopWithError(const wxString& msg)
{
    m_running = false;

    m_spinner->Stop();
    m_label->SetForegroundColour(*wxRED);
    m_label->SetLabel(msg);

    auto sizer = GetSizer();
    sizer->Hide(m_spinner);
    sizer->Show(m_label);
    Layout();
}
<commit_msg>Fix WrapTextAtWidth to actually respect the language<commit_after>/*
 *  This file is part of Poedit (https://poedit.net)
 *
 *  Copyright (C) 2015-2016 Vaclav Slavik
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 *
 */

#include "customcontrols.h"

#include "concurrency.h"
#include "errors.h"
#include "hidpi.h"

#include <wx/app.h>
#include <wx/clipbrd.h>
#include <wx/menu.h>
#include <wx/settings.h>
#include <wx/sizer.h>
#include <wx/weakref.h>
#include <wx/wupdlock.h>

#if wxCHECK_VERSION(3,1,0)
    #include <wx/activityindicator.h>
#else
    #include "wx_backports/activityindicator.h"
#endif

#include <unicode/brkiter.h>
#ifdef __WXGTK__
#include <gtk/gtk.h>
#endif

#include "str_helpers.h"
#include "unicode_helpers.h"

#include <map>
#include <memory>

namespace
{

wxString WrapTextAtWidth(const wxString& text_, int width, Language lang, wxWindow *wnd)
{
    if (text_.empty())
        return text_;

#ifdef BIDI_NEEDS_DIRECTION_ON_EACH_LINE
    wchar_t directionMark = 0;
    if (bidi::is_direction_mark(*text_.begin()))
        directionMark = *text_.begin();
#endif

    auto text = str::to_icu(text_);

    static std::map<std::string, std::shared_ptr<icu::BreakIterator>> lang_iters;
    std::shared_ptr<icu::BreakIterator> iter;
    auto lang_name = lang.IcuLocaleName();
    auto li = lang_iters.find(lang_name);
    if (li == lang_iters.end())
    {
        UErrorCode err = U_ZERO_ERROR;
        iter.reset(icu::BreakIterator::createLineInstance(lang.IsValid() ? lang.ToIcu() : icu::Locale(), err));
        if (!iter)
            iter.reset(icu::BreakIterator::createLineInstance(icu::Locale::getEnglish(), err));
        lang_iters[lang_name] = iter;
    }
    else
    {
        iter = li->second;
    }

    iter->setText(text);

    wxString out;
    out.reserve(text_.length() + 10);

    int32_t lineStart = 0;
    wxString previousSubstr;

    for (int32_t pos = iter->next(); pos != icu::BreakIterator::DONE; pos = iter->next())
    {
        auto substr = str::to_wx(text.tempSubStringBetween(lineStart, pos));

        if (wnd->GetTextExtent(substr).x > width)
        {
            auto previousPos = iter->previous();
            if (previousPos == lineStart || previousPos == icu::BreakIterator::DONE)
            {
                // line is too large but we can't break it, so have no choice but not to wrap
                out += substr;
                lineStart = pos;
            }
            else
            {
                // need to wrap at previous linebreak position
                out += previousSubstr;
                lineStart = previousPos;
            }

            out += '\n';
#ifdef BIDI_NEEDS_DIRECTION_ON_EACH_LINE
            if (directionMark)
                out += directionMark;
#endif

            previousSubstr.clear();
        }
        else if (pos > 0 && text[pos-1] == '\n') // forced line feed
        {
            out += substr;
            lineStart = pos;
            previousSubstr.clear();
        }
        else
        {
            previousSubstr = substr;
        }
    }

    if (!previousSubstr.empty())
    {
        out += previousSubstr;
    }

    if (out.Last() == '\n')
        out.RemoveLast();

    return out;
}

} // anonymous namespace

AutoWrappingText::AutoWrappingText(wxWindow *parent, const wxString& label)
    : wxStaticText(parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE),
      m_text(label),
      m_wrapWidth(-1)
{
    m_text.Replace("\n", " ");

    SetInitialSize(wxSize(10,10));
    Bind(wxEVT_SIZE, &AutoWrappingText::OnSize, this);
}

void AutoWrappingText::SetLanguage(Language lang)
{
    m_language = lang;
    SetAlignment(m_language.Direction());
}

void AutoWrappingText::SetAlignment(TextDirection dir)
{
    // a quirk of wx API: if the current locale is RTL, the meaning of L and R is reversed
    // for alignments
    bool isRTL = (dir == TextDirection::RTL);
    if (GetLayoutDirection() == wxLayout_RightToLeft)
        isRTL = !isRTL;

    const int align = isRTL ? wxALIGN_RIGHT : wxALIGN_LEFT;
    if (HasFlag(align))
        return;
    SetWindowStyleFlag(wxST_NO_AUTORESIZE | align);
}

void AutoWrappingText::SetAndWrapLabel(const wxString& label)
{
    m_text = bidi::platform_mark_direction(label);
    if (!m_language.IsValid())
        SetAlignment(bidi::get_base_direction(m_text));

    wxWindowUpdateLocker lock(this);
    m_wrapWidth = GetSize().x;
    SetLabelText(WrapTextAtWidth(label, m_wrapWidth, m_language, this));

    InvalidateBestSize();
    SetMinSize(wxDefaultSize);
    SetMinSize(GetBestSize());
}

void AutoWrappingText::OnSize(wxSizeEvent& e)
{
    e.Skip();
    int w = wxMax(0, e.GetSize().x - PX(4));
    if (w == m_wrapWidth)
        return;

    wxWindowUpdateLocker lock(this);

    m_wrapWidth = w;
    SetLabel(WrapTextAtWidth(m_text, w, m_language, this));

    InvalidateBestSize();
    SetMinSize(wxDefaultSize);
    SetMinSize(GetBestSize());
}

SelectableAutoWrappingText::SelectableAutoWrappingText(wxWindow *parent, const wxString& label)
    : AutoWrappingText(parent, label)
{
#if defined(__WXOSX__)
    NSTextField *view = (NSTextField*)GetHandle();
    [view setSelectable:YES];
#elif defined(__WXGTK__)
    GtkLabel *view = GTK_LABEL(GetHandle());
    gtk_label_set_selectable(view, TRUE);
#else
    // at least allow copying
    static wxWindowID idCopy = wxNewId();
    Bind(wxEVT_CONTEXT_MENU, [=](wxContextMenuEvent&){
        wxMenu *menu = new wxMenu();
        menu->Append(idCopy, _("&Copy"));
        PopupMenu(menu);
    });
    Bind(wxEVT_MENU, [=](wxCommandEvent&){
        wxClipboardLocker lock;
        wxClipboard::Get()->SetData(new wxTextDataObject(m_text));
    }, idCopy);
#endif
}

ExplanationLabel::ExplanationLabel(wxWindow *parent, const wxString& label)
    : AutoWrappingText(parent, label)
{
#if defined(__WXOSX__)
    SetWindowVariant(wxWINDOW_VARIANT_SMALL);
#elif defined(__WXGTK__)
    #if wxCHECK_VERSION(3,1,0)
        SetWindowVariant(wxWINDOW_VARIANT_SMALL);
    #else
        SetFont(GetFont().Smaller());
    #endif
#endif
#ifndef __WXGTK__
    SetForegroundColour(GetTextColor());
#endif
}

wxColour ExplanationLabel::GetTextColor()
{
#if defined(__WXOSX__)
    return wxColour("#777777");
#elif defined(__WXGTK__)
    return wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
#else
    return wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT);
#endif
}

SecondaryLabel::SecondaryLabel(wxWindow *parent, const wxString& label)
    : wxStaticText(parent, wxID_ANY, label)
{
#if defined(__WXOSX__)
    SetWindowVariant(wxWINDOW_VARIANT_SMALL);
#elif defined(__WXGTK__)
    #if wxCHECK_VERSION(3,1,0)
        SetWindowVariant(wxWINDOW_VARIANT_SMALL);
    #else
        SetFont(GetFont().Smaller());
    #endif
#endif
#ifndef __WXGTK__
    SetForegroundColour(GetTextColor());
#endif
}

LearnMoreLink::LearnMoreLink(wxWindow *parent, const wxString& url, wxString label, wxWindowID winid)
{
    if (label.empty())
    {
#ifdef __WXMSW__
        label = _("Learn more");
#else
        label = _("Learn More");
#endif
    }

    wxHyperlinkCtrl::Create(parent, winid, label, url);
    SetNormalColour("#2F79BE");
    SetVisitedColour("#2F79BE");
    SetHoverColour("#3D8DD5");

#ifdef __WXOSX__
    SetWindowVariant(wxWINDOW_VARIANT_SMALL);
    SetFont(GetFont().Underlined());
#endif
}

wxObject *LearnMoreLinkXmlHandler::DoCreateResource()
{
    auto w = new LearnMoreLink(m_parentAsWindow, GetText("url"), GetText("label"), GetID());
    w->SetName(GetName());
    SetupWindow(w);
    return w;
}

bool LearnMoreLinkXmlHandler::CanHandle(wxXmlNode *node)
{
    return IsOfClass(node, "LearnMoreLink");
}

ActivityIndicator::ActivityIndicator(wxWindow *parent)
    : wxWindow(parent, wxID_ANY), m_running(false)
{
    auto sizer = new wxBoxSizer(wxHORIZONTAL);
    SetSizer(sizer);

    m_spinner = new wxActivityIndicator(this, wxID_ANY);
    m_spinner->SetWindowVariant(wxWINDOW_VARIANT_SMALL);
    m_label = new wxStaticText(this, wxID_ANY, "");
#ifdef __WXOSX__
    m_label->SetWindowVariant(wxWINDOW_VARIANT_SMALL);
#endif

    sizer->Add(m_spinner, wxSizerFlags().Center().Border(wxRIGHT, PX(4)));
    sizer->Add(m_label, wxSizerFlags(1).Center());

    HandleError = on_main_thread_for_window<std::exception_ptr>(this, [=](std::exception_ptr e){
        StopWithError(DescribeException(e));
    });
}

void ActivityIndicator::Start(const wxString& msg)
{
    m_running = true;

    m_label->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
    m_label->SetLabel(msg);

    auto sizer = GetSizer();
    sizer->Show(m_spinner);
    sizer->Show(m_label, !msg.empty());
    Layout();

    m_spinner->Start();
}

void ActivityIndicator::Stop()
{
    m_running = false;

    m_spinner->Stop();
    m_label->SetLabel("");

    auto sizer = GetSizer();
    sizer->Hide(m_spinner);
    sizer->Hide(m_label);
    Layout();
}

void ActivityIndicator::StopWithError(const wxString& msg)
{
    m_running = false;

    m_spinner->Stop();
    m_label->SetForegroundColour(*wxRED);
    m_label->SetLabel(msg);

    auto sizer = GetSizer();
    sizer->Hide(m_spinner);
    sizer->Show(m_label);
    Layout();
}
<|endoftext|>


<commit_before>/*
 * Illarionserver - server for the game Illarion
 * Copyright 2011 Illarion e.V.
 *
 * This file is part of Illarionserver.
 *
 * Illarionserver  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.
 *
 * Illarionserver 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
 * Illarionserver. If not, see <http://www.gnu.org/licenses/>.
 */

#include "RaceTable.hpp"

std::string RaceTable::getTableName() {
    return "race";
}

std::vector<std::string> RaceTable::getColumnNames() {
    return {
        "race_id",
        "race_name"
        "race_height_min",
        "race_height_max",
        "race_agility_min",
        "race_agility_max",
        "race_constitution_min",
        "race_constitution_max",
        "race_dexterity_min",
        "race_dexterity_max",
        "race_essence_min",
        "race_essence_max",
        "race_intelligence_min",
        "race_intelligence_max",
        "race_perception_min",
        "race_perception_max",
        "race_strength_min",
        "race_strength_max",
        "race_willpower_min",
        "race_willpower_max",
        "race_attribute_points_max"
    };
}

TYPE_OF_ITEM_ID RaceTable::assignId(const Database::ResultTuple &row) {
    return uint16_t(row["race_id"].as<int32_t>());
}

RaceStruct RaceTable::assignTable(const Database::ResultTuple &row) {
    RaceStruct race;
    race.serverName = row["race_name"].as<std::string>("unknown");
    race.minSize = uint16_t(row["race_height_min"].as<int32_t>(100));
    race.maxSize = uint16_t(row["race_height_max"].as<int32_t>(100));
    race.minAgility = uint8_t(row["race_agility_min"].as<int32_t>(2));
    race.maxAgility = uint8_t(row["race_agility_max"].as<int32_t>(20));
    race.minConstitution = uint8_t(row["race_constitution_min"].as<int32_t>(2));
    race.maxConstitution = uint8_t(row["race_constitution_max"].as<int32_t>(20));
    race.minDexterity = uint8_t(row["race_dexterity_min"].as<int32_t>(2));
    race.maxDexterity = uint8_t(row["race_dexterity_max"].as<int32_t>(20));
    race.minEssence = uint8_t(row["race_essence_min"].as<int32_t>(2));
    race.maxEssence = uint8_t(row["race_essence_max"].as<int32_t>(20));
    race.minIntelligence = uint8_t(row["race_intelligence_min"].as<int32_t>(2));
    race.maxIntelligence = uint8_t(row["race_intelligence_max"].as<int32_t>(20));
    race.minPerception = uint8_t(row["race_perception_min"].as<int32_t>(2));
    race.maxPerception = uint8_t(row["race_perception_max"].as<int32_t>(20));
    race.minStrength = uint8_t(row["race_strength_min"].as<int32_t>(2));
    race.maxStrength = uint8_t(row["race_strength_max"].as<int32_t>(20));
    race.minWillpower = uint8_t(row["race_willpower_min"].as<int32_t>(2));
    race.maxWillpower = uint8_t(row["race_willpower_max"].as<int32_t>(20));
    race.maxAttribs = uint8_t(row["race_attribute_points_max"].as<int16_t>(84));
    return race;
}

uint8_t RaceTable::getRelativeSize(TYPE_OF_RACE_ID race, uint16_t size) const {
    // relative size is between 50 and 120 (in percent) and a linear interploation between min and max size
    if (!exists(race)) {
        return 100;
    }

    const auto &sizes = this->get(race);

    const auto minSize = sizes.minSize;

    const auto maxSize = sizes.maxSize;

    if (size >= minSize && size <= maxSize) {
        return uint8_t((40*(size - minSize))/(maxSize - minSize) + 80);
    } else {
        return 100;
    }
}

bool RaceTable::isBaseAttributeInLimits(TYPE_OF_RACE_ID race, Character::attributeIndex attribute, Attribute::attribute_t value) const {
    if (!exists(race)) {
        return false;
    }

    const auto &attributes = this->get(race);

    switch (attribute) {
        case Character::agility:
            return value >= attributes.minAgility && value <= attributes.maxAgility;

        case Character::constitution:
            return value >= attributes.minConstitution && value <= attributes.maxConstitution;

        case Character::dexterity:
            return value >= attributes.minDexterity && value <= attributes.maxDexterity;

        case Character::essence:
            return value >= attributes.minEssence && value <= attributes.maxEssence;

        case Character::intelligence:
            return value >= attributes.minIntelligence && value <= attributes.maxIntelligence;

        case Character::perception:
            return value >= attributes.minPerception && value <= attributes.maxPerception;

        case Character::strength:
            return value >= attributes.minStrength && value <= attributes.maxStrength;

        case Character::willpower:
            return value >= attributes.minWillpower && value <= attributes.maxWillpower;

        default: return false;
    }
}

uint8_t RaceTable::getMaxAttributePoints(TYPE_OF_RACE_ID race) const {
    if (!exists(race)) {
        return 0;
    }

    const auto &attributes = this->get(race);
    return attributes.maxAttribs;
}

<commit_msg>Insert missing character<commit_after>/*
 * Illarionserver - server for the game Illarion
 * Copyright 2011 Illarion e.V.
 *
 * This file is part of Illarionserver.
 *
 * Illarionserver  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.
 *
 * Illarionserver 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
 * Illarionserver. If not, see <http://www.gnu.org/licenses/>.
 */

#include "RaceTable.hpp"

std::string RaceTable::getTableName() {
    return "race";
}

std::vector<std::string> RaceTable::getColumnNames() {
    return {
        "race_id",
        "race_name",
        "race_height_min",
        "race_height_max",
        "race_agility_min",
        "race_agility_max",
        "race_constitution_min",
        "race_constitution_max",
        "race_dexterity_min",
        "race_dexterity_max",
        "race_essence_min",
        "race_essence_max",
        "race_intelligence_min",
        "race_intelligence_max",
        "race_perception_min",
        "race_perception_max",
        "race_strength_min",
        "race_strength_max",
        "race_willpower_min",
        "race_willpower_max",
        "race_attribute_points_max"
    };
}

TYPE_OF_ITEM_ID RaceTable::assignId(const Database::ResultTuple &row) {
    return uint16_t(row["race_id"].as<int32_t>());
}

RaceStruct RaceTable::assignTable(const Database::ResultTuple &row) {
    RaceStruct race;
    race.serverName = row["race_name"].as<std::string>("unknown");
    race.minSize = uint16_t(row["race_height_min"].as<int32_t>(100));
    race.maxSize = uint16_t(row["race_height_max"].as<int32_t>(100));
    race.minAgility = uint8_t(row["race_agility_min"].as<int32_t>(2));
    race.maxAgility = uint8_t(row["race_agility_max"].as<int32_t>(20));
    race.minConstitution = uint8_t(row["race_constitution_min"].as<int32_t>(2));
    race.maxConstitution = uint8_t(row["race_constitution_max"].as<int32_t>(20));
    race.minDexterity = uint8_t(row["race_dexterity_min"].as<int32_t>(2));
    race.maxDexterity = uint8_t(row["race_dexterity_max"].as<int32_t>(20));
    race.minEssence = uint8_t(row["race_essence_min"].as<int32_t>(2));
    race.maxEssence = uint8_t(row["race_essence_max"].as<int32_t>(20));
    race.minIntelligence = uint8_t(row["race_intelligence_min"].as<int32_t>(2));
    race.maxIntelligence = uint8_t(row["race_intelligence_max"].as<int32_t>(20));
    race.minPerception = uint8_t(row["race_perception_min"].as<int32_t>(2));
    race.maxPerception = uint8_t(row["race_perception_max"].as<int32_t>(20));
    race.minStrength = uint8_t(row["race_strength_min"].as<int32_t>(2));
    race.maxStrength = uint8_t(row["race_strength_max"].as<int32_t>(20));
    race.minWillpower = uint8_t(row["race_willpower_min"].as<int32_t>(2));
    race.maxWillpower = uint8_t(row["race_willpower_max"].as<int32_t>(20));
    race.maxAttribs = uint8_t(row["race_attribute_points_max"].as<int16_t>(84));
    return race;
}

uint8_t RaceTable::getRelativeSize(TYPE_OF_RACE_ID race, uint16_t size) const {
    // relative size is between 50 and 120 (in percent) and a linear interploation between min and max size
    if (!exists(race)) {
        return 100;
    }

    const auto &sizes = this->get(race);

    const auto minSize = sizes.minSize;

    const auto maxSize = sizes.maxSize;

    if (size >= minSize && size <= maxSize) {
        return uint8_t((40*(size - minSize))/(maxSize - minSize) + 80);
    } else {
        return 100;
    }
}

bool RaceTable::isBaseAttributeInLimits(TYPE_OF_RACE_ID race, Character::attributeIndex attribute, Attribute::attribute_t value) const {
    if (!exists(race)) {
        return false;
    }

    const auto &attributes = this->get(race);

    switch (attribute) {
        case Character::agility:
            return value >= attributes.minAgility && value <= attributes.maxAgility;

        case Character::constitution:
            return value >= attributes.minConstitution && value <= attributes.maxConstitution;

        case Character::dexterity:
            return value >= attributes.minDexterity && value <= attributes.maxDexterity;

        case Character::essence:
            return value >= attributes.minEssence && value <= attributes.maxEssence;

        case Character::intelligence:
            return value >= attributes.minIntelligence && value <= attributes.maxIntelligence;

        case Character::perception:
            return value >= attributes.minPerception && value <= attributes.maxPerception;

        case Character::strength:
            return value >= attributes.minStrength && value <= attributes.maxStrength;

        case Character::willpower:
            return value >= attributes.minWillpower && value <= attributes.maxWillpower;

        default: return false;
    }
}

uint8_t RaceTable::getMaxAttributePoints(TYPE_OF_RACE_ID race) const {
    if (!exists(race)) {
        return 0;
    }

    const auto &attributes = this->get(race);
    return attributes.maxAttribs;
}

<|endoftext|>


<commit_before>// Copyright (C) 2012, Chris J. Foster and the other authors and contributors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
// * Neither the name of the software's owners nor the names of its
//   contributors may be used to endorse or promote products derived from this
//   software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// (This is the BSD 3-clause license)

#include "mainwindow.h"
#include "ptview.h"

#include <QtGui/QApplication>
#include <QtOpenGL/QGLFormat>

#include "argparse.h"

QStringList g_pointFileNames;
static int storeFileName (int argc, const char *argv[])
{
    for(int i = 0; i < argc; ++i)
        g_pointFileNames.push_back (argv[i]);
    return 0;
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    ArgParse::ArgParse ap;
    int maxPointCount = 10000000;

    ap.options(
        "qtlasview - view a LAS point cloud\n"
        "Usage: qtlasview [opts] file1.las [file2.las ...]",
        "%*", storeFileName, "",
        "-maxpoints %d", &maxPointCount, "Maximum number of points to load at a time",
        NULL
    );

    if(ap.parse(argc, const_cast<const char**>(argv)) < 0)
    {
        std::cerr << ap.geterror() << std::endl;
        ap.usage();
        return EXIT_FAILURE;
    }

    // Turn on multisampled antialiasing - this makes rendered point clouds
    // look much nicer.
    QGLFormat f = QGLFormat::defaultFormat();
    //f.setSampleBuffers(true);
    QGLFormat::setDefaultFormat(f);

    PointViewerMainWindow window;
    window.captureStdout();
    window.pointView().setMaxPointCount(maxPointCount);
    if(!g_pointFileNames.empty())
        window.pointView().loadPointFiles(g_pointFileNames);
    window.show();

    return app.exec();
}

<commit_msg>Fix command line help<commit_after>// Copyright (C) 2012, Chris J. Foster and the other authors and contributors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
// * Neither the name of the software's owners nor the names of its
//   contributors may be used to endorse or promote products derived from this
//   software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// (This is the BSD 3-clause license)

#include "mainwindow.h"
#include "ptview.h"

#include <QtGui/QApplication>
#include <QtOpenGL/QGLFormat>

#include "argparse.h"

QStringList g_pointFileNames;
static int storeFileName (int argc, const char *argv[])
{
    for(int i = 0; i < argc; ++i)
        g_pointFileNames.push_back (argv[i]);
    return 0;
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    ArgParse::ArgParse ap;
    int maxPointCount = 10000000;

    ap.options(
        "displaz - view a LAS point cloud\n"
        "Usage: displaz [opts] file1.las [file2.las ...]",
        "%*", storeFileName, "",
        "-maxpoints %d", &maxPointCount, "Maximum number of points to load at a time",
        NULL
    );

    if(ap.parse(argc, const_cast<const char**>(argv)) < 0)
    {
        std::cerr << ap.geterror() << std::endl;
        ap.usage();
        return EXIT_FAILURE;
    }

    // Turn on multisampled antialiasing - this makes rendered point clouds
    // look much nicer.
    QGLFormat f = QGLFormat::defaultFormat();
    //f.setSampleBuffers(true);
    QGLFormat::setDefaultFormat(f);

    PointViewerMainWindow window;
    window.captureStdout();
    window.pointView().setMaxPointCount(maxPointCount);
    if(!g_pointFileNames.empty())
        window.pointView().loadPointFiles(g_pointFileNames);
    window.show();

    return app.exec();
}

<|endoftext|>


<commit_before><commit_msg>Fix for bug 1236.<commit_after><|endoftext|>


<commit_before>/*
 * Delegate helper pooling.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "Stock.hxx"
#include "stock/MapStock.hxx"
#include "stock/Class.hxx"
#include "stock/Item.hxx"
#include "async.hxx"
#include "failure.hxx"
#include "system/fd_util.h"
#include "system/sigutil.h"
#include "event/Event.hxx"
#include "event/Callback.hxx"
#include "spawn/exec.hxx"
#include "spawn/ChildOptions.hxx"
#include "gerrno.h"
#include "pool.hxx"

#include <daemon/log.h>

#include <assert.h>
#include <unistd.h>
#include <sched.h>
#include <sys/un.h>
#include <sys/socket.h>

struct DelegateArgs {
    const char *helper;

    const ChildOptions *options;

    int fds[2];
    sigset_t signals;
};

struct DelegateProcess final : HeapStockItem {
    const char *const uri;

    pid_t pid;
    int fd = -1;

    Event event;

    explicit DelegateProcess(CreateStockItem c,
                             const char *_uri)
        :HeapStockItem(c), uri(_uri) {}

    ~DelegateProcess() override {
        if (fd >= 0) {
            event.Delete();
            close(fd);
        }
    }

    void EventCallback(int fd, short event);

    /* virtual methods from class StockItem */
    bool Borrow(gcc_unused void *ctx) override {
        event.Delete();
        return true;
    }

    bool Release(gcc_unused void *ctx) override {
        static constexpr struct timeval tv = {
            .tv_sec = 60,
            .tv_usec = 0,
        };

        event.Add(tv);
        return true;
    }
};

/*
 * libevent callback
 *
 */

inline void
DelegateProcess::EventCallback(gcc_unused int _fd, short events)
{
    assert(_fd == fd);

    if ((events & EV_TIMEOUT) == 0) {
        assert((events & EV_READ) != 0);

        char buffer;
        ssize_t nbytes = recv(fd, &buffer, sizeof(buffer), MSG_DONTWAIT);
        if (nbytes < 0)
            daemon_log(2, "error on idle delegate process: %s\n",
                       strerror(errno));
        else if (nbytes > 0)
            daemon_log(2, "unexpected data from idle delegate process\n");
    }

    InvokeIdleDisconnect();
    pool_commit();
}

/*
 * clone() function
 *
 */

static int
delegate_stock_fn(void *ctx)
{
    auto *info = (DelegateArgs *)ctx;

    install_default_signal_handlers();
    leave_signal_section(&info->signals);

    info->options->Apply(true);

    dup2(info->fds[1], STDIN_FILENO);
    close(info->fds[0]);
    close(info->fds[1]);

    Exec e;
    info->options->jail.InsertWrapper(e, nullptr);
    e.Append(info->helper);
    e.DoExec();
}

/*
 * stock class
 *
 */

static void
delegate_stock_create(gcc_unused void *ctx,
                      gcc_unused struct pool &parent_pool, CreateStockItem c,
                      const char *uri, void *_info,
                      gcc_unused struct pool &caller_pool,
                      gcc_unused struct async_operation_ref &async_ref)
{
    auto *const info = (DelegateArgs *)_info;
    const auto *const options = info->options;

    if (socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, info->fds) < 0) {
        GError *error = new_error_errno_msg("socketpair() failed: %s");
        c.InvokeCreateError(error);
        return;
    }

    int clone_flags = SIGCHLD;
    clone_flags = options->ns.GetCloneFlags(clone_flags);

    /* avoid race condition due to libevent signal handler in child
       process */
    enter_signal_section(&info->signals);

    char stack[8192];
    long pid = clone(delegate_stock_fn, stack + sizeof(stack),
                     clone_flags, info);
    if (pid < 0) {
        GError *error = new_error_errno_msg("clone() failed");
        leave_signal_section(&info->signals);
        close(info->fds[0]);
        close(info->fds[1]);
        c.InvokeCreateError(error);
        return;
    }

    leave_signal_section(&info->signals);

    close(info->fds[1]);

    auto *process = new DelegateProcess(c, uri);

    process->pid = pid;
    process->fd = info->fds[0];

    process->event.Set(process->fd, EV_READ|EV_TIMEOUT,
                       MakeEventCallback(DelegateProcess, EventCallback),
                       process);

    process->InvokeCreateSuccess();
}

static constexpr StockClass delegate_stock_class = {
    .create = delegate_stock_create,
};

/*
 * interface
 *
 */

StockMap *
delegate_stock_new(struct pool *pool)
{
    return hstock_new(*pool, delegate_stock_class, nullptr, 0, 16);
}

void
delegate_stock_get(StockMap *delegate_stock, struct pool *pool,
                   const char *helper,
                   const ChildOptions &options,
                   StockGetHandler &handler,
                   struct async_operation_ref &async_ref)
{
    const char *uri = helper;

    char options_buffer[4096];
    *options.MakeId(options_buffer) = 0;
    if (*options_buffer != 0)
        uri = p_strcat(pool, helper, "|", options_buffer, nullptr);

    auto info = NewFromPool<DelegateArgs>(*pool);
    info->helper = helper;
    info->options = &options;

    hstock_get(*delegate_stock, *pool, uri, info, handler, async_ref);
}

void
delegate_stock_put(StockMap *delegate_stock,
                   StockItem &item, bool destroy)
{
    auto *process = (DelegateProcess *)&item;

    hstock_put(*delegate_stock, process->uri, item, destroy);
}

int
delegate_stock_item_get(StockItem &item)
{
    auto *process = (DelegateProcess *)&item;

    return process->fd;
}
<commit_msg>delegate/Stock: move code to constructor<commit_after>/*
 * Delegate helper pooling.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "Stock.hxx"
#include "stock/MapStock.hxx"
#include "stock/Class.hxx"
#include "stock/Item.hxx"
#include "async.hxx"
#include "failure.hxx"
#include "system/fd_util.h"
#include "system/sigutil.h"
#include "event/Event.hxx"
#include "event/Callback.hxx"
#include "spawn/exec.hxx"
#include "spawn/ChildOptions.hxx"
#include "gerrno.h"
#include "pool.hxx"

#include <daemon/log.h>

#include <assert.h>
#include <unistd.h>
#include <sched.h>
#include <sys/un.h>
#include <sys/socket.h>

struct DelegateArgs {
    const char *helper;

    const ChildOptions *options;

    int fds[2];
    sigset_t signals;
};

struct DelegateProcess final : HeapStockItem {
    const char *const uri;

    const pid_t pid;
    const int fd;

    Event event;

    explicit DelegateProcess(CreateStockItem c,
                             const char *_uri,
                             pid_t _pid, int _fd)
        :HeapStockItem(c), uri(_uri), pid(_pid), fd(_fd) {
        event.Set(fd, EV_READ|EV_TIMEOUT,
                  MakeEventCallback(DelegateProcess, EventCallback), this);
    }

    ~DelegateProcess() override {
        if (fd >= 0) {
            event.Delete();
            close(fd);
        }
    }

    void EventCallback(int fd, short event);

    /* virtual methods from class StockItem */
    bool Borrow(gcc_unused void *ctx) override {
        event.Delete();
        return true;
    }

    bool Release(gcc_unused void *ctx) override {
        static constexpr struct timeval tv = {
            .tv_sec = 60,
            .tv_usec = 0,
        };

        event.Add(tv);
        return true;
    }
};

/*
 * libevent callback
 *
 */

inline void
DelegateProcess::EventCallback(gcc_unused int _fd, short events)
{
    assert(_fd == fd);

    if ((events & EV_TIMEOUT) == 0) {
        assert((events & EV_READ) != 0);

        char buffer;
        ssize_t nbytes = recv(fd, &buffer, sizeof(buffer), MSG_DONTWAIT);
        if (nbytes < 0)
            daemon_log(2, "error on idle delegate process: %s\n",
                       strerror(errno));
        else if (nbytes > 0)
            daemon_log(2, "unexpected data from idle delegate process\n");
    }

    InvokeIdleDisconnect();
    pool_commit();
}

/*
 * clone() function
 *
 */

static int
delegate_stock_fn(void *ctx)
{
    auto *info = (DelegateArgs *)ctx;

    install_default_signal_handlers();
    leave_signal_section(&info->signals);

    info->options->Apply(true);

    dup2(info->fds[1], STDIN_FILENO);
    close(info->fds[0]);
    close(info->fds[1]);

    Exec e;
    info->options->jail.InsertWrapper(e, nullptr);
    e.Append(info->helper);
    e.DoExec();
}

/*
 * stock class
 *
 */

static void
delegate_stock_create(gcc_unused void *ctx,
                      gcc_unused struct pool &parent_pool, CreateStockItem c,
                      const char *uri, void *_info,
                      gcc_unused struct pool &caller_pool,
                      gcc_unused struct async_operation_ref &async_ref)
{
    auto *const info = (DelegateArgs *)_info;
    const auto *const options = info->options;

    if (socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, info->fds) < 0) {
        GError *error = new_error_errno_msg("socketpair() failed: %s");
        c.InvokeCreateError(error);
        return;
    }

    int clone_flags = SIGCHLD;
    clone_flags = options->ns.GetCloneFlags(clone_flags);

    /* avoid race condition due to libevent signal handler in child
       process */
    enter_signal_section(&info->signals);

    char stack[8192];
    long pid = clone(delegate_stock_fn, stack + sizeof(stack),
                     clone_flags, info);
    if (pid < 0) {
        GError *error = new_error_errno_msg("clone() failed");
        leave_signal_section(&info->signals);
        close(info->fds[0]);
        close(info->fds[1]);
        c.InvokeCreateError(error);
        return;
    }

    leave_signal_section(&info->signals);

    close(info->fds[1]);

    auto *process = new DelegateProcess(c, uri, pid, info->fds[0]);
    process->InvokeCreateSuccess();
}

static constexpr StockClass delegate_stock_class = {
    .create = delegate_stock_create,
};

/*
 * interface
 *
 */

StockMap *
delegate_stock_new(struct pool *pool)
{
    return hstock_new(*pool, delegate_stock_class, nullptr, 0, 16);
}

void
delegate_stock_get(StockMap *delegate_stock, struct pool *pool,
                   const char *helper,
                   const ChildOptions &options,
                   StockGetHandler &handler,
                   struct async_operation_ref &async_ref)
{
    const char *uri = helper;

    char options_buffer[4096];
    *options.MakeId(options_buffer) = 0;
    if (*options_buffer != 0)
        uri = p_strcat(pool, helper, "|", options_buffer, nullptr);

    auto info = NewFromPool<DelegateArgs>(*pool);
    info->helper = helper;
    info->options = &options;

    hstock_get(*delegate_stock, *pool, uri, info, handler, async_ref);
}

void
delegate_stock_put(StockMap *delegate_stock,
                   StockItem &item, bool destroy)
{
    auto *process = (DelegateProcess *)&item;

    hstock_put(*delegate_stock, process->uri, item, destroy);
}

int
delegate_stock_item_get(StockItem &item)
{
    auto *process = (DelegateProcess *)&item;

    return process->fd;
}
<|endoftext|>


<commit_before>//
// Created by votick on 10/05/16.
//

#include "main.h"
int main() {
    std::cout << "hi";
    return 0;
}
<commit_msg>Added support for walls, in which prevent agents from passing through them.<commit_after><|endoftext|>


<commit_before>#include "FlowJunction.h"
#include "Factory.h"
#include "Conversion.h"
#include "Simulation.h"
#include "FEProblem.h"
#include "GeometricalComponent.h"
#include "FluidProperties.h"
#include <sstream>

template <>
InputParameters
validParams<FlowJunction>()
{
  InputParameters params = validParams<Junction>();
  params.addParam<std::vector<Real>>("K", "Form loss coefficients");
  params.addParam<Real>(
      "scaling_factor", 1., "Scaling factor for the Lagrange multiplier variable");
  std::vector<Real> sf4(4, 1.);
  sf4[0] = 1.e+3;
  sf4[1] = 1.e+0;
  sf4[2] = 1.e+6;
  sf4[3] = 1.;
  params.addParam<std::vector<Real>>("scaling_factor_bcs", sf4, "Scaling factors for the BCs");
  params.addRequiredParam<UserObjectName>("fp", "The name of fluid properties user object to use.");
  return params;
}

FlowJunction::FlowJunction(const InputParameters & params)
  : Junction(params),
    _lm_name(genName(name(), "lm")),
    _K(getParam<std::vector<Real>>("K")),
    _scaling_factor(getParam<Real>("scaling_factor")),
    _scaling_factor_bcs(getParam<std::vector<Real>>("scaling_factor_bcs"))
{
}

void
FlowJunction::check()
{
  if (_model_type == FlowModel::EQ_MODEL_7)
    logError("Cannot be used with 7-equation model: not implemented yet.");
}

void
FlowJunction::addVariables()
{
  std::vector<unsigned int> connected_subdomains;
  this->getConnectedSubdomains(connected_subdomains);

  // add scalar variable (i.e. Lagrange multiplier)
  _sim.addVariable(true, _lm_name, FEType(THIRD, SCALAR), connected_subdomains, _scaling_factor);
}

void
FlowJunction::addMooseObjects()
{
  std::vector<VariableName> cv_area(1, FlowModel::AREA);
  std::vector<VariableName> cv_vel(1, FlowModel::VELOCITY);
  std::vector<VariableName> cv_pressure(1, FlowModel::PRESSURE);
  std::vector<VariableName> cv_enthalpy(1, FlowModel::SPECIFIC_TOTAL_ENTHALPY);
  std::vector<VariableName> cv_rhoA(1, FlowModel::RHOA);
  std::vector<VariableName> cv_rhouA(1, FlowModel::RHOUA);
  std::vector<VariableName> cv_rhoEA(1, FlowModel::RHOEA);
  std::vector<VariableName> cv_v(1, FlowModel::SPECIFIC_VOLUME);
  std::vector<VariableName> cv_e(1, FlowModel::SPECIFIC_INTERNAL_ENERGY);
  std::vector<VariableName> cv_lambda(1, _lm_name);

  MultiMooseEnum execute_options(SetupInterface::getExecuteOptions());
  execute_options = "linear";

  std::string c_pps = genName(name(), "flow_pps");
  {
    InputParameters params = _factory.getValidParams("PressureCB");
    params.set<std::vector<unsigned int>>("r7:boundary") = _bnd_id;
    params.set<MultiMooseEnum>("execute_on") = execute_options;
    params.set<std::string>("r7:output") = "none";
    // coupling
    params.set<std::vector<VariableName>>("area") = cv_area;

    _sim.addPostprocessor("PressureCB", c_pps, params);
  }

  // add BC terms
  for (unsigned int i = 0; i < _bnd_id.size(); ++i)
  {
    std::vector<unsigned int> bnd_id(1, _bnd_id[i]);

    // mass
    {
      InputParameters params = _factory.getValidParams("OneDFreeMassBC");
      params.set<NonlinearVariableName>("variable") = FlowModel::RHOA;
      params.set<std::vector<unsigned int>>("r7:boundary") = bnd_id;
      params.set<PostprocessorName>("c") = c_pps;
      params.set<std::vector<Real>>("scaling_factors") = _scaling_factor_bcs;
      // coupling
      params.set<std::vector<VariableName>>("rhoA") = cv_rhoA;
      params.set<std::vector<VariableName>>("rhouA") = cv_rhouA;
      params.set<std::vector<VariableName>>("vel") = cv_vel;
      params.set<std::vector<VariableName>>("area") = cv_area;
      params.set<std::vector<VariableName>>("lambda") = cv_lambda;
      params.set<std::vector<VariableName>>("H") = cv_enthalpy;
      params.set<MaterialPropertyName>("p") = FlowModel::PRESSURE;

      _sim.addBoundaryCondition("OneDFreeMassBC", genName(name(), _bnd_id[i], "mass_bc"), params);
    }
    // momentum
    {
      InputParameters params = _factory.getValidParams("OneDFreeMomentumBC");
      params.set<NonlinearVariableName>("variable") = FlowModel::RHOUA;
      params.set<std::vector<unsigned int>>("r7:boundary") = bnd_id;
      params.set<PostprocessorName>("c") = c_pps;
      params.set<std::vector<Real>>("scaling_factors") = _scaling_factor_bcs;
      // coupling
      params.set<std::vector<VariableName>>("rhoA") = cv_rhoA;
      params.set<std::vector<VariableName>>("rhouA") = cv_rhouA;
      params.set<std::vector<VariableName>>("vel") = cv_vel;
      params.set<std::vector<VariableName>>("area") = cv_area;
      params.set<std::vector<VariableName>>("lambda") = cv_lambda;
      params.set<std::vector<VariableName>>("rhoEA") = cv_rhoEA;
      params.set<std::vector<VariableName>>("H") = cv_enthalpy;
      params.set<MaterialPropertyName>("p") = FlowModel::PRESSURE;

      _sim.addBoundaryCondition(
          "OneDFreeMomentumBC", genName(name(), _bnd_id[i], "mom_bc"), params);
    }
    // energy
    {
      InputParameters params = _factory.getValidParams("OneDFreeEnergyBC");
      params.set<NonlinearVariableName>("variable") = FlowModel::RHOEA;
      params.set<std::vector<unsigned int>>("r7:boundary") = bnd_id;
      // coupling
      params.set<std::vector<VariableName>>("rhoA") = cv_rhoA;
      params.set<std::vector<VariableName>>("rhouA") = cv_rhouA;
      params.set<std::vector<VariableName>>("rhoEA") = cv_rhoEA;
      params.set<std::vector<VariableName>>("vel") = cv_vel;
      params.set<std::vector<VariableName>>("H") = cv_enthalpy;
      params.set<std::vector<VariableName>>("area") = cv_area;
      params.set<MaterialPropertyName>("p") = FlowModel::PRESSURE;
      params.set<PostprocessorName>("c") = c_pps;
      params.set<std::vector<Real>>("scaling_factors") = _scaling_factor_bcs;
      params.set<std::vector<VariableName>>("lambda") = cv_lambda;

      _sim.addBoundaryCondition("OneDFreeEnergyBC", genName(name(), _bnd_id[i], "erg_bc"), params);
    }
  }

  // add the constraints
  {
    InputParameters params = _factory.getValidParams("FlowConstraint");
    params.set<NonlinearVariableName>("variable") = _lm_name;

    params.set<FlowModel::EModelType>("model_type") = _model_type;
    params.set<std::vector<dof_id_type>>("nodes") = _nodes;
    params.set<std::vector<Real>>("normals") = _normals;
    params.set<std::vector<Real>>("K") = _K;
    params.set<UserObjectName>("fp") = getParam<UserObjectName>("fp");
    // coupling
    params.set<std::vector<VariableName>>("rhoA") = cv_rhoA;
    params.set<std::vector<VariableName>>("rhouA") = cv_rhouA;
    params.set<std::vector<VariableName>>("e") = cv_e;
    params.set<std::vector<VariableName>>("v") = cv_v;
    params.set<std::vector<VariableName>>("vel") = cv_vel;
    params.set<std::vector<VariableName>>("p") = cv_pressure;
    params.set<std::vector<VariableName>>("area") = cv_area;
    params.set<std::vector<VariableName>>("rhoEA") = cv_rhoEA;
    params.set<std::vector<VariableName>>("H") = cv_enthalpy;

    _sim.addScalarKernel("FlowConstraint", genName(name(), "flow_c0"), params);
  }
}
<commit_msg>Applied naming conventions to area<commit_after>#include "FlowJunction.h"
#include "Factory.h"
#include "Conversion.h"
#include "Simulation.h"
#include "FEProblem.h"
#include "GeometricalComponent.h"
#include "FluidProperties.h"
#include <sstream>

template <>
InputParameters
validParams<FlowJunction>()
{
  InputParameters params = validParams<Junction>();
  params.addParam<std::vector<Real>>("K", "Form loss coefficients");
  params.addParam<Real>(
      "scaling_factor", 1., "Scaling factor for the Lagrange multiplier variable");
  std::vector<Real> sf4(4, 1.);
  sf4[0] = 1.e+3;
  sf4[1] = 1.e+0;
  sf4[2] = 1.e+6;
  sf4[3] = 1.;
  params.addParam<std::vector<Real>>("scaling_factor_bcs", sf4, "Scaling factors for the BCs");
  params.addRequiredParam<UserObjectName>("fp", "The name of fluid properties user object to use.");
  return params;
}

FlowJunction::FlowJunction(const InputParameters & params)
  : Junction(params),
    _lm_name(genName(name(), "lm")),
    _K(getParam<std::vector<Real>>("K")),
    _scaling_factor(getParam<Real>("scaling_factor")),
    _scaling_factor_bcs(getParam<std::vector<Real>>("scaling_factor_bcs"))
{
}

void
FlowJunction::check()
{
  if (_model_type == FlowModel::EQ_MODEL_7)
    logError("Cannot be used with 7-equation model: not implemented yet.");
}

void
FlowJunction::addVariables()
{
  std::vector<unsigned int> connected_subdomains;
  this->getConnectedSubdomains(connected_subdomains);

  // add scalar variable (i.e. Lagrange multiplier)
  _sim.addVariable(true, _lm_name, FEType(THIRD, SCALAR), connected_subdomains, _scaling_factor);
}

void
FlowJunction::addMooseObjects()
{
  std::vector<VariableName> cv_area(1, FlowModel::AREA);
  std::vector<VariableName> cv_vel(1, FlowModel::VELOCITY);
  std::vector<VariableName> cv_pressure(1, FlowModel::PRESSURE);
  std::vector<VariableName> cv_enthalpy(1, FlowModel::SPECIFIC_TOTAL_ENTHALPY);
  std::vector<VariableName> cv_rhoA(1, FlowModel::RHOA);
  std::vector<VariableName> cv_rhouA(1, FlowModel::RHOUA);
  std::vector<VariableName> cv_rhoEA(1, FlowModel::RHOEA);
  std::vector<VariableName> cv_v(1, FlowModel::SPECIFIC_VOLUME);
  std::vector<VariableName> cv_e(1, FlowModel::SPECIFIC_INTERNAL_ENERGY);
  std::vector<VariableName> cv_lambda(1, _lm_name);

  MultiMooseEnum execute_options(SetupInterface::getExecuteOptions());
  execute_options = "linear";

  std::string c_pps = genName(name(), "flow_pps");
  {
    InputParameters params = _factory.getValidParams("PressureCB");
    params.set<std::vector<unsigned int>>("r7:boundary") = _bnd_id;
    params.set<MultiMooseEnum>("execute_on") = execute_options;
    params.set<std::string>("r7:output") = "none";
    // coupling
    params.set<std::vector<VariableName>>("A") = cv_area;

    _sim.addPostprocessor("PressureCB", c_pps, params);
  }

  // add BC terms
  for (unsigned int i = 0; i < _bnd_id.size(); ++i)
  {
    std::vector<unsigned int> bnd_id(1, _bnd_id[i]);

    // mass
    {
      InputParameters params = _factory.getValidParams("OneDFreeMassBC");
      params.set<NonlinearVariableName>("variable") = FlowModel::RHOA;
      params.set<std::vector<unsigned int>>("r7:boundary") = bnd_id;
      params.set<PostprocessorName>("c") = c_pps;
      params.set<std::vector<Real>>("scaling_factors") = _scaling_factor_bcs;
      // coupling
      params.set<std::vector<VariableName>>("rhoA") = cv_rhoA;
      params.set<std::vector<VariableName>>("rhouA") = cv_rhouA;
      params.set<std::vector<VariableName>>("vel") = cv_vel;
      params.set<std::vector<VariableName>>("A") = cv_area;
      params.set<std::vector<VariableName>>("lambda") = cv_lambda;
      params.set<std::vector<VariableName>>("H") = cv_enthalpy;
      params.set<MaterialPropertyName>("p") = FlowModel::PRESSURE;

      _sim.addBoundaryCondition("OneDFreeMassBC", genName(name(), _bnd_id[i], "mass_bc"), params);
    }
    // momentum
    {
      InputParameters params = _factory.getValidParams("OneDFreeMomentumBC");
      params.set<NonlinearVariableName>("variable") = FlowModel::RHOUA;
      params.set<std::vector<unsigned int>>("r7:boundary") = bnd_id;
      params.set<PostprocessorName>("c") = c_pps;
      params.set<std::vector<Real>>("scaling_factors") = _scaling_factor_bcs;
      // coupling
      params.set<std::vector<VariableName>>("rhoA") = cv_rhoA;
      params.set<std::vector<VariableName>>("rhouA") = cv_rhouA;
      params.set<std::vector<VariableName>>("vel") = cv_vel;
      params.set<std::vector<VariableName>>("A") = cv_area;
      params.set<std::vector<VariableName>>("lambda") = cv_lambda;
      params.set<std::vector<VariableName>>("rhoEA") = cv_rhoEA;
      params.set<std::vector<VariableName>>("H") = cv_enthalpy;
      params.set<MaterialPropertyName>("p") = FlowModel::PRESSURE;

      _sim.addBoundaryCondition(
          "OneDFreeMomentumBC", genName(name(), _bnd_id[i], "mom_bc"), params);
    }
    // energy
    {
      InputParameters params = _factory.getValidParams("OneDFreeEnergyBC");
      params.set<NonlinearVariableName>("variable") = FlowModel::RHOEA;
      params.set<std::vector<unsigned int>>("r7:boundary") = bnd_id;
      // coupling
      params.set<std::vector<VariableName>>("rhoA") = cv_rhoA;
      params.set<std::vector<VariableName>>("rhouA") = cv_rhouA;
      params.set<std::vector<VariableName>>("rhoEA") = cv_rhoEA;
      params.set<std::vector<VariableName>>("vel") = cv_vel;
      params.set<std::vector<VariableName>>("H") = cv_enthalpy;
      params.set<std::vector<VariableName>>("A") = cv_area;
      params.set<MaterialPropertyName>("p") = FlowModel::PRESSURE;
      params.set<PostprocessorName>("c") = c_pps;
      params.set<std::vector<Real>>("scaling_factors") = _scaling_factor_bcs;
      params.set<std::vector<VariableName>>("lambda") = cv_lambda;

      _sim.addBoundaryCondition("OneDFreeEnergyBC", genName(name(), _bnd_id[i], "erg_bc"), params);
    }
  }

  // add the constraints
  {
    InputParameters params = _factory.getValidParams("FlowConstraint");
    params.set<NonlinearVariableName>("variable") = _lm_name;

    params.set<FlowModel::EModelType>("model_type") = _model_type;
    params.set<std::vector<dof_id_type>>("nodes") = _nodes;
    params.set<std::vector<Real>>("normals") = _normals;
    params.set<std::vector<Real>>("K") = _K;
    params.set<UserObjectName>("fp") = getParam<UserObjectName>("fp");
    // coupling
    params.set<std::vector<VariableName>>("rhoA") = cv_rhoA;
    params.set<std::vector<VariableName>>("rhouA") = cv_rhouA;
    params.set<std::vector<VariableName>>("e") = cv_e;
    params.set<std::vector<VariableName>>("v") = cv_v;
    params.set<std::vector<VariableName>>("vel") = cv_vel;
    params.set<std::vector<VariableName>>("p") = cv_pressure;
    params.set<std::vector<VariableName>>("A") = cv_area;
    params.set<std::vector<VariableName>>("rhoEA") = cv_rhoEA;
    params.set<std::vector<VariableName>>("H") = cv_enthalpy;

    _sim.addScalarKernel("FlowConstraint", genName(name(), "flow_c0"), params);
  }
}
<|endoftext|>


<commit_before>dbefffb0-2747-11e6-811a-e0f84713e7b8<commit_msg>Backup, rebase this later<commit_after>dc00db82-2747-11e6-b676-e0f84713e7b8<|endoftext|>


<commit_before>/* -*- C++ -*- */

/**
 * @file AtomSet.cpp
 * @author Roman Schindlauer
 * @date Tue Feb  7 17:19:18 CET 2006
 *
 * @brief AtomSet class.
 *
 *
 */

#include <vector>
#include <algorithm>

#include "dlvhex/AtomSet.h"
#include "dlvhex/AtomFactory.h"

void
multiplySets(std::vector<AtomSet>& s1,
             std::vector<AtomSet>& s2,
             std::vector<AtomSet>& result)
{
    //
    // write result into temporary vector. in case the result parameter
    // is one of the two input vectors
    //
    std::vector<AtomSet> tmpset;

    AtomSet un;

    for (std::vector<AtomSet>::iterator i1 = s1.begin();
            i1 != s1.end();
            ++i1)
    {
        for (std::vector<AtomSet>::iterator i2 = s2.begin();
                i2 != s2.end();
                ++i2)
        {
            un = *i1;
            un.insert(*i2);
            //std::cout << "inserted: " << un << std::endl;

            tmpset.push_back(un);
        }
    }

    //
    // now we can write the result
    //
    swap(result, tmpset);
}

AtomSet::const_iterator
AtomSet::begin() const
{
    return const_iterator(atoms.begin());
}

AtomSet::const_iterator
AtomSet::end() const
{
    return const_iterator(atoms.end());
}

/*
void
AtomSet::initialize(const GAtomSet& in)
{
    for (GAtomSet::const_iterator i = in.begin();
         i != in.end();
         ++i)
    {
        insert(*i);
    }
}
*/

void
AtomSet::clear()
{
    atoms.clear();
}

bool
AtomSet::empty() const
{
    return atoms.empty();
}

size_t
AtomSet::size() const
{
    return atoms.size();
}

/*
void
AtomSet::insert(Atom* a)
{
    insert(*a);
}
*/

void
AtomSet::insert(AtomPtr& ap)
{
    /// @todo test if *ap really exists

    //
    // inserting the AtomPtr in the factory ensures that
//    AtomFactory::Instance()->insert(ap);

    atoms.insert(ap);
}

/*
void
AtomSet::insert(Atom& a)
{
    atoms.insert(&a);
}
*/

/*
void
AtomSet::insert(Atom a)
{
    AtomFactory::AtomPtr pa = AtomFactory::Instance()->insert(a);

    atoms.insert(pa);
}
*/

void
AtomSet::insert(const AtomSet& add)
{
    atoms.insert(add.atoms.begin(), add.atoms.end());
}

void
AtomSet::matchPredicate(const std::string pred,
                        AtomSet& matched) const
{
    /// @todo: stdlib algorithm!
    for (atomset_t::const_iterator a = atoms.begin();
         a != atoms.end();
         a++)
    {
        if ((*a)->getPredicate() == pred)
            matched.atoms.insert(*a);
    }
}

void
AtomSet::print(std::ostream& stream, const bool ho) const
{
    stream << "{";

    for (atomset_t::const_iterator a = atoms.begin();
         a != atoms.end();
         a++)
    {
        if (a != atoms.begin())
            stream << ", ";

        (*a)->print(stream, ho);
    }

    stream << "}";
}

struct predicateMatches : public std::binary_function<AtomPtr, Term, bool>
{
    bool operator()(const AtomPtr g, const Term& pred) const
    {
        return (g->getPredicate() == pred);
    }
};

void
AtomSet::remove(const std::string& pred)
{
    atomset_t::iterator cur = atoms.begin();

    atomset_t::const_iterator last = atoms.end();

    while ((cur = std::find_if(cur, last, bind2nd(predicateMatches(), pred))) != last)
    {
        atomset_t::iterator tmp = cur++;

        atoms.erase(tmp);
    }
}

void
AtomSet::keep(const std::vector<std::string>& preds)
{
    atomset_t::iterator cur = atoms.begin();

    atomset_t::const_iterator last = atoms.end();

    //
    // go through all atoms of this set
    //
    while (cur != last)
    {
        //
        // look if the current atom is in the filter set
        //
        if ((std::find_if(preds.begin(),
                          preds.end(),
                          bind1st(predicateMatches(), *cur))) == preds.end())
        {
            //
            // if not, delete this atom
            //
            atomset_t::iterator tmp = cur++;

            atoms.erase(tmp);
        }
        else
        {
            cur++;
        }
    }
}

struct AtomSetEqual : public std::binary_function<const AtomPtr&, const Atom&, bool>
{
    bool operator()(const AtomPtr& a, const Atom& b) const
    {
        return *a == b;
    }
};

bool
AtomSet::operator== (const AtomSet& atomset2) const
{
  return std::equal(atoms.begin(), atoms.end(),
		    atomset2.begin(), AtomSetEqual());
}

bool
AtomSet::operator!= (const AtomSet& atomset2) const
{
    return !(atoms == atomset2.atoms);
}
<commit_msg>another bugfix from thomas<commit_after>/* -*- C++ -*- */

/**
 * @file AtomSet.cpp
 * @author Roman Schindlauer
 * @date Tue Feb  7 17:19:18 CET 2006
 *
 * @brief AtomSet class.
 *
 *
 */

#include <vector>
#include <algorithm>

#include "dlvhex/AtomSet.h"
#include "dlvhex/AtomFactory.h"

void
multiplySets(std::vector<AtomSet>& s1,
             std::vector<AtomSet>& s2,
             std::vector<AtomSet>& result)
{
    //
    // write result into temporary vector. in case the result parameter
    // is one of the two input vectors
    //
    std::vector<AtomSet> tmpset;

    AtomSet un;

    for (std::vector<AtomSet>::iterator i1 = s1.begin();
            i1 != s1.end();
            ++i1)
    {
        for (std::vector<AtomSet>::iterator i2 = s2.begin();
                i2 != s2.end();
                ++i2)
        {
            un = *i1;
            un.insert(*i2);
            //std::cout << "inserted: " << un << std::endl;

            tmpset.push_back(un);
        }
    }

    //
    // now we can write the result
    //
    swap(result, tmpset);
}

AtomSet::const_iterator
AtomSet::begin() const
{
    return const_iterator(atoms.begin());
}

AtomSet::const_iterator
AtomSet::end() const
{
    return const_iterator(atoms.end());
}

/*
void
AtomSet::initialize(const GAtomSet& in)
{
    for (GAtomSet::const_iterator i = in.begin();
         i != in.end();
         ++i)
    {
        insert(*i);
    }
}
*/

void
AtomSet::clear()
{
    atoms.clear();
}

bool
AtomSet::empty() const
{
    return atoms.empty();
}

size_t
AtomSet::size() const
{
    return atoms.size();
}

/*
void
AtomSet::insert(Atom* a)
{
    insert(*a);
}
*/

void
AtomSet::insert(AtomPtr& ap)
{
    /// @todo test if *ap really exists

    //
    // inserting the AtomPtr in the factory ensures that
//    AtomFactory::Instance()->insert(ap);

    atoms.insert(ap);
}

/*
void
AtomSet::insert(Atom& a)
{
    atoms.insert(&a);
}
*/

/*
void
AtomSet::insert(Atom a)
{
    AtomFactory::AtomPtr pa = AtomFactory::Instance()->insert(a);

    atoms.insert(pa);
}
*/

void
AtomSet::insert(const AtomSet& add)
{
    atoms.insert(add.atoms.begin(), add.atoms.end());
}

void
AtomSet::matchPredicate(const std::string pred,
                        AtomSet& matched) const
{
    /// @todo: stdlib algorithm!
    for (atomset_t::const_iterator a = atoms.begin();
         a != atoms.end();
         a++)
    {
        if ((*a)->getPredicate() == pred)
            matched.atoms.insert(*a);
    }
}

void
AtomSet::print(std::ostream& stream, const bool ho) const
{
    stream << "{";

    for (atomset_t::const_iterator a = atoms.begin();
         a != atoms.end();
         a++)
    {
        if (a != atoms.begin())
            stream << ", ";

        (*a)->print(stream, ho);
    }

    stream << "}";
}

struct predicateMatches : public std::binary_function<AtomPtr, Term, bool>
{
    bool operator()(const AtomPtr g, const Term& pred) const
    {
        return (g->getPredicate() == pred);
    }
};

void
AtomSet::remove(const std::string& pred)
{
    atomset_t::iterator cur = atoms.begin();

    atomset_t::const_iterator last = atoms.end();

    while ((cur = std::find_if(cur, last, bind2nd(predicateMatches(), pred))) != last)
    {
        atomset_t::iterator tmp = cur++;

        atoms.erase(tmp);
    }
}

void
AtomSet::keep(const std::vector<std::string>& preds)
{
    atomset_t::iterator cur = atoms.begin();

    atomset_t::const_iterator last = atoms.end();

    //
    // go through all atoms of this set
    //
    while (cur != last)
    {
        //
        // look if the current atom is in the filter set
        //
        if ((std::find_if(preds.begin(),
                          preds.end(),
                          bind1st(predicateMatches(), *cur))) == preds.end())
        {
            //
            // if not, delete this atom
            //
            atomset_t::iterator tmp = cur++;

            atoms.erase(tmp);
        }
        else
        {
            cur++;
        }
    }
}

bool
AtomSet::operator== (const AtomSet& atomset2) const
{
    return this->size() == atomset2.size()
      && std::equal(this->begin(), this->end(), atomset2.begin());
}

bool
AtomSet::operator!= (const AtomSet& atomset2) const
{
    return !(*this == atomset2);
}
<|endoftext|>


<commit_before>
#include <signal.h>
#include <iomanip>
#include <boost/program_options.hpp>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "SDL/SDL.h"

#include "config.hpp"
#include "display.hpp"
#include "camera-opencv.hpp"
#include "camera-mmal.hpp"
#include "input.hpp"

namespace po = boost::program_options;
namespace pt = boost::posix_time;
using namespace std;

//bool lapser_verbose = false;
#ifdef ARM_BUILD
static string camera_type = "mmal";
#else
static string camera_type = "opencv";
#endif
static string fb_device = "/dev/fb1";
static string config_filename = "config.json";
static string fourcc = "XVID";

static boost::recursive_mutex capture_mutex;
static cv::Mat shared_frame;
static bool shared_frame_updated;
static pt::ptime goal;
static pt::ptime last_shot;
static cv::VideoWriter *video_writer;
static ICamera *camera;

boost::posix_time::time_facet *facet;

static void signal_handler(int signum)
{
    if(signum != SIGUSR1)
    {
        //cout << "Exiting due to signal." << endl;
        cout << "Got signal" << endl;
        SDL_Quit();
        if(camera)
        {
            cout << "Deleting camera" << endl;
            delete camera;
        }
        if(video_writer)
        {
            cout << "Deleting video writer" << endl;
            delete video_writer;
        }
        exit(0);
    }
}

static int parse_arguments(int argc, char *argv[])
{
    bool args_valid = true;

    po::options_description visible_options("Usage: lapser \n\nOptions are: ");
    visible_options.add_options()
        ("help", "Print this message.")
        //("verbose,v", "Print more information." )
        ("camera-type,c", po::value < string >(&camera_type), "Camera Type [ mmal, opencv ]")
        ("framebuffer-device,f", po::value < string >(&fb_device))
        ("config", po::value < string >(&config_filename), "Config file [ config.json ]")
        ("fourcc", po::value < string > (&fourcc), "Output file FOURCC code [ XVID ]")
        ;

    try
    {
        po::variables_map vm;
        po::store(po::command_line_parser(argc, argv).options(visible_options).run(), vm);
        po::notify(vm);

        if(vm.count("help"))
        {
            cerr << visible_options << endl;
            return 1;
        }

        /*if(vm.count("verbose"))
        {
            lapser_verbose = true;
            }*/

#ifdef ARM_BUILD
        if(camera_type != "mmal" && camera_type != "opencv")
        {
            cout << "Invalid camera type: " << camera_type << endl;
            args_valid = false;
        }
#else
        if(camera_type != "opencv")
        {
            cout << "Invalid camera type: " << camera_type << endl;
            args_valid = false;
        }
#endif

        if(fourcc.size() != 4)
        {
            cout << "Invalid FOURCC code (must be 4 characters)" << endl;
            args_valid = false;
        }

#ifdef ARM_BUILD
        if(fb_device != "/dev/fb0")
        {
            setenv("SDL_FBDEV", fb_device.c_str(), 1);
        }
        setenv("SDL_MOUSEDRV", "TSLIB", 1);
        setenv("SDL_MOUSEDEV", "/dev/input/touchscreen", 1);
#endif
        //setenv("SDL_NOMOUSE", "1", 1);
    }
    catch(const exception &e)
    {
        cerr << "Error " << e.what() << endl;
        args_valid = false;
    }

    if(!args_valid)
    {
        cout << endl << visible_options << endl;
        return 2;
    }

    return 0;
}

static void capture_thread(Config &config, Display &display)
{
    try
    {
        const int interval = config.get_interval();
        //cout << "interval: " << interval << endl;

        cv::Mat frame(config.get_capture_height(), config.get_capture_width(), CV_8UC3);
        if(camera_type == "opencv")
        {
            camera = new CameraOCV(config.get_capture_name());
        }
#ifdef ARM_BUILD
        else if(camera_type == "mmal")
        {
            camera = new CameraMMAL(config.get_capture_name(), config.get_light_enable());
        }
#endif

        if(!camera)
        {
            cout << "Couldn't create camera of type: " << camera_type << " (was it compiled in?)" << endl;
            SDL_Quit();
            exit(-1);
        }

        pt::ptime last = pt::microsec_clock::local_time();
        goal = last;
        last_shot = last;

        while(1)
        {
            const pt::ptime current = pt::microsec_clock::local_time();

            if(current >= goal)
            {
                cout << "Taking picture!" << endl;

                if(!camera->read_frame(frame))
                {
                    //cout << "Capture ended" << endl;
                    break;
                }
                const pt::ptime post_pic = pt::microsec_clock::local_time();
                cout << "Picture took: " << post_pic - current << endl;

                if(current - goal < pt::microseconds(50000))
                {
                    // more precise if we only update based on goal
                    goal = goal + pt::microseconds(interval * 1000);
                }
                else
                {
                    cout << "Resetting goal..." << endl;
                    goal = current + pt::microseconds(interval * 1000);
                }

                cv::Size desired(config.get_output_width(), config.get_output_height());
                if(!video_writer)
                {
                    //cout << "Creating new VideoWriter" << endl;
                    video_writer = new cv::VideoWriter(config.get_output_name(), CV_FOURCC(fourcc[0], fourcc[1], fourcc[2], fourcc[3]), 30,
                                                       desired);
                }

                if(desired != frame.size())
                {
                    cv::Mat vid_frame;
                    cv::resize(frame, vid_frame, desired);
                    *video_writer << vid_frame;
                }
                else
                    *video_writer << frame;

                {
                    boost::recursive_mutex::scoped_lock lock(capture_mutex);
                    if(frame.type() != shared_frame.type() || frame.size() != shared_frame.size())
                    {
                        shared_frame = cv::Mat(frame.rows, frame.cols, frame.type());
                    }
                    frame.copyTo(shared_frame);
                    shared_frame_updated = true;
                }

                last_shot = current;
            }

            boost::this_thread::sleep(pt::microseconds(33333));
            last = current;
        }

        delete camera;
    }
    catch(const exception &e)
    {
        cout << "Capture thread got exception: " << e.what() << endl;
        SDL_Quit();
        exit(-1);
    }
}

int main(int argc, char *argv[])
{
    facet = new boost::posix_time::time_facet("%Y-%b-%d %k:%M:%S");
    cout.imbue(locale(cout.getloc(), facet));

    if(parse_arguments(argc, argv) != 0)
    {
        return -1;
    }

    signal(SIGINT, signal_handler);

    bool enabled = true;
    try
    {
        Config config(config_filename);

        Display display(config);
        Input input(display);

        //r.x = 200;
        //r.y = 200;
        //input.add_region(Action::DELETE_LAST, r);

        cv::Mat frame(config.get_capture_height(), config.get_capture_width(), CV_8UC3);
        boost::thread cap_thread(&capture_thread, config, display);
        bool running = true;
        while(running)
        {
            const pt::ptime current = pt::microsec_clock::local_time();

            if(shared_frame_updated)
            {
                boost::recursive_mutex::scoped_lock lock(capture_mutex);
                if(frame.type() != shared_frame.type() || frame.size() != shared_frame.size())
                {
                    frame = cv::Mat(shared_frame.rows, shared_frame.cols, shared_frame.type());
                }
                shared_frame.copyTo(frame);
                shared_frame_updated = false;
            }
            display.put_frame(frame);

            SDL_Rect r;
            r.x = 200;
            r.y = 0;
            r.w = 120;
            r.h = 40;
            if(enabled)
            {
                input.add_region(Action::DISABLE, r);

                ostringstream oss;
                oss << "Next shot in: ";
                const pt::time_duration remaining = goal - current;
                oss << remaining.seconds() << "." << remaining.fractional_seconds() / (int)pow(10, remaining.num_fractional_digits() - 1);
                display.put_string(oss.str(), 0, -1);
            }
            else
            {
                input.add_region(Action::ENABLE, r);

                display.put_string("Time lapse disabled", 0, -1);
            }

            // display current time
            ostringstream oss;
            oss.imbue(locale(cout.getloc(), facet));
            oss << last_shot << "." << last_shot.time_of_day().fractional_seconds() / (int)pow(10, last_shot.time_of_day().num_fractional_digits() - 1);
            display.put_string(oss.str());

            Action::Action a = input.process();
            switch(a)
            {
            case Action::QUIT:
                running = false;
                break;
            case Action::ENABLE:
                cout << "Got enable" << endl;
                enabled = true;
                input.remove_region(Action::ENABLE);
                break;
            case Action::DISABLE:
                cout << "Got disable" << endl;
                enabled = false;
                input.remove_region(Action::DISABLE);
                break;
            case Action::DELETE_LAST:
                cout << "Got delete" << endl;
                break;
            case Action::CONTINUE:
                break;
            }

            input.draw_regions();
            if(!display.draw())
                running = false;

            boost::this_thread::sleep(pt::microseconds(33333));
        }
    }
    catch(const exception &e)
    {
        cerr << "Exception: " << e.what() << endl;
        SDL_Quit();
        exit(-1);
    }

    SDL_Quit();

    return 0;
}
<commit_msg>Also stop capture thread when disabled<commit_after>
#include <signal.h>
#include <iomanip>
#include <boost/program_options.hpp>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "SDL/SDL.h"

#include "config.hpp"
#include "display.hpp"
#include "camera-opencv.hpp"
#include "camera-mmal.hpp"
#include "input.hpp"

namespace po = boost::program_options;
namespace pt = boost::posix_time;
using namespace std;

//bool lapser_verbose = false;
#ifdef ARM_BUILD
static string camera_type = "mmal";
#else
static string camera_type = "opencv";
#endif
static string fb_device = "/dev/fb1";
static string config_filename = "config.json";
static string fourcc = "XVID";

static boost::recursive_mutex capture_mutex;
static cv::Mat shared_frame;
static bool shared_frame_updated;
static pt::ptime goal;
static pt::ptime last_shot;
static cv::VideoWriter *video_writer;
static ICamera *camera;
static bool capture_enabled = true;

boost::posix_time::time_facet *facet;

static void signal_handler(int signum)
{
    if(signum != SIGUSR1)
    {
        //cout << "Exiting due to signal." << endl;
        cout << "Got signal" << endl;
        SDL_Quit();
        if(camera)
        {
            cout << "Deleting camera" << endl;
            delete camera;
        }
        if(video_writer)
        {
            cout << "Deleting video writer" << endl;
            delete video_writer;
        }
        exit(0);
    }
}

static int parse_arguments(int argc, char *argv[])
{
    bool args_valid = true;

    po::options_description visible_options("Usage: lapser \n\nOptions are: ");
    visible_options.add_options()
        ("help", "Print this message.")
        //("verbose,v", "Print more information." )
        ("camera-type,c", po::value < string >(&camera_type), "Camera Type [ mmal, opencv ]")
        ("framebuffer-device,f", po::value < string >(&fb_device))
        ("config", po::value < string >(&config_filename), "Config file [ config.json ]")
        ("fourcc", po::value < string > (&fourcc), "Output file FOURCC code [ XVID ]")
        ;

    try
    {
        po::variables_map vm;
        po::store(po::command_line_parser(argc, argv).options(visible_options).run(), vm);
        po::notify(vm);

        if(vm.count("help"))
        {
            cerr << visible_options << endl;
            return 1;
        }

        /*if(vm.count("verbose"))
        {
            lapser_verbose = true;
            }*/

#ifdef ARM_BUILD
        if(camera_type != "mmal" && camera_type != "opencv")
        {
            cout << "Invalid camera type: " << camera_type << endl;
            args_valid = false;
        }
#else
        if(camera_type != "opencv")
        {
            cout << "Invalid camera type: " << camera_type << endl;
            args_valid = false;
        }
#endif

        if(fourcc.size() != 4)
        {
            cout << "Invalid FOURCC code (must be 4 characters)" << endl;
            args_valid = false;
        }

#ifdef ARM_BUILD
        if(fb_device != "/dev/fb0")
        {
            setenv("SDL_FBDEV", fb_device.c_str(), 1);
        }
        setenv("SDL_MOUSEDRV", "TSLIB", 1);
        setenv("SDL_MOUSEDEV", "/dev/input/touchscreen", 1);
#endif
        //setenv("SDL_NOMOUSE", "1", 1);
    }
    catch(const exception &e)
    {
        cerr << "Error " << e.what() << endl;
        args_valid = false;
    }

    if(!args_valid)
    {
        cout << endl << visible_options << endl;
        return 2;
    }

    return 0;
}

static void capture_thread(Config &config, Display &display)
{
    try
    {
        const int interval = config.get_interval();
        //cout << "interval: " << interval << endl;

        cv::Mat frame(config.get_capture_height(), config.get_capture_width(), CV_8UC3);
        if(camera_type == "opencv")
        {
            camera = new CameraOCV(config.get_capture_name());
        }
#ifdef ARM_BUILD
        else if(camera_type == "mmal")
        {
            camera = new CameraMMAL(config.get_capture_name(), config.get_light_enable());
        }
#endif

        if(!camera)
        {
            cout << "Couldn't create camera of type: " << camera_type << " (was it compiled in?)" << endl;
            SDL_Quit();
            exit(-1);
        }

        pt::ptime last = pt::microsec_clock::local_time();
        goal = last;
        last_shot = last;

        while(1)
        {
            const pt::ptime current = pt::microsec_clock::local_time();

            if(current >= goal && capture_enabled)
            {
                cout << "Taking picture!" << endl;

                if(!camera->read_frame(frame))
                {
                    //cout << "Capture ended" << endl;
                    break;
                }
                const pt::ptime post_pic = pt::microsec_clock::local_time();
                cout << "Picture took: " << post_pic - current << endl;

                if(current - goal < pt::microseconds(50000))
                {
                    // more precise if we only update based on goal
                    goal = goal + pt::microseconds(interval * 1000);
                }
                else
                {
                    cout << "Resetting goal..." << endl;
                    goal = current + pt::microseconds(interval * 1000);
                }

                cv::Size desired(config.get_output_width(), config.get_output_height());
                if(!video_writer)
                {
                    //cout << "Creating new VideoWriter" << endl;
                    video_writer = new cv::VideoWriter(config.get_output_name(), CV_FOURCC(fourcc[0], fourcc[1], fourcc[2], fourcc[3]), 30,
                                                       desired);
                }

                if(desired != frame.size())
                {
                    cv::Mat vid_frame;
                    cv::resize(frame, vid_frame, desired);
                    *video_writer << vid_frame;
                }
                else
                    *video_writer << frame;

                {
                    boost::recursive_mutex::scoped_lock lock(capture_mutex);
                    if(frame.type() != shared_frame.type() || frame.size() != shared_frame.size())
                    {
                        shared_frame = cv::Mat(frame.rows, frame.cols, frame.type());
                    }
                    frame.copyTo(shared_frame);
                    shared_frame_updated = true;
                }

                last_shot = current;
            }

            boost::this_thread::sleep(pt::microseconds(33333));
            last = current;
        }

        delete camera;
    }
    catch(const exception &e)
    {
        cout << "Capture thread got exception: " << e.what() << endl;
        SDL_Quit();
        exit(-1);
    }
}

int main(int argc, char *argv[])
{
    facet = new boost::posix_time::time_facet("%Y-%b-%d %k:%M:%S");
    cout.imbue(locale(cout.getloc(), facet));

    if(parse_arguments(argc, argv) != 0)
    {
        return -1;
    }

    signal(SIGINT, signal_handler);

    try
    {
        Config config(config_filename);

        Display display(config);
        Input input(display);

        //r.x = 200;
        //r.y = 200;
        //input.add_region(Action::DELETE_LAST, r);

        cv::Mat frame(config.get_capture_height(), config.get_capture_width(), CV_8UC3);
        boost::thread cap_thread(&capture_thread, config, display);
        bool running = true;
        while(running)
        {
            const pt::ptime current = pt::microsec_clock::local_time();

            if(shared_frame_updated)
            {
                boost::recursive_mutex::scoped_lock lock(capture_mutex);
                if(frame.type() != shared_frame.type() || frame.size() != shared_frame.size())
                {
                    frame = cv::Mat(shared_frame.rows, shared_frame.cols, shared_frame.type());
                }
                shared_frame.copyTo(frame);
                shared_frame_updated = false;
            }
            display.put_frame(frame);

            SDL_Rect r;
            r.x = 200;
            r.y = 0;
            r.w = 120;
            r.h = 40;
            if(capture_enabled)
            {
                input.add_region(Action::DISABLE, r);

                ostringstream oss;
                oss << "Next shot in: ";
                const pt::time_duration remaining = goal - current;
                oss << remaining.seconds() << "." << remaining.fractional_seconds() / (int)pow(10, remaining.num_fractional_digits() - 1);
                display.put_string(oss.str(), 0, -1);
            }
            else
            {
                input.add_region(Action::ENABLE, r);

                display.put_string("Time lapse disabled", 0, -1);
            }

            // display current time
            ostringstream oss;
            oss.imbue(locale(cout.getloc(), facet));
            oss << last_shot << "." << last_shot.time_of_day().fractional_seconds() / (int)pow(10, last_shot.time_of_day().num_fractional_digits() - 1);
            display.put_string(oss.str());

            Action::Action a = input.process();
            switch(a)
            {
            case Action::QUIT:
                running = false;
                break;
            case Action::ENABLE:
                cout << "Got enable" << endl;
                capture_enabled = true;
                input.remove_region(Action::ENABLE);
                break;
            case Action::DISABLE:
                cout << "Got disable" << endl;
                capture_enabled = false;
                input.remove_region(Action::DISABLE);
                break;
            case Action::DELETE_LAST:
                cout << "Got delete" << endl;
                break;
            case Action::CONTINUE:
                break;
            }

            input.draw_regions();
            if(!display.draw())
                running = false;

            boost::this_thread::sleep(pt::microseconds(33333));
        }
    }
    catch(const exception &e)
    {
        cerr << "Exception: " << e.what() << endl;
        SDL_Quit();
        exit(-1);
    }

    SDL_Quit();

    return 0;
}
<|endoftext|>