<commit_before>#include <windows.h>

#include "macros.h"

class Test
{
public:
    Test();
    int length() const;
private:
    int size;
};

Test::Test()
    :size(0)
{}

FORCE_INLINE int Test::length() const
{
    return size;
}

int main()
{
    Test *a;
    a = NULL;
    int l = a->length();
    return l != 0;
}

// CHECK_STDERR: /  cxx_inline\.exe\!main  \[.*\bcxx_inline\.cpp @ (21|28)\]/
// CHECK_EXIT_CODE: 0xc0000005
<commit_msg>tests/apps: Fix cxx_inline failures with release builds.<commit_after>#include <windows.h>

#include "macros.h"

class Test
{
public:
    Test();
    int length() const;
private:
    int size;
};

Test::Test()
    :size(0)
{}

FORCE_INLINE int Test::length() const
{
    return size;
}

int main()
{
    Test *a;
    a = NULL;
    int l = a->length(); LINE_BARRIER
    return l != 0;
}

// CHECK_STDERR: /  cxx_inline\.exe\!main  \[.*\bcxx_inline\.cpp @ (21|28)\]/
// CHECK_EXIT_CODE: 0xc0000005
<|endoftext|>


<commit_before>namespace mant {
  inline bool isRotationMatrix(
      const arma::Mat<double>& matrix) noexcept;

  inline bool isCompatibleDimension(
      const std::size_t firstDimension,
      const std::size_t secondDimension) noexcept;

  inline void checkRotationMatrix(
      const std::string& name,
      const arma::Mat<double>& matrix);

  inline void checkCompatibleDimension(
      const std::string& firstName,
      const std::size_t firstDimension,
      const std::string& secondName,
      const std::size_t secondDimension);

  inline bool isRotationMatrix(
      const arma::Mat<double>& matrix) noexcept {
    // is suqare?
    if (!matrix.is_square()) {
      return false;
    // is orthonormal?
    } else if(arma::any(arma::vectorise(arma::abs(matrix.i() - matrix.t()) > 1.0e-12 * std::max(1.0, std::abs(arma::median(arma::vectorise(matrix))))))) {
      return false;
    // determinant is either 1 or -1?
    } else if(std::abs(std::abs(arma::det(matrix)) - 1.0) > 1.0e-12) {
      return false;
    }

    return true;
  }

  inline bool isCompatibleDimension(
      const std::size_t firstDimension,
      const std::size_t secondDimension) noexcept {
    return (firstDimension == secondDimension);
  }

  inline void checkRotationMatrix(
      const std::string& name,
      const arma::Mat<double>& matrix) {
    if(!isRotationMatrix(matrix)) {
      throw std::logic_error("Rotation matrix required: " + name + " must be square, orthonormal and its determinant be either 1 or -1.");
    }
  }

  inline void checkCompatibleDimension(
      const std::string& firstName,
      const std::size_t firstDimension,
      const std::string& secondName,
      const std::size_t secondDimension) {
    if(!isCompatibleDimension(firstDimension, secondDimension)) {
      throw std::logic_error("Incompatible dimensions: " + firstName + " must be equal to " + secondName);
    }
  }
}
<commit_msg>Added inBetween assertions<commit_after>namespace mant {
  inline bool isRotationMatrix(
      const arma::Mat<double>& matrix) noexcept;

  inline bool isCompatibleDimension(
      const std::size_t firstDimension,
      const std::size_t secondDimension) noexcept;

  template <typename ParameterType>
  inline bool isBetween(
      const arma::Col<ParameterType>& parameter,
      const arma::Col<ParameterType>& lowerBound,
      const arma::Col<ParameterType>& upperBound);

  template <typename ParameterType>
  inline bool isBetween(
      const arma::Col<ParameterType>& parameter,
      const ParameterType lowerBound,
      const ParameterType upperBound);

  inline void checkRotationMatrix(
      const std::string& name,
      const arma::Mat<double>& matrix);

  inline void checkCompatibleDimension(
      const std::string& firstName,
      const std::size_t firstDimension,
      const std::string& secondName,
      const std::size_t secondDimension);

  template <typename ParameterType>
  inline void checkBetween(
      const std::string& parameterName,
      const arma::Col<ParameterType>& parameter,
      const std::string& lowerBoundName,
      const arma::Col<ParameterType>& lowerBound,
      const std::string& upperBoundName,
      const arma::Col<ParameterType>& upperBound);

  template <typename ParameterType>
  inline void checkBetween(
      const std::string& parameterName,
      const arma::Col<ParameterType>& parameter,
      const std::string& lowerBoundName,
      const ParameterType lowerBound,
      const std::string& upperBoundName,
      const ParameterType upperBound);

  inline bool isRotationMatrix(
      const arma::Mat<double>& matrix) noexcept {
    // is suqare?
    if (!matrix.is_square()) {
      return false;
    // is orthonormal?
    } else if(arma::any(arma::vectorise(arma::abs(matrix.i() - matrix.t()) > 1.0e-12 * std::max(1.0, std::abs(arma::median(arma::vectorise(matrix))))))) {
      return false;
    // determinant is either 1 or -1?
    } else if(std::abs(std::abs(arma::det(matrix)) - 1.0) > 1.0e-12) {
      return false;
    }

    return true;
  }

  inline bool isCompatibleDimension(
      const std::size_t firstDimension,
      const std::size_t secondDimension) noexcept {
    return (firstDimension == secondDimension);
  }

  template <typename ParameterType>
  inline bool isBetween(
      const arma::Col<ParameterType>& parameter,
      const arma::Col<ParameterType>& lowerBound,
      const arma::Col<ParameterType>& upperBound) {
    for(std::size_t n = 0; n < parameter.n_elem; ++n) {
      const double value = parameter(n);

      if(value < lowerBound(n) || value > upperBound(n)) {
        return false;
      }
    }

    return true;
  }

  template <typename ParameterType>
  inline bool isBetween(
      const arma::Col<ParameterType>& parameter,
      const ParameterType lowerBound,
      const ParameterType upperBound) {
    for(std::size_t n = 0; n < parameter.n_elem; ++n) {
      const double value = parameter(n);

      if(value < lowerBound || value > upperBound) {
        return false;
      }
    }

    return true;
  }

  template <typename ParameterType>
  inline bool isBetween(
      const arma::Col<ParameterType>& parameter,
      const ParameterType lowerBound,
      const ParameterType upperBound) noexcept {

  }

  inline void checkRotationMatrix(
      const std::string& name,
      const arma::Mat<double>& matrix) {
    if(!isRotationMatrix(matrix)) {
      throw std::logic_error("Rotation matrix required: " + name + " must be square, orthonormal and its determinant be either 1 or -1.");
    }
  }

  inline void checkCompatibleDimension(
      const std::string& firstName,
      const std::size_t firstDimension,
      const std::string& secondName,
      const std::size_t secondDimension) {
    if(!isCompatibleDimension(firstDimension, secondDimension)) {
      throw std::logic_error("Incompatible dimensions: " + firstName + " must be equal to " + secondName);
    }
  }

  template <typename ParameterType>
  inline void checkBetween(
      const std::string& parameterName,
      const arma::Col<ParameterType>& parameter,
      const std::string& lowerBoundName,
      const arma::Col<ParameterType>& lowerBound,
      const std::string& upperBoundName,
      const arma::Col<ParameterType>& upperBound) {
    if(!isBetween(parameter, lowerBound, upperBound)) {
      throw std::logic_error();
    }
  }

  template <typename ParameterType>
  inline void checkBetween(
      const std::string& parameterName,
      const arma::Col<ParameterType>& parameter,
      const std::string& lowerBoundName,
      const ParameterType lowerBound,
      const std::string& upperBoundName,
      const ParameterType upperBound) {
    if(!isBetween(parameter, lowerBound, upperBound)) {
      throw std::logic_error();
    }
  }
}
<|endoftext|>


<commit_before>#include <cmath>

#include "adapters/alsa/generic.hpp"
#include "adapters/alsa/mixer.hpp"
#include "utils/math.hpp"

#define MAX_LINEAR_DB_SCALE 24

POLYBAR_NS

namespace alsa {
  /**
   * Construct mixer object
   */
  mixer::mixer(string&& mixer_selem_name, string&& soundcard_name)
      : m_name(forward<string>(mixer_selem_name)), s_name(soundcard_name) {
    int err = 0;

    if ((err = snd_mixer_open(&m_mixer, 1)) == -1) {
      throw_exception<mixer_error>("Failed to open hardware mixer", err);
    }

    snd_config_update_free_global();

    if ((err = snd_mixer_attach(m_mixer, s_name.c_str())) == -1) {
      throw_exception<mixer_error>("Failed to attach hardware mixer control", err);
    }
    if ((err = snd_mixer_selem_register(m_mixer, nullptr, nullptr)) == -1) {
      throw_exception<mixer_error>("Failed to register simple mixer element", err);
    }
    if ((err = snd_mixer_load(m_mixer)) == -1) {
      throw_exception<mixer_error>("Failed to load mixer", err);
    }

    snd_mixer_selem_id_t* sid{nullptr};
    snd_mixer_selem_id_alloca(&sid);
    snd_mixer_selem_id_set_index(sid, 0);
    snd_mixer_selem_id_set_name(sid, m_name.c_str());

    if ((m_elem = snd_mixer_find_selem(m_mixer, sid)) == nullptr) {
      throw mixer_error("Cannot find simple element");
    }
  }

  /**
   * Deconstruct mixer
   */
  mixer::~mixer() {
    if (m_mixer != nullptr) {
      snd_mixer_close(m_mixer);
    }
  }

  /**
   * Get mixer name
   */
  const string& mixer::get_name() {
    return m_name;
  }

  /**
   * Get the name of the soundcard that is associated with the mixer
   */
  const string& mixer::get_sound_card() {
    return s_name;
  }

  /**
   * Wait for events
   */
  bool mixer::wait(int timeout) {
    assert(m_mixer);

    int err = 0;

    if ((err = snd_mixer_wait(m_mixer, timeout)) == -1) {
      throw_exception<mixer_error>("Failed to wait for events", err);
    }

    return process_events() > 0;
  }

  /**
   * Process queued mixer events
   */
  int mixer::process_events() {
    int num_events{0};
    if ((num_events = snd_mixer_handle_events(m_mixer)) == -1) {
      throw_exception<mixer_error>("Failed to process pending events", num_events);
    }

    return num_events;
  }

  /**
   * Get volume in percentage
   */
  int mixer::get_volume() {
    assert(m_elem != nullptr);

    long chan_n = 0, vol_total = 0, vol, vol_min, vol_max;

    snd_mixer_selem_get_playback_volume_range(m_elem, &vol_min, &vol_max);

    for (int i = 0; i <= SND_MIXER_SCHN_LAST; i++) {
      if (snd_mixer_selem_has_playback_channel(m_elem, static_cast<snd_mixer_selem_channel_id_t>(i))) {
        snd_mixer_selem_get_playback_volume(m_elem, static_cast<snd_mixer_selem_channel_id_t>(i), &vol);
        vol_total += vol;
        chan_n++;
      }
    }

    return math_util::percentage(vol_total / chan_n, vol_min, vol_max);
  }

  /**
   * Get normalized volume in percentage
   */
  int mixer::get_normalized_volume() {
    assert(m_elem != nullptr);

    long chan_n = 0, vol_total = 0, vol, vol_min, vol_max;
    double normalized, min_norm;

    snd_mixer_selem_get_playback_dB_range(m_elem, &vol_min, &vol_max);

    for (int i = 0; i <= SND_MIXER_SCHN_LAST; i++) {
      if (snd_mixer_selem_has_playback_channel(m_elem, static_cast<snd_mixer_selem_channel_id_t>(i))) {
        snd_mixer_selem_get_playback_dB(m_elem, static_cast<snd_mixer_selem_channel_id_t>(i), &vol);
        vol_total += vol;
        chan_n++;
      }
    }

    if (vol_max - vol_min <= MAX_LINEAR_DB_SCALE * 100) {
      return math_util::percentage(vol_total / chan_n, vol_min, vol_max);
    }

    normalized = pow10((vol_total / chan_n - vol_max) / 6000.0);
    if (vol_min != SND_CTL_TLV_DB_GAIN_MUTE) {
      min_norm = pow10((vol_min - vol_max) / 6000.0);
      normalized = (normalized - min_norm) / (1 - min_norm);
    }

    return 100.0f * normalized + 0.5f;
  }

  /**
   * Set volume to given percentage
   */
  void mixer::set_volume(float percentage) {
    assert(m_elem != nullptr);

    if (is_muted()) {
      return;
    }

    long vol_min, vol_max;
    snd_mixer_selem_get_playback_volume_range(m_elem, &vol_min, &vol_max);
    snd_mixer_selem_set_playback_volume_all(m_elem, math_util::percentage_to_value<int>(percentage, vol_min, vol_max));
  }

