<commit_before>// Copyright 2016, Alex Dunyak

#include "drake/solvers/MosekLP.h"

extern "C" {
  #include <mosek/mosek.h>
}

#include <memory>
#include <vector>
#include <iostream>
#include <string>
#include <map>

#include <Eigen/Sparse>
#include <Eigen/Core>

#include "drake/solvers/Constraint.h"

namespace drake {
namespace solvers {

MosekLP::MosekLP(int num_variables, int num_constraints,
    std::vector<double> equationScalars,
    Eigen::MatrixXd cons,
    std::vector<MSKboundkeye> mosek_constraint_bounds,
    std::vector<double> upper_constraint_bounds,
    std::vector<double> lower_constraint_bounds,
    std::vector<MSKboundkeye> mosek_variable_bounds,
    std::vector<double> upper_variable_bounds,
    std::vector<double> lower_variable_bounds) {
  numvar_ = num_variables;
  numcon_ = num_constraints;
  env_ = NULL;
  task_ = NULL;
  solutions_.clear();
  r_ = MSK_makeenv(&env_, NULL);
  if (r_ == MSK_RES_OK) {
    // Creates optimization task
    r_ = MSK_maketask(env_, numcon_, numvar_, &task_);
    // Append numcon_ empty constraints
    if (r_ == MSK_RES_OK)
      r_ = MSK_appendcons(task_, numcon_);

    // Append numvar_ variables, initially fixed at zero
    if (r_ == MSK_RES_OK)
      r_ = MSK_appendvars(task_, numvar_);
  }
  // add the equation to maximize to the environment.
  int j = 0;
  for (j = 0; j < numvar_ && r_ == MSK_RES_OK; j++) {
    if (r_ == MSK_RES_OK)
      r_ = MSK_putcj(task_, j, equationScalars[j]);
  }
  AddVariableBounds(mosek_variable_bounds, upper_variable_bounds,
      lower_variable_bounds);
  AddLinearConstraintMatrix(cons);
  AddLinearConstraintBounds(mosek_constraint_bounds, upper_constraint_bounds,
      lower_constraint_bounds);
}

void MosekLP::AddLinearConstraintMatrix(const Eigen::MatrixXd& cons) {
  Eigen::SparseMatrix<double> sparsecons = cons.sparseView();
  // Send the sparse matrix rep into addLinearConstraintSparseColumnMatrix(),
  // which will handle setting the mosek constraints
  MosekLP::AddLinearConstraintSparseColumnMatrix(sparsecons);
}

void MosekLP::AddLinearConstraintSparseColumnMatrix(
    const Eigen::SparseMatrix<double>& sparsecons) {
  int j = 0;  // iterator
  // Define sparse matrix representation to be the same size as the desired
  // constraints
  std::vector<MSKint32t> aptrb;
  std::vector<MSKint32t> aptre;
  std::vector<MSKint32t> asub;
  std::vector<double> aval;

  for (j = 0; j < sparsecons.cols(); j++)
    aptrb.push_back((MSKint32t) sparsecons.outerIndexPtr()[j]);
  for (j = 0; j < sparsecons.cols(); j++)
    aptre.push_back((MSKint32t) sparsecons.outerIndexPtr()[j+1]);
  for (j = 0; j < sparsecons.nonZeros(); j++)
    asub.push_back((MSKint32t) sparsecons.innerIndexPtr()[j]);
  for (j = 0; j < sparsecons.nonZeros(); j++)
    aval.push_back(sparsecons.valuePtr()[j]);

  // following code adapted from http://docs.mosek.com/7.1/capi/Linear_optimization.html
  // check if still working in valid environment
  for (j = 0; j < numvar_ && r_ == MSK_RES_OK; j++) {
    r_ = MSK_putacol(task_,
                    j,
                    aptre[j] - aptrb[j],  // Number of nonzeros in column i
                    &asub[0] + aptrb[j],  // Pointer to row indexes of column i
                    &aval[0] + aptrb[j]);  // pointer to values of column i
  }
}

void MosekLP::AddLinearConstraintBounds(
    const std::vector<MSKboundkeye>& mosek_bounds_,
    const std::vector<double>& upper_bounds_,
    const std::vector<double>& lower_bounds_) {
  int i = 0;
  for (; i < numcon_ && r_ == MSK_RES_OK; i++) {
    r_ = MSK_putconbound(task_, i, mosek_bounds_[i],
                        lower_bounds_[i], upper_bounds_[i]);
  }
}

void MosekLP::AddVariableBounds(const std::vector<MSKboundkeye>& mosek_bounds_,
                                const std::vector<double>& upper_bounds_,
                                const std::vector<double>& lower_bounds_) {
  int j = 0;
  for (; j < numvar_ && r_ == MSK_RES_OK; j++) {
    r_ = MSK_putvarbound(task_, j, mosek_bounds_[j], lower_bounds_[j],
        upper_bounds_[j]);
  }
}

std::vector<MSKboundkeye> MosekLP::FindMosekBounds(
    const std::vector<double>& upper_bounds_,
    const std::vector<double>& lower_bounds_) const {
  assert(upper_bounds_.size() == lower_bounds_.size());
  std::vector<MSKboundkeye> mosek_bounds_;
  unsigned int i = 0;
  for (i = 0; i != upper_bounds_.size(); i++) {
    if (upper_bounds_[i] == +MSK_INFINITY) {
      if (lower_bounds_[i] == -MSK_INFINITY) {
        mosek_bounds_.push_back(MSK_BK_FR);
      } else {
        mosek_bounds_.push_back(MSK_BK_LO);
      }
    } else {
      if (upper_bounds_[i] == lower_bounds_[i]) {
        mosek_bounds_.push_back(MSK_BK_FX);
      } else if (lower_bounds_[i] == -MSK_INFINITY) {
        mosek_bounds_.push_back(MSK_BK_UP);
      } else {
        mosek_bounds_.push_back(MSK_BK_RA);
      }
    }
  }
  return mosek_bounds_;
}

SolutionResult MosekLP::Solve(OptimizationProblem &prog) const {
  // construct an object that calls all the previous work so I can salvage
  // something at least.
  // assume that the problem type is linear currently.
  // TODO(adunyak): Add support for quadratic objective and constraints
  if (!prog.GetSolverOptionsStr("Mosek").empty()) {
    if (prog.GetSolverOptionsStr("Mosek").at("problemtype").find("linear")
        == std::string::npos) {
      return kUnknownError;  // Not a linear optimization
    }
  } else {
      return kUnknownError;
  }
  int totalconnum = 0, i = 0;
  for (auto&& con_ : prog.GetAllLinearConstraints()) {
    // check to see if the constraint references a single variable,
    // which is handles as a variable bound by mosek
    for (i = 0; i < (con_.constraint())->A().rows(); ++i) {
      auto row = (con_.constraint())->A().row(i);
      if (row.nonZeros() != 1)
        totalconnum++;
    }
  }
  Eigen::MatrixXd linear_cons(totalconnum, prog.num_vars());
  std::vector<double> upper_constraint_bounds(totalconnum);
  std::vector<double> lower_constraint_bounds(totalconnum);
  std::vector<MSKboundkeye> mosek_constraint_bounds(totalconnum);
  std::vector<MSKboundkeye> mosek_variable_bounds(prog.num_vars());
  std::vector<double> upper_variable_bounds(numvar_);
  std::vector<double> lower_variable_bounds(numvar_);
  linear_cons.setZero(totalconnum, prog.num_vars());

  // Expect only one boundingbox constraint or no such constraint.
  if (!(prog.bounding_box_constraints().empty())) {
    assert(&(prog.bounding_box_constraints().front()) ==
        &(prog.bounding_box_constraints().back()));
    auto bbox = *(prog.bounding_box_constraints().front().constraint());
    std::vector<double> lower_variable_bounds(bbox.lower_bound().data(),
        bbox.lower_bound().data() +
        bbox.lower_bound().rows() * bbox.lower_bound().cols());
    std::vector<double> upper_variable_bounds(bbox.upper_bound().data(),
        bbox.upper_bound().data() +
        bbox.upper_bound().rows() * bbox.upper_bound().cols());
    for (auto& b : lower_variable_bounds) {
      if (b == -std::numeric_limits<double>::infinity())
        b = -MSK_INFINITY;
    }
    for (auto& b : upper_variable_bounds) {
      if (b == +std::numeric_limits<double>::infinity())
        b = MSK_INFINITY;
    }
    mosek_variable_bounds = FindMosekBounds(upper_variable_bounds,
                                           lower_variable_bounds);
  } else {
    // No bounding box constraint
    for (i = 0; i < numvar_; i++) {
      upper_variable_bounds[i] = +MSK_INFINITY;
      lower_variable_bounds[i] = -MSK_INFINITY;
    }
    mosek_variable_bounds = FindMosekBounds(upper_variable_bounds,
                                            lower_variable_bounds);
  }
  int connum = 0;
  i = 0;
  // TODO(alexdunyak): Allow constraints to affect specific variables
  for (const auto& con : prog.GetAllLinearConstraints()) {
    // con can call functions of  Binding<LinearConstraint>, but the actual
    // type is const std::list<Binding<LinearConstraint>>::const_iterator&
    // Address the constraint matrix directly, translating back to our original
    // variable space
    for (int i = 0; static_cast<unsigned int>(i) <
        con.constraint()->num_constraints(); i++) {
      for (int j = 0; j < (con.constraint())->A().cols(); j++) {
        linear_cons(connum, j) = (con.constraint()->A())(i, j);
      }
      // lower bounds first
      lower_constraint_bounds[connum] =
          (con.constraint())->lower_bound()(i);
      if (lower_constraint_bounds[connum] ==
          -std::numeric_limits<double>::infinity())
        lower_constraint_bounds[connum] = -MSK_INFINITY;
      // upper bound
      upper_constraint_bounds[connum] =
          (con.constraint())->upper_bound()(i);
      if (upper_constraint_bounds[connum] ==
          +std::numeric_limits<double>::infinity())
        upper_constraint_bounds[connum] = +MSK_INFINITY;
      connum++;
    }
  }
  mosek_constraint_bounds = FindMosekBounds(upper_constraint_bounds,
                                            lower_constraint_bounds);
  // find the linear objective here
  LinearConstraint *obj_ = static_cast<LinearConstraint *>(
      &(*(prog.generic_costs().front().constraint())));
  std::vector<double> linobj_((*obj_).A().data(),
      (*obj_).A().data() + (*obj_).A().rows() * (*obj_).A().cols());
  MosekLP opt(prog.num_vars(),
              totalconnum,
              linobj_,
              linear_cons,
              mosek_constraint_bounds,
              upper_constraint_bounds,
              lower_constraint_bounds,
              mosek_variable_bounds,
              upper_variable_bounds,
              lower_variable_bounds);
  std::string mom = prog.GetSolverOptionsStr("Mosek").at("maxormin");
  std::string ptype = prog.GetSolverOptionsStr("Mosek").at("problemtype");
  SolutionResult s = opt.OptimizeTask(mom, ptype);
  prog.SetDecisionVariableValues(opt.GetEigenVectorSolutions());
  return s;
}

SolutionResult MosekLP::OptimizeTask(const std::string& maxormin,
                                     const std::string& ptype) {
  solutions_.clear();
  MSKsoltypee problemtype = MSK_SOL_BAS;
  if (ptype.find("quad") != std::string::npos)
    problemtype = MSK_SOL_ITR;
  else if (ptype.find("linear") != std::string::npos)
    problemtype = MSK_SOL_BAS;
  else
    return kUnknownError;
  if (r_ == MSK_RES_OK && maxormin == "max")
    r_ = MSK_putobjsense(task_, MSK_OBJECTIVE_SENSE_MAXIMIZE);
  else if (r_ == MSK_RES_OK && maxormin == "min")
    r_ = MSK_putobjsense(task_, MSK_OBJECTIVE_SENSE_MINIMIZE);
  if (r_ == MSK_RES_OK) {
    MSKrescodee trmcode;

    r_ = MSK_optimizetrm(task_, &trmcode);
    if (r_ == MSK_RES_OK) {
      MSKsolstae solsta;
      if (r_ == MSK_RES_OK) {
        r_ = MSK_getsolsta(task_, problemtype, &solsta);

        switch (solsta) {
          case MSK_SOL_STA_OPTIMAL:
          case MSK_SOL_STA_NEAR_OPTIMAL: {
            std::unique_ptr<double[]> xx(new double[numvar_]);
            if (xx) {
              /* Request the basic solution. */
              MSK_getxx(task_, problemtype, xx.get());
              for (int j = 0; j < numvar_; ++j) {
                solutions_.push_back(xx[j]);
              }
              return kSolutionFound;
            } else {
              r_ = MSK_RES_ERR_SPACE;
              return kUnknownError;
            }
            break;
          }
          case MSK_SOL_STA_DUAL_INFEAS_CER:
          case MSK_SOL_STA_PRIM_INFEAS_CER:
          case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER:
          case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER:
            printf("Primal or dual infeasibility certificate found.\n");
            return kInfeasibleConstraints;
            break;
          case MSK_SOL_STA_UNKNOWN: {
            char symname[MSK_MAX_STR_LEN];
            char desc[MSK_MAX_STR_LEN];

            /* If the solutions status is unknown, print the termination code
               indicating why the optimizer terminated prematurely. */
            MSK_getcodedesc(trmcode, symname, desc);
            printf("The solution status is unknown.\n");
            printf("The optimizer terminitated with code: %s\n", symname);
            break;
          }
          default:
            printf("Other solution status.\n");
            break;
        }
      }
    }
  }
  return kUnknownError;
}

Eigen::VectorXd MosekLP::GetEigenVectorSolutions() const {
  Eigen::VectorXd soln(numvar_);
  if (solutions_.empty())
    return soln;
  unsigned int i = 0;
  for (i = 0; i < solutions_.size(); ++i) {
    soln(i) = solutions_[i];
  }
  return soln.transpose();
}

}  // namespace solvers
}  // namespace drake
<commit_msg>changed a static_cast using a reference-dereference to simply use the get() function of std::unique_ptr.<commit_after>// Copyright 2016, Alex Dunyak

