<commit_before>// Ouzel by Elviss Strazdins

#include "core/Engine.hpp"
#include "InputSample.hpp"
#include "MainMenu.hpp"

using namespace ouzel;
using namespace input;
using namespace math;

namespace samples
{
    InputSample::InputSample():
        hideButton{"button.png", "button_selected.png", "button_down.png", "", "Show/hide", "Arial", 1.0F, blackColor, blackColor, blackColor},
        discoverButton{"button.png", "button_selected.png", "button_down.png", "", "Discover gamepads", "Arial", 0.8F, blackColor, blackColor, blackColor},
        backButton{"button.png", "button_selected.png", "button_down.png", "", "Back", "Arial", 1.0F, blackColor, blackColor, blackColor},
        cursor{engine->getInputManager()}
    {
        cursor.init("cursor.png", Vector<float, 2>{0.0F, 63.0F});

        handler.keyboardHandler = [this](const KeyboardEvent& event) {
            if (event.type == Event::Type::keyboardKeyPress)
            {
                auto flamePosition = camera.convertWorldToNormalized(flame.getPosition());

                switch (event.key)
                {
                    case Keyboard::Key::up:
                        flamePosition.y() += 0.01F;
                        break;
                    case Keyboard::Key::down:
                        flamePosition.y() -= 0.01F;
                        break;
                    case Keyboard::Key::left:
                        flamePosition.x() -= 0.01F;
                        break;
                    case Keyboard::Key::right:
                        flamePosition.x() += 0.01F;
                        break;
                    case Keyboard::Key::r:
                        engine->getWindow().setSize(math::Size<std::uint32_t, 2>{640U, 480U});
                        break;
                    case Keyboard::Key::tab:
                        hideButton.setEnabled(!hideButton.isEnabled());
                        break;
                    case Keyboard::Key::escape:
                    case Keyboard::Key::menu:
                    case Keyboard::Key::back:
                        if (Mouse* mouse = engine->getInputManager().getMouse())
                            mouse->setCursorVisible(true);
                        engine->getSceneManager().setScene(std::make_unique<MainMenu>());
                        return true;
                    default:
                        break;
                }

                const auto worldLocation = Vector<float, 2>{camera.convertNormalizedToWorld(flamePosition)};

                flame.setPosition(worldLocation);
            }
            else if (event.type == Event::Type::keyboardKeyRelease)
            {
                switch (event.key)
                {
                    case Keyboard::Key::escape:
                    case Keyboard::Key::menu:
                    case Keyboard::Key::back:
                        return true;
                    default:
                        break;
                }
            }

            return false;
        };

        handler.mouseHandler = [this](const MouseEvent& event) {
            switch (event.type)
            {
                case Event::Type::mouseMove:
                {
                    const auto worldLocation = Vector<float, 2>{camera.convertNormalizedToWorld(event.position)};
                    flame.setPosition(worldLocation);
                    break;
                }
                default:
                    break;
            }

            return false;
        };

        handler.touchHandler = [this](const TouchEvent& event) {
            if (event.touchpad->isScreen())
            {
                const auto worldLocation = Vector<float, 2>{camera.convertNormalizedToWorld(event.position)};
                flame.setPosition(worldLocation);
            }

            return false;
        };

        handler.gamepadHandler = [this](const GamepadEvent& event) {
            if (event.type == Event::Type::gamepadButtonChange)
            {
                auto flamePosition = camera.convertWorldToNormalized(flame.getPosition());

                switch (event.button)
                {
                    case Gamepad::Button::faceRight:
                        if (event.pressed) engine->getSceneManager().setScene(std::make_unique<MainMenu>());
                        return false;
                    case Gamepad::Button::dPadUp:
                    case Gamepad::Button::leftThumbUp:
                    case Gamepad::Button::rightThumbUp:
                        flamePosition.y() = event.value / 2.0F + 0.5F;
                        break;
                    case Gamepad::Button::dPadDown:
                    case Gamepad::Button::leftThumbDown:
                    case Gamepad::Button::rightThumbDown:
                        flamePosition.y() = -event.value / 2.0F + 0.5F;
                        break;
                    case Gamepad::Button::dPadLeft:
                    case Gamepad::Button::leftThumbLeft:
                    case Gamepad::Button::rightThumbLeft:
                        flamePosition.x() = -event.value / 2.0F + 0.5F;
                        break;
                    case Gamepad::Button::dPadRight:
                    case Gamepad::Button::leftThumbRight:
                    case Gamepad::Button::rightThumbRight:
                        flamePosition.x() = event.value / 2.0F + 0.5F;
                        break;
                    default:
                        break;
                }

                const auto worldLocation = Vector<float, 2>{camera.convertNormalizedToWorld(flamePosition)};
                flame.setPosition(worldLocation);
            }

            return false;
        };

        handler.uiHandler = [this](const UIEvent& event) {
            if (event.type == Event::Type::actorClick)
            {
                if (event.actor == &backButton)
                {
                    if (Mouse* mouse = engine->getInputManager().getMouse())
                        mouse->setCursorVisible(true);
                    engine->getSceneManager().setScene(std::make_unique<MainMenu>());
                }
                else if (event.actor == &hideButton)
                {
                    if (Mouse* mouse = engine->getInputManager().getMouse())
                        mouse->setCursorVisible(!engine->getInputManager().getMouse()->isCursorVisible());
                }
                else if (event.actor == &discoverButton)
                    engine->getInputManager().startDeviceDiscovery();
            }

            return false;
        };

        engine->getEventDispatcher().addEventHandler(handler);

        camera.setClearColorBuffer(true);
        camera.setClearColor(math::Color{64, 0, 0});
        camera.setScaleMode(scene::Camera::ScaleMode::showAll);
        camera.setTargetContentSize(math::Size<float, 2>{800.0F, 600.0F});
        cameraActor.addComponent(camera);

        mover = std::make_unique<Mover>();
        cameraActor.addComponent(*mover);

        layer.addChild(cameraActor);
        addLayer(layer);

        flameParticleSystem.init(*engine->getCache().getParticleSystemData("flame.json"));

        flame.addComponent(flameParticleSystem);
        flame.setPickable(false);
        layer.addChild(flame);

        guiCamera.setScaleMode(scene::Camera::ScaleMode::showAll);
        guiCamera.setTargetContentSize(math::Size<float, 2>{800.0F, 600.0F});
        guiCameraActor.addComponent(guiCamera);
        guiLayer.addChild(guiCameraActor);
        addLayer(guiLayer);

        guiLayer.addChild(menu);

        hideButton.setPosition(Vector<float, 2>{-200.0F, 200.0F});
        menu.addWidget(hideButton);

        discoverButton.setPosition(Vector<float, 2>{-200.0F, 140.0F});
        menu.addWidget(discoverButton);

        backButton.setPosition(Vector<float, 2>{-200.0F, -200.0F});
        menu.addWidget(backButton);

        if (auto mouse = engine->getInputManager().getMouse())
        {
            mouse->setCursor(&cursor);

            const auto worldLocation = Vector<float, 2>{camera.convertNormalizedToWorld(mouse->getPosition())};
            flame.setPosition(worldLocation);
        }
    }
}
<commit_msg>Fix the direction of arrows in input sample<commit_after>// Ouzel by Elviss Strazdins

#include "core/Engine.hpp"
#include "InputSample.hpp"
#include "MainMenu.hpp"

using namespace ouzel;
using namespace input;
using namespace math;

