<commit_before>/*      _______   __   __   __   ______   __   __   _______   __   __
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
 *
 * Copyright (c) 2004, 2005, 2006, 2007 Olof Naessn and Per Larsson
 *
 *                                                         Js_./
 * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
 * Olof Naessn a.k.a jansem/yakslem                _asww7!uY`>  )\a//
 *                                                 _Qhm`] _f "'c  1!5m
 * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
 *                                               .)j(] .d_/ '-(  P .   S
 * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
 * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
 * binary forms, with or without                 )4d[#7r, .   '     )d`)[
 * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
 * that the following conditions are met:       j<<WP+k/);.        _W=j f
 * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
 *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
 *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
 *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
 * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
 *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
 *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
 *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
 *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
 *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
 * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
 *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
 *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
 *    from this software without specific        (js, \[QQW$QWW#?!V"".
 *    prior written permission.                    ]y:.<\..          .
 *                                                 -]n w/ '         [.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION)                     ^
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * For comments regarding functions please see the header file.
 */

#include "guichan/allegro/allegroinput.hpp"

#include <allegro.h>

#include "guichan/exception.hpp"

namespace gcn
{
    AllegroInput::AllegroInput()
    {
        mMouseButton1 = mMouseButton2 = mMouseButton3 = false;
        mLastMouseZ = 0;
        mLastMouseX = 0;
        mLastMouseY = 0;
    }

    bool AllegroInput::isKeyQueueEmpty()
    {
        return mKeyQueue.empty();
    }

    KeyInput AllegroInput::dequeueKeyInput()
    {
        if (isKeyQueueEmpty())
        {
            throw GCN_EXCEPTION("Key queue is empty.");
        }

        KeyInput ki = mKeyQueue.front();
        mKeyQueue.pop();

        return ki;
    }

    bool AllegroInput::isMouseQueueEmpty()
    {
        return mMouseQueue.empty();
    }

    MouseInput AllegroInput::dequeueMouseInput()
    {
        if (isMouseQueueEmpty())
        {
            throw GCN_EXCEPTION("Mouse queue is empty.");
        }

        MouseInput mi = mMouseQueue.front();
        mMouseQueue.pop();

        return mi;
    }

    void AllegroInput::_pollInput()
    {
        pollMouseInput();
        pollKeyInput();
    }

    void AllegroInput::pollMouseInput()
    {
        if (mouse_needs_poll())
        {
            poll_mouse();
        }
        int mouseX = mouse_x;
        int mouseY = mouse_y;
        int mouseZ = mouse_z;
        int mouseB1 = mouse_b & 1;
        int mouseB2 = mouse_b & 2;
        int mouseB3 = mouse_b & 4;

        // Check mouse movement
        if (mouseX != mLastMouseX || mouseY != mLastMouseY)
        {
            mMouseQueue.push(MouseInput(MouseInput::EMPTY,
                                        MouseInput::MOVED,
                                        mouseX,
                                        mouseY,
                                        0));
            mLastMouseX = mouseX;
            mLastMouseY = mouseY;
        }

        // Check mouse Wheel
        while (mLastMouseZ < mouseZ)
        {
            mMouseQueue.push(MouseInput(MouseInput::EMPTY,
                                        MouseInput::WHEEL_MOVED_UP,
                                        mouseX,
                                        mouseY,
                                        0));
            mLastMouseZ++;
        }

        while (mLastMouseZ > mouseZ)
        {
            mMouseQueue.push(MouseInput(MouseInput::EMPTY,
                                        MouseInput::WHEEL_MOVED_DOWN,
                                        mouseX,
                                        mouseY,
                                        0));
            mLastMouseZ--;
        }

        // Check mouse buttons
        if (!mMouseButton1 && mouseB1)
        {
            mMouseQueue.push(MouseInput(MouseInput::LEFT,
                                        MouseInput::PRESSED,
                                        mouseX,
                                        mouseY,
                                        0));
        }

        if (mMouseButton1 && !mouseB1)
        {
            mMouseQueue.push(MouseInput(MouseInput::LEFT,
                                        MouseInput::RELEASED,
                                        mouseX,
                                        mouseY,
                                        0));
        }

        if (!mMouseButton2 && mouseB2)
        {
            mMouseQueue.push(MouseInput(MouseInput::RIGHT,
                                        MouseInput::PRESSED,
                                        mouseX,
                                        mouseY,
                                        0));
        }

        if (mMouseButton2 && !mouseB2)
        {
            mMouseQueue.push(MouseInput(MouseInput::RIGHT,
                                        MouseInput::RELEASED,
                                        mouseX,
                                        mouseY,
                                        0));
        }

        if (!mMouseButton3 && mouseB3)
        {
            mMouseQueue.push(MouseInput(MouseInput::MIDDLE,
                                        MouseInput::PRESSED,
                                        mouseX,
                                        mouseY,
                                        0));
        }

        if (mMouseButton3 && !mouseB3)
        {
            mMouseQueue.push(MouseInput(MouseInput::MIDDLE,
                                        MouseInput::RELEASED,
                                        mouseX,
                                        mouseY,
                                        0));
        }

        mMouseButton1 = mouseB1;
        mMouseButton2 = mouseB2;
        mMouseButton3 = mouseB3;
    }

    void AllegroInput::pollKeyInput()
    {
        int unicode, scancode;

        if (keyboard_needs_poll())
        {
            poll_keyboard();
        }

        while (keypressed())
        {
            unicode = ureadkey(&scancode);
            Key keyObj = convertToKey(scancode, unicode);

            KeyInput keyInput(keyObj, KeyInput::PRESSED);

            keyInput.setNumericPad(isNumericPad(scancode));
            keyInput.setShiftPressed(key_shifts & KB_SHIFT_FLAG);
            keyInput.setAltPressed(key_shifts & KB_ALT_FLAG);
            keyInput.setControlPressed(key_shifts & KB_CTRL_FLAG);
#ifdef KB_COMMAND_FLAG
            keyInput.setMetaPressed(key_shifts & (KB_COMMAND_FLAG |
                                           KB_LWIN_FLAG |
                                           KB_RWIN_FLAG));
#else
            keyInput.setMetaPressed(key_shifts & (KB_LWIN_FLAG |
                                                  KB_RWIN_FLAG));
#endif

            mKeyQueue.push(keyInput);

            mPressedKeys[scancode] = keyInput;
        }

         // Check for released keys
        std::map<int, KeyInput>::iterator iter, tempIter;
        for (iter = mPressedKeys.begin(); iter != mPressedKeys.end(); )
         {
            if (!key[iter->first])
            {
                KeyInput keyInput(iter->second.getKey(), KeyInput::RELEASED);
                keyInput.setNumericPad(iter->second.isNumericPad());
                keyInput.setShiftPressed(iter->second.isShiftPressed());
                keyInput.setAltPressed(iter->second.isAltPressed());
                keyInput.setControlPressed(iter->second.isControlPressed());

                mKeyQueue.push(keyInput);

                tempIter = iter;
                iter++;
                mPressedKeys.erase(tempIter);
            }
            else
            {
                iter++;
            }
        }
    }

    Key AllegroInput::convertToKey(int scancode, int unicode)
    {
        int keysym;
        bool pad = false;

        switch(scancode)
        {
          case KEY_ESC:
              keysym = Key::ESCAPE;
              break;

          case KEY_ALT:
              keysym = Key::LEFT_ALT;
              break;

          case KEY_ALTGR:
              keysym = Key::RIGHT_ALT;
              break;

          case KEY_LSHIFT:
              keysym = Key::LEFT_SHIFT;
              break;

          case KEY_RSHIFT:
              keysym = Key::RIGHT_SHIFT;
              break;

          case KEY_LCONTROL:
              keysym = Key::LEFT_CONTROL;
              break;

          case KEY_RCONTROL:
              keysym = Key::RIGHT_CONTROL;
              break;

          case KEY_LWIN:
              keysym = Key::LEFT_META;
              break;

          case KEY_RWIN:
              keysym = Key::RIGHT_META;
              break;

          case KEY_INSERT:
              keysym = Key::INSERT;
              break;

          case KEY_HOME:
              keysym = Key::HOME;
              break;

          case KEY_PGUP:
              keysym = Key::PAGE_UP;
              break;

          case KEY_PGDN:
              keysym = Key::PAGE_DOWN;
              break;

          case KEY_DEL:
              keysym = Key::DELETE;
              break;

          case KEY_DEL_PAD:
              keysym = Key::DELETE;
              pad = true;
              break;

          case KEY_END:
              keysym = Key::END;
              break;

          case KEY_CAPSLOCK:
              keysym = Key::CAPS_LOCK;
              break;

          case KEY_BACKSPACE:
              keysym = Key::BACKSPACE;
              break;

          case KEY_F1:
              keysym = Key::F1;
              break;

          case KEY_F2:
              keysym = Key::F2;
              break;

          case KEY_F3:
              keysym = Key::F3;
              break;

          case KEY_F4:
              keysym = Key::F4;
              break;

          case KEY_F5:
              keysym = Key::F5;
              break;

          case KEY_F6:
              keysym = Key::F6;
              break;

          case KEY_F7:
              keysym = Key::F7;
              break;

          case KEY_F8:
              keysym = Key::F8;
              break;

          case KEY_F9:
              keysym = Key::F9;
              break;

          case KEY_F10:
              keysym = Key::F10;
              break;

          case KEY_F11:
              keysym = Key::F11;
              break;

          case KEY_F12:
              keysym = Key::F12;
              break;

          case KEY_PRTSCR:
              keysym = Key::PRINT_SCREEN;
              break;

          case KEY_PAUSE:
              keysym = Key::PAUSE;
              break;

          case KEY_SCRLOCK:
              keysym = Key::SCROLL_LOCK;
              break;

          case KEY_NUMLOCK:
              keysym = Key::NUM_LOCK;
              break;

          case KEY_LEFT:
              keysym = Key::LEFT;
              break;

          case KEY_RIGHT:
              keysym = Key::RIGHT;
              break;

          case KEY_UP:
              keysym = Key::UP;
              break;

          case KEY_DOWN:
              keysym = Key::DOWN;
              break;

          case KEY_ENTER_PAD:
              pad = true;
          case KEY_ENTER:
              keysym = Key::ENTER;
              break;
     default:
              keysym = unicode;
        }

        Key k = Key(keysym);

        return k;

        //Now, THAT was fun to code! =D =D =D
    }