#include "drake/solvers/MosekLP.h"

extern "C" {
  #include <mosek/mosek.h>
}

#include <memory>
#include <vector>
#include <iostream>
#include <string>
#include <map>

#include <Eigen/Sparse>
#include <Eigen/Core>

#include "drake/solvers/Constraint.h"

namespace drake {
namespace solvers {

MosekLP::MosekLP(int num_variables, int num_constraints,
    std::vector<double> equationScalars,
    Eigen::MatrixXd cons,
    std::vector<MSKboundkeye> mosek_constraint_bounds,
    std::vector<double> upper_constraint_bounds,
    std::vector<double> lower_constraint_bounds,
    std::vector<MSKboundkeye> mosek_variable_bounds,
    std::vector<double> upper_variable_bounds,
    std::vector<double> lower_variable_bounds) {
  numvar_ = num_variables;
  numcon_ = num_constraints;
  env_ = NULL;
  task_ = NULL;
  solutions_.clear();
  r_ = MSK_makeenv(&env_, NULL);
  if (r_ == MSK_RES_OK) {
    // Creates optimization task
    r_ = MSK_maketask(env_, numcon_, numvar_, &task_);
    // Append numcon_ empty constraints
    if (r_ == MSK_RES_OK)
      r_ = MSK_appendcons(task_, numcon_);

    // Append numvar_ variables, initially fixed at zero
    if (r_ == MSK_RES_OK)
      r_ = MSK_appendvars(task_, numvar_);
  }
  // add the equation to maximize to the environment.
  int j = 0;
  for (j = 0; j < numvar_ && r_ == MSK_RES_OK; j++) {
    if (r_ == MSK_RES_OK)
      r_ = MSK_putcj(task_, j, equationScalars[j]);
  }
  AddVariableBounds(mosek_variable_bounds, upper_variable_bounds,
      lower_variable_bounds);
  AddLinearConstraintMatrix(cons);
  AddLinearConstraintBounds(mosek_constraint_bounds, upper_constraint_bounds,
      lower_constraint_bounds);
}

void MosekLP::AddLinearConstraintMatrix(const Eigen::MatrixXd& cons) {
  Eigen::SparseMatrix<double> sparsecons = cons.sparseView();
  // Send the sparse matrix rep into addLinearConstraintSparseColumnMatrix(),
  // which will handle setting the mosek constraints
  MosekLP::AddLinearConstraintSparseColumnMatrix(sparsecons);
}

void MosekLP::AddLinearConstraintSparseColumnMatrix(
    const Eigen::SparseMatrix<double>& sparsecons) {
  int j = 0;  // iterator
  // Define sparse matrix representation to be the same size as the desired
  // constraints
  std::vector<MSKint32t> aptrb;
  std::vector<MSKint32t> aptre;
  std::vector<MSKint32t> asub;
  std::vector<double> aval;

  for (j = 0; j < sparsecons.cols(); j++)
    aptrb.push_back((MSKint32t) sparsecons.outerIndexPtr()[j]);
  for (j = 0; j < sparsecons.cols(); j++)
    aptre.push_back((MSKint32t) sparsecons.outerIndexPtr()[j+1]);
  for (j = 0; j < sparsecons.nonZeros(); j++)
    asub.push_back((MSKint32t) sparsecons.innerIndexPtr()[j]);
  for (j = 0; j < sparsecons.nonZeros(); j++)
    aval.push_back(sparsecons.valuePtr()[j]);

  // following code adapted from http://docs.mosek.com/7.1/capi/Linear_optimization.html
  // check if still working in valid environment
  for (j = 0; j < numvar_ && r_ == MSK_RES_OK; j++) {
    r_ = MSK_putacol(task_,
                    j,
                    aptre[j] - aptrb[j],  // Number of nonzeros in column i
                    &asub[0] + aptrb[j],  // Pointer to row indexes of column i
                    &aval[0] + aptrb[j]);  // pointer to values of column i
  }
}

void MosekLP::AddLinearConstraintBounds(
    const std::vector<MSKboundkeye>& mosek_bounds_,
    const std::vector<double>& upper_bounds_,
    const std::vector<double>& lower_bounds_) {
  int i = 0;
  for (; i < numcon_ && r_ == MSK_RES_OK; i++) {
    r_ = MSK_putconbound(task_, i, mosek_bounds_[i],
                        lower_bounds_[i], upper_bounds_[i]);
  }
}

void MosekLP::AddVariableBounds(const std::vector<MSKboundkeye>& mosek_bounds_,
                                const std::vector<double>& upper_bounds_,
                                const std::vector<double>& lower_bounds_) {
  int j = 0;
  for (; j < numvar_ && r_ == MSK_RES_OK; j++) {
    r_ = MSK_putvarbound(task_, j, mosek_bounds_[j], lower_bounds_[j],
        upper_bounds_[j]);
  }
}

std::vector<MSKboundkeye> MosekLP::FindMosekBounds(
    const std::vector<double>& upper_bounds_,
    const std::vector<double>& lower_bounds_) const {
  assert(upper_bounds_.size() == lower_bounds_.size());
  std::vector<MSKboundkeye> mosek_bounds_;
  unsigned int i = 0;
  for (i = 0; i != upper_bounds_.size(); i++) {
    if (upper_bounds_[i] == +MSK_INFINITY) {
      if (lower_bounds_[i] == -MSK_INFINITY) {
        mosek_bounds_.push_back(MSK_BK_FR);
      } else {
        mosek_bounds_.push_back(MSK_BK_LO);
      }
    } else {
      if (upper_bounds_[i] == lower_bounds_[i]) {
        mosek_bounds_.push_back(MSK_BK_FX);
      } else if (lower_bounds_[i] == -MSK_INFINITY) {
        mosek_bounds_.push_back(MSK_BK_UP);
      } else {
        mosek_bounds_.push_back(MSK_BK_RA);
      }
    }
  }
  return mosek_bounds_;
}

SolutionResult MosekLP::Solve(OptimizationProblem &prog) const {
  // construct an object that calls all the previous work so I can salvage
  // something at least.
  // assume that the problem type is linear currently.
  // TODO(adunyak): Add support for quadratic objective and constraints
  if (!prog.GetSolverOptionsStr("Mosek").empty()) {
    if (prog.GetSolverOptionsStr("Mosek").at("problemtype").find("linear")
        == std::string::npos) {
      return kUnknownError;  // Not a linear optimization
    }
  } else {
      return kUnknownError;
  }
  int totalconnum = 0, i = 0;
  for (auto&& con_ : prog.GetAllLinearConstraints()) {
    // check to see if the constraint references a single variable,
    // which is handles as a variable bound by mosek
    for (i = 0; i < (con_.constraint())->A().rows(); ++i) {
      auto row = (con_.constraint())->A().row(i);
      if (row.nonZeros() != 1)
        totalconnum++;
    }
  }
  Eigen::MatrixXd linear_cons(totalconnum, prog.num_vars());
  std::vector<double> upper_constraint_bounds(totalconnum);
  std::vector<double> lower_constraint_bounds(totalconnum);
  std::vector<MSKboundkeye> mosek_constraint_bounds(totalconnum);
  std::vector<MSKboundkeye> mosek_variable_bounds(prog.num_vars());
  std::vector<double> upper_variable_bounds(numvar_);
  std::vector<double> lower_variable_bounds(numvar_);
  linear_cons.setZero(totalconnum, prog.num_vars());

  // Expect only one boundingbox constraint or no such constraint.
  if (!(prog.bounding_box_constraints().empty())) {
    assert(&(prog.bounding_box_constraints().front()) ==
        &(prog.bounding_box_constraints().back()));
    auto bbox = *(prog.bounding_box_constraints().front().constraint());
    std::vector<double> lower_variable_bounds(bbox.lower_bound().data(),
        bbox.lower_bound().data() +
        bbox.lower_bound().rows() * bbox.lower_bound().cols());
    std::vector<double> upper_variable_bounds(bbox.upper_bound().data(),
        bbox.upper_bound().data() +
        bbox.upper_bound().rows() * bbox.upper_bound().cols());
    for (auto& b : lower_variable_bounds) {
      if (b == -std::numeric_limits<double>::infinity())
        b = -MSK_INFINITY;
    }
    for (auto& b : upper_variable_bounds) {
      if (b == +std::numeric_limits<double>::infinity())
        b = MSK_INFINITY;
    }
    mosek_variable_bounds = FindMosekBounds(upper_variable_bounds,
                                           lower_variable_bounds);
  } else {
    // No bounding box constraint
    for (i = 0; i < numvar_; i++) {
      upper_variable_bounds[i] = +MSK_INFINITY;
      lower_variable_bounds[i] = -MSK_INFINITY;
    }
    mosek_variable_bounds = FindMosekBounds(upper_variable_bounds,
                                            lower_variable_bounds);
  }
  int connum = 0;
  i = 0;
  // TODO(alexdunyak): Allow constraints to affect specific variables
  for (const auto& con : prog.GetAllLinearConstraints()) {
    // con can call functions of  Binding<LinearConstraint>, but the actual
    // type is const std::list<Binding<LinearConstraint>>::const_iterator&
    // Address the constraint matrix directly, translating back to our original
    // variable space
    for (int i = 0; static_cast<unsigned int>(i) <
        con.constraint()->num_constraints(); i++) {
      for (int j = 0; j < (con.constraint())->A().cols(); j++) {
        linear_cons(connum, j) = (con.constraint()->A())(i, j);
      }
      // lower bounds first
      lower_constraint_bounds[connum] =
          (con.constraint())->lower_bound()(i);
      if (lower_constraint_bounds[connum] ==
          -std::numeric_limits<double>::infinity())
        lower_constraint_bounds[connum] = -MSK_INFINITY;
      // upper bound
      upper_constraint_bounds[connum] =
          (con.constraint())->upper_bound()(i);
      if (upper_constraint_bounds[connum] ==
          +std::numeric_limits<double>::infinity())
        upper_constraint_bounds[connum] = +MSK_INFINITY;
      connum++;
    }
  }
  mosek_constraint_bounds = FindMosekBounds(upper_constraint_bounds,
                                            lower_constraint_bounds);
  // find the linear objective here
  LinearConstraint *obj_ = static_cast<LinearConstraint *>(
      (prog.generic_costs().front().constraint()).get());
  std::vector<double> linobj_((*obj_).A().data(),
      (*obj_).A().data() + (*obj_).A().rows() * (*obj_).A().cols());
  MosekLP opt(prog.num_vars(),
              totalconnum,
              linobj_,
              linear_cons,
              mosek_constraint_bounds,
              upper_constraint_bounds,
              lower_constraint_bounds,
              mosek_variable_bounds,
              upper_variable_bounds,
              lower_variable_bounds);
  std::string mom = prog.GetSolverOptionsStr("Mosek").at("maxormin");
  std::string ptype = prog.GetSolverOptionsStr("Mosek").at("problemtype");
  SolutionResult s = opt.OptimizeTask(mom, ptype);
  prog.SetDecisionVariableValues(opt.GetEigenVectorSolutions());
  return s;
}

SolutionResult MosekLP::OptimizeTask(const std::string& maxormin,
                                     const std::string& ptype) {
  solutions_.clear();
  MSKsoltypee problemtype = MSK_SOL_BAS;
  if (ptype.find("quad") != std::string::npos)
    problemtype = MSK_SOL_ITR;
  else if (ptype.find("linear") != std::string::npos)
    problemtype = MSK_SOL_BAS;
  else
    return kUnknownError;
  if (r_ == MSK_RES_OK && maxormin == "max")
    r_ = MSK_putobjsense(task_, MSK_OBJECTIVE_SENSE_MAXIMIZE);
  else if (r_ == MSK_RES_OK && maxormin == "min")
    r_ = MSK_putobjsense(task_, MSK_OBJECTIVE_SENSE_MINIMIZE);
  if (r_ == MSK_RES_OK) {
    MSKrescodee trmcode;

    r_ = MSK_optimizetrm(task_, &trmcode);
    if (r_ == MSK_RES_OK) {
      MSKsolstae solsta;
      if (r_ == MSK_RES_OK) {
        r_ = MSK_getsolsta(task_, problemtype, &solsta);

        switch (solsta) {
          case MSK_SOL_STA_OPTIMAL:
          case MSK_SOL_STA_NEAR_OPTIMAL: {
            std::unique_ptr<double[]> xx(new double[numvar_]);
            if (xx) {
              /* Request the basic solution. */
              MSK_getxx(task_, problemtype, xx.get());
              for (int j = 0; j < numvar_; ++j) {
                solutions_.push_back(xx[j]);
              }
              return kSolutionFound;
            } else {
              r_ = MSK_RES_ERR_SPACE;
              return kUnknownError;
            }
            break;
          }
          case MSK_SOL_STA_DUAL_INFEAS_CER:
          case MSK_SOL_STA_PRIM_INFEAS_CER:
          case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER:
          case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER:
            printf("Primal or dual infeasibility certificate found.\n");
            return kInfeasibleConstraints;
            break;
          case MSK_SOL_STA_UNKNOWN: {
            char symname[MSK_MAX_STR_LEN];
            char desc[MSK_MAX_STR_LEN];

            /* If the solutions status is unknown, print the termination code
               indicating why the optimizer terminated prematurely. */
            MSK_getcodedesc(trmcode, symname, desc);
            printf("The solution status is unknown.\n");
            printf("The optimizer terminitated with code: %s\n", symname);
            break;
          }
          default:
            printf("Other solution status.\n");
            break;
        }
      }
    }
  }
  return kUnknownError;
}

Eigen::VectorXd MosekLP::GetEigenVectorSolutions() const {
  Eigen::VectorXd soln(numvar_);
  if (solutions_.empty())
    return soln;
  unsigned int i = 0;
  for (i = 0; i < solutions_.size(); ++i) {
    soln(i) = solutions_[i];
  }
  return soln.transpose();
}

}  // namespace solvers
}  // namespace drake
<|endoftext|>