  /**
   * Set normalized volume to given percentage
   */
  void mixer::set_normalized_volume(float percentage) {
    assert(m_elem != nullptr);

    if (is_muted()) {
      return;
    }

    long vol_min, vol_max;
    double min_norm;
    percentage = percentage / 100.0f;

    snd_mixer_selem_get_playback_dB_range(m_elem, &vol_min, &vol_max);

    if (vol_max - vol_min <= MAX_LINEAR_DB_SCALE * 100) {
      snd_mixer_selem_set_playback_dB_all(m_elem, lrint(percentage * (vol_max - vol_min)) + vol_min, 0);
      return;
    }

    if (vol_min != SND_CTL_TLV_DB_GAIN_MUTE) {
      min_norm = pow10((vol_min - vol_max) / 6000.0);
      percentage = percentage * (1 - min_norm) + min_norm;
    }

    snd_mixer_selem_set_playback_dB_all(m_elem, lrint(6000.0 * log10(percentage)) + vol_max, 0);
  }

  /**
   * Set mute state
   */
  void mixer::set_mute(bool mode) {
    assert(m_elem != nullptr);

    snd_mixer_selem_set_playback_switch_all(m_elem, mode);
  }

  /**
   * Toggle mute state
   */
  void mixer::toggle_mute() {
    assert(m_elem != nullptr);

    int state;

    snd_mixer_selem_get_playback_switch(m_elem, SND_MIXER_SCHN_MONO, &state);
    snd_mixer_selem_set_playback_switch_all(m_elem, !state);
  }

  /**
   * Get current mute state
   */
  bool mixer::is_muted() {
    assert(m_elem != nullptr);

    int state = 0;

    for (int i = 0; i <= SND_MIXER_SCHN_LAST; i++) {
      if (snd_mixer_selem_has_playback_channel(m_elem, static_cast<snd_mixer_selem_channel_id_t>(i))) {
        int state_ = 0;
        snd_mixer_selem_get_playback_switch(m_elem, static_cast<snd_mixer_selem_channel_id_t>(i), &state_);
        state = state || state_;
      }
    }
    return !state;
  }
}

