<commit_before>#include <cstdlib>
#include <ctime>
#include <iostream>
#include <iterator>

#include "bench_common.h"
#include <dariadb.h>
#include <algorithm>
#include <atomic>
#include <chrono>
#include <cmath>
#include <ctime>
#include <limits>
#include <random>
#include <storage/capacitor.h>
#include <thread>
#include <utils/fs.h>
#include <utils/metrics.h>
#include <boost/program_options.hpp>

namespace po = boost::program_options;

std::atomic_long append_count{0};
std::atomic_size_t reads_count{0};
bool stop_info = false;
bool stop_readers = false;

class BenchCallback : public dariadb::storage::ReaderClb {
public:
  BenchCallback() { count = 0; }
  void call(const dariadb::Meas &) { count++; }
  size_t count;
};

void show_info(dariadb::storage::Engine *storage) {
  clock_t t0 = clock();
  auto all_writes = dariadb_bench::total_threads_count * dariadb_bench::iteration_count;
  while (true) {
    std::this_thread::sleep_for(std::chrono::milliseconds(100));

    clock_t t1 = clock();
    auto writes_per_sec = append_count.load() / double((t1 - t0) / CLOCKS_PER_SEC);
    auto reads_per_sec = reads_count.load() / double((t1 - t0) / CLOCKS_PER_SEC);
    auto queue_sizes = storage->queue_size();
    std::cout << "\r"
              << " in queue: (p:" << queue_sizes.pages_count
              << " cap:" << queue_sizes.cola_count << " a:" << queue_sizes.aofs_count
              << ")"
              << " reads: " << reads_count << " speed:" << reads_per_sec << "/sec"
              << " writes: " << append_count << " speed: " << writes_per_sec
              << "/sec progress:" << (int64_t(100) * append_count) / all_writes
              << "%                ";
    std::cout.flush();
    if (stop_info) {
      std::cout.flush();
      break;
    }
  }
  std::cout << "\n";
}

void reader(dariadb::storage::MeasStorage_ptr ms, dariadb::IdSet all_id_set,
            dariadb::Time from, dariadb::Time to) {
  std::random_device r;
  std::default_random_engine e1(r());
  std::uniform_int_distribution<dariadb::Id> uniform_dist(from, to);
  std::shared_ptr<BenchCallback> clbk{new BenchCallback};

  while (true) {
    clbk->count = 0;
    auto time_point1 = uniform_dist(e1);
    auto time_point2 = uniform_dist(e1);
    auto f = std::min(time_point1, time_point2);
    auto t = std::max(time_point1, time_point2);

    auto qi = dariadb::storage::QueryInterval(
        dariadb::IdArray(all_id_set.begin(), all_id_set.end()), 0, f, t);
    ms->readInterval(qi)->readAll(clbk.get());

    reads_count += clbk->count;
    if (stop_readers) {
      break;
    }
  }
}

int main(int argc, char *argv[]) {
  (void)argc;
  (void)argv;
  std::cout << "Performance benchmark" << std::endl;
  std::cout << "Writers count:" << dariadb_bench::total_threads_count << std::endl;

  const std::string storage_path = "testStorage";
  bool readers_enable = false;
  bool metrics_enable = false;
  bool readonly = false;
  bool readall_enabled = false;
  bool dont_clean = false;
  po::options_description desc("Allowed options");
  desc.add_options()("help", "produce help message")
          ("readonly", "readonly mode")
	  ("readall", "read all benchmark enable.")
	  ("enable-readers", po::value<bool>(&readers_enable)->default_value(readers_enable),"enable readers threads")
	  ("enable-metrics", po::value<bool>(&metrics_enable)->default_value(metrics_enable))
	  ("dont-clean", po::value<bool>(&dont_clean)->default_value(dont_clean),"dont clean storage path before start.");

  po::variables_map vm;
  try {
    po::store(po::parse_command_line(argc, argv, desc), vm);
  } catch (std::exception &ex) {
    logger("Error: " << ex.what());
    exit(1);
  }
  po::notify(vm);

  if (vm.count("help")) {
    std::cout << desc << std::endl;
    return 1;
  }

  if (metrics_enable) {
	  std::cout << "enable metrics." << std::endl;
  }

  if (vm.count("readonly")) {
      std::cout << "Readonly mode." << std::endl;
    readonly=true;
  }

  if (vm.count("readall")) {
	  std::cout << "Read all benchmark enabled." << std::endl;
	  readall_enabled = true;
  }

  if (readers_enable) {
    std::cout << "Readers enable. count: " << dariadb_bench::total_readers_count
              << std::endl;
  }

  {
    std::cout << "write..." << std::endl;

    const size_t chunk_per_storage = 1024 * 100;
    const size_t chunk_size = 1024;
    const size_t cap_B = 50;
    const size_t max_mem_chunks = 100;

    // dont_clean = true;
    if (!dont_clean && dariadb::utils::fs::path_exists(storage_path)) {
        if(!readonly){
            std::cout<<" remove "<<storage_path<<std::endl;
            dariadb::utils::fs::rm(storage_path);
        }
    }

    dariadb::Time start_time = dariadb::timeutil::current_time();
    std::cout << " start time: " << dariadb::timeutil::to_string(start_time) << std::endl;
    dariadb::storage::PageManager::Params page_param(storage_path, chunk_per_storage,
                                                     chunk_size);
    dariadb::storage::CapacitorManager::Params cap_param(storage_path, cap_B);
    cap_param.max_levels = 11;

    dariadb::storage::AOFManager::Params aof_param(storage_path, 0);
    aof_param.buffer_size = 1000;
    aof_param.max_size = cap_param.measurements_count();

    cap_param.max_levels = 11;
    auto raw_ptr =
        new dariadb::storage::Engine(aof_param, page_param, cap_param,
                                     dariadb::storage::Engine::Limits(max_mem_chunks));

    dariadb::storage::MeasStorage_ptr ms{raw_ptr};

    dariadb::IdSet all_id_set;
    append_count = 0;
    stop_info = false;

    std::thread info_thread(show_info, raw_ptr);

    std::vector<std::thread> writers(dariadb_bench::total_threads_count);
    std::vector<std::thread> readers(dariadb_bench::total_readers_count);

    size_t pos = 0;
    for (size_t i = 1; i < dariadb_bench::total_threads_count + 1; i++) {
      auto id_from = dariadb_bench::get_id_from(pos);
      auto id_to = dariadb_bench::get_id_to(pos);
      for (size_t j = id_from; j < id_to; j++) {
        all_id_set.insert(j);
      }
      if(!readonly){
          std::thread t{dariadb_bench::thread_writer_rnd_stor, dariadb::Id(pos),
                      dariadb::Time(i), &append_count, raw_ptr};
          writers[pos] = std::move(t);
      }
	  pos++;
    }
    if (readers_enable) {
      pos = 0;
      for (size_t i = 1; i < dariadb_bench::total_readers_count + 1; i++) {
        std::thread t{reader, ms, all_id_set, dariadb::Time(0),
                      dariadb::timeutil::current_time()};
        readers[pos++] = std::move(t);
      }
    }

    if(!readonly){
        pos = 0;
        for (size_t i = 1; i < dariadb_bench::total_threads_count + 1; i++) {
            std::thread t = std::move(writers[pos++]);
            t.join();
        }
    }
    stop_readers = true;
    if (readers_enable) {
      pos = 0;
      for (size_t i = 1; i < dariadb_bench::total_readers_count + 1; i++) {
        std::thread t = std::move(readers[pos++]);
        t.join();
      }
    }

    stop_info = true;
    info_thread.join();
    std::cout << " total id:" << all_id_set.size() << std::endl;
    {
      std::cout << "full flush..." << std::endl;
      auto start = clock();
      raw_ptr->flush();
      auto elapsed = (((float)clock() - start) / CLOCKS_PER_SEC);
      std::cout << "flush time: " << elapsed << std::endl;
    }

    auto queue_sizes = raw_ptr->queue_size();
    std::cout << "\r"
              << " in queue: (p:" << queue_sizes.pages_count
              << " cap:" << queue_sizes.cola_count << " a:" << queue_sizes.aofs_count
              << ")"
              << " reads: " << reads_count
              << " writes: " << append_count
              << std::endl;

    dariadb_bench::readBenchark(all_id_set, ms.get(), 10, start_time,
                                dariadb::timeutil::current_time());
	if(readall_enabled){
      std::cout << "read all..." << std::endl;
      std::shared_ptr<BenchCallback> clbk{new BenchCallback()};
      auto max_time = ms->maxTime();
      std::cout << " end time: " << dariadb::timeutil::to_string(max_time) << std::endl;

      auto start = clock();

      dariadb::storage::QueryInterval qi{
          dariadb::IdArray(all_id_set.begin(), all_id_set.end()), 0, start_time,
          max_time};
      ms->readInterval(qi)->readAll(clbk.get());

      auto elapsed = (((float)clock() - start) / CLOCKS_PER_SEC);
      std::cout << "readed: " << clbk->count << std::endl;
      std::cout << "time: " << elapsed << std::endl;
      auto expected = (dariadb_bench::iteration_count *
                       dariadb_bench::total_threads_count * dariadb_bench::id_per_thread);

      if (!readonly && (!dont_clean && clbk->count != expected))  {
        std::cout << "expected: " << expected << " get:" << clbk->count << std::endl;
        throw MAKE_EXCEPTION("(clbk->count!=(iteration_count*total_threads_count))");
      } else {
        if (!readonly && (dont_clean && clbk->count < expected)) {
          std::cout << "expected: " << expected << " get:" << clbk->count << std::endl;
          throw MAKE_EXCEPTION("(clbk->count!=(iteration_count*total_threads_count))");
        }
      }
    }
    std::cout << "stoping storage...\n";
    ms = nullptr;
  }
  std::cout << "cleaning...\n";
  if (dariadb::utils::fs::path_exists(storage_path)) {
    dariadb::utils::fs::rm(storage_path);
  }
  if (metrics_enable) {
	  std::cout << "metrics:\n" << dariadb::utils::MetricsManager::instance()->to_string() << std::endl;
  }
}
<commit_msg>perf_benchmark: refact.<commit_after>#include <cstdlib>
#include <ctime>
#include <iostream>
#include <iterator>

#include "bench_common.h"
#include <dariadb.h>
#include <algorithm>
#include <atomic>
#include <chrono>
#include <cmath>
#include <ctime>
#include <limits>
#include <random>
#include <storage/capacitor.h>
#include <thread>
#include <utils/fs.h>
#include <utils/metrics.h>
#include <boost/program_options.hpp>

namespace po = boost::program_options;

std::atomic_long append_count{0};
std::atomic_size_t reads_count{0};
bool stop_info = false;
bool stop_readers = false;

class BenchCallback : public dariadb::storage::ReaderClb {
public:
  BenchCallback() { count = 0; }
  void call(const dariadb::Meas &) { count++; }
  size_t count;
};