<commit_before>#include "mainwindow.hpp"

#include "drape_surface.hpp"

#include <QtWidgets/QWidget>

MainWindow::MainWindow(QWidget *parent)
  : QMainWindow(parent)
  , m_surface(NULL)
{
  resize(1200, 800);
  DrapeSurface * surface = new DrapeSurface();
  m_surface = QWidget::createWindowContainer(surface, this);
  setCentralWidget(m_surface);
}

MainWindow::~MainWindow()
{
  ASSERT(m_surface == NULL, ());
}

void MainWindow::closeEvent(QCloseEvent * closeEvent)
{
  delete m_surface;
  m_surface = NULL;
}
<commit_msg>[drape] request depth buffer for drawable surface<commit_after>#include "mainwindow.hpp"

#include "drape_surface.hpp"

#include <QtWidgets/QWidget>

MainWindow::MainWindow(QWidget *parent)
  : QMainWindow(parent)
  , m_surface(NULL)
{
  resize(1200, 800);

  DrapeSurface * surface = new DrapeSurface();
  QSurfaceFormat format = surface->requestedFormat();
  format.setDepthBufferSize(16);
  surface->setFormat(format);
  m_surface = QWidget::createWindowContainer(surface, this);
  setCentralWidget(m_surface);
}

MainWindow::~MainWindow()
{
  ASSERT(m_surface == NULL, ());
}

void MainWindow::closeEvent(QCloseEvent * closeEvent)
{
  delete m_surface;
  m_surface = NULL;
}
<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Sensics, Inc.
//
// 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.

// Internal Includes
#include "VideoIMUFusionDevice.h"
#include <osvr/AnalysisPluginKit/AnalysisPluginKitC.h>
#include <osvr/ClientKit/InterfaceCallbackC.h>
#include <osvr/ClientKit/InterfaceStateC.h>
#include <osvr/Util/EigenInterop.h>
#include <osvr/Util/Verbosity.h>

// Generated JSON header file
#include "org_osvr_filter_videoimufusion_json.h"

// Library/third-party includes
// - none

// Standard includes
#include <iostream>
#include <cmath>

static const OSVR_ChannelCount FUSED_SENSOR_ID = 0;
static const OSVR_ChannelCount TRANSFORMED_VIDEO_SENSOR_ID = 1;

VideoIMUFusionDevice::VideoIMUFusionDevice(OSVR_PluginRegContext ctx,
                                           std::string const &name,
                                           std::string const &imuPath,
                                           std::string const &videoPath,
                                           VideoIMUFusionParams const &params)
    : m_fusion(params) {
    /// Create the initialization options
    OSVR_DeviceInitOptions opts = osvrDeviceCreateInitOptions(ctx);

    osvrDeviceTrackerConfigure(opts, &m_trackerOut);

    /// Create the device token with the options
    OSVR_DeviceToken dev;
    if (OSVR_RETURN_FAILURE ==
        osvrAnalysisSyncInit(ctx, name.c_str(), opts, &dev, &m_clientCtx)) {
        throw std::runtime_error("Could not initialize analysis plugin!");
    }
    m_dev = osvr::pluginkit::DeviceToken(dev);

    /// Send JSON descriptor
    m_dev.sendJsonDescriptor(org_osvr_filter_videoimufusion_json);

    /// Register update callback
    m_dev.registerUpdateCallback(this);

    /// Set up to receive our input.
    osvrClientGetInterface(m_clientCtx, imuPath.c_str(), &m_imu);
    osvrRegisterOrientationCallback(
        m_imu, &VideoIMUFusionDevice::s_handleIMUData, this);
    osvrRegisterAngularVelocityCallback(
        m_imu, &VideoIMUFusionDevice::s_handleIMUVelocity, this);

    osvrClientGetInterface(m_clientCtx, videoPath.c_str(), &m_videoTracker);

    osvrRegisterPoseCallback(
        m_videoTracker, &VideoIMUFusionDevice::s_handleVideoTrackerData, this);
}

VideoIMUFusionDevice::~VideoIMUFusionDevice() {
    /// free the interfaces before the pointed-to function objects
    /// disappear.
    if (m_imu) {
        osvrClientFreeInterface(m_clientCtx, m_imu);
        m_imu = nullptr;
    }
    if (m_videoTracker) {
        osvrClientFreeInterface(m_clientCtx, m_videoTracker);
        m_imu = nullptr;
    }
}

void VideoIMUFusionDevice::s_handleIMUData(
    void *userdata, const OSVR_TimeValue *timestamp,
    const OSVR_OrientationReport *report) {
    static_cast<VideoIMUFusionDevice *>(userdata)
        ->handleIMUData(*timestamp, *report);
}
void VideoIMUFusionDevice::s_handleIMUVelocity(
    void *userdata, const OSVR_TimeValue *timestamp,
    const OSVR_AngularVelocityReport *report) {
    static_cast<VideoIMUFusionDevice *>(userdata)
        ->handleIMUVelocity(*timestamp, *report);
}
void VideoIMUFusionDevice::s_handleVideoTrackerData(
    void *userdata, const OSVR_TimeValue *timestamp,
    const OSVR_PoseReport *report) {
    static_cast<VideoIMUFusionDevice *>(userdata)
        ->handleVideoTrackerData(*timestamp, *report);
}

void VideoIMUFusionDevice::handleIMUData(const OSVR_TimeValue &timestamp,
                                         const OSVR_OrientationReport &report) {
    m_fusion.handleIMUData(timestamp, report);
    if (m_fusion.running()) {
        sendMainPoseReport();
    }
}
void VideoIMUFusionDevice::handleIMUVelocity(
    const OSVR_TimeValue &timestamp, const OSVR_AngularVelocityReport &report) {

    using namespace osvr::util::eigen_interop;
    Eigen::Quaterniond q = map(report.state.incrementalRotation);
    Eigen::Vector3d rot;
    if (q.w() >= 1. || q.vec().isZero(1e-10)) {
        rot = Eigen::Vector3d::Zero();
    } else {
        auto magnitude = q.vec().blueNorm();
        rot = (q.vec() / magnitude * (2. * std::atan2(magnitude, q.w()))) /
              report.state.dt;
        /// @todo without transformations being applied to vel quats, this
        /// is needed.
        // std::swap(rot[0], rot[1]);
        rot[1] *= -1.;
        rot[2] *= -1.;
    }

    m_fusion.handleIMUVelocity(timestamp, rot);
    if (m_fusion.running()) {
        sendMainPoseReport();
    }
}
void VideoIMUFusionDevice::handleVideoTrackerData(
    const OSVR_TimeValue &timestamp, const OSVR_PoseReport &report) {
    if (!m_fusion.running()) {
        auto ts = OSVR_TimeValue{};
        auto oriState = OSVR_OrientationState{};
        auto ret = osvrGetOrientationState(m_imu, &ts, &oriState);
        if (ret != OSVR_RETURN_SUCCESS) {
            std::cout << "Got a video report before an IMU report, ignoring it"
                      << std::endl;
            return;
        }
        m_fusion.handleVideoTrackerDataDuringStartup(timestamp, report,
                                                     oriState);
        return;
    }
    m_fusion.handleVideoTrackerDataWhileRunning(timestamp, report);
    sendMainPoseReport();
    osvrDeviceTrackerSendPoseTimestamped(
        m_dev, m_trackerOut, &m_fusion.getLatestReorientedVideoPose(),
        TRANSFORMED_VIDEO_SENSOR_ID, &timestamp);
}