POLYBAR_NS_END
<commit_msg>fix(build): pow10 not defined on Fedora Rawhide (#807)<commit_after>#include <cmath>

#include "adapters/alsa/generic.hpp"
#include "adapters/alsa/mixer.hpp"
#include "utils/math.hpp"

#define MAX_LINEAR_DB_SCALE 24

POLYBAR_NS

namespace alsa {
  /**
   * Construct mixer object
   */
  mixer::mixer(string&& mixer_selem_name, string&& soundcard_name)
      : m_name(forward<string>(mixer_selem_name)), s_name(soundcard_name) {
    int err = 0;

    if ((err = snd_mixer_open(&m_mixer, 1)) == -1) {
      throw_exception<mixer_error>("Failed to open hardware mixer", err);
    }

    snd_config_update_free_global();

    if ((err = snd_mixer_attach(m_mixer, s_name.c_str())) == -1) {
      throw_exception<mixer_error>("Failed to attach hardware mixer control", err);
    }
    if ((err = snd_mixer_selem_register(m_mixer, nullptr, nullptr)) == -1) {
      throw_exception<mixer_error>("Failed to register simple mixer element", err);
    }
    if ((err = snd_mixer_load(m_mixer)) == -1) {
      throw_exception<mixer_error>("Failed to load mixer", err);
    }

    snd_mixer_selem_id_t* sid{nullptr};
    snd_mixer_selem_id_alloca(&sid);
    snd_mixer_selem_id_set_index(sid, 0);
    snd_mixer_selem_id_set_name(sid, m_name.c_str());

    if ((m_elem = snd_mixer_find_selem(m_mixer, sid)) == nullptr) {
      throw mixer_error("Cannot find simple element");
    }
  }

  /**
   * Deconstruct mixer
   */
  mixer::~mixer() {
    if (m_mixer != nullptr) {
      snd_mixer_close(m_mixer);
    }
  }

  /**
   * Get mixer name
   */
  const string& mixer::get_name() {
    return m_name;
  }

  /**
   * Get the name of the soundcard that is associated with the mixer
   */
  const string& mixer::get_sound_card() {
    return s_name;
  }

  /**
   * Wait for events
   */
  bool mixer::wait(int timeout) {
    assert(m_mixer);

    int err = 0;

    if ((err = snd_mixer_wait(m_mixer, timeout)) == -1) {
      throw_exception<mixer_error>("Failed to wait for events", err);
    }

    return process_events() > 0;
  }

  /**
   * Process queued mixer events
   */
  int mixer::process_events() {
    int num_events{0};
    if ((num_events = snd_mixer_handle_events(m_mixer)) == -1) {
      throw_exception<mixer_error>("Failed to process pending events", num_events);
    }

    return num_events;
  }

  /**
   * Get volume in percentage
   */
  int mixer::get_volume() {
    assert(m_elem != nullptr);

    long chan_n = 0, vol_total = 0, vol, vol_min, vol_max;

    snd_mixer_selem_get_playback_volume_range(m_elem, &vol_min, &vol_max);

    for (int i = 0; i <= SND_MIXER_SCHN_LAST; i++) {
      if (snd_mixer_selem_has_playback_channel(m_elem, static_cast<snd_mixer_selem_channel_id_t>(i))) {
        snd_mixer_selem_get_playback_volume(m_elem, static_cast<snd_mixer_selem_channel_id_t>(i), &vol);
        vol_total += vol;
        chan_n++;
      }
    }

    return math_util::percentage(vol_total / chan_n, vol_min, vol_max);
  }

  /**
   * Get normalized volume in percentage
   */
  int mixer::get_normalized_volume() {
    assert(m_elem != nullptr);

    long chan_n = 0, vol_total = 0, vol, vol_min, vol_max;
    double normalized, min_norm;

    snd_mixer_selem_get_playback_dB_range(m_elem, &vol_min, &vol_max);

    for (int i = 0; i <= SND_MIXER_SCHN_LAST; i++) {
      if (snd_mixer_selem_has_playback_channel(m_elem, static_cast<snd_mixer_selem_channel_id_t>(i))) {
        snd_mixer_selem_get_playback_dB(m_elem, static_cast<snd_mixer_selem_channel_id_t>(i), &vol);
        vol_total += vol;
        chan_n++;
      }
    }

    if (vol_max - vol_min <= MAX_LINEAR_DB_SCALE * 100) {
      return math_util::percentage(vol_total / chan_n, vol_min, vol_max);
    }

    normalized = pow(10, (vol_total / chan_n - vol_max) / 6000.0);
    if (vol_min != SND_CTL_TLV_DB_GAIN_MUTE) {
      min_norm = pow(10, (vol_min - vol_max) / 6000.0);
      normalized = (normalized - min_norm) / (1 - min_norm);
    }

    return 100.0f * normalized + 0.5f;
  }

  /**
   * Set volume to given percentage
   */
  void mixer::set_volume(float percentage) {
    assert(m_elem != nullptr);

    if (is_muted()) {
      return;
    }

    long vol_min, vol_max;
    snd_mixer_selem_get_playback_volume_range(m_elem, &vol_min, &vol_max);
    snd_mixer_selem_set_playback_volume_all(m_elem, math_util::percentage_to_value<int>(percentage, vol_min, vol_max));
  }

  /**
   * Set normalized volume to given percentage
   */
  void mixer::set_normalized_volume(float percentage) {
    assert(m_elem != nullptr);

    if (is_muted()) {
      return;
    }

    long vol_min, vol_max;
    double min_norm;
    percentage = percentage / 100.0f;

    snd_mixer_selem_get_playback_dB_range(m_elem, &vol_min, &vol_max);

    if (vol_max - vol_min <= MAX_LINEAR_DB_SCALE * 100) {
      snd_mixer_selem_set_playback_dB_all(m_elem, lrint(percentage * (vol_max - vol_min)) + vol_min, 0);
      return;
    }

    if (vol_min != SND_CTL_TLV_DB_GAIN_MUTE) {
      min_norm = pow(10, (vol_min - vol_max) / 6000.0);
      percentage = percentage * (1 - min_norm) + min_norm;
    }

    snd_mixer_selem_set_playback_dB_all(m_elem, lrint(6000.0 * log10(percentage)) + vol_max, 0);
  }

  /**
   * Set mute state
   */
  void mixer::set_mute(bool mode) {
    assert(m_elem != nullptr);

    snd_mixer_selem_set_playback_switch_all(m_elem, mode);
  }

  /**
   * Toggle mute state
   */
  void mixer::toggle_mute() {
    assert(m_elem != nullptr);

    int state;

    snd_mixer_selem_get_playback_switch(m_elem, SND_MIXER_SCHN_MONO, &state);
    snd_mixer_selem_set_playback_switch_all(m_elem, !state);
  }

  /**
   * Get current mute state
   */
  bool mixer::is_muted() {
    assert(m_elem != nullptr);

    int state = 0;

    for (int i = 0; i <= SND_MIXER_SCHN_LAST; i++) {
      if (snd_mixer_selem_has_playback_channel(m_elem, static_cast<snd_mixer_selem_channel_id_t>(i))) {
        int state_ = 0;
        snd_mixer_selem_get_playback_switch(m_elem, static_cast<snd_mixer_selem_channel_id_t>(i), &state_);
        state = state || state_;
      }
    }
    return !state;
  }
}

POLYBAR_NS_END
<|endoftext|>


<commit_before>#include <libmesh/equation_systems.h>
#include <libmesh/mesh.h>
#include <libmesh/mesh_generation.h>
#include <libmesh/elem.h>
#include <libmesh/dof_map.h>

#include "test_comm.h"
#include "libmesh_cppunit.h"

#include <regex>
#include <string>

using namespace libMesh;

#ifdef LIBMESH_ENABLE_CONSTRAINTS
// This class is used by testConstraintLoopDetection
class MyConstraint : public System::Constraint
{
private:

  System & _sys;

public:

  MyConstraint( System & sys ) : Constraint(), _sys(sys) {}

  virtual ~MyConstraint() {}

  void constrain()
  {
    {
      const dof_id_type constrained_dof_index = 0;
      DofConstraintRow constraint_row;
      constraint_row[1] = 1.0;
      _sys.get_dof_map().add_constraint_row( constrained_dof_index, constraint_row, 0., true);
    }
    {
      const dof_id_type constrained_dof_index = 1;
      DofConstraintRow constraint_row;
      constraint_row[0] = 1.0;
      _sys.get_dof_map().add_constraint_row( constrained_dof_index, constraint_row, 0., true);
    }
  }
};
#endif

class DofMapTest : public CppUnit::TestCase {
public:
  LIBMESH_CPPUNIT_TEST_SUITE( DofMapTest );

  CPPUNIT_TEST( testDofOwnerOnEdge3 );
#if LIBMESH_DIM > 1
  CPPUNIT_TEST( testDofOwnerOnQuad9 );
  CPPUNIT_TEST( testDofOwnerOnTri6 );
#endif
#if LIBMESH_DIM > 2
  CPPUNIT_TEST( testDofOwnerOnHex27 );
#endif

#if defined(LIBMESH_ENABLE_EXCEPTIONS)
  CPPUNIT_TEST( testBadElemFECombo );
#endif

#if defined(LIBMESH_ENABLE_CONSTRAINTS) && defined(LIBMESH_ENABLE_EXCEPTIONS) && LIBMESH_DIM > 1
  CPPUNIT_TEST( testConstraintLoopDetection );
#endif

  CPPUNIT_TEST_SUITE_END();

private:

public:
  void setUp()
  {}

  void tearDown()
  {}

  void testDofOwner(const ElemType elem_type)
  {
    Mesh mesh(*TestCommWorld);

    EquationSystems es(mesh);
    System &sys = es.add_system<System> ("SimpleSystem");
    sys.add_variable("u", THIRD, HIERARCHIC);

    const unsigned int n_elem_per_side = 3;
    const std::unique_ptr<Elem> test_elem = Elem::build(elem_type);
    const unsigned int ymax = test_elem->dim() > 1;
    const unsigned int zmax = test_elem->dim() > 2;
    const unsigned int ny = ymax * n_elem_per_side;
    const unsigned int nz = zmax * n_elem_per_side;

    MeshTools::Generation::build_cube (mesh,
                                       n_elem_per_side,
                                       ny,
                                       nz,
                                       0., 1.,
                                       0., ymax,
                                       0., zmax,
                                       elem_type);

    es.init();

    DofMap & dof_map = sys.get_dof_map();
    for (dof_id_type id = 0; id != dof_map.n_dofs(); ++id)
      {
        const processor_id_type pid = dof_map.dof_owner(id);
        CPPUNIT_ASSERT(dof_map.first_dof(pid) <= id);
        CPPUNIT_ASSERT(id < dof_map.end_dof(pid));
      }
  }

  void testDofOwnerOnEdge3() { LOG_UNIT_TEST; testDofOwner(EDGE3); }
  void testDofOwnerOnQuad9() { LOG_UNIT_TEST; testDofOwner(QUAD9); }
  void testDofOwnerOnTri6()  { LOG_UNIT_TEST; testDofOwner(TRI6); }
  void testDofOwnerOnHex27() { LOG_UNIT_TEST; testDofOwner(HEX27); }

#if defined(LIBMESH_ENABLE_EXCEPTIONS)
  void testBadElemFECombo()
  {
    LOG_UNIT_TEST;
    Mesh mesh(*TestCommWorld);

    EquationSystems es(mesh);
    System & sys = es.add_system<System> ("SimpleSystem");
    sys.add_variable("u", SECOND);

    MeshTools::Generation::build_square (mesh,4,4,-1., 1.,-1., 1., QUAD4);

    // We can't just CPPUNIT_ASSERT_THROW, because we want to make
    // sure we were thrown from the right place with the right error
    // message!
    bool threw_desired_exception = false;
    try {
      es.init();
    }
    catch (libMesh::LogicError & e) {
      std::regex msg_regex("only supports FEInterface::max_order");
      CPPUNIT_ASSERT(std::regex_search(e.what(), msg_regex));
      threw_desired_exception = true;
    }
    catch (...) {
      CPPUNIT_ASSERT(false);
    }

    CPPUNIT_ASSERT(threw_desired_exception);

    CPPUNIT_ASSERT_THROW_MESSAGE("Incompatible Elem/FE combo not detected", es.init(), libMesh::LogicError);
  }
#endif

#if defined(LIBMESH_ENABLE_CONSTRAINTS) && defined(LIBMESH_ENABLE_EXCEPTIONS)
  void testConstraintLoopDetection()
  {
    LOG_UNIT_TEST;
    Mesh mesh(*TestCommWorld);

    EquationSystems es(mesh);
    System & sys = es.add_system<System> ("SimpleSystem");
    sys.add_variable("u", FIRST);

    MyConstraint my_constraint(sys);
    sys.attach_constraint_object(my_constraint);

    MeshTools::Generation::build_square (mesh,4,4,-1., 1.,-1., 1., QUAD4);

    // Tell the dof_map to check for constraint loops
    DofMap & dof_map = sys.get_dof_map();
    dof_map.set_error_on_constraint_loop(true);

    CPPUNIT_ASSERT_THROW_MESSAGE("Constraint loop not detected", es.init(), libMesh::LogicError);
  }
#endif

};

CPPUNIT_TEST_SUITE_REGISTRATION( DofMapTest );
<commit_msg>Try testBadElemFECombo only if min(n_local_elem)<commit_after>#include <libmesh/equation_systems.h>
#include <libmesh/mesh.h>
#include <libmesh/mesh_generation.h>
#include <libmesh/elem.h>
#include <libmesh/dof_map.h>

#include <timpi/parallel_implementation.h>

#include "test_comm.h"
#include "libmesh_cppunit.h"

#include <regex>
#include <string>

using namespace libMesh;

#ifdef LIBMESH_ENABLE_CONSTRAINTS
// This class is used by testConstraintLoopDetection
class MyConstraint : public System::Constraint
{
private:

  System & _sys;

public:

  MyConstraint( System & sys ) : Constraint(), _sys(sys) {}

  virtual ~MyConstraint() {}

  void constrain()
  {
    {
      const dof_id_type constrained_dof_index = 0;
      DofConstraintRow constraint_row;
      constraint_row[1] = 1.0;
      _sys.get_dof_map().add_constraint_row( constrained_dof_index, constraint_row, 0., true);
    }
    {
      const dof_id_type constrained_dof_index = 1;
      DofConstraintRow constraint_row;
      constraint_row[0] = 1.0;
      _sys.get_dof_map().add_constraint_row( constrained_dof_index, constraint_row, 0., true);
    }
  }
};
#endif

class DofMapTest : public CppUnit::TestCase {
public:
  LIBMESH_CPPUNIT_TEST_SUITE( DofMapTest );

  CPPUNIT_TEST( testDofOwnerOnEdge3 );
#if LIBMESH_DIM > 1
  CPPUNIT_TEST( testDofOwnerOnQuad9 );
  CPPUNIT_TEST( testDofOwnerOnTri6 );
#endif
#if LIBMESH_DIM > 2
  CPPUNIT_TEST( testDofOwnerOnHex27 );
#endif

#if defined(LIBMESH_ENABLE_EXCEPTIONS)
  CPPUNIT_TEST( testBadElemFECombo );
#endif

#if defined(LIBMESH_ENABLE_CONSTRAINTS) && defined(LIBMESH_ENABLE_EXCEPTIONS) && LIBMESH_DIM > 1
  CPPUNIT_TEST( testConstraintLoopDetection );
#endif

  CPPUNIT_TEST_SUITE_END();

private:

public:
  void setUp()
  {}

  void tearDown()
  {}

  void testDofOwner(const ElemType elem_type)
  {
    Mesh mesh(*TestCommWorld);

    EquationSystems es(mesh);
    System &sys = es.add_system<System> ("SimpleSystem");
    sys.add_variable("u", THIRD, HIERARCHIC);

    const unsigned int n_elem_per_side = 3;
    const std::unique_ptr<Elem> test_elem = Elem::build(elem_type);
    const unsigned int ymax = test_elem->dim() > 1;
    const unsigned int zmax = test_elem->dim() > 2;
    const unsigned int ny = ymax * n_elem_per_side;
    const unsigned int nz = zmax * n_elem_per_side;

    MeshTools::Generation::build_cube (mesh,
                                       n_elem_per_side,
                                       ny,
                                       nz,
                                       0., 1.,
                                       0., ymax,
                                       0., zmax,
                                       elem_type);

    es.init();

    DofMap & dof_map = sys.get_dof_map();
    for (dof_id_type id = 0; id != dof_map.n_dofs(); ++id)
      {
        const processor_id_type pid = dof_map.dof_owner(id);
        CPPUNIT_ASSERT(dof_map.first_dof(pid) <= id);
        CPPUNIT_ASSERT(id < dof_map.end_dof(pid));
      }
  }

  void testDofOwnerOnEdge3() { LOG_UNIT_TEST; testDofOwner(EDGE3); }
  void testDofOwnerOnQuad9() { LOG_UNIT_TEST; testDofOwner(QUAD9); }
  void testDofOwnerOnTri6()  { LOG_UNIT_TEST; testDofOwner(TRI6); }
  void testDofOwnerOnHex27() { LOG_UNIT_TEST; testDofOwner(HEX27); }

#if defined(LIBMESH_ENABLE_EXCEPTIONS)
  void testBadElemFECombo()
  {
    LOG_UNIT_TEST;

    Mesh mesh(*TestCommWorld);

    EquationSystems es(mesh);
    System & sys = es.add_system<System> ("SimpleSystem");
    sys.add_variable("u", SECOND);

    MeshTools::Generation::build_square (mesh,4,4,-1., 1.,-1., 1., QUAD4);

    // We need at least one element per processor to make sure
    // everyone throws and we don't get out of sync before going on to
    // future tests.
    dof_id_type min_local_elem = mesh.n_local_elem();
    mesh.comm().min(min_local_elem);

    if (!min_local_elem)
      return;

    // We can't just CPPUNIT_ASSERT_THROW, because we want to make
    // sure we were thrown from the right place with the right error
    // message!
    bool threw_desired_exception = false;
    try {
      es.init();
    }
    catch (libMesh::LogicError & e) {
      std::regex msg_regex("only supports FEInterface::max_order");
      CPPUNIT_ASSERT(std::regex_search(e.what(), msg_regex));
      threw_desired_exception = true;
    }
    catch (...) {
      CPPUNIT_ASSERT_MESSAGE("Unexpected exception type thrown", false);
    }

    // If we have more than 4*4 processors, or a poor partitioner, we
    // might not get an exception on every processor
    mesh.comm().max(threw_desired_exception);

    CPPUNIT_ASSERT(threw_desired_exception);
  }
#endif

#if defined(LIBMESH_ENABLE_CONSTRAINTS) && defined(LIBMESH_ENABLE_EXCEPTIONS)
  void testConstraintLoopDetection()
  {
    LOG_UNIT_TEST;
    Mesh mesh(*TestCommWorld);

    EquationSystems es(mesh);
    System & sys = es.add_system<System> ("SimpleSystem");
    sys.add_variable("u", FIRST);

    MyConstraint my_constraint(sys);
    sys.attach_constraint_object(my_constraint);

    MeshTools::Generation::build_square (mesh,4,4,-1., 1.,-1., 1., QUAD4);

    // Tell the dof_map to check for constraint loops
    DofMap & dof_map = sys.get_dof_map();
    dof_map.set_error_on_constraint_loop(true);

    CPPUNIT_ASSERT_THROW_MESSAGE("Constraint loop not detected", es.init(), libMesh::LogicError);
  }
#endif

};

CPPUNIT_TEST_SUITE_REGISTRATION( DofMapTest );
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_SHARED_DATA_STORE_HPP
#define RJ_SHARED_DATA_STORE_HPP

#include <map>
#include <string>
#include <utility>
#include <vector>

#include <mlk/types/types.h>

namespace rj
{
	// TODO: move this helpers ???
	template<std::size_t tup_index, typename Type, typename Func, typename Tup>
	typename std::enable_if<tup_index == std::tuple_size<Tup>::value, void>::type
	get_type_index(Func&& f, Tup& t)
	{ }

	template<std::size_t tup_index, typename Type, typename Func, typename Tup>
	typename std::enable_if<tup_index < std::tuple_size<Tup>::value, void>::type
	get_type_index(Func&& f, Tup& t)
	{
		if(std::is_same<Type, typename std::tuple_element<tup_index, Tup>::type>::value)
			f(tup_index); // type match
		get_type_index<tup_index + 1, Type, Func, Tup>(f, t);
	}

	template<typename Type, typename Func, typename Tup>
	void get_type_index(Func&& f, Tup& t)
	{get_type_index<0, Type>(f, t);}

	struct store_base
	{ };

	template<typename Data_Type>
	struct basic_store : public store_base
	{
		using value_type = Data_Type;
		using map_type = std::map<std::string, value_type>;
		map_type m_values;

		basic_store(const map_type& m) :
			m_values{m}
		{ }
	};

	template<typename... Data_Types>
	class data_store
	{
		using types_tuple = std::tuple<Data_Types...>;
		types_tuple m_helpertuple;
		std::vector<mlk::sptr<store_base>> m_stores;

	public:
		template<typename... Map_Data_Types>
		data_store(Map_Data_Types&&... vars)
		{this->init(std::forward<Map_Data_Types>(vars)...);}

		template<typename Data_Type>
		Data_Type& get(const std::string& id)
		{
			auto index(0);
			get_type_index<Data_Type>([&index](int found_index){index = found_index;}, m_helpertuple);

			auto ptr(std::static_pointer_cast<basic_store<Data_Type>>(m_stores.at(index)));
			return ptr->m_values.at(id);
		}

	private:
		template<typename Head, typename... Tail>
		void init(const std::map<std::string, Head>& h, Tail&&... t)
		{
			auto ptr(std::make_shared<basic_store<Head>>(h));
			m_stores.emplace_back(ptr);
			this->init(std::forward<Tail>(t)...);
		}

		void init()
		{ }
	};
}

#endif // RJ_SHARED_DATA_STORE_HPP
<commit_msg>data_store: added static_assert arg checking<commit_after>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_SHARED_DATA_STORE_HPP
#define RJ_SHARED_DATA_STORE_HPP

#include <map>
#include <string>
#include <utility>
#include <vector>

#include <mlk/types/types.h>

namespace rj
{
	// TODO: move this helpers ???
	template<std::size_t tup_index, typename Type, typename Func, typename Tup>
	typename std::enable_if<tup_index == std::tuple_size<Tup>::value, void>::type
	get_type_index(Func&& f, Tup& t)
	{ }

	template<std::size_t tup_index, typename Type, typename Func, typename Tup>
	typename std::enable_if<tup_index < std::tuple_size<Tup>::value, void>::type
	get_type_index(Func&& f, Tup& t)
	{
		if(std::is_same<Type, typename std::tuple_element<tup_index, Tup>::type>::value)
			f(tup_index); // type match
		get_type_index<tup_index + 1, Type, Func, Tup>(f, t);
	}

	template<typename Type, typename Func, typename Tup>
	void get_type_index(Func&& f, Tup& t)
	{get_type_index<0, Type>(f, t);}

	struct store_base
	{ };

	template<typename Data_Type>
	struct basic_store : public store_base
	{
		using value_type = Data_Type;
		using map_type = std::map<std::string, value_type>;
		map_type m_values;

		basic_store(const map_type& m) :
			m_values{m}
		{ }
	};

	template<typename... Data_Types>
	class data_store
	{
		using types_tuple = std::tuple<Data_Types...>;
		types_tuple m_helpertuple;
		std::vector<mlk::sptr<store_base>> m_stores;

	public:
		template<typename... Map_Data_Types>
		data_store(Map_Data_Types&&... vars)
		{
			// check number of args
			static_assert(sizeof...(vars) == sizeof...(Data_Types), "rj::data_store<T...>: number of args is not matching");

			this->init(std::forward<Map_Data_Types>(vars)...);
		}

		template<typename Data_Type>
		Data_Type& get(const std::string& id)
		{
			auto index(0);
			get_type_index<Data_Type>([&index](int found_index){index = found_index;}, m_helpertuple);

			auto ptr(std::static_pointer_cast<basic_store<Data_Type>>(m_stores.at(index)));
			return ptr->m_values.at(id);
		}

	private:
		template<typename Head, typename... Tail>
		void init(const std::map<std::string, Head>& h, Tail&&... t)
		{
			auto ptr(std::make_shared<basic_store<Head>>(h));
			m_stores.emplace_back(ptr);
			this->init(std::forward<Tail>(t)...);
		}

		void init()
		{ }
	};
}

#endif // RJ_SHARED_DATA_STORE_HPP
<|endoftext|>


<commit_before>#include "alg/StrategySelecter.hh"
#include "alg/StrategyOptim.hh"
#include "alg/dummyStrategyOptim/DummyStrategyOptim.hh"
#include "alg/MCTS/MCTSStrategyOptim.hh"
#include "alg/printDebug/PrintDebugStrategy.hh"

StrategyOptim* StrategySelecter::buildStrategy(const variables_map& opt_p){
    string strategyName_l;
    if ( opt_p.count("strategy") ){
        strategyName_l = opt_p["strategy"].as<string>();
    }

    /* Ajouter ici une ribambelle de "if(strategyName_l == myName) return new myStrategy;
     */

    if(strategyName_l == "mcts")
        return new MCTSStrategyOptim();

    if(strategyName_l == "print" ){
        return new PrintDebugStrategy();
    }

    //Cas par defaut (ou : lever une exception ?)
    return new DummyStrategyOptim();
}
<commit_msg>MCTS Strategy par defaut<commit_after>#include "alg/StrategySelecter.hh"
#include "alg/StrategyOptim.hh"
#include "alg/dummyStrategyOptim/DummyStrategyOptim.hh"
#include "alg/MCTS/MCTSStrategyOptim.hh"
#include "alg/printDebug/PrintDebugStrategy.hh"

StrategyOptim* StrategySelecter::buildStrategy(const variables_map& opt_p){
    string strategyName_l;
    if ( opt_p.count("strategy") ){
        strategyName_l = opt_p["strategy"].as<string>();
    }

    /* Ajouter ici une ribambelle de "if(strategyName_l == myName) return new myStrategy;
     */

    if(strategyName_l == "mcts"){
        return new MCTSStrategyOptim();
    }

    if(strategyName_l == "print" ){
        return new PrintDebugStrategy();
    }

    //Cas par defaut
    return new MCTSStrategyOptim();
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2013 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_SHARED_DEBUG_TEXT_HPP
#define RJ_SHARED_DEBUG_TEXT_HPP

#include <rectojump/global/common.hpp>
#include <rectojump/global/errors.hpp>

#include <mlk/log/log.h>

#include <SFML/Graphics.hpp>

namespace rj
{
	class debug_text : public sf::Drawable
	{
		std::string m_current_str;
		sf::Color m_color;
		sf::Texture m_texture;
		sf::VertexArray m_verts{sf::Quads};
		vec2f m_size{0.f, 0.f};
		bool m_valid{false};

	public:
		debug_text(const std::string& tile_map_path, const sf::Color& color = {255, 255, 255}) :
			m_valid{m_texture.loadFromFile(tile_map_path)},
			m_color{color}
		{
			if(!m_valid)
				mlk::lerr(errors::io_open_file) << "filename=" << tile_map_path;
		}

		void set_text(const std::string& text) noexcept
		{m_current_str = text; this->refresh();}

		void set_color(const sf::Color& color) noexcept
		{m_color = color;}

		const vec2f& get_size() const noexcept
		{return m_size;}

	private:
		virtual void draw(sf::RenderTarget& target, sf::RenderStates) const override
		{target.draw(m_verts, &m_texture);}

		void reset() noexcept
		{m_verts.clear();}

		void refresh() noexcept
		{
			if(!m_valid)
				return;

			this->reset();

			auto posx(0.f), posy(0.f);
			auto lines(0);
			m_size.x = posx; m_size.y = posy;
			for(const auto& a : m_current_str)
			{
				if(a == '\n')
				{
					posy += 16.f;
					posx = 0.f;
					++lines;
					continue;
				}

				// tile position
				auto tiley(static_cast<float>((a / 16) * 16)), tilex(static_cast<float>((a % 16) * 16));

				// create quad
				m_verts.append({{posx, posy + 16.f}, m_color, {tilex, tiley + 16.f}});
				m_verts.append({{posx, posy}, m_color, {tilex, tiley}});
				m_verts.append({{posx + 16.f, posy}, m_color, {tilex + 16.f, tiley}});
				m_verts.append({{posx + 16.f, posy + 16.f}, m_color, {tilex + 16.f, tiley + 16.f}});

				posx += 16.f;
				if(posx > m_size.x) m_size.x = posx;
			}
			m_size.y = (lines + 1) * 16.f;
		}
	};
}

#endif // RJ_SHARED_DEBUG_TEXT_HPP
<commit_msg>added fontsize<commit_after>//
// Copyright (c) 2013 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_SHARED_DEBUG_TEXT_HPP
#define RJ_SHARED_DEBUG_TEXT_HPP

#include <rectojump/global/common.hpp>
#include <rectojump/global/errors.hpp>

#include <mlk/log/log.h>

#include <SFML/Graphics.hpp>

namespace rj
{
	class debug_text : public sf::Drawable
	{
		std::string m_current_str;
		sf::Color m_color;
		sf::Texture m_texture;
		sf::VertexArray m_verts{sf::Quads};
		vec2f m_size{0.f, 0.f};
		float m_fontsize;
		bool m_valid{false};

	public:
		debug_text(const std::string& tile_map_path, const sf::Color& color = {255, 255, 255}, float fontsize = 16.f) :
			m_valid{m_texture.loadFromFile(tile_map_path)},
			m_color{color},
			m_fontsize{fontsize}
		{
			if(!m_valid)
				mlk::lerr(errors::io_open_file) << "filename=" << tile_map_path;
		}

		void set_text(const std::string& text) noexcept
		{m_current_str = text; this->refresh();}

		void set_color(const sf::Color& color) noexcept
		{m_color = color;}

		void set_fontsize(float fontsize) noexcept
		{m_fontsize = fontsize;}

		float get_fontsize() const noexcept
		{return m_fontsize;}

		const vec2f& get_size() const noexcept
		{return m_size;}

	private:
		virtual void draw(sf::RenderTarget& target, sf::RenderStates) const override
		{target.draw(m_verts, &m_texture);}

		void reset() noexcept
		{m_verts.clear();}

		void refresh() noexcept
		{
			if(!m_valid)
				return;

			this->reset();

			auto posx(0.f), posy(0.f);
			auto lines(0);
			m_size.x = posx; m_size.y = posy;
			for(const auto& a : m_current_str)
			{
				if(a == '\n')
				{
					posy += m_fontsize;
					posx = 0.f;
					++lines;
					continue;
				}

				// tile position
				auto tiley(static_cast<float>((a / 16) * 16)), tilex(static_cast<float>((a % 16) * 16));

				// create quad
				m_verts.append({{posx, posy + m_fontsize}, m_color, {tilex, tiley + 16.f}});
				m_verts.append({{posx, posy}, m_color, {tilex, tiley}});
				m_verts.append({{posx + m_fontsize, posy}, m_color, {tilex + 16.f, tiley}});
				m_verts.append({{posx + m_fontsize, posy + m_fontsize}, m_color, {tilex + 16.f, tiley + 16.f}});

				posx += m_fontsize;
				if(posx > m_size.x) m_size.x = posx;
			}
			m_size.y = (lines + 1) * m_fontsize;
		}
	};
}

#endif // RJ_SHARED_DEBUG_TEXT_HPP
<|endoftext|>


<commit_before>/* algorithm.cpp - CS 472 Project #3: Genetic Programming
 * Copyright 2014 Andrew Schwartzmeyer
 *
 * Source file for algorithm namespace
 */

#include <algorithm>
#include <cassert>
#include <ctime>
#include <fstream>
#include <future>
#include <thread>

#include "algorithm.hpp"
#include "../individual/individual.hpp"
#include "../logging/logging.hpp"
#include "../options/options.hpp"
#include "../random_generator/random_generator.hpp"

namespace algorithm
{
  using std::vector;
  using individual::Individual;
  using options::Options;
  using namespace random_generator;

  // Returns true if "a" is closer to 0 than "b" and is also normal.
  bool
  compare_fitness::operator()(const Individual& a, const Individual& b)
  {
    return std::isnormal(a.get_fitness())
      ? (a.get_fitness() > b.get_fitness()) : false;
  }

  /* Create an initial population using "ramped half-and-half" (half
     full trees, half randomly grown trees, all to random depths
     between 0 and maximum depth). */
  vector<Individual>
  new_population(const Options& options)
  {
    vector<Individual> population;
    int_dist depth_dist{0, static_cast<int>(options.max_depth)}; // ramped
    for (unsigned int i = 0; i < options.population_size; ++i)
      {
	/* The depth is ramped, and so drawn randomly for each
	   individual. */
	unsigned int depth = depth_dist(rg.engine);
	population.emplace_back(Individual{
	    depth, options.grow_chance, options.map});
      }
    return population;
  }

  /* Return best candidate from size number of contestants randomly
     drawn from population. */
  Individual
  selection(const unsigned int& size, const vector<Individual>& population)
  {
    int_dist dist{0, static_cast<int>(population.size()) - 1}; // closed interval
    vector<Individual> contestants;

    for (unsigned int i = 0; i < size; ++i)
      contestants.emplace_back(population[dist(rg.engine)]);

    return *std::min_element(contestants.begin(), contestants.end(),
			     compare_fitness());
  }

  /* Return new offspring population reassembled from parallel calls to
     get_children () delegate. */
  vector<Individual>
  new_offspring(const Options& options, const vector<Individual>& population)
  {
    vector<Individual> offspring;
    offspring.reserve(population.size());
    // Select parents for children.
    while (offspring.size() != population.size())
      {
	offspring.emplace_back(selection(options.tournament_size, population));
      }
    // Binary crossover with probability.
    if (options.crossover_size == 2)
      {
	real_dist dist{0, 1};
	for (unsigned int i = 0; i < offspring.size(); i += 2)
	  {
	    if (dist(rg.engine) < options.crossover_chance)
	      {
		crossover(options.internals_chance,
			  offspring[i], offspring[i + 1]);
	      }
	  }
      }
    // Mutate and evaluate children.
    for (Individual& child : offspring)
      {
	real_dist dist{0, 1};
	// Mutate children conditionally
	if (dist(rg.engine) < options.mutate_chance)
	  child.mutate();
	// Evaluate all children
	child.evaluate(options.map, options.penalty); // Evaluate children
      }
    assert(offspring.size() == population.size());
    return offspring;
  }

  /* The actual genetic algorithm applied which (hopefully) produces a
     well-fit expression for a given dataset. */
  const individual::Individual
  genetic(unsigned int trial, const std::time_t& time, const Options& options)
  {
    // Start logging
    std::ofstream log;
    if (options.verbosity > 0)
      {
	logging::open_log(log, time, trial, options.logs_dir);
	logging::start_log(log, time, options);
      }
    // Begin timing algorithm.
    std::chrono::time_point<std::chrono::system_clock> start, end;
    start = std::chrono::system_clock::now();

    // Create initial population.
    vector<Individual> population = new_population(options);
    Individual best;

    // Run algorithm to termination.
    for (unsigned int i = 0; i < options.iterations; ++i)
      {
	// Find best Individual of current population.
	best = *std::min_element(population.begin(), population.end(),
				 compare_fitness());
	// Launch background logging thread.
	auto log_thread = std::async(std::launch::async, logging::log_info,
				     options.verbosity, options.logs_dir, time,
				     trial, i, best, population);
	// Create replacement population.
	vector<Individual> offspring = new_offspring(options, population);
	// Perform elitism replacement of random individuals.
	int_dist dist{0, static_cast<int>(options.population_size) - 1};
	for (unsigned int e = 0; e < options.elitism_size; ++e)
	  offspring[dist(rg.engine)] = best;
	// Replace current population with offspring.
	population = offspring;
	// Sync with background logging thread.
	log_thread.wait();
      }
    // End timing algorithm.
    end = std::chrono::system_clock::now();
    std::chrono::duration<double> elapsed_seconds = end - start;
    std::time_t end_time = std::chrono::system_clock::to_time_t(end);

    // Log time information.
    if (options.verbosity > 0)
      {
	logging::open_log(log, time, trial, options.logs_dir);
	log << best.print() << best.print_formula()
	    << "# Finished computation @ " << std::ctime(&end_time)
	    << "# Elapsed time: " << elapsed_seconds.count() << "s\n";
	log.close();
      }
    // Log evaluation plot data of best individual.
    std::ofstream plot;
    logging::open_log(plot, time, trial, options.plots_dir);
    plot << best.evaluate(options.map, options.penalty, true);
    plot.close();

    return best;
  }
}
<commit_msg>Adding missing cmath library to algorithm<commit_after>/* algorithm.cpp - CS 472 Project #3: Genetic Programming
 * Copyright 2014 Andrew Schwartzmeyer
 *
 * Source file for algorithm namespace
 */

#include <algorithm>
#include <cassert>
#include <cmath>
#include <ctime>
#include <fstream>
#include <future>
#include <thread>

#include "algorithm.hpp"
#include "../individual/individual.hpp"
#include "../logging/logging.hpp"
#include "../options/options.hpp"
#include "../random_generator/random_generator.hpp"

namespace algorithm
{
  using std::vector;
  using individual::Individual;
  using options::Options;
  using namespace random_generator;

  // Returns true if "a" is closer to 0 than "b" and is also normal.
  bool
  compare_fitness::operator()(const Individual& a, const Individual& b)
  {
    return std::isnormal(a.get_fitness())
      ? (a.get_fitness() > b.get_fitness()) : false;
  }

  /* Create an initial population using "ramped half-and-half" (half
     full trees, half randomly grown trees, all to random depths
     between 0 and maximum depth). */
  vector<Individual>
  new_population(const Options& options)
  {
    vector<Individual> population;
    int_dist depth_dist{0, static_cast<int>(options.max_depth)}; // ramped
    for (unsigned int i = 0; i < options.population_size; ++i)
      {
	/* The depth is ramped, and so drawn randomly for each
	   individual. */
	unsigned int depth = depth_dist(rg.engine);
	population.emplace_back(Individual{
	    depth, options.grow_chance, options.map});
      }
    return population;
  }

  /* Return best candidate from size number of contestants randomly
     drawn from population. */
  Individual
  selection(const unsigned int& size, const vector<Individual>& population)
  {
    int_dist dist{0, static_cast<int>(population.size()) - 1}; // closed interval
    vector<Individual> contestants;

    for (unsigned int i = 0; i < size; ++i)
      contestants.emplace_back(population[dist(rg.engine)]);

    return *std::min_element(contestants.begin(), contestants.end(),
			     compare_fitness());
  }

  /* Return new offspring population reassembled from parallel calls to
     get_children () delegate. */
  vector<Individual>
  new_offspring(const Options& options, const vector<Individual>& population)
  {
    vector<Individual> offspring;
    offspring.reserve(population.size());
    // Select parents for children.
    while (offspring.size() != population.size())
      {
	offspring.emplace_back(selection(options.tournament_size, population));
      }
    // Binary crossover with probability.
    if (options.crossover_size == 2)
      {
	real_dist dist{0, 1};
	for (unsigned int i = 0; i < offspring.size(); i += 2)
	  {
	    if (dist(rg.engine) < options.crossover_chance)
	      {
		crossover(options.internals_chance,
			  offspring[i], offspring[i + 1]);
	      }
	  }
      }
    // Mutate and evaluate children.
    for (Individual& child : offspring)
      {
	real_dist dist{0, 1};
	// Mutate children conditionally
	if (dist(rg.engine) < options.mutate_chance)
	  child.mutate();
	// Evaluate all children
	child.evaluate(options.map, options.penalty); // Evaluate children
      }
    assert(offspring.size() == population.size());
    return offspring;
  }

  /* The actual genetic algorithm applied which (hopefully) produces a
     well-fit expression for a given dataset. */
  const individual::Individual
  genetic(unsigned int trial, const std::time_t& time, const Options& options)
  {
    // Start logging
    std::ofstream log;
    if (options.verbosity > 0)
      {
	logging::open_log(log, time, trial, options.logs_dir);
	logging::start_log(log, time, options);
      }
    // Begin timing algorithm.
    std::chrono::time_point<std::chrono::system_clock> start, end;
    start = std::chrono::system_clock::now();

    // Create initial population.
    vector<Individual> population = new_population(options);
    Individual best;

    // Run algorithm to termination.
    for (unsigned int i = 0; i < options.iterations; ++i)
      {
	// Find best Individual of current population.
	best = *std::min_element(population.begin(), population.end(),
				 compare_fitness());
	// Launch background logging thread.
	auto log_thread = std::async(std::launch::async, logging::log_info,
				     options.verbosity, options.logs_dir, time,
				     trial, i, best, population);
	// Create replacement population.
	vector<Individual> offspring = new_offspring(options, population);
	// Perform elitism replacement of random individuals.
	int_dist dist{0, static_cast<int>(options.population_size) - 1};
	for (unsigned int e = 0; e < options.elitism_size; ++e)
	  offspring[dist(rg.engine)] = best;
	// Replace current population with offspring.
	population = offspring;
	// Sync with background logging thread.
	log_thread.wait();
      }
    // End timing algorithm.
    end = std::chrono::system_clock::now();
    std::chrono::duration<double> elapsed_seconds = end - start;
    std::time_t end_time = std::chrono::system_clock::to_time_t(end);

    // Log time information.
    if (options.verbosity > 0)
      {
	logging::open_log(log, time, trial, options.logs_dir);
	log << best.print() << best.print_formula()
	    << "# Finished computation @ " << std::ctime(&end_time)
	    << "# Elapsed time: " << elapsed_seconds.count() << "s\n";
	log.close();
      }
    // Log evaluation plot data of best individual.
    std::ofstream plot;
    logging::open_log(plot, time, trial, options.plots_dir);
    plot << best.evaluate(options.map, options.penalty, true);
    plot.close();

    return best;
  }
}
<|endoftext|>


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

#include <cerrno>
#include <cstring>
#include <iostream>
#include <stdexcept>

#include "gtest/gtest.h"

#include "checkcall.hpp"
#include "test_api.h"

using namespace ::cwrap;
using namespace ::cwrap::testing::mock;
using namespace ::cwrap::testing::mock::api;
using namespace ::cwrap::testing::assertions;

TEST(CheckCallTest, testStadardUsage) {
    MockAPI::instance().reset();
    ASSERT_NOT_CALLED(MockAPI::instance().someFuncWithErrorCode());
    const auto x = CALL_CHECKED(some_func_with_error_code, 0);
    ASSERT_CALLED(MockAPI::instance().someFuncWithErrorCode());
    ASSERT_EQ(x, 0);
}

TEST(CheckCallTest, testIsNotZeroReturnCheckPolicy) {
    MockAPI::instance().reset();
    ASSERT_NOT_CALLED(MockAPI::instance().someFuncWithErrorCode());
    const auto x = CALL_CHECKED<IsNotZeroReturnCheckPolicy>(some_func_with_error_code, 1);
    ASSERT_CALLED(MockAPI::instance().someFuncWithErrorCode());
    ASSERT_EQ(x, 1);
}

TEST(CallGuardTest, testCallGuardClassCallCorrectly) {
    bool called{false};
    auto func = [&called](int x, bool y) {
        called = true;
        return y ? 2 * x : x;
    };
    CallGuard<decltype(func), IsNotNegativeReturnCheckPolicy> guard{std::move(func)};
    ASSERT_FALSE(called);
    const auto x = guard(8, true);
    ASSERT_TRUE(called);
    ASSERT_EQ(x, 16);
}

TEST(CallGuardTest, functionPointerTest) {
    MockAPI::instance().reset();
    CallGuard<decltype(some_func_with_error_code), IsNotNegativeReturnCheckPolicy> guard{
            some_func_with_error_code};
    const auto x = guard(17);
    ASSERT_EQ(x, 17);
    ASSERT_CALLED(MockAPI::instance().someFuncWithErrorCode());
}

TEST(CallGuardTest, testCallGuardDefaultConstructor) {
    // functor has a default constructor
    struct Functor {
        bool operator()(int x) { return x > 0; }
    };
    struct CustomReturnPolicy {
        static inline bool returnValueIsOk(bool b) { return b; }
    };

    CallGuard<Functor, CustomReturnPolicy> guard{};
    ASSERT_TRUE(guard(17));
    static_assert(std::is_same<bool, decltype(guard(17))>::value,
                  "Return type should be identical to functor");
}

TEST(CallGuardTest, testIsZeroReturnCheckPolicy) {
    auto lambda = [](int x) { return x; };
    // IsZeroReturnCheckPolicy should be default, so don't specify it.
    CallGuard<decltype(lambda)> guard{std::move(lambda)};
    ASSERT_THROW(guard(1), std::runtime_error);
    ASSERT_THROW(guard(-1), std::runtime_error);
    ASSERT_NO_THROW(guard(0));
}

TEST(CallGuardTest, testIsNotNegativeCheckPolicy) {
    auto lambda = [](int x) { return x; };
    CallGuard<decltype(lambda), IsNotNegativeReturnCheckPolicy> guard{std::move(lambda)};
    ASSERT_NO_THROW(guard(1));
    ASSERT_NO_THROW(guard(0));
    ASSERT_THROW(guard(-1), std::runtime_error);
}

TEST(CallGuardTest, defaultErrorPolicyTest) {
    auto lambda = [](int x) { return x; };
    CallGuard<decltype(lambda), IsNotNegativeReturnCheckPolicy> guard{std::move(lambda)};
    try {
        guard(-1337);
    } catch (const std::runtime_error &e) {
        ASSERT_NE(std::string::npos, std::string(e.what()).find("-1337"));
        return;
    }
    FAIL() << "Execution should not reach this line";
}

TEST(CallGuardTest, testErrnoErrorPolicy) {
    auto lambda = [](int x) { return x; };
    CallGuard<decltype(lambda), IsNotNegativeReturnCheckPolicy, ErrnoErrorPolicy> guard{
            std::move(lambda)};
    errno = EINVAL;
    try {
        guard(-1337);
    } catch (const std::runtime_error &e) {
        ASSERT_EQ(std::string(e.what()), std::string(std::strerror(EINVAL)));
        return;
    }
    FAIL() << "Execution should not reach this line";
}

TEST(CallGuardTest, testErrorCodeErrorPolicy) {
    auto lambda = [](int x) { return x; };
    CallGuard<decltype(lambda), IsNotNegativeReturnCheckPolicy, ErrorCodeErrorPolicy> guard{
            std::move(lambda)};
    try {
        guard(-EINVAL);
    } catch (const std::runtime_error &e) {
        ASSERT_EQ(std::string(e.what()), std::string(std::strerror(EINVAL)));
        return;
    }
    FAIL() << "Execution should not reach this line";
}
<commit_msg>checkcall: Refactor unit tests<commit_after>/*
 *  CWrap - A library to use C-code in C++.
 *  Copyright (C) 2016  Marcus Gelderie
 *
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
 *  USA
 */

#include <cerrno>
#include <cstring>
#include <iostream>
#include <stdexcept>

#include "gtest/gtest.h"

#include "checkcall.hpp"
#include "test_api.h"

using namespace ::cwrap;
using namespace ::cwrap::testing::mock;
using namespace ::cwrap::testing::mock::api;
using namespace ::cwrap::testing::assertions;

class CheckCallTest : public ::testing::Test {
public:
    void SetUp() override { MockAPI::instance().reset(); }
};

TEST_F(CheckCallTest, testStadardUsage) {
    ASSERT_NOT_CALLED(MockAPI::instance().someFuncWithErrorCode());
    const auto x = CALL_CHECKED(some_func_with_error_code, 0);
    ASSERT_CALLED(MockAPI::instance().someFuncWithErrorCode());
    ASSERT_EQ(x, 0);
}

TEST_F(CheckCallTest, testIsNotZeroReturnCheckPolicy) {
    MockAPI::instance().reset();
    ASSERT_NOT_CALLED(MockAPI::instance().someFuncWithErrorCode());
    const auto x = CALL_CHECKED<IsNotZeroReturnCheckPolicy>(some_func_with_error_code, 1);
    ASSERT_CALLED(MockAPI::instance().someFuncWithErrorCode());
    ASSERT_EQ(x, 1);
}

class CallGuardTest : public ::testing::Test {
public:
    void SetUp() override {
        MockAPI::instance().reset();
        _called = false;
        _func = [this](int x) {
            _called = true;
            return x;
        };
    }

protected:
    bool _called{false};
    std::function<int(int)> _func;
};

TEST_F(CallGuardTest, testCallGuardClassCallCorrectly) {
    CallGuard<decltype(_func), IsNotNegativeReturnCheckPolicy> guard{std::move(_func)};
    ASSERT_FALSE(_called);
    const auto x = guard(8);
    ASSERT_TRUE(_called);
    ASSERT_EQ(x, 8);
}

TEST_F(CallGuardTest, functionPointerTest) {
    CallGuard<decltype(some_func_with_error_code), IsNotNegativeReturnCheckPolicy> guard{
            some_func_with_error_code};
    const auto x = guard(17);
    ASSERT_EQ(x, 17);
    ASSERT_CALLED(MockAPI::instance().someFuncWithErrorCode());
}

TEST_F(CallGuardTest, testCallGuardDefaultConstructor) {
    // functor has a default constructor
    struct Functor {
        bool operator()(int x) { return x > 0; }
    };
    struct CustomReturnPolicy {
        static inline bool returnValueIsOk(bool b) { return b; }
    };

    CallGuard<Functor, CustomReturnPolicy> guard{};
    ASSERT_TRUE(guard(17));
    static_assert(std::is_same<bool, decltype(guard(17))>::value,
                  "Return type should be identical to functor");
}

TEST_F(CallGuardTest, testIsZeroReturnCheckPolicy) {
    // IsZeroReturnCheckPolicy should be default, so don't specify it.
    CallGuard<decltype(_func)> guard{std::move(_func)};
    ASSERT_THROW(guard(1), std::runtime_error);
    ASSERT_THROW(guard(-1), std::runtime_error);
    ASSERT_NO_THROW(guard(0));
}

TEST_F(CallGuardTest, testIsNotNegativeCheckPolicy) {
    CallGuard<decltype(_func), IsNotNegativeReturnCheckPolicy> guard{std::move(_func)};
    ASSERT_NO_THROW(guard(1));
    ASSERT_NO_THROW(guard(0));
    ASSERT_THROW(guard(-1), std::runtime_error);
}

TEST_F(CallGuardTest, defaultErrorPolicyTest) {
    CallGuard<decltype(_func), IsNotNegativeReturnCheckPolicy> guard{std::move(_func)};
    try {
        guard(-1337);
    } catch (const std::runtime_error &e) {
        ASSERT_NE(std::string::npos, std::string(e.what()).find("-1337"));
        return;
    }
    FAIL() << "Execution should not reach this line";
}

TEST_F(CallGuardTest, testErrnoErrorPolicy) {
    CallGuard<decltype(_func), IsNotNegativeReturnCheckPolicy, ErrnoErrorPolicy> guard{
            std::move(_func)};
    errno = EINVAL;
    try {
        guard(-1337);
    } catch (const std::runtime_error &e) {
        ASSERT_EQ(std::string(e.what()), std::string(std::strerror(EINVAL)));
        return;
    }
    FAIL() << "Execution should not reach this line";
}

TEST_F(CallGuardTest, testErrorCodeErrorPolicy) {
    CallGuard<decltype(_func), IsNotNegativeReturnCheckPolicy, ErrorCodeErrorPolicy> guard{
            std::move(_func)};
    try {
        guard(-EINVAL);
    } catch (const std::runtime_error &e) {
        ASSERT_EQ(std::string(e.what()), std::string(std::strerror(EINVAL)));
        return;
    }
    FAIL() << "Execution should not reach this line";
}
<|endoftext|>


<commit_before>#ifndef SIPLASPLAS_VARIANT_OPTIONAL_HPP
#define SIPLASPLAS_VARIANT_OPTIONAL_HPP

#include "variant.hpp"

namespace cpp
{

template<typename T>
class Optional
{
public:
    Optional() = default;

    template<typename... Args>
    Optional(Args&&... args) :
        _variant{T{std::forward<Args>(args)...}}
    {}

    template<typename U>
    Optional(const Optional<U>& other) :
        Optional{other.empty() ? Optional() : other.get()}
    {}

    template<typename U>
    Optional(Optional<U>&& other) :
        Optional{other.empty() ? Optional() : std::move(std::move(other).get())}
    {}

    template<typename U>
    Optional& operator=(U&& value)
    {
        _variant = T{std::forward<U>(value)};
        return *this;
    }

    template<typename U>
    Optional& operator=(const Optional<U>& other)
    {
        if(other.empty())
        {
            clear();
        }
        else
        {
            _variant = other.get();
        }

        return *this;
    }

    template<typename U>
    Optional& operator=(Optional<U>&& other)
    {
        if(other.empty())
        {
            clear();
        }
        else
        {
            _variant = std::move(std::move(other).get());
        }

        return *this;
    }

    const T& get() const
    {
        return _variant.template get<T>();
    }

    T& get()
    {
        return _variant.template get<T>();
    }

    const T* operator->() const
    {
        return &get();
    }

    T* operator->()
    {
        return &get();
    }

    void clear()
    {
        _variant.clear();
    }

    bool empty() const
    {
        return _variant.empty();
    }

    explicit operator bool() const
    {
        return !empty;
    }

private:
    cpp::Variant<T> _variant;
};

class Nothing
{
public:
    template<typename T>
    operator Optional<T>()
    {
        return Optional<T>();
    }
};

template<typename T>
Optional<std::decay_t<T>> just(T&& value)
{
    return {value};
}

Nothing nothing()
{
    return {};
}

}

#endif // SIPLASPLAS_VARIANT_OPTIONAL_HPP
<commit_msg>Fix call to Optional::empty() in Optional::operator bool()<commit_after>#ifndef SIPLASPLAS_VARIANT_OPTIONAL_HPP
#define SIPLASPLAS_VARIANT_OPTIONAL_HPP

#include "variant.hpp"

namespace cpp
{

template<typename T>
class Optional
{
public:
    Optional() = default;

    template<typename... Args>
    Optional(Args&&... args) :
        _variant{T{std::forward<Args>(args)...}}
    {}

    template<typename U>
    Optional(const Optional<U>& other) :
        Optional{other.empty() ? Optional() : other.get()}
    {}

    template<typename U>
    Optional(Optional<U>&& other) :
        Optional{other.empty() ? Optional() : std::move(std::move(other).get())}
    {}

    template<typename U>
    Optional& operator=(U&& value)
    {
        _variant = T{std::forward<U>(value)};
        return *this;
    }

    template<typename U>
    Optional& operator=(const Optional<U>& other)
    {
        if(other.empty())
        {
            clear();
        }
        else
        {
            _variant = other.get();
        }

        return *this;
    }

    template<typename U>
    Optional& operator=(Optional<U>&& other)
    {
        if(other.empty())
        {
            clear();
        }
        else
        {
            _variant = std::move(std::move(other).get());
        }

        return *this;
    }

    const T& get() const
    {
        return _variant.template get<T>();
    }

    T& get()
    {
        return _variant.template get<T>();
    }

    const T* operator->() const
    {
        return &get();
    }

    T* operator->()
    {
        return &get();
    }

    void clear()
    {
        _variant.clear();
    }

    bool empty() const
    {
        return _variant.empty();
    }

    explicit operator bool() const
    {
        return !empty();
    }

private:
    cpp::Variant<T> _variant;
};

class Nothing
{
public:
    template<typename T>
    operator Optional<T>()
    {
        return Optional<T>();
    }
};

template<typename T>
Optional<std::decay_t<T>> just(T&& value)
{
    return {value};
}

Nothing nothing()
{
    return {};
}

}

#endif // SIPLASPLAS_VARIANT_OPTIONAL_HPP
<|endoftext|>


<commit_before>/* Copyright 2013-2016 CyberTech Labs Ltd.
 *
 * 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 "trikKitInterpreterCommon/trikKitInterpreterPluginBase.h"

#include <QtWidgets/QApplication>
#include <QtWidgets/QLineEdit>

#include <twoDModel/engine/twoDModelEngineFacade.h>
#include <qrkernel/settingsManager.h>
#include <qrkernel/settingsListener.h>

#include <qrgui/textEditor/qscintillaTextEdit.h>
#include <qrgui/textEditor/languageInfo.h>

using namespace trik;
using namespace qReal;

const Id robotDiagramType = Id("RobotsMetamodel", "RobotsDiagram", "RobotsDiagramNode");
const Id subprogramDiagramType = Id("RobotsMetamodel", "RobotsDiagram", "SubprogramDiagram");

TrikKitInterpreterPluginBase::TrikKitInterpreterPluginBase() :
	mStart(tr("Start QTS"), nullptr), mStop(tr("Stop QTS"), nullptr)
{
}

TrikKitInterpreterPluginBase::~TrikKitInterpreterPluginBase()
{
	if (mOwnsAdditionalPreferences) {
		delete mAdditionalPreferences;
	}

	if (mOwnsBlocksFactory) {
		delete mBlocksFactory;
	}
}

void TrikKitInterpreterPluginBase::initKitInterpreterPluginBase
		(robotModel::TrikRobotModelBase * const realRobotModel
		, robotModel::twoD::TrikTwoDRobotModel * const twoDRobotModel
		, blocks::TrikBlocksFactoryBase * const blocksFactory
		)
{
	mRealRobotModel.reset(realRobotModel);
	mTwoDRobotModel.reset(twoDRobotModel);
	mBlocksFactory = blocksFactory;

	const auto modelEngine = new twoDModel::engine::TwoDModelEngineFacade(*mTwoDRobotModel);

	mTwoDRobotModel->setEngine(modelEngine->engine());
	mTwoDModel.reset(modelEngine);

	connectDevicesConfigurationProvider(devicesConfigurationProvider()); // ... =(

	mAdditionalPreferences = new TrikAdditionalPreferences({ mRealRobotModel->name() });

	mQtsInterpreter.reset(new TrikQtsInterpreter(mTwoDRobotModel));
}

void TrikKitInterpreterPluginBase::startJSInterpretation(const QString &code)
{
	emit codeInterpretationStarted(code);

	auto model = mTwoDRobotModel;
	model->stopRobot(); // testStop?
	const QString modelName = model->robotId();

	for (const kitBase::robotModel::PortInfo &port : model->configurablePorts()) {
		const kitBase::robotModel::DeviceInfo deviceInfo = currentConfiguration(modelName, port);
		model->configureDevice(port, deviceInfo);
	}

	model->applyConfiguration();

	qtsInterpreter()->init();

	qtsInterpreter()->setCurrentDir(mProjectManager->saveFilePath());
	qtsInterpreter()->setRunning(true);
	emit started();
	qtsInterpreter()->interpretScript(code);
}

void TrikKitInterpreterPluginBase::startJSInterpretation(const QString &code, const QString &inputs)
{
	// we are in exercise mode (maybe rename it later)
	emit codeInterpretationStarted(code);

	auto model = mTwoDRobotModel;
	model->stopRobot(); // testStop?
	const QString modelName = model->robotId();

	for (const kitBase::robotModel::PortInfo &port : model->configurablePorts()) {
		const kitBase::robotModel::DeviceInfo deviceInfo = currentConfiguration(modelName, port);
		model->configureDevice(port, deviceInfo);
	}

	model->applyConfiguration();

	qtsInterpreter()->init();

	qtsInterpreter()->setCurrentDir(mProjectManager->saveFilePath());
	qtsInterpreter()->setRunning(true);
	emit started();
	qtsInterpreter()->interpretScriptExercise(code, inputs);
}

TrikQtsInterpreter * TrikKitInterpreterPluginBase::qtsInterpreter() const
{
	return mQtsInterpreter.data();
}

void TrikKitInterpreterPluginBase::init(const kitBase::KitPluginConfigurator &configurer)
{
	connect(&configurer.eventsForKitPlugin()
			, &kitBase::EventsForKitPluginInterface::robotModelChanged
			, [this](const QString &modelName) { mCurrentlySelectedModelName = modelName; });

	qReal::gui::MainWindowInterpretersInterface &interpretersInterface
			= configurer.qRealConfigurator().mainWindowInterpretersInterface();

	mProjectManager = &configurer.qRealConfigurator().projectManager();

	mTwoDModel->init(configurer.eventsForKitPlugin()
			, configurer.qRealConfigurator().systemEvents()
			, configurer.qRealConfigurator().logicalModelApi()
			, configurer.qRealConfigurator().controller()
			, interpretersInterface
			, configurer.qRealConfigurator().mainWindowDockInterface()
			, configurer.qRealConfigurator().projectManager()
			, configurer.interpreterControl());

	mRealRobotModel->setErrorReporter(*interpretersInterface.errorReporter());
	mTwoDRobotModel->setErrorReporter(*interpretersInterface.errorReporter());

	mQtsInterpreter->setErrorReporter(*interpretersInterface.errorReporter());

	mMainWindow = &configurer.qRealConfigurator().mainWindowInterpretersInterface();

	mSystemEvents = &configurer.qRealConfigurator().systemEvents();

	/// @todo: refactor?
	mStart.setObjectName("runQts");
	mStart.setText(tr("Run program"));
	mStart.setIcon(QIcon(":/trik/qts/images/run.png"));

	mStop.setObjectName("stopQts");
	mStop.setText(tr("Stop robot"));
	mStop.setIcon(QIcon(":/trik/qts/images/stop.png"));

	mStop.setVisible(false);
	mStart.setVisible(false);

	connect(&configurer.eventsForKitPlugin()
			, &kitBase::EventsForKitPluginInterface::interpretCode
			, [this](const QString &code, const QString &inputs){
		if (mIsModelSelected) {
			startJSInterpretation(code, inputs);
		}
	});

	connect(&configurer.robotModelManager()
			, &kitBase::robotModel::RobotModelManagerInterface::robotModelChanged
			, [this](kitBase::robotModel::RobotModelInterface &model){
		mIsModelSelected = robotModels().contains(&model);
		/// @todo: would probably make sense to make the current opened tab info available globally somewhere
		bool isCodeTabOpen = dynamic_cast<qReal::text::QScintillaTextEdit *>(mMainWindow->currentTab()) != nullptr;
		/// @todo: bad, relies on the slot order, because of another @todo in actionManager (custom visibility logic)
		bool isQtsInterp = mQtsInterpreter->supportedRobotModelNames().contains(model.name());
		mStart.setVisible(mIsModelSelected && isCodeTabOpen && isQtsInterp);
		mStop.setVisible(false); // interpretation should always stop when switching models?
	});

	connect(&configurer.interpreterControl()
			, &kitBase::InterpreterControlInterface::stopAllInterpretation
			, this
			, [this](qReal::interpretation::StopReason) {
		if (mQtsInterpreter->isRunning()) {
			testStop();
		}
	});

	connect(&configurer.interpreterControl()
			, &kitBase::InterpreterControlInterface::startJsInterpretation
			, this
			, [this]() {
		if (!mQtsInterpreter->isRunning() && mIsModelSelected) { // temporary
			testStart();
		}
	});

	connect(&mStart, &QAction::triggered, this, &TrikKitInterpreterPluginBase::testStart);
	connect(&mStop, &QAction::triggered, this, &TrikKitInterpreterPluginBase::testStop);
	connect(mQtsInterpreter.data()
			, &TrikQtsInterpreter::completed
			, this
			, &TrikKitInterpreterPluginBase::testStop);
	// refactor?
	connect(this
			, &TrikKitInterpreterPluginBase::started
			, &configurer.eventsForKitPlugin()
			, &kitBase::EventsForKitPluginInterface::interpretationStarted
			);

	connect(this
			, &TrikKitInterpreterPluginBase::stopped
			, &configurer.eventsForKitPlugin()
			, &kitBase::EventsForKitPluginInterface::interpretationStopped
			);

//	connect(&configurer.qRealConfigurator().systemEvents(),
//			&kitBase::EventsForKitPluginInterface:)

	connect(&configurer.eventsForKitPlugin()
			, &kitBase::EventsForKitPluginInterface::interpretationStarted
			, [this](){ /// @todo
		const bool isQtsInt = mQtsInterpreter->isRunning();
		mStart.setEnabled(isQtsInt);
		mStop.setEnabled(isQtsInt);
	}
	);

	QObject::connect(
				this
				, &TrikKitInterpreterPluginBase::codeInterpretationStarted
				, &configurer.eventsForKitPlugin()
				, &kitBase::EventsForKitPluginInterface::codeInterpretationStarted
				);

	QObject::connect(
				&configurer.eventsForKitPlugin()
				, &kitBase::EventsForKitPluginInterface::interpretationStopped
				, [this](qReal::interpretation::StopReason reason){ /// @todo
		Q_UNUSED(reason);
		mStart.setEnabled(true);
		mStop.setEnabled(true);
	}
	);

	connect(mSystemEvents
			, &qReal::SystemEvents::activeTabChanged
			, this
			, &TrikKitInterpreterPluginBase::onTabChanged);

	connect(mAdditionalPreferences, &TrikAdditionalPreferences::settingsChanged
			, mRealRobotModel.data(), &robotModel::TrikRobotModelBase::rereadSettings);

	connect(mAdditionalPreferences, &TrikAdditionalPreferences::settingsChanged
			, mTwoDRobotModel.data(), &robotModel::twoD::TrikTwoDRobotModel::rereadSettings);
}

QList<kitBase::robotModel::RobotModelInterface *> TrikKitInterpreterPluginBase::robotModels()
{
	return {mRealRobotModel.data(), mTwoDRobotModel.data()};
}

kitBase::blocksBase::BlocksFactoryInterface *TrikKitInterpreterPluginBase::blocksFactoryFor(
		const kitBase::robotModel::RobotModelInterface *model)
{
	Q_UNUSED(model);

	mOwnsBlocksFactory = false;
	return mBlocksFactory;
}

kitBase::robotModel::RobotModelInterface *TrikKitInterpreterPluginBase::defaultRobotModel()
{
	return mTwoDRobotModel.data();
}

QList<kitBase::AdditionalPreferences *> TrikKitInterpreterPluginBase::settingsWidgets()
{
	mOwnsAdditionalPreferences = false;
	return {mAdditionalPreferences};
}

QWidget *TrikKitInterpreterPluginBase::quickPreferencesFor(const kitBase::robotModel::RobotModelInterface &model)
{
	return model.name().toLower().contains("twod")
			? nullptr
			: produceIpAddressConfigurer();
}

QList<qReal::ActionInfo> TrikKitInterpreterPluginBase::customActions()
{
	return { qReal::ActionInfo(&mStart, "interpreters", "tools"), qReal::ActionInfo(&mStop, "interpreters", "tools") };
}

QList<HotKeyActionInfo> TrikKitInterpreterPluginBase::hotKeyActions()
{
	return {};
}

QString TrikKitInterpreterPluginBase::defaultSettingsFile() const
{
	return ":/trikDefaultSettings.ini";
}

QIcon TrikKitInterpreterPluginBase::iconForFastSelector(
		const kitBase::robotModel::RobotModelInterface &robotModel) const
{
	return &robotModel == mRealRobotModel.data()
			? QIcon(":/icons/switch-real-trik.svg")
			: &robotModel == mTwoDRobotModel.data()
					? QIcon(":/icons/switch-2d.svg")
					: QIcon();
}

kitBase::DevicesConfigurationProvider *TrikKitInterpreterPluginBase::devicesConfigurationProvider()
{
	return &mTwoDModel->devicesConfigurationProvider();
}

QWidget *TrikKitInterpreterPluginBase::produceIpAddressConfigurer()
{
	QLineEdit * const quickPreferences = new QLineEdit;
	quickPreferences->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
	quickPreferences->setPlaceholderText(tr("Enter robot`s IP-address here..."));
	const auto updateQuickPreferences = [quickPreferences]() {
		const QString ip = qReal::SettingsManager::value("TrikTcpServer").toString();
		if (quickPreferences->text() != ip) {
			quickPreferences->setText(ip);
		}
	};

	updateQuickPreferences();
	connect(mAdditionalPreferences, &TrikAdditionalPreferences::settingsChanged, updateQuickPreferences);
	qReal::SettingsListener::listen("TrikTcpServer", updateQuickPreferences, this);
	connect(quickPreferences, &QLineEdit::textChanged, [](const QString &text) {
		qReal::SettingsManager::setValue("TrikTcpServer", text);
	});

	connect(this, &QObject::destroyed, [quickPreferences]() { delete quickPreferences; });
	return quickPreferences;
}

void TrikKitInterpreterPluginBase::testStart()
{
	mStop.setVisible(true);
	mStart.setVisible(false);
	/// todo: bad

	auto texttab = dynamic_cast<qReal::text::QScintillaTextEdit *>(mMainWindow->currentTab());
	auto isJS = [](const QString &ext){ return ext == "js" || ext == "qts"; };

	if (texttab && isJS(texttab->currentLanguage().extension)) {
		startJSInterpretation(texttab->text());
	} else {
		qDebug("wrong tab selected");
		mStop.setVisible(false);
		mStart.setVisible(true);
		/// todo: refactor the whole button shenanigans
	}
}

void TrikKitInterpreterPluginBase::testStop()
{
	mStop.setVisible(false);
	mStart.setVisible(true);

	qtsInterpreter()->abort();
	mTwoDRobotModel->stopRobot();
	emit stopped(qReal::interpretation::StopReason::userStop);
}

void TrikKitInterpreterPluginBase::onTabChanged(const TabInfo &info)
{
	if (!mIsModelSelected) {
		return;
	}
	const bool isCodeTab = info.type() == qReal::TabInfo::TabType::code;
	const bool isQtsInterp = mQtsInterpreter->supportedRobotModelNames().contains(mCurrentlySelectedModelName);

	if (isCodeTab) {
		auto texttab = dynamic_cast<qReal::text::QScintillaTextEdit *>(mMainWindow->currentTab());
		auto isJS = [](const QString &ext){ return ext == "js" || ext == "qts"; };
		bool enable = texttab && isJS(texttab->currentLanguage().extension) && isQtsInterp;
		mStart.setEnabled(enable);
		mStop.setEnabled(enable);
		//mStart.setVisible(enable);
	} else {
		mStart.setEnabled(false); // Should matter
		mStop.setEnabled(false);
	}
	if (mQtsInterpreter->isRunning()) {
		mStop.trigger(); // Should interpretation should always stops at the change of tabs or not?
	}
	mStart.setVisible(isCodeTab && isQtsInterp);
	mStop.setVisible(false);
}
<commit_msg>Implemented clearing js errors when interpretation starts.<commit_after>/* Copyright 2013-2016 CyberTech Labs Ltd.
 *
 * 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 "trikKitInterpreterCommon/trikKitInterpreterPluginBase.h"

#include <QtWidgets/QApplication>
#include <QtWidgets/QLineEdit>

#include <twoDModel/engine/twoDModelEngineFacade.h>
#include <qrkernel/settingsManager.h>
#include <qrkernel/settingsListener.h>

#include <qrgui/textEditor/qscintillaTextEdit.h>
#include <qrgui/textEditor/languageInfo.h>

using namespace trik;
using namespace qReal;

const Id robotDiagramType = Id("RobotsMetamodel", "RobotsDiagram", "RobotsDiagramNode");
const Id subprogramDiagramType = Id("RobotsMetamodel", "RobotsDiagram", "SubprogramDiagram");

TrikKitInterpreterPluginBase::TrikKitInterpreterPluginBase() :
	mStart(tr("Start QTS"), nullptr), mStop(tr("Stop QTS"), nullptr)
{
}

TrikKitInterpreterPluginBase::~TrikKitInterpreterPluginBase()
{
	if (mOwnsAdditionalPreferences) {
		delete mAdditionalPreferences;
	}

	if (mOwnsBlocksFactory) {
		delete mBlocksFactory;
	}
}

void TrikKitInterpreterPluginBase::initKitInterpreterPluginBase
		(robotModel::TrikRobotModelBase * const realRobotModel
		, robotModel::twoD::TrikTwoDRobotModel * const twoDRobotModel
		, blocks::TrikBlocksFactoryBase * const blocksFactory
		)
{
	mRealRobotModel.reset(realRobotModel);
	mTwoDRobotModel.reset(twoDRobotModel);
	mBlocksFactory = blocksFactory;

	const auto modelEngine = new twoDModel::engine::TwoDModelEngineFacade(*mTwoDRobotModel);

	mTwoDRobotModel->setEngine(modelEngine->engine());
	mTwoDModel.reset(modelEngine);

	connectDevicesConfigurationProvider(devicesConfigurationProvider()); // ... =(

	mAdditionalPreferences = new TrikAdditionalPreferences({ mRealRobotModel->name() });

	mQtsInterpreter.reset(new TrikQtsInterpreter(mTwoDRobotModel));
}

void TrikKitInterpreterPluginBase::startJSInterpretation(const QString &code)
{
	emit codeInterpretationStarted(code);

	auto model = mTwoDRobotModel;
	model->stopRobot(); // testStop?
	const QString modelName = model->robotId();

	for (const kitBase::robotModel::PortInfo &port : model->configurablePorts()) {
		const kitBase::robotModel::DeviceInfo deviceInfo = currentConfiguration(modelName, port);
		model->configureDevice(port, deviceInfo);
	}

	model->applyConfiguration();

	mMainWindow->errorReporter()->clear();
	qtsInterpreter()->init();

	qtsInterpreter()->setCurrentDir(mProjectManager->saveFilePath());
	qtsInterpreter()->setRunning(true);
	emit started();
	qtsInterpreter()->interpretScript(code);
}

void TrikKitInterpreterPluginBase::startJSInterpretation(const QString &code, const QString &inputs)
{
	// we are in exercise mode (maybe rename it later)
	emit codeInterpretationStarted(code);

	auto model = mTwoDRobotModel;
	model->stopRobot(); // testStop?
	const QString modelName = model->robotId();

	for (const kitBase::robotModel::PortInfo &port : model->configurablePorts()) {
		const kitBase::robotModel::DeviceInfo deviceInfo = currentConfiguration(modelName, port);
		model->configureDevice(port, deviceInfo);
	}

	model->applyConfiguration();

	mMainWindow->errorReporter()->clear();
	qtsInterpreter()->init();

	qtsInterpreter()->setCurrentDir(mProjectManager->saveFilePath());
	qtsInterpreter()->setRunning(true);
	emit started();
	qtsInterpreter()->interpretScriptExercise(code, inputs);
}

TrikQtsInterpreter * TrikKitInterpreterPluginBase::qtsInterpreter() const
{
	return mQtsInterpreter.data();
}

void TrikKitInterpreterPluginBase::init(const kitBase::KitPluginConfigurator &configurer)
{
	connect(&configurer.eventsForKitPlugin()
			, &kitBase::EventsForKitPluginInterface::robotModelChanged
			, [this](const QString &modelName) { mCurrentlySelectedModelName = modelName; });

	qReal::gui::MainWindowInterpretersInterface &interpretersInterface
			= configurer.qRealConfigurator().mainWindowInterpretersInterface();

	mProjectManager = &configurer.qRealConfigurator().projectManager();

	mTwoDModel->init(configurer.eventsForKitPlugin()
			, configurer.qRealConfigurator().systemEvents()
			, configurer.qRealConfigurator().logicalModelApi()
			, configurer.qRealConfigurator().controller()
			, interpretersInterface
			, configurer.qRealConfigurator().mainWindowDockInterface()
			, configurer.qRealConfigurator().projectManager()
			, configurer.interpreterControl());

	mRealRobotModel->setErrorReporter(*interpretersInterface.errorReporter());
	mTwoDRobotModel->setErrorReporter(*interpretersInterface.errorReporter());

	mQtsInterpreter->setErrorReporter(*interpretersInterface.errorReporter());

	mMainWindow = &configurer.qRealConfigurator().mainWindowInterpretersInterface();

	mSystemEvents = &configurer.qRealConfigurator().systemEvents();

	/// @todo: refactor?
	mStart.setObjectName("runQts");
	mStart.setText(tr("Run program"));
	mStart.setIcon(QIcon(":/trik/qts/images/run.png"));

	mStop.setObjectName("stopQts");
	mStop.setText(tr("Stop robot"));
	mStop.setIcon(QIcon(":/trik/qts/images/stop.png"));

	mStop.setVisible(false);
	mStart.setVisible(false);

	connect(&configurer.eventsForKitPlugin()
			, &kitBase::EventsForKitPluginInterface::interpretCode
			, [this](const QString &code, const QString &inputs){
		if (mIsModelSelected) {
			startJSInterpretation(code, inputs);
		}
	});

	connect(&configurer.robotModelManager()
			, &kitBase::robotModel::RobotModelManagerInterface::robotModelChanged
			, [this](kitBase::robotModel::RobotModelInterface &model){
		mIsModelSelected = robotModels().contains(&model);
		/// @todo: would probably make sense to make the current opened tab info available globally somewhere
		bool isCodeTabOpen = dynamic_cast<qReal::text::QScintillaTextEdit *>(mMainWindow->currentTab()) != nullptr;
		/// @todo: bad, relies on the slot order, because of another @todo in actionManager (custom visibility logic)
		bool isQtsInterp = mQtsInterpreter->supportedRobotModelNames().contains(model.name());
		mStart.setVisible(mIsModelSelected && isCodeTabOpen && isQtsInterp);
		mStop.setVisible(false); // interpretation should always stop when switching models?
	});

	connect(&configurer.interpreterControl()
			, &kitBase::InterpreterControlInterface::stopAllInterpretation
			, this
			, [this](qReal::interpretation::StopReason) {
		if (mQtsInterpreter->isRunning()) {
			testStop();
		}
	});

	connect(&configurer.interpreterControl()
			, &kitBase::InterpreterControlInterface::startJsInterpretation
			, this
			, [this]() {
		if (!mQtsInterpreter->isRunning() && mIsModelSelected) { // temporary
			testStart();
		}
	});

	connect(&mStart, &QAction::triggered, this, &TrikKitInterpreterPluginBase::testStart);
	connect(&mStop, &QAction::triggered, this, &TrikKitInterpreterPluginBase::testStop);
	connect(mQtsInterpreter.data()
			, &TrikQtsInterpreter::completed
			, this
			, &TrikKitInterpreterPluginBase::testStop);
	// refactor?
	connect(this
			, &TrikKitInterpreterPluginBase::started
			, &configurer.eventsForKitPlugin()
			, &kitBase::EventsForKitPluginInterface::interpretationStarted
			);

	connect(this
			, &TrikKitInterpreterPluginBase::stopped
			, &configurer.eventsForKitPlugin()
			, &kitBase::EventsForKitPluginInterface::interpretationStopped
			);

//	connect(&configurer.qRealConfigurator().systemEvents(),
//			&kitBase::EventsForKitPluginInterface:)

	connect(&configurer.eventsForKitPlugin()
			, &kitBase::EventsForKitPluginInterface::interpretationStarted
			, [this](){ /// @todo
		const bool isQtsInt = mQtsInterpreter->isRunning();
		mStart.setEnabled(isQtsInt);
		mStop.setEnabled(isQtsInt);
	}
	);

	QObject::connect(
				this
				, &TrikKitInterpreterPluginBase::codeInterpretationStarted
				, &configurer.eventsForKitPlugin()
				, &kitBase::EventsForKitPluginInterface::codeInterpretationStarted
				);

	QObject::connect(
				&configurer.eventsForKitPlugin()
				, &kitBase::EventsForKitPluginInterface::interpretationStopped
				, [this](qReal::interpretation::StopReason reason){ /// @todo
		Q_UNUSED(reason);
		mStart.setEnabled(true);
		mStop.setEnabled(true);
	}
	);

	connect(mSystemEvents
			, &qReal::SystemEvents::activeTabChanged
			, this
			, &TrikKitInterpreterPluginBase::onTabChanged);

	connect(mAdditionalPreferences, &TrikAdditionalPreferences::settingsChanged
			, mRealRobotModel.data(), &robotModel::TrikRobotModelBase::rereadSettings);

	connect(mAdditionalPreferences, &TrikAdditionalPreferences::settingsChanged
			, mTwoDRobotModel.data(), &robotModel::twoD::TrikTwoDRobotModel::rereadSettings);
}

QList<kitBase::robotModel::RobotModelInterface *> TrikKitInterpreterPluginBase::robotModels()
{
	return {mRealRobotModel.data(), mTwoDRobotModel.data()};
}

kitBase::blocksBase::BlocksFactoryInterface *TrikKitInterpreterPluginBase::blocksFactoryFor(
		const kitBase::robotModel::RobotModelInterface *model)
{
	Q_UNUSED(model);

	mOwnsBlocksFactory = false;
	return mBlocksFactory;
}

kitBase::robotModel::RobotModelInterface *TrikKitInterpreterPluginBase::defaultRobotModel()
{
	return mTwoDRobotModel.data();
}

QList<kitBase::AdditionalPreferences *> TrikKitInterpreterPluginBase::settingsWidgets()
{
	mOwnsAdditionalPreferences = false;
	return {mAdditionalPreferences};
}

QWidget *TrikKitInterpreterPluginBase::quickPreferencesFor(const kitBase::robotModel::RobotModelInterface &model)
{
	return model.name().toLower().contains("twod")
			? nullptr
			: produceIpAddressConfigurer();
}

QList<qReal::ActionInfo> TrikKitInterpreterPluginBase::customActions()
{
	return { qReal::ActionInfo(&mStart, "interpreters", "tools"), qReal::ActionInfo(&mStop, "interpreters", "tools") };
}

QList<HotKeyActionInfo> TrikKitInterpreterPluginBase::hotKeyActions()
{
	return {};
}

QString TrikKitInterpreterPluginBase::defaultSettingsFile() const
{
	return ":/trikDefaultSettings.ini";
}

QIcon TrikKitInterpreterPluginBase::iconForFastSelector(
		const kitBase::robotModel::RobotModelInterface &robotModel) const
{
	return &robotModel == mRealRobotModel.data()
			? QIcon(":/icons/switch-real-trik.svg")
			: &robotModel == mTwoDRobotModel.data()
					? QIcon(":/icons/switch-2d.svg")
					: QIcon();
}

kitBase::DevicesConfigurationProvider *TrikKitInterpreterPluginBase::devicesConfigurationProvider()
{
	return &mTwoDModel->devicesConfigurationProvider();
}

QWidget *TrikKitInterpreterPluginBase::produceIpAddressConfigurer()
{
	QLineEdit * const quickPreferences = new QLineEdit;
	quickPreferences->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
	quickPreferences->setPlaceholderText(tr("Enter robot`s IP-address here..."));
	const auto updateQuickPreferences = [quickPreferences]() {
		const QString ip = qReal::SettingsManager::value("TrikTcpServer").toString();
		if (quickPreferences->text() != ip) {
			quickPreferences->setText(ip);
		}
	};

	updateQuickPreferences();
	connect(mAdditionalPreferences, &TrikAdditionalPreferences::settingsChanged, updateQuickPreferences);
	qReal::SettingsListener::listen("TrikTcpServer", updateQuickPreferences, this);
	connect(quickPreferences, &QLineEdit::textChanged, [](const QString &text) {
		qReal::SettingsManager::setValue("TrikTcpServer", text);
	});

	connect(this, &QObject::destroyed, [quickPreferences]() { delete quickPreferences; });
	return quickPreferences;
}

void TrikKitInterpreterPluginBase::testStart()
{
	mStop.setVisible(true);
	mStart.setVisible(false);
	/// todo: bad

	auto texttab = dynamic_cast<qReal::text::QScintillaTextEdit *>(mMainWindow->currentTab());
	auto isJS = [](const QString &ext){ return ext == "js" || ext == "qts"; };

	if (texttab && isJS(texttab->currentLanguage().extension)) {
		startJSInterpretation(texttab->text());
	} else {
		qDebug("wrong tab selected");
		mStop.setVisible(false);
		mStart.setVisible(true);
		/// todo: refactor the whole button shenanigans
	}
}

void TrikKitInterpreterPluginBase::testStop()
{
	mStop.setVisible(false);
	mStart.setVisible(true);

	qtsInterpreter()->abort();
	mTwoDRobotModel->stopRobot();
	emit stopped(qReal::interpretation::StopReason::userStop);
}

void TrikKitInterpreterPluginBase::onTabChanged(const TabInfo &info)
{
	if (!mIsModelSelected) {
		return;
	}
	const bool isCodeTab = info.type() == qReal::TabInfo::TabType::code;
	const bool isQtsInterp = mQtsInterpreter->supportedRobotModelNames().contains(mCurrentlySelectedModelName);

	if (isCodeTab) {
		auto texttab = dynamic_cast<qReal::text::QScintillaTextEdit *>(mMainWindow->currentTab());
		auto isJS = [](const QString &ext){ return ext == "js" || ext == "qts"; };
		bool enable = texttab && isJS(texttab->currentLanguage().extension) && isQtsInterp;
		mStart.setEnabled(enable);
		mStop.setEnabled(enable);
		//mStart.setVisible(enable);
	} else {
		mStart.setEnabled(false); // Should matter
		mStop.setEnabled(false);
	}
	if (mQtsInterpreter->isRunning()) {
		mStop.trigger(); // Should interpretation should always stops at the change of tabs or not?
	}
	mStart.setVisible(isCodeTab && isQtsInterp);
	mStop.setVisible(false);
}
<|endoftext|>