<commit_before>/** \file
 *
 *  Copyright (c) 2012 by Travis Gockel. All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
 *  as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
 *  version.
 *
 *  \author Travis Gockel (travis@gockelhut.com)
**/
#include <json-voorhees/object.hpp>

#include "detail.hpp"

#include <cstring>

using namespace jsonv::detail;

namespace jsonv
{

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// object                                                                                //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define OBJ _data.object->_values

object::object()
{
    _data.object = new detail::object_impl;
    _kind = kind::object;
}

object::object(const object& source) :
        value(source)
{ }

object::object(object&& source) :
        value(std::move(source))
{ }

object& object::operator =(const object& source)
{
    value::operator=(source);
    return *this;
}

object& object::operator =(object&& source)
{
    value::operator=(std::move(source));
    return *this;
}

void object::ensure_object() const
{
    check_type(kind::object, get_kind());
}

object::size_type object::size() const
{
    ensure_object();
    return OBJ.size();
}

object::iterator object::begin()
{
    ensure_object();
    return iterator(OBJ.begin());
}

object::const_iterator object::begin() const
{
    ensure_object();
    return const_iterator(OBJ.begin());
}

object::iterator object::end()
{
    ensure_object();
    return iterator(OBJ.end());
}

object::const_iterator object::end() const
{
    ensure_object();
    return const_iterator(OBJ.end());
}

value& object::operator[](const string_type& key)
{
    ensure_object();
    return OBJ[key];
}

const value& object::operator[](const string_type& key) const
{
    ensure_object();
    return OBJ[key];
}

object::size_type object::count(const key_type& key) const
{
    ensure_object();
    return OBJ.count(key);
}

object::iterator object::find(const string_type& key)
{
    ensure_object();
    return iterator(OBJ.find(key));
}

object::const_iterator object::find(const string_type& key) const
{
    ensure_object();
    return const_iterator(OBJ.find(key));
}

void object::insert(const value_type& pair)
{
    OBJ.insert(pair);
}

object::size_type object::erase(const key_type& key)
{
    ensure_object();
    return OBJ.erase(key);
}

bool object::operator ==(const object& other) const
{
    if (this == &other)
        return true;
    if (size() != other.size())
        return false;

    typedef object_impl::map_type::const_iterator const_iterator;
    const_iterator self_iter  = OBJ.begin();
    const_iterator other_iter = other.OBJ.begin();

    for (const const_iterator self_end = OBJ.end();
         self_iter != self_end;
         ++self_iter, ++other_iter
        )
    {
        if (self_iter->first != other_iter->first)
            return false;
        if (self_iter->second != other_iter->second)
            return false;
    }

    return true;
}

bool object::operator !=(const object& other) const
{
    return !operator==(other);
}

static void stream_single(ostream_type& stream, const object_impl::map_type::value_type& pair)
{
    stream_escaped_string(stream, pair.first)
        << ":"
        << pair.second;
}

ostream_type& operator <<(ostream_type& stream, const object& view)
{
    typedef object_impl::map_type::const_iterator const_iterator;
    typedef object_impl::map_type::value_type     value_type;

    const_iterator iter = view.OBJ.begin();
    const_iterator end  = view.OBJ.end();

    stream << "{";

    if (iter != end)
    {
        stream_single(stream, *iter);
        ++iter;
    }

    for ( ; iter != end; ++iter)
    {
        stream << ", ";
        stream_single(stream, *iter);
    }

    stream << "}";

    return stream;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// object::basic_iterator<T>                                                                                //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template <typename T>
struct object_iter_converter;

template <>
struct object_iter_converter<object::value_type>
{
    union impl
    {
        char* storage;
        object_impl::map_type::iterator* iter;
    };

    union const_impl
    {
        const char* storage;
        const object_impl::map_type::iterator* iter;
    };
};

template <>
struct object_iter_converter<const object::value_type>
{
    union impl
    {
        char* storage;
        object_impl::map_type::const_iterator* iter;
    };

    union const_impl
    {
        const char* storage;
        const object_impl::map_type::const_iterator* iter;
    };
};

#define JSONV_INSTANTIATE_OBJVIEW_BASIC_ITERATOR_FUNC(return_, ...)                                                    \
    template return_ object::basic_iterator<object::value_type>::__VA_ARGS__;                                          \
    template return_ object::basic_iterator<const object::value_type>::__VA_ARGS__;                                    \

template <typename T>
object::basic_iterator<T>::basic_iterator()
{
    memset(_storage, 0, sizeof _storage);
}
JSONV_INSTANTIATE_OBJVIEW_BASIC_ITERATOR_FUNC(, basic_iterator())

// private
template <typename T>
template <typename U>
object::basic_iterator<T>::basic_iterator(const U& source)
{
    static_assert(sizeof(U) == sizeof(_storage), "Input must be the same size of storage");

    memcpy(_storage, &source, sizeof _storage);
}

template <typename T>
void object::basic_iterator<T>::increment()
{
    typedef typename object_iter_converter<T>::impl converter_union;
    converter_union convert;
    convert.storage = _storage;
    ++(*convert.iter);
}
JSONV_INSTANTIATE_OBJVIEW_BASIC_ITERATOR_FUNC(void, increment())

template <typename T>
void object::basic_iterator<T>::decrement()
{
    typedef typename object_iter_converter<T>::impl converter_union;
    converter_union convert;
    convert.storage = _storage;
    --(*convert.iter);
}
JSONV_INSTANTIATE_OBJVIEW_BASIC_ITERATOR_FUNC(void, decrement())

template <typename T>
T& object::basic_iterator<T>::current() const
{
    typedef typename object_iter_converter<T>::const_impl converter_union;
    converter_union convert;
    convert.storage = _storage;
    return **convert.iter;
}
template object::value_type& object::basic_iterator<object::value_type>::current() const;
template const object::value_type& object::basic_iterator<const object::value_type>::current() const;

template <typename T>
bool object::basic_iterator<T>::equals(const char* other_storage) const
{
    typedef typename object_iter_converter<T>::const_impl converter_union;
    converter_union self_convert;
    self_convert.storage = _storage;
    converter_union other_convert;
    other_convert.storage = other_storage;

    return *self_convert.iter == *other_convert.iter;
}
JSONV_INSTANTIATE_OBJVIEW_BASIC_ITERATOR_FUNC(bool, equals(const char*) const)

template <typename T>
void object::basic_iterator<T>::copy_from(const char* other_storage)
{
    typedef typename object_iter_converter<T>::impl       converter_union;
    typedef typename object_iter_converter<T>::const_impl const_converter_union;
    converter_union self_convert;
    self_convert.storage = _storage;
    const_converter_union other_convert;
    other_convert.storage = other_storage;

    *self_convert.iter = *other_convert.iter;
}
JSONV_INSTANTIATE_OBJVIEW_BASIC_ITERATOR_FUNC(void, copy_from(const char*))

template <typename T>
template <typename U>
object::basic_iterator<T>::basic_iterator(const basic_iterator<U>& source,
                                          typename std::enable_if<std::is_convertible<U*, T*>::value>::type*
                                         )
{
    typedef typename object_iter_converter<T>::impl       converter_union;
    typedef typename object_iter_converter<U>::const_impl const_converter_union;
    converter_union self_convert;
    self_convert.storage = _storage;
    const_converter_union other_convert;
    other_convert.storage = source._storage;

    *self_convert.iter = *other_convert.iter;
}
template object::basic_iterator<const object::value_type>
               ::basic_iterator<object::value_type>(const basic_iterator<object::value_type>&, void*);

object::iterator object::erase(const_iterator position)
{
    ensure_object();
    typedef typename object_iter_converter<const object::value_type>::const_impl const_converter_union;
    const_converter_union pos_convert;
    pos_convert.storage = position._storage;
    return iterator(OBJ.erase(*pos_convert.iter));
}

object::iterator object::erase(const_iterator first, const_iterator last)
{
    ensure_object();
    typedef typename object_iter_converter<const object::value_type>::const_impl const_converter_union;
    const_converter_union first_convert;
    first_convert.storage = first._storage;
    const_converter_union last_convert;
    last_convert.storage = last._storage;
    return iterator(OBJ.erase(*first_convert.iter, *last_convert.iter));
}

}
<commit_msg>Remove unused local typedef in operator <<(ostream_type&, const object&).<commit_after>/** \file
 *
 *  Copyright (c) 2012 by Travis Gockel. All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
 *  as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
 *  version.
 *
 *  \author Travis Gockel (travis@gockelhut.com)
**/
#include <json-voorhees/object.hpp>

#include "detail.hpp"

#include <cstring>

using namespace jsonv::detail;

namespace jsonv
{

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// object                                                                                //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define OBJ _data.object->_values

object::object()
{
    _data.object = new detail::object_impl;
    _kind = kind::object;
}

object::object(const object& source) :
        value(source)
{ }

object::object(object&& source) :
        value(std::move(source))
{ }

object& object::operator =(const object& source)
{
    value::operator=(source);
    return *this;
}

object& object::operator =(object&& source)
{
    value::operator=(std::move(source));
    return *this;
}

void object::ensure_object() const
{
    check_type(kind::object, get_kind());
}

object::size_type object::size() const
{
    ensure_object();
    return OBJ.size();
}

object::iterator object::begin()
{
    ensure_object();
    return iterator(OBJ.begin());
}

object::const_iterator object::begin() const
{
    ensure_object();
    return const_iterator(OBJ.begin());
}

object::iterator object::end()
{
    ensure_object();
    return iterator(OBJ.end());
}

object::const_iterator object::end() const
{
    ensure_object();
    return const_iterator(OBJ.end());
}

value& object::operator[](const string_type& key)
{
    ensure_object();
    return OBJ[key];
}

const value& object::operator[](const string_type& key) const
{
    ensure_object();
    return OBJ[key];
}

object::size_type object::count(const key_type& key) const
{
    ensure_object();
    return OBJ.count(key);
}

object::iterator object::find(const string_type& key)
{
    ensure_object();
    return iterator(OBJ.find(key));
}

object::const_iterator object::find(const string_type& key) const
{
    ensure_object();
    return const_iterator(OBJ.find(key));
}

void object::insert(const value_type& pair)
{
    OBJ.insert(pair);
}

object::size_type object::erase(const key_type& key)
{
    ensure_object();
    return OBJ.erase(key);
}

bool object::operator ==(const object& other) const
{
    if (this == &other)
        return true;
    if (size() != other.size())
        return false;

    typedef object_impl::map_type::const_iterator const_iterator;
    const_iterator self_iter  = OBJ.begin();
    const_iterator other_iter = other.OBJ.begin();

    for (const const_iterator self_end = OBJ.end();
         self_iter != self_end;
         ++self_iter, ++other_iter
        )
    {
        if (self_iter->first != other_iter->first)
            return false;
        if (self_iter->second != other_iter->second)
            return false;
    }

    return true;
}

bool object::operator !=(const object& other) const
{
    return !operator==(other);
}

static void stream_single(ostream_type& stream, const object_impl::map_type::value_type& pair)
{
    stream_escaped_string(stream, pair.first)
        << ":"
        << pair.second;
}

ostream_type& operator <<(ostream_type& stream, const object& view)
{
    typedef object_impl::map_type::const_iterator const_iterator;

    const_iterator iter = view.OBJ.begin();
    const_iterator end  = view.OBJ.end();

    stream << "{";

    if (iter != end)
    {
        stream_single(stream, *iter);
        ++iter;
    }

    for ( ; iter != end; ++iter)
    {
        stream << ", ";
        stream_single(stream, *iter);
    }

    stream << "}";

    return stream;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// object::basic_iterator<T>                                                                                //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template <typename T>
struct object_iter_converter;

template <>
struct object_iter_converter<object::value_type>
{
    union impl
    {
        char* storage;
        object_impl::map_type::iterator* iter;
    };

    union const_impl
    {
        const char* storage;
        const object_impl::map_type::iterator* iter;
    };
};

template <>
struct object_iter_converter<const object::value_type>
{
    union impl
    {
        char* storage;
        object_impl::map_type::const_iterator* iter;
    };

    union const_impl
    {
        const char* storage;
        const object_impl::map_type::const_iterator* iter;
    };
};

#define JSONV_INSTANTIATE_OBJVIEW_BASIC_ITERATOR_FUNC(return_, ...)                                                    \
    template return_ object::basic_iterator<object::value_type>::__VA_ARGS__;                                          \
    template return_ object::basic_iterator<const object::value_type>::__VA_ARGS__;                                    \

template <typename T>
object::basic_iterator<T>::basic_iterator()
{
    memset(_storage, 0, sizeof _storage);
}
JSONV_INSTANTIATE_OBJVIEW_BASIC_ITERATOR_FUNC(, basic_iterator())

// private
template <typename T>
template <typename U>
object::basic_iterator<T>::basic_iterator(const U& source)
{
    static_assert(sizeof(U) == sizeof(_storage), "Input must be the same size of storage");

    memcpy(_storage, &source, sizeof _storage);
}

template <typename T>
void object::basic_iterator<T>::increment()
{
    typedef typename object_iter_converter<T>::impl converter_union;
    converter_union convert;
    convert.storage = _storage;
    ++(*convert.iter);
}
JSONV_INSTANTIATE_OBJVIEW_BASIC_ITERATOR_FUNC(void, increment())

template <typename T>
void object::basic_iterator<T>::decrement()
{
    typedef typename object_iter_converter<T>::impl converter_union;
    converter_union convert;
    convert.storage = _storage;
    --(*convert.iter);
}
JSONV_INSTANTIATE_OBJVIEW_BASIC_ITERATOR_FUNC(void, decrement())

template <typename T>
T& object::basic_iterator<T>::current() const
{
    typedef typename object_iter_converter<T>::const_impl converter_union;
    converter_union convert;
    convert.storage = _storage;
    return **convert.iter;
}
template object::value_type& object::basic_iterator<object::value_type>::current() const;
template const object::value_type& object::basic_iterator<const object::value_type>::current() const;

template <typename T>
bool object::basic_iterator<T>::equals(const char* other_storage) const
{
    typedef typename object_iter_converter<T>::const_impl converter_union;
    converter_union self_convert;
    self_convert.storage = _storage;
    converter_union other_convert;
    other_convert.storage = other_storage;

    return *self_convert.iter == *other_convert.iter;
}
JSONV_INSTANTIATE_OBJVIEW_BASIC_ITERATOR_FUNC(bool, equals(const char*) const)

template <typename T>
void object::basic_iterator<T>::copy_from(const char* other_storage)
{
    typedef typename object_iter_converter<T>::impl       converter_union;
    typedef typename object_iter_converter<T>::const_impl const_converter_union;
    converter_union self_convert;
    self_convert.storage = _storage;
    const_converter_union other_convert;
    other_convert.storage = other_storage;

    *self_convert.iter = *other_convert.iter;
}
JSONV_INSTANTIATE_OBJVIEW_BASIC_ITERATOR_FUNC(void, copy_from(const char*))

template <typename T>
template <typename U>
object::basic_iterator<T>::basic_iterator(const basic_iterator<U>& source,
                                          typename std::enable_if<std::is_convertible<U*, T*>::value>::type*
                                         )
{
    typedef typename object_iter_converter<T>::impl       converter_union;
    typedef typename object_iter_converter<U>::const_impl const_converter_union;
    converter_union self_convert;
    self_convert.storage = _storage;
    const_converter_union other_convert;
    other_convert.storage = source._storage;

    *self_convert.iter = *other_convert.iter;
}
template object::basic_iterator<const object::value_type>
               ::basic_iterator<object::value_type>(const basic_iterator<object::value_type>&, void*);

object::iterator object::erase(const_iterator position)
{
    ensure_object();
    typedef typename object_iter_converter<const object::value_type>::const_impl const_converter_union;
    const_converter_union pos_convert;
    pos_convert.storage = position._storage;
    return iterator(OBJ.erase(*pos_convert.iter));
}

object::iterator object::erase(const_iterator first, const_iterator last)
{
    ensure_object();
    typedef typename object_iter_converter<const object::value_type>::const_impl const_converter_union;
    const_converter_union first_convert;
    first_convert.storage = first._storage;
    const_converter_union last_convert;
    last_convert.storage = last._storage;
    return iterator(OBJ.erase(*first_convert.iter, *last_convert.iter));
}

}
<|endoftext|>


<commit_before>//=============================================================================================================
/**
* @file     ssvepBCIFlickeringItem.cpp
* @author   Viktor Klüber <viktor.klueber@tu-ilmenauz.de>;
*           Lorenz Esch <Lorenz.Esch@tu-ilmenau.de>;
*           Christoph Dinh <chdinh@nmr.mgh.harvard.edu>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     May 2016
*
* @section  LICENSE
*
* Copyright (C) 2014, Lorenz Esch, Christoph Dinh and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    Contains the implementation of the ssvepBCIFlickeringItem class.
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "ssvepbciflickeringitem.h"

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace ssvepBCIPlugin;

//*************************************************************************************************************
//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

ssvepBCIFlickeringItem::ssvepBCIFlickeringItem()
    : m_dPosX(0)
    , m_dPosY(0)
    , m_dWidth(0.4)
    , m_dHeight(0.4)
    , m_bFlickerState(true)
    , m_bSignFlag(false)
    , m_bIter(m_bRenderOrder)

{
    m_bRenderOrder << 0 << 0 << 1 << 1; //default
}

//*************************************************************************************************************

ssvepBCIFlickeringItem::~ssvepBCIFlickeringItem(){
}

//*************************************************************************************************************

void ssvepBCIFlickeringItem::setPos(double x, double y){
        m_dPosX = x;
        m_dPosY = y;
}

//*************************************************************************************************************

void ssvepBCIFlickeringItem::setDim(double w, double h){
    m_dWidth    = w;
    m_dHeight   = h;
}

//*************************************************************************************************************

void ssvepBCIFlickeringItem::setRenderOrder(QList<bool> renderOrder, int freqKey){

    //clear the old rendering order list
    m_bRenderOrder.clear();

    //setup the iterator and assign it to the new list
    m_bRenderOrder  = renderOrder;
    m_bIter         = m_bRenderOrder;
    m_iFreqKey      = freqKey;
}

//*************************************************************************************************************

void ssvepBCIFlickeringItem::paint(QPaintDevice *paintDevice)
{
    //setting the nex flicker state (moving iterater to front if necessary)
    if(!m_bIter.hasNext())
        m_bIter.toFront();
    m_bFlickerState = m_bIter.next();

    //painting the itme's shape
    QPainter p(paintDevice);

    if(m_bSignFlag){
//        // scaling the letter size to the biggest sign "DEL"
//        float factor =0.2* m_dWidth*paintDevice->width() / p.fontMetrics().width(m_sSign);
//        if ((factor < 1) || (factor > 1.25))
//        {
//            QFont f = p.font();
//            f.setBold(true);
//            f.setPointSizeF(f.pointSizeF()*factor);
//            p.setFont(f);
//        }

        QFont f = p.font();
        f.setBold(true);
        f.setPointSize(30);
        p.setFont(f);
    }

    QRect rectangle(m_dPosX*paintDevice->width(),m_dPosY*paintDevice->height(),m_dWidth*paintDevice->width(),m_dHeight*paintDevice->height());

    if(true){
        p.fillRect(rectangle,Qt::white);
        p.drawText(rectangle, Qt::AlignCenter, m_sSign);
    }
//    else
//        p.fillRect(m_dPosX*paintDevice->width(),m_dPosY*paintDevice->height(),m_dWidth*paintDevice->width(),m_dHeight*paintDevice->height(),Qt::black);

}

//*************************************************************************************************************

int ssvepBCIFlickeringItem::getFreqKey()
{
    return m_iFreqKey;
}

void ssvepBCIFlickeringItem::addSign(QString sign){

    m_bSignFlag = true;
    m_sSign = sign;
}
<commit_msg>[SC-115] edit screen-keyboard<commit_after>//=============================================================================================================
/**
* @file     ssvepBCIFlickeringItem.cpp
* @author   Viktor Klüber <viktor.klueber@tu-ilmenauz.de>;
*           Lorenz Esch <Lorenz.Esch@tu-ilmenau.de>;
*           Christoph Dinh <chdinh@nmr.mgh.harvard.edu>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     May 2016
*
* @section  LICENSE
*
* Copyright (C) 2014, Lorenz Esch, Christoph Dinh and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    Contains the implementation of the ssvepBCIFlickeringItem class.
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "ssvepbciflickeringitem.h"

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace ssvepBCIPlugin;

//*************************************************************************************************************
//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

ssvepBCIFlickeringItem::ssvepBCIFlickeringItem()
    : m_dPosX(0)
    , m_dPosY(0)
    , m_dWidth(0.4)
    , m_dHeight(0.4)
    , m_bFlickerState(true)
    , m_bSignFlag(false)
    , m_bIter(m_bRenderOrder)

{
    m_bRenderOrder << 0 << 0 << 1 << 1; //default
}

//*************************************************************************************************************

ssvepBCIFlickeringItem::~ssvepBCIFlickeringItem(){
}

//*************************************************************************************************************

void ssvepBCIFlickeringItem::setPos(double x, double y){
        m_dPosX = x;
        m_dPosY = y;
}

//*************************************************************************************************************

void ssvepBCIFlickeringItem::setDim(double w, double h){
    m_dWidth    = w;
    m_dHeight   = h;
}

//*************************************************************************************************************

void ssvepBCIFlickeringItem::setRenderOrder(QList<bool> renderOrder, int freqKey){

    //clear the old rendering order list
    m_bRenderOrder.clear();

    //setup the iterator and assign it to the new list
    m_bRenderOrder  = renderOrder;
    m_bIter         = m_bRenderOrder;
    m_iFreqKey      = freqKey;
}

//*************************************************************************************************************

void ssvepBCIFlickeringItem::paint(QPaintDevice *paintDevice)
{
    //setting the nex flicker state (moving iterater to front if necessary)
    if(!m_bIter.hasNext())
        m_bIter.toFront();
    m_bFlickerState = m_bIter.next();

    //painting the itme's shape
    QPainter p(paintDevice);

    if(m_bSignFlag){
//        // scaling the letter size to the biggest sign "DEL"
//        float factor =0.2* m_dWidth*paintDevice->width() / p.fontMetrics().width(m_sSign);
//        if ((factor < 1) || (factor > 1.25))
//        {
//            QFont f = p.font();
//            f.setBold(true);
//            f.setPointSizeF(f.pointSizeF()*factor);
//            p.setFont(f);
//        }

        QFont f = p.font();
        f.setBold(true);
        f.setPointSize(30);
        p.setFont(f);
    }

    QRect rectangle(m_dPosX*paintDevice->width(),m_dPosY*paintDevice->height(),m_dWidth*paintDevice->width(),m_dHeight*paintDevice->height());

    if(m_bFlickerState){
        p.fillRect(rectangle,Qt::white);
        p.drawText(rectangle, Qt::AlignCenter, m_sSign);
    }
    else
        p.fillRect(m_dPosX*paintDevice->width(),m_dPosY*paintDevice->height(),m_dWidth*paintDevice->width(),m_dHeight*paintDevice->height(),Qt::black);

}

//*************************************************************************************************************

int ssvepBCIFlickeringItem::getFreqKey()
{
    return m_iFreqKey;
}

void ssvepBCIFlickeringItem::addSign(QString sign){

    m_bSignFlag = true;
    m_sSign = sign;
}
<|endoftext|>


<commit_before>
#include <Atomic/IO/Log.h>
#include <Atomic/Core/CoreEvents.h>

#include <Atomic/Graphics/Graphics.h>
#include <Atomic/Graphics/Drawable.h>
#include <Atomic/Graphics/DebugRenderer.h>
#include <Atomic/Atomic3D/Terrain.h>

#include <Atomic/Scene/SceneEvents.h>
#include <Atomic/Scene/Node.h>
#include <Atomic/Scene/Scene.h>

#include "SceneEditor3D.h"
#include "SceneEditor3DEvents.h"
#include "SceneSelection.h"

namespace AtomicEditor
{

SceneSelection::SceneSelection(Context* context, SceneEditor3D *sceneEditor) : Object(context)
{
    sceneEditor3D_ = sceneEditor;
    scene_ = sceneEditor3D_->GetScene();

    SubscribeToEvent(E_POSTRENDERUPDATE, HANDLER(SceneSelection, HandlePostRenderUpdate));
    SubscribeToEvent(scene_, E_NODEREMOVED, HANDLER(SceneSelection, HandleNodeRemoved));
}

SceneSelection::~SceneSelection()
{

}

Node* SceneSelection::GetSelectedNode(unsigned index) const
{
    if (index > nodes_.Size())
        return 0;

    return nodes_[index];
}

bool SceneSelection::Contains(Node* node)
{
    SharedPtr<Node> _node(node);
    return nodes_.Contains(_node);
}

void SceneSelection::AddNode(Node* node, bool clear)
{
    if (clear)
        Clear();

    SharedPtr<Node> _node(node);
    if (!nodes_.Contains(_node))
    {
        nodes_.Push(_node);

        VariantMap eventData;
        eventData[SceneNodeSelected::P_SCENE] = scene_;
        eventData[SceneNodeSelected::P_NODE] = node;
        eventData[SceneNodeSelected::P_SELECTED] = true;
        scene_->SendEvent(E_SCENENODESELECTED, eventData);
    }
}

void SceneSelection::RemoveNode(Node* node, bool quiet)
{
    SharedPtr<Node> _node(node);
    if(!nodes_.Contains(_node))
        return;

    nodes_.Remove(_node);

    if (quiet)
        return;

    VariantMap eventData;
    eventData[SceneNodeSelected::P_SCENE] = scene_;
    eventData[SceneNodeSelected::P_NODE] = node;
    eventData[SceneNodeSelected::P_SELECTED] = false;
    scene_->SendEvent(E_SCENENODESELECTED, eventData);

}

void SceneSelection::Clear()
{
    Vector<SharedPtr<Node>> nodes = nodes_;

    for (unsigned i = 0; i < nodes.Size(); i++)
    {
        RemoveNode(nodes[i]);
    }

}

void SceneSelection::Paste()
{

    if (!clipBoardNodes_.Size())
        return;

    Vector<SharedPtr<Node>> newClipBoardNodes;

    Node* parent = scene_;

    if (nodes_.Size() == 1)
        parent = nodes_[0];

    Clear();

    VariantMap eventData;
    eventData[SceneEditAddRemoveNodes::P_END] = false;
    scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);

    for (unsigned i = 0; i < clipBoardNodes_.Size(); i++)
    {
        // Nodes must have a parent to clone, so first parent
        Node* clipNode = clipBoardNodes_[i];

        Matrix3x4 transform = clipNode->GetWorldTransform();

        parent->AddChild(clipNode);
        clipNode->SetWorldTransform(transform.Translation(), transform.Rotation(), transform.Scale());

        // clone
        newClipBoardNodes.Push(SharedPtr<Node>(clipNode->Clone()));
        // remove from parent
        newClipBoardNodes.Back()->Remove();
        newClipBoardNodes.Back()->SetWorldTransform(transform.Translation(), transform.Rotation(), transform.Scale());

        // generate scene edit event
        VariantMap nodeAddedEventData;
        nodeAddedEventData[SceneEditNodeAdded::P_NODE] = clipNode;
        nodeAddedEventData[SceneEditNodeAdded::P_PARENT] = parent;
        nodeAddedEventData[SceneEditNodeAdded::P_SCENE] = scene_;
        scene_->SendEvent(E_SCENEEDITNODEADDED, nodeAddedEventData);
    }

    eventData[SceneEditAddRemoveNodes::P_END] = true;
    scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);

    for (unsigned i = 0; i < clipBoardNodes_.Size(); i++)
    {
        AddNode(clipBoardNodes_[i], false);
    }

    clipBoardNodes_ = newClipBoardNodes;

}

void SceneSelection::Copy()
{
    clipBoardNodes_.Clear();

    for (unsigned i = 0; i < nodes_.Size(); i++)
    {
        Node* node = nodes_[i];

        if (!node->GetParent())
        {
            clipBoardNodes_.Clear();
            LOGERROR("SceneSelection::Copy - unable to copy node to clipboard (no parent)");
            return;
        }

        for (unsigned j = 0; j < nodes_.Size(); j++)
        {
            if ( i == j )
                continue;

            PODVector<Node*> children;
            nodes_[j]->GetChildren(children, true);
            if (children.Contains(node))
            {
                node = 0;
                break;
            }

        }

        if (node)
        {
            SharedPtr<Node> clipNode(node->Clone());
            clipNode->Remove();
            clipBoardNodes_.Push(clipNode);
        }

    }
}

void SceneSelection::Delete()
{

    Vector<SharedPtr<Node>> nodes = nodes_;

    Clear();

    VariantMap eventData;
    eventData[SceneEditAddRemoveNodes::P_END] = false;
    scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);

    for (unsigned i = 0; i < nodes.Size(); i++)
    {
        // generate scene edit event
        VariantMap nodeRemovedEventData;
        nodeRemovedEventData[SceneEditNodeAdded::P_NODE] = nodes[i];
        nodeRemovedEventData[SceneEditNodeAdded::P_PARENT] = nodes[i]->GetParent();
        nodeRemovedEventData[SceneEditNodeAdded::P_SCENE] = scene_;
        scene_->SendEvent(E_SCENEEDITNODEREMOVED, nodeRemovedEventData);

        nodes[i]->Remove();

    }

    eventData[SceneEditAddRemoveNodes::P_END] = true;
    scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);

}

void SceneSelection::GetBounds(BoundingBox& bbox)
{

    bbox.Clear();

    if (!nodes_.Size())
        return;

    // Get all the drawables, which define the bounding box of the selection
    PODVector<Drawable*> drawables;

    for (unsigned i = 0; i < nodes_.Size(); i++)
    {
        Node* node = nodes_[i];
        node->GetDerivedComponents<Drawable>(drawables, true, false);
    }

    if (!drawables.Size())
        return;

    // Calculate the combined bounding box of all drawables
    for (unsigned i = 0; i < drawables.Size(); i++  )
    {
        Drawable* drawable = drawables[i];
        bbox.Merge(drawable->GetWorldBoundingBox());
    }

}

void SceneSelection::DrawNodeDebug(Node* node, DebugRenderer* debug, bool drawNode)
{
    if (drawNode)
        debug->AddNode(node, 1.0, false);

    // Exception for the scene to avoid bringing the editor to its knees: drawing either the whole hierarchy or the subsystem-
    // components can have a large performance hit. Also do not draw terrain child nodes due to their large amount
    // (TerrainPatch component itself draws nothing as debug geometry)
    if (node != scene_ && !node->GetComponent<Terrain>())
    {
        const Vector<SharedPtr<Component> >& components = node->GetComponents();

        for (unsigned j = 0; j < components.Size(); ++j)
            components[j]->DrawDebugGeometry(debug, false);

        // To avoid cluttering the view, do not draw the node axes for child nodes
        for (unsigned k = 0; k < node->GetNumChildren(); ++k)
            DrawNodeDebug(node->GetChild(k), debug, false);
    }
}

void SceneSelection::HandleNodeRemoved(StringHash eventType, VariantMap& eventData)
{
    Node* node = (Node*) (eventData[NodeRemoved::P_NODE].GetPtr());
    RemoveNode(node, true);
}

void SceneSelection::HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData)
{

    if (!nodes_.Size())
        return;

    // Visualize the currently selected nodes
    DebugRenderer* debugRenderer = sceneEditor3D_->GetSceneView3D()->GetDebugRenderer();

    for (unsigned i = 0; i < nodes_.Size(); i++)
    {
        DrawNodeDebug(nodes_[i], debugRenderer);
    }

}

}
<commit_msg>Copy/Paste updates<commit_after>
#include <Atomic/IO/Log.h>
#include <Atomic/Core/CoreEvents.h>

#include <Atomic/Graphics/Graphics.h>
#include <Atomic/Graphics/Drawable.h>
#include <Atomic/Graphics/DebugRenderer.h>
#include <Atomic/Atomic3D/Terrain.h>

#include <Atomic/Scene/SceneEvents.h>
#include <Atomic/Scene/Node.h>
#include <Atomic/Scene/Scene.h>

#include "SceneEditor3D.h"
#include "SceneEditor3DEvents.h"
#include "SceneSelection.h"

namespace AtomicEditor
{

SceneSelection::SceneSelection(Context* context, SceneEditor3D *sceneEditor) : Object(context)
{
    sceneEditor3D_ = sceneEditor;
    scene_ = sceneEditor3D_->GetScene();

    SubscribeToEvent(E_POSTRENDERUPDATE, HANDLER(SceneSelection, HandlePostRenderUpdate));
    SubscribeToEvent(scene_, E_NODEREMOVED, HANDLER(SceneSelection, HandleNodeRemoved));
}

SceneSelection::~SceneSelection()
{

}

Node* SceneSelection::GetSelectedNode(unsigned index) const
{
    if (index > nodes_.Size())
        return 0;

    return nodes_[index];
}

bool SceneSelection::Contains(Node* node)
{
    SharedPtr<Node> _node(node);
    return nodes_.Contains(_node);
}

void SceneSelection::AddNode(Node* node, bool clear)
{
    if (clear)
        Clear();

    SharedPtr<Node> _node(node);
    if (!nodes_.Contains(_node))
    {
        nodes_.Push(_node);

        VariantMap eventData;
        eventData[SceneNodeSelected::P_SCENE] = scene_;
        eventData[SceneNodeSelected::P_NODE] = node;
        eventData[SceneNodeSelected::P_SELECTED] = true;
        scene_->SendEvent(E_SCENENODESELECTED, eventData);
    }
}

void SceneSelection::RemoveNode(Node* node, bool quiet)
{
    SharedPtr<Node> _node(node);
    if(!nodes_.Contains(_node))
        return;

    nodes_.Remove(_node);

    if (quiet)
        return;

    VariantMap eventData;
    eventData[SceneNodeSelected::P_SCENE] = scene_;
    eventData[SceneNodeSelected::P_NODE] = node;
    eventData[SceneNodeSelected::P_SELECTED] = false;
    scene_->SendEvent(E_SCENENODESELECTED, eventData);

}

void SceneSelection::Clear()
{
    Vector<SharedPtr<Node>> nodes = nodes_;

    for (unsigned i = 0; i < nodes.Size(); i++)
    {
        RemoveNode(nodes[i]);
    }

}

void SceneSelection::Paste()
{

    if (!clipBoardNodes_.Size())
        return;

    Vector<SharedPtr<Node>> newClipBoardNodes;

    Node* parent = scene_;

    if (nodes_.Size() >= 1)
        parent = nodes_[0]->GetParent();

    if (!parent)
        parent = scene_;

    Clear();

    VariantMap eventData;
    eventData[SceneEditAddRemoveNodes::P_END] = false;
    scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);

    for (unsigned i = 0; i < clipBoardNodes_.Size(); i++)
    {
        // Nodes must have a parent to clone, so first parent
        Node* clipNode = clipBoardNodes_[i];

        Matrix3x4 transform = clipNode->GetWorldTransform();

        clipNode->SetWorldTransform(transform.Translation(), transform.Rotation(), transform.Scale());
        parent->AddChild(clipNode);

        // clone
        newClipBoardNodes.Push(SharedPtr<Node>(clipNode->Clone()));
        // remove from parent
        newClipBoardNodes.Back()->Remove();
        newClipBoardNodes.Back()->SetWorldTransform(transform.Translation(), transform.Rotation(), transform.Scale());

        // generate scene edit event
        VariantMap nodeAddedEventData;
        nodeAddedEventData[SceneEditNodeAdded::P_NODE] = clipNode;
        nodeAddedEventData[SceneEditNodeAdded::P_PARENT] = parent;
        nodeAddedEventData[SceneEditNodeAdded::P_SCENE] = scene_;
        scene_->SendEvent(E_SCENEEDITNODEADDED, nodeAddedEventData);
    }

    eventData[SceneEditAddRemoveNodes::P_END] = true;
    scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);

    for (unsigned i = 0; i < clipBoardNodes_.Size(); i++)
    {
        AddNode(clipBoardNodes_[i], false);
    }

    clipBoardNodes_ = newClipBoardNodes;

}

void SceneSelection::Copy()
{
    clipBoardNodes_.Clear();

    for (unsigned i = 0; i < nodes_.Size(); i++)
    {
        Node* node = nodes_[i];

        if (!node->GetParent())
        {
            clipBoardNodes_.Clear();
            LOGERROR("SceneSelection::Copy - unable to copy node to clipboard (no parent)");
            return;
        }

        for (unsigned j = 0; j < nodes_.Size(); j++)
        {
            if ( i == j )
                continue;

            PODVector<Node*> children;
            nodes_[j]->GetChildren(children, true);
            if (children.Contains(node))
            {
                node = 0;
                break;
            }

        }

        if (node)
        {
            SharedPtr<Node> clipNode(node->Clone());
            clipNode->Remove();
            clipBoardNodes_.Push(clipNode);
        }

    }
}

void SceneSelection::Delete()
{

    Vector<SharedPtr<Node>> nodes = nodes_;

    Clear();

    VariantMap eventData;
    eventData[SceneEditAddRemoveNodes::P_END] = false;
    scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);

    for (unsigned i = 0; i < nodes.Size(); i++)
    {
        // generate scene edit event
        VariantMap nodeRemovedEventData;
        nodeRemovedEventData[SceneEditNodeAdded::P_NODE] = nodes[i];
        nodeRemovedEventData[SceneEditNodeAdded::P_PARENT] = nodes[i]->GetParent();
        nodeRemovedEventData[SceneEditNodeAdded::P_SCENE] = scene_;
        scene_->SendEvent(E_SCENEEDITNODEREMOVED, nodeRemovedEventData);

        nodes[i]->Remove();

    }

    eventData[SceneEditAddRemoveNodes::P_END] = true;
    scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);

}

void SceneSelection::GetBounds(BoundingBox& bbox)
{

    bbox.Clear();

    if (!nodes_.Size())
        return;

    // Get all the drawables, which define the bounding box of the selection
    PODVector<Drawable*> drawables;

    for (unsigned i = 0; i < nodes_.Size(); i++)
    {
        Node* node = nodes_[i];
        node->GetDerivedComponents<Drawable>(drawables, true, false);
    }

    if (!drawables.Size())
        return;

    // Calculate the combined bounding box of all drawables
    for (unsigned i = 0; i < drawables.Size(); i++  )
    {
        Drawable* drawable = drawables[i];
        bbox.Merge(drawable->GetWorldBoundingBox());
    }

}

void SceneSelection::DrawNodeDebug(Node* node, DebugRenderer* debug, bool drawNode)
{
    if (drawNode)
        debug->AddNode(node, 1.0, false);

    // Exception for the scene to avoid bringing the editor to its knees: drawing either the whole hierarchy or the subsystem-
    // components can have a large performance hit. Also do not draw terrain child nodes due to their large amount
    // (TerrainPatch component itself draws nothing as debug geometry)
    if (node != scene_ && !node->GetComponent<Terrain>())
    {
        const Vector<SharedPtr<Component> >& components = node->GetComponents();

        for (unsigned j = 0; j < components.Size(); ++j)
            components[j]->DrawDebugGeometry(debug, false);

        // To avoid cluttering the view, do not draw the node axes for child nodes
        for (unsigned k = 0; k < node->GetNumChildren(); ++k)
            DrawNodeDebug(node->GetChild(k), debug, false);
    }
}

void SceneSelection::HandleNodeRemoved(StringHash eventType, VariantMap& eventData)
{
    Node* node = (Node*) (eventData[NodeRemoved::P_NODE].GetPtr());
    RemoveNode(node, true);
}

void SceneSelection::HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData)
{

    if (!nodes_.Size())
        return;

    // Visualize the currently selected nodes
    DebugRenderer* debugRenderer = sceneEditor3D_->GetSceneView3D()->GetDebugRenderer();

    for (unsigned i = 0; i < nodes_.Size(); i++)
    {
        DrawNodeDebug(nodes_[i], debugRenderer);
    }

}

}
<|endoftext|>


<commit_before>#ifndef Ancona_Engine_Core_Systems_Collision_CollisionSystem_H_
#define Ancona_Engine_Core_Systems_Collision_CollisionSystem_H_

#include <vector>
#include <functional>

#include <Ancona/Engine/EntityFramework/UnorderedSystem.hpp>
#include <Ancona/Engine/Core/Systems/Physics/BasePhysicsSystem.hpp>
#include <Ancona/Util/Data.hpp>

#include "CollisionComponent.hpp"

namespace ild
{

/**
 * @brief Function signature used by the collision system.
 */
typedef std::function<void(const Entity&,const Entity&)> CollisionCallback;

/**
 * @brief System used to provide collision interactions and callbacks for entities.
 * @author Jeff Swenson
 */
class CollisionSystem : public UnorderedSystem<CollisionComponent>
{
    public:
        /**
         * @brief Construct a collision system and register it with the manager.
         *
         * @param name The systems name used for loading.
         * @param manager Manager that the system belongs to.
         * @param positions System that defines the position of an entity.
         */
        CollisionSystem(const std::string & name, SystemManager & manager, BasePhysicsSystem & positions);