void VideoIMUFusionDevice::sendMainPoseReport() {
    osvrDeviceTrackerSendPoseTimestamped(
        m_dev, m_trackerOut, &m_fusion.getLatestFusedPose(), FUSED_SENSOR_ID,
        &m_fusion.getLatestFusedTime());
}
<commit_msg>Alternate method of getting the angular velocity vector out of that incremental quat.<commit_after>/** @file
    @brief Implementation

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Sensics, Inc.
//
// 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.

// Internal Includes
#include "VideoIMUFusionDevice.h"
#include <osvr/AnalysisPluginKit/AnalysisPluginKitC.h>
#include <osvr/ClientKit/InterfaceCallbackC.h>
#include <osvr/ClientKit/InterfaceStateC.h>
#include <osvr/Util/EigenInterop.h>
#include <osvr/Util/Verbosity.h>

// Generated JSON header file
#include "org_osvr_filter_videoimufusion_json.h"

// Library/third-party includes
// - none

// Standard includes
#include <iostream>
#include <cmath>

static const OSVR_ChannelCount FUSED_SENSOR_ID = 0;
static const OSVR_ChannelCount TRANSFORMED_VIDEO_SENSOR_ID = 1;

VideoIMUFusionDevice::VideoIMUFusionDevice(OSVR_PluginRegContext ctx,
                                           std::string const &name,
                                           std::string const &imuPath,
                                           std::string const &videoPath,
                                           VideoIMUFusionParams const &params)
    : m_fusion(params) {
    /// Create the initialization options
    OSVR_DeviceInitOptions opts = osvrDeviceCreateInitOptions(ctx);

    osvrDeviceTrackerConfigure(opts, &m_trackerOut);

    /// Create the device token with the options
    OSVR_DeviceToken dev;
    if (OSVR_RETURN_FAILURE ==
        osvrAnalysisSyncInit(ctx, name.c_str(), opts, &dev, &m_clientCtx)) {
        throw std::runtime_error("Could not initialize analysis plugin!");
    }
    m_dev = osvr::pluginkit::DeviceToken(dev);

    /// Send JSON descriptor
    m_dev.sendJsonDescriptor(org_osvr_filter_videoimufusion_json);

    /// Register update callback
    m_dev.registerUpdateCallback(this);

    /// Set up to receive our input.
    osvrClientGetInterface(m_clientCtx, imuPath.c_str(), &m_imu);
    osvrRegisterOrientationCallback(
        m_imu, &VideoIMUFusionDevice::s_handleIMUData, this);
    osvrRegisterAngularVelocityCallback(
        m_imu, &VideoIMUFusionDevice::s_handleIMUVelocity, this);

    osvrClientGetInterface(m_clientCtx, videoPath.c_str(), &m_videoTracker);

    osvrRegisterPoseCallback(
        m_videoTracker, &VideoIMUFusionDevice::s_handleVideoTrackerData, this);
}

VideoIMUFusionDevice::~VideoIMUFusionDevice() {
    /// free the interfaces before the pointed-to function objects
    /// disappear.
    if (m_imu) {
        osvrClientFreeInterface(m_clientCtx, m_imu);
        m_imu = nullptr;
    }
    if (m_videoTracker) {
        osvrClientFreeInterface(m_clientCtx, m_videoTracker);
        m_imu = nullptr;
    }
}

void VideoIMUFusionDevice::s_handleIMUData(
    void *userdata, const OSVR_TimeValue *timestamp,
    const OSVR_OrientationReport *report) {
    static_cast<VideoIMUFusionDevice *>(userdata)
        ->handleIMUData(*timestamp, *report);
}
void VideoIMUFusionDevice::s_handleIMUVelocity(
    void *userdata, const OSVR_TimeValue *timestamp,
    const OSVR_AngularVelocityReport *report) {
    static_cast<VideoIMUFusionDevice *>(userdata)
        ->handleIMUVelocity(*timestamp, *report);
}
void VideoIMUFusionDevice::s_handleVideoTrackerData(
    void *userdata, const OSVR_TimeValue *timestamp,
    const OSVR_PoseReport *report) {
    static_cast<VideoIMUFusionDevice *>(userdata)
        ->handleVideoTrackerData(*timestamp, *report);
}

void VideoIMUFusionDevice::handleIMUData(const OSVR_TimeValue &timestamp,
                                         const OSVR_OrientationReport &report) {
    m_fusion.handleIMUData(timestamp, report);
    if (m_fusion.running()) {
        sendMainPoseReport();
    }
}
void VideoIMUFusionDevice::handleIMUVelocity(
    const OSVR_TimeValue &timestamp, const OSVR_AngularVelocityReport &report) {

    using namespace osvr::util::eigen_interop;
    Eigen::Quaterniond q = map(report.state.incrementalRotation);
    Eigen::Vector3d rot;
    if (q.w() >= 1. || q.vec().isZero(1e-10)) {
        rot = Eigen::Vector3d::Zero();
    } else {
#if 0
        auto magnitude = q.vec().blueNorm();
        rot = (q.vec() / magnitude * (2. * std::atan2(magnitude, q.w()))) /
              report.state.dt;
        /// @todo without transformations being applied to vel quats, this
        /// is needed.
        // std::swap(rot[0], rot[1]);
        rot[1] *= -1.;
        rot[2] *= -1.;
#else
        auto angle = std::acos(q.w());
        rot = q.vec().normalized() * angle * 2 / report.state.dt;

        /// @todo without transformations being applied to vel quats, this
        /// is needed.
        rot[1] *= -1.;
        rot[2] *= -1.;
#endif
    }

    m_fusion.handleIMUVelocity(timestamp, rot);
    if (m_fusion.running()) {
        sendMainPoseReport();
    }
}
void VideoIMUFusionDevice::handleVideoTrackerData(
    const OSVR_TimeValue &timestamp, const OSVR_PoseReport &report) {
    if (!m_fusion.running()) {
        auto ts = OSVR_TimeValue{};
        auto oriState = OSVR_OrientationState{};
        auto ret = osvrGetOrientationState(m_imu, &ts, &oriState);
        if (ret != OSVR_RETURN_SUCCESS) {
            std::cout << "Got a video report before an IMU report, ignoring it"
                      << std::endl;
            return;
        }
        m_fusion.handleVideoTrackerDataDuringStartup(timestamp, report,
                                                     oriState);
        return;
    }
    m_fusion.handleVideoTrackerDataWhileRunning(timestamp, report);
    sendMainPoseReport();
    osvrDeviceTrackerSendPoseTimestamped(
        m_dev, m_trackerOut, &m_fusion.getLatestReorientedVideoPose(),
        TRANSFORMED_VIDEO_SENSOR_ID, &timestamp);
}

void VideoIMUFusionDevice::sendMainPoseReport() {
    osvrDeviceTrackerSendPoseTimestamped(
        m_dev, m_trackerOut, &m_fusion.getLatestFusedPose(), FUSED_SENSOR_ID,
        &m_fusion.getLatestFusedTime());
}
<|endoftext|>


<commit_before>// [WriteFile Name=ConfigureSubnetworkTrace, Category=Analysis]
// [Legal]
// Copyright 2020 Esri.

// 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.
// [Legal]

#ifdef PCH_BUILD
#include "pch.hpp"
#endif // PCH_BUILD

#include "ConfigureSubnetworkTrace.h"

#include "CodedValueDomain.h"
#include "TaskWatcher.h"
#include "UtilityAssetGroup.h"
#include "UtilityAssetType.h"
#include "UtilityCategory.h"
#include "UtilityCategoryComparison.h"
#include "UtilityDomainNetwork.h"
#include "UtilityElement.h"
#include "UtilityElementTraceResult.h"
#include "UtilityNetwork.h"
#include "UtilityNetworkDefinition.h"
#include "UtilityNetworkSource.h"
#include "UtilityNetworkTypes.h"
#include "UtilityTerminal.h"
#include "UtilityTerminalConfiguration.h"
#include "UtilityTier.h"
#include "UtilityTraceAndCondition.h"
#include "UtilityTraceConfiguration.h"
#include "UtilityTraceOrCondition.h"
#include "UtilityTraceParameters.h"
#include "UtilityTraceResultListModel.h"
#include "UtilityTraversability.h"

#include <QQmlEngine>
#include <algorithm>

using namespace Esri::ArcGISRuntime;

ConfigureSubnetworkTrace::ConfigureSubnetworkTrace(QObject* parent /* = nullptr */):
  QObject(parent)
{
  m_utilityNetwork = new UtilityNetwork(m_featureLayerUrl, this);

  connect(m_utilityNetwork, &UtilityNetwork::doneLoading, this, &ConfigureSubnetworkTrace::onUtilityNetworkLoaded);

  connect(m_utilityNetwork, &UtilityNetwork::traceCompleted, this, &ConfigureSubnetworkTrace::onTraceCompleted);

  m_utilityNetwork->load();
}

QString ConfigureSubnetworkTrace::expressionToString(UtilityTraceConditionalExpression* expression)
{
  switch (expression->traceConditionType())
  {
    case UtilityTraceConditionType::UtilityNetworkAttributeComparison:
    {
      const UtilityNetworkAttributeComparison* attributeExpression = static_cast<UtilityNetworkAttributeComparison*>(expression);
      const UtilityNetworkAttribute* networkAttribute = attributeExpression->networkAttribute();
      const UtilityNetworkAttribute* otherNetworkAttribute = attributeExpression->otherNetworkAttribute();
      const Domain networkDomain = networkAttribute->domain();
      const QString operatorAsString = comparisonOperatorToString(attributeExpression->comparisonOperator());

      // check if attribute domain is a coded value domain.
      if (!networkDomain.isEmpty() && (networkDomain.domainType() == DomainType::CodedValueDomain))
      {
        const CodedValueDomain codedValueDomain = static_cast<CodedValueDomain>(networkDomain);
        const QList<CodedValue> codedValues = codedValueDomain.codedValues();

        // get the coded value using the value as the index for the list of coded values
        const QString codedValueName = codedValues[attributeExpression->value().toInt()].name();

        return QString("`%1` %2 `%3`").arg(networkAttribute->name(), operatorAsString, codedValueName);
      }
      else
      {
        if (otherNetworkAttribute)
        {
          return QString("`%1` %2 `%3`").arg(networkAttribute->name(), operatorAsString, otherNetworkAttribute->name());
        }
        return QString("`%1` %2 `%3`").arg(networkAttribute->name(), operatorAsString, attributeExpression->value().toString());
      }
    }
    case UtilityTraceConditionType::UtilityCategoryComparison:
    {
      const UtilityCategoryComparison* comparisonExpression = static_cast<UtilityCategoryComparison*>(expression);

      return QString("`%1` %2").arg(comparisonExpression->category()->name(), (comparisonExpression->comparisonOperator() == UtilityCategoryComparisonOperator::Exists) ? "Exists" : "DoesNotExist");
    }
    case UtilityTraceConditionType::UtilityTraceAndCondition:
    {
      const UtilityTraceAndCondition* andExpression = static_cast<UtilityTraceAndCondition*>(expression);

      return QString("(%1) AND\n (%2)").arg(expressionToString(andExpression->leftExpression()), expressionToString(andExpression->rightExpression()));
    }
    case UtilityTraceConditionType::UtilityTraceOrCondition:
    {
      const UtilityTraceOrCondition* orExpression = static_cast<UtilityTraceOrCondition*>(expression);
      return QString("(%1) OR\n (%2)").arg(expressionToString(orExpression->leftExpression()), expressionToString(orExpression->rightExpression()));
    }
    default:
      return QString("Unknown trace conditional expression");
  }
}