    bool AllegroInput::isNumericPad(int scancode)
    {
        switch (scancode)
        {
          case KEY_0_PAD:
          case KEY_1_PAD:
          case KEY_2_PAD:
          case KEY_3_PAD:
          case KEY_4_PAD:
          case KEY_5_PAD:
          case KEY_6_PAD:
          case KEY_7_PAD:
          case KEY_8_PAD:
          case KEY_9_PAD:
          case KEY_SLASH_PAD:
          case KEY_MINUS_PAD:
          case KEY_PLUS_PAD:
              return true;
          default:
              return false;
        }
    }
}
<commit_msg>A bug has been fixed so Alt, Control and Shift will generate key presses.<commit_after>/*      _______   __   __   __   ______   __   __   _______   __   __
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
 *
 * Copyright (c) 2004, 2005, 2006, 2007 Olof Naessn and Per Larsson
 *
 *                                                         Js_./
 * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
 * Olof Naessn a.k.a jansem/yakslem                _asww7!uY`>  )\a//
 *                                                 _Qhm`] _f "'c  1!5m
 * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
 *                                               .)j(] .d_/ '-(  P .   S
 * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
 * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
 * binary forms, with or without                 )4d[#7r, .   '     )d`)[
 * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
 * that the following conditions are met:       j<<WP+k/);.        _W=j f
 * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
 *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
 *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
 *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
 * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
 *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
 *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
 *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
 *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
 *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
 * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
 *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
 *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
 *    from this software without specific        (js, \[QQW$QWW#?!V"".
 *    prior written permission.                    ]y:.<\..          .
 *                                                 -]n w/ '         [.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION)                     ^
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * For comments regarding functions please see the header file.
 */

#include "guichan/allegro/allegroinput.hpp"

#include <allegro.h>

#include "guichan/exception.hpp"

namespace gcn
{
    AllegroInput::AllegroInput()
    {
        mMouseButton1 = mMouseButton2 = mMouseButton3 = false;
        mLastMouseZ = 0;
        mLastMouseX = 0;
        mLastMouseY = 0;
    }

    bool AllegroInput::isKeyQueueEmpty()
    {
        return mKeyQueue.empty();
    }

    KeyInput AllegroInput::dequeueKeyInput()
    {
        if (isKeyQueueEmpty())
        {
            throw GCN_EXCEPTION("Key queue is empty.");
        }

        KeyInput ki = mKeyQueue.front();
        mKeyQueue.pop();

        return ki;
    }

    bool AllegroInput::isMouseQueueEmpty()
    {
        return mMouseQueue.empty();
    }

    MouseInput AllegroInput::dequeueMouseInput()
    {
        if (isMouseQueueEmpty())
        {
            throw GCN_EXCEPTION("Mouse queue is empty.");
        }

        MouseInput mi = mMouseQueue.front();
        mMouseQueue.pop();

        return mi;
    }

    void AllegroInput::_pollInput()
    {
        pollMouseInput();
        pollKeyInput();
    }

    void AllegroInput::pollMouseInput()
    {
        if (mouse_needs_poll())
        {
            poll_mouse();
        }
        int mouseX = mouse_x;
        int mouseY = mouse_y;
        int mouseZ = mouse_z;
        int mouseB1 = mouse_b & 1;
        int mouseB2 = mouse_b & 2;
        int mouseB3 = mouse_b & 4;

        // Check mouse movement
        if (mouseX != mLastMouseX || mouseY != mLastMouseY)
        {
            mMouseQueue.push(MouseInput(MouseInput::EMPTY,
                                        MouseInput::MOVED,
                                        mouseX,
                                        mouseY,
                                        0));
            mLastMouseX = mouseX;
            mLastMouseY = mouseY;
        }

        // Check mouse Wheel
        while (mLastMouseZ < mouseZ)
        {
            mMouseQueue.push(MouseInput(MouseInput::EMPTY,
                                        MouseInput::WHEEL_MOVED_UP,
                                        mouseX,
                                        mouseY,
                                        0));
            mLastMouseZ++;
        }

        while (mLastMouseZ > mouseZ)
        {
            mMouseQueue.push(MouseInput(MouseInput::EMPTY,
                                        MouseInput::WHEEL_MOVED_DOWN,
                                        mouseX,
                                        mouseY,
                                        0));
            mLastMouseZ--;
        }

        // Check mouse buttons
        if (!mMouseButton1 && mouseB1)
        {
            mMouseQueue.push(MouseInput(MouseInput::LEFT,
                                        MouseInput::PRESSED,
                                        mouseX,
                                        mouseY,
                                        0));
        }

        if (mMouseButton1 && !mouseB1)
        {
            mMouseQueue.push(MouseInput(MouseInput::LEFT,
                                        MouseInput::RELEASED,
                                        mouseX,
                                        mouseY,
                                        0));
        }

        if (!mMouseButton2 && mouseB2)
        {
            mMouseQueue.push(MouseInput(MouseInput::RIGHT,
                                        MouseInput::PRESSED,
                                        mouseX,
                                        mouseY,
                                        0));
        }

        if (mMouseButton2 && !mouseB2)
        {
            mMouseQueue.push(MouseInput(MouseInput::RIGHT,
                                        MouseInput::RELEASED,
                                        mouseX,
                                        mouseY,
                                        0));
        }

        if (!mMouseButton3 && mouseB3)
        {
            mMouseQueue.push(MouseInput(MouseInput::MIDDLE,
                                        MouseInput::PRESSED,
                                        mouseX,
                                        mouseY,
                                        0));
        }

        if (mMouseButton3 && !mouseB3)
        {
            mMouseQueue.push(MouseInput(MouseInput::MIDDLE,
                                        MouseInput::RELEASED,
                                        mouseX,
                                        mouseY,
                                        0));
        }

        mMouseButton1 = mouseB1;
        mMouseButton2 = mouseB2;
        mMouseButton3 = mouseB3;
    }

    void AllegroInput::pollKeyInput()
    {
        int unicode, scancode;

        if (keyboard_needs_poll())
        {
            poll_keyboard();
        }

        while (keypressed())
        {
            unicode = ureadkey(&scancode);
            Key keyObj = convertToKey(scancode, unicode);

            KeyInput keyInput(keyObj, KeyInput::PRESSED);

            keyInput.setNumericPad(isNumericPad(scancode));
            keyInput.setShiftPressed(key_shifts & KB_SHIFT_FLAG);
            keyInput.setAltPressed(key_shifts & KB_ALT_FLAG);
            keyInput.setControlPressed(key_shifts & KB_CTRL_FLAG);
#ifdef KB_COMMAND_FLAG
            keyInput.setMetaPressed(key_shifts & (KB_COMMAND_FLAG |
                                           KB_LWIN_FLAG |
                                           KB_RWIN_FLAG));
#else
            keyInput.setMetaPressed(key_shifts & (KB_LWIN_FLAG |
                                                  KB_RWIN_FLAG));
#endif

            mKeyQueue.push(keyInput);

            mPressedKeys[scancode] = keyInput;
        }

        if (key[KEY_ALT] && mPressedKeys.find(KEY_ALT) == mPressedKeys.end())
		{
			KeyInput keyInput(convertToKey(KEY_ALT, 0), KeyInput::PRESSED);
            mKeyQueue.push(keyInput);
            mPressedKeys[KEY_ALT] = keyInput;
		}

		if (key[KEY_ALTGR] && mPressedKeys.find(KEY_ALTGR) == mPressedKeys.end())
		{
			KeyInput keyInput(convertToKey(KEY_ALTGR, 0), KeyInput::PRESSED);
            mKeyQueue.push(keyInput);
            mPressedKeys[KEY_ALTGR] = keyInput;
		}

		if (key[KEY_LSHIFT] && mPressedKeys.find(KEY_LSHIFT) == mPressedKeys.end())
		{
			KeyInput keyInput(convertToKey(KEY_LSHIFT, 0), KeyInput::PRESSED);
            mKeyQueue.push(keyInput);
            mPressedKeys[KEY_LSHIFT] = keyInput;
		}

		if (key[KEY_RSHIFT] && mPressedKeys.find(KEY_RSHIFT) == mPressedKeys.end())
		{
			KeyInput keyInput(convertToKey(KEY_RSHIFT, 0), KeyInput::PRESSED);
            mKeyQueue.push(keyInput);
            mPressedKeys[KEY_RSHIFT] = keyInput;
		}

		if (key[KEY_LCONTROL] && mPressedKeys.find(KEY_LCONTROL) == mPressedKeys.end())
		{
			KeyInput keyInput(convertToKey(KEY_LCONTROL, 0), KeyInput::PRESSED);
            mKeyQueue.push(keyInput);
            mPressedKeys[KEY_LCONTROL] = keyInput;
		}

		if (key[KEY_RCONTROL] && mPressedKeys.find(KEY_RCONTROL) == mPressedKeys.end())
		{
			KeyInput keyInput(convertToKey(KEY_RCONTROL, 0), KeyInput::PRESSED);
            mKeyQueue.push(keyInput);
            mPressedKeys[KEY_RCONTROL] = keyInput;
		}

         // Check for released keys
        std::map<int, KeyInput>::iterator iter, tempIter;
        for (iter = mPressedKeys.begin(); iter != mPressedKeys.end(); )
         {
            if (!key[iter->first])
            {
                KeyInput keyInput(iter->second.getKey(), KeyInput::RELEASED);
                keyInput.setNumericPad(iter->second.isNumericPad());
                keyInput.setShiftPressed(iter->second.isShiftPressed());
                keyInput.setAltPressed(iter->second.isAltPressed());
                keyInput.setControlPressed(iter->second.isControlPressed());

                mKeyQueue.push(keyInput);

                tempIter = iter;
                iter++;
                mPressedKeys.erase(tempIter);
            }
            else
            {
                iter++;
            }
        }
    }