void show_info(dariadb::storage::Engine *storage) {
  clock_t t0 = clock();
  auto all_writes = dariadb_bench::total_threads_count * dariadb_bench::iteration_count;
  while (true) {
    std::this_thread::sleep_for(std::chrono::milliseconds(100));

    clock_t t1 = clock();
    auto writes_per_sec = append_count.load() / double((t1 - t0) / CLOCKS_PER_SEC);
    auto reads_per_sec = reads_count.load() / double((t1 - t0) / CLOCKS_PER_SEC);
    auto queue_sizes = storage->queue_size();
    std::cout << "\r"
              << " in queue: (p:" << queue_sizes.pages_count
              << " cap:" << queue_sizes.cola_count << " a:" << queue_sizes.aofs_count
              << ")"
              << " reads: " << reads_count << " speed:" << reads_per_sec << "/sec"
              << " writes: " << append_count << " speed: " << writes_per_sec
              << "/sec progress:" << (int64_t(100) * append_count) / all_writes
              << "%                ";
    std::cout.flush();
    if (stop_info) {
      std::cout.flush();
      break;
    }
  }
  std::cout << "\n";
}

void reader(dariadb::storage::MeasStorage_ptr ms, dariadb::IdSet all_id_set,
            dariadb::Time from, dariadb::Time to) {
  std::random_device r;
  std::default_random_engine e1(r());
  std::uniform_int_distribution<dariadb::Id> uniform_dist(from, to);
  std::shared_ptr<BenchCallback> clbk{new BenchCallback};

  while (true) {
    clbk->count = 0;
    auto time_point1 = uniform_dist(e1);
    auto time_point2 = uniform_dist(e1);
    auto f = std::min(time_point1, time_point2);
    auto t = std::max(time_point1, time_point2);

    auto qi = dariadb::storage::QueryInterval(
        dariadb::IdArray(all_id_set.begin(), all_id_set.end()), 0, f, t);
    ms->readInterval(qi)->readAll(clbk.get());

    reads_count += clbk->count;
    if (stop_readers) {
      break;
    }
  }
}

int main(int argc, char *argv[]) {
  (void)argc;
  (void)argv;
  std::cout << "Performance benchmark" << std::endl;
  std::cout << "Writers count:" << dariadb_bench::total_threads_count << std::endl;

  const std::string storage_path = "testStorage";
  bool readers_enable = false;
  bool metrics_enable = false;
  bool readonly = false;
  bool readall_enabled = false;
  bool dont_clean = false;
  po::options_description desc("Allowed options");
  desc.add_options()("help", "produce help message")
          ("readonly", "readonly mode")
	  ("readall", "read all benchmark enable.")
	  ("enable-readers", po::value<bool>(&readers_enable)->default_value(readers_enable),"enable readers threads")
	  ("enable-metrics", po::value<bool>(&metrics_enable)->default_value(metrics_enable))
	  ("dont-clean", po::value<bool>(&dont_clean)->default_value(dont_clean),"dont clean storage path before start.");

  po::variables_map vm;
  try {
    po::store(po::parse_command_line(argc, argv, desc), vm);
  } catch (std::exception &ex) {
    logger("Error: " << ex.what());
    exit(1);
  }
  po::notify(vm);

  if (vm.count("help")) {
    std::cout << desc << std::endl;
    return 1;
  }

  if (metrics_enable) {
	  std::cout << "enable metrics." << std::endl;
  }

  if (vm.count("readonly")) {
      std::cout << "Readonly mode." << std::endl;
    readonly=true;
  }

  if (vm.count("readall")) {
	  std::cout << "Read all benchmark enabled." << std::endl;
	  readall_enabled = true;
  }

  if (readers_enable) {
    std::cout << "Readers enable. count: " << dariadb_bench::total_readers_count
              << std::endl;
  }

  {
    std::cout << "write..." << std::endl;

    const size_t chunk_per_storage = 1024 * 100;
    const size_t chunk_size = 1024;
    const size_t cap_B = 50;
    const size_t max_mem_chunks = 100;

    // dont_clean = true;
    if (!dont_clean && dariadb::utils::fs::path_exists(storage_path)) {
        if(!readonly){
            std::cout<<" remove "<<storage_path<<std::endl;
            dariadb::utils::fs::rm(storage_path);
        }
    }

    dariadb::Time start_time = dariadb::timeutil::current_time();
    std::cout << " start time: " << dariadb::timeutil::to_string(start_time) << std::endl;
    dariadb::storage::PageManager::Params page_param(storage_path, chunk_per_storage,
                                                     chunk_size);
    dariadb::storage::CapacitorManager::Params cap_param(storage_path, cap_B);
    cap_param.max_levels = 11;

    dariadb::storage::AOFManager::Params aof_param(storage_path, 0);
    aof_param.buffer_size = 1000;
    aof_param.max_size = cap_param.measurements_count();

    cap_param.max_levels = 11;
    auto raw_ptr =
        new dariadb::storage::Engine(aof_param, page_param, cap_param,
                                     dariadb::storage::Engine::Limits(max_mem_chunks));

    dariadb::storage::MeasStorage_ptr ms{raw_ptr};

    dariadb::IdSet all_id_set;
    append_count = 0;
    stop_info = false;

    std::thread info_thread(show_info, raw_ptr);

    std::vector<std::thread> writers(dariadb_bench::total_threads_count);
    std::vector<std::thread> readers(dariadb_bench::total_readers_count);

    size_t pos = 0;
    for (size_t i = 1; i < dariadb_bench::total_threads_count + 1; i++) {
      auto id_from = dariadb_bench::get_id_from(pos);
      auto id_to = dariadb_bench::get_id_to(pos);
      for (size_t j = id_from; j < id_to; j++) {
        all_id_set.insert(j);
      }
      if(!readonly){
          std::thread t{dariadb_bench::thread_writer_rnd_stor, dariadb::Id(pos),
                      dariadb::Time(i), &append_count, raw_ptr};
          writers[pos] = std::move(t);
      }
	  pos++;
    }
    if (readers_enable) {
      pos = 0;
      for (size_t i = 1; i < dariadb_bench::total_readers_count + 1; i++) {
        std::thread t{reader, ms, all_id_set, dariadb::Time(0),
                      dariadb::timeutil::current_time()};
        readers[pos++] = std::move(t);
      }
    }

    if(!readonly){
        pos = 0;
        for (size_t i = 1; i < dariadb_bench::total_threads_count + 1; i++) {
            std::thread t = std::move(writers[pos++]);
            t.join();
        }
    }
    stop_readers = true;
    if (readers_enable) {
      pos = 0;
      for (size_t i = 1; i < dariadb_bench::total_readers_count + 1; i++) {
        std::thread t = std::move(readers[pos++]);
        t.join();
      }
    }

    stop_info = true;
    info_thread.join();
    std::cout << " total id:" << all_id_set.size() << std::endl;
    {
      std::cout << "full flush..." << std::endl;
      auto start = clock();
      raw_ptr->flush();
      auto elapsed = (((float)clock() - start) / CLOCKS_PER_SEC);
      std::cout << "flush time: " << elapsed << std::endl;
    }

    auto queue_sizes = raw_ptr->queue_size();
    std::cout << "\r"
              << " in queue: (p:" << queue_sizes.pages_count
              << " cap:" << queue_sizes.cola_count << " a:" << queue_sizes.aofs_count
              << ")"
              << " reads: " << reads_count
              << " writes: " << append_count
              << std::endl;

    dariadb_bench::readBenchark(all_id_set, ms.get(), 10, start_time,
                                dariadb::timeutil::current_time());
	if(readall_enabled){
      std::cout << "read all..." << std::endl;
      std::shared_ptr<BenchCallback> clbk{new BenchCallback()};
      auto max_time = ms->maxTime();
      std::cout << " end time: " << dariadb::timeutil::to_string(max_time) << std::endl;

      auto start = clock();

      dariadb::storage::QueryInterval qi{
          dariadb::IdArray(all_id_set.begin(), all_id_set.end()), 0, start_time,
          max_time};
      ms->readInterval(qi)->readAll(clbk.get());

      auto elapsed = (((float)clock() - start) / CLOCKS_PER_SEC);
      std::cout << "readed: " << clbk->count << std::endl;
      std::cout << "time: " << elapsed << std::endl;
      auto expected = (dariadb_bench::iteration_count *
                       dariadb_bench::total_threads_count * dariadb_bench::id_per_thread);

      if (!readonly && (!dont_clean && clbk->count != expected))  {
        std::cout << "expected: " << expected << " get:" << clbk->count << std::endl;
        throw MAKE_EXCEPTION("(clbk->count!=(iteration_count*total_threads_count))");
      } else {
        if (!readonly && (dont_clean && clbk->count < expected)) {
          std::cout << "expected: " << expected << " get:" << clbk->count << std::endl;
          throw MAKE_EXCEPTION("(clbk->count!=(iteration_count*total_threads_count))");
        }
      }
    }
    std::cout << "stoping storage...\n";
    ms = nullptr;
  }

  if(!(dont_clean || readonly) && (dariadb::utils::fs::path_exists(storage_path)) ){
    std::cout << "cleaning...\n";
    dariadb::utils::fs::rm(storage_path);
  }

  if (metrics_enable) {
	  std::cout << "metrics:\n" << dariadb::utils::MetricsManager::instance()->to_string() << std::endl;
  }
}
<|endoftext|>


<commit_before>#include "Hardware.h"

#include <unistd.h>
#include <stdlib.h>
#include <iostream>

#include "../../../Fido/include/Fido.h"
#include "../../Connection.h"

#define I_MIN_SAFE_ANG -65
#define I_MAX_SAFE_ANG 65

#define J_MIN_SAFE_ANG 35
#define J_MAX_SAFE_ANG 180

#define K_MIN_SAFE_ANG 0
#define K_MAX_SAFE_ANG 90

double randOutput() {
	return ((double) rand() / (RAND_MAX))*2.0 - 1.0;
}

bool executeScaledAngles(Hardware *hardware, double i, double j, double k) {
	double iAng = Hardware::map(i, -1, 1, I_MIN_SAFE_ANG, I_MAX_SAFE_ANG);
	double jAng = Hardware::map(j, -1, 1, J_MIN_SAFE_ANG, J_MAX_SAFE_ANG);
	double kAng = Hardware::map(k, -1, 1, K_MIN_SAFE_ANG, K_MAX_SAFE_ANG);

	return hardware->setJoints(iAng, jAng, kAng);
}

void stressTest(Hardware *hardware, int trials) {
	for (int i=0; i<trials; i++) {
		if (executeScaledAngles(hardware,randOutput(),randOutput(),randOutput())) {
			std::cout << "Move executed.\n";
		} else {
			std::cout << "Move fail-safed.\n";
		} usleep(3000000);
	}
}

void testSonars(Hardware *hardware, int trials) {
	for (int i=0; i<trials; i++) {
		int l, r; hardware->getSonars(&l, &r);
		std::cout << "Sonars: (" << l << ", " << r << ")\n";
		std::cout.flush();
	}
}

void proceduralPingPong() {
	Hardware hand;

	int THRESH = 50;
	int NUM_SONAR_READINGS = 1;

	hand.setJoints(0, 180, 45);

	while (true) {
		int l, r;
		hand.getSonars(&l, &r);

        std::cout << l << ", " << r << "\n";

		int delay = 0;
		double i = 0;
		if (abs(r-l) > THRESH) {
			if (r > l) {
				std::cout << "RIGHT\n";
				i = -30;
			} else {
				std::cout << "LEFT\n";
				i = 30;
			} delay = 500000;
		} else std::cout << "NOTHING\n";

		//hand.setJoints(i, 180, 40, true);
		//usleep(delay);
	}
}

