<commit_before>/*
 *  Copyright 2013 The OpenMx Project
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include "omxState.h"
#include "omxFitFunction.h"
#include "omxExportBackendState.h"
#include "Compute.h"

class ComputeNR : public omxComputeOperation {
	typedef omxComputeOperation super;
	omxMatrix *fitMatrix;

	int maxIter;
	double tolerance;
	int inform, iter;

public:
	ComputeNR();
	virtual void initFromFrontend(SEXP rObj);
	virtual void compute(FitContext *fc);
	virtual void reportResults(FitContext *fc, MxRList *out);
	virtual double getOptimizerStatus() { return inform; }  // backward compatibility
};

class omxCompute *newComputeNewtonRaphson()
{
	return new ComputeNR();
}

ComputeNR::ComputeNR()
{
	inform = 0;
	iter = 0;
}

void ComputeNR::initFromFrontend(SEXP rObj)
{
	super::initFromFrontend(rObj);

	fitMatrix = omxNewMatrixFromSlot(rObj, globalState, "fitfunction");
	setFreeVarGroup(fitMatrix->fitFunction, varGroup);
	omxCompleteFitFunction(fitMatrix);

	if (!fitMatrix->fitFunction->hessianAvailable ||
	    !fitMatrix->fitFunction->gradientAvailable) {
		error("Newton-Raphson requires derivatives");
	}

	SEXP slotValue;
	PROTECT(slotValue = GET_SLOT(rObj, install("maxIter")));
	maxIter = INTEGER(slotValue)[0];

	PROTECT(slotValue = GET_SLOT(rObj, install("tolerance")));
	tolerance = REAL(slotValue)[0];
	if (tolerance <= 0) error("tolerance must be positive");
}

void ComputeNR::compute(FitContext *fc)
{
	// complain if there are non-linear constraints TODO

	size_t numParam = varGroup->vars.size();
	if (numParam <= 0) {
		error("Model has no free parameters");
		return;
	}

	omxFitFunctionCompute(fitMatrix->fitFunction, FF_COMPUTE_PREOPTIMIZE, fc);

	iter = 0;

	while (1) {
		const int want = FF_COMPUTE_FIT|FF_COMPUTE_GRADIENT|FF_COMPUTE_HESSIAN;

		OMXZERO(fc->grad, numParam);
		OMXZERO(fc->hess, numParam * numParam);

		omxFitFunctionCompute(fitMatrix->fitFunction, want, fc);

		fc->fixHessianSymmetry();
		//fc->log(FF_COMPUTE_ESTIMATE|FF_COMPUTE_GRADIENT|FF_COMPUTE_HESSIAN);

		std::vector<double> ihess(numParam * numParam);
		for (size_t rx=0; rx < numParam; rx++) {
			for (size_t cx=0; cx < numParam; cx++) {
				ihess[rx * numParam + cx] = rx==cx? 1 : 0;
			}
		}
		std::vector<int> ipiv(numParam);
		int info;
		int dim = int(numParam);
		F77_CALL(dgesv)(&dim, &dim, fc->hess, &dim, ipiv.data(),
				ihess.data(), &dim, &info);
		if (info < 0) error("Arg %d is invalid", -info);
		if (info > 0) {
			omxRaiseErrorf(globalState, "Hessian is singular and cannot be inverted");
			break;
		}

		std::vector<double> adj(numParam);
		char trans = 'N';
		double alpha = -1;
		int incx = 1;
		double beta = 0;
		F77_CALL(dgemv)(&trans, &dim, &dim, &alpha, ihess.data(), &dim,
				fc->grad, &incx, &beta, adj.data(), &incx);

		double maxAdj = 0;
		for (size_t px=0; px < numParam; ++px) {
			double param = fc->est[px];
			param += adj[px];
			omxFreeVar *fv = fc->varGroup->vars[px];
			if (param < fv->lbound) param = fv->lbound;
			if (param > fv->ubound) param = fv->ubound;
			double adj = fabs(param - fc->est[px]);
			if (maxAdj < adj)
				maxAdj = adj;
			fc->est[px] = param;
		}
		fc->copyParamToModel(globalState);
		R_CheckUserInterrupt();
		if (maxAdj < tolerance || ++iter > maxIter) break;
	}
}

void ComputeNR::reportResults(FitContext *fc, MxRList *out)
{
	if (Global->numIntervals) {
		warning("Confidence intervals are not implemented for Newton-Raphson");
	}

	omxPopulateFitFunction(fitMatrix, out);

	size_t numFree = varGroup->vars.size();

	SEXP minimum, estimate;
	PROTECT(minimum = NEW_NUMERIC(1));
	PROTECT(estimate = allocVector(REALSXP, numFree));

	REAL(minimum)[0] = fc->fit;
	memcpy(REAL(estimate), fc->est, sizeof(double) * numFree);

	out->push_back(std::make_pair(mkChar("minimum"), minimum));
	out->push_back(std::make_pair(mkChar("estimate"), estimate));

	SEXP code, iterations;

	PROTECT(code = NEW_NUMERIC(1));
	REAL(code)[0] = inform;
	out->push_back(std::make_pair(mkChar("nr.code"), code));

	PROTECT(iterations = NEW_NUMERIC(1));
	REAL(iterations)[0] = iter;
	out->push_back(std::make_pair(mkChar("nr.iterations"), iterations));
}
<commit_msg>Check whether LL is decreasing (not enabled by default)<commit_after>/*
 *  Copyright 2013 The OpenMx Project
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include "omxState.h"
#include "omxFitFunction.h"
#include "omxExportBackendState.h"
#include "Compute.h"

class ComputeNR : public omxComputeOperation {
	typedef omxComputeOperation super;
	omxMatrix *fitMatrix;

	int maxIter;
	double tolerance;
	int inform, iter;

public:
	ComputeNR();
	virtual void initFromFrontend(SEXP rObj);
	virtual void compute(FitContext *fc);
	virtual void reportResults(FitContext *fc, MxRList *out);
	virtual double getOptimizerStatus() { return inform; }  // backward compatibility
};

class omxCompute *newComputeNewtonRaphson()
{
	return new ComputeNR();
}

ComputeNR::ComputeNR()
{
	inform = 0;
	iter = 0;
}

void ComputeNR::initFromFrontend(SEXP rObj)
{
	super::initFromFrontend(rObj);

	fitMatrix = omxNewMatrixFromSlot(rObj, globalState, "fitfunction");
	setFreeVarGroup(fitMatrix->fitFunction, varGroup);
	omxCompleteFitFunction(fitMatrix);

	if (!fitMatrix->fitFunction->hessianAvailable ||
	    !fitMatrix->fitFunction->gradientAvailable) {
		error("Newton-Raphson requires derivatives");
	}

	SEXP slotValue;
	PROTECT(slotValue = GET_SLOT(rObj, install("maxIter")));
	maxIter = INTEGER(slotValue)[0];

	PROTECT(slotValue = GET_SLOT(rObj, install("tolerance")));
	tolerance = REAL(slotValue)[0];
	if (tolerance <= 0) error("tolerance must be positive");
}

void ComputeNR::compute(FitContext *fc)
{
	// complain if there are non-linear constraints TODO

	size_t numParam = varGroup->vars.size();
	if (numParam <= 0) {
		error("Model has no free parameters");
		return;
	}

	omxFitFunctionCompute(fitMatrix->fitFunction, FF_COMPUTE_PREOPTIMIZE, fc);

	iter = 0;
	double prevLL = nan("unset");
	bool decreasing = TRUE;

	while (1) {
		const int want = FF_COMPUTE_FIT|FF_COMPUTE_GRADIENT|FF_COMPUTE_HESSIAN;

		OMXZERO(fc->grad, numParam);
		OMXZERO(fc->hess, numParam * numParam);

		omxFitFunctionCompute(fitMatrix->fitFunction, want, fc);

		// Only need LL for diagnostics; Can avoid computing it? TODO
		double LL = fitMatrix->data[0];
		if (isfinite(prevLL) && prevLL < LL - tolerance) decreasing = FALSE;
		prevLL = LL;

		fc->fixHessianSymmetry();
		//		fc->log(FF_COMPUTE_ESTIMATE|FF_COMPUTE_GRADIENT|FF_COMPUTE_HESSIAN);

		std::vector<double> ihess(numParam * numParam);
		for (size_t rx=0; rx < numParam; rx++) {
			for (size_t cx=0; cx < numParam; cx++) {
				ihess[rx * numParam + cx] = rx==cx? 1 : 0;
			}
		}
		std::vector<int> ipiv(numParam);
		int info;
		int dim = int(numParam);
		F77_CALL(dgesv)(&dim, &dim, fc->hess, &dim, ipiv.data(),
				ihess.data(), &dim, &info);
		if (info < 0) error("Arg %d is invalid", -info);
		if (info > 0) {
			omxRaiseErrorf(globalState, "Hessian is singular and cannot be inverted");
			break;
		}

		std::vector<double> adj(numParam);
		char trans = 'N';
		double alpha = -1;
		int incx = 1;
		double beta = 0;
		F77_CALL(dgemv)(&trans, &dim, &dim, &alpha, ihess.data(), &dim,
				fc->grad, &incx, &beta, adj.data(), &incx);

		double maxAdj = 0;
		for (size_t px=0; px < numParam; ++px) {
			double param = fc->est[px];
			param += adj[px];
			omxFreeVar *fv = fc->varGroup->vars[px];
			if (param < fv->lbound) param = fv->lbound;
			if (param > fv->ubound) param = fv->ubound;
			double adj = fabs(param - fc->est[px]);
			if (maxAdj < adj)
				maxAdj = adj;
			fc->est[px] = param;
		}
		fc->copyParamToModel(globalState);
		R_CheckUserInterrupt();
		if (maxAdj < tolerance || ++iter > maxIter) break;
	}

	// The check is too dependent on numerical precision to enable by default.
	// Anyway, it's just a tool for developers.
	if (0 && !decreasing) warning("Newton-Raphson iterations did not converge");
}

void ComputeNR::reportResults(FitContext *fc, MxRList *out)
{
	if (Global->numIntervals) {
		warning("Confidence intervals are not implemented for Newton-Raphson");
	}

	omxPopulateFitFunction(fitMatrix, out);

	size_t numFree = varGroup->vars.size();

	SEXP minimum, estimate;
	PROTECT(minimum = NEW_NUMERIC(1));
	PROTECT(estimate = allocVector(REALSXP, numFree));

	REAL(minimum)[0] = fc->fit;
	memcpy(REAL(estimate), fc->est, sizeof(double) * numFree);

	out->push_back(std::make_pair(mkChar("minimum"), minimum));
	out->push_back(std::make_pair(mkChar("estimate"), estimate));

	SEXP code, iterations;

	PROTECT(code = NEW_NUMERIC(1));
	REAL(code)[0] = inform;
	out->push_back(std::make_pair(mkChar("nr.code"), code));

	PROTECT(iterations = NEW_NUMERIC(1));
	REAL(iterations)[0] = iter;
	out->push_back(std::make_pair(mkChar("nr.iterations"), iterations));
}
<|endoftext|>


<commit_before>#include "FusionEKF.h"
#include "tools.h"
#include "Eigen/Dense"
#include <iostream>

using namespace std;
using Eigen::MatrixXd;
using Eigen::VectorXd;
using std::vector;

/*
 * Constructor.
 */
FusionEKF::FusionEKF() {
  is_initialized_ = false;

  previous_timestamp_ = 0;

  // initializing matrices
  R_laser_ = MatrixXd(2, 2);
  R_radar_ = MatrixXd(3, 3);
  H_laser_ = MatrixXd(2, 4);
  Hj_ = MatrixXd(3, 4);

  //measurement covariance matrix - laser
  R_laser_ << 0.0225, 0,
        0, 0.0225;

  //measurement covariance matrix - radar
  R_radar_ << 0.09, 0, 0,
        0, 0.0009, 0,
        0, 0, 0.09;

  /**
  TODO:
    * Finish initializing the FusionEKF.
    * Set the process and measurement noises
  */

  //state covariance matrix P
  ekf_.P_ = MatrixXd(4, 4);
  ekf_.P_ << 1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1000, 0,
            0, 0, 0, 1000;

  //the initial transition matrix F_
  ekf_.F_ = MatrixXd(4, 4);
  ekf_.F_ << 1, 0, 1, 0,
            0, 1, 0, 1,
            0, 0, 1, 0,
            0, 0, 0, 1;

  noise_ax = 9;
  noise_ay = 9;

}

/**
* Destructor.
*/
FusionEKF::~FusionEKF() {}