    Key AllegroInput::convertToKey(int scancode, int unicode)
    {
        int keysym;
        bool pad = false;

        switch(scancode)
        {
          case KEY_ESC:
              keysym = Key::ESCAPE;
              break;

          case KEY_ALT:
              keysym = Key::LEFT_ALT;
              break;

          case KEY_ALTGR:
              keysym = Key::RIGHT_ALT;
              break;

          case KEY_LSHIFT:
              keysym = Key::LEFT_SHIFT;
              break;

          case KEY_RSHIFT:
              keysym = Key::RIGHT_SHIFT;
              break;

          case KEY_LCONTROL:
              keysym = Key::LEFT_CONTROL;
              break;

          case KEY_RCONTROL:
              keysym = Key::RIGHT_CONTROL;
              break;

          case KEY_LWIN:
              keysym = Key::LEFT_META;
              break;

          case KEY_RWIN:
              keysym = Key::RIGHT_META;
              break;

          case KEY_INSERT:
              keysym = Key::INSERT;
              break;

          case KEY_HOME:
              keysym = Key::HOME;
              break;

          case KEY_PGUP:
              keysym = Key::PAGE_UP;
              break;

          case KEY_PGDN:
              keysym = Key::PAGE_DOWN;
              break;

          case KEY_DEL:
              keysym = Key::DELETE;
              break;

          case KEY_DEL_PAD:
              keysym = Key::DELETE;
              pad = true;
              break;

          case KEY_END:
              keysym = Key::END;
              break;

          case KEY_CAPSLOCK:
              keysym = Key::CAPS_LOCK;
              break;

          case KEY_BACKSPACE:
              keysym = Key::BACKSPACE;
              break;

          case KEY_F1:
              keysym = Key::F1;
              break;

          case KEY_F2:
              keysym = Key::F2;
              break;

          case KEY_F3:
              keysym = Key::F3;
              break;

          case KEY_F4:
              keysym = Key::F4;
              break;

          case KEY_F5:
              keysym = Key::F5;
              break;

          case KEY_F6:
              keysym = Key::F6;
              break;

          case KEY_F7:
              keysym = Key::F7;
              break;

          case KEY_F8:
              keysym = Key::F8;
              break;

          case KEY_F9:
              keysym = Key::F9;
              break;

          case KEY_F10:
              keysym = Key::F10;
              break;

          case KEY_F11:
              keysym = Key::F11;
              break;

          case KEY_F12:
              keysym = Key::F12;
              break;

          case KEY_PRTSCR:
              keysym = Key::PRINT_SCREEN;
              break;

          case KEY_PAUSE:
              keysym = Key::PAUSE;
              break;

          case KEY_SCRLOCK:
              keysym = Key::SCROLL_LOCK;
              break;

          case KEY_NUMLOCK:
              keysym = Key::NUM_LOCK;
              break;

          case KEY_LEFT:
              keysym = Key::LEFT;
              break;

          case KEY_RIGHT:
              keysym = Key::RIGHT;
              break;

          case KEY_UP:
              keysym = Key::UP;
              break;

          case KEY_DOWN:
              keysym = Key::DOWN;
              break;

          case KEY_ENTER_PAD:
              pad = true;
          case KEY_ENTER:
              keysym = Key::ENTER;
              break;
     default:
              keysym = unicode;
        }

        Key k = Key(keysym);

        return k;

        //Now, THAT was fun to code! =D =D =D
    }

    bool AllegroInput::isNumericPad(int scancode)
    {
        switch (scancode)
        {
          case KEY_0_PAD:
          case KEY_1_PAD:
          case KEY_2_PAD:
          case KEY_3_PAD:
          case KEY_4_PAD:
          case KEY_5_PAD:
          case KEY_6_PAD:
          case KEY_7_PAD:
          case KEY_8_PAD:
          case KEY_9_PAD:
          case KEY_SLASH_PAD:
          case KEY_MINUS_PAD:
          case KEY_PLUS_PAD:
              return true;
          default:
              return false;
        }
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017-present Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <thrift/lib/cpp2/transport/inmemory/InMemoryConnection.h>

#include <gflags/gflags.h>
#include <glog/logging.h>
#include <thrift/lib/cpp2/transport/inmemory/InMemoryChannel.h>

DEFINE_int32(num_cpu_threads, 1, "Number of cpu threads");

namespace apache {
namespace thrift {

InMemoryConnection::InMemoryConnection(
    std::shared_ptr<AsyncProcessorFactory> pFac,
    const apache::thrift::server::ServerConfigs& serverConfigs) {
  CHECK(FLAGS_num_cpu_threads > 0);
  threadManager_ =
      PriorityThreadManager::newPriorityThreadManager(FLAGS_num_cpu_threads);
  threadManager_->start();
  processor_ =
      std::make_unique<ThriftProcessor>(pFac->getProcessor(), serverConfigs);
  processor_->setThreadManager(threadManager_.get());
}

std::shared_ptr<ThriftChannelIf> InMemoryConnection::getChannel(
    RequestRpcMetadata*) {
  return std::make_shared<InMemoryChannel>(
      processor_.get(), runner_.getEventBase());
}

void InMemoryConnection::setMaxPendingRequests(uint32_t /*num*/) {
  // not implemented
}

folly::EventBase* InMemoryConnection::getEventBase() const {
  return runner_.getEventBase();
}

apache::thrift::async::TAsyncTransport* InMemoryConnection::getTransport() {
  LOG(FATAL) << "Method should not be called";
}

bool InMemoryConnection::good() {
  LOG(FATAL) << "Method should not be called";
}

ClientChannel::SaturationStatus InMemoryConnection::getSaturationStatus() {
  LOG(FATAL) << "Method should not be called";
}

void InMemoryConnection::attachEventBase(folly::EventBase* /*evb*/) {
  LOG(FATAL) << "Method should not be called";
}

void InMemoryConnection::detachEventBase() {
  LOG(FATAL) << "Method should not be called";
}

bool InMemoryConnection::isDetachable() {
  LOG(FATAL) << "Method should not be called";
}

bool InMemoryConnection::isSecurityActive() {
  return false;
}

uint32_t InMemoryConnection::getTimeout() {
  LOG(FATAL) << "Method should not be called";
}

void InMemoryConnection::setTimeout(uint32_t /*ms*/) {
  LOG(FATAL) << "Method should not be called";
}

void InMemoryConnection::closeNow() {
  LOG(FATAL) << "Method should not be called";
}

CLIENT_TYPE InMemoryConnection::getClientType() {
  LOG(FATAL) << "Method should not be called";
}

} // namespace thrift
} // namespace apache
<commit_msg>Change flag name to avoid conflicts<commit_after>/*
 * Copyright 2017-present Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <thrift/lib/cpp2/transport/inmemory/InMemoryConnection.h>

#include <gflags/gflags.h>
#include <glog/logging.h>
#include <thrift/lib/cpp2/transport/inmemory/InMemoryChannel.h>

DEFINE_int32(thrift_num_cpu_threads, 1, "Number of cpu threads");

namespace apache {
namespace thrift {

InMemoryConnection::InMemoryConnection(
    std::shared_ptr<AsyncProcessorFactory> pFac,
    const apache::thrift::server::ServerConfigs& serverConfigs) {
  CHECK_GT(FLAGS_thrift_num_cpu_threads, 0);
  threadManager_ = PriorityThreadManager::newPriorityThreadManager(
      FLAGS_thrift_num_cpu_threads);
  threadManager_->start();
  processor_ =
      std::make_unique<ThriftProcessor>(pFac->getProcessor(), serverConfigs);
  processor_->setThreadManager(threadManager_.get());
}

std::shared_ptr<ThriftChannelIf> InMemoryConnection::getChannel(
    RequestRpcMetadata*) {
  return std::make_shared<InMemoryChannel>(
      processor_.get(), runner_.getEventBase());
}

void InMemoryConnection::setMaxPendingRequests(uint32_t /*num*/) {
  // not implemented
}

folly::EventBase* InMemoryConnection::getEventBase() const {
  return runner_.getEventBase();
}

apache::thrift::async::TAsyncTransport* InMemoryConnection::getTransport() {
  LOG(FATAL) << "Method should not be called";
}

bool InMemoryConnection::good() {
  LOG(FATAL) << "Method should not be called";
}

ClientChannel::SaturationStatus InMemoryConnection::getSaturationStatus() {
  LOG(FATAL) << "Method should not be called";
}

void InMemoryConnection::attachEventBase(folly::EventBase* /*evb*/) {
  LOG(FATAL) << "Method should not be called";
}

void InMemoryConnection::detachEventBase() {
  LOG(FATAL) << "Method should not be called";
}

bool InMemoryConnection::isDetachable() {
  LOG(FATAL) << "Method should not be called";
}

bool InMemoryConnection::isSecurityActive() {
  return false;
}

uint32_t InMemoryConnection::getTimeout() {
  LOG(FATAL) << "Method should not be called";
}

void InMemoryConnection::setTimeout(uint32_t /*ms*/) {
  LOG(FATAL) << "Method should not be called";
}

void InMemoryConnection::closeNow() {
  LOG(FATAL) << "Method should not be called";
}

CLIENT_TYPE InMemoryConnection::getClientType() {
  LOG(FATAL) << "Method should not be called";
}

} // namespace thrift
} // namespace apache
<|endoftext|>