namespace samples
{
    InputSample::InputSample():
        hideButton{"button.png", "button_selected.png", "button_down.png", "", "Show/hide", "Arial", 1.0F, blackColor, blackColor, blackColor},
        discoverButton{"button.png", "button_selected.png", "button_down.png", "", "Discover gamepads", "Arial", 0.8F, blackColor, blackColor, blackColor},
        backButton{"button.png", "button_selected.png", "button_down.png", "", "Back", "Arial", 1.0F, blackColor, blackColor, blackColor},
        cursor{engine->getInputManager()}
    {
        cursor.init("cursor.png", Vector<float, 2>{0.0F, 63.0F});

        handler.keyboardHandler = [this](const KeyboardEvent& event) {
            if (event.type == Event::Type::keyboardKeyPress)
            {
                auto flamePosition = camera.convertWorldToNormalized(flame.getPosition());

                switch (event.key)
                {
                    case Keyboard::Key::up:
                        flamePosition.y() -= 0.01F;
                        break;
                    case Keyboard::Key::down:
                        flamePosition.y() += 0.01F;
                        break;
                    case Keyboard::Key::left:
                        flamePosition.x() -= 0.01F;
                        break;
                    case Keyboard::Key::right:
                        flamePosition.x() += 0.01F;
                        break;
                    case Keyboard::Key::r:
                        engine->getWindow().setSize(math::Size<std::uint32_t, 2>{640U, 480U});
                        break;
                    case Keyboard::Key::tab:
                        hideButton.setEnabled(!hideButton.isEnabled());
                        break;
                    case Keyboard::Key::escape:
                    case Keyboard::Key::menu:
                    case Keyboard::Key::back:
                        if (Mouse* mouse = engine->getInputManager().getMouse())
                            mouse->setCursorVisible(true);
                        engine->getSceneManager().setScene(std::make_unique<MainMenu>());
                        return true;
                    default:
                        break;
                }

                const auto worldLocation = Vector<float, 2>{camera.convertNormalizedToWorld(flamePosition)};

                flame.setPosition(worldLocation);
            }
            else if (event.type == Event::Type::keyboardKeyRelease)
            {
                switch (event.key)
                {
                    case Keyboard::Key::escape:
                    case Keyboard::Key::menu:
                    case Keyboard::Key::back:
                        return true;
                    default:
                        break;
                }
            }

            return false;
        };

        handler.mouseHandler = [this](const MouseEvent& event) {
            switch (event.type)
            {
                case Event::Type::mouseMove:
                {
                    const auto worldLocation = Vector<float, 2>{camera.convertNormalizedToWorld(event.position)};
                    flame.setPosition(worldLocation);
                    break;
                }
                default:
                    break;
            }

            return false;
        };

        handler.touchHandler = [this](const TouchEvent& event) {
            if (event.touchpad->isScreen())
            {
                const auto worldLocation = Vector<float, 2>{camera.convertNormalizedToWorld(event.position)};
                flame.setPosition(worldLocation);
            }

            return false;
        };

        handler.gamepadHandler = [this](const GamepadEvent& event) {
            if (event.type == Event::Type::gamepadButtonChange)
            {
                auto flamePosition = camera.convertWorldToNormalized(flame.getPosition());

                switch (event.button)
                {
                    case Gamepad::Button::faceRight:
                        if (event.pressed) engine->getSceneManager().setScene(std::make_unique<MainMenu>());
                        return false;
                    case Gamepad::Button::dPadUp:
                    case Gamepad::Button::leftThumbUp:
                    case Gamepad::Button::rightThumbUp:
                        flamePosition.y() = event.value / 2.0F + 0.5F;
                        break;
                    case Gamepad::Button::dPadDown:
                    case Gamepad::Button::leftThumbDown:
                    case Gamepad::Button::rightThumbDown:
                        flamePosition.y() = -event.value / 2.0F + 0.5F;
                        break;
                    case Gamepad::Button::dPadLeft:
                    case Gamepad::Button::leftThumbLeft:
                    case Gamepad::Button::rightThumbLeft:
                        flamePosition.x() = -event.value / 2.0F + 0.5F;
                        break;
                    case Gamepad::Button::dPadRight:
                    case Gamepad::Button::leftThumbRight:
                    case Gamepad::Button::rightThumbRight:
                        flamePosition.x() = event.value / 2.0F + 0.5F;
                        break;
                    default:
                        break;
                }

                const auto worldLocation = Vector<float, 2>{camera.convertNormalizedToWorld(flamePosition)};
                flame.setPosition(worldLocation);
            }

            return false;
        };

        handler.uiHandler = [this](const UIEvent& event) {
            if (event.type == Event::Type::actorClick)
            {
                if (event.actor == &backButton)
                {
                    if (Mouse* mouse = engine->getInputManager().getMouse())
                        mouse->setCursorVisible(true);
                    engine->getSceneManager().setScene(std::make_unique<MainMenu>());
                }
                else if (event.actor == &hideButton)
                {
                    if (Mouse* mouse = engine->getInputManager().getMouse())
                        mouse->setCursorVisible(!engine->getInputManager().getMouse()->isCursorVisible());
                }
                else if (event.actor == &discoverButton)
                    engine->getInputManager().startDeviceDiscovery();
            }

            return false;
        };

        engine->getEventDispatcher().addEventHandler(handler);

        camera.setClearColorBuffer(true);
        camera.setClearColor(math::Color{64, 0, 0});
        camera.setScaleMode(scene::Camera::ScaleMode::showAll);
        camera.setTargetContentSize(math::Size<float, 2>{800.0F, 600.0F});
        cameraActor.addComponent(camera);

        mover = std::make_unique<Mover>();
        cameraActor.addComponent(*mover);

        layer.addChild(cameraActor);
        addLayer(layer);

        flameParticleSystem.init(*engine->getCache().getParticleSystemData("flame.json"));

        flame.addComponent(flameParticleSystem);
        flame.setPickable(false);
        layer.addChild(flame);

        guiCamera.setScaleMode(scene::Camera::ScaleMode::showAll);
        guiCamera.setTargetContentSize(math::Size<float, 2>{800.0F, 600.0F});
        guiCameraActor.addComponent(guiCamera);
        guiLayer.addChild(guiCameraActor);
        addLayer(guiLayer);

        guiLayer.addChild(menu);

        hideButton.setPosition(Vector<float, 2>{-200.0F, 200.0F});
        menu.addWidget(hideButton);

        discoverButton.setPosition(Vector<float, 2>{-200.0F, 140.0F});
        menu.addWidget(discoverButton);

        backButton.setPosition(Vector<float, 2>{-200.0F, -200.0F});
        menu.addWidget(backButton);

        if (auto mouse = engine->getInputManager().getMouse())
        {
            mouse->setCursor(&cursor);

            const auto worldLocation = Vector<float, 2>{camera.convertNormalizedToWorld(mouse->getPosition())};
            flame.setPosition(worldLocation);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2016 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/ColinH/PEGTL/

#ifndef PEGTL_CONTRIB_UNESCAPE_HH
#define PEGTL_CONTRIB_UNESCAPE_HH

#include <string>
#include <cassert>

#include <pegtl/ascii.hh>
#include <pegtl/parse_error.hh>

namespace pegtl
{
   namespace unescape
   {
      struct state
      {
         std::string unescaped;
      };

      // Utility functions for the unescape actions.

      inline bool utf8_append_utf32( std::string & string, const unsigned utf32 )
      {
         if ( utf32 <= 0x7f ) {
            string += char( utf32 & 0xff );
            return true;
         }
         else if ( utf32 <= 0x7ff ) {
            char tmp[] = { char( ( ( utf32 & 0x7c0 ) >> 6 ) | 0xc0 ),
                           char( ( ( utf32 & 0x03f )      ) | 0x80 ) };
            string.append( tmp, sizeof( tmp ) );
            return true;
         }
         else if ( utf32 <= 0xffff ) {
            char tmp[] = { char( ( ( utf32 & 0xf000 ) >> 12 ) | 0xe0 ),
                           char( ( ( utf32 & 0x0fc0 ) >> 6  ) | 0x80 ),
                           char( ( ( utf32 & 0x003f )       ) | 0x80 ) };
            string.append( tmp, sizeof( tmp ) );
            return true;
         }
         else if ( utf32 <= 0x10ffff ) {
            char tmp[] = { char( ( ( utf32 & 0x1c0000 ) >> 18 ) | 0xf0 ),
                           char( ( ( utf32 & 0x03f000 ) >> 12 ) | 0x80 ),
                           char( ( ( utf32 & 0x000fc0 ) >> 6  ) | 0x80 ),
                           char( ( ( utf32 & 0x00003f )       ) | 0x80 ) };
            string.append( tmp, sizeof( tmp ) );
            return true;
         }
         return false;
      }

      // This function MUST only be called for characters matching pegtl::ascii::xdigit!
      template< typename I >
      I unhex_char( const char c )
      {
         switch ( c ) {
            case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
               return I( c - '0' );
            case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
               return I( c - 'a' + 10 );
            case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
               return I( c - 'A' + 10 );
         }
         throw std::runtime_error( "invalid character in unhex" );  // LCOV_EXCL_LINE
      }

      template< typename I >
      I unhex_string( const char * begin, const char * const end )
      {
         I r = 0;
         while ( begin != end ) {
            r <<= 4;
            r += unhex_char< I >( *begin++ );
         }
         return r;
      }

      // Actions for common unescape situations.

      struct append_all
      {
         template< typename Input, typename State >
         static void apply( const Input & in, State & st )
         {
            st.unescaped.append( in.begin(), in.size() );
         }
      };

      // This action MUST be called for a character matching T which MUST be pegtl::one< ... >.
      template< typename T, char ... Rs >
      struct unescape_c
      {
         template< typename Input, typename State >
         static void apply( const Input & in, State & st )
         {
            assert( in.size() == 1 );
            st.unescaped += apply_one( * in.begin(), static_cast< const T * >( nullptr ) );
         }

         template< char ... Qs >
         static char apply_one( const char c, const one< Qs ... > * )
         {
            static_assert( sizeof ... ( Qs ) == sizeof ... ( Rs ), "size mismatch between escaped characters and their mappings" );
            return apply_two( c, { Qs ... }, { Rs ... } );
         }

         static char apply_two( const char c, const std::initializer_list< char > & q, const std::initializer_list< char > & r )
         {
            for ( std::size_t i = 0; i < q.size(); ++i ) {
               if ( * ( q.begin() + i ) == c ) {
                  return * ( r.begin() + i );
               }
            }
            throw std::runtime_error( "invalid character in unescape" );  // LCOV_EXCL_LINE
         }
      };

      // See examples/unescape.cc for why the following two actions
      // skip the first input character. They also MUST be called
      // with non-empty matched inputs!

      struct unescape_u
      {
         template< typename Input, typename State >
         static void apply( const Input & in, State & st )
         {
            assert( ! in.empty() );  // First character MUST be present, usually 'u' or 'U'.
            if ( ! utf8_append_utf32( st.unescaped, unhex_string< unsigned >( in.begin() + 1, in.end() ) ) ) {
               throw parse_error( "invalid escaped unicode code point", in );
            }
         }
      };

      struct unescape_x
      {
         template< typename Input, typename State >
         static void apply( const Input & in, State & st )
         {
            assert( ! in.empty() );  // First character MUST be present, usually 'x'.
            st.unescaped += unhex_string< char >( in.begin() + 1, in.end() );
         }
      };

      // The unescape_j action is similar to unescape_u, however unlike
      // unescape_u it
      // (a) assumes exactly 4 hexdigits per escape sequence,
      // (b) accepts multiple consecutive escaped 16-bit values.
      // When applied to more than one escape sequence, unescape_j
      // translates UTF-16 surrogate pairs in the input into a single
      // UTF-8 sequence in st.unescaped, as required for JSON by RFC 7159.

      struct unescape_j
      {
         template< typename Input, typename State >
         static void apply( const Input & in, State & st )
         {
            assert( ( ( in.size() + 1 ) % 6 ) == 0 );  // Expects multiple "\\u1234", starting with the first "u".
            for ( const char * b = in.begin() + 1; b < in.end(); b += 6 ) {
               const auto c = unhex_string< unsigned >( b, b + 4 );
               if ( ( 0xd800 <= c ) && ( c <= 0xdbff ) && ( b + 6 < in.end() ) ) {
                  const auto d = unhex_string< unsigned >( b + 6, b + 10 );
                  if ( ( 0xdc00 <= d ) && ( d <= 0xdfff ) ) {
                     b += 6;
                     utf8_append_utf32( st.unescaped, ( ( ( c & 0x03ff ) << 10 ) | ( d & 0x03ff ) ) + 0x10000 );
                     continue;
                  }
               }
               utf8_append_utf32( st.unescaped, c );
            }
         }
      };

   } // unescape

} // pegtl

#endif
<commit_msg>Fix includes<commit_after>// Copyright (c) 2014-2016 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/ColinH/PEGTL/

#ifndef PEGTL_CONTRIB_UNESCAPE_HH
#define PEGTL_CONTRIB_UNESCAPE_HH

#include <string>
#include <cassert>

#include "../ascii.hh"
#include "../parse_error.hh"

namespace pegtl
{
   namespace unescape
   {
      struct state
      {
         std::string unescaped;
      };

      // Utility functions for the unescape actions.

      inline bool utf8_append_utf32( std::string & string, const unsigned utf32 )
      {
         if ( utf32 <= 0x7f ) {
            string += char( utf32 & 0xff );
            return true;
         }
         else if ( utf32 <= 0x7ff ) {
            char tmp[] = { char( ( ( utf32 & 0x7c0 ) >> 6 ) | 0xc0 ),
                           char( ( ( utf32 & 0x03f )      ) | 0x80 ) };
            string.append( tmp, sizeof( tmp ) );
            return true;
         }
         else if ( utf32 <= 0xffff ) {
            char tmp[] = { char( ( ( utf32 & 0xf000 ) >> 12 ) | 0xe0 ),
                           char( ( ( utf32 & 0x0fc0 ) >> 6  ) | 0x80 ),
                           char( ( ( utf32 & 0x003f )       ) | 0x80 ) };
            string.append( tmp, sizeof( tmp ) );
            return true;
         }
         else if ( utf32 <= 0x10ffff ) {
            char tmp[] = { char( ( ( utf32 & 0x1c0000 ) >> 18 ) | 0xf0 ),
                           char( ( ( utf32 & 0x03f000 ) >> 12 ) | 0x80 ),
                           char( ( ( utf32 & 0x000fc0 ) >> 6  ) | 0x80 ),
                           char( ( ( utf32 & 0x00003f )       ) | 0x80 ) };
            string.append( tmp, sizeof( tmp ) );
            return true;
         }
         return false;
      }

      // This function MUST only be called for characters matching pegtl::ascii::xdigit!
      template< typename I >
      I unhex_char( const char c )
      {
         switch ( c ) {
            case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
               return I( c - '0' );
            case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
               return I( c - 'a' + 10 );
            case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
               return I( c - 'A' + 10 );
         }
         throw std::runtime_error( "invalid character in unhex" );  // LCOV_EXCL_LINE
      }

      template< typename I >
      I unhex_string( const char * begin, const char * const end )
      {
         I r = 0;
         while ( begin != end ) {
            r <<= 4;
            r += unhex_char< I >( *begin++ );
         }
         return r;
      }

      // Actions for common unescape situations.

      struct append_all
      {
         template< typename Input, typename State >
         static void apply( const Input & in, State & st )
         {
            st.unescaped.append( in.begin(), in.size() );
         }
      };

      // This action MUST be called for a character matching T which MUST be pegtl::one< ... >.
      template< typename T, char ... Rs >
      struct unescape_c
      {
         template< typename Input, typename State >
         static void apply( const Input & in, State & st )
         {
            assert( in.size() == 1 );
            st.unescaped += apply_one( * in.begin(), static_cast< const T * >( nullptr ) );
         }

         template< char ... Qs >
         static char apply_one( const char c, const one< Qs ... > * )
         {
            static_assert( sizeof ... ( Qs ) == sizeof ... ( Rs ), "size mismatch between escaped characters and their mappings" );
            return apply_two( c, { Qs ... }, { Rs ... } );
         }

         static char apply_two( const char c, const std::initializer_list< char > & q, const std::initializer_list< char > & r )
         {
            for ( std::size_t i = 0; i < q.size(); ++i ) {
               if ( * ( q.begin() + i ) == c ) {
                  return * ( r.begin() + i );
               }
            }
            throw std::runtime_error( "invalid character in unescape" );  // LCOV_EXCL_LINE
         }
      };

      // See examples/unescape.cc for why the following two actions
      // skip the first input character. They also MUST be called
      // with non-empty matched inputs!

      struct unescape_u
      {
         template< typename Input, typename State >
         static void apply( const Input & in, State & st )
         {
            assert( ! in.empty() );  // First character MUST be present, usually 'u' or 'U'.
            if ( ! utf8_append_utf32( st.unescaped, unhex_string< unsigned >( in.begin() + 1, in.end() ) ) ) {
               throw parse_error( "invalid escaped unicode code point", in );
            }
         }
      };

      struct unescape_x
      {
         template< typename Input, typename State >
         static void apply( const Input & in, State & st )
         {
            assert( ! in.empty() );  // First character MUST be present, usually 'x'.
            st.unescaped += unhex_string< char >( in.begin() + 1, in.end() );
         }
      };

      // The unescape_j action is similar to unescape_u, however unlike
      // unescape_u it
      // (a) assumes exactly 4 hexdigits per escape sequence,
      // (b) accepts multiple consecutive escaped 16-bit values.
      // When applied to more than one escape sequence, unescape_j
      // translates UTF-16 surrogate pairs in the input into a single
      // UTF-8 sequence in st.unescaped, as required for JSON by RFC 7159.

      struct unescape_j
      {
         template< typename Input, typename State >
         static void apply( const Input & in, State & st )
         {
            assert( ( ( in.size() + 1 ) % 6 ) == 0 );  // Expects multiple "\\u1234", starting with the first "u".
            for ( const char * b = in.begin() + 1; b < in.end(); b += 6 ) {
               const auto c = unhex_string< unsigned >( b, b + 4 );
               if ( ( 0xd800 <= c ) && ( c <= 0xdbff ) && ( b + 6 < in.end() ) ) {
                  const auto d = unhex_string< unsigned >( b + 6, b + 10 );
                  if ( ( 0xdc00 <= d ) && ( d <= 0xdfff ) ) {
                     b += 6;
                     utf8_append_utf32( st.unescaped, ( ( ( c & 0x03ff ) << 10 ) | ( d & 0x03ff ) ) + 0x10000 );
                     continue;
                  }
               }
               utf8_append_utf32( st.unescaped, c );
            }
         }
      };

   } // unescape

} // pegtl

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015, 2016 arduino-menusystem
 * Licensed under the MIT license (see LICENSE)
 */

#include "MenuSystem.h"
#include <stdlib.h>

// *********************************************************
// MenuComponent
// *********************************************************

MenuComponent::MenuComponent(const char* name)
: _name(name),
  _has_focus(false)
{
}

const char* MenuComponent::get_name() const
{
    return _name;
}

void MenuComponent::set_name(const char* name)
{
    _name = name;
}

bool MenuComponent::has_focus() const
{
    return _has_focus;
}

// *********************************************************
// Menu
// *********************************************************

Menu::Menu(const char* name)
: MenuComponent(name),
  _p_cur_menu_component(nullptr),
  _menu_components(nullptr),
  _p_parent(nullptr),
  _num_menu_components(0),
  _cur_menu_component_num(0),
  _prev_menu_component_num(0)
{
}

bool Menu::next(bool loop)
{
    _prev_menu_component_num = _cur_menu_component_num;

    if (!_num_menu_components)
    {
        return false;
    }
    else if (_cur_menu_component_num != _num_menu_components - 1)
    {
        _cur_menu_component_num++;
        _p_cur_menu_component = _menu_components[_cur_menu_component_num];

        return true;
    }
    else if (loop)
    {
        _cur_menu_component_num = 0;
        _p_cur_menu_component = _menu_components[_cur_menu_component_num];

        return true;
    }
    return false;
}

bool Menu::prev(bool loop)
{
    _prev_menu_component_num = _cur_menu_component_num;

    if (!_num_menu_components)
    {
        return false;
    }
    else if (_cur_menu_component_num != 0)
    {
        _cur_menu_component_num--;
        _p_cur_menu_component = _menu_components[_cur_menu_component_num];

        return true;
    }
    else if (loop)
    {
        _cur_menu_component_num = _num_menu_components - 1;
        _p_cur_menu_component = _menu_components[_cur_menu_component_num];

        return true;
    }
    return false;
}

Menu* Menu::activate()
{
    if (!_num_menu_components)
        return nullptr;

    MenuComponent* pComponent = _menu_components[_cur_menu_component_num];

    if (pComponent == nullptr)
        return nullptr;

    return pComponent->select();
}

Menu* Menu::select()
{
    return this;
}

void Menu::reset()
{
    for (int i = 0; i < _num_menu_components; ++i)
        _menu_components[i]->reset();

    _prev_menu_component_num = 0;
    _cur_menu_component_num = 0;
    _p_cur_menu_component = _num_menu_components ? _menu_components[0] : nullptr;
}

void Menu::add_item(MenuItem* pItem)
{
    // Resize menu component list, keeping existing items.
    // If it fails, there the item is not added and the function returns.
    _menu_components = (MenuComponent**) realloc(_menu_components,
                                                 (_num_menu_components + 1)
                                                 * sizeof(MenuComponent*));
    if (_menu_components == nullptr)
      return;

    _menu_components[_num_menu_components] = pItem;

    if (_num_menu_components == 0)
        _p_cur_menu_component = pItem;

    _num_menu_components++;
}

Menu const* Menu::get_parent() const
{
    return _p_parent;
}

void Menu::set_parent(Menu* pParent)
{
    _p_parent = pParent;
}

void Menu::add_menu(Menu* pMenu)
{
    // Resize menu component list, keeping existing items.
    // If it fails, there the item is not added and the function returns.
    _menu_components = (MenuComponent**) realloc(_menu_components,
                                                 (_num_menu_components + 1)
                                                 * sizeof(MenuComponent*));
    if (_menu_components == nullptr)
      return;

    pMenu->set_parent(this);

    _menu_components[_num_menu_components] = pMenu;

    if (_num_menu_components == 0)
        _p_cur_menu_component = pMenu;

    _num_menu_components++;
}

MenuComponent const* Menu::get_menu_component(byte index) const
{
    return _menu_components[index];
}

MenuComponent const* Menu::get_current_component() const
{
    return _p_cur_menu_component;
}

byte Menu::get_num_menu_components() const
{
    return _num_menu_components;
}

byte Menu::get_cur_menu_component_num() const
{
    return _cur_menu_component_num;
}

byte Menu::get_prev_menu_component_num() const
{
    return _prev_menu_component_num;
}

void Menu::render(MenuComponentRenderer const& renderer) const
{
    renderer.render_menu(*this);
}

// *********************************************************
// BackMenuItem
// *********************************************************

BackMenuItem::BackMenuItem(const char* name, SelectFnPtr select_fn,
                           MenuSystem* ms)
: MenuItem(name, select_fn),
  menu_system(ms)
{
}

Menu* BackMenuItem::select()
{
    if (_select_fn!=nullptr)
        _select_fn(this);

    if (menu_system!=nullptr)
        menu_system->back();

    return nullptr;
}

void BackMenuItem::render(MenuComponentRenderer const& renderer) const
{
    renderer.render_back_menu_item(*this);
}

// *********************************************************
// MenuItem
// *********************************************************

MenuItem::MenuItem(const char* name, SelectFnPtr select_fn)
: MenuComponent(name),
  _select_fn(select_fn)
{
}

void MenuItem::set_select_function(SelectFnPtr select_fn)
{
    _select_fn = select_fn;
}

Menu* MenuItem::select()
{
    if (_select_fn != nullptr)
        _select_fn(this);

    return nullptr;
}

void MenuItem::reset()
{
    // Do nothing.
}

void MenuItem::render(MenuComponentRenderer const& renderer) const
{
    renderer.render_menu_item(*this);
}

bool MenuItem::next(bool loop)
{
    return false;
}

bool MenuItem::prev(bool loop)
{
    return false;
}

// *********************************************************
// NumericMenuItem
// *********************************************************

NumericMenuItem::NumericMenuItem(const char* basename, SelectFnPtr select_fn,
                                 float value, float minValue, float maxValue,
                                 float increment,
                                 FormatValueFnPtr format_value_fn)
: MenuItem(basename, select_fn),
  _value(value),
  _minValue(minValue),
  _maxValue(maxValue),
  _increment(increment),
  _format_value_fn(format_value_fn)
{
    if (_increment < 0.0) _increment = -_increment;
    if (_minValue > _maxValue)
    {
        float tmp = _maxValue;
        _maxValue = _minValue;
        _minValue = tmp;
    }
};

void NumericMenuItem::set_number_formatter(FormatValueFnPtr format_value_fn)
{
    _format_value_fn = format_value_fn;
}

Menu* NumericMenuItem::select()
{
    _has_focus = !_has_focus;

    // Only run _select_fn when the user is done editing the value
    if (!_has_focus && _select_fn != nullptr)
        _select_fn(this);
    return nullptr;
}

void NumericMenuItem::render(MenuComponentRenderer const& renderer) const
{
    renderer.render_numeric_menu_item(*this);
}

float NumericMenuItem::get_value() const
{
    return _value;
}

float NumericMenuItem::get_minValue() const
{
    return _minValue;
}

float NumericMenuItem::get_maxValue() const
{
    return _maxValue;
}

String NumericMenuItem::get_value_string() const
{
    String buffer;
    if (_format_value_fn != nullptr)
        buffer += _format_value_fn(_value);
    else
        buffer += _value;
    return buffer;
}

void NumericMenuItem::set_value(float value)
{
    _value = value;
}

bool NumericMenuItem::next(bool loop)
{
    _value += _increment;
    if (_value > _maxValue)
        if (loop)
            _value = _minValue;
        else
            _value = _maxValue;
    return true;
}

bool NumericMenuItem::prev(bool loop)
{
    _value -= _increment;
    if (_value < _minValue)
        if (loop)
            _value = _maxValue;
        else
            _value = _minValue;
    return true;
}

// *********************************************************
// MenuSystem
// *********************************************************

MenuSystem::MenuSystem(MenuComponentRenderer const& renderer)
: _p_root_menu(new Menu("")),
  _p_curr_menu(_p_root_menu),
  _renderer(renderer)
{
}

bool MenuSystem::next(bool loop)
{
    if (_p_curr_menu->_p_cur_menu_component->has_focus())
        return _p_curr_menu->_p_cur_menu_component->next(loop);
    else
        return _p_curr_menu->next(loop);
}

bool MenuSystem::prev(bool loop)
{
    if (_p_curr_menu->_p_cur_menu_component->has_focus())
        return _p_curr_menu->_p_cur_menu_component->prev(loop);
    else
        return _p_curr_menu->prev(loop);
}

void MenuSystem::reset()
{
    _p_curr_menu = _p_root_menu;
    _p_root_menu->reset();
}

void MenuSystem::select(bool reset)
{
    Menu* pMenu = _p_curr_menu->activate();

    if (pMenu != nullptr)
        _p_curr_menu = pMenu;
    else
        if (reset)
            this->reset();
}

bool MenuSystem::back()
{
    if (_p_curr_menu != _p_root_menu)
    {
        _p_curr_menu = const_cast<Menu*>(_p_curr_menu->get_parent());
        return true;
    }

    // We are already in the root menu
    return false;
}

Menu& MenuSystem::get_root_menu() const
{
    return *_p_root_menu;
}

Menu const* MenuSystem::get_current_menu() const
{
    return _p_curr_menu;
}

void MenuSystem::display() const
{
    if (_p_curr_menu != nullptr)
        _renderer.render(*_p_curr_menu);
}
<commit_msg>Fix ambiguous else compiler warning<commit_after>/*
 * Copyright (c) 2015, 2016 arduino-menusystem
 * Licensed under the MIT license (see LICENSE)
 */

#include "MenuSystem.h"
#include <stdlib.h>

// *********************************************************
// MenuComponent
// *********************************************************

MenuComponent::MenuComponent(const char* name)
: _name(name),
  _has_focus(false)
{
}

const char* MenuComponent::get_name() const
{
    return _name;
}

void MenuComponent::set_name(const char* name)
{
    _name = name;
}

bool MenuComponent::has_focus() const
{
    return _has_focus;
}

// *********************************************************
// Menu
// *********************************************************

Menu::Menu(const char* name)
: MenuComponent(name),
  _p_cur_menu_component(nullptr),
  _menu_components(nullptr),
  _p_parent(nullptr),
  _num_menu_components(0),
  _cur_menu_component_num(0),
  _prev_menu_component_num(0)
{
}

bool Menu::next(bool loop)
{
    _prev_menu_component_num = _cur_menu_component_num;

    if (!_num_menu_components)
    {
        return false;
    }
    else if (_cur_menu_component_num != _num_menu_components - 1)
    {
        _cur_menu_component_num++;
        _p_cur_menu_component = _menu_components[_cur_menu_component_num];

        return true;
    }
    else if (loop)
    {
        _cur_menu_component_num = 0;
        _p_cur_menu_component = _menu_components[_cur_menu_component_num];

        return true;
    }
    return false;
}

bool Menu::prev(bool loop)
{
    _prev_menu_component_num = _cur_menu_component_num;

    if (!_num_menu_components)
    {
        return false;
    }
    else if (_cur_menu_component_num != 0)
    {
        _cur_menu_component_num--;
        _p_cur_menu_component = _menu_components[_cur_menu_component_num];

        return true;
    }
    else if (loop)
    {
        _cur_menu_component_num = _num_menu_components - 1;
        _p_cur_menu_component = _menu_components[_cur_menu_component_num];

        return true;
    }
    return false;
}

Menu* Menu::activate()
{
    if (!_num_menu_components)
        return nullptr;

    MenuComponent* pComponent = _menu_components[_cur_menu_component_num];

    if (pComponent == nullptr)
        return nullptr;

    return pComponent->select();
}

Menu* Menu::select()
{
    return this;
}

void Menu::reset()
{
    for (int i = 0; i < _num_menu_components; ++i)
        _menu_components[i]->reset();

    _prev_menu_component_num = 0;
    _cur_menu_component_num = 0;
    _p_cur_menu_component = _num_menu_components ? _menu_components[0] : nullptr;
}

void Menu::add_item(MenuItem* pItem)
{
    // Resize menu component list, keeping existing items.
    // If it fails, there the item is not added and the function returns.
    _menu_components = (MenuComponent**) realloc(_menu_components,
                                                 (_num_menu_components + 1)
                                                 * sizeof(MenuComponent*));
    if (_menu_components == nullptr)
      return;

    _menu_components[_num_menu_components] = pItem;

    if (_num_menu_components == 0)
        _p_cur_menu_component = pItem;

    _num_menu_components++;
}

Menu const* Menu::get_parent() const
{
    return _p_parent;
}

void Menu::set_parent(Menu* pParent)
{
    _p_parent = pParent;
}

void Menu::add_menu(Menu* pMenu)
{
    // Resize menu component list, keeping existing items.
    // If it fails, there the item is not added and the function returns.
    _menu_components = (MenuComponent**) realloc(_menu_components,
                                                 (_num_menu_components + 1)
                                                 * sizeof(MenuComponent*));
    if (_menu_components == nullptr)
      return;

    pMenu->set_parent(this);

    _menu_components[_num_menu_components] = pMenu;

    if (_num_menu_components == 0)
        _p_cur_menu_component = pMenu;

    _num_menu_components++;
}

MenuComponent const* Menu::get_menu_component(byte index) const
{
    return _menu_components[index];
}

MenuComponent const* Menu::get_current_component() const
{
    return _p_cur_menu_component;
}

byte Menu::get_num_menu_components() const
{
    return _num_menu_components;
}

byte Menu::get_cur_menu_component_num() const
{
    return _cur_menu_component_num;
}

byte Menu::get_prev_menu_component_num() const
{
    return _prev_menu_component_num;
}

void Menu::render(MenuComponentRenderer const& renderer) const
{
    renderer.render_menu(*this);
}

// *********************************************************
// BackMenuItem
// *********************************************************

BackMenuItem::BackMenuItem(const char* name, SelectFnPtr select_fn,
                           MenuSystem* ms)
: MenuItem(name, select_fn),
  menu_system(ms)
{
}

Menu* BackMenuItem::select()
{
    if (_select_fn!=nullptr)
        _select_fn(this);

    if (menu_system!=nullptr)
        menu_system->back();

    return nullptr;
}

void BackMenuItem::render(MenuComponentRenderer const& renderer) const
{
    renderer.render_back_menu_item(*this);
}

// *********************************************************
// MenuItem
// *********************************************************

MenuItem::MenuItem(const char* name, SelectFnPtr select_fn)
: MenuComponent(name),
  _select_fn(select_fn)
{
}

void MenuItem::set_select_function(SelectFnPtr select_fn)
{
    _select_fn = select_fn;
}

Menu* MenuItem::select()
{
    if (_select_fn != nullptr)
        _select_fn(this);

    return nullptr;
}

void MenuItem::reset()
{
    // Do nothing.
}

void MenuItem::render(MenuComponentRenderer const& renderer) const
{
    renderer.render_menu_item(*this);
}

bool MenuItem::next(bool loop)
{
    return false;
}

bool MenuItem::prev(bool loop)
{
    return false;
}

// *********************************************************
// NumericMenuItem
// *********************************************************

NumericMenuItem::NumericMenuItem(const char* basename, SelectFnPtr select_fn,
                                 float value, float minValue, float maxValue,
                                 float increment,
                                 FormatValueFnPtr format_value_fn)
: MenuItem(basename, select_fn),
  _value(value),
  _minValue(minValue),
  _maxValue(maxValue),
  _increment(increment),
  _format_value_fn(format_value_fn)
{
    if (_increment < 0.0) _increment = -_increment;
    if (_minValue > _maxValue)
    {
        float tmp = _maxValue;
        _maxValue = _minValue;
        _minValue = tmp;
    }
};

void NumericMenuItem::set_number_formatter(FormatValueFnPtr format_value_fn)
{
    _format_value_fn = format_value_fn;
}

Menu* NumericMenuItem::select()
{
    _has_focus = !_has_focus;

    // Only run _select_fn when the user is done editing the value
    if (!_has_focus && _select_fn != nullptr)
        _select_fn(this);
    return nullptr;
}

void NumericMenuItem::render(MenuComponentRenderer const& renderer) const
{
    renderer.render_numeric_menu_item(*this);
}

float NumericMenuItem::get_value() const
{
    return _value;
}

float NumericMenuItem::get_minValue() const
{
    return _minValue;
}

float NumericMenuItem::get_maxValue() const
{
    return _maxValue;
}

String NumericMenuItem::get_value_string() const
{
    String buffer;
    if (_format_value_fn != nullptr)
        buffer += _format_value_fn(_value);
    else
        buffer += _value;
    return buffer;
}

void NumericMenuItem::set_value(float value)
{
    _value = value;
}

bool NumericMenuItem::next(bool loop)
{
    _value += _increment;
    if (_value > _maxValue)
    {
        if (loop)
            _value = _minValue;
        else
            _value = _maxValue;
    }
    return true;
}

bool NumericMenuItem::prev(bool loop)
{
    _value -= _increment;
    if (_value < _minValue)
    {
        if (loop)
            _value = _maxValue;
        else
            _value = _minValue;
    }
    return true;
}

// *********************************************************
// MenuSystem
// *********************************************************

MenuSystem::MenuSystem(MenuComponentRenderer const& renderer)
: _p_root_menu(new Menu("")),
  _p_curr_menu(_p_root_menu),
  _renderer(renderer)
{
}

bool MenuSystem::next(bool loop)
{
    if (_p_curr_menu->_p_cur_menu_component->has_focus())
        return _p_curr_menu->_p_cur_menu_component->next(loop);
    else
        return _p_curr_menu->next(loop);
}

bool MenuSystem::prev(bool loop)
{
    if (_p_curr_menu->_p_cur_menu_component->has_focus())
        return _p_curr_menu->_p_cur_menu_component->prev(loop);
    else
        return _p_curr_menu->prev(loop);
}

void MenuSystem::reset()
{
    _p_curr_menu = _p_root_menu;
    _p_root_menu->reset();
}

void MenuSystem::select(bool reset)
{
    Menu* pMenu = _p_curr_menu->activate();

    if (pMenu != nullptr)
        _p_curr_menu = pMenu;
    else
        if (reset)
            this->reset();
}

bool MenuSystem::back()
{
    if (_p_curr_menu != _p_root_menu)
    {
        _p_curr_menu = const_cast<Menu*>(_p_curr_menu->get_parent());
        return true;
    }

    // We are already in the root menu
    return false;
}

Menu& MenuSystem::get_root_menu() const
{
    return *_p_root_menu;
}

Menu const* MenuSystem::get_current_menu() const
{
    return _p_curr_menu;
}

void MenuSystem::display() const
{
    if (_p_curr_menu != nullptr)
        _renderer.render(*_p_curr_menu);
}
<|endoftext|>


<commit_before>#include "b5mc_scd_generator.h"
#include "b5m_types.h"
#include "b5m_mode.h"
#include "b5m_helper.h"
#include <common/ScdParser.h>
#include <common/ScdWriter.h>
#include <common/Utilities.h>
#include <product-manager/product_price.h>
#include <product-manager/uuid_generator.h>
#include <am/sequence_file/ssfr.h>
#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include <glog/logging.h>

using namespace sf1r;
//#define B5MC_DEBUG

B5mcScdGenerator::B5mcScdGenerator(CommentDb* cdb, OfferDbRecorder* odb, BrandDb* bdb, ProductMatcher* matcher, int mode)
:cdb_(cdb), odb_(odb), bdb_(bdb), matcher_(matcher), mode_(mode)
{
}

bool B5mcScdGenerator::Generate(const std::string& scd_path, const std::string& mdb_instance)
{
    if(!cdb_->is_open())
    {
        if(!cdb_->open())
        {
            LOG(ERROR)<<"cdb open fail"<<std::endl;
            return false;
        }
    }
    LOG(INFO)<<"cdb count "<<cdb_->Count()<<std::endl;
    if(!odb_->is_open())
    {
        if(!odb_->open())
        {
            LOG(ERROR)<<"odb open fail"<<std::endl;
            return false;
        }
    }
    if(bdb_!=NULL)
    {
        if(!bdb_->is_open())
        {
            if(!bdb_->open())
            {
                LOG(ERROR)<<"bdb open error"<<std::endl;
                return false;
            }
        }
    }
    std::vector<std::string> scd_list;
    B5MHelper::GetScdList(scd_path, scd_list);
    if(scd_list.empty())
    {
        LOG(WARNING)<<"scd path empty"<<std::endl;
        return true;
    }
    static const std::string oid_property_name = "ProdDocid";
    std::string output_dir = B5MHelper::GetB5mcPath(mdb_instance);
    B5MHelper::PrepareEmptyDir(output_dir);
    ScdWriter b5mc_u(output_dir, UPDATE_SCD);
    std::size_t new_count = 0;
    std::size_t pid_changed_count = 0;
    for(uint32_t i=0;i<scd_list.size();i++)
    {
        std::string scd_file = scd_list[i];
        int type = ScdParser::checkSCDType(scd_file);
        if(type==DELETE_SCD) continue;
        LOG(INFO)<<"Processing "<<scd_file<<std::endl;
        ScdParser parser(izenelib::util::UString::UTF_8);
        parser.load(scd_file);
        uint32_t n=0;
        for( ScdParser::iterator doc_iter = parser.begin();
          doc_iter!= parser.end(); ++doc_iter, ++n)
        {
            if(n%100000==0)
            {
                LOG(INFO)<<"Find Documents "<<n<<","<<new_count<<","<<pid_changed_count<<std::endl;
            }
            Document doc;
            SCDDoc& scddoc = *(*doc_iter);
            SCDDoc::iterator p = scddoc.begin();
            for(; p!=scddoc.end(); ++p)
            {
                const std::string& property_name = p->first;
                doc.property(property_name) = p->second;
            }
            doc.eraseProperty("uuid");
            doc.eraseProperty(B5MHelper::GetBrandPropertyName());
            std::string scid;
            doc.getString("DOCID", scid);
            if(scid.empty()) continue;
            uint128_t cid = B5MHelper::StringToUint128(scid);
            bool has_oid = false;
            std::string soid;
            doc.getString(oid_property_name, soid);
            if(!soid.empty()) has_oid = true;

            bool is_new_cid = true;
            if(cdb_->Get(cid))
            {
                is_new_cid = false;
            }
            else {
                cdb_->Insert(cid);
                new_count++;
            }
            //if(mode_==B5MMode::INC&&cdb_->Count()==0)
            //{
                //is_new_cid = false;
            //}
            //else{
            //}
            //{
                //bool test_is_new_cid = true;
                //if(uset.find(cid)!=uset.end())
                //{
                    //test_is_new_cid = false;
                //}
                //else
                //{
                    //uset.insert(cid);
                //}
                //if(is_new_cid!=test_is_new_cid)
                //{
                    //LOG(ERROR)<<"filter error on "<<scid<<std::endl;
                //}
            //}
            std::string spid;
            bool pid_changed = false;
            if(has_oid)
            {
                odb_->get(soid, spid, pid_changed);
            }
            if(pid_changed)
            {
                pid_changed_count++;
#ifdef B5MC_DEBUG
                std::string last_spid;
                odb_->get_last(soid, last_spid);
                LOG(INFO)<<soid<<" changed from "<<last_spid<<" to "<<spid<<std::endl;
#endif
            }
            if(!spid.empty())
            {
                doc.property("uuid") = UString(spid, UString::UTF_8);
            }
            //std::cerr<<is_new_cid<<","<<pid_changed<<","<<spid<<std::endl;
            bool need_process = is_new_cid || pid_changed;
            if(!need_process) continue;
            ProcessFurther_(doc);
            spid.clear();
            doc.getString("uuid", spid);
            if(spid.empty()) continue;
            b5mc_u.Append(doc);
        }
    }
    b5mc_u.Close();
    cdb_->flush();
    LOG(INFO)<<"new cid "<<new_count<<", pid_changed "<<pid_changed_count<<std::endl;
    return true;
}

void B5mcScdGenerator::ProcessFurther_(Document& doc)
{
    static const std::string title_property_name = "ProdName";
    std::string spid;
    doc.getString("uuid", spid);
    if(spid.empty())
    {
        ProductMatcher::Product product;
        std::string isbn;
        if(ProductMatcher::GetIsbnAttribute(doc, isbn))
        {
            Document book_doc;
            book_doc.property("Category") = UString(B5MHelper::BookCategoryName(), UString::UTF_8);
            book_doc.property("Attribute") = doc.property("Attribute");
            ProductMatcher::ProcessBook(book_doc, product);
        }
        else
        {
            UString title;
            doc.getProperty(title_property_name, title);
            if(!title.empty())
            {
                Document matcher_doc;
                matcher_doc.property("Title") = title;
                ProductMatcher* matcher = GetMatcher_();
                if(matcher!=NULL)
                {
                    matcher->Process(matcher_doc, product);
                }
            }
        }
        if(!product.spid.empty())
        {
            spid = product.spid;
        }
    }
    if(!spid.empty() && bdb_!=NULL)
    {
        uint128_t pid = B5MHelper::StringToUint128(spid);
        izenelib::util::UString brand;
        bdb_->get(pid, brand);
        if(brand.length()>0)
        {
            doc.property(B5MHelper::GetBrandPropertyName()) = brand;
        }
    }
    if(!spid.empty())
    {
        doc.property("uuid") = UString(spid, UString::UTF_8);
    }
}

ProductMatcher* B5mcScdGenerator::GetMatcher_()
{
    if(matcher_==NULL) return NULL;
    //if(!matcher_->IsOpen())
    //{
        //matcher_->Open();
        //matcher_->SetUsePriceSim(false);
    //}
    return matcher_;
}
<commit_msg>tiny b5mc output<commit_after>#include "b5mc_scd_generator.h"
#include "b5m_types.h"
#include "b5m_mode.h"
#include "b5m_helper.h"
#include <common/ScdParser.h>
#include <common/ScdWriter.h>
#include <common/Utilities.h>
#include <product-manager/product_price.h>
#include <product-manager/uuid_generator.h>
#include <am/sequence_file/ssfr.h>
#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include <glog/logging.h>

using namespace sf1r;
//#define B5MC_DEBUG

B5mcScdGenerator::B5mcScdGenerator(CommentDb* cdb, OfferDbRecorder* odb, BrandDb* bdb, ProductMatcher* matcher, int mode)
:cdb_(cdb), odb_(odb), bdb_(bdb), matcher_(matcher), mode_(mode)
{
}

bool B5mcScdGenerator::Generate(const std::string& scd_path, const std::string& mdb_instance)
{
    if(!cdb_->is_open())
    {
        if(!cdb_->open())
        {
            LOG(ERROR)<<"cdb open fail"<<std::endl;
            return false;
        }
    }
    LOG(INFO)<<"cdb count "<<cdb_->Count()<<std::endl;
    if(!odb_->is_open())
    {
        if(!odb_->open())
        {
            LOG(ERROR)<<"odb open fail"<<std::endl;
            return false;
        }
    }
    if(bdb_!=NULL)
    {
        if(!bdb_->is_open())
        {
            if(!bdb_->open())
            {
                LOG(ERROR)<<"bdb open error"<<std::endl;
                return false;
            }
        }
    }
    std::vector<std::string> scd_list;
    B5MHelper::GetScdList(scd_path, scd_list);
    if(scd_list.empty())
    {
        LOG(WARNING)<<"scd path empty"<<std::endl;
        return true;
    }
    static const std::string oid_property_name = "ProdDocid";
    std::string output_dir = B5MHelper::GetB5mcPath(mdb_instance);
    B5MHelper::PrepareEmptyDir(output_dir);
    ScdWriter b5mc_u(output_dir, UPDATE_SCD);
    std::size_t new_count = 0;
    std::size_t pid_changed_count = 0;
    std::size_t pid_not_changed_count = 0;
    for(uint32_t i=0;i<scd_list.size();i++)
    {
        std::string scd_file = scd_list[i];
        int type = ScdParser::checkSCDType(scd_file);
        if(type==DELETE_SCD) continue;
        LOG(INFO)<<"Processing "<<scd_file<<std::endl;
        ScdParser parser(izenelib::util::UString::UTF_8);
        parser.load(scd_file);
        uint32_t n=0;
        for( ScdParser::iterator doc_iter = parser.begin();
          doc_iter!= parser.end(); ++doc_iter, ++n)
        {
            if(n%100000==0)
            {
                LOG(INFO)<<"Find Documents "<<n<<","<<new_count<<","<<pid_changed_count<<","<<pid_not_changed_count<<std::endl;
            }
            Document doc;
            SCDDoc& scddoc = *(*doc_iter);
            SCDDoc::iterator p = scddoc.begin();
            for(; p!=scddoc.end(); ++p)
            {
                const std::string& property_name = p->first;
                doc.property(property_name) = p->second;
            }
            doc.eraseProperty("uuid");
            doc.eraseProperty(B5MHelper::GetBrandPropertyName());
            std::string scid;
            doc.getString("DOCID", scid);
            if(scid.empty()) continue;
            uint128_t cid = B5MHelper::StringToUint128(scid);
            bool has_oid = false;
            std::string soid;
            doc.getString(oid_property_name, soid);
            if(!soid.empty()) has_oid = true;

            bool is_new_cid = true;
            if(cdb_->Get(cid))
            {
                is_new_cid = false;
            }
            else {
                cdb_->Insert(cid);
                new_count++;
            }
            //if(mode_==B5MMode::INC&&cdb_->Count()==0)
            //{
                //is_new_cid = false;
            //}
            //else{
            //}
            //{
                //bool test_is_new_cid = true;
                //if(uset.find(cid)!=uset.end())
                //{
                    //test_is_new_cid = false;
                //}
                //else
                //{
                    //uset.insert(cid);
                //}
                //if(is_new_cid!=test_is_new_cid)
                //{
                    //LOG(ERROR)<<"filter error on "<<scid<<std::endl;
                //}
            //}
            std::string spid;
            bool pid_changed = false;
            if(has_oid)
            {
                odb_->get(soid, spid, pid_changed);
            }
            if(pid_changed)
            {
                pid_changed_count++;
#ifdef B5MC_DEBUG
                std::string last_spid;
                odb_->get_last(soid, last_spid);
                LOG(INFO)<<soid<<" changed from "<<last_spid<<" to "<<spid<<std::endl;
#endif
            }
            else
            {
                if(!spid.empty())
                {
                    pid_not_changed_count++;
                }
            }
            if(!spid.empty())
            {
                doc.property("uuid") = UString(spid, UString::UTF_8);
            }
            //std::cerr<<is_new_cid<<","<<pid_changed<<","<<spid<<std::endl;
            bool need_process = is_new_cid || pid_changed;
            if(!need_process) continue;
            ProcessFurther_(doc);
            spid.clear();
            doc.getString("uuid", spid);
            if(spid.empty()) continue;
            b5mc_u.Append(doc);
        }
    }
    b5mc_u.Close();
    cdb_->flush();
    LOG(INFO)<<"new cid "<<new_count<<", pid_changed "<<pid_changed_count<<", pid_not_changed "<<pid_not_changed_count<<std::endl;
    return true;
}

void B5mcScdGenerator::ProcessFurther_(Document& doc)
{
    static const std::string title_property_name = "ProdName";
    std::string spid;
    doc.getString("uuid", spid);
    if(spid.empty())
    {
        ProductMatcher::Product product;
        std::string isbn;
        if(ProductMatcher::GetIsbnAttribute(doc, isbn))
        {
            Document book_doc;
            book_doc.property("Category") = UString(B5MHelper::BookCategoryName(), UString::UTF_8);
            book_doc.property("Attribute") = doc.property("Attribute");
            ProductMatcher::ProcessBook(book_doc, product);
        }
        else
        {
            UString title;
            doc.getProperty(title_property_name, title);
            if(!title.empty())
            {
                Document matcher_doc;
                matcher_doc.property("Title") = title;
                ProductMatcher* matcher = GetMatcher_();
                if(matcher!=NULL)
                {
                    matcher->Process(matcher_doc, product);
                }
            }
        }
        if(!product.spid.empty())
        {
            spid = product.spid;
        }
    }
    if(!spid.empty() && bdb_!=NULL)
    {
        uint128_t pid = B5MHelper::StringToUint128(spid);
        izenelib::util::UString brand;
        bdb_->get(pid, brand);
        if(brand.length()>0)
        {
            doc.property(B5MHelper::GetBrandPropertyName()) = brand;
        }
    }
    if(!spid.empty())
    {
        doc.property("uuid") = UString(spid, UString::UTF_8);
    }
}

ProductMatcher* B5mcScdGenerator::GetMatcher_()
{
    if(matcher_==NULL) return NULL;
    //if(!matcher_->IsOpen())
    //{
        //matcher_->Open();
        //matcher_->SetUsePriceSim(false);
    //}
    return matcher_;
}
<|endoftext|>


<commit_before>#include "optionsdialog.h"
#include "ui_optionsdialog.h"

#include "bitcoinunits.h"
#include "monitoreddatamapper.h"
#include "netbase.h"
#include "optionsmodel.h"

#include <QDir>
#include <QIntValidator>
#include <QLocale>
#include <QMessageBox>
#include <QRegExp>
#include <QRegExpValidator>

OptionsDialog::OptionsDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::OptionsDialog),
    model(0),
    mapper(0),
    fRestartWarningDisplayed_Proxy(false),
    fRestartWarningDisplayed_Lang(false),
    fProxyIpValid(true)
{
    ui->setupUi(this);

    /* Network elements init */
#ifndef USE_UPNP
    ui->mapPortUpnp->setEnabled(false);
#endif

    ui->proxyIp->setEnabled(false);
    ui->proxyPort->setEnabled(false);
    ui->proxyPort->setValidator(new QIntValidator(1, 65535, this));

    ui->socksVersion->setEnabled(false);
    ui->socksVersion->addItem("5", 5);
    ui->socksVersion->addItem("4", 4);
    ui->socksVersion->setCurrentIndex(0);

    connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyIp, SLOT(setEnabled(bool)));
    connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyPort, SLOT(setEnabled(bool)));
    connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->socksVersion, SLOT(setEnabled(bool)));
    connect(ui->connectSocks, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning_Proxy()));

    ui->proxyIp->installEventFilter(this);

    /* Window elements init */
