<commit_before>//ibnu.yahya@toroo.org
#include "fs.h"
#include <QDebug>

fs::fs(QObject *parent) :
    QObject(parent)
{

}

bool fs::fileRemove(const QString &path){
    QFile file(path);
    return file.remove();
}

bool fs::fileWrite(const QString &path, const QString &data){
    QFile file(path);
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)){
        QTextStream out(&file);
        out << data;
        return true;
    }
    else {
        return false;
    }
    file.close();
}

QString fs::fileRead(const QString &path){
    //QStringList fields;
    QFile file(path);
    if (file.open(QIODevice::ReadOnly | QIODevice::Text)){
        QTextStream out(&file);

        /*while(!out.atEnd()){
            fields.append(out.readLine());

        }*/
        QString data = out.readAll();
        /*foreach (const QString text, fields){
            qDebug() << text.toUtf8();
        }*/
        file.close();
        //return fields;
        return data;
    }
    else {
        qDebug()<< "Err : File not found";
        return "";
    }
}

QString fs::appPath(){
    return QApplication::applicationDirPath();
}

QString fs::homePath(){
    QString home = QDir::homePath();
    return home;
}

bool fs::dir(const QString &opt, const QString &path){
    QDir dir;
    if(opt == "create"){
        return dir.mkdir(path);
    }
    else if(opt == "remove"){
        return dir.rmdir(path);
    }
    else{
        return false;
    }
}

bool fs::isExist(const QString &path)
{
    return QFile::exists(path);
}

bool fs::isDirectory(const QString &path)
{
    return QFileInfo(path).isDir();
}

bool fs::isFile(const QString &path)
{
    return QFileInfo(path).isFile();
}

bool fs::isAbsolute(const QString &path)
{
   return QFileInfo(path).isAbsolute();
}

bool fs::isExecutable(const QString &path)
{
   return QFileInfo(path).isExecutable();
}

bool fs::isSymlink(const QString &path)
{
   return QFileInfo(path).isSymLink();
}

bool fs::isReadable(const QString &path)
{
   return QFileInfo(path).isReadable();
}

bool fs::isWritable(const QString &path)
{
   return QFileInfo(path).isWritable();
}

bool fs::copy(const QString &src, const QString &des){
    if(QFile::exists(des)){
        QFile::remove(des);
    }
    return QFile::copy(src,des);
}

QString fs::openFileDialog(){
    QFileDialog *fd = new QFileDialog;
    int result = fd->exec();
    if (result)
    {
        QString directory = fd->selectedFiles()[0];
        return directory;
    }
    else {
        return "";
    }
}

QString fs::openDirDialog(){
    QFileDialog *fd = new QFileDialog;
#ifdef Linux
    QTreeView *tree = fd->findChild <QTreeView*>();
    tree->setRootIsDecorated(true);
    tree->setItemsExpandable(true);
#endif
    fd->setFileMode(QFileDialog::Directory);
    fd->setOption(QFileDialog::ShowDirsOnly);
    fd->setViewMode(QFileDialog::Detail);
    int result = fd->exec();
    QString directory;
    if (result)
    {
        directory = fd->selectedFiles()[0];
        return directory;
    }
    else {
        return "";
    }
}

QString fs::saveFileDialog(){
    QFileDialog *fd = new QFileDialog;
    QString directory = fd->getSaveFileName();
    return directory;
}

QString fs::saveFileDialog(const QVariant &config){
    QVariantMap conf = json->jsonParser(config).toVariantMap();
    QString title = "Save File",
            path = this->homePath(),
            ext = "";
    if(conf["title"].toString() != ""){
        title = conf["title"].toString();
    }

    if(conf["path"].toString() != ""){
        path = conf["path"].toString();
    }

    if(conf["info"].toString() != ""){
        ext = conf["info"].toString();
    }

    QFileDialog *fd = new QFileDialog;
    QWidget *widget = new QWidget();
    QString directory = fd->getSaveFileName(widget, title,path,ext);
    return directory;
}

QStringList fs::list(const QString &path){
    QDirIterator dirIt(path,QDirIterator::Subdirectories);
    QStringList list;
    while (dirIt.hasNext()) {
        dirIt.next();
        list.push_front(dirIt.filePath());
    }
    return list;
}

QVariant fs::info(const QString &path){
    QVariantMap map;
    QFileInfo info(path);
    QVariant size = info.size();
    QVariant absoluteFilePath = info.absoluteFilePath();
    QVariant baseName = info.baseName();
    QVariant isSymlink = info.isSymLink();
    QVariant isAbsolute = info.isAbsolute();
    QVariant isBundle = info.isBundle();
    QVariant isDir = info.isDir();
    QVariant isExecutable = info.isExecutable();
    QVariant isFile = info.isFile();
    QVariant isHidden = info.isHidden();
    QVariant isReadable = info.isReadable();
    QVariant isRelative = info.isRelative();
    QVariant isRoot = info.isRoot();
    QVariant isWritable = info.isWritable();
    QVariant bundleName = info.bundleName();
    QVariant exists = info.exists();
    QVariant fileName = info.fileName();
    QVariant filePath = info.filePath();
    QVariant group = info.group();
    QVariant lastModified = info.lastModified();
    QVariant lastRead = info.lastRead();
    map.insert("size",size);
    map.insert("absoluteFilePath",absoluteFilePath);
    map.insert("baseName",baseName);
    map.insert("isSymlink",isSymlink);
    map.insert("isAbsolute",isAbsolute);
    map.insert("isBundle",isBundle);
    map.insert("isDir",isDir);
    map.insert("isExecutable",isExecutable);
    map.insert("isFile",isFile);
    map.insert("isHidden",isHidden);
    map.insert("isReadable",isReadable);
    map.insert("isRelative",isRelative);
    map.insert("isRoot",isRoot);
    map.insert("isWritable",isWritable);
    map.insert("filePath",filePath);
    map.insert("bundleName",bundleName);
    map.insert("exists",exists);
    map.insert("fileName",fileName);
    map.insert("group",group);
    map.insert("lastModified",lastModified);
    map.insert("lastRead",lastRead);
    QJsonDocument json_enc = QJsonDocument::fromVariant(map);
    return json_enc.toVariant();
}
<commit_msg>FIX: warning msg return type filewriter<commit_after>//ibnu.yahya@toroo.org
#include "fs.h"
#include <QDebug>

fs::fs(QObject *parent) :
    QObject(parent)
{

}

bool fs::fileRemove(const QString &path){
    QFile file(path);
    return file.remove();
}

bool fs::fileWrite(const QString &path, const QString &data){
    QFile file(path);
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)){
        QTextStream out(&file);
        out << data;
        file.close();
        return true;
    }
    else {
        return false;
    }
}

QString fs::fileRead(const QString &path){
    //QStringList fields;
    QFile file(path);
    if (file.open(QIODevice::ReadOnly | QIODevice::Text)){
        QTextStream out(&file);

        /*while(!out.atEnd()){
            fields.append(out.readLine());

        }*/
        QString data = out.readAll();
        /*foreach (const QString text, fields){
            qDebug() << text.toUtf8();
        }*/
        file.close();
        //return fields;
        return data;
    }
    else {
        qDebug()<< "Err : File not found";
        return "";
    }
}

QString fs::appPath(){
    return QApplication::applicationDirPath();
}

QString fs::homePath(){
    QString home = QDir::homePath();
    return home;
}

bool fs::dir(const QString &opt, const QString &path){
    QDir dir;
    if(opt == "create"){
        return dir.mkdir(path);
    }
    else if(opt == "remove"){
        return dir.rmdir(path);
    }
    else{
        return false;
    }
}

bool fs::isExist(const QString &path)
{
    return QFile::exists(path);
}

bool fs::isDirectory(const QString &path)
{
    return QFileInfo(path).isDir();
}

bool fs::isFile(const QString &path)
{
    return QFileInfo(path).isFile();
}

bool fs::isAbsolute(const QString &path)
{
   return QFileInfo(path).isAbsolute();
}

bool fs::isExecutable(const QString &path)
{
   return QFileInfo(path).isExecutable();
}

bool fs::isSymlink(const QString &path)
{
   return QFileInfo(path).isSymLink();
}

bool fs::isReadable(const QString &path)
{
   return QFileInfo(path).isReadable();
}

bool fs::isWritable(const QString &path)
{
   return QFileInfo(path).isWritable();
}

bool fs::copy(const QString &src, const QString &des){
    if(QFile::exists(des)){
        QFile::remove(des);
    }
    return QFile::copy(src,des);
}

QString fs::openFileDialog(){
    QFileDialog *fd = new QFileDialog;
    int result = fd->exec();
    if (result)
    {
        QString directory = fd->selectedFiles()[0];
        return directory;
    }
    else {
        return "";
    }
}

QString fs::openDirDialog(){
    QFileDialog *fd = new QFileDialog;
#ifdef Linux
    QTreeView *tree = fd->findChild <QTreeView*>();
    tree->setRootIsDecorated(true);
    tree->setItemsExpandable(true);
#endif
    fd->setFileMode(QFileDialog::Directory);
    fd->setOption(QFileDialog::ShowDirsOnly);
    fd->setViewMode(QFileDialog::Detail);
    int result = fd->exec();
    QString directory;
    if (result)
    {
        directory = fd->selectedFiles()[0];
        return directory;
    }
    else {
        return "";
    }
}

QString fs::saveFileDialog(){
    QFileDialog *fd = new QFileDialog;
    QString directory = fd->getSaveFileName();
    return directory;
}

QString fs::saveFileDialog(const QVariant &config){
    QVariantMap conf = json->jsonParser(config).toVariantMap();
    QString title = "Save File",
            path = this->homePath(),
            ext = "";
    if(conf["title"].toString() != ""){
        title = conf["title"].toString();
    }

    if(conf["path"].toString() != ""){
        path = conf["path"].toString();
    }

    if(conf["info"].toString() != ""){
        ext = conf["info"].toString();
    }

    QFileDialog *fd = new QFileDialog;
    QWidget *widget = new QWidget();
    QString directory = fd->getSaveFileName(widget, title,path,ext);
    return directory;
}

QStringList fs::list(const QString &path){
    QDirIterator dirIt(path,QDirIterator::Subdirectories);
    QStringList list;
    while (dirIt.hasNext()) {
        dirIt.next();
        list.push_front(dirIt.filePath());
    }
    return list;
}

QVariant fs::info(const QString &path){
    QVariantMap map;
    QFileInfo info(path);
    QVariant size = info.size();
    QVariant absoluteFilePath = info.absoluteFilePath();
    QVariant baseName = info.baseName();
    QVariant isSymlink = info.isSymLink();
    QVariant isAbsolute = info.isAbsolute();
    QVariant isBundle = info.isBundle();
    QVariant isDir = info.isDir();
    QVariant isExecutable = info.isExecutable();
    QVariant isFile = info.isFile();
    QVariant isHidden = info.isHidden();
    QVariant isReadable = info.isReadable();
    QVariant isRelative = info.isRelative();
    QVariant isRoot = info.isRoot();
    QVariant isWritable = info.isWritable();
    QVariant bundleName = info.bundleName();
    QVariant exists = info.exists();
    QVariant fileName = info.fileName();
    QVariant filePath = info.filePath();
    QVariant group = info.group();
    QVariant lastModified = info.lastModified();
    QVariant lastRead = info.lastRead();
    map.insert("size",size);
    map.insert("absoluteFilePath",absoluteFilePath);
    map.insert("baseName",baseName);
    map.insert("isSymlink",isSymlink);
    map.insert("isAbsolute",isAbsolute);
    map.insert("isBundle",isBundle);
    map.insert("isDir",isDir);
    map.insert("isExecutable",isExecutable);
    map.insert("isFile",isFile);
    map.insert("isHidden",isHidden);
    map.insert("isReadable",isReadable);
    map.insert("isRelative",isRelative);
    map.insert("isRoot",isRoot);
    map.insert("isWritable",isWritable);
    map.insert("filePath",filePath);
    map.insert("bundleName",bundleName);
    map.insert("exists",exists);
    map.insert("fileName",fileName);
    map.insert("group",group);
    map.insert("lastModified",lastModified);
    map.insert("lastRead",lastRead);
    QJsonDocument json_enc = QJsonDocument::fromVariant(map);
    return json_enc.toVariant();
}
<|endoftext|>


