<commit_before>#include <iostream>
#include <sstream>
#include <iterator>
#include <stdexcept>

#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/BriefTestProgressListener.h>

#include "pandora/File.hpp"
#include "pandora/Block.hpp"
#include "pandora/Section.hpp"
#include "pandora/Source.hpp"
#include "pandora/SourceIterator.hpp"
#include "pandora/SourceTreeIterator.hpp"

using namespace std;
using namespace pandora;

class TestSource:public CPPUNIT_NS::TestFixture {
private:

  CPPUNIT_TEST_SUITE(TestSource);

  CPPUNIT_TEST(testCreateAndRemove);
  CPPUNIT_TEST(testIterators);
  CPPUNIT_TEST(testFindSources);

  CPPUNIT_TEST_SUITE_END ();

  File *f1;
public:

  void setUp() {
    f1 = new File("test_block.h5", FileMode::ReadWrite);
  }

  void tearDown() {
    delete f1;
  }

  void testCreateAndRemove() {
    Block b1 = f1->createBlock("test block","test");
    Source s1 = b1.createSource("S1","test");
    Source s2 = b1.createSource("S2","test");

    stringstream msg;
    msg << "Creating s1 or s2 failed!" ;
    CPPUNIT_ASSERT_MESSAGE(msg.str(), b1.hasSource(s1.id()) && b1.hasSource(s2.id()) );

    size_t count = b1.sourceCount();
    stringstream errmsg;
    errmsg << "Source count does not match! Found " << count << " should have been 2";
    CPPUNIT_ASSERT_MESSAGE(errmsg.str(), count == 2);

    b1.removeSource(s1.id());
    stringstream msg2;
    msg2 << "Removing s1 failed!" ;
    CPPUNIT_ASSERT_MESSAGE(msg2.str(), !b1.hasSource(s1.id()));
    b1.removeSource(s2.id());
    f1->removeBlock(b1.id());
  }

  void testIterators(){
    Block b1 = f1->createBlock("test block","test");
    Source s1 = b1.createSource("S1","test");
    s1.createSource("S3","test");
    s1.createSource("S4","test");
    Source s2 = b1.createSource("S2","test");
    s2.createSource("S5","test");

    size_t count = s1.sourceCount();
    CPPUNIT_ASSERT_EQUAL(count,(size_t)2);
    count = s2.sourceCount();
    CPPUNIT_ASSERT_EQUAL(count,(size_t)1);

    b1.removeSource(s1.id());
    b1.removeSource(s2.id());
    f1->removeBlock(b1.id());

  }

  void testFindSources(){
    Block b1 = f1->createBlock("test block","test");
    Source s1 = b1.createSource("S1","test");
    Source s2 = b1.createSource("S2","test");
    Source s3 = s1.createSource("S3","test");
    Source s4 = s1.createSource("S4","test");
    Source s5 = s2.createSource("S5","test");

    vector<Source> res = s1.findSources([&](const Source &source) {
      bool found = source.id() == s4.id();
      return found;
    });

    CPPUNIT_ASSERT_EQUAL(static_cast<vector<Source>::size_type>(1), res.size());
    CPPUNIT_ASSERT_EQUAL(s4.id(), res[0].id());

//    CPPUNIT_ASSERT_EQUAL(b1.hasSource("invalid_id"),false);
//    CPPUNIT_ASSERT_EQUAL(b1.hasSource(s3.id()),true);
//    CPPUNIT_ASSERT_EQUAL(b1.existsSource(s3.id(),"test"),true);
//    CPPUNIT_ASSERT_EQUAL(b1.existsSource(s3.id(),"no test"),false);
//    CPPUNIT_ASSERT_EQUAL(b1.existsSource(s3.id(),"test",1),false);
//    CPPUNIT_ASSERT_EQUAL(b1.existsSource(s3.id(),"test",2),true);

    b1.removeSource(s1.id());
    b1.removeSource(s2.id());
    f1->removeBlock(b1.id());
  }

};

<commit_msg>[test] TestSource: add some more checks for findSources<commit_after>#include <iostream>
#include <sstream>
#include <iterator>
#include <stdexcept>

#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/BriefTestProgressListener.h>

#include "pandora/File.hpp"
#include "pandora/Block.hpp"
#include "pandora/Section.hpp"
#include "pandora/Source.hpp"
#include "pandora/SourceIterator.hpp"
#include "pandora/SourceTreeIterator.hpp"

using namespace std;
using namespace pandora;

class TestSource:public CPPUNIT_NS::TestFixture {
private:

  CPPUNIT_TEST_SUITE(TestSource);

  CPPUNIT_TEST(testCreateAndRemove);
  CPPUNIT_TEST(testIterators);
  CPPUNIT_TEST(testFindSources);

  CPPUNIT_TEST_SUITE_END ();

  File *f1;
public:

  void setUp() {
    f1 = new File("test_block.h5", FileMode::ReadWrite);
  }

  void tearDown() {
    delete f1;
  }

  void testCreateAndRemove() {
    Block b1 = f1->createBlock("test block","test");
    Source s1 = b1.createSource("S1","test");
    Source s2 = b1.createSource("S2","test");

    stringstream msg;
    msg << "Creating s1 or s2 failed!" ;
    CPPUNIT_ASSERT_MESSAGE(msg.str(), b1.hasSource(s1.id()) && b1.hasSource(s2.id()) );

    size_t count = b1.sourceCount();
    stringstream errmsg;
    errmsg << "Source count does not match! Found " << count << " should have been 2";
    CPPUNIT_ASSERT_MESSAGE(errmsg.str(), count == 2);

    b1.removeSource(s1.id());
    stringstream msg2;
    msg2 << "Removing s1 failed!" ;
    CPPUNIT_ASSERT_MESSAGE(msg2.str(), !b1.hasSource(s1.id()));
    b1.removeSource(s2.id());
    f1->removeBlock(b1.id());
  }

  void testIterators(){
    Block b1 = f1->createBlock("test block","test");
    Source s1 = b1.createSource("S1","test");
    s1.createSource("S3","test");
    s1.createSource("S4","test");
    Source s2 = b1.createSource("S2","test");
    s2.createSource("S5","test");

    size_t count = s1.sourceCount();
    CPPUNIT_ASSERT_EQUAL(count,(size_t)2);
    count = s2.sourceCount();
    CPPUNIT_ASSERT_EQUAL(count,(size_t)1);

    b1.removeSource(s1.id());
    b1.removeSource(s2.id());
    f1->removeBlock(b1.id());

  }

  void testFindSources(){
    Block b1 = f1->createBlock("test block","test");
    Source s1 = b1.createSource("S1","test");
    Source s2 = b1.createSource("S2","test");
    Source s3 = s1.createSource("S3","test");
    Source s4 = s1.createSource("S4","test");
    Source s5 = s2.createSource("S5","test");

    //sanity check
    vector<Source> res = s1.findSources([&](const Source &source) {
      return false;
    });

    CPPUNIT_ASSERT_EQUAL(static_cast<vector<Source>::size_type>(0), res.size());

    //now some actual work
    res = s1.findSources([&](const Source &source) {
      bool found = source.id() == s4.id();
      return found;
    });

    CPPUNIT_ASSERT_EQUAL(static_cast<vector<Source>::size_type>(1), res.size());
    CPPUNIT_ASSERT_EQUAL(s4.id(), res[0].id());

    res = s1.findSources([&](const Source &source) {
      return true;
    }, true, 1);

    CPPUNIT_ASSERT_EQUAL(res.size(), s1.sourceCount());
    vector<Source> children = s1.sources();

    for (int i = 0; i < res.size(); i++) {
      CPPUNIT_ASSERT_EQUAL(res[i].id(), children[i].id());
    }

//    CPPUNIT_ASSERT_EQUAL(b1.hasSource("invalid_id"),false);
//    CPPUNIT_ASSERT_EQUAL(b1.hasSource(s3.id()),true);
//    CPPUNIT_ASSERT_EQUAL(b1.existsSource(s3.id(),"test"),true);
//    CPPUNIT_ASSERT_EQUAL(b1.existsSource(s3.id(),"no test"),false);
//    CPPUNIT_ASSERT_EQUAL(b1.existsSource(s3.id(),"test",1),false);
//    CPPUNIT_ASSERT_EQUAL(b1.existsSource(s3.id(),"test",2),true);

    b1.removeSource(s1.id());
    b1.removeSource(s2.id());
    f1->removeBlock(b1.id());
  }

};

<|endoftext|>


<commit_before><commit_msg>More tests<commit_after><|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "variant.hpp"
#include "StringPool.hpp"
#include "VisitorUtils.hpp"

#include "ast/StringChecker.hpp"
#include "ast/SourceFile.hpp"
#include "ast/ASTVisitor.hpp"

using namespace eddic;

class StringCheckerVisitor : public boost::static_visitor<> {
    private:
        StringPool& pool;

    public:
        StringCheckerVisitor(StringPool& p) : pool(p) {}

        AUTO_RECURSE_PROGRAM()
        AUTO_RECURSE_STRUCT()
        AUTO_RECURSE_CONSTRUCTOR()
        AUTO_RECURSE_DESTRUCTOR()
        AUTO_RECURSE_FUNCTION_DECLARATION()
        AUTO_RECURSE_GLOBAL_DECLARATION()
        AUTO_RECURSE_FUNCTION_CALLS()
        AUTO_RECURSE_BUILTIN_OPERATORS()
        AUTO_RECURSE_SIMPLE_LOOPS()
        AUTO_RECURSE_FOREACH()
        AUTO_RECURSE_BRANCHES()
        AUTO_RECURSE_BINARY_CONDITION()
        AUTO_RECURSE_COMPOSED_VALUES()
        AUTO_RECURSE_RETURN_VALUES()
        AUTO_RECURSE_ARRAY_VALUES()
        AUTO_RECURSE_VARIABLE_OPERATIONS()
        AUTO_RECURSE_TERNARY()
        AUTO_RECURSE_SWITCH()
        AUTO_RECURSE_SWITCH_CASE()
        AUTO_RECURSE_DEFAULT_CASE()
        AUTO_RECURSE_NEW()

        void operator()(ast::Litteral& litteral){
            litteral.label = pool.label(litteral.value);
        }

        AUTO_IGNORE_OTHERS()
};

void ast::checkStrings(ast::SourceFile& program, StringPool& pool){
   StringCheckerVisitor visitor(pool);
   visitor(program);
}
<commit_msg>Fix recursion<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "variant.hpp"
#include "StringPool.hpp"
#include "VisitorUtils.hpp"

#include "ast/StringChecker.hpp"
#include "ast/SourceFile.hpp"
#include "ast/ASTVisitor.hpp"

using namespace eddic;

class StringCheckerVisitor : public boost::static_visitor<> {
    private:
        StringPool& pool;

    public:
        StringCheckerVisitor(StringPool& p) : pool(p) {}