        /**
         * @brief Update the position for all components based off of their velocity
         *
         * @param delta Number of ms since last update
         */
        void Update(float delta);

        /**
         * @brief Create and attach a collision component for the entity.
         *
         * @param entity Entity that the component is attached to.
         * @param dim Dimension for the entity to be used for collision.
         * @param type The collision type of the entity.
         * @param bodyType The body type of the entity.  Determines how collision fixing
         *  is handled for it. Defaults to BodyType::None.
         *
         * @return A pointer to the component.
         */
        CollisionComponent * CreateComponent(const Entity & entity,
                const sf::Vector3f & dim,
                CollisionType type,
                BodyTypeEnum bodyType = BodyType::None);

        /**
         * @brief Create a Type that can be assigned to a component.
         *
         * @param key describing the collision type.
         *
         * @return A unique Collision Type.
         */
        CollisionType CreateType(const std::string & key);

        /**
         * @brief Get the collision type associated with the key.
         */
        CollisionType GetType(const std::string & key);

        /**
         * @brief Define the handler that will be used for the collisions between the two types.
         *
         * @param typeA One type involved in the collision.
         * @param typeB The second type involved in the collision.
         * @param callback The callback will be called as callback(entityA, entityB) where
         *  entityA is an entity of the first type and entityB is an entity of second type.
         */
        void DefineCollisionCallback(CollisionType typeA, CollisionType typeB, CollisionCallback callback);