<commit_before>#include <armadillo>
#include <gnuplot-iostream.h>

using namespace arma;
using namespace std;

namespace ic {

class SOM {
public:
    // Constructores
    SOM(const mat& patrones, pair<int, int> dimensiones, const vec& salidaDeseada = {});

    // Interfaz
    void entrenar(int nEpocas,
                  double velocidadInicial,
                  double velocidadFinal,
                  int vecindadInicial,
                  int vecindadFinal);
    void etiquetar();
    int clasificar(const rowvec& patron) const;
    vec clasificar(const mat& patrones) const;
    void graficar(Gnuplot& gp, bool graficarVecindades = true) const;

    // Acceso a miembros
    const field<rowvec>& mapa() const { return m_mapa; };
    const mat& etiquetas() const { return m_etiquetas; };
    const mat& patrones() const { return m_patrones; };

private:
    field<rowvec> m_mapa;
    mat m_etiquetas;
    const mat m_patrones;
    const vec m_salidaDeseada;

    pair<pair<int, int>, double> buscarGanadora(const rowvec& patron) const;
};

SOM::SOM(const mat& patrones, pair<int, int> dimensiones, const vec& salidaDeseada)
    : m_patrones{patrones}
    , m_salidaDeseada{salidaDeseada}
{
    m_mapa = field<rowvec>(dimensiones.first, dimensiones.second);

    // Inicializar mapa
    for (unsigned int i = 0; i < m_mapa.n_rows; ++i) {
        for (unsigned int j = 0; j < m_mapa.n_cols; ++j) {
            m_mapa(i, j) = randu<rowvec>(patrones.n_cols) - 0.5;
        }
    }
}

pair<pair<int, int>, double> SOM::buscarGanadora(const rowvec& patron) const
{
    pair<int, int> coordGanadora;
    double distanciaGanadora = numeric_limits<double>::max();

    for (unsigned int j = 0; j < m_mapa.n_rows; ++j) {
        for (unsigned int k = 0; k < m_mapa.n_cols; ++k) {
            const double distancia = norm(patron - m_mapa(j, k));

            if (distancia < distanciaGanadora) {
                distanciaGanadora = distancia;
                coordGanadora = {j, k};
            }
        }
    }

    return {coordGanadora, distanciaGanadora};
}

void SOM::entrenar(int nEpocas,
                   double velocidadInicial,
                   double velocidadFinal,
                   int vecindadInicial,
                   int vecindadFinal)
{
    const vec velocidad = linspace(velocidadInicial, velocidadFinal, nEpocas);
    // Redondeamos la vecindad porque necesitamos que tenga valores enteros
    const vec vecindad = round(linspace(vecindadInicial, vecindadFinal, nEpocas));

    for (int epoca = 0; epoca < nEpocas; ++epoca) {
        for (unsigned int n = 0; n < m_patrones.n_rows; ++n) {

            // Buscamos la neurona ganadora
            pair<int, int> coordGanadora;
            double distanciaGanadora;
            tie(coordGanadora, distanciaGanadora) = buscarGanadora(m_patrones.row(n));

            // Adaptación de pesos
            const int maxX = int(m_mapa.n_rows - 1);
            const int maxY = int(m_mapa.n_cols - 1);
            const int xInicial = (coordGanadora.first - vecindad(epoca) < 0) ? 0 : (coordGanadora.first - vecindad(epoca));
            const int xFinal = (coordGanadora.first + vecindad(epoca) > maxX) ? maxX : (coordGanadora.first + vecindad(epoca));
            const int yInicial = (coordGanadora.second - vecindad(epoca) < 0) ? 0 : (coordGanadora.second - vecindad(epoca));
            const int yFinal = (coordGanadora.second + vecindad(epoca) > maxY) ? maxY : (coordGanadora.second + vecindad(epoca));

            for (int x = xInicial; x <= xFinal; ++x) {
                for (int y = yInicial; y <= yFinal; ++y) {
                    m_mapa(x, y) += velocidad(epoca) * (m_patrones.row(n) - m_mapa(x, y));
                }
            }
        }
    }
}

void SOM::etiquetar()
{
    if (m_salidaDeseada.empty())
        throw runtime_error("Este SOM no posee una salida deseada asociada a los patrones");

    field<ivec> mapaContador(m_mapa.n_rows, m_mapa.n_cols);

    // Inicializar los contadores de clases
    for (unsigned int x = 0; x < m_mapa.n_rows; ++x) {
        for (unsigned int y = 0; y < m_mapa.n_cols; ++y) {
            mapaContador(x, y) = zeros<ivec>(2);
        }
    }

    // Contamos, para cada neurona, qué cantidad de veces gana para cada clase
    for (unsigned int n = 0; n < m_patrones.n_rows; ++n) {
        pair<int, int> ganadora;
        tie(ganadora, ignore) = buscarGanadora(m_patrones.row(n));

        if (m_salidaDeseada(n) == 0)
            mapaContador(ganadora.first, ganadora.second).at(0) += 1;
        else
            mapaContador(ganadora.first, ganadora.second).at(1) += 1;
    }

    m_etiquetas = mat(m_mapa.n_rows, m_mapa.n_cols);

    // Se asignan las etiquetas de clase
    for (unsigned int x = 0; x < m_mapa.n_rows; ++x) {
        for (unsigned int y = 0; y < m_mapa.n_cols; ++y) {
            if (max(mapaContador(x, y)) == min(mapaContador(x, y)))
                throw runtime_error("La neurona se activó el mismo nro de veces para las dos clases");

            m_etiquetas(x, y) = index_max(mapaContador(x, y));
        }
    }
}

int SOM::clasificar(const rowvec& patron) const
{
    pair<int, int> ganadora;
    tie(ganadora, ignore) = buscarGanadora(patron);

    return m_etiquetas(ganadora.first, ganadora.second);
}

vec SOM::clasificar(const mat& patrones) const
{
    vec result = zeros(patrones.n_rows);

    for (unsigned int n = 0; n < patrones.n_rows; ++n) {
        result(n) = clasificar(rowvec{patrones.row(n)});
    }

    return result;
}

void SOM::graficar(Gnuplot& gp, bool graficarVecindades) const
{
    gp << "set key box opaque width 3" << endl
       << "set xlabel 'x_1' font ',11'" << endl
       << "set ylabel 'x_2' font ',11'" << endl

       // Graficar patrones
       << "plot " << gp.file1d(m_patrones) << "title 'Patrones' with points pt 2 ps 1 lt rgb 'blue', ";

    // Graficar neuronas del mapa y las conexiones
    for (unsigned int x = 0; x < m_mapa.n_rows; ++x) {
        for (unsigned int y = 0; y < m_mapa.n_cols; ++y) {
            // Graficar la neurona
            gp << gp.file1d(m_mapa(x, y).eval()) << "notitle with points ps 2 pt 1 lt -1 lw 3, ";

            if (graficarVecindades) {
                // Graficar conexiones con las vecinas horizontales y verticales
                if (x != 0)
                    gp << gp.file1d(join_vert(m_mapa(x, y), m_mapa(x - 1, y)).eval()) << "notitle with lines lt -1, ";
                if (x != m_mapa.n_rows - 1)
                    gp << gp.file1d(join_vert(m_mapa(x, y), m_mapa(x + 1, y)).eval()) << "notitle with lines lt -1, ";
                if (y != 0)
                    gp << gp.file1d(join_vert(m_mapa(x, y), m_mapa(x, y - 1)).eval()) << "notitle with lines lt -1, ";
                if (y != m_mapa.n_cols - 1)
                    gp << gp.file1d(join_vert(m_mapa(x, y), m_mapa(x, y + 1)).eval()) << "notitle with lines lt -1, ";
            }
        }
    }

    // Título de los centroides para la leyenda
    gp << "NaN title 'Neuronas' with points ps 2 pt 1 lt -1 lw 3" << endl;
}
}
<commit_msg>Guia 2 - SOM: En SOM::etiquetar, cuando una neurona se activa la misma cantidad de veces para las dos clases, asignarle una etiqueta aleatoria<commit_after>#include <armadillo>
#include <gnuplot-iostream.h>

using namespace arma;
using namespace std;

namespace ic {

class SOM {
public:
    // Constructores
    SOM(const mat& patrones, pair<int, int> dimensiones, const vec& salidaDeseada = {});

    // Interfaz
    void entrenar(int nEpocas,
                  double velocidadInicial,
                  double velocidadFinal,
                  int vecindadInicial,
                  int vecindadFinal);
    void etiquetar();
    int clasificar(const rowvec& patron) const;
    vec clasificar(const mat& patrones) const;
    void graficar(Gnuplot& gp, bool graficarVecindades = true) const;

    // Acceso a miembros
    const field<rowvec>& mapa() const { return m_mapa; };
    const mat& etiquetas() const { return m_etiquetas; };
    const mat& patrones() const { return m_patrones; };

private:
    field<rowvec> m_mapa;
    mat m_etiquetas;
    const mat m_patrones;
    const vec m_salidaDeseada;

