<commit_before>/**
 * This file is part of the zyan core library (zyantific.com).
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Joel Höner (athre0z)
 *
 * 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.
 */

#ifndef ZYCORE_SIGNAL_HPP
#define ZYCORE_SIGNAL_HPP

#include "zycore/Utils.hpp"

#include <map>
#include <thread>
#include <mutex>

namespace zycore
{

class SignalObject;

using SlotHandle = size_t;

// ============================================================================================== //
// Internal base classes                                                                          //
// ============================================================================================== //

namespace internal
{
    class SignalBase
    {
        friend SignalObject;
        virtual void onSlotsObjectDestroyed(SlotHandle handle) = 0;
    public:
        virtual ~SignalBase() = default;
    };

    struct SignalObjectBase
    {
        template<typename Object, typename... ArgsT>
        friend class ClassFuncConnection;

        virtual ~SignalObjectBase() = default;
        virtual void onSignalConnected(SignalBase *signal, SlotHandle handle) = 0;
        virtual void onSignalDisconnected(SlotHandle handle) = 0;
    };
} // namespace internal

// ============================================================================================== //
// [ConnectionBase]                                                                               //
// ============================================================================================== //

/**
 * @brief   Abstract base class for connections between signals and slots.
 * @tparam  ArgsT The slot's argument types.
 */
template<typename... ArgsT>
struct ConnectionBase
{
    template<typename...>
    friend class Signal;
public: // Public interface.
    /**
     * @brief   Default constructor.
     */
    ConnectionBase() = default;

    /**
     * @brief   Destructor.
     */
    virtual ~ConnectionBase() = default;

    /**
     * @brief   Calls the connected slot.
     * @param   args The arguments.
     */
    virtual void call(ArgsT... args) const = 0;
private: // Private interface.
    /**
     * @brief   Called when connection is destroyed.
     * @param   handle  The slot handle.
     */
    virtual void onDestroy(SlotHandle handle) = 0;
};

// ============================================================================================== //
// [FuncConnection]                                                                               //
// ============================================================================================== //

/**
 * @brief   Connection between static slot and signal.
 * @tparam  ArgsT The slot's argument types.
 */
template<typename... ArgsT>
class FuncConnection
    : public ConnectionBase<ArgsT...>
{
public:
    using Function = std::function<void(ArgsT... args)>;
    /**
     * @brief   Constructor.
     * @param   func The slot to be connected.
     */
    explicit FuncConnection(Function func);
public: // Implementation of public, virtual member-functions.
    /**
     * @brief   Calls the slot.
     * @param   args  Arguments.
     */
    virtual void call(ArgsT... args) const override;
private:
    Function m_func;
private: // Implementation of private interface.
    virtual void onDestroy(SlotHandle /*handle*/) override {}
};

// ============================================================================================== //
// [LifetimedConnection]                                                                          //
// ============================================================================================== //

/**
 * @brief   Connection automatically loosened when either the signal or the lifetime-giving objects
 *          is destoyed.
 * @tparam  ArgsT   The slot's member function argument types.
 */
template<typename... ArgsT>
class LifetimedConnection
    : public ConnectionBase<ArgsT...>
    , public NonCopyable
{
public:
    using Function = std::function<void(ArgsT...)>;
private:
    Function m_func;
    internal::SignalObjectBase* m_lifetimeObject;
public: // Constructor
    /**
     * @brief   Constructor.
     * @param   obj     The object whose lifetime to bind to.
     * @param   func    The callback function.
     * @param   sig     The signal to connect to.
     * @param   handle  The slot handle.
     */
    LifetimedConnection(internal::SignalObjectBase *obj, Function func,
        internal::SignalBase* sig, SlotHandle handle);
public: // Implementation of public interface.
    void call(ArgsT... args) const override;
private: // Implementation of private interface.
    void onDestroy(SlotHandle handle) override;
};

// ============================================================================================== //
// [internal::MemberFuncBinding]                                                                  //
// ============================================================================================== //

namespace internal
{

/**
 * @brief   Binds @c this to a member-function without the need of placeholders.
 */
template<typename ObjectT, typename... ArgsT>
class MemberFuncBinding
{
    using Member = void (ObjectT::*)(ArgsT...);
    ObjectT* m_obj;
    Member m_member;
public:
    MemberFuncBinding(ObjectT* obj, Member memberFunc);
    void operator() (ArgsT... args);
};

} // namespace internal

// ============================================================================================== //
// [Signal]                                                                                //
// ============================================================================================== //

/**
 * @brief   Type and thread safe signal implementation.
 * @tparam  ArgsT The slot's argument types.
 *
 * For more information, see Signals & Slots at wikipedia:
 * http://en.wikipedia.org/wiki/Signals_and_slots
 */
template<typename... ArgsT>
class Signal
    : public internal::SignalBase
    , public NonCopyable
{
    // Typedefs and private member-variables
    using ConnectionBase = ConnectionBase<ArgsT...>;
    std::map<SlotHandle, ConnectionBase*> m_slots;
    SlotHandle m_IdCtr;
    mutable std::recursive_mutex m_mutex;
public: // Con- & Destructor.
    /**
     * @brief   Default constructor.
     */
    Signal();

    /**
     * @brief   Destructor.
     */
    virtual ~Signal();
public: // Public interface.
    /**
     * @brief   Adds a given connection to the internal list.
     * @param   connection The connection to be added. The pointer will be
     *                     stolen.
     */
    void connect(FuncConnection<ArgsT...>* connection);

    /**
     * @brief   Connects a static slot to the signal.
     * @param   func The function/lambda to connect.
     */
    void connect(typename FuncConnection<ArgsT...>::Function func);

    /**
     * @brief   Emits the signal and calls all connected slots.
     * @param   args  Arguments to be passed to the slots.
     */
    void emit(ArgsT... args) const;

    /**
     * @brief   Shorthand for @c emit.
     */
    void operator () (ArgsT... args) const;

    /**
     * @brief   Shorthand for @c connect.
     * @param   func  The function (slot) to connect with the signal.
     * @return  This instance.
     */
    Signal& operator += (typename FuncConnection<ArgsT...>::Function func);

    /**
     * @brief   Adds a given connection to the internal list.
     * @param   connection The connection to be added. Ownership is transfered.
     */
    template<typename Object>
    void connect(LifetimedConnection<Object, ArgsT...>* connection)
    {
        std::lock_guard<std::recursive_mutex> lock(m_mutex);
        m_slots.emplace(m_IdCtr++, connection);
    }

    /**
     * @brief   Connects a function to the signal binding the connection lifetime to a
     *          signal object.
     * @param   object The object to be connected.
     * @param	member The member function.
     *
     * The connection is automatically released as soon as either the signal or the
     * lifetime-giver is destroyed.
     */
    void connect(SignalObject* lifetimeGiver, std::function<void(ArgsT...)> func)
    {
        std::lock_guard<std::recursive_mutex> lock(m_mutex);
        SlotHandle handle = m_IdCtr++;
        m_slots.emplace(handle, new LifetimedConnection<ArgsT...>(
            lifetimeGiver, func, this, handle));
    }

    /**
     * @brief   Connects a member-function slot to the signal.
     * @param   object The object to be connected.
     * @param	member The member function.
     *
     * The connection is automatically released as soon as either the signal or the object
     * with the slot is destroyed.
     */
    template<typename ObjectT>
    void connect(ObjectT* object, void(ObjectT::*member)(ArgsT...))
    {
        static_assert(std::is_base_of<SignalObject, ObjectT>::value,
            "type has to be derived from SignalObject");
        connect(object, internal::MemberFuncBinding<ObjectT, ArgsT...>(object, member));
    }
private: // Interface for SignalObject.
    /**
     * @brief   Callback used by slots when they are destroyed.
     */
    void onSlotsObjectDestroyed(SlotHandle handle) override;
};

// ============================================================================================== //
// Implementation of inline methods [FuncConnection]                                              //
// ============================================================================================== //

template<typename... ArgsT>
inline FuncConnection<ArgsT...>::FuncConnection(Function func)
    : m_func(func)
{}

template<typename... ArgsT>
inline void FuncConnection<ArgsT...>::call(ArgsT... args) const
{
    m_func(args...);
}

// ============================================================================================== //
// Implementation of inline methods [LifetimedConnection]                                         //
// ============================================================================================== //

template<typename... ArgsT>
inline LifetimedConnection<ArgsT...>::LifetimedConnection(internal::SignalObjectBase *lifetimeObj,
        Function func, internal::SignalBase* sig, SlotHandle handle)
    : m_lifetimeObject(lifetimeObj)
    , m_func(func)
{
    lifetimeObj->onSignalConnected(sig, handle);
}

template<typename... ArgsT>
inline void LifetimedConnection<ArgsT...>::call(ArgsT... args) const
{
    m_func(args...);
}

template<typename... ArgsT>
inline void LifetimedConnection<ArgsT...>::onDestroy(SlotHandle handle)
{
    m_lifetimeObject->onSignalDisconnected(handle);
}

// ============================================================================================== //
// Implementation of inline functions [internal::MemberFuncBinding]                               //
// ============================================================================================== //

namespace internal
{

template<typename ObjectT, typename... ArgsT>
inline MemberFuncBinding<ObjectT, ArgsT...>::MemberFuncBinding(ObjectT* obj, Member memberFunc)
    : m_obj(obj)
    , m_member(memberFunc)
{}

template<typename ObjectT, typename... ArgsT>
inline void MemberFuncBinding<ObjectT, ArgsT...>::operator() (ArgsT... args)
{
    (m_obj->*m_member)(args...);
}

} // namespace internal

// ============================================================================================== //
// Implementation of inline functions [Signal]                                                    //
// ============================================================================================== //

template<typename... ArgsT>
inline Signal<ArgsT...>::Signal()
    : m_IdCtr(1)
{}

template<typename... ArgsT>
inline Signal<ArgsT...>::~Signal()
{
    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    for (auto i = m_slots.begin(); i != m_slots.end(); ++i)
    {
        i->second->onDestroy(i->first);
        delete i->second;
    }
}

template<typename... ArgsT>
inline void Signal<ArgsT...>::connect(FuncConnection<ArgsT...>* connection)
{
    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    m_slots.emplace(m_IdCtr++, connection);
}

template<typename... ArgsT>
inline void Signal<ArgsT...>::connect(typename FuncConnection<ArgsT...>::Function func)
{
    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    auto connection = new FuncConnection<ArgsT...>(func);
    m_slots.emplace(m_IdCtr++, connection);
}

template<typename... ArgsT>
inline void Signal<ArgsT...>::emit(ArgsT... args) const
{
    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    for (const auto &cur : m_slots)
    {
        cur.second->call(args...);
    }
}

template<typename... ArgsT>
inline void Signal<ArgsT...>::operator()(ArgsT... args) const
{
    emit(args...);
}

template<typename... ArgsT>
inline Signal<ArgsT...>& Signal<ArgsT...>::operator += (
    typename FuncConnection<ArgsT...>::Function func)
{
    connect(func);
    return *this;
}

template<typename... ArgsT>
inline void Signal<ArgsT...>::onSlotsObjectDestroyed(SlotHandle handle)
{
    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    for (auto i = m_slots.begin(); i != m_slots.end();)
    {
        if (i->first == handle)
        {
            delete i->second;
            i = m_slots.erase(i);
        }
        else
        {
            ++i;
        }
    }
}

// ============================================================================================== //

} // namespace zycore

#endif // ZYCORE_SIGNAL_HPP
<commit_msg>added support for disconnecting slots<commit_after>/**
 * This file is part of the zyan core library (zyantific.com).
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Joel Höner (athre0z)
 *
 * 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.
 */

#ifndef ZYCORE_SIGNAL_HPP
#define ZYCORE_SIGNAL_HPP

#include "zycore/Utils.hpp"

#include <map>
#include <thread>
#include <mutex>

namespace zycore
{

class SignalObject;

using SlotHandle = size_t;

// ============================================================================================== //
// Internal base classes                                                                          //
// ============================================================================================== //

namespace internal
{
    class SignalBase
    {
        friend SignalObject;
        virtual void onSlotsObjectDestroyed(SlotHandle handle) = 0;
    public:
        virtual ~SignalBase() = default;
    };

    struct SignalObjectBase
    {
        template<typename Object, typename... ArgsT>
        friend class ClassFuncConnection;

        virtual ~SignalObjectBase() = default;
        virtual void onSignalConnected(SignalBase *signal, SlotHandle handle) = 0;
        virtual void onSignalDisconnected(SlotHandle handle) = 0;
    };
} // namespace internal

// ============================================================================================== //
// [ConnectionBase]                                                                               //
// ============================================================================================== //

/**
 * @brief   Abstract base class for connections between signals and slots.
 * @tparam  ArgsT The slot's argument types.
 */
template<typename... ArgsT>
struct ConnectionBase
{
    template<typename...>
    friend class Signal;
public: // Public interface.
    /**
     * @brief   Default constructor.
     */
    ConnectionBase() = default;