        AUTO_RECURSE_PROGRAM()
        AUTO_RECURSE_STRUCT()
        AUTO_RECURSE_CONSTRUCTOR()
        AUTO_RECURSE_DESTRUCTOR()
        AUTO_RECURSE_FUNCTION_DECLARATION()
        AUTO_RECURSE_GLOBAL_DECLARATION()
        AUTO_RECURSE_FUNCTION_CALLS()
        AUTO_RECURSE_BUILTIN_OPERATORS()
        AUTO_RECURSE_SIMPLE_LOOPS()
        AUTO_RECURSE_FOREACH()
        AUTO_RECURSE_BRANCHES()
        AUTO_RECURSE_BINARY_CONDITION()
        AUTO_RECURSE_COMPOSED_VALUES()
        AUTO_RECURSE_RETURN_VALUES()
        AUTO_RECURSE_ARRAY_VALUES()
        AUTO_RECURSE_VARIABLE_OPERATIONS()
        AUTO_RECURSE_STRUCT_DECLARATION()
        AUTO_RECURSE_TERNARY()
        AUTO_RECURSE_SWITCH()
        AUTO_RECURSE_SWITCH_CASE()
        AUTO_RECURSE_DEFAULT_CASE()
        AUTO_RECURSE_NEW()

        void operator()(ast::Litteral& litteral){
            litteral.label = pool.label(litteral.value);
        }

        AUTO_IGNORE_OTHERS()
};

void ast::checkStrings(ast::SourceFile& program, StringPool& pool){
   StringCheckerVisitor visitor(pool);
   visitor(program);
}
<|endoftext|>


<commit_before><commit_msg>Disable test-explorer.cpp<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sysdata.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2007-11-02 12:43:30 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SV_SYSDATA_HXX
#define _SV_SYSDATA_HXX

#if defined( QUARTZ )
#include <premac.h>
#include <Carbon/Carbon.h>
#include <postmac.h>
#endif

// -----------------
// - SystemEnvData -
// -----------------

struct SystemEnvData
{
    unsigned long       nSize;          // size in bytes of this structure
#if defined( WNT ) || defined( OS2 )
    HWND                hWnd;           // the window hwnd
#elif defined( QUARTZ )
    WindowRef           rWindow;        // Window reference
#endif

#if defined( UNX )
    void*               pDisplay;       // the relevant display connection
    long                aWindow;        // the window of the object
    void*               pSalFrame;      // contains a salframe, if object has one
    void*               pWidget;        // the corresponding widget
    void*               pVisual;        // the visual in use
    int                 nDepth;         // depth of said visual
    long                aColormap;      // the colormap being used
    void*               pAppContext;    // the application context in use
    long                aShellWindow;   // the window of the frame's shell
    void*               pShellWidget;   // the frame's shell widget
#endif
};

#define SystemChildData SystemEnvData

// --------------------
// - SystemParentData -
// --------------------

struct SystemParentData
{
    unsigned long   nSize;            // size in bytes of this structure
#if defined( WNT ) || defined( OS2 )
    HWND            hWnd;             // the window hwnd
#elif defined( QUARTZ )
    WindowRef       rWindow;        // Window reference
#elif defined( UNX )
    long            aWindow;          // the window of the object
    bool            bXEmbedSupport:1; // decides whether the object in question
                                      // should support the XEmbed protocol
#endif
};

// --------------------
// - SystemMenuData -
// --------------------

struct SystemMenuData
{
    unsigned long   nSize;          // size in bytes of this structure
#if defined( WNT )
    HMENU           hMenu;          // the menu handle of the menu bar
#elif defined( UNX )
    long            aMenu;          // ???
#endif
};

// --------------------
// - SystemGraphicsData -
// --------------------

struct SystemGraphicsData
{
    unsigned long   nSize;          // size in bytes of this structure
#if defined( WNT )
    HDC             hDC;            // handle to a device context
#elif defined( QUARTZ )
    CGContextRef            rCGContext;     // QUARTZ graphic context
#elif defined( UNX )
    long            hDrawable;      // a drawable
    void*           pRenderFormat;  // render format for drawable
#endif
};

// --------------------
// - SystemWindowData -
// --------------------

struct SystemWindowData
{
    unsigned long   nSize;          // size in bytes of this structure
#if defined( WNT )                  // meaningless on Windows
#elif defined( QUARTZ )             // meaningless on Mac OS X / Quartz
#elif defined( UNX )
    void*           pVisual;        // the visual to be used
#endif
};

#endif // _SV_SYSDATA_HXX
<commit_msg>INTEGRATION: CWS macosxquicktime01 (1.4.52); FILE MERGED 2007/10/15 11:11:26 pl 1.4.52.1: #i82621# initial implementation of SalObject for MacOSX aqua<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sysdata.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: vg $ $Date: 2007-12-07 11:50:12 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SV_SYSDATA_HXX
#define _SV_SYSDATA_HXX

// -----------------
// - SystemEnvData -
// -----------------

struct SystemEnvData
{
    unsigned long       nSize;          // size in bytes of this structure
#if defined( WNT ) || defined( OS2 )
    HWND                hWnd;           // the window hwnd
#elif defined( QUARTZ )
    NSView*             pView;          // the cocoa view ptr implementing this object
#endif

#if defined( UNX )
    void*               pDisplay;       // the relevant display connection
    long                aWindow;        // the window of the object
    void*               pSalFrame;      // contains a salframe, if object has one
    void*               pWidget;        // the corresponding widget
    void*               pVisual;        // the visual in use
    int                 nDepth;         // depth of said visual
    long                aColormap;      // the colormap being used
    void*               pAppContext;    // the application context in use
    long                aShellWindow;   // the window of the frame's shell
    void*               pShellWidget;   // the frame's shell widget
#endif
};

#define SystemChildData SystemEnvData

// --------------------
// - SystemParentData -
// --------------------

struct SystemParentData
{
    unsigned long   nSize;            // size in bytes of this structure
#if defined( WNT ) || defined( OS2 )
    HWND            hWnd;             // the window hwnd
#elif defined( QUARTZ )
    NSView*         pView;            // the cocoa view ptr implementing this object
#elif defined( UNX )
    long            aWindow;          // the window of the object
    bool            bXEmbedSupport:1; // decides whether the object in question
                                      // should support the XEmbed protocol
#endif
};

// --------------------
// - SystemMenuData -
// --------------------

struct SystemMenuData
{
    unsigned long   nSize;          // size in bytes of this structure
#if defined( WNT )
    HMENU           hMenu;          // the menu handle of the menu bar
#elif defined( UNX )
    long            aMenu;          // ???
#endif
};

// --------------------
// - SystemGraphicsData -
// --------------------

struct SystemGraphicsData
{
    unsigned long   nSize;          // size in bytes of this structure
#if defined( WNT )
    HDC             hDC;            // handle to a device context
#elif defined( QUARTZ )
    CGContextRef            rCGContext;     // QUARTZ graphic context
#elif defined( UNX )
    long            hDrawable;      // a drawable
    void*           pRenderFormat;  // render format for drawable
#endif
};

// --------------------
// - SystemWindowData -
// --------------------

struct SystemWindowData
{
    unsigned long   nSize;          // size in bytes of this structure
#if defined( WNT )                  // meaningless on Windows
#elif defined( QUARTZ )             // meaningless on Mac OS X / Quartz
#elif defined( UNX )
    void*           pVisual;        // the visual to be used
#endif
};

#endif // _SV_SYSDATA_HXX
<|endoftext|>


<commit_before>#include "acmacs-base/virus-name.hh"
#include "acmacs-base/range.hh"
#include "acmacs-draw/surface-cairo.hh"
#include "acmacs-draw/geographic-map.hh"
#include "geographic-map.hh"

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

void GeographicMapPoints::draw(Surface& aSurface) const
{
    for (const auto& point: *this) {
        point.draw(aSurface);
    }

} // GeographicMapPoints::draw

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

GeographicMapDraw::~GeographicMapDraw()
{
} // GeographicMapDraw::~GeographicMapDraw

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

void GeographicMapDraw::prepare(Surface&)
{
} // GeographicMapDraw::prepare

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

void GeographicMapDraw::draw(Surface& aOutlineSurface, Surface& aPointSurface) const
{
    geographic_map_draw(aOutlineSurface, mOutline, mOutlineWidth);
    mPoints.draw(aPointSurface);
    mTitle.draw(aOutlineSurface);

} // GeographicMapDraw::draw

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

void GeographicMapDraw::draw(std::string aFilename, double aImageWidth)
{
    const acmacs::Size size = geographic_map_size();
    PdfCairo outline_surface(aFilename, aImageWidth, aImageWidth / size.width * size.height, size.width);
    auto& point_surface = outline_surface.subsurface(outline_surface.viewport().origin, Scaled{outline_surface.viewport().size.width}, geographic_map_viewport(), false);
    prepare(point_surface);
    draw(outline_surface, point_surface);

} // GeographicMapDraw::draw

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

void GeographicMapDraw::add_point(long aPriority, double aLat, double aLong, Color aFill, Pixels aSize, Color aOutline, Pixels aOutlineWidth)
{
    mPoints.emplace_back(LongLat{aLong, -aLat}, aPriority);
    auto& style = mPoints.back();
    style.shape = acmacs::PointShape::Circle;
    style.fill = aFill;
    style.outline = aOutline;
    style.outline_width = aOutlineWidth;
    style.size = aSize;

} // GeographicMapDraw::add_point

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

GeographicMapColoring::~GeographicMapColoring()
{
}

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

ColorOverride::TagColor ColoringByClade::color(const hidb::Antigen& aAntigen) const
{
    ColoringData result("grey50");
    std::string tag{"UNKNOWN"};
    try {
        const auto* entry_seq = seqdb::get(report_time::Yes).find_hi_name(aAntigen.full_name());
        if (entry_seq) {
            for (const auto& clade: entry_seq->seq().clades()) {
                try {
                    result = mColors.at(clade); // find first clade that has corresponding entry in mColors and use it
                    tag = clade;
                    break;
                }
                catch (...) {
                }
            }
        }
    }
    catch (std::exception& err) {
        std::cerr << "ERROR: ColoringByClade " << aAntigen.full_name() << ": " << err.what() << '\n';
    }
    catch (...) {
    }
      // std::cerr << "INFO: ColoringByClade " << aAntigen.full_name() << ": " << tag << '\n';
    return {tag, result};

} // ColoringByClade::color

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

