<commit_before>#include <fstream>
#include <string>
#include <iostream>
#include <vector>

#include "io.hh"
#include "str.hh"
#include "conf.hh"
#include "HmmSet.hh"
#include "Pcgmm.hh"
#include "Scgmm.hh"

int info_flag;
int pcgmm_flag;
int scgmm_flag;
int kl_flag;
int old_flag;

int dim;
int lambda_dim;
int basis_dim;
int num_gaussians;

conf::Config config;
HmmSet fc_model;
Pcgmm pcgmm;
Scgmm scgmm;
std::vector<float> kl_divergences;

void compress_pcgmm();
void compress_scgmm();

int
main(int argc, char *argv[])
{
  try {
    config("usage: basis_compress [OPTION...]\n")
      ('h', "help", "", "", "display help")
      ('g', "gk=FILE", "arg must", "", "full covariance gaussians")
      ('o', "out=FILE", "arg must", "", "compressed gaussians")
      ('p', "old=FILE", "arg", "", ".gk with old basis coefficients")
      ('b', "basis=FILE", "arg", "", "basis to be used")
      ('d', "dim", "arg", "", "dimension of untied parameters, default=basis dimension")
      ('k', "kl=FILE", "arg", "", "kullback-leibler divergences for each gaussian")
      ('i', "info=INT", "arg", "0", "info level")
      ('a', "affine", "", "", "affine subspace")
      ('\0', "hcl_bfgs_cfg=FILE", "arg", "", "configuration file for HCL biconjugate gradient algorithm")
      ('\0', "hcl_line_cfg=FILE", "arg", "", "configuration file for HCL line search algorithm")
      ;
    config.default_parse(argc, argv);

    old_flag = config["old"].specified;
    info_flag = config["info"].get_int();
    kl_flag = config["kl"].specified;

    if (config["gk"].specified) {
      fc_model.read_gk(config["gk"].get_str());
      num_gaussians=fc_model.num_kernels();
      if (kl_flag)
	kl_divergences.resize(num_gaussians);
    }
    else
      throw std::string("--gk=FILE must be specified");

    if (!config["out"].specified)
      throw std::string("--out=FILE must be specified");

    if (config["basis"].specified && config["old"].specified)
      throw std::string("you don't have to define both --basis and --old");

    if (!config["basis"].specified && !config["old"].specified)
      throw std::string("you have to define either --basis or --old");
  }
  catch (std::exception &e) {
    fprintf(stderr, "exception: %s\n", e.what());
    abort();
  }
  catch (std::string &str) {
    fprintf(stderr, "exception: %s\n", str.c_str());
    abort();
  }

  // Read parameters from the first line
  std::string type_line;
  if (config["basis"].specified) {
    std::ifstream ibasis(config["basis"].get_str().c_str());
    ibasis >> dim >> type_line >> basis_dim;
    ibasis.close();
  }
  else if (config["old"].specified) {
    std::ifstream iold(config["old"].get_str().c_str());
    int dummy;
    iold >> dummy >> dim >> type_line >> basis_dim;
    iold.close();
  }

  if (config["dim"].specified) {
    lambda_dim=config["dim"].get_int();
    if (lambda_dim>basis_dim)
      throw std::string("--dim is bigger than basis dimension");
  }
  else
    lambda_dim=basis_dim;

  if (type_line == "pcgmm") {
    pcgmm_flag=1;
    scgmm_flag=0;
  }
  else if (type_line == "scgmm") {
    pcgmm_flag=0;
    scgmm_flag=1;
  }

  // Compress all gaussians
  if (pcgmm_flag)
    compress_pcgmm();
  else if (scgmm_flag)
    compress_scgmm();

  // Print kullback-leibler divergences to file if desired
  if (kl_flag) {
    std::ofstream klfile(config["kl"].get_str().c_str());
    for (int g=0; g<num_gaussians; g++)
      klfile << kl_divergences[g] << std::endl;
  }
}

void compress_pcgmm() {

  pcgmm.reset(basis_dim, dim, num_gaussians);

  if (old_flag) {
    pcgmm.read_gk(config["old"].get_str());
    assert((int)pcgmm.num_gaussians()==fc_model.num_kernels());
  } else
    pcgmm.read_basis(config["basis"].get_str());

  LaGenMatDouble sample_cov(dim, dim);
  LaGenMatDouble model_cov(dim, dim);

  // Optimize and set the optimized parameters
  if (config["hcl_bfgs_cfg"].specified)
    pcgmm.set_hcl_bfgs_cfg_file(config["hcl_bfgs_cfg"].get_str());
  if (config["hcl_line_cfg"].specified)
    pcgmm.set_hcl_line_cfg_file(config["hcl_line_cfg"].get_str());
  if (config["affine"].specified)
    pcgmm.set_affine();

  for (int k=0; k<fc_model.num_kernels(); k++) {

    if (info_flag > 0)
      printf("Optimizing parameters for gaussian %i\n",k);

    // Fetch the next gaussian to be processed
    HmmKernel &fc_kernel=fc_model.kernel(k);
    // Fetch the target pcgmm gaussian
    Pcgmm::Gaussian &pcgmm_gaussian=pcgmm.get_gaussian(k);
    // Fetch the target lambda
    LaVectorDouble &lambda=pcgmm_gaussian.lambda;

    // Just copy mean
    for (int i=0; i<dim; i++)
      pcgmm_gaussian.mu(i)=fc_kernel.center[i];

    // Copy covariance to sample_cov
    for (int i=0; i<dim; i++)
      for (int j=0; j<dim; j++)
	sample_cov(i,j)=fc_kernel.cov.full(i,j);

    // Initialize untied parameters
    if (!old_flag) {
      lambda(LaIndex())=0;
      lambda(0)=1;
    }

    // Optimize and set the optimized parameters
    pcgmm.optimize_lambda(sample_cov, lambda);

    // Save kullback-leibler divergences KL(sample_fc, model_fc)
    if (kl_flag) {
      pcgmm.calculate_covariance(lambda, model_cov);
      kl_divergences[k]=pcgmm.kullback_leibler_covariance(sample_cov, model_cov);
    }
  }

  // Write pcgmm to file
  pcgmm.write_gk(config["out"].get_str());
}

void compress_scgmm() {

  scgmm.reset(basis_dim, dim, num_gaussians);

  if (old_flag) {
    scgmm.read_gk(config["old"].get_str());
    assert((int)scgmm.num_gaussians()==fc_model.num_kernels());
  }
  else
    scgmm.read_basis(config["basis"].get_str());

  LaVectorDouble sample_mean(dim);
  LaGenMatDouble sample_cov(dim, dim);
  LaVectorDouble model_mean(dim);
  LaGenMatDouble model_cov(dim, dim);

  // Optimize and set the optimization parameters
  if (config["hcl_bfgs_cfg"].specified)
    scgmm.set_hcl_bfgs_cfg_file(config["hcl_bfgs_cfg"].get_str());
  if (config["hcl_line_cfg"].specified)
    scgmm.set_hcl_line_cfg_file(config["hcl_line_cfg"].get_str());
  if (config["affine"].specified)
    scgmm.set_affine();

  for (int k=0; k<fc_model.num_kernels(); k++) {

    if (info_flag > 0)
      printf("Optimizing parameters for gaussian %i\n",k);

    // Fetch the next gaussian to be processed
    HmmKernel &fc_kernel=fc_model.kernel(k);
    // Fetch the target scgmm gaussian
    Scgmm::Gaussian &scgmm_gaussian=scgmm.get_gaussian(k);
    // Fetch the target lambda
    LaVectorDouble &lambda=scgmm_gaussian.lambda;

    // Copy mean to sample_mean
    for (int i=0; i<dim; i++)
      sample_mean(i)=fc_kernel.center[i];

    // Copy covariance to sample_cov
    for (int i=0; i<dim; i++)
      for (int j=0; j<dim; j++)
	sample_cov(i,j)=fc_kernel.cov.full(i,j);

    // Initialize untied parameters
    if (!old_flag) {
      lambda(LaIndex())=0;
      lambda(0)=1;
    }

    scgmm.optimize_lambda(sample_cov, sample_mean, lambda);

    // Save kullback-leibler divergences KL(sample_fc, model_fc)
    if (kl_flag) {
      scgmm.calculate_mu(lambda, model_mean);
      scgmm.calculate_covariance(lambda, model_cov);
      kl_divergences[k]=scgmm.kullback_leibler(sample_mean, sample_cov,
					       model_mean, model_cov);
    }
  }

  // Write scgmm to file
  scgmm.write_gk(config["out"].get_str());
}

<commit_msg>possibility to use --old with some gaussians pruned<commit_after>#include <fstream>
#include <string>
#include <iostream>
#include <vector>

#include "io.hh"
#include "str.hh"
#include "conf.hh"
#include "HmmSet.hh"
#include "Pcgmm.hh"
#include "Scgmm.hh"

int info_flag;
int pcgmm_flag;
int scgmm_flag;
int kl_flag;
int old_flag;

int dim;
int lambda_dim;
int basis_dim;
int num_gaussians;

conf::Config config;
HmmSet fc_stats;
HmmSet model_states;
Pcgmm pcgmm;
Scgmm scgmm;
std::vector<float> kl_divergences;
std::ifstream stats_file;

void compress_pcgmm();
void compress_scgmm();

int
main(int argc, char *argv[])
{
  try {
    config("usage: basis_compress [OPTION...]\n")
      ('h', "help", "", "", "display help")
      ('g', "stats=FILE", "arg must", "", "full covariance statistics (gk and mc)")
      ('o', "out=FILE", "arg must", "", "compressed gaussians (gk and mc)")
      ('p', "old=FILE", "arg", "", ".gk with old basis coefficients (gk and mc)")
      ('b', "basis=FILE", "arg", "", "basis to be used")
      ('d', "dim", "arg", "", "dimension of untied parameters, default=basis dimension")
      ('k', "kl=FILE", "arg", "", "kullback-leibler divergences for each gaussian")
      ('i', "info=INT", "arg", "0", "info level")
      ('a', "affine", "", "", "affine subspace")
      ('\0', "hcl_bfgs_cfg=FILE", "arg", "", "configuration file for HCL biconjugate gradient algorithm")
      ('\0', "hcl_line_cfg=FILE", "arg", "", "configuration file for HCL line search algorithm")
      ;
    config.default_parse(argc, argv);

    old_flag = config["old"].specified;
    info_flag = config["info"].get_int();
    kl_flag = config["kl"].specified;

    if (config["stats"].specified) {
      std::string dummy;
      fc_stats.read_mc(config["stats"].get_str()+".mc");
      stats_file.open((config["stats"].get_str()+".gk").c_str());
      stats_file >> num_gaussians >> dim >> dummy;
      assert(dummy=="full_cov");
      if (kl_flag)
	kl_divergences.resize(num_gaussians);
    }
    else
      throw std::string("--gk=FILE must be specified");

    if (!config["out"].specified)
      throw std::string("--out=FILE must be specified");

    if (config["basis"].specified && config["old"].specified)
      throw std::string("you don't have to define both --basis and --old");

    if (!config["basis"].specified && !config["old"].specified)
      throw std::string("you have to define either --basis or --old");
  }
  catch (std::exception &e) {
    fprintf(stderr, "exception: %s\n", e.what());
    abort();
  }
  catch (std::string &str) {
    fprintf(stderr, "exception: %s\n", str.c_str());
    abort();
  }

  // Read parameters from the first line
  std::string type_line;
  if (config["basis"].specified) {
    std::ifstream ibasis(config["basis"].get_str().c_str());
    ibasis >> dim >> type_line >> basis_dim;
    ibasis.close();
  }
  else if (config["old"].specified) {
    std::ifstream iold((config["old"].get_str()+".gk").c_str());
    int dummy;
    iold >> dummy >> dim >> type_line >> basis_dim;
    iold.close();
  }

  if (config["dim"].specified) {
    lambda_dim=config["dim"].get_int();
    if (lambda_dim>basis_dim)
      throw std::string("--dim is bigger than basis dimension");
  }
  else
    lambda_dim=basis_dim;

  if (type_line == "pcgmm") {
    pcgmm_flag=1;
    scgmm_flag=0;
  }
  else if (type_line == "scgmm") {
    pcgmm_flag=0;
    scgmm_flag=1;
  }

  // Compress all gaussians
  if (pcgmm_flag)
    compress_pcgmm();
  else if (scgmm_flag)
    compress_scgmm();

  // Print kullback-leibler divergences to file if desired
  if (kl_flag) {
    std::ofstream klfile(config["kl"].get_str().c_str());
    for (int g=0; g<num_gaussians; g++)
      klfile << kl_divergences[g] << std::endl;
  }
}