void proceduralDrawing(Hardware *hand) {
	hand->setJoints(-6, 95, 50);
    usleep(500000);
	hand->setJoints(6, 95, 50);
	usleep(500000);
	hand->setJoints(6, 100, 30);
	usleep(500000);
	hand->setJoints(-6, 100, 30);
	usleep(500000);
	hand->setJoints(-6, 95, 50);
    usleep(500000);
	hand->poise();
}

int main() {
	srand(time(NULL));
    proceduralPingPong();
}
<commit_msg>Work on procedural ping pong<commit_after>#include "Hardware.h"

#include <unistd.h>
#include <stdlib.h>
#include <iostream>

#include "../../../Fido/include/Fido.h"
#include "../../Connection.h"

#define I_MIN_SAFE_ANG -65
#define I_MAX_SAFE_ANG 65

#define J_MIN_SAFE_ANG 35
#define J_MAX_SAFE_ANG 180

#define K_MIN_SAFE_ANG 0
#define K_MAX_SAFE_ANG 90

double randOutput() {
	return ((double) rand() / (RAND_MAX))*2.0 - 1.0;
}

bool executeScaledAngles(Hardware *hardware, double i, double j, double k) {
	double iAng = Hardware::map(i, -1, 1, I_MIN_SAFE_ANG, I_MAX_SAFE_ANG);
	double jAng = Hardware::map(j, -1, 1, J_MIN_SAFE_ANG, J_MAX_SAFE_ANG);
	double kAng = Hardware::map(k, -1, 1, K_MIN_SAFE_ANG, K_MAX_SAFE_ANG);

	return hardware->setJoints(iAng, jAng, kAng);
}

void stressTest(Hardware *hardware, int trials) {
	for (int i=0; i<trials; i++) {
		if (executeScaledAngles(hardware,randOutput(),randOutput(),randOutput())) {
			std::cout << "Move executed.\n";
		} else {
			std::cout << "Move fail-safed.\n";
		} usleep(3000000);
	}
}

void testSonars(Hardware *hardware, int trials) {
	for (int i=0; i<trials; i++) {
		int l, r; hardware->getSonars(&l, &r);
		std::cout << "Sonars: (" << l << ", " << r << ")\n";
		std::cout.flush();
	}
}

void proceduralPingPong() {
	Hardware hand;

	int THRESH = 300;
	int NUM_SONAR_READINGS = 1;

	hand.setJoints(0, 180, 45);

	while (true) {
		double l = 0, r = 0;
		const int NUM_READINGS = 3;
        for(int a = 0; a < NUM_READINGS; a++) {
            int tempL, tempR;
            hand.getSonars(&tempL, &tempR);
            l += tempL;
            r += tempR;
        }
        l /= double(NUM_READINGS);
        r /= double(NUM_READINGS);

        std::cout << l << ", " << r << "\n";

        int delay = 0;
		double i = 0;
		if (fabs(r-l) > THRESH) {
			if (r < l) {
				std::cout << "RIGHT\n";
				i = -30;
			} else {
				std::cout << "LEFT\n";
				i = 30;
			} delay = 500000;
		} else std::cout << "NOTHING\n";

		//hand.setJoints(i, 180, 40, true);
		//usleep(delay);
	}
}

void proceduralDrawing(Hardware *hand) {
	hand->setJoints(-6, 95, 50);
    usleep(500000);
	hand->setJoints(6, 95, 50);
	usleep(500000);
	hand->setJoints(6, 100, 30);
	usleep(500000);
	hand->setJoints(-6, 100, 30);
	usleep(500000);
	hand->setJoints(-6, 95, 50);
    usleep(500000);
	hand->poise();
}

int main() {
	srand(time(NULL));
    proceduralPingPong();
}
<|endoftext|>


<commit_before>// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <cassert>
#include <ostream>
// Boost
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/posix_time/ptime.hpp>
// Standard Airline Object Model
#include <stdair/STDAIR_Types.hpp>
#include <stdair/bom/AirlineFeature.hpp>
#include <stdair/bom/AirlineFeatureSet.hpp>
#include <stdair/factory/FacBomContent.hpp>
// Airline Inventory
#include <airinv/AIRINV_Service.hpp>
// Airline Schedule
#include <airsched/AIRSCHED_Service.hpp>
// Simcrs
#include <simcrs/basic/BasConst_SIMCRS_Service.hpp>
#include <simcrs/basic/BasChronometer.hpp>
#include <simcrs/command/DistributionManager.hpp>
#include <simcrs/factory/FacSimcrsServiceContext.hpp>
#include <simcrs/service/SIMCRS_ServiceContext.hpp>
#include <simcrs/service/Logger.hpp>
#include <simcrs/SIMCRS_Service.hpp>

namespace SIMCRS {

  // //////////////////////////////////////////////////////////////////////
  SIMCRS_Service::
  SIMCRS_Service (std::ostream& ioLogStream, const CRSCode_T& iCRSCode,
                  const stdair::Filename_T& iScheduleInputFilename)
    : _simcrsServiceContext (NULL) {
    init (ioLogStream, iCRSCode, iScheduleInputFilename);
  }

  // //////////////////////////////////////////////////////////////////////
  SIMCRS_Service::SIMCRS_Service () : _simcrsServiceContext (NULL) {
    assert (false);
  }

  // //////////////////////////////////////////////////////////////////////
  SIMCRS_Service::SIMCRS_Service (const SIMCRS_Service& iService) {
    assert (false);
  }

  // //////////////////////////////////////////////////////////////////////
  SIMCRS_Service::~SIMCRS_Service () {
    // Delete/Clean all the objects from memory
    finalise();
  }

  // //////////////////////////////////////////////////////////////////////
  void logInit (const LOG::EN_LogLevel iLogLevel,
                std::ostream& ioLogOutputFile) {
    Logger::instance().setLogParameters (iLogLevel, ioLogOutputFile);
  }

  // //////////////////////////////////////////////////////////////////////
  void SIMCRS_Service::init (std::ostream& ioLogStream,
                             const CRSCode_T& iCRSCode,
                             const stdair::Filename_T& iScheduleInputFilename) {
    // Set the log file
    logInit (LOG::DEBUG, ioLogStream);

    // Initialise the context
    SIMCRS_ServiceContext& lSIMCRS_ServiceContext =
      FacSimcrsServiceContext::instance().create (iCRSCode);
    _simcrsServiceContext = &lSIMCRS_ServiceContext;

    // /////////////// Airline Inventory Management (AirInv) /////////////
    // TODO: do not hardcode the airline code (e.g., take it from a
    // configuration file).
    // Initialise the AIRINV service handler
    const stdair::AirlineCode_T lAirlineCode = "BA";

    // Note that the (Boost.)Smart Pointer keeps track of the references
    // on the Service object, and deletes that object when it is no longer
    // referenced (e.g., at the end of the process).
    AIRINV_ServicePtr_T lAIRINV_Service =
      AIRINV_ServicePtr_T (new AIRINV::AIRINV_Service (ioLogStream,
                                                       lAirlineCode));

    // Store the AirInv service object within the (SimCRS) service context
    lSIMCRS_ServiceContext.setAIRINV_Service (lAIRINV_Service);

    // ////////////// Airline Schedule Management (AirSched) /////////////
    // TODO: do not hardcode the initialisation phase of the schedule
    // Initialise the schedule
    stdair::AirlineFeatureSet& lAirlineFeatureSet =
      stdair::FacBomContent::instance().create<stdair::AirlineFeatureSet>();

    // TODO: do not harcode the airline code for the AirlineFeature object
    stdair::AirlineFeatureKey_T lAirlineFeatureKey (lAirlineCode);
    stdair::AirlineFeature& lAirlineFeature = stdair::FacBomContent::instance().
      create<stdair::AirlineFeature> (lAirlineFeatureSet, lAirlineFeatureKey);

    // TODO: do not hardcode the start analysis date
    const stdair::Date_T lStartAnalysisDate (2000, 1, 1);

    // Initialise the AIRSCHED service handler
    AIRSCHED_ServicePtr_T lAIRSCHED_Service =
      AIRSCHED_ServicePtr_T (new AIRSCHED::
                             AIRSCHED_Service (ioLogStream, lAirlineFeatureSet,
                                               lStartAnalysisDate,
                                               iScheduleInputFilename));

    // Store the AirSched service object within the (SimCRS) service context
    lSIMCRS_ServiceContext.setAIRSCHED_Service (lAIRSCHED_Service);
  }

  // //////////////////////////////////////////////////////////////////////
  void SIMCRS_Service::finalise () {
    assert (_simcrsServiceContext != NULL);
  }

  // //////////////////////////////////////////////////////////////////////
  void SIMCRS_Service::sell (const stdair::AirlineCode_T& iAirlineCode,
                             const stdair::PartySize_T& iPartySize) {

    if (_simcrsServiceContext == NULL) {
      throw NonInitialisedServiceException();
    }
    assert (_simcrsServiceContext != NULL);
    SIMCRS_ServiceContext& lSIMCRS_ServiceContext= *_simcrsServiceContext;

    try {

      // Get a reference on the AIRINV service handler
      AIRINV::AIRINV_Service& lAIRINV_Service =
        lSIMCRS_ServiceContext.getAIRINV_Service();

      // Retrieve the airline code
      const CRSCode_T& lCRSCode =
        lSIMCRS_ServiceContext.getCRSCode();

      // Delegate the booking to the dedicated command
      BasChronometer lSellChronometer;
      lSellChronometer.start();
      DistributionManager::sell (lAIRINV_Service,
                                 lCRSCode, iAirlineCode, iPartySize);
      const double lSellMeasure = lSellChronometer.elapsed();

      // DEBUG
      SIMCRS_LOG_DEBUG ("Booking sell: " << lSellMeasure << " - "
                        << lSIMCRS_ServiceContext.display());

    } catch (const std::exception& error) {
      SIMCRS_LOG_ERROR ("Exception: "  << error.what());
      throw BookingException();
    }
  }

}
<commit_msg>Seperate the linkage phase from the initialisation phase of the content child.<commit_after>// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <cassert>
#include <ostream>
// Boost
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/posix_time/ptime.hpp>
// Standard Airline Object Model
#include <stdair/STDAIR_Types.hpp>
#include <stdair/bom/AirlineFeature.hpp>
#include <stdair/bom/AirlineFeatureSet.hpp>
#include <stdair/factory/FacBomContent.hpp>
// Airline Inventory
#include <airinv/AIRINV_Service.hpp>
// Airline Schedule
#include <airsched/AIRSCHED_Service.hpp>
// Simcrs
#include <simcrs/basic/BasConst_SIMCRS_Service.hpp>
#include <simcrs/basic/BasChronometer.hpp>
#include <simcrs/command/DistributionManager.hpp>
#include <simcrs/factory/FacSimcrsServiceContext.hpp>
#include <simcrs/service/SIMCRS_ServiceContext.hpp>
#include <simcrs/service/Logger.hpp>
#include <simcrs/SIMCRS_Service.hpp>