    /**
     * @brief   Destructor.
     */
    virtual ~ConnectionBase() = default;

    /**
     * @brief   Calls the connected slot.
     * @param   args The arguments.
     */
    virtual void call(ArgsT... args) const = 0;
private: // Private interface.
    /**
     * @brief   Called when connection is destroyed.
     * @param   handle  The slot handle.
     */
    virtual void onDestroy(SlotHandle handle) = 0;
};

// ============================================================================================== //
// [FuncConnection]                                                                               //
// ============================================================================================== //

/**
 * @brief   Connection between static slot and signal.
 * @tparam  ArgsT The slot's argument types.
 */
template<typename... ArgsT>
class FuncConnection
    : public ConnectionBase<ArgsT...>
{
public:
    using Function = std::function<void(ArgsT... args)>;
    /**
     * @brief   Constructor.
     * @param   func The slot to be connected.
     */
    explicit FuncConnection(Function func);
public: // Implementation of public, virtual member-functions.
    /**
     * @brief   Calls the slot.
     * @param   args  Arguments.
     */
    virtual void call(ArgsT... args) const override;
private:
    Function m_func;
private: // Implementation of private interface.
    virtual void onDestroy(SlotHandle /*handle*/) override {}
};

// ============================================================================================== //
// [LifetimedConnection]                                                                          //
// ============================================================================================== //

/**
 * @brief   Connection automatically loosened when either the signal or the lifetime-giving objects
 *          is destoyed.
 * @tparam  ArgsT   The slot's member function argument types.
 */
template<typename... ArgsT>
class LifetimedConnection
    : public ConnectionBase<ArgsT...>
    , public NonCopyable
{
public:
    using Function = std::function<void(ArgsT...)>;
private:
    Function m_func;
    internal::SignalObjectBase* m_lifetimeObject;
public: // Constructor
    /**
     * @brief   Constructor.
     * @param   obj     The object whose lifetime to bind to.
     * @param   func    The callback function.
     * @param   sig     The signal to connect to.
     * @param   handle  The slot handle.
     */
    LifetimedConnection(internal::SignalObjectBase *obj, Function func,
        internal::SignalBase* sig, SlotHandle handle);
public: // Implementation of public interface.
    void call(ArgsT... args) const override;
private: // Implementation of private interface.
    void onDestroy(SlotHandle handle) override;
};

// ============================================================================================== //
// [internal::MemberFuncBinding]                                                                  //
// ============================================================================================== //

namespace internal
{

/**
 * @brief   Binds @c this to a member-function without the need of placeholders.
 */
template<typename ObjectT, typename... ArgsT>
class MemberFuncBinding
{
    using Member = void (ObjectT::*)(ArgsT...);
    ObjectT* m_obj;
    Member m_member;
public:
    MemberFuncBinding(ObjectT* obj, Member memberFunc);
    void operator() (ArgsT... args);
};

} // namespace internal

// ============================================================================================== //
// [Signal]                                                                                //
// ============================================================================================== //

/**
 * @brief   Type and thread safe signal implementation.
 * @tparam  ArgsT The slot's argument types.
 *
 * For more information, see Signals & Slots at wikipedia:
 * http://en.wikipedia.org/wiki/Signals_and_slots
 */
template<typename... ArgsT>
class Signal
    : public internal::SignalBase
    , public NonCopyable
{
    // Typedefs and private member-variables
    using ConnectionBase = ConnectionBase<ArgsT...>;
    std::map<SlotHandle, ConnectionBase*> m_slots;
    SlotHandle m_IdCtr;
    mutable std::recursive_mutex m_mutex;
public: // Con- & Destructor.
    /**
     * @brief   Default constructor.
     */
    Signal();

    /**
     * @brief   Destructor.
     */
    virtual ~Signal();
public: // Public interface.
    /**
     * @brief   Adds a given connection to the internal list.
     * @param   connection The connection to be added. The pointer will be
     *                     stolen.
     */
    SlotHandle connect(FuncConnection<ArgsT...>* connection);

    /**
     * @brief   Connects a static slot to the signal.
     * @param   func The function/lambda to connect.
     */
    SlotHandle connect(typename FuncConnection<ArgsT...>::Function func);

    /**
     * @brief   Disconnects an existing connetion by it's handle
     * @param   handle  The connection handle.
     * @return  `true` on success, `false` if the connection didn't exist.
     */
    bool disconnect(SlotHandle handle);

    /**
     * @brief   Emits the signal and calls all connected slots.
     * @param   args  Arguments to be passed to the slots.
     */
    void emit(ArgsT... args) const;

    /**
     * @brief   Shorthand for @c emit.
     */
    void operator () (ArgsT... args) const;

    /**
     * @brief   Shorthand for @c connect.
     * @param   func  The function (slot) to connect with the signal.
     * @return  This instance.
     */
    Signal& operator += (typename FuncConnection<ArgsT...>::Function func);

    /**
     * @brief   Adds a given connection to the internal list.
     * @param   connection The connection to be added. Ownership is transfered.
     */
    template<typename Object>
    SlotHandle connect(LifetimedConnection<Object, ArgsT...>* connection)
    {
        std::lock_guard<std::recursive_mutex> lock(m_mutex);
        m_slots.emplace(m_IdCtr, connection);
        return m_IdCtr++;
    }

    /**
     * @brief   Connects a function to the signal binding the connection lifetime to a
     *          signal object.
     * @param   object The object to be connected.
     * @param	member The member function.
     *
     * The connection is automatically released as soon as either the signal or the
     * lifetime-giver is destroyed.
     */
    SlotHandle connect(SignalObject* lifetimeGiver, std::function<void(ArgsT...)> func)
    {
        std::lock_guard<std::recursive_mutex> lock(m_mutex);
        SlotHandle handle = m_IdCtr++;
        m_slots.emplace(handle, new LifetimedConnection<ArgsT...>(
            lifetimeGiver, func, this, handle));
        return handle;
    }

    /**
     * @brief   Connects a member-function slot to the signal.
     * @param   object The object to be connected.
     * @param	member The member function.
     *
     * The connection is automatically released as soon as either the signal or the object
     * with the slot is destroyed.
     */
    template<typename ObjectT>
    SlotHandle connect(ObjectT* object, void(ObjectT::*member)(ArgsT...))
    {
        static_assert(std::is_base_of<SignalObject, ObjectT>::value,
            "type has to be derived from SignalObject");
        return connect(object, internal::MemberFuncBinding<ObjectT, ArgsT...>(object, member));
    }
private: // Interface for SignalObject.
    /**
     * @brief   Callback used by slots when they are destroyed.
     */
    void onSlotsObjectDestroyed(SlotHandle handle) override;
};

// ============================================================================================== //
// Implementation of inline methods [FuncConnection]                                              //
// ============================================================================================== //

template<typename... ArgsT>
inline FuncConnection<ArgsT...>::FuncConnection(Function func)
    : m_func(func)
{}

template<typename... ArgsT>
inline void FuncConnection<ArgsT...>::call(ArgsT... args) const
{
    m_func(args...);
}

// ============================================================================================== //
// Implementation of inline methods [LifetimedConnection]                                         //
// ============================================================================================== //

template<typename... ArgsT>
inline LifetimedConnection<ArgsT...>::LifetimedConnection(internal::SignalObjectBase *lifetimeObj,
        Function func, internal::SignalBase* sig, SlotHandle handle)
    : m_func(func)
    , m_lifetimeObject(lifetimeObj)
{
    lifetimeObj->onSignalConnected(sig, handle);
}

template<typename... ArgsT>
inline void LifetimedConnection<ArgsT...>::call(ArgsT... args) const
{
    m_func(args...);
}

template<typename... ArgsT>
inline void LifetimedConnection<ArgsT...>::onDestroy(SlotHandle handle)
{
    m_lifetimeObject->onSignalDisconnected(handle);
}

// ============================================================================================== //
// Implementation of inline functions [internal::MemberFuncBinding]                               //
// ============================================================================================== //

namespace internal
{

template<typename ObjectT, typename... ArgsT>
inline MemberFuncBinding<ObjectT, ArgsT...>::MemberFuncBinding(ObjectT* obj, Member memberFunc)
    : m_obj(obj)
    , m_member(memberFunc)
{}

template<typename ObjectT, typename... ArgsT>
inline void MemberFuncBinding<ObjectT, ArgsT...>::operator() (ArgsT... args)
{
    (m_obj->*m_member)(args...);
}

} // namespace internal

// ============================================================================================== //
// Implementation of inline functions [Signal]                                                    //
// ============================================================================================== //

template<typename... ArgsT>
inline Signal<ArgsT...>::Signal()
    : m_IdCtr(1)
{}

template<typename... ArgsT>
inline Signal<ArgsT...>::~Signal()
{
    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    for (auto i = m_slots.begin(); i != m_slots.end(); ++i)
    {
        i->second->onDestroy(i->first);
        delete i->second;
    }
}

template<typename... ArgsT>
inline SlotHandle Signal<ArgsT...>::connect(FuncConnection<ArgsT...>* connection)
{
    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    m_slots.emplace(m_IdCtr, connection);
    return m_IdCtr++;
}

template<typename... ArgsT>
inline bool Signal<ArgsT...>::disconnect(SlotHandle handle)
{
    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    auto it = m_slots.find(handle);
    if (it == m_slots.end()) return false;
    it->second->onDestroy(it->first);
    delete it->second;
    m_slots.erase(it);
    return true;
}

template<typename... ArgsT>
inline SlotHandle Signal<ArgsT...>::connect(typename FuncConnection<ArgsT...>::Function func)
{
    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    auto connection = new FuncConnection<ArgsT...>(func);
    m_slots.emplace(m_IdCtr, connection);
    return m_IdCtr++;
}

template<typename... ArgsT>
inline void Signal<ArgsT...>::emit(ArgsT... args) const
{
    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    for (const auto &cur : m_slots)
    {
        cur.second->call(args...);
    }
}

template<typename... ArgsT>
inline void Signal<ArgsT...>::operator()(ArgsT... args) const
{
    emit(args...);
}

template<typename... ArgsT>
inline Signal<ArgsT...>& Signal<ArgsT...>::operator += (
    typename FuncConnection<ArgsT...>::Function func)
{
    connect(func);
    return *this;
}

template<typename... ArgsT>
inline void Signal<ArgsT...>::onSlotsObjectDestroyed(SlotHandle handle)
{
    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    for (auto i = m_slots.begin(); i != m_slots.end();)
    {
        if (i->first == handle)
        {
            delete i->second;
            i = m_slots.erase(i);
        }
        else
        {
            ++i;
        }
    }
}

// ============================================================================================== //

} // namespace zycore

#endif // ZYCORE_SIGNAL_HPP
<|endoftext|>


<commit_before>#include "stdafx.h"

#include "LuaCustomTypes.hpp"
#include "LuaLayout.h"

// TODO: maybe template these add functions?
int Lua_FoneOSScreen_AddLabel(lua_State * _L)
{
	FoneOSScreen* obj = luaW_check<FoneOSScreen>(_L, 1);
	FoneOSLabel* lbl = luaW_check<FoneOSLabel>(_L, 2);
	obj->labels.push_back(lbl);
	return 0;
}

int Lua_FoneOSScreen_AddTitle(lua_State * _L)
{
	FoneOSScreen* obj = luaW_check<FoneOSScreen>(_L, 1);
	FoneOSTitle* title = luaW_check<FoneOSTitle>(_L, 2);
	obj->titles.push_back(title);
	return 0;
}

int Lua_FoneOSScreen_AddButton(lua_State * _L)
{
	FoneOSScreen* obj = luaW_check<FoneOSScreen>(_L, 1);
	FoneOSButton* btn = luaW_check<FoneOSButton>(_L, 2);
	obj->buttons.push_back(btn);
	return 0;
}

int Lua_FoneOSScreen_Draw(lua_State * _L)
{
	FoneOSScreen* obj = luaW_check<FoneOSScreen>(_L, 1);
	obj->Draw();
	return 0;
}

#define SearchAllOfType(t, a) \
	do { \
		std::vector<t*> pointer = a; \
		int i = 0; \
		for (i = 0; i < pointer.size(); i++) { \
			t * it = pointer[i]; \
			if (it->id == id) { \
				luaW_push<t>(_L, it); \
				return 1; \
			}\
		} \
	} while (0)
