<commit_before>// Ylikuutio - A 3D game and simulation engine.
//
// Copyright (C) 2015-2020 Antti Nuortimo.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

#include "location_and_orientation_snippets.hpp"
#include "code/ylikuutio/ontology/entity.hpp"
#include "code/ylikuutio/ontology/movable_variable_activation.hpp"
#include "code/ylikuutio/ontology/movable_variable_read.hpp"
#include "code/ylikuutio/ontology/variable_struct.hpp"
#include "code/ylikuutio/data/spherical_coordinates_struct.hpp"
#include "code/ylikuutio/data/any_value.hpp"

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp> // glm
#endif

// Include standard headers
#include <cmath>         // NAN, std::isnan, std::pow
#include <iostream>      // std::cout, std::cin, std::cerr
#include <memory>        // std::make_shared, std::shared_ptr

namespace yli::snippets
{
    void set_location_and_orientation(
            yli::ontology::Entity* const entity,
            const float rho,
            const float theta,
            const float phi,
            const float x,
            const float y,
            const float z)
    {
        // Variables related to location and orientation.
        yli::data::SphericalCoordinatesStruct spherical_coordinates_struct;
        spherical_coordinates_struct.rho = rho;
        spherical_coordinates_struct.theta = theta;
        spherical_coordinates_struct.phi = phi;
        yli::ontology::VariableStruct spherical_coordinates_variable_struct(std::make_shared<yli::data::AnyValue>(&spherical_coordinates_struct));
        spherical_coordinates_variable_struct.local_name = "spherical_coordinates";
        spherical_coordinates_variable_struct.activate_callback = &yli::ontology::activate_spherical_coordinates;
        spherical_coordinates_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(spherical_coordinates_variable_struct);` ...\n";
        entity->create_variable(spherical_coordinates_variable_struct);

        yli::ontology::VariableStruct rho_variable_struct(std::make_shared<yli::data::AnyValue>(rho));
        rho_variable_struct.local_name = "rho";
        rho_variable_struct.activate_callback = &yli::ontology::activate_rho;
        rho_variable_struct.read_callback = &yli::ontology::read_rho;
        rho_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(rho_variable_struct);` ...\n";
        entity->create_variable(rho_variable_struct);

        yli::ontology::VariableStruct theta_variable_struct(std::make_shared<yli::data::AnyValue>(theta));
        theta_variable_struct.local_name = "theta";
        theta_variable_struct.activate_callback = &yli::ontology::activate_theta;
        theta_variable_struct.read_callback = &yli::ontology::read_theta;
        theta_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(theta_variable_struct);` ...\n";
        entity->create_variable(theta_variable_struct);

        yli::ontology::VariableStruct phi_variable_struct(std::make_shared<yli::data::AnyValue>(phi));
        phi_variable_struct.local_name = "phi";
        phi_variable_struct.activate_callback = &yli::ontology::activate_phi;
        phi_variable_struct.read_callback = &yli::ontology::read_phi;
        phi_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(phi_variable_struct);` ...\n";
        entity->create_variable(phi_variable_struct);

        yli::ontology::VariableStruct cartesian_coordinates_variable_struct(std::make_shared<yli::data::AnyValue>(std::make_shared<glm::vec3>(x, y, z)));
        cartesian_coordinates_variable_struct.local_name = "cartesian_coordinates";
        cartesian_coordinates_variable_struct.activate_callback = &yli::ontology::activate_cartesian_coordinates;
        cartesian_coordinates_variable_struct.read_callback = &yli::ontology::read_cartesian_coordinates;
        cartesian_coordinates_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(cartesian_coordinates_variable_struct);` ...\n";
        entity->create_variable(cartesian_coordinates_variable_struct);

        yli::ontology::VariableStruct x_variable_struct(std::make_shared<yli::data::AnyValue>(x));
        x_variable_struct.local_name = "x";
        x_variable_struct.activate_callback = &yli::ontology::activate_x;
        x_variable_struct.read_callback = &yli::ontology::read_x;
        x_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(x_variable_struct);` ...\n";
        entity->create_variable(x_variable_struct);

        yli::ontology::VariableStruct y_variable_struct(std::make_shared<yli::data::AnyValue>(y));
        y_variable_struct.local_name = "y";
        y_variable_struct.activate_callback = &yli::ontology::activate_y;
        y_variable_struct.read_callback = &yli::ontology::read_y;
        y_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(y_variable_struct);` ...\n";
        entity->create_variable(y_variable_struct);

        yli::ontology::VariableStruct z_variable_struct(std::make_shared<yli::data::AnyValue>(z));
        z_variable_struct.local_name = "z";
        z_variable_struct.activate_callback = &yli::ontology::activate_z;
        z_variable_struct.read_callback = &yli::ontology::read_z;
        z_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(z_variable_struct);` ...\n";
        entity->create_variable(z_variable_struct);

        const float yaw = 0.31f;
        yli::ontology::VariableStruct horizontal_angle_variable_struct(std::make_shared<yli::data::AnyValue>(yaw));
        horizontal_angle_variable_struct.local_name = "yaw";
        horizontal_angle_variable_struct.activate_callback = &yli::ontology::activate_horizontal_angle;
        horizontal_angle_variable_struct.read_callback = &yli::ontology::read_horizontal_angle;
        horizontal_angle_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(horizontal_angle_variable_struct);` ...\n";
        entity->create_variable(horizontal_angle_variable_struct);

        const float pitch = -0.38f;
        yli::ontology::VariableStruct vertical_angle_variable_struct(std::make_shared<yli::data::AnyValue>(pitch));
        vertical_angle_variable_struct.local_name = "pitch";
        vertical_angle_variable_struct.activate_callback = &yli::ontology::activate_vertical_angle;
        vertical_angle_variable_struct.read_callback = &yli::ontology::read_vertical_angle;
        vertical_angle_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(vertical_angle_variable_struct);` ...\n";
        entity->create_variable(vertical_angle_variable_struct);

        const float right = NAN; // the value does not matter, `right` is read with a read callback.
        yli::ontology::VariableStruct right_variable_struct(std::make_shared<yli::data::AnyValue>(right));
        right_variable_struct.local_name = "right";
        right_variable_struct.read_callback = &yli::ontology::read_right;
        right_variable_struct.should_ylikuutio_call_activate_callback_now = false;
        std::cout << "Executing `entity->create_variable(right_variable_struct);` ...\n";
        entity->create_variable(right_variable_struct);

        const float up = NAN; // the value does not matter, `up` is read with a read callback.
        yli::ontology::VariableStruct up_variable_struct(std::make_shared<yli::data::AnyValue>(up));
        up_variable_struct.local_name = "up";
        up_variable_struct.read_callback = &yli::ontology::read_up;
        up_variable_struct.should_ylikuutio_call_activate_callback_now = false;
        std::cout << "Executing `entity->create_variable(up_variable_struct);` ...\n";
        entity->create_variable(up_variable_struct);

        std::cout << "Setting up location and orientation ... ready.\n";
    }
}
<commit_msg>Set initial yaw to -0.41 and initial pitch to -0.19.<commit_after>// Ylikuutio - A 3D game and simulation engine.
//
// Copyright (C) 2015-2020 Antti Nuortimo.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

#include "location_and_orientation_snippets.hpp"
#include "code/ylikuutio/ontology/entity.hpp"
#include "code/ylikuutio/ontology/movable_variable_activation.hpp"
#include "code/ylikuutio/ontology/movable_variable_read.hpp"
#include "code/ylikuutio/ontology/variable_struct.hpp"
#include "code/ylikuutio/data/spherical_coordinates_struct.hpp"
#include "code/ylikuutio/data/any_value.hpp"

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp> // glm
#endif

// Include standard headers
#include <cmath>         // NAN, std::isnan, std::pow
#include <iostream>      // std::cout, std::cin, std::cerr
#include <memory>        // std::make_shared, std::shared_ptr