namespace SIMCRS {

  // //////////////////////////////////////////////////////////////////////
  SIMCRS_Service::
  SIMCRS_Service (std::ostream& ioLogStream, const CRSCode_T& iCRSCode,
                  const stdair::Filename_T& iScheduleInputFilename)
    : _simcrsServiceContext (NULL) {
    init (ioLogStream, iCRSCode, iScheduleInputFilename);
  }

  // //////////////////////////////////////////////////////////////////////
  SIMCRS_Service::SIMCRS_Service () : _simcrsServiceContext (NULL) {
    assert (false);
  }

  // //////////////////////////////////////////////////////////////////////
  SIMCRS_Service::SIMCRS_Service (const SIMCRS_Service& iService) {
    assert (false);
  }

  // //////////////////////////////////////////////////////////////////////
  SIMCRS_Service::~SIMCRS_Service () {
    // Delete/Clean all the objects from memory
    finalise();
  }

  // //////////////////////////////////////////////////////////////////////
  void logInit (const LOG::EN_LogLevel iLogLevel,
                std::ostream& ioLogOutputFile) {
    Logger::instance().setLogParameters (iLogLevel, ioLogOutputFile);
  }

  // //////////////////////////////////////////////////////////////////////
  void SIMCRS_Service::init (std::ostream& ioLogStream,
                             const CRSCode_T& iCRSCode,
                             const stdair::Filename_T& iScheduleInputFilename) {
    // Set the log file
    logInit (LOG::DEBUG, ioLogStream);

    // Initialise the context
    SIMCRS_ServiceContext& lSIMCRS_ServiceContext =
      FacSimcrsServiceContext::instance().create (iCRSCode);
    _simcrsServiceContext = &lSIMCRS_ServiceContext;

    // /////////////// Airline Inventory Management (AirInv) /////////////
    // TODO: do not hardcode the airline code (e.g., take it from a
    // configuration file).
    // Initialise the AIRINV service handler
    const stdair::AirlineCode_T lAirlineCode = "BA";

    // Note that the (Boost.)Smart Pointer keeps track of the references
    // on the Service object, and deletes that object when it is no longer
    // referenced (e.g., at the end of the process).
    AIRINV_ServicePtr_T lAIRINV_Service =
      AIRINV_ServicePtr_T (new AIRINV::AIRINV_Service (ioLogStream,
                                                       lAirlineCode));

    // Store the AirInv service object within the (SimCRS) service context
    lSIMCRS_ServiceContext.setAIRINV_Service (lAIRINV_Service);

    // ////////////// Airline Schedule Management (AirSched) /////////////
    // TODO: do not hardcode the initialisation phase of the schedule
    // Initialise the schedule
    stdair::AirlineFeatureSet& lAirlineFeatureSet =
      stdair::FacBomContent::instance().create<stdair::AirlineFeatureSet>();

    // TODO: do not harcode the airline code for the AirlineFeature object
    stdair::AirlineFeatureKey_T lAirlineFeatureKey (lAirlineCode);
    stdair::AirlineFeature& lAirlineFeature = stdair::FacBomContent::
      instance().create<stdair::AirlineFeature> (lAirlineFeatureKey);
    stdair::FacBomContent::
      linkWithParent<stdair::AirlineFeature> (lAirlineFeature,
                                              lAirlineFeatureSet);

    // TODO: do not hardcode the start analysis date
    const stdair::Date_T lStartAnalysisDate (2000, 1, 1);

    // Initialise the AIRSCHED service handler
    AIRSCHED_ServicePtr_T lAIRSCHED_Service =
      AIRSCHED_ServicePtr_T (new AIRSCHED::
                             AIRSCHED_Service (ioLogStream, lAirlineFeatureSet,
                                               lStartAnalysisDate,
                                               iScheduleInputFilename));

    // Store the AirSched service object within the (SimCRS) service context
    lSIMCRS_ServiceContext.setAIRSCHED_Service (lAIRSCHED_Service);
  }

  // //////////////////////////////////////////////////////////////////////
  void SIMCRS_Service::finalise () {
    assert (_simcrsServiceContext != NULL);
  }

  // //////////////////////////////////////////////////////////////////////
  void SIMCRS_Service::sell (const stdair::AirlineCode_T& iAirlineCode,
                             const stdair::PartySize_T& iPartySize) {

    if (_simcrsServiceContext == NULL) {
      throw NonInitialisedServiceException();
    }
    assert (_simcrsServiceContext != NULL);
    SIMCRS_ServiceContext& lSIMCRS_ServiceContext= *_simcrsServiceContext;

    try {

      // Get a reference on the AIRINV service handler
      AIRINV::AIRINV_Service& lAIRINV_Service =
        lSIMCRS_ServiceContext.getAIRINV_Service();

      // Retrieve the airline code
      const CRSCode_T& lCRSCode =
        lSIMCRS_ServiceContext.getCRSCode();

      // Delegate the booking to the dedicated command
      BasChronometer lSellChronometer;
      lSellChronometer.start();
      DistributionManager::sell (lAIRINV_Service,
                                 lCRSCode, iAirlineCode, iPartySize);
      const double lSellMeasure = lSellChronometer.elapsed();

      // DEBUG
      SIMCRS_LOG_DEBUG ("Booking sell: " << lSellMeasure << " - "
                        << lSIMCRS_ServiceContext.display());

    } catch (const std::exception& error) {
      SIMCRS_LOG_ERROR ("Exception: "  << error.what());
      throw BookingException();
    }
  }

}
<|endoftext|>


<commit_before>/*
   Source File : InputFlateDecodeStream.cpp

   Copyright 2011 Gal Kahana PDFWriter

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

*/
#include "InputFlateDecodeStream.h"

#include "Trace.h"
#include "zlib.h"

InputFlateDecodeStream::InputFlateDecodeStream(void)
{
	mZLibState = new z_stream;
	mSourceStream = NULL;
	mCurrentlyEncoding = false;
	mEndOfCompressionEoncountered = false;
}

InputFlateDecodeStream::~InputFlateDecodeStream(void)
{
	if(mCurrentlyEncoding)
		FinalizeEncoding();
	if(mSourceStream)
		delete mSourceStream;
	delete mZLibState;
}

void InputFlateDecodeStream::FinalizeEncoding()
{
	// no need for flushing here, there's no notion of Z_FINISH. so just end the library work
	inflateEnd(mZLibState);
	mCurrentlyEncoding = false;
}

InputFlateDecodeStream::InputFlateDecodeStream(IByteReader* inSourceReader)
{
	mZLibState = new z_stream;
	mSourceStream = NULL;
	mCurrentlyEncoding = false;

	Assign(inSourceReader);
}

void InputFlateDecodeStream::Assign(IByteReader* inSourceReader)
{
	mSourceStream = inSourceReader;
	if(mSourceStream)
		StartEncoding();
}

void InputFlateDecodeStream::StartEncoding()
{
	mZLibState->zalloc = Z_NULL;
    mZLibState->zfree = Z_NULL;
    mZLibState->opaque = Z_NULL;
	mZLibState->avail_in = 0;
	mZLibState->next_in = Z_NULL;
	mEndOfCompressionEoncountered = false;

    int inflateStatus = inflateInit(mZLibState);
    if (inflateStatus != Z_OK)
		TRACE_LOG1("InputFlateDecodeStream::StartEncoding, Unexpected failure in initializating flate library. status code = %d",inflateStatus);
	else
		mCurrentlyEncoding = true;
}

static bool isError(int inflateResult)
{
	return (Z_STREAM_ERROR == inflateResult ||
		Z_NEED_DICT == inflateResult ||
		Z_DATA_ERROR == inflateResult ||
		Z_MEM_ERROR == inflateResult);
}

IOBasicTypes::LongBufferSizeType InputFlateDecodeStream::Read(IOBasicTypes::Byte* inBuffer,IOBasicTypes::LongBufferSizeType inBufferSize)
{
	if(mCurrentlyEncoding)
		return DecodeBufferAndRead(inBuffer,inBufferSize);
	else if(mSourceStream)
		return mSourceStream->Read(inBuffer,inBufferSize);
	else
		return 0;
}

IOBasicTypes::LongBufferSizeType InputFlateDecodeStream::DecodeBufferAndRead(const IOBasicTypes::Byte* inBuffer,IOBasicTypes::LongBufferSizeType inSize)
{
	if(0 == inSize)
		return 0; // inflate kinda touchy about getting 0 lengths

	int inflateResult = Z_OK;

	do
	{
		mZLibState->avail_out = (uInt)inSize;
		mZLibState->next_out = (Bytef*)inBuffer;

		// first, flush whatever is already available
		while(mZLibState->avail_in != 0 && mZLibState->avail_out != 0)
		{
			inflateResult = inflate(mZLibState,Z_NO_FLUSH);
			if(isError(inflateResult))
			{
				TRACE_LOG1("InputFlateDecodeStream::DecodeBufferAndRead, failed to read zlib information. returned error code = %d",inflateResult);
				inflateEnd(mZLibState);
				break;
			}
		}
		if(Z_OK != inflateResult && Z_STREAM_END != inflateResult)
			break;

		// if not finished read buffer, repeatedly read from input stream, and inflate till done
		while((0 < mZLibState->avail_out) && mSourceStream->NotEnded())
		{
			if(mSourceStream->Read(&mBuffer,1) != 1)
			{
				TRACE_LOG("InputFlateDecodeStream::DecodeBufferAndRead, failed to read from source stream");
				inflateEnd(mZLibState);
				inflateResult = Z_STREAM_ERROR;
				mCurrentlyEncoding = false;
				break;
			}

			mZLibState->avail_in = 1;
			mZLibState->next_in = (Bytef*)&mBuffer;

			while(mZLibState->avail_in != 0 && mZLibState->avail_out != 0 && inflateResult != Z_STREAM_END)
			{
				inflateResult = inflate(mZLibState,Z_NO_FLUSH);
				if(isError(inflateResult))
				{
					TRACE_LOG1("InputFlateDecodeStream::DecodeBufferAndRead, failed to read zlib information. returned error code = %d",inflateResult);
					inflateEnd(mZLibState);
					break;
				}
			}
			if(Z_OK != inflateResult && Z_STREAM_END != inflateResult)
				break;
		}
	} while(false);

	// should be that at the last buffer we'll get here a nice Z_STREAM_END
	mEndOfCompressionEoncountered = (Z_STREAM_END == inflateResult) || isError(inflateResult);
	if(Z_OK == inflateResult || Z_STREAM_END == inflateResult)
		return inSize - mZLibState->avail_out;
	else
		return 0;
}

bool InputFlateDecodeStream::NotEnded()
{
	if(mSourceStream)
		return (mSourceStream->NotEnded() || mZLibState->avail_in != 0) && !mEndOfCompressionEoncountered;
	else
		return mZLibState->avail_in != 0 && mEndOfCompressionEoncountered;
}<commit_msg>to switch<commit_after>/*
   Source File : InputFlateDecodeStream.cpp

   Copyright 2011 Gal Kahana PDFWriter

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

*/
#include "InputFlateDecodeStream.h"