void GeographicMapWithPointsFromHidb::prepare(Surface& aSurface)
{
    GeographicMapDraw::prepare(aSurface);

    const double point_scaled = aSurface.convert(mPointSize).value();
    for (const auto& location_color: mPointsAtLocation) {
        try {
            const auto location = get_locdb().find(location_color.first);
            const double center_lat = location.latitude(), center_long = location.longitude();
            auto iter = location_color.second.iterator();
            auto [coloring_data, priority] = *iter;
            add_point(priority, center_lat, center_long, coloring_data.fill, mPointSize, coloring_data.outline, coloring_data.outline_width);
            ++iter;
            for (size_t circle_no = 1; iter; ++circle_no) {
                const double distance = point_scaled * mDensity * circle_no;
                const size_t circle_capacity = static_cast<size_t>(M_PI * 2.0 * distance * circle_no / (point_scaled * mDensity));
                const size_t points_on_circle = std::min(circle_capacity, iter.left());
                const double step = 2.0 * M_PI / points_on_circle;
                for (auto index: acmacs::incrementer(0UL, points_on_circle)) {
                    std::tie(coloring_data, priority) = *iter;
                    add_point(priority, center_lat + distance * std::cos(index * step), center_long + distance * std::sin(index * step), coloring_data.fill, mPointSize, coloring_data.outline, coloring_data.outline_width);
                    ++iter;
                }
            }
        }
        catch (LocationNotFound&) {
        }
    }

    sort_points();

} // GeographicMapWithPointsFromHidb::prepare

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

void GeographicMapWithPointsFromHidb::add_points_from_hidb_colored_by(const GeographicMapColoring& aColoring, const ColorOverride& aColorOverride, const std::vector<std::string>& aPriority, std::string aStartDate, std::string aEndDate)
{
      // std::cerr << "add_points_from_hidb_colored_by" << '\n';
    const auto& hidb = hidb::get(mVirusType);
    auto antigens = hidb.antigens()->date_range(aStartDate, aEndDate);
    std::cerr << "INFO: dates: " << aStartDate << ".." << aEndDate << "  antigens: " << antigens.size() << std::endl;
    if (!aPriority.empty())
        std::cerr << "INFO: priority: " << aPriority << " (the last in this list to be drawn on top of others)\n";
    for (auto antigen: antigens) {
        auto [tag, coloring_data] = aColorOverride.color(*antigen);
        if (coloring_data.fill.empty())
            std::tie(tag, coloring_data) = aColoring.color(*antigen);
        try {
            auto location = virus_name::location(antigen->name());
            if (location == "GEORGIA" && hidb.tables()->most_recent(antigen->tables())->lab() == "CDC")
                location = "GEORGIA STATE"; // somehow disambiguate
            const auto found = std::find(std::begin(aPriority), std::end(aPriority), tag);
            mPointsAtLocation.add(location, found == std::end(aPriority) ? 0 : (found - std::begin(aPriority) + 1), coloring_data);
        }
        catch (virus_name::Unrecognized&) {
        }
    }
      // std::transform(mPoints.begin(), mPoints.end(), std::ostream_iterator<std::string>(std::cerr, "\n"), [](const auto& e) -> std::string { return e.first; });

} // GeographicMapWithPointsFromHidb::add_points_from_hidb_colored_by

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

GeographicTimeSeriesBase::~GeographicTimeSeriesBase()
{
} // GeographicTimeSeriesBase::~GeographicTimeSeriesBase

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

void GeographicTimeSeriesBase::draw(std::string aFilenamePrefix, TimeSeriesIterator& aBegin, const TimeSeriesIterator& aEnd, const std::vector<std::string>& aPriority, const GeographicMapColoring& aColoring, const ColorOverride& aColorOverride, double aImageWidth) const
{
    for (; aBegin != aEnd; ++aBegin) {
        auto map = mMap;        // make a copy!
        map.add_points_from_hidb_colored_by(aColoring, aColorOverride, aPriority, *aBegin, aBegin.next());
        map.title().add_line(aBegin.text_name());
        map.draw(aFilenamePrefix + aBegin.numeric_name() + ".pdf", aImageWidth);
    }

} // GeographicTimeSeriesBase::draw

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>acmacs:incrementer renamed to acmacs::range<commit_after>#include "acmacs-base/virus-name.hh"
#include "acmacs-base/range.hh"
#include "acmacs-draw/surface-cairo.hh"
#include "acmacs-draw/geographic-map.hh"
#include "geographic-map.hh"

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

void GeographicMapPoints::draw(Surface& aSurface) const
{
    for (const auto& point: *this) {
        point.draw(aSurface);
    }

} // GeographicMapPoints::draw

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

GeographicMapDraw::~GeographicMapDraw()
{
} // GeographicMapDraw::~GeographicMapDraw

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

void GeographicMapDraw::prepare(Surface&)
{
} // GeographicMapDraw::prepare

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

void GeographicMapDraw::draw(Surface& aOutlineSurface, Surface& aPointSurface) const
{
    geographic_map_draw(aOutlineSurface, mOutline, mOutlineWidth);
    mPoints.draw(aPointSurface);
    mTitle.draw(aOutlineSurface);

} // GeographicMapDraw::draw

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

void GeographicMapDraw::draw(std::string aFilename, double aImageWidth)
{
    const acmacs::Size size = geographic_map_size();
    PdfCairo outline_surface(aFilename, aImageWidth, aImageWidth / size.width * size.height, size.width);
    auto& point_surface = outline_surface.subsurface(outline_surface.viewport().origin, Scaled{outline_surface.viewport().size.width}, geographic_map_viewport(), false);
    prepare(point_surface);
    draw(outline_surface, point_surface);

} // GeographicMapDraw::draw

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

void GeographicMapDraw::add_point(long aPriority, double aLat, double aLong, Color aFill, Pixels aSize, Color aOutline, Pixels aOutlineWidth)
{
    mPoints.emplace_back(LongLat{aLong, -aLat}, aPriority);
    auto& style = mPoints.back();
    style.shape = acmacs::PointShape::Circle;
    style.fill = aFill;
    style.outline = aOutline;
    style.outline_width = aOutlineWidth;
    style.size = aSize;

} // GeographicMapDraw::add_point

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

GeographicMapColoring::~GeographicMapColoring()
{
}

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

ColorOverride::TagColor ColoringByClade::color(const hidb::Antigen& aAntigen) const
{
    ColoringData result("grey50");
    std::string tag{"UNKNOWN"};
    try {
        const auto* entry_seq = seqdb::get(report_time::Yes).find_hi_name(aAntigen.full_name());
        if (entry_seq) {
            for (const auto& clade: entry_seq->seq().clades()) {
                try {
                    result = mColors.at(clade); // find first clade that has corresponding entry in mColors and use it
                    tag = clade;
                    break;
                }
                catch (...) {
                }
            }
        }
    }
    catch (std::exception& err) {
        std::cerr << "ERROR: ColoringByClade " << aAntigen.full_name() << ": " << err.what() << '\n';
    }
    catch (...) {
    }
      // std::cerr << "INFO: ColoringByClade " << aAntigen.full_name() << ": " << tag << '\n';
    return {tag, result};

} // ColoringByClade::color

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

void GeographicMapWithPointsFromHidb::prepare(Surface& aSurface)
{
    GeographicMapDraw::prepare(aSurface);

    const double point_scaled = aSurface.convert(mPointSize).value();
    for (const auto& location_color: mPointsAtLocation) {
        try {
            const auto location = get_locdb().find(location_color.first);
            const double center_lat = location.latitude(), center_long = location.longitude();
            auto iter = location_color.second.iterator();
            auto [coloring_data, priority] = *iter;
            add_point(priority, center_lat, center_long, coloring_data.fill, mPointSize, coloring_data.outline, coloring_data.outline_width);
            ++iter;
            for (size_t circle_no = 1; iter; ++circle_no) {
                const double distance = point_scaled * mDensity * circle_no;
                const size_t circle_capacity = static_cast<size_t>(M_PI * 2.0 * distance * circle_no / (point_scaled * mDensity));
                const size_t points_on_circle = std::min(circle_capacity, iter.left());
                const double step = 2.0 * M_PI / points_on_circle;
                for (auto index: acmacs::range(0UL, points_on_circle)) {
                    std::tie(coloring_data, priority) = *iter;
                    add_point(priority, center_lat + distance * std::cos(index * step), center_long + distance * std::sin(index * step), coloring_data.fill, mPointSize, coloring_data.outline, coloring_data.outline_width);
                    ++iter;
                }
            }
        }
        catch (LocationNotFound&) {
        }
    }

    sort_points();

} // GeographicMapWithPointsFromHidb::prepare

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

void GeographicMapWithPointsFromHidb::add_points_from_hidb_colored_by(const GeographicMapColoring& aColoring, const ColorOverride& aColorOverride, const std::vector<std::string>& aPriority, std::string aStartDate, std::string aEndDate)
{
      // std::cerr << "add_points_from_hidb_colored_by" << '\n';
    const auto& hidb = hidb::get(mVirusType);
    auto antigens = hidb.antigens()->date_range(aStartDate, aEndDate);
    std::cerr << "INFO: dates: " << aStartDate << ".." << aEndDate << "  antigens: " << antigens.size() << std::endl;
    if (!aPriority.empty())
        std::cerr << "INFO: priority: " << aPriority << " (the last in this list to be drawn on top of others)\n";
    for (auto antigen: antigens) {
        auto [tag, coloring_data] = aColorOverride.color(*antigen);
        if (coloring_data.fill.empty())
            std::tie(tag, coloring_data) = aColoring.color(*antigen);
        try {
            auto location = virus_name::location(antigen->name());
            if (location == "GEORGIA" && hidb.tables()->most_recent(antigen->tables())->lab() == "CDC")
                location = "GEORGIA STATE"; // somehow disambiguate
            const auto found = std::find(std::begin(aPriority), std::end(aPriority), tag);
            mPointsAtLocation.add(location, found == std::end(aPriority) ? 0 : (found - std::begin(aPriority) + 1), coloring_data);
        }
        catch (virus_name::Unrecognized&) {
        }
    }
      // std::transform(mPoints.begin(), mPoints.end(), std::ostream_iterator<std::string>(std::cerr, "\n"), [](const auto& e) -> std::string { return e.first; });

} // GeographicMapWithPointsFromHidb::add_points_from_hidb_colored_by

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

GeographicTimeSeriesBase::~GeographicTimeSeriesBase()
{
} // GeographicTimeSeriesBase::~GeographicTimeSeriesBase

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

void GeographicTimeSeriesBase::draw(std::string aFilenamePrefix, TimeSeriesIterator& aBegin, const TimeSeriesIterator& aEnd, const std::vector<std::string>& aPriority, const GeographicMapColoring& aColoring, const ColorOverride& aColorOverride, double aImageWidth) const
{
    for (; aBegin != aEnd; ++aBegin) {
        auto map = mMap;        // make a copy!
        map.add_points_from_hidb_colored_by(aColoring, aColorOverride, aPriority, *aBegin, aBegin.next());
        map.title().add_line(aBegin.text_name());
        map.draw(aFilenamePrefix + aBegin.numeric_name() + ".pdf", aImageWidth);
    }

} // GeographicTimeSeriesBase::draw

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#include "bananagrams.hpp"

using std::cerr;
using std::endl;
using std::string;

Typer::Typer()
{
	ch = 'A' - 1;
}