        /**
         * @brief Determine if the collision type has already been created.
         *
         * @param key Key that was used to create the collision type.
         *
         * @return True if the collision type is defined.  False otherwise.
         */
        bool IsCollisionTypeDefined(std::string const &key);

        /* Getters and Setters */
        BasePhysicsSystem & GetPhysics() { return _positions; }
        void SetMaxSlope(float value) { _maxSlope = value; }
    private:
        int _nextType;
        Table<CollisionCallback> _callbackTable;
        BasePhysicsSystem & _positions;
        std::unordered_map<std::string,CollisionType> _collisionTypes;
        Point _leftGravityBound;
        Point _rightGravityBound;
        float _maxSlope = 45;

        bool UniqueCollision(const Entity & entityA, const Entity & entityB);
        void HandleCollision(
                EntityComponentPair &pairA,
                EntityComponentPair &pairB,
                const Point &fixNormal,
                float fixMagnitude);
        bool EntitiesOverlapping(float fixMagnitude);

        void UpdateGravityBounds();
        void FixCollision(CollisionComponent * a, CollisionComponent * b, const Point & fixNormal, float fixMagnitude);
        bool IsOnGround(const Point & groundNormal);

        void PushApart(CollisionComponent * a, CollisionComponent * b, const Point & correctFix);
        void PushFirstOutOfSecond(CollisionComponent * a, CollisionComponent * b, const Point & correctFix);

};

}
#endif
<commit_msg>CollisionSystem.hpp header order fixed<commit_after>#ifndef Ancona_Engine_Core_Systems_Collision_CollisionSystem_H_
#define Ancona_Engine_Core_Systems_Collision_CollisionSystem_H_

#include <functional>
#include <vector>

#include <Ancona/Engine/Core/Systems/Physics/BasePhysicsSystem.hpp>
#include <Ancona/Engine/EntityFramework/UnorderedSystem.hpp>
#include <Ancona/Util/Data.hpp>

#include "CollisionComponent.hpp"

namespace ild
{

/**
 * @brief Function signature used by the collision system.
 */
typedef std::function<void(const Entity&,const Entity&)> CollisionCallback;

/**
 * @brief System used to provide collision interactions and callbacks for entities.
 * @author Jeff Swenson
 */
class CollisionSystem : public UnorderedSystem<CollisionComponent>
{
    public:
        /**
         * @brief Construct a collision system and register it with the manager.
         *
         * @param name The systems name used for loading.
         * @param manager Manager that the system belongs to.
         * @param positions System that defines the position of an entity.
         */
        CollisionSystem(const std::string & name, SystemManager & manager, BasePhysicsSystem & positions);