void FusionEKF::ProcessMeasurement(const MeasurementPackage &measurement_pack) {

  /*****************************************************************************
   *  Initialization
   ****************************************************************************/
  if (!is_initialized_) {
    /**
    TODO:
      * Initialize the state ekf_.x_ with the first measurement.
      * Create the covariance matrix.
      * Remember: you'll need to convert radar from polar to cartesian coordinates.
    */
    // first measurement
    cout << "EKF: " << endl;

    previous_timestamp_ = measurement_pack.timestamp;

    if (measurement_pack.sensor_type_ == MeasurementPackage::RADAR) {
      /**
      Convert radar from polar to cartesian coordinates and initialize state.
      */
      ekf_.x_ = VectorXd(3);
      ekf_.x_ << measurement_pack.raw_measurements_[0], measurement_pack.raw_measurements_[1], measurement_pack.raw_measurements_[2];

    }
    else if (measurement_pack.sensor_type_ == MeasurementPackage::LASER) {
      /**
      Initialize state.
      */
      ekf_.x_ = VectorXd(4);
      ekf_.x_ << measurement_pack.raw_measurements_[0], measurement_pack.raw_measurements_[1], 0, 0;
    }

    // done initializing, no need to predict or update
    is_initialized_ = true;
    return;
  }

  /*****************************************************************************
   *  Prediction
   ****************************************************************************/

  /**
   TODO:
     * Update the state transition matrix F according to the new elapsed time.
      - Time is measured in seconds.
     * Update the process noise covariance matrix.
     * Use noise_ax = 9 and noise_ay = 9 for your Q matrix.
   */

  //compute the time elapsed between the current and previous measurements
  float dt = (measurement_pack.timestamp - previous_timestamp_) / 1000000.0;	//dt - expressed in seconds
  previous_timestamp_ = measurement_pack.timestamp;

  float dt_2 = dt * dt;
  float dt_3 = dt_2 * dt;
  float dt_4 = dt_3 * dt;

  /Modify the F matrix so that the time is integrated
  ekf_.F_(0, 2) = dt;
  ekf_.F_(1, 3) = dt;

  //set the process covariance matrix Q
  ekf_.Q_ = MatrixXd(4, 4);
  ekf_.Q_ <<  dt_4/4*noise_ax, 0, dt_3/2*noise_ax, 0,
              0, dt_4/4*noise_ay, 0, dt_3/2*noise_ay,
              dt_3/2*noise_ax, 0, dt_2*noise_ax, 0,
              0, dt_3/2*noise_ay, 0, dt_2*noise_ay;

  ekf_.Predict();

  /*****************************************************************************
   *  Update
   ****************************************************************************/

  /**
   TODO:
     * Use the sensor type to perform the update step.
     * Update the state and covariance matrices.
   */

  if (measurement_pack.sensor_type_ == MeasurementPackage::RADAR) {
    // Radar updates
    ekf_.R_ = R_radar_;
    ekf_.H_ =
  } else {
    // Laser updates
  }

  // print the output
  cout << "x_ = " << ekf_.x_ << endl;
  cout << "P_ = " << ekf_.P_ << endl;
}
<commit_msg>adding completed FusionEFK.cpp<commit_after>#include "FusionEKF.h"
#include "tools.h"
#include "Eigen/Dense"
#include <iostream>

using namespace std;
using Eigen::MatrixXd;
using Eigen::VectorXd;
using std::vector;

/*
 * Constructor.
 */
FusionEKF::FusionEKF() {
  is_initialized_ = false;

  previous_timestamp_ = 0;

  // initializing matrices
  R_laser_ = MatrixXd(2, 2);
  R_radar_ = MatrixXd(3, 3);
  H_laser_ = MatrixXd(2, 4);
  Hj_ = MatrixXd(3, 4);

  //measurement covariance matrix - laser
  R_laser_ << 0.0225, 0,
        0, 0.0225;

  //measurement covariance matrix - radar
  R_radar_ << 0.09, 0, 0,
        0, 0.0009, 0,
        0, 0, 0.09;

  /**
  TODO:
    * Finish initializing the FusionEKF.
    * Set the process and measurement noises
  */

  //state covariance matrix P
  ekf_.P_ = MatrixXd(4, 4);
  ekf_.P_ << 1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1000, 0,
            0, 0, 0, 1000;

  //the initial transition matrix F_
  ekf_.F_ = MatrixXd(4, 4);
  ekf_.F_ << 1, 0, 1, 0,
            0, 1, 0, 1,
            0, 0, 1, 0,
            0, 0, 0, 1;

  H_laser_ = MatrixXd(2, 4);
  H_laser_ << 1, 0, 0, 0,
              0, 1, 0, 0;

  Hj_ = MatrixXd(3, 4);
  Hj_ << 1, 1, 0, 0,
         1, 1, 0, 0,
         1, 1, 1, 1;

  noise_ax = 9;
  noise_ay = 9;

}

/**
* Destructor.
*/
FusionEKF::~FusionEKF() {}

void FusionEKF::ProcessMeasurement(const MeasurementPackage &measurement_pack) {

  /*****************************************************************************
   *  Initialization
   ****************************************************************************/
  if (!is_initialized_) {
    /**
    TODO:
      * Initialize the state ekf_.x_ with the first measurement.
      * Create the covariance matrix.
      * Remember: you'll need to convert radar from polar to cartesian coordinates.
    */
    // first measurement
    cout << "EKF: " << endl;

    previous_timestamp_ = measurement_pack.timestamp;
    ekf_.x_ = VectorXd(4);

    if (measurement_pack.sensor_type_ == MeasurementPackage::RADAR) {
      /**
      Convert radar from polar to cartesian coordinates and initialize state.
      */
      float ro = measurement_pack.raw_measurements_[0];
      float phi = measurement_pack.raw_measurements_[1];
      float ro_dot = measurement_pack.raw_measurements_[2];

      ekf_.x_ << rho * cos(phi), rho * sin(phi), rho_dot * cos(phi), rho_dot * sin(phi);

    }
    else if (measurement_pack.sensor_type_ == MeasurementPackage::LASER) {
      /**
      Initialize state.
      */

      ekf_.x_ << measurement_pack.raw_measurements_[0], measurement_pack.raw_measurements_[1], 0, 0;
    }

    // done initializing, no need to predict or update
    is_initialized_ = true;
    return;
  }

  /*****************************************************************************
   *  Prediction
   ****************************************************************************/

  /**
   TODO:
     * Update the state transition matrix F according to the new elapsed time.
      - Time is measured in seconds.
     * Update the process noise covariance matrix.
     * Use noise_ax = 9 and noise_ay = 9 for your Q matrix.
   */

  //compute the time elapsed between the current and previous measurements
  float dt = (measurement_pack.timestamp - previous_timestamp_) / 1000000.0;	//dt - expressed in seconds
  previous_timestamp_ = measurement_pack.timestamp;

  float dt_2 = dt * dt;
  float dt_3 = dt_2 * dt;
  float dt_4 = dt_3 * dt;

  //Modify the F matrix so that the time is integrated
  ekf_.F_(0, 2) = dt;
  ekf_.F_(1, 3) = dt;

  //set the process covariance matrix Q
  ekf_.Q_ = MatrixXd(4, 4);
  ekf_.Q_ <<  dt_4/4*noise_ax, 0, dt_3/2*noise_ax, 0,
              0, dt_4/4*noise_ay, 0, dt_3/2*noise_ay,
              dt_3/2*noise_ax, 0, dt_2*noise_ax, 0,
              0, dt_3/2*noise_ay, 0, dt_2*noise_ay;

  ekf_.Predict();

  /*****************************************************************************
   *  Update
   ****************************************************************************/

  /**
   TODO:
     * Use the sensor type to perform the update step.
     * Update the state and covariance matrices.
   */

  if (measurement_pack.sensor_type_ == MeasurementPackage::RADAR) {
    // Radar updates
    ekf_.R_ = R_radar_;
    Hj_ = tools.CalculateJacobian(ekf_.x_);
    ekf_.H_ = Hj_;
    ekf_.UpdateEKF(measurement_pack.raw_measurements_);
  } else {
    // Laser updates
    ekf_.R_ = R_laser_;
    ekf_.H_ = H_laser_;
    ekf_.Update(measurement_pack.raw_measurements_);
  }

  // print the output
  cout << "x_ = " << ekf_.x_ << endl;
  cout << "P_ = " << ekf_.P_ << endl;
}
<|endoftext|>


<commit_before>// Generator requires C++11
#if __cplusplus > 199711L

#include "Generator.h"

namespace {

// Return true iff the name is valid for Generators or Params.
// (NOTE: gcc didn't add proper std::regex support until v4.9;
// we don't yet require this, hence the hand-rolled replacement.)

bool is_alpha(char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); }

// Note that this includes '_'
bool is_alnum(char c) { return is_alpha(c) || (c == '_') || (c >= '0' && c <= '9'); }

bool is_valid_name(const std::string& n) {
    if (n.empty()) return false;
    if (!is_alpha(n[0])) return false;
    for (size_t i = 1; i < n.size(); ++i) {
        if (!is_alnum(n[i])) return false;
    }
    return true;
}

}  // namespace

namespace Halide {
namespace Internal {

int generate_filter_main(int argc, char **argv, std::ostream &cerr) {
    const char kUsage[] = "gengen [-g GENERATOR_NAME] [-f FUNCTION_NAME] [-o OUTPUT_DIR]  "
                          "target=target-string [generator_arg=value [...]]\n";

    std::map<std::string, std::string> flags_info = { { "-f", "" }, { "-g", "" }, { "-o", "" } };
    std::map<std::string, std::string> generator_args;

    for (int i = 1; i < argc; ++i) {
        if (argv[i][0] != '-') {
            std::vector<std::string> v = split_string(argv[i], "=");
            if (v.size() != 2 || v[0].empty() || v[1].empty()) {
                cerr << kUsage;
                return 1;
            }
            generator_args[v[0]] = v[1];
            continue;
        }
        auto it = flags_info.find(argv[i]);
        if (it != flags_info.end()) {
            if (i + 1 >= argc) {
                cerr << kUsage;
                return 1;
            }
            it->second = argv[i + 1];
            ++i;
            continue;
        }
        cerr << "Unknown flag: " << argv[i] << "\n";
        cerr << kUsage;
        return 1;
    }

    std::vector<std::string> generator_names = Internal::GeneratorRegistry::enumerate();
    if (generator_names.size() == 0) {
        cerr << "No generators have been registered\n";
        cerr << kUsage;
        return 1;
    }

    std::string generator_name = flags_info["-g"];
    if (generator_name.empty()) {
        // If -g isn't specified, but there's only one generator registered, just use that one.
        if (generator_names.size() != 1) {
            cerr << "-g must be specified if multiple generators are registered\n";
            cerr << kUsage;
            return 1;
        }
        generator_name = generator_names[0];
    }
    std::string function_name = flags_info["-f"];
    if (function_name.empty()) {
        // If -f isn't specified, but there's only one generator registered,
        // just assume function name = generator name.
        if (generator_names.size() != 1) {
            cerr << "-f must be specified if multiple generators are registered\n";
            cerr << kUsage;
            return 1;
        }
        function_name = generator_names[0];
    }
    std::string output_dir = flags_info["-o"];
    if (output_dir.empty()) {
        cerr << "-o must always be specified.\n";
        cerr << kUsage;
        return 1;
    }
    if (generator_args.find("target") == generator_args.end()) {
        cerr << "Target missing\n";
        cerr << kUsage;
        return 1;
    }

    std::unique_ptr<GeneratorBase> gen =
        Internal::GeneratorRegistry::create(generator_name, generator_args);
    if (gen == nullptr) {
        cerr << "Unknown generator: " << generator_name << "\n";
        cerr << kUsage;
        return 1;
    }
    gen->emit_filter(output_dir, function_name);
    return 0;
}

GeneratorParamBase::GeneratorParamBase(const std::string &name) : name(name) {
    ObjectInstanceRegistry::register_instance(this, 0, ObjectInstanceRegistry::GeneratorParam,
                                              this);
}

GeneratorParamBase::~GeneratorParamBase() { ObjectInstanceRegistry::unregister_instance(this); }

/* static */
GeneratorRegistry &GeneratorRegistry::get_registry() {
    static GeneratorRegistry *registry = new GeneratorRegistry;
    return *registry;
}

/* static */
void GeneratorRegistry::register_factory(const std::string &name,
                                         std::unique_ptr<GeneratorFactory> factory) {
    user_assert(is_valid_name(name)) << "Invalid Generator name: " << name;
    GeneratorRegistry &registry = get_registry();
    std::lock_guard<std::mutex> lock(registry.mutex);
    internal_assert(registry.factories.find(name) == registry.factories.end())
        << "Duplicate Generator name: " << name;
    registry.factories[name] = std::move(factory);
}

/* static */
void GeneratorRegistry::unregister_factory(const std::string &name) {
    GeneratorRegistry &registry = get_registry();
    std::lock_guard<std::mutex> lock(registry.mutex);
    internal_assert(registry.factories.find(name) != registry.factories.end())
        << "Generator not found: " << name;
    registry.factories.erase(name);
}

/* static */
std::unique_ptr<GeneratorBase> GeneratorRegistry::create(const std::string &name,
                                                         const GeneratorParamValues &params) {
    GeneratorRegistry &registry = get_registry();
    std::lock_guard<std::mutex> lock(registry.mutex);
    auto it = registry.factories.find(name);
    user_assert(it != registry.factories.end()) << "Generator not found: " << name;
    return it->second->create(params);
}

/* static */
std::vector<std::string> GeneratorRegistry::enumerate() {
    GeneratorRegistry &registry = get_registry();
    std::lock_guard<std::mutex> lock(registry.mutex);
    std::vector<std::string> result;
    for (auto it = registry.factories.begin(); it != registry.factories.end(); ++it) {
        result.push_back(it->first);
    }
    return result;
}

GeneratorBase::GeneratorBase(size_t size) : size(size), params_built(false) {
    ObjectInstanceRegistry::register_instance(this, size, ObjectInstanceRegistry::Generator, this);
}

GeneratorBase::~GeneratorBase() { ObjectInstanceRegistry::unregister_instance(this); }

void GeneratorBase::build_params() {
    if (!params_built) {
        std::vector<void *> vf = ObjectInstanceRegistry::instances_in_range(
            this, size, ObjectInstanceRegistry::FilterParam);
        for (size_t i = 0; i < vf.size(); ++i) {
            Parameter *param = static_cast<Parameter *>(vf[i]);
            internal_assert(param != nullptr);
            user_assert(param->is_explicit_name()) << "Params in Generators must have explicit names: " << param->name();
            user_assert(is_valid_name(param->name())) << "Invalid Param name: " << param->name();
            user_assert(filter_params.find(param->name()) == filter_params.end())
                << "Duplicate Param name: " << param->name();
            filter_params[param->name()] = param;
            filter_arguments.push_back(Argument(param->name(), param->is_buffer(), param->type()));
        }

        std::vector<void *> vg = ObjectInstanceRegistry::instances_in_range(
            this, size, ObjectInstanceRegistry::GeneratorParam);
        for (size_t i = 0; i < vg.size(); ++i) {
            GeneratorParamBase *param = static_cast<GeneratorParamBase *>(vg[i]);
            internal_assert(param != nullptr);
            user_assert(is_valid_name(param->name)) << "Invalid GeneratorParam name: " << param->name;
            user_assert(generator_params.find(param->name) == generator_params.end())
                << "Duplicate GeneratorParam name: " << param->name;
            generator_params[param->name] = param;
        }
        params_built = true;
    }
}

void GeneratorBase::set_generator_param_values(const GeneratorParamValues &params) {
    build_params();
    for (auto key_value : params) {
        const std::string &key = key_value.first;
        const std::string &value = key_value.second;
        auto param = generator_params.find(key);
        user_assert(param != generator_params.end())
            << "Generator has no GeneratorParam named: " << key;
        param->second->set_from_string(value);
    }
}

void GeneratorBase::emit_filter(const std::string &output_dir, const std::string &function_name,
                                const std::string &file_base_name, const EmitOptions &options) {
    Func func = build();

    build_params();

    std::string base_path = file_base_name.empty() ?
        output_dir + "/" + function_name :
        output_dir + "/" + file_base_name;
    if (options.emit_o) {
        func.compile_to_object(base_path + ".o", filter_arguments, function_name, target);
    }
    if (options.emit_h) {
        func.compile_to_header(base_path + ".h", filter_arguments, function_name);
    }
    if (options.emit_cpp) {
        func.compile_to_c(base_path + ".cpp", filter_arguments, function_name, target);
    }
    if (options.emit_assembly) {
        func.compile_to_assembly(base_path + ".s", filter_arguments, function_name, target);
    }
    if (options.emit_bitcode) {
        func.compile_to_bitcode(base_path + ".bc", filter_arguments, function_name, target);
    }
    if (options.emit_stmt) {
        func.compile_to_lowered_stmt(base_path + ".stmt", Halide::Text, target);
    }
    if (options.emit_stmt_html) {
        func.compile_to_lowered_stmt(base_path + ".html", Halide::HTML, target);
    }
}

}  // namespace Internal
}  // namespace Halide