    pair<pair<int, int>, double> buscarGanadora(const rowvec& patron) const;
};

SOM::SOM(const mat& patrones, pair<int, int> dimensiones, const vec& salidaDeseada)
    : m_patrones{patrones}
    , m_salidaDeseada{salidaDeseada}
{
    m_mapa = field<rowvec>(dimensiones.first, dimensiones.second);

    // Inicializar mapa
    for (unsigned int i = 0; i < m_mapa.n_rows; ++i) {
        for (unsigned int j = 0; j < m_mapa.n_cols; ++j) {
            m_mapa(i, j) = randu<rowvec>(patrones.n_cols) - 0.5;
        }
    }
}

pair<pair<int, int>, double> SOM::buscarGanadora(const rowvec& patron) const
{
    pair<int, int> coordGanadora;
    double distanciaGanadora = numeric_limits<double>::max();

    for (unsigned int j = 0; j < m_mapa.n_rows; ++j) {
        for (unsigned int k = 0; k < m_mapa.n_cols; ++k) {
            const double distancia = norm(patron - m_mapa(j, k));

            if (distancia < distanciaGanadora) {
                distanciaGanadora = distancia;
                coordGanadora = {j, k};
            }
        }
    }

    return {coordGanadora, distanciaGanadora};
}

void SOM::entrenar(int nEpocas,
                   double velocidadInicial,
                   double velocidadFinal,
                   int vecindadInicial,
                   int vecindadFinal)
{
    const vec velocidad = linspace(velocidadInicial, velocidadFinal, nEpocas);
    // Redondeamos la vecindad porque necesitamos que tenga valores enteros
    const vec vecindad = round(linspace(vecindadInicial, vecindadFinal, nEpocas));

    for (int epoca = 0; epoca < nEpocas; ++epoca) {
        for (unsigned int n = 0; n < m_patrones.n_rows; ++n) {

            // Buscamos la neurona ganadora
            pair<int, int> coordGanadora;
            double distanciaGanadora;
            tie(coordGanadora, distanciaGanadora) = buscarGanadora(m_patrones.row(n));

            // Adaptación de pesos
            const int maxX = int(m_mapa.n_rows - 1);
            const int maxY = int(m_mapa.n_cols - 1);
            const int xInicial = (coordGanadora.first - vecindad(epoca) < 0) ? 0 : (coordGanadora.first - vecindad(epoca));
            const int xFinal = (coordGanadora.first + vecindad(epoca) > maxX) ? maxX : (coordGanadora.first + vecindad(epoca));
            const int yInicial = (coordGanadora.second - vecindad(epoca) < 0) ? 0 : (coordGanadora.second - vecindad(epoca));
            const int yFinal = (coordGanadora.second + vecindad(epoca) > maxY) ? maxY : (coordGanadora.second + vecindad(epoca));

            for (int x = xInicial; x <= xFinal; ++x) {
                for (int y = yInicial; y <= yFinal; ++y) {
                    m_mapa(x, y) += velocidad(epoca) * (m_patrones.row(n) - m_mapa(x, y));
                }
            }
        }
    }
}

void SOM::etiquetar()
{
    if (m_salidaDeseada.empty())
        throw runtime_error("Este SOM no posee una salida deseada asociada a los patrones");

    field<ivec> mapaContador(m_mapa.n_rows, m_mapa.n_cols);

    // Inicializar los contadores de clases
    for (unsigned int x = 0; x < m_mapa.n_rows; ++x) {
        for (unsigned int y = 0; y < m_mapa.n_cols; ++y) {
            mapaContador(x, y) = zeros<ivec>(2);
        }
    }

    // Contamos, para cada neurona, qué cantidad de veces gana para cada clase
    for (unsigned int n = 0; n < m_patrones.n_rows; ++n) {
        pair<int, int> ganadora;
        tie(ganadora, ignore) = buscarGanadora(m_patrones.row(n));

        if (m_salidaDeseada(n) == 0)
            mapaContador(ganadora.first, ganadora.second).at(0) += 1;
        else
            mapaContador(ganadora.first, ganadora.second).at(1) += 1;
    }

    m_etiquetas = mat(m_mapa.n_rows, m_mapa.n_cols);

    // Se asignan las etiquetas de clase
    for (unsigned int x = 0; x < m_mapa.n_rows; ++x) {
        for (unsigned int y = 0; y < m_mapa.n_cols; ++y) {
            if (mapaContador(x, y)(0) == mapaContador(x, y)(1))
                // Si la neurona ganó la misma cantidad de veces para ambas clases,
                // se le asigna la clase al azar.
                m_etiquetas(x, y) = as_scalar(randi(1, distr_param(0, 1)));
            else
                m_etiquetas(x, y) = index_max(mapaContador(x, y));
        }
    }
}

int SOM::clasificar(const rowvec& patron) const
{
    pair<int, int> ganadora;
    tie(ganadora, ignore) = buscarGanadora(patron);

    return m_etiquetas(ganadora.first, ganadora.second);
}

vec SOM::clasificar(const mat& patrones) const
{
    vec result = zeros(patrones.n_rows);

    for (unsigned int n = 0; n < patrones.n_rows; ++n) {
        result(n) = clasificar(rowvec{patrones.row(n)});
    }

    return result;
}

void SOM::graficar(Gnuplot& gp, bool graficarVecindades) const
{
    gp << "set key box opaque width 3" << endl
       << "set xlabel 'x_1' font ',11'" << endl
       << "set ylabel 'x_2' font ',11'" << endl

       // Graficar patrones
       << "plot " << gp.file1d(m_patrones) << "title 'Patrones' with points pt 2 ps 1 lt rgb 'blue', ";

    // Graficar neuronas del mapa y las conexiones
    for (unsigned int x = 0; x < m_mapa.n_rows; ++x) {
        for (unsigned int y = 0; y < m_mapa.n_cols; ++y) {
            // Graficar la neurona
            gp << gp.file1d(m_mapa(x, y).eval()) << "notitle with points ps 2 pt 1 lt -1 lw 3, ";

            if (graficarVecindades) {
                // Graficar conexiones con las vecinas horizontales y verticales
                if (x != 0)
                    gp << gp.file1d(join_vert(m_mapa(x, y), m_mapa(x - 1, y)).eval()) << "notitle with lines lt -1, ";
                if (x != m_mapa.n_rows - 1)
                    gp << gp.file1d(join_vert(m_mapa(x, y), m_mapa(x + 1, y)).eval()) << "notitle with lines lt -1, ";
                if (y != 0)
                    gp << gp.file1d(join_vert(m_mapa(x, y), m_mapa(x, y - 1)).eval()) << "notitle with lines lt -1, ";
                if (y != m_mapa.n_cols - 1)
                    gp << gp.file1d(join_vert(m_mapa(x, y), m_mapa(x, y + 1)).eval()) << "notitle with lines lt -1, ";
            }
        }
    }

    // Título de los centroides para la leyenda
    gp << "NaN title 'Neuronas' with points ps 2 pt 1 lt -1 lw 3" << endl;
}
}
<|endoftext|>


<commit_before>#include "controller.h"
#include "animation/animation.h"
#include "engine/log.h"
#include "engine/resource_manager.h"
#include "engine/resource_manager_base.h"

namespace Lumix
{

static const ResourceType ANIMATION_TYPE("animation");

namespace Anim
{

enum class Version : int
{
	LAST
};

struct Header
{
	static const uint32 FILE_MAGIC = '_LAC'; // == '_LAC'
	uint32 magic = FILE_MAGIC;
	int version = (int)Version::LAST;
	uint32 reserved[4] = {0};
};

ControllerResource::ControllerResource(const Path& path, ResourceManagerBase& resource_manager, IAllocator& allocator)
	: Resource(path, resource_manager, allocator)
	, m_root(nullptr)
	, m_allocator(allocator)
	, m_anim_set(allocator)
{
}

ControllerResource::~ControllerResource()
{
	unload();
}

void ControllerResource::unload()
{
	LUMIX_DELETE(m_allocator, m_root);
	m_root = nullptr;
	for (Animation* anim : m_anim_set)
	{
		if (anim)
		{
			removeDependency(*anim);
			anim->getResourceManager().unload(*anim);
		}
	}
	m_anim_set.clear();
}

bool ControllerResource::load(FS::IFile& file)
{
	InputBlob blob(file.getBuffer(), (int)file.size());
	return deserialize(blob);
	return true;
}

void ControllerResource::setRoot(Component* component)
{
	m_root = component;
}

bool ControllerResource::deserialize(InputBlob& blob)
{
	Header header;
	blob.read(header);
	if (header.magic != Header::FILE_MAGIC)
	{
		g_log_error.log("Animation") << getPath().c_str() << " is not an animation controller file.";
		return false;
	}
	if (header.version != (int)Version::LAST)
	{
		g_log_error.log("Animation") << getPath().c_str() << " has unsupported version.";
		return false;
	}
	Component::Type type;
	blob.read(type);
	m_root = createComponent(type, m_allocator);
	m_root->deserialize(blob, nullptr);
	blob.read(m_input_decl.inputs_count);
	for (int i = 0; i < m_input_decl.inputs_count; ++i)
	{
		auto& input = m_input_decl.inputs[i];
		blob.readString(input.name, lengthOf(input.name));
		blob.read(input.type);
		blob.read(input.offset);
	}

	blob.read(m_input_decl.constants_count);
	for (int i = 0; i < m_input_decl.constants_count; ++i)
	{
		auto& constant = m_input_decl.constants[i];
		blob.readString(constant.name, lengthOf(constant.name));
		blob.read(constant.type);
		switch (constant.type)
		{
			case InputDecl::BOOL: blob.read(constant.b_value); break;
			case InputDecl::INT: blob.read(constant.i_value); break;
			case InputDecl::FLOAT: blob.read(constant.f_value); break;
			default: ASSERT(false); return false;
		}
	}

	m_anim_set.clear();
	int count;
	blob.read(count);
	auto* manager = m_resource_manager.getOwner().get(ANIMATION_TYPE);
	for (int i = 0; i < count; ++i)
	{
		uint32 key;
		char path[MAX_PATH_LENGTH];
		blob.read(key);
		blob.readString(path, lengthOf(path));
		Animation* anim = path[0] ? (Animation*)manager->load(Path(path)) : nullptr;
		if(anim) addDependency(*anim);
		m_anim_set.insert(key, anim);
	}
	return true;
}

void ControllerResource::serialize(OutputBlob& blob)
{
	Header header;
	blob.write(header);
	blob.write(m_root->type);
	m_root->serialize(blob);
	blob.write(m_input_decl.inputs_count);
	for (int i = 0; i < m_input_decl.inputs_count; ++i)
	{
		auto& input = m_input_decl.inputs[i];
		blob.writeString(input.name);
		blob.write(input.type);
		blob.write(input.offset);
	}
	blob.write(m_input_decl.constants_count);
	for (int i = 0; i < m_input_decl.constants_count; ++i)
	{
		auto& constant = m_input_decl.constants[i];
		blob.writeString(constant.name);
		blob.write(constant.type);
		switch (constant.type)
		{
			case InputDecl::BOOL: blob.write(constant.b_value); break;
			case InputDecl::INT: blob.write(constant.i_value); break;
			case InputDecl::FLOAT: blob.write(constant.f_value); break;
			default: ASSERT(false); return;
		}

	}
	blob.write(m_anim_set.size());
	for (auto iter = m_anim_set.begin(), end = m_anim_set.end(); iter != end; ++iter)
	{
		blob.write(iter.key());
		blob.writeString(iter.value() ? iter.value()->getPath().c_str() : "");
	}
}

ComponentInstance* ControllerResource::createInstance(IAllocator& allocator)
{
	return m_root ? m_root->createInstance(allocator) : nullptr;
}

Resource* ControllerManager::createResource(const Path& path)
{
	return LUMIX_NEW(m_allocator, ControllerResource)(path, *this, m_allocator);
}

void ControllerManager::destroyResource(Resource& resource)
{
	LUMIX_DELETE(m_allocator, (ControllerResource*)&resource);
}

} // namespace Anim

} // namespace Lumix<commit_msg>fixed linux build<commit_after>#include "controller.h"
#include "animation/animation.h"
#include "engine/log.h"
#include "engine/resource_manager.h"
#include "engine/resource_manager_base.h"