#ifdef Q_OS_MAC
    ui->tabWindow->setVisible(false);
#endif

    /* Display elements init */
    QDir translations(":translations");
    ui->lang->addItem(QString("(") + tr("default") + QString(")"), QVariant(""));
    foreach(const QString &langStr, translations.entryList())
    {
        QLocale locale(langStr);

        /** check if the locale name consists of 2 parts (language_country) */
        if(langStr.contains("_"))
        {
#if QT_VERSION >= 0x040800
            /** display language strings as "native language - native country (locale name)", e.g. "Deutsch - Deutschland (de)" */
            ui->lang->addItem(locale.nativeLanguageName() + QString(" - ") + locale.nativeCountryName() + QString(" (") + langStr + QString(")"), QVariant(langStr));
#else
            /** display language strings as "language - country (locale name)", e.g. "German - Germany (de)" */
            ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" - ") + QLocale::countryToString(locale.country()) + QString(" (") + langStr + QString(")"), QVariant(langStr));
#endif
        }
        else
        {
#if QT_VERSION >= 0x040800
            /** display language strings as "native language (locale name)", e.g. "Deutsch (de)" */
            ui->lang->addItem(locale.nativeLanguageName() + QString(" (") + langStr + QString(")"), QVariant(langStr));
#else
            /** display language strings as "language (locale name)", e.g. "German (de)" */
            ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" (") + langStr + QString(")"), QVariant(langStr));