<commit_before><commit_msg>[editor] Fix asserts.<commit_after><|endoftext|>


<commit_before>//
// CMatrix/instance_method_equals.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2014 Rick Yang (rick68 at gmail dot com)
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

#ifndef EIGENJS_CMATRIX_INSTANCE_METHOD_EQUALS_HPP
#define EIGENJS_CMATRIX_INSTANCE_METHOD_EQUALS_HPP

namespace EigenJS {

EIGENJS_INSTANCE_METHOD(CMatrix, equals,
{
  NanScope();

  if (args.Length() == 1) {
    const T* const& obj = node::ObjectWrap::Unwrap<T>(args.This());
    const typename T::value_type& value = **obj;

    if (CMatrix::is_cmatrix(args[0])) {
      const CMatrix* const& rhs_obj =
          node::ObjectWrap::Unwrap<CMatrix>(args[0]->ToObject());
      const typename CMatrix::value_type& rhs_cmatrix = **rhs_obj;

      if (T::is_nonconformate_arguments(obj, rhs_obj)) {
        NanReturnUndefined();
      }

      NanReturnValue(NanNew<v8::Boolean>(value == rhs_cmatrix));
    } else if (CVector::is_cvector(args[0])) {
      const CVector* const& rhs_obj =
          node::ObjectWrap::Unwrap<CVector>(args[0]->ToObject());
      const typename CVector::value_type& rhs_cvector = **rhs_obj;

      if (T::is_nonconformate_arguments(obj, rhs_obj)) {
        NanReturnUndefined();
      }

      NanReturnValue(NanNew<v8::Boolean>(value == rhs_cvector));
    } else if (CRowVector::is_crowvector(args[0])) {
      const CRowVector* const& rhs_obj =
          node::ObjectWrap::Unwrap<CRowVector>(args[0]->ToObject());
      const typename CRowVector::value_type& rhs_crowvector = **rhs_obj;

      if (T::is_nonconformate_arguments(obj, rhs_obj)) {
        NanReturnUndefined();
      }

      NanReturnValue(NanNew<v8::Boolean>(value == rhs_crowvector));
    } else if (CMatrixBlock::is_cmatrixblock(args[0])) {
      const CMatrixBlock* const& rhs_obj =
          node::ObjectWrap::Unwrap<CMatrixBlock>(args[0]->ToObject());
      const typename CMatrixBlock::value_type& rhs_cmatrixblock = **rhs_obj;

      if (T::is_nonconformate_arguments(obj, rhs_obj)) {
        NanReturnUndefined();
      }

      NanReturnValue(NanNew<v8::Boolean>(value == rhs_cmatrixblock));
    }
  }

  EIGENJS_THROW_ERROR_INVALID_ARGUMENT()
  NanReturnUndefined();
})

}  // namespace EigenJS

#endif  // EIGENJS_CMATRIX_INSTANCE_METHOD_EQUALS_HPP
<commit_msg>src: supported CVectorBlock and CRowVectorBlock<commit_after>//
// CMatrix/instance_method_equals.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2014 Rick Yang (rick68 at gmail dot com)
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

#ifndef EIGENJS_CMATRIX_INSTANCE_METHOD_EQUALS_HPP
#define EIGENJS_CMATRIX_INSTANCE_METHOD_EQUALS_HPP

namespace EigenJS {

EIGENJS_INSTANCE_METHOD(CMatrix, equals,
{
  NanScope();

  if (args.Length() == 1) {
    const T* const& obj = node::ObjectWrap::Unwrap<T>(args.This());
    const typename T::value_type& value = **obj;

    if (CMatrix::is_cmatrix(args[0])) {
      const CMatrix* const& rhs_obj =
          node::ObjectWrap::Unwrap<CMatrix>(args[0]->ToObject());
      const typename CMatrix::value_type& rhs_cmatrix = **rhs_obj;

      if (T::is_nonconformate_arguments(obj, rhs_obj)) {
        NanReturnUndefined();
      }

      NanReturnValue(NanNew<v8::Boolean>(value == rhs_cmatrix));
    } else if (CVector::is_cvector(args[0])) {
      const CVector* const& rhs_obj =
          node::ObjectWrap::Unwrap<CVector>(args[0]->ToObject());
      const typename CVector::value_type& rhs_cvector = **rhs_obj;

      if (T::is_nonconformate_arguments(obj, rhs_obj)) {
        NanReturnUndefined();
      }

      NanReturnValue(NanNew<v8::Boolean>(value == rhs_cvector));
    } else if (CRowVector::is_crowvector(args[0])) {
      const CRowVector* const& rhs_obj =
          node::ObjectWrap::Unwrap<CRowVector>(args[0]->ToObject());
      const typename CRowVector::value_type& rhs_crowvector = **rhs_obj;

      if (T::is_nonconformate_arguments(obj, rhs_obj)) {
        NanReturnUndefined();
      }

      NanReturnValue(NanNew<v8::Boolean>(value == rhs_crowvector));
    } else if (CMatrixBlock::is_cmatrixblock(args[0])) {
      const CMatrixBlock* const& rhs_obj =
          node::ObjectWrap::Unwrap<CMatrixBlock>(args[0]->ToObject());
      const typename CMatrixBlock::value_type& rhs_cmatrixblock = **rhs_obj;

      if (T::is_nonconformate_arguments(obj, rhs_obj)) {
        NanReturnUndefined();
      }

      NanReturnValue(NanNew<v8::Boolean>(value == rhs_cmatrixblock));
    } else if (CVectorBlock::is_cvectorblock(args[0])) {
      const CVectorBlock* const& rhs_obj =
          node::ObjectWrap::Unwrap<CVectorBlock>(args[0]->ToObject());
      const typename CVectorBlock::value_type& rhs_cvectorblock = **rhs_obj;

      if (T::is_nonconformate_arguments(obj, rhs_obj)) {
        NanReturnUndefined();
      }

      NanReturnValue(NanNew<v8::Boolean>(value == rhs_cvectorblock));
    } else if (CRowVectorBlock::is_crowvectorblock(args[0])) {
      const CRowVectorBlock* const& rhs_obj =
          node::ObjectWrap::Unwrap<CRowVectorBlock>(args[0]->ToObject());
      const typename CRowVectorBlock::value_type& rhs_crowvectorblock =
          **rhs_obj;

      if (T::is_nonconformate_arguments(obj, rhs_obj)) {
        NanReturnUndefined();
      }

      NanReturnValue(NanNew<v8::Boolean>(value == rhs_crowvectorblock));
    }
  }

  EIGENJS_THROW_ERROR_INVALID_ARGUMENT()
  NanReturnUndefined();
})

}  // namespace EigenJS

#endif  // EIGENJS_CMATRIX_INSTANCE_METHOD_EQUALS_HPP
<|endoftext|>


<commit_before>
#ifndef __UTILS_H
#define __UTILS_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <math.h>

/**
 * @brief Flash size register address
 */
#define ID_FLASH_ADDRESS (0x1FFF7A22)

/**
 * @brief Device ID register address
 */
#define ID_DBGMCU_IDCODE (0xE0042000)

/**
 * "Returns" the device signature
 *
 * Possible returns:
 *    - 0x0413: STM32F405xx/07xx and STM32F415xx/17xx)
 *    - 0x0419: STM32F42xxx and STM32F43xxx
 *    - 0x0423: STM32F401xB/C
 *    - 0x0433: STM32F401xD/E
 *    - 0x0431: STM32F411xC/E
 *
 * Returned data is in 16-bit mode, but only bits 11:0 are valid, bits 15:12 are always 0.
 * Defined as macro
 */
#define STM_ID_GetSignature() ((*(uint16_t *)(ID_DBGMCU_IDCODE)) & 0x0FFF)

/**
 * "Returns" the device revision
 *
 * Revisions possible:
 *    - 0x1000: Revision A
 *    - 0x1001: Revision Z
 *    - 0x1003: Revision Y
 *    - 0x1007: Revision 1
 *    - 0x2001: Revision 3
 *
 * Returned data is in 16-bit mode.
 */
#define STM_ID_GetRevision() (*(uint16_t *)(ID_DBGMCU_IDCODE + 2))

/**
* "Returns" the Flash size
*
* Returned data is in 16-bit mode, returned value is flash size in kB (kilo bytes).
*/
#define STM_ID_GetFlashSize() (*(uint16_t *)(ID_FLASH_ADDRESS))

#ifdef M_PI
#undef M_PI
#endif
#define M_PI (3.14159265358979323846f)

#define MACRO_MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MACRO_MIN(x, y) (((x) < (y)) ? (x) : (y))

#define SQ(x) ((x) * (x))

static const float one_by_sqrt3 = 0.57735026919f;
static const float two_by_sqrt3 = 1.15470053838f;
static const float sqrt3_by_2 = 0.86602540378f;

// like fmodf, but always positive
static inline float fmodf_pos(float x, float y) {
    float out = fmodf(x, y);
    if (out < 0.0f)
        out += y;
    return out;
}

/**
 * @brief Similar to modulo operator, except that the output range is centered
 * around zero.
 * The returned value is always in the range [-pm_range, pm_range).
 */
static inline float wrap_pm(float x, float pm_range) {
    return fmodf_pos(x + pm_range, 2.0f * pm_range) - pm_range;
}

//beware of inserting large angles!
static inline float wrap_pm_pi(float theta) {
    return wrap_pm(theta, M_PI);
}

// Compute rising edge timings (0.0 - 1.0) as a function of alpha-beta
// as per the magnitude invariant clarke transform
// The magnitude of the alpha-beta vector may not be larger than sqrt(3)/2
// Returns 0 on success, and -1 if the input was out of range
int SVM(float alpha, float beta, float* tA, float* tB, float* tC);

float fast_atan2(float y, float x);
float horner_fma(float x, const float *coeffs, size_t count);
int mod(int dividend, int divisor);

uint32_t deadline_to_timeout(uint32_t deadline_ms);
uint32_t timeout_to_deadline(uint32_t timeout_ms);
int is_in_the_future(uint32_t time_ms);

uint32_t micros(void);
void delay_us(uint32_t us);

float our_arm_sin_f32(float x);
float our_arm_cos_f32(float x);

#ifdef __cplusplus
}
#endif

#endif  //__UTILS_H
<commit_msg>remove obsolete comment<commit_after>
#ifndef __UTILS_H
#define __UTILS_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <math.h>

/**
 * @brief Flash size register address
 */
#define ID_FLASH_ADDRESS (0x1FFF7A22)

/**
 * @brief Device ID register address
 */
#define ID_DBGMCU_IDCODE (0xE0042000)

/**
 * "Returns" the device signature
 *
 * Possible returns:
 *    - 0x0413: STM32F405xx/07xx and STM32F415xx/17xx)
 *    - 0x0419: STM32F42xxx and STM32F43xxx
 *    - 0x0423: STM32F401xB/C
 *    - 0x0433: STM32F401xD/E
 *    - 0x0431: STM32F411xC/E
 *
 * Returned data is in 16-bit mode, but only bits 11:0 are valid, bits 15:12 are always 0.
 * Defined as macro
 */
#define STM_ID_GetSignature() ((*(uint16_t *)(ID_DBGMCU_IDCODE)) & 0x0FFF)

/**
 * "Returns" the device revision
 *
 * Revisions possible:
 *    - 0x1000: Revision A
 *    - 0x1001: Revision Z
 *    - 0x1003: Revision Y
 *    - 0x1007: Revision 1
 *    - 0x2001: Revision 3
 *
 * Returned data is in 16-bit mode.
 */
#define STM_ID_GetRevision() (*(uint16_t *)(ID_DBGMCU_IDCODE + 2))

/**
* "Returns" the Flash size
*
* Returned data is in 16-bit mode, returned value is flash size in kB (kilo bytes).
*/
#define STM_ID_GetFlashSize() (*(uint16_t *)(ID_FLASH_ADDRESS))

#ifdef M_PI
#undef M_PI
#endif
#define M_PI (3.14159265358979323846f)

#define MACRO_MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MACRO_MIN(x, y) (((x) < (y)) ? (x) : (y))

#define SQ(x) ((x) * (x))