namespace Lumix
{

static const ResourceType ANIMATION_TYPE("animation");

namespace Anim
{

enum class Version : int
{
	LAST
};

struct Header
{
	static const uint32 FILE_MAGIC = 0x5f4c4143; // == '_LAC'
	uint32 magic = FILE_MAGIC;
	int version = (int)Version::LAST;
	uint32 reserved[4] = {0};
};

ControllerResource::ControllerResource(const Path& path, ResourceManagerBase& resource_manager, IAllocator& allocator)
	: Resource(path, resource_manager, allocator)
	, m_root(nullptr)
	, m_allocator(allocator)
	, m_anim_set(allocator)
{
}

ControllerResource::~ControllerResource()
{
	unload();
}

void ControllerResource::unload()
{
	LUMIX_DELETE(m_allocator, m_root);
	m_root = nullptr;
	for (Animation* anim : m_anim_set)
	{
		if (anim)
		{
			removeDependency(*anim);
			anim->getResourceManager().unload(*anim);
		}
	}
	m_anim_set.clear();
}

bool ControllerResource::load(FS::IFile& file)
{
	InputBlob blob(file.getBuffer(), (int)file.size());
	return deserialize(blob);
	return true;
}

void ControllerResource::setRoot(Component* component)
{
	m_root = component;
}

bool ControllerResource::deserialize(InputBlob& blob)
{
	Header header;
	blob.read(header);
	if (header.magic != Header::FILE_MAGIC)
	{
		g_log_error.log("Animation") << getPath().c_str() << " is not an animation controller file.";
		return false;
	}
	if (header.version != (int)Version::LAST)
	{
		g_log_error.log("Animation") << getPath().c_str() << " has unsupported version.";
		return false;
	}
	Component::Type type;
	blob.read(type);
	m_root = createComponent(type, m_allocator);
	m_root->deserialize(blob, nullptr);
	blob.read(m_input_decl.inputs_count);
	for (int i = 0; i < m_input_decl.inputs_count; ++i)
	{
		auto& input = m_input_decl.inputs[i];
		blob.readString(input.name, lengthOf(input.name));
		blob.read(input.type);
		blob.read(input.offset);
	}

	blob.read(m_input_decl.constants_count);
	for (int i = 0; i < m_input_decl.constants_count; ++i)
	{
		auto& constant = m_input_decl.constants[i];
		blob.readString(constant.name, lengthOf(constant.name));
		blob.read(constant.type);
		switch (constant.type)
		{
			case InputDecl::BOOL: blob.read(constant.b_value); break;
			case InputDecl::INT: blob.read(constant.i_value); break;
			case InputDecl::FLOAT: blob.read(constant.f_value); break;
			default: ASSERT(false); return false;
		}
	}

	m_anim_set.clear();
	int count;
	blob.read(count);
	auto* manager = m_resource_manager.getOwner().get(ANIMATION_TYPE);
	for (int i = 0; i < count; ++i)
	{
		uint32 key;
		char path[MAX_PATH_LENGTH];
		blob.read(key);
		blob.readString(path, lengthOf(path));
		Animation* anim = path[0] ? (Animation*)manager->load(Path(path)) : nullptr;
		if(anim) addDependency(*anim);
		m_anim_set.insert(key, anim);
	}
	return true;
}

void ControllerResource::serialize(OutputBlob& blob)
{
	Header header;
	blob.write(header);
	blob.write(m_root->type);
	m_root->serialize(blob);
	blob.write(m_input_decl.inputs_count);
	for (int i = 0; i < m_input_decl.inputs_count; ++i)
	{
		auto& input = m_input_decl.inputs[i];
		blob.writeString(input.name);
		blob.write(input.type);
		blob.write(input.offset);
	}
	blob.write(m_input_decl.constants_count);
	for (int i = 0; i < m_input_decl.constants_count; ++i)
	{
		auto& constant = m_input_decl.constants[i];
		blob.writeString(constant.name);
		blob.write(constant.type);
		switch (constant.type)
		{
			case InputDecl::BOOL: blob.write(constant.b_value); break;
			case InputDecl::INT: blob.write(constant.i_value); break;
			case InputDecl::FLOAT: blob.write(constant.f_value); break;
			default: ASSERT(false); return;
		}

	}
	blob.write(m_anim_set.size());
	for (auto iter = m_anim_set.begin(), end = m_anim_set.end(); iter != end; ++iter)
	{
		blob.write(iter.key());
		blob.writeString(iter.value() ? iter.value()->getPath().c_str() : "");
	}
}

ComponentInstance* ControllerResource::createInstance(IAllocator& allocator)
{
	return m_root ? m_root->createInstance(allocator) : nullptr;
}

Resource* ControllerManager::createResource(const Path& path)
{
	return LUMIX_NEW(m_allocator, ControllerResource)(path, *this, m_allocator);
}

void ControllerManager::destroyResource(Resource& resource)
{
	LUMIX_DELETE(m_allocator, (ControllerResource*)&resource);
}

} // namespace Anim

} // namespace Lumix<|endoftext|>


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

#include "common/RhoTime.h"
#include "common/RhodesApp.h"