#endif
        }
    }
#if QT_VERSION >= 0x040700
    ui->thirdPartyTxUrls->setPlaceholderText("https://example.com/tx/%s");
#endif

    ui->unit->setModel(new BitcoinUnits(this));

    /* Widget-to-option mapper */
    mapper = new MonitoredDataMapper(this);
    mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
    mapper->setOrientation(Qt::Vertical);

    /* enable apply button when data modified */
    connect(mapper, SIGNAL(viewModified()), this, SLOT(enableApplyButton()));
    /* disable apply button when new data loaded */
    connect(mapper, SIGNAL(currentIndexChanged(int)), this, SLOT(disableApplyButton()));
    /* setup/change UI elements when proxy IP is invalid/valid */
    connect(this, SIGNAL(proxyIpValid(QValidatedLineEdit *, bool)), this, SLOT(handleProxyIpValid(QValidatedLineEdit *, bool)));
}

OptionsDialog::~OptionsDialog()
{
    delete ui;
}

void OptionsDialog::setModel(OptionsModel *model)
{
    this->model = model;
    if(model->isLocked==false)
        ui->passwordOnSend->setEnabled(false);
    else
        ui->passwordOnSend->setEnabled(true);

    if(model)
    {
        connect(model, SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));

        mapper->setModel(model);
        setMapper();
        mapper->toFirst();
    }

    /* update the display unit, to not use the default ("BTC") */
    updateDisplayUnit();

    /* warn only when language selection changes by user action (placed here so init via mapper doesn't trigger this) */
    connect(ui->lang, SIGNAL(valueChanged()), this, SLOT(showRestartWarning_Lang()));
    connect(ui->thirdPartyTxUrls, SIGNAL(textChanged(const QString &)), this, SLOT(showRestartWarning_TxUrls()));

    /* disable apply button after settings are loaded as there is nothing to save */
    disableApplyButton();
}

