<commit_before>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <iostream>
#include "system/globalenv.h"
#include "types/typeconstants.h"
#include "types/typeimpl.h"
#include "types/typeops.h"
#include "types/root_typemanager.h"
#include "zorbaerrors/Assert.h"

namespace zorba {

const char* XQType::KIND_STRINGS[XQType::MAX_TYPE_KIND] =
{
  "EMPTY_KIND",
  "ATOMIC_TYPE_KIND",
  "ITEM_KIND",
  "NODE_TYPE_KIND",
  "ANY_TYPE_KIND",
  "ANY_SIMPLE_TYPE_KIND",
  "UNTYPED_KIND",
  "NONE_KIND"
};

const char *AtomicXQType::ATOMIC_TYPE_CODE_STRINGS[TypeConstants::ATOMIC_TYPE_CODE_LIST_SIZE] =
{
  "XS_ANY_ATOMIC",
  "XS_STRING",
  "XS_NORMALIZED_STRING",
  "XS_TOKEN",
  "XS_LANGUAGE",
  "XS_NMTOKEN",
  "XS_NAME",
  "XS_NCNAME",
  "XS_ID",
  "XS_IDREF",
  "XS_ENTITY",
  "XS_UNTYPED_ATOMIC",
  "XS_DATETIME",
  "XS_DATE",
  "XS_TIME",
  "XS_DURATION",
  "XS_DT_DURATION",
  "XS_YM_DURATION",
  "XS_FLOAT",
  "XS_DOUBLE",
  "XS_DECIMAL",
  "XS_INTEGER",
  "XS_NON_POSITIVE_INTEGER",
  "XS_NEGATIVE_INTEGER",
  "XS_LONG",
  "XS_INT",
  "XS_SHORT",
  "XS_BYTE",
  "XS_NON_NEGATIVE_INTEGER",
  "XS_UNSIGNED_LONG",
  "XS_UNSIGNED_INT",
  "XS_UNSIGNED_SHORT",
  "XS_UNSIGNED_BYTE",
  "XS_POSITIVE_INTEGER",
  "XS_GYEAR_MONTH",
  "XS_GYEAR",
  "XS_GMONTH_DAY",
  "XS_GDAY",
  "XS_GMONTH",
  "XS_BOOLEAN",
  "XS_BASE64BINARY",
  "XS_HEXBINARY",
  "XS_ANY_URI",
  "XS_QNAME",
  "XS_NOTATION"
};

std::ostream& XQType::serialize(std::ostream& os) const
{
  return os << "[XQType " << KIND_STRINGS[type_kind()]
            << TypeOps::decode_quantifier(get_quantifier()) << "]";
}

std::string XQType::toString() const
{
  std::ostringstream os;
  serialize(os);
  return os.str();
}

std::ostream& AtomicXQType::serialize(std::ostream& os) const
{
  return os << "[AtomicXQType " << ATOMIC_TYPE_CODE_STRINGS[get_type_code()]
            << TypeOps::decode_quantifier (get_quantifier()) << "]";
}

store::Item_t AtomicXQType::get_qname() const
{
  return GENV_TYPESYSTEM.m_atomic_typecode_qname_map[m_type_code];
}

store::Item_t AnyXQType::get_qname() const
{
  return GENV_TYPESYSTEM.XS_ANY_TYPE_QNAME;
}

store::Item_t AnySimpleXQType::get_qname() const
{
  return GENV_TYPESYSTEM.XS_ANY_SIMPLE_TYPE_QNAME;
}

store::Item_t UntypedXQType::get_qname() const
{
  return GENV_TYPESYSTEM.XS_UNTYPED_QNAME;
}

#if 0
static void foo()
{
  std::cout << "Hell" << std::endl;
}
#endif

NodeXQType::NodeXQType(
    const TypeManager* manager,
    rchandle<NodeTest> nodetest,
    xqtref_t contentType,
    TypeConstants::quantifier_t quantifier,
    bool nillable,
    bool builtin)
  :
  XQType(manager, NODE_TYPE_KIND, quantifier, builtin),
  m_nodetest(nodetest),
  m_content_type(contentType),
  m_nillable(nillable)
{
  //foo();
}

NodeXQType::NodeXQType(
    const TypeManager* manager,
    store::StoreConsts::NodeKind nodekind,
    const store::Item* nodename,
    xqtref_t contentType,
    TypeConstants::quantifier_t quantifier,
    bool nillable,
    bool builtin)
  :
  XQType(manager, NODE_TYPE_KIND, quantifier, builtin),
  m_nodetest(new NodeTest(nodekind, nodename)),
  m_content_type(contentType),
  m_nillable(nillable)
{
}

NodeXQType::NodeXQType(
    const NodeXQType& source,
    TypeConstants::quantifier_t quantifier)
  :
  XQType(source.m_manager, NODE_TYPE_KIND, quantifier, false),
  m_nodetest(source.m_nodetest),
  m_content_type(source.m_content_type),
  m_nillable(source.m_nillable)
{
}

bool NodeXQType::is_untyped() const
{
  return m_content_type == GENV_TYPESYSTEM.UNTYPED_TYPE;
}

std::ostream& NodeXQType::serialize(std::ostream& os) const
{
  rchandle<NodeTest> node_test = get_nodetest ();
  store::StoreConsts::NodeKind node_kind = node_test->get_node_kind();
  xqtref_t content_type = get_content_type ();
  rchandle<NodeNameTest> nametest = node_test->get_nametest();
  os << "[NodeXQType " << store::StoreConsts::toString (node_kind)
     << TypeOps::decode_quantifier (get_quantifier()) << " ";
  if (nametest != NULL) {
    os << "nametest=[uri: " << nametest->get_uri () << ", local: " << nametest->get_local () << "]";
  }
  if (content_type != NULL)
  {
    os << " content=";
    os << content_type->toString ();
  }
  return os << "]";
}

UserDefinedXQType::UserDefinedXQType(
    const TypeManager *manager,
    store::Item_t qname,
    xqtref_t baseType,
    TypeConstants::quantifier_t quantifier,
    content_kind_t contentKind)
  :
  XQType(manager, USER_DEFINED_KIND, quantifier, false),
  m_qname(qname),
  m_baseType(baseType),
  m_contentKind(contentKind),
  m_listItemType(NULL)
{
  ZORBA_ASSERT(baseType!=NULL);

  switch (baseType.getp()->type_kind())
  {
  case USER_DEFINED_KIND:
  {
    const UserDefinedXQType& udBaseType = static_cast<const UserDefinedXQType&>(*baseType);
    m_typeCategory = udBaseType.getTypeCategory();
    switch (m_typeCategory)
    {
    case ATOMIC_TYPE:
    case COMPLEX_TYPE:
      break;

    case LIST_TYPE:
      m_listItemType = udBaseType.getListItemType();
      break;

    case UNION_TYPE:
      m_unionItemTypes = udBaseType.getUnionItemTypes();
      break;

    default:
      ZORBA_ASSERT(false);
    }

    break;
  }
  case ATOMIC_TYPE_KIND:
  {
    m_typeCategory = ATOMIC_TYPE;
    break;
  }
  default:
  {
    m_typeCategory = COMPLEX_TYPE;
  }
  }
}

  // Constructor for List types
UserDefinedXQType::UserDefinedXQType(
    const TypeManager *manager,
    store::Item_t qname,
    xqtref_t baseType,
    TypeConstants::quantifier_t quantifier,
    const XQType* listItemType)
  :
  XQType(manager, USER_DEFINED_KIND, quantifier, false),
  m_qname(qname),
  m_baseType(baseType),
  m_typeCategory(LIST_TYPE),
  m_contentKind(SIMPLE_CONTENT_KIND),
  m_listItemType(listItemType)
{
  ZORBA_ASSERT( listItemType );
}

  // Constructor for Union types
UserDefinedXQType::UserDefinedXQType(
    const TypeManager *manager,
    store::Item_t qname,
    xqtref_t baseType,
    TypeConstants::quantifier_t quantifier,
    std::vector<const XQType*> unionItemTypes)
  :
  XQType(manager, USER_DEFINED_KIND, quantifier, false),
  m_qname(qname),
  m_baseType(baseType),
  m_typeCategory(UNION_TYPE),
  m_contentKind(SIMPLE_CONTENT_KIND),
  m_unionItemTypes(unionItemTypes),
  m_listItemType(NULL)
{
}

bool UserDefinedXQType::isSuperTypeOf(const XQType& subType) const
{
  const XQType* subtype = &subType;

  do
  {
    if (this == subtype)
      return true;

    if (subtype->type_kind() == XQType::USER_DEFINED_KIND)
    {
      const UserDefinedXQType* tmp = static_cast<const UserDefinedXQType*>(subtype);
      subtype = tmp->getBaseType().getp();
    }
    else
    {
      return false;
    }
  }
  while(true);

  return false;
}

std::ostream& UserDefinedXQType::serialize(std::ostream& os) const
{
  std::string info = "";

  switch (m_typeCategory)
  {
  case ATOMIC_TYPE:
    info += "isAtomic";
    break;
  case COMPLEX_TYPE:
    info += "isComplex";
    break;
  case LIST_TYPE:
    info += " isList itemType:";
    info += m_listItemType->toString();
    break;
  case UNION_TYPE:
    info += " isUnion ";
    info += m_unionItemTypes.size() + ":";
    for ( unsigned int i=0; i<m_unionItemTypes.size(); i++)
    {
      info += m_unionItemTypes[i]->toString();
    }
    break;
  default:
    ZORBA_ASSERT(false);
  }

  return os << "[UserDefinedXQType " << " "
            << TypeOps::decode_quantifier (get_quantifier())
            << m_qname->getLocalName()->str() << "@"
            << m_qname->getNamespace()->str() << " "
            << info
            << " base:"
            << ( m_baseType ? TypeOps::toString(*m_baseType) : "NULL" )
            << " ]";
}

}  // namespace zorba
<commit_msg>fix in UserDefinedXQType::isSuperTypeOf()<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <iostream>
#include "system/globalenv.h"
#include "types/typeconstants.h"
#include "types/typeimpl.h"
#include "types/typeops.h"
#include "types/root_typemanager.h"
#include "zorbaerrors/Assert.h"