QString ConfigureSubnetworkTrace::comparisonOperatorToString(const UtilityAttributeComparisonOperator& comparisonOperator)
{
  switch (comparisonOperator)
  {
    case UtilityAttributeComparisonOperator::Equal:
      return QString("Equal");
    case UtilityAttributeComparisonOperator::NotEqual:
      return QString("NotEqual");
    case UtilityAttributeComparisonOperator::GreaterThan:
      return QString("GreaterThan");
    case UtilityAttributeComparisonOperator::GreaterThanEqual:
      return QString("GreaterThanEqual");
    case UtilityAttributeComparisonOperator::LessThan:
      return QString("LessThan");
    case UtilityAttributeComparisonOperator::LessThanEqual:
      return QString("LessThanEqual");
    case UtilityAttributeComparisonOperator::IncludesTheValues:
      return QString("IncludesTheValues");
    case UtilityAttributeComparisonOperator::DoesNotIncludeTheValues:
      return QString("DoesNotIncludeTheValues");
    case UtilityAttributeComparisonOperator::IncludesAny:
      return QString("IncludesAny");
    case UtilityAttributeComparisonOperator::DoesNotIncludeAny:
      return QString("DoesNotIncludeAny");
    default:
      return QString("Unknown comparison operator");
  }
}

QVariant ConfigureSubnetworkTrace::convertToDataType(const QVariant& value, const Esri::ArcGISRuntime::UtilityNetworkAttributeDataType& dataType)
{
  switch (dataType)
  {
    case UtilityNetworkAttributeDataType::Integer:
    {
      // inconsistent results when using QVariant.toInt() on a
      // QString that doesn't contain an Integer dataType.
      // e.g. QVariant(QString("123.321")).toInt();
      return static_cast<int>(value.toDouble());
    }
    case UtilityNetworkAttributeDataType::Float:
    {
      return value.toFloat();
    }
    case UtilityNetworkAttributeDataType::Double:
    {
      return value.toDouble();
    }
    case UtilityNetworkAttributeDataType::Boolean:
    {
      return value.toBool();
    }
    default:
      return QVariant();
  }
}

void ConfigureSubnetworkTrace::codedValueOrInputText(const QString& currentText)
{
  // Update the UI to show the correct value entry for the attribute.
  if (m_networkDefinition)
  {
    const Domain domain = m_networkDefinition->networkAttribute(currentText)->domain();
    if (!domain.isEmpty() && (domain.domainType() == DomainType::CodedValueDomain))
    {
      m_valueSelectionListModel.clear();
      const CodedValueDomain codedValueDomain = static_cast<CodedValueDomain>(domain);

      for (CodedValue codedValue: codedValueDomain.codedValues())
        m_valueSelectionListModel.append(codedValue.name());

      m_textFieldVisible = false;
    }
    else
    {
      m_textFieldVisible = true;
    }
    emit valueSelectionListModelChanged();
    emit textFieldVisibleChanged();
  }
}

void ConfigureSubnetworkTrace::addCondition(const QString& selectedAttribute, int selectedOperator, const QVariant& selectedValue)
{
  // NOTE: You may also create a UtilityCategoryComparison with UtilityNetworkDefinition.Categories and UtilityCategoryComparisonOperator.

  UtilityNetworkAttribute* selectedNetworkAttribute = m_networkDefinition->networkAttribute(selectedAttribute);
  const QVariant convertedSelectedValue = convertToDataType(selectedValue, selectedNetworkAttribute->dataType());

  if (convertedSelectedValue.isNull())
  {
    m_dialogText = "Unknow network attribute data type";
    emit dialogTextChanged();
    emit showDialog();
    return;
  }

  const UtilityAttributeComparisonOperator selectedOperatorEnum = static_cast<UtilityAttributeComparisonOperator>(selectedOperator);

  // NOTE: You may also create a UtilityNetworkAttributeComparison with another NetworkAttribute.
  UtilityTraceConditionalExpression* expression = new UtilityNetworkAttributeComparison(selectedNetworkAttribute, selectedOperatorEnum, convertedSelectedValue, this);

  UtilityTraceConditionalExpression* otherExpression = static_cast<UtilityTraceConditionalExpression*>(m_traceConfiguration->traversability()->barriers());

  // NOTE: You may also combine expressions with UtilityTraceAndCondition
  UtilityTraceConditionalExpression* combineExpressions = new UtilityTraceOrCondition(otherExpression, expression, this);

  m_expressionBuilder = expressionToString(combineExpressions);
  emit expressionBuilderChanged();

  m_traceConfiguration->traversability()->setBarriers(combineExpressions);
}

void ConfigureSubnetworkTrace::changeIncludeBarriersState(bool includeBarriers)
{
  m_traceConfiguration->setIncludeBarriers(includeBarriers);
}

void ConfigureSubnetworkTrace::changeIncludeContainersState(bool includeContainers)
{
  m_traceConfiguration->setIncludeContainers(includeContainers);
}

void ConfigureSubnetworkTrace::reset()
{
  // Reset the barrier condition to the initial value.
  m_traceConfiguration->traversability()->setBarriers(m_initialExpression);
  m_expressionBuilder.clear();
  m_expressionBuilder = expressionToString(static_cast<UtilityTraceConditionalExpression*>(m_initialExpression));
  emit expressionBuilderChanged();
}

void ConfigureSubnetworkTrace::trace()
{
  if (!m_utilityNetwork || !m_utilityElementStartingLocation)
  {
    return;
  }

  m_busy = true;
  emit busyChanged();
  const QList<UtilityElement*> startingLocations {m_utilityElementStartingLocation};
  // Create utility trace parameters for the starting location.
  m_traceParams = new UtilityTraceParameters(UtilityTraceType::Subnetwork, startingLocations, this);
  m_traceParams->setTraceConfiguration(m_traceConfiguration);

  // trace the network
  m_utilityNetwork->trace(m_traceParams);
}

void ConfigureSubnetworkTrace::onTraceCompleted()
{
  if (m_utilityNetwork->traceResult()->isEmpty())
  {
    m_dialogText = "No results returned";
    emit dialogTextChanged();
    emit showDialog();
  }
  // Get the first result.
  UtilityTraceResult* result = m_utilityNetwork->traceResult()->at(0);

  const QList<UtilityElement*> elements = static_cast<UtilityElementTraceResult*>(result)->elements(this);

  // Display the number of elements found by the trace.
  m_dialogText = QString("%1 elements found.").arg(elements.length());
  m_busy = false;
  emit dialogTextChanged();
  emit showDialog();
  emit busyChanged();
}

void ConfigureSubnetworkTrace::onUtilityNetworkLoaded(const Error& e)
{
  if (!e.isEmpty())
  {
    m_dialogText = QString("%1 - %2").arg(e.message(), e.additionalMessage());
    m_busy = false;
    emit dialogTextChanged();
    emit showDialog();
    emit busyChanged();
    return;
  }

  m_busy = false;
  emit busyChanged();
  m_networkDefinition = m_utilityNetwork->definition();

  // Build the choice lists for network attribute comparison.
  for (UtilityNetworkAttribute* networkAttribute : m_networkDefinition->networkAttributes())
  {
    if (!networkAttribute->isSystemDefined())
      m_attributeListModel.append(networkAttribute->name());
  }
  emit attributeListModelChanged();

  // Create a default starting location.
  const UtilityNetworkSource* networkSource = m_networkDefinition->networkSource(m_deviceTableName);
  const UtilityAssetGroup* assetGroup = networkSource->assetGroup(m_assetGroupName);
  UtilityAssetType* assetType = assetGroup->assetType(m_assetTypeName);
  m_utilityElementStartingLocation = m_utilityNetwork->createElementWithAssetType(assetType, m_gloabId);

  QList<UtilityTerminal*> terminals = m_utilityElementStartingLocation->assetType()->terminalConfiguration()->terminals();

  // Set the terminal for this location. (For our case, we use the 'Load' terminal.)
  auto terminal = std::find_if(terminals.begin(), terminals.end(), [](UtilityTerminal* terminal)
  {
      return terminal->name() == "Load";
  });

  m_utilityElementStartingLocation->setTerminal(static_cast<UtilityTerminal*>(*terminal));

  // Get a default trace configuration from a tier to update the UI.
  const UtilityDomainNetwork* domainNetwork = m_networkDefinition->domainNetwork(m_domainNetworkName);
  const UtilityTier* utilityTierSource = domainNetwork->tier(m_tierName);

  // Set the trace configuration.
  m_traceConfiguration = utilityTierSource->traceConfiguration();

  m_initialExpression = m_traceConfiguration->traversability()->barriers();

  if (m_initialExpression)
  {
    m_expressionBuilder = expressionToString(static_cast<UtilityTraceConditionalExpression*>(m_initialExpression));
    emit expressionBuilderChanged();
  }

  // Set the traversability scope.
  utilityTierSource->traceConfiguration()->traversability()->setScope(UtilityTraversabilityScope::Junctions);
}

ConfigureSubnetworkTrace::~ConfigureSubnetworkTrace() = default;

void ConfigureSubnetworkTrace::init()
{
  qmlRegisterType<ConfigureSubnetworkTrace>("Esri.Samples", 1, 0, "ConfigureSubnetworkTraceSample");
}
<commit_msg>adding checks and return<commit_after>// [WriteFile Name=ConfigureSubnetworkTrace, Category=Analysis]
// [Legal]
// Copyright 2020 Esri.

// 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.
// [Legal]

#ifdef PCH_BUILD
#include "pch.hpp"
#endif // PCH_BUILD

#include "ConfigureSubnetworkTrace.h"

#include "CodedValueDomain.h"
#include "TaskWatcher.h"
#include "UtilityAssetGroup.h"
#include "UtilityAssetType.h"
#include "UtilityCategory.h"
#include "UtilityCategoryComparison.h"
#include "UtilityDomainNetwork.h"
#include "UtilityElement.h"
#include "UtilityElementTraceResult.h"
#include "UtilityNetwork.h"
#include "UtilityNetworkDefinition.h"
#include "UtilityNetworkSource.h"
#include "UtilityNetworkTypes.h"
#include "UtilityTerminal.h"
#include "UtilityTerminalConfiguration.h"
#include "UtilityTier.h"
#include "UtilityTraceAndCondition.h"
#include "UtilityTraceConfiguration.h"
#include "UtilityTraceOrCondition.h"
#include "UtilityTraceParameters.h"
#include "UtilityTraceResultListModel.h"
#include "UtilityTraversability.h"

#include <QQmlEngine>
#include <algorithm>

using namespace Esri::ArcGISRuntime;

ConfigureSubnetworkTrace::ConfigureSubnetworkTrace(QObject* parent /* = nullptr */):
  QObject(parent)
{
  m_utilityNetwork = new UtilityNetwork(m_featureLayerUrl, this);

  connect(m_utilityNetwork, &UtilityNetwork::doneLoading, this, &ConfigureSubnetworkTrace::onUtilityNetworkLoaded);

  connect(m_utilityNetwork, &UtilityNetwork::traceCompleted, this, &ConfigureSubnetworkTrace::onTraceCompleted);

  m_utilityNetwork->load();
}

QString ConfigureSubnetworkTrace::expressionToString(UtilityTraceConditionalExpression* expression)
{
  switch (expression->traceConditionType())
  {
    case UtilityTraceConditionType::UtilityNetworkAttributeComparison:
    {
      const UtilityNetworkAttributeComparison* attributeExpression = static_cast<UtilityNetworkAttributeComparison*>(expression);
      const UtilityNetworkAttribute* networkAttribute = attributeExpression->networkAttribute();
      const UtilityNetworkAttribute* otherNetworkAttribute = attributeExpression->otherNetworkAttribute();
      const Domain networkDomain = networkAttribute->domain();
      const QString operatorAsString = comparisonOperatorToString(attributeExpression->comparisonOperator());

      // check if attribute domain is a coded value domain.
      if (!networkDomain.isEmpty() && (networkDomain.domainType() == DomainType::CodedValueDomain))
      {
        const CodedValueDomain codedValueDomain = static_cast<CodedValueDomain>(networkDomain);
        const QList<CodedValue> codedValues = codedValueDomain.codedValues();

        // get the coded value using the value as the index for the list of coded values
        const QString codedValueName = codedValues[attributeExpression->value().toInt()].name();

        return QString("`%1` %2 `%3`").arg(networkAttribute->name(), operatorAsString, codedValueName);
      }
      else
      {
        if (otherNetworkAttribute)
        {
          return QString("`%1` %2 `%3`").arg(networkAttribute->name(), operatorAsString, otherNetworkAttribute->name());
        }
        return QString("`%1` %2 `%3`").arg(networkAttribute->name(), operatorAsString, attributeExpression->value().toString());
      }
    }
    case UtilityTraceConditionType::UtilityCategoryComparison:
    {
      const UtilityCategoryComparison* comparisonExpression = static_cast<UtilityCategoryComparison*>(expression);

      return QString("`%1` %2").arg(comparisonExpression->category()->name(), (comparisonExpression->comparisonOperator() == UtilityCategoryComparisonOperator::Exists) ? "Exists" : "DoesNotExist");
    }
    case UtilityTraceConditionType::UtilityTraceAndCondition:
    {
      const UtilityTraceAndCondition* andExpression = static_cast<UtilityTraceAndCondition*>(expression);

      return QString("(%1) AND\n (%2)").arg(expressionToString(andExpression->leftExpression()), expressionToString(andExpression->rightExpression()));
    }
    case UtilityTraceConditionType::UtilityTraceOrCondition:
    {
      const UtilityTraceOrCondition* orExpression = static_cast<UtilityTraceOrCondition*>(expression);
      return QString("(%1) OR\n (%2)").arg(expressionToString(orExpression->leftExpression()), expressionToString(orExpression->rightExpression()));
    }
    default:
      return QString("Unknown trace conditional expression");
  }
}