void OptionsDialog::setMapper()
{
    /* Main */
    mapper->addMapping(ui->transactionFee, OptionsModel::Fee);
    mapper->addMapping(ui->bitcoinAtStartup, OptionsModel::StartAtStartup);
    mapper->addMapping(ui->detachDatabases, OptionsModel::DetachDatabases);

    /* Network */
    mapper->addMapping(ui->mapPortUpnp, OptionsModel::MapPortUPnP);

    mapper->addMapping(ui->connectSocks, OptionsModel::ProxyUse);
    mapper->addMapping(ui->proxyIp, OptionsModel::ProxyIP);
    mapper->addMapping(ui->proxyPort, OptionsModel::ProxyPort);
    mapper->addMapping(ui->socksVersion, OptionsModel::ProxySocksVersion);

    /* Window */
#ifndef Q_OS_MAC
    mapper->addMapping(ui->minimizeToTray, OptionsModel::MinimizeToTray);
    mapper->addMapping(ui->minimizeOnClose, OptionsModel::MinimizeOnClose);
#endif

    /* Display */
    mapper->addMapping(ui->lang, OptionsModel::Language);
    mapper->addMapping(ui->unit, OptionsModel::DisplayUnit);
    mapper->addMapping(ui->displayAddresses, OptionsModel::DisplayAddresses);
    mapper->addMapping(ui->coinControlFeatures, OptionsModel::CoinControlFeatures);
    mapper->addMapping(ui->showShopDonate, OptionsModel::ShowShopDonate);
    mapper->addMapping(ui->showOverviewNews, OptionsModel::ShowOverviewNews);
    mapper->addMapping(ui->passwordOnSend,OptionsModel::PasswordOnSend);
    mapper->addMapping(ui->thirdPartyTxUrls, OptionsModel::ThirdPartyTxUrls);
}