#endif  // __cplusplus > 199711L
<commit_msg>__user_context *is* allowed to start with underscore.<commit_after>// Generator requires C++11
#if __cplusplus > 199711L

#include "Generator.h"

namespace {

// Return true iff the name is valid for Generators or Params.
// (NOTE: gcc didn't add proper std::regex support until v4.9;
// we don't yet require this, hence the hand-rolled replacement.)

bool is_alpha(char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); }

// Note that this includes '_'
bool is_alnum(char c) { return is_alpha(c) || (c == '_') || (c >= '0' && c <= '9'); }

bool is_valid_name(const std::string& n) {
    if (n.empty()) {
        return false;
    }
    if (!is_alpha(n[0])) {
        // __user_context is allowed to start with non-alpha, but nothing else is
        return (n == "__user_context");
    }
    for (size_t i = 1; i < n.size(); ++i) {
        if (!is_alnum(n[i])) {
            return false;
        }
    }
    return true;
}

}  // namespace

namespace Halide {
namespace Internal {

int generate_filter_main(int argc, char **argv, std::ostream &cerr) {
    const char kUsage[] = "gengen [-g GENERATOR_NAME] [-f FUNCTION_NAME] [-o OUTPUT_DIR]  "
                          "target=target-string [generator_arg=value [...]]\n";

    std::map<std::string, std::string> flags_info = { { "-f", "" }, { "-g", "" }, { "-o", "" } };
    std::map<std::string, std::string> generator_args;

    for (int i = 1; i < argc; ++i) {
        if (argv[i][0] != '-') {
            std::vector<std::string> v = split_string(argv[i], "=");
            if (v.size() != 2 || v[0].empty() || v[1].empty()) {
                cerr << kUsage;
                return 1;
            }
            generator_args[v[0]] = v[1];
            continue;
        }
        auto it = flags_info.find(argv[i]);
        if (it != flags_info.end()) {
            if (i + 1 >= argc) {
                cerr << kUsage;
                return 1;
            }
            it->second = argv[i + 1];
            ++i;
            continue;
        }
        cerr << "Unknown flag: " << argv[i] << "\n";
        cerr << kUsage;
        return 1;
    }

    std::vector<std::string> generator_names = Internal::GeneratorRegistry::enumerate();
    if (generator_names.size() == 0) {
        cerr << "No generators have been registered\n";
        cerr << kUsage;
        return 1;
    }

    std::string generator_name = flags_info["-g"];
    if (generator_name.empty()) {
        // If -g isn't specified, but there's only one generator registered, just use that one.
        if (generator_names.size() != 1) {
            cerr << "-g must be specified if multiple generators are registered\n";
            cerr << kUsage;
            return 1;
        }
        generator_name = generator_names[0];
    }
    std::string function_name = flags_info["-f"];
    if (function_name.empty()) {
        // If -f isn't specified, but there's only one generator registered,
        // just assume function name = generator name.
        if (generator_names.size() != 1) {
            cerr << "-f must be specified if multiple generators are registered\n";
            cerr << kUsage;
            return 1;
        }
        function_name = generator_names[0];
    }
    std::string output_dir = flags_info["-o"];
    if (output_dir.empty()) {
        cerr << "-o must always be specified.\n";
        cerr << kUsage;
        return 1;
    }
    if (generator_args.find("target") == generator_args.end()) {
        cerr << "Target missing\n";
        cerr << kUsage;
        return 1;
    }

    std::unique_ptr<GeneratorBase> gen =
        Internal::GeneratorRegistry::create(generator_name, generator_args);
    if (gen == nullptr) {
        cerr << "Unknown generator: " << generator_name << "\n";
        cerr << kUsage;
        return 1;
    }
    gen->emit_filter(output_dir, function_name);
    return 0;
}

GeneratorParamBase::GeneratorParamBase(const std::string &name) : name(name) {
    ObjectInstanceRegistry::register_instance(this, 0, ObjectInstanceRegistry::GeneratorParam,
                                              this);
}

GeneratorParamBase::~GeneratorParamBase() { ObjectInstanceRegistry::unregister_instance(this); }

/* static */
GeneratorRegistry &GeneratorRegistry::get_registry() {
    static GeneratorRegistry *registry = new GeneratorRegistry;
    return *registry;
}

/* static */
void GeneratorRegistry::register_factory(const std::string &name,
                                         std::unique_ptr<GeneratorFactory> factory) {
    user_assert(is_valid_name(name)) << "Invalid Generator name: " << name;
    GeneratorRegistry &registry = get_registry();
    std::lock_guard<std::mutex> lock(registry.mutex);
    internal_assert(registry.factories.find(name) == registry.factories.end())
        << "Duplicate Generator name: " << name;
    registry.factories[name] = std::move(factory);
}

/* static */
void GeneratorRegistry::unregister_factory(const std::string &name) {
    GeneratorRegistry &registry = get_registry();
    std::lock_guard<std::mutex> lock(registry.mutex);
    internal_assert(registry.factories.find(name) != registry.factories.end())
        << "Generator not found: " << name;
    registry.factories.erase(name);
}

/* static */
std::unique_ptr<GeneratorBase> GeneratorRegistry::create(const std::string &name,
                                                         const GeneratorParamValues &params) {
    GeneratorRegistry &registry = get_registry();
    std::lock_guard<std::mutex> lock(registry.mutex);
    auto it = registry.factories.find(name);
    user_assert(it != registry.factories.end()) << "Generator not found: " << name;
    return it->second->create(params);
}

/* static */
std::vector<std::string> GeneratorRegistry::enumerate() {
    GeneratorRegistry &registry = get_registry();
    std::lock_guard<std::mutex> lock(registry.mutex);
    std::vector<std::string> result;
    for (auto it = registry.factories.begin(); it != registry.factories.end(); ++it) {
        result.push_back(it->first);
    }
    return result;
}

GeneratorBase::GeneratorBase(size_t size) : size(size), params_built(false) {
    ObjectInstanceRegistry::register_instance(this, size, ObjectInstanceRegistry::Generator, this);
}

GeneratorBase::~GeneratorBase() { ObjectInstanceRegistry::unregister_instance(this); }

void GeneratorBase::build_params() {
    if (!params_built) {
        std::vector<void *> vf = ObjectInstanceRegistry::instances_in_range(
            this, size, ObjectInstanceRegistry::FilterParam);
        for (size_t i = 0; i < vf.size(); ++i) {
            Parameter *param = static_cast<Parameter *>(vf[i]);
            internal_assert(param != nullptr);
            user_assert(param->is_explicit_name()) << "Params in Generators must have explicit names: " << param->name();
            user_assert(is_valid_name(param->name())) << "Invalid Param name: " << param->name();
            user_assert(filter_params.find(param->name()) == filter_params.end())
                << "Duplicate Param name: " << param->name();
            filter_params[param->name()] = param;
            filter_arguments.push_back(Argument(param->name(), param->is_buffer(), param->type()));
        }

        std::vector<void *> vg = ObjectInstanceRegistry::instances_in_range(
            this, size, ObjectInstanceRegistry::GeneratorParam);
        for (size_t i = 0; i < vg.size(); ++i) {
            GeneratorParamBase *param = static_cast<GeneratorParamBase *>(vg[i]);
            internal_assert(param != nullptr);
            user_assert(is_valid_name(param->name)) << "Invalid GeneratorParam name: " << param->name;
            user_assert(generator_params.find(param->name) == generator_params.end())
                << "Duplicate GeneratorParam name: " << param->name;
            generator_params[param->name] = param;
        }
        params_built = true;
    }
}

void GeneratorBase::set_generator_param_values(const GeneratorParamValues &params) {
    build_params();
    for (auto key_value : params) {
        const std::string &key = key_value.first;
        const std::string &value = key_value.second;
        auto param = generator_params.find(key);
        user_assert(param != generator_params.end())
            << "Generator has no GeneratorParam named: " << key;
        param->second->set_from_string(value);
    }
}

void GeneratorBase::emit_filter(const std::string &output_dir, const std::string &function_name,
                                const std::string &file_base_name, const EmitOptions &options) {
    Func func = build();

    build_params();

    std::string base_path = file_base_name.empty() ?
        output_dir + "/" + function_name :
        output_dir + "/" + file_base_name;
    if (options.emit_o) {
        func.compile_to_object(base_path + ".o", filter_arguments, function_name, target);
    }
    if (options.emit_h) {
        func.compile_to_header(base_path + ".h", filter_arguments, function_name);
    }
    if (options.emit_cpp) {
        func.compile_to_c(base_path + ".cpp", filter_arguments, function_name, target);
    }
    if (options.emit_assembly) {
        func.compile_to_assembly(base_path + ".s", filter_arguments, function_name, target);
    }
    if (options.emit_bitcode) {
        func.compile_to_bitcode(base_path + ".bc", filter_arguments, function_name, target);
    }
    if (options.emit_stmt) {
        func.compile_to_lowered_stmt(base_path + ".stmt", Halide::Text, target);
    }
    if (options.emit_stmt_html) {
        func.compile_to_lowered_stmt(base_path + ".html", Halide::HTML, target);
    }
}

}  // namespace Internal
}  // namespace Halide

#endif  // __cplusplus > 199711L
<|endoftext|>


<commit_before>#include <string>
#include <map>

#include "JonTelldus.h"
#include "QueueInvoker.h"
#include "RawDeviceEventCallbackInvoker.h"
#include "SensorEventCallbackInvoker.h"
#include "GetDevicesWorker.h"
#include "IntIdWorker.h"

namespace JonTelldus {