QString ConfigureSubnetworkTrace::comparisonOperatorToString(const UtilityAttributeComparisonOperator& comparisonOperator)
{
  switch (comparisonOperator)
  {
    case UtilityAttributeComparisonOperator::Equal:
      return QString("Equal");
    case UtilityAttributeComparisonOperator::NotEqual:
      return QString("NotEqual");
    case UtilityAttributeComparisonOperator::GreaterThan:
      return QString("GreaterThan");
    case UtilityAttributeComparisonOperator::GreaterThanEqual:
      return QString("GreaterThanEqual");
    case UtilityAttributeComparisonOperator::LessThan:
      return QString("LessThan");
    case UtilityAttributeComparisonOperator::LessThanEqual:
      return QString("LessThanEqual");
    case UtilityAttributeComparisonOperator::IncludesTheValues:
      return QString("IncludesTheValues");
    case UtilityAttributeComparisonOperator::DoesNotIncludeTheValues:
      return QString("DoesNotIncludeTheValues");
    case UtilityAttributeComparisonOperator::IncludesAny:
      return QString("IncludesAny");
    case UtilityAttributeComparisonOperator::DoesNotIncludeAny:
      return QString("DoesNotIncludeAny");
    default:
      return QString("Unknown comparison operator");
  }
}

QVariant ConfigureSubnetworkTrace::convertToDataType(const QVariant& value, const Esri::ArcGISRuntime::UtilityNetworkAttributeDataType& dataType)
{
  switch (dataType)
  {
    case UtilityNetworkAttributeDataType::Integer:
    {
      // inconsistent results when using QVariant.toInt() on a
      // QString that doesn't contain an Integer dataType.
      // e.g. QVariant(QString("123.321")).toInt();
      return static_cast<int>(value.toDouble());
    }
    case UtilityNetworkAttributeDataType::Float:
    {
      return value.toFloat();
    }
    case UtilityNetworkAttributeDataType::Double:
    {
      return value.toDouble();
    }
    case UtilityNetworkAttributeDataType::Boolean:
    {
      return value.toBool();
    }
    default:
      return QVariant();
  }
}

void ConfigureSubnetworkTrace::codedValueOrInputText(const QString& currentText)
{
  // Update the UI to show the correct value entry for the attribute.
  if (m_networkDefinition)
  {
    const Domain domain = m_networkDefinition->networkAttribute(currentText)->domain();
    if (!domain.isEmpty() && (domain.domainType() == DomainType::CodedValueDomain))
    {
      m_valueSelectionListModel.clear();
      const CodedValueDomain codedValueDomain = static_cast<CodedValueDomain>(domain);

      for (CodedValue codedValue: codedValueDomain.codedValues())
        m_valueSelectionListModel.append(codedValue.name());

      m_textFieldVisible = false;
    }
    else
    {
      m_textFieldVisible = true;
    }
    emit valueSelectionListModelChanged();
    emit textFieldVisibleChanged();
  }
}

void ConfigureSubnetworkTrace::addCondition(const QString& selectedAttribute, int selectedOperator, const QVariant& selectedValue)
{
  // NOTE: You may also create a UtilityCategoryComparison with UtilityNetworkDefinition.Categories and UtilityCategoryComparisonOperator.

  UtilityNetworkAttribute* selectedNetworkAttribute = m_networkDefinition->networkAttribute(selectedAttribute);
  const QVariant convertedSelectedValue = convertToDataType(selectedValue, selectedNetworkAttribute->dataType());

  if (convertedSelectedValue.isNull())
  {
    m_dialogText = "Unknow network attribute data type";
    emit dialogTextChanged();
    emit showDialog();
    return;
  }

  const UtilityAttributeComparisonOperator selectedOperatorEnum = static_cast<UtilityAttributeComparisonOperator>(selectedOperator);

  // NOTE: You may also create a UtilityNetworkAttributeComparison with another NetworkAttribute.
  UtilityTraceConditionalExpression* expression = new UtilityNetworkAttributeComparison(selectedNetworkAttribute, selectedOperatorEnum, convertedSelectedValue, this);

  UtilityTraceConditionalExpression* otherExpression = static_cast<UtilityTraceConditionalExpression*>(m_traceConfiguration->traversability()->barriers());

  // NOTE: You may also combine expressions with UtilityTraceAndCondition
  UtilityTraceConditionalExpression* combineExpressions = new UtilityTraceOrCondition(otherExpression, expression, this);

  m_expressionBuilder = expressionToString(combineExpressions);
  emit expressionBuilderChanged();

  if (m_traceConfiguration)
    m_traceConfiguration->traversability()->setBarriers(combineExpressions);
}

void ConfigureSubnetworkTrace::changeIncludeBarriersState(bool includeBarriers)
{
  if (m_traceConfiguration)
    m_traceConfiguration->setIncludeBarriers(includeBarriers);
}

void ConfigureSubnetworkTrace::changeIncludeContainersState(bool includeContainers)
{
  if (m_traceConfiguration)
    m_traceConfiguration->setIncludeContainers(includeContainers);
}

void ConfigureSubnetworkTrace::reset()
{
  // Reset the barrier condition to the initial value.
  m_traceConfiguration->traversability()->setBarriers(m_initialExpression);
  m_expressionBuilder.clear();
  m_expressionBuilder = expressionToString(static_cast<UtilityTraceConditionalExpression*>(m_initialExpression));
  emit expressionBuilderChanged();
}

void ConfigureSubnetworkTrace::trace()
{
  if (!m_utilityNetwork || !m_utilityElementStartingLocation)
  {
    return;
  }

  m_busy = true;
  emit busyChanged();
  const QList<UtilityElement*> startingLocations {m_utilityElementStartingLocation};
  // Create utility trace parameters for the starting location.
  m_traceParams = new UtilityTraceParameters(UtilityTraceType::Subnetwork, startingLocations, this);
  m_traceParams->setTraceConfiguration(m_traceConfiguration);

  // trace the network
  m_utilityNetwork->trace(m_traceParams);
}

void ConfigureSubnetworkTrace::onTraceCompleted()
{
  if (m_utilityNetwork->traceResult()->isEmpty())
  {
    m_dialogText = "No results returned";
    emit dialogTextChanged();
    emit showDialog();
    return;
  }
  // Get the first result.
  UtilityTraceResult* result = m_utilityNetwork->traceResult()->at(0);

  const QList<UtilityElement*> elements = static_cast<UtilityElementTraceResult*>(result)->elements(this);

  // Display the number of elements found by the trace.
  m_dialogText = QString("%1 elements found.").arg(elements.length());
  m_busy = false;
  emit dialogTextChanged();
  emit showDialog();
  emit busyChanged();
}

void ConfigureSubnetworkTrace::onUtilityNetworkLoaded(const Error& e)
{
  if (!e.isEmpty())
  {
    m_dialogText = QString("%1 - %2").arg(e.message(), e.additionalMessage());
    m_busy = false;
    emit dialogTextChanged();
    emit showDialog();
    emit busyChanged();
    return;
  }

  m_busy = false;
  emit busyChanged();
  m_networkDefinition = m_utilityNetwork->definition();

  // Build the choice lists for network attribute comparison.
  for (UtilityNetworkAttribute* networkAttribute : m_networkDefinition->networkAttributes())
  {
    if (!networkAttribute->isSystemDefined())
      m_attributeListModel.append(networkAttribute->name());
  }
  emit attributeListModelChanged();

  // Create a default starting location.
  const UtilityNetworkSource* networkSource = m_networkDefinition->networkSource(m_deviceTableName);
  const UtilityAssetGroup* assetGroup = networkSource->assetGroup(m_assetGroupName);
  UtilityAssetType* assetType = assetGroup->assetType(m_assetTypeName);
  m_utilityElementStartingLocation = m_utilityNetwork->createElementWithAssetType(assetType, m_gloabId);

  QList<UtilityTerminal*> terminals = m_utilityElementStartingLocation->assetType()->terminalConfiguration()->terminals();

  // Set the terminal for this location. (For our case, we use the 'Load' terminal.)
  auto terminal = std::find_if(terminals.begin(), terminals.end(), [](UtilityTerminal* terminal)
  {
      return terminal->name() == "Load";
  });

  m_utilityElementStartingLocation->setTerminal(static_cast<UtilityTerminal*>(*terminal));

  // Get a default trace configuration from a tier to update the UI.
  const UtilityDomainNetwork* domainNetwork = m_networkDefinition->domainNetwork(m_domainNetworkName);
  const UtilityTier* utilityTierSource = domainNetwork->tier(m_tierName);

  // Set the trace configuration.
  m_traceConfiguration = utilityTierSource->traceConfiguration();

  m_initialExpression = m_traceConfiguration->traversability()->barriers();

  if (m_initialExpression)
  {
    m_expressionBuilder = expressionToString(static_cast<UtilityTraceConditionalExpression*>(m_initialExpression));
    emit expressionBuilderChanged();
  }

  // Set the traversability scope.
  utilityTierSource->traceConfiguration()->traversability()->setScope(UtilityTraversabilityScope::Junctions);
}

ConfigureSubnetworkTrace::~ConfigureSubnetworkTrace() = default;

void ConfigureSubnetworkTrace::init()
{
  qmlRegisterType<ConfigureSubnetworkTrace>("Esri.Samples", 1, 0, "ConfigureSubnetworkTraceSample");
}
<|endoftext|>


<commit_before>/*************************************************************************
                           E12  -  Etat de l'analyseur
                             -------------------
    début                : 8 mars 2016 10:43:21
    copyright            : (C) 2016 par H4112
*************************************************************************/

//---------- Réalisation de la classe <E12> (fichier E12.cpp) --

//---------------------------------------------------------------- INCLUDE

//-------------------------------------------------------- Include système
#include <iostream>
using namespace std;

//------------------------------------------------------ Include personnel
#include "E12.h"

//------------------------------------------------------------- Constantes

//---------------------------------------------------- Variables de classe

//----------------------------------------------------------- Types privés

//----------------------------------------------------------------- PUBLIC
//-------------------------------------------------------- Fonctions amies

//----------------------------------------------------- Méthodes publiques
void E12::Print ( ) const
{
	cout << "E12" << endl;
}

bool E12::Transition ( Automate & automate, Symbole * s )
{
	switch(*s)
	{
		case VIRGULE:
		case POINT_VIRGULE:
		{
			Symbole * id = automate.PopSymbole();

			Symbole * nouveauSymbole;
			//TODO remplir cette variable pour réduire R6
			automate.Reduction(nouveauSymbole, 1);
			return true;
		}
	}

	return false;
}

//------------------------------------------------- Surcharge d'opérateurs