void compress_pcgmm() {

  pcgmm.reset(basis_dim, dim, num_gaussians);

  if (old_flag) {
    pcgmm.read_gk(config["old"].get_str()+".gk");
    model_states.read_mc(config["old"].get_str()+".mc");
    assert(model_states.num_states()==fc_stats.num_states());
  } else
    pcgmm.read_basis(config["basis"].get_str());

  LaGenMatDouble sample_cov(dim, dim);
  LaGenMatDouble model_cov(dim, dim);

  // Optimize and set the optimized parameters
  if (config["hcl_bfgs_cfg"].specified)
    pcgmm.set_hcl_bfgs_cfg_file(config["hcl_bfgs_cfg"].get_str());
  if (config["hcl_line_cfg"].specified)
    pcgmm.set_hcl_line_cfg_file(config["hcl_line_cfg"].get_str());
  if (config["affine"].specified)
    pcgmm.set_affine();

  // Go through every state
  int kernel_pos=0;
  for (int s=0; s<fc_stats.num_states(); s++) {
    HmmState &fc_state=fc_stats.state(s);
    HmmState &model_state=model_states.state(s);

    // Remove kernels so long that the fc and pcgmm state mixtures match
    if (old_flag) {
      while (fc_state.weights.size()<model_state.weights.size()) {
	scgmm.remove_gaussian(model_state.weights[model_state.weights.size()-1].kernel);
	model_states.remove_kernel(model_state.weights[model_state.weights.size()-1].kernel);
      }
    }

    // Go through every state Gaussian
    for (unsigned int k=0; k<fc_state.weights.size(); k++, kernel_pos++) {

      if (info_flag > 0)
	printf("Optimizing parameters for gaussian %i\n",kernel_pos);

      // Fetch the target pcgmm gaussian
      Pcgmm::Gaussian &pcgmm_gaussian=pcgmm.get_gaussian(kernel_pos);
      // Fetch the target lambda
      LaVectorDouble &lambda=pcgmm_gaussian.lambda;

      // Just copy mean from the file
      for (int i=0; i<dim; i++)
	stats_file >> pcgmm_gaussian.mu(i);

      // Copy covariance to sample_cov
      for (int i=0; i<dim; i++)
	for (int j=0; j<dim; j++)
	  stats_file >> sample_cov(i,j);

      // Initialize untied parameters
      if (!old_flag) {
	lambda(LaIndex())=0;
	lambda(0)=1;
      }

      // Optimize and set the optimized parameters
      pcgmm.optimize_lambda(sample_cov, lambda);

      // Save kullback-leibler divergences KL(sample_fc, model_fc)
      if (kl_flag) {
	pcgmm.calculate_covariance(lambda, model_cov);
	kl_divergences[kernel_pos]=pcgmm.kullback_leibler_covariance(sample_cov, model_cov);
      }
    }
  }

  // Write pcgmm to file
  pcgmm.write_gk(config["out"].get_str()+".gk");
  fc_stats.write_mc(config["out"].get_str()+".mc");
}

void compress_scgmm() {

  scgmm.reset(basis_dim, dim, num_gaussians);

  if (old_flag) {
    scgmm.read_gk(config["old"].get_str()+".gk");
    model_states.read_mc(config["old"].get_str()+".mc");
    assert(model_states.num_states()==fc_stats.num_states());
  }
  else
    scgmm.read_basis(config["basis"].get_str());

  LaVectorDouble sample_mean(dim);
  LaGenMatDouble sample_cov(dim, dim);
  LaVectorDouble model_mean(dim);
  LaGenMatDouble model_cov(dim, dim);

  // Optimize and set the optimization parameters
  if (config["hcl_bfgs_cfg"].specified)
    scgmm.set_hcl_bfgs_cfg_file(config["hcl_bfgs_cfg"].get_str());
  if (config["hcl_line_cfg"].specified)
    scgmm.set_hcl_line_cfg_file(config["hcl_line_cfg"].get_str());
  if (config["affine"].specified)
    scgmm.set_affine();

  // Go through every state
  int kernel_pos=0;
  for (int s=0; s<fc_stats.num_states(); s++) {
    HmmState &fc_state=fc_stats.state(s);
    HmmState &model_state=model_states.state(s);

    // Remove kernels so long that the fc and pcgmm state mixtures match
    if (old_flag) {
      while (fc_state.weights.size()<model_state.weights.size()) {
	scgmm.remove_gaussian(model_state.weights[model_state.weights.size()-1].kernel);
	model_states.remove_kernel(model_state.weights[model_state.weights.size()-1].kernel);
      }
    }

    // Go through every state Gaussian
    for (unsigned int k=0; k<fc_state.weights.size(); k++, kernel_pos++) {

      if (info_flag > 0)
	printf("Optimizing parameters for gaussian %i\n",kernel_pos);

      // Fetch the target scgmm gaussian
      Scgmm::Gaussian &scgmm_gaussian=scgmm.get_gaussian(kernel_pos);
      // Fetch the target lambda
      LaVectorDouble &lambda=scgmm_gaussian.lambda;

      // Copy mean to sample_mean
      for (int i=0; i<dim; i++)
	stats_file >> sample_mean(i);

      // Copy covariance to sample_cov
      for (int i=0; i<dim; i++)
	for (int j=0; j<dim; j++)
	  stats_file >> sample_cov(i,j);

      // Initialize untied parameters
      if (!old_flag) {
	lambda(LaIndex())=0;
	lambda(0)=1;
      }

      scgmm.optimize_lambda(sample_cov, sample_mean, lambda);

      // Save kullback-leibler divergences KL(sample_fc, model_fc)
      if (kl_flag) {
	scgmm.calculate_mu(lambda, model_mean);
	scgmm.calculate_covariance(lambda, model_cov);
	kl_divergences[kernel_pos]=scgmm.kullback_leibler(sample_mean, sample_cov,
							  model_mean, model_cov);
      }
    }
  }

  // Write scgmm to file
  scgmm.write_gk(config["out"].get_str()+".gk");
  fc_stats.write_mc(config["out"].get_str()+".mc");
}

<|endoftext|>


<commit_before>#include "timing.h"
#include <omp.h>
#include <signal.h>

static rangetree<u32, u32> tree;
static volatile u32 running = 0;
static u32 loops = 0;

enum {
	numhigh = 1000000,
	looper = 500
};

static inline u32 subrand() {
	return rand() % numhigh;
}

static void doit() {
	running = 1;

	while (running) {
		s32 i;
		#pragma omp parallel for
		for (i = 0; i < looper; i++) {
			tree.count(subrand(), subrand(), subrand(), subrand());
		}
		loops += looper;
//		usleep(1);
	}
}

static void sig(int a) {
	if (a == SIGALRM)
		running = 0;
}

int main() {

	srand(time(NULL));

	const u32 max = omp_get_num_procs();
	printf("Running scaling tests, two seconds per core...\n");
	printf("Detected a total of %u cores.\n", max);

	u32 i;

	// Set the signaller
	struct sigaction sa;
	memset(&sa, 0, sizeof(struct sigaction));
	sa.sa_handler = sig;
	sigaction(SIGALRM, &sa, NULL);

	// init the tree
	for (i = 0; i < numhigh; i++) {
		const u32 x = subrand();
		const u32 y = subrand();
		tree.add(x, y, 0);
	}
	tree.finalize();
	printf("Tree finalized, starting tests.\n");

	u32 results[max + 1];

	for (i = 1; i <= max; i++) {
		omp_set_num_threads(i);
		printf("%u.. ", i);
		fflush(stdout);

		alarm(2);
		doit();

		results[i] = loops/2;
		loops = 0;
	}

	printf("\n\n\nScaling results:\n");
	for (i = 1; i <= max; i++) {
		printf("%u core%s: %u searches/sec, normalized %.2f\n",
			i, i > 1 ? "s" : "",
			results[i],
			(float) results[i]/results[1]);
	}

	return 0;
}
<commit_msg>scaling: Up the looper a bit<commit_after>#include "timing.h"
#include <omp.h>
#include <signal.h>

static rangetree<u32, u32> tree;
static volatile u32 running = 0;
static u32 loops = 0;

enum {
	numhigh = 1000000,
	looper = 5000
};

static inline u32 subrand() {
	return rand() % numhigh;
}

static void doit() {
	running = 1;

	while (running) {
		s32 i;
		#pragma omp parallel for
		for (i = 0; i < looper; i++) {
			tree.count(subrand(), subrand(), subrand(), subrand());
		}
		loops += looper;
//		usleep(1);
	}
}

static void sig(int a) {
	if (a == SIGALRM)
		running = 0;
}

int main() {

	srand(time(NULL));

	const u32 max = omp_get_num_procs();
	printf("Running scaling tests, two seconds per core...\n");
	printf("Detected a total of %u cores.\n", max);

	u32 i;

	// Set the signaller
	struct sigaction sa;
	memset(&sa, 0, sizeof(struct sigaction));
	sa.sa_handler = sig;
	sigaction(SIGALRM, &sa, NULL);

	// init the tree
	for (i = 0; i < numhigh; i++) {
		const u32 x = subrand();
		const u32 y = subrand();
		tree.add(x, y, 0);
	}
	tree.finalize();
	printf("Tree finalized, starting tests.\n");

	u32 results[max + 1];

	for (i = 1; i <= max; i++) {
		omp_set_num_threads(i);
		printf("%u.. ", i);
		fflush(stdout);

		alarm(2);
		doit();

		results[i] = loops/2;
		loops = 0;
	}

	printf("\n\n\nScaling results:\n");
	for (i = 1; i <= max; i++) {
		printf("%u core%s: %u searches/sec, normalized %.2f\n",
			i, i > 1 ? "s" : "",
			results[i],
			(float) results[i]/results[1]);
	}

	return 0;
}
<|endoftext|>


<commit_before>/*
 *  \remark This file is part of VITA.
 *
 *  \copyright Copyright (C) 2017 EOS di Manlio Morini.
 *
 *  \license
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this file,
 *  You can obtain one at http://mozilla.org/MPL/2.0/
 */

#include "kernel/vita.h"
#include "trade_simulator.h"

enum timeframe : unsigned {short_tf = 0, medium_tf, long_tf, sup_tf};

namespace fxs  // Forex symbols
{
using team = vita::team<vita::i_mep>;

enum
{
  c_logic,  // boolean values
  c_money,  // currencies
  c_volume  // volume of a transaction
};

///
/// \tparam TF timeframe
/// \tparam I  index of a candle. `0` is the current bar, `1` is the previous
///            one and so on (a greater value identifies an older candle).
///            It's called shift in Metatrader
///
template<timeframe TF, unsigned I>
class tfi_terminal : public vita::terminal
{
public:
  tfi_terminal(const std::string &n, vita::category_t c)
    : vita::terminal(n + "("
                     + std::to_string(TF) + "," + std::to_string(I) +
                     ")", c)
  {
  }