#include "Trace.h"
#include "zlib.h"

InputFlateDecodeStream::InputFlateDecodeStream(void)
{
	mZLibState = new z_stream;
	mSourceStream = NULL;
	mCurrentlyEncoding = false;
	mEndOfCompressionEoncountered = false;
}

InputFlateDecodeStream::~InputFlateDecodeStream(void)
{
	if(mCurrentlyEncoding)
		FinalizeEncoding();
	if(mSourceStream)
		delete mSourceStream;
	delete mZLibState;
}

void InputFlateDecodeStream::FinalizeEncoding()
{
	// no need for flushing here, there's no notion of Z_FINISH. so just end the library work
	inflateEnd(mZLibState);
	mCurrentlyEncoding = false;
}

InputFlateDecodeStream::InputFlateDecodeStream(IByteReader* inSourceReader)
{
	mZLibState = new z_stream;
	mSourceStream = NULL;
	mCurrentlyEncoding = false;

	Assign(inSourceReader);
}

void InputFlateDecodeStream::Assign(IByteReader* inSourceReader)
{
	mSourceStream = inSourceReader;
	if(mSourceStream)
		StartEncoding();
}

void InputFlateDecodeStream::StartEncoding()
{
	mZLibState->zalloc = Z_NULL;
    mZLibState->zfree = Z_NULL;
    mZLibState->opaque = Z_NULL;
	mZLibState->avail_in = 0;
	mZLibState->next_in = Z_NULL;
	mEndOfCompressionEoncountered = false;

    int inflateStatus = inflateInit(mZLibState);
    if (inflateStatus != Z_OK)
		TRACE_LOG1("InputFlateDecodeStream::StartEncoding, Unexpected failure in initializating flate library. status code = %d",inflateStatus);
	else
		mCurrentlyEncoding = true;
}

static bool isError(int inflateResult)
{
	switch(inflateResult) {
		case Z_STREAM_ERROR:
		case Z_NEED_DICT:
		case Z_DATA_ERROR:
		case Z_MEM_ERROR:
			return true;
		default:
			return false;
	}
}

IOBasicTypes::LongBufferSizeType InputFlateDecodeStream::Read(IOBasicTypes::Byte* inBuffer,IOBasicTypes::LongBufferSizeType inBufferSize)
{
	if(mCurrentlyEncoding)
		return DecodeBufferAndRead(inBuffer,inBufferSize);
	else if(mSourceStream)
		return mSourceStream->Read(inBuffer,inBufferSize);
	else
		return 0;
}

IOBasicTypes::LongBufferSizeType InputFlateDecodeStream::DecodeBufferAndRead(const IOBasicTypes::Byte* inBuffer,IOBasicTypes::LongBufferSizeType inSize)
{
	if(0 == inSize)
		return 0; // inflate kinda touchy about getting 0 lengths

	int inflateResult = Z_OK;

	do
	{
		mZLibState->avail_out = (uInt)inSize;
		mZLibState->next_out = (Bytef*)inBuffer;

		// first, flush whatever is already available
		while(mZLibState->avail_in != 0 && mZLibState->avail_out != 0)
		{
			inflateResult = inflate(mZLibState,Z_NO_FLUSH);
			if(isError(inflateResult))
			{
				TRACE_LOG1("InputFlateDecodeStream::DecodeBufferAndRead, failed to read zlib information. returned error code = %d",inflateResult);
				inflateEnd(mZLibState);
				break;
			}
		}
		if(Z_OK != inflateResult && Z_STREAM_END != inflateResult)
			break;

		// if not finished read buffer, repeatedly read from input stream, and inflate till done
		while((0 < mZLibState->avail_out) && mSourceStream->NotEnded())
		{
			if(mSourceStream->Read(&mBuffer,1) != 1)
			{
				TRACE_LOG("InputFlateDecodeStream::DecodeBufferAndRead, failed to read from source stream");
				inflateEnd(mZLibState);
				inflateResult = Z_STREAM_ERROR;
				mCurrentlyEncoding = false;
				break;
			}

			mZLibState->avail_in = 1;
			mZLibState->next_in = (Bytef*)&mBuffer;

			while(mZLibState->avail_in != 0 && mZLibState->avail_out != 0 && inflateResult != Z_STREAM_END)
			{
				inflateResult = inflate(mZLibState,Z_NO_FLUSH);
				if(isError(inflateResult))
				{
					TRACE_LOG1("InputFlateDecodeStream::DecodeBufferAndRead, failed to read zlib information. returned error code = %d",inflateResult);
					inflateEnd(mZLibState);
					break;
				}
			}
			if(Z_OK != inflateResult && Z_STREAM_END != inflateResult)
				break;
		}
	} while(false);

	// should be that at the last buffer we'll get here a nice Z_STREAM_END
	mEndOfCompressionEoncountered = (Z_STREAM_END == inflateResult) || isError(inflateResult);
	if(Z_OK == inflateResult || Z_STREAM_END == inflateResult)
		return inSize - mZLibState->avail_out;
	else
		return 0;
}

bool InputFlateDecodeStream::NotEnded()
{
	if(mSourceStream)
		return (mSourceStream->NotEnded() || mZLibState->avail_in != 0) && !mEndOfCompressionEoncountered;
	else
		return mZLibState->avail_in != 0 && mEndOfCompressionEoncountered;
}<|endoftext|>


<commit_before>AliAnalysisTaskStrange *AddTaskStrange(Short_t lCollidingSystems=0,  /*0 = pp, 1 = AA*/,
				       TString lAnalysisCut="no" )
{
// Creates, configures and attaches to the train a strangeness task.
   // Get the pointer to the existing analysis manager via the static access method.
   //==============================================================================
   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
   if (!mgr) {
      ::Error("AddTaskStrange", "No analysis manager to connect to.");
      return NULL;
   }

   // Check the analysis type using the event handlers connected to the analysis manager.
   //==============================================================================
   if (!mgr->GetInputEventHandler()) {
      ::Error("AddTaskStrange", "This task requires an input event handler");
      return NULL;
   }
   TString type = mgr->GetInputEventHandler()->GetDataType(); // can be "ESD" or "AOD"

   // Create and configure the task
	AliAnalysisTaskStrange *taskstrange = new AliAnalysisTaskStrange("TaskStrange");
   taskstrange->SetCollidingSystems(lCollidingSystems);
   taskstrange->SetAnalysisType(type);
   taskstrange->SetAnalysisCut(lAnalysisCut);
   mgr->AddTask(taskstrange);

   // Create ONLY the output containers for the data produced by the task.
   // Get and connect other common input/output containers via the manager as below
   //==============================================================================
   TString outname = "PP";
   if (lCollidingSystems) outname = "AA";
   if (mgr->GetMCtruthEventHandler()) outname += "-MC-";
   outname += "StrangeList.root";
	AliAnalysisDataContainer *coutput1 = mgr->CreateContainer("clistStrange",
								   TList::Class(),
								   AliAnalysisManager::kOutputContainer,
								   outname );

   mgr->ConnectInput(taskstrange, 0, mgr->GetCommonInputContainer());
   mgr->ConnectOutput(taskstrange, 1, coutput1);
   return taskstrange;
}
<commit_msg>Fix trivial syntax error<commit_after>AliAnalysisTaskStrange *AddTaskStrange(Short_t lCollidingSystems=0,  /*0 = pp, 1 = AA*/
				       TString lAnalysisCut="no" )
{
// Creates, configures and attaches to the train a strangeness task.
   // Get the pointer to the existing analysis manager via the static access method.
   //==============================================================================
   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
   if (!mgr) {
      ::Error("AddTaskStrange", "No analysis manager to connect to.");
      return NULL;
   }

   // Check the analysis type using the event handlers connected to the analysis manager.
   //==============================================================================
   if (!mgr->GetInputEventHandler()) {
      ::Error("AddTaskStrange", "This task requires an input event handler");
      return NULL;
   }
   TString type = mgr->GetInputEventHandler()->GetDataType(); // can be "ESD" or "AOD"

   // Create and configure the task
	AliAnalysisTaskStrange *taskstrange = new AliAnalysisTaskStrange("TaskStrange");
   taskstrange->SetCollidingSystems(lCollidingSystems);
   taskstrange->SetAnalysisType(type);
   taskstrange->SetAnalysisCut(lAnalysisCut);
   mgr->AddTask(taskstrange);

   // Create ONLY the output containers for the data produced by the task.
   // Get and connect other common input/output containers via the manager as below
   //==============================================================================
   TString outname = "PP";
   if (lCollidingSystems) outname = "AA";
   if (mgr->GetMCtruthEventHandler()) outname += "-MC-";
   outname += "StrangeList.root";
	AliAnalysisDataContainer *coutput1 = mgr->CreateContainer("clistStrange",
								   TList::Class(),
								   AliAnalysisManager::kOutputContainer,
								   outname );

   mgr->ConnectInput(taskstrange, 0, mgr->GetCommonInputContainer());
   mgr->ConnectOutput(taskstrange, 1, coutput1);
   return taskstrange;
}
<|endoftext|>


<commit_before>/*
 *  Copyright (C) 2012 Austin Robot Technology
 *  License: Modified BSD Software License Agreement
 *
 *  $Id$
 */

/** @file

    Implementation for converting a Velodyne 3D LIDAR PointXYZIR cloud
    to PointXYZRGB, assigning colors for visualization of the laser
    rings.

    @author Jack O'Quin
*/

#include "colors.h"
#include <velodyne_pointcloud/point_types.h>

/// @todo make sure these includes are really necessary
#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>

namespace
{
  // RGB color values
  const int color_red =       0xff0000;
  const int color_orange =    0xff8800;
  const int color_yellow =    0xffff00;
  const int color_green =     0x00ff00;
  const int color_blue =      0x0000ff;
  const int color_violet =    0xff00ff;

  const int N_COLORS = 6;
  int rainbow[N_COLORS] = {color_red, color_orange, color_yellow,
                           color_green, color_blue, color_violet};
}

namespace velodyne_pointcloud
{

  /** types of output point and cloud */
  typedef pcl::PointXYZRGB RGBPoint;
  typedef pcl::PointCloud<RGBPoint> RGBPointCloud;

  /** @brief Constructor. */
  RingColors::RingColors(ros::NodeHandle node, ros::NodeHandle private_nh)
  {
    // advertise output point cloud (before subscribing to input data)
    output_ =
      node.advertise<sensor_msgs::PointCloud2>("velodyne_rings", 10);

    // subscribe to VelodyneScan packets
    input_ =
      node.subscribe("velodyne_points", 10,
                     &RingColors::convertPoints, this,
                     ros::TransportHints().tcpNoDelay(true));
  }