namespace rho{
namespace common{

CRhoTimer::CTimerItem::CTimerItem(int nInterval, const char* szCallback, const char* szCallbackData):
    m_nInterval(nInterval), m_strCallback(szCallback), m_strCallbackData(szCallbackData)
{
	m_oFireTime = CTimeInterval::getCurrentTime();
	m_overflow = m_oFireTime.addMillis(nInterval);
}

CRhoTimer::CNativeTimerItem::CNativeTimerItem(int nInterval, CRhoTimer::ICallback* callback):
    m_nInterval(nInterval), m_pCallback(callback)
{
	m_oFireTime = CTimeInterval::getCurrentTime();
    m_overflow = m_oFireTime.addMillis(nInterval);
}

CRhoTimer::CRhoTimer() : m_checkerThread(*this)
{
  m_checkerThread.start(IRhoRunnable::epNormal);
}

CRhoTimer::~CRhoTimer()
{
  m_checkerThread.stop(1000);
}

void CRhoTimer::addTimer(int nInterval, const char* szCallback, const char* szCallbackData)
{
    RAWTRACE2("CRhoTimer::addTimer %d, %s", nInterval, szCallback);

    synchronized(m_mxAccess)
    {
      m_arItems.addElement(CTimerItem(nInterval, szCallback, szCallbackData));
// Multiple Timer blocking case fix
#if defined(OS_MACOSX) || defined(OS_IPHONE)
    //Nothing to do
#else
      m_checkerThread.stopWait();
#endif
    }
}

void CRhoTimer::addNativeTimer(int nInterval, CRhoTimer::ICallback* callback)
{
    RAWTRACE1("CRhoTimer::addNativeTimer %d", nInterval);

    synchronized(m_mxAccess)
    {
      m_arNativeItems.addElement(CNativeTimerItem(nInterval, callback));
#if defined(OS_MACOSX) || defined(OS_IPHONE)
        //Nothing to do
#else
      m_checkerThread.stopWait();
#endif
    }
}

unsigned long CRhoTimer::getNextTimeout()
{
    synchronized(m_mxAccess);

    if ( (m_arItems.size() == 0) && (m_arNativeItems.size() == 0) )
        return 0;

    CTimeInterval curTime = CTimeInterval::getCurrentTime();
    unsigned long nMinInterval = ((unsigned long)-1);

    for( int i = 0; i < (int)m_arItems.size(); i++ )
    {
        unsigned long nInterval = 0;
        if ( m_arItems.elementAt(i).m_oFireTime.toULong() > curTime.toULong() )
    		{
            nInterval = m_arItems.elementAt(i).m_oFireTime.toULong() - curTime.toULong();
    		}
    		else
    		{
        		nInterval=nMinInterval+m_arItems.elementAt(i).m_oFireTime.toULong() - curTime.toULong();
    		}

        if ( nInterval < nMinInterval )
            nMinInterval = nInterval;
    }

    for( int i = 0; i < (int)m_arNativeItems.size(); i++ )
    {
        unsigned long nInterval = 0;
        if ( m_arNativeItems.elementAt(i).m_oFireTime.toULong() > curTime.toULong() )
    		{
            nInterval = m_arNativeItems.elementAt(i).m_oFireTime.toULong() - curTime.toULong();
    		}
    		else
    		{
        		nInterval=nMinInterval+m_arNativeItems.elementAt(i).m_oFireTime.toULong() - curTime.toULong();
    		}

        if ( nInterval < nMinInterval )
            nMinInterval = nInterval;
    }

    if ( nMinInterval < 100 )
        nMinInterval = 100;

    RAWTRACE1("CRhoTimer::getNextTimeout: %d",nMinInterval);

    return nMinInterval;
}

boolean CRhoTimer::checkTimers()
{
    RAWTRACE("CRhoTimer::checkTimers");

    synchronized(m_mxAccess);

    boolean bRet = false;
    CTimeInterval curTime = CTimeInterval::getCurrentTime();
    for( int i = (int)m_arItems.size()-1; i >= 0; i--)
    {
        CTimerItem oItem = m_arItems.elementAt(i);
		if(oItem.m_overflow==false)
		{

			if ( curTime.toULong() >= oItem.m_oFireTime.toULong() )
			{
                RAWTRACE("CRhoTimer::checkTimers: firing timer");
				m_arItems.removeElementAt(i);
				if ( RHODESAPP().callTimerCallback(oItem.m_strCallback, oItem.m_strCallbackData) )
					bRet = true;
			}

		}
		else
		{
			if ( curTime.toULong() >= oItem.m_oFireTime.toULong() )
			{
				if((curTime.toULong()-oItem.m_oFireTime.toULong())<=oItem.m_nInterval)
				{
                    RAWTRACE("CRhoTimer::checkTimers: firing timer");
					m_arItems.removeElementAt(i);
					if ( RHODESAPP().callTimerCallback(oItem.m_strCallback, oItem.m_strCallbackData) )
						bRet = true;
				}

			}

		}
    }

    for( int i = (int)m_arNativeItems.size()-1; i >= 0; i--)
    {
        CNativeTimerItem oItem = m_arNativeItems.elementAt(i);

        if(oItem.m_overflow==false)
		{
            if ( curTime.toULong() >= oItem.m_oFireTime.toULong() )
            {
                RAWTRACE("CRhoTimer::checkTimers: firing native timer");
                m_arNativeItems.removeElementAt(i);
                if ( oItem.m_pCallback->onTimer() )
                    bRet = true;
            }
        }
        else
        {
            if ( curTime.toULong() >= oItem.m_oFireTime.toULong() )
			{
				if((curTime.toULong()-oItem.m_oFireTime.toULong())<=oItem.m_nInterval)
				{
                    RAWTRACE("CRhoTimer::checkTimers: firing native timer");
                    m_arNativeItems.removeElementAt(i);
                    if ( oItem.m_pCallback->onTimer() )
                        bRet = true;
				}

			}
        }
    }

    return bRet;
}

void CRhoTimer::stopTimer(const char* szCallback)
{
    RAWTRACE1("CRhoTimer::stopTimer: %s",szCallback);

    synchronized(m_mxAccess);

    if ( !szCallback || !*szCallback)
        m_arItems.removeAllElements();

    for( int i = (int)m_arItems.size()-1; i >= 0; i--)
    {
        CTimerItem oItem = m_arItems.elementAt(i);
        if ( oItem.m_strCallback.compare(szCallback) == 0 )
        {
            m_arItems.removeElementAt(i);
        }
    }
}

void CRhoTimer::stopNativeTimer(CRhoTimer::ICallback* callback)
{
  RAWTRACE("CRhoTimer::stopNativeTimer");

  synchronized(m_mxAccess);

  if ( 0 == callback )
  {
    m_arNativeItems.removeAllElements();
  }

  for( int i = (int)m_arNativeItems.size()-1; i >= 0; i--)
  {
    CNativeTimerItem oItem = m_arNativeItems.elementAt(i);
    if ( oItem.m_pCallback == callback )
    {
      m_arNativeItems.removeElementAt(i);
    }
  }

}

bool CRhoTimer::isNativeTimerExist(CRhoTimer::ICallback* callback)
{
	if (callback)
	{
		for (int i = (int)m_arNativeItems.size() - 1; i >= 0; i--)
		{
			CNativeTimerItem oItem = m_arNativeItems.elementAt(i);
			if (oItem.m_pCallback == callback)
			{
				return true;
			}
		}
	}

	return false;
}

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

#include "common/RhoTime.h"
#include "common/RhodesApp.h"

namespace rho{
namespace common{

CRhoTimer::CTimerItem::CTimerItem(int nInterval, const char* szCallback, const char* szCallbackData):
    m_nInterval(nInterval), m_strCallback(szCallback), m_strCallbackData(szCallbackData)
{
	m_oFireTime = CTimeInterval::getCurrentTime();
	m_overflow = m_oFireTime.addMillis(nInterval);
}

CRhoTimer::CNativeTimerItem::CNativeTimerItem(int nInterval, CRhoTimer::ICallback* callback):
    m_nInterval(nInterval), m_pCallback(callback)
{
	m_oFireTime = CTimeInterval::getCurrentTime();
    m_overflow = m_oFireTime.addMillis(nInterval);
}

CRhoTimer::CRhoTimer() : m_checkerThread(*this)
{
  m_checkerThread.start(IRhoRunnable::epNormal);
}

CRhoTimer::~CRhoTimer()
{
  m_checkerThread.stop(1000);
}

void CRhoTimer::addTimer(int nInterval, const char* szCallback, const char* szCallbackData)
{
    RAWTRACE2("CRhoTimer::addTimer %d, %s", nInterval, szCallback);

    synchronized(m_mxAccess)
    {
      m_arItems.addElement(CTimerItem(nInterval, szCallback, szCallbackData));

      m_checkerThread.stopWait();

    }
}

void CRhoTimer::addNativeTimer(int nInterval, CRhoTimer::ICallback* callback)
{
    RAWTRACE1("CRhoTimer::addNativeTimer %d", nInterval);

    synchronized(m_mxAccess)
    {
      m_arNativeItems.addElement(CNativeTimerItem(nInterval, callback));

      m_checkerThread.stopWait();

    }
}

unsigned long CRhoTimer::getNextTimeout()
{
    synchronized(m_mxAccess);

    if ( (m_arItems.size() == 0) && (m_arNativeItems.size() == 0) )
        return 0;

    CTimeInterval curTime = CTimeInterval::getCurrentTime();
    unsigned long nMinInterval = ((unsigned long)-1);

    for( int i = 0; i < (int)m_arItems.size(); i++ )
    {
        unsigned long nInterval = 0;
        if ( m_arItems.elementAt(i).m_oFireTime.toULong() > curTime.toULong() )
    		{
            nInterval = m_arItems.elementAt(i).m_oFireTime.toULong() - curTime.toULong();
    		}
    		else
    		{
        		nInterval=nMinInterval+m_arItems.elementAt(i).m_oFireTime.toULong() - curTime.toULong();
    		}

        if ( nInterval < nMinInterval )
            nMinInterval = nInterval;
    }

    for( int i = 0; i < (int)m_arNativeItems.size(); i++ )
    {
        unsigned long nInterval = 0;
        if ( m_arNativeItems.elementAt(i).m_oFireTime.toULong() > curTime.toULong() )
    		{
            nInterval = m_arNativeItems.elementAt(i).m_oFireTime.toULong() - curTime.toULong();
    		}
    		else
    		{
        		nInterval=nMinInterval+m_arNativeItems.elementAt(i).m_oFireTime.toULong() - curTime.toULong();
    		}

        if ( nInterval < nMinInterval )
            nMinInterval = nInterval;
    }

    if ( nMinInterval < 100 )
        nMinInterval = 100;

    RAWTRACE1("CRhoTimer::getNextTimeout: %d",nMinInterval);

    return nMinInterval;
}

boolean CRhoTimer::checkTimers()
{
    RAWTRACE("CRhoTimer::checkTimers");

    synchronized(m_mxAccess);

    boolean bRet = false;
    CTimeInterval curTime = CTimeInterval::getCurrentTime();
    for( int i = (int)m_arItems.size()-1; i >= 0; i--)
    {
        CTimerItem oItem = m_arItems.elementAt(i);
		if(oItem.m_overflow==false)
		{

			if ( curTime.toULong() >= oItem.m_oFireTime.toULong() )
			{
                RAWTRACE("CRhoTimer::checkTimers: firing timer");
				m_arItems.removeElementAt(i);
				if ( RHODESAPP().callTimerCallback(oItem.m_strCallback, oItem.m_strCallbackData) )
					bRet = true;
			}

		}
		else
		{
			if ( curTime.toULong() >= oItem.m_oFireTime.toULong() )
			{
				if((curTime.toULong()-oItem.m_oFireTime.toULong())<=oItem.m_nInterval)
				{
                    RAWTRACE("CRhoTimer::checkTimers: firing timer");
					m_arItems.removeElementAt(i);
					if ( RHODESAPP().callTimerCallback(oItem.m_strCallback, oItem.m_strCallbackData) )
						bRet = true;
				}

			}

		}
    }

    for( int i = (int)m_arNativeItems.size()-1; i >= 0; i--)
    {
        CNativeTimerItem oItem = m_arNativeItems.elementAt(i);

        if(oItem.m_overflow==false)
		{
            if ( curTime.toULong() >= oItem.m_oFireTime.toULong() )
            {
                RAWTRACE("CRhoTimer::checkTimers: firing native timer");
                m_arNativeItems.removeElementAt(i);
                if ( oItem.m_pCallback->onTimer() )
                    bRet = true;
            }
        }
        else
        {
            if ( curTime.toULong() >= oItem.m_oFireTime.toULong() )
			{
				if((curTime.toULong()-oItem.m_oFireTime.toULong())<=oItem.m_nInterval)
				{
                    RAWTRACE("CRhoTimer::checkTimers: firing native timer");
                    m_arNativeItems.removeElementAt(i);
                    if ( oItem.m_pCallback->onTimer() )
                        bRet = true;
				}

			}
        }
    }

    return bRet;
}

void CRhoTimer::stopTimer(const char* szCallback)
{
    RAWTRACE1("CRhoTimer::stopTimer: %s",szCallback);

    synchronized(m_mxAccess);

    if ( !szCallback || !*szCallback)
        m_arItems.removeAllElements();

    for( int i = (int)m_arItems.size()-1; i >= 0; i--)
    {
        CTimerItem oItem = m_arItems.elementAt(i);
        if ( oItem.m_strCallback.compare(szCallback) == 0 )
        {
            m_arItems.removeElementAt(i);
        }
    }
}

void CRhoTimer::stopNativeTimer(CRhoTimer::ICallback* callback)
{
  RAWTRACE("CRhoTimer::stopNativeTimer");

  synchronized(m_mxAccess);

  if ( 0 == callback )
  {
    m_arNativeItems.removeAllElements();
  }

  for( int i = (int)m_arNativeItems.size()-1; i >= 0; i--)
  {
    CNativeTimerItem oItem = m_arNativeItems.elementAt(i);
    if ( oItem.m_pCallback == callback )
    {
      m_arNativeItems.removeElementAt(i);
    }
  }

}

bool CRhoTimer::isNativeTimerExist(CRhoTimer::ICallback* callback)
{
	if (callback)
	{
		for (int i = (int)m_arNativeItems.size() - 1; i >= 0; i--)
		{
			CNativeTimerItem oItem = m_arNativeItems.elementAt(i);
			if (oItem.m_pCallback == callback)
			{
				return true;
			}
		}
	}

	return false;
}

}
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Andrew Toulouse.
// Distributed under the MIT License.

#include "PlayerSegment.h"

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

namespace libol {
    bool PlayerSegment::probe(std::ifstream& ifs) {
        auto pos = ifs.tellg();
        ifs.ignore(2);
        uint8_t test = ifs.get();
        ifs.seekg(pos);

        return test == 0xC3;
    }