  bool input() const override { return true; }
  vita::any eval(vita::core_interpreter *) const override { return {}; }

  std::string display(terminal::param_t, format) const override
  {
    return name();
  }
};

template<timeframe TF, unsigned I>
struct close : tfi_terminal<TF, I>
{
  close() : tfi_terminal<TF, I>("close", c_money) {}
};

template<timeframe TF, unsigned I>
struct high : tfi_terminal<TF, I>
{
  high() : tfi_terminal<TF, I>("high", c_money) {}
};

template<timeframe TF, unsigned I>
struct low : tfi_terminal<TF, I>
{
  low() : tfi_terminal<TF, I>("low", c_money) {}
};

template<timeframe TF, unsigned I>
struct open : tfi_terminal<TF, I>
{
  open() : tfi_terminal<TF, I>("open", c_money) {}
};

/// Black candle is formed when the opening price is higher than the closing
/// price.
template<timeframe TF, unsigned I>
struct black_candle : tfi_terminal<TF, I>
{
  black_candle() : tfi_terminal<TF, I>("black_candle", c_logic) {}
};

/// White candle is formed when the opening price is lower than the closing
/// price.
template<timeframe TF, unsigned I>
struct white_candle : tfi_terminal<TF, I>
{
  white_candle() : tfi_terminal<TF, I>("white_candle", c_logic) {}
};

/// Doji are important candlesticks that provide information on their own and
/// as components of in a number of important patterns. Doji form when a
/// security's open and close are virtually equal.
/// The length of the upper and lower shadows can vary and the resulting
/// candlestick looks like a cross, inverted cross or plus sign. Alone, doji
/// are neutral patterns. Any bullish or bearish bias is based on preceding
/// price action and future confirmation.
template<timeframe TF, unsigned I>
struct doji : tfi_terminal<TF, I>
{
  doji() : tfi_terminal<TF, I>("doji", c_logic) {}
};

/// Bearish Harami (meaning "pregnant" in Japanese) consists of an unusually
/// large white body followed by a small black body (contained within large
/// white body).
/// It's considered as a bearish pattern when preceded by an uptrend.
template<timeframe TF>
struct bearish_harami : tfi_terminal<TF, 1>
{
  bearish_harami() : tfi_terminal<TF, 1>("bearish_harami", c_logic) {}
};

/// Bullish Harami (meaning "pregnant" in Japanese) consists of an unusually
/// large black body followed by a small white body (contained within large
/// black body).
/// It's considered as a bullish pattern when preceded by a downtrend.
template<timeframe TF>
struct bullish_harami : tfi_terminal<TF, 1>
{
  bullish_harami() : tfi_terminal<TF, 1>("bullish_harami", c_logic) {}
};

/// Dark Cloud Cover consists of a long white candlestick followed by a black
/// candlestick that opens above the high of the white candlestick and closes
/// well into the body of the white candlestick. It is considered as a bearish
/// reversal signal during an uptrend.
template<timeframe TF>
struct dark_cloud_cover : tfi_terminal<TF, 1>
{
  dark_cloud_cover() : tfi_terminal<TF, 1>("dark_cloud_cover", c_logic) {}
};

template<timeframe TF, unsigned I>
struct long_candle : tfi_terminal<TF, I>
{
  long_candle() : tfi_terminal<TF, I>("long_candle", c_logic) {}
};

template<timeframe TF, unsigned I>
struct long_black_candle : tfi_terminal<TF, I>
{
  long_black_candle() : tfi_terminal<TF, I>("long_black_candle", c_logic) {}
};

template<timeframe TF, unsigned I>
struct long_white_candle : tfi_terminal<TF, I>
{
  long_white_candle() : tfi_terminal<TF, I>("long_white_candle", c_logic) {}
};

struct l_and : vita::boolean::l_and
{
  l_and() : vita::boolean::l_and({c_logic}) {}
};

struct l_or : vita::boolean::l_or
{
  l_or() : vita::boolean::l_or({c_logic}) {}
};

struct add : vita::real::add
{
  add() : vita::real::add({c_money}) {}
};

struct sub : vita::real::sub
{
  sub() : vita::real::sub({c_money}) {}
};

struct lt_m : vita::real::lt
{
  lt_m() : vita::real::lt({c_money, c_logic}) {}
};

class evaluator : public vita::evaluator<team>
{
public:
  explicit evaluator(trade_simulator *ts) : ts_(ts) {}

  vita::fitness_t operator()(const team &t) final
  {
    return {ts_->run(t)};
  }

private:
  trade_simulator *ts_;
};

class search : public vita::search<team, vita::alps_es>
{
public:
  using vita::search<team, vita::alps_es>::search;
};

}  // namespace fxs

template<template<timeframe, unsigned> class F, timeframe TF>
void insert_symbol(vita::symbol_set *ss)
{
  ss->insert(std::make_unique<F<TF, 1>>());
  ss->insert(std::make_unique<F<TF, 2>>());
  ss->insert(std::make_unique<F<TF, 3>>());
}

template<template<timeframe, unsigned> class F>
void insert_symbol(vita::symbol_set *ss)
{
  insert_symbol<F, short_tf>(ss);
  insert_symbol<F, medium_tf>(ss);
  insert_symbol<F, long_tf>(ss);
}

template<template<timeframe> class F>
void insert_symbol(vita::symbol_set *ss)
{
  ss->insert(std::make_unique<F<short_tf>>());
  ss->insert(std::make_unique<F<medium_tf>>());
  ss->insert(std::make_unique<F<long_tf>>());
}

bool setup_symbols(vita::symbol_set *ss)
{
  insert_symbol<fxs::close>(ss);
  insert_symbol<fxs::high>(ss);
  insert_symbol<fxs::low>(ss);
  insert_symbol<fxs::open>(ss);

  insert_symbol<fxs::black_candle>(ss);
  insert_symbol<fxs::white_candle>(ss);

  insert_symbol<fxs::long_candle>(ss);
  insert_symbol<fxs::long_black_candle>(ss);
  insert_symbol<fxs::long_white_candle>(ss);

  insert_symbol<fxs::doji>(ss);

  insert_symbol<fxs::bearish_harami>(ss);
  insert_symbol<fxs::bullish_harami>(ss);
  insert_symbol<fxs::dark_cloud_cover>(ss);

  ss->insert(std::make_unique<fxs::l_and>(), 2.0);
  ss->insert(std::make_unique< fxs::l_or>(), 2.0);

  ss->insert(std::make_unique<fxs::add>());
  ss->insert(std::make_unique<fxs::sub>());

  ss->insert(std::make_unique<fxs::lt_m>(), 2.0);

  return true;
}

int main()
{
  vita::problem p(vita::initialization::standard);

  if (!setup_symbols(&p.sset))
    return EXIT_FAILURE;

  p.env.individuals = 30;
  p.env.min_individuals =  8;
  p.env.code_length = 200;
  p.env.generations = 400;
  p.env.layers = 6;
  p.env.team.individuals = 2;  // DO NOT CHANGE
  p.env.alps.age_gap = 10;
  p.env.cache_size = 19;       // A hash table of `2^19 = 524288` elements.
                               // Considering the speed of the Metatrader
                               // back-tester this should ensure a very low
                               // hash collision rate.

  p.env.stat.dynamic_file    = "dynamic.txt";
  p.env.stat.layers_file     = "layers.txt";
  p.env.stat.population_file = "population.txt";
  p.env.stat.summary_file    = "summary.txt";
  p.env.stat.ind_format = vita::out::mql_language_f;

  p.env.misc.serialization_file = "cache.txt";

  fxs::search engine(p);

  trade_simulator ts;
  engine.set_evaluator<fxs::evaluator>(&ts);

  std::cout << "STARTING RUN\n";
  engine.run(1);
}
<commit_msg>[REF] Higher probability for functions in Forex example<commit_after>/*
 *  \remark This file is part of VITA.
 *
 *  \copyright Copyright (C) 2017 EOS di Manlio Morini.
 *
 *  \license
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this file,
 *  You can obtain one at http://mozilla.org/MPL/2.0/
 */

#include "kernel/vita.h"
#include "trade_simulator.h"

enum timeframe : unsigned {short_tf = 0, medium_tf, long_tf, sup_tf};

namespace fxs  // Forex symbols
{
using team = vita::team<vita::i_mep>;

enum
{
  c_logic,  // boolean values
  c_money,  // currencies
  c_volume  // volume of a transaction
};

///
/// \tparam TF timeframe
/// \tparam I  index of a candle. `0` is the current bar, `1` is the previous
///            one and so on (a greater value identifies an older candle).
///            It's called shift in Metatrader
///
template<timeframe TF, unsigned I>
class tfi_terminal : public vita::terminal
{
public:
  tfi_terminal(const std::string &n, vita::category_t c)
    : vita::terminal(n + "("
                     + std::to_string(TF) + "," + std::to_string(I) +
                     ")", c)
  {
  }

  bool input() const override { return true; }
  vita::any eval(vita::core_interpreter *) const override { return {}; }

  std::string display(terminal::param_t, format) const override
  {
    return name();
  }
};

template<timeframe TF, unsigned I>
struct close : tfi_terminal<TF, I>
{
  close() : tfi_terminal<TF, I>("close", c_money) {}
};

template<timeframe TF, unsigned I>
struct high : tfi_terminal<TF, I>
{
  high() : tfi_terminal<TF, I>("high", c_money) {}
};

template<timeframe TF, unsigned I>
struct low : tfi_terminal<TF, I>
{
  low() : tfi_terminal<TF, I>("low", c_money) {}
};

template<timeframe TF, unsigned I>
struct open : tfi_terminal<TF, I>
{
  open() : tfi_terminal<TF, I>("open", c_money) {}
};

/// Black candle is formed when the opening price is higher than the closing
/// price.
template<timeframe TF, unsigned I>
struct black_candle : tfi_terminal<TF, I>
{
  black_candle() : tfi_terminal<TF, I>("black_candle", c_logic) {}
};

/// White candle is formed when the opening price is lower than the closing
/// price.
template<timeframe TF, unsigned I>
struct white_candle : tfi_terminal<TF, I>
{
  white_candle() : tfi_terminal<TF, I>("white_candle", c_logic) {}
};

/// Doji are important candlesticks that provide information on their own and
/// as components of in a number of important patterns. Doji form when a
/// security's open and close are virtually equal.
/// The length of the upper and lower shadows can vary and the resulting
/// candlestick looks like a cross, inverted cross or plus sign. Alone, doji
/// are neutral patterns. Any bullish or bearish bias is based on preceding
/// price action and future confirmation.
template<timeframe TF, unsigned I>
struct doji : tfi_terminal<TF, I>
{
  doji() : tfi_terminal<TF, I>("doji", c_logic) {}
};

/// Bearish Harami (meaning "pregnant" in Japanese) consists of an unusually
/// large white body followed by a small black body (contained within large
/// white body).
/// It's considered as a bearish pattern when preceded by an uptrend.
template<timeframe TF>
struct bearish_harami : tfi_terminal<TF, 1>
{
  bearish_harami() : tfi_terminal<TF, 1>("bearish_harami", c_logic) {}
};

/// Bullish Harami (meaning "pregnant" in Japanese) consists of an unusually
/// large black body followed by a small white body (contained within large
/// black body).
/// It's considered as a bullish pattern when preceded by a downtrend.
template<timeframe TF>
struct bullish_harami : tfi_terminal<TF, 1>
{
  bullish_harami() : tfi_terminal<TF, 1>("bullish_harami", c_logic) {}
};

/// Dark Cloud Cover consists of a long white candlestick followed by a black
/// candlestick that opens above the high of the white candlestick and closes
/// well into the body of the white candlestick. It is considered as a bearish
/// reversal signal during an uptrend.
template<timeframe TF>
struct dark_cloud_cover : tfi_terminal<TF, 1>
{
  dark_cloud_cover() : tfi_terminal<TF, 1>("dark_cloud_cover", c_logic) {}
};

template<timeframe TF, unsigned I>
struct long_candle : tfi_terminal<TF, I>
{
  long_candle() : tfi_terminal<TF, I>("long_candle", c_logic) {}
};

template<timeframe TF, unsigned I>
struct long_black_candle : tfi_terminal<TF, I>
{
  long_black_candle() : tfi_terminal<TF, I>("long_black_candle", c_logic) {}
};

template<timeframe TF, unsigned I>
struct long_white_candle : tfi_terminal<TF, I>
{
  long_white_candle() : tfi_terminal<TF, I>("long_white_candle", c_logic) {}
};

struct l_and : vita::boolean::l_and
{
  l_and() : vita::boolean::l_and({c_logic}) {}
};

struct l_or : vita::boolean::l_or
{
  l_or() : vita::boolean::l_or({c_logic}) {}
};

struct add : vita::real::add
{
  add() : vita::real::add({c_money}) {}
};

struct sub : vita::real::sub
{
  sub() : vita::real::sub({c_money}) {}
};

struct lt_m : vita::real::lt
{
  lt_m() : vita::real::lt({c_money, c_logic}) {}
};

class evaluator : public vita::evaluator<team>
{
public:
  explicit evaluator(trade_simulator *ts) : ts_(ts) {}