        /**
         * @brief Update the position for all components based off of their velocity
         *
         * @param delta Number of ms since last update
         */
        void Update(float delta);

        /**
         * @brief Create and attach a collision component for the entity.
         *
         * @param entity Entity that the component is attached to.
         * @param dim Dimension for the entity to be used for collision.
         * @param type The collision type of the entity.
         * @param bodyType The body type of the entity.  Determines how collision fixing
         *  is handled for it. Defaults to BodyType::None.
         *
         * @return A pointer to the component.
         */
        CollisionComponent * CreateComponent(const Entity & entity,
                const sf::Vector3f & dim,
                CollisionType type,
                BodyTypeEnum bodyType = BodyType::None);

        /**
         * @brief Create a Type that can be assigned to a component.
         *
         * @param key describing the collision type.
         *
         * @return A unique Collision Type.
         */
        CollisionType CreateType(const std::string & key);

        /**
         * @brief Get the collision type associated with the key.
         */
        CollisionType GetType(const std::string & key);

        /**
         * @brief Define the handler that will be used for the collisions between the two types.
         *
         * @param typeA One type involved in the collision.
         * @param typeB The second type involved in the collision.
         * @param callback The callback will be called as callback(entityA, entityB) where
         *  entityA is an entity of the first type and entityB is an entity of second type.
         */
        void DefineCollisionCallback(CollisionType typeA, CollisionType typeB, CollisionCallback callback);