bool Typer::get_ch(char* chr)
{
	if (ch >= 'A' && ch <= 'Z')
	{
		*chr = ch;
		ch = 'A' - 1;
		return true;
	}
	return false;
}

bool Typer::process_event(sf::Event& event)
{
	if (event.type == sf::Event::KeyPressed && event.key.code >= sf::Keyboard::Key::A && event.key.code <= sf::Keyboard::Key::Z)
		ch = event.key.code - sf::Keyboard::Key::A + 'A';
	return true;
}

MouseControls::MouseControls(State* m)
{
	state = m;
}

bool MouseControls::process_event(sf::Event& event)
{
	switch(event.type)
	{
		case sf::Event::MouseButtonPressed:
			if (event.mouseButton.button == sf::Mouse::Left)
				state->start_selection = true;
			else if (event.mouseButton.button == sf::Mouse::Right)
				state->mremove = true;
			break;
		case sf::Event::MouseButtonReleased:
			state->update = true;
			if (event.mouseButton.button == sf::Mouse::Left)
				state->end_selection = true;
			else if (event.mouseButton.button == sf::Mouse::Right)
				state->mremove = false;
			break;
		case sf::Event::MouseMoved:
			{
				state->update = true;
				state->pos[0] = event.mouseMove.x;
				state->pos[1] = event.mouseMove.y;
			}
			break;
		case sf::Event::MouseWheelMoved:
			state->wheel_delta = event.mouseWheel.delta;
			break;
		default:
			break;
	}

	return true;
}

KeyControls::Command::Command(repeat_t rep)
{
	pressed = false;
	ready = true;
	repeat = rep;
}

KeyControls::KeyControls()
{
	set_defaults();
}

void KeyControls::bind(const sf::Event::KeyEvent& key, const string& command, repeat_t rep)
{
	binds[key] = command;
	commands[command] = Command(rep);
}

void KeyControls::rebind(const sf::Event::KeyEvent& key, const string& command)
{
	if (!has_bind(command))
		throw NotFound(command);
	binds[key] = command;
	commands[command].pressed = false;
	commands[command].ready = true;
}

void KeyControls::set_defaults()
{
	// TODO is there a better way to structure these?
	binds.clear();
	commands.clear();

	sf::Event::KeyEvent key;
	key.alt = false;
	key.control = false;
	key.shift = false;
	key.system = false;

	key.code = sf::Keyboard::Key::Left;
	bind(key, "left", REPEAT);
	key.code = sf::Keyboard::Right;
	bind(key, "right", REPEAT);
	key.code = sf::Keyboard::Up;
	bind(key, "up", REPEAT);
	key.code = sf::Keyboard::Down;
	bind(key, "down", REPEAT);
	key.shift = true;
	key.code = sf::Keyboard::Left;
	bind(key, "left_fast", REPEAT);
	key.code = sf::Keyboard::Right;
	bind(key, "right_fast", REPEAT);
	key.code = sf::Keyboard::Up;
	bind(key, "up_fast", REPEAT);
	key.code = sf::Keyboard::Down;
	bind(key, "down_fast", REPEAT);
	key.control = true;
	key.shift = false;
	key.code = sf::Keyboard::Key::Up;
	bind(key, "zoom_in", HOLD);
	key.code = sf::Keyboard::Key::Down;
	bind(key, "zoom_out", HOLD);
	key.shift = true;
	key.code = sf::Keyboard::Key::Up;
	bind(key, "zoom_in_fast", HOLD);
	key.code = sf::Keyboard::Key::Down;
	bind(key, "zoom_out_fast", HOLD);
	key.control = false;
	key.shift = false;
	key.code = sf::Keyboard::BackSpace;
	bind(key, "remove", REPEAT);
	key.code = sf::Keyboard::Space;
	bind(key, "peel", PRESS);
	key.control = true;
	key.code = sf::Keyboard::C;
	bind(key, "center", PRESS);
	key.code = sf::Keyboard::D;
	bind(key, "dump", PRESS);
	key.code = sf::Keyboard::X;
	bind(key, "cut", PRESS);
	key.code = sf::Keyboard::V;
	bind(key, "paste", PRESS);
	key.code = sf::Keyboard::F;
	bind(key, "flip", PRESS);
	key.control = false;
	key.code = sf::Keyboard::LControl;
	bind(key, "quick_place", HOLD);
}

bool KeyControls::load_from_file(const string& filename)
{
	bool bad = false;
	YAML::Node bindings;
	try
	{
		bindings = YAML::LoadFile(filename);
	}
	catch (YAML::BadFile)
	{
		bad = true;
	}

	if (bad || !bindings.IsMap())
	{
		cerr << "Ignoring bad/missing config file\n";
		return false;
	}

	for (auto binding : bindings)
	{
		try
		{
			rebind(binding.second.as<sf::Event::KeyEvent>(), binding.first.as<string>());
		}
		catch (NotFound)
		{
			cerr << "Unrecognized command: " << binding.first.as<string>() << endl;
		}
		catch (YAML::TypedBadConversion<sf::Event::KeyEvent>)
		{
			// YAML conversion already prints errors
		}
	}

	return true;
}

bool KeyControls::operator[](const string& command)
{
	Command& c = commands[command];
	bool press = c.pressed;

	if (c.get_repeat() != HOLD)
		c.pressed = false;

	return press;
}

bool KeyControls::process_event(sf::Event& event)
{
	if (event.type == sf::Event::KeyPressed)
	{
		// TODO this doesn't work if you release modifier keys in different orders
		auto it = binds.find(event.key);
		if (it != binds.end())
		{
			Command& c = commands[it->second];
			switch (c.get_repeat())
			{
				case PRESS:
					if (c.ready)
					{
						c.pressed = true;
						c.ready = false;
					}
					break;
				case REPEAT:
				case HOLD:
					c.pressed = true;
					break;
			}

			// don't continue bound keypresses
			return false;
		}
	}
	else if (event.type == sf::Event::KeyReleased)
	{
		switch (event.key.code)
		{
			case sf::Keyboard::Key::LAlt:
			case sf::Keyboard::Key::RAlt:
				for (auto pair : binds)
					if (commands[pair.second].get_repeat() == HOLD && (pair.first.alt || pair.first.code == sf::Keyboard::Key::LAlt || pair.first.code == sf::Keyboard::Key::RAlt))
						commands[pair.second].pressed = false;
				break;
			case sf::Keyboard::Key::LControl:
			case sf::Keyboard::Key::RControl:
				for (auto pair : binds)
					if (commands[pair.second].get_repeat() == HOLD && (pair.first.control || pair.first.code == sf::Keyboard::Key::LControl || pair.first.code == sf::Keyboard::Key::RControl))
						commands[pair.second].pressed = false;
				break;
			case sf::Keyboard::Key::LShift:
			case sf::Keyboard::Key::RShift:
				for (auto pair : binds)
					if (commands[pair.second].get_repeat() == HOLD && (pair.first.shift || pair.first.code == sf::Keyboard::Key::LShift || pair.first.code == sf::Keyboard::Key::RShift))
						commands[pair.second].pressed = false;
				break;
			case sf::Keyboard::Key::LSystem:
			case sf::Keyboard::Key::RSystem:
				for (auto pair : binds)
					if (commands[pair.second].get_repeat() == HOLD && (pair.first.system || pair.first.code == sf::Keyboard::Key::LSystem || pair.first.code == sf::Keyboard::Key::RSystem))
						commands[pair.second].pressed = false;
				break;
			default:
				break;
		}
		auto it = binds.find(event.key);
		if (it != binds.end())
		{
			Command& c = commands[it->second];
			switch (c.get_repeat())
			{
				case PRESS:
					c.ready = true;
					break;
				case REPEAT:
					break;
				case HOLD:
					c.pressed = false;
					break;
			}
		}
	}

	return true;
}
<commit_msg>Soft error for blank bindings in config<commit_after>#include "bananagrams.hpp"

using std::cerr;
using std::endl;
using std::string;

Typer::Typer()
{
	ch = 'A' - 1;
}

bool Typer::get_ch(char* chr)
{
	if (ch >= 'A' && ch <= 'Z')
	{
		*chr = ch;
		ch = 'A' - 1;
		return true;
	}
	return false;
}

bool Typer::process_event(sf::Event& event)
{
	if (event.type == sf::Event::KeyPressed && event.key.code >= sf::Keyboard::Key::A && event.key.code <= sf::Keyboard::Key::Z)
		ch = event.key.code - sf::Keyboard::Key::A + 'A';
	return true;
}

MouseControls::MouseControls(State* m)
{
	state = m;
}

bool MouseControls::process_event(sf::Event& event)
{
	switch(event.type)
	{
		case sf::Event::MouseButtonPressed:
			if (event.mouseButton.button == sf::Mouse::Left)
				state->start_selection = true;
			else if (event.mouseButton.button == sf::Mouse::Right)
				state->mremove = true;
			break;
		case sf::Event::MouseButtonReleased:
			state->update = true;
			if (event.mouseButton.button == sf::Mouse::Left)
				state->end_selection = true;
			else if (event.mouseButton.button == sf::Mouse::Right)
				state->mremove = false;
			break;
		case sf::Event::MouseMoved:
			{
				state->update = true;
				state->pos[0] = event.mouseMove.x;
				state->pos[1] = event.mouseMove.y;
			}
			break;
		case sf::Event::MouseWheelMoved:
			state->wheel_delta = event.mouseWheel.delta;
			break;
		default:
			break;
	}

	return true;
}

KeyControls::Command::Command(repeat_t rep)
{
	pressed = false;
	ready = true;
	repeat = rep;
}

KeyControls::KeyControls()
{
	set_defaults();
}

void KeyControls::bind(const sf::Event::KeyEvent& key, const string& command, repeat_t rep)
{
	binds[key] = command;
	commands[command] = Command(rep);
}

void KeyControls::rebind(const sf::Event::KeyEvent& key, const string& command)
{
	if (!has_bind(command))
		throw NotFound(command);
	binds[key] = command;
	commands[command].pressed = false;
	commands[command].ready = true;
}