  /** @brief Callback for Velodyne PointXYZRI messages. */
  void
    RingColors::convertPoints(const VPointCloud::ConstPtr &inMsg)
  {
    if (output_.getNumSubscribers() == 0)         // no one listening?
      return;                                     // do nothing

    // allocate an PointXYZRGB message with same time and frame ID as
    // input data
    RGBPointCloud::Ptr outMsg(new RGBPointCloud());
    outMsg->header.stamp = inMsg->header.stamp;
    outMsg->header.frame_id = inMsg->header.frame_id;
    outMsg->height = 1;

    for (size_t i = 0; i < inMsg->points.size(); ++i)
      {
        RGBPoint p;
        p.x = inMsg->points[i].x;
        p.y = inMsg->points[i].y;
        p.z = inMsg->points[i].z;

        // color lasers with the rainbow array
        int color = inMsg->points[i].ring % N_COLORS;
        p.rgb = *reinterpret_cast<float*>(&rainbow[color]);

        outMsg->points.push_back(p);
        ++outMsg->width;
      }

    output_.publish(outMsg);
  }

} // namespace velodyne_pcl
<commit_msg>Modified  velodyne_pointcloud/src/conversion/colors.cc to remove address build warning for strict-aliasing.<commit_after>/*
 *  Copyright (C) 2012 Austin Robot Technology
 *  License: Modified BSD Software License Agreement
 *
 *  $Id$
 */

/** @file

    Implementation for converting a Velodyne 3D LIDAR PointXYZIR cloud
    to PointXYZRGB, assigning colors for visualization of the laser
    rings.

    @author Jack O'Quin
*/

#include "colors.h"
#include <velodyne_pointcloud/point_types.h>

/// @todo make sure these includes are really necessary
#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>

namespace
{
  // RGB color values
  const int color_red =       0xff0000;
  const int color_orange =    0xff8800;
  const int color_yellow =    0xffff00;
  const int color_green =     0x00ff00;
  const int color_blue =      0x0000ff;
  const int color_violet =    0xff00ff;

  const int N_COLORS = 6;
  int rainbow[N_COLORS] = {color_red, color_orange, color_yellow,
                           color_green, color_blue, color_violet};
}

namespace velodyne_pointcloud
{

  /** types of output point and cloud */
  typedef pcl::PointXYZRGB RGBPoint;
  typedef pcl::PointCloud<RGBPoint> RGBPointCloud;

  /** @brief Constructor. */
  RingColors::RingColors(ros::NodeHandle node, ros::NodeHandle private_nh)
  {
    // advertise output point cloud (before subscribing to input data)
    output_ =
      node.advertise<sensor_msgs::PointCloud2>("velodyne_rings", 10);

    // subscribe to VelodyneScan packets
    input_ =
      node.subscribe("velodyne_points", 10,
                     &RingColors::convertPoints, this,
                     ros::TransportHints().tcpNoDelay(true));
  }

  /** @brief Callback for Velodyne PointXYZRI messages. */
  void
    RingColors::convertPoints(const VPointCloud::ConstPtr &inMsg)
  {
    if (output_.getNumSubscribers() == 0)         // no one listening?
      return;                                     // do nothing

    // allocate an PointXYZRGB message with same time and frame ID as
    // input data
    RGBPointCloud::Ptr outMsg(new RGBPointCloud());
    outMsg->header.stamp = inMsg->header.stamp;
    outMsg->header.frame_id = inMsg->header.frame_id;
    outMsg->height = 1;

    for (size_t i = 0; i < inMsg->points.size(); ++i)
      {
        RGBPoint p;
        p.x = inMsg->points[i].x;
        p.y = inMsg->points[i].y;
        p.z = inMsg->points[i].z;

        // color lasers with the rainbow array
        int color = inMsg->points[i].ring % N_COLORS;
        p.rgb = *reinterpret_cast<float*>(rainbow+color);

        outMsg->points.push_back(p);
        ++outMsg->width;
      }

    output_.publish(outMsg);
  }

} // namespace velodyne_pcl
<|endoftext|>


<commit_before>#include "Genes/King_Confinement_Gene.h"

#include <cmath>
#include <array>
#include <map>

#include "Genes/Gene.h"
#include "Game/Board.h"
#include "Game/Color.h"
#include "Game/Square.h"
#include "Game/Piece.h"

#include "Utility/Random.h"
#include "Utility/Math.h"

King_Confinement_Gene::King_Confinement_Gene() noexcept
{
    Math::normalize(friendly_block_score, opponent_block_score);
}

std::string King_Confinement_Gene::name() const noexcept
{
    return "King Confinement Gene";
}

void King_Confinement_Gene::load_gene_properties(const std::map<std::string, double>& properties)
{
    friendly_block_score = properties.at("Friendly Block Score");
    opponent_block_score = properties.at("Opponent Block Score");
    Math::normalize(friendly_block_score, opponent_block_score);
}

void King_Confinement_Gene::adjust_properties(std::map<std::string, double>& properties) const noexcept
{
    properties["Friendly Block Score"] = friendly_block_score;
    properties["Opponent Block Score"] = opponent_block_score;
}

void King_Confinement_Gene::gene_specific_mutation() noexcept
{
    auto mutation_size = Random::random_laplace(0.03);
    if(Random::coin_flip())
    {
        friendly_block_score += mutation_size;
    }
    else
    {
        opponent_block_score += mutation_size;
    }

    Math::normalize(friendly_block_score, opponent_block_score);
}

double King_Confinement_Gene::score_board(const Board& board, Piece_Color perspective, size_t) const noexcept
{
    std::array<Square, 64> square_queue{};
    size_t queue_insertion_point = 0;
    std::array<bool, 64> in_queue{};

    const auto king_square = board.find_king(perspective);

    square_queue[queue_insertion_point++] = king_square;
    in_queue[king_square.index()] = true;

    double friendly_block_total = 0.0;
    double opponent_block_total = 0.0;
    int free_space_total = 0;

    for(auto square : square_queue)
    {
        if( ! square.is_set())
        {
            break;
        }

        // Always check the squares surrounding the king's current positions, even if
        // it is not safe (i.e., the king is in check).
        auto add_surrounding_squares = square == king_square;

        auto piece = board.piece_on_square(square);

        if(piece && piece.color() == perspective && piece.type() != Piece_Type::KING) // Square is blocked by a friendly piece
        {
            friendly_block_total += friendly_block_score;
        }
        else if( ! board.safe_for_king(square, perspective)) // Square is attacked by an opposing piece
        {
            opponent_block_total += opponent_block_score;
        }
        else
        {
            ++free_space_total;
            add_surrounding_squares = true;
        }

        // Add surrounding squares to square_queue.
        if(add_surrounding_squares)
        {
            for(auto file_step = -1; file_step <= 1; ++file_step)
            {
                for(auto rank_step = -1; rank_step <= 1; ++rank_step)
                {
                    auto new_square = square + Square_Difference{file_step, rank_step};
                    if(new_square.inside_board() && ! in_queue[new_square.index()])
                    {
                        square_queue[queue_insertion_point++] = new_square;
                        in_queue[new_square.index()] = true;
                    }
                }
            }
        }
    }

    return (friendly_block_total + opponent_block_total)/(1 + free_space_total);
}
<commit_msg>Reduce numeric conversions<commit_after>#include "Genes/King_Confinement_Gene.h"

#include <cmath>
#include <array>
#include <map>

#include "Genes/Gene.h"
#include "Game/Board.h"
#include "Game/Color.h"
#include "Game/Square.h"
#include "Game/Piece.h"

#include "Utility/Random.h"
#include "Utility/Math.h"

King_Confinement_Gene::King_Confinement_Gene() noexcept
{
    Math::normalize(friendly_block_score, opponent_block_score);
}

std::string King_Confinement_Gene::name() const noexcept
{
    return "King Confinement Gene";
}

void King_Confinement_Gene::load_gene_properties(const std::map<std::string, double>& properties)
{
    friendly_block_score = properties.at("Friendly Block Score");
    opponent_block_score = properties.at("Opponent Block Score");
    Math::normalize(friendly_block_score, opponent_block_score);
}

void King_Confinement_Gene::adjust_properties(std::map<std::string, double>& properties) const noexcept
{
    properties["Friendly Block Score"] = friendly_block_score;
    properties["Opponent Block Score"] = opponent_block_score;
}

void King_Confinement_Gene::gene_specific_mutation() noexcept
{
    auto mutation_size = Random::random_laplace(0.03);
    if(Random::coin_flip())
    {
        friendly_block_score += mutation_size;
    }
    else
    {
        opponent_block_score += mutation_size;
    }

    Math::normalize(friendly_block_score, opponent_block_score);
}

double King_Confinement_Gene::score_board(const Board& board, Piece_Color perspective, size_t) const noexcept
{
    std::array<Square, 64> square_queue{};
    size_t queue_insertion_point = 0;
    std::array<bool, 64> in_queue{};

    const auto king_square = board.find_king(perspective);

    square_queue[queue_insertion_point++] = king_square;
    in_queue[king_square.index()] = true;

    double friendly_block_total = 0.0;
    double opponent_block_total = 0.0;
    double free_space_total = 0.0;

    for(auto square : square_queue)
    {
        if( ! square.is_set())
        {
            break;
        }

        // Always check the squares surrounding the king's current positions, even if
        // it is not safe (i.e., the king is in check).
        auto add_surrounding_squares = square == king_square;

        auto piece = board.piece_on_square(square);

        if(piece && piece.color() == perspective && piece.type() != Piece_Type::KING) // Square is blocked by a friendly piece
        {
            friendly_block_total += friendly_block_score;
        }
        else if( ! board.safe_for_king(square, perspective)) // Square is attacked by an opposing piece
        {
            opponent_block_total += opponent_block_score;
        }
        else
        {
            free_space_total += 1.0;
            add_surrounding_squares = true;
        }

        // Add surrounding squares to square_queue.
        if(add_surrounding_squares)
        {
            for(auto file_step = -1; file_step <= 1; ++file_step)
            {
                for(auto rank_step = -1; rank_step <= 1; ++rank_step)
                {
                    auto new_square = square + Square_Difference{file_step, rank_step};
                    if(new_square.inside_board() && ! in_queue[new_square.index()])
                    {
                        square_queue[queue_insertion_point++] = new_square;
                        in_queue[new_square.index()] = true;
                    }
                }
            }
        }
    }

    return (friendly_block_total + opponent_block_total)/(1.0 + free_space_total);
}
<|endoftext|>


<commit_before>#include "Genes/King_Confinement_Gene.h"

#include <cmath>

#include "Game/Board.h"
#include "Game/Color.h"
#include "Pieces/Piece.h"

King_Confinement_Gene::King_Confinement_Gene() : maximum_score(0.0)
{
    // Maximum score comes from a king in the middle of an empty board
    auto king_file = 'e';
    auto king_rank = 4;

    for(auto file = 'a'; file <= 'h'; ++file)
    {
        for(auto rank = 1; rank <= 8; ++rank)
        {
            auto distance = std::max(std::abs(king_file - file), std::abs(king_rank - rank));
            maximum_score += 1.0/(distance + 1.0);
        }
    }
}

King_Confinement_Gene::~King_Confinement_Gene()
{
}

King_Confinement_Gene* King_Confinement_Gene::duplicate() const
{
    return new King_Confinement_Gene(*this);
}

std::string King_Confinement_Gene::name() const
{
    return "King Confinement Gene";
}