namespace zorba {

const char* XQType::KIND_STRINGS[XQType::MAX_TYPE_KIND] =
{
  "EMPTY_KIND",
  "ATOMIC_TYPE_KIND",
  "ITEM_KIND",
  "NODE_TYPE_KIND",
  "ANY_TYPE_KIND",
  "ANY_SIMPLE_TYPE_KIND",
  "UNTYPED_KIND",
  "NONE_KIND"
};

const char *AtomicXQType::ATOMIC_TYPE_CODE_STRINGS[TypeConstants::ATOMIC_TYPE_CODE_LIST_SIZE] =
{
  "XS_ANY_ATOMIC",
  "XS_STRING",
  "XS_NORMALIZED_STRING",
  "XS_TOKEN",
  "XS_LANGUAGE",
  "XS_NMTOKEN",
  "XS_NAME",
  "XS_NCNAME",
  "XS_ID",
  "XS_IDREF",
  "XS_ENTITY",
  "XS_UNTYPED_ATOMIC",
  "XS_DATETIME",
  "XS_DATE",
  "XS_TIME",
  "XS_DURATION",
  "XS_DT_DURATION",
  "XS_YM_DURATION",
  "XS_FLOAT",
  "XS_DOUBLE",
  "XS_DECIMAL",
  "XS_INTEGER",
  "XS_NON_POSITIVE_INTEGER",
  "XS_NEGATIVE_INTEGER",
  "XS_LONG",
  "XS_INT",
  "XS_SHORT",
  "XS_BYTE",
  "XS_NON_NEGATIVE_INTEGER",
  "XS_UNSIGNED_LONG",
  "XS_UNSIGNED_INT",
  "XS_UNSIGNED_SHORT",
  "XS_UNSIGNED_BYTE",
  "XS_POSITIVE_INTEGER",
  "XS_GYEAR_MONTH",
  "XS_GYEAR",
  "XS_GMONTH_DAY",
  "XS_GDAY",
  "XS_GMONTH",
  "XS_BOOLEAN",
  "XS_BASE64BINARY",
  "XS_HEXBINARY",
  "XS_ANY_URI",
  "XS_QNAME",
  "XS_NOTATION"
};

std::ostream& XQType::serialize(std::ostream& os) const
{
  return os << "[XQType " << KIND_STRINGS[type_kind()]
            << TypeOps::decode_quantifier(get_quantifier()) << "]";
}

std::string XQType::toString() const
{
  std::ostringstream os;
  serialize(os);
  return os.str();
}

std::ostream& AtomicXQType::serialize(std::ostream& os) const
{
  return os << "[AtomicXQType " << ATOMIC_TYPE_CODE_STRINGS[get_type_code()]
            << TypeOps::decode_quantifier (get_quantifier()) << "]";
}

store::Item_t AtomicXQType::get_qname() const
{
  return GENV_TYPESYSTEM.m_atomic_typecode_qname_map[m_type_code];
}

store::Item_t AnyXQType::get_qname() const
{
  return GENV_TYPESYSTEM.XS_ANY_TYPE_QNAME;
}

store::Item_t AnySimpleXQType::get_qname() const
{
  return GENV_TYPESYSTEM.XS_ANY_SIMPLE_TYPE_QNAME;
}

store::Item_t UntypedXQType::get_qname() const
{
  return GENV_TYPESYSTEM.XS_UNTYPED_QNAME;
}

#if 0
static void foo()
{
  std::cout << "Hell" << std::endl;
}
#endif

NodeXQType::NodeXQType(
    const TypeManager* manager,
    rchandle<NodeTest> nodetest,
    xqtref_t contentType,
    TypeConstants::quantifier_t quantifier,
    bool nillable,
    bool builtin)
  :
  XQType(manager, NODE_TYPE_KIND, quantifier, builtin),
  m_nodetest(nodetest),
  m_content_type(contentType),
  m_nillable(nillable)
{
  //foo();
}

NodeXQType::NodeXQType(
    const TypeManager* manager,
    store::StoreConsts::NodeKind nodekind,
    const store::Item* nodename,
    xqtref_t contentType,
    TypeConstants::quantifier_t quantifier,
    bool nillable,
    bool builtin)
  :
  XQType(manager, NODE_TYPE_KIND, quantifier, builtin),
  m_nodetest(new NodeTest(nodekind, nodename)),
  m_content_type(contentType),
  m_nillable(nillable)
{
}

NodeXQType::NodeXQType(
    const NodeXQType& source,
    TypeConstants::quantifier_t quantifier)
  :
  XQType(source.m_manager, NODE_TYPE_KIND, quantifier, false),
  m_nodetest(source.m_nodetest),
  m_content_type(source.m_content_type),
  m_nillable(source.m_nillable)
{
}

bool NodeXQType::is_untyped() const
{
  return m_content_type == GENV_TYPESYSTEM.UNTYPED_TYPE;
}

std::ostream& NodeXQType::serialize(std::ostream& os) const
{
  rchandle<NodeTest> node_test = get_nodetest ();
  store::StoreConsts::NodeKind node_kind = node_test->get_node_kind();
  xqtref_t content_type = get_content_type ();
  rchandle<NodeNameTest> nametest = node_test->get_nametest();
  os << "[NodeXQType " << store::StoreConsts::toString (node_kind)
     << TypeOps::decode_quantifier (get_quantifier()) << " ";
  if (nametest != NULL) {
    os << "nametest=[uri: " << nametest->get_uri () << ", local: " << nametest->get_local () << "]";
  }
  if (content_type != NULL)
  {
    os << " content=";
    os << content_type->toString ();
  }
  return os << "]";
}

UserDefinedXQType::UserDefinedXQType(
    const TypeManager *manager,
    store::Item_t qname,
    xqtref_t baseType,
    TypeConstants::quantifier_t quantifier,
    content_kind_t contentKind)
  :
  XQType(manager, USER_DEFINED_KIND, quantifier, false),
  m_qname(qname),
  m_baseType(baseType),
  m_contentKind(contentKind),
  m_listItemType(NULL)
{
  ZORBA_ASSERT(baseType!=NULL);

  switch (baseType.getp()->type_kind())
  {
  case USER_DEFINED_KIND:
  {
    const UserDefinedXQType& udBaseType = static_cast<const UserDefinedXQType&>(*baseType);
    m_typeCategory = udBaseType.getTypeCategory();
    switch (m_typeCategory)
    {
    case ATOMIC_TYPE:
    case COMPLEX_TYPE:
      break;

    case LIST_TYPE:
      m_listItemType = udBaseType.getListItemType();
      break;

    case UNION_TYPE:
      m_unionItemTypes = udBaseType.getUnionItemTypes();
      break;

    default:
      ZORBA_ASSERT(false);
    }

    break;
  }
  case ATOMIC_TYPE_KIND:
  {
    m_typeCategory = ATOMIC_TYPE;
    break;
  }
  default:
  {
    m_typeCategory = COMPLEX_TYPE;
  }
  }
}

  // Constructor for List types
UserDefinedXQType::UserDefinedXQType(
    const TypeManager *manager,
    store::Item_t qname,
    xqtref_t baseType,
    TypeConstants::quantifier_t quantifier,
    const XQType* listItemType)
  :
  XQType(manager, USER_DEFINED_KIND, quantifier, false),
  m_qname(qname),
  m_baseType(baseType),
  m_typeCategory(LIST_TYPE),
  m_contentKind(SIMPLE_CONTENT_KIND),
  m_listItemType(listItemType)
{
  ZORBA_ASSERT( listItemType );
}

  // Constructor for Union types
UserDefinedXQType::UserDefinedXQType(
    const TypeManager *manager,
    store::Item_t qname,
    xqtref_t baseType,
    TypeConstants::quantifier_t quantifier,
    std::vector<const XQType*> unionItemTypes)
  :
  XQType(manager, USER_DEFINED_KIND, quantifier, false),
  m_qname(qname),
  m_baseType(baseType),
  m_typeCategory(UNION_TYPE),
  m_contentKind(SIMPLE_CONTENT_KIND),
  m_unionItemTypes(unionItemTypes),
  m_listItemType(NULL)
{
}

bool UserDefinedXQType::isSuperTypeOf(const XQType& subType) const
{
  if (subType.type_kind() != XQType::USER_DEFINED_KIND)
    return false;

  const UserDefinedXQType* subtype = static_cast<const UserDefinedXQType*>(&subType);

  do
  {
    if (TypeOps::is_equal(*this, *subtype))
      return true;

    if (subtype->type_kind() == XQType::USER_DEFINED_KIND)
    {
      subtype = static_cast<const UserDefinedXQType*>(subtype->getBaseType().getp());
    }
    else
    {
      return false;
    }
  }
  while(true);

  return false;
}

std::ostream& UserDefinedXQType::serialize(std::ostream& os) const
{
  std::string info = "";

  switch (m_typeCategory)
  {
  case ATOMIC_TYPE:
    info += "isAtomic";
    break;
  case COMPLEX_TYPE:
    info += "isComplex";
    break;
  case LIST_TYPE:
    info += " isList itemType:";
    info += m_listItemType->toString();
    break;
  case UNION_TYPE:
    info += " isUnion ";
    info += m_unionItemTypes.size() + ":";
    for ( unsigned int i=0; i<m_unionItemTypes.size(); i++)
    {
      info += m_unionItemTypes[i]->toString();
    }
    break;
  default:
    ZORBA_ASSERT(false);
  }

  return os << "[UserDefinedXQType " << " "
            << TypeOps::decode_quantifier (get_quantifier())
            << m_qname->getLocalName()->str() << "@"
            << m_qname->getNamespace()->str() << " "
            << info
            << " base:"
            << ( m_baseType ? TypeOps::toString(*m_baseType) : "NULL" )
            << " ]";
}

}  // namespace zorba
<|endoftext|>


<commit_before>// Copyright 2013 Tanel Lebedev

#include "./main.h"

#include <sstream>

#include "Poco/Message.h"
#include "Poco/Util/Application.h"

#define ERRLEN 1024