  using v8::FunctionTemplate;
  using v8::Handle;
  using v8::Local;
  using v8::Isolate;
  using v8::Array;
  using v8::FunctionCallbackInfo;
  using v8::Value;
  using v8::Object;
  using v8::String;
  using v8::Number;
  using v8::Exception;
  using v8::Persistent;
  using v8::Function;

#define INT_ID_METHOD(name, fn) \
  NAN_METHOD(name) { \
    if (info.Length() < 2) { \
      Nan::ThrowSyntaxError("Missing arguments. Id and callback needed."); \
      return; \
    } \
    if (!info[0]->IsInt32()) { \
      Nan::ThrowSyntaxError("Id must be integer"); \
      return; \
    } \
    if (!info[1]->IsFunction()) { \
      Nan::ThrowSyntaxError("Callback must be function, duh"); \
      return; \
    } \
    Nan::Callback *callback = new Nan::Callback(info[1].As<Function>()); \
    Nan::AsyncQueueWorker(new IntIdWorker(callback, fn, info[0]->IntegerValue())); \
    info.GetReturnValue().Set(Nan::Undefined()); \
  }

  void sensorEventCallback(
      const char *protocol,
      const char *model,
      int id,
      int dataType,
      const char *value,
      int timestamp,
      int callbackId,
      void *context) {
    Nan::Callback *callback = static_cast<Nan::Callback *>(context);
    QueueCallback(new SensorEventCallbackInvoker(callback, protocol, model, id, dataType, value, timestamp));
  }

  NAN_METHOD(addSensorEventListener) {
    if (info.Length() < 1 || !info[0]->IsFunction()) {
      Nan::ThrowSyntaxError("argument must be function");
      return;
    }
    Nan::Callback *callback = new Nan::Callback(info[0].As<Function>());
    tdRegisterSensorEvent(&sensorEventCallback, callback);
    info.GetReturnValue().Set(Nan::Undefined());
  }

  void rawDeviceEventCallback(const char* data, int controllerId, int callbackId, void *context) {
    Nan::Callback *callback = static_cast<Nan::Callback *>(context);
    QueueCallback(new RawDeviceEventCallbackInvoker(callback, controllerId, data));
  }

  NAN_METHOD(addRawDeviceEventListener) {
    if (info.Length() < 1 || !info[0]->IsFunction()) {
      Nan::ThrowSyntaxError("argument must be function");
      return;
    }
    Nan::Callback *callback = new Nan::Callback(info[0].As<Function>());
    tdRegisterRawDeviceEvent(&rawDeviceEventCallback, callback);
    info.GetReturnValue().Set(Nan::Undefined());
  }

  NAN_METHOD(getDevices) {
    if (info.Length() < 1 || !info[0]->IsFunction()) {
      Nan::ThrowSyntaxError("argument must be function");
      return;
    }
    Nan::Callback *callback = new Nan::Callback(info[0].As<Function>());
    Nan::AsyncQueueWorker(new GetDevicesWorker(callback));
    info.GetReturnValue().Set(Nan::Undefined());
  }

  INT_ID_METHOD(up, tdUp);
  INT_ID_METHOD(down, tdDown);
  INT_ID_METHOD(bell, tdBell);
  INT_ID_METHOD(turnOn, tdTurnOn);
  INT_ID_METHOD(turnOff, tdTurnOff);
  INT_ID_METHOD(execute, tdExecute);
  INT_ID_METHOD(stop, tdStop);
  INT_ID_METHOD(learn, tdLearn);

  NAN_MODULE_INIT(Init) {
    tdInit();
    Set(target, "getDevices", Nan::GetFunction(Nan::New<FunctionTemplate>(getDevices)).ToLocalChecked());
    Set(target, "turnOn", Nan::GetFunction(Nan::New<FunctionTemplate>(turnOn)).ToLocalChecked());
    Set(target, "turnOff",Nan::GetFunction(Nan::New<FunctionTemplate>(turnOff)).ToLocalChecked());
    Set(target, "bell",Nan::GetFunction(Nan::New<FunctionTemplate>(bell)).ToLocalChecked());
    Set(target, "up",Nan::GetFunction(Nan::New<FunctionTemplate>(up)).ToLocalChecked());
    Set(target, "down",Nan::GetFunction(Nan::New<FunctionTemplate>(down)).ToLocalChecked());
    Set(target, "execute",Nan::GetFunction(Nan::New<FunctionTemplate>(execute)).ToLocalChecked());
    Set(target, "stop",Nan::GetFunction(Nan::New<FunctionTemplate>(stop)).ToLocalChecked());
    Set(target, "learn",Nan::GetFunction(Nan::New<FunctionTemplate>(learn)).ToLocalChecked());
    Set(target, "addRawDeviceEventListener", Nan::GetFunction(Nan::New<FunctionTemplate>(addRawDeviceEventListener)).ToLocalChecked());
    Set(target, "addSensorEventListener", Nan::GetFunction(Nan::New<FunctionTemplate>(addSensorEventListener)).ToLocalChecked());

    // "ENUMS"
    v8::PropertyAttribute readOnlyDontDelete = (v8::PropertyAttribute)(v8::ReadOnly|v8::DontDelete);
    // data type enum
    v8::Local<v8::Object> datatypesObj = Nan::New<v8::Object>();
    Set(datatypesObj, "Temperature", TELLSTICK_TEMPERATURE, readOnlyDontDelete);
    Set(datatypesObj, "Humidity", TELLSTICK_HUMIDITY, readOnlyDontDelete);
    Set(datatypesObj, "RainTotal", TELLSTICK_RAINTOTAL, readOnlyDontDelete);
    Set(datatypesObj, "RainRate", TELLSTICK_RAINRATE, readOnlyDontDelete);
    Set(datatypesObj, "WindDirection", TELLSTICK_WINDDIRECTION, readOnlyDontDelete);
    Set(datatypesObj, "WindAverage", TELLSTICK_WINDAVERAGE, readOnlyDontDelete);
    Set(datatypesObj, "WindGust", TELLSTICK_WINDGUST, readOnlyDontDelete);
    Set(target, "sensorValueType", datatypesObj, readOnlyDontDelete);
    // methods enum
    v8::Local<v8::Object> methodsObj = Nan::New<v8::Object>();
    Set(methodsObj, "TurnOn", TELLSTICK_TURNON, readOnlyDontDelete);
    Set(methodsObj, "TurnOff", TELLSTICK_TURNOFF, readOnlyDontDelete);
    Set(methodsObj, "Bell", TELLSTICK_BELL, readOnlyDontDelete);
    Set(methodsObj, "Toggle", TELLSTICK_TOGGLE, readOnlyDontDelete);
    Set(methodsObj, "Dim", TELLSTICK_DIM, readOnlyDontDelete);
    Set(methodsObj, "Execute", TELLSTICK_EXECUTE, readOnlyDontDelete);
    Set(methodsObj, "Up", TELLSTICK_UP, readOnlyDontDelete);
    Set(methodsObj, "Down", TELLSTICK_DOWN, readOnlyDontDelete);
    Set(methodsObj, "Stop", TELLSTICK_STOP, readOnlyDontDelete);
    Set(target, "method", methodsObj, readOnlyDontDelete);
    // error codes
    v8::Local<v8::Object> errorObj = Nan::New<v8::Object>();
    Set(errorObj, "NoError", TELLSTICK_SUCCESS, readOnlyDontDelete);
    Set(errorObj, "NotFound", TELLSTICK_ERROR_NOT_FOUND, readOnlyDontDelete);
    Set(errorObj, "PermissionDenied", TELLSTICK_ERROR_PERMISSION_DENIED, readOnlyDontDelete);
    Set(errorObj, "DeviceNotFound", TELLSTICK_ERROR_DEVICE_NOT_FOUND, readOnlyDontDelete);
    Set(errorObj, "MethodNotSupported", TELLSTICK_ERROR_METHOD_NOT_SUPPORTED, readOnlyDontDelete);
    Set(errorObj, "Communication", TELLSTICK_ERROR_COMMUNICATION, readOnlyDontDelete);
    Set(errorObj, "ConnectingService", TELLSTICK_ERROR_CONNECTING_SERVICE, readOnlyDontDelete);
    Set(errorObj, "UnknownResponse", TELLSTICK_ERROR_UNKNOWN_RESPONSE, readOnlyDontDelete);
    Set(errorObj, "Syntax", TELLSTICK_ERROR_SYNTAX, readOnlyDontDelete);
    Set(errorObj, "BrokenPipe", TELLSTICK_ERROR_BROKEN_PIPE, readOnlyDontDelete);
    Set(errorObj, "CommunicatingService", TELLSTICK_ERROR_COMMUNICATING_SERVICE, readOnlyDontDelete);
    Set(errorObj, "Unknown", TELLSTICK_ERROR_UNKNOWN, readOnlyDontDelete);
    Set(target, "errorCode", errorObj, readOnlyDontDelete);
  }
  NODE_MODULE(jontelldus, Init)
}
<commit_msg>Refactorized enums<commit_after>#include <string>
#include <map>

#include "JonTelldus.h"
#include "QueueInvoker.h"
#include "RawDeviceEventCallbackInvoker.h"
#include "SensorEventCallbackInvoker.h"
#include "GetDevicesWorker.h"
#include "IntIdWorker.h"

namespace JonTelldus {

  using v8::FunctionTemplate;
  using v8::Handle;
  using v8::Local;
  using v8::Isolate;
  using v8::Array;
  using v8::FunctionCallbackInfo;
  using v8::Value;
  using v8::Object;
  using v8::String;
  using v8::Number;
  using v8::Exception;
  using v8::Persistent;
  using v8::Function;

  struct keyvalue {
    const char *key;
    int value;
  };

  struct keyvalue sensorValueTypes[] = {
    {"Temperature", TELLSTICK_TEMPERATURE },
    {"Humidity", TELLSTICK_HUMIDITY },
    {"RainTotal", TELLSTICK_RAINTOTAL },
    {"RainRate", TELLSTICK_RAINRATE },
    {"WindDirection", TELLSTICK_WINDDIRECTION },
    {"WindAverage", TELLSTICK_WINDAVERAGE },
    {"WindGust", TELLSTICK_WINDGUST }
  };
  struct keyvalue methods[] = {
    { "TurnOn", TELLSTICK_TURNON },
    { "TurnOff", TELLSTICK_TURNOFF },
    { "Bell", TELLSTICK_BELL },
    { "Toggle", TELLSTICK_TOGGLE },
    { "Dim", TELLSTICK_DIM },
    { "Execute", TELLSTICK_EXECUTE },
    { "Up", TELLSTICK_UP},
    { "Down", TELLSTICK_DOWN },
    { "Stop", TELLSTICK_STOP },
  };
  struct keyvalue errorCodes[] = {
    { "NoError", TELLSTICK_SUCCESS },
    { "NotFound", TELLSTICK_ERROR_NOT_FOUND },
    { "PermissionDenied", TELLSTICK_ERROR_PERMISSION_DENIED },
    { "DeviceNotFound", TELLSTICK_ERROR_DEVICE_NOT_FOUND },
    { "MethodNotSupported", TELLSTICK_ERROR_METHOD_NOT_SUPPORTED },
    { "Communication", TELLSTICK_ERROR_COMMUNICATION },
    { "ConnectingService", TELLSTICK_ERROR_CONNECTING_SERVICE },
    { "UnknownResponse", TELLSTICK_ERROR_UNKNOWN_RESPONSE },
    { "Syntax", TELLSTICK_ERROR_SYNTAX },
    { "BrokenPipe", TELLSTICK_ERROR_BROKEN_PIPE },
    { "CommunicatingService", TELLSTICK_ERROR_COMMUNICATING_SERVICE },
    { "Unknown", TELLSTICK_ERROR_UNKNOWN }
  };

#define INT_ID_METHOD(name, fn) \
  NAN_METHOD(name) { \
    if (info.Length() < 2) { \
      Nan::ThrowSyntaxError("Missing arguments. Id and callback needed."); \
      return; \
    } \
    if (!info[0]->IsInt32()) { \
      Nan::ThrowSyntaxError("Id must be integer"); \
      return; \
    } \
    if (!info[1]->IsFunction()) { \
      Nan::ThrowSyntaxError("Callback must be function, duh"); \
      return; \
    } \
    Nan::Callback *callback = new Nan::Callback(info[1].As<Function>()); \
    Nan::AsyncQueueWorker(new IntIdWorker(callback, fn, info[0]->IntegerValue())); \
    info.GetReturnValue().Set(Nan::Undefined()); \
  }

  void sensorEventCallback(
      const char *protocol,
      const char *model,
      int id,
      int dataType,
      const char *value,
      int timestamp,
      int callbackId,
      void *context) {
    Nan::Callback *callback = static_cast<Nan::Callback *>(context);
    QueueCallback(new SensorEventCallbackInvoker(callback, protocol, model, id, dataType, value, timestamp));
  }

  NAN_METHOD(addSensorEventListener) {
    if (info.Length() < 1 || !info[0]->IsFunction()) {
      Nan::ThrowSyntaxError("argument must be function");
      return;
    }
    Nan::Callback *callback = new Nan::Callback(info[0].As<Function>());
    tdRegisterSensorEvent(&sensorEventCallback, callback);
    info.GetReturnValue().Set(Nan::Undefined());
  }