  vita::fitness_t operator()(const team &t) final
  {
    return {ts_->run(t)};
  }

private:
  trade_simulator *ts_;
};

class search : public vita::search<team, vita::alps_es>
{
public:
  using vita::search<team, vita::alps_es>::search;
};

}  // namespace fxs

template<template<timeframe, unsigned> class F, timeframe TF>
void insert_symbol(vita::symbol_set *ss)
{
  ss->insert(std::make_unique<F<TF, 1>>());
  ss->insert(std::make_unique<F<TF, 2>>());
  ss->insert(std::make_unique<F<TF, 3>>());
}

template<template<timeframe, unsigned> class F>
void insert_symbol(vita::symbol_set *ss)
{
  insert_symbol<F, short_tf>(ss);
  insert_symbol<F, medium_tf>(ss);
  insert_symbol<F, long_tf>(ss);
}

template<template<timeframe> class F>
void insert_symbol(vita::symbol_set *ss)
{
  ss->insert(std::make_unique<F<short_tf>>());
  ss->insert(std::make_unique<F<medium_tf>>());
  ss->insert(std::make_unique<F<long_tf>>());
}

bool setup_symbols(vita::symbol_set *ss)
{
  insert_symbol<fxs::close>(ss);
  insert_symbol<fxs::high>(ss);
  insert_symbol<fxs::low>(ss);
  insert_symbol<fxs::open>(ss);

  insert_symbol<fxs::black_candle>(ss);
  insert_symbol<fxs::white_candle>(ss);

  insert_symbol<fxs::long_candle>(ss);
  insert_symbol<fxs::long_black_candle>(ss);
  insert_symbol<fxs::long_white_candle>(ss);

  insert_symbol<fxs::doji>(ss);

  insert_symbol<fxs::bearish_harami>(ss);
  insert_symbol<fxs::bullish_harami>(ss);
  insert_symbol<fxs::dark_cloud_cover>(ss);

  ss->insert(std::make_unique<fxs::l_and>(), 20.0);
  ss->insert(std::make_unique< fxs::l_or>(), 20.0);

  ss->insert(std::make_unique<fxs::add>(), 20.0);
  ss->insert(std::make_unique<fxs::sub>(), 20.0);

  ss->insert(std::make_unique<fxs::lt_m>(), 20.0);

  return true;
}

int main()
{
  vita::problem p(vita::initialization::standard);

  if (!setup_symbols(&p.sset))
    return EXIT_FAILURE;

  p.env.individuals = 30;
  p.env.min_individuals =  8;
  p.env.code_length = 200;
  p.env.generations = 400;
  p.env.layers = 6;
  p.env.team.individuals = 2;  // DO NOT CHANGE
  p.env.alps.age_gap = 10;
  p.env.cache_size = 19;       // A hash table of `2^19 = 524288` elements.
                               // Considering the speed of the Metatrader
                               // back-tester this should ensure a very low
                               // hash collision rate.

  p.env.stat.dynamic_file    = "dynamic.txt";
  p.env.stat.layers_file     = "layers.txt";
  p.env.stat.population_file = "population.txt";
  p.env.stat.summary_file    = "summary.txt";
  p.env.stat.ind_format = vita::out::mql_language_f;

  p.env.misc.serialization_file = "cache.txt";

  fxs::search engine(p);

  trade_simulator ts;
  engine.set_evaluator<fxs::evaluator>(&ts);

  std::cout << "STARTING RUN\n";
  engine.run(1);
}
<|endoftext|>


<commit_before>/** \copyright
 * Copyright (c) 2013, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file Dispatcher.hxx
 *
 * Class for dispatching incoming messages to handlers.
 *
 * @author Balazs Racz
 * @date 2 Dec 2013
 */

#ifndef _EXECUTOR_DISPATCHER_HXX_
#define _EXECUTOR_DISPATCHER_HXX_

#include <vector>

#include "executor/Notifiable.hxx"
#include "executor/StateFlow.hxx"

/**
   This class takes registrations of StateFlows for incoming messages. When a
   message shows up, all the Flows that match that message will be
   invoked.

   Handlers are called in no particular order.
 */
template <int NUM_PRIO>
class DispatchFlowBase : public UntypedStateFlow<QList<NUM_PRIO>>
{
public:
    /** Construct a dispatchflow.
     *
     * @param service the Service this flow belongs to. */
    DispatchFlowBase(Service *service);

    typedef StateFlowBase::Action Action;

    ~DispatchFlowBase();

    /** @returns the number of handlers registered. */
    size_t size();

protected:
    typedef uint32_t ID;
    typedef void UntypedHandler;
    /**
       Adds a new handler to this dispatcher.

       A handler will be called if incoming_id & mask == id & mask.
       If negateMatch_ then the handler will be called if incoming_id & mask !=
       id & mask.

       @param id is the identifier of the message to listen to.
       @param mask is the mask of the ID matcher. 0=match all; 0xff...f=match
       one
       @param handler is the flow to forward message to. It must stay alive so
       long as *this is alive or the handler is removed.
     */
    void register_handler(UntypedHandler *handler, ID id, ID mask);

    /// Removes a specific instance of a handler from this dispatcher.
    void unregister_handler(UntypedHandler *handler, ID id, ID mask);

    /// Removes all instances of a handler from this dispatcher.
    void unregister_handler_all(UntypedHandler *handler);

    /// Returns the current message's ID.
    virtual ID get_message_id() = 0;

    /** Allocates an entry from lastHandlerToCall_, invoking clone() when done:
     *  return allocate_and_call(lastHandlerToCall_, STATE(clone));
     */
    virtual Action allocate_and_clone() = 0;

    /** Sends the current message to lastHandlerToCall, transferring ownership.
     */
    virtual void send_transfer() = 0;

    /*typedef typename StateFlow<MessageType, QList<NUM_PRIO>>::Callback Callback;
    using StateFlow<MessageType, QList<NUM_PRIO>>::again;
    using StateFlow<MessageType, QList<NUM_PRIO>>::allocate_and_call;
    using StateFlow<MessageType, QList<NUM_PRIO>>::get_allocation_result;
    using StateFlow<MessageType, QList<NUM_PRIO>>::message;
    using StateFlow<MessageType, QList<NUM_PRIO>>::release_and_exit;
    using StateFlow<MessageType, QList<NUM_PRIO>>::transfer_message;*/
    using StateFlowBase::call_immediately;
    using StateFlowBase::again;
    using StateFlowWithQueue::release_and_exit;

    STATE_FLOW_STATE(entry);

    /*    Action entry()
        {
            currentIndex_ = 0;
            lastHandlerToCall_ = nullptr;
            return call_immediately(STATE(iterate));
            }*/

    STATE_FLOW_STATE(iterate);
    STATE_FLOW_STATE(clone_done);
    STATE_FLOW_STATE(iteration_done);

private:
    // true if this flow should negate the match condition.
    bool negateMatch_;
    friend class HubFlow;
    friend class CanHubFlow;

    struct HandlerInfo
    {
        HandlerInfo() : handler(nullptr)
        {
        }
        ID id;
        ID mask;
        // NULL if the handler has been removed.
        UntypedHandler *handler;

        bool Equals(ID id, ID mask, UntypedHandler *handler)
        {
            return (this->id == id && this->mask == mask &&
                    this->handler == handler);
        }
    };

    vector<HandlerInfo> handlers_;

    /// Index of the next handler to look at.
    size_t currentIndex_;

protected:
    /// If non-NULL we still need to call this handler.
    UntypedHandler *lastHandlerToCall_;
private:
    /// Protects handler add / remove against iteration.
    OSMutex lock_;
};

// ==================== TEMPLATED =====================

#ifdef TARGET_LPC11Cxx
#define BASE_NUM_PRIO 4
#else
#define BASE_NUM_PRIO NUM_PRIO
#endif

template <class MessageType, int NUM_PRIO>
class DispatchFlow : public TypedStateFlow<MessageType, DispatchFlowBase<BASE_NUM_PRIO> > {
public:
    typedef TypedStateFlow<MessageType, DispatchFlowBase<BASE_NUM_PRIO> > Base;

    DispatchFlow(Service *service)
        :  Base(service) {}

    typedef StateFlowBase::Action Action;
    using StateFlowBase::call_immediately;
    using StateFlowBase::allocate_and_call;
    using StateFlowBase::get_allocation_result;

    typedef FlowInterface<MessageType> HandlerType;
    typedef typename MessageType::value_type::id_type ID;

    Action entry() OVERRIDE {
        return DispatchFlowBase<BASE_NUM_PRIO>::entry();
    }

    /**
       Adds a new handler to this dispatcher.

       A handler will be called if incoming_id & mask == id & mask.
       If negateMatch_ then the handler will be called if incoming_id & mask !=
       id & mask.

       @param id is the identifier of the message to listen to.
       @param mask is the mask of the ID matcher. 0=match all; 0xff...f=match
       one
       @param handler is the flow to forward message to. It must stay alive so
       long as *this is alive or the handler is removed.
     */
    void register_handler(HandlerType *handler, ID id, ID mask) {
        Base::register_handler(handler, id, mask);
    }

    /// Removes a specific instance of a handler from this dispatcher.
    void unregister_handler(HandlerType *handler, ID id, ID mask) {
        Base::unregister_handler(handler, id, mask);
    }

    /// Removes all instances of a handler from this dispatcher.
    void unregister_handler_all(HandlerType *handler) {
        Base::unregister_handler_all(handler);
    }

protected:
    typename Base::ID get_message_id() OVERRIDE {
        return this->message()->data()->id();
    }

    Action allocate_and_clone() OVERRIDE {
        HandlerType* h = static_cast<HandlerType *>(this->lastHandlerToCall_);
        return allocate_and_call(h, STATE(clone));
    }