void KeyControls::set_defaults()
{
	// TODO is there a better way to structure these?
	binds.clear();
	commands.clear();

	sf::Event::KeyEvent key;
	key.alt = false;
	key.control = false;
	key.shift = false;
	key.system = false;

	key.code = sf::Keyboard::Key::Left;
	bind(key, "left", REPEAT);
	key.code = sf::Keyboard::Right;
	bind(key, "right", REPEAT);
	key.code = sf::Keyboard::Up;
	bind(key, "up", REPEAT);
	key.code = sf::Keyboard::Down;
	bind(key, "down", REPEAT);
	key.shift = true;
	key.code = sf::Keyboard::Left;
	bind(key, "left_fast", REPEAT);
	key.code = sf::Keyboard::Right;
	bind(key, "right_fast", REPEAT);
	key.code = sf::Keyboard::Up;
	bind(key, "up_fast", REPEAT);
	key.code = sf::Keyboard::Down;
	bind(key, "down_fast", REPEAT);
	key.control = true;
	key.shift = false;
	key.code = sf::Keyboard::Key::Up;
	bind(key, "zoom_in", HOLD);
	key.code = sf::Keyboard::Key::Down;
	bind(key, "zoom_out", HOLD);
	key.shift = true;
	key.code = sf::Keyboard::Key::Up;
	bind(key, "zoom_in_fast", HOLD);
	key.code = sf::Keyboard::Key::Down;
	bind(key, "zoom_out_fast", HOLD);
	key.control = false;
	key.shift = false;
	key.code = sf::Keyboard::BackSpace;
	bind(key, "remove", REPEAT);
	key.code = sf::Keyboard::Space;
	bind(key, "peel", PRESS);
	key.control = true;
	key.code = sf::Keyboard::C;
	bind(key, "center", PRESS);
	key.code = sf::Keyboard::D;
	bind(key, "dump", PRESS);
	key.code = sf::Keyboard::X;
	bind(key, "cut", PRESS);
	key.code = sf::Keyboard::V;
	bind(key, "paste", PRESS);
	key.code = sf::Keyboard::F;
	bind(key, "flip", PRESS);
	key.control = false;
	key.code = sf::Keyboard::LControl;
	bind(key, "quick_place", HOLD);
}

bool KeyControls::load_from_file(const string& filename)
{
	bool bad = false;
	YAML::Node bindings;
	try
	{
		bindings = YAML::LoadFile(filename);
	}
	catch (YAML::BadFile)
	{
		bad = true;
	}

	if (bad || !bindings.IsMap())
	{
		cerr << "Ignoring bad/missing config file\n";
		return false;
	}

	for (auto binding : bindings)
	{
		try
		{
			rebind(binding.second.as<sf::Event::KeyEvent>(), binding.first.as<string>());
		}
		catch (NotFound)
		{
			cerr << "Unrecognized command: " << binding.first.as<string>() << endl;
		}
		catch (YAML::TypedBadConversion<sf::Event::KeyEvent>)
		{
			// YAML conversion already prints errors
		}
		catch (YAML::TypedBadConversion<std::string>)
		{
			cerr << "Empty binding: " << binding.first.as<string>() << endl;
		}
	}

	return true;
}

bool KeyControls::operator[](const string& command)
{
	Command& c = commands[command];
	bool press = c.pressed;

	if (c.get_repeat() != HOLD)
		c.pressed = false;

	return press;
}

bool KeyControls::process_event(sf::Event& event)
{
	if (event.type == sf::Event::KeyPressed)
	{
		// TODO this doesn't work if you release modifier keys in different orders
		auto it = binds.find(event.key);
		if (it != binds.end())
		{
			Command& c = commands[it->second];
			switch (c.get_repeat())
			{
				case PRESS:
					if (c.ready)
					{
						c.pressed = true;
						c.ready = false;
					}
					break;
				case REPEAT:
				case HOLD:
					c.pressed = true;
					break;
			}

			// don't continue bound keypresses
			return false;
		}
	}
	else if (event.type == sf::Event::KeyReleased)
	{
		switch (event.key.code)
		{
			case sf::Keyboard::Key::LAlt:
			case sf::Keyboard::Key::RAlt:
				for (auto pair : binds)
					if (commands[pair.second].get_repeat() == HOLD && (pair.first.alt || pair.first.code == sf::Keyboard::Key::LAlt || pair.first.code == sf::Keyboard::Key::RAlt))
						commands[pair.second].pressed = false;
				break;
			case sf::Keyboard::Key::LControl:
			case sf::Keyboard::Key::RControl:
				for (auto pair : binds)
					if (commands[pair.second].get_repeat() == HOLD && (pair.first.control || pair.first.code == sf::Keyboard::Key::LControl || pair.first.code == sf::Keyboard::Key::RControl))
						commands[pair.second].pressed = false;
				break;
			case sf::Keyboard::Key::LShift:
			case sf::Keyboard::Key::RShift:
				for (auto pair : binds)
					if (commands[pair.second].get_repeat() == HOLD && (pair.first.shift || pair.first.code == sf::Keyboard::Key::LShift || pair.first.code == sf::Keyboard::Key::RShift))
						commands[pair.second].pressed = false;
				break;
			case sf::Keyboard::Key::LSystem:
			case sf::Keyboard::Key::RSystem:
				for (auto pair : binds)
					if (commands[pair.second].get_repeat() == HOLD && (pair.first.system || pair.first.code == sf::Keyboard::Key::LSystem || pair.first.code == sf::Keyboard::Key::RSystem))
						commands[pair.second].pressed = false;
				break;
			default:
				break;
		}
		auto it = binds.find(event.key);
		if (it != binds.end())
		{
			Command& c = commands[it->second];
			switch (c.get_repeat())
			{
				case PRESS:
					c.ready = true;
					break;
				case REPEAT:
					break;
				case HOLD:
					c.pressed = false;
					break;
			}
		}
	}

	return true;
}
<|endoftext|>


<commit_before>// Copyright 2017 Global Phasing Ltd.

#include <iostream> // temporary, for debugging
#include "gemmi/cifgz.hpp"
#include "gemmi/mmcif.hpp"
#include "gemmi/pdbgz.hpp"
#include "gemmi/to_cif.hpp"
#include "gemmi/to_json.hpp"
#include "gemmi/to_pdb.hpp"
// set this before only one of stb_sprintf.h includes
#define STB_SPRINTF_IMPLEMENTATION
#include "gemmi/to_mmcif.hpp"

#include <cstring>
#include <iostream>
#include <map>
#include <optionparser.h>

#define EXE_NAME "gemmi-convert"

enum class FileType : char { Json, Pdb, Cif, Null, Unknown };

struct Arg: public option::Arg {
  static option::ArgStatus Required(const option::Option& option, bool msg) {
    if (option.arg != nullptr)
      return option::ARG_OK;
    if (msg)
      std::cerr << "Option '" << option.name << "' requires an argument\n";
    return option::ARG_ILLEGAL;
  }

  static option::ArgStatus Choice(const option::Option& option, bool msg,
                                  std::vector<const char*> choices) {
    if (Required(option, msg) == option::ARG_ILLEGAL)
      return option::ARG_ILLEGAL;
    for (const char* a : choices)
      if (strcmp(option.arg, a) == 0)
        return option::ARG_OK;
    if (msg)
      std::cerr << "Invalid argument for "
                << std::string(option.name, option.namelen) << ": "
                << option.arg << "\n";
    return option::ARG_ILLEGAL;
  }

  static option::ArgStatus FileFormat(const option::Option& option, bool msg) {
    // the hidden option "none" is for testing only
    return Arg::Choice(option, msg, {"json", "pdb", "cif", "none"});
  }

  static option::ArgStatus NumbChoice(const option::Option& option, bool msg) {
    return Arg::Choice(option, msg, {"quote", "nosu", "mix"});
  }
};

enum OptionIndex { Unknown, Help, Verbose, FormatIn, FormatOut,
                   Bare, Numb, QMark };
static const option::Descriptor usage[] = {
  { Unknown, 0, "", "", Arg::None,
    "Usage:"
    "\n " EXE_NAME " [options] INPUT_FILE OUTPUT_FILE"
    "\n\nwith possible conversions: cif->json and cif<->pdb."
    "\n\nGeneral options:" },
  { Help, 0, "h", "help", Arg::None, "  -h, --help  \tPrint usage and exit." },
  { Verbose, 0, "", "verbose", Arg::None, "  --verbose  \tVerbose output." },
  { FormatIn, 0, "", "from", Arg::FileFormat,
    "  --from=pdb|cif  \tInput format (default: from the file extension)." },
  { FormatOut, 0, "", "to", Arg::FileFormat,
    "  --to=json|pdb  \tOutput format (default: from the file extension)." },
  { Unknown, 0, "", "", Arg::None, "\nCIF output options:" },
  { Bare, 0, "b", "bare-tags", Arg::None,
    "  -b, --bare-tags  \tOutput tags without the first underscore." },
  { Numb, 0, "", "numb", Arg::NumbChoice,
    "  --numb=quote|nosu|mix  \tConvert the CIF numb type to one of:"
                             "\v  quote - string in quotes,"
                             "\v  nosu - number without s.u.,"
                             "\v  mix (default) - quote only numbs with s.u." },
  { QMark, 0, "", "unknown", Arg::Required,
    "  --unknown=STRING  \tJSON representation of CIF's '?' (default: null)." },
  { Unknown, 0, "", "", Arg::None, "\nMacromolecular options:" },
  { ExpandNcs, 0, "", "expand-ncs", Arg::None,
    "  --expand-ncs  \tExpand NCS mates specified in MTRIXn or equivalent." },
  { Unknown, 0, "", "", Arg::None,
    "\nWhen output file is -, write to standard output." },
  { 0, 0, 0, 0, 0, 0 }
};

FileType get_format_from_extension(const std::string& path) {
  using gemmi::iends_with;
  if (iends_with(path, ".pdb") || iends_with(path, ".ent") ||
      iends_with(path, ".pdb.gz") || iends_with(path, ".ent.gz"))
    return FileType::Pdb;
  if (iends_with(path, ".js") || iends_with(path, ".json"))
    return FileType::Json;
  if (iends_with(path, ".cif") || iends_with(path, ".cif.gz"))
    return FileType::Cif;
  if (path == "/dev/null")
    return FileType::Null;
  return FileType::Unknown;
}

[[noreturn]]
inline void fail(const std::string& msg) { throw std::runtime_error(msg); }