  void rawDeviceEventCallback(const char* data, int controllerId, int callbackId, void *context) {
    Nan::Callback *callback = static_cast<Nan::Callback *>(context);
    QueueCallback(new RawDeviceEventCallbackInvoker(callback, controllerId, data));
  }

  NAN_METHOD(addRawDeviceEventListener) {
    if (info.Length() < 1 || !info[0]->IsFunction()) {
      Nan::ThrowSyntaxError("argument must be function");
      return;
    }
    Nan::Callback *callback = new Nan::Callback(info[0].As<Function>());
    tdRegisterRawDeviceEvent(&rawDeviceEventCallback, callback);
    info.GetReturnValue().Set(Nan::Undefined());
  }

  NAN_METHOD(getDevices) {
    if (info.Length() < 1 || !info[0]->IsFunction()) {
      Nan::ThrowSyntaxError("argument must be function");
      return;
    }
    Nan::Callback *callback = new Nan::Callback(info[0].As<Function>());
    Nan::AsyncQueueWorker(new GetDevicesWorker(callback));
    info.GetReturnValue().Set(Nan::Undefined());
  }

  INT_ID_METHOD(up, tdUp);
  INT_ID_METHOD(down, tdDown);
  INT_ID_METHOD(bell, tdBell);
  INT_ID_METHOD(turnOn, tdTurnOn);
  INT_ID_METHOD(turnOff, tdTurnOff);
  INT_ID_METHOD(execute, tdExecute);
  INT_ID_METHOD(stop, tdStop);
  INT_ID_METHOD(learn, tdLearn);

  NAN_MODULE_INIT(Init) {
    tdInit();
    Set(target, "getDevices", Nan::GetFunction(Nan::New<FunctionTemplate>(getDevices)).ToLocalChecked());
    Set(target, "turnOn", Nan::GetFunction(Nan::New<FunctionTemplate>(turnOn)).ToLocalChecked());
    Set(target, "turnOff",Nan::GetFunction(Nan::New<FunctionTemplate>(turnOff)).ToLocalChecked());
    Set(target, "bell",Nan::GetFunction(Nan::New<FunctionTemplate>(bell)).ToLocalChecked());
    Set(target, "up",Nan::GetFunction(Nan::New<FunctionTemplate>(up)).ToLocalChecked());
    Set(target, "down",Nan::GetFunction(Nan::New<FunctionTemplate>(down)).ToLocalChecked());
    Set(target, "execute",Nan::GetFunction(Nan::New<FunctionTemplate>(execute)).ToLocalChecked());
    Set(target, "stop",Nan::GetFunction(Nan::New<FunctionTemplate>(stop)).ToLocalChecked());
    Set(target, "learn",Nan::GetFunction(Nan::New<FunctionTemplate>(learn)).ToLocalChecked());
    Set(target, "addRawDeviceEventListener", Nan::GetFunction(Nan::New<FunctionTemplate>(addRawDeviceEventListener)).ToLocalChecked());
    Set(target, "addSensorEventListener", Nan::GetFunction(Nan::New<FunctionTemplate>(addSensorEventListener)).ToLocalChecked());

    // "ENUMS"
    v8::PropertyAttribute readOnlyDontDelete = (v8::PropertyAttribute)(v8::ReadOnly|v8::DontDelete);
    // data type enum
    v8::Local<v8::Object> sensorTypesObj = Nan::New<v8::Object>();
    for (auto& sensorValueType: sensorValueTypes)
      Set(sensorTypesObj, sensorValueType.key, sensorValueType.value, readOnlyDontDelete);
    Set(target, "sensorValueType", sensorTypesObj, readOnlyDontDelete);
    // methods enum
    v8::Local<v8::Object> methodsObj = Nan::New<v8::Object>();
    for (auto& method: methods)
      Set(methodsObj, method.key, method.value, readOnlyDontDelete);
    Set(target, "method", methodsObj, readOnlyDontDelete);
    // error codes
    v8::Local<v8::Object> errorObj = Nan::New<v8::Object>();
    for (auto& errorCode: errorCodes)
      Set(errorObj, errorCode.key, errorCode.value);
    Set(target, "errorCode", errorObj, readOnlyDontDelete);
  }
  NODE_MODULE(jontelldus, Init)
}
<|endoftext|>


<commit_before>#include <Vertica.h>
using Vertica::ScalarFunction;
using Vertica::ScalarFunctionFactory;

extern "C" {
#include <json/selector.h>
#include <json/slice.h>
}
#include "JsonCopyResult.hpp"

template<class Q>
class AbstractJsonQuery : public ScalarFunction {
public:

	virtual void processBlock(Vertica::ServerInterface &,
	                          Vertica::BlockReader &argReader,
	                          Vertica::BlockWriter &resWriter)
	{
		do {
			const Vertica::VString &jsonSrc = argReader.getStringRef(0);
			const Vertica::VString &querySrc = argReader.getStringRef(1);
			Vertica::VString &resSrc = resWriter.getStringRef();

			json_slice_t jsonIn = json_slice_new(jsonSrc.data(), jsonSrc.length());
			json_slice_t jsonOut;
			if (json_slice_query(&jsonIn,
			                     querySrc.data(), querySrc.length(),
			                     &jsonOut)) {
				Q::copyResult(jsonOut, resSrc);
			} else {
				resSrc.setNull();
			}
			resWriter.next();
		} while (argReader.next());
	}
};

class JsonQuery :
	public JsonValueResult,
	public AbstractJsonQuery<JsonQuery> {
};

class JsonQueryString :
	public JsonStringResult,
	public AbstractJsonQuery<JsonQueryString> {
};

class JsonQueryUnquoted :
	public JsonUnquotedResult,
	public AbstractJsonQuery<JsonQueryUnquoted> {
};

class AbstractJsonQueryFactory : public ScalarFunctionFactory {
public:

	explicit AbstractJsonQueryFactory()
	{
		vol = Vertica::IMMUTABLE;
		strict = Vertica::STRICT;
	}

	virtual void getPrototype(Vertica::ServerInterface &,
	                          Vertica::ColumnTypes &argTypes,
	                          Vertica::ColumnTypes &resTypes)
	{
		argTypes.addVarchar();
		argTypes.addVarchar();
		resTypes.addVarchar();
	}

	virtual void getReturnType(Vertica::ServerInterface &,
	                           const Vertica::SizedColumnTypes &argTypes,
	                           Vertica::SizedColumnTypes &resTypes)
	{
		const Vertica::VerticaType &jsonSrcType = argTypes.getColumnType(0);
		resTypes.addVarchar(jsonSrcType.getStringLength());
	}

	virtual void getPerInstanceResources(Vertica::ServerInterface &,
	                                     Vertica::VResources &resources)
	{
		resources.nFileHandles = 0;
		resources.scratchMemory = 0;
	}
};

class JsonQueryFactory : public AbstractJsonQueryFactory {
public:

	virtual ScalarFunction *createScalarFunction(Vertica::ServerInterface &iface)
	{
		return vt_createFuncObj(iface.allocator, JsonQuery);
	}
};

class JsonQueryStringFactory : public AbstractJsonQueryFactory {
public:

	virtual ScalarFunction *createScalarFunction(Vertica::ServerInterface &iface)
	{
		return vt_createFuncObj(iface.allocator, JsonQueryString);
	}
};

class JsonQueryUnquotedFactory : public AbstractJsonQueryFactory {
public:

	virtual ScalarFunction *createScalarFunction(Vertica::ServerInterface &iface)
	{
		return vt_createFuncObj(iface.allocator, JsonQueryUnquoted);
	}
};

RegisterFactory(JsonQueryFactory);
RegisterFactory(JsonQueryStringFactory);
RegisterFactory(JsonQueryUnquotedFactory);
<commit_msg>Use long varchars in JsonQuery.<commit_after>#include <Vertica.h>
using Vertica::ScalarFunction;
using Vertica::ScalarFunctionFactory;

extern "C" {
#include <json/selector.h>
#include <json/slice.h>
}
#include "JsonCopyResult.hpp"

template<class Q>
class AbstractJsonQuery : public ScalarFunction {
public:

	virtual void processBlock(Vertica::ServerInterface &,
	                          Vertica::BlockReader &argReader,
	                          Vertica::BlockWriter &resWriter)
	{
		do {
			const Vertica::VString &jsonSrc = argReader.getStringRef(0);
			const Vertica::VString &querySrc = argReader.getStringRef(1);
			Vertica::VString &resSrc = resWriter.getStringRef();

			json_slice_t jsonIn = json_slice_new(jsonSrc.data(), jsonSrc.length());
			json_slice_t jsonOut;
			if (json_slice_query(&jsonIn,
			                     querySrc.data(), querySrc.length(),
			                     &jsonOut)) {
				Q::copyResult(jsonOut, resSrc);
			} else {
				resSrc.setNull();
			}
			resWriter.next();
		} while (argReader.next());
	}
};

class JsonQuery :
	public JsonValueResult,
	public AbstractJsonQuery<JsonQuery> {
};

class JsonQueryString :
	public JsonStringResult,
	public AbstractJsonQuery<JsonQueryString> {
};

class JsonQueryUnquoted :
	public JsonUnquotedResult,
	public AbstractJsonQuery<JsonQueryUnquoted> {
};

class AbstractJsonQueryFactory : public ScalarFunctionFactory {
public:

	explicit AbstractJsonQueryFactory()
	{
		vol = Vertica::IMMUTABLE;
		strict = Vertica::STRICT;
	}

	virtual void getPrototype(Vertica::ServerInterface &,
	                          Vertica::ColumnTypes &argTypes,
	                          Vertica::ColumnTypes &resTypes)
	{
		argTypes.addLongVarchar();
		argTypes.addLongVarchar();
		resTypes.addLongVarchar();
	}

	virtual void getReturnType(Vertica::ServerInterface &,
	                           const Vertica::SizedColumnTypes &argTypes,
	                           Vertica::SizedColumnTypes &resTypes)
	{
		const Vertica::VerticaType &jsonSrcType = argTypes.getColumnType(0);
		resTypes.addLongVarchar(jsonSrcType.getStringLength());
	}

	virtual void getPerInstanceResources(Vertica::ServerInterface &,
	                                     Vertica::VResources &resources)
	{
		resources.nFileHandles = 0;
		resources.scratchMemory = 0;
	}
};

class JsonQueryFactory : public AbstractJsonQueryFactory {
public:

	virtual ScalarFunction *createScalarFunction(Vertica::ServerInterface &iface)
	{
		return vt_createFuncObj(iface.allocator, JsonQuery);
	}
};

class JsonQueryStringFactory : public AbstractJsonQueryFactory {
public:

	virtual ScalarFunction *createScalarFunction(Vertica::ServerInterface &iface)
	{
		return vt_createFuncObj(iface.allocator, JsonQueryString);
	}
};

class JsonQueryUnquotedFactory : public AbstractJsonQueryFactory {
public:

	virtual ScalarFunction *createScalarFunction(Vertica::ServerInterface &iface)
	{
		return vt_createFuncObj(iface.allocator, JsonQueryUnquoted);
	}
};

RegisterFactory(JsonQueryFactory);
RegisterFactory(JsonQueryStringFactory);
RegisterFactory(JsonQueryUnquotedFactory);
<|endoftext|>


<commit_before>#include "Landmarks.hh"

Landmarks::Landmark::Landmark()
{
  this->pos[0] = 0.0;
  this->pos[1] = 0.0;
  this->id = -1;
  this->life = LIFE;
  this->totalTimeObserved = 0;
  this->range = -1;
  this->bearing = -1;
}

Landmarks::Landmark::~Landmark()
{}

Landmarks::Landmarks(double degrees)
{
  this->DBSize = 0;
  this->EKFLandmarks = 0;
  this->degreePerScan = degrees;
  this->IDtoID.reserve(MAXLANDMARKS);
  this->landmarkDB.reserve(MAXLANDMARKS);
}

Landmarks::~Landmarks()
{}

int Landmarks::getDBSize() const
{
  return (this->DBSize);
}

int Landmarks::getSLamId(int id) const
{
  for(int i = 0; i < this->EKFLandmarks; ++i)
    {
      if(IDtoID[i].first == id)
	return (IDtoID[i].second);
    }
  return (-1);
}
<commit_msg>SLAM: add addSlamId function<commit_after>#include "Landmarks.hh"

Landmarks::Landmark::Landmark()
{
  this->pos[0] = 0.0;
  this->pos[1] = 0.0;
  this->id = -1;
  this->life = LIFE;
  this->totalTimeObserved = 0;
  this->range = -1;
  this->bearing = -1;
}

Landmarks::Landmark::~Landmark()
{}

Landmarks::Landmarks(double degrees)
{
  this->DBSize = 0;
  this->EKFLandmarks = 0;
  this->degreePerScan = degrees;
  this->IDtoID.reserve(MAXLANDMARKS);
  this->landmarkDB.reserve(MAXLANDMARKS);
}

Landmarks::~Landmarks()
{}

int Landmarks::getDBSize() const
{
  return (this->DBSize);
}

int Landmarks::getSLamId(int id) const
{
  for(int i = 0; i < this->EKFLandmarks; ++i)
    {
      if(IDtoID[i].first == id)
	return (IDtoID[i].second);
    }
  return (-1);
}