    Action clone() {
        HandlerType* h = static_cast<HandlerType *>(this->lastHandlerToCall_);
        MessageType *copy = get_allocation_result(h);
        copy->set_done(this->message()->new_child());
        *copy->data() = *this->message()->data();
        h->send(copy);
        return call_immediately(STATE(clone_done));
    }

    void send_transfer() OVERRIDE {
        HandlerType* h = static_cast<HandlerType *>(this->lastHandlerToCall_);
        h->send(this->transfer_message());
    }
};

// ================== IMPLEMENTATION ==================

template <int NUM_PRIO>
DispatchFlowBase<NUM_PRIO>::DispatchFlowBase(Service *service)
    : UntypedStateFlow<QList<NUM_PRIO>>(service)
    , negateMatch_(false)
{
}

template<int NUM_PRIO>
DispatchFlowBase<NUM_PRIO>::~DispatchFlowBase()
{
    HASSERT(this->is_waiting());
}

template<int NUM_PRIO>
size_t DispatchFlowBase<NUM_PRIO>::size()
{
    OSMutexLock h(&lock_);
    size_t ret = 0;
    for (auto &h : handlers_)
    {
        if (h.handler)
        {
            ++ret;
        }
    }
    return ret;
}

template<int NUM_PRIO>
void DispatchFlowBase<NUM_PRIO>::register_handler(UntypedHandler *handler,
                                                  ID id, ID mask)
{
    OSMutexLock h(&lock_);
    size_t idx = 0;
    while (idx < handlers_.size() && handlers_[idx].handler)
    {
        ++idx;
    }
    if (idx >= handlers_.size())
    {
        handlers_.resize(handlers_.size() + 1);
    }
    handlers_[idx].handler = handler;
    handlers_[idx].id = id;
    handlers_[idx].mask = mask;
}

template<int NUM_PRIO>
void
DispatchFlowBase<NUM_PRIO>::unregister_handler(UntypedHandler *handler,
                                               ID id, ID mask)
{
    OSMutexLock h(&lock_);
    /// @todo(balazs.racz) optimize by looking at the current index - 1.
    size_t idx = 0;
    while (idx < handlers_.size() && !handlers_[idx].Equals(id, mask, handler))
    {
        ++idx;
    }
    // Checks that we found the thing to unregister.
    HASSERT(idx < handlers_.size() &&
            "Tried to unregister a handler not previously registered.");
    handlers_[idx].handler = nullptr;
    if (idx == handlers_.size() - 1)
    {
        handlers_.resize(handlers_.size() - 1);
    }
}

template<int NUM_PRIO>
void DispatchFlowBase<NUM_PRIO>::unregister_handler_all(
    UntypedHandler *handler)
{
    OSMutexLock h(&lock_);
    for (size_t i = 0; i < handlers_.size(); ++i)
    {
        if (handlers_[i].handler == handler)
        {
            handlers_[i].handler = nullptr;
        }
    }
    while (!handlers_.empty() && handlers_.back().handler == nullptr)
    {
        handlers_.pop_back();
    }
}

template<int NUM_PRIO>
StateFlowBase::Action DispatchFlowBase<NUM_PRIO>::entry()
{
    currentIndex_ = 0;
    lastHandlerToCall_ = nullptr;
    return call_immediately(STATE(iterate));
}

template<int NUM_PRIO>
StateFlowBase::Action DispatchFlowBase<NUM_PRIO>::iterate()
{
    ID id = get_message_id();
    {
        OSMutexLock l(&lock_);
        for (; currentIndex_ < handlers_.size(); ++currentIndex_)
        {
            auto &h = handlers_[currentIndex_];
            if (!h.handler)
            {
                continue;
            }
            if (negateMatch_ && (id & h.mask) == (h.id & h.mask))
            {
                continue;
            }
            if ((!negateMatch_) && (id & h.mask) != (h.id & h.mask))
            {
                continue;
            }
            break;
        }
    }
    if (currentIndex_ >= handlers_.size())
    {
        return call_immediately(STATE(iteration_done));
    }
    // At this point: we have another handler.
    if (!lastHandlerToCall_)
    {
        // This was the first we found.
        lastHandlerToCall_ = handlers_[currentIndex_].handler;
        ++currentIndex_;
        return again();
    }
    // Now: we have at least two different handler. We need to clone the
    // message. We use the pool of the last handler to call by default.
    return allocate_and_clone();
}

template<int NUM_PRIO>
StateFlowBase::Action DispatchFlowBase<NUM_PRIO>::clone_done()
{
    lastHandlerToCall_ = handlers_[currentIndex_].handler;
    ++currentIndex_;
    return call_immediately(STATE(iterate));
}

template<int NUM_PRIO>
StateFlowBase::Action DispatchFlowBase<NUM_PRIO>::iteration_done()
{
    if (lastHandlerToCall_)
    {
        send_transfer();
    }
    return release_and_exit();
}

#endif // _EXECUTOR_DISPATCHER_HXX_
<commit_msg>Fix a compilation error on earlier gcc versions.<commit_after>/** \copyright
 * Copyright (c) 2013, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file Dispatcher.hxx
 *
 * Class for dispatching incoming messages to handlers.
 *
 * @author Balazs Racz
 * @date 2 Dec 2013
 */

#ifndef _EXECUTOR_DISPATCHER_HXX_
#define _EXECUTOR_DISPATCHER_HXX_

#include <vector>

#include "executor/Notifiable.hxx"
#include "executor/StateFlow.hxx"

/**
   This class takes registrations of StateFlows for incoming messages. When a
   message shows up, all the Flows that match that message will be
   invoked.

   Handlers are called in no particular order.
 */
template <int NUM_PRIO>
class DispatchFlowBase : public UntypedStateFlow<QList<NUM_PRIO>>
{
public:
    /** Construct a dispatchflow.
     *
     * @param service the Service this flow belongs to. */
    DispatchFlowBase(Service *service);

    typedef StateFlowBase::Action Action;

    ~DispatchFlowBase();

    /** @returns the number of handlers registered. */
    size_t size();

protected:
    typedef uint32_t ID;
    typedef void UntypedHandler;
    /**
       Adds a new handler to this dispatcher.

       A handler will be called if incoming_id & mask == id & mask.
       If negateMatch_ then the handler will be called if incoming_id & mask !=
       id & mask.

       @param id is the identifier of the message to listen to.
       @param mask is the mask of the ID matcher. 0=match all; 0xff...f=match
       one
       @param handler is the flow to forward message to. It must stay alive so
       long as *this is alive or the handler is removed.
     */
    void register_handler(UntypedHandler *handler, ID id, ID mask);

    /// Removes a specific instance of a handler from this dispatcher.
    void unregister_handler(UntypedHandler *handler, ID id, ID mask);

    /// Removes all instances of a handler from this dispatcher.
    void unregister_handler_all(UntypedHandler *handler);

    /// Returns the current message's ID.
    virtual ID get_message_id() = 0;

    /** Allocates an entry from lastHandlerToCall_, invoking clone() when done:
     *  return allocate_and_call(lastHandlerToCall_, STATE(clone));
     */
    virtual Action allocate_and_clone() = 0;

    /** Sends the current message to lastHandlerToCall, transferring ownership.
     */
    virtual void send_transfer() = 0;

    /*typedef typename StateFlow<MessageType, QList<NUM_PRIO>>::Callback Callback;
    using StateFlow<MessageType, QList<NUM_PRIO>>::again;
    using StateFlow<MessageType, QList<NUM_PRIO>>::allocate_and_call;
    using StateFlow<MessageType, QList<NUM_PRIO>>::get_allocation_result;
    using StateFlow<MessageType, QList<NUM_PRIO>>::message;
    using StateFlow<MessageType, QList<NUM_PRIO>>::release_and_exit;
    using StateFlow<MessageType, QList<NUM_PRIO>>::transfer_message;*/
    using StateFlowBase::call_immediately;
    using StateFlowBase::again;
    using StateFlowWithQueue::release_and_exit;

    STATE_FLOW_STATE(entry);

    /*    Action entry()
        {
            currentIndex_ = 0;
            lastHandlerToCall_ = nullptr;
            return call_immediately(STATE(iterate));
            }*/

    STATE_FLOW_STATE(iterate);
    STATE_FLOW_STATE(clone_done);
    STATE_FLOW_STATE(iteration_done);

private:
    // true if this flow should negate the match condition.
    bool negateMatch_;
    friend class HubFlow;
    friend class CanHubFlow;

    struct HandlerInfo
    {
        HandlerInfo() : handler(nullptr)
        {
        }
        ID id;
        ID mask;
        // NULL if the handler has been removed.
        UntypedHandler *handler;

        bool Equals(ID id, ID mask, UntypedHandler *handler)
        {
            return (this->id == id && this->mask == mask &&
                    this->handler == handler);
        }
    };

    vector<HandlerInfo> handlers_;

    /// Index of the next handler to look at.
    size_t currentIndex_;

protected:
    /// If non-NULL we still need to call this handler.
    UntypedHandler *lastHandlerToCall_;
private:
    /// Protects handler add / remove against iteration.
    OSMutex lock_;
};

// ==================== TEMPLATED =====================

#ifdef TARGET_LPC11Cxx
#define BASE_NUM_PRIO 4
#else
#define BASE_NUM_PRIO NUM_PRIO
#endif

template <class MessageType, int NUM_PRIO>
class DispatchFlow : public TypedStateFlow<MessageType, DispatchFlowBase<BASE_NUM_PRIO> > {
public:
    typedef TypedStateFlow<MessageType, DispatchFlowBase<BASE_NUM_PRIO> > Base;

    DispatchFlow(Service *service)
        :  Base(service) {}

    typedef StateFlowBase::Action Action;
    using StateFlowBase::call_immediately;
    using StateFlowBase::allocate_and_call;
    using StateFlowBase::get_allocation_result;

    typedef FlowInterface<MessageType> HandlerType;
    typedef typename MessageType::value_type::id_type ID;

    Action entry() OVERRIDE {
        return DispatchFlowBase<BASE_NUM_PRIO>::entry();
    }

    /**
       Adds a new handler to this dispatcher.

       A handler will be called if incoming_id & mask == id & mask.
       If negateMatch_ then the handler will be called if incoming_id & mask !=
       id & mask.

       @param id is the identifier of the message to listen to.
       @param mask is the mask of the ID matcher. 0=match all; 0xff...f=match
       one
       @param handler is the flow to forward message to. It must stay alive so
       long as *this is alive or the handler is removed.
     */
    void register_handler(HandlerType *handler, ID id, ID mask) {
        Base::register_handler(handler, id, mask);
    }

    /// Removes a specific instance of a handler from this dispatcher.
    void unregister_handler(HandlerType *handler, ID id, ID mask) {
        Base::unregister_handler(handler, id, mask);
    }

    /// Removes all instances of a handler from this dispatcher.
    void unregister_handler_all(HandlerType *handler) {
        Base::unregister_handler_all(handler);
    }

protected:
    typename Base::ID get_message_id() OVERRIDE {
        return this->message()->data()->id();
    }

    Action allocate_and_clone() OVERRIDE {
        HandlerType* h = static_cast<HandlerType *>(this->lastHandlerToCall_);
        return allocate_and_call(h, STATE(clone));
    }

    Action clone() {
        HandlerType* h = static_cast<HandlerType *>(this->lastHandlerToCall_);
        MessageType *copy = this->get_allocation_result(h);
        copy->set_done(this->message()->new_child());
        *copy->data() = *this->message()->data();
        h->send(copy);
        return call_immediately(STATE(clone_done));
    }

    void send_transfer() OVERRIDE {
        HandlerType* h = static_cast<HandlerType *>(this->lastHandlerToCall_);
        h->send(this->transfer_message());
    }
};