//-------------------------------------------- Constructeurs - destructeur
E12::E12 ( const E12 & unE12 )
	: Etat ( unE12 )
{
#ifdef MAP
    cout << "Appel au constructeur de copie de <E12>" << endl;
#endif
} //----- Fin de E12 (constructeur de copie)

E12::E12 ( )
	: Etat ( )
{
#ifdef MAP
    cout << "Appel au constructeur de <E12>" << endl;
#endif
} //----- Fin de E12

E12::~E12 ( )
{
#ifdef MAP
    cout << "Appel au destructeur de <E12>" << endl;
#endif
} //----- Fin de ~E12

//------------------------------------------------------------------ PRIVE

//----------------------------------------------------- Méthodes protégées

//------------------------------------------------------- Méthodes privées
<commit_msg>État E12<commit_after>/*************************************************************************
                           E12  -  Etat de l'analyseur
                             -------------------
    début                : 8 mars 2016 10:43:21
    copyright            : (C) 2016 par H4112
*************************************************************************/

//---------- Réalisation de la classe <E12> (fichier E12.cpp) --

//---------------------------------------------------------------- INCLUDE

//-------------------------------------------------------- Include système
#include <iostream>
using namespace std;

//------------------------------------------------------ Include personnel
#include "E12.h"

#include "../symboles/ListeIdentifiants.h"
#include "../symboles/Identifiant.h"

//------------------------------------------------------------- Constantes

//---------------------------------------------------- Variables de classe

//----------------------------------------------------------- Types privés

//----------------------------------------------------------------- PUBLIC
//-------------------------------------------------------- Fonctions amies

//----------------------------------------------------- Méthodes publiques
void E12::Print ( ) const
{
	cout << "E12" << endl;
}

bool E12::Transition ( Automate & automate, Symbole * s )
{
	switch(*s)
	{
		case VIRGULE:
		case POINT_VIRGULE:
		{
			Identifiant * id = (Identifiant *) automate.PopSymbole();

			ListeIdentifiants * lid = new ListeIdentifiants();
			lid->AjouterVariable(id);

			delete id;

			//réduire R6
			automate.Reduction(lid, 1);
			return true;
		}
	}

	return false;
}

//------------------------------------------------- Surcharge d'opérateurs

//-------------------------------------------- Constructeurs - destructeur
E12::E12 ( const E12 & unE12 )
	: Etat ( unE12 )
{
#ifdef MAP
    cout << "Appel au constructeur de copie de <E12>" << endl;
#endif
} //----- Fin de E12 (constructeur de copie)

E12::E12 ( )
	: Etat ( )
{
#ifdef MAP
    cout << "Appel au constructeur de <E12>" << endl;
#endif
} //----- Fin de E12

E12::~E12 ( )
{
#ifdef MAP
    cout << "Appel au destructeur de <E12>" << endl;
#endif
} //----- Fin de ~E12

//------------------------------------------------------------------ PRIVE

//----------------------------------------------------- Méthodes protégées

//------------------------------------------------------- Méthodes privées
<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/celltypes.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

bool check_label(bool &active, std::string run_from, std::string run_to, std::string label)
{
	if (!run_from.empty() && run_from == run_to) {
		active = (label == run_from);
	} else {
		if (label == run_from)
			active = true;
		if (label == run_to)
			active = false;
	}
	return active;
}

struct SynthPass : public Pass {
	SynthPass() : Pass("synth", "generic synthesis script") { }
	virtual void help()
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    synth [options]\n");
		log("\n");
		log("This command runs the default synthesis script. This command does not operate\n");
		log("on partly selected designs.\n");
		log("\n");
		log("    -top <module>\n");
		log("        use the specified module as top module (default='top')\n");
		log("\n");
		log("    -encfile <file>\n");
		log("        passed to 'fsm_recode' via 'fsm'\n");
		log("\n");
		log("    -noabc\n");
		log("        do not run abc (as if yosys was compiled without ABC support)\n");
		log("\n");
		log("    -run <from_label>[:<to_label>]\n");
		log("        only run the commands between the labels (see below). an empty\n");
		log("        from label is synonymous to 'begin', and empty to label is\n");
		log("        synonymous to the end of the command list.\n");
		log("\n");
		log("\n");
		log("The following commands are executed by this synthesis command:\n");
		log("\n");
		log("    begin:\n");
		log("        hierarchy -check [-top <top>]\n");
		log("\n");
		log("    coarse:\n");
		log("        proc\n");
		log("        opt_clean\n");
		log("        check\n");
		log("        opt\n");
		log("        wreduce\n");
		log("        alumacc\n");
		log("        share\n");
		log("        opt\n");
		log("        fsm\n");
		log("        opt -fast\n");
		log("        memory -nomap\n");
		log("        opt_clean\n");
		log("\n");
		log("    fine:\n");
		log("        opt -fast -full\n");
		log("        memory_map\n");
		log("        opt -full\n");
		log("        techmap\n");
		log("        opt -fast\n");
	#ifdef YOSYS_ENABLE_ABC
		log("        abc -fast\n");
		log("        opt -fast\n");
	#endif
		log("\n");
		log("    check:\n");
		log("        hierarchy -check\n");
		log("        stat\n");
		log("        check\n");
		log("\n");
	}
	virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
	{
		std::string top_module, fsm_opts;
		std::string run_from, run_to;
		bool noabc = false;

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			if (args[argidx] == "-top" && argidx+1 < args.size()) {
				top_module = args[++argidx];
				continue;
			}
			if (args[argidx] == "-encfile" && argidx+1 < args.size()) {
				fsm_opts = " -encfile " + args[++argidx];
				continue;
			}
			if (args[argidx] == "-run" && argidx+1 < args.size()) {
				size_t pos = args[argidx+1].find(':');
				if (pos == std::string::npos) {
					run_from = args[++argidx];
					run_to = args[argidx];
				} else {
					run_from = args[++argidx].substr(0, pos);
					run_to = args[argidx].substr(pos+1);
				}
				continue;
			}
			if (args[argidx] == "-noabc") {
				noabc = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		if (!design->full_selection())
			log_cmd_error("This comannd only operates on fully selected designs!\n");

		bool active = run_from.empty();

		log_header("Executing SYNTH pass.\n");
		log_push();

		if (check_label(active, run_from, run_to, "begin"))
		{
			if (top_module.empty())
				Pass::call(design, stringf("hierarchy -check"));
			else
				Pass::call(design, stringf("hierarchy -check -top %s", top_module.c_str()));
		}

		if (check_label(active, run_from, run_to, "coarse"))
		{
			Pass::call(design, "proc");
			Pass::call(design, "opt_clean");
			Pass::call(design, "check");
			Pass::call(design, "opt");
			Pass::call(design, "wreduce");
			Pass::call(design, "alumacc");
			Pass::call(design, "share");
			Pass::call(design, "opt");
			Pass::call(design, "fsm" + fsm_opts);
			Pass::call(design, "opt -fast");
			Pass::call(design, "memory -nomap");
			Pass::call(design, "opt_clean");
		}

		if (check_label(active, run_from, run_to, "fine"))
		{
			Pass::call(design, "opt -fast -full");
			Pass::call(design, "memory_map");
			Pass::call(design, "opt -full");
			Pass::call(design, "techmap");
			Pass::call(design, "opt -fast");

			if (!noabc) {
		#ifdef YOSYS_ENABLE_ABC
				Pass::call(design, "abc -fast");
				Pass::call(design, "opt -fast");
		#endif
			}
		}

		if (check_label(active, run_from, run_to, "check"))
		{
			Pass::call(design, "hierarchy -check");
			Pass::call(design, "stat");
			Pass::call(design, "check");
		}

		log_pop();
	}
} SynthPass;

PRIVATE_NAMESPACE_END
<commit_msg>Added "synth -nordff -noalumacc"<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/celltypes.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

bool check_label(bool &active, std::string run_from, std::string run_to, std::string label)
{
	if (!run_from.empty() && run_from == run_to) {
		active = (label == run_from);
	} else {
		if (label == run_from)
			active = true;
		if (label == run_to)
			active = false;
	}
	return active;
}

struct SynthPass : public Pass {
	SynthPass() : Pass("synth", "generic synthesis script") { }
	virtual void help()
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    synth [options]\n");
		log("\n");
		log("This command runs the default synthesis script. This command does not operate\n");
		log("on partly selected designs.\n");
		log("\n");
		log("    -top <module>\n");
		log("        use the specified module as top module (default='top')\n");
		log("\n");
		log("    -encfile <file>\n");
		log("        passed to 'fsm_recode' via 'fsm'\n");
		log("\n");
		log("    -noabc\n");
		log("        do not run abc (as if yosys was compiled without ABC support)\n");
		log("\n");
		log("    -noalumacc\n");
		log("        do not run 'alumacc' pass. i.e. keep arithmetic operators in\n");
		log("        their direct form ($add, $sub, etc.).\n");
		log("\n");
		log("    -nordff\n");
		log("        passed to 'memory'. prohibits merging of FFs into memory read ports\n");
		log("\n");
		log("    -run <from_label>[:<to_label>]\n");
		log("        only run the commands between the labels (see below). an empty\n");
		log("        from label is synonymous to 'begin', and empty to label is\n");
		log("        synonymous to the end of the command list.\n");
		log("\n");
		log("\n");
		log("The following commands are executed by this synthesis command:\n");
		log("\n");
		log("    begin:\n");
		log("        hierarchy -check [-top <top>]\n");
		log("\n");
		log("    coarse:\n");
		log("        proc\n");
		log("        opt_clean\n");
		log("        check\n");
		log("        opt\n");
		log("        wreduce\n");
		log("        alumacc\n");
		log("        share\n");
		log("        opt\n");
		log("        fsm\n");
		log("        opt -fast\n");
		log("        memory -nomap\n");
		log("        opt_clean\n");
		log("\n");
		log("    fine:\n");
		log("        opt -fast -full\n");
		log("        memory_map\n");
		log("        opt -full\n");
		log("        techmap\n");
		log("        opt -fast\n");
	#ifdef YOSYS_ENABLE_ABC
		log("        abc -fast\n");
		log("        opt -fast\n");
	#endif
		log("\n");
		log("    check:\n");
		log("        hierarchy -check\n");
		log("        stat\n");
		log("        check\n");
		log("\n");
	}
	virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
	{
		std::string top_module, fsm_opts, memory_opts;
		std::string run_from, run_to;
		bool noalumacc = false;
		bool noabc = false;

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			if (args[argidx] == "-top" && argidx+1 < args.size()) {
				top_module = args[++argidx];
				continue;
			}
			if (args[argidx] == "-encfile" && argidx+1 < args.size()) {
				fsm_opts = " -encfile " + args[++argidx];
				continue;
			}
			if (args[argidx] == "-run" && argidx+1 < args.size()) {
				size_t pos = args[argidx+1].find(':');
				if (pos == std::string::npos) {
					run_from = args[++argidx];
					run_to = args[argidx];
				} else {
					run_from = args[++argidx].substr(0, pos);
					run_to = args[argidx].substr(pos+1);
				}
				continue;
			}
			if (args[argidx] == "-noabc") {
				noabc = true;
				continue;
			}
			if (args[argidx] == "-noalumacc") {
				noalumacc = true;
				continue;
			}
			if (args[argidx] == "-nordff") {
				memory_opts += " -nordff";
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		if (!design->full_selection())
			log_cmd_error("This comannd only operates on fully selected designs!\n");

		bool active = run_from.empty();

		log_header("Executing SYNTH pass.\n");
		log_push();

		if (check_label(active, run_from, run_to, "begin"))
		{
			if (top_module.empty())
				Pass::call(design, stringf("hierarchy -check"));
			else
				Pass::call(design, stringf("hierarchy -check -top %s", top_module.c_str()));
		}

		if (check_label(active, run_from, run_to, "coarse"))
		{
			Pass::call(design, "proc");
			Pass::call(design, "opt_clean");
			Pass::call(design, "check");
			Pass::call(design, "opt");
			Pass::call(design, "wreduce");
			if (!noalumacc)
				Pass::call(design, "alumacc");
			Pass::call(design, "share");
			Pass::call(design, "opt");
			Pass::call(design, "fsm" + fsm_opts);
			Pass::call(design, "opt -fast");
			Pass::call(design, "memory -nomap" + memory_opts);
			Pass::call(design, "opt_clean");
		}

		if (check_label(active, run_from, run_to, "fine"))
		{
			Pass::call(design, "opt -fast -full");
			Pass::call(design, "memory_map");
			Pass::call(design, "opt -full");
			Pass::call(design, "techmap");
			Pass::call(design, "opt -fast");

			if (!noabc) {
		#ifdef YOSYS_ENABLE_ABC
				Pass::call(design, "abc -fast");
				Pass::call(design, "opt -fast");
		#endif
			}
		}

		if (check_label(active, run_from, run_to, "check"))
		{
			Pass::call(design, "hierarchy -check");
			Pass::call(design, "stat");
			Pass::call(design, "check");
		}

		log_pop();
	}
} SynthPass;