namespace command_line_client {

bool syncing = false;

std::string model_change_to_string(
    KopsikModelChange &change) {
  std::stringstream ss;
  ss  << "model_type=" << change.ModelType
      << ", change_type=" << change.ChangeType
      << ", model_id=" << change.ModelID
      << ", GUID=" << change.GUID;
  return ss.str();
}

void main_change_callback(
    kopsik_api_result result,
    const char *errmsg,
    KopsikModelChange *change) {
  if (KOPSIK_API_SUCCESS != result) {
    std::cerr << "main_change_callback errmsg="
              << std::string(errmsg)
              << std::endl;
    return;
  }
  std::cout << "main_change_callback change="
            << model_change_to_string(*change)
            << std::endl;
}

void main_on_error_callback(
    const char *errmsg) {
  std::cerr << "main_on_error_callback errmsg="
            << std::string(errmsg)
            << std::endl;
}

void main_check_updates_callback(
    const int is_update_available,
    const char *url,
    const char *version) {
  if (KOPSIK_API_SUCCESS != result) {
    std::cerr << "main_check_updates_callback errmsg="
              << std::string(errmsg)
              << std::endl;
    return;
  }
  std::cout << "main_check_updates_callback is_update_available="
            << is_update_available
            << " url=" << std::string(url)
            << " version=" << std::string(version)
            << std::endl;
}

void main_online_callback() {
  std::cout << "main_online_callback" << std::endl;
}

void on_sync_result(
    kopsik_api_result result,
    const char *errmsg) {
  if (KOPSIK_API_SUCCESS != result) {
    std::cerr << "Error " << std::string(errmsg) << std::endl;
    syncing = false;
    return;
  }
  std::cout << "Success" << std::endl;
  syncing = false;
}

Main::Main()
    : ctx_(0) {
  kopsik_set_log_path("kopsik.log");
  ctx_ = kopsik_context_init(
    "cmdline",
    "0.0.1",
    main_change_callback,
    main_on_error_callback,
    main_check_updates_callback,
    main_online_callback);
  poco_assert(ctx_);
}

Main::~Main() {
  kopsik_context_clear(ctx_);
}

void Main::exception(const Poco::Exception& exc) {
  std::cerr << exc.displayText() << std::endl;
}

void Main::exception(const std::exception& exc) {
  std::cerr << exc.what() << std::endl;
}

void Main::exception() {
  std::cerr << "unknown exception" << std::endl;
}

void Main::initialize(Poco::Util::Application &self) { // NOLINT
  Poco::Util::Application::initialize(self);
};

void Main::usage() const {
  std::cout << "Recognized commands are: "
    "sync, start, stop, status, pushable, list, continue, listen"
    << std::endl;
}

void Main::defineOptions(Poco::Util::OptionSet& options) { // NOLINT
  Poco::Util::Application::defineOptions(options);
  options.addOption(Poco::Util::Option(
    "verbose", "v", "verbose logging, to the console"));
}

int Main::sync() {
  syncing = true;
  kopsik_sync(ctx_);
  while (syncing) {
    Poco::Thread::sleep(1000);
  }
  return Poco::Util::Application::EXIT_OK;
}

int Main::continueTimeEntry() {
  char errmsg[ERRLEN];
  KopsikTimeEntryViewItem *first = 0;
  if (KOPSIK_API_SUCCESS != kopsik_time_entry_view_items(
      ctx_, errmsg, ERRLEN, &first)) {
    std::cerr << std::string(errmsg) << std::endl;
    kopsik_time_entry_view_item_clear(first);
    return Poco::Util::Application::EXIT_SOFTWARE;
  }

  if (!first) {
    std::cout << "No time entry found to continue." << std::endl;
    kopsik_time_entry_view_item_clear(first);
    return Poco::Util::Application::EXIT_OK;
  }

  KopsikTimeEntryViewItem *te = kopsik_time_entry_view_item_init();
  if (KOPSIK_API_SUCCESS != kopsik_continue(
      ctx_, errmsg, ERRLEN, first->GUID, te)) {
    std::cerr << std::string(errmsg) << std::endl;
    kopsik_time_entry_view_item_clear(first);
    kopsik_time_entry_view_item_clear(te);
    return Poco::Util::Application::EXIT_SOFTWARE;
  }

  kopsik_time_entry_view_item_clear(first);
  kopsik_time_entry_view_item_clear(te);
  return Poco::Util::Application::EXIT_OK;
}

int Main::status() {
  KopsikTimeEntryViewItem *te = kopsik_time_entry_view_item_init();
  int found(0);
  char errmsg[ERRLEN];
  if (KOPSIK_API_SUCCESS != kopsik_running_time_entry_view_item(
      ctx_, errmsg, ERRLEN, te, &found)) {
    std::cerr << std::string(errmsg) << std::endl;
    kopsik_time_entry_view_item_clear(te);
    return Poco::Util::Application::EXIT_SOFTWARE;
  }
  if (found) {
    std::cout << "Tracking: " << te->Description << std::endl;
  } else {
    std::cout << "Not tracking." << std::endl;
  }
  kopsik_time_entry_view_item_clear(te);
  return Poco::Util::Application::EXIT_OK;
}

int Main::main(const std::vector<std::string>& args) {
  if (args.empty()) {
    usage();
    return Poco::Util::Application::EXIT_USAGE;
  }

  char* apitoken = getenv("TOGGL_API_TOKEN");
  if (!apitoken) {
    std::cerr << "Please set TOGGL_API_TOKEN in environment"
              << std::endl;
    return Poco::Util::Application::EXIT_USAGE;
  }

  char errmsg[ERRLEN];
  if (KOPSIK_API_SUCCESS != kopsik_set_db_path(
      ctx_, errmsg, ERRLEN, "kopsik.db")) {
    std::cerr << errmsg << std::endl;
    return Poco::Util::Application::EXIT_SOFTWARE;
  }

  Poco::ErrorHandler::set(this);

  // Start session in lib
  if (KOPSIK_API_SUCCESS != kopsik_set_api_token(
      ctx_, errmsg, ERRLEN, apitoken)) {
    std::cerr << errmsg << std::endl;
    return Poco::Util::Application::EXIT_SOFTWARE;
  }

  // Load user that is referenced by the session
  KopsikUser *user = kopsik_user_init();
  if (KOPSIK_API_SUCCESS != kopsik_current_user(
      ctx_, errmsg, ERRLEN, user)) {
    std::cerr << std::string(errmsg) << std::endl;
    return Poco::Util::Application::EXIT_SOFTWARE;
  }
  kopsik_user_clear(user);

  // Handle commands
  if ("sync" == args[0]) {
    return sync();
  }
  if ("status" == args[0]) {
    return status();
  }
  if ("pushable" == args[0]) {
    return showPushableData();
  }
  if ("start" == args[0]) {
    return startTimeEntry();
  }
  if ("stop" == args[0]) {
    return stopTimeEntry();
  }
  if ("list" == args[0]) {
    return listTimeEntries();
  }
  if ("listen" == args[0]) {
    return listenToWebSocket();
  }
  if ("continue" == args[0]) {
    return continueTimeEntry();
  }

  usage();
  return Poco::Util::Application::EXIT_USAGE;
}

int Main::showPushableData() {
  KopsikPushableModelStats stats;
  char errmsg[ERRLEN];
  if (KOPSIK_API_SUCCESS != kopsik_pushable_models(
          ctx_, errmsg, ERRLEN, &stats)) {
      std::cerr << std::string(errmsg) << std::endl;
      return Poco::Util::Application::EXIT_SOFTWARE;
  }
  std::cout << stats.TimeEntries
            << " pushable time entries."
            << std::endl;
  return Poco::Util::Application::EXIT_OK;
}

std::string Main::timeEntryToString(
    KopsikTimeEntryViewItem *item) {
  std::stringstream ss;
  ss << item->Description;
  if (item->ProjectAndTaskLabel) {
    ss << " [" << item->ProjectAndTaskLabel << "]";
  }
  if (item->Duration) {
    ss << " (" << item->Duration << ")";
  }
  return ss.str();
}

int Main::listenToWebSocket() {
  std::cout << "Listening to websocket.. " << std::endl;
  kopsik_websocket_switch(ctx_, 1);
  while (true) {
    Poco::Thread::sleep(1000);
  }
  kopsik_websocket_switch(ctx_, 0);
  return Poco::Util::Application::EXIT_OK;
}

int Main::listTimeEntries() {
  KopsikTimeEntryViewItem *first = 0;
  char errmsg[ERRLEN];
  if (KOPSIK_API_SUCCESS != kopsik_time_entry_view_items(
      ctx_, errmsg, ERRLEN, &first)) {
    std::cerr << std::string(errmsg) << std::endl;
    kopsik_time_entry_view_item_clear(first);
    return Poco::Util::Application::EXIT_SOFTWARE;
  }
  int n = 0;
  while (true) {
    std::cout << timeEntryToString(first) << std::endl;
    n++;
    if (!first->Next) {
      break;
    }
    first = reinterpret_cast<KopsikTimeEntryViewItem *>(first->Next);
  }
  std::cout << "Got " << n << " time entry view items." << std::endl;
  kopsik_time_entry_view_item_clear(first);
  return Poco::Util::Application::EXIT_OK;
}

int Main::startTimeEntry() {
  KopsikTimeEntryViewItem *te = kopsik_time_entry_view_item_init();
  char errmsg[ERRLEN];
  if (KOPSIK_API_SUCCESS != kopsik_start(
    ctx_, errmsg, ERRLEN, "New time entry", "", 0, 0, te)) {
    std::cerr << errmsg << std::endl;
    kopsik_time_entry_view_item_clear(te);
    return Poco::Util::Application::EXIT_SOFTWARE;
  }
  kopsik_time_entry_view_item_clear(te);
  return Poco::Util::Application::EXIT_OK;
}

int Main::stopTimeEntry() {
  KopsikTimeEntryViewItem *te = kopsik_time_entry_view_item_init();
  int was_found(0);
  char errmsg[ERRLEN];
  if (KOPSIK_API_SUCCESS != kopsik_stop(
      ctx_, errmsg, ERRLEN, te, &was_found)) {
    std::cerr << errmsg << std::endl;
    kopsik_time_entry_view_item_clear(te);
    return Poco::Util::Application::EXIT_SOFTWARE;
  }
  if (!was_found) {
    std::cout << "No time entry found to stop." << std::endl;
  }
  kopsik_time_entry_view_item_clear(te);
  return Poco::Util::Application::EXIT_OK;
}

}  // namespace command_line_client
<commit_msg>Fix command line app build<commit_after>// Copyright 2013 Tanel Lebedev

#include "./main.h"

#include <sstream>

#include "Poco/Message.h"
#include "Poco/Util/Application.h"

#define ERRLEN 1024