// ================== IMPLEMENTATION ==================

template <int NUM_PRIO>
DispatchFlowBase<NUM_PRIO>::DispatchFlowBase(Service *service)
    : UntypedStateFlow<QList<NUM_PRIO>>(service)
    , negateMatch_(false)
{
}

template<int NUM_PRIO>
DispatchFlowBase<NUM_PRIO>::~DispatchFlowBase()
{
    HASSERT(this->is_waiting());
}

template<int NUM_PRIO>
size_t DispatchFlowBase<NUM_PRIO>::size()
{
    OSMutexLock h(&lock_);
    size_t ret = 0;
    for (auto &h : handlers_)
    {
        if (h.handler)
        {
            ++ret;
        }
    }
    return ret;
}

template<int NUM_PRIO>
void DispatchFlowBase<NUM_PRIO>::register_handler(UntypedHandler *handler,
                                                  ID id, ID mask)
{
    OSMutexLock h(&lock_);
    size_t idx = 0;
    while (idx < handlers_.size() && handlers_[idx].handler)
    {
        ++idx;
    }
    if (idx >= handlers_.size())
    {
        handlers_.resize(handlers_.size() + 1);
    }
    handlers_[idx].handler = handler;
    handlers_[idx].id = id;
    handlers_[idx].mask = mask;
}

template<int NUM_PRIO>
void
DispatchFlowBase<NUM_PRIO>::unregister_handler(UntypedHandler *handler,
                                               ID id, ID mask)
{
    OSMutexLock h(&lock_);
    /// @todo(balazs.racz) optimize by looking at the current index - 1.
    size_t idx = 0;
    while (idx < handlers_.size() && !handlers_[idx].Equals(id, mask, handler))
    {
        ++idx;
    }
    // Checks that we found the thing to unregister.
    HASSERT(idx < handlers_.size() &&
            "Tried to unregister a handler not previously registered.");
    handlers_[idx].handler = nullptr;
    if (idx == handlers_.size() - 1)
    {
        handlers_.resize(handlers_.size() - 1);
    }
}

template<int NUM_PRIO>
void DispatchFlowBase<NUM_PRIO>::unregister_handler_all(
    UntypedHandler *handler)
{
    OSMutexLock h(&lock_);
    for (size_t i = 0; i < handlers_.size(); ++i)
    {
        if (handlers_[i].handler == handler)
        {
            handlers_[i].handler = nullptr;
        }
    }
    while (!handlers_.empty() && handlers_.back().handler == nullptr)
    {
        handlers_.pop_back();
    }
}

template<int NUM_PRIO>
StateFlowBase::Action DispatchFlowBase<NUM_PRIO>::entry()
{
    currentIndex_ = 0;
    lastHandlerToCall_ = nullptr;
    return call_immediately(STATE(iterate));
}

template<int NUM_PRIO>
StateFlowBase::Action DispatchFlowBase<NUM_PRIO>::iterate()
{
    ID id = get_message_id();
    {
        OSMutexLock l(&lock_);
        for (; currentIndex_ < handlers_.size(); ++currentIndex_)
        {
            auto &h = handlers_[currentIndex_];
            if (!h.handler)
            {
                continue;
            }
            if (negateMatch_ && (id & h.mask) == (h.id & h.mask))
            {
                continue;
            }
            if ((!negateMatch_) && (id & h.mask) != (h.id & h.mask))
            {
                continue;
            }
            break;
        }
    }
    if (currentIndex_ >= handlers_.size())
    {
        return call_immediately(STATE(iteration_done));
    }
    // At this point: we have another handler.
    if (!lastHandlerToCall_)
    {
        // This was the first we found.
        lastHandlerToCall_ = handlers_[currentIndex_].handler;
        ++currentIndex_;
        return again();
    }
    // Now: we have at least two different handler. We need to clone the
    // message. We use the pool of the last handler to call by default.
    return allocate_and_clone();
}

template<int NUM_PRIO>
StateFlowBase::Action DispatchFlowBase<NUM_PRIO>::clone_done()
{
    lastHandlerToCall_ = handlers_[currentIndex_].handler;
    ++currentIndex_;
    return call_immediately(STATE(iterate));
}

template<int NUM_PRIO>
StateFlowBase::Action DispatchFlowBase<NUM_PRIO>::iteration_done()
{
    if (lastHandlerToCall_)
    {
        send_transfer();
    }
    return release_and_exit();
}

#endif // _EXECUTOR_DISPATCHER_HXX_
<|endoftext|>


<commit_before>#include <cstdio>

int main(){
    char n[3];
    int d, dd, h, hh, m, mm, s, ss;
    scanf("%s %d", n, &d);
    scanf("%d : %d : %d", &h, &m, &s);
    scanf("%s %d", n, &dd);
    scanf("%d : %d : %d", &hh, &mm, &ss);

    s = ss - s;
    m = mm - m;
    if (h < hh) {
        d = dd - d;
    } else {
        d = dd - d - 1;
        if (d < 0)
            d = 0;
    }
    h = hh - h;
    if (h < 0)
        h = 24 + h;

    printf("%d dia(s)\n", d);
    printf("%d hora(s)\n", h);
    printf("%d minuto(s)\n", m);
    printf("%d segundo(s)\n", s);
}
<commit_msg>Formata código no padrão.<commit_after>#include <cstdio>

int main(){
    int d, dd, h, hh, m, mm, s, ss;
    scanf("Dia %d", &d);
    scanf("%d : %d : %d\n", &h, &m, &s);
    scanf("Dia %d", &dd);
    scanf("%d : %d : %d", &hh, &mm, &ss);

    s = ss - s;
    m = mm - m;
    h = hh - h;
    d = dd - d;

    if (s < 0){
    	s += 60;
    	m--;
    }

    if (m < 0){
    	m += 60;
    	h--;
    }

    if (h < 0){
    	h += 24;
    	d--;
    }

    printf("%d dia(s)\n", d);
    printf("%d hora(s)\n", h);
    printf("%d minuto(s)\n", m);
    printf("%d segundo(s)\n", s);
}
<|endoftext|>


<commit_before>#include <enet/enet.h>
#include <map>
#include "Net.h"
#include "MessageDecode.h"
#include "Utilities/GameTime.h"

namespace Net
{

namespace Server
{

ENetHost* serverHost = NULL;
typedef std::map<unsigned int, ENetPeer*> ClientMap;
ClientMap clients;
static unsigned int nextClientID = 1;

const uint32_t SERVER_BANDWIDTH_LIMIT = 1024 * 64; // 64 kB/s
const int SERVER_MAX_CLIENTS = 8; // plucked this one out of my arse.

unsigned int badMessage[SERVER_MAX_CLIENTS+1][5]; //[clientID][n] = time bad packet was sent
unsigned int badMessageCount[SERVER_MAX_CLIENTS]; //number of bad packets sent

void Startup ( unsigned short port, const std::string& password )
{
	if (serverHost)
	{
		Shutdown();
	}
	ENetAddress addr;
	addr.port = htons(port);
	addr.host = INADDR_ANY;
	serverHost = enet_host_create(&addr, SERVER_MAX_CLIENTS, SERVER_BANDWIDTH_LIMIT, SERVER_BANDWIDTH_LIMIT);
}

void Shutdown ()
{
	if (serverHost)
	{
		clients.clear();
		enet_host_destroy(serverHost);
		serverHost = NULL;
	}
}

bool IsRunning ()
{
	return serverHost != NULL;
}

unsigned ClientCount ()
{
	return clients.size();
}

void KillClient ( unsigned int clientID ) //this is the nice disconnect
{
	ClientMap::iterator iter = clients.find(clientID);
	if (iter != clients.end())
	{
		enet_peer_disconnect_later(iter->second, 0);
		clients.erase(iter);
	}

}

void ChopClient (unsigned int clientID) //do not confuse with killClient, this is a harsh disconnect
	{
		ClientMap::iterator iter = clients.find(clientID);
		if (iter != clients.end())
		{
			enet_peer_reset(iter->second); //disconnect now, regardless of what the client does
			clients.erase(iter);
		}
	}

void SendMessage ( unsigned int clientID, const Message& msg )
{
	ClientMap::iterator iter = clients.find(clientID);
	if (iter != clients.end())
	{
		ENetPacket* packet = MessageEncoding::Encode(msg);
		enet_peer_send(iter->second, 0, packet);
	}
}

void BroadcastMessage ( const Message& msg )
{
	if (!serverHost)
		return;
	ENetPacket* packet = MessageEncoding::Encode(msg);
	enet_host_broadcast(serverHost, 0, packet);
}

bool IsConnected ( unsigned int clientID )
{
	return clients.find(clientID) != clients.end();
}

void badClient(unsigned int clientID) //deal with a bad message
	{
		time = int(GameTime());
		unsigned int* count;
		count = &badMessageCount[clientID]; //no need to take up new memory, just a pointer for simplicity

		if(count > 1)
		{
			if((time - badMessage[clientID][count]) < 10) { //kick on 2nd in 10 seconds
				KillClient(clientID);
				return;
			}
		}

		badMessageCount[clientID]++;
		badMessage[clientID][count] = time;
	}

Message* GetMessage ()
{
	ENetEvent event;
	if (enet_host_service(serverHost, &event, 0))
	{
		Message* msg = NULL;
		unsigned int clientID = 0;
		for (ClientMap::iterator iter = clients.begin(); iter != clients.end(); iter++)
		{
			if (iter->second == event.peer)
			{
				clientID = iter->first;
			}
		}
		switch (event.type)
		{
			case ENET_EVENT_TYPE_CONNECT:
				msg = new Message ( "CONNECT", NULL, 0 );
				clientID = nextClientID++;
				msg->clientID = clientID;
				clients[clientID] = event.peer;
				badMessage[clientID][0] = 0; //clear bad-message entry so it can be used
				break;
			case ENET_EVENT_TYPE_DISCONNECT:
				{
					msg = new Message ( "DISCONNECT", NULL, 0 );
					msg->clientID = clientID;
					ClientMap::iterator iter = clients.find(clientID);
					clients.erase(iter);
				}
				break;
			case ENET_EVENT_TYPE_RECEIVE:
				msg = MessageEncoding::Decode(event.packet);

				if(msg == 0) { //handle bad message
					badMessageCount[clientID] >= 4 ? KillClient[clientID] : badClient(clientID);
				} else {
					msg->clientID = clientID;
				}

				enet_packet_destroy(event.packet);
				break;
		}
		return msg;
	}
	return NULL;
}

}

}
<commit_msg>fixed mistakes I made last night<commit_after>#include <enet/enet.h>
#include <map>
#include "Net.h"
#include "MessageDecode.h"
#include "Utilities/GameTime.h"