static const float one_by_sqrt3 = 0.57735026919f;
static const float two_by_sqrt3 = 1.15470053838f;
static const float sqrt3_by_2 = 0.86602540378f;

// like fmodf, but always positive
static inline float fmodf_pos(float x, float y) {
    float out = fmodf(x, y);
    if (out < 0.0f)
        out += y;
    return out;
}

/**
 * @brief Similar to modulo operator, except that the output range is centered
 * around zero.
 * The returned value is always in the range [-pm_range, pm_range).
 */
static inline float wrap_pm(float x, float pm_range) {
    return fmodf_pos(x + pm_range, 2.0f * pm_range) - pm_range;
}

static inline float wrap_pm_pi(float theta) {
    return wrap_pm(theta, M_PI);
}

// Compute rising edge timings (0.0 - 1.0) as a function of alpha-beta
// as per the magnitude invariant clarke transform
// The magnitude of the alpha-beta vector may not be larger than sqrt(3)/2
// Returns 0 on success, and -1 if the input was out of range
int SVM(float alpha, float beta, float* tA, float* tB, float* tC);

float fast_atan2(float y, float x);
float horner_fma(float x, const float *coeffs, size_t count);
int mod(int dividend, int divisor);

uint32_t deadline_to_timeout(uint32_t deadline_ms);
uint32_t timeout_to_deadline(uint32_t timeout_ms);
int is_in_the_future(uint32_t time_ms);

uint32_t micros(void);
void delay_us(uint32_t us);

float our_arm_sin_f32(float x);
float our_arm_cos_f32(float x);

#ifdef __cplusplus
}
#endif

#endif  //__UTILS_H
<|endoftext|>


<commit_before>using namespace std;

#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <locale>
#include <assert.h>

//Size of insult list
#define SIZE 246

struct s_insults{
	string insult;
	int pos;
	int strSize;
} insults[SIZE];

//Function declarations
void addInsults(s_insults insults[]);
void printInsults(s_insults insults[]);
string replaceInsults(string data, s_insults insults[] );

int main(){
	string data;

	cout<<"input> ";
		getline(cin,data);

	//Add the insults from the text file to
	//the array of structs
	addInsults(insults);

	//Prints insult list out for verification purposes
	//printInsults(insults);

	//Prints out words before replacing them
	cout<<"You input "<<data<<endl;

	//Replaces insults in test string
	data = replaceInsults(data, insults);

	//Verifies insults have been replaced
	cout<<"This is now "<<data<<endl;

	return 0;
}

/** @brief          Adds insults to struct array
 *
 *  @details        Grabs the insults from "insults.txt" and adds
 *                  them to the insults struct array
 *  @param insults  Array of struct s_insults
 */
void addInsults(s_insults insults[]){
	//Variables
	int x=0;
	string data;
	ifstream fin;

	//Opens file
    fin.open("insults.txt",ios::in);
    assert (!fin.fail( ));

	//Reads from the file until the end of file
    while ( !fin.eof( ) ){
		getline(fin,data);
        insults[x].insult = data;
		insults[x].pos = 0;
		insults[x].strSize = data.length();
		x++;
     }
	//Close the file
     fin.close( );
     assert(!fin.fail( ));
}

/** @brief          Prints out the insults in the struct array
 *
 *  @param insults  Array of struct s_insults
 */
void printInsults(s_insults insults[]){
	cout<<"The insults in the array are:"<<endl;
	for(int i=0;i<SIZE;i++)
		cout<<insults[i].insult<<endl;
}

/** @brief          Replaces words that are insults
 *
 *  @details        Compares words in the buffer with a predetermined
 *                  list of insults.
 *
 *  @param data     String of data that may contain insults
 *
 *  @param insults  Array of struct s_insults that contains the insults
 */
string replaceInsults(string data, s_insults insults[] ){
 	//Variables
	string temp, buffer, newData;	//Used to convert text in buff to lowercase
	locale loc;

	istringstream stream(data);

	while(stream>>buffer){
		//converts buffer to lower case to test for insults
		temp = buffer;
		for(int k=0; k<temp.length(); k++)
			temp[k] = tolower(temp[k],loc);
		temp = temp + "\r";

		for(int j=0; j<SIZE; j++){
			//Moves to next word if the two strings are of different length
			if(insults[j].strSize !=  temp.length() && (j+1) != SIZE )
				j++;
			if( temp.compare(insults[j].insult) == 0){
				buffer="*****";
				break;
			}
		}
		newData+=" "+buffer;
	}
	cout<<"New data is "<<newData<<endl;
	return newData;

/* 	for(int i=0; i<data.length(); i++){

		//Converts data to lowercase
		temp = data[i];
		for(int k=0; k<temp.length(); k++)
			temp[i] = tolower(temp[i],loc);
		temp = temp + "\r";
		//for loop for the insult list size
		for(int j=0; j<SIZE; j++){
			//Moves to next word if the two strings are of different length
			if(insults[j].strSize !=  temp.length() && (j+1) != SIZE )
				j++;
			if( temp.compare(insults[j].insult) == 0){
				data="*****";
				break; //break to move on to the next word in the buffer
			}

		}//end inner forloop
	}//end while  */
}

<commit_msg>Standalone Insult Filter<commit_after>using namespace std;

#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <locale>
#include <assert.h>

//Size of insult list
#define SIZE 246

struct s_insults{
	string insult;
	int pos;
	int strSize;
} insults[SIZE];

//Function declarations
void addInsults(s_insults insults[]);
void printInsults(s_insults insults[]);
string replaceInsults(string data, s_insults insults[] );
bool checkInsults (string data, s_insults[]);

int main(){
	string data;

	cout<<"input> ";
		getline(cin,data);

	//Add the insults from the text file to
	//the array of structs
	addInsults(insults);

	//Prints insult list out for verification purposes
	//printInsults(insults);

	//Prints out words before replacing them
	cout<<"You input "<<data<<endl;

	//Replaces insults in test string
	data = replaceInsults(data, insults);

	//Verifies insults have been replaced
	cout<<"This is now "<<data<<endl;

	return 0;
}

/** @brief          Adds insults to struct array
 *
 *  @details        Grabs the insults from "insults.txt" and adds
 *                  them to the insults struct array
 *  @param insults  Array of struct s_insults
 */
void addInsults(s_insults insults[]){
	//Variables
	int x=0;
	string data;
	ifstream fin;

	//Opens file
    fin.open("insults.txt",ios::in);
    assert (!fin.fail( ));

	//Reads from the file until the end of file
    while ( !fin.eof( ) ){
		getline(fin,data);
		for(int i=0;i<data.length()-1;i++)
			insults[x].insult += data[i];
		insults[x].pos = 0;
		insults[x].strSize = data.length() -1;
		x++;
     }
	//Close the file
     fin.close( );
     assert(!fin.fail( ));
}

/** @brief          Prints out the insults in the struct array
 *
 *  @param insults  Array of struct s_insults
 */
void printInsults(s_insults insults[]){
	cout<<"The insults in the array are:"<<endl;
	for(int i=0;i<SIZE;i++)
		cout<<insults[i].insult<<endl;
}

/** @brief          Replaces words that are insults
 *
 *  @details        Compares words in the buffer with a predetermined
 *                  list of insults.
 *
 *  @param data     String of data that may contain insults
 *
 *  @param insults  Array of struct s_insults that contains the insults
 */
string replaceInsults(string data, s_insults insults[] ){
 	//Variables
	string goodStr, compareStr, newData;
	locale loc;
	int counter=0;

	for(int i=0; i<data.length(); i++){
		//Checks to see if character is not a new line
		//character or white-space
		if(data[i]!=' ' || data[i]!='\0'
		|| data[i]!='\r'|| data[i]!='\n'){
			//Creates compareStr string character by character
			//and makes them lower-case to prevent filter bypass
			compareStr+=data[i];
			goodStr+=data[i];
			compareStr[counter] = tolower(compareStr[counter],loc);
			counter++;
			//Looks ahead for new line characters and
			//white-spaces to know that a word is complete
 			if(data[i+1]==' ' || data[i+1]=='\0'
			|| data[i+1]=='\r'|| data[i+1]=='\n'){
				//Runs if a word has been completed
				if(checkInsults(compareStr,insults)){
					//Replaces word and resets strings and counter
					compareStr="*****";
					newData+=compareStr;
					compareStr.clear();
					goodStr.clear();
					counter=0;
				}
				else{
					//Adds word to return string and resets strings and counter
					newData+=goodStr;
					compareStr.clear();
					goodStr.clear();
					counter=0;
				}
			}
		}
		//Adds white-spaces and new lines to return string
		if(data[i]==' ' || data[i]=='\0'
		|| data[i]=='\r'|| data[i]=='\n'){
			newData+=data[i];
		}
	}
	return newData;
}

bool checkInsults(string data, s_insults insults[]){
	cout<<"Word to be compared is "<<data<<endl;
	cout<<"Length of word is "<<data.length()<<endl;
	 for(int j=0; j<SIZE; j++){
		//Moves to next word if the two strings are of different length
		if(insults[j].strSize !=  data.length() && (j+1) != SIZE )
			j++;
		//Compares the two words and returns true if they match
		if( data.compare(insults[j].insult) == 0){
			return true;
		}
	}
	//If no insult has been found return false
	return false;
}<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/kernel/scheduler.C $                                      */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2010,2014              */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include <kernel/task.H>
#include <kernel/scheduler.H>
#include <kernel/taskmgr.H>
#include <kernel/cpu.H>
#include <kernel/cpumgr.H>
#include <kernel/console.H>
#include <kernel/timemgr.H>
#include <util/lockfree/atomic_construct.H>

void Scheduler::addTask(task_t* t)
{
    t->state = TASK_STATE_READY;

    if (t->cpu->idle_task != t)
    {
        // If task is pinned to this CPU, add to the per-CPU queue.
        if (0 != t->affinity_pinned)
        {
            // Allocate a per-CPU queue if this is the first pinning to CPU.
            Util::Lockfree::atomic_construct
                (reinterpret_cast<Runqueue_t**>(&t->cpu->scheduler_extra));

            // Insert into queue.
            static_cast<Runqueue_t*>(t->cpu->scheduler_extra)->insert(t);
        }
        // Not pinned, add to global run-queue.
        else
        {
            iv_taskList.insert(t);
        }
    }
}

void Scheduler::addTaskMasterCPU(task_t* t)
{
    t->state = TASK_STATE_READY;

    if (t->cpu->idle_task != t)
    {
        cpu_t* master = CpuManager::getMasterCPU();

        // Allocate a per-CPU queue if this is the first pinning to CPU.
        Util::Lockfree::atomic_construct(
                reinterpret_cast<Runqueue_t**>(&master->scheduler_extra));

        // Insert into queue.
        static_cast<Runqueue_t*>(master->scheduler_extra)->insert(t);

    }
}

void Scheduler::returnRunnable()
{
    this->addTask(TaskManager::getCurrentTask());
}

void Scheduler::setNextRunnable()
{
    task_t* t = NULL;
    cpu_t* cpu = CpuManager::getCurrentCPU();

    // Check for ready task in local run-queue, if it exists.
    if (NULL != cpu->scheduler_extra)
    {
        t = static_cast<Runqueue_t*>(cpu->scheduler_extra)->remove();
    }

    // Check for ready task in global run-queue.
    if (NULL == t)
    {
        t = iv_taskList.remove();
    }

    // Choose idle task if no other ready task is available.
    if (NULL == t)
    {
        t = cpu->idle_task;
        setDEC(TimeManager::getIdleTimeSliceCount());
    }
    else // Set normal timeslice to decrementer.
    {
        setDEC(TimeManager::getTimeSliceCount());
    }

    TaskManager::setCurrentTask(t);
}
<commit_msg>Optimize Hostboot scheduler setNextRunnable<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/kernel/scheduler.C $                                      */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2010,2022                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include <kernel/task.H>
#include <kernel/scheduler.H>
#include <kernel/taskmgr.H>
#include <kernel/cpu.H>
#include <kernel/cpumgr.H>
#include <kernel/console.H>
#include <kernel/timemgr.H>
#include <util/lockfree/atomic_construct.H>