int Landmarks::addSlamId(int landmarkID, int slamID)
{
  std::pair<int, int> newSlamID;
  newSlamID.first = landmarkID;
  newSlamID.first = slamID;
  this->IDtoID.push_back(newSlamID);
  ++this->EKFLandmarks;
  return (0);
}
<|endoftext|>


<commit_before>/**
 * \file MainFrame.cpp
 * \brief Main Windows Class
 */

#include "MainFrame.h"

#include "icons.h"

BEGIN_EVENT_TABLE(MainFrame,wxFrame)
    EVT_MENU(ID_EXIT, MainFrame::OnExit)
    EVT_MENU(ID_OPEN, MainFrame::OpenReplay)
    EVT_MENU(ID_SAVE_AISCRIPT, MainFrame::SaveToAiscript)
    EVT_BUTTON(ID_RUN_BUTTON, MainFrame::RunAI)
    EVT_CLOSE(MainFrame::OnClose)
    EVT_COMBOBOX(ID_PLAYERSELECTION, MainFrame::SelectPlayer)
END_EVENT_TABLE()

MainFrame::MainFrame(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
: wxFrame(parent, id, title, position, size, style) {
    /**
    *   Constructor for the Main frame.
    */
    CreateGUIControls();
    replayFilename = "";
    playerSelected = false;
    replayOpen = false;
}

MainFrame::~MainFrame() {
    /**
    *   Destructor for the Main form.
    */
}

void MainFrame::CreateGUIControls() {
    /**
    *   Creates all of the GUI controls on the main form.
    */

    // Set window properties and title bar
    SetTitle(wxT("rep2ai"));
    SetIcon(wxNullIcon);

    // Menu Bar
    menuBar = new wxMenuBar();

    fileMenu = new wxMenu();
    fileMenu->Append(ID_OPEN, _T("&Open"));
    fileMenu->Append(ID_SAVE_AISCRIPT, _T("&Save to aiscript.bin"));
    fileMenu->Append(ID_EXIT, _T("&Quit"));
    menuBar->Append(fileMenu, _T("&File"));

    SetMenuBar(menuBar);

    // Main Panel
    sizer = new wxBoxSizer(wxVERTICAL);
    panel = new wxPanel(this);
    panel->SetSizer(sizer);

    // Controls
    controlsSizer = new wxBoxSizer(wxHORIZONTAL);
    sizer->Add(controlsSizer,0);

    // Player Selection
    playerSelectionLabel = new wxStaticText(panel, -1, wxT("Player:"));
    playerSelection = new wxComboBox(panel, ID_PLAYERSELECTION, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL,wxCB_READONLY|wxCB_SORT);
    playerSelection->Append(wxT("Open a Replay first"));

    controlsSizer->Add(playerSelectionLabel);
    controlsSizer->Add(playerSelection);

    // Run Button

    runButton = new wxBitmapButton(panel, ID_RUN_BUTTON, wxBitmap(controller_xpm));
    controlsSizer->Add(runButton);

    // Text Area

    text = new wxTextCtrl(panel, ID_TEXT, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxVSCROLL|wxHSCROLL|wxNO_BORDER|wxTE_READONLY|wxTE_MULTILINE);
    sizer->Add(text,1,wxEXPAND|wxALL);
}

void MainFrame::OnClose(wxCloseEvent& event) {
    /**
    *   Event handler for the form closing event
    *   Exit the ChaosConnect Program
    */
    exit(0);
}

void MainFrame::OnExit( wxCommandEvent& event ) {
    /**
    *   Event handler for the form closing event
    *   Exit the ChaosConnect Program
    */
    exit(0);
}

void MainFrame::OpenReplay( wxCommandEvent& event ) {
    /**
    *   Event handler opening a replay
    */
    wxFileDialog file_dialog(this, wxT("Select a replay to open"), wxT(""), wxT(""), wxT("*.rep"), wxOPEN);
    file_dialog.ShowModal();

    replayFilename = file_dialog.GetPath();

    *text << "Opening replay " << replayFilename << "...\n";

    replay = new Replay((char*)replayFilename.c_str());

    *text << "Parsing Player List...\n";

    playerSelection->Clear();
    for(int i = 0; i < 8; i++) {
        if (replay->playerID[i] > -1 ) {
            playerSelection->Append(wxString(replay->playerName[i]));
        }
    }

    replayOpen = true;
    playerSelected = false;
}

void MainFrame::SaveToAiscript( wxCommandEvent& event ) {
    /**
    *   Event handler opening a replay
    */
    if ( replayOpen && playerSelected ) {
        wxFileDialog file_dialog(this, wxT("Select a replay to open"), wxT(""), wxT("aiscript.bin"), wxT("*.bin"), wxSAVE);
        file_dialog.ShowModal();

        wxString filename = file_dialog.GetPath();

        *text << "Saving AI as " << filename << "...\n";

        rep2ai->saveToAiscript((char*)filename.c_str());
    }
}

void MainFrame::SelectPlayer( wxCommandEvent& event ) {
    /**
    *   Event handler for selecting a player
    */
	wxString player(playerSelection->GetString(playerSelection->GetCurrentSelection()));

	if(replayFilename == "") return;

    rep2ai = new Rep2AI(replay);

    *text << "Creating AI script for " << player << "...\n";

	rep2ai->findPlayer((char*)player.c_str());

    *text << "Writing aiscript.bin...\n";
	rep2ai->makeAI();

    *text << "Build Order:\n" << rep2ai->getBuildOrderAsText();

    playerSelected = true;
}

void MainFrame::RunAI( wxCommandEvent& event ) {
    /**
    *   Event handler for running the AI
    */
    if ( replayOpen && playerSelected ) {
        rep2ai->runAI();
    }
}
<commit_msg>- updated dialog box text<commit_after>/**
 * \file MainFrame.cpp
 * \brief Main Windows Class
 */

#include "MainFrame.h"

#include "icons.h"

BEGIN_EVENT_TABLE(MainFrame,wxFrame)
    EVT_MENU(ID_EXIT, MainFrame::OnExit)
    EVT_MENU(ID_OPEN, MainFrame::OpenReplay)
    EVT_MENU(ID_SAVE_AISCRIPT, MainFrame::SaveToAiscript)
    EVT_BUTTON(ID_RUN_BUTTON, MainFrame::RunAI)
    EVT_CLOSE(MainFrame::OnClose)
    EVT_COMBOBOX(ID_PLAYERSELECTION, MainFrame::SelectPlayer)
END_EVENT_TABLE()

MainFrame::MainFrame(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
: wxFrame(parent, id, title, position, size, style) {
    /**
    *   Constructor for the Main frame.
    */
    CreateGUIControls();
    replayFilename = "";
    playerSelected = false;
    replayOpen = false;
}

MainFrame::~MainFrame() {
    /**
    *   Destructor for the Main form.
    */
}

void MainFrame::CreateGUIControls() {
    /**
    *   Creates all of the GUI controls on the main form.
    */

    // Set window properties and title bar
    SetTitle(wxT("rep2ai"));
    SetIcon(wxNullIcon);

    // Menu Bar
    menuBar = new wxMenuBar();

    fileMenu = new wxMenu();
    fileMenu->Append(ID_OPEN, _T("&Open"));
    fileMenu->Append(ID_SAVE_AISCRIPT, _T("&Save to aiscript.bin"));
    fileMenu->Append(ID_EXIT, _T("&Quit"));
    menuBar->Append(fileMenu, _T("&File"));

    SetMenuBar(menuBar);

    // Main Panel
    sizer = new wxBoxSizer(wxVERTICAL);
    panel = new wxPanel(this);
    panel->SetSizer(sizer);

    // Controls
    controlsSizer = new wxBoxSizer(wxHORIZONTAL);
    sizer->Add(controlsSizer,0);

    // Player Selection
    playerSelectionLabel = new wxStaticText(panel, -1, wxT("Player:"));
    playerSelection = new wxComboBox(panel, ID_PLAYERSELECTION, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL,wxCB_READONLY|wxCB_SORT);
    playerSelection->Append(wxT("Open a Replay first"));

    controlsSizer->Add(playerSelectionLabel);
    controlsSizer->Add(playerSelection);

    // Run Button

    runButton = new wxBitmapButton(panel, ID_RUN_BUTTON, wxBitmap(controller_xpm));
    controlsSizer->Add(runButton);

    // Text Area

    text = new wxTextCtrl(panel, ID_TEXT, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxVSCROLL|wxHSCROLL|wxNO_BORDER|wxTE_READONLY|wxTE_MULTILINE);
    sizer->Add(text,1,wxEXPAND|wxALL);
}

void MainFrame::OnClose(wxCloseEvent& event) {
    /**
    *   Event handler for the form closing event
    *   Exit the ChaosConnect Program
    */
    exit(0);
}

void MainFrame::OnExit( wxCommandEvent& event ) {
    /**
    *   Event handler for the form closing event
    *   Exit the ChaosConnect Program
    */
    exit(0);
}

void MainFrame::OpenReplay( wxCommandEvent& event ) {
    /**
    *   Event handler opening a replay
    */
    wxFileDialog file_dialog(this, wxT("Select a replay to open"), wxT(""), wxT(""), wxT("*.rep"), wxOPEN);
    file_dialog.ShowModal();

    replayFilename = file_dialog.GetPath();

    *text << "Opening replay " << replayFilename << "...\n";

    replay = new Replay((char*)replayFilename.c_str());

    *text << "Parsing Player List...\n";

    playerSelection->Clear();
    for(int i = 0; i < 8; i++) {
        if (replay->playerID[i] > -1 ) {
            playerSelection->Append(wxString(replay->playerName[i]));
        }
    }

    replayOpen = true;
    playerSelected = false;
}

void MainFrame::SaveToAiscript( wxCommandEvent& event ) {
    /**
    *   Event handler opening a replay
    */
    if ( replayOpen && playerSelected ) {
        wxFileDialog file_dialog(this, wxT("Select location to save to"), wxT(""), wxT("aiscript.bin"), wxT("*.bin"), wxSAVE);
        file_dialog.ShowModal();

        wxString filename = file_dialog.GetPath();

        *text << "Saving AI as " << filename << "...\n";

        rep2ai->saveToAiscript((char*)filename.c_str());
    }
}

void MainFrame::SelectPlayer( wxCommandEvent& event ) {
    /**
    *   Event handler for selecting a player
    */
	wxString player(playerSelection->GetString(playerSelection->GetCurrentSelection()));

	if(replayFilename == "") return;

    rep2ai = new Rep2AI(replay);

    *text << "Creating AI script for " << player << "...\n";

	rep2ai->findPlayer((char*)player.c_str());

    *text << "Writing aiscript.bin...\n";
	rep2ai->makeAI();

    *text << "Build Order:\n" << rep2ai->getBuildOrderAsText();

    playerSelected = true;
}

void MainFrame::RunAI( wxCommandEvent& event ) {
    /**
    *   Event handler for running the AI
    */
    if ( replayOpen && playerSelected ) {
        rep2ai->runAI();
    }
}
<|endoftext|>


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

#include "MovieImpl.hpp"
#include "Demuxer.hpp"
#include "Timer.hpp"
#include "Log.hpp"
#include "Utilities.hpp"
#include <cmath>
#include <iostream>

namespace sfe {
	MovieImpl::MovieImpl(sf::Transformable& movieView) :
		m_movieView(movieView),
		m_demuxer(NULL),
		m_timer(NULL),
		m_videoSprite(),
		m_scaleX(1.0f),
		m_scaleY(1.0f)
	{
	}

	MovieImpl::~MovieImpl()
	{
		cleanResources();
	}

	bool MovieImpl::openFromFile(const std::string& filename)
	{
		cleanResources();

		try {
			m_timer = new Timer;
			m_demuxer = new Demuxer(filename, *m_timer, *this,*this);
			m_audioStreamsDesc = m_demuxer->computeStreamDescriptors(Audio);
			m_videoStreamsDesc = m_demuxer->computeStreamDescriptors(Video);
			m_subtitleStreamsDesc = m_demuxer->computeStreamDescriptors(Subtitle);

			std::set<Stream*> audioStreams = m_demuxer->getStreamsOfType(Audio);
			std::set<Stream*> videoStreams = m_demuxer->getStreamsOfType(Video);
			std::set<Stream*> subtitleStreams = m_demuxer->getStreamsOfType(Subtitle);

			m_demuxer->selectFirstAudioStream();
			m_demuxer->selectFirstVideoStream();
			m_demuxer->selectFirstSubtitleStream();

			if (!audioStreams.size() && !videoStreams.size()) {
				sfeLogError("Movie::openFromFile() - No supported audio or video stream in this media");
				cleanResources();
				return false;
			}
			else {
                if (videoStreams.size()) {
                    sf::Vector2i size = getSize();
                    m_displayFrame = sf::IntRect(0, 0, size.x, size.y);
                }

				return true;
			}
		}
		catch (std::runtime_error& e) {
			sfeLogError(e.what());
			cleanResources();
			return false;
		}
	}

	const Streams& MovieImpl::getStreams(MediaType type) const
	{
		switch (type) {
		case Audio: return m_audioStreamsDesc;
		case Video: return m_videoStreamsDesc;
		case Subtitle: return m_subtitleStreamsDesc;
		default: CHECK(false, "Movie::getStreams() - Unknown stream type:" + MediaTypeToString(type));
		}
	}

	void MovieImpl::selectStream(const StreamDescriptor& streamDescriptor)
	{
		if (!m_demuxer || !m_timer) {
			sfeLogError("Movie::selectStream() - cannot select a stream with no opened media");
			return;
		}

		if (m_timer->getStatus() != Stopped) {
			sfeLogError("Movie::selectStream() - cannot select a stream while media is not stopped");
			return;
		}

		std::map<int, Stream*> streams = m_demuxer->getStreams();
		std::map<int, Stream*>::iterator it = streams.find(streamDescriptor.identifier);
		Stream* streamToSelect = NULL;

		if (it != streams.end()) {
			streamToSelect = it->second;
		}

		switch (streamDescriptor.type) {
		case Audio:
			m_demuxer->selectAudioStream(dynamic_cast<AudioStream*>(streamToSelect));
			break;
		case Video:
			m_demuxer->selectVideoStream(dynamic_cast<VideoStream*>(streamToSelect));
			break;
		case Subtitle:
			m_demuxer->selectSubtitleStream(dynamic_cast<SubtitleStream*>(streamToSelect));
			break;
		default:
			sfeLogWarning("Movie::selectStream() - stream activation for stream of kind "
				+ MediaTypeToString(it->second->getStreamKind()) + " is not supported");
			break;
		}
	}

	void MovieImpl::play()
	{
		if (m_demuxer && m_timer) {
			if (m_timer->getStatus() == Playing) {
				sfeLogError("Movie::play() - media is already playing");
				return;
			}

			m_timer->play();
			update();
		}
		else {
			sfeLogError("Movie::play() - No media loaded, cannot play");
		}
	}

	void MovieImpl::pause()
	{
		if (m_demuxer && m_timer) {
			if (m_timer->getStatus() == Paused) {
				sfeLogError("Movie::pause() - media is already paused");
				return;
			}

			m_timer->pause();
			update();
		}
		else {
			sfeLogError("Movie::pause() - No media loaded, cannot pause");
		}
	}

	void MovieImpl::stop()
	{
		if (m_demuxer && m_timer) {
			if (m_timer->getStatus() == Stopped) {
				sfeLogError("Movie::stop() - media is already stopped");
				return;
			}

			m_timer->stop();
			update();
		}
		else {
			sfeLogError("Movie::stop() - No media loaded, cannot stop");
		}
	}

	void MovieImpl::update()
	{
		if (m_demuxer && m_timer) {
			m_demuxer->update();

			if (getStatus() == Stopped && m_timer->getStatus() != Stopped) {
				m_timer->stop();
			}

			// Enable smoothing when the video is scaled
			sfe::VideoStream* vStream = m_demuxer->getSelectedVideoStream();
			if (vStream) {
				sf::Vector2f movieScale = m_movieView.getScale();
				sf::Vector2f subviewScale = m_videoSprite.getScale();

				if (std::fabs(movieScale.x - 1.f) < 0.00001 &&
					std::fabs(movieScale.y - 1.f) < 0.00001 &&
					std::fabs(subviewScale.x - 1.f) < 0.00001 &&
					std::fabs(subviewScale.y - 1.f) < 0.00001)
				{
					vStream->getVideoTexture().setSmooth(false);
				}
				else
				{
					vStream->getVideoTexture().setSmooth(true);
				}
			}
		}
		else {
			sfeLogWarning("Movie::update() - No media loaded, nothing to update");
		}
	}

	void MovieImpl::setVolume(float volume)
	{
		if (m_demuxer && m_timer) {
			std::set<Stream*> audioStreams = m_demuxer->getStreamsOfType(Audio);
			std::set<Stream*>::const_iterator it;

			for (it = audioStreams.begin(); it != audioStreams.end(); it++) {
				AudioStream* audioStream = dynamic_cast<AudioStream*>(*it);
				audioStream->setVolume(volume);
			}
		}
		else {
			sfeLogError("Movie::setVolume() - No media loaded, cannot set volume");
		}
	}

	float MovieImpl::getVolume() const
	{
		if (m_demuxer && m_timer) {
			AudioStream* audioStream = m_demuxer->getSelectedAudioStream();

			if (audioStream)
				return audioStream->getVolume();
		}

		sfeLogError("Movie::getVolume() - No selected audio stream or no media loaded, cannot return a volume");
		return 0;
	}

	sf::Time MovieImpl::getDuration() const
	{
		if (m_demuxer && m_timer) {
			return m_demuxer->getDuration();
		}

		sfeLogError("Movie::getDuration() - No media loaded, cannot return a duration");
		return sf::Time::Zero;
	}

	sf::Vector2i MovieImpl::getSize() const
	{
		if (m_demuxer && m_timer) {
			VideoStream* videoStream = m_demuxer->getSelectedVideoStream();

			if (videoStream) {
				return videoStream->getFrameSize();
			}
		}
		sfeLogError("Movie::getSize() called but there is no active video stream");
		return sf::Vector2i(0, 0);
	}

	void MovieImpl::fit(int x, int y, int width, int height, bool preserveRatio)
	{
		fit(sf::IntRect(x, y, width, height), preserveRatio);
	}

	void MovieImpl::fit(sf::IntRect frame, bool preserveRatio)
	{
		sf::Vector2i movie_size = getSize();

		if (movie_size.x == 0 || movie_size.y == 0) {
			sfeLogError("Movie::fit() called but the video frame size is (0, 0)");
			return;
		}

		sf::Vector2i wanted_size = sf::Vector2i(frame.width, frame.height);
		sf::Vector2i new_size;

		if (preserveRatio)
		{
			sf::Vector2i target_size = movie_size;

			float source_ratio = (float)movie_size.x / movie_size.y;
			float target_ratio = (float)wanted_size.x / wanted_size.y;

			if (source_ratio > target_ratio)
			{
				target_size.x = movie_size.x * ((float)wanted_size.x / movie_size.x);
				target_size.y = movie_size.y * ((float)wanted_size.x / movie_size.x);
			}
			else
			{
				target_size.x = movie_size.x * ((float)wanted_size.y / movie_size.y);
				target_size.y = movie_size.y * ((float)wanted_size.y / movie_size.y);
			}

			new_size = target_size;
		}
		else
		{
			new_size = wanted_size;
		}

		m_videoSprite.setPosition(frame.left + (wanted_size.x - new_size.x) / 2,
			frame.top + (wanted_size.y - new_size.y) / 2);
		m_movieView.setPosition(frame.left, frame.top);
		m_scaleX = (float)new_size.x / movie_size.x;
		m_scaleY = (float)new_size.y / movie_size.y;
		m_videoSprite.setScale(m_scaleX, m_scaleY);
        m_displayFrame = frame;

		for (uint32_t i = 0; i < m_subtitleSprites.size(); ++i)
		{
			m_subtitleSprites[i].setScale(m_scaleX, m_scaleY);
		}
	}

	float MovieImpl::getFramerate() const
	{
		if (m_demuxer && m_timer) {
			VideoStream* videoStream = m_demuxer->getSelectedVideoStream();

			if (videoStream)
				return videoStream->getFrameRate();
		}

		sfeLogError("Movie::getFramerate() - No selected video stream or no media loaded, cannot return a frame rate");
		return 0;
	}

	unsigned int MovieImpl::getSampleRate() const
	{
		if (m_demuxer && m_timer) {
			AudioStream* audioStream = m_demuxer->getSelectedAudioStream();

			if (audioStream)
				return audioStream->getSampleRate();
		}

		sfeLogError("Movie::getSampleRate - No selected audio stream or no media loaded, cannot return a sample rate");
		return 0;
	}

	unsigned int MovieImpl::getChannelCount() const
	{
		if (m_demuxer && m_timer) {
			AudioStream* audioStream = m_demuxer->getSelectedAudioStream();
			if (audioStream)
				return audioStream->getChannelCount();
		}

		sfeLogError("Movie::getChannelCount() - No selected audio stream or no media loaded, cannot return a channel count");
		return 0;
	}

	Status MovieImpl::getStatus() const
	{
		Status st = Stopped;

		if (m_demuxer) {
			VideoStream* videoStream = m_demuxer->getSelectedVideoStream();
			AudioStream* audioStream = m_demuxer->getSelectedAudioStream();
			SubtitleStream* subtitleStream = m_demuxer->getSelectedSubtitleStream();
			Status vStatus = videoStream ? videoStream->getStatus() : Stopped;
			Status aStatus = audioStream ? audioStream->Stream::getStatus() : Stopped;
			Status sStatus = subtitleStream ? subtitleStream->getStatus() : Stopped;

			if (vStatus == Playing || aStatus == Playing || sStatus == Playing) {
				st = Playing;
			}
			else if (vStatus == Paused || aStatus == Paused || sStatus == Paused) {
				st = Paused;
			}

		}

		return st;
	}

	sf::Time MovieImpl::getPlayingOffset() const
	{
		if (m_demuxer && m_timer) {
			return m_timer->getOffset();
		}

		sfeLogError("Movie::getPlayingOffset() - No media loaded, cannot return a playing offset");
		return sf::Time::Zero;
	}

	const sf::Texture& MovieImpl::getCurrentImage() const
	{
		static sf::Texture emptyTexture;

		if (m_videoSprite.getTexture()) {
			return *m_videoSprite.getTexture();
		}
		else {
			return emptyTexture;
		}
	}

	void MovieImpl::cleanResources()
	{
		if (m_demuxer)
			delete m_demuxer, m_demuxer = NULL;

		if (m_timer)
			delete m_timer, m_timer = NULL;
	}

	void MovieImpl::draw(sf::RenderTarget& target, sf::RenderStates states) const
	{

		target.draw(m_videoSprite, states);
		for (uint32_t i = 0; i < m_subtitleSprites.size(); ++i)
		{
			target.draw(m_subtitleSprites[i], states);
            sfeLogWarning("draw sub");
		}
	}

	void MovieImpl::didUpdateVideo(const VideoStream& sender, const sf::Texture& image)
	{
		if (m_videoSprite.getTexture() != &image) {
			m_videoSprite.setTexture(image);
		}
	}

	void MovieImpl::didUpdateSubtitle(const SubtitleStream& sender, const std::vector<sf::Sprite>& subs,
                                      const std::vector<sf::Vector2u>& subSizes)
	{
		m_subtitleSprites = subs;

        sf::Vector2f subtitlesCenter(m_displayFrame.width / 2, m_displayFrame.height * 0.9);

		for (uint32_t i = 0; i < m_subtitleSprites.size(); ++i)
		{
            sf::Sprite& subtitleSprite = m_subtitleSprites[i];
            subtitleSprite.setPosition(subtitlesCenter.x - (subSizes[i].x / 2),
                                       subtitlesCenter.y - (subSizes[i].y / 2));
            subtitleSprite.setScale(m_scaleX, m_scaleY);
		}
	}
}
<commit_msg>#7 Make the subtitle correctly centered when scaling<commit_after>/*
*  MovieImpl.cpp
*  sfeMovie project
*
*  Copyright (C) 2010-2014 Lucas Soltic
*  lucas.soltic@orange.fr
*
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public
*  License as published by the Free Software Foundation; either
*  version 2.1 of the License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
*  Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public
*  License along with this program; if not, write to the Free Software
*  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/

#include "MovieImpl.hpp"
#include "Demuxer.hpp"
#include "Timer.hpp"
#include "Log.hpp"
#include "Utilities.hpp"
#include <cmath>
#include <iostream>

namespace sfe {
	MovieImpl::MovieImpl(sf::Transformable& movieView) :
		m_movieView(movieView),
		m_demuxer(NULL),
		m_timer(NULL),
		m_videoSprite(),
		m_scaleX(1.0f),
		m_scaleY(1.0f)
	{
	}

	MovieImpl::~MovieImpl()
	{
		cleanResources();
	}

	bool MovieImpl::openFromFile(const std::string& filename)
	{
		cleanResources();

		try {
			m_timer = new Timer;
			m_demuxer = new Demuxer(filename, *m_timer, *this,*this);
			m_audioStreamsDesc = m_demuxer->computeStreamDescriptors(Audio);
			m_videoStreamsDesc = m_demuxer->computeStreamDescriptors(Video);
			m_subtitleStreamsDesc = m_demuxer->computeStreamDescriptors(Subtitle);

			std::set<Stream*> audioStreams = m_demuxer->getStreamsOfType(Audio);
			std::set<Stream*> videoStreams = m_demuxer->getStreamsOfType(Video);
			std::set<Stream*> subtitleStreams = m_demuxer->getStreamsOfType(Subtitle);

			m_demuxer->selectFirstAudioStream();
			m_demuxer->selectFirstVideoStream();
			m_demuxer->selectFirstSubtitleStream();

			if (!audioStreams.size() && !videoStreams.size()) {
				sfeLogError("Movie::openFromFile() - No supported audio or video stream in this media");
				cleanResources();
				return false;
			}
			else {
                if (videoStreams.size()) {
                    sf::Vector2i size = getSize();
                    m_displayFrame = sf::IntRect(0, 0, size.x, size.y);
                }

				return true;
			}
		}
		catch (std::runtime_error& e) {
			sfeLogError(e.what());
			cleanResources();
			return false;
		}
	}

	const Streams& MovieImpl::getStreams(MediaType type) const
	{
		switch (type) {
		case Audio: return m_audioStreamsDesc;
		case Video: return m_videoStreamsDesc;
		case Subtitle: return m_subtitleStreamsDesc;
		default: CHECK(false, "Movie::getStreams() - Unknown stream type:" + MediaTypeToString(type));
		}
	}

	void MovieImpl::selectStream(const StreamDescriptor& streamDescriptor)
	{
		if (!m_demuxer || !m_timer) {
			sfeLogError("Movie::selectStream() - cannot select a stream with no opened media");
			return;
		}

		if (m_timer->getStatus() != Stopped) {
			sfeLogError("Movie::selectStream() - cannot select a stream while media is not stopped");
			return;
		}

		std::map<int, Stream*> streams = m_demuxer->getStreams();
		std::map<int, Stream*>::iterator it = streams.find(streamDescriptor.identifier);
		Stream* streamToSelect = NULL;

		if (it != streams.end()) {
			streamToSelect = it->second;
		}

		switch (streamDescriptor.type) {
		case Audio:
			m_demuxer->selectAudioStream(dynamic_cast<AudioStream*>(streamToSelect));
			break;
		case Video:
			m_demuxer->selectVideoStream(dynamic_cast<VideoStream*>(streamToSelect));
			break;
		case Subtitle:
			m_demuxer->selectSubtitleStream(dynamic_cast<SubtitleStream*>(streamToSelect));
			break;
		default:
			sfeLogWarning("Movie::selectStream() - stream activation for stream of kind "
				+ MediaTypeToString(it->second->getStreamKind()) + " is not supported");
			break;
		}
	}

	void MovieImpl::play()
	{
		if (m_demuxer && m_timer) {
			if (m_timer->getStatus() == Playing) {
				sfeLogError("Movie::play() - media is already playing");
				return;
			}

			m_timer->play();
			update();
		}
		else {
			sfeLogError("Movie::play() - No media loaded, cannot play");
		}
	}

	void MovieImpl::pause()
	{
		if (m_demuxer && m_timer) {
			if (m_timer->getStatus() == Paused) {
				sfeLogError("Movie::pause() - media is already paused");
				return;
			}

			m_timer->pause();
			update();
		}
		else {
			sfeLogError("Movie::pause() - No media loaded, cannot pause");
		}
	}

	void MovieImpl::stop()
	{
		if (m_demuxer && m_timer) {
			if (m_timer->getStatus() == Stopped) {
				sfeLogError("Movie::stop() - media is already stopped");
				return;
			}

			m_timer->stop();
			update();
		}
		else {
			sfeLogError("Movie::stop() - No media loaded, cannot stop");
		}
	}

	void MovieImpl::update()
	{
		if (m_demuxer && m_timer) {
			m_demuxer->update();

			if (getStatus() == Stopped && m_timer->getStatus() != Stopped) {
				m_timer->stop();
			}

			// Enable smoothing when the video is scaled
			sfe::VideoStream* vStream = m_demuxer->getSelectedVideoStream();
			if (vStream) {
				sf::Vector2f movieScale = m_movieView.getScale();
				sf::Vector2f subviewScale = m_videoSprite.getScale();

				if (std::fabs(movieScale.x - 1.f) < 0.00001 &&
					std::fabs(movieScale.y - 1.f) < 0.00001 &&
					std::fabs(subviewScale.x - 1.f) < 0.00001 &&
					std::fabs(subviewScale.y - 1.f) < 0.00001)
				{
					vStream->getVideoTexture().setSmooth(false);
				}
				else
				{
					vStream->getVideoTexture().setSmooth(true);
				}
			}
		}
		else {
			sfeLogWarning("Movie::update() - No media loaded, nothing to update");
		}
	}

	void MovieImpl::setVolume(float volume)
	{
		if (m_demuxer && m_timer) {
			std::set<Stream*> audioStreams = m_demuxer->getStreamsOfType(Audio);
			std::set<Stream*>::const_iterator it;

			for (it = audioStreams.begin(); it != audioStreams.end(); it++) {
				AudioStream* audioStream = dynamic_cast<AudioStream*>(*it);
				audioStream->setVolume(volume);
			}
		}
		else {
			sfeLogError("Movie::setVolume() - No media loaded, cannot set volume");
		}
	}

	float MovieImpl::getVolume() const
	{
		if (m_demuxer && m_timer) {
			AudioStream* audioStream = m_demuxer->getSelectedAudioStream();

			if (audioStream)
				return audioStream->getVolume();
		}

		sfeLogError("Movie::getVolume() - No selected audio stream or no media loaded, cannot return a volume");
		return 0;
	}

	sf::Time MovieImpl::getDuration() const
	{
		if (m_demuxer && m_timer) {
			return m_demuxer->getDuration();
		}

		sfeLogError("Movie::getDuration() - No media loaded, cannot return a duration");
		return sf::Time::Zero;
	}

	sf::Vector2i MovieImpl::getSize() const
	{
		if (m_demuxer && m_timer) {
			VideoStream* videoStream = m_demuxer->getSelectedVideoStream();

			if (videoStream) {
				return videoStream->getFrameSize();
			}
		}
		sfeLogError("Movie::getSize() called but there is no active video stream");
		return sf::Vector2i(0, 0);
	}

	void MovieImpl::fit(int x, int y, int width, int height, bool preserveRatio)
	{
		fit(sf::IntRect(x, y, width, height), preserveRatio);
	}

	void MovieImpl::fit(sf::IntRect frame, bool preserveRatio)
	{
		sf::Vector2i movie_size = getSize();

		if (movie_size.x == 0 || movie_size.y == 0) {
			sfeLogError("Movie::fit() called but the video frame size is (0, 0)");
			return;
		}

		sf::Vector2i wanted_size = sf::Vector2i(frame.width, frame.height);
		sf::Vector2i new_size;

		if (preserveRatio)
		{
			sf::Vector2i target_size = movie_size;

			float source_ratio = (float)movie_size.x / movie_size.y;
			float target_ratio = (float)wanted_size.x / wanted_size.y;

			if (source_ratio > target_ratio)
			{
				target_size.x = movie_size.x * ((float)wanted_size.x / movie_size.x);
				target_size.y = movie_size.y * ((float)wanted_size.x / movie_size.x);
			}
			else
			{
				target_size.x = movie_size.x * ((float)wanted_size.y / movie_size.y);
				target_size.y = movie_size.y * ((float)wanted_size.y / movie_size.y);
			}

			new_size = target_size;
		}
		else
		{
			new_size = wanted_size;
		}

		m_videoSprite.setPosition(frame.left + (wanted_size.x - new_size.x) / 2,
			frame.top + (wanted_size.y - new_size.y) / 2);
		m_movieView.setPosition(frame.left, frame.top);
		m_scaleX = (float)new_size.x / movie_size.x;
		m_scaleY = (float)new_size.y / movie_size.y;
		m_videoSprite.setScale(m_scaleX, m_scaleY);
        m_displayFrame = frame;

		for (uint32_t i = 0; i < m_subtitleSprites.size(); ++i)
		{
			m_subtitleSprites[i].setScale(m_scaleX, m_scaleY);
		}
	}

	float MovieImpl::getFramerate() const
	{
		if (m_demuxer && m_timer) {
			VideoStream* videoStream = m_demuxer->getSelectedVideoStream();

			if (videoStream)
				return videoStream->getFrameRate();
		}

		sfeLogError("Movie::getFramerate() - No selected video stream or no media loaded, cannot return a frame rate");
		return 0;
	}

	unsigned int MovieImpl::getSampleRate() const
	{
		if (m_demuxer && m_timer) {
			AudioStream* audioStream = m_demuxer->getSelectedAudioStream();

			if (audioStream)
				return audioStream->getSampleRate();
		}

		sfeLogError("Movie::getSampleRate - No selected audio stream or no media loaded, cannot return a sample rate");
		return 0;
	}

	unsigned int MovieImpl::getChannelCount() const
	{
		if (m_demuxer && m_timer) {
			AudioStream* audioStream = m_demuxer->getSelectedAudioStream();
			if (audioStream)
				return audioStream->getChannelCount();
		}

		sfeLogError("Movie::getChannelCount() - No selected audio stream or no media loaded, cannot return a channel count");
		return 0;
	}

	Status MovieImpl::getStatus() const
	{
		Status st = Stopped;

		if (m_demuxer) {
			VideoStream* videoStream = m_demuxer->getSelectedVideoStream();
			AudioStream* audioStream = m_demuxer->getSelectedAudioStream();
			SubtitleStream* subtitleStream = m_demuxer->getSelectedSubtitleStream();
			Status vStatus = videoStream ? videoStream->getStatus() : Stopped;
			Status aStatus = audioStream ? audioStream->Stream::getStatus() : Stopped;
			Status sStatus = subtitleStream ? subtitleStream->getStatus() : Stopped;

			if (vStatus == Playing || aStatus == Playing || sStatus == Playing) {
				st = Playing;
			}
			else if (vStatus == Paused || aStatus == Paused || sStatus == Paused) {
				st = Paused;
			}

		}

		return st;
	}

	sf::Time MovieImpl::getPlayingOffset() const
	{
		if (m_demuxer && m_timer) {
			return m_timer->getOffset();
		}

		sfeLogError("Movie::getPlayingOffset() - No media loaded, cannot return a playing offset");
		return sf::Time::Zero;
	}

	const sf::Texture& MovieImpl::getCurrentImage() const
	{
		static sf::Texture emptyTexture;

		if (m_videoSprite.getTexture()) {
			return *m_videoSprite.getTexture();
		}
		else {
			return emptyTexture;
		}
	}

	void MovieImpl::cleanResources()
	{
		if (m_demuxer)
			delete m_demuxer, m_demuxer = NULL;

		if (m_timer)
			delete m_timer, m_timer = NULL;
	}

	void MovieImpl::draw(sf::RenderTarget& target, sf::RenderStates states) const
	{

		target.draw(m_videoSprite, states);
		for (uint32_t i = 0; i < m_subtitleSprites.size(); ++i)
		{
			target.draw(m_subtitleSprites[i], states);
            sfeLogWarning("draw sub");
		}
	}

	void MovieImpl::didUpdateVideo(const VideoStream& sender, const sf::Texture& image)
	{
		if (m_videoSprite.getTexture() != &image) {
			m_videoSprite.setTexture(image);
		}
	}

	void MovieImpl::didUpdateSubtitle(const SubtitleStream& sender, const std::vector<sf::Sprite>& subs,
                                      const std::vector<sf::Vector2u>& subSizes)
	{
		m_subtitleSprites = subs;

        sf::Vector2f subtitlesCenter(m_displayFrame.width / 2, m_displayFrame.height * 0.9);

		for (uint32_t i = 0; i < m_subtitleSprites.size(); ++i)
		{
            sf::Sprite& subtitleSprite = m_subtitleSprites[i];
            subtitleSprite.setPosition(subtitlesCenter.x - (subSizes[i].x * m_scaleX / 2),
                                       subtitlesCenter.y - (subSizes[i].y * m_scaleY / 2));
            subtitleSprite.setScale(m_scaleX, m_scaleY);
		}
	}
}
<|endoftext|>


<commit_before>/*
The MIT License (MIT)

Copyright (c) 2013 rajendrauppal

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include <iostream>

bool Quadratic(int n)
{
	return true;
}

int main()
{
	return 0;
}
<commit_msg>Implemented Quadratic equation solver<commit_after>/*
The MIT License (MIT)

Copyright (c) 2013 rajendrauppal

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include <iostream>
#include <math.h>

using std::cout;
using std::cin;
using std::endl;
using std::sqrt;
using std::pow;

struct Roots
{
	double alpha;
	double beta;
};

/*
* Solves a quadratic equation of the form
* (a * x ^ 2 + b * x + c) = 0
* alpha = -b + sqrt(b ^ 2 - 4 * a * c) / 2 * a
* beta = -b - sqrt(b ^ 2 - 4 * a * c) / 2 * a
*/
Roots Quadratic(double a, double b, double c)
{
	Roots roots;
	double d = sqrt(pow(b, 2) - 4 * a * c);
	roots.alpha = ( -b + d ) / ( 2 * a );
	roots.beta = ( -b - d ) / ( 2 * a );
	return roots;
}

int main()
{
	// Tests - Solving quadratic equations
	Roots roots = Quadratic(3, 2, -1);	// 3x^2 + 2*x - 1 = 0
	cout << "3x^2 + 2*x - 1 = 0" << endl;
	cout << "alpha = " << roots.alpha << " beta = " << roots.beta << endl;

	roots = Quadratic(1, 2, 1);	// x^2 + 2*x + 1 = 0
	cout << "x^2 + 2*x + 1 = 0" << endl;
	cout << "alpha = " << roots.alpha << " beta = " << roots.beta << endl;

	cout << "Press Enter to continue..." << endl;
	cin.get();
	return 0;
}
<|endoftext|>