    PlayerSegment PlayerSegment::decode(std::ifstream& ifs) {
        PlayerSegment player;

        // Header
        ifs.read(reinterpret_cast<char *>(player.header.data()), player.header.size());

        // Summoner name
        char summonerChars[0x81];
        ifs.read(summonerChars, 0x80);
        summonerChars[0x80] = 0x00;
        player.summonerName = summonerChars;

        // Champion name
        char championChars[0x11];
        ifs.read(championChars, 0x10);
        summonerChars[0x10] = 0x00;
        player.championName = championChars;

        // Unknown 0
        ifs.read(reinterpret_cast<char *>(player.unk0.data()), player.unk0.size());

        // Runes
        ifs.read(reinterpret_cast<char *>(player.runes.data()), player.runes.size() * 4);

        // Masteries
        ifs.read(reinterpret_cast<char *>(player.masteriesHeader.data()), player.masteriesHeader.size());
        auto pos = ifs.tellg();
        int masteryCount = 0;
        while(MasteryEntry::probe(ifs) && masteryCount < 79) {
            player.masteries.push_back(MasteryEntry::decode(ifs));
            masteryCount++;
        }
        ifs.seekg(pos);
        ifs.ignore(0x18C);
        ifs.ignore(4); // Padding

        // Items
        ifs.read(reinterpret_cast<char *>(player.itemsHeader.data()), player.itemsHeader.size());
        for(int i = 0; i < player.items.size(); i++) {
            player.items[i] = ItemEntry::decode(ifs);
        }

        for(int i = 0; i < player.items.size(); i++) {
            player.items[i].decodeCooldown(ifs);
        }

        // Playerdata
        ifs.ignore(0x0C /* or 0x0F ? */); // Ignore playerData header
        ifs.read(reinterpret_cast<char *>(player.playerData.data()), player.playerData.size());

        while(ifs.peek() == 0x00 || ifs.peek() == 0x01) ifs.ignore(1); // Jump over some nulls (not in wiki)

        // Abilities
        ifs.ignore(0x04); // Ignore abilities header
        int abilities = 3;
        while(--abilities) {
            ifs.ignore(0x04);
            uint8_t first = ifs.peek();
            if(first == 0xF3)
                ifs.ignore(3);
            else if(first == 0x73)
                ifs.ignore(6);
            else if(first == 0x33)
                ifs.ignore(6);
            else {
                std::cout << "unkown ability format @ " << std::hex << ifs.tellg() << std::endl;
                exit(1);
            }
        }
        ifs.ignore(3); // Ignore last ability

        // Footer
        uint8_t marker[] = {0x00, 0x00, 0x15, 0x01}; // Search for this
        char buf[sizeof(marker)];
        while(true) {
            auto pos = ifs.tellg();
            ifs.read(buf, sizeof(marker));
            if(ifs.eof()) {
                std::cout << "footer not found" << std::endl;
                exit(1);
            }
            ifs.seekg(pos);
            if(!memcmp((void*) marker, (void*) buf, sizeof(marker)))
                break;
            ifs.ignore(1);
        }
        ifs.read(reinterpret_cast<char *>(player.footer.data()), player.footer.size());

        return player;
    }
}
<commit_msg>Nukes unsigned/signed mismatch warning<commit_after>// Copyright (c) 2014 Andrew Toulouse.
// Distributed under the MIT License.

#include "PlayerSegment.h"

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

namespace libol {
    bool PlayerSegment::probe(std::ifstream& ifs) {
        auto pos = ifs.tellg();
        ifs.ignore(2);
        uint8_t test = ifs.get();
        ifs.seekg(pos);

        return test == 0xC3;
    }

    PlayerSegment PlayerSegment::decode(std::ifstream& ifs) {
        PlayerSegment player;

        // Header
        ifs.read(reinterpret_cast<char *>(player.header.data()), player.header.size());

        // Summoner name
        char summonerChars[0x81];
        ifs.read(summonerChars, 0x80);
        summonerChars[0x80] = 0x00;
        player.summonerName = summonerChars;

        // Champion name
        char championChars[0x11];
        ifs.read(championChars, 0x10);
        summonerChars[0x10] = 0x00;
        player.championName = championChars;

        // Unknown 0
        ifs.read(reinterpret_cast<char *>(player.unk0.data()), player.unk0.size());

        // Runes
        ifs.read(reinterpret_cast<char *>(player.runes.data()), player.runes.size() * 4);

        // Masteries
        ifs.read(reinterpret_cast<char *>(player.masteriesHeader.data()), player.masteriesHeader.size());
        auto pos = ifs.tellg();
        int masteryCount = 0;
        while(MasteryEntry::probe(ifs) && masteryCount < 79) {
            player.masteries.push_back(MasteryEntry::decode(ifs));
            masteryCount++;
        }
        ifs.seekg(pos);
        ifs.ignore(0x18C);
        ifs.ignore(4); // Padding

        // Items
        ifs.read(reinterpret_cast<char *>(player.itemsHeader.data()), player.itemsHeader.size());
        for(uint8_t i = 0; i < player.items.size(); i++) {
            player.items[i] = ItemEntry::decode(ifs);
        }

        for(uint8_t i = 0; i < player.items.size(); i++) {
            player.items[i].decodeCooldown(ifs);
        }

        // Playerdata
        ifs.ignore(0x0C /* or 0x0F ? */); // Ignore playerData header
        ifs.read(reinterpret_cast<char *>(player.playerData.data()), player.playerData.size());

        while(ifs.peek() == 0x00 || ifs.peek() == 0x01) ifs.ignore(1); // Jump over some nulls (not in wiki)

        // Abilities
        ifs.ignore(0x04); // Ignore abilities header
        int abilities = 3;
        while(--abilities) {
            ifs.ignore(0x04);
            uint8_t first = ifs.peek();
            if(first == 0xF3)
                ifs.ignore(3);
            else if(first == 0x73)
                ifs.ignore(6);
            else if(first == 0x33)
                ifs.ignore(6);
            else {
                std::cout << "unkown ability format @ " << std::hex << ifs.tellg() << std::endl;
                exit(1);
            }
        }
        ifs.ignore(3); // Ignore last ability

        // Footer
        uint8_t marker[] = {0x00, 0x00, 0x15, 0x01}; // Search for this
        char buf[sizeof(marker)];
        while(true) {
            auto pos = ifs.tellg();
            ifs.read(buf, sizeof(marker));
            if(ifs.eof()) {
                std::cout << "footer not found" << std::endl;
                exit(1);
            }
            ifs.seekg(pos);
            if(!memcmp((void*) marker, (void*) buf, sizeof(marker)))
                break;
            ifs.ignore(1);
        }
        ifs.read(reinterpret_cast<char *>(player.footer.data()), player.footer.size());

        return player;
    }
}
<|endoftext|>