void OptionsDialog::enableApplyButton()
{
    ui->applyButton->setEnabled(true);
}

void OptionsDialog::disableApplyButton()
{
    ui->applyButton->setEnabled(false);
}

void OptionsDialog::enableSaveButtons()
{
    /* prevent enabling of the save buttons when data modified, if there is an invalid proxy address present */
    if(fProxyIpValid)
        setSaveButtonState(true);
}

void OptionsDialog::disableSaveButtons()
{
    setSaveButtonState(false);
}

void OptionsDialog::setSaveButtonState(bool fState)
{
    ui->applyButton->setEnabled(fState);
    ui->okButton->setEnabled(fState);
}

void OptionsDialog::on_okButton_clicked()
{
    mapper->submit();
    accept();
}

void OptionsDialog::on_cancelButton_clicked()
{
    reject();
}

void OptionsDialog::on_applyButton_clicked()
{
    mapper->submit();
    disableApplyButton();
}

void OptionsDialog::showRestartWarning_Proxy()
{
    if(!fRestartWarningDisplayed_Proxy)
    {
        QMessageBox::warning(this, tr("Warning"), tr("This setting will take effect after restarting MintCoin."), QMessageBox::Ok);
        fRestartWarningDisplayed_Proxy = true;
    }
}

void OptionsDialog::showRestartWarning_Lang()
{
    if(!fRestartWarningDisplayed_Lang)
    {
        QMessageBox::warning(this, tr("Warning"), tr("This setting will take effect after restarting MintCoin."), QMessageBox::Ok);
        fRestartWarningDisplayed_Lang = true;
    }
}