void Scheduler::addTask(task_t* t)
{
    t->state = TASK_STATE_READY;

    if (t->cpu->idle_task != t)
    {
        // If task is pinned to this CPU, add to the per-CPU queue.
        if (0 != t->affinity_pinned)
        {
            // Allocate a per-CPU queue if this is the first pinning to CPU.
            Util::Lockfree::atomic_construct
                (reinterpret_cast<Runqueue_t**>(&t->cpu->scheduler_extra));

            // Insert into queue.
            static_cast<Runqueue_t*>(t->cpu->scheduler_extra)->insert(t);
        }
        // Not pinned, add to global run-queue.
        else
        {
            iv_taskList.insert(t);
        }
    }
}

void Scheduler::addTaskMasterCPU(task_t* t)
{
    t->state = TASK_STATE_READY;

    if (t->cpu->idle_task != t)
    {
        cpu_t* master = CpuManager::getMasterCPU();

        // Allocate a per-CPU queue if this is the first pinning to CPU.
        Util::Lockfree::atomic_construct(
                reinterpret_cast<Runqueue_t**>(&master->scheduler_extra));

        // Insert into queue.
        static_cast<Runqueue_t*>(master->scheduler_extra)->insert(t);

    }
}

void Scheduler::returnRunnable()
{
    this->addTask(TaskManager::getCurrentTask());
}

void Scheduler::setNextRunnable()
{
    task_t* t = NULL;
    cpu_t* cpu = CpuManager::getCurrentCPU();

    // Check for ready task in local run-queue, if it exists.
    if (NULL != cpu->scheduler_extra)
    {
        t = static_cast<Runqueue_t*>(cpu->scheduler_extra)->remove();
    }

    // Check for ready task in global run-queue.  Only try the remove
    // if there is something in the queue to prevent excessive lock
    // contention
    if ((NULL == t) && iv_taskList.size())
    {
        t = iv_taskList.remove();
    }

    // Choose idle task if no other ready task is available.
    if (NULL == t)
    {
        t = cpu->idle_task;
        setDEC(TimeManager::getIdleTimeSliceCount());
    }
    else // Set normal timeslice to decrementer.
    {
        setDEC(TimeManager::getTimeSliceCount());
    }

    TaskManager::setCurrentTask(t);
}
<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2002 MandrakeSoft S.A.
//
//  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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

/////////////////////////////////////////////////////////////////////////
//
// Todo
//  . Currently supported only by x11. Check if other guis need mapping.
//  . Tables look-up should be optimised.
//

#include "bochs.h"

// Table of bocks "BX_KEY_*" symbols
// the table must be in BX_KEY_* order
char *bx_key_symbol[BX_KEY_NBKEYS] = {
  "BX_KEY_CTRL_L",         "BX_KEY_SHIFT_L",        "BX_KEY_F1",
  "BX_KEY_F2",             "BX_KEY_F3",             "BX_KEY_F4",
  "BX_KEY_F5",             "BX_KEY_F6",             "BX_KEY_F7",
  "BX_KEY_F8",             "BX_KEY_F9",             "BX_KEY_F10",
  "BX_KEY_F11",            "BX_KEY_F12",            "BX_KEY_CTRL_R",
  "BX_KEY_SHIFT_R",        "BX_KEY_CAPS_LOCK",      "BX_KEY_NUM_LOCK",
  "BX_KEY_ALT_L",          "BX_KEY_ALT_R",          "BX_KEY_A",
  "BX_KEY_B",              "BX_KEY_C",              "BX_KEY_D",
  "BX_KEY_E",              "BX_KEY_F",              "BX_KEY_G",
  "BX_KEY_H",              "BX_KEY_I",              "BX_KEY_J",
  "BX_KEY_K",              "BX_KEY_L",              "BX_KEY_M",
  "BX_KEY_N",              "BX_KEY_O",              "BX_KEY_P",
  "BX_KEY_Q",              "BX_KEY_R",              "BX_KEY_S",
  "BX_KEY_T",              "BX_KEY_U",              "BX_KEY_V",
  "BX_KEY_W",              "BX_KEY_X",              "BX_KEY_Y",
  "BX_KEY_Z",              "BX_KEY_0",              "BX_KEY_1",
  "BX_KEY_2",              "BX_KEY_3",              "BX_KEY_4",
  "BX_KEY_5",              "BX_KEY_6",              "BX_KEY_7",
  "BX_KEY_8",              "BX_KEY_9",              "BX_KEY_ESC",
  "BX_KEY_SPACE",          "BX_KEY_SINGLE_QUOTE",   "BX_KEY_COMMA",
  "BX_KEY_PERIOD",         "BX_KEY_SLASH",          "BX_KEY_SEMICOLON",
  "BX_KEY_EQUALS",         "BX_KEY_LEFT_BRACKET",   "BX_KEY_BACKSLASH",
  "BX_KEY_RIGHT_BRACKET",  "BX_KEY_MINUS",          "BX_KEY_GRAVE",
  "BX_KEY_BACKSPACE",      "BX_KEY_ENTER",          "BX_KEY_TAB",
  "BX_KEY_LEFT_BACKSLASH", "BX_KEY_PRINT",          "BX_KEY_SCRL_LOCK",
  "BX_KEY_PAUSE",          "BX_KEY_INSERT",         "BX_KEY_DELETE",
  "BX_KEY_HOME",           "BX_KEY_END",            "BX_KEY_PAGE_UP",
  "BX_KEY_PAGE_DOWN",      "BX_KEY_KP_ADD",         "BX_KEY_KP_SUBTRACT",
  "BX_KEY_KP_END",         "BX_KEY_KP_DOWN",        "BX_KEY_KP_PAGE_DOWN",
  "BX_KEY_KP_LEFT",        "BX_KEY_KP_RIGHT",       "BX_KEY_KP_HOME",
  "BX_KEY_KP_UP",          "BX_KEY_KP_PAGE_UP",     "BX_KEY_KP_INSERT",
  "BX_KEY_KP_DELETE",      "BX_KEY_KP_5",           "BX_KEY_UP",
  "BX_KEY_DOWN",           "BX_KEY_LEFT",           "BX_KEY_RIGHT",
  "BX_KEY_KP_ENTER",       "BX_KEY_KP_MULTIPLY",    "BX_KEY_KP_DIVIDE",
  "BX_KEY_WIN_L",          "BX_KEY_WIN_R",          "BX_KEY_MENU",
  "BX_KEY_ALT_SYSREQ",     "BX_KEY_CTRL_BREAK",     "BX_KEY_INT_BACK",
  "BX_KEY_INT_FORWARD",    "BX_KEY_INT_STOP",       "BX_KEY_INT_MAIL",
  "BX_KEY_INT_SEARCH",     "BX_KEY_INT_FAV",        "BX_KEY_INT_HOME",
  "BX_KEY_POWER_MYCOMP",   "BX_KEY_POWER_CALC",     "BX_KEY_POWER_SLEEP",
  "BX_KEY_POWER_POWER",    "BX_KEY_POWER_WAKE",
  };

bx_keymap_c bx_keymap;

#define LOG_THIS bx_keymap.

bx_keymap_c::bx_keymap_c(void)
{
    put("KMAP");

    keymapCount = 0;
    keymapTable = (BXKeyEntry *)NULL;

}

bx_keymap_c::~bx_keymap_c(void)
{
    if(keymapTable != NULL) {
      free(keymapTable);
      keymapTable = (BXKeyEntry *)NULL;
      }
    keymapCount = 0;
}

    void
bx_keymap_c::loadKeymap(Bit32u stringToSymbol(const char*))
{
  if(bx_options.keyboard.OuseMapping->get()) {
    loadKeymap(stringToSymbol,bx_options.keyboard.Okeymap->getptr());
    }
}

Boolean
bx_keymap_c::isKeymapLoaded ()
{
  return (keymapCount > 0);
}

///////////////////
// I'll add these to the keymap object in a minute.
static char *lineptr = NULL;
static int lineCount;

static void
init_parse ()
{
  lineCount = 0;
}

static void
init_parse_line (char *line_to_parse)
{
  // chop off newline
  lineptr = line_to_parse;
  char *nl;
  if( (nl = strchr(line_to_parse,'\n')) != NULL) {
    *nl = 0;
  }
}

static Bit32s
get_next_word (char *output)
{
  char *copyp = output;
  // find first nonspace
  while (*lineptr && isspace (*lineptr))
    lineptr++;
  if (!*lineptr)
    return -1;  // nothing but spaces until end of line
  if (*lineptr == '#')
    return -1;  // nothing but a comment
  // copy nonspaces into the output
  while (*lineptr && !isspace (*lineptr))
    *copyp++ = *lineptr++;
  *copyp=0;  // null terminate the copy
  // there must be at least one nonspace, since that's why we stopped the
  // first loop!
  BX_ASSERT (copyp != output);
  return 0;
}

static Bit32s
get_next_keymap_line (FILE *fp, char *bxsym, char *modsym, Bit32s *ascii, char *xwinsym)
{
  char line[256];
  char buf[256];
  line[0] = 0;
  while (1) {
    lineCount++;
    if (!fgets(line, sizeof(line)-1, fp)) return -1;  // EOF
    init_parse_line (line);
    if (get_next_word (bxsym) >= 0) {
      modsym[0] = 0;
      char *p;
      if ((p = strchr (bxsym, '+')) != NULL) {
	*p = 0;  // truncate bxsym.
	p++;  // move one char beyond the +
	strcpy (modsym, p);  // copy the rest to modsym
      }
      BX_ASSERT (get_next_word (buf) >= 0);
      if (buf[0] == '\'' && buf[2] == '\'' && buf[3]==0) {
	*ascii = (Bit32s) buf[1];
      } else if (!strcmp(buf, "space")) {
	*ascii = ' ';
      } else if (!strcmp(buf, "return")) {
	*ascii = '\n';
      } else if (!strcmp(buf, "tab")) {
	*ascii = '\t';
      } else if (!strcmp(buf, "backslash")) {
	*ascii = '\\';
      } else if (!strcmp(buf, "apostrophe")) {
	*ascii = '\'';
      } else if (!strcmp(buf, "none")) {
	*ascii = -1;
      } else {
	BX_PANIC (("keymap line %d: ascii equivalent is \"%s\" but it must be char constant like 'x', or one of space,tab,return,none", lineCount, buf));
      }
      BX_ASSERT (get_next_word (xwinsym) >= 0);
      return 0;
    }
    // no words on this line, keep reading.
  }
}

    void
bx_keymap_c::loadKeymap(Bit32u stringToSymbol(const char*), const char* filename)
{
    FILE   *keymapFile;
    char   line[256], c, *p;
    char baseSym[256], modSym[256], xwinSym[256];
    Bit32s ascii;
    Bit32u baseKey, modKey, xwinKey;

    if((keymapFile = fopen(filename,"r"))==NULL) {
      BX_PANIC(("Can not open keymap file '%s'.",filename));
      }

    BX_INFO(("Loading keymap from '%s'",filename));
    init_parse ();

    // Read keymap file one line at a time
    while(1) {
      if (get_next_keymap_line (keymapFile,
	    baseSym, modSym, &ascii, xwinSym) < 0) { break; }

      BX_DEBUG (("bxsym='%s', modSym='%s', ascii=%d, guisym='%s'", baseSym, modSym, ascii, xwinSym));

      // convert X_KEY_* symbols to values
      baseKey = convertStringToBXKey(baseSym);
      if (strncmp ("XK_", xwinSym, 3) != 0) {
	BX_PANIC (("keymap line %d: X windows symbol '%s' must start with XK_", lineCount, xwinSym));
      }
      modKey = convertStringToBXKey(modSym);
	  xwinKey = 0;
	  if (stringToSymbol != NULL)
        xwinKey = stringToSymbol(xwinSym + 3);  // skip over the "XK_"

      // Check if data is valid
      if( baseKey==BX_KEYMAP_UNKNOWN ) {
        BX_PANIC (("line %d: unknown BX_KEY constant '%s'",lineCount,baseSym));
        continue;
        }

      if( xwinKey==BX_KEYMAP_UNKNOWN ) {
        BX_PANIC (("line %d: unknown GUI constant '%s'",lineCount,xwinSym));
        continue;
        }

      keymapTable=(BXKeyEntry*)realloc(keymapTable,(keymapCount+1) * sizeof(BXKeyEntry));

      if(keymapTable==NULL)
        BX_PANIC(("Can not allocate memory for keymap table."));

      keymapTable[keymapCount].baseKey=baseKey;
      keymapTable[keymapCount].modKey=modKey;
      keymapTable[keymapCount].ascii=ascii;
      keymapTable[keymapCount].xwinKey=xwinKey;

      keymapCount++;
      }

    BX_INFO(("Loaded %d symbols",keymapCount));

    fclose(keymapFile);
}

    Bit32u