namespace Net
{

namespace Server
{

ENetHost* serverHost = NULL;
typedef std::map<unsigned int, ENetPeer*> ClientMap;
ClientMap clients;
static unsigned int nextClientID = 1;

const uint32_t SERVER_BANDWIDTH_LIMIT = 1024 * 64; // 64 kB/s
const int SERVER_MAX_CLIENTS = 8; // plucked this one out of my arse.

unsigned int badMessage[SERVER_MAX_CLIENTS+1][5]; //[clientID][n] = time bad packet was sent
unsigned int badMessageCount[SERVER_MAX_CLIENTS]; //number of bad packets sent

void Startup ( unsigned short port, const std::string& password )
{
	if (serverHost)
	{
		Shutdown();
	}
	ENetAddress addr;
	addr.port = htons(port);
	addr.host = INADDR_ANY;
	serverHost = enet_host_create(&addr, SERVER_MAX_CLIENTS, SERVER_BANDWIDTH_LIMIT, SERVER_BANDWIDTH_LIMIT);
}

void Shutdown ()
{
	if (serverHost)
	{
		clients.clear();
		enet_host_destroy(serverHost);
		serverHost = NULL;
	}
}

bool IsRunning ()
{
	return serverHost != NULL;
}

unsigned ClientCount ()
{
	return clients.size();
}

void KillClient ( unsigned int clientID ) //this is the nice disconnect
{
	ClientMap::iterator iter = clients.find(clientID);
	if (iter != clients.end())
	{
		enet_peer_disconnect_later(iter->second, 0);
		clients.erase(iter);
	}

}

void ChopClient (unsigned int clientID) //do not confuse with killClient, this is a harsh disconnect
	{
		ClientMap::iterator iter = clients.find(clientID);
		if (iter != clients.end())
		{
			enet_peer_reset(iter->second); //disconnect now, regardless of what the client does
			clients.erase(iter);
		}
	}

void SendMessage ( unsigned int clientID, const Message& msg )
{
	ClientMap::iterator iter = clients.find(clientID);
	if (iter != clients.end())
	{
		ENetPacket* packet = MessageEncoding::Encode(msg);
		enet_peer_send(iter->second, 0, packet);
	}
}

void BroadcastMessage ( const Message& msg )
{
	if (!serverHost)
		return;
	ENetPacket* packet = MessageEncoding::Encode(msg);
	enet_host_broadcast(serverHost, 0, packet);
}

bool IsConnected ( unsigned int clientID )
{
	return clients.find(clientID) != clients.end();
}

void badClient(unsigned int clientID) //deal with a bad message
	{
		time = int(GameTime());

		if(count > 1)
		{
			if((time - badMessage[clientID][badMessageCount[clientID]]) < 10) { //kick on 2nd in 10 seconds
				KillClient(clientID);
				return;
			}
		}

		badMessageCount[clientID]++;
		badMessage[clientID][badMessageCount[clientID]] = time;
	}

Message* GetMessage ()
{
	ENetEvent event;
	if (enet_host_service(serverHost, &event, 0))
	{
		Message* msg = NULL;
		unsigned int clientID = 0;
		for (ClientMap::iterator iter = clients.begin(); iter != clients.end(); iter++)
		{
			if (iter->second == event.peer)
			{
				clientID = iter->first;
			}
		}
		switch (event.type)
		{
			case ENET_EVENT_TYPE_CONNECT:
				msg = new Message ( "CONNECT", NULL, 0 );
				clientID = nextClientID++;
				msg->clientID = clientID;
				clients[clientID] = event.peer;
				badMessage[clientID][0] = 0; //clear bad-message entry so it can be used
				break;
			case ENET_EVENT_TYPE_DISCONNECT:
				{
					msg = new Message ( "DISCONNECT", NULL, 0 );
					msg->clientID = clientID;
					ClientMap::iterator iter = clients.find(clientID);
					clients.erase(iter);
				}
				break;
			case ENET_EVENT_TYPE_RECEIVE:
				msg = MessageEncoding::Decode(event.packet);

				if(msg == 0) { //handle bad message
					badMessageCount[clientID] >= 4 ? KillClient[clientID] : badClient(clientID);
				} else {
					msg->clientID = clientID;
				}

				enet_packet_destroy(event.packet);
				break;
		}
		return msg;
	}
	return NULL;
}

}

}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	delay
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>

namespace utils {

	//-----------------------------------------------------------------//
	/*!
		@brief	無駄ループによる時間待ち
		@param[in]	n	無駄ループ回数
	 */
	//-----------------------------------------------------------------//
	inline void wait_delay(uint32_t n) {
		static volatile uint8_t dummy_;
		// とりあえず無駄ループ
		for(uint32_t i = 0; i < n; ++i) {
			dummy_ += i & 255;
		}
	}
}
<commit_msg>update delay loop<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	delay ユーティリティー (RX) @n
			Copyright 2016 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>

#ifndef F_PCKA
#  error "delay.hpp requires F_PCKA to be defined"
#endif