void OptionsDialog::showRestartWarning_TxUrls()
{
    if(!fRestartWarningDisplayed_TxUrls)
    {
        QMessageBox::warning(this, tr("Warning"), tr("This setting will take effect after restarting LiteDoge."), QMessageBox::Ok);
        fRestartWarningDisplayed_TxUrls = true;
    }
}

void OptionsDialog::updateDisplayUnit()
{
    if(model)
    {
        /* Update transactionFee with the current unit */
        ui->transactionFee->setDisplayUnit(model->getDisplayUnit());
    }
}

void OptionsDialog::handleProxyIpValid(QValidatedLineEdit *object, bool fState)
{
    // this is used in a check before re-enabling the save buttons
    fProxyIpValid = fState;

    if(fProxyIpValid)
    {
        enableSaveButtons();
        ui->statusLabel->clear();
    }
    else
    {
        disableSaveButtons();
        object->setValid(fProxyIpValid);
        ui->statusLabel->setStyleSheet("QLabel { color: red; }");
        ui->statusLabel->setText(tr("The supplied proxy address is invalid."));
    }
}

bool OptionsDialog::eventFilter(QObject *object, QEvent *event)
{
    if(event->type() == QEvent::FocusOut)
    {
        if(object == ui->proxyIp)
        {
            CService addr;
            /* Check proxyIp for a valid IPv4/IPv6 address and emit the proxyIpValid signal */
            emit proxyIpValid(ui->proxyIp, LookupNumeric(ui->proxyIp->text().toStdString().c_str(), addr));
        }
    }
    return QDialog::eventFilter(object, event);
}
<commit_msg>Mintify the restart notice when changing 3rd party tx urls<commit_after>#include "optionsdialog.h"
#include "ui_optionsdialog.h"

#include "bitcoinunits.h"
#include "monitoreddatamapper.h"
#include "netbase.h"
#include "optionsmodel.h"

#include <QDir>
#include <QIntValidator>
#include <QLocale>
#include <QMessageBox>
#include <QRegExp>
#include <QRegExpValidator>

OptionsDialog::OptionsDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::OptionsDialog),
    model(0),
    mapper(0),
    fRestartWarningDisplayed_Proxy(false),
    fRestartWarningDisplayed_Lang(false),
    fProxyIpValid(true)
{
    ui->setupUi(this);

    /* Network elements init */
#ifndef USE_UPNP
    ui->mapPortUpnp->setEnabled(false);
#endif

    ui->proxyIp->setEnabled(false);
    ui->proxyPort->setEnabled(false);
    ui->proxyPort->setValidator(new QIntValidator(1, 65535, this));

    ui->socksVersion->setEnabled(false);
    ui->socksVersion->addItem("5", 5);
    ui->socksVersion->addItem("4", 4);
    ui->socksVersion->setCurrentIndex(0);

    connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyIp, SLOT(setEnabled(bool)));
    connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyPort, SLOT(setEnabled(bool)));
    connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->socksVersion, SLOT(setEnabled(bool)));
    connect(ui->connectSocks, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning_Proxy()));

    ui->proxyIp->installEventFilter(this);

    /* Window elements init */
#ifdef Q_OS_MAC
    ui->tabWindow->setVisible(false);
#endif

    /* Display elements init */
    QDir translations(":translations");
    ui->lang->addItem(QString("(") + tr("default") + QString(")"), QVariant(""));
    foreach(const QString &langStr, translations.entryList())
    {
        QLocale locale(langStr);

        /** check if the locale name consists of 2 parts (language_country) */
        if(langStr.contains("_"))
        {
#if QT_VERSION >= 0x040800
            /** display language strings as "native language - native country (locale name)", e.g. "Deutsch - Deutschland (de)" */
            ui->lang->addItem(locale.nativeLanguageName() + QString(" - ") + locale.nativeCountryName() + QString(" (") + langStr + QString(")"), QVariant(langStr));
#else
            /** display language strings as "language - country (locale name)", e.g. "German - Germany (de)" */
            ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" - ") + QLocale::countryToString(locale.country()) + QString(" (") + langStr + QString(")"), QVariant(langStr));
#endif
        }
        else
        {
#if QT_VERSION >= 0x040800
            /** display language strings as "native language (locale name)", e.g. "Deutsch (de)" */
            ui->lang->addItem(locale.nativeLanguageName() + QString(" (") + langStr + QString(")"), QVariant(langStr));
#else
            /** display language strings as "language (locale name)", e.g. "German (de)" */
            ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" (") + langStr + QString(")"), QVariant(langStr));
#endif
        }
    }
#if QT_VERSION >= 0x040700
    ui->thirdPartyTxUrls->setPlaceholderText("https://example.com/tx/%s");
#endif

    ui->unit->setModel(new BitcoinUnits(this));

    /* Widget-to-option mapper */
    mapper = new MonitoredDataMapper(this);
    mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
    mapper->setOrientation(Qt::Vertical);

    /* enable apply button when data modified */
    connect(mapper, SIGNAL(viewModified()), this, SLOT(enableApplyButton()));
    /* disable apply button when new data loaded */
    connect(mapper, SIGNAL(currentIndexChanged(int)), this, SLOT(disableApplyButton()));
    /* setup/change UI elements when proxy IP is invalid/valid */
    connect(this, SIGNAL(proxyIpValid(QValidatedLineEdit *, bool)), this, SLOT(handleProxyIpValid(QValidatedLineEdit *, bool)));
}

OptionsDialog::~OptionsDialog()
{
    delete ui;
}

void OptionsDialog::setModel(OptionsModel *model)
{
    this->model = model;
    if(model->isLocked==false)
        ui->passwordOnSend->setEnabled(false);
    else
        ui->passwordOnSend->setEnabled(true);

    if(model)
    {
        connect(model, SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));

        mapper->setModel(model);
        setMapper();
        mapper->toFirst();
    }

    /* update the display unit, to not use the default ("BTC") */
    updateDisplayUnit();

    /* warn only when language selection changes by user action (placed here so init via mapper doesn't trigger this) */
    connect(ui->lang, SIGNAL(valueChanged()), this, SLOT(showRestartWarning_Lang()));
    connect(ui->thirdPartyTxUrls, SIGNAL(textChanged(const QString &)), this, SLOT(showRestartWarning_TxUrls()));

    /* disable apply button after settings are loaded as there is nothing to save */
    disableApplyButton();
}

void OptionsDialog::setMapper()
{
    /* Main */
    mapper->addMapping(ui->transactionFee, OptionsModel::Fee);
    mapper->addMapping(ui->bitcoinAtStartup, OptionsModel::StartAtStartup);
    mapper->addMapping(ui->detachDatabases, OptionsModel::DetachDatabases);

    /* Network */
    mapper->addMapping(ui->mapPortUpnp, OptionsModel::MapPortUPnP);

    mapper->addMapping(ui->connectSocks, OptionsModel::ProxyUse);
    mapper->addMapping(ui->proxyIp, OptionsModel::ProxyIP);
    mapper->addMapping(ui->proxyPort, OptionsModel::ProxyPort);
    mapper->addMapping(ui->socksVersion, OptionsModel::ProxySocksVersion);

    /* Window */
#ifndef Q_OS_MAC
    mapper->addMapping(ui->minimizeToTray, OptionsModel::MinimizeToTray);
    mapper->addMapping(ui->minimizeOnClose, OptionsModel::MinimizeOnClose);
#endif

    /* Display */
    mapper->addMapping(ui->lang, OptionsModel::Language);
    mapper->addMapping(ui->unit, OptionsModel::DisplayUnit);
    mapper->addMapping(ui->displayAddresses, OptionsModel::DisplayAddresses);
    mapper->addMapping(ui->coinControlFeatures, OptionsModel::CoinControlFeatures);
    mapper->addMapping(ui->showShopDonate, OptionsModel::ShowShopDonate);
    mapper->addMapping(ui->showOverviewNews, OptionsModel::ShowOverviewNews);
    mapper->addMapping(ui->passwordOnSend,OptionsModel::PasswordOnSend);
    mapper->addMapping(ui->thirdPartyTxUrls, OptionsModel::ThirdPartyTxUrls);
}

void OptionsDialog::enableApplyButton()
{
    ui->applyButton->setEnabled(true);
}

void OptionsDialog::disableApplyButton()
{
    ui->applyButton->setEnabled(false);
}

void OptionsDialog::enableSaveButtons()
{
    /* prevent enabling of the save buttons when data modified, if there is an invalid proxy address present */
    if(fProxyIpValid)
        setSaveButtonState(true);
}

void OptionsDialog::disableSaveButtons()
{
    setSaveButtonState(false);
}

void OptionsDialog::setSaveButtonState(bool fState)
{
    ui->applyButton->setEnabled(fState);
    ui->okButton->setEnabled(fState);
}

void OptionsDialog::on_okButton_clicked()
{
    mapper->submit();
    accept();
}

void OptionsDialog::on_cancelButton_clicked()
{
    reject();
}

void OptionsDialog::on_applyButton_clicked()
{
    mapper->submit();
    disableApplyButton();
}

void OptionsDialog::showRestartWarning_Proxy()
{
    if(!fRestartWarningDisplayed_Proxy)
    {
        QMessageBox::warning(this, tr("Warning"), tr("This setting will take effect after restarting MintCoin."), QMessageBox::Ok);
        fRestartWarningDisplayed_Proxy = true;
    }
}

void OptionsDialog::showRestartWarning_Lang()
{
    if(!fRestartWarningDisplayed_Lang)
    {
        QMessageBox::warning(this, tr("Warning"), tr("This setting will take effect after restarting MintCoin."), QMessageBox::Ok);
        fRestartWarningDisplayed_Lang = true;
    }
}

void OptionsDialog::showRestartWarning_TxUrls()
{
    if(!fRestartWarningDisplayed_TxUrls)
    {
        QMessageBox::warning(this, tr("Warning"), tr("This setting will take effect after restarting MintCoin."), QMessageBox::Ok);
        fRestartWarningDisplayed_TxUrls = true;
    }
}