double King_Confinement_Gene::score_board(const Board& board, Color perspective) const
{
    // A flood-fill-like algorithm to count the squares that are reachable by the
    // king from its current positions with unlimited consecutive moves. The
    // boundaries of this area area squares attacked by the other color or occupied
    // by pieces of the same color.
    //
    // The more moves it takes to reach a square, the less it adds to the score.

    std::vector<Square> square_queue;
    square_queue.reserve(64);
    auto king_square = board.find_king(perspective);
    square_queue.push_back(king_square);

    std::map<Square, int> distance;
    distance[king_square] = 1;

    double score = 0.0;

    for(size_t i = 0; i < square_queue.size(); ++i)
    {
        auto square = square_queue[i];

        bool attacked_by_other = ! board.safe_for_king(square.file,
                                                       square.rank,
                                                       perspective);

        auto piece = board.view_piece_on_square(square.file, square.rank);
        bool occupied_by_same = piece &&
                                piece->color() == perspective &&
                                ! piece->is_king();

        auto is_safe = ! attacked_by_other && ! occupied_by_same;
        if(is_safe)
        {
            score += 1.0/distance[square];
        }

        // Add surrounding squares to square_queue.
        // always check the squares surrounding the king's current positions, even if
        // it is not safe (i.e., the king is in check).
        if(is_safe || square_queue.size() == 1)
        {
            for(char new_file = square.file - 1; new_file <= square.file + 1; ++new_file)
            {
                if( ! board.inside_board(new_file))
                {
                    continue;
                }

                for(int new_rank = square.rank - 1; new_rank <= square.rank + 1; ++new_rank)
                {
                    if( ! board.inside_board(new_rank))
                    {
                        continue;
                    }

                    auto new_square = Square{new_file, new_rank};
                    if(distance[new_square] == 0) // never checked
                    {
                        square_queue.push_back(new_square);
                        distance[new_square] = distance[square] + 1;
                    }
                }
            }
        }
    }

    return score/maximum_score; // normalized so max is 1
}
<commit_msg>Simplifying calculation of King Confinement normalization<commit_after>#include "Genes/King_Confinement_Gene.h"

#include <cmath>

#include "Game/Board.h"
#include "Game/Color.h"
#include "Pieces/Piece.h"

King_Confinement_Gene::King_Confinement_Gene() : maximum_score(0.0)
{
    // Maximum score comes from a king in the middle of an empty board
    auto king_square = Square{'e', 4};

    for(auto file = 'a'; file <= 'h'; ++file)
    {
        for(auto rank = 1; rank <= 8; ++rank)
        {
            auto distance = king_distance(king_square, {file, rank});
            maximum_score += 1.0/(distance + 1.0);
        }
    }
}

King_Confinement_Gene::~King_Confinement_Gene()
{
}

King_Confinement_Gene* King_Confinement_Gene::duplicate() const
{
    return new King_Confinement_Gene(*this);
}

std::string King_Confinement_Gene::name() const
{
    return "King Confinement Gene";
}

double King_Confinement_Gene::score_board(const Board& board, Color perspective) const
{
    // A flood-fill-like algorithm to count the squares that are reachable by the
    // king from its current positions with unlimited consecutive moves. The
    // boundaries of this area area squares attacked by the other color or occupied
    // by pieces of the same color.
    //
    // The more moves it takes to reach a square, the less it adds to the score.

    std::vector<Square> square_queue;
    square_queue.reserve(64);
    auto king_square = board.find_king(perspective);
    square_queue.push_back(king_square);

    std::map<Square, int> distance;
    distance[king_square] = 1;

    double score = 0.0;

    for(size_t i = 0; i < square_queue.size(); ++i)
    {
        auto square = square_queue[i];

        bool attacked_by_other = ! board.safe_for_king(square.file,
                                                       square.rank,
                                                       perspective);

        auto piece = board.view_piece_on_square(square.file, square.rank);
        bool occupied_by_same = piece &&
                                piece->color() == perspective &&
                                ! piece->is_king();

        auto is_safe = ! attacked_by_other && ! occupied_by_same;
        if(is_safe)
        {
            score += 1.0/distance[square];
        }

        // Add surrounding squares to square_queue.
        // always check the squares surrounding the king's current positions, even if
        // it is not safe (i.e., the king is in check).
        if(is_safe || square_queue.size() == 1)
        {
            for(char new_file = square.file - 1; new_file <= square.file + 1; ++new_file)
            {
                if( ! board.inside_board(new_file))
                {
                    continue;
                }

                for(int new_rank = square.rank - 1; new_rank <= square.rank + 1; ++new_rank)
                {
                    if( ! board.inside_board(new_rank))
                    {
                        continue;
                    }

                    auto new_square = Square{new_file, new_rank};
                    if(distance[new_square] == 0) // never checked
                    {
                        square_queue.push_back(new_square);
                        distance[new_square] = distance[square] + 1;
                    }
                }
            }
        }
    }

    return score/maximum_score; // normalized so max is 1
}
<|endoftext|>


<commit_before>#pragma once

#include <QXmlStreamWriter>
#include <QtGui/QKeyEvent>
#include <QtGui/QMouseEvent>
#include <QtXml/QtXml>

#include <Gui/RaGui.hpp>

#include <Core/Utils/Index.hpp>
#include <Core/Utils/Log.hpp>
#include <Core/Utils/Observable.hpp>
#include <Core/Utils/Singleton.hpp>

namespace Ra {
namespace Gui {
/// An utility class used to map a (combination) of key / modifier to a specific action.
/// It can load configuration from a file or if no config is found it will load an
/// internal version of the default configuration.
class RA_GUI_API KeyMappingManager : public Ra::Core::Utils::ObservableVoid
{
    RA_SINGLETON_INTERFACE( KeyMappingManager );

    // Needed by Q_ENUM
    Q_GADGET

  public:
    using KeyMappingAction = Ra::Core::Utils::Index;
    using Context          = Ra::Core::Utils::Index;

    /// load configuration from filename, or default configration filename. It
    /// calls the listener callback then.
    void loadConfiguration( const char* filename = nullptr );

    /// Save the configuration
    /// @param filename the file to write to. It will be replaced
    /// @return true if file was correctly saved
    bool saveConfiguration( const char* filename = nullptr );

    /// reload last open file.
    void reloadConfiguration();

    /// Return the action associated to the binding buttons + modifiers + key
    /// \param buttons are the mouse buttons pressed, could be NoButton
    /// \param modifiers are the keyboard modifiers, could be NoModifiers
    /// \param key is the key pressed, could be -1
    KeyMappingManager::KeyMappingAction getAction( const KeyMappingManager::Context& context,
                                                   const Qt::MouseButtons& buttons,
                                                   const Qt::KeyboardModifiers& modifiers,
                                                   int key,
                                                   bool wheel = false );

    /// Add a given action to the mapping system.
    /// This allow to define default behavior when some KeyMappingManageable object is not
    /// parameterized in the application config file. The action is added to the current config file
    /// so that it will remain for subsequent usage.
    /// @todo write the configuration in the configFile to be later reused or modified ?
    /// @param context the context of the action
    /// @param keyString  represents the key that needs to be pressed to trigger the event
    /// (ie Key_Z, for example), "" or "-1" corresponds to no key needed.
    /// @param modifiersString represents the modifier used along with key or mouse button `
    /// (needs to be a Qt::Modifier enum value) to trigger the action. Multiples modifiers can be
    /// specified, separated by commas as in "ControlModifier,ShiftModifier".
    /// @param buttonsString represents the button to trigger the event (e.g. LeftButton).
    /// @param wheelString if true, it's a wheel event !
    /// @param actionString represents the KeyMappingAction enum's value you want to
    /// trigger.
    void addAction( const std::string& context,
                    const std::string& keyString,
                    const std::string& modifiersString,
                    const std::string& buttonsString,
                    const std::string& wheelString,
                    const std::string& actionString );

    /// Return the context index corresponding to contextName
    /// \param contextName the name of the context
    /// \return an invalid context if contextName has not been created
    Context getContext( const std::string& contextName );

    /// Return the action index corresponding to a context index and actionName
    /// \param context the index of the context
    /// \param actionName the name of the action
    /// \return an invalid action if context is not valid, or if actionName has  not been created.
    /// (i,e action.isInvalid())
    KeyMappingAction getActionIndex( const Context& context, const std::string& actionName );

    /// \return Action name if context index and action index are valid, "Invalid" otherwise
    std::string getActionName( const Context& context, const KeyMappingAction& action );

    /// \return Context name if context index is valid, "Invalid" otherwise
    std::string getContextName( const Context& context );

    /// Add a callback, triggered when configuration is load or reloaded.
    int addListener( Observable::Observer callback );

    /// Remove a callback. To be called when the related Context/Actions are no more needed.
    /// @param callbackId the Id, returned by addListener, of the Observer to be removed.
    void removeListener( int callbackId );

    /// return a string of enum names from mouse buttons, comma separated,
    /// without space
    static std::string enumNamesFromMouseButtons( const Qt::MouseButtons& buttons );

    /// return a string of enum names from keyboard modifiers, comma separated,
    /// without space
    static std::string enumNamesFromKeyboardModifiers( const Qt::KeyboardModifiers& modifiers );

  private:
    KeyMappingManager();
    ~KeyMappingManager();

    /// Save an XML node that describes an event/action.
    void saveNode( QXmlStreamWriter& stream, const QDomNode& domNode );

    // Private for now, but may need to be public if we want to customize keymapping configuration
    // otherwise than by editing the XML configuration file.
    class MouseBinding
    {
      public:
        explicit MouseBinding( Qt::MouseButtons buttons,
                               Qt::KeyboardModifiers modifiers = Qt::NoModifier,
                               int key                         = -1,
                               bool wheel                      = false ) :

            m_buttons {buttons}, m_modifiers {modifiers}, m_key {key}, m_wheel {wheel} {}
        bool operator<( const MouseBinding& b ) const {
            return ( m_buttons < b.m_buttons ) ||
                   ( ( m_buttons == b.m_buttons ) && ( m_modifiers < b.m_modifiers ) ) ||
                   ( ( m_buttons == b.m_buttons ) && ( m_modifiers == b.m_modifiers ) &&
                     ( m_key < b.m_key ) ) ||
                   ( ( m_buttons == b.m_buttons ) && ( m_modifiers == b.m_modifiers ) &&
                     ( m_key == b.m_key ) && ( m_wheel < b.m_wheel ) );
        }

        //  private:
        Qt::MouseButtons m_buttons;
        Qt::KeyboardModifiers m_modifiers;
        // only one key
        int m_key;
        bool m_wheel;
    };

    /// bind binding to actionIndex, in contextIndex. If replace previously
    /// binded action, with a warning if binding was alreasly present.,
    void bindKeyToAction( Ra::Core::Utils::Index contextIndex,
                          const MouseBinding& binding,
                          Ra::Core::Utils::Index actionIndex );

    void loadConfigurationInternal();
    void loadConfigurationTagsInternal( QDomElement& node );
    void loadConfigurationMappingInternal( const std::string& context,
                                           const std::string& keyString,
                                           const std::string& modifiersString,
                                           const std::string& buttonsString,
                                           const std::string& wheelString,
                                           const std::string& actionString );