namespace command_line_client {

bool syncing = false;

std::string model_change_to_string(
    KopsikModelChange &change) {
  std::stringstream ss;
  ss  << "model_type=" << change.ModelType
      << ", change_type=" << change.ChangeType
      << ", model_id=" << change.ModelID
      << ", GUID=" << change.GUID;
  return ss.str();
}

void main_change_callback(
    kopsik_api_result result,
    const char *errmsg,
    KopsikModelChange *change) {
  if (KOPSIK_API_SUCCESS != result) {
    std::cerr << "main_change_callback errmsg="
              << std::string(errmsg)
              << std::endl;
    return;
  }
  std::cout << "main_change_callback change="
            << model_change_to_string(*change)
            << std::endl;
}

void main_on_error_callback(
    const char *errmsg) {
  std::cerr << "main_on_error_callback errmsg="
            << std::string(errmsg)
            << std::endl;
}

void main_check_updates_callback(
    const int is_update_available,
    const char *url,
    const char *version) {
  std::cout << "main_check_updates_callback is_update_available="
            << is_update_available
            << " url=" << std::string(url)
            << " version=" << std::string(version)
            << std::endl;
}

void main_online_callback() {
  std::cout << "main_online_callback" << std::endl;
}

void on_sync_result(
    kopsik_api_result result,
    const char *errmsg) {
  if (KOPSIK_API_SUCCESS != result) {
    std::cerr << "Error " << std::string(errmsg) << std::endl;
    syncing = false;
    return;
  }
  std::cout << "Success" << std::endl;
  syncing = false;
}

Main::Main()
    : ctx_(0) {
  kopsik_set_log_path("kopsik.log");
  ctx_ = kopsik_context_init(
    "cmdline",
    "0.0.1",
    main_change_callback,
    main_on_error_callback,
    main_check_updates_callback,
    main_online_callback);
  poco_assert(ctx_);
}

Main::~Main() {
  kopsik_context_clear(ctx_);
}

void Main::exception(const Poco::Exception& exc) {
  std::cerr << exc.displayText() << std::endl;
}

void Main::exception(const std::exception& exc) {
  std::cerr << exc.what() << std::endl;
}

void Main::exception() {
  std::cerr << "unknown exception" << std::endl;
}

void Main::initialize(Poco::Util::Application &self) { // NOLINT
  Poco::Util::Application::initialize(self);
};

void Main::usage() const {
  std::cout << "Recognized commands are: "
    "sync, start, stop, status, pushable, list, continue, listen"
    << std::endl;
}

void Main::defineOptions(Poco::Util::OptionSet& options) { // NOLINT
  Poco::Util::Application::defineOptions(options);
  options.addOption(Poco::Util::Option(
    "verbose", "v", "verbose logging, to the console"));
}

int Main::sync() {
  syncing = true;
  kopsik_sync(ctx_);
  while (syncing) {
    Poco::Thread::sleep(1000);
  }
  return Poco::Util::Application::EXIT_OK;
}

int Main::continueTimeEntry() {
  char errmsg[ERRLEN];
  KopsikTimeEntryViewItem *first = 0;
  if (KOPSIK_API_SUCCESS != kopsik_time_entry_view_items(
      ctx_, errmsg, ERRLEN, &first)) {
    std::cerr << std::string(errmsg) << std::endl;
    kopsik_time_entry_view_item_clear(first);
    return Poco::Util::Application::EXIT_SOFTWARE;
  }

  if (!first) {
    std::cout << "No time entry found to continue." << std::endl;
    kopsik_time_entry_view_item_clear(first);
    return Poco::Util::Application::EXIT_OK;
  }

  KopsikTimeEntryViewItem *te = kopsik_time_entry_view_item_init();
  if (KOPSIK_API_SUCCESS != kopsik_continue(
      ctx_, errmsg, ERRLEN, first->GUID, te)) {
    std::cerr << std::string(errmsg) << std::endl;
    kopsik_time_entry_view_item_clear(first);
    kopsik_time_entry_view_item_clear(te);
    return Poco::Util::Application::EXIT_SOFTWARE;
  }

  kopsik_time_entry_view_item_clear(first);
  kopsik_time_entry_view_item_clear(te);
  return Poco::Util::Application::EXIT_OK;
}

int Main::status() {
  KopsikTimeEntryViewItem *te = kopsik_time_entry_view_item_init();
  int found(0);
  char errmsg[ERRLEN];
  if (KOPSIK_API_SUCCESS != kopsik_running_time_entry_view_item(
      ctx_, errmsg, ERRLEN, te, &found)) {
    std::cerr << std::string(errmsg) << std::endl;
    kopsik_time_entry_view_item_clear(te);
    return Poco::Util::Application::EXIT_SOFTWARE;
  }
  if (found) {
    std::cout << "Tracking: " << te->Description << std::endl;
  } else {
    std::cout << "Not tracking." << std::endl;
  }
  kopsik_time_entry_view_item_clear(te);
  return Poco::Util::Application::EXIT_OK;
}

int Main::main(const std::vector<std::string>& args) {
  if (args.empty()) {
    usage();
    return Poco::Util::Application::EXIT_USAGE;
  }

  char* apitoken = getenv("TOGGL_API_TOKEN");
  if (!apitoken) {
    std::cerr << "Please set TOGGL_API_TOKEN in environment"
              << std::endl;
    return Poco::Util::Application::EXIT_USAGE;
  }

  char errmsg[ERRLEN];
  if (KOPSIK_API_SUCCESS != kopsik_set_db_path(
      ctx_, errmsg, ERRLEN, "kopsik.db")) {
    std::cerr << errmsg << std::endl;
    return Poco::Util::Application::EXIT_SOFTWARE;
  }

  Poco::ErrorHandler::set(this);

  // Start session in lib
  if (KOPSIK_API_SUCCESS != kopsik_set_api_token(
      ctx_, errmsg, ERRLEN, apitoken)) {
    std::cerr << errmsg << std::endl;
    return Poco::Util::Application::EXIT_SOFTWARE;
  }

  // Load user that is referenced by the session
  KopsikUser *user = kopsik_user_init();
  if (KOPSIK_API_SUCCESS != kopsik_current_user(
      ctx_, errmsg, ERRLEN, user)) {
    std::cerr << std::string(errmsg) << std::endl;
    return Poco::Util::Application::EXIT_SOFTWARE;
  }
  kopsik_user_clear(user);

  // Handle commands
  if ("sync" == args[0]) {
    return sync();
  }
  if ("status" == args[0]) {
    return status();
  }
  if ("pushable" == args[0]) {
    return showPushableData();
  }
  if ("start" == args[0]) {
    return startTimeEntry();
  }
  if ("stop" == args[0]) {
    return stopTimeEntry();
  }
  if ("list" == args[0]) {
    return listTimeEntries();
  }
  if ("listen" == args[0]) {
    return listenToWebSocket();
  }
  if ("continue" == args[0]) {
    return continueTimeEntry();
  }

  usage();
  return Poco::Util::Application::EXIT_USAGE;
}

int Main::showPushableData() {
  KopsikPushableModelStats stats;
  char errmsg[ERRLEN];
  if (KOPSIK_API_SUCCESS != kopsik_pushable_models(
          ctx_, errmsg, ERRLEN, &stats)) {
      std::cerr << std::string(errmsg) << std::endl;
      return Poco::Util::Application::EXIT_SOFTWARE;
  }
  std::cout << stats.TimeEntries
            << " pushable time entries."
            << std::endl;
  return Poco::Util::Application::EXIT_OK;
}

std::string Main::timeEntryToString(
    KopsikTimeEntryViewItem *item) {
  std::stringstream ss;
  ss << item->Description;
  if (item->ProjectAndTaskLabel) {
    ss << " [" << item->ProjectAndTaskLabel << "]";
  }
  if (item->Duration) {
    ss << " (" << item->Duration << ")";
  }
  return ss.str();
}

int Main::listenToWebSocket() {
  std::cout << "Listening to websocket.. " << std::endl;
  kopsik_websocket_switch(ctx_, 1);
  while (true) {
    Poco::Thread::sleep(1000);
  }
  kopsik_websocket_switch(ctx_, 0);
  return Poco::Util::Application::EXIT_OK;
}

int Main::listTimeEntries() {
  KopsikTimeEntryViewItem *first = 0;
  char errmsg[ERRLEN];
  if (KOPSIK_API_SUCCESS != kopsik_time_entry_view_items(
      ctx_, errmsg, ERRLEN, &first)) {
    std::cerr << std::string(errmsg) << std::endl;
    kopsik_time_entry_view_item_clear(first);
    return Poco::Util::Application::EXIT_SOFTWARE;
  }
  int n = 0;
  while (true) {
    std::cout << timeEntryToString(first) << std::endl;
    n++;
    if (!first->Next) {
      break;
    }
    first = reinterpret_cast<KopsikTimeEntryViewItem *>(first->Next);
  }
  std::cout << "Got " << n << " time entry view items." << std::endl;
  kopsik_time_entry_view_item_clear(first);
  return Poco::Util::Application::EXIT_OK;
}

int Main::startTimeEntry() {
  KopsikTimeEntryViewItem *te = kopsik_time_entry_view_item_init();
  char errmsg[ERRLEN];
  if (KOPSIK_API_SUCCESS != kopsik_start(
    ctx_, errmsg, ERRLEN, "New time entry", "", 0, 0, te)) {
    std::cerr << errmsg << std::endl;
    kopsik_time_entry_view_item_clear(te);
    return Poco::Util::Application::EXIT_SOFTWARE;
  }
  kopsik_time_entry_view_item_clear(te);
  return Poco::Util::Application::EXIT_OK;
}

int Main::stopTimeEntry() {
  KopsikTimeEntryViewItem *te = kopsik_time_entry_view_item_init();
  int was_found(0);
  char errmsg[ERRLEN];
  if (KOPSIK_API_SUCCESS != kopsik_stop(
      ctx_, errmsg, ERRLEN, te, &was_found)) {
    std::cerr << errmsg << std::endl;
    kopsik_time_entry_view_item_clear(te);
    return Poco::Util::Application::EXIT_SOFTWARE;
  }
  if (!was_found) {
    std::cout << "No time entry found to stop." << std::endl;
  }
  kopsik_time_entry_view_item_clear(te);
  return Poco::Util::Application::EXIT_OK;
}

}  // namespace command_line_client
<|endoftext|>


<commit_before>
#include "rpi_gpio.hpp"
#include <cossb.hpp>
#include <3rdparty/bcm2835.h>

using namespace std;

USE_COMPONENT_INTERFACE(rpi_gpio)