bx_keymap_c::convertStringToBXKey(const char* string)
{
    Bit16u i;

    // We look through the bx_key_symbol table to find the searched string
    for (i=0; i<BX_KEY_NBKEYS; i++) {
      if (strcmp(string,bx_key_symbol[i])==0) {
        return i;
        }
      }

    // Key is not known
    return BX_KEYMAP_UNKNOWN;
}

    BXKeyEntry *
bx_keymap_c::getKeyXwin(Bit32u key)
{
    Bit16u i;

    // We look through the keymap table to find the searched key
    for (i=0; i<keymapCount; i++) {
      if (keymapTable[i].xwinKey == key) {
	BX_DEBUG (("key 0x%02x matches xwinKey for entry #%d", key, i));
        return &keymapTable[i];
        }
      }
    BX_DEBUG (("key %02x matches no entries", key));

    // Return default
    return NULL;
}

    BXKeyEntry *
bx_keymap_c::getKeyASCII(Bit8u ch)
{
    Bit16u i;
    BX_DEBUG (("getKeyASCII (0x%02x)", ch));

    // We look through the keymap table to find the searched key
    for (i=0; i<keymapCount; i++) {
      if (keymapTable[i].ascii == ch) {
	BX_DEBUG (("key %02x matches ascii for entry #%d", ch, i));
        return &keymapTable[i];
        }
      }
    BX_DEBUG (("key 0x%02x matches no entries", ch));

    // Return default
    return NULL;
}