int Lua_FoneOSScreen_GetId(lua_State * _L)
{
	FoneOSScreen* obj = luaW_check<FoneOSScreen>(_L, 1);
	std::string id = luaL_checkstring(_L, 2);

	SearchAllOfType(FoneOSImage, obj->images);
	SearchAllOfType(FoneOSTitle, obj->titles);
	SearchAllOfType(FoneOSLabel, obj->labels);
	SearchAllOfType(FoneOSButton, obj->buttons);

	lua_pushnil(_L);
	return 1;
}

int Lua_FoneOSContainer_Create(lua_State * _L)
{
	FoneOSContainer* obj = luaW_check<FoneOSContainer>(_L, 1);
	obj->Create();
	return 0;
}

int Lua_FoneOSContainer_Draw(lua_State * _L)
{
	// no-op because you should not draw containers alone
    //FoneOSContainer* obj = luaW_check<FoneOSContainer>(_L, 1);
    //obj->Draw();
    return 0;
}

void Lua_FoneOSButton_callbackHandler(FoneOSContainer* cont)
{
	FoneOSButton* btn = (FoneOSButton*)cont;
	lua_State * _L = (lua_State*)btn->metadata["state"];
	lua_rawgeti(_L, LUA_REGISTRYINDEX, *(int*)btn->metadata["onActivate"]); // retrieve the function
	luaW_push<FoneOSButton>(_L, btn);
	int ret = lua_pcall(_L, 1, 0, 0);
	if (ret != 0)
	{
		Logging::LogMessage(STR("Error occurred in app!"));
		Logging::LogMessage(Utils::CharArrayToFoneOSString((char*)lua_tostring(_L, -1)));
	}
}

int Lua_FoneOSButton_onActivate(lua_State * _L)
{
	// TODO: Parameter checking
	FoneOSButton* btn = luaW_check<FoneOSButton>(_L, 1);
	int funcId = luaL_ref(_L, LUA_REGISTRYINDEX);
	btn->metadata["onActivate"] = (void*)new int(funcId);
	btn->metadata["state"] = (void*)_L;
	btn->onActivate = Lua_FoneOSButton_callbackHandler;
	return 0;
}

static luaL_Reg FoneOSContainer_table[] =
{
	{ NULL, NULL }
};

static luaL_Reg FoneOSContainer_metatable[] =
{
	{ "x", luaU_getset<FoneOSContainer, int, &FoneOSContainer::x> },
	{ "y", luaU_getset<FoneOSContainer, int, &FoneOSContainer::y> },

	{ "width", luaU_getset<FoneOSContainer, int, &FoneOSContainer::width> },
	{ "height", luaU_getset<FoneOSContainer, int, &FoneOSContainer::height> },

	{ "id", luaU_getset<FoneOSContainer, FoneOSString, &FoneOSContainer::id> },

    { "create", Lua_FoneOSContainer_Create },
    { "draw", Lua_FoneOSContainer_Draw },
	{ NULL, NULL }
};

static luaL_Reg FoneOSLabel_metatable[] =
{
	{ "text", luaU_getset<FoneOSLabel, FoneOSString, &FoneOSLabel::text> },
	{ NULL, NULL }
};

static luaL_Reg FoneOSTitle_metatable[] =
{
	{ "text", luaU_getset<FoneOSTitle, FoneOSString, &FoneOSTitle::text> },
	{ NULL, NULL }
};

static luaL_Reg FoneOSButton_metatable[] =
{
	{ "text", luaU_getset<FoneOSButton, FoneOSString, &FoneOSButton::text> },
	{ "onActivate", Lua_FoneOSButton_onActivate },
	{ NULL, NULL }
};

static luaL_Reg FoneOSScreen_metatable[] =
{
	{ "addLabel", Lua_FoneOSScreen_AddLabel },
	{ "addTitle", Lua_FoneOSScreen_AddTitle },
	{ "addButton", Lua_FoneOSScreen_AddButton },

	{ "draw", Lua_FoneOSScreen_Draw },

	{ "getId", Lua_FoneOSScreen_GetId },

	{ "width", luaU_getset<FoneOSScreen, int, &FoneOSScreen::width> },
	{ "height", luaU_getset<FoneOSScreen, int, &FoneOSScreen::height> },

	{ NULL, NULL }
};

int luaopen_Layout(lua_State* L)
{
	luaW_register<FoneOSContainer>(L,
		"FoneOSContainer",
		FoneOSContainer_table,
		FoneOSContainer_metatable//,
//		FoneOSContainer_new // If your class has a default constructor you can omit this argument,
				    // LuaWrapper will generate a default allocator for you.
	);

	luaW_register<FoneOSLabel>(L, "FoneOSLabel", FoneOSContainer_table, FoneOSLabel_metatable);
	luaW_extend<FoneOSLabel, FoneOSContainer>(L); // Informs the wrapper that FoneOSLabel inherits from the class FoneOSContainer

	luaW_register<FoneOSTitle>(L, "FoneOSTitle", FoneOSContainer_table, FoneOSTitle_metatable);
	luaW_extend<FoneOSTitle, FoneOSContainer>(L); // Informs the wrapper that FoneOSTitle inherits from the class FoneOSContainer

	luaW_register<FoneOSButton>(L, "FoneOSButton", FoneOSContainer_table, FoneOSButton_metatable);
	luaW_extend<FoneOSButton, FoneOSContainer>(L); // FoneOSButton inherits FoneOSContainer

	luaW_register<FoneOSScreen>(L, "FoneOSScreen", FoneOSContainer_table, FoneOSScreen_metatable);

	return 1;
}
<commit_msg>Add Lua support for FoneOSKeyboard<commit_after>#include "stdafx.h"

#include "LuaCustomTypes.hpp"
#include "LuaLayout.h"

// TODO: maybe template these add functions?
int Lua_FoneOSScreen_AddLabel(lua_State * _L)
{
	FoneOSScreen* obj = luaW_check<FoneOSScreen>(_L, 1);
	FoneOSLabel* lbl = luaW_check<FoneOSLabel>(_L, 2);
	obj->labels.push_back(lbl);
	return 0;
}

int Lua_FoneOSScreen_AddTitle(lua_State * _L)
{
	FoneOSScreen* obj = luaW_check<FoneOSScreen>(_L, 1);
	FoneOSTitle* title = luaW_check<FoneOSTitle>(_L, 2);
	obj->titles.push_back(title);
	return 0;
}

int Lua_FoneOSScreen_AddButton(lua_State * _L)
{
	FoneOSScreen* obj = luaW_check<FoneOSScreen>(_L, 1);
	FoneOSButton* btn = luaW_check<FoneOSButton>(_L, 2);
	obj->buttons.push_back(btn);
	return 0;
}

int Lua_FoneOSScreen_AddKeyboard(lua_State * _L)
{
	FoneOSScreen* obj = luaW_check<FoneOSScreen>(_L, 1);
	FoneOSKeyboard* kbd = luaW_check<FoneOSKeyboard>(_L, 2);
	obj->buttons.push_back(kbd);
	return 0;
}

int Lua_FoneOSScreen_Draw(lua_State * _L)
{
	FoneOSScreen* obj = luaW_check<FoneOSScreen>(_L, 1);
	obj->Draw();
	return 0;
}

#define SearchAllOfType(t, a) \
	do { \
		std::vector<t*> pointer = a; \
		int i = 0; \
		for (i = 0; i < pointer.size(); i++) { \
			t * it = pointer[i]; \
			if (it->id == id) { \
				luaW_push<t>(_L, it); \
				return 1; \
			}\
		} \
	} while (0)
int Lua_FoneOSScreen_GetId(lua_State * _L)
{
	FoneOSScreen* obj = luaW_check<FoneOSScreen>(_L, 1);
	std::string id = luaL_checkstring(_L, 2);

	SearchAllOfType(FoneOSImage, obj->images);
	SearchAllOfType(FoneOSTitle, obj->titles);
	SearchAllOfType(FoneOSLabel, obj->labels);
	SearchAllOfType(FoneOSButton, obj->buttons);
	SearchAllOfType(FoneOSKeyboard, obj->keyboards);

	lua_pushnil(_L);
	return 1;
}

int Lua_FoneOSContainer_Create(lua_State * _L)
{
	FoneOSContainer* obj = luaW_check<FoneOSContainer>(_L, 1);
	obj->Create();
	return 0;
}

int Lua_FoneOSContainer_Draw(lua_State * _L)
{
	// no-op because you should not draw containers alone
    //FoneOSContainer* obj = luaW_check<FoneOSContainer>(_L, 1);
    //obj->Draw();
    return 0;
}

void Lua_FoneOSButton_callbackHandler(FoneOSContainer* cont)
{
	FoneOSButton* btn = (FoneOSButton*)cont;
	lua_State * _L = (lua_State*)btn->metadata["state"];
	lua_rawgeti(_L, LUA_REGISTRYINDEX, *(int*)btn->metadata["onActivate"]); // retrieve the function
	luaW_push<FoneOSButton>(_L, btn);
	int ret = lua_pcall(_L, 1, 0, 0);
	if (ret != 0)
	{
		Logging::LogMessage(STR("Error occurred in app!"));
		Logging::LogMessage(Utils::CharArrayToFoneOSString((char*)lua_tostring(_L, -1)));
	}
}

int Lua_FoneOSButton_onActivate(lua_State * _L)
{
	// TODO: Parameter checking
	FoneOSButton* btn = luaW_check<FoneOSButton>(_L, 1);
	int funcId = luaL_ref(_L, LUA_REGISTRYINDEX);
	btn->metadata["onActivate"] = (void*)new int(funcId);
	btn->metadata["state"] = (void*)_L;
	btn->onActivate = Lua_FoneOSButton_callbackHandler;
	return 0;
}

static luaL_Reg FoneOSContainer_table[] =
{
	{ NULL, NULL }
};

static luaL_Reg FoneOSContainer_metatable[] =
{
	{ "x", luaU_getset<FoneOSContainer, int, &FoneOSContainer::x> },
	{ "y", luaU_getset<FoneOSContainer, int, &FoneOSContainer::y> },

	{ "width", luaU_getset<FoneOSContainer, int, &FoneOSContainer::width> },
	{ "height", luaU_getset<FoneOSContainer, int, &FoneOSContainer::height> },

	{ "id", luaU_getset<FoneOSContainer, FoneOSString, &FoneOSContainer::id> },

	{ "create", Lua_FoneOSContainer_Create },
	{ "draw", Lua_FoneOSContainer_Draw },
	{ NULL, NULL }
};

static luaL_Reg FoneOSLabel_metatable[] =
{
	{ "text", luaU_getset<FoneOSLabel, FoneOSString, &FoneOSLabel::text> },
	{ NULL, NULL }
};

static luaL_Reg FoneOSTitle_metatable[] =
{
	{ "text", luaU_getset<FoneOSTitle, FoneOSString, &FoneOSTitle::text> },
	{ NULL, NULL }
};

static luaL_Reg FoneOSButton_metatable[] =
{
	{ "text", luaU_getset<FoneOSButton, FoneOSString, &FoneOSButton::text> },
	{ "onActivate", Lua_FoneOSButton_onActivate },
	{ NULL, NULL }
};

static luaL_Reg FoneOSKeyboard_metatable[] =
{
	{ NULL, NULL }
};

static luaL_Reg FoneOSScreen_metatable[] =
{
	{ "addLabel", Lua_FoneOSScreen_AddLabel },
	{ "addTitle", Lua_FoneOSScreen_AddTitle },
	{ "addButton", Lua_FoneOSScreen_AddButton },

	{ "draw", Lua_FoneOSScreen_Draw },

	{ "getId", Lua_FoneOSScreen_GetId },

	{ "width", luaU_getset<FoneOSScreen, int, &FoneOSScreen::width> },
	{ "height", luaU_getset<FoneOSScreen, int, &FoneOSScreen::height> },

	{ NULL, NULL }
};

int luaopen_Layout(lua_State* L)
{
	luaW_register<FoneOSContainer>(L,
		"FoneOSContainer",
		FoneOSContainer_table,
		FoneOSContainer_metatable//,
//		FoneOSContainer_new // If your class has a default constructor you can omit this argument,
				    // LuaWrapper will generate a default allocator for you.
	);

	luaW_register<FoneOSLabel>(L, "FoneOSLabel", FoneOSContainer_table, FoneOSLabel_metatable);
	luaW_extend<FoneOSLabel, FoneOSContainer>(L); // Informs the wrapper that FoneOSLabel inherits from the class FoneOSContainer

	luaW_register<FoneOSTitle>(L, "FoneOSTitle", FoneOSContainer_table, FoneOSTitle_metatable);
	luaW_extend<FoneOSTitle, FoneOSContainer>(L); // Informs the wrapper that FoneOSTitle inherits from the class FoneOSContainer

	luaW_register<FoneOSButton>(L, "FoneOSButton", FoneOSContainer_table, FoneOSButton_metatable);
	luaW_extend<FoneOSButton, FoneOSContainer>(L); // FoneOSButton inherits FoneOSContainer

	luaW_register<FoneOSKeyboard>(L, "FoneOSKeyboard", FoneOSContainer_table, FoneOSKeyboard_metatable);
	luaW_extend<FoneOSKeyboard, FoneOSContainer>(L); // FoneOSKeyboard inherits FoneOSContainer

	luaW_register<FoneOSScreen>(L, "FoneOSScreen", FoneOSContainer_table, FoneOSScreen_metatable);

	return 1;
}
<|endoftext|>