rpi_gpio::rpi_gpio()
:cossb::interface::icomponent(COMPONENT(rpi_gpio)){
	// TODO Auto-generated constructor stub

}

rpi_gpio::~rpi_gpio() {

}

bool rpi_gpio::setup()
{
	if(!bcm2835_init())
		return false;

	//set output port
	for(auto outport:get_profile()->gets(profile::section::property, "output")){
		int port = outport.asInt(-1);
		_portmap[port] = true;
		bcm2835_gpio_fsel(port, BCM2835_GPIO_FSEL_OUTP);
	}

	//set input port
	for(auto inport:get_profile()->gets(profile::section::property, "input")){
		int port = inport.asInt(-1);
		_portmap[port] = false;
		bcm2835_gpio_fsel(port, BCM2835_GPIO_FSEL_INPT);
		bcm2835_gpio_set_pud(port, BCM2835_GPIO_PUD_UP);
	}

	return true;
}

bool rpi_gpio::run()
{
	map<int, unsigned char> port_read;
	string read="";
	for(auto const& port:_portmap){
		if(!port.second){
			port_read[port.first] = bcm2835_gpio_lev(port.first);
			read += fmt::format("{}:0x{0:x}\t",port.first, port_read[port.first]);
		}
	}

	if(!port_read.empty()){
		cossb::message msg(this, cossb::base::msg_type::DATA);
		msg.pack(port_read);
		cossb_broker->publish("rpi_gpio_read", msg);
		cossb_log->log(log::loglevel::INFO, fmt::format("Read GPIO: {}",read));
	}

	return true;
}

bool rpi_gpio::stop()
{
	if(!bcm2835_close())
		return false;

	return true;
}

void rpi_gpio::subscribe(cossb::message* const msg)
{
	switch(msg->get_frame()->type) {
		case cossb::base::msg_type::REQUEST: break;
		case cossb::base::msg_type::DATA: {

			//subscribe emotion data
			try {
				map<int, unsigned char> data = boost::any_cast<map<int, unsigned char>>(*msg); //{key, value} pair

				//1. extract keys
				vector<int> keys;
				for(auto const& port: data)
					keys.push_back(port.first);

				//2. compare port set, then write data if it is outport
				for(auto const& key:keys){
					if(_portmap.find(key)!=_portmap.end()){
						if(_portmap[key]){ //output port
							bcm2835_gpio_write(key, data[key]); //write data
							cossb_log->log(log::loglevel::INFO, fmt::format("Write GPIO({}) : 0x{0:x}", key, data[key]));
						}
					}
				}
			}
			catch(const boost::bad_any_cast&){
				cossb_log->log(log::loglevel::ERROR, "Invalid type casting, should be map<int, unsigned char> type.");
			}
		} break;
		case cossb::base::msg_type::RESPONSE: break;
		case cossb::base::msg_type::EVENT:  break;
		}
}

<commit_msg>- update<commit_after>
#include "rpi_gpio.hpp"
#include <cossb.hpp>
#include <3rdparty/bcm2835.h>

using namespace std;

USE_COMPONENT_INTERFACE(rpi_gpio)

rpi_gpio::rpi_gpio()
:cossb::interface::icomponent(COMPONENT(rpi_gpio)){
	// TODO Auto-generated constructor stub

}

rpi_gpio::~rpi_gpio() {

}

bool rpi_gpio::setup()
{
	if(!bcm2835_init())
		return false;

	//set output port
	for(auto outport:get_profile()->gets(profile::section::property, "output")){
		int port = outport.asInt(-1);
		_portmap[port] = true;
		bcm2835_gpio_fsel(port, BCM2835_GPIO_FSEL_OUTP);
	}

	//set input port
	for(auto inport:get_profile()->gets(profile::section::property, "input")){
		int port = inport.asInt(-1);
		_portmap[port] = false;
		bcm2835_gpio_fsel(port, BCM2835_GPIO_FSEL_INPT);
		bcm2835_gpio_set_pud(port, BCM2835_GPIO_PUD_UP);
	}

	return true;
}

bool rpi_gpio::run()
{
	map<int, unsigned char> port_read;
	for(auto const& port:_portmap){
		if(!port.second){
			port_read[port.first] = bcm2835_gpio_lev(port.first);
			cossb_log->log(log::loglevel::INFO, fmt::format("Read GPIO({}):0x{0:x}",port.first, port_read[port.first]));
		}
	}

	if(!port_read.empty()){
		cossb::message msg(this, cossb::base::msg_type::DATA);
		msg.pack(port_read);
		cossb_broker->publish("rpi_gpio_read", msg);
	}

	return true;
}

bool rpi_gpio::stop()
{
	if(!bcm2835_close())
		return false;

	return true;
}

void rpi_gpio::subscribe(cossb::message* const msg)
{
	switch(msg->get_frame()->type) {
		case cossb::base::msg_type::REQUEST: break;
		case cossb::base::msg_type::DATA: {

			//subscribe emotion data
			try {
				map<int, unsigned char> data = boost::any_cast<map<int, unsigned char>>(*msg); //{key, value} pair

				//1. extract keys
				vector<int> keys;
				for(auto const& port: data)
					keys.push_back(port.first);

				//2. compare port set, then write data if it is outport
				for(auto const& key:keys){
					if(_portmap.find(key)!=_portmap.end()){
						if(_portmap[key]){ //output port
							bcm2835_gpio_write(key, data[key]); //write data
							cossb_log->log(log::loglevel::INFO, fmt::format("Write GPIO({}) : 0x{0:x}", key, data[key]));
						}
					}
				}
			}
			catch(const boost::bad_any_cast&){
				cossb_log->log(log::loglevel::ERROR, "Invalid type casting, should be map<int, unsigned char> type.");
			}
		} break;
		case cossb::base::msg_type::RESPONSE: break;
		case cossb::base::msg_type::EVENT:  break;
		}
}

<|endoftext|>


<commit_before>#include <math.h>
#include <stdio.h>

#include "particle.h"
#include "simulation.h"
#include "vector3d.h"
#include "boundaryFieldEvaluator.h"
#include "util.h"

void Simulation::initializeHarris() {
	//boundaryConditionTypeX = SUPER_CONDUCTOR_LEFT;
	//boundaryConditionTypeX = FREE_BOTH;
	boundaryConditionTypeX = FREE_MIRROR_BOTH;
	double l = 5*deltaX;
    //E0 = Vector3d(0, 0, 0);
	//B0 = Vector3d(0, 0, 0);
	for (int i = 0; i < xnumberAdded; ++i) {
		for (int j = 0; j < ynumberAdded; ++j) {
			for (int k = 0; k < znumberAdded; ++k) {
				Bfield[i][j][k] = B0*tanh((xgrid[i] - 1.5*xsizeGeneral)/l);
				newBfield[i][j][k] = Bfield[i][j][k];
			}
		}
	}
	createParticlesHarris(l);
	E0 = Vector3d(0, 0, 0);

	for (int i = 0; i < xnumberAdded + 1; ++i) {
		for (int j = 0; j < ynumberAdded + 1; ++j) {
			for (int k = 0; k < znumberAdded + 1; ++k) {
				Efield[i][j][k] = E0;
				newEfield[i][j][k] = Efield[i][j][k];
			}
		}
	}

	rightBoundaryFieldEvaluator = new ConstantBoundaryFieldEvaluator(E0, B0);
	Vector3d B1 = B0*(-1.0);
	leftBoundaryFieldEvaluator = new ConstantBoundaryFieldEvaluator(E0, B1);

}

void Simulation::createParticlesHarris(double harrisWidth) {
	evaluateParticleTypesAlpha();
	if (rank == 0) printf("creating particles harris\n");
	fflush(stdout);
	if (rank == 0) printLog("creating particles harris\n");
	double n0 = types[0].concentration;
	int n = 0;
	double ionTemperatureFactor = 5;
	double electronTemperature = B0.scalarMult(B0)/(2*kBoltzman_normalized*types[0].concentration*(1 + ionTemperatureFactor)*4*pi);
	types[0].temperatureX = electronTemperature;
	types[0].temperatureY = electronTemperature;
	types[0].temperatureZ = electronTemperature;
	for(int t = 1; t < typesNumber; ++t) {
		types[t].temperatureX = types[0].temperatureX*ionTemperatureFactor;
		types[t].temperatureY = types[0].temperatureY*ionTemperatureFactor;
		types[t].temperatureZ = types[0].temperatureZ*ionTemperatureFactor;
	}
	//int density = ; %
	//for (int i = 0; i < xnumber; ++i) {
	for (int i = 1 + additionalBinNumber; i < xnumberAdded - additionalBinNumber - 1; ++i) {
		for (int j = 1 + additionalBinNumber; j < ynumberAdded - additionalBinNumber - 1; ++j) {
			for (int k = 1 + additionalBinNumber; k < znumberAdded - additionalBinNumber - 1; ++k) {
				//int maxParticlesPerBin = types[0].particlesPerBin;
				double x = xgrid[i] + 0.0001 * deltaX;
				double y = ygrid[j] + 0.0001 * deltaY;
				double z = zgrid[k] + 0.0001 * deltaZ;
				double ch = cosh((xgrid[i] - 1.5*xsizeGeneral)/harrisWidth);
				double concentr = n0/(ch*ch);
				//for (int l = 0; l < maxParticlesPerBin; ++l) {
				for (int typeCounter = 0; typeCounter < typesNumber; ++typeCounter) {
					double weight = (concentr* volumeB()) / types[typeCounter].particlesPerBin ;
					double deltaXParticles = types[typeCounter].particesDeltaX;
					double deltaYParticles = types[typeCounter].particesDeltaY;
					double deltaZParticles = types[typeCounter].particesDeltaZ;
					//if (l < types[typeCounter].particlesPerBin) {
					for (int l = 0; l < types[typeCounter].particlesPerBin; ++l) {
						ParticleTypes type = types[typeCounter].type;
						Particle* particle = createParticle(n, i, j, k, weight, type, types[typeCounter],
						                                    types[typeCounter].temperatureX,
						                                    types[typeCounter].temperatureY,
						                                    types[typeCounter].temperatureZ);
						n++;
						particle->coordinates.x = x + deltaXParticles * l;
						particle->coordinates.y = y + deltaYParticles * l;
						particle->coordinates.z = z + deltaZParticles * l;
						//particle->coordinates.x = middleXgrid[i];
						//particle->coordinates.y = middleYgrid[j];
						//particle->coordinates.z = middleZgrid[k];

						//particle->coordinates.x = xgrid[i] + uniformDistribution()*deltaX;
						//particle->coordinates.y = ygrid[j] + uniformDistribution()*deltaY;
						//particle->coordinates.z = zgrid[k] + uniformDistribution()*deltaZ;
						particle->initialCoordinates = particle->coordinates;

						double P=harrisWidth*B0.norm()*types[typeCounter].charge;
						Vector3d V = Vector3d(0, 1.0, 0) * (-2*kBoltzman_normalized*speed_of_light_normalized*types[typeCounter].temperatureX/P);

							particle->addVelocity(V, speed_of_light_normalized);

						Vector3d momentum = particle->getMomentum();
						particle->initialMomentum = momentum;
						particle->prevMomentum = momentum;
						particles.push_back(particle);
						particlesNumber++;
						if (particlesNumber % 1000 == 0) {
							if ((rank == 0) && (verbosity > 0))printf("create particle number %d\n", particlesNumber);
						}
						alertNaNOrInfinity(particle->coordinates.x, "particle.x = NaN in createParticles\n");
						alertNaNOrInfinity(particle->coordinates.y, "particle.y = NaN in createParticles\n");
						alertNaNOrInfinity(particle->coordinates.z, "particle.z = NaN in createParticles\n");
					}
				}
			}
		}
	}

}<commit_msg>update harris<commit_after>#include <math.h>
#include <stdio.h>