        /**
         * @brief Determine if the collision type has already been created.
         *
         * @param key Key that was used to create the collision type.
         *
         * @return True if the collision type is defined.  False otherwise.
         */
        bool IsCollisionTypeDefined(std::string const &key);

        /* Getters and Setters */
        BasePhysicsSystem & GetPhysics() { return _positions; }
        void SetMaxSlope(float value) { _maxSlope = value; }
    private:
        int _nextType;
        Table<CollisionCallback> _callbackTable;
        BasePhysicsSystem & _positions;
        std::unordered_map<std::string,CollisionType> _collisionTypes;
        Point _leftGravityBound;
        Point _rightGravityBound;
        float _maxSlope = 45;

        bool UniqueCollision(const Entity & entityA, const Entity & entityB);
        void HandleCollision(
                EntityComponentPair &pairA,
                EntityComponentPair &pairB,
                const Point &fixNormal,
                float fixMagnitude);
        bool EntitiesOverlapping(float fixMagnitude);

        void UpdateGravityBounds();
        void FixCollision(CollisionComponent * a, CollisionComponent * b, const Point & fixNormal, float fixMagnitude);
        bool IsOnGround(const Point & groundNormal);

        void PushApart(CollisionComponent * a, CollisionComponent * b, const Point & correctFix);
        void PushFirstOutOfSecond(CollisionComponent * a, CollisionComponent * b, const Point & correctFix);

};

}
#endif
<|endoftext|>


<commit_before>/*
    Persons Model
    Copyright (C) 2012  Aleix Pol Gonzalez <aleixpol@blue-systems.com>

    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 Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "duplicatesfinder.h"
#include "persons-model.h"
#include <QDebug>

DuplicatesFinder::DuplicatesFinder(PersonsModel* model, QObject* parent)
    : KJob(parent)
    , m_model(model)
{
    m_compareRoles << PersonsModel::NameRole << PersonsModel::EmailRole << PersonsModel::NickRole << PersonsModel::PhoneRole << PersonsModel::IMRole;
}

void DuplicatesFinder::start()
{
    QMetaObject::invokeMethod(this, "doSearch", Qt::QueuedConnection);
}

//TODO: start providing partial results so that we can start processing matches while it's not done
void DuplicatesFinder::doSearch()
{
    //NOTE: This can probably optimized. I'm just trying to get the semantics right at the moment
    //maybe using nepomuk for the matching would help?

    QVector< QVariantList > collectedValues;
    m_matches.clear();

    int count = m_model->rowCount();
    for(int i=0; i<count; i++) {
        QModelIndex idx = m_model->index(i, 0);

        //we gather the values
        QVariantList values;
        for(int role=0; role<m_compareRoles.size(); role++) {
            values += idx.data(m_compareRoles[role]);
        }
        Q_ASSERT(values.size()==m_compareRoles.size());

        //we check if it matches
        int j=0;
        foreach(const QVariantList& valueToCompare, collectedValues) {
            QList< int > matchedRoles = matchAt(values, valueToCompare);
            if(!matchedRoles.isEmpty())
                m_matches.append(Match(matchedRoles, i, j));
            j++;
        }

        //we add our data for comparing later
        collectedValues.append(values);
    }
    emitResult();
}

QList<int> DuplicatesFinder::matchAt(const QVariantList& value, const QVariantList& toCompare) const
{
    QList<int> ret;
    Q_ASSERT(value.size()==toCompare.size());
    for(int i=0; i<toCompare.size(); i++) {
        if(!value[i].isNull() && value[i]==toCompare[i])
            ret += m_compareRoles[i];
    }
    return ret;
}

QList< Match > DuplicatesFinder::results() const
{
    return m_matches;
}
<commit_msg>Improve duplicates lookup<commit_after>/*
    Persons Model
    Copyright (C) 2012  Aleix Pol Gonzalez <aleixpol@blue-systems.com>

    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 Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "duplicatesfinder.h"
#include "persons-model.h"
#include <QDebug>

DuplicatesFinder::DuplicatesFinder(PersonsModel* model, QObject* parent)
    : KJob(parent)
    , m_model(model)
{
    m_compareRoles << PersonsModel::NameRole << PersonsModel::EmailRole << PersonsModel::NickRole << PersonsModel::PhoneRole << PersonsModel::IMRole;
}

void DuplicatesFinder::start()
{
    QMetaObject::invokeMethod(this, "doSearch", Qt::QueuedConnection);
}

//TODO: start providing partial results so that we can start processing matches while it's not done
void DuplicatesFinder::doSearch()
{
    //NOTE: This can probably optimized. I'm just trying to get the semantics right at the moment
    //maybe using nepomuk for the matching would help?

    QVector< QVariantList > collectedValues;
    m_matches.clear();

    int count = m_model->rowCount();
    for(int i=0; i<count; i++) {
        QModelIndex idx = m_model->index(i, 0);

        //we gather the values
        QVariantList values;
        for(int role=0; role<m_compareRoles.size(); role++) {
            values += idx.data(m_compareRoles[role]);
        }
        Q_ASSERT(values.size()==m_compareRoles.size());

        //we check if it matches
        int j=0;
        foreach(const QVariantList& valueToCompare, collectedValues) {
            QList< int > matchedRoles = matchAt(values, valueToCompare);
            if(!matchedRoles.isEmpty())
                m_matches.append(Match(matchedRoles, i, j));
            j++;
        }

        //we add our data for comparing later
        collectedValues.append(values);
    }
    emitResult();
}

QList<int> DuplicatesFinder::matchAt(const QVariantList& value, const QVariantList& toCompare) const
{
    QList<int> ret;
    Q_ASSERT(value.size()==toCompare.size());
    for(int i=0; i<toCompare.size(); i++) {
        const QVariant& v = value[i];
        if(!v.isNull() && v==toCompare[i] && (v.type()!=QVariant::List || !v.toList().isEmpty())) {
            ret += m_compareRoles[i];
        }
    }
    return ret;
}

QList< Match > DuplicatesFinder::results() const
{
    return m_matches;
}
<|endoftext|>


<commit_before>#include "ros/ros.h"

#include "EventTriggerUtility.h"
#include "elderly_care_simulation/EventTrigger.h"
#include <queue>
#include <unistd.h> // sleep
#include "Scheduler.h"

using namespace elderly_care_simulation;

Scheduler scheduler;

Scheduler::Scheduler(){
    concurrentWeight = 0;
    allowNewEvents = true;
    stopRosInfoSpam = false;

    randomEventLimit[EVENT_TRIGGER_EVENT_TYPE_MORAL_SUPPORT] = false;
    randomEventLimit[EVENT_TRIGGER_EVENT_TYPE_ILL] = false;
    randomEventLimit[EVENT_TRIGGER_EVENT_TYPE_VERY_ILL] = false;
}

Scheduler::~Scheduler() {}

/**
 * Creates a Request EventTrigger message for requesting robot tasks.
 * @param eventType the event type for the message
 */
EventTrigger Scheduler::createEventRequestMsg(int eventType, int priority){
    EventTrigger msg;
    msg.msg_type = EVENT_TRIGGER_MSG_TYPE_REQUEST;
    msg.event_type = eventType;
    msg.event_priority = priority;
    msg.event_weight = getEventWeight(eventType);
    msg.result = EVENT_TRIGGER_RESULT_UNDEFINED;

    return msg;
}

/**
 * Clears the eventQueue.
 */
void Scheduler::clearEventQueue() {
    eventQueue = std::priority_queue<EventNode >();
}

/**
 * Reset all random event occurrence back to false.
 */
void Scheduler::resetRandomEventOccurrence() {

    for(std::map<int, bool >::iterator iter = randomEventLimit.begin(); iter != randomEventLimit.end(); ++iter) {
        randomEventLimit[iter->first] = false;
    }
}

void Scheduler::resetConcurrentWeight() {
    concurrentWeight = 0;
}

/**
 * Returns the current concurrent weight count
 */
int Scheduler::getConcurrentWeight() const {
    return concurrentWeight;
}

/**
 * Returns the current event queue size
 */
int Scheduler::getEventQueueSize() const {
    return eventQueue.size();
}

/**
 * Callback function to deal with external events
 */
void Scheduler::externalEventReceivedCallback(EventTrigger msg) {

    // Only allows random events to be added to event queue in the allowed
    // timeframe (between WAKE and SLEEP)
    if(!allowNewEvents) {
        ROS_INFO("Scheduler: Additional events are not allowed at this time.");
        return;
    }

    // If the incoming event is a random event
    if(randomEventLimit.count(msg.event_type) != 0) {

        // If it havent occured before, change the flag and continue
        if(randomEventLimit[msg.event_type] == false) {
            randomEventLimit[msg.event_type] = true;

        // If event occured before, then block it
        } else {
            ROS_INFO("Scheduler: [%s] cannot occur more than once per day.",
                eventTypeToString(msg.event_type));
            return;
        }
    }

    ROS_INFO("Scheduler: Enqueuing event: [%s] with priority [%s]",
             eventTypeToString(msg.event_type),
             priorityToString(msg.event_priority));

    eventQueue.push(EventNode(msg));
}

/**
 * Callback function to deal with events replied from service provider robots
 */
void Scheduler::eventTriggerCallback(EventTrigger msg) {

    if (msg.msg_type == EVENT_TRIGGER_MSG_TYPE_RESPONSE) {
        if(msg.result == EVENT_TRIGGER_RESULT_SUCCESS){

            if (msg.event_type == EVENT_TRIGGER_EVENT_TYPE_COOK) {
                ROS_INFO("Scheduler: [%s] done.", eventTypeToString(msg.event_type));

                EventTrigger eatMsg;
                eatMsg = createEventRequestMsg(EVENT_TRIGGER_EVENT_TYPE_EAT, EVENT_TRIGGER_PRIORITY_HIGH);
                ROS_INFO("Scheduler: Enqueuing event: [%s] with priority [%s]",
                          eventTypeToString(eatMsg.event_type),
                          priorityToString(eatMsg.event_priority));

                eventQueue.push(EventNode(eatMsg));
            }else{

                // ILL has a weight of 0, but still blocks all other events (taking up 2 slots)
                // Therefore need to -2 to concurrent weight to free the slot.
                if (msg.event_type == EVENT_TRIGGER_EVENT_TYPE_ILL ||
                    msg.event_type == EVENT_TRIGGER_EVENT_TYPE_VERY_ILL) {
                    concurrentWeight -= 2;
                }else {
                    concurrentWeight -= msg.event_weight;
                }

                ROS_INFO("Scheduler: [%s] done.", eventTypeToString(msg.event_type));
            }
        }
    }
}

/**
 * Populates daily scheduled tasks into the event queue.
 *
 * Daily Schedule will be queued in the following sequence:
 * NOTE: The timestamp is just for referencing purpose.
 *
 *  07:00   WAKE
 *  07:00   COOK ---> EAT
 *  07:00   MEDICATION
 *  08:00   EXERCISE
 *  09:00   SHOWER
 *  10:00   ENTERTAINMENT
 *
 *  12:00   COOK ---> EAT
 *  12:00   MEDICATION
 *  13:00   CONVERSATION
 *  14:00   FRIEND & RELATIVE
 *  16:00   ENTERTAINMENT
 *
 *  18:00   COOK ---> EAT
 *  18:00   MEDICATION
 *  19:00   COMPANIONSHIP
 *  20:00   SLEEP
 *
 *  PAUSE FOR 20 SEC
 *  CLEAR LIST & REPOPULATE DAILY TASKS
 *
 */
void Scheduler::populateDailyTasks() {

    int eventSequence[][2] = {

        // ======================================
        // =        COMMENTED OUT STUFF         =
        // ======================================

        // // Morning
        // { EVENT_TRIGGER_EVENT_TYPE_WAKE,            EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_COOK,            EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_MOVE_TO_KITCHEN, EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_MEDICATION,      EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_EXERCISE,        EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_SHOWER,          EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_MOVE_TO_BEDROOM, EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_COOK,            EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_ENTERTAINMENT,   EVENT_TRIGGER_PRIORITY_LOW },

        // // Noon
        // { EVENT_TRIGGER_EVENT_TYPE_MEDICATION,      EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_CONVERSATION,    EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_MOVE_TO_HALLWAY, EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_RELATIVE,        EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_FRIEND,          EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_COOK,            EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_ENTERTAINMENT,   EVENT_TRIGGER_PRIORITY_LOW },

        // // Evening
        // { EVENT_TRIGGER_EVENT_TYPE_MEDICATION,      EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_MOVE_TO_BEDROOM, EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_COMPANIONSHIP,   EVENT_TRIGGER_PRIORITY_LOW }
        // { EVENT_TRIGGER_EVENT_TYPE_SLEEP,           EVENT_TRIGGER_PRIORITY_VERY_LOW }
    };
    for(unsigned int i = 0; i < sizeof(eventSequence)/sizeof(*eventSequence); i++) {
        eventQueue.push(EventNode(createEventRequestMsg(eventSequence[i][0], eventSequence[i][1])));
    }
}

/**
 * Dequeues an event and publishes to the event_trigger topic.
 * Allows concurrent events to be triggered up to the limit
 * set in MAX_CONCURRENT_WEIGHT
 *
 * COOK event is not affected as it acts independently of the
 * Resident.
 */
void Scheduler::dequeueEvent() {

    if (eventQueue.size() < 1) {
        return;
    }

    EventTrigger msg;
    msg = eventQueue.top().getEventTriggerMessage();

    // Publish event if enough concurrent weight available
    if (concurrentWeight + msg.event_weight <= MAX_CONCURRENT_WEIGHT) {

        ROS_INFO("Scheduler: Publishing event: [%s]", eventTypeToString(msg.event_type));

        stopRosInfoSpam = false;
        switch(msg.event_type) {
            case EVENT_TRIGGER_EVENT_TYPE_SLEEP:
                allowNewEvents = true;

                concurrentWeight += msg.event_weight;
                eventTriggerPub.publish(msg);
                eventQueue.pop();

                break;

            case EVENT_TRIGGER_EVENT_TYPE_ILL:
                allowNewEvents = false;

                // ILL has a weight of 0, but still blocks all other events
                concurrentWeight += 2;
                eventTriggerPub.publish(msg);
                eventQueue.pop();

                eventQueue.push(EventNode(createEventRequestMsg(EVENT_TRIGGER_EVENT_TYPE_SLEEP,
                                                                EVENT_TRIGGER_PRIORITY_VERY_HIGH)));
                eventQueue.push(EventNode(createEventRequestMsg(EVENT_TRIGGER_EVENT_TYPE_WAKE,
                                                                EVENT_TRIGGER_PRIORITY_VERY_HIGH)));
                break;

            case EVENT_TRIGGER_EVENT_TYPE_VERY_ILL:
                allowNewEvents = false;

                // VERY_ILL has a weight of 0, but still blocks all other events
                concurrentWeight += 2;
                eventTriggerPub.publish(msg);
                eventQueue.pop();

                clearEventQueue();

                // Enqueue a SLEEP event with max priority so when resident comes back from
                // hospital it goes to sleep right away.
                // Since the queue is now empty after the SLEEP event, a new batch of daily
                // schedules will be repopulated automatically (in the main method).
                eventQueue.push(EventNode(createEventRequestMsg(EVENT_TRIGGER_EVENT_TYPE_SLEEP,
                                                                EVENT_TRIGGER_PRIORITY_VERY_HIGH)));
                break;

            default:
                if(msg.event_type == EVENT_TRIGGER_EVENT_TYPE_WAKE) {
                    allowNewEvents = true;
                }

                eventTriggerPub.publish(msg);
                concurrentWeight += msg.event_weight;
                eventQueue.pop();
                break;
        }

    } else {
        if(!stopRosInfoSpam){
            ROS_INFO("Scheduler: Pending event: [%s]",
                eventTypeToString(msg.event_type));
            stopRosInfoSpam = true;
        }
    }
}

void callEventTriggerCallback(EventTrigger msg) {
    scheduler.eventTriggerCallback(msg);
}

void callExternalEventReceivedCallback(EventTrigger msg) {
    scheduler.externalEventReceivedCallback(msg);
}

/**
 * Main
 */
int main(int argc, char **argv) {

    //You must call ros::init() first of all. ros::init() function needs to see argc and argv. The third argument is the name of the node
    ros::init(argc, argv, "Scheduler");

    //NodeHandle is the main access point to communicate with ros.
    ros::NodeHandle nodeHandle;

    scheduler = Scheduler();

    // advertise to event_trigger topic
    scheduler.eventTriggerPub = nodeHandle.advertise<EventTrigger>("event_trigger",1000, true);

    // subscribe to event_trigger topic
    scheduler.eventTriggerSub = nodeHandle.subscribe<EventTrigger>("event_trigger",1000, callEventTriggerCallback);
    scheduler.externalEventSub = nodeHandle.subscribe<EventTrigger>("external_event",1000, callExternalEventReceivedCallback);

    ros::Rate loop_rate(10);

    // populate queue with day's events

    scheduler.populateDailyTasks();

    //a count of howmany messages we have sent
    int count = 0;
    sleep(5);

    while (ros::ok()) {

        if(scheduler.getEventQueueSize() == 0 && scheduler.getConcurrentWeight() <= 0) {
            ROS_INFO("Day Ends....");
            sleep(10);
            scheduler.clearEventQueue();
            scheduler.resetConcurrentWeight();
            scheduler.resetRandomEventOccurrence();
            scheduler.populateDailyTasks();
            ROS_INFO("Day Starts....");
        }else {
            scheduler.dequeueEvent();
        }

        ros::spinOnce();
        loop_rate.sleep();
        ++count;
    }
    return 0;
}
<commit_msg>Resident now moves to hallway instead of kitchen when it wakes up.<commit_after>#include "ros/ros.h"

#include "EventTriggerUtility.h"
#include "elderly_care_simulation/EventTrigger.h"
#include <queue>
#include <unistd.h> // sleep
#include "Scheduler.h"

using namespace elderly_care_simulation;

Scheduler scheduler;

Scheduler::Scheduler(){
    concurrentWeight = 0;
    allowNewEvents = true;
    stopRosInfoSpam = false;

    randomEventLimit[EVENT_TRIGGER_EVENT_TYPE_MORAL_SUPPORT] = false;
    randomEventLimit[EVENT_TRIGGER_EVENT_TYPE_ILL] = false;
    randomEventLimit[EVENT_TRIGGER_EVENT_TYPE_VERY_ILL] = false;
}

Scheduler::~Scheduler() {}

/**
 * Creates a Request EventTrigger message for requesting robot tasks.
 * @param eventType the event type for the message
 */
EventTrigger Scheduler::createEventRequestMsg(int eventType, int priority){
    EventTrigger msg;
    msg.msg_type = EVENT_TRIGGER_MSG_TYPE_REQUEST;
    msg.event_type = eventType;
    msg.event_priority = priority;
    msg.event_weight = getEventWeight(eventType);
    msg.result = EVENT_TRIGGER_RESULT_UNDEFINED;

    return msg;
}

/**
 * Clears the eventQueue.
 */
void Scheduler::clearEventQueue() {
    eventQueue = std::priority_queue<EventNode >();
}

/**
 * Reset all random event occurrence back to false.
 */
void Scheduler::resetRandomEventOccurrence() {

    for(std::map<int, bool >::iterator iter = randomEventLimit.begin(); iter != randomEventLimit.end(); ++iter) {
        randomEventLimit[iter->first] = false;
    }
}

void Scheduler::resetConcurrentWeight() {
    concurrentWeight = 0;
}

/**
 * Returns the current concurrent weight count
 */
int Scheduler::getConcurrentWeight() const {
    return concurrentWeight;
}

/**
 * Returns the current event queue size
 */
int Scheduler::getEventQueueSize() const {
    return eventQueue.size();
}

/**
 * Callback function to deal with external events
 */
void Scheduler::externalEventReceivedCallback(EventTrigger msg) {

    // Only allows random events to be added to event queue in the allowed
    // timeframe (between WAKE and SLEEP)
    if(!allowNewEvents) {
        ROS_INFO("Scheduler: Additional events are not allowed at this time.");
        return;
    }

    // If the incoming event is a random event
    if(randomEventLimit.count(msg.event_type) != 0) {

        // If it havent occured before, change the flag and continue
        if(randomEventLimit[msg.event_type] == false) {
            randomEventLimit[msg.event_type] = true;

        // If event occured before, then block it
        } else {
            ROS_INFO("Scheduler: [%s] cannot occur more than once per day.",
                eventTypeToString(msg.event_type));
            return;
        }
    }

    ROS_INFO("Scheduler: Enqueuing event: [%s] with priority [%s]",
             eventTypeToString(msg.event_type),
             priorityToString(msg.event_priority));

    eventQueue.push(EventNode(msg));
}

/**
 * Callback function to deal with events replied from service provider robots
 */
void Scheduler::eventTriggerCallback(EventTrigger msg) {

    if (msg.msg_type == EVENT_TRIGGER_MSG_TYPE_RESPONSE) {
        if(msg.result == EVENT_TRIGGER_RESULT_SUCCESS){

            if (msg.event_type == EVENT_TRIGGER_EVENT_TYPE_COOK) {
                ROS_INFO("Scheduler: [%s] done.", eventTypeToString(msg.event_type));

                EventTrigger eatMsg;
                eatMsg = createEventRequestMsg(EVENT_TRIGGER_EVENT_TYPE_EAT, EVENT_TRIGGER_PRIORITY_HIGH);
                ROS_INFO("Scheduler: Enqueuing event: [%s] with priority [%s]",
                          eventTypeToString(eatMsg.event_type),
                          priorityToString(eatMsg.event_priority));

                eventQueue.push(EventNode(eatMsg));
            }else{

                // ILL has a weight of 0, but still blocks all other events (taking up 2 slots)
                // Therefore need to -2 to concurrent weight to free the slot.
                if (msg.event_type == EVENT_TRIGGER_EVENT_TYPE_ILL ||
                    msg.event_type == EVENT_TRIGGER_EVENT_TYPE_VERY_ILL) {
                    concurrentWeight -= 2;
                }else {
                    concurrentWeight -= msg.event_weight;
                }

                ROS_INFO("Scheduler: [%s] done.", eventTypeToString(msg.event_type));
            }
        }
    }
}

/**
 * Populates daily scheduled tasks into the event queue.
 *
 * Daily Schedule will be queued in the following sequence:
 * NOTE: The timestamp is just for referencing purpose.
 *
 *  07:00   WAKE
 *  07:00   COOK ---> EAT
 *  07:00   MEDICATION
 *  08:00   EXERCISE
 *  09:00   SHOWER
 *  10:00   ENTERTAINMENT
 *
 *  12:00   COOK ---> EAT
 *  12:00   MEDICATION
 *  13:00   CONVERSATION
 *  14:00   FRIEND & RELATIVE
 *  16:00   ENTERTAINMENT
 *
 *  18:00   COOK ---> EAT
 *  18:00   MEDICATION
 *  19:00   COMPANIONSHIP
 *  20:00   SLEEP
 *
 *  PAUSE FOR 20 SEC
 *  CLEAR LIST & REPOPULATE DAILY TASKS
 *
 */
void Scheduler::populateDailyTasks() {

    int eventSequence[][2] = {

        // ======================================
        // =        COMMENTED OUT STUFF         =
        // ======================================

        // // Morning
        // { EVENT_TRIGGER_EVENT_TYPE_WAKE,            EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_COOK,            EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_MOVE_TO_HALLWAY, EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_MEDICATION,      EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_EXERCISE,        EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_SHOWER,          EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_MOVE_TO_BEDROOM, EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_COOK,            EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_ENTERTAINMENT,   EVENT_TRIGGER_PRIORITY_LOW },

        // // Noon
        // { EVENT_TRIGGER_EVENT_TYPE_MEDICATION,      EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_CONVERSATION,    EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_MOVE_TO_HALLWAY, EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_RELATIVE,        EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_FRIEND,          EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_COOK,            EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_ENTERTAINMENT,   EVENT_TRIGGER_PRIORITY_LOW },

        // // Evening
        // { EVENT_TRIGGER_EVENT_TYPE_MEDICATION,      EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_MOVE_TO_BEDROOM, EVENT_TRIGGER_PRIORITY_LOW },
        // { EVENT_TRIGGER_EVENT_TYPE_COMPANIONSHIP,   EVENT_TRIGGER_PRIORITY_LOW }
        // { EVENT_TRIGGER_EVENT_TYPE_SLEEP,           EVENT_TRIGGER_PRIORITY_VERY_LOW }
    };
    for(unsigned int i = 0; i < sizeof(eventSequence)/sizeof(*eventSequence); i++) {
        eventQueue.push(EventNode(createEventRequestMsg(eventSequence[i][0], eventSequence[i][1])));
    }
}

/**
 * Dequeues an event and publishes to the event_trigger topic.
 * Allows concurrent events to be triggered up to the limit
 * set in MAX_CONCURRENT_WEIGHT
 *
 * COOK event is not affected as it acts independently of the
 * Resident.
 */
void Scheduler::dequeueEvent() {

    if (eventQueue.size() < 1) {
        return;
    }

    EventTrigger msg;
    msg = eventQueue.top().getEventTriggerMessage();

    // Publish event if enough concurrent weight available
    if (concurrentWeight + msg.event_weight <= MAX_CONCURRENT_WEIGHT) {

        ROS_INFO("Scheduler: Publishing event: [%s]", eventTypeToString(msg.event_type));

        stopRosInfoSpam = false;
        switch(msg.event_type) {
            case EVENT_TRIGGER_EVENT_TYPE_SLEEP:
                allowNewEvents = true;

                concurrentWeight += msg.event_weight;
                eventTriggerPub.publish(msg);
                eventQueue.pop();

                break;

            case EVENT_TRIGGER_EVENT_TYPE_ILL:
                allowNewEvents = false;

                // ILL has a weight of 0, but still blocks all other events
                concurrentWeight += 2;
                eventTriggerPub.publish(msg);
                eventQueue.pop();

                eventQueue.push(EventNode(createEventRequestMsg(EVENT_TRIGGER_EVENT_TYPE_SLEEP,
                                                                EVENT_TRIGGER_PRIORITY_VERY_HIGH)));
                eventQueue.push(EventNode(createEventRequestMsg(EVENT_TRIGGER_EVENT_TYPE_WAKE,
                                                                EVENT_TRIGGER_PRIORITY_VERY_HIGH)));
                break;

            case EVENT_TRIGGER_EVENT_TYPE_VERY_ILL:
                allowNewEvents = false;

                // VERY_ILL has a weight of 0, but still blocks all other events
                concurrentWeight += 2;
                eventTriggerPub.publish(msg);
                eventQueue.pop();

                clearEventQueue();

                // Enqueue a SLEEP event with max priority so when resident comes back from
                // hospital it goes to sleep right away.
                // Since the queue is now empty after the SLEEP event, a new batch of daily
                // schedules will be repopulated automatically (in the main method).
                eventQueue.push(EventNode(createEventRequestMsg(EVENT_TRIGGER_EVENT_TYPE_SLEEP,
                                                                EVENT_TRIGGER_PRIORITY_VERY_HIGH)));
                break;

            default:
                if(msg.event_type == EVENT_TRIGGER_EVENT_TYPE_WAKE) {
                    allowNewEvents = true;
                }

                eventTriggerPub.publish(msg);
                concurrentWeight += msg.event_weight;
                eventQueue.pop();
                break;
        }

    } else {
        if(!stopRosInfoSpam){
            ROS_INFO("Scheduler: Pending event: [%s]",
                eventTypeToString(msg.event_type));
            stopRosInfoSpam = true;
        }
    }
}

void callEventTriggerCallback(EventTrigger msg) {
    scheduler.eventTriggerCallback(msg);
}

void callExternalEventReceivedCallback(EventTrigger msg) {
    scheduler.externalEventReceivedCallback(msg);
}

/**
 * Main
 */
int main(int argc, char **argv) {

    //You must call ros::init() first of all. ros::init() function needs to see argc and argv. The third argument is the name of the node
    ros::init(argc, argv, "Scheduler");

    //NodeHandle is the main access point to communicate with ros.
    ros::NodeHandle nodeHandle;

    scheduler = Scheduler();

    // advertise to event_trigger topic
    scheduler.eventTriggerPub = nodeHandle.advertise<EventTrigger>("event_trigger",1000, true);

    // subscribe to event_trigger topic
    scheduler.eventTriggerSub = nodeHandle.subscribe<EventTrigger>("event_trigger",1000, callEventTriggerCallback);
    scheduler.externalEventSub = nodeHandle.subscribe<EventTrigger>("external_event",1000, callExternalEventReceivedCallback);

    ros::Rate loop_rate(10);

    // populate queue with day's events

    scheduler.populateDailyTasks();

    //a count of howmany messages we have sent
    int count = 0;
    sleep(5);

    while (ros::ok()) {

        if(scheduler.getEventQueueSize() == 0 && scheduler.getConcurrentWeight() <= 0) {
            ROS_INFO("Day Ends....");
            sleep(10);
            scheduler.clearEventQueue();
            scheduler.resetConcurrentWeight();
            scheduler.resetRandomEventOccurrence();
            scheduler.populateDailyTasks();
            ROS_INFO("Day Starts....");
        }else {
            scheduler.dequeueEvent();
        }

        ros::spinOnce();
        loop_rate.sleep();
        ++count;
    }
    return 0;
}
<|endoftext|>


<commit_before>#include <ellis/ellis_array_node.hpp>

#include <ellis/ellis_node.hpp>
#include <ellis/private/using.hpp>

namespace ellis {

ellis_array_node::~ellis_array_node()
{
  /* Do nothing; destruction is handled by ellis_node. */
}

ellis_node& ellis_array_node::operator[](size_t index)
{
  return m_node.m_blk->m_arr.operator[](index);
}

const ellis_node& ellis_array_node::operator[](size_t index) const
{
  return m_node.m_blk->m_arr.operator[](index);
}

void ellis_array_node::append(const ellis_node &node)
{
  m_node.m_blk->m_arr.push_back(node);
}

void ellis_array_node::append(ellis_node &&node)
{
  m_node.m_blk->m_arr.push_back(node);
}

void ellis_array_node::extend(const ellis_array_node &other)
{
  m_node.m_blk->m_arr.insert(
    m_node.m_blk->m_arr.cend(),
    other.m_node.m_blk->m_arr.cbegin(),
    other.m_node.m_blk->m_arr.cend());
}

void ellis_array_node::extend(ellis_array_node &&other)
{
  m_node.m_blk->m_arr.insert(
    m_node.m_blk->m_arr.end(),
    other.m_node.m_blk->m_arr.begin(),
    other.m_node.m_blk->m_arr.end());
}

void ellis_array_node::insert(size_t pos, const ellis_node &other)
{
  m_node.m_blk->m_arr.insert(m_node.m_blk->m_arr.cbegin() + pos, other);
}

void ellis_array_node::insert(size_t pos, ellis_node &&other)
{
  m_node.m_blk->m_arr.insert(m_node.m_blk->m_arr.begin() + pos, other);
}

void ellis_array_node::erase(size_t pos)
{
  m_node.m_blk->m_arr.erase(m_node.m_blk->m_arr.begin() + pos);
}

void ellis_array_node::reserve(size_t n)
{
  m_node.m_blk->m_arr.reserve(n);
}

void ellis_array_node::foreach(std::function<void(ellis_node &)> fn)
{
  for (ellis_node &node : m_node.m_blk->m_arr) {
    fn(node);
  }
}

void ellis_array_node::foreach(std::function<void(const ellis_node &)> fn) const
{
  for (const ellis_node &node : m_node.m_blk->m_arr) {
    fn(node);
  }
}

ellis_array_node ellis_array_node::filter(std::function<bool(const ellis_node &)> fn) const
{
  ellis_node res_node(ellis_type::ARRAY);
  /* TODO: add unsafe version of as_array and other functions and use it */
  ellis_array_node &res_arr = res_node.as_array();
  for (ellis_node &node : m_node.m_blk->m_arr) {
    if (fn(node)) {
      res_arr.append(node);
    }
  }

  /* TODO: is there a way to directly return res_arr? i shouldn't have to
   * re-call the function, but res_arr is indeed a local reference... */
  return res_node.as_array();
}

size_t ellis_array_node::length() const
{
  return m_node.m_blk->m_arr.size();
}

bool ellis_array_node::empty() const
{
  return m_node.m_blk->m_arr.empty();
}

void ellis_array_node::clear()
{
  m_node.m_blk->m_arr.clear();
}

}  /* namespace ellis */
<commit_msg>ellis_array_node: small consistency fix<commit_after>#include <ellis/ellis_array_node.hpp>

#include <ellis/ellis_node.hpp>
#include <ellis/private/using.hpp>

namespace ellis {

ellis_array_node::~ellis_array_node()
{
  /* Do nothing; destruction is handled by ellis_node. */
}

ellis_node& ellis_array_node::operator[](size_t index)
{
  return m_node.m_blk->m_arr[index];
}

const ellis_node& ellis_array_node::operator[](size_t index) const
{
  return m_node.m_blk->m_arr[index];
}

void ellis_array_node::append(const ellis_node &node)
{
  m_node.m_blk->m_arr.push_back(node);
}

void ellis_array_node::append(ellis_node &&node)
{
  m_node.m_blk->m_arr.push_back(node);
}

void ellis_array_node::extend(const ellis_array_node &other)
{
  m_node.m_blk->m_arr.insert(
    m_node.m_blk->m_arr.cend(),
    other.m_node.m_blk->m_arr.cbegin(),
    other.m_node.m_blk->m_arr.cend());
}

void ellis_array_node::extend(ellis_array_node &&other)
{
  m_node.m_blk->m_arr.insert(
    m_node.m_blk->m_arr.end(),
    other.m_node.m_blk->m_arr.begin(),
    other.m_node.m_blk->m_arr.end());
}

void ellis_array_node::insert(size_t pos, const ellis_node &other)
{
  m_node.m_blk->m_arr.insert(m_node.m_blk->m_arr.cbegin() + pos, other);
}

void ellis_array_node::insert(size_t pos, ellis_node &&other)
{
  m_node.m_blk->m_arr.insert(m_node.m_blk->m_arr.begin() + pos, other);
}

void ellis_array_node::erase(size_t pos)
{
  m_node.m_blk->m_arr.erase(m_node.m_blk->m_arr.begin() + pos);
}

void ellis_array_node::reserve(size_t n)
{
  m_node.m_blk->m_arr.reserve(n);
}

void ellis_array_node::foreach(std::function<void(ellis_node &)> fn)
{
  for (ellis_node &node : m_node.m_blk->m_arr) {
    fn(node);
  }
}

void ellis_array_node::foreach(std::function<void(const ellis_node &)> fn) const
{
  for (const ellis_node &node : m_node.m_blk->m_arr) {
    fn(node);
  }
}

ellis_array_node ellis_array_node::filter(std::function<bool(const ellis_node &)> fn) const
{
  ellis_node res_node(ellis_type::ARRAY);
  /* TODO: add unsafe version of as_array and other functions and use it */
  ellis_array_node &res_arr = res_node.as_array();
  for (ellis_node &node : m_node.m_blk->m_arr) {
    if (fn(node)) {
      res_arr.append(node);
    }
  }

  /* TODO: is there a way to directly return res_arr? i shouldn't have to
   * re-call the function, but res_arr is indeed a local reference... */
  return res_node.as_array();
}

size_t ellis_array_node::length() const
{
  return m_node.m_blk->m_arr.size();
}

bool ellis_array_node::empty() const
{
  return m_node.m_blk->m_arr.empty();
}

void ellis_array_node::clear()
{
  m_node.m_blk->m_arr.clear();
}

}  /* namespace ellis */
<|endoftext|>


<commit_before>#include "data-general.hpp"
#include "data-course.hpp"
#include "data-student.hpp"
using namespace std;

vector<Course> all_courses;
Student user;

void loadCourses() {
	ifstream infile("data/2012-13-s2-csv.csv");
	string str; // read in the header line
	getline(infile, str);
	while (infile.peek() != -1){
		Course incourse(infile);
		all_courses.push_back(incourse);
		cout << incourse << endl;
	}
}

void whatDidICallThisWith(int argc, const char *argv[]) {
	printf ("This program was called with \"%s\".\n",argv[0]);

	if (argc > 1)
		for (int count = 1; count < argc; count++)
			printf("argv[%d] = %s\n", count, argv[count]);
	else
		printf("The command had no other arguments.\n");
}

void welcome() {
	string name, yearS = "", yearE = "", majors;
	// cout << "Welcome!" << endl;
	// cout << "What is your name? ";
	// getline(cin, name);
	name = "Xandra Best";
	// cout << "What year do you graduate? ";
	// cin >> yearE;
	// cout << "What are your majors (ex. CSCI, ASIAN) ";
	// getline(cin, majors);
	majors = "CSCI, STAT, ASIAN";
	user = Student(name, yearS, yearE, majors);
}

void getCourses() {
	string courses;
	// cout << "What are some courses that you have taken? (ex. CSCI125, STAT 110)" << endl;
	// cout << "> ";
	// getline(cin, courses);
	courses = "CSCI 251, stat 110, THEAT398, writ211";
	user.addCourses(courses);
}

int main(int argc, const char *argv[]) {
	loadCourses();
	// cout << getCourse("STAT 10") << endl;
	// Course c("BIO 126");
	// cout << c << endl;
	welcome();
	getCourses();
	user.display();

	return 0;
}
<commit_msg>… and actually use it, too.<commit_after>#include "data-general.hpp"
#include "data-course.hpp"
#include "data-student.hpp"
using namespace std;

vector<Course> all_courses;
Student user;

void loadCourses() {
	ifstream infile("data/2012-13-s2-csv.csv");
	string str; // read in the header line
	getline(infile, str);
	while (infile.peek() != -1){
		Course incourse(infile);
		all_courses.push_back(incourse);
	}
	for (vector<Course>::iterator c = all_courses.begin(); c != all_courses.end(); ++c)
		c->displayMany();
}

void whatDidICallThisWith(int argc, const char *argv[]) {
	printf ("This program was called with \"%s\".\n",argv[0]);

	if (argc > 1)
		for (int count = 1; count < argc; count++)
			printf("argv[%d] = %s\n", count, argv[count]);
	else
		printf("The command had no other arguments.\n");
}

void welcome() {
	string name, yearS = "", yearE = "", majors;
	// cout << "Welcome!" << endl;
	// cout << "What is your name? ";
	// getline(cin, name);
	name = "Xandra Best";
	// cout << "What year do you graduate? ";
	// cin >> yearE;
	// cout << "What are your majors (ex. CSCI, ASIAN) ";
	// getline(cin, majors);
	majors = "CSCI, STAT, ASIAN";
	user = Student(name, yearS, yearE, majors);
}

void getCourses() {
	string courses;
	// cout << "What are some courses that you have taken? (ex. CSCI125, STAT 110)" << endl;
	// cout << "> ";
	// getline(cin, courses);
	courses = "CSCI 251, stat 110, THEAT398, writ211";
	user.addCourses(courses);
}

int main(int argc, const char *argv[]) {
	loadCourses();
	// cout << getCourse("STAT 10") << endl;
	// Course c("BIO 126");
	// cout << c << endl;
	welcome();
	getCourses();
	user.display();

	return 0;
}
<|endoftext|>