<commit_before>// This is free and unencumbered software released into the public domain.
// For more information, please refer to <http://unlicense.org/>

#include "sagtension/cable_component_elongation_model.h"

#include <cmath>
#include <vector>

#include "base/convert_units.h"
#include "gtest/gtest.h"

class CableComponentElongationModelTest : public ::testing::Test {
 protected:
  CableComponentElongationModelTest() {

    // builds dependency object - component
    const double area_physical = 0.7264;

    std::vector<double> coefficients_creep;
    coefficients_creep.push_back(-544.8 * area_physical);
    coefficients_creep.push_back(21426.8 * area_physical);
    coefficients_creep.push_back(-18842.2 * area_physical);
    coefficients_creep.push_back(5495 * area_physical);
    coefficients_creep.push_back(0 * area_physical);

    std::vector<double> coefficients_loadstrain;
    coefficients_loadstrain.push_back(-1213 * area_physical);
    coefficients_loadstrain.push_back(44308.1 * area_physical);
    coefficients_loadstrain.push_back(-14004.4 * area_physical);
    coefficients_loadstrain.push_back(-37618 * area_physical);
    coefficients_loadstrain.push_back(30676 * area_physical);

    CableComponent shell;
    shell.coefficient_expansion_linear_thermal = 0.0000128;
    shell.coefficients_polynomial_creep = coefficients_creep;
    shell.coefficients_polynomial_loadstrain = coefficients_loadstrain;
    shell.load_limit_polynomial_creep = 7535 * area_physical;
    shell.load_limit_polynomial_loadstrain = 20252 * area_physical;
    shell.modulus_compression_elastic_area = 1500 * area_physical * 100;
    shell.modulus_tension_elastic_area = 64000 * area_physical * 100;

    // builds fixture object
    c_.set_component_cable(shell);
    c_.set_load_stretch(5000);
    c_.set_temperature(70);
    c_.set_temperature_reference(70);
    c_.set_type_polynomial_active(CablePolynomialType::kLoadStrain);
  }

  CableComponentElongationModel c_;
};

TEST_F(CableComponentElongationModelTest, Load) {

  // compressed region
  EXPECT_EQ(-211.1, supportfunctions::Round(c_.Load(-0.001), 1));

  // stretched region
  EXPECT_EQ(289.3, supportfunctions::Round(c_.Load(0.001), 1));
  EXPECT_EQ(4938.2, supportfunctions::Round(c_.Load(0.002), 1));

  // polynomial region
  EXPECT_EQ(7301.6, supportfunctions::Round(c_.Load(0.003), 1));
  EXPECT_EQ(9187, supportfunctions::Round(c_.Load(0.004), 1));
  EXPECT_EQ(10645.4, supportfunctions::Round(c_.Load(0.005), 1));

  // extrapolated region
  EXPECT_EQ(18756.6, supportfunctions::Round(c_.Load(0.010), 1));
}

TEST_F(CableComponentElongationModelTest, PointPolynomialEnd) {

  Point2d p = c_.PointPolynomialEnd();
  EXPECT_EQ(0.0091, supportfunctions::Round(p.x, 4));
  EXPECT_EQ(14711.1, supportfunctions::Round(p.y, 1));
}

TEST_F(CableComponentElongationModelTest, PointPolynomialStart) {

  Point2d p = c_.PointPolynomialStart();
  EXPECT_EQ(0.0020, supportfunctions::Round(p.x, 4));
  EXPECT_EQ(5000, supportfunctions::Round(p.y, 1));
}

TEST_F(CableComponentElongationModelTest, PointUnloaded) {

  Point2d p = c_.PointUnloaded();
  EXPECT_EQ(0.000938, supportfunctions::Round(p.x, 6));
  EXPECT_EQ(0, supportfunctions::Round(p.y, 1));
}

TEST_F(CableComponentElongationModelTest, Slope) {

  // compressed region
  EXPECT_EQ(108960, supportfunctions::Round(c_.Slope(-0.001), 0));

  // stretched region
  EXPECT_EQ(4648960, supportfunctions::Round(c_.Slope(0.001), 0));
  EXPECT_EQ(4648960, supportfunctions::Round(c_.Slope(0.002), 0));

  // polynomial region
  EXPECT_EQ(2111035, supportfunctions::Round(c_.Slope(0.003), 0));
  EXPECT_EQ(1663528, supportfunctions::Round(c_.Slope(0.004), 0));
  EXPECT_EQ(1265984, supportfunctions::Round(c_.Slope(0.005), 0));

  // extrapolated region
  EXPECT_EQ(4648960, supportfunctions::Round(c_.Slope(0.010), 0));
}

TEST_F(CableComponentElongationModelTest, Strain) {

  // compressed region
  EXPECT_EQ(-0.001, supportfunctions::Round(c_.Strain(-211.1), 3));

  // stretched region
  EXPECT_EQ(0.001, supportfunctions::Round(c_.Strain(289.3), 3));
  EXPECT_EQ(0.002, supportfunctions::Round(c_.Strain(4938.2), 3));

  // polynomial region
  EXPECT_EQ(0.003, supportfunctions::Round(c_.Strain(7301.6), 3));
  EXPECT_EQ(0.004, supportfunctions::Round(c_.Strain(9187.0), 3));
  EXPECT_EQ(0.005, supportfunctions::Round(c_.Strain(10645.4), 3));

  // extrapolated region
  EXPECT_EQ(0.010, supportfunctions::Round(c_.Strain(18756.6), 3));
}

TEST_F(CableComponentElongationModelTest, StrainThermal) {

  // at reference temperature
  EXPECT_EQ(0, supportfunctions::Round(c_.StrainThermal(), 7));

  // above reference temperature
  c_.set_temperature(212);
  EXPECT_EQ(0.0018176, supportfunctions::Round(c_.StrainThermal(), 7));

  // below reference temperature
  c_.set_temperature(0);
  EXPECT_EQ(-0.000896, supportfunctions::Round(c_.StrainThermal(), 7));
}

TEST_F(CableComponentElongationModelTest, Validate) {

  // when checking for warnings, it does not pass the polynomial slope validation
  EXPECT_EQ(true, c_.Validate(false, nullptr));
}
<commit_msg>Added missing test function. In fixture, updated variable to coding convention naming style.<commit_after>// This is free and unencumbered software released into the public domain.
// For more information, please refer to <http://unlicense.org/>

#include "sagtension/cable_component_elongation_model.h"

#include "base/convert_units.h"
#include "gtest/gtest.h"

class CableComponentElongationModelTest : public ::testing::Test {
 protected:
  CableComponentElongationModelTest() {

    // builds dependency object - component
    const double kAreaPhysical = 0.7264;

    std::vector<double> coefficients_creep;
    coefficients_creep.push_back(-544.8 * kAreaPhysical);
    coefficients_creep.push_back(21426.8 * kAreaPhysical);
    coefficients_creep.push_back(-18842.2 * kAreaPhysical);
    coefficients_creep.push_back(5495 * kAreaPhysical);
    coefficients_creep.push_back(0 * kAreaPhysical);

    std::vector<double> coefficients_loadstrain;
    coefficients_loadstrain.push_back(-1213 * kAreaPhysical);
    coefficients_loadstrain.push_back(44308.1 * kAreaPhysical);
    coefficients_loadstrain.push_back(-14004.4 * kAreaPhysical);
    coefficients_loadstrain.push_back(-37618 * kAreaPhysical);
    coefficients_loadstrain.push_back(30676 * kAreaPhysical);

    CableComponent shell;
    shell.coefficient_expansion_linear_thermal = 0.0000128;
    shell.coefficients_polynomial_creep = coefficients_creep;
    shell.coefficients_polynomial_loadstrain = coefficients_loadstrain;
    shell.load_limit_polynomial_creep = 7535 * kAreaPhysical;
    shell.load_limit_polynomial_loadstrain = 20252 * kAreaPhysical;
    shell.modulus_compression_elastic_area = 1500 * kAreaPhysical * 100;
    shell.modulus_tension_elastic_area = 64000 * kAreaPhysical * 100;

    // builds fixture object
    c_.set_component_cable(shell);
    c_.set_load_stretch(5000);
    c_.set_temperature(70);
    c_.set_temperature_reference(70);
    c_.set_type_polynomial_active(CablePolynomialType::kLoadStrain);
  }

  CableComponentElongationModel c_;
};

TEST_F(CableComponentElongationModelTest, Load) {

  // compressed region
  EXPECT_EQ(-211.1, supportfunctions::Round(c_.Load(-0.001), 1));

  // stretched region
  EXPECT_EQ(289.3, supportfunctions::Round(c_.Load(0.001), 1));
  EXPECT_EQ(4938.2, supportfunctions::Round(c_.Load(0.002), 1));

  // polynomial region
  EXPECT_EQ(7301.6, supportfunctions::Round(c_.Load(0.003), 1));
  EXPECT_EQ(9187, supportfunctions::Round(c_.Load(0.004), 1));
  EXPECT_EQ(10645.4, supportfunctions::Round(c_.Load(0.005), 1));

  // extrapolated region
  EXPECT_EQ(18756.6, supportfunctions::Round(c_.Load(0.010), 1));
}

TEST_F(CableComponentElongationModelTest, PointPolynomialEnd) {

  Point2d p = c_.PointPolynomialEnd();
  EXPECT_EQ(0.0091, supportfunctions::Round(p.x, 4));
  EXPECT_EQ(14711.1, supportfunctions::Round(p.y, 1));
}

TEST_F(CableComponentElongationModelTest, PointPolynomialStart) {

  Point2d p = c_.PointPolynomialStart();
  EXPECT_EQ(0.0020, supportfunctions::Round(p.x, 4));
  EXPECT_EQ(5000, supportfunctions::Round(p.y, 1));
}

TEST_F(CableComponentElongationModelTest, PointsRegions) {

  std::vector<Point2d> points = c_.PointsRegions();
  Point2d p;

  p = points.at(0);
  EXPECT_EQ(0.000938, supportfunctions::Round(p.x, 6));
  EXPECT_EQ(0, supportfunctions::Round(p.y, 1));

  p = points.at(1);
  EXPECT_EQ(0.0020, supportfunctions::Round(p.x, 4));
  EXPECT_EQ(5000, supportfunctions::Round(p.y, 1));

  p = points.at(2);
  EXPECT_EQ(0.0091, supportfunctions::Round(p.x, 4));
  EXPECT_EQ(14711.1, supportfunctions::Round(p.y, 1));
}

TEST_F(CableComponentElongationModelTest, PointUnloaded) {

  Point2d p = c_.PointUnloaded();
  EXPECT_EQ(0.000938, supportfunctions::Round(p.x, 6));
  EXPECT_EQ(0, supportfunctions::Round(p.y, 1));
}

TEST_F(CableComponentElongationModelTest, Slope) {

  // compressed region
  EXPECT_EQ(108960, supportfunctions::Round(c_.Slope(-0.001), 0));

  // stretched region
  EXPECT_EQ(4648960, supportfunctions::Round(c_.Slope(0.001), 0));
  EXPECT_EQ(4648960, supportfunctions::Round(c_.Slope(0.002), 0));

  // polynomial region
  EXPECT_EQ(2111035, supportfunctions::Round(c_.Slope(0.003), 0));
  EXPECT_EQ(1663528, supportfunctions::Round(c_.Slope(0.004), 0));
  EXPECT_EQ(1265984, supportfunctions::Round(c_.Slope(0.005), 0));

  // extrapolated region
  EXPECT_EQ(4648960, supportfunctions::Round(c_.Slope(0.010), 0));
}

TEST_F(CableComponentElongationModelTest, Strain) {

  // compressed region
  EXPECT_EQ(-0.001, supportfunctions::Round(c_.Strain(-211.1), 3));

  // stretched region
  EXPECT_EQ(0.001, supportfunctions::Round(c_.Strain(289.3), 3));
  EXPECT_EQ(0.002, supportfunctions::Round(c_.Strain(4938.2), 3));

  // polynomial region
  EXPECT_EQ(0.003, supportfunctions::Round(c_.Strain(7301.6), 3));
  EXPECT_EQ(0.004, supportfunctions::Round(c_.Strain(9187.0), 3));
  EXPECT_EQ(0.005, supportfunctions::Round(c_.Strain(10645.4), 3));

  // extrapolated region
  EXPECT_EQ(0.010, supportfunctions::Round(c_.Strain(18756.6), 3));
}