#include "particle.h"
#include "simulation.h"
#include "vector3d.h"
#include "boundaryFieldEvaluator.h"
#include "util.h"

void Simulation::initializeHarris() {
	//boundaryConditionTypeX = SUPER_CONDUCTOR_LEFT;
	//boundaryConditionTypeX = FREE_BOTH;
	boundaryConditionTypeX = FREE_MIRROR_BOTH;
	double l = 5*deltaX;
    //E0 = Vector3d(0, 0, 0);
	//B0 = Vector3d(0, 0, 0);
	for (int i = 0; i < xnumberAdded; ++i) {
		for (int j = 0; j < ynumberAdded; ++j) {
			for (int k = 0; k < znumberAdded; ++k) {
				Bfield[i][j][k] = B0*tanh((xgrid[i] - 1.5*xsizeGeneral)/l);
				newBfield[i][j][k] = Bfield[i][j][k];
			}
		}
	}
	createParticlesHarris(l);
	E0 = Vector3d(0, 0, 0);

	for (int i = 0; i < xnumberAdded + 1; ++i) {
		for (int j = 0; j < ynumberAdded + 1; ++j) {
			for (int k = 0; k < znumberAdded + 1; ++k) {
				Efield[i][j][k] = E0;
				newEfield[i][j][k] = Efield[i][j][k];
			}
		}
	}

	rightBoundaryFieldEvaluator = new ConstantBoundaryFieldEvaluator(E0, B0);
	Vector3d B1 = B0*(-1.0);
	leftBoundaryFieldEvaluator = new ConstantBoundaryFieldEvaluator(E0, B1);

}

void Simulation::createParticlesHarris(double harrisWidth) {
	evaluateParticleTypesAlpha();
	if (rank == 0) printf("creating particles harris\n");
	fflush(stdout);
	if (rank == 0) printLog("creating particles harris\n");
	double n0 = types[0].concentration;
	int n = 0;

	//int density = ; %
	//for (int i = 0; i < xnumber; ++i) {
	for (int i = 1 + additionalBinNumber; i < xnumberAdded - additionalBinNumber - 1; ++i) {
		for (int j = 1 + additionalBinNumber; j < ynumberAdded - additionalBinNumber - 1; ++j) {
			for (int k = 1 + additionalBinNumber; k < znumberAdded - additionalBinNumber - 1; ++k) {
				//int maxParticlesPerBin = types[0].particlesPerBin;
				double x = xgrid[i] + 0.0001 * deltaX;
				double y = ygrid[j] + 0.0001 * deltaY;
				double z = zgrid[k] + 0.0001 * deltaZ;
				double ch = cosh((xgrid[i] - 1.5*xsizeGeneral)/harrisWidth);
				double concentr = n0/(ch*ch);
				//for (int l = 0; l < maxParticlesPerBin; ++l) {
				for (int typeCounter = 0; typeCounter < typesNumber; ++typeCounter) {
					double weight = (concentr* volumeB()) / types[typeCounter].particlesPerBin ;
					double deltaXParticles = types[typeCounter].particesDeltaX;
					double deltaYParticles = types[typeCounter].particesDeltaY;
					double deltaZParticles = types[typeCounter].particesDeltaZ;
					//if (l < types[typeCounter].particlesPerBin) {
					for (int l = 0; l < types[typeCounter].particlesPerBin; ++l) {
						ParticleTypes type = types[typeCounter].type;
						Particle* particle = createParticle(n, i, j, k, weight, type, types[typeCounter],
						                                    types[typeCounter].temperatureX,
						                                    types[typeCounter].temperatureY,
						                                    types[typeCounter].temperatureZ);
						n++;
						particle->coordinates.x = x + deltaXParticles * l;
						particle->coordinates.y = y + deltaYParticles * l;
						particle->coordinates.z = z + deltaZParticles * l;
						//particle->coordinates.x = middleXgrid[i];
						//particle->coordinates.y = middleYgrid[j];
						//particle->coordinates.z = middleZgrid[k];

						//particle->coordinates.x = xgrid[i] + uniformDistribution()*deltaX;
						//particle->coordinates.y = ygrid[j] + uniformDistribution()*deltaY;
						//particle->coordinates.z = zgrid[k] + uniformDistribution()*deltaZ;
						particle->initialCoordinates = particle->coordinates;

						double P=harrisWidth*B0.norm()*types[typeCounter].charge;
						Vector3d V = Vector3d(0, 1.0, 0) * (-2*kBoltzman_normalized*speed_of_light_normalized*types[typeCounter].temperatureX/P);

							particle->addVelocity(V, speed_of_light_normalized);

						Vector3d momentum = particle->getMomentum();
						particle->initialMomentum = momentum;
						particle->prevMomentum = momentum;
						particles.push_back(particle);
						particlesNumber++;
						if (particlesNumber % 1000 == 0) {
							if ((rank == 0) && (verbosity > 0))printf("create particle number %d\n", particlesNumber);
						}
						alertNaNOrInfinity(particle->coordinates.x, "particle.x = NaN in createParticles\n");
						alertNaNOrInfinity(particle->coordinates.y, "particle.y = NaN in createParticles\n");
						alertNaNOrInfinity(particle->coordinates.z, "particle.z = NaN in createParticles\n");
					}
				}
			}
		}
	}

}<|endoftext|>


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

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

using namespace elderly_care_simulation;

Scheduler scheduler;

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

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

Scheduler::~Scheduler() {}

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

    return msg;
}

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

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

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

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

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

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

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

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

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

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

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

    eventQueue.push(EventNode(msg));
}

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

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

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

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

                eventQueue.push(EventNode(eatMsg));
            }else{
                concurrentWeight -= msg.event_weight;
                ROS_INFO("Scheduler: [%s] done.", eventTypeToString(msg.event_type));
            }
        }
    }
}

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

    int eventSequence[][2] = {

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

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

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

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

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

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

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

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

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

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

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

                break;

            case EVENT_TRIGGER_EVENT_TYPE_ILL:
                allowNewEvents = false;

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

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

            case EVENT_TRIGGER_EVENT_TYPE_VERY_ILL:
                allowNewEvents = false;

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

                clearEventQueue();

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

            default:
                allowNewEvents = false;
                eventTriggerPub.publish(msg);
                concurrentWeight += msg.event_weight;
                eventQueue.pop();
                break;
        }

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

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

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

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

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

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

    scheduler = Scheduler();

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

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

    ros::Rate loop_rate(10);

    // populate queue with day's events

    scheduler.populateDailyTasks();

    //a count of howmany messages we have sent
    int count = 0;
    sleep(3);
    ROS_INFO("Day Starts....");

    while (ros::ok()) {

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

        ros::spinOnce();
        loop_rate.sleep();
        ++count;
    }
    return 0;
}
<commit_msg>Increased scheduler's startup sleep time to fix timing issues. [#54][#56]<commit_after>#include "ros/ros.h"

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

using namespace elderly_care_simulation;

Scheduler scheduler;

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

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