void OptionsDialog::updateDisplayUnit()
{
    if(model)
    {
        /* Update transactionFee with the current unit */
        ui->transactionFee->setDisplayUnit(model->getDisplayUnit());
    }
}

void OptionsDialog::handleProxyIpValid(QValidatedLineEdit *object, bool fState)
{
    // this is used in a check before re-enabling the save buttons
    fProxyIpValid = fState;

    if(fProxyIpValid)
    {
        enableSaveButtons();
        ui->statusLabel->clear();
    }
    else
    {
        disableSaveButtons();
        object->setValid(fProxyIpValid);
        ui->statusLabel->setStyleSheet("QLabel { color: red; }");
        ui->statusLabel->setText(tr("The supplied proxy address is invalid."));
    }
}

bool OptionsDialog::eventFilter(QObject *object, QEvent *event)
{
    if(event->type() == QEvent::FocusOut)
    {
        if(object == ui->proxyIp)
        {
            CService addr;
            /* Check proxyIp for a valid IPv4/IPv6 address and emit the proxyIpValid signal */
            emit proxyIpValid(ui->proxyIp, LookupNumeric(ui->proxyIp->text().toStdString().c_str(), addr));
        }
    }
    return QDialog::eventFilter(object, event);
}
<|endoftext|>


<commit_before>/* NMEA GPS Coordinate Parser for Arduino and Ublox MAX 7Q
 * Developed for the Space Systems Laboratory at the University of Maryland
 * Part of the BPPCell library
..
 *
 * Copyright (c) 2015 Luke Renegar
 *
 * 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 <Arduino.h>
//#include <Wire.h>
#include <BPPCell.h>
#include <I2C.h>

NMEAParser::NMEAParser() { }

GPSCoords NMEAParser::parseCoords(String GGAString) {
	//Start indices are the first characters indices of the given field
	//End indices are the indices of the comma after the given field
	int NUMBER_OF_COMMAS = 14; // Number of commas in a GGA string
	int indicesOfCommas[NUMBER_OF_COMMAS];
	int lastCommaIndex = 0;
	for(int i = 0; i < NUMBER_OF_COMMAS; i++) {
		indicesOfCommas[i] = GGAString.indexOf(",", lastCommaIndex);
		lastCommaIndex = indicesOfCommas[i] + 1;
	}
	//The field goes from the index immediately following the first comma to the index immediately preceding the second comma
	String time = GGAString.substring(indicesOfCommas[0] + 1, indicesOfCommas[1]);
	String latString = GGAString.substring(indicesOfCommas[1] + 1, indicesOfCommas[2]);
	String NSString = GGAString.substring(indicesOfCommas[2] + 1, indicesOfCommas[3]);
	String lonString = GGAString.substring(indicesOfCommas[3] + 1, indicesOfCommas[4]);
	String EWString = GGAString.substring(indicesOfCommas[4] + 1, indicesOfCommas[5]);
	String altString = GGAString.substring(indicesOfCommas[8] + 1, indicesOfCommas[9]);
	bool isNorth;
	if(NSString.equals("N"))
		isNorth = true;
	else
		isNorth = false;
	bool isEast;
	if(EWString.equals("E"))
		isEast = true;
	else
		isEast = false;
	float lat = parseLatFromGGA(latString, isNorth);
	float lon = parseLonFromGGA(lonString, isEast);
	float alt = altString.toFloat();
	return GPSCoords(time, lat, lon, alt);
}

/* Parses the latitude from an NMEA GGA string
 *
 *
 */
long NMEAParser::parseLatFromGGA(String latString, bool isNorth)
{
	int degrees = latString.substring(0, 2).toInt(); //Gets the degree component of the latitude
	int minutes = latString.substring(2, 4).toInt(); //Gets the integral minutes component of the latitude
	float decMinutes = latString.substring(4).toFloat(); //Gets the decimal minutes component of the latitude
	int NSMultiplier ; //North-south multiplier indicates if the latitude is north or south, with positive values being north
	if(isNorth)
		NSMultiplier = 1;
	else
		NSMultiplier = -1;
	int MINUTES_PER_DEGREE = 60;
	const long TEN_THOUSANDTHS_PER_MINUTE = 10000;
	return NSMultiplier*(degrees*MINUTES_PER_DEGREE*TEN_THOUSANDTHS_PER_MINUTE + minutes*TEN_THOUSANDTHS_PER_MINUTE + ((long) (decMinutes*(TEN_THOUSANDTHS_PER_MINUTE))));
}

long NMEAParser::parseLonFromGGA(String lonString, bool isEast)
{
	int degrees = lonString.substring(0, 3).toInt(); //Gets the degree component of the longitude
	int minutes = lonString.substring(3, 5).toInt(); //Gets the integral minutes component of the longitude
	float decMinutes = lonString.substring(5).toFloat(); //Gets the decimal minutes component of the longitude
	int EWMultiplier ; //East-west multiplier indicates if the longitude is east or west, with positive values being east
	if(isEast)
		EWMultiplier = 1;
	else
		EWMultiplier = -1;
	int MINUTES_PER_DEGREE = 60;
	const long TEN_THOUSANDTHS_PER_MINUTE = 10000;
	return EWMultiplier*(degrees*MINUTES_PER_DEGREE*TEN_THOUSANDTHS_PER_MINUTE + minutes*TEN_THOUSANDTHS_PER_MINUTE + ((long) (decMinutes*(TEN_THOUSANDTHS_PER_MINUTE))));
}

<commit_msg>added geoidal separation to calculation of altitude<commit_after>/* NMEA GPS Coordinate Parser for Arduino and Ublox MAX 7Q
 * Developed for the Space Systems Laboratory at the University of Maryland
 * Part of the BPPCell library
 ..
 *
 * Copyright (c) 2015 Luke Renegar
 *
 * 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 <Arduino.h>
//#include <Wire.h>
#include <BPPCell.h>
#include <I2C.h>

NMEAParser::NMEAParser()
{
}

GPSCoords NMEAParser::parseCoords(String GGAString)
{
    //Start indices are the first characters indices of the given field
    //End indices are the indices of the comma after the given field
    int NUMBER_OF_COMMAS = 14; // Number of commas in a GGA string
    int indicesOfCommas[NUMBER_OF_COMMAS];
    int lastCommaIndex = 0;

    for (int i = 0; i < NUMBER_OF_COMMAS; i++)
    {
        indicesOfCommas[i] = GGAString.indexOf(",", lastCommaIndex);
        lastCommaIndex = indicesOfCommas[i] + 1;
    }

    //The field goes from the index immediately following the first comma to the index immediately preceding the second comma
    String time = GGAString.substring(indicesOfCommas[0] + 1,
            indicesOfCommas[1]);
    String latString = GGAString.substring(indicesOfCommas[1] + 1,
            indicesOfCommas[2]);
    String NSString = GGAString.substring(indicesOfCommas[2] + 1,
            indicesOfCommas[3]);
    String lonString = GGAString.substring(indicesOfCommas[3] + 1,
            indicesOfCommas[4]);
    String EWString = GGAString.substring(indicesOfCommas[4] + 1,
            indicesOfCommas[5]);
    String altString = GGAString.substring(indicesOfCommas[8] + 1,
            indicesOfCommas[9]);
    String geoString = GGAString.substring(indicesOfCommas[10] + 1,
            indicesOfCommas[11]); // geoid separation

    bool isNorth;
    if (NSString.equals("N"))
        isNorth = true;
    else
        isNorth = false;

    bool isEast;
    if (EWString.equals("E"))
        isEast = true;
    else
        isEast = false;

    float lat = parseLatFromGGA(latString, isNorth);
    float lon = parseLonFromGGA(lonString, isEast);
    float alt = altString.toFloat() + geoString.toFloat();
    return GPSCoords(time, lat, lon, alt);
}

/* Parses the latitude from an NMEA GGA string
 *
 *
 */
long NMEAParser::parseLatFromGGA(String latString, bool isNorth)
{
    int degrees = latString.substring(0, 2).toInt(); //Gets the degree component of the latitude
    int minutes = latString.substring(2, 4).toInt(); //Gets the integral minutes component of the latitude
    float decMinutes = latString.substring(4).toFloat(); //Gets the decimal minutes component of the latitude
    int NSMultiplier; //North-south multiplier indicates if the latitude is north or south, with positive values being north
    int MINUTES_PER_DEGREE = 60;
    const long TEN_THOUSANDTHS_PER_MINUTE = 10000;

    if (isNorth)
        NSMultiplier = 1;
    else
        NSMultiplier = -1;

    return NSMultiplier
            * (degrees * MINUTES_PER_DEGREE * TEN_THOUSANDTHS_PER_MINUTE
                    + minutes * TEN_THOUSANDTHS_PER_MINUTE
                    + ((long) (decMinutes * (TEN_THOUSANDTHS_PER_MINUTE))));
}

long NMEAParser::parseLonFromGGA(String lonString, bool isEast)
{
    int degrees = lonString.substring(0, 3).toInt(); //Gets the degree component of the longitude
    int minutes = lonString.substring(3, 5).toInt(); //Gets the integral minutes component of the longitude
    float decMinutes = lonString.substring(5).toFloat(); //Gets the decimal minutes component of the longitude
    int EWMultiplier; //East-west multiplier indicates if the longitude is east or west, with positive values being east
    int MINUTES_PER_DEGREE = 60;
    const long TEN_THOUSANDTHS_PER_MINUTE = 10000;

    if (isEast)
        EWMultiplier = 1;
    else
        EWMultiplier = -1;

    return EWMultiplier
            * (degrees * MINUTES_PER_DEGREE * TEN_THOUSANDTHS_PER_MINUTE
                    + minutes * TEN_THOUSANDTHS_PER_MINUTE
                    + ((long) (decMinutes * (TEN_THOUSANDTHS_PER_MINUTE))));
}

<|endoftext|>


<commit_before>#include <iostream>
#include <string>

#include "BossFight.hpp"

void run_part_one() {
    std::cout << find_lowest_gold_to_win(100,8,2) << std::endl;
}
void run_part_two() {
}

int main(int argc, char* argv[]) {
    if (argc > 1) {
        if (std::string(argv[1]) == "--part_two") {
            run_part_two();
        } else {
            std::cout << "Usage: day21 [--part_two]" << std::endl;
            return -1;
        }
    } else {
        run_part_one();
    }
}
<commit_msg>added runtime code for day 21 part two<commit_after>#include <iostream>
#include <string>

#include "BossFight.hpp"

void run_part_one() {
    std::cout << find_lowest_gold_to_win(100,8,2) << std::endl;
}
void run_part_two() {
    std::cout << find_lowest_gold_to_lose(100,8,2) << std::endl;
}

int main(int argc, char* argv[]) {
    if (argc > 1) {
        if (std::string(argv[1]) == "--part_two") {
            run_part_two();
        } else {
            std::cout << "Usage: day21 [--part_two]" << std::endl;
            return -1;
        }
    } else {
        run_part_one();
    }
}
<|endoftext|>