namespace yli::snippets
{
    void set_location_and_orientation(
            yli::ontology::Entity* const entity,
            const float rho,
            const float theta,
            const float phi,
            const float x,
            const float y,
            const float z)
    {
        // Variables related to location and orientation.
        yli::data::SphericalCoordinatesStruct spherical_coordinates_struct;
        spherical_coordinates_struct.rho = rho;
        spherical_coordinates_struct.theta = theta;
        spherical_coordinates_struct.phi = phi;
        yli::ontology::VariableStruct spherical_coordinates_variable_struct(std::make_shared<yli::data::AnyValue>(&spherical_coordinates_struct));
        spherical_coordinates_variable_struct.local_name = "spherical_coordinates";
        spherical_coordinates_variable_struct.activate_callback = &yli::ontology::activate_spherical_coordinates;
        spherical_coordinates_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(spherical_coordinates_variable_struct);` ...\n";
        entity->create_variable(spherical_coordinates_variable_struct);

        yli::ontology::VariableStruct rho_variable_struct(std::make_shared<yli::data::AnyValue>(rho));
        rho_variable_struct.local_name = "rho";
        rho_variable_struct.activate_callback = &yli::ontology::activate_rho;
        rho_variable_struct.read_callback = &yli::ontology::read_rho;
        rho_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(rho_variable_struct);` ...\n";
        entity->create_variable(rho_variable_struct);

        yli::ontology::VariableStruct theta_variable_struct(std::make_shared<yli::data::AnyValue>(theta));
        theta_variable_struct.local_name = "theta";
        theta_variable_struct.activate_callback = &yli::ontology::activate_theta;
        theta_variable_struct.read_callback = &yli::ontology::read_theta;
        theta_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(theta_variable_struct);` ...\n";
        entity->create_variable(theta_variable_struct);

        yli::ontology::VariableStruct phi_variable_struct(std::make_shared<yli::data::AnyValue>(phi));
        phi_variable_struct.local_name = "phi";
        phi_variable_struct.activate_callback = &yli::ontology::activate_phi;
        phi_variable_struct.read_callback = &yli::ontology::read_phi;
        phi_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(phi_variable_struct);` ...\n";
        entity->create_variable(phi_variable_struct);

        yli::ontology::VariableStruct cartesian_coordinates_variable_struct(std::make_shared<yli::data::AnyValue>(std::make_shared<glm::vec3>(x, y, z)));
        cartesian_coordinates_variable_struct.local_name = "cartesian_coordinates";
        cartesian_coordinates_variable_struct.activate_callback = &yli::ontology::activate_cartesian_coordinates;
        cartesian_coordinates_variable_struct.read_callback = &yli::ontology::read_cartesian_coordinates;
        cartesian_coordinates_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(cartesian_coordinates_variable_struct);` ...\n";
        entity->create_variable(cartesian_coordinates_variable_struct);

        yli::ontology::VariableStruct x_variable_struct(std::make_shared<yli::data::AnyValue>(x));
        x_variable_struct.local_name = "x";
        x_variable_struct.activate_callback = &yli::ontology::activate_x;
        x_variable_struct.read_callback = &yli::ontology::read_x;
        x_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(x_variable_struct);` ...\n";
        entity->create_variable(x_variable_struct);

        yli::ontology::VariableStruct y_variable_struct(std::make_shared<yli::data::AnyValue>(y));
        y_variable_struct.local_name = "y";
        y_variable_struct.activate_callback = &yli::ontology::activate_y;
        y_variable_struct.read_callback = &yli::ontology::read_y;
        y_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(y_variable_struct);` ...\n";
        entity->create_variable(y_variable_struct);

        yli::ontology::VariableStruct z_variable_struct(std::make_shared<yli::data::AnyValue>(z));
        z_variable_struct.local_name = "z";
        z_variable_struct.activate_callback = &yli::ontology::activate_z;
        z_variable_struct.read_callback = &yli::ontology::read_z;
        z_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(z_variable_struct);` ...\n";
        entity->create_variable(z_variable_struct);

        const float yaw = -0.41f;
        yli::ontology::VariableStruct horizontal_angle_variable_struct(std::make_shared<yli::data::AnyValue>(yaw));
        horizontal_angle_variable_struct.local_name = "yaw";
        horizontal_angle_variable_struct.activate_callback = &yli::ontology::activate_horizontal_angle;
        horizontal_angle_variable_struct.read_callback = &yli::ontology::read_horizontal_angle;
        horizontal_angle_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(horizontal_angle_variable_struct);` ...\n";
        entity->create_variable(horizontal_angle_variable_struct);

        const float pitch = -0.19f;
        yli::ontology::VariableStruct vertical_angle_variable_struct(std::make_shared<yli::data::AnyValue>(pitch));
        vertical_angle_variable_struct.local_name = "pitch";
        vertical_angle_variable_struct.activate_callback = &yli::ontology::activate_vertical_angle;
        vertical_angle_variable_struct.read_callback = &yli::ontology::read_vertical_angle;
        vertical_angle_variable_struct.should_ylikuutio_call_activate_callback_now = true;
        std::cout << "Executing `entity->create_variable(vertical_angle_variable_struct);` ...\n";
        entity->create_variable(vertical_angle_variable_struct);

        const float right = NAN; // the value does not matter, `right` is read with a read callback.
        yli::ontology::VariableStruct right_variable_struct(std::make_shared<yli::data::AnyValue>(right));
        right_variable_struct.local_name = "right";
        right_variable_struct.read_callback = &yli::ontology::read_right;
        right_variable_struct.should_ylikuutio_call_activate_callback_now = false;
        std::cout << "Executing `entity->create_variable(right_variable_struct);` ...\n";
        entity->create_variable(right_variable_struct);

        const float up = NAN; // the value does not matter, `up` is read with a read callback.
        yli::ontology::VariableStruct up_variable_struct(std::make_shared<yli::data::AnyValue>(up));
        up_variable_struct.local_name = "up";
        up_variable_struct.read_callback = &yli::ontology::read_up;
        up_variable_struct.should_ylikuutio_call_activate_callback_now = false;
        std::cout << "Executing `entity->create_variable(up_variable_struct);` ...\n";
        entity->create_variable(up_variable_struct);

        std::cout << "Setting up location and orientation ... ready.\n";
    }
}
<|endoftext|>


<commit_before>#pragma once
#include "SolverProcess.hpp"
#include <metaSMT/support/parser/SMT2Parser.hpp>
#include <metaSMT/support/parser/UTreeEvaluator.hpp>
#include <metaSMT/support/parser/UTreeToString.hpp>
#include <metaSMT/support/SimpleSymbolTable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/optional.hpp>
#include <sstream>
#include <string>

namespace eval = metaSMT::evaluator;
namespace spirit = boost::spirit;

template < typename Context >
class Solver : public SolverBase {
public:
  typedef typename eval::UTreeEvaluator<Context> Evaluator;
  typedef metaSMT::type::TypedSymbol<Context> TypedSymbol;
  typedef boost::shared_ptr<TypedSymbol> TypedSymbolPtr;
  typedef std::map<std::string, TypedSymbolPtr> VarMap;

  typedef typename eval::SMT_Command_Map<Context>::Command Command;

public:
  Solver()
    : evaluator(solver, var_map)
    , parser(evaluator)
  {}

  void start() {
    std::cerr << "START" << '\n';
    for (;;) {
      std::string ret = "OK";
      std::string s = sp->child_read_command();
      // std::cerr << "[SOLVER] " << s << '\n';

      try {
        spirit::utree::list_type const list = parse(s);

        for ( spirit::utree::const_iterator it = list.begin(), ie = list.end();
                it != ie; ++it ) {
          spirit::utree const ast = *it;
          assert( ast.size() > 0 );

          std::string const command = eval::utreeToString(*ast.begin());
          // std::cerr << "COMMAND: " << command << '\n';

          boost::optional<Command> cmd =
          eval::SMT_Command_Map<Context>::get_command(command, solver, var_map, table);
          assert ( !cmd );
          boost::optional<boost::any> result =
          eval::SMT_Command_Map<Context>::execute_command(*cmd, ast);
          if ( result ) {
            ret = makeResultString(command, *result);
          }
        }
      } catch (std::invalid_argument e) {
        std::cerr << "[SOLVER] " << e.what() << std::endl;
        ret = e.what();
      }
      // std::cerr << "[SOLVER] CHILD WRITE COMMAND: " << ret << '\n';
      sp->child_write_command(ret);
    }
  }

private:
  spirit::utree::list_type parse(std::string const &s) {
    std::stringstream ss(s);
    spirit::utree::list_type list;
    bool const success = parser.parse(ss, list);
    // std::cerr << "[SOLVER] SUCCESS = " << success << '\n';
    if ( !success )
      throw std::invalid_argument( "Could not parse input format" );
    return list;
  }

  std::string makeCheckSatResult(boost::any const &result) {
    bool const sat = boost::any_cast<bool>(result);
    std::cerr << "[SOLVER] check-sat = " << sat << '\n';
    return (sat ? "sat" : "unsat");
  }

  std::string makeGetValueResult(boost::any const &result) {
    typedef boost::tuple<std::string,TypedSymbolPtr> var_type;
    var_type var = boost::any_cast<var_type>(result);
    std::string const name = boost::get<0>(var);
    TypedSymbolPtr const symbol = boost::get<1>(var);
    std::string ret = "<Unknown>";
    if ( symbol->isBool() ) {
      bool const b = read_value(solver, symbol->eval(solver));
      ret = "((" + name + " " + (b ? "true" : "false") + "))";
    }
    else if (symbol->isBitVector() ) {
      std::string const value = read_value(solver, symbol->eval(solver));
      ret = "((" + name + " #b" + value + "))";
    }
    else {
      assert( false && "Variable type is not supported" );
    }
    std::cerr << "[SOLVER] get-value = " << ret << '\n';
    return ret;
  }

  std::string makeResultString(std::string const &name,
                               boost::any const &result) {
    if ( name == "check-sat" ) {
      return makeCheckSatResult(result);
    }
    else if ( name == "get-value" ) {
      return makeGetValueResult(result);
    }
    assert( false && "Command has no result" );
    return "<Unknown>";
  }

private:
  Context solver;
  VarMap var_map;
  Evaluator evaluator;
  metaSMT::smt2::SMT2Parser<Evaluator> parser;
  metaSMT::support::simple_symbol_table table;
}; // Solver
<commit_msg>metaSMT-server throws exceptions in case of unsupported commands<commit_after>#pragma once
#include "SolverProcess.hpp"
#include <metaSMT/support/parser/SMT2Parser.hpp>
#include <metaSMT/support/parser/UTreeEvaluator.hpp>
#include <metaSMT/support/parser/UTreeToString.hpp>
#include <metaSMT/support/SimpleSymbolTable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/optional.hpp>
#include <sstream>
#include <string>

namespace eval = metaSMT::evaluator;
namespace spirit = boost::spirit;

template < typename Context >
class Solver : public SolverBase {
public:
  typedef typename eval::UTreeEvaluator<Context> Evaluator;
  typedef metaSMT::type::TypedSymbol<Context> TypedSymbol;
  typedef boost::shared_ptr<TypedSymbol> TypedSymbolPtr;
  typedef std::map<std::string, TypedSymbolPtr> VarMap;

  typedef typename eval::SMT_Command_Map<Context>::Command Command;

public:
  Solver()
    : evaluator(solver, var_map)
    , parser(evaluator)
  {}

  void start() {
    std::cerr << "START" << '\n';
    for (;;) {
      std::string ret = "OK";
      std::string s = sp->child_read_command();
      // std::cerr << "[SOLVER] " << s << '\n';

      try {
        spirit::utree::list_type const list = parse(s);

        for ( spirit::utree::const_iterator it = list.begin(), ie = list.end();
                it != ie; ++it ) {
          spirit::utree const ast = *it;
          assert( ast.size() > 0 );

          std::string const command = eval::utreeToString(*ast.begin());
          // std::cerr << "COMMAND: " << command << '\n';

          boost::optional<Command> cmd =
          eval::SMT_Command_Map<Context>::get_command(command, solver, var_map, table);
          if ( !cmd )
            throw std::invalid_argument( "Unsupported command" );
          boost::optional<boost::any> result =
          eval::SMT_Command_Map<Context>::execute_command(*cmd, ast);
          if ( result ) {
            ret = makeResultString(command, *result);
          }
        }
      } catch (std::invalid_argument e) {
        std::cerr << "[SOLVER] " << e.what() << std::endl;
        ret = e.what();
      }
      // std::cerr << "[SOLVER] CHILD WRITE COMMAND: " << ret << '\n';
      sp->child_write_command(ret);
    }
  }

private:
  spirit::utree::list_type parse(std::string const &s) {
    std::stringstream ss(s);
    spirit::utree::list_type list;
    bool const success = parser.parse(ss, list);
    // std::cerr << "[SOLVER] SUCCESS = " << success << '\n';
    if ( !success )
      throw std::invalid_argument( "Could not parse input format" );
    return list;
  }

  std::string makeCheckSatResult(boost::any const &result) {
    bool const sat = boost::any_cast<bool>(result);
    std::cerr << "[SOLVER] check-sat = " << sat << '\n';
    return (sat ? "sat" : "unsat");
  }

  std::string makeGetValueResult(boost::any const &result) {
    typedef boost::tuple<std::string,TypedSymbolPtr> var_type;
    var_type var = boost::any_cast<var_type>(result);
    std::string const name = boost::get<0>(var);
    TypedSymbolPtr const symbol = boost::get<1>(var);
    std::string ret = "<Unknown>";
    if ( symbol->isBool() ) {
      bool const b = read_value(solver, symbol->eval(solver));
      ret = "((" + name + " " + (b ? "true" : "false") + "))";
    }
    else if (symbol->isBitVector() ) {
      std::string const value = read_value(solver, symbol->eval(solver));
      ret = "((" + name + " #b" + value + "))";
    }
    else {
      assert( false && "Variable type is not supported" );
    }
    std::cerr << "[SOLVER] get-value = " << ret << '\n';
    return ret;
  }

  std::string makeResultString(std::string const &name,
                               boost::any const &result) {
    if ( name == "check-sat" ) {
      return makeCheckSatResult(result);
    }
    else if ( name == "get-value" ) {
      return makeGetValueResult(result);
    }
    assert( false && "Command has no result" );
    return "<Unknown>";
  }

private:
  Context solver;
  VarMap var_map;
  Evaluator evaluator;
  metaSMT::smt2::SMT2Parser<Evaluator> parser;
  metaSMT::support::simple_symbol_table table;
}; // Solver
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2022 Samsung Electronics Co., 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.
 *
 */

// CLASS HEADER
#include <dali-scene3d/internal/controls/scene-view/scene-view-impl.h>

// EXTERNAL INCLUDES
#include <dali-toolkit/dali-toolkit.h>
#include <dali-toolkit/devel-api/controls/control-devel.h>
#include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
#include <dali-toolkit/internal/controls/control/control-data-impl.h>
#include <dali-toolkit/public-api/image-loader/image-url.h>
#include <dali-toolkit/public-api/image-loader/image.h>
#include <dali/devel-api/actors/camera-actor-devel.h>
#include <dali/devel-api/adaptor-framework/window-devel.h>
#include <dali/devel-api/common/stage.h>
#include <dali/integration-api/debug.h>
#include <dali/public-api/object/type-registry-helper.h>
#include <dali/public-api/object/type-registry.h>

// INTERNAL INCLUDES
#include <dali-scene3d/internal/controls/model/model-impl.h>
#include <dali-scene3d/public-api/loader/cube-map-loader.h>

#include <dali/integration-api/debug.h>

using namespace Dali;

namespace Dali
{
namespace Scene3D
{
namespace Internal
{
namespace
{
BaseHandle Create()
{
  return Scene3D::SceneView::New();
}

// Setup properties, signals and actions using the type-registry.
DALI_TYPE_REGISTRATION_BEGIN(Scene3D::SceneView, Toolkit::Control, Create);
DALI_TYPE_REGISTRATION_END()

Property::Index   RENDERING_BUFFER    = Dali::Toolkit::Control::CONTROL_PROPERTY_END_INDEX + 1;
constexpr int32_t DEFAULT_ORIENTATION = 0;

} // anonymous namespace

SceneView::SceneView()
: Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
  mWindowOrientation(DEFAULT_ORIENTATION)
{
}

SceneView::~SceneView() = default;

Dali::Scene3D::SceneView SceneView::New()
{
  SceneView* impl = new SceneView();

  Dali::Scene3D::SceneView handle = Dali::Scene3D::SceneView(*impl);

  // Second-phase init of the implementation
  // This can only be done after the CustomActor connection has been made...
  impl->Initialize();

  return handle;
}

void SceneView::AddCamera(CameraActor camera)
{
  if(camera)
  {
    if(mCameras.empty())
    {
      UpdateCamera(camera);
    }
    mCameras.push_back(camera);
  }
}

void SceneView::RemoveCamera(CameraActor camera)
{
  if(camera == mDefaultCamera)
  {
    DALI_LOG_ERROR("Default Camera cannot removed.\n");
    return;
  }

  if(camera)
  {
    for(uint32_t i = 0; i < mCameras.size(); ++i)
    {
      if(mCameras[i] == camera)
      {
        mCameras.erase(mCameras.begin() + i);
        break;
      }
    }

    if(mSelectedCamera == camera)
    {
      CameraActor newCurrentCamera = *mCameras.begin();
      UpdateCamera(newCurrentCamera);
    }
  }
}

uint32_t SceneView::GetCameraCount() const
{
  return mCameras.size();
}

CameraActor SceneView::GetSelectedCamera() const
{
  return mSelectedCamera;
}

CameraActor SceneView::GetCamera(uint32_t index) const
{
  if(index < mCameras.size())
  {
    return mCameras[index];
  }
  DALI_LOG_ERROR("Input index is out of bounds\n");
  return CameraActor();
}

CameraActor SceneView::GetCamera(const std::string& name) const
{
  CameraActor returnCamera;
  for(auto&& camera : mCameras)
  {
    if(camera.GetProperty<std::string>(Actor::Property::NAME) == name)
    {
      returnCamera = camera;
      break;
    }
  }
  return returnCamera;
}

void SceneView::SelectCamera(uint32_t index)
{
  UpdateCamera(GetCamera(index));
}

void SceneView::SelectCamera(const std::string& name)
{
  UpdateCamera(GetCamera(name));
}

void SceneView::RegisterModel(Scene3D::Model model)
{
  if(model)
  {
    model.SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor);
    mModels.push_back(model);
  }
}

void SceneView::UnregisterModel(Scene3D::Model model)
{
  if(model)
  {
    for(uint32_t i = 0; i < mModels.size(); ++i)
    {
      if(mModels[i] == model)
      {
        mModels.erase(mModels.begin() + i);
        break;
      }
    }
  }
}

void SceneView::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor)
{
  mIBLResourceReady      = false;
  Texture diffuseTexture = Dali::Scene3D::Loader::LoadCubeMap(diffuseUrl);
  if(diffuseTexture)
  {
    Texture specularTexture = Dali::Scene3D::Loader::LoadCubeMap(specularUrl);
    if(specularTexture)
    {
      mDiffuseTexture  = diffuseTexture;
      mSpecularTexture = specularTexture;
      mIblScaleFactor  = scaleFactor;

      for(auto&& model : mModels)
      {
        if(model)
        {
          model.SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor);
        }
      }
    }
  }
  mIBLResourceReady = true;
  Control::SetResourceReady(false);
}

void SceneView::SetImageBasedLightScaleFactor(float scaleFactor)
{
  mIblScaleFactor = scaleFactor;
  for(auto&& model : mModels)
  {
    if(model)
    {
      model.SetImageBasedLightScaleFactor(scaleFactor);
    }
  }
}

float SceneView::GetImageBasedLightScaleFactor() const
{
  return mIblScaleFactor;
}

void SceneView::UseFramebuffer(bool useFramebuffer)
{
  if(mUseFrameBuffer != useFramebuffer)
  {
    mUseFrameBuffer = useFramebuffer;
    UpdateRenderTask();
  }
}

bool SceneView::IsUsingFramebuffer() const
{
  return mUseFrameBuffer;
}

///////////////////////////////////////////////////////////
//
// Private methods
//

void SceneView::OnSceneConnection(int depth)
{
  UpdateRenderTask();

  Window window = DevelWindow::Get(Self());
  if(window)
  {
    window.ResizeSignal().Connect(this, &SceneView::OnWindowResized);
  }

  Control::OnSceneConnection(depth);
}

void SceneView::OnSceneDisconnection()
{
  mModels.clear();

  Window window = DevelWindow::Get(Self());
  if(window)
  {
    window.ResizeSignal().Disconnect(this, &SceneView::OnWindowResized);
  }

  Control::OnSceneDisconnection();
}

void SceneView::OnInitialize()
{
  Actor self = Self();
  mRootLayer = Layer::New();
  mRootLayer.SetProperty(Layer::Property::BEHAVIOR, Layer::LAYER_3D);
  mRootLayer.SetProperty(Layer::Property::DEPTH_TEST, true);
  // The models in the SceneView should be have independent coordinate with DALi default coordinate.
  mRootLayer.SetProperty(Dali::Actor::Property::INHERIT_POSITION, false);
  mRootLayer.SetProperty(Dali::Actor::Property::INHERIT_ORIENTATION, false);
  mRootLayer.SetProperty(Dali::Actor::Property::INHERIT_SCALE, false);
  self.Add(mRootLayer);

  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
  mRenderTask             = taskList.CreateTask();
  mRenderTask.SetSourceActor(mRootLayer);
  mRenderTask.SetExclusive(true);
  mRenderTask.SetInputEnabled(true);
  mRenderTask.SetCullMode(false);
  mRenderTask.SetScreenToFrameBufferMappingActor(Self());

  mDefaultCamera = Dali::CameraActor::New();
  mDefaultCamera.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
  mDefaultCamera.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
  mDefaultCamera.SetNearClippingPlane(1.0f);
  AddCamera(mDefaultCamera);
  UpdateCamera(mDefaultCamera);
}

void SceneView::OnChildAdd(Actor& child)
{
  if(child != mRootLayer)
  {
    mRootLayer.Add(child);
  }
  Control::OnChildAdd(child);
}

void SceneView::OnChildRemove(Actor& child)
{
  mRootLayer.Remove(child);
  Control::OnChildRemove(child);
}

float SceneView::GetHeightForWidth(float width)
{
  Extents padding;
  padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
  return Control::GetHeightForWidth(width) + padding.top + padding.bottom;
}

float SceneView::GetWidthForHeight(float height)
{
  Extents padding;
  padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
  return Control::GetWidthForHeight(height) + padding.start + padding.end;
}

void SceneView::OnRelayout(const Vector2& size, RelayoutContainer& container)
{
  Control::OnRelayout(size, container);
  // Change canvas size of camera actor.
  UpdateRenderTask();
}

bool SceneView::IsResourceReady() const
{
  return mIBLResourceReady;
}

void SceneView::UpdateCamera(CameraActor camera)
{
  if(camera)
  {
    if(mSelectedCamera && mSelectedCamera.GetParent())
    {
      mSelectedCamera.Unparent();
    }
    mRootLayer.Add(camera);
  }

  mSelectedCamera = camera;
  UpdateRenderTask();
}

void SceneView::UpdateRenderTask()
{
  if(mRenderTask)
  {
    if(mSelectedCamera != mRenderTask.GetCameraActor())
    {
      mRenderTask.SetCameraActor(mSelectedCamera);
    }

    Vector3     size        = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
    const float aspectRatio = size.width / size.height;
    mSelectedCamera.SetAspectRatio(aspectRatio);
    const float halfHeight                                              = mSelectedCamera[Dali::CameraActor::Property::TOP_PLANE_DISTANCE];
    const float halfWidth                                               = aspectRatio * halfHeight;
    mSelectedCamera[Dali::CameraActor::Property::LEFT_PLANE_DISTANCE]   = -halfWidth;
    mSelectedCamera[Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE]  = halfWidth;
    mSelectedCamera[Dali::CameraActor::Property::TOP_PLANE_DISTANCE]    = halfHeight;  // Top is +ve to keep consistency with orthographic values
    mSelectedCamera[Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE] = -halfHeight; // Bottom is -ve to keep consistency with orthographic values
    if(mUseFrameBuffer)
    {
      Dali::FrameBuffer currentFrameBuffer = mRenderTask.GetFrameBuffer();
      if(!currentFrameBuffer ||
         currentFrameBuffer.GetColorTexture().GetWidth() != size.width ||
         currentFrameBuffer.GetColorTexture().GetHeight() != size.height)
      {
        mRenderTask.ResetViewportGuideActor();
        mRenderTask.SetViewport(Dali::Viewport(Vector4::ZERO));

        // create offscreen buffer of new size to render our child actors to
        mTexture      = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, unsigned(size.width), unsigned(size.height));
        mRenderTarget = FrameBuffer::New(size.width, size.height, FrameBuffer::Attachment::DEPTH_STENCIL);
        mRenderTarget.AttachColorTexture(mTexture);
        Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::Image::GenerateUrl(mRenderTarget, 0u);

        Property::Map imagePropertyMap;
        imagePropertyMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE);
        imagePropertyMap.Insert(Toolkit::ImageVisual::Property::URL, imageUrl.GetUrl());
        // To flip rendered scene without CameraActor::SetInvertYAxis() to avoid backface culling.
        imagePropertyMap.Insert(Toolkit::ImageVisual::Property::PIXEL_AREA, Vector4(0.0f, 1.0f, 1.0f, -1.0f));
        mVisual = Toolkit::VisualFactory::Get().CreateVisual(imagePropertyMap);

        Toolkit::DevelControl::RegisterVisual(*this, RENDERING_BUFFER, mVisual);

        mRenderTask.SetFrameBuffer(mRenderTarget);
        mRenderTask.SetClearEnabled(true);
        mRenderTask.SetClearColor(Color::TRANSPARENT);
      }
    }
    else
    {
      mRenderTask.SetViewportGuideActor(Self());
      if(mRenderTask.GetFrameBuffer())
      {
        FrameBuffer framebuffer;
        mRenderTask.SetFrameBuffer(framebuffer);
        mRenderTask.SetClearEnabled(false);

        Toolkit::DevelControl::UnregisterVisual(*this, RENDERING_BUFFER);

        mVisual.Reset();
        mRenderTarget.Reset();
        mTexture.Reset();
      }
    }

    RotateCamera();
  }
}

void SceneView::OnWindowResized(Window window, Window::WindowSize size)
{
  mWindowOrientation = DevelWindow::GetPhysicalOrientation(window);
  RotateCamera();
}

void SceneView::RotateCamera()
{
  if(mUseFrameBuffer)
  {
    DevelCameraActor::RotateProjection(mSelectedCamera, DEFAULT_ORIENTATION);
  }
  else
  {
    DevelCameraActor::RotateProjection(mSelectedCamera, mWindowOrientation);
  }
}

} // namespace Internal
} // namespace Scene3D
} // namespace Dali
<commit_msg>Apply ProjectionDirection property when SceneView size changed<commit_after>/*
 * Copyright (c) 2022 Samsung Electronics Co., 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.
 *
 */

// CLASS HEADER
#include <dali-scene3d/internal/controls/scene-view/scene-view-impl.h>

// EXTERNAL INCLUDES
#include <dali-toolkit/dali-toolkit.h>
#include <dali-toolkit/devel-api/controls/control-devel.h>
#include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
#include <dali-toolkit/internal/controls/control/control-data-impl.h>
#include <dali-toolkit/public-api/image-loader/image-url.h>
#include <dali-toolkit/public-api/image-loader/image.h>
#include <dali/devel-api/actors/camera-actor-devel.h>
#include <dali/devel-api/adaptor-framework/window-devel.h>
#include <dali/devel-api/common/stage.h>
#include <dali/integration-api/debug.h>
#include <dali/public-api/object/type-registry-helper.h>
#include <dali/public-api/object/type-registry.h>

// INTERNAL INCLUDES
#include <dali-scene3d/internal/controls/model/model-impl.h>
#include <dali-scene3d/public-api/loader/cube-map-loader.h>

#include <dali/integration-api/debug.h>

using namespace Dali;

namespace Dali
{
namespace Scene3D
{
namespace Internal
{
namespace
{
BaseHandle Create()
{
  return Scene3D::SceneView::New();
}

// Setup properties, signals and actions using the type-registry.
DALI_TYPE_REGISTRATION_BEGIN(Scene3D::SceneView, Toolkit::Control, Create);
DALI_TYPE_REGISTRATION_END()

Property::Index   RENDERING_BUFFER    = Dali::Toolkit::Control::CONTROL_PROPERTY_END_INDEX + 1;
constexpr int32_t DEFAULT_ORIENTATION = 0;

} // anonymous namespace

SceneView::SceneView()
: Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
  mWindowOrientation(DEFAULT_ORIENTATION)
{
}

SceneView::~SceneView() = default;

Dali::Scene3D::SceneView SceneView::New()
{
  SceneView* impl = new SceneView();

  Dali::Scene3D::SceneView handle = Dali::Scene3D::SceneView(*impl);

  // Second-phase init of the implementation
  // This can only be done after the CustomActor connection has been made...
  impl->Initialize();

  return handle;
}

void SceneView::AddCamera(CameraActor camera)
{
  if(camera)
  {
    if(mCameras.empty())
    {
      UpdateCamera(camera);
    }
    mCameras.push_back(camera);
  }
}

void SceneView::RemoveCamera(CameraActor camera)
{
  if(camera == mDefaultCamera)
  {
    DALI_LOG_ERROR("Default Camera cannot removed.\n");
    return;
  }

  if(camera)
  {
    for(uint32_t i = 0; i < mCameras.size(); ++i)
    {
      if(mCameras[i] == camera)
      {
        mCameras.erase(mCameras.begin() + i);
        break;
      }
    }

    if(mSelectedCamera == camera)
    {
      CameraActor newCurrentCamera = *mCameras.begin();
      UpdateCamera(newCurrentCamera);
    }
  }
}

uint32_t SceneView::GetCameraCount() const
{
  return mCameras.size();
}

CameraActor SceneView::GetSelectedCamera() const
{
  return mSelectedCamera;
}

CameraActor SceneView::GetCamera(uint32_t index) const
{
  if(index < mCameras.size())
  {
    return mCameras[index];
  }
  DALI_LOG_ERROR("Input index is out of bounds\n");
  return CameraActor();
}

CameraActor SceneView::GetCamera(const std::string& name) const
{
  CameraActor returnCamera;
  for(auto&& camera : mCameras)
  {
    if(camera.GetProperty<std::string>(Actor::Property::NAME) == name)
    {
      returnCamera = camera;
      break;
    }
  }
  return returnCamera;
}

void SceneView::SelectCamera(uint32_t index)
{
  UpdateCamera(GetCamera(index));
}

void SceneView::SelectCamera(const std::string& name)
{
  UpdateCamera(GetCamera(name));
}

void SceneView::RegisterModel(Scene3D::Model model)
{
  if(model)
  {
    model.SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor);
    mModels.push_back(model);
  }
}

void SceneView::UnregisterModel(Scene3D::Model model)
{
  if(model)
  {
    for(uint32_t i = 0; i < mModels.size(); ++i)
    {
      if(mModels[i] == model)
      {
        mModels.erase(mModels.begin() + i);
        break;
      }
    }
  }
}

void SceneView::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor)
{
  mIBLResourceReady      = false;
  Texture diffuseTexture = Dali::Scene3D::Loader::LoadCubeMap(diffuseUrl);
  if(diffuseTexture)
  {
    Texture specularTexture = Dali::Scene3D::Loader::LoadCubeMap(specularUrl);
    if(specularTexture)
    {
      mDiffuseTexture  = diffuseTexture;
      mSpecularTexture = specularTexture;
      mIblScaleFactor  = scaleFactor;

      for(auto&& model : mModels)
      {
        if(model)
        {
          model.SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor);
        }
      }
    }
  }
  mIBLResourceReady = true;
  Control::SetResourceReady(false);
}

void SceneView::SetImageBasedLightScaleFactor(float scaleFactor)
{
  mIblScaleFactor = scaleFactor;
  for(auto&& model : mModels)
  {
    if(model)
    {
      model.SetImageBasedLightScaleFactor(scaleFactor);
    }
  }
}

float SceneView::GetImageBasedLightScaleFactor() const
{
  return mIblScaleFactor;
}

void SceneView::UseFramebuffer(bool useFramebuffer)
{
  if(mUseFrameBuffer != useFramebuffer)
  {
    mUseFrameBuffer = useFramebuffer;
    UpdateRenderTask();
  }
}

bool SceneView::IsUsingFramebuffer() const
{
  return mUseFrameBuffer;
}

///////////////////////////////////////////////////////////
//
// Private methods
//

void SceneView::OnSceneConnection(int depth)
{
  UpdateRenderTask();

  Window window = DevelWindow::Get(Self());
  if(window)
  {
    window.ResizeSignal().Connect(this, &SceneView::OnWindowResized);
  }

  Control::OnSceneConnection(depth);
}

void SceneView::OnSceneDisconnection()
{
  mModels.clear();

  Window window = DevelWindow::Get(Self());
  if(window)
  {
    window.ResizeSignal().Disconnect(this, &SceneView::OnWindowResized);
  }

  Control::OnSceneDisconnection();
}

void SceneView::OnInitialize()
{
  Actor self = Self();
  mRootLayer = Layer::New();
  mRootLayer.SetProperty(Layer::Property::BEHAVIOR, Layer::LAYER_3D);
  mRootLayer.SetProperty(Layer::Property::DEPTH_TEST, true);
  // The models in the SceneView should be have independent coordinate with DALi default coordinate.
  mRootLayer.SetProperty(Dali::Actor::Property::INHERIT_POSITION, false);
  mRootLayer.SetProperty(Dali::Actor::Property::INHERIT_ORIENTATION, false);
  mRootLayer.SetProperty(Dali::Actor::Property::INHERIT_SCALE, false);
  self.Add(mRootLayer);

  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
  mRenderTask             = taskList.CreateTask();
  mRenderTask.SetSourceActor(mRootLayer);
  mRenderTask.SetExclusive(true);
  mRenderTask.SetInputEnabled(true);
  mRenderTask.SetCullMode(false);
  mRenderTask.SetScreenToFrameBufferMappingActor(Self());

  mDefaultCamera = Dali::CameraActor::New();
  mDefaultCamera.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
  mDefaultCamera.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
  mDefaultCamera.SetNearClippingPlane(1.0f);
  AddCamera(mDefaultCamera);
  UpdateCamera(mDefaultCamera);
}

void SceneView::OnChildAdd(Actor& child)
{
  if(child != mRootLayer)
  {
    mRootLayer.Add(child);
  }
  Control::OnChildAdd(child);
}

void SceneView::OnChildRemove(Actor& child)
{
  mRootLayer.Remove(child);
  Control::OnChildRemove(child);
}

float SceneView::GetHeightForWidth(float width)
{
  Extents padding;
  padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
  return Control::GetHeightForWidth(width) + padding.top + padding.bottom;
}

float SceneView::GetWidthForHeight(float height)
{
  Extents padding;
  padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
  return Control::GetWidthForHeight(height) + padding.start + padding.end;
}

void SceneView::OnRelayout(const Vector2& size, RelayoutContainer& container)
{
  Control::OnRelayout(size, container);
  // Change canvas size of camera actor.
  UpdateRenderTask();
}

bool SceneView::IsResourceReady() const
{
  return mIBLResourceReady;
}

void SceneView::UpdateCamera(CameraActor camera)
{
  if(camera)
  {
    if(mSelectedCamera && mSelectedCamera.GetParent())
    {
      mSelectedCamera.Unparent();
    }
    mRootLayer.Add(camera);
  }

  mSelectedCamera = camera;
  UpdateRenderTask();
}

void SceneView::UpdateRenderTask()
{
  if(mRenderTask)
  {
    if(mSelectedCamera != mRenderTask.GetCameraActor())
    {
      mRenderTask.SetCameraActor(mSelectedCamera);
    }

    Vector3     size        = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
    const float aspectRatio = size.width / size.height;
    mSelectedCamera.SetAspectRatio(aspectRatio);
    const bool projectionVertical = mSelectedCamera.GetProperty<int>(Dali::DevelCameraActor::Property::PROJECTION_DIRECTION) == Dali::DevelCameraActor::VERTICAL;

    // if projectionVertical, Top / Bottom is +-ve to keep consistency with orthographic values
    // else, Left / Right is +-ve to keep consistency with orthographic values
    const float orthographicSize = DALI_LIKELY(projectionVertical) ? mSelectedCamera[Dali::CameraActor::Property::TOP_PLANE_DISTANCE] : mSelectedCamera[Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE];
    const float halfHeight       = DALI_LIKELY(projectionVertical) ? orthographicSize : orthographicSize / aspectRatio;
    const float halfWidth        = DALI_LIKELY(projectionVertical) ? orthographicSize * aspectRatio : orthographicSize;

    mSelectedCamera[Dali::CameraActor::Property::LEFT_PLANE_DISTANCE]   = -halfWidth;
    mSelectedCamera[Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE]  = halfWidth;
    mSelectedCamera[Dali::CameraActor::Property::TOP_PLANE_DISTANCE]    = halfHeight;
    mSelectedCamera[Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE] = -halfHeight;

    if(mUseFrameBuffer)
    {
      Dali::FrameBuffer currentFrameBuffer = mRenderTask.GetFrameBuffer();
      if(!currentFrameBuffer ||
         currentFrameBuffer.GetColorTexture().GetWidth() != size.width ||
         currentFrameBuffer.GetColorTexture().GetHeight() != size.height)
      {
        mRenderTask.ResetViewportGuideActor();
        mRenderTask.SetViewport(Dali::Viewport(Vector4::ZERO));

        // create offscreen buffer of new size to render our child actors to
        mTexture      = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, unsigned(size.width), unsigned(size.height));
        mRenderTarget = FrameBuffer::New(size.width, size.height, FrameBuffer::Attachment::DEPTH_STENCIL);
        mRenderTarget.AttachColorTexture(mTexture);
        Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::Image::GenerateUrl(mRenderTarget, 0u);

        Property::Map imagePropertyMap;
        imagePropertyMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE);
        imagePropertyMap.Insert(Toolkit::ImageVisual::Property::URL, imageUrl.GetUrl());
        // To flip rendered scene without CameraActor::SetInvertYAxis() to avoid backface culling.
        imagePropertyMap.Insert(Toolkit::ImageVisual::Property::PIXEL_AREA, Vector4(0.0f, 1.0f, 1.0f, -1.0f));
        mVisual = Toolkit::VisualFactory::Get().CreateVisual(imagePropertyMap);

        Toolkit::DevelControl::RegisterVisual(*this, RENDERING_BUFFER, mVisual);

        mRenderTask.SetFrameBuffer(mRenderTarget);
        mRenderTask.SetClearEnabled(true);
        mRenderTask.SetClearColor(Color::TRANSPARENT);
      }
    }
    else
    {
      mRenderTask.SetViewportGuideActor(Self());
      if(mRenderTask.GetFrameBuffer())
      {
        FrameBuffer framebuffer;
        mRenderTask.SetFrameBuffer(framebuffer);
        mRenderTask.SetClearEnabled(false);

        Toolkit::DevelControl::UnregisterVisual(*this, RENDERING_BUFFER);

        mVisual.Reset();
        mRenderTarget.Reset();
        mTexture.Reset();
      }
    }

    RotateCamera();
  }
}

void SceneView::OnWindowResized(Window window, Window::WindowSize size)
{
  mWindowOrientation = DevelWindow::GetPhysicalOrientation(window);
  RotateCamera();
}

void SceneView::RotateCamera()
{
  if(mUseFrameBuffer)
  {
    DevelCameraActor::RotateProjection(mSelectedCamera, DEFAULT_ORIENTATION);
  }
  else
  {
    DevelCameraActor::RotateProjection(mSelectedCamera, mWindowOrientation);
  }
}

} // namespace Internal
} // namespace Scene3D
} // namespace Dali
<|endoftext|>


<commit_before>#ifndef __FACTOR_MASTER_H__
#define __FACTOR_MASTER_H__

#ifndef _THREAD_SAFE
#define _THREAD_SAFE
#endif

#ifndef _REENTRANT
#define _REENTRANT
#endif

#include <errno.h>

// C headers
#include <fcntl.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <wchar.h>
#include <stdint.h>

// C++ headers
#include <algorithm>
#include <list>
#include <map>
#include <set>
#include <vector>
#include <iostream>
#include <iomanip>
#include <limits>
#include <sstream>
#include <string>

#define FACTOR_STRINGIZE_I(x) #x
#define FACTOR_STRINGIZE(x) FACTOR_STRINGIZE_I(x)

// Record compiler version
#if defined(__clang__)
#define FACTOR_COMPILER_VERSION "Clang (GCC " __VERSION__ ")"
#elif defined(__INTEL_COMPILER)
#define FACTOR_COMPILER_VERSION \
  "Intel C Compiler " FACTOR_STRINGIZE(__INTEL_COMPILER)
#elif defined(__MINGW32__)
#define FACTOR_COMPILER_VERSION "MinGW (GCC " __VERSION__ ")"
#elif defined(__GNUC__)
#define FACTOR_COMPILER_VERSION "GCC " __VERSION__
#elif defined(_MSC_FULL_VER)
#define FACTOR_COMPILER_VERSION \
  "Microsoft Visual C++ " FACTOR_STRINGIZE(_MSC_FULL_VER)
#else
#define FACTOR_COMPILER_VERSION "unknown"
#endif

#if defined(FACTOR_REPRODUCIBLE)
  #define FACTOR_COMPILE_TIME "[reproducible]"
#else
  // Record compilation time
  #define FACTOR_COMPILE_TIME  __DATE__ " " __TIME__
#endif

// Detect target CPU type
#if defined(__arm__)
#define FACTOR_ARM
#elif defined(__aarch64__)
#define FACTOR_ARM64
#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
#define FACTOR_AMD64
#define FACTOR_64
#elif defined(i386) || defined(__i386) || defined(__i386__) || defined(_M_IX86)
#define FACTOR_X86
#elif(defined(__POWERPC__) || defined(__ppc__) || defined(_ARCH_PPC)) && \
    (defined(__PPC64__) || defined(__64BIT__))
#define FACTOR_PPC64
#define FACTOR_PPC
#define FACTOR_64
#elif defined(__POWERPC__) || defined(__ppc__) || defined(_ARCH_PPC)
#define FACTOR_PPC32
#define FACTOR_PPC
#else
#error "Unsupported architecture"
#endif

#if defined(_MSC_VER) || defined (__MINGW32__)
#define WINDOWS
#define WINNT
#elif defined(WIN32)
#define WINDOWS
#endif

// Forward-declare this since it comes up in function prototypes
namespace factor { struct factor_vm; }

// Factor headers
#include "assert.hpp"
#include "debug.hpp"
#include "layouts.hpp"
#include "platform.hpp"
#include "utilities.hpp"
#include "primitives.hpp"
#include "errors.hpp"
#include "segments.hpp"
#include "gc_info.hpp"
#include "contexts.hpp"
#include "run.hpp"
#include "objects.hpp"
#include "sampling_profiler.hpp"
#include "bignumint.hpp"
#include "bignum.hpp"
#include "booleans.hpp"
#include "instruction_operands.hpp"
#include "tagged.hpp"
#include "code_blocks.hpp"
#include "bump_allocator.hpp"
#include "bitwise_hacks.hpp"
#include "mark_bits.hpp"
#include "fixup.hpp"
#include "free_list.hpp"
#include "write_barrier.hpp"
#include "object_start_map.hpp"
#include "aging_space.hpp"
#include "tenured_space.hpp"
#include "data_heap.hpp"
#include "code_heap.hpp"
#include "gc.hpp"
#include "float_bits.hpp"
#include "io.hpp"
#include "image.hpp"
#include "callbacks.hpp"
#include "dispatch.hpp"
#include "vm.hpp"
#include "allot.hpp"
#include "data_roots.hpp"
#include "code_roots.hpp"
#include "generic_arrays.hpp"
#include "callstack.hpp"
#include "slot_visitor.hpp"
#include "to_tenured_collector.hpp"
#include "arrays.hpp"
#include "math.hpp"
#include "byte_arrays.hpp"
#include "jit.hpp"
#include "quotations.hpp"
#include "inline_cache.hpp"
#include "mvm.hpp"
#include "factor.hpp"

#endif // __FACTOR_MASTER_H__
<commit_msg>master.hpp: Define FACTOR64 on arm64<commit_after>#ifndef __FACTOR_MASTER_H__
#define __FACTOR_MASTER_H__

#ifndef _THREAD_SAFE
#define _THREAD_SAFE
#endif

#ifndef _REENTRANT
#define _REENTRANT
#endif

#include <errno.h>

// C headers
#include <fcntl.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <wchar.h>
#include <stdint.h>

// C++ headers
#include <algorithm>
#include <list>
#include <map>
#include <set>
#include <vector>
#include <iostream>
#include <iomanip>
#include <limits>
#include <sstream>
#include <string>

#define FACTOR_STRINGIZE_I(x) #x
#define FACTOR_STRINGIZE(x) FACTOR_STRINGIZE_I(x)

// Record compiler version
#if defined(__clang__)
#define FACTOR_COMPILER_VERSION "Clang (GCC " __VERSION__ ")"
#elif defined(__INTEL_COMPILER)
#define FACTOR_COMPILER_VERSION \
  "Intel C Compiler " FACTOR_STRINGIZE(__INTEL_COMPILER)
#elif defined(__MINGW32__)
#define FACTOR_COMPILER_VERSION "MinGW (GCC " __VERSION__ ")"
#elif defined(__GNUC__)
#define FACTOR_COMPILER_VERSION "GCC " __VERSION__
#elif defined(_MSC_FULL_VER)
#define FACTOR_COMPILER_VERSION \
  "Microsoft Visual C++ " FACTOR_STRINGIZE(_MSC_FULL_VER)
#else
#define FACTOR_COMPILER_VERSION "unknown"
#endif

#if defined(FACTOR_REPRODUCIBLE)
  #define FACTOR_COMPILE_TIME "[reproducible]"
#else
  // Record compilation time
  #define FACTOR_COMPILE_TIME  __DATE__ " " __TIME__
#endif

// Detect target CPU type
#if defined(__arm__)
#define FACTOR_ARM
#elif defined(__aarch64__)
#define FACTOR_ARM64
#define FACTOR_64
#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
#define FACTOR_AMD64
#define FACTOR_64
#elif defined(i386) || defined(__i386) || defined(__i386__) || defined(_M_IX86)
#define FACTOR_X86
#elif(defined(__POWERPC__) || defined(__ppc__) || defined(_ARCH_PPC)) && \
    (defined(__PPC64__) || defined(__64BIT__))
#define FACTOR_PPC64
#define FACTOR_PPC
#define FACTOR_64
#elif defined(__POWERPC__) || defined(__ppc__) || defined(_ARCH_PPC)
#define FACTOR_PPC32
#define FACTOR_PPC
#else
#error "Unsupported architecture"
#endif

#if defined(_MSC_VER) || defined (__MINGW32__)
#define WINDOWS
#define WINNT
#elif defined(WIN32)
#define WINDOWS
#endif

// Forward-declare this since it comes up in function prototypes
namespace factor { struct factor_vm; }

// Factor headers
#include "assert.hpp"
#include "debug.hpp"
#include "layouts.hpp"
#include "platform.hpp"
#include "utilities.hpp"
#include "primitives.hpp"
#include "errors.hpp"
#include "segments.hpp"
#include "gc_info.hpp"
#include "contexts.hpp"
#include "run.hpp"
#include "objects.hpp"
#include "sampling_profiler.hpp"
#include "bignumint.hpp"
#include "bignum.hpp"
#include "booleans.hpp"
#include "instruction_operands.hpp"
#include "tagged.hpp"
#include "code_blocks.hpp"
#include "bump_allocator.hpp"
#include "bitwise_hacks.hpp"
#include "mark_bits.hpp"
#include "fixup.hpp"
#include "free_list.hpp"
#include "write_barrier.hpp"
#include "object_start_map.hpp"
#include "aging_space.hpp"
#include "tenured_space.hpp"
#include "data_heap.hpp"
#include "code_heap.hpp"
#include "gc.hpp"
#include "float_bits.hpp"
#include "io.hpp"
#include "image.hpp"
#include "callbacks.hpp"
#include "dispatch.hpp"
#include "vm.hpp"
#include "allot.hpp"
#include "data_roots.hpp"
#include "code_roots.hpp"
#include "generic_arrays.hpp"
#include "callstack.hpp"
#include "slot_visitor.hpp"
#include "to_tenured_collector.hpp"
#include "arrays.hpp"
#include "math.hpp"
#include "byte_arrays.hpp"
#include "jit.hpp"
#include "quotations.hpp"
#include "inline_cache.hpp"
#include "mvm.hpp"
#include "factor.hpp"

#endif // __FACTOR_MASTER_H__
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file state.cpp
 * @author Christoph Jentzsch <cj@ethdev.com>
 * @date 2014
 * State test functions.
 */

#include <boost/filesystem/operations.hpp>
#include <boost/test/unit_test.hpp>
#include "JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h>
#include <libethereum/CanonBlockChain.h>
#include <libethereum/State.h>
#include <libethereum/ExtVM.h>
#include <libethereum/Defaults.h>
#include <libevm/VM.h>
#include "TestHelper.h"

using namespace std;
using namespace json_spirit;
using namespace dev;
using namespace dev::eth;

namespace dev {  namespace test {

void doStateTests(json_spirit::mValue& v, bool _fillin)
{
	processCommandLineOptions();

	for (auto& i: v.get_obj())
	{
		cerr << i.first << endl;
		mObject& o = i.second.get_obj();

		BOOST_REQUIRE(o.count("env") > 0);
		BOOST_REQUIRE(o.count("pre") > 0);
		BOOST_REQUIRE(o.count("transaction") > 0);

		ImportTest importer(o, _fillin);

		State theState = importer.m_statePre;
		bytes tx = importer.m_transaction.rlp();
		bytes output;

		try
		{
			theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx, &output);
		}
		catch (Exception const& _e)
		{
			cnote << "state execution did throw an exception: " << diagnostic_information(_e);
			theState.commit();
		}
		catch (std::exception const& _e)
		{
			cnote << "state execution did throw an exception: " << _e.what();
		}

		if (_fillin)
		{
#if ETH_FATDB
			importer.exportTest(output, theState);
#else
			BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("You can not fill tests when FATDB is switched off"));
#endif
		}
		else
		{
			BOOST_REQUIRE(o.count("post") > 0);
			BOOST_REQUIRE(o.count("out") > 0);

			// check output
			checkOutput(output, o);

			// check logs
			checkLog(theState.pending().size() ? theState.log(0) : LogEntries(), importer.m_environment.sub.logs);

			// check addresses
#if ETH_FATDB
			auto expectedAddrs = importer.m_statePost.addresses();
			auto resultAddrs = theState.addresses();
			for (auto& expectedPair : expectedAddrs)
			{
				auto& expectedAddr = expectedPair.first;
				auto resultAddrIt = resultAddrs.find(expectedAddr);
				if (resultAddrIt == resultAddrs.end())
					BOOST_ERROR("Missing expected address " << expectedAddr);
				else
				{
					BOOST_CHECK_MESSAGE(importer.m_statePost.balance(expectedAddr) ==  theState.balance(expectedAddr), expectedAddr << ": incorrect balance " << theState.balance(expectedAddr) << ", expected " << importer.m_statePost.balance(expectedAddr));
					BOOST_CHECK_MESSAGE(importer.m_statePost.transactionsFrom(expectedAddr) ==  theState.transactionsFrom(expectedAddr), expectedAddr << ": incorrect txCount " << theState.transactionsFrom(expectedAddr) << ", expected " << importer.m_statePost.transactionsFrom(expectedAddr));
					BOOST_CHECK_MESSAGE(importer.m_statePost.code(expectedAddr) == theState.code(expectedAddr), expectedAddr << ": incorrect code");

					checkStorage(importer.m_statePost.storage(expectedAddr), theState.storage(expectedAddr), expectedAddr);
				}
			}
			checkAddresses<map<Address, u256> >(expectedAddrs, resultAddrs);
#endif
			BOOST_CHECK_MESSAGE(theState.rootHash() == h256(o["postStateRoot"].get_str()), "wrong post state root");
		}
	}
}
} }// Namespace Close

BOOST_AUTO_TEST_SUITE(StateTests)

BOOST_AUTO_TEST_CASE(stExample)
{
	dev::test::executeTests("stExample", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stSystemOperationsTest)
{
	dev::test::executeTests("stSystemOperationsTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stPreCompiledContracts)
{
	dev::test::executeTests("stPreCompiledContracts", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stLogTests)
{
	dev::test::executeTests("stLogTests", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stRecursiveCreate)
{
	dev::test::executeTests("stRecursiveCreate", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stInitCodeTest)
{
	dev::test::executeTests("stInitCodeTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stTransactionTest)
{
	dev::test::executeTests("stTransactionTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stSpecialTest)
{
	dev::test::executeTests("stSpecialTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stRefundTest)
{
	dev::test::executeTests("stRefundTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stBlockHashTest)
{
	dev::test::executeTests("stBlockHashTest", "/StateTests", dev::test::doStateTests);
}

//BOOST_AUTO_TEST_CASE(stQuadraticComplexityTest)
//{
//	   for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
//	   {
//			   string arg = boost::unit_test::framework::master_test_suite().argv[i];
//			   if (arg == "--quadratic" || arg == "--all")
//			   {
//					   auto start = chrono::steady_clock::now();

//					   dev::test::executeTests("stQuadraticComplexityTest", "/StateTests", dev::test::doStateTests);

//					   auto end = chrono::steady_clock::now();
//					   auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
//					   cnote << "test duration: " << duration.count() << " milliseconds.\n";
//			   }
//	   }
//}

BOOST_AUTO_TEST_CASE(stMemoryStressTest)
{
	   for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
	   {
			   string arg = boost::unit_test::framework::master_test_suite().argv[i];
			   if (arg == "--memory" || arg == "--all")
			   {
					   auto start = chrono::steady_clock::now();

					   dev::test::executeTests("stMemoryStressTest", "/StateTests", dev::test::doStateTests);

					   auto end = chrono::steady_clock::now();
					   auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
					   cnote << "test duration: " << duration.count() << " milliseconds.\n";
			   }
	   }
}

 BOOST_AUTO_TEST_CASE(stSolidityTest)
 {
		dev::test::executeTests("stSolidityTest", "/StateTests", dev::test::doStateTests);
 }

BOOST_AUTO_TEST_CASE(stMemoryTest)
{
	   dev::test::executeTests("stMemoryTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stCreateTest)
{
	for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
	{
		string arg = boost::unit_test::framework::master_test_suite().argv[i];
		if (arg == "--createtest")
		{
			if (boost::unit_test::framework::master_test_suite().argc <= i + 2)
			{
				cnote << "usage: ./testeth --createtest <PathToConstructor> <PathToDestiny>\n";
				return;
			}
			try
			{
				cnote << "Populating tests...";
				json_spirit::mValue v;
				string s = asString(dev::contents(boost::unit_test::framework::master_test_suite().argv[i + 1]));
				BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + (string)boost::unit_test::framework::master_test_suite().argv[i + 1] + " is empty.");
				json_spirit::read_string(s, v);
				dev::test::doStateTests(v, true);
				writeFile(boost::unit_test::framework::master_test_suite().argv[i + 2], asBytes(json_spirit::write_string(v, true)));
			}
			catch (Exception const& _e)
			{
				BOOST_ERROR("Failed state test with Exception: " << diagnostic_information(_e));
			}
			catch (std::exception const& _e)
			{
				BOOST_ERROR("Failed state test with Exception: " << _e.what());
			}
		}
	}
}

BOOST_AUTO_TEST_CASE(userDefinedFileState)
{
	dev::test::userDefinedTest("--statetest", dev::test::doStateTests);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>add quadratic complexity tests<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file state.cpp
 * @author Christoph Jentzsch <cj@ethdev.com>
 * @date 2014
 * State test functions.
 */

#include <boost/filesystem/operations.hpp>
#include <boost/test/unit_test.hpp>
#include "JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h>
#include <libethereum/CanonBlockChain.h>
#include <libethereum/State.h>
#include <libethereum/ExtVM.h>
#include <libethereum/Defaults.h>
#include <libevm/VM.h>
#include "TestHelper.h"

using namespace std;
using namespace json_spirit;
using namespace dev;
using namespace dev::eth;

namespace dev {  namespace test {

void doStateTests(json_spirit::mValue& v, bool _fillin)
{
	processCommandLineOptions();

	for (auto& i: v.get_obj())
	{
		cerr << i.first << endl;
		mObject& o = i.second.get_obj();

		BOOST_REQUIRE(o.count("env") > 0);
		BOOST_REQUIRE(o.count("pre") > 0);
		BOOST_REQUIRE(o.count("transaction") > 0);

		ImportTest importer(o, _fillin);

		State theState = importer.m_statePre;
		bytes tx = importer.m_transaction.rlp();
		bytes output;

		try
		{
			theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx, &output);
		}
		catch (Exception const& _e)
		{
			cnote << "state execution did throw an exception: " << diagnostic_information(_e);
			theState.commit();
		}
		catch (std::exception const& _e)
		{
			cnote << "state execution did throw an exception: " << _e.what();
		}

		if (_fillin)
		{
#if ETH_FATDB
			importer.exportTest(output, theState);
#else
			BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("You can not fill tests when FATDB is switched off"));
#endif
		}
		else
		{
			BOOST_REQUIRE(o.count("post") > 0);
			BOOST_REQUIRE(o.count("out") > 0);

			// check output
			checkOutput(output, o);

			// check logs
			checkLog(theState.pending().size() ? theState.log(0) : LogEntries(), importer.m_environment.sub.logs);

			// check addresses
#if ETH_FATDB
			auto expectedAddrs = importer.m_statePost.addresses();
			auto resultAddrs = theState.addresses();
			for (auto& expectedPair : expectedAddrs)
			{
				auto& expectedAddr = expectedPair.first;
				auto resultAddrIt = resultAddrs.find(expectedAddr);
				if (resultAddrIt == resultAddrs.end())
					BOOST_ERROR("Missing expected address " << expectedAddr);
				else
				{
					BOOST_CHECK_MESSAGE(importer.m_statePost.balance(expectedAddr) ==  theState.balance(expectedAddr), expectedAddr << ": incorrect balance " << theState.balance(expectedAddr) << ", expected " << importer.m_statePost.balance(expectedAddr));
					BOOST_CHECK_MESSAGE(importer.m_statePost.transactionsFrom(expectedAddr) ==  theState.transactionsFrom(expectedAddr), expectedAddr << ": incorrect txCount " << theState.transactionsFrom(expectedAddr) << ", expected " << importer.m_statePost.transactionsFrom(expectedAddr));
					BOOST_CHECK_MESSAGE(importer.m_statePost.code(expectedAddr) == theState.code(expectedAddr), expectedAddr << ": incorrect code");

					checkStorage(importer.m_statePost.storage(expectedAddr), theState.storage(expectedAddr), expectedAddr);
				}
			}
			checkAddresses<map<Address, u256> >(expectedAddrs, resultAddrs);
#endif
			BOOST_CHECK_MESSAGE(theState.rootHash() == h256(o["postStateRoot"].get_str()), "wrong post state root");
		}
	}
}
} }// Namespace Close

BOOST_AUTO_TEST_SUITE(StateTests)

BOOST_AUTO_TEST_CASE(stExample)
{
	dev::test::executeTests("stExample", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stSystemOperationsTest)
{
	dev::test::executeTests("stSystemOperationsTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stPreCompiledContracts)
{
	dev::test::executeTests("stPreCompiledContracts", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stLogTests)
{
	dev::test::executeTests("stLogTests", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stRecursiveCreate)
{
	dev::test::executeTests("stRecursiveCreate", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stInitCodeTest)
{
	dev::test::executeTests("stInitCodeTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stTransactionTest)
{
	dev::test::executeTests("stTransactionTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stSpecialTest)
{
	dev::test::executeTests("stSpecialTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stRefundTest)
{
	dev::test::executeTests("stRefundTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stBlockHashTest)
{
	dev::test::executeTests("stBlockHashTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stQuadraticComplexityTest)
{
	   for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
	   {
			   string arg = boost::unit_test::framework::master_test_suite().argv[i];
			   if (arg == "--quadratic" || arg == "--all")
			   {
					   auto start = chrono::steady_clock::now();

					   dev::test::executeTests("stQuadraticComplexityTest", "/StateTests", dev::test::doStateTests);

					   auto end = chrono::steady_clock::now();
					   auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
					   cnote << "test duration: " << duration.count() << " milliseconds.\n";
			   }
	   }
}

BOOST_AUTO_TEST_CASE(stMemoryStressTest)
{
	   for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
	   {
			   string arg = boost::unit_test::framework::master_test_suite().argv[i];
			   if (arg == "--memory" || arg == "--all")
			   {
					   auto start = chrono::steady_clock::now();

					   dev::test::executeTests("stMemoryStressTest", "/StateTests", dev::test::doStateTests);

					   auto end = chrono::steady_clock::now();
					   auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
					   cnote << "test duration: " << duration.count() << " milliseconds.\n";
			   }
	   }
}

 BOOST_AUTO_TEST_CASE(stSolidityTest)
 {
		dev::test::executeTests("stSolidityTest", "/StateTests", dev::test::doStateTests);
 }

BOOST_AUTO_TEST_CASE(stMemoryTest)
{
	   dev::test::executeTests("stMemoryTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stCreateTest)
{
	for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
	{
		string arg = boost::unit_test::framework::master_test_suite().argv[i];
		if (arg == "--createtest")
		{
			if (boost::unit_test::framework::master_test_suite().argc <= i + 2)
			{
				cnote << "usage: ./testeth --createtest <PathToConstructor> <PathToDestiny>\n";
				return;
			}
			try
			{
				cnote << "Populating tests...";
				json_spirit::mValue v;
				string s = asString(dev::contents(boost::unit_test::framework::master_test_suite().argv[i + 1]));
				BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + (string)boost::unit_test::framework::master_test_suite().argv[i + 1] + " is empty.");
				json_spirit::read_string(s, v);
				dev::test::doStateTests(v, true);
				writeFile(boost::unit_test::framework::master_test_suite().argv[i + 2], asBytes(json_spirit::write_string(v, true)));
			}
			catch (Exception const& _e)
			{
				BOOST_ERROR("Failed state test with Exception: " << diagnostic_information(_e));
			}
			catch (std::exception const& _e)
			{
				BOOST_ERROR("Failed state test with Exception: " << _e.what());
			}
		}
	}
}

BOOST_AUTO_TEST_CASE(userDefinedFileState)
{
	dev::test::userDefinedTest("--statetest", dev::test::doStateTests);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#ifndef HMLIB_TABLE_INC
#define HMLIB_TABLE_INC
#
#include<hmLib/position.hpp>
namespace hmLib{
	template<typename T>
	class table{
	public:
		using size_type = unsigned int;
		using column_type = std::vector < T > ;
	private:
	public:
		T& at(size_type pos_row, size_type pos_col);
		const T& at(size_type pos_row, size_type pos_col)const;
		T& operator()(size_type pos_row, size_type pos_col);
		const T& operator()(size_type pos_row, size_type pos_col)const;
		size_type column_size(size_type column_pos_)const;
	};

	template<typename T>
	class named_table;

}
#
#endif
<commit_msg>Define class basic_table interface.<commit_after>#ifndef HMLIB_TABLE_INC
#define HMLIB_TABLE_INC 100
#
#include<string>
#include<vector>
#include<algorithm>
#include<hmLib/position.hpp>
namespace hmLib{
	template<class Elem = char, class Traits = std::char_traits<Elem> >
	class basic_table{
	private:
		using my_type = basic_table < Elem, Traits >;
	public:
		using size_type = unsigned int;
		using string_type = std::basic_string < Elem, Traits >;
		using column_type = std::vector < string_type >;
		using data_type = std::pair < string_type, column_type >;
	private:
		std::vector<data_type> Data;
	private:
		struct proxy{
			operator string_type&();
			operator const string_type&()const;
			proxy& operator=(const string_type& Str_);
			template<typename type>
			void operator>>(type Type);
			template<typename type>
			void operator<<(type Type);
		};
		struct const_proxy{
			operator const string_type&()const;
			template<typename type>
			void operator>>(type Type);
		};
		template<typename type>
		struct type_proxy{
			operator type();
			type_proxy<type>& operator=(const type& Val);
		};
		template<typename type>
		struct const_type_proxy{
			operator type();
		};
	private:
		using data_iterator = typename std::vector<data_type>::iterator;
		using const_data_iterator = typename std::vector<data_type>::const_iterator;
		data_iterator data_begin(){ return Data.begin(); }
		data_iterator data_end(){ return Data.end(); }
		const_data_iterator data_begin()const{ return Data.begin(); }
		const_data_iterator data_end()const{ return Data.end(); }
	public:
		struct row_iterator;
		struct const_row_iterator;
		struct column_iterator;
		struct const_column_iterator;
		struct casted_column_iterator;
		struct const_casted_column_iterator;
		struct name_iterator;
		struct const_name_iterator;
	public:
		size_type find_column(const string_type& column_name_)const{ return std::find_if(data_begin(), data_end(), [](const data_type& d)->bool{return d.first == column_name; }); }
		void push_back_column(column_type column_ = column_type(), string_type column_name_ = ""){ Data.push_back(std::make_pair(column_name_, column_); }
		void pop_back_column(){ Data.pop_back(); }
		void insert_column(size_type column_no_, column_type column_ = column_type(), string_type column_name_ = "");
		void erase_column(size_type column_no_);
		void clear();
	public://access column
		column_iterator column_begin(size_type column_no_){ return column_iterator(Data.at(column_no_).second.begin()); }
		column_iterator column_end(size_type column_no_){ return column_iterator(Data.at(column_no_).second.end()); }
		const_column_iterator column_begin(size_type column_no_)const{ return const_column_iterator(Data.at(column_no_).second.begin()); }
		const_column_iterator column_end(size_type column_no_)const{ return const_column_iterator(Data.at(column_no_).second.end()); }
	public://access column as casted style
		casted_column_iterator casted_column_begin(size_type column_no_);
		casted_column_iterator casted_column_end(size_type column_no_);
		const_casted_column_iterator casted_column_begin(size_type column_no_)const;
		const_casted_column_iterator casted_column_end(size_type column_no_)const;
	public://access name of column
		name_iterator name_begin(){ return name_iterator(data_begin()); }
		name_iterator name_end(){ return name_iterator(data_end()); }
		const_name_iterator name_begin()const{ return const_name_iterator(data_begin()); }
		const_name_iterator name_end()const{ return const_name_iterator(data_end()); }
	public://access row
		row_iterator row_begin(size_type row_no_){ return row_iterator(data_begin(),row_no_); }
		row_iterator row_end(size_type row_no_){ return row_iterator(data_end(), row_no_); }
		const_row_iterator row_begin(size_type row_no_)const{ return const_row_iterator(data_begin(), row_no_); }
		const_row_iterator row_end(size_type row_no_)const{ return const_row_iterator(data_end(), row_no_); }
	public://access directoly
		proxy at(size_type row_pos_, size_type column_pos_){ return proxy(Data.at(column_pos_).second.at(row_pos_)); }
		const_proxy at(size_type row_pos_, size_type column_pos_)const{ return const_proxy(Data.at(column_pos_).second.at(row_pos_)); }
		proxy operator()(size_type row_pos_, size_type column_pos_){ return proxy(Data.at(column_pos_).second.at(row_pos_)); }
		const_proxy operator()(size_type row_pos_, size_type column_pos_)const{ return const_proxy(Data.at(column_pos_).second.at(row_pos_)); }
		template<typename type>
		type_proxy<type> casted_at(size_type row_pos_, size_type column_pos_){ return type_proxy<type>(Data.at(column_pos_).second.at(row_pos_)); }
		template<typename type>
		const_type_proxy<type> casted_at(size_type row_pos_, size_type column_pos_)const{ return const_type_proxy<type>(Data.at(column_pos_).second.at(row_pos_)); }
	};
	using table = basic_table<char, std::char_traits < char >> ;
}
#
#endif
<|endoftext|>


<commit_before>#include <thread>
#include <ctime>
#include <QSettings>

#include "lirch_plugin.h"
#include "userlist_messages.h"
#include "user_status.h"
#include "received_messages.h"
#include "notify_messages.h"
#include "grinder_messages.h"
#include "lirch_constants.h"
#include "nick_messages.h"

using namespace std;

message sendNick(QString str, QString)
{
	if (str.startsWith("/nick "))
	{
		return nick_message::create(str.section(' ',1));
	}
	return empty_message::create();
}

class userlist_timer : public message_data
{
public:
	virtual std::unique_ptr<message_data> copy() const {return std::unique_ptr<message_data>(nullptr);}
	static message create() {return message_create("userlist_timer", nullptr);}
};

class list_channels : public message_data
{
public:
	virtual std::unique_ptr<message_data> copy() const {return std::unique_ptr<message_data>(new list_channels(*this));}
	static message create(const QString &fch, const QString &dch) {return message_create("list_channels", new list_channels(fch,dch));}
	list_channels(const QString &fch, const QString &dch) : filterChannel(fch), destinationChannel(dch) {}

	QString filterChannel;
	QString destinationChannel;
};

message sendList(QString text, QString channel)
{
	return list_channels::create(text.section(QChar(' '), 1), channel);
}

//updates all of the relevent fields of out status map based on the received message
void updateSenderStatus(plugin_pipe p, received_message * message, unordered_map<QString, user_status> & userList)
{
	userList[message->nick].nick=message->nick;
	if (message->subtype==received_message_subtype::NORMAL || message->subtype==received_message_subtype::ME || message->subtype==received_message_subtype::NOTIFY)
		userList[message->nick].channels.insert(message->channel);

	//message->channel is storing the old nickname of the user in the case that it is a nick type received.
	//if it is, remove the person of the old nickname
	else if (message->subtype==received_message_subtype::NICK)
		userList.erase(message->channel);

	userList[message->nick].ip=message->ipAddress;
	userList[message->nick].lastseen=time(NULL);

	p.write(userlist_message::create(userList));
}

void askForUsers(plugin_pipe p, QString channel)
{
	time_t start = time(NULL);
	while (time(NULL)-start < 1)
	{
		p.write(who_is_here_message::create(channel));
		this_thread::sleep_for(chrono::milliseconds(50));
	}
}

//validateName also sets old nick to new nick if it is acceptable
bool setNick(plugin_pipe p, unordered_map<QString, user_status> & userList,QString & oldNick, QString newNick)
{
	if (newNick!=LIRCH_DEFAULT_NICK && userList.count(newNick))
		return false;
	else
	{
		p.write(changed_nick_message::create(oldNick,newNick));
		oldNick = newNick;
		return true;
	}
}

void populateDefaultChannel(plugin_pipe p, QString channel, unordered_map<QString, user_status> & userList,QString & nick)
{
	QSettings settings(QSettings::IniFormat, QSettings::UserScope, LIRCH_COMPANY_NAME, LIRCH_PRODUCT_NAME);
	settings.beginGroup("UserData");
	QString defaultNick = settings.value("nick",LIRCH_DEFAULT_NICK).value<QString>();
	settings.sync();
	settings.endGroup();

	askForUsers(p,channel);

	if (defaultNick.toUtf8().size() > 64)
	{
		p.write(notify_message::create("","Default nick too long.  You are spartacus."));
		return;
	}

	if (setNick(p,userList,nick,defaultNick))
		p.write(notify_message::create(channel,"Welcome to LIRCH, "+defaultNick+"."));
	else
		p.write(notify_message::create(channel,"Default nick taken.  You can assign a new one with /nick <username>"));

}

void run(plugin_pipe p, string name)
{
	p.write(registration_message::create(0, name, "userlist_request"));
	p.write(registration_message::create(0, name, "userlist_timer"));
	p.write(registration_message::create(30000, name, "received"));
	p.write(registration_message::create(0, name, "list_channels"));
	p.write(registration_message::create(0, name, "handler_ready"));
	p.write(registration_message::create(-30000, name, "nick"));

	unordered_map<QString, user_status> userList;

	QString currentNick = LIRCH_DEFAULT_NICK;

	populateDefaultChannel(p,LIRCH_DEFAULT_CHANNEL,userList,currentNick);

	p.write(register_handler::create("/nick", sendNick));

	while (true)
	{
		message m=p.blocking_read();
		if (m.type=="shutdown")
		{
			return;
		}
		else if (m.type=="registration_status")
		{
			auto s=dynamic_cast<registration_status *>(m.getdata());
			if (!s)
				continue;
			if (!s->status)
			{
				if ((0>=s->priority && s->priority>-200) || (30000>=s->priority && s->priority>29000))
					p.write(registration_message::create(s->priority-1, name, s->type));
				else
					return;
			}
			else
			{
				if (s->type=="userlist_timer")
				{
					p.write(userlist_timer::create());
				}
				else if (s->type=="list_channels")
				{
					p.write(register_handler::create("/list", sendList));
				}
			}
		}
		else if (m.type=="userlist_request")
		{
			p.write(userlist_message::create(userList));
		}
		else if (m.type=="userlist_timer")
		{
			time_t now=time(NULL);
			//Remove all nicks that haven't been seen in 2 minutes
			decltype(userList.begin()) i;
			while ((i=std::find_if(userList.begin(), userList.end(), [now](const std::pair<const QString &, const user_status &> &p) {return p.second.lastseen<now-2*60;}))!=userList.end())
				userList.erase(i);
			p.write(userlist_message::create(userList));
			thread([](plugin_pipe p)
			{
				this_thread::sleep_for(chrono::seconds(10));
				p.write(userlist_timer::create());
			}, p).detach();
		}
		else if (m.type=="handler_ready")
		{
			p.write(register_handler::create("/list", sendList));
			p.write(register_handler::create("/nick", sendNick));
		}
		else if (m.type=="received")
		{
			auto s=dynamic_cast<received_message *>(m.getdata());
			if (!s)
				continue;
			p.write(m.decrement_priority());
			updateSenderStatus(p,s,userList);
			if (s->subtype==received_message_subtype::WHOHERE)
			{
				p.write(here_message::create(s->channel));
			}
		}
		else if (m.type=="nick")
		{
			auto s=dynamic_cast<nick_message *>(m.getdata());
			if (!s)
				continue;
			p.write(m.decrement_priority());
			if (s->nick.toUtf8().size() > 64)
			{
				p.write(notify_message::create("","Nick too long.  Keeping old nick."));
				continue;
			}
			QString newNick=s->nick;
			QString oldNick=currentNick;
			if (setNick(p,userList,currentNick,newNick))
				p.write(sendable_notify_message::create("",oldNick+" has changed their nick to "+newNick+"."));
			else
				p.write(notify_message::create("","Nick taken.  Keeping old nick."));
		}
		else if (m.type=="list_channels")
		{
			auto s=dynamic_cast<list_channels *>(m.getdata());
			if (!s)
				continue;
			for (auto &i : userList)
			{
				if (s->filterChannel=="" || i.second.channels.count(s->filterChannel)!=0)
				{
					QStringList channelList;
					for (auto &c : i.second.channels)
						channelList.append(c);
					p.write(notify_message::create(s->destinationChannel, QObject::tr("User %1 (%2) was last seen at %3 and is in the following channels: %4").arg(i.second.nick, i.second.ip.toString(), ctime(&i.second.lastseen), channelList.join(" "))));
				}
			}
		}
		else
			p.write(m.decrement_priority());
	}
}

<commit_msg>made userlist keep info on people after they change name<commit_after>#include <thread>
#include <ctime>
#include <QSettings>

#include "lirch_plugin.h"
#include "userlist_messages.h"
#include "user_status.h"
#include "received_messages.h"
#include "notify_messages.h"
#include "grinder_messages.h"
#include "lirch_constants.h"
#include "nick_messages.h"

using namespace std;

message sendNick(QString str, QString)
{
	if (str.startsWith("/nick "))
	{
		return nick_message::create(str.section(' ',1));
	}
	return empty_message::create();
}

class userlist_timer : public message_data
{
public:
	virtual std::unique_ptr<message_data> copy() const {return std::unique_ptr<message_data>(nullptr);}
	static message create() {return message_create("userlist_timer", nullptr);}
};

class list_channels : public message_data
{
public:
	virtual std::unique_ptr<message_data> copy() const {return std::unique_ptr<message_data>(new list_channels(*this));}
	static message create(const QString &fch, const QString &dch) {return message_create("list_channels", new list_channels(fch,dch));}
	list_channels(const QString &fch, const QString &dch) : filterChannel(fch), destinationChannel(dch) {}

	QString filterChannel;
	QString destinationChannel;
};

message sendList(QString text, QString channel)
{
	return list_channels::create(text.section(QChar(' '), 1), channel);
}

//updates all of the relevent fields of out status map based on the received message
void updateSenderStatus(plugin_pipe p, received_message * message, unordered_map<QString, user_status> & userList)
{
	//message->channel is storing the old nickname of the user in the case that it is a nick type received.
	//if it is, remove the person of the old nickname
	if (message->subtype==received_message_subtype::NICK)
	{
		user_status oldNickInfo = userList[message->channel];
		oldNickInfo.nick=message->nick;
		userList.erase(message->channel);
		userList[message->nick]=oldNickInfo;
		return;
	}

	userList[message->nick].nick=message->nick;
	if (message->subtype==received_message_subtype::NORMAL || message->subtype==received_message_subtype::ME || message->subtype==received_message_subtype::NOTIFY)
		userList[message->nick].channels.insert(message->channel);

	userList[message->nick].ip=message->ipAddress;
	userList[message->nick].lastseen=time(NULL);

	p.write(userlist_message::create(userList));
}

void askForUsers(plugin_pipe p, QString channel)
{
	time_t start = time(NULL);
	while (time(NULL)-start < 1)
	{
		p.write(who_is_here_message::create(channel));
		this_thread::sleep_for(chrono::milliseconds(50));
	}
}

//validateName also sets old nick to new nick if it is acceptable
bool setNick(plugin_pipe p, unordered_map<QString, user_status> & userList,QString & oldNick, QString newNick)
{
	if (newNick!=LIRCH_DEFAULT_NICK && userList.count(newNick))
		return false;
	else
	{
		p.write(changed_nick_message::create(oldNick,newNick));
		oldNick = newNick;
		return true;
	}
}

void populateDefaultChannel(plugin_pipe p, QString channel, unordered_map<QString, user_status> & userList,QString & nick)
{
	QSettings settings(QSettings::IniFormat, QSettings::UserScope, LIRCH_COMPANY_NAME, LIRCH_PRODUCT_NAME);
	settings.beginGroup("UserData");
	QString defaultNick = settings.value("nick",LIRCH_DEFAULT_NICK).value<QString>();
	settings.sync();
	settings.endGroup();

	askForUsers(p,channel);

	if (defaultNick.toUtf8().size() > 64)
	{
		p.write(notify_message::create("","Default nick too long.  You are spartacus."));
		return;
	}

	if (setNick(p,userList,nick,defaultNick))
		p.write(notify_message::create(channel,"Welcome to LIRCH, "+defaultNick+"."));
	else
		p.write(notify_message::create(channel,"Default nick taken.  You can assign a new one with /nick <username>"));

}

void run(plugin_pipe p, string name)
{
	p.write(registration_message::create(0, name, "userlist_request"));
	p.write(registration_message::create(0, name, "userlist_timer"));
	p.write(registration_message::create(30000, name, "received"));
	p.write(registration_message::create(0, name, "list_channels"));
	p.write(registration_message::create(0, name, "handler_ready"));
	p.write(registration_message::create(-30000, name, "nick"));

	unordered_map<QString, user_status> userList;

	QString currentNick = LIRCH_DEFAULT_NICK;

	populateDefaultChannel(p,LIRCH_DEFAULT_CHANNEL,userList,currentNick);

	p.write(register_handler::create("/nick", sendNick));

	while (true)
	{
		message m=p.blocking_read();
		if (m.type=="shutdown")
		{
			return;
		}
		else if (m.type=="registration_status")
		{
			auto s=dynamic_cast<registration_status *>(m.getdata());
			if (!s)
				continue;
			if (!s->status)
			{
				if ((0>=s->priority && s->priority>-200) || (30000>=s->priority && s->priority>29000))
					p.write(registration_message::create(s->priority-1, name, s->type));
				else
					return;
			}
			else
			{
				if (s->type=="userlist_timer")
				{
					p.write(userlist_timer::create());
				}
				else if (s->type=="list_channels")
				{
					p.write(register_handler::create("/list", sendList));
				}
			}
		}
		else if (m.type=="userlist_request")
		{
			p.write(userlist_message::create(userList));
		}
		else if (m.type=="userlist_timer")
		{
			time_t now=time(NULL);
			//Remove all nicks that haven't been seen in 2 minutes
			decltype(userList.begin()) i;
			while ((i=std::find_if(userList.begin(), userList.end(), [now](const std::pair<const QString &, const user_status &> &p) {return p.second.lastseen<now-2*60;}))!=userList.end())
				userList.erase(i);
			p.write(userlist_message::create(userList));
			thread([](plugin_pipe p)
			{
				this_thread::sleep_for(chrono::seconds(10));
				p.write(userlist_timer::create());
			}, p).detach();
		}
		else if (m.type=="handler_ready")
		{
			p.write(register_handler::create("/list", sendList));
			p.write(register_handler::create("/nick", sendNick));
		}
		else if (m.type=="received")
		{
			auto s=dynamic_cast<received_message *>(m.getdata());
			if (!s)
				continue;
			p.write(m.decrement_priority());
			updateSenderStatus(p,s,userList);
			if (s->subtype==received_message_subtype::WHOHERE)
			{
				p.write(here_message::create(s->channel));
			}
		}
		else if (m.type=="nick")
		{
			auto s=dynamic_cast<nick_message *>(m.getdata());
			if (!s)
				continue;
			p.write(m.decrement_priority());
			if (s->nick.toUtf8().size() > 64)
			{
				p.write(notify_message::create("","Nick too long.  Keeping old nick."));
				continue;
			}
			QString newNick=s->nick;
			QString oldNick=currentNick;
			if (setNick(p,userList,currentNick,newNick))
				p.write(sendable_notify_message::create("",oldNick+" has changed their nick to "+newNick+"."));
			else
				p.write(notify_message::create("","Nick taken.  Keeping old nick."));
		}
		else if (m.type=="list_channels")
		{
			auto s=dynamic_cast<list_channels *>(m.getdata());
			if (!s)
				continue;
			for (auto &i : userList)
			{
				if (s->filterChannel=="" || i.second.channels.count(s->filterChannel)!=0)
				{
					QStringList channelList;
					for (auto &c : i.second.channels)
						channelList.append(c);
					p.write(notify_message::create(s->destinationChannel, QObject::tr("User %1 (%2) was last seen at %3 and is in the following channels: %4").arg(i.second.nick, i.second.ip.toString(), ctime(&i.second.lastseen), channelList.join(" "))));
				}
			}
		}
		else
			p.write(m.decrement_priority());
	}
}

<|endoftext|>