TEST_F(CableComponentElongationModelTest, StrainThermal) {

  // at reference temperature
  EXPECT_EQ(0, supportfunctions::Round(c_.StrainThermal(), 7));

  // above reference temperature
  c_.set_temperature(212);
  EXPECT_EQ(0.0018176, supportfunctions::Round(c_.StrainThermal(), 7));

  // below reference temperature
  c_.set_temperature(0);
  EXPECT_EQ(-0.000896, supportfunctions::Round(c_.StrainThermal(), 7));
}

TEST_F(CableComponentElongationModelTest, Validate) {

  // when checking for warnings, it does not pass the polynomial slope validation
  EXPECT_EQ(true, c_.Validate(false, nullptr));
}
<|endoftext|>


<commit_before>#include "thread_context.hh"
#include <sys/syscall.h>

namespace ten {

bool glog_inited;

namespace {
    std::once_flag boot_flag;
}

static void kernel_boot() {
    CHECK(is_main_thread()) << "must call in main thread before anything else";

    InitGoogleLogging(program_invocation_short_name);
    glog_inited = true;

    // default to logging everything to stderr only.
    // ten::application turns this off again in favor of finer control.
    FLAGS_logtostderr = true;

    stack_t ss;
    ss.ss_sp = calloc(1, SIGSTKSZ);
    ss.ss_size = SIGSTKSZ;
    ss.ss_flags = 0;
    throw_if(sigaltstack(&ss, NULL) == -1);

    InstallFailureSignalHandler();

    struct sigaction act;

    // ignore SIGPIPE
    memset(&act, 0, sizeof(act));
    throw_if(sigaction(SIGPIPE, NULL, &act) == -1);
    if (act.sa_handler == SIG_DFL) {
        act.sa_handler = SIG_IGN;
        throw_if(sigaction(SIGPIPE, &act, NULL) == -1);
    }

    netinit();
}

kernel::time_point kernel::now() {
    return this_ctx->scheduler._now;
}

bool kernel::is_main_thread() {
    // TODO: could cache this in thread_context
    return getpid() == syscall(SYS_gettid);
}

size_t kernel::cpu_count() {
    return sysconf(_SC_NPROCESSORS_ONLN);
}

void kernel::shutdown() {
    this_ctx->cancel_all();
}

int32_t kernel::is_computer_on() { return 1; }

double kernel::is_computer_on_fire() {
    // TODO: implement
    return 7.0;
}

void kernel::boot() {
    std::call_once(boot_flag, kernel_boot);
}

void kernel::wait_for_tasks() {
    this_ctx->scheduler.wait_for_all();
}

kernel::kernel() {
    boot();
}

kernel::~kernel() {
    wait_for_tasks();
}

} // ten

<commit_msg>store signal stack addr so valgrind doesn't think it's leaked<commit_after>#include "thread_context.hh"
#include <sys/syscall.h>

namespace ten {

bool glog_inited;

namespace {
    std::once_flag boot_flag;
    void *signal_stack; // for valgrind
}

static void kernel_boot() {
    CHECK(is_main_thread()) << "must call in main thread before anything else";

    InitGoogleLogging(program_invocation_short_name);
    glog_inited = true;

    // default to logging everything to stderr only.
    // ten::application turns this off again in favor of finer control.
    FLAGS_logtostderr = true;

    signal_stack = calloc(1, SIGSTKSZ);
    stack_t ss;
    ss.ss_sp = signal_stack;
    ss.ss_size = SIGSTKSZ;
    ss.ss_flags = 0;
    throw_if(sigaltstack(&ss, NULL) == -1);

    InstallFailureSignalHandler();

    struct sigaction act;

    // ignore SIGPIPE
    memset(&act, 0, sizeof(act));
    throw_if(sigaction(SIGPIPE, NULL, &act) == -1);
    if (act.sa_handler == SIG_DFL) {
        act.sa_handler = SIG_IGN;
        throw_if(sigaction(SIGPIPE, &act, NULL) == -1);
    }

    netinit();
}

kernel::time_point kernel::now() {
    return this_ctx->scheduler._now;
}

bool kernel::is_main_thread() {
    // TODO: could cache this in thread_context
    return getpid() == syscall(SYS_gettid);
}

size_t kernel::cpu_count() {
    return sysconf(_SC_NPROCESSORS_ONLN);
}

void kernel::shutdown() {
    this_ctx->cancel_all();
}

int32_t kernel::is_computer_on() { return 1; }

double kernel::is_computer_on_fire() {
    // TODO: implement
    return 7.0;
}

void kernel::boot() {
    std::call_once(boot_flag, kernel_boot);
}

void kernel::wait_for_tasks() {
    this_ctx->scheduler.wait_for_all();
}

kernel::kernel() {
    boot();
}

kernel::~kernel() {
    wait_for_tasks();
}

} // ten

<|endoftext|>


<commit_before>#include "rubymotion.h"

VALUE rb_cLayer = Qnil;

class mc_Layer : private cocos2d::Layer {
    public:
	VALUE obj;

    mc_Layer() {
	obj = Qnil;
    }

    virtual void update(float delta) {
	VALUE arg = DBL2NUM(delta);
	rb_send(obj, rb_selector("update:"), 1, &arg);
    }
};

static VALUE
layer_alloc(VALUE rcv, SEL sel)
{
    mc_Layer *layer = new mc_Layer();
    VALUE obj = rb_class_wrap_new((void *)layer, rcv);
    layer->obj = rb_retain(obj);
    return obj;
}

static VALUE
layer_initialize(VALUE rcv, SEL sel)
{
    //LAYER(rcv)->init();
    return rcv;
}

extern "C"
void
Init_Layer(void)
{
    rb_cLayer = rb_define_class_under(rb_mMC, "Layer", rb_cNode);

    rb_define_singleton_method(rb_cLayer, "alloc", layer_alloc, 0);
    rb_define_method(rb_cLayer, "initialize", layer_initialize, 0);
}
<commit_msg>update: on iOS, update on android<commit_after>#include "rubymotion.h"

VALUE rb_cLayer = Qnil;

class mc_Layer : private cocos2d::Layer {
    public:
	VALUE obj;
	SEL update_sel;

    mc_Layer() {
	obj = Qnil;
#if CC_TARGET_OS_IPHONE
	update_sel = rb_selector("update:");
#else
	update_sel = rb_selector("update");
#endif
    }

    virtual void update(float delta) {
	VALUE arg = DBL2NUM(delta);
	rb_send(obj, update_sel, 1, &arg);
    }
};

static VALUE
layer_alloc(VALUE rcv, SEL sel)
{
    mc_Layer *layer = new mc_Layer();
    VALUE obj = rb_class_wrap_new((void *)layer, rcv);
    layer->obj = rb_retain(obj);
    return obj;
}

static VALUE
layer_initialize(VALUE rcv, SEL sel)
{
    //LAYER(rcv)->init();
    return rcv;
}

extern "C"
void
Init_Layer(void)
{
    rb_cLayer = rb_define_class_under(rb_mMC, "Layer", rb_cNode);

    rb_define_singleton_method(rb_cLayer, "alloc", layer_alloc, 0);
    rb_define_method(rb_cLayer, "initialize", layer_initialize, 0);
}
<|endoftext|>


<commit_before>/*
Resembla: Word-based Japanese similar sentence search library
https://github.com/tuem/resembla

Copyright 2017 Takashi Uemura

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef __STRING_UTIL_HPP__
#define __STRING_UTIL_HPP__

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

namespace resembla {

using string_type = std::wstring;

// common initialization procedures for using wchar_t
void init_locale();

template<typename src_type, typename dest_type>
void cast_string(const src_type& src, dest_type& dest);

template<typename src_type>
void cast_string(const src_type& src, src_type& dest)
{
    dest = src;
}

template<typename dest_type, typename src_type>
dest_type cast_string(const src_type& src)
{
    dest_type desc;
    cast_string(src, desc);
    return desc;
}

// split text by delimiter
template<typename string_type>
std::vector<string_type> split(const string_type& text, const typename string_type::value_type delimiter)
{
    std::vector<string_type> result;
    for(size_t start = 0, end; start < text.length(); start = end + 1){
        end = text.find(delimiter, start);
        if(end == string_type::npos){
            end = text.length();
        }
        result.push_back(text.substr(start, end - start));
        start = end + 1;
    }
    return result;
}

}
#endif
<commit_msg>fix bug in split()<commit_after>/*
Resembla: Word-based Japanese similar sentence search library
https://github.com/tuem/resembla

Copyright 2017 Takashi Uemura

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef __STRING_UTIL_HPP__
#define __STRING_UTIL_HPP__

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

namespace resembla {

using string_type = std::wstring;

// common initialization procedures for using wchar_t
void init_locale();

template<typename src_type, typename dest_type>
void cast_string(const src_type& src, dest_type& dest);

template<typename src_type>
void cast_string(const src_type& src, src_type& dest)
{
    dest = src;
}

template<typename dest_type, typename src_type>
dest_type cast_string(const src_type& src)
{
    dest_type desc;
    cast_string(src, desc);
    return desc;
}

// split text by delimiter
template<typename string_type>
std::vector<string_type> split(const string_type& text, const typename string_type::value_type delimiter)
{
    std::vector<string_type> result;
    bool finished = false;
    for(size_t start = 0, end; start < text.length();){
        end = text.find(delimiter, start);
        if(end == string_type::npos){
            end = text.length();
            finished = true;
        }
        result.push_back(text.substr(start, end - start));
        start = end + 1;
    }
    if(!finished){
        result.push_back(string_type());
    }
    return result;
}

}
#endif
<|endoftext|>


<commit_before>#include <stdlib.h>
#include "ros/ros.h"
#include <mongodb_store/message_store.h>
#include <boost/foreach.hpp>
#include <strands_navigation_msgs/NavStatistics.h>
#include <strands_navigation_msgs/TopologicalMap.h>
#include <strands_navigation_msgs/TopologicalNode.h>
#include <strands_executive_msgs/AddTask.h>
#include <strands_executive_msgs/SetExecutionStatus.h>
//#include <strands_executive_msgs/TaskUtils.h>
#include <std_msgs/Empty.h>
#include <geometry_msgs/PoseStamped.h>
#include <std_srvs/Empty.h>
#include <std_msgs/String.h>
#include <std_msgs/Int32.h>
#include "CFrelementSet.h"
#include <time.h>

#define MAX_EDGES 10000

const mongo::BSONObj EMPTY_BSON_OBJ;
int waitingInterval = 60;
int taskLength = 120;
int numTasks = 5;

using namespace mongodb_store;
using namespace std;

ros::NodeHandle *n;
ros::Publisher  taskPub;
bool debug = false;
ros::ServiceClient taskAdder;
ros::ServiceClient taskClear;
ros::ServiceClient taskStart;
std_srvs::Empty dummySrv;

CFrelementSet frelementSet;
string nodeName;
uint32_t 	times[100000];
unsigned char 	state[100000];
float wheel[1000];
int numNodes = 0;
float lastWheel = 0;

CTimer timer;
CTimer interactionTimer;

void recalculateModels()
{
	numNodes = frelementSet.numFrelements;
	float explorationRatio = 0.5;
	float entropy[1],probability[1];
	uint32_t times[1];
	times[0] = 0;//TODO current time
	lastWheel = 0;
	for (int i=0;i<numNodes;i++)
	{
		frelementSet.frelements[i]->estimateEntropy(times,entropy,1,1);
		frelementSet.frelements[i]->estimate(times,probability,1,1);
		lastWheel += explorationRatio*entropy[0]+(1-explorationRatio)*probability[0];
		wheel[i] = lastWheel;
	}
	printf("Wheel: ");
	for (int i=0;i<numNodes;i++) printf("%.3f ",wheel[i]);
	printf("%.3f \n",lastWheel);
}

/*loads nodes from the map description*/
void loadMap(const strands_navigation_msgs::TopologicalMap::ConstPtr& msg)
{

  	for (int i=0;i<msg->nodes.size();i++)
	{
		printf("MAP: %s.\n",msg->nodes[i].name.c_str());
		frelementSet.add(msg->nodes[i].name.c_str(),times,state,0);
	}
	numNodes = frelementSet.numFrelements;
  	for (int i=0;i<numNodes;i++)
	{
		printf("Final: %s.\n",frelementSet.frelements[i]->id);
	}
	recalculateModels();
}