namespace utils {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  ソフトウェアー待ち
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	struct delay {

		//-----------------------------------------------------------------//
		/*!
			@brief  マイクロ秒単位の待ち
			@param[in]	us	待ち時間（マイクロ秒）
		*/
		//-----------------------------------------------------------------//
		static void micro_second(uint32_t us) {
			while(us > 0) {
				for(uint32_t n = 0; n < (F_PCKA / 4285714); ++n) {
					asm("nop");
				}
				--us;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  ミリ秒単位の待ち
			@param[in]	ms	待ち時間（ミリ秒）
		*/
		//-----------------------------------------------------------------//
		static void milli_second(uint32_t ms) {
			for(uint32_t i = 0; i < ms; ++i) {
				micro_second(1000);
			}
		}
	};
}
<|endoftext|>


<commit_before>#ifndef __MODEL_HPP_INCLUDED
#define __MODEL_HPP_INCLUDED

// Include GLEW
#ifndef __GL_GLEW_H_INCLUDED
#define __GL_GLEW_H_INCLUDED
#include <GL/glew.h>
#endif

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

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

#include <iostream>
#include <queue> // std::queue
#include <string.h>
#include "globals.hpp"
#include "shader.hpp"
#include "heightmap_loader.hpp"
#include "objloader.hpp"

namespace model
{
    class World
    {
        public:
            // constructor.
            World();

            // destructor.
            ~World();

            // this method renders the entire world, one shader at a time.
            void render();

            // this method sets a shader pointer.
            void set_shader_pointer(GLuint shaderID, void* shader_pointer);

            // this method gets a shader pointer.
            void* get_shader_pointer(GLuint shaderID);

            // this method gets a shader ID and removes it from the `free_shaderID_queue` if it was popped from the queue.
            GLuint get_shaderID();

        private:
            std::vector<void*> shader_pointer_vector;
            std::queue<GLuint> free_shaderID_queue;
    };

    class Shader
    {
        public:
            // constructor.
            Shader(ShaderStruct shader_struct);

            // destructor.
            ~Shader();

            // this method renders all textures using this shader.
            void render();

            // this method sets a texture pointer.
            void set_texture_pointer(GLuint textureID, void* texture_pointer);

            // this method gets a texture pointer.
            void* get_texture_pointer(GLuint textureID);

            // this method gets a texture ID and removes it from the `free_textureID_queue` if it was popped from the queue.
            GLuint get_textureID();

            // this method sets pointer to this shader to NULL, sets `world_pointer` according to the input, and requests a new `shaderID` from the new world.
            void switch_to_new_world(model::World *new_world_pointer);

            model::World *world_pointer;          // pointer to the world.

            GLuint programID;                     // shaders' programID, returned by `LoadShaders`.

        private:
            void bind_to_world();

            GLuint shaderID;                      // shader ID, returned by `model::World->get_shaderID()`.

            std::string vertex_shader;            // filename of vertex shader.
            std::string fragment_shader;          // filename of fragment shader.

            std::vector<void*> texture_pointer_vector;
            std::queue<GLuint> free_textureID_queue;

            const char *char_vertex_shader;
            const char *char_fragment_shader;
    };

    class Texture
    {
        public:
            void bind_to_shader();

            // constructor.
            Texture(TextureStruct texture_struct);

            // destructor.
            ~Texture();

            // this method renders all species using this texture.
            void render();

            // this method sets a species pointer.
            void set_species_pointer(GLuint speciesID, void* species_pointer);

            // this method gets a species pointer.
            void* get_species_pointer(GLuint speciesID);

            // this method gets a species ID and removes it from the `free_speciesID_queue` if it was popped from the queue.
            GLuint get_speciesID();

            // this method sets pointer to this shader to NULL, sets `shader_pointer` according to the input, and requests a new `textureID` from the new shader.
            void switch_to_new_shader(model::Shader *new_world_pointer);

            model::Shader *shader_pointer;         // pointer to the shader.

        private:
            GLuint texture;                        // Texture, returned by `load_DDS_texture` or `load_BMP_texture`.
            GLuint openGL_textureID;               // texture ID, returned by `glGetUniformLocation(programID, "myTextureSampler");`.

            std::vector<void*> species_pointer_vector;
            std::queue<GLuint> free_speciesID_queue;

            std::string texture_file_format;       // type of the model file, eg. `"bmp"`.
            std::string texture_filename;          // filename of the model file.
            GLuint textureID;                      // texture ID, returned by `Shader::get_textureID`.
            const char *char_texture_file_format;
            const char *char_texture_filename;
    };

    class Graph
    {
        public:
            // constructor.
            Graph();

            // destructor.
            ~Graph();

            // this method sets a node pointer.
            void set_node_pointer(GLuint nodeID, void* node_pointer);

            // this method gets a node pointer.
            void* get_node_pointer(GLuint nodeID);

            // this method gets a node ID and removes it from the `free_nodeID_queue` if it was popped from the queue.
            GLuint get_nodeID();

        private:
            std::vector<void*> node_pointer_vector;
            std::queue<GLuint> free_nodeID_queue;
    };

    // `Node` is not a subclass of `Graph` because if the graph splits, node may be transferred to an another graph.
    // Transferring a node to a new graph naturally requires appropriate reindexing of `nodeID`s.
    // The graph in which a node belongs is accessible through `void* graph_pointer` (must be cast to `model::Graph*`).
    class Node
    {
        public:
            // constructor.
            Node(NodeStruct node_struct);

            // destructor.
            ~Node();

            // this method creates a bidirectional link.
            // creating of bidirectional links is not possible before all nodes are created.
            void create_bidirectional_link(GLuint nodeID);

            // this method deletes a bidirectional link.
            // deleting of links is not possible before all nodes are created.
            void delete_bidirectional_link(GLuint nodeID);

            // this method transfers this node to a new graph.
            // links will not be changed.
            // all nodes that are to be transferred must be transferred separately.
            // before transfering any node to a new graph,
            // all links to nodes that do not belong to the new graph of this node must be deleted with separate `delete_bidirectional_link` calls.
            void transfer_to_new_graph(model::Graph *new_graph_pointer);

            GLuint nodeID;
            model::Graph *graph_pointer;

            // nodes do not keep pointers to neighbor nodes, because all pointer values are not known yet before all nodes are created.
            std::vector<GLuint> neighbor_nodeIDs;

        private:
            // this method creates an unidirectional link.
            // in the constructor only unidirectional links can be created.
            void create_unidirectional_link(GLuint nodeID);

            // this method deletes an unidirectional link.
            void delete_unidirectional_link(GLuint nodeID);

            glm::vec3 coordinate_vector;
    };

    class Species
    {
        public:
            void bind_to_texture();

            // constructor.
            Species(SpeciesStruct species_struct);

            // destructor.
            ~Species();

            // this method renders all objects of this species.
            void render();

            // this method sets a object pointer.
            void set_object_pointer(GLuint objectID, void* object_pointer);

            // this method gets a object pointer.
            void* get_object_pointer(GLuint objectID);

            // this method gets a object ID and removes it from the `free_objectID_queue` if it was popped from the queue.
            GLuint get_objectID();

            // this method sets pointer to this species to NULL, sets `texture_pointer` according to the input, and requests a new `speciesID` from the new texture.
            void switch_to_new_texture(model::Texture *new_texture_pointer);

            bool is_world;                           // worlds currently do not rotate nor translate.

            std::string color_channel;               // color channel in use: `"red"`, `"green"`, `"blue"`, `"mean"` or `"all"`.
            std::vector<ObjectStruct> object_vector; // vector of individual objects of this species.
            glm::vec3 lightPos;                      // light position.

            // The rest fields are created in the constructor.
            GLuint image_width;
            GLuint image_height;

            GLuint MatrixID;
            GLuint ViewMatrixID;
            GLuint ModelMatrixID;
            GLuint vertexPosition_modelspaceID;
            GLuint vertexUVID;
            GLuint vertexNormal_modelspaceID;

            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object.

            std::vector<GLuint> indices;           // the deleted vertices will be reused (though it is not required, if there's enough memory).
            std::vector<glm::vec3> indexed_vertices;
            std::vector<glm::vec2> indexed_UVs;
            std::vector<glm::vec3> indexed_normals;

            GLuint vertexbuffer;
            GLuint uvbuffer;
            GLuint normalbuffer;
            GLuint elementbuffer;

            glm::mat4 ProjectionMatrix;
            glm::mat4 ViewMatrix;
        private:
            model::Texture *texture_pointer;       // pointer to the texture.

            std::string model_file_format;         // type of the model file, eg. `"bmp"`.
            std::string model_filename;            // filename of the model file.
            GLuint speciesID;                      // species ID, returned by `model::Texture->get_speciesID()`.
            GLuint lightID;                        // light ID, returned by `glGetUniformLocation(programID, "LightPosition_worldspace");`.
            const char *char_model_file_format;
            const char *char_model_filename;
            const char *char_color_channel;

            std::vector<void*> object_pointer_vector;
            std::queue<GLuint> free_objectID_queue;
    };

    class Object
    {
        public:
            void bind_to_species();

            // constructor.
            Object(ObjectStruct object_struct);

            // destructor.
            ~Object();

            // this method renders this object.
            void render();

            // this method sets pointer to this object to NULL, sets `species_pointer` according to the input, and requests a new `objectID` from the new species.
            void switch_to_new_species(model::Species *new_species_pointer);

            model::Species *species_pointer;       // pointer to the species.

            GLuint objectID;                      // object ID, returned by `model::Species->get_objectID()`.

            bool has_entered;
            glm::vec3 coordinate_vector;           // rotate vector.
            GLfloat rotate_angle;                  // rotate angle.
            glm::vec3 rotate_vector;               // rotate vector.
            glm::vec3 translate_vector;            // translate vector.

            // The rest fields are created in the constructor.
            glm::mat4 model_matrix;                // model matrix.
            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object. not used at the moment.

            glm::mat4 MVP_matrix;                  // model view projection matrix.
    };
}

#endif
<commit_msg>`class Texture`: `void bind_to_shader()` on `private`-funktio.<commit_after>#ifndef __MODEL_HPP_INCLUDED
#define __MODEL_HPP_INCLUDED

// Include GLEW
#ifndef __GL_GLEW_H_INCLUDED
#define __GL_GLEW_H_INCLUDED
#include <GL/glew.h>
#endif

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

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

#include <iostream>
#include <queue> // std::queue
#include <string.h>
#include "globals.hpp"
#include "shader.hpp"
#include "heightmap_loader.hpp"
#include "objloader.hpp"

namespace model
{
    class World
    {
        public:
            // constructor.
            World();

            // destructor.
            ~World();

            // this method renders the entire world, one shader at a time.
            void render();

            // this method sets a shader pointer.
            void set_shader_pointer(GLuint shaderID, void* shader_pointer);

            // this method gets a shader pointer.
            void* get_shader_pointer(GLuint shaderID);

            // this method gets a shader ID and removes it from the `free_shaderID_queue` if it was popped from the queue.
            GLuint get_shaderID();

        private:
            std::vector<void*> shader_pointer_vector;
            std::queue<GLuint> free_shaderID_queue;
    };

    class Shader
    {
        public:
            // constructor.
            Shader(ShaderStruct shader_struct);

            // destructor.
            ~Shader();

            // this method renders all textures using this shader.
            void render();

            // this method sets a texture pointer.
            void set_texture_pointer(GLuint textureID, void* texture_pointer);

            // this method gets a texture pointer.
            void* get_texture_pointer(GLuint textureID);

            // this method gets a texture ID and removes it from the `free_textureID_queue` if it was popped from the queue.
            GLuint get_textureID();

            // this method sets pointer to this shader to NULL, sets `world_pointer` according to the input, and requests a new `shaderID` from the new world.
            void switch_to_new_world(model::World *new_world_pointer);

            model::World *world_pointer;          // pointer to the world.

            GLuint programID;                     // shaders' programID, returned by `LoadShaders`.

        private:
            void bind_to_world();

            GLuint shaderID;                      // shader ID, returned by `model::World->get_shaderID()`.

            std::string vertex_shader;            // filename of vertex shader.
            std::string fragment_shader;          // filename of fragment shader.

            std::vector<void*> texture_pointer_vector;
            std::queue<GLuint> free_textureID_queue;

            const char *char_vertex_shader;
            const char *char_fragment_shader;
    };

    class Texture
    {
        public:
            // constructor.
            Texture(TextureStruct texture_struct);

            // destructor.
            ~Texture();

            // this method renders all species using this texture.
            void render();

            // this method sets a species pointer.
            void set_species_pointer(GLuint speciesID, void* species_pointer);

            // this method gets a species pointer.
            void* get_species_pointer(GLuint speciesID);

            // this method gets a species ID and removes it from the `free_speciesID_queue` if it was popped from the queue.
            GLuint get_speciesID();

            // this method sets pointer to this shader to NULL, sets `shader_pointer` according to the input, and requests a new `textureID` from the new shader.
            void switch_to_new_shader(model::Shader *new_world_pointer);

            model::Shader *shader_pointer;         // pointer to the shader.

        private:
            void bind_to_shader();

            GLuint texture;                        // Texture, returned by `load_DDS_texture` or `load_BMP_texture`.
            GLuint openGL_textureID;               // texture ID, returned by `glGetUniformLocation(programID, "myTextureSampler");`.

            std::vector<void*> species_pointer_vector;
            std::queue<GLuint> free_speciesID_queue;

            std::string texture_file_format;       // type of the model file, eg. `"bmp"`.
            std::string texture_filename;          // filename of the model file.
            GLuint textureID;                      // texture ID, returned by `Shader::get_textureID`.
            const char *char_texture_file_format;
            const char *char_texture_filename;
    };

    class Graph
    {
        public:
            // constructor.
            Graph();

            // destructor.
            ~Graph();

            // this method sets a node pointer.
            void set_node_pointer(GLuint nodeID, void* node_pointer);

            // this method gets a node pointer.
            void* get_node_pointer(GLuint nodeID);

            // this method gets a node ID and removes it from the `free_nodeID_queue` if it was popped from the queue.
            GLuint get_nodeID();

        private:
            std::vector<void*> node_pointer_vector;
            std::queue<GLuint> free_nodeID_queue;
    };

    // `Node` is not a subclass of `Graph` because if the graph splits, node may be transferred to an another graph.
    // Transferring a node to a new graph naturally requires appropriate reindexing of `nodeID`s.
    // The graph in which a node belongs is accessible through `void* graph_pointer` (must be cast to `model::Graph*`).
    class Node
    {
        public:
            // constructor.
            Node(NodeStruct node_struct);

            // destructor.
            ~Node();

            // this method creates a bidirectional link.
            // creating of bidirectional links is not possible before all nodes are created.
            void create_bidirectional_link(GLuint nodeID);

            // this method deletes a bidirectional link.
            // deleting of links is not possible before all nodes are created.
            void delete_bidirectional_link(GLuint nodeID);

            // this method transfers this node to a new graph.
            // links will not be changed.
            // all nodes that are to be transferred must be transferred separately.
            // before transfering any node to a new graph,
            // all links to nodes that do not belong to the new graph of this node must be deleted with separate `delete_bidirectional_link` calls.
            void transfer_to_new_graph(model::Graph *new_graph_pointer);

            GLuint nodeID;
            model::Graph *graph_pointer;

            // nodes do not keep pointers to neighbor nodes, because all pointer values are not known yet before all nodes are created.
            std::vector<GLuint> neighbor_nodeIDs;

        private:
            // this method creates an unidirectional link.
            // in the constructor only unidirectional links can be created.
            void create_unidirectional_link(GLuint nodeID);

            // this method deletes an unidirectional link.
            void delete_unidirectional_link(GLuint nodeID);

            glm::vec3 coordinate_vector;
    };

    class Species
    {
        public:
            void bind_to_texture();

            // constructor.
            Species(SpeciesStruct species_struct);

            // destructor.
            ~Species();

            // this method renders all objects of this species.
            void render();

            // this method sets a object pointer.
            void set_object_pointer(GLuint objectID, void* object_pointer);

            // this method gets a object pointer.
            void* get_object_pointer(GLuint objectID);

            // this method gets a object ID and removes it from the `free_objectID_queue` if it was popped from the queue.
            GLuint get_objectID();

            // this method sets pointer to this species to NULL, sets `texture_pointer` according to the input, and requests a new `speciesID` from the new texture.
            void switch_to_new_texture(model::Texture *new_texture_pointer);

            bool is_world;                           // worlds currently do not rotate nor translate.

            std::string color_channel;               // color channel in use: `"red"`, `"green"`, `"blue"`, `"mean"` or `"all"`.
            std::vector<ObjectStruct> object_vector; // vector of individual objects of this species.
            glm::vec3 lightPos;                      // light position.

            // The rest fields are created in the constructor.
            GLuint image_width;
            GLuint image_height;

            GLuint MatrixID;
            GLuint ViewMatrixID;
            GLuint ModelMatrixID;
            GLuint vertexPosition_modelspaceID;
            GLuint vertexUVID;
            GLuint vertexNormal_modelspaceID;

            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object.

            std::vector<GLuint> indices;           // the deleted vertices will be reused (though it is not required, if there's enough memory).
            std::vector<glm::vec3> indexed_vertices;
            std::vector<glm::vec2> indexed_UVs;
            std::vector<glm::vec3> indexed_normals;

            GLuint vertexbuffer;
            GLuint uvbuffer;
            GLuint normalbuffer;
            GLuint elementbuffer;

            glm::mat4 ProjectionMatrix;
            glm::mat4 ViewMatrix;
        private:
            model::Texture *texture_pointer;       // pointer to the texture.

            std::string model_file_format;         // type of the model file, eg. `"bmp"`.
            std::string model_filename;            // filename of the model file.
            GLuint speciesID;                      // species ID, returned by `model::Texture->get_speciesID()`.
            GLuint lightID;                        // light ID, returned by `glGetUniformLocation(programID, "LightPosition_worldspace");`.
            const char *char_model_file_format;
            const char *char_model_filename;
            const char *char_color_channel;

            std::vector<void*> object_pointer_vector;
            std::queue<GLuint> free_objectID_queue;
    };

    class Object
    {
        public:
            void bind_to_species();

            // constructor.
            Object(ObjectStruct object_struct);

            // destructor.
            ~Object();

            // this method renders this object.
            void render();

            // this method sets pointer to this object to NULL, sets `species_pointer` according to the input, and requests a new `objectID` from the new species.
            void switch_to_new_species(model::Species *new_species_pointer);

            model::Species *species_pointer;       // pointer to the species.

            GLuint objectID;                      // object ID, returned by `model::Species->get_objectID()`.

            bool has_entered;
            glm::vec3 coordinate_vector;           // rotate vector.
            GLfloat rotate_angle;                  // rotate angle.
            glm::vec3 rotate_vector;               // rotate vector.
            glm::vec3 translate_vector;            // translate vector.

            // The rest fields are created in the constructor.
            glm::mat4 model_matrix;                // model matrix.
            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object. not used at the moment.

            glm::mat4 MVP_matrix;                  // model view projection matrix.
    };
}

#endif
<|endoftext|>