<commit_msg>- b_dolata@compfort.pl sent in this patch to fix a problem Christophe   described in bug [ #538214 ] directory as keymap file<commit_after>/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2002 MandrakeSoft S.A.
//
//  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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

/////////////////////////////////////////////////////////////////////////
//
// Todo
//  . Currently supported only by x11. Check if other guis need mapping.
//  . Tables look-up should be optimised.
//

#include "bochs.h"

// Table of bocks "BX_KEY_*" symbols
// the table must be in BX_KEY_* order
char *bx_key_symbol[BX_KEY_NBKEYS] = {
  "BX_KEY_CTRL_L",         "BX_KEY_SHIFT_L",        "BX_KEY_F1",
  "BX_KEY_F2",             "BX_KEY_F3",             "BX_KEY_F4",
  "BX_KEY_F5",             "BX_KEY_F6",             "BX_KEY_F7",
  "BX_KEY_F8",             "BX_KEY_F9",             "BX_KEY_F10",
  "BX_KEY_F11",            "BX_KEY_F12",            "BX_KEY_CTRL_R",
  "BX_KEY_SHIFT_R",        "BX_KEY_CAPS_LOCK",      "BX_KEY_NUM_LOCK",
  "BX_KEY_ALT_L",          "BX_KEY_ALT_R",          "BX_KEY_A",
  "BX_KEY_B",              "BX_KEY_C",              "BX_KEY_D",
  "BX_KEY_E",              "BX_KEY_F",              "BX_KEY_G",
  "BX_KEY_H",              "BX_KEY_I",              "BX_KEY_J",
  "BX_KEY_K",              "BX_KEY_L",              "BX_KEY_M",
  "BX_KEY_N",              "BX_KEY_O",              "BX_KEY_P",
  "BX_KEY_Q",              "BX_KEY_R",              "BX_KEY_S",
  "BX_KEY_T",              "BX_KEY_U",              "BX_KEY_V",
  "BX_KEY_W",              "BX_KEY_X",              "BX_KEY_Y",
  "BX_KEY_Z",              "BX_KEY_0",              "BX_KEY_1",
  "BX_KEY_2",              "BX_KEY_3",              "BX_KEY_4",
  "BX_KEY_5",              "BX_KEY_6",              "BX_KEY_7",
  "BX_KEY_8",              "BX_KEY_9",              "BX_KEY_ESC",
  "BX_KEY_SPACE",          "BX_KEY_SINGLE_QUOTE",   "BX_KEY_COMMA",
  "BX_KEY_PERIOD",         "BX_KEY_SLASH",          "BX_KEY_SEMICOLON",
  "BX_KEY_EQUALS",         "BX_KEY_LEFT_BRACKET",   "BX_KEY_BACKSLASH",
  "BX_KEY_RIGHT_BRACKET",  "BX_KEY_MINUS",          "BX_KEY_GRAVE",
  "BX_KEY_BACKSPACE",      "BX_KEY_ENTER",          "BX_KEY_TAB",
  "BX_KEY_LEFT_BACKSLASH", "BX_KEY_PRINT",          "BX_KEY_SCRL_LOCK",
  "BX_KEY_PAUSE",          "BX_KEY_INSERT",         "BX_KEY_DELETE",
  "BX_KEY_HOME",           "BX_KEY_END",            "BX_KEY_PAGE_UP",
  "BX_KEY_PAGE_DOWN",      "BX_KEY_KP_ADD",         "BX_KEY_KP_SUBTRACT",
  "BX_KEY_KP_END",         "BX_KEY_KP_DOWN",        "BX_KEY_KP_PAGE_DOWN",
  "BX_KEY_KP_LEFT",        "BX_KEY_KP_RIGHT",       "BX_KEY_KP_HOME",
  "BX_KEY_KP_UP",          "BX_KEY_KP_PAGE_UP",     "BX_KEY_KP_INSERT",
  "BX_KEY_KP_DELETE",      "BX_KEY_KP_5",           "BX_KEY_UP",
  "BX_KEY_DOWN",           "BX_KEY_LEFT",           "BX_KEY_RIGHT",
  "BX_KEY_KP_ENTER",       "BX_KEY_KP_MULTIPLY",    "BX_KEY_KP_DIVIDE",
  "BX_KEY_WIN_L",          "BX_KEY_WIN_R",          "BX_KEY_MENU",
  "BX_KEY_ALT_SYSREQ",     "BX_KEY_CTRL_BREAK",     "BX_KEY_INT_BACK",
  "BX_KEY_INT_FORWARD",    "BX_KEY_INT_STOP",       "BX_KEY_INT_MAIL",
  "BX_KEY_INT_SEARCH",     "BX_KEY_INT_FAV",        "BX_KEY_INT_HOME",
  "BX_KEY_POWER_MYCOMP",   "BX_KEY_POWER_CALC",     "BX_KEY_POWER_SLEEP",
  "BX_KEY_POWER_POWER",    "BX_KEY_POWER_WAKE",
  };

bx_keymap_c bx_keymap;

#define LOG_THIS bx_keymap.

bx_keymap_c::bx_keymap_c(void)
{
    put("KMAP");

    keymapCount = 0;
    keymapTable = (BXKeyEntry *)NULL;

}

bx_keymap_c::~bx_keymap_c(void)
{
    if(keymapTable != NULL) {
      free(keymapTable);
      keymapTable = (BXKeyEntry *)NULL;
      }
    keymapCount = 0;
}

    void
bx_keymap_c::loadKeymap(Bit32u stringToSymbol(const char*))
{
  if(bx_options.keyboard.OuseMapping->get()) {
    loadKeymap(stringToSymbol,bx_options.keyboard.Okeymap->getptr());
    }
}

Boolean
bx_keymap_c::isKeymapLoaded ()
{
  return (keymapCount > 0);
}

///////////////////
// I'll add these to the keymap object in a minute.
static char *lineptr = NULL;
static int lineCount;

static void
init_parse ()
{
  lineCount = 0;
}

static void
init_parse_line (char *line_to_parse)
{
  // chop off newline
  lineptr = line_to_parse;
  char *nl;
  if( (nl = strchr(line_to_parse,'\n')) != NULL) {
    *nl = 0;
  }
}

static Bit32s
get_next_word (char *output)
{
  char *copyp = output;
  // find first nonspace
  while (*lineptr && isspace (*lineptr))
    lineptr++;
  if (!*lineptr)
    return -1;  // nothing but spaces until end of line
  if (*lineptr == '#')
    return -1;  // nothing but a comment
  // copy nonspaces into the output
  while (*lineptr && !isspace (*lineptr))
    *copyp++ = *lineptr++;
  *copyp=0;  // null terminate the copy
  // there must be at least one nonspace, since that's why we stopped the
  // first loop!
  BX_ASSERT (copyp != output);
  return 0;
}

static Bit32s
get_next_keymap_line (FILE *fp, char *bxsym, char *modsym, Bit32s *ascii, char *xwinsym)
{
  char line[256];
  char buf[256];
  line[0] = 0;
  while (1) {
    lineCount++;
    if (!fgets(line, sizeof(line)-1, fp)) return -1;  // EOF
    init_parse_line (line);
    if (get_next_word (bxsym) >= 0) {
      modsym[0] = 0;
      char *p;
      if ((p = strchr (bxsym, '+')) != NULL) {
	*p = 0;  // truncate bxsym.
	p++;  // move one char beyond the +
	strcpy (modsym, p);  // copy the rest to modsym
      }
      BX_ASSERT (get_next_word (buf) >= 0);
      if (buf[0] == '\'' && buf[2] == '\'' && buf[3]==0) {
	*ascii = (Bit32s) buf[1];
      } else if (!strcmp(buf, "space")) {
	*ascii = ' ';
      } else if (!strcmp(buf, "return")) {
	*ascii = '\n';
      } else if (!strcmp(buf, "tab")) {
	*ascii = '\t';
      } else if (!strcmp(buf, "backslash")) {
	*ascii = '\\';
      } else if (!strcmp(buf, "apostrophe")) {
	*ascii = '\'';
      } else if (!strcmp(buf, "none")) {
	*ascii = -1;
      } else {
	BX_PANIC (("keymap line %d: ascii equivalent is \"%s\" but it must be char constant like 'x', or one of space,tab,return,none", lineCount, buf));
      }
      BX_ASSERT (get_next_word (xwinsym) >= 0);
      return 0;
    }
    // no words on this line, keep reading.
  }
}

    void
bx_keymap_c::loadKeymap(Bit32u stringToSymbol(const char*), const char* filename)
{
    FILE   *keymapFile;
    char   line[256], c, *p;
    char baseSym[256], modSym[256], xwinSym[256];
    Bit32s ascii;
    Bit32u baseKey, modKey, xwinKey;
    struct stat status;

    if (stat(filename, &status)) {
      BX_PANIC(("Can not stat keymap file '%s'.",filename));
      }

    if (!(S_ISREG(status.st_mode))) {
      BX_PANIC(("Keymap file '%s' is not a file",filename));
      }

    if((keymapFile = fopen(filename,"r"))==NULL) {
      BX_PANIC(("Can not open keymap file '%s'.",filename));
      }

    BX_INFO(("Loading keymap from '%s'",filename));
    init_parse ();

    // Read keymap file one line at a time
    while(1) {
      if (get_next_keymap_line (keymapFile,
	    baseSym, modSym, &ascii, xwinSym) < 0) { break; }

      BX_DEBUG (("bxsym='%s', modSym='%s', ascii=%d, guisym='%s'", baseSym, modSym, ascii, xwinSym));

      // convert X_KEY_* symbols to values
      baseKey = convertStringToBXKey(baseSym);
      if (strncmp ("XK_", xwinSym, 3) != 0) {
	BX_PANIC (("keymap line %d: X windows symbol '%s' must start with XK_", lineCount, xwinSym));
      }
      modKey = convertStringToBXKey(modSym);
	  xwinKey = 0;
	  if (stringToSymbol != NULL)
        xwinKey = stringToSymbol(xwinSym + 3);  // skip over the "XK_"

      // Check if data is valid
      if( baseKey==BX_KEYMAP_UNKNOWN ) {
        BX_PANIC (("line %d: unknown BX_KEY constant '%s'",lineCount,baseSym));
        continue;
        }

      if( xwinKey==BX_KEYMAP_UNKNOWN ) {
        BX_PANIC (("line %d: unknown GUI constant '%s'",lineCount,xwinSym));
        continue;
        }

      keymapTable=(BXKeyEntry*)realloc(keymapTable,(keymapCount+1) * sizeof(BXKeyEntry));

      if(keymapTable==NULL)
        BX_PANIC(("Can not allocate memory for keymap table."));

      keymapTable[keymapCount].baseKey=baseKey;
      keymapTable[keymapCount].modKey=modKey;
      keymapTable[keymapCount].ascii=ascii;
      keymapTable[keymapCount].xwinKey=xwinKey;

      keymapCount++;
      }

    BX_INFO(("Loaded %d symbols",keymapCount));

    fclose(keymapFile);
}

    Bit32u
bx_keymap_c::convertStringToBXKey(const char* string)
{
    Bit16u i;

    // We look through the bx_key_symbol table to find the searched string
    for (i=0; i<BX_KEY_NBKEYS; i++) {
      if (strcmp(string,bx_key_symbol[i])==0) {
        return i;
        }
      }

    // Key is not known
    return BX_KEYMAP_UNKNOWN;
}

    BXKeyEntry *
bx_keymap_c::getKeyXwin(Bit32u key)
{
    Bit16u i;

    // We look through the keymap table to find the searched key
    for (i=0; i<keymapCount; i++) {
      if (keymapTable[i].xwinKey == key) {
	BX_DEBUG (("key 0x%02x matches xwinKey for entry #%d", key, i));
        return &keymapTable[i];
        }
      }
    BX_DEBUG (("key %02x matches no entries", key));

    // Return default
    return NULL;
}

    BXKeyEntry *
bx_keymap_c::getKeyASCII(Bit8u ch)
{
    Bit16u i;
    BX_DEBUG (("getKeyASCII (0x%02x)", ch));

    // We look through the keymap table to find the searched key
    for (i=0; i<keymapCount; i++) {
      if (keymapTable[i].ascii == ch) {
	BX_DEBUG (("key %02x matches ascii for entry #%d", ch, i));
        return &keymapTable[i];
        }
      }
    BX_DEBUG (("key 0x%02x matches no entries", ch));

    // Return default
    return NULL;
}

<|endoftext|>


<commit_before><commit_msg>Reduce scope of a stack variable.<commit_after><|endoftext|>


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

#include "EventTriggerConstants.h"
#include "elderly_care_simulation/EventTrigger.h"
#include <queue>
#include "EventNode.h"
#include <unistd.h> // sleep

// constants
const int MAX_CONCURRENT_EVENTS = 2;

// globals
std::priority_queue<EventNode > eventQueue;
ros::Publisher eventTriggerPub;
ros::Subscriber eventTriggerSub;
ros::Subscriber randomEventSub;
int ongoingEvents = 0;
bool allowRandomEvents = false;

/**
 * Returns a C string representation of the coresponding event type
 */
const char * eventTypeToString(int eventType) {
    switch(eventType){

        case EVENT_TRIGGER_EVENT_TYPE_EAT:              return "EAT";
        case EVENT_TRIGGER_EVENT_TYPE_SHOWER:           return "SHOWER";
        case EVENT_TRIGGER_EVENT_TYPE_EXERCISE:         return "EXERCISE";
        case EVENT_TRIGGER_EVENT_TYPE_CONVERSATION:     return "CONVERSATION";
        case EVENT_TRIGGER_EVENT_TYPE_MORAL_SUPPORT:    return "MORAL_SUPPORT";
        case EVENT_TRIGGER_EVENT_TYPE_FRIEND_RELATIVE:  return "FRIEND_RELATIVE";
        case EVENT_TRIGGER_EVENT_TYPE_ILL:              return "ILL";
        case EVENT_TRIGGER_EVENT_TYPE_VERY_ILL:         return "VERY_ILL";
        case EVENT_TRIGGER_EVENT_TYPE_MEDICATION:       return "MEDICATION";
        case EVENT_TRIGGER_EVENT_TYPE_COOK:             return "COOK";
        case EVENT_TRIGGER_EVENT_TYPE_ENTERTAINMENT:    return "ENTERTAINMENT";
        case EVENT_TRIGGER_EVENT_TYPE_COMPANIONSHIP:    return "COMPANIONSHIP";
        case EVENT_TRIGGER_EVENT_TYPE_WAKE:             return "WAKE";
        case EVENT_TRIGGER_EVENT_TYPE_SLEEP:            return "SLEEP";
    }
}

/**
 * Creates a Request EventTrigger message for requesting robot tasks.
 * @param eventType the event type for the message
 */
elderly_care_simulation::EventTrigger createEventRequestMsg(int eventType){
    elderly_care_simulation::EventTrigger msg;
    msg.msg_type = EVENT_TRIGGER_MSG_TYPE_REQUEST;
    msg.event_type = eventType;
    msg.result = EVENT_TRIGGER_RESULT_FAILURE;

    return msg;
}

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

/**
 * Callback function to deal with random events published by the resident
 */
void randomEventInterceptCallback(elderly_care_simulation::EventTrigger msg) {
	ROS_INFO("Scheduler: Received Message from Resident");
	int priority = 2; // default
	switch(msg.event_type) {
		case EVENT_TRIGGER_EVENT_TYPE_MORAL_SUPPORT:
			priority = 2;
			break;
		case EVENT_TRIGGER_EVENT_TYPE_ILL:
			priority = 0;
			break;
        case EVENT_TRIGGER_EVENT_TYPE_VERY_ILL:
            priority = 0;
            break;
	}

    // Only allows random events to be added to event queue in the allowed
    // timeframe (between WAKE and SLEEP)
    if (allowRandomEvents){
        ROS_INFO("Scheduler: Adding random event: [%s] to queue.", eventTypeToString(msg.event_type));
        eventQueue.push(EventNode(priority, msg));
    }else{
        ROS_INFO("Scheduler: Random events are not allowed at this time.");
    }

}

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

	if (msg.msg_type == EVENT_TRIGGER_MSG_TYPE_RESPONSE) {
		if(msg.result == EVENT_TRIGGER_RESULT_SUCCESS){
			// reset ability to send
            if (msg.event_type != EVENT_TRIGGER_EVENT_TYPE_COOK) {
                elderly_care_simulation::EventTrigger msg;
                msg = createEventRequestMsg(EVENT_TRIGGER_EVENT_TYPE_EAT);

                ROS_INFO("Scheduler: Adding [%s] event to queue.", eventTypeToString(msg.event_type));
                eventQueue.push(EventNode(1, msg));
            }else{
                ongoingEvents--;
                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 populateDailyTasks(void) {

    int eventSequence[] = {

        // Morning
        EVENT_TRIGGER_EVENT_TYPE_WAKE,
        EVENT_TRIGGER_EVENT_TYPE_COOK,
        EVENT_TRIGGER_EVENT_TYPE_MEDICATION,
        EVENT_TRIGGER_EVENT_TYPE_EXERCISE,
        EVENT_TRIGGER_EVENT_TYPE_SHOWER,
        EVENT_TRIGGER_EVENT_TYPE_ENTERTAINMENT,

        // Noon
        EVENT_TRIGGER_EVENT_TYPE_COOK,
        EVENT_TRIGGER_EVENT_TYPE_MEDICATION,
        EVENT_TRIGGER_EVENT_TYPE_CONVERSATION,
        EVENT_TRIGGER_EVENT_TYPE_FRIEND_RELATIVE,
        EVENT_TRIGGER_EVENT_TYPE_ENTERTAINMENT,

        // Evening
        EVENT_TRIGGER_EVENT_TYPE_COOK,
        EVENT_TRIGGER_EVENT_TYPE_MEDICATION,
        EVENT_TRIGGER_EVENT_TYPE_COMPANIONSHIP,
        EVENT_TRIGGER_EVENT_TYPE_SLEEP
    };

    for(int i = 0; i < sizeof(eventSequence)/sizeof(*eventSequence); i++) {
        eventQueue.push(EventNode(3, createEventRequestMsg(eventSequence[i])));
    }
}

/**
 * Dequeues an event and publishes to the event_trigger topic.
 * Allows concurrent events to be triggered up to the limit
 * set in MAX_CONCURRENT_EVENTS
 *
 * COOK event is not affected as it acts independently of the
 * Resident.
 */
void dequeueEvent(void) {
    if (eventQueue.size() < 1) {
        return;
    }

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

    // Enable random events to be added to queue only after WAKE event
    if (msg.event_type == EVENT_TRIGGER_EVENT_TYPE_WAKE){
        allowRandomEvents = true;
    }

    // Disable random events from being added to queue after SLEEP event
    if (msg.event_type == EVENT_TRIGGER_EVENT_TYPE_SLEEP){
        allowRandomEvents = false;

    // cooking event type is published immediately
    } else if (msg.event_type == EVENT_TRIGGER_EVENT_TYPE_COOK) {
        eventQueue.pop();
        eventTriggerPub.publish(msg);
        ROS_INFO("Scheduler: Publishing event: [%s]", eventTypeToString(msg.event_type));
    } else {
        // publish new event only if less than two events are ongoing
        if (ongoingEvents < MAX_CONCURRENT_EVENTS) {
            eventQueue.pop();
            eventTriggerPub.publish(msg);
            ROS_INFO("Scheduler: Publishing event: [%s]", eventTypeToString(msg.event_type));
            ongoingEvents++;
        }
    }
}

/**
 * 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;

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

	// subscribe to event_trigger topic
	eventTriggerSub = nodeHandle.subscribe<elderly_care_simulation::EventTrigger>("event_trigger",1000, eventTriggerCallback);
	randomEventSub = nodeHandle.subscribe<elderly_care_simulation::EventTrigger>("resident_event",1000, randomEventInterceptCallback);

	ros::Rate loop_rate(10);

    // populate queue with day's events
    populateDailyTasks();

	//a count of howmany messages we have sent
	int count = 0;

	while (ros::ok()) {

        dequeueEvent();

		ros::spinOnce();
		loop_rate.sleep();
		++count;
	}
	return 0;
}
<commit_msg>Worked on fixing corner case where the scheduler publishes a normal event and the SLEEP event to ongoing event. (NOT TESTED)<commit_after>#include "ros/ros.h"
#include "std_msgs/String.h"

#include "EventTriggerConstants.h"
#include "elderly_care_simulation/EventTrigger.h"
#include <queue>
#include "EventNode.h"
#include <unistd.h> // sleep

// constants
const int MAX_CONCURRENT_EVENTS = 2;

// globals
std::priority_queue<EventNode > eventQueue;
ros::Publisher eventTriggerPub;
ros::Subscriber eventTriggerSub;
ros::Subscriber randomEventSub;
int ongoingEvents = 0;
bool allowRandomEvents = false;

/**
 * Returns a C string representation of the coresponding event type
 */
const char * eventTypeToString(int eventType) {
    switch(eventType){

        case EVENT_TRIGGER_EVENT_TYPE_EAT:              return "EAT";
        case EVENT_TRIGGER_EVENT_TYPE_SHOWER:           return "SHOWER";
        case EVENT_TRIGGER_EVENT_TYPE_EXERCISE:         return "EXERCISE";
        case EVENT_TRIGGER_EVENT_TYPE_CONVERSATION:     return "CONVERSATION";
        case EVENT_TRIGGER_EVENT_TYPE_MORAL_SUPPORT:    return "MORAL_SUPPORT";
        case EVENT_TRIGGER_EVENT_TYPE_FRIEND_RELATIVE:  return "FRIEND_RELATIVE";
        case EVENT_TRIGGER_EVENT_TYPE_ILL:              return "ILL";
        case EVENT_TRIGGER_EVENT_TYPE_VERY_ILL:         return "VERY_ILL";
        case EVENT_TRIGGER_EVENT_TYPE_MEDICATION:       return "MEDICATION";
        case EVENT_TRIGGER_EVENT_TYPE_COOK:             return "COOK";
        case EVENT_TRIGGER_EVENT_TYPE_ENTERTAINMENT:    return "ENTERTAINMENT";
        case EVENT_TRIGGER_EVENT_TYPE_COMPANIONSHIP:    return "COMPANIONSHIP";
        case EVENT_TRIGGER_EVENT_TYPE_WAKE:             return "WAKE";
        case EVENT_TRIGGER_EVENT_TYPE_SLEEP:            return "SLEEP";
    }
}

/**
 * Creates a Request EventTrigger message for requesting robot tasks.
 * @param eventType the event type for the message
 */
elderly_care_simulation::EventTrigger createEventRequestMsg(int eventType){
    elderly_care_simulation::EventTrigger msg;
    msg.msg_type = EVENT_TRIGGER_MSG_TYPE_REQUEST;
    msg.event_type = eventType;
    msg.result = EVENT_TRIGGER_RESULT_FAILURE;

    return msg;
}

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

/**
 * Callback function to deal with random events published by the resident
 */
void randomEventInterceptCallback(elderly_care_simulation::EventTrigger msg) {
	ROS_INFO("Scheduler: Received Message from Resident");
	int priority = 2; // default
	switch(msg.event_type) {
		case EVENT_TRIGGER_EVENT_TYPE_MORAL_SUPPORT:
			priority = 2;
			break;
		case EVENT_TRIGGER_EVENT_TYPE_ILL:
			priority = 0;
			break;
        case EVENT_TRIGGER_EVENT_TYPE_VERY_ILL:
            priority = 0;
            break;
	}

    // Only allows random events to be added to event queue in the allowed
    // timeframe (between WAKE and SLEEP)
    if (allowRandomEvents){
        ROS_INFO("Scheduler: Adding random event: [%s] to queue.", eventTypeToString(msg.event_type));
        eventQueue.push(EventNode(priority, msg));
    }else{
        ROS_INFO("Scheduler: Random events are not allowed at this time.");
    }

}

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

	if (msg.msg_type == EVENT_TRIGGER_MSG_TYPE_RESPONSE) {
		if(msg.result == EVENT_TRIGGER_RESULT_SUCCESS){
			// reset ability to send
            if (msg.event_type != EVENT_TRIGGER_EVENT_TYPE_COOK) {
                elderly_care_simulation::EventTrigger msg;
                msg = createEventRequestMsg(EVENT_TRIGGER_EVENT_TYPE_EAT);

                ROS_INFO("Scheduler: Adding [%s] event to queue.", eventTypeToString(msg.event_type));
                eventQueue.push(EventNode(1, msg));
            }else{
                ongoingEvents--;
                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 populateDailyTasks(void) {

    int eventSequence[] = {

        // Morning
        EVENT_TRIGGER_EVENT_TYPE_WAKE,
        EVENT_TRIGGER_EVENT_TYPE_COOK,
        EVENT_TRIGGER_EVENT_TYPE_MEDICATION,
        EVENT_TRIGGER_EVENT_TYPE_EXERCISE,
        EVENT_TRIGGER_EVENT_TYPE_SHOWER,
        EVENT_TRIGGER_EVENT_TYPE_ENTERTAINMENT,

        // Noon
        EVENT_TRIGGER_EVENT_TYPE_COOK,
        EVENT_TRIGGER_EVENT_TYPE_MEDICATION,
        EVENT_TRIGGER_EVENT_TYPE_CONVERSATION,
        EVENT_TRIGGER_EVENT_TYPE_FRIEND_RELATIVE,
        EVENT_TRIGGER_EVENT_TYPE_ENTERTAINMENT,

        // Evening
        EVENT_TRIGGER_EVENT_TYPE_COOK,
        EVENT_TRIGGER_EVENT_TYPE_MEDICATION,
        EVENT_TRIGGER_EVENT_TYPE_COMPANIONSHIP,
        EVENT_TRIGGER_EVENT_TYPE_SLEEP
    };

    for(int i = 0; i < sizeof(eventSequence)/sizeof(*eventSequence); i++) {
        eventQueue.push(EventNode(3, createEventRequestMsg(eventSequence[i])));
    }
}

/**
 * Dequeues an event and publishes to the event_trigger topic.
 * Allows concurrent events to be triggered up to the limit
 * set in MAX_CONCURRENT_EVENTS
 *
 * COOK event is not affected as it acts independently of the
 * Resident.
 */
void dequeueEvent(void) {
    if (eventQueue.size() < 1) {
        return;
    }

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

    // Enable random events to be added to queue only after WAKE event
    if (msg.event_type == EVENT_TRIGGER_EVENT_TYPE_WAKE){
        allowRandomEvents = true;
    }

    // Disable random events from being added to queue after SLEEP event
    // Also prevent the SLEEP event until all tasks are finished.
    if (msg.event_type == EVENT_TRIGGER_EVENT_TYPE_SLEEP){
        allowRandomEvents = false;

        // If no more tasks, then publish SLEEP event
        if(ongoingEvents == 0) {
            eventQueue.pop();
            eventTriggerPub.publish(msg);
            ROS_INFO("Scheduler: Publishing event: [%s]", eventTypeToString(msg.event_type));
            ongoingEvents++;

        // If tasks still ongoing, do not allow SLEEP
        }else{
            ROS_INFO("Scheduler: Target still busy, cannot do event: [%s]", eventTypeToString(msg.event_type));
            return;
        }

    // cooking event type is published immediately
    } else if (msg.event_type == EVENT_TRIGGER_EVENT_TYPE_COOK) {
        eventQueue.pop();
        eventTriggerPub.publish(msg);
        ROS_INFO("Scheduler: Publishing event: [%s]", eventTypeToString(msg.event_type));
    } else {
        // publish new event only if less than two events are ongoing
        if (ongoingEvents < MAX_CONCURRENT_EVENTS) {
            eventQueue.pop();
            eventTriggerPub.publish(msg);
            ROS_INFO("Scheduler: Publishing event: [%s]", eventTypeToString(msg.event_type));
            ongoingEvents++;
        }
    }
}

/**
 * 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;

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

	// subscribe to event_trigger topic
	eventTriggerSub = nodeHandle.subscribe<elderly_care_simulation::EventTrigger>("event_trigger",1000, eventTriggerCallback);
	randomEventSub = nodeHandle.subscribe<elderly_care_simulation::EventTrigger>("resident_event",1000, randomEventInterceptCallback);

	ros::Rate loop_rate(10);

    // populate queue with day's events
    populateDailyTasks();

	//a count of howmany messages we have sent
	int count = 0;

	while (ros::ok()) {

        if(eventQueue.size() == 0 && ongoingEvents == 0) {
            sleep(10);
            clearEventQueue();
            populateDailyTasks();
        }else {
            dequeueEvent();
        }

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


<commit_before>#include "BackendWorker.hpp"

#include <iostream>

#include <opencv2/opencv.hpp>

#include "SgPoint.h"
#include "SgSystem.h"

namespace Go_AR {

// converts a cv::Mat to a QImage
// inspired from http://www.qtforum.de/forum/viewtopic.php?t=9721
//
// Has two preconditions:
//   - depth of the cv::Mat has to be CV_8U = 8-bit unsigned integers ( 0..255 )
//   - number of channels has to be 3 (RGB, or BGR in opencv)
QImage mat_to_QImage(cv::Mat source)
{
    assert(source.depth() == CV_8U);
    assert(source.channels() == 3);

    // "cast" or convert to an IplImage to get easier access to needed infos,
    // no copying involved
    IplImage image = source;

    // create QImage from IplImage
    QImage ret((uchar*) image.imageData, image.width, image.height, QImage::Format_RGB888);

    // swap BGR (opencv format) to RGB
    ret = ret.rgbSwapped();

    return ret;
}

BackendWorker::BackendWorker()
    : _game(),
    _scanner(),
    _game_is_initialized(false),
    _scan_timer(this) // this makes sure that the timer has the same thread affinity as its parent (this)
{
    /* define default game rules
     *     handicap: 0
     *     komi:     6.5
     *     scoring:  japanese
     *     game end: after 2 consecutive passes
     */
    _new_game_rules = GoRules(0, GoKomi(6.5), true, true);

    connect(&_scan_timer, SIGNAL(timeout()), this, SLOT(scan()));
    _scan_timer.setInterval(2000);// call the connected slot every 1000 msec
    _scan_timer.start();  // put one event in this threads event queue
}

BackendWorker::~BackendWorker()
{}

void BackendWorker::scan() {
    cv::Mat image;
    GoSetup setup;
    int board_size = 19;

    // fetch new camera image
    auto scan_result = _scanner.scanCamera(setup, board_size, image);

    using Go_Scanner::ScanResult;
    using GoBackend::UpdateResult;

    switch (scan_result) {
    case ScanResult::Success:
        {
            if (_game_is_initialized) {
                // update game state
                UpdateResult result = _game.update(setup);
                if (result == UpdateResult::Illegal)
                    emit displayErrorMessage("Your board differs from virtual board!");
                else {
                    emit displayErrorMessage(""); // no error
                }
            }
            else {
                // the gui doesn't support other sizes
                if (board_size == 9 || board_size == 13 || board_size == 19) {
                    _game.init(board_size, setup, _new_game_rules);
                    _game_is_initialized = true;
                    emit displayErrorMessage("");
                }
                else {
                    emit displayErrorMessage(QString("Not supported board size of %1x%1 detected!").arg(board_size));
                }
            }

            signalGuiGameDataChanged();

            // don't break because Success implies getting an image,
            // so let control flow fall through
        }
    case ScanResult::Failed:
        {
            // we still have a camera image to display, even when the scanning failed
            // converting image (OpenCV data type) to QImage (Qt data type)
            const auto scanner_image = mat_to_QImage(image);
            // send signal with new image to gui
            emit newImage(scanner_image);

            emit displayErrorMessage("Board could not be detected correctly!\nBoard selection still accurate?");
            break;
        }
    case ScanResult::NoCamera:
        // disables board detection menu items
        // the menu items will be reactivated when the next newImage signal gets handled
        emit noCameraImage();
        emit displayErrorMessage("No camera image could be retrieved!");
        break;
    default:
        assert(!"Unknown ScanResult?!");
    }
}

void BackendWorker::saveSgf(QString path, QString blackplayer_name, QString whiteplayer_name, QString game_name) {
    auto filepath = path.toStdString();

    if (!_game.saveGame(filepath, blackplayer_name.toStdString(), whiteplayer_name.toStdString(), game_name.toStdString()))
        std::cerr << "Error writing game data to file \"" << filepath << "\"!" << std::endl;
}

void BackendWorker::pass() {
    _game.pass();

    if (_game.hasEnded())
        signalGuiGameHasEnded();

    signalGuiGameDataChanged();
}

void BackendWorker::resetGame(GoRules rules) {
    _game_is_initialized = false;
    _new_game_rules      = rules;

    if (virtualModeActive()) {
        _game.init(19, GoSetup(), _new_game_rules);

        signalGuiGameDataChanged();
    }
}

void BackendWorker::finish() {
    _game.finishGame();

    signalGuiGameHasEnded();
}

void BackendWorker::resign() {
    _game.resign();

    signalGuiGameHasEnded();
}

void BackendWorker::signalGuiGameHasEnded() const {
    auto result = _game.getResult();

    // signal gui that game has ended with this result
    emit finishedGameResult(QString(result.c_str()));
}

void BackendWorker::setVirtualGameMode(bool checked) {
    if (virtualModeActive()) {
        // go into augmented mode -> do the scanning!
        _scan_timer.start();
    }
    else {
        // go into virtual mode -> no scanning!
        _scan_timer.stop();
        // also hide any scanning related error messages
        emit displayErrorMessage("");

        // initialize a game
        if (!_game_is_initialized)
            _game.init(19, GoSetup(), _new_game_rules);

        signalGuiGameDataChanged();
    }
}

void BackendWorker::playMove(const int x, const int y){
    auto position = SgPointUtil::Pt(x, y);
    _game.playMove(position);

    signalGuiGameDataChanged();
}

void BackendWorker::selectBoardManually() {
    _scanner.selectBoardManually();
}

void BackendWorker::selectBoardAutomatically() {
    _scanner.selectBoardAutomatically();
}

void BackendWorker::setScannerDebugImage(bool debug) {
    if (debug)
        _scanner.setDebugImage();
    else
        _scanner.setNormalImage();
}

bool BackendWorker::virtualModeActive() const {
    return !_scan_timer.isActive();
}

void BackendWorker::signalGuiGameDataChanged() const {
    // send board data to gui
    // the GUI controls the lifetime of this thread,
    // so passing a pointer to the GoBoard is safe and won't be invalidated
    // as long as the GUI says so
    emit gameDataChanged(&_game);
}

} // namespace Go_AR<commit_msg>[Close #128] Stop camera scanning while doing board detection<commit_after>#include "BackendWorker.hpp"

#include <iostream>

#include <opencv2/opencv.hpp>

#include "SgPoint.h"
#include "SgSystem.h"

namespace Go_AR {

// converts a cv::Mat to a QImage
// inspired from http://www.qtforum.de/forum/viewtopic.php?t=9721
//
// Has two preconditions:
//   - depth of the cv::Mat has to be CV_8U = 8-bit unsigned integers ( 0..255 )
//   - number of channels has to be 3 (RGB, or BGR in opencv)
QImage mat_to_QImage(cv::Mat source)
{
    assert(source.depth() == CV_8U);
    assert(source.channels() == 3);

    // "cast" or convert to an IplImage to get easier access to needed infos,
    // no copying involved
    IplImage image = source;

    // create QImage from IplImage
    QImage ret((uchar*) image.imageData, image.width, image.height, QImage::Format_RGB888);

    // swap BGR (opencv format) to RGB
    ret = ret.rgbSwapped();

    return ret;
}

BackendWorker::BackendWorker()
    : _game(),
    _scanner(),
    _game_is_initialized(false),
    _scan_timer(this) // this makes sure that the timer has the same thread affinity as its parent (this)
{
    /* define default game rules
     *     handicap: 0
     *     komi:     6.5
     *     scoring:  japanese
     *     game end: after 2 consecutive passes
     */
    _new_game_rules = GoRules(0, GoKomi(6.5), true, true);

    connect(&_scan_timer, SIGNAL(timeout()), this, SLOT(scan()));
    _scan_timer.setInterval(2000);// call the connected slot every 1000 msec
    _scan_timer.start();  // put one event in this threads event queue
}

BackendWorker::~BackendWorker()
{}

void BackendWorker::scan() {
    cv::Mat image;
    GoSetup setup;
    int board_size = 19;

    // fetch new camera image
    auto scan_result = _scanner.scanCamera(setup, board_size, image);

    using Go_Scanner::ScanResult;
    using GoBackend::UpdateResult;

    switch (scan_result) {
    case ScanResult::Success:
        {
            if (_game_is_initialized) {
                // update game state
                UpdateResult result = _game.update(setup);
                if (result == UpdateResult::Illegal)
                    emit displayErrorMessage("Your board differs from virtual board!");
                else {
                    emit displayErrorMessage(""); // no error
                }
            }
            else {
                // the gui doesn't support other sizes
                if (board_size == 9 || board_size == 13 || board_size == 19) {
                    _game.init(board_size, setup, _new_game_rules);
                    _game_is_initialized = true;
                    emit displayErrorMessage("");
                }
                else {
                    emit displayErrorMessage(QString("Not supported board size of %1x%1 detected!").arg(board_size));
                }
            }

            signalGuiGameDataChanged();

            // don't break because Success implies getting an image,
            // so let control flow fall through
        }
    case ScanResult::Failed:
        {
            // we still have a camera image to display, even when the scanning failed
            // converting image (OpenCV data type) to QImage (Qt data type)
            const auto scanner_image = mat_to_QImage(image);
            // send signal with new image to gui
            emit newImage(scanner_image);

            emit displayErrorMessage("Board could not be detected correctly!\nBoard selection still accurate?");
            break;
        }
    case ScanResult::NoCamera:
        // disables board detection menu items
        // the menu items will be reactivated when the next newImage signal gets handled
        emit noCameraImage();
        emit displayErrorMessage("No camera image could be retrieved!");
        break;
    default:
        assert(!"Unknown ScanResult?!");
    }
}

void BackendWorker::saveSgf(QString path, QString blackplayer_name, QString whiteplayer_name, QString game_name) {
    auto filepath = path.toStdString();

    if (!_game.saveGame(filepath, blackplayer_name.toStdString(), whiteplayer_name.toStdString(), game_name.toStdString()))
        std::cerr << "Error writing game data to file \"" << filepath << "\"!" << std::endl;
}

void BackendWorker::pass() {
    _game.pass();

    if (_game.hasEnded())
        signalGuiGameHasEnded();

    signalGuiGameDataChanged();
}

void BackendWorker::resetGame(GoRules rules) {
    _game_is_initialized = false;
    _new_game_rules      = rules;

    if (virtualModeActive()) {
        _game.init(19, GoSetup(), _new_game_rules);

        signalGuiGameDataChanged();
    }
}

void BackendWorker::finish() {
    _game.finishGame();

    signalGuiGameHasEnded();
}

void BackendWorker::resign() {
    _game.resign();

    signalGuiGameHasEnded();
}

void BackendWorker::signalGuiGameHasEnded() const {
    auto result = _game.getResult();

    // signal gui that game has ended with this result
    emit finishedGameResult(QString(result.c_str()));
}

void BackendWorker::setVirtualGameMode(bool checked) {
    if (virtualModeActive()) {
        // go into augmented mode -> do the scanning!
        _scan_timer.start();
    }
    else {
        // go into virtual mode -> no scanning!
        _scan_timer.stop();
        // also hide any scanning related error messages
        emit displayErrorMessage("");

        // initialize a game
        if (!_game_is_initialized)
            _game.init(19, GoSetup(), _new_game_rules);

        signalGuiGameDataChanged();
    }
}

void BackendWorker::playMove(const int x, const int y){
    auto position = SgPointUtil::Pt(x, y);
    _game.playMove(position);

    signalGuiGameDataChanged();
}

void BackendWorker::selectBoardManually() {
    _scan_timer.stop();
    _scanner.selectBoardManually();
    _scan_timer.start();
}

void BackendWorker::selectBoardAutomatically() {
    _scan_timer.stop();
    _scanner.selectBoardAutomatically();
    _scan_timer.start();
}

void BackendWorker::setScannerDebugImage(bool debug) {
    if (debug)
        _scanner.setDebugImage();
    else
        _scanner.setNormalImage();
}

bool BackendWorker::virtualModeActive() const {
    return !_scan_timer.isActive();
}

void BackendWorker::signalGuiGameDataChanged() const {
    // send board data to gui
    // the GUI controls the lifetime of this thread,
    // so passing a pointer to the GoBoard is safe and won't be invalidated
    // as long as the GUI says so
    emit gameDataChanged(&_game);
}

} // namespace Go_AR<|endoftext|>


<commit_before>#include "SceneEditor.hpp"

#include <Engine/Hymn.hpp>
#include <Engine/Util/FileSystem.hpp>
#include <Engine/Util/Log.hpp>
#include <imgui.h>

using namespace GUI;

void SceneEditor::Show() {
    if (ImGui::Begin(("Scene: " + Hymn().scenes[sceneIndex] + "###Scene").c_str(), &visible, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_ShowBorders)) {
        ImGui::InputText("Name", name, 128);
        Hymn().scenes[sceneIndex] = name;

        // Entities.
        entityPressed = false;
        ShowEntity(Hymn().world.GetRoot());
    }
    ImGui::End();
}

void SceneEditor::SetScene(std::size_t sceneIndex) {
    entityEditor.SetVisible(false);

    if (sceneIndex < Hymn().scenes.size()) {
        this->sceneIndex = sceneIndex;
        strcpy(name, Hymn().scenes[sceneIndex].c_str());
    }
}

bool SceneEditor::IsVisible() const {
    return visible;
}

void SceneEditor::SetVisible(bool visible) {
    this->visible = visible;
}

void SceneEditor::Save() const {
    if (sceneIndex < Hymn().scenes.size())
        Hymn().world.Save(Hymn().GetPath() + FileSystem::DELIMITER + "Scenes" + FileSystem::DELIMITER + Hymn().scenes[sceneIndex] + ".json");
}

void SceneEditor::ShowEntity(Entity* entity) {
    bool leaf = entity->IsScene() || entity->GetChildren().empty();
    bool opened = ImGui::TreeNodeEx(entity->name.c_str(), leaf ? ImGuiTreeNodeFlags_Leaf : 0);

    if (ImGui::BeginPopupContextItem(entity->name.c_str())) {
        if (ImGui::Selectable("Edit")) {
            entityPressed = true;
            entityEditor.SetEntity(entity);
        }

        if (!entity->IsScene()) {
            if (ImGui::Selectable("Add child"))
                entity->AddChild("Entity #" + std::to_string(Hymn().entityNumber++));

            if (ImGui::Selectable("Instantiate scene"))
                ImGui::OpenPopup("Select scene");

            if (ImGui::BeginPopup("Select scene")) {
                ImGui::Text("Scenes");
                ImGui::Separator();

                for (const std::string& scene : Hymn().scenes) {
                    if (ImGui::Selectable(scene.c_str()))
                        entity->InstantiateScene(scene);
                }

                ImGui::EndPopup();
            }
        }

        if (entity != Hymn().world.GetRoot()) {
            if (ImGui::Selectable("Delete")) {
                entity->Kill();
                if (entityEditor.ShowsEntity(entity))
                    entityEditor.SetVisible(false);
            }
        }

        ImGui::EndPopup();
    }

    if (opened) {
        if (!entity->IsScene()) {
            for (Entity* child : entity->GetChildren()) {
                ShowEntity(child);
            }
        }

        ImGui::TreePop();
    }
}
<commit_msg>Fix instantiating scene<commit_after>#include "SceneEditor.hpp"

#include <Engine/Hymn.hpp>
#include <Engine/Util/FileSystem.hpp>
#include <Engine/Util/Log.hpp>
#include <imgui.h>

using namespace GUI;

void SceneEditor::Show() {
    if (ImGui::Begin(("Scene: " + Hymn().scenes[sceneIndex] + "###Scene").c_str(), &visible, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_ShowBorders)) {
        ImGui::InputText("Name", name, 128);
        Hymn().scenes[sceneIndex] = name;

        // Entities.
        entityPressed = false;
        ShowEntity(Hymn().world.GetRoot());
    }
    ImGui::End();
}

void SceneEditor::SetScene(std::size_t sceneIndex) {
    entityEditor.SetVisible(false);

    if (sceneIndex < Hymn().scenes.size()) {
        this->sceneIndex = sceneIndex;
        strcpy(name, Hymn().scenes[sceneIndex].c_str());
    }
}

bool SceneEditor::IsVisible() const {
    return visible;
}

void SceneEditor::SetVisible(bool visible) {
    this->visible = visible;
}

void SceneEditor::Save() const {
    if (sceneIndex < Hymn().scenes.size())
        Hymn().world.Save(Hymn().GetPath() + FileSystem::DELIMITER + "Scenes" + FileSystem::DELIMITER + Hymn().scenes[sceneIndex] + ".json");
}

void SceneEditor::ShowEntity(Entity* entity) {
    bool leaf = entity->IsScene() || entity->GetChildren().empty();
    bool opened = ImGui::TreeNodeEx(entity->name.c_str(), leaf ? ImGuiTreeNodeFlags_Leaf : 0);
    bool instantiate = false;

    if (ImGui::BeginPopupContextItem(entity->name.c_str())) {
        if (ImGui::Selectable("Edit")) {
            entityPressed = true;
            entityEditor.SetEntity(entity);
        }

        if (!entity->IsScene()) {
            if (ImGui::Selectable("Add child"))
                entity->AddChild("Entity #" + std::to_string(Hymn().entityNumber++));

            if (ImGui::Selectable("Instantiate scene"))
                instantiate = true;
        }

        if (entity != Hymn().world.GetRoot()) {
            if (ImGui::Selectable("Delete")) {
                entity->Kill();
                if (entityEditor.ShowsEntity(entity))
                    entityEditor.SetVisible(false);
            }
        }

        ImGui::EndPopup();
    }

    if (instantiate)
        ImGui::OpenPopup("Select scene");

    if (ImGui::BeginPopup("Select scene")) {
        ImGui::Text("Scenes");
        ImGui::Separator();

        for (const std::string& scene : Hymn().scenes) {
            if (ImGui::Selectable(scene.c_str()))
                entity->InstantiateScene(scene);
        }

        ImGui::EndPopup();
    }

    if (opened) {
        if (!entity->IsScene()) {
            for (Entity* child : entity->GetChildren()) {
                ShowEntity(child);
            }
        }

        ImGui::TreePop();
    }
}
<|endoftext|>