/*loads nodes from the map description*/
void getCurrentNode(const std_msgs::String::ConstPtr& msg)
{
	nodeName = msg->data;
	printf("Current node %s.\n",nodeName.c_str());
	timer.reset(waitingInterval);
}

void addResult(const char *name,unsigned char state)
{
	uint32_t times[1];
	unsigned char signal[1];
	signal[0] = state;
	printf("%s-%i-%i\n",nodeName.c_str(),times[0],signal[0]);
	times[0] = (uint32_t)ros::Time::now().toSec();
	frelementSet.add(nodeName.c_str(),times,signal,1);
}

/*loads nodes from the map description*/
void getCommand(const std_msgs::String::ConstPtr& msg)
{
	printf("Current command %s.\n",msg->data.c_str());
	if (msg->data == "INFO_TERMINAL"){
		timer.reset(waitingInterval);
		printf("Info request at %s.",nodeName.c_str());
		if (interactionTimer.timeOut())
		{
			printf(" - FreMEnized.");
			interactionTimer.reset(waitingInterval/2);
			addResult(msg->data.c_str(),1);
		}
		printf("\n");
	}
}

void interacted(const std_msgs::Int32::ConstPtr& msg)
{
	printf("Infoterminal %i clicked at %s.",msg->data,nodeName.c_str());
	if (interactionTimer.timeOut())
	{
		printf(" - FreMEnized.");
		interactionTimer.reset(waitingInterval/2);
		addResult(nodeName.c_str(),1);
	}
	printf("\n");
}

void timeOut()
{
	timer.reset(waitingInterval);
	addResult(nodeName.c_str(),0);
}

/*recalculates models*/
void recalculate(const std_msgs::Empty::ConstPtr& msg)
{
	recalculateModels();
}

/*generates a task - invoked every minute*/
int generateTasks()
{
	time_t t;
	srand((unsigned int)time(&t));
	strands_executive_msgs::SetExecutionStatus runExec;
	//if (taskClear.call(dummySrv)) ROS_INFO("Tasks cleared.");
	for (int i=0;i<numTasks;i++)
	{
		int node = 0;
		float randomNum = 0;
		if (numNodes > 0){
			randomNum = (float)rand()/RAND_MAX*lastWheel;
			int p = 0;
			while (p <numNodes && randomNum > wheel[p]) p++;
			node = p;
		}

		//printf("Throw: %lf %i %s\n",randomNum,node,frelementSet.frelements[node]->id);

		strands_executive_msgs::AddTask taskAdd;
		strands_executive_msgs::Task task;
		task.start_node_id = frelementSet.frelements[node]->id;
		task.action = "wait_action";
		task.start_after = ros::Time::now()+ros::Duration(taskLength*i);
		task.end_before  = ros::Time::now()+ros::Duration(taskLength*(i+1)-1);
		task.max_duration = ros::Duration(waitingInterval);
		taskAdd.request.task = task;
		if (taskAdder.call(taskAdd))
		{
			ROS_INFO("Task ID: %ld", taskAdd.response.task_id);
		}
		printf("Time slot: %i-%i %i %s \n",taskLength*i,taskLength*(i+1)-1,numNodes,frelementSet.frelements[node]->id);
	}
	runExec.request.status = true;
	if (taskStart.call(runExec)) ROS_INFO("Task execution enabled.");
}

int main(int argc,char* argv[])
{
	ros::init(argc, argv, "infremen");
	n = new ros::NodeHandle();
        MessageStoreProxy messageStore(*n,"message_store");
	geometry_msgs::PoseStamped dummyPose;
	messageStore.insert(dummyPose);
	ros::Subscriber  topoMapSub = n->subscribe("/topological_map", 1000, loadMap);
	ros::Subscriber  currentNodeSub = n->subscribe("/closest_node", 1000, getCurrentNode);
	ros::Subscriber  getCommandSub = n->subscribe("/socialCardReader/commands", 1000, getCommand);
	ros::Subscriber  interfaceSub = n->subscribe("/info_terminal/active_screen", 1000, interacted);
	timer.start();
	timer.reset(waitingInterval);
	interactionTimer.start();
	interactionTimer.reset(waitingInterval);
	//ros::Subscriber  recalculateSub = n->subscribe("/recalculate", 1000, recalculate);
//	taskPub = n->advertise<strands_executive_msgs::Task>("/taskTopic", 1000, recalculate);
	taskAdder = n->serviceClient<strands_executive_msgs::AddTask>("/task_executor/add_task");
	//taskClear = n->serviceClient<std_msgs::Empty>("/task_executor/clear_schedule");
	taskStart = n->serviceClient<strands_executive_msgs::SetExecutionStatus>("/task_executor/set_execution_status");
	int periodicity = 20*(taskLength*numTasks+5);
	int iii = periodicity-5*20;
	while (ros::ok())
	{
		ros::spinOnce();
		usleep(50000);
		if (iii++>periodicity){
			recalculateModels();
			generateTasks();
			iii=0;
		}
		if (timer.timeOut())timeOut();
	}
	frelementSet.save("latest.fre");
	return 0;
}

<commit_msg>MongoDB stuff commented out<commit_after>#include <stdlib.h>
#include "ros/ros.h"
//#include <mongodb_store/message_store.h>
#include <boost/foreach.hpp>
#include <strands_navigation_msgs/NavStatistics.h>
#include <strands_navigation_msgs/TopologicalMap.h>
#include <strands_navigation_msgs/TopologicalNode.h>
#include <strands_executive_msgs/AddTask.h>
#include <strands_executive_msgs/SetExecutionStatus.h>
//#include <strands_executive_msgs/TaskUtils.h>
#include <std_msgs/Empty.h>
#include <geometry_msgs/PoseStamped.h>
#include <std_srvs/Empty.h>
#include <std_msgs/String.h>
#include <std_msgs/Int32.h>
#include "CFrelementSet.h"
#include <time.h>

#define MAX_EDGES 10000

//const mongo::BSONObj EMPTY_BSON_OBJ;
int waitingInterval = 60;
int taskLength = 120;
int numTasks = 5;

//using namespace mongodb_store;
using namespace std;

ros::NodeHandle *n;
ros::Publisher  taskPub;
bool debug = false;
ros::ServiceClient taskAdder;
ros::ServiceClient taskClear;
ros::ServiceClient taskStart;
std_srvs::Empty dummySrv;

CFrelementSet frelementSet;
string nodeName;
uint32_t 	times[100000];
unsigned char 	state[100000];
float wheel[1000];
int numNodes = 0;
float lastWheel = 0;

CTimer timer;
CTimer interactionTimer;

void recalculateModels()
{
	numNodes = frelementSet.numFrelements;
	float explorationRatio = 0.5;
	float entropy[1],probability[1];
	uint32_t times[1];
	times[0] = 0;//TODO current time
	lastWheel = 0;
	for (int i=0;i<numNodes;i++)
	{
		frelementSet.frelements[i]->estimateEntropy(times,entropy,1,1);
		frelementSet.frelements[i]->estimate(times,probability,1,1);
		lastWheel += explorationRatio*entropy[0]+(1-explorationRatio)*probability[0];
		wheel[i] = lastWheel;
	}
	printf("Wheel: ");
	for (int i=0;i<numNodes;i++) printf("%.3f ",wheel[i]);
	printf("%.3f \n",lastWheel);
}

/*loads nodes from the map description*/
void loadMap(const strands_navigation_msgs::TopologicalMap::ConstPtr& msg)
{

  	for (int i=0;i<msg->nodes.size();i++)
	{
		printf("MAP: %s.\n",msg->nodes[i].name.c_str());
		frelementSet.add(msg->nodes[i].name.c_str(),times,state,0);
	}
	numNodes = frelementSet.numFrelements;
  	for (int i=0;i<numNodes;i++)
	{
		printf("Final: %s.\n",frelementSet.frelements[i]->id);
	}
	recalculateModels();
}

/*loads nodes from the map description*/
void getCurrentNode(const std_msgs::String::ConstPtr& msg)
{
	nodeName = msg->data;
	printf("Current node %s.\n",nodeName.c_str());
	timer.reset(waitingInterval);
}

void addResult(const char *name,unsigned char state)
{
	uint32_t times[1];
	unsigned char signal[1];
	signal[0] = state;
	printf("%s-%i-%i\n",nodeName.c_str(),times[0],signal[0]);
	times[0] = (uint32_t)ros::Time::now().toSec();
	frelementSet.add(nodeName.c_str(),times,signal,1);
}

/*loads nodes from the map description*/
void getCommand(const std_msgs::String::ConstPtr& msg)
{
	printf("Current command %s.\n",msg->data.c_str());
	if (msg->data == "INFO_TERMINAL"){
		timer.reset(waitingInterval);
		printf("Info request at %s.",nodeName.c_str());
		if (interactionTimer.timeOut())
		{
			printf(" - FreMEnized.");
			interactionTimer.reset(waitingInterval/2);
			addResult(msg->data.c_str(),1);
		}
		printf("\n");
	}
}

void interacted(const std_msgs::Int32::ConstPtr& msg)
{
	printf("Infoterminal %i clicked at %s.",msg->data,nodeName.c_str());
	if (interactionTimer.timeOut())
	{
		printf(" - FreMEnized.");
		interactionTimer.reset(waitingInterval/2);
		addResult(nodeName.c_str(),1);
	}
	printf("\n");
}

void timeOut()
{
	timer.reset(waitingInterval);
	addResult(nodeName.c_str(),0);
}

/*recalculates models*/
void recalculate(const std_msgs::Empty::ConstPtr& msg)
{
	recalculateModels();
}

/*generates a task - invoked every minute*/
int generateTasks()
{
	time_t t;
	srand((unsigned int)time(&t));
	strands_executive_msgs::SetExecutionStatus runExec;
	//if (taskClear.call(dummySrv)) ROS_INFO("Tasks cleared.");
	for (int i=0;i<numTasks;i++)
	{
		int node = 0;
		float randomNum = 0;
		if (numNodes > 0){
			randomNum = (float)rand()/RAND_MAX*lastWheel;
			int p = 0;
			while (p <numNodes && randomNum > wheel[p]) p++;
			node = p;
		}

		//printf("Throw: %lf %i %s\n",randomNum,node,frelementSet.frelements[node]->id);

		strands_executive_msgs::AddTask taskAdd;
		strands_executive_msgs::Task task;
		task.start_node_id = frelementSet.frelements[node]->id;
		task.action = "wait_action";
		task.start_after = ros::Time::now()+ros::Duration(taskLength*i);
		task.end_before  = ros::Time::now()+ros::Duration(taskLength*(i+1)-1);
		task.max_duration = ros::Duration(waitingInterval);
		taskAdd.request.task = task;
		if (taskAdder.call(taskAdd))
		{
			ROS_INFO("Task ID: %ld", taskAdd.response.task_id);
		}
		printf("Time slot: %i-%i %i %s \n",taskLength*i,taskLength*(i+1)-1,numNodes,frelementSet.frelements[node]->id);
	}
	runExec.request.status = true;
	if (taskStart.call(runExec)) ROS_INFO("Task execution enabled.");
}

int main(int argc,char* argv[])
{
	ros::init(argc, argv, "infremen");
	n = new ros::NodeHandle();
//        MessageStoreProxy messageStore(*n,"message_store");
//	geometry_msgs::PoseStamped dummyPose;
//	messageStore.insert(dummyPose);
	ros::Subscriber  topoMapSub = n->subscribe("/topological_map", 1000, loadMap);
	ros::Subscriber  currentNodeSub = n->subscribe("/closest_node", 1000, getCurrentNode);
	ros::Subscriber  getCommandSub = n->subscribe("/socialCardReader/commands", 1000, getCommand);
	ros::Subscriber  interfaceSub = n->subscribe("/info_terminal/active_screen", 1000, interacted);
	timer.start();
	timer.reset(waitingInterval);
	interactionTimer.start();
	interactionTimer.reset(waitingInterval);
	//ros::Subscriber  recalculateSub = n->subscribe("/recalculate", 1000, recalculate);
//	taskPub = n->advertise<strands_executive_msgs::Task>("/taskTopic", 1000, recalculate);
	taskAdder = n->serviceClient<strands_executive_msgs::AddTask>("/task_executor/add_task");
	//taskClear = n->serviceClient<std_msgs::Empty>("/task_executor/clear_schedule");
	taskStart = n->serviceClient<strands_executive_msgs::SetExecutionStatus>("/task_executor/set_execution_status");
	int periodicity = 20*(taskLength*numTasks+5);
	int iii = periodicity-5*20;
	while (ros::ok())
	{
		ros::spinOnce();
		usleep(50000);
		if (iii++>periodicity){
			recalculateModels();
			generateTasks();
			iii=0;
		}
		if (timer.timeOut())timeOut();
	}
	frelementSet.save("latest.fre");
	return 0;
}