    /// Return KeyboardModifiers described in modifierString, multiple modifiers
    /// are comma separated in the modifiers string, as in
    /// "ShiftModifier,AltModifier". This function do note trim any white space.
    static Qt::KeyboardModifiers getQtModifiersValue( const std::string& modifierString );

    /// Return MouseButtons desribed in buttonString, multiple modifiers
    /// are comma separated in the modifiers string, \note only one button is
    /// supported for the moment.
    static Qt::MouseButtons getQtMouseButtonsValue( const std::string& buttonsString );

  private:
    std::string m_defaultConfigFile;
    // For XML parsing using Qt
    QDomDocument m_domDocument;
    QMetaEnum m_metaEnumAction;
    QMetaEnum m_metaEnumKey;
    QFile* m_file;

    using MouseBindingMapping = std::map<MouseBinding, KeyMappingAction>;
    using ContextNameMap      = std::map<std::string, Context>;
    using ActionNameMap       = std::map<std::string, Ra::Core::Utils::Index>;

    ContextNameMap m_contextNameToIndex;              ///< context string give index
    std::vector<ActionNameMap> m_actionNameToIndex;   ///< one element per context
    std::vector<MouseBindingMapping> m_mappingAction; ///< one element per context
};

/// KeyMappingManageable decorate, typical use as a CRTP :
/// class MyClass : public KeyMappingManageable<MyClass> { [...]
/// it defines a static class member m_keyMappingContext, readable with
/// getContext()
/// This context index must be registered by the class to the KeyMappingManager
/// with KeyMappingManager::getContext("MyClassContextName"); after a
/// configuration file is loaded.
template <typename T>
class KeyMappingManageable
{
  public:
    static inline KeyMappingManager::Context getContext() { return m_keyMappingContext; }

    /// KeyManageable class should implement static configureKeyMapping_impl to get their
    /// keyMappingAction constants.
    static inline void configureKeyMapping() { T::configureKeyMapping_impl(); }

  protected:
    T& self() { return static_cast<T&>( *this ); }
    static inline void setContext( const KeyMappingManager::Context& c ) {
        m_keyMappingContext = c;
    }

  private:
    static KeyMappingManager::Context m_keyMappingContext;
};

/// create one m_keyMappingContext by template type.
template <typename T>
KeyMappingManager::Context KeyMappingManageable<T>::m_keyMappingContext;

} // namespace Gui
} // namespace Ra
<commit_msg>[gui] add accessor to keymapping filename.<commit_after>#pragma once

#include <QXmlStreamWriter>
#include <QtGui/QKeyEvent>
#include <QtGui/QMouseEvent>
#include <QtXml/QtXml>

#include <Gui/RaGui.hpp>

#include <Core/Utils/Index.hpp>
#include <Core/Utils/Log.hpp>
#include <Core/Utils/Observable.hpp>
#include <Core/Utils/Singleton.hpp>

namespace Ra {
namespace Gui {
/// An utility class used to map a (combination) of key / modifier to a specific action.
/// It can load configuration from a file or if no config is found it will load an
/// internal version of the default configuration.
class RA_GUI_API KeyMappingManager : public Ra::Core::Utils::ObservableVoid
{
    RA_SINGLETON_INTERFACE( KeyMappingManager );

    // Needed by Q_ENUM
    Q_GADGET

  public:
    using KeyMappingAction = Ra::Core::Utils::Index;
    using Context          = Ra::Core::Utils::Index;

    /// load configuration from filename, or default configration filename. It
    /// calls the listener callback then.
    void loadConfiguration( const char* filename = nullptr );

    /// Save the configuration
    /// @param filename the file to write to. It will be replaced
    /// @return true if file was correctly saved
    bool saveConfiguration( const char* filename = nullptr );

    /// reload last open file.
    void reloadConfiguration();

    std::string getLoadedFilename() { return m_file->fileName().toStdString(); }

    /// Return the action associated to the binding buttons + modifiers + key
    /// \param buttons are the mouse buttons pressed, could be NoButton
    /// \param modifiers are the keyboard modifiers, could be NoModifiers
    /// \param key is the key pressed, could be -1
    KeyMappingManager::KeyMappingAction getAction( const KeyMappingManager::Context& context,
                                                   const Qt::MouseButtons& buttons,
                                                   const Qt::KeyboardModifiers& modifiers,
                                                   int key,
                                                   bool wheel = false );

    /// Add a given action to the mapping system.
    /// This allow to define default behavior when some KeyMappingManageable object is not
    /// parameterized in the application config file. The action is added to the current config file
    /// so that it will remain for subsequent usage.
    /// @todo write the configuration in the configFile to be later reused or modified ?
    /// @param context the context of the action
    /// @param keyString  represents the key that needs to be pressed to trigger the event
    /// (ie Key_Z, for example), "" or "-1" corresponds to no key needed.
    /// @param modifiersString represents the modifier used along with key or mouse button `
    /// (needs to be a Qt::Modifier enum value) to trigger the action. Multiples modifiers can be
    /// specified, separated by commas as in "ControlModifier,ShiftModifier".
    /// @param buttonsString represents the button to trigger the event (e.g. LeftButton).
    /// @param wheelString if true, it's a wheel event !
    /// @param actionString represents the KeyMappingAction enum's value you want to
    /// trigger.
    void addAction( const std::string& context,
                    const std::string& keyString,
                    const std::string& modifiersString,
                    const std::string& buttonsString,
                    const std::string& wheelString,
                    const std::string& actionString );

    /// Return the context index corresponding to contextName
    /// \param contextName the name of the context
    /// \return an invalid context if contextName has not been created
    Context getContext( const std::string& contextName );

    /// Return the action index corresponding to a context index and actionName
    /// \param context the index of the context
    /// \param actionName the name of the action
    /// \return an invalid action if context is not valid, or if actionName has  not been created.
    /// (i,e action.isInvalid())
    KeyMappingAction getActionIndex( const Context& context, const std::string& actionName );

    /// \return Action name if context index and action index are valid, "Invalid" otherwise
    std::string getActionName( const Context& context, const KeyMappingAction& action );

    /// \return Context name if context index is valid, "Invalid" otherwise
    std::string getContextName( const Context& context );

    /// Add a callback, triggered when configuration is load or reloaded.
    int addListener( Observable::Observer callback );

    /// Remove a callback. To be called when the related Context/Actions are no more needed.
    /// @param callbackId the Id, returned by addListener, of the Observer to be removed.
    void removeListener( int callbackId );

    /// return a string of enum names from mouse buttons, comma separated,
    /// without space
    static std::string enumNamesFromMouseButtons( const Qt::MouseButtons& buttons );

    /// return a string of enum names from keyboard modifiers, comma separated,
    /// without space
    static std::string enumNamesFromKeyboardModifiers( const Qt::KeyboardModifiers& modifiers );

  private:
    KeyMappingManager();
    ~KeyMappingManager();

    /// Save an XML node that describes an event/action.
    void saveNode( QXmlStreamWriter& stream, const QDomNode& domNode );

    // Private for now, but may need to be public if we want to customize keymapping configuration
    // otherwise than by editing the XML configuration file.
    class MouseBinding
    {
      public:
        explicit MouseBinding( Qt::MouseButtons buttons,
                               Qt::KeyboardModifiers modifiers = Qt::NoModifier,
                               int key                         = -1,
                               bool wheel                      = false ) :

            m_buttons {buttons}, m_modifiers {modifiers}, m_key {key}, m_wheel {wheel} {}
        bool operator<( const MouseBinding& b ) const {
            return ( m_buttons < b.m_buttons ) ||
                   ( ( m_buttons == b.m_buttons ) && ( m_modifiers < b.m_modifiers ) ) ||
                   ( ( m_buttons == b.m_buttons ) && ( m_modifiers == b.m_modifiers ) &&
                     ( m_key < b.m_key ) ) ||
                   ( ( m_buttons == b.m_buttons ) && ( m_modifiers == b.m_modifiers ) &&
                     ( m_key == b.m_key ) && ( m_wheel < b.m_wheel ) );
        }

        //  private:
        Qt::MouseButtons m_buttons;
        Qt::KeyboardModifiers m_modifiers;
        // only one key
        int m_key;
        bool m_wheel;
    };

    /// bind binding to actionIndex, in contextIndex. If replace previously
    /// binded action, with a warning if binding was alreasly present.,
    void bindKeyToAction( Ra::Core::Utils::Index contextIndex,
                          const MouseBinding& binding,
                          Ra::Core::Utils::Index actionIndex );

    void loadConfigurationInternal();
    void loadConfigurationTagsInternal( QDomElement& node );
    void loadConfigurationMappingInternal( const std::string& context,
                                           const std::string& keyString,
                                           const std::string& modifiersString,
                                           const std::string& buttonsString,
                                           const std::string& wheelString,
                                           const std::string& actionString );

    /// Return KeyboardModifiers described in modifierString, multiple modifiers
    /// are comma separated in the modifiers string, as in
    /// "ShiftModifier,AltModifier". This function do note trim any white space.
    static Qt::KeyboardModifiers getQtModifiersValue( const std::string& modifierString );

    /// Return MouseButtons desribed in buttonString, multiple modifiers
    /// are comma separated in the modifiers string, \note only one button is
    /// supported for the moment.
    static Qt::MouseButtons getQtMouseButtonsValue( const std::string& buttonsString );

  private:
    std::string m_defaultConfigFile;
    // For XML parsing using Qt
    QDomDocument m_domDocument;
    QMetaEnum m_metaEnumAction;
    QMetaEnum m_metaEnumKey;
    QFile* m_file;

    using MouseBindingMapping = std::map<MouseBinding, KeyMappingAction>;
    using ContextNameMap      = std::map<std::string, Context>;
    using ActionNameMap       = std::map<std::string, Ra::Core::Utils::Index>;

    ContextNameMap m_contextNameToIndex;              ///< context string give index
    std::vector<ActionNameMap> m_actionNameToIndex;   ///< one element per context
    std::vector<MouseBindingMapping> m_mappingAction; ///< one element per context
};

/// KeyMappingManageable decorate, typical use as a CRTP :
/// class MyClass : public KeyMappingManageable<MyClass> { [...]
/// it defines a static class member m_keyMappingContext, readable with
/// getContext()
/// This context index must be registered by the class to the KeyMappingManager
/// with KeyMappingManager::getContext("MyClassContextName"); after a
/// configuration file is loaded.
template <typename T>
class KeyMappingManageable
{
  public:
    static inline KeyMappingManager::Context getContext() { return m_keyMappingContext; }

    /// KeyManageable class should implement static configureKeyMapping_impl to get their
    /// keyMappingAction constants.
    static inline void configureKeyMapping() { T::configureKeyMapping_impl(); }

  protected:
    T& self() { return static_cast<T&>( *this ); }
    static inline void setContext( const KeyMappingManager::Context& c ) {
        m_keyMappingContext = c;
    }

  private:
    static KeyMappingManager::Context m_keyMappingContext;
};

/// create one m_keyMappingContext by template type.
template <typename T>
KeyMappingManager::Context KeyMappingManageable<T>::m_keyMappingContext;

} // namespace Gui
} // namespace Ra
<|endoftext|>