PRIVATE_NAMESPACE_END
<|endoftext|>


<commit_before>#include "command.h"

#include <QRegExp>

#include "engine/util.h"

Command::Command(Player *player, QObject *parent) :
    QObject(parent),
    m_player(player) {

    Q_ASSERT(m_player);
}

Command::~Command() {
}

void Command::setDescription(const QString &description) {

    m_description = description;
}

void Command::setCommand(const QString &_command) {

    QRegExp whitespace("\\s+");
    QString command = _command.trimmed();

    m_words = command.split(whitespace);
    if (m_player->isAdmin()) {
        if (m_words[0] == "exec-script") {
            m_words.clear();
            m_words << command.section(whitespace, 0, 0);
            m_words << command.section(whitespace, 1);
            return;
        }
        if (m_words[0] == "get-trigger" || m_words[0] == "set-trigger") {
            m_words.clear();
            m_words << command.section(whitespace, 0, 0);
            m_words << command.section(whitespace, 1, 1);
            m_words << command.section(whitespace, 2, 2);
            if (m_words.last().toInt() > 0) {
                m_words << command.section(whitespace, 3, 3);
                m_words << command.section(whitespace, 4);
            } else {
                m_words << command.section(whitespace, 3);
            }
            return;
        }
        if (m_words[0] == "set-prop" &&
            m_words.length() >= 3 && m_words[2] == "description") {
            return;
        }
    }

    for (int i = 0; i < m_words.length(); i++) {
        QString word = m_words[i];
        if (word.startsWith("\"")) {
            while (i < m_words.length() - 1 && !word.endsWith("\"")) {
                word += " " + m_words[i + 1];
                m_words.removeAt(i);
            }
            if (word.endsWith("\"")) {
                m_words[i] = word.mid(1, word.length() - 2);
            } else {
                m_words[i] = word.mid(1);
            }
        }
    }
}

void Command::prependWord(const QString &word) {

    m_words.prepend(word);
}

void Command::appendWord(const QString &word) {

    m_words.append(word);
}

bool Command::assertWordsLeft(const QString &noneLeftText) {

    if (!hasWordsLeft()) {
        m_player->send(noneLeftText);
        return false;
    } else {
        return true;
    }
}

QString Command::takeWord(Options options) {

    if (m_words.length() > 0) {
        if (options & IfNotLast && m_words.length() == 1) {
            return QString();
        }
        return m_words.takeFirst();
    }

    return QString();
}

QString Command::takeWord(const char *pattern, Options options) {

    return takeWord(QRegExp(QString(pattern)), options);
}

QString Command::takeWord(const QRegExp &pattern, Options options) {

    if (m_words.length() > 0) {
        if (options & IfNotLast && m_words.length() == 1) {
            return QString();
        }
        if (pattern.exactMatch(m_words[0])) {
            return m_words.takeFirst();
        }
    }

    return QString();
}

GameObjectPtr Command::takeObject(const GameObjectPtrList &pool) {

    QPair<QString, uint> description = takeObjectsDescription();
    if (!description.first.isEmpty()) {
        GameObjectPtrList objects = objectsByDescription(description, pool);
        if (objects.length() > 0) {
            return objects[0];
        }
    }

    return GameObjectPtr();
}

GameObjectPtrList Command::takeObjects(const GameObjectPtrList &pool) {

    QPair<QString, uint> description = takeObjectsDescription();
    if (!description.first.isEmpty()) {
        return objectsByDescription(description, pool);
    }

    return GameObjectPtrList();
}

QPair<QString, uint> Command::takeObjectsDescription() {

    QPair<QString, uint> description;
    if (m_words.length() > 0) {
        description.first = m_words.takeFirst().toLower();
        if (m_words.length() > 0) {
            description.second = m_words.first().toInt();
            if (description.second > 0) {
                m_words.removeFirst();
            }
        }
    }
    return description;
}

QString Command::takeRest() {

    QString rest = m_words.join(" ");
    m_words.clear();
    return rest;
}

GameObjectPtrList Command::objectsByDescription(const QPair<QString, uint> &description,
                                                const GameObjectPtrList &pool) {

    GameObjectPtrList objects;
    if (description.first == "all") {
        objects = pool;
    } else {
        for (const GameObjectPtr &object : pool) {
            QString loweredName = object->name().toLower();
            if (loweredName == description.first) {
                objects.clear();
                objects << object;
                break;
            }
            for (const QString &word : loweredName.split(' ')) {
                if (word.startsWith(description.first)) {
                    objects << object;
                    break;
                }
            }
        }
    }
    if (description.second > 0) {
        if (description.second <= (uint) objects.length()) {
            GameObjectPtr selected = objects[description.second - 1];
            objects.clear();
            objects << selected;
        } else {
            objects.clear();
        }
    }
    return objects;
}

bool Command::requireSome(const GameObjectPtr &object, const QString &tooFewText) {

    if (object.isNull()) {
        m_player->send(tooFewText);
        return false;
    } else {
        return true;
    }
}

bool Command::requireSome(const GameObjectPtrList &objects,
                          const QString &tooFewText) {

    if (objects.length() == 0) {
        m_player->send(tooFewText);
        return false;
    } else {
        return true;
    }
}

bool Command::requireUnique(const GameObjectPtrList &objects,
                            const QString &tooFewText,
                            const QString &tooManyText) {

    if (objects.length() == 0) {
        m_player->send(tooFewText);
        return false;
    } else if (objects.length() > 1) {
        m_player->send(tooManyText);
        return false;
    } else {
        return true;
    }
}
<commit_msg>Don't be an ass when there are multiple exits with the same name.<commit_after>#include "command.h"

#include <QRegExp>

#include "engine/util.h"

Command::Command(Player *player, QObject *parent) :
    QObject(parent),
    m_player(player) {

    Q_ASSERT(m_player);
}

Command::~Command() {
}

void Command::setDescription(const QString &description) {

    m_description = description;
}

void Command::setCommand(const QString &_command) {

    QRegExp whitespace("\\s+");
    QString command = _command.trimmed();

    m_words = command.split(whitespace);
    if (m_player->isAdmin()) {
        if (m_words[0] == "exec-script") {
            m_words.clear();
            m_words << command.section(whitespace, 0, 0);
            m_words << command.section(whitespace, 1);
            return;
        }
        if (m_words[0] == "get-trigger" || m_words[0] == "set-trigger") {
            m_words.clear();
            m_words << command.section(whitespace, 0, 0);
            m_words << command.section(whitespace, 1, 1);
            m_words << command.section(whitespace, 2, 2);
            if (m_words.last().toInt() > 0) {
                m_words << command.section(whitespace, 3, 3);
                m_words << command.section(whitespace, 4);
            } else {
                m_words << command.section(whitespace, 3);
            }
            return;
        }
        if (m_words[0] == "set-prop" &&
            m_words.length() >= 3 && m_words[2] == "description") {
            return;
        }
    }

    for (int i = 0; i < m_words.length(); i++) {
        QString word = m_words[i];
        if (word.startsWith("\"")) {
            while (i < m_words.length() - 1 && !word.endsWith("\"")) {
                word += " " + m_words[i + 1];
                m_words.removeAt(i);
            }
            if (word.endsWith("\"")) {
                m_words[i] = word.mid(1, word.length() - 2);
            } else {
                m_words[i] = word.mid(1);
            }
        }
    }
}

void Command::prependWord(const QString &word) {

    m_words.prepend(word);
}

void Command::appendWord(const QString &word) {

    m_words.append(word);
}

bool Command::assertWordsLeft(const QString &noneLeftText) {

    if (!hasWordsLeft()) {
        m_player->send(noneLeftText);
        return false;
    } else {
        return true;
    }
}

QString Command::takeWord(Options options) {

    if (m_words.length() > 0) {
        if (options & IfNotLast && m_words.length() == 1) {
            return QString();
        }
        return m_words.takeFirst();
    }

    return QString();
}

QString Command::takeWord(const char *pattern, Options options) {

    return takeWord(QRegExp(QString(pattern)), options);
}

QString Command::takeWord(const QRegExp &pattern, Options options) {

    if (m_words.length() > 0) {
        if (options & IfNotLast && m_words.length() == 1) {
            return QString();
        }
        if (pattern.exactMatch(m_words[0])) {
            return m_words.takeFirst();
        }
    }

    return QString();
}

GameObjectPtr Command::takeObject(const GameObjectPtrList &pool) {

    QPair<QString, uint> description = takeObjectsDescription();
    if (!description.first.isEmpty()) {
        GameObjectPtrList objects = objectsByDescription(description, pool);
        if (objects.length() > 0) {
            return objects[0];
        }
    }

    return GameObjectPtr();
}

GameObjectPtrList Command::takeObjects(const GameObjectPtrList &pool) {

    QPair<QString, uint> description = takeObjectsDescription();
    if (!description.first.isEmpty()) {
        return objectsByDescription(description, pool);
    }

    return GameObjectPtrList();
}

QPair<QString, uint> Command::takeObjectsDescription() {

    QPair<QString, uint> description;
    if (m_words.length() > 0) {
        description.first = m_words.takeFirst().toLower();
        if (m_words.length() > 0) {
            description.second = m_words.first().toInt();
            if (description.second > 0) {
                m_words.removeFirst();
            }
        }
    }
    return description;
}

QString Command::takeRest() {

    QString rest = m_words.join(" ");
    m_words.clear();
    return rest;
}

GameObjectPtrList Command::objectsByDescription(const QPair<QString, uint> &description,
                                                const GameObjectPtrList &pool) {

    GameObjectPtrList objects;
    if (description.first == "all") {
        objects = pool;
    } else {
        for (const GameObjectPtr &object : pool) {
            QString loweredName = object->name().toLower();
            for (const QString &word : loweredName.split(' ')) {
                if (word.startsWith(description.first)) {
                    objects << object;
                    break;
                }
            }
        }
    }
    if (description.second > 0) {
        if (description.second <= (uint) objects.length()) {
            GameObjectPtr selected = objects[description.second - 1];
            objects.clear();
            objects << selected;
        } else {
            objects.clear();
        }
    }
    return objects;
}

bool Command::requireSome(const GameObjectPtr &object, const QString &tooFewText) {

    if (object.isNull()) {
        m_player->send(tooFewText);
        return false;
    } else {
        return true;
    }
}

bool Command::requireSome(const GameObjectPtrList &objects,
                          const QString &tooFewText) {

    if (objects.length() == 0) {
        m_player->send(tooFewText);
        return false;
    } else {
        return true;
    }
}

bool Command::requireUnique(const GameObjectPtrList &objects,
                            const QString &tooFewText,
                            const QString &tooManyText) {

    if (objects.length() == 0) {
        m_player->send(tooFewText);
        return false;
    } else if (objects.length() > 1) {
        m_player->send(tooManyText);
        return false;
    } else {
        return true;
    }
}
<|endoftext|>