static std::string get_chain_letter(const std::vector<Chain>& chains,
                                    bool short_chain_names) {
  if (short_chain_names) {
    char symbols[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                     "abcdefghijklmnopqrstuvwxyz01234567890";
    for (char symbol : symbols)
      if (find_if(chains.begin(), chains.end(),
                  [&](const Chain& ch) { return ch.name == symbol; })
          == std::end(symbols))
        return std::string(1, symbol);
  }
}

static void expand_ncs(Structure& st, bool short_chain_names) {
  int n_ops = std::count_if(st.ncs.begin(), st.ncs.end(),
                            [](NcsOp& op){ return !op.given; });
  if (n_ops == 0)
    return;
  for (Model& model : st.models) {
    size_t new_length = model.chains.size() * (n_ops + 1);
    if (new_length >= 63)
      short_chain_names = false;
    std::string next_name;
    model.chains.reserve(new_length);
    for (const NcsOp& op : st.ncs)
      if (!op.given)
        for (chain : model.chains) {
          model.chains.push_back(chain);
          Chain& new_chain = model.chains.back();
          new_chain.name = next_chain_letter(model.chains, short_chain_names)
                                             : "2";
          new_chain.auth_name = "";
          for (Residue& res : new_chain.residues)
            for (Atom& a : res.atoms) {
              //TODO
            }
        }
  for (NcsOp& op : st.ncs)
    op.given = true;
}

void convert(const char* input, FileType input_type,
             const char* output, FileType output_type,
             const std::vector<option::Option>& options) {
  gemmi::cif::Document cif_in;
  gemmi::mol::Structure st;
  // for cif->cif we do either cif->DOM->Structure->DOM->cif or cif->DOM->cif
  bool need_structure = options[ExpandNcs];
  if (input_type == FileType::Cif) {
    cif_in = gemmi::cif::read_any(input);
    if (output_type == FileType::Pdb || output_type == FileType::Null ||
        need_structure) {
      st = gemmi::mol::read_atoms(cif_in);
      if (st.models.empty())
        fail("No atoms in the input file. Is it mmCIF?");
    }
  } else if (input_type == FileType::Pdb) {
    st = gemmi::mol::read_pdb_any(input);
  } else {
    fail("Unexpected input format.");
  }

  if (options[ExpandNcs])
    expand_ncs(st);

  std::ostream* os;
  std::unique_ptr<std::ostream> os_deleter;
  if (output != std::string("-")) {
    os_deleter.reset(new std::ofstream(output));
    os = os_deleter.get();
    if (!os || !*os)
      fail("Failed to open for writing: " + std::string(output));
  } else {
    os = &std::cout;
  }

  if (output_type == FileType::Json) {
    if (input_type != FileType::Cif)
      fail("Conversion to JSON is possible only from CIF");
    gemmi::cif::JsonWriter writer(*os);
    writer.use_bare_tags = options[Bare];
    if (options[Numb]) {
      char first_letter = options[Numb].arg[0];
      if (first_letter == 'q')
        writer.quote_numbers = 2;
      else if (first_letter == 'n')
        writer.quote_numbers = 0;
    }
    if (options[QMark])
      writer.unknown = options[QMark].arg;
    writer.write_json(cif_in);
  }

  else if (output_type == FileType::Pdb || output_type == FileType::Null) {
    if (output_type == FileType::Pdb)
      gemmi::mol::write_pdb(st, *os);
    else {
      *os << st.name << ": " << count_atom_sites(st) << " atom locations";
      if (st.models.size() > 1)
        *os << " (total in " << st.models.size() << " models)";
      *os << ".\n";
    }
  } else if (output_type == FileType::Cif) {
    // cif to cif round trip is for testing only
    if (input_type != FileType::Cif || need_structure) {
      cif_in.blocks.clear();  // temporary, for testing
      cif_in.blocks.resize(1);
      gemmi::mol::update_cif_block(st, cif_in.blocks[0]);
    }
    *os << cif_in;
  }
}

int main(int argc, char **argv) {
  if (argc < 1)
    return 2;
  std::ios_base::sync_with_stdio(false);
  option::Stats stats(usage, argc-1, argv+1);
  std::vector<option::Option> options(stats.options_max);
  std::vector<option::Option> buffer(stats.buffer_max);
  option::Parser parse(usage, argc-1, argv+1, options.data(), buffer.data());
  if (parse.error()) {
    option::printUsage(std::cerr, usage);
    return 1;
  }
  if (options[Help]) {
    option::printUsage(std::cout, usage);
    return 0;
  }
  if (options[Unknown]) {
    std::cerr << "Invalid option.\n";
    option::printUsage(std::cerr, usage);
    return 1;
  }
  if (parse.nonOptionsCount() != 2) {
    std::cerr << "This program requires 2 arguments (input and output), "
              << parse.nonOptionsCount() << " given.\n"
                 "Try '" EXE_NAME " --help' for more information.\n";
    return 1;
  }

  const char* input = parse.nonOption(0);
  const char* output = parse.nonOption(1);

  std::map<std::string, FileType> filetypes {{"json", FileType::Json},
                                             {"pdb", FileType::Pdb},
                                             {"cif", FileType::Cif},
                                             {"none", FileType::Null}};

  FileType in_type = options[FormatIn] ? filetypes[options[FormatIn].arg]
                                       : get_format_from_extension(input);
  if (in_type == FileType::Unknown) {
    std::cerr << "The input format cannot be determined from input"
                 " filename. Use option --from.\n";
    return 1;
  }

  FileType out_type = options[FormatOut] ? filetypes[options[FormatOut].arg]
                                         : get_format_from_extension(output);
  if (out_type == FileType::Unknown) {
    std::cerr << "The output format cannot be determined from output"
                 " filename. Use option --to.\n";
    return 1;
  }
  if (options[Verbose])
    std::cerr << "Converting " << input << " ..." << std::endl;

  try {
    convert(input, in_type, output, out_type, options);
  } catch (tao::pegtl::parse_error& e) {
    std::cerr << e.what() << std::endl;
    return 1;
  } catch (std::runtime_error& e) {
    std::cerr << "ERROR: " << e.what() << std::endl;
    return 2;
  }
  return 0;
}

// vim:sw=2:ts=2:et
<commit_msg>convert --expand-ncs: needs testing<commit_after>// Copyright 2017 Global Phasing Ltd.

#include <iostream> // temporary, for debugging
#include "gemmi/cifgz.hpp"
#include "gemmi/mmcif.hpp"
#include "gemmi/pdbgz.hpp"
#include "gemmi/to_cif.hpp"
#include "gemmi/to_json.hpp"
#include "gemmi/to_pdb.hpp"
// set this before only one of stb_sprintf.h includes
#define STB_SPRINTF_IMPLEMENTATION
#include "gemmi/to_mmcif.hpp"

#include <cstring>
#include <iostream>
#include <map>
#include <optionparser.h>

#define EXE_NAME "gemmi-convert"

enum class FileType : char { Json, Pdb, Cif, Null, Unknown };

struct Arg: public option::Arg {
  static option::ArgStatus Required(const option::Option& option, bool msg) {
    if (option.arg != nullptr)
      return option::ARG_OK;
    if (msg)
      std::cerr << "Option '" << option.name << "' requires an argument\n";
    return option::ARG_ILLEGAL;
  }

  static option::ArgStatus Choice(const option::Option& option, bool msg,
                                  std::vector<const char*> choices) {
    if (Required(option, msg) == option::ARG_ILLEGAL)
      return option::ARG_ILLEGAL;
    for (const char* a : choices)
      if (strcmp(option.arg, a) == 0)
        return option::ARG_OK;
    if (msg)
      std::cerr << "Invalid argument for "
                << std::string(option.name, option.namelen) << ": "
                << option.arg << "\n";
    return option::ARG_ILLEGAL;
  }

  static option::ArgStatus FileFormat(const option::Option& option, bool msg) {
    // the hidden option "none" is for testing only
    return Arg::Choice(option, msg, {"json", "pdb", "cif", "none"});
  }

  static option::ArgStatus NumbChoice(const option::Option& option, bool msg) {
    return Arg::Choice(option, msg, {"quote", "nosu", "mix"});
  }
};

enum OptionIndex { Unknown, Help, Verbose, FormatIn, FormatOut,
                   Bare, Numb, QMark, ExpandNcs };
static const option::Descriptor usage[] = {
  { Unknown, 0, "", "", Arg::None,
    "Usage:"
    "\n " EXE_NAME " [options] INPUT_FILE OUTPUT_FILE"
    "\n\nwith possible conversions: cif->json and cif<->pdb."
    "\n\nGeneral options:" },
  { Help, 0, "h", "help", Arg::None, "  -h, --help  \tPrint usage and exit." },
  { Verbose, 0, "", "verbose", Arg::None, "  --verbose  \tVerbose output." },
  { FormatIn, 0, "", "from", Arg::FileFormat,
    "  --from=pdb|cif  \tInput format (default: from the file extension)." },
  { FormatOut, 0, "", "to", Arg::FileFormat,
    "  --to=json|pdb  \tOutput format (default: from the file extension)." },
  { Unknown, 0, "", "", Arg::None, "\nCIF output options:" },
  { Bare, 0, "b", "bare-tags", Arg::None,
    "  -b, --bare-tags  \tOutput tags without the first underscore." },
  { Numb, 0, "", "numb", Arg::NumbChoice,
    "  --numb=quote|nosu|mix  \tConvert the CIF numb type to one of:"
                             "\v  quote - string in quotes,"
                             "\v  nosu - number without s.u.,"
                             "\v  mix (default) - quote only numbs with s.u." },
  { QMark, 0, "", "unknown", Arg::Required,
    "  --unknown=STRING  \tJSON representation of CIF's '?' (default: null)." },
  { Unknown, 0, "", "", Arg::None, "\nMacromolecular options:" },
  { ExpandNcs, 0, "", "expand-ncs", Arg::None,
    "  --expand-ncs  \tExpand strict NCS specified in MTRIXn or equivalent." },
  { Unknown, 0, "", "", Arg::None,
    "\nWhen output file is -, write to standard output." },
  { 0, 0, 0, 0, 0, 0 }
};

FileType get_format_from_extension(const std::string& path) {
  using gemmi::iends_with;
  if (iends_with(path, ".pdb") || iends_with(path, ".ent") ||
      iends_with(path, ".pdb.gz") || iends_with(path, ".ent.gz"))
    return FileType::Pdb;
  if (iends_with(path, ".js") || iends_with(path, ".json"))
    return FileType::Json;
  if (iends_with(path, ".cif") || iends_with(path, ".cif.gz"))
    return FileType::Cif;
  if (path == "/dev/null")
    return FileType::Null;
  return FileType::Unknown;
}

[[noreturn]]
inline void fail(const std::string& msg) { throw std::runtime_error(msg); }

static char symbols[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                        "abcdefghijklmnopqrstuvwxyz01234567890";

static void expand_ncs(gemmi::mol::Structure& st, bool short_chain_names) {
  namespace mol = gemmi::mol;
  int n_ops = std::count_if(st.ncs.begin(), st.ncs.end(),
                            [](mol::NcsOp& op){ return !op.given; });
  if (n_ops == 0)
    return;
  for (mol::Model& model : st.models) {
    size_t new_length = model.chains.size() * (n_ops + 1);
    if (new_length >= 63)
      short_chain_names = false;
    model.chains.reserve(new_length);
    for (const mol::Chain& chain : model.chains) {
      int op_num = 0;
      for (const mol::NcsOp& op : st.ncs)
        if (!op.given) {
          op_num++;
          // the most difficult part - choosing names for new chains
          std::string name;
          if (short_chain_names) {
            for (char symbol : symbols) {
              name = std::string(1, symbol);
              if (!model.find_chain(name))
                break;
            }
          }
          else {
            name = chain.name + std::to_string(op_num+1);
            while (model.find_chain(name))
              name += "a";
          }

          model.chains.push_back(chain);
          mol::Chain& new_chain = model.chains.back();
          new_chain.name = name;
          new_chain.auth_name = "";

          for (mol::Residue& res : new_chain.residues)
            for (mol::Atom& a : res.atoms) {
              linalg::vec<double,4> pos = {a.pos.x, a.pos.y, a.pos.z,  1.0};
              pos = linalg::mul(op.transform, pos);
              a.pos = {pos.x, pos.y, pos.z};
            }
        }
    }
  }
  for (mol::NcsOp& op : st.ncs)
    op.given = true;
}

void convert(const char* input, FileType input_type,
             const char* output, FileType output_type,
             const std::vector<option::Option>& options) {
  gemmi::cif::Document cif_in;
  gemmi::mol::Structure st;
  // for cif->cif we do either cif->DOM->Structure->DOM->cif or cif->DOM->cif
  bool need_structure = options[ExpandNcs];
  if (input_type == FileType::Cif) {
    cif_in = gemmi::cif::read_any(input);
    if (output_type == FileType::Pdb || output_type == FileType::Null ||
        need_structure) {
      st = gemmi::mol::read_atoms(cif_in);
      if (st.models.empty())
        fail("No atoms in the input file. Is it mmCIF?");
    }
  } else if (input_type == FileType::Pdb) {
    st = gemmi::mol::read_pdb_any(input);
  } else {
    fail("Unexpected input format.");
  }

  if (options[ExpandNcs])
    expand_ncs(st, output_type == FileType::Pdb);

  std::ostream* os;
  std::unique_ptr<std::ostream> os_deleter;
  if (output != std::string("-")) {
    os_deleter.reset(new std::ofstream(output));
    os = os_deleter.get();
    if (!os || !*os)
      fail("Failed to open for writing: " + std::string(output));
  } else {
    os = &std::cout;
  }

  if (output_type == FileType::Json) {
    if (input_type != FileType::Cif)
      fail("Conversion to JSON is possible only from CIF");
    gemmi::cif::JsonWriter writer(*os);
    writer.use_bare_tags = options[Bare];
    if (options[Numb]) {
      char first_letter = options[Numb].arg[0];
      if (first_letter == 'q')
        writer.quote_numbers = 2;
      else if (first_letter == 'n')
        writer.quote_numbers = 0;
    }
    if (options[QMark])
      writer.unknown = options[QMark].arg;
    writer.write_json(cif_in);
  }

  else if (output_type == FileType::Pdb || output_type == FileType::Null) {
    if (output_type == FileType::Pdb)
      gemmi::mol::write_pdb(st, *os);
    else {
      *os << st.name << ": " << count_atom_sites(st) << " atom locations";
      if (st.models.size() > 1)
        *os << " (total in " << st.models.size() << " models)";
      *os << ".\n";
    }
  } else if (output_type == FileType::Cif) {
    // cif to cif round trip is for testing only
    if (input_type != FileType::Cif || need_structure) {
      cif_in.blocks.clear();  // temporary, for testing
      cif_in.blocks.resize(1);
      gemmi::mol::update_cif_block(st, cif_in.blocks[0]);
    }
    *os << cif_in;
  }
}

int main(int argc, char **argv) {
  if (argc < 1)
    return 2;
  std::ios_base::sync_with_stdio(false);
  option::Stats stats(usage, argc-1, argv+1);
  std::vector<option::Option> options(stats.options_max);
  std::vector<option::Option> buffer(stats.buffer_max);
  option::Parser parse(usage, argc-1, argv+1, options.data(), buffer.data());
  if (parse.error()) {
    option::printUsage(std::cerr, usage);
    return 1;
  }
  if (options[Help]) {
    option::printUsage(std::cout, usage);
    return 0;
  }
  if (options[Unknown]) {
    std::cerr << "Invalid option.\n";
    option::printUsage(std::cerr, usage);
    return 1;
  }
  if (parse.nonOptionsCount() != 2) {
    std::cerr << "This program requires 2 arguments (input and output), "
              << parse.nonOptionsCount() << " given.\n"
                 "Try '" EXE_NAME " --help' for more information.\n";
    return 1;
  }

  const char* input = parse.nonOption(0);
  const char* output = parse.nonOption(1);

  std::map<std::string, FileType> filetypes {{"json", FileType::Json},
                                             {"pdb", FileType::Pdb},
                                             {"cif", FileType::Cif},
                                             {"none", FileType::Null}};

  FileType in_type = options[FormatIn] ? filetypes[options[FormatIn].arg]
                                       : get_format_from_extension(input);
  if (in_type == FileType::Unknown) {
    std::cerr << "The input format cannot be determined from input"
                 " filename. Use option --from.\n";
    return 1;
  }

  FileType out_type = options[FormatOut] ? filetypes[options[FormatOut].arg]
                                         : get_format_from_extension(output);
  if (out_type == FileType::Unknown) {
    std::cerr << "The output format cannot be determined from output"
                 " filename. Use option --to.\n";
    return 1;
  }
  if (options[Verbose])
    std::cerr << "Converting " << input << " ..." << std::endl;

  try {
    convert(input, in_type, output, out_type, options);
  } catch (tao::pegtl::parse_error& e) {
    std::cerr << e.what() << std::endl;
    return 1;
  } catch (std::runtime_error& e) {
    std::cerr << "ERROR: " << e.what() << std::endl;
    return 2;
  }
  return 0;
}

// vim:sw=2:ts=2:et
<|endoftext|>


<commit_before>/*
 * PuckManager.cpp
 *
 *  Created on: 09.06.2017
 *      Author: aca592
 */

#include "PuckManager.h"

PuckManager::PuckManager() {
	// TODO Auto-generated constructor stub
}

PuckManager::~PuckManager() {
	// TODO Auto-generated destructor stub
}

void PuckManager::addPuck(PuckContext *puck) {
	puck->setPuckID(nextPuckID++);
	puckList.push_back(puck);
}

PuckManager::ManagerReturn PuckManager::process(PuckSignal::Signal signal) {
	ManagerReturn prioReturnVal; // the prioritized return value
	prioReturnVal.puckSpeed = PuckSignal::PuckSpeed::FAST;
	prioReturnVal.actorFlag = false;
	prioReturnVal.errorFlag = false;
	prioReturnVal.slideFullFlag = false;
	prioReturnVal.puck = nullptr;

	if(signal.signalType == PuckSignal::SignalType::TIMER_SIGNAL) {
		std::list<PuckContext*>::iterator it = puckList.begin();
		do {
			if((*it)->getCurrentSpeed() > prioReturnVal.puckSpeed) { // Check for speed prio
				prioReturnVal.puckSpeed = (*it)->getCurrentSpeed();
			}

			uint16_t currentPuckID = (*it)->getPuckID();
			if(currentPuckID == signal.timerSignal.puckID) {
				PuckSignal::Return returnVal = (*it)->process(signal);

				switch(returnVal.puckReturn) {
					case PuckSignal::PuckReturn::ACCEPT:
						break;
					case PuckSignal::PuckReturn::DELETE:
						delete *it;					// delete the puck from memory
						it = puckList.erase(it);	// delete the puck from list
						break;
					case PuckSignal::PuckReturn::SEND:
						prioReturnVal.puck = (*it);
						prioReturnVal.actorFlag = true;
						prioReturnVal.actorSignal = ActorSignal::SEND_PUCK;
						break;
					case PuckSignal::PuckReturn::EVALUATE:
						// todo: sort
						break;
					case PuckSignal::PuckReturn::HEIGHT:
						prioReturnVal.actorFlag = true;
						prioReturnVal.actorSignal = ActorSignal::START_MEASUREMENT;
						break;
					case PuckSignal::PuckReturn::SLIDE_FULL:
						prioReturnVal.slideFullFlag = true;
						break;
					//
					case PuckSignal::PuckReturn::WARNING:
						prioReturnVal.errorFlag = true;
						prioReturnVal.errorSignal = ErrorSignal::UNEXPECTED_SIGNAL;
						break;
					case PuckSignal::PuckReturn::DENY:
						prioReturnVal.errorFlag = true;
						prioReturnVal.errorSignal = ErrorSignal::UNEXPECTED_SIGNAL;
						break;
					case PuckSignal::PuckReturn::ERROR:
						prioReturnVal.errorFlag = true;
						prioReturnVal.errorSignal = ErrorSignal::PUCK_LOST;
						break;
					default:
						prioReturnVal.errorFlag = true;
						prioReturnVal.errorSignal = ErrorSignal::UNEXPECTED_SIGNAL;
				}
			}
		} while (it != puckList.end());

		return prioReturnVal;
	}

	int32_t acceptCounter = 0; // count all accepted signals
	int32_t warningCounter = 0; // count all warnings

	std::list<PuckContext*>::iterator it = puckList.begin();
	do {
		PuckSignal::Return returnVal = (*it)->process(signal);

		if(returnVal.puckSpeed > prioReturnVal.puckSpeed) { // Check for speed prio
			prioReturnVal.puckSpeed = returnVal.puckSpeed;
		}

		switch(returnVal.puckReturn) {
			case PuckSignal::PuckReturn::ACCEPT:
				acceptCounter++;
				break;
			case PuckSignal::PuckReturn::DELETE:
				acceptCounter++;
				delete *it;					// delete the puck from memory
				it = puckList.erase(it);	// delete the puck from list
				break;
			case PuckSignal::PuckReturn::SEND:
				acceptCounter++;
				prioReturnVal.puck = (*it);
				prioReturnVal.actorFlag = true;
				prioReturnVal.actorSignal = ActorSignal::SEND_PUCK;
				break;
			case PuckSignal::PuckReturn::EVALUATE:
				acceptCounter++;
				// todo: sort
				break;
			case PuckSignal::PuckReturn::HEIGHT:
				acceptCounter++;
				prioReturnVal.actorFlag = true;
				prioReturnVal.actorSignal = ActorSignal::START_MEASUREMENT;
				break;
			case PuckSignal::PuckReturn::SLIDE_FULL:
				acceptCounter++;
				prioReturnVal.slideFullFlag = true;
				break;
			//
			case PuckSignal::PuckReturn::WARNING:
				warningCounter++;
				break;
			case PuckSignal::PuckReturn::DENY:
				break;
			case PuckSignal::PuckReturn::ERROR:
				prioReturnVal.errorFlag = true;
				prioReturnVal.errorSignal = ErrorSignal::PUCK_LOST;
				break;
			default:
				prioReturnVal.errorFlag = true;
				prioReturnVal.errorSignal = ErrorSignal::UNEXPECTED_SIGNAL;
				return prioReturnVal;
		}

		if(returnVal.puckReturn != PuckSignal::PuckReturn::DELETE) {
			++it;
		}
	} while ( it != puckList.end());

	if(!prioReturnVal.errorFlag) {
		if(acceptCounter > 1 || acceptCounter < 0) {
			prioReturnVal.errorFlag = true;
			prioReturnVal.errorSignal = ErrorSignal::MULTIPLE_ACCEPT;
			return prioReturnVal;
		}

		if(acceptCount == 0) {
			prioReturnVal.errorFlag = true;
			prioReturnVal.errorSignal = ErrorSignal::UNEXPECTED_SIGNAL;
			return prioReturnVal;
		}

		// acceptCounter == 1
		if(warningCounter > 1 || warningCounter < 0) {
			prioReturnVal.errorFlag = true;
			prioReturnVal.errorSignal = ErrorSignal::MULTIPLE_WARNING;
			return prioReturnVal;
		}

		// warning can be ignored
	}

	// everything OK
	return prioReturnVal;
}
<commit_msg>Timer signal functionality<commit_after>/*
 * PuckManager.cpp
 *
 *  Created on: 09.06.2017
 *      Author: aca592
 */

#include "PuckManager.h"

PuckManager::PuckManager() {
	// TODO Auto-generated constructor stub
}

PuckManager::~PuckManager() {
	// TODO Auto-generated destructor stub
}

void PuckManager::addPuck(PuckContext *puck) {
	puck->setPuckID(nextPuckID++);
	puckList.push_back(puck);
}

PuckManager::ManagerReturn PuckManager::process(PuckSignal::Signal signal) {
	ManagerReturn prioReturnVal; // the prioritized return value
	prioReturnVal.puckSpeed = PuckSignal::PuckSpeed::FAST;
	prioReturnVal.actorFlag = false;
	prioReturnVal.errorFlag = false;
	prioReturnVal.slideFullFlag = false;
	prioReturnVal.puck = nullptr;

	// Pass the timer signal to the given puckID
	if(signal.signalType == PuckSignal::SignalType::TIMER_SIGNAL) {
		std::list<PuckContext*>::iterator it = puckList.begin();
		do {
			if((*it)->getCurrentSpeed() > prioReturnVal.puckSpeed) { // Check for speed prio
				prioReturnVal.puckSpeed = (*it)->getCurrentSpeed();
			}

			// check for puckID
			uint16_t currentPuckID = (*it)->getPuckID();
			if(currentPuckID == signal.timerSignal.puckID) {
				// pass the timer signal
				PuckSignal::Return returnVal = (*it)->process(signal);

				// check return value
				if(	returnVal.puckReturn != PuckSignal::PuckReturn::ACCEPT &&
					returnVal.puckReturn != PuckSignal::PuckReturn::ERROR) {
						// puck should be triggered on accept or error -> unexpected otherwise
						prioReturnVal.errorFlag = true;
						prioReturnVal.errorSignal = ErrorSignal::UNEXPECTED_SIGNAL;
				}
			}
		} while (it != puckList.end());

		return prioReturnVal;
	}

	int32_t acceptCounter = 0; // count all accepted signals
	int32_t warningCounter = 0; // count all warnings

	std::list<PuckContext*>::iterator it = puckList.begin();
	do {
		PuckSignal::Return returnVal = (*it)->process(signal);

		if(returnVal.puckSpeed > prioReturnVal.puckSpeed) { // Check for speed prio
			prioReturnVal.puckSpeed = returnVal.puckSpeed;
		}

		switch(returnVal.puckReturn) {
			case PuckSignal::PuckReturn::ACCEPT:
				acceptCounter++;
				break;
			case PuckSignal::PuckReturn::DELETE:
				acceptCounter++;
				delete *it;					// delete the puck from memory
				it = puckList.erase(it);	// delete the puck from list
				break;
			case PuckSignal::PuckReturn::SEND:
				acceptCounter++;
				prioReturnVal.puck = (*it);
				prioReturnVal.actorFlag = true;
				prioReturnVal.actorSignal = ActorSignal::SEND_PUCK;
				break;
			case PuckSignal::PuckReturn::EVALUATE:
				acceptCounter++;
				// todo: sort
				break;
			case PuckSignal::PuckReturn::HEIGHT:
				acceptCounter++;
				prioReturnVal.actorFlag = true;
				prioReturnVal.actorSignal = ActorSignal::START_MEASUREMENT;
				break;
			case PuckSignal::PuckReturn::SLIDE_FULL:
				acceptCounter++;
				prioReturnVal.slideFullFlag = true;
				break;
			//
			case PuckSignal::PuckReturn::WARNING:
				warningCounter++;
				break;
			case PuckSignal::PuckReturn::DENY:
				break;
			case PuckSignal::PuckReturn::ERROR:
				prioReturnVal.errorFlag = true;
				prioReturnVal.errorSignal = ErrorSignal::PUCK_LOST;
				break;
			default:
				prioReturnVal.errorFlag = true;
				prioReturnVal.errorSignal = ErrorSignal::UNEXPECTED_SIGNAL;
				return prioReturnVal;
		}

		if(returnVal.puckReturn != PuckSignal::PuckReturn::DELETE) {
			++it;
		}
	} while ( it != puckList.end());

	if(!prioReturnVal.errorFlag) {
		if(acceptCounter > 1 || acceptCounter < 0) {
			prioReturnVal.errorFlag = true;
			prioReturnVal.errorSignal = ErrorSignal::MULTIPLE_ACCEPT;
			return prioReturnVal;
		}

		if(acceptCount == 0) {
			prioReturnVal.errorFlag = true;
			prioReturnVal.errorSignal = ErrorSignal::UNEXPECTED_SIGNAL;
			return prioReturnVal;
		}

		// acceptCounter == 1
		if(warningCounter > 1 || warningCounter < 0) {
			prioReturnVal.errorFlag = true;
			prioReturnVal.errorSignal = ErrorSignal::MULTIPLE_WARNING;
			return prioReturnVal;
		}

		// warning can be ignored
	}

	// everything OK
	return prioReturnVal;
}
<|endoftext|>


<commit_before>// 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.

#ifndef __STOUT_FLAGS_PARSE_HPP__
#define __STOUT_FLAGS_PARSE_HPP__

#include <sstream> // For istringstream.
#include <string>

#include <stout/bytes.hpp>
#include <stout/duration.hpp>
#include <stout/error.hpp>
#include <stout/json.hpp>
#include <stout/path.hpp>
#include <stout/strings.hpp>
#include <stout/try.hpp>

#include <stout/os/read.hpp>

namespace flags {

template <typename T>
Try<T> parse(const std::string& value)
{
  T t;
  std::istringstream in(value);
  in >> t;

  if (in && in.eof()) {
    return t;
  }

  return Error("Failed to convert into required type");
}

template <>
inline Try<std::string> parse(const std::string& value)
{
  return value;
}

template <>
inline Try<bool> parse(const std::string& value)
{
  if (value == "true" || value == "1") {
    return true;
  } else if (value == "false" || value == "0") {
    return false;
  }
  return Error("Expecting a boolean (e.g., true or false)");
}

template <>
inline Try<Duration> parse(const std::string& value)
{
  return Duration::parse(value);
}

template <>
inline Try<Bytes> parse(const std::string& value)
{
  return Bytes::parse(value);
}

template <>
inline Try<JSON::Object> parse(const std::string& value)
{
  // A value that already starts with 'file://' will properly be
  // loaded from the file and put into 'value' but if it starts with
  // '/' we need to explicitly handle it for backwards compatibility
  // reasons (because we used to handle it before we introduced the
  // 'fetch' mechanism for flags that first fetches the data from URIs
  // such as 'file://').
  if (strings::startsWith(value, "/")) {
    LOG(WARNING) << "Specifying an absolute filename to read a command line "
                    "option out of without using 'file:// is deprecated and "
                    "will be removed in a future release. Simply adding "
                    "'file://' to the beginning of the path should eliminate "
                    "this warning.";

    Try<std::string> read = os::read(value);
    if (read.isError()) {
      return Error("Error reading file '" + value + "': " + read.error());
    }
    return JSON::parse<JSON::Object>(read.get());
  }
  return JSON::parse<JSON::Object>(value);
}

template <>
inline Try<Path> parse(const std::string& value)
{
  return Path(value);
}

} // namespace flags {

#endif // __STOUT_FLAGS_PARSE_HPP__
<commit_msg>Stout: Added parse() for JSON::Array.<commit_after>// 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.

#ifndef __STOUT_FLAGS_PARSE_HPP__
#define __STOUT_FLAGS_PARSE_HPP__

#include <sstream> // For istringstream.
#include <string>

#include <stout/bytes.hpp>
#include <stout/duration.hpp>
#include <stout/error.hpp>
#include <stout/json.hpp>
#include <stout/path.hpp>
#include <stout/strings.hpp>
#include <stout/try.hpp>

#include <stout/os/read.hpp>

namespace flags {

template <typename T>
Try<T> parse(const std::string& value)
{
  T t;
  std::istringstream in(value);
  in >> t;

  if (in && in.eof()) {
    return t;
  }

  return Error("Failed to convert into required type");
}

template <>
inline Try<std::string> parse(const std::string& value)
{
  return value;
}

template <>
inline Try<bool> parse(const std::string& value)
{
  if (value == "true" || value == "1") {
    return true;
  } else if (value == "false" || value == "0") {
    return false;
  }
  return Error("Expecting a boolean (e.g., true or false)");
}

template <>
inline Try<Duration> parse(const std::string& value)
{
  return Duration::parse(value);
}

template <>
inline Try<Bytes> parse(const std::string& value)
{
  return Bytes::parse(value);
}

template <>
inline Try<JSON::Object> parse(const std::string& value)
{
  // A value that already starts with 'file://' will properly be
  // loaded from the file and put into 'value' but if it starts with
  // '/' we need to explicitly handle it for backwards compatibility
  // reasons (because we used to handle it before we introduced the
  // 'fetch' mechanism for flags that first fetches the data from URIs
  // such as 'file://').
  if (strings::startsWith(value, "/")) {
    LOG(WARNING) << "Specifying an absolute filename to read a command line "
                    "option out of without using 'file:// is deprecated and "
                    "will be removed in a future release. Simply adding "
                    "'file://' to the beginning of the path should eliminate "
                    "this warning.";

    Try<std::string> read = os::read(value);
    if (read.isError()) {
      return Error("Error reading file '" + value + "': " + read.error());
    }
    return JSON::parse<JSON::Object>(read.get());
  }
  return JSON::parse<JSON::Object>(value);
}

template <>
inline Try<JSON::Array> parse(const std::string& value)
{
  // A value that already starts with 'file://' will properly be
  // loaded from the file and put into 'value' but if it starts with
  // '/' we need to explicitly handle it for backwards compatibility
  // reasons (because we used to handle it before we introduced the
  // 'fetch' mechanism for flags that first fetches the data from URIs
  // such as 'file://').
  if (strings::startsWith(value, "/")) {
    LOG(WARNING) << "Specifying an absolute filename to read a command line "
                    "option out of without using 'file:// is deprecated and "
                    "will be removed in a future release. Simply adding "
                    "'file://' to the beginning of the path should eliminate "
                    "this warning.";

    Try<std::string> read = os::read(value);
    if (read.isError()) {
      return Error("Error reading file '" + value + "': " + read.error());
    }
    return JSON::parse<JSON::Array>(read.get());
  }
  return JSON::parse<JSON::Array>(value);
}

template <>
inline Try<Path> parse(const std::string& value)
{
  return Path(value);
}

} // namespace flags {

#endif // __STOUT_FLAGS_PARSE_HPP__
<|endoftext|>