Scheduler::~Scheduler() {}

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

    return msg;
}

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

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

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

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

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

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

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

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

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

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

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

    eventQueue.push(EventNode(msg));
}

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

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

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

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

                eventQueue.push(EventNode(eatMsg));
            }else{
                concurrentWeight -= msg.event_weight;
                ROS_INFO("Scheduler: [%s] done.", eventTypeToString(msg.event_type));
            }
        }
    }
}

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

    int eventSequence[][2] = {

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

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

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

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

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

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

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

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

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

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

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

                break;

            case EVENT_TRIGGER_EVENT_TYPE_ILL:
                allowNewEvents = false;

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

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

            case EVENT_TRIGGER_EVENT_TYPE_VERY_ILL:
                allowNewEvents = false;

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

                clearEventQueue();

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

            default:
                allowNewEvents = false;
                eventTriggerPub.publish(msg);
                concurrentWeight += msg.event_weight;
                eventQueue.pop();
                break;
        }

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

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

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

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

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

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

    scheduler = Scheduler();

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

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

    ros::Rate loop_rate(10);

    // populate queue with day's events

    scheduler.populateDailyTasks();

    //a count of howmany messages we have sent
    int count = 0;
    sleep(5);
    ROS_INFO("Day Starts....");

    while (ros::ok()) {

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

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


<commit_before>/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkRTConf.h"
#include "SkOSFile.h"

SkRTConfRegistry::SkRTConfRegistry(): fConfs(100) {

    SkFILE *fp = sk_fopen(configFileLocation(), kRead_SkFILE_Flag);

    if (!fp) {
        return;
    }

    char line[1024];

    while (!sk_feof(fp)) {

        if (!sk_fgets(line, sizeof(line), fp)) {
            break;
        }

        char *commentptr = strchr(line, '#');
        if (commentptr == line) {
            continue;
        }
        if (NULL != commentptr) {
            *commentptr = '\0';
        }

        char sep[] = " \t\r\n";

        char *keyptr = strtok(line, sep);
        if (!keyptr) {
            continue;
        }

        char *valptr = strtok(NULL, sep);
        if (!valptr) {
            continue;
        }

        SkString* key = new SkString(keyptr);
        SkString* val = new SkString(valptr);

        fConfigFileKeys.append(1, &key);
        fConfigFileValues.append(1, &val);
    }
    sk_fclose(fp);
}

const char *SkRTConfRegistry::configFileLocation() const {
    return "skia.conf"; // for now -- should probably do something fancier like home directories or whatever.
}

// dump all known runtime config options to the file with their default values.
// to trigger this, make a config file of zero size.
void SkRTConfRegistry::possiblyDumpFile() const {
    const char *path = configFileLocation();
    SkFILE *fp = sk_fopen(path, kRead_SkFILE_Flag);
    if (!fp) {
        return;
    }
    size_t configFileSize = sk_fgetsize(fp);
    if (configFileSize == 0) {
        printAll(path);
    }
    sk_fclose(fp);
}

// Run through every provided configuration option and print a warning if the user hasn't
// declared a correponding configuration object somewhere.
void SkRTConfRegistry::validate() const {
    for (int i = 0 ; i < fConfigFileKeys.count() ; i++) {
        if (fConfs.find(fConfigFileKeys[i]->c_str())) {
            SkDebugf("WARNING: You have config value %s in your configuration file, but I've never heard of that.\n", fConfigFileKeys[i]->c_str());
        }
    }
}

void SkRTConfRegistry::printAll(const char *fname) const {
    SkWStream *o;

    if (NULL != fname) {
        o = new SkFILEWStream(fname);
    } else {
        o = new SkDebugWStream();
    }

    ConfMap::Iter iter(fConfs);
    SkTDArray<SkRTConfBase *> *confArray;

    while (iter.next(&confArray)) {
        if (confArray->getAt(0)->isDefault()) {
            o->writeText("# ");
        }
        confArray->getAt(0)->print(o);
        o->newline();
    }

    delete o;
}

void SkRTConfRegistry::printNonDefault(const char *fname) const {
    SkWStream *o;

    if (NULL != fname) {
        o = new SkFILEWStream(fname);
    } else {
        o = new SkDebugWStream();
    }
    ConfMap::Iter iter(fConfs);
    SkTDArray<SkRTConfBase *> *confArray;

    while (iter.next(&confArray)) {
        if (!confArray->getAt(0)->isDefault()) {
            confArray->getAt(0)->print(o);
            o->newline();
        }
    }

    delete o;
}

// register a configuration variable after its value has been set by the parser.
// we maintain a vector of these things instead of just a single one because the
// user might set the value after initialization time and we need to have
// all the pointers lying around, not just one.
void SkRTConfRegistry::registerConf(SkRTConfBase *conf) {
    SkTDArray<SkRTConfBase *> *confArray;
    if (fConfs.find(conf->getName(), &confArray)) {
        if (!conf->equals(confArray->getAt(0))) {
            SkDebugf("WARNING: Skia config \"%s\" was registered more than once in incompatible ways.\n", conf->getName());
        } else {
            confArray->append(1, &conf);
        }
    } else {
        confArray = new SkTDArray<SkRTConfBase *>;
        confArray->append(1, &conf);
        fConfs.set(conf->getName(),confArray);
    }
}

template <typename T> T doParse(const char *s, bool *success ) {
    SkDebugf("WARNING: Invoked non-specialized doParse function...\n");
    if (success) {
        *success = false;
    }
    return (T) 0;
}

template<> bool doParse<bool>(const char *s, bool *success) {
    if (success) {
        *success = true;
    }
    if (!strcmp(s,"1") || !strcmp(s,"true")) {
        return true;
    }
    if (!strcmp(s,"0") || !strcmp(s,"false")) {
        return false;
    }
    if (success) {
        *success = false;
    }
    return false;
}

template<> const char * doParse<const char *>(const char * s, bool *success) {
    if (success) {
        *success = true;
    }
    return s;
}

template<> int doParse<int>(const char * s, bool *success) {
    return atoi(s);
}

template<> unsigned int doParse<unsigned int>(const char * s, bool *success) {
    return (unsigned int) atoi(s);
}

template<> float doParse<float>(const char * s, bool *success) {
    return (float) atof(s);
}

template<> double doParse<double>(const char * s, bool *success) {
    return atof(s);
}

static inline void str_replace(char *s, char search, char replace) {
    for (char *ptr = s ; *ptr ; ptr++) {
        if (*ptr == search) {
            *ptr = replace;
        }
    }
}

template<typename T> bool SkRTConfRegistry::parse(const char *name, T* value) {
    SkString *str = NULL;

    for (int i = 0 ; i < fConfigFileKeys.count() ; i++) {
        if (fConfigFileKeys[i]->equals(name)) {
            str = fConfigFileValues[i];
        }
    }

    SkString environment_variable("skia.");
    environment_variable.append(name);

    const char *environment_value = getenv(environment_variable.c_str());
    if (environment_value) {
        str->set(environment_value);
    } else {
        // apparently my shell doesn't let me have environment variables that
        // have periods in them, so also let the user substitute underscores.
        SkString underscore_environment_variable("skia_");
        char *underscore_name = SkStrDup(name);
        str_replace(underscore_name,'.','_');
        underscore_environment_variable.append(underscore_name);
        sk_free(underscore_name);
        environment_value = getenv(underscore_environment_variable.c_str());
        if (environment_value) {
            str->set(environment_value);
        }
    }

    if (!str) {
        return false;
    }

    bool success;
    T new_value = doParse<T>(str->c_str(),&success);
    if (success) {
        *value = new_value;
    } else {
        SkDebugf("WARNING: Couldn't parse value \'%s\' for variable \'%s\'\n", str->c_str(), name);
    }
    return success;
}

// need to explicitly instantiate the parsing function for every config type we might have...

template bool SkRTConfRegistry::parse(const char *name, bool *value);
template bool SkRTConfRegistry::parse(const char *name, int *value);
template bool SkRTConfRegistry::parse(const char *name, unsigned int *value);
template bool SkRTConfRegistry::parse(const char *name, float *value);
template bool SkRTConfRegistry::parse(const char *name, double *value);
template bool SkRTConfRegistry::parse(const char *name, const char **value);

template <typename T> void SkRTConfRegistry::set(const char *name, T value) {

    SkTDArray<SkRTConfBase *> *confArray;
    if (!fConfs.find(name, &confArray)) {
        SkDebugf("WARNING: Attempting to set configuration value \"%s\", but I've never heard of that.\n", name);
        return;
    }

    for (SkRTConfBase **confBase = confArray->begin(); confBase != confArray->end(); confBase++) {
        // static_cast here is okay because there's only one kind of child class.
        SkRTConf<T> *concrete = static_cast<SkRTConf<T> *>(*confBase);

        if (concrete) {
            concrete->set(value);
        }
    }
}

template void SkRTConfRegistry::set(const char *name, bool value);
template void SkRTConfRegistry::set(const char *name, int value);
template void SkRTConfRegistry::set(const char *name, unsigned int value);
template void SkRTConfRegistry::set(const char *name, float value);
template void SkRTConfRegistry::set(const char *name, double value);
template void SkRTConfRegistry::set(const char *name, char * value);

SkRTConfRegistry &skRTConfRegistry() {
    static SkRTConfRegistry r;
    return r;
}
<commit_msg>Fixed doParse functions<commit_after>/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkRTConf.h"
#include "SkOSFile.h"

SkRTConfRegistry::SkRTConfRegistry(): fConfs(100) {

    SkFILE *fp = sk_fopen(configFileLocation(), kRead_SkFILE_Flag);

    if (!fp) {
        return;
    }

    char line[1024];

    while (!sk_feof(fp)) {

        if (!sk_fgets(line, sizeof(line), fp)) {
            break;
        }

        char *commentptr = strchr(line, '#');
        if (commentptr == line) {
            continue;
        }
        if (NULL != commentptr) {
            *commentptr = '\0';
        }

        char sep[] = " \t\r\n";

        char *keyptr = strtok(line, sep);
        if (!keyptr) {
            continue;
        }

        char *valptr = strtok(NULL, sep);
        if (!valptr) {
            continue;
        }

        SkString* key = new SkString(keyptr);
        SkString* val = new SkString(valptr);

        fConfigFileKeys.append(1, &key);
        fConfigFileValues.append(1, &val);
    }
    sk_fclose(fp);
}

const char *SkRTConfRegistry::configFileLocation() const {
    return "skia.conf"; // for now -- should probably do something fancier like home directories or whatever.
}

// dump all known runtime config options to the file with their default values.
// to trigger this, make a config file of zero size.
void SkRTConfRegistry::possiblyDumpFile() const {
    const char *path = configFileLocation();
    SkFILE *fp = sk_fopen(path, kRead_SkFILE_Flag);
    if (!fp) {
        return;
    }
    size_t configFileSize = sk_fgetsize(fp);
    if (configFileSize == 0) {
        printAll(path);
    }
    sk_fclose(fp);
}

// Run through every provided configuration option and print a warning if the user hasn't
// declared a correponding configuration object somewhere.
void SkRTConfRegistry::validate() const {
    for (int i = 0 ; i < fConfigFileKeys.count() ; i++) {
        if (fConfs.find(fConfigFileKeys[i]->c_str())) {
            SkDebugf("WARNING: You have config value %s in your configuration file, but I've never heard of that.\n", fConfigFileKeys[i]->c_str());
        }
    }
}

void SkRTConfRegistry::printAll(const char *fname) const {
    SkWStream *o;

    if (NULL != fname) {
        o = new SkFILEWStream(fname);
    } else {
        o = new SkDebugWStream();
    }

    ConfMap::Iter iter(fConfs);
    SkTDArray<SkRTConfBase *> *confArray;

    while (iter.next(&confArray)) {
        if (confArray->getAt(0)->isDefault()) {
            o->writeText("# ");
        }
        confArray->getAt(0)->print(o);
        o->newline();
    }

    delete o;
}

void SkRTConfRegistry::printNonDefault(const char *fname) const {
    SkWStream *o;

    if (NULL != fname) {
        o = new SkFILEWStream(fname);
    } else {
        o = new SkDebugWStream();
    }
    ConfMap::Iter iter(fConfs);
    SkTDArray<SkRTConfBase *> *confArray;

    while (iter.next(&confArray)) {
        if (!confArray->getAt(0)->isDefault()) {
            confArray->getAt(0)->print(o);
            o->newline();
        }
    }

    delete o;
}

// register a configuration variable after its value has been set by the parser.
// we maintain a vector of these things instead of just a single one because the
// user might set the value after initialization time and we need to have
// all the pointers lying around, not just one.
void SkRTConfRegistry::registerConf(SkRTConfBase *conf) {
    SkTDArray<SkRTConfBase *> *confArray;
    if (fConfs.find(conf->getName(), &confArray)) {
        if (!conf->equals(confArray->getAt(0))) {
            SkDebugf("WARNING: Skia config \"%s\" was registered more than once in incompatible ways.\n", conf->getName());
        } else {
            confArray->append(1, &conf);
        }
    } else {
        confArray = new SkTDArray<SkRTConfBase *>;
        confArray->append(1, &conf);
        fConfs.set(conf->getName(),confArray);
    }
}

template <typename T> T doParse(const char *, bool *success ) {
    SkDebugf("WARNING: Invoked non-specialized doParse function...\n");
    if (success) {
        *success = false;
    }
    return (T) 0;
}

template<> bool doParse<bool>(const char *s, bool *success) {
    if (success) {
        *success = true;
    }
    if (!strcmp(s,"1") || !strcmp(s,"true")) {
        return true;
    }
    if (!strcmp(s,"0") || !strcmp(s,"false")) {
        return false;
    }
    if (success) {
        *success = false;
    }
    return false;
}

template<> const char * doParse<const char *>(const char * s, bool *success) {
    if (success) {
        *success = true;
    }
    return s;
}

template<> int doParse<int>(const char * s, bool *success) {
    if (success) {
        *success = true;
    }
    return atoi(s);
}

template<> unsigned int doParse<unsigned int>(const char * s, bool *success) {
    if (success) {
        *success = true;
    }
    return (unsigned int) atoi(s);
}

template<> float doParse<float>(const char * s, bool *success) {
    if (success) {
        *success = true;
    }
    return (float) atof(s);
}

template<> double doParse<double>(const char * s, bool *success) {
    if (success) {
        *success = true;
    }
    return atof(s);
}

static inline void str_replace(char *s, char search, char replace) {
    for (char *ptr = s ; *ptr ; ptr++) {
        if (*ptr == search) {
            *ptr = replace;
        }
    }
}

template<typename T> bool SkRTConfRegistry::parse(const char *name, T* value) {
    SkString *str = NULL;

    for (int i = 0 ; i < fConfigFileKeys.count() ; i++) {
        if (fConfigFileKeys[i]->equals(name)) {
            str = fConfigFileValues[i];
        }
    }

    SkString environment_variable("skia.");
    environment_variable.append(name);

    const char *environment_value = getenv(environment_variable.c_str());
    if (environment_value) {
        str->set(environment_value);
    } else {
        // apparently my shell doesn't let me have environment variables that
        // have periods in them, so also let the user substitute underscores.
        SkString underscore_environment_variable("skia_");
        char *underscore_name = SkStrDup(name);
        str_replace(underscore_name,'.','_');
        underscore_environment_variable.append(underscore_name);
        sk_free(underscore_name);
        environment_value = getenv(underscore_environment_variable.c_str());
        if (environment_value) {
            str->set(environment_value);
        }
    }

    if (!str) {
        return false;
    }

    bool success;
    T new_value = doParse<T>(str->c_str(),&success);
    if (success) {
        *value = new_value;
    } else {
        SkDebugf("WARNING: Couldn't parse value \'%s\' for variable \'%s\'\n", str->c_str(), name);
    }
    return success;
}

// need to explicitly instantiate the parsing function for every config type we might have...

template bool SkRTConfRegistry::parse(const char *name, bool *value);
template bool SkRTConfRegistry::parse(const char *name, int *value);
template bool SkRTConfRegistry::parse(const char *name, unsigned int *value);
template bool SkRTConfRegistry::parse(const char *name, float *value);
template bool SkRTConfRegistry::parse(const char *name, double *value);
template bool SkRTConfRegistry::parse(const char *name, const char **value);

template <typename T> void SkRTConfRegistry::set(const char *name, T value) {

    SkTDArray<SkRTConfBase *> *confArray;
    if (!fConfs.find(name, &confArray)) {
        SkDebugf("WARNING: Attempting to set configuration value \"%s\", but I've never heard of that.\n", name);
        return;
    }

    for (SkRTConfBase **confBase = confArray->begin(); confBase != confArray->end(); confBase++) {
        // static_cast here is okay because there's only one kind of child class.
        SkRTConf<T> *concrete = static_cast<SkRTConf<T> *>(*confBase);

        if (concrete) {
            concrete->set(value);
        }
    }
}

template void SkRTConfRegistry::set(const char *name, bool value);
template void SkRTConfRegistry::set(const char *name, int value);
template void SkRTConfRegistry::set(const char *name, unsigned int value);
template void SkRTConfRegistry::set(const char *name, float value);
template void SkRTConfRegistry::set(const char *name, double value);
template void SkRTConfRegistry::set(const char *name, char * value);

SkRTConfRegistry &skRTConfRegistry() {
    static SkRTConfRegistry r;
    return r;
}
<|endoftext|>


<commit_before>// Fill out your copyright notice in the Description page of Project Settings.

#include "UE4_TurnBased.h"
#include "TB_Name.h"

//init static members
TArray<FString> UTB_Name::MaleFirstNames = TArray<FString>();
TArray<FString> UTB_Name::FemaleFirstNames = TArray<FString>();
TArray<FString> UTB_Name::LastNames = TArray<FString>();

void UTB_Name::PostInitProperties()
{
	Super::PostInitProperties();

	//Load namelists if they are not already loaded
	Mutex.Lock();
	if (!MaleFirstNameFile.IsEmpty() && MaleFirstNames.Num() == 0)
	{
		LoadNames(MaleFirstNameFile, MaleFirstNames);
	}
	if (!FemaleFirstNameFile.IsEmpty() && FemaleFirstNames.Num() == 0)
	{
		LoadNames(FemaleFirstNameFile, FemaleFirstNames);
	}
	if (!LastNameFile.IsEmpty() && LastNames.Num() == 0)
	{
		LoadNames(LastNameFile, LastNames);
	}
	Mutex.Unlock();

	FGenericPlatformMath::RandInit(GetUniqueID()); // use a different seed for each thread
}

void UTB_Name::Generate_Implementation(ETB_Gender Gender)
{
	switch (Gender)
	{
	case ETB_Gender::VE_Male:
		PickRandomName(MaleFirstNames, FirstName);
		break;
	case ETB_Gender::VE_Female:
		PickRandomName(FemaleFirstNames, FirstName);
		break;
	case ETB_Gender::VE_None:
		PickRandomName(MaleFirstNames, FirstName); //i don't know....
		break;
	};

	PickRandomName(LastNames, LastName);
}

FString UTB_Name::ToString()
{
	return FString::Printf(TEXT("%s %s"), *FirstName, *LastName);
}

FText UTB_Name::ToText()
{
	return FText::FromString(ToString());
}

void UTB_Name::LoadNames(FString &NameFile, TArray<FString> &Names)
{
	FString FullPath = FPaths::GameContentDir() + NameFile;
	UE_LOG(LogTemp, Log, TEXT("Loading names from %s"), *FullPath);

	bool Result = FFileHelper::LoadANSITextFileToStrings(*FullPath, NULL, Names);
	if (!Result)
	{
		UE_LOG(LogTemp, Error, TEXT("Could not open %s"), *FullPath);
	}
}

void UTB_Name::PickRandomName(TArray<FString> &NameList, FString &Name)
{
	if (NameList.Num() > 0)
	{
		int32 RandomNumber = FGenericPlatformMath::Rand();
		Name = NameList[RandomNumber % NameList.Num()];
	}
}<commit_msg>use TB_Log when logging<commit_after>// Fill out your copyright notice in the Description page of Project Settings.

#include "UE4_TurnBased.h"
#include "TB_Name.h"

//init static members
TArray<FString> UTB_Name::MaleFirstNames = TArray<FString>();
TArray<FString> UTB_Name::FemaleFirstNames = TArray<FString>();
TArray<FString> UTB_Name::LastNames = TArray<FString>();

void UTB_Name::PostInitProperties()
{
	Super::PostInitProperties();

	//Load namelists if they are not already loaded
	Mutex.Lock();
	if (!MaleFirstNameFile.IsEmpty() && MaleFirstNames.Num() == 0)
	{
		LoadNames(MaleFirstNameFile, MaleFirstNames);
	}
	if (!FemaleFirstNameFile.IsEmpty() && FemaleFirstNames.Num() == 0)
	{
		LoadNames(FemaleFirstNameFile, FemaleFirstNames);
	}
	if (!LastNameFile.IsEmpty() && LastNames.Num() == 0)
	{
		LoadNames(LastNameFile, LastNames);
	}
	Mutex.Unlock();

	FGenericPlatformMath::RandInit(GetUniqueID()); // use a different seed for each thread
}

void UTB_Name::Generate_Implementation(ETB_Gender Gender)
{
	switch (Gender)
	{
	case ETB_Gender::VE_Male:
		PickRandomName(MaleFirstNames, FirstName);
		break;
	case ETB_Gender::VE_Female:
		PickRandomName(FemaleFirstNames, FirstName);
		break;
	case ETB_Gender::VE_None:
		PickRandomName(MaleFirstNames, FirstName); //i don't know....
		break;
	};

	PickRandomName(LastNames, LastName);
}

FString UTB_Name::ToString()
{
	return FString::Printf(TEXT("%s %s"), *FirstName, *LastName);
}

FText UTB_Name::ToText()
{
	return FText::FromString(ToString());
}

void UTB_Name::LoadNames(FString &NameFile, TArray<FString> &Names)
{
	FString FullPath = FPaths::GameContentDir() + NameFile;
	UE_LOG(TB_Log, Log, TEXT("Loading names from %s"), *FullPath);

	bool Result = FFileHelper::LoadANSITextFileToStrings(*FullPath, NULL, Names);
	if (!Result)
	{
		UE_LOG(TB_Log, Error, TEXT("Could not open %s"), *FullPath);
	}
}

void UTB_Name::PickRandomName(TArray<FString> &NameList, FString &Name)
{
	if (NameList.Num() > 0)
	{
		int32 RandomNumber = FGenericPlatformMath::Rand();
		Name = NameList[RandomNumber % NameList.Num()];
	}
}<|endoftext|>