<|endoftext|>


<commit_before>#include <KAI/Core/Detail/Function.h>

#include "MyTestStruct.h"

USING_NAMESPACE_KAI

using namespace std;

bool funCalled[5];

// just making some functions that we will also add to the runtime soon
void Function_0()
{
	funCalled[0] = true;
}

void Function_1(int )
{
	funCalled[1] = true;
}

String Function_2(int n, int f, String p)
{
	funCalled[2] = true;
	// KAI_TRACE_3(n, f, p);
	return p + "foo";
}

Object Function_3(Object object)
{
	funCalled[3] = true;
	KAI_TRACE_1(object);
	return object["num"];
}

TEST(TestFunctionScripting, Test)
{
	try
	{
		Console console;
		console.SetLanguage(Language::Rho);
		Object root = console.GetRoot();
		Registry &reg = console.GetRegistry();
		MyStruct::Register(reg);

		Pointer<MyStruct> mystruct = reg.New<MyStruct>();
		mystruct->num = 345;
		mystruct->string = "hello world";

		console.GetTree().AddSearchPath(root);//Pathname("/"));

		// Process::trace = 10;
		root["mystruct"] = mystruct;
		AddFunction(root, Function_0, Label("Function0"));
		AddFunction(root, Function_1, Label("Function1"));
		AddFunction(root, Function_2, Label("Function2"));
		AddFunction(root, Function_3, Label("Function3"));

		console.Execute("Function0()");
		console.Execute("Function1(42)");
		console.Execute("Function2(123, 3, \"bar\")");
		console.Execute("Function3(mystruct)");

		for (int n = 0; n < 2; ++n)
			ASSERT_TRUE(funCalled[n]);

		Value<Stack> stack = console.GetExecutor()->GetDataStack();
		EXPECT_EQ(stack->Size(), 2);
		EXPECT_EQ(ConstDeref<int>(stack->Pop()), 345);
		EXPECT_EQ(ConstDeref<String>(stack->Pop()), "barfoo");
		EXPECT_EQ(stack->Size(), 0);
	}

	catch (kai::Exception::Base &e)
	{
		cerr << e.ToString() << endl;
	}
	catch (std::exception &e)
	{
		cerr << e.what() << endl;
	}
}

<commit_msg>Remove unnecessary try/catch from test now that I found --gtest_use_exceptions.<commit_after>#include <KAI/Core/Detail/Function.h>

#include "MyTestStruct.h"

USING_NAMESPACE_KAI

using namespace std;

bool funCalled[5];

// just making some functions that we will also add to the runtime soon
void Function_0()
{
	funCalled[0] = true;
}

void Function_1(int )
{
	funCalled[1] = true;
}

String Function_2(int n, int f, String p)
{
	funCalled[2] = true;
	// KAI_TRACE_3(n, f, p);
	return p + "foo";
}

Object Function_3(Object object)
{
	funCalled[3] = true;
	KAI_TRACE_1(object);
	return object["num"];
}

TEST(TestFunctionScripting, Test)
{
	Console console;
	console.SetLanguage(Language::Rho);
	Object root = console.GetRoot();
	Registry &reg = console.GetRegistry();
	MyStruct::Register(reg);

	Pointer<MyStruct> mystruct = reg.New<MyStruct>();
	mystruct->num = 345;
	mystruct->string = "hello world";

	console.GetTree().AddSearchPath(root);//Pathname("/"));

	// Process::trace = 10;
	root["mystruct"] = mystruct;
	AddFunction(root, Function_0, Label("Function0"));
	AddFunction(root, Function_1, Label("Function1"));
	AddFunction(root, Function_2, Label("Function2"));
	AddFunction(root, Function_3, Label("Function3"));

	console.Execute("Function0()");
	console.Execute("Function1(42)");
	console.Execute("Function2(123, 3, \"bar\")");
	console.Execute("Function3(mystruct)");

	for (int n = 0; n < 2; ++n)
		ASSERT_TRUE(funCalled[n]);

	Value<Stack> stack = console.GetExecutor()->GetDataStack();
	EXPECT_EQ(stack->Size(), 2);
	EXPECT_EQ(ConstDeref<int>(stack->Pop()), 345);
	EXPECT_EQ(ConstDeref<String>(stack->Pop()), "barfoo");
	EXPECT_EQ(stack->Size(), 0);
}

<|endoftext|>


<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkGenericProperty.h"

#include <iostream>

// call with testValue1 != testValue2
template <typename T>
int TestGenericPropertyForDataType(T testValue1, T testValue2, std::string testValue1AsString, std::string testValue2AsString)
{
  std::cout << "Testing mitk::GenericProperty<>(: " << testValue1 << ", " << testValue2 << ") ";

  typename mitk::GenericProperty<T>::Pointer prop = new mitk::GenericProperty<T>();
  typename mitk::GenericProperty<T>::Pointer prop2 = new mitk::GenericProperty<T>(testValue1);
  typename mitk::GenericProperty<T>::Pointer prop3 = new mitk::GenericProperty<T>(testValue2);

  unsigned long tBefore = prop->GetMTime();
  prop->SetValue(testValue1);
  unsigned long tAfter = prop->GetMTime();
  prop->SetValue(testValue1);
  unsigned long tAfterAll = prop->GetMTime();

  if (prop->GetValue() != testValue1 || prop->GetValueAsString() != testValue1AsString)
  {
    std::cout << "[FAILED]" << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "[PASSED]" << std::endl;

  std::cout << "Testing equality operator (operator==): ";
  if ( (! (*prop == *prop2)) || (*prop2 == *prop3) ) {
    std::cout << " [FAILED]" << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "[PASSED]" << std::endl;

  prop->SetValue(testValue2);
  unsigned long tAfterEverything = prop->GetMTime();

  std::cout << "Testing MTime correctness when changing property value: ";
  if (tBefore >= tAfter || tAfterAll != tAfter || tAfterEverything <= tAfterAll) {
     std::cout << "[FAILED]" << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "[PASSED]" << std::endl;

  prop->SetValue(testValue1);
  std::cout << "Testing assignment operator (operator=): ";
  *prop = *prop3;
  if ( (! (*prop == *prop3)) || (*prop == *prop2) ) {
    std::cout << " [FAILED]" << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "[PASSED]" << std::endl;

  return EXIT_SUCCESS;
}

int mitkGenericPropertyTest(int /*argc*/, char* /*argv*/[])
{
  int retVal(EXIT_SUCCESS);

  TestGenericPropertyForDataType<int>(1, 2, "1", "2");
  TestGenericPropertyForDataType<bool>(true, false, "1", "0");

  std::cout << "[TEST DONE]"<<std::endl;
  return retVal;
}
<commit_msg>Add some more data types to test<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkGenericProperty.h"
#include "mitkVector.h"

#include <iostream>
#include <string>

// call with testValue1 != testValue2
template <typename T>
int TestGenericPropertyForDataType(T testValue1, T testValue2, std::string testValue1AsString, std::string testValue2AsString, std::string type)
{
  std::cout << "Testing mitk::GenericProperty<" << type << ">(" << testValue1 << ", " << testValue2 << ") ";

  typename mitk::GenericProperty<T>::Pointer prop = new mitk::GenericProperty<T>();
  typename mitk::GenericProperty<T>::Pointer prop2 = new mitk::GenericProperty<T>(testValue1);
  typename mitk::GenericProperty<T>::Pointer prop3 = new mitk::GenericProperty<T>(testValue2);

  unsigned long tBefore = prop->GetMTime();
  prop->SetValue(testValue1);
  unsigned long tAfter = prop->GetMTime();
  prop->SetValue(testValue1);
  unsigned long tAfterAll = prop->GetMTime();

  if (prop->GetValue() != testValue1 || prop->GetValueAsString() != testValue1AsString)
  {
    std::cout << "[FAILED]" << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "[PASSED]" << std::endl;

  std::cout << "    Testing equality operator (operator==): ";
  if ( (! (*prop == *prop2)) || (*prop2 == *prop3) ) {
    std::cout << " [FAILED]" << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "[PASSED]" << std::endl;

  prop->SetValue(testValue2);
  unsigned long tAfterEverything = prop->GetMTime();

  std::cout << "    Testing MTime correctness when changing property value: ";
  if (tBefore >= tAfter || tAfterAll != tAfter || tAfterEverything <= tAfterAll) {
     std::cout << "[FAILED]" << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "[PASSED]" << std::endl;

  prop->SetValue(testValue1);
  std::cout << "    Testing assignment operator (operator=): ";
  *prop = *prop3;
  if ( (! (*prop == *prop3)) || (*prop == *prop2) ) {
    std::cout << " [FAILED]" << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "[PASSED]" << std::endl;
  std::cout << std::endl;

  return EXIT_SUCCESS;
}

int mitkGenericPropertyTest(int /*argc*/, char* /*argv*/[])
{
  int retVal(EXIT_SUCCESS);

  // testing for some different data types
  TestGenericPropertyForDataType<int>(1, 2, "1", "2", "int");
  TestGenericPropertyForDataType<bool>(true, false, "1", "0", "bool");
  TestGenericPropertyForDataType<float>(1.0, -1.0, "1", "-1", "float");
  TestGenericPropertyForDataType<double>(1.0, -1.0, "1", "-1", "double");

  TestGenericPropertyForDataType<std::string>("eins", "zwei", "eins", "zwei", "std::string");

  {
  mitk::Point3D p1; p1[0] = 2.0; p1[1] = 3.0; p1[2] = 4.0;
  mitk::Point3D p2; p2[0] =-1.0; p2[1] = 2.0; p2[2] = 3.0;
  TestGenericPropertyForDataType<mitk::Point3D>( p1, p2, "[2, 3, 4]", "[-1, 2, 3]", "mitk::Point3D");
  }

  {
  mitk::Point4D p1; p1[0] = 2.0; p1[1] = 3.0; p1[2] = 4.0; p1[3] =-2.0;
  mitk::Point4D p2; p2[0] =-1.0; p2[1] = 2.0; p2[2] = 3.0; p2[3] = 5.0;
  TestGenericPropertyForDataType<mitk::Point4D>( p1, p2, "[2, 3, 4, -2]", "[-1, 2, 3, 5]", "mitk::Point4D");
  }

  /*  THIS won't compile because of the interface of XMLWriter... that should be reworked perhaps
  {
  mitk::Vector2D p1; p1[0] = 2.0; p1[1] = 3.0;
  mitk::Vector2D p2; p2[0] =-1.0; p2[1] = 2.0;
  TestGenericPropertyForDataType<mitk::Vector2D>( p1, p2, "[2, 3]", "[-1, 2]", "mitk::Vector2D");
  }
  */

  {
  mitk::Vector3D p1; p1[0] = 2.0; p1[1] = 3.0; p1[2] = 4.0;
  mitk::Vector3D p2; p2[0] =-1.0; p2[1] = 2.0; p2[2] = 3.0;
  TestGenericPropertyForDataType<mitk::Vector3D>( p1, p2, "[2, 3, 4]", "[-1, 2, 3]", "mitk::Vector3D");
  }

  std::cout << "[TEST DONE]"<<std::endl;
  return retVal;
}
<|endoftext|>


<commit_before>#include <DebugLib/mDebugLib.hpp>

int main(void)
{

}<commit_msg>Tests/DebugLib_MultiThreadTests.cpp removed<commit_after><|endoftext|>


<commit_before>#include "common.h"

namespace Plow {
namespace Gui {

// createQApp
QApplication* createQApp(int &argc, char **argv, int flags)
{
    PlowStyle *plowStyle = new PlowStyle;
    QApplication::setStyle(plowStyle);

    QApplication *app  = new QApplication(argc, argv, flags);
    app->setStyleSheet(
                "QScrollBar {"
                "  border: 2px solid rgb(30,29,28);"
                "  border-radius: 6px;"
                "  background: rgb(18,18,16);"
                "  margin: 0 0 0 0;"
                "}"
                "QScrollBar:vertical {"
//                "  background: qlineargradient(x1:0, y1:0, x2:1, y2:0, "
//                "              stop:0 rgb(255,255,18), stop:1 rgb(30,29,28));"
                "  width: 15px;"
                "}"
                "QScrollBar:horizontal {"
//                "  background: qlineargradient(x1:0, y1:1, x2:0, y2:0,"
//                "              stop:0 rgb(19,18,18), stop:1 rgb(30,29,28));"
                "  height: 15px;"
                "}"
                "QScrollBar::handle {"
                "  border-radius: 4px;"
                "}"
                "QScrollBar::handle:vertical {"
                "  background: qlineargradient(x1:0, y1:0, x2:1, y2:0,"
                "              stop:0 rgb(67,66,63), stop:1 rgb(39,38,35));"
                "  min-height: 20px;"
                "}"
                "QScrollBar::handle:horizontal {"
                "  background: qlineargradient(x1:0, y1:0, x2:0, y2:1,"
                "              stop:0 rgb(67,66,63), stop:1 rgb(39,38,35));"
                "  min-width: 20px;"
                "}"
                "QScrollBar::add-line:vertical, QScrollBar::add-line:horizontal {"
                "  width: 1px;"
                "  height: 1px;"
                "}"
                "QScrollBar::sub-line:vertical, QScrollBar::sub-line:horizontal {"
                "  width: 1px;"
                "  height: 1px;"
                "}"
            );

    return app;
}

QList<QColor> PlowStyle::TaskColors = QList<QColor>()
    << QColor(60, 59, 55) // INIT - should never see
    << QColor(22, 47, 167) // WAITING
    << QColor(167, 159, 22) // RUNNING
    << QColor(167, 20, 14) // DEAD
    << QColor(116, 5, 0) // EATEN
    << QColor(166, 12, 143) // DEPEND
    << QColor(111, 167, 14); // SUCCEEEDED

// PlowStyle
PlowStyle::PlowStyle() :
    QPlastiqueStyle()
{}

void PlowStyle::polish(QPalette &palette) {

    QColor grayish(73, 72, 68);

    palette = QPalette(grayish);

    palette.setBrush(QPalette::Window, QColor(60, 59, 55));
    palette.setBrush(QPalette::WindowText, QColor(195, 194, 190));
    palette.setBrush(QPalette::ButtonText, QColor(211, 207, 196));
    palette.setBrush(QPalette::Text, QColor(223, 219, 207));
    palette.setBrush(QPalette::BrightText, QColor(224, 218, 220));

    QLinearGradient baseGrad(0, 0, 1, 1);
    baseGrad.setColorAt(0, QColor(29, 29, 27));
    baseGrad.setColorAt(1, QColor(38, 38, 36));
    palette.setBrush(QPalette::Base, baseGrad);

    QLinearGradient buttonGrad(0, 0, 1, 1);
    buttonGrad.setColorAt(0, QColor(75, 74, 70));
    buttonGrad.setColorAt(1, QColor(43, 42, 38));
    palette.setBrush(QPalette::Button, buttonGrad);

    palette.setBrush(QPalette::Highlight, QColor(105, 55, 88));
    palette.setBrush(QPalette::HighlightedText, Qt::white);

    QBrush brush = palette.background();
    brush.setColor(brush.color().dark());

    palette.setBrush(QPalette::Disabled, QPalette::WindowText, brush);
    palette.setBrush(QPalette::Disabled, QPalette::Text, brush);
    palette.setBrush(QPalette::Disabled, QPalette::ButtonText, brush);
    palette.setBrush(QPalette::Disabled, QPalette::Base, brush);
    palette.setBrush(QPalette::Disabled, QPalette::Button, brush);
    palette.setBrush(QPalette::Disabled, QPalette::Mid, brush);
}

}
}
<commit_msg>style: increased foreground text brightness and darkened Task state colors a bit<commit_after>#include "common.h"

namespace Plow {
namespace Gui {

// createQApp
QApplication* createQApp(int &argc, char **argv, int flags)
{
    PlowStyle *plowStyle = new PlowStyle;
    QApplication::setStyle(plowStyle);

    QApplication *app  = new QApplication(argc, argv, flags);
    app->setStyleSheet(
                "QScrollBar {"
                "  border: 2px solid rgb(30,29,28);"
                "  border-radius: 6px;"
                "  background: rgb(18,18,16);"
                "  margin: 0 0 0 0;"
                "}"
                "QScrollBar:vertical {"
//                "  background: qlineargradient(x1:0, y1:0, x2:1, y2:0, "
//                "              stop:0 rgb(255,255,18), stop:1 rgb(30,29,28));"
                "  width: 15px;"
                "}"
                "QScrollBar:horizontal {"
//                "  background: qlineargradient(x1:0, y1:1, x2:0, y2:0,"
//                "              stop:0 rgb(19,18,18), stop:1 rgb(30,29,28));"
                "  height: 15px;"
                "}"
                "QScrollBar::handle {"
                "  border-radius: 4px;"
                "}"
                "QScrollBar::handle:vertical {"
                "  background: qlineargradient(x1:0, y1:0, x2:1, y2:0,"
                "              stop:0 rgb(67,66,63), stop:1 rgb(39,38,35));"
                "  min-height: 20px;"
                "}"
                "QScrollBar::handle:horizontal {"
                "  background: qlineargradient(x1:0, y1:0, x2:0, y2:1,"
                "              stop:0 rgb(67,66,63), stop:1 rgb(39,38,35));"
                "  min-width: 20px;"
                "}"
                "QScrollBar::add-line:vertical, QScrollBar::add-line:horizontal {"
                "  width: 1px;"
                "  height: 1px;"
                "}"
                "QScrollBar::sub-line:vertical, QScrollBar::sub-line:horizontal {"
                "  width: 1px;"
                "  height: 1px;"
                "}"
            );

    return app;
}

QList<QColor> PlowStyle::TaskColors = QList<QColor>()
    << QColor(60, 59, 55).darker(150) // INIT - should never see
    << QColor(22, 47, 167).darker(150) // WAITING
    << QColor(167, 159, 22).darker(150) // RUNNING
    << QColor(167, 20, 14).darker(150) // DEAD
    << QColor(116, 5, 0).darker(150) // EATEN
    << QColor(166, 12, 143).darker(150) // DEPEND
    << QColor(111, 167, 14).darker(150); // SUCCEEEDED

// PlowStyle
PlowStyle::PlowStyle() :
    QPlastiqueStyle()
{}

void PlowStyle::polish(QPalette &palette) {

    QColor grayish(73, 72, 68);
    QColor fg(195,194,190);

    palette = QPalette(grayish);

    palette.setBrush(QPalette::Window, QColor(60, 59, 55));
    palette.setBrush(QPalette::WindowText, fg);
    palette.setBrush(QPalette::Text, fg.lighter(130));
    palette.setBrush(QPalette::ButtonText, QColor(211, 207, 196));
    palette.setBrush(QPalette::BrightText, QColor(242, 237, 240));

    QLinearGradient baseGrad(0, 0, 1, 1);
    baseGrad.setColorAt(0, QColor(29, 29, 27));
    baseGrad.setColorAt(1, QColor(38, 38, 36));
    palette.setBrush(QPalette::Base, baseGrad);

    QLinearGradient buttonGrad(0, 0, 1, 1);
    buttonGrad.setColorAt(0, QColor(75, 74, 70));
    buttonGrad.setColorAt(1, QColor(43, 42, 38));
    palette.setBrush(QPalette::Button, buttonGrad);

    palette.setBrush(QPalette::Highlight, QColor(105, 55, 88));
    palette.setBrush(QPalette::HighlightedText, Qt::white);

    QBrush brush = palette.window();
    brush.setColor(brush.color().darker());

    palette.setBrush(QPalette::Disabled, QPalette::WindowText, brush);
    palette.setBrush(QPalette::Disabled, QPalette::Text, brush);
    palette.setBrush(QPalette::Disabled, QPalette::ButtonText, brush);
    palette.setBrush(QPalette::Disabled, QPalette::Base, brush);
    palette.setBrush(QPalette::Disabled, QPalette::Button, brush);
    palette.setBrush(QPalette::Disabled, QPalette::Mid, brush);
}

}
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2013 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/image_reader.hpp>

extern "C"
{
#include <webp/types.h>
#include <webp/decode.h>
}

// boost
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>

namespace mapnik
{

class webp_reader : public image_reader
{
private:
    uint8_t const* data_;
    size_t size_;
    unsigned width_;
    unsigned height_;
public:
    explicit webp_reader(char const* data, std::size_t size);
    ~webp_reader();
    unsigned width() const;
    unsigned height() const;
    bool premultiplied_alpha() const { return false; }
    void read(unsigned x,unsigned y,image_data_32& image);
private:
    void init();
};

namespace
{
image_reader* create_webp_reader(char const * data, std::size_t size)
{
    return new webp_reader(data, size);
}

const bool registered = register_image_reader("webp", create_webp_reader);

}

// ctor
webp_reader::webp_reader(char const* data, std::size_t size)
    : data_(reinterpret_cast<uint8_t const*>(data)),
      size_(size),
      width_(0),
      height_(0)
{
    init();
}

// dtor
webp_reader::~webp_reader()
{
    //
}

void webp_reader::init()
{
    WebPDecoderConfig config;
    if (!WebPGetFeatures(data_, size_, &config.input) == VP8_STATUS_OK)
    {
        throw image_reader_exception("WEBP: can't open image");
    }
    width_ = config.input.width;
    height_ = config.input.height;
}

unsigned webp_reader::width() const
{
    return width_;
}

unsigned webp_reader::height() const
{
    return height_;
}

void webp_reader::read(unsigned x0, unsigned y0,image_data_32& image)
{
    WebPDecoderConfig config;
    config.options.use_cropping = 1;
    config.options.crop_left = x0;
    config.options.crop_top = y0;
    config.options.crop_width = image.width();
    config.options.crop_height = image.height();

    if (WebPGetFeatures(data_, size_, &config.input) != VP8_STATUS_OK)
    {
        throw image_reader_exception("WEBP reader: WebPGetFeatures failed");
    }

    config.output.colorspace = MODE_RGBA;
    config.output.u.RGBA.rgba = (uint8_t*)image.getBytes();
    config.output.u.RGBA.stride = 4 * image.width();
    config.output.u.RGBA.size = image.width()*image.height()*4;
    if (WebPDecode(data_, size_, &config) != VP8_STATUS_OK)
    {
        throw image_reader_exception("WEBP reader: WebPDecode failed");
    }
}

}
<commit_msg>+ fixes and improved error handling<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2013 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/image_reader.hpp>

extern "C"
{
#include <webp/types.h>
#include <webp/decode.h>
}

// boost
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>

namespace mapnik
{

class webp_reader : public image_reader
{
private:

    struct config_guard
    {
        config_guard(WebPDecoderConfig & config)
            : config_(config) {}

        ~config_guard()
        {
            WebPFreeDecBuffer(&config_.output);
        }
        WebPDecoderConfig & config_;
    };

    uint8_t const* data_;
    size_t size_;
    unsigned width_;
    unsigned height_;
public:
    explicit webp_reader(char const* data, std::size_t size);
    ~webp_reader();
    unsigned width() const;
    unsigned height() const;
    bool premultiplied_alpha() const { return false; }
    void read(unsigned x,unsigned y,image_data_32& image);
private:
    void init();
};

namespace
{
image_reader* create_webp_reader(char const * data, std::size_t size)
{
    return new webp_reader(data, size);
}

const bool registered = register_image_reader("webp", create_webp_reader);

}

// ctor
webp_reader::webp_reader(char const* data, std::size_t size)
    : data_(reinterpret_cast<uint8_t const*>(data)),
      size_(size),
      width_(0),
      height_(0)
{
    init();
}

// dtor
webp_reader::~webp_reader()
{
    //
}

void webp_reader::init()
{
    int width, height;
    if (!WebPGetInfo(data_, size_, &width, &height))
    {
        throw image_reader_exception("WEBP reader: WebPGetInfo failed");
    }
    width_ = width;
    height_ = height;
}

unsigned webp_reader::width() const
{
    return width_;
}

unsigned webp_reader::height() const
{
    return height_;
}

void webp_reader::read(unsigned x0, unsigned y0,image_data_32& image)
{
    WebPDecoderConfig config;
    config_guard guard(config);
    if (!WebPInitDecoderConfig(&config))
    {
        throw image_reader_exception("WEBP reader: WebPInitDecoderConfig failed");
    }

    config.options.use_cropping = 1;
    config.options.crop_left = x0;
    config.options.crop_top = y0;
    config.options.crop_width = image.width();
    config.options.crop_height = image.height();

    if (WebPGetFeatures(data_, size_, &config.input) != VP8_STATUS_OK)
    {
        throw image_reader_exception("WEBP reader: WebPGetFeatures failed");
    }

    config.output.colorspace = MODE_RGBA;
    config.output.u.RGBA.rgba = (uint8_t *)image.getBytes();
    config.output.u.RGBA.stride = 4 * image.width();
    config.output.u.RGBA.size = image.width() * image.height() * 4;
    config.output.is_external_memory = 1;
    if (WebPDecode(data_, size_, &config) != VP8_STATUS_OK)
    {
        throw image_reader_exception("WEBP reader: WebPDecode failed");
    }
}

}
<|endoftext|>