<commit_before>#include <hydra/network/tcpclient.hpp>
#include <vector>
#include <SDL2/SDL_net.h>

using namespace Hydra::Network;

TCPClient::TCPClient() {
    this->_connected = false;
}
TCPClient::~TCPClient() {
	close();
}

bool TCPClient::initialize(char* ip, int port) {
	IPaddress ipaddr;
	if(SDLNet_ResolveHost(&ipaddr, ip, port)) {
		return false;
	}

	this->_tcp = SDLNet_TCP_Open(&ipaddr);
	if(!this->_tcp) {
		const char* c = SDLNet_GetError();
		return false;
	}
	this->_msg = new char[MAX_NETWORK_LENGTH];
	this->_connected = true;
	this->_sset = SDLNet_AllocSocketSet(1);
	SDLNet_TCP_AddSocket(this->_sset, this->_tcp);
	return true;
}

int TCPClient::send(void* data, int length) {
	if (!_connected)
		return -1;
	((Packet*)data)->h.client = -7;
	return SDLNet_TCP_Send(this->_tcp, data, length);
}

std::vector<Packet*> TCPClient::receiveData() {
	static std::vector<uint8_t> data;
	std::vector<Packet*> packets;
	if (!_connected)
		return packets;

	if (SDLNet_CheckSockets(this->_sset, 0) == 1) {
		ssize_t lenTmp = SDLNet_TCP_Recv(this->_tcp, this->_msg, MAX_NETWORK_LENGTH);
		if (lenTmp <= 0) {
			close();
			return packets;
		}

		size_t offset = 0;
		size_t len = lenTmp;
		while (offset < len) {
			Packet* p = (Packet*)(&(this->_msg[offset]));
			//if (p->h.type != ServerUpdate)
				printf("Reading packet: offset: %zu\n\ttype: %s\n\tlen: %d\n\tclient: %d\n", offset, Hydra::Network::PacketTypeName[p->h.type], p->h.len, p->h.client);
			offset += p->h.len;
			if (offset > len) {
				fprintf(stderr, "PACKET NEEDED MORE DATA THAN AVAILABLE!");
				break;
			}

			Packet* newPacket = (Packet*)(new char[p->h.len]);
			memcpy(newPacket, p, p->h.len);
			packets.push_back(newPacket);
		}
	}

	return packets;
}

bool TCPClient::isConnected() {
	return this->_connected;
}

void TCPClient::close() {
	printf("Disconnecting from the server!\n");
	_connected = false;
	SDLNet_FreeSocketSet(_sset);
	_sset = nullptr;
	SDLNet_TCP_Close(_tcp);
	_tcp = nullptr;
	delete[] this->_msg;
}
<commit_msg>Windows fix<commit_after>#include <hydra/network/tcpclient.hpp>
#include <vector>
#include <SDL2/SDL_net.h>

using namespace Hydra::Network;

TCPClient::TCPClient() {
    this->_connected = false;
}
TCPClient::~TCPClient() {
	close();
}

bool TCPClient::initialize(char* ip, int port) {
	IPaddress ipaddr;
	if(SDLNet_ResolveHost(&ipaddr, ip, port)) {
		return false;
	}

	this->_tcp = SDLNet_TCP_Open(&ipaddr);
	if(!this->_tcp) {
		const char* c = SDLNet_GetError();
		return false;
	}
	this->_msg = new char[MAX_NETWORK_LENGTH];
	this->_connected = true;
	this->_sset = SDLNet_AllocSocketSet(1);
	SDLNet_TCP_AddSocket(this->_sset, this->_tcp);
	return true;
}

int TCPClient::send(void* data, int length) {
	if (!_connected)
		return -1;
	((Packet*)data)->h.client = -7;
	return SDLNet_TCP_Send(this->_tcp, data, length);
}

std::vector<Packet*> TCPClient::receiveData() {
	static std::vector<uint8_t> data;
	std::vector<Packet*> packets;
	if (!_connected)
		return packets;

	if (SDLNet_CheckSockets(this->_sset, 0) == 1) {
		int64_t lenTmp = SDLNet_TCP_Recv(this->_tcp, this->_msg, MAX_NETWORK_LENGTH);
		if (lenTmp <= 0) {
			close();
			return packets;
		}

		size_t offset = 0;
		size_t len = lenTmp;
		while (offset < len) {
			Packet* p = (Packet*)(&(this->_msg[offset]));
			//if (p->h.type != ServerUpdate)
				printf("Reading packet: offset: %zu\n\ttype: %s\n\tlen: %d\n\tclient: %d\n", offset, Hydra::Network::PacketTypeName[p->h.type], p->h.len, p->h.client);
			offset += p->h.len;
			if (offset > len) {
				fprintf(stderr, "PACKET NEEDED MORE DATA THAN AVAILABLE!");
				break;
			}

			Packet* newPacket = (Packet*)(new char[p->h.len]);
			memcpy(newPacket, p, p->h.len);
			packets.push_back(newPacket);
		}
	}

	return packets;
}

bool TCPClient::isConnected() {
	return this->_connected;
}

void TCPClient::close() {
	printf("Disconnecting from the server!\n");
	_connected = false;
	SDLNet_FreeSocketSet(_sset);
	_sset = nullptr;
	SDLNet_TCP_Close(_tcp);
	_tcp = nullptr;
	delete[] this->_msg;
}
<|endoftext|>


<commit_before>#include <cstdlib>
#include <iostream>
#include <fstream>

#include <sqlite3.h>

sqlite3 * open_database(const char * filename)
{
  sqlite3 * db;
  if (sqlite3_open(filename, &db) != SQLITE_OK) {
    std::cerr << "An error occurred while opening the db file: "
	      << filename << std::endl;
  }
  return db;
}

void load_chemicalite(sqlite3 * db)
{
  char * errmsg = 0;
  if (sqlite3_enable_load_extension(db, 1) != SQLITE_OK) {
    std::cerr << "Could not enable loading extensions" << std::endl;
  }
  else if (sqlite3_load_extension(db, "chemicalite", 0, &errmsg) != SQLITE_OK) {
    std::cerr << "An error occurred while loading chemicalite: "
	      << errmsg << std::endl;
    sqlite3_free(errmsg);
  }
  else if (sqlite3_enable_load_extension(db, 0) != SQLITE_OK) {
    std::cerr << "Could not enable loading extensions" << std::endl;
  }
}

void initialize_database(sqlite3 * db)
{
  char * errmsg = 0;
  if (sqlite3_exec(db,
 		   "PRAGMA page_size=4096; "
		   "CREATE TABLE chembl("
		   "id INTEGER PRIMARY KEY, chembl_id TEXT, smiles TEXT, "
		   "molecule MOL); "
		   "SELECT create_molecule_rdtree('chembl', 'molecule')",
		   NULL,  /* Callback function */
		   0,     /* 1st argument to callback */
		   &errmsg) != SQLITE_OK) {
    std::cerr << "An error occurred while initializing the db: "
	      << errmsg << std::endl;
    sqlite3_free(errmsg);
  }
}

void replace_substring(std::string & str,
		       const std::string & from, const std::string & to)
{
  if(from.empty())
    return;
  size_t start_pos = 0;
  while((start_pos = str.find(from, start_pos)) != std::string::npos) {
    str.replace(start_pos, from.length(), to);
    start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
  }
}

void fix_smiles(std::string & smiles)
{
  replace_substring(smiles, "=N#N", "=[N+]=[N-]");
  replace_substring(smiles, "N#N=", "[N-]=[N+]=");
}

void insert_molecules(sqlite3 * db, std::istream & input)
{
  char * errmsg = 0;

  if (sqlite3_exec(db, "BEGIN",
		   NULL,  /* Callback function */
		   0,     /* 1st argument to callback */
		   &errmsg) != SQLITE_OK) {
    std::cerr << "Could not begin transaction: " << errmsg << std::endl;
    sqlite3_free(errmsg);
  }

  const char * sql =
    "INSERT INTO chembl(chembl_id, smiles, molecule) VALUES(?, ?, mol(?))";

  sqlite3_stmt * stmt = 0;
  if (sqlite3_prepare_v2(db, sql, -1, & stmt, 0) != SQLITE_OK) {
    std::cerr << "Could not prepare sql statement" << std::endl;
  }

  // skip the header line
  static const int BUFFER_SIZE = 4096;
  char buffer[BUFFER_SIZE];
  input.getline(buffer, BUFFER_SIZE);

  if (!input) {
    std::cerr << "Unexpected end of input after header line" << std::endl;
  }

  int line_count = 0;

  while (input) {

    std::string chembl_id, smiles;
    input >> chembl_id >> smiles;
    input.getline(buffer, BUFFER_SIZE); // discard the rest of the line

    if (input) {

      ++line_count;

      if (smiles.size() > 300) {
	continue;
      }

      fix_smiles(smiles);

      // bind the query parameter
      if (sqlite3_bind_text(stmt, 1, chembl_id.c_str(), -1, SQLITE_STATIC)
	  != SQLITE_OK) {
	std::cerr << "Couldn't bind chembl_id parameter" << std::endl;
	break;
      }
      if (sqlite3_bind_text(stmt, 2, smiles.c_str(), -1, SQLITE_STATIC)
	  != SQLITE_OK) {
	std::cerr << "Couldn't bind smiles parameter" << std::endl;
	break;
      }
      if (sqlite3_bind_text(stmt, 3, smiles.c_str(), -1, SQLITE_STATIC)
	  != SQLITE_OK) {
   	std::cerr << "Couldn't bind mol() parameter" << std::endl;
	break;
      }

      // execute the query
      if (sqlite3_step(stmt) != SQLITE_DONE) {
   	std::cerr << "Couldn't execute sql statement: "
		  << line_count << std::endl;
	// don't break; just reset the statement and continue.
      }

      // reset the query
      if (sqlite3_reset(stmt) != SQLITE_OK) {
	 std::cerr << "Couldn't successfully reset sql statement" << std::endl;
      }

      // clear the bindings
      if (sqlite3_clear_bindings(stmt) != SQLITE_OK) {
	std::cerr << "Couldn't successfully clear the bindings" << std::endl;
      }
    }
  }

  if (sqlite3_finalize(stmt) != SQLITE_OK)  {
    //std::cerr << "Couldn't finalize statement" << std::endl;
  }

  if (sqlite3_exec(db, "COMMIT",
		   NULL,  /* Callback function */
		   0,     /* 1st argument to callback */
		   &errmsg) != SQLITE_OK) {
    std::cerr << "Could not commit transaction: " << errmsg << std::endl;
    sqlite3_free(errmsg);
  }
}

void close_database(sqlite3 * db)
{
  if (sqlite3_close(db) != SQLITE_OK) {
    std::cerr << "An error occurred while closing the db" << std::endl;
  }
}

int main(int argc, char * argv[])
{
  const char * input_path = argv[1];
  const char * db_path = argv[2];

  std::ifstream input_file(input_path);

  if (!input_file) {
    std::cerr << "Couldn't open input file: " << input_path << std::endl;
    return 1;
  }

  sqlite3 * db = open_database(db_path);

  load_chemicalite(db);
  initialize_database(db);
  insert_molecules(db, input_file);
  close_database(db);
}
<commit_msg>create mol structural index at end of insertion<commit_after>#include <cstdlib>
#include <iostream>
#include <fstream>

#include <sqlite3.h>

sqlite3 * open_database(const char * filename)
{
  sqlite3 * db;
  if (sqlite3_open(filename, &db) != SQLITE_OK) {
    std::cerr << "An error occurred while opening the db file: "
	      << filename << std::endl;
  }
  return db;
}

void load_chemicalite(sqlite3 * db)
{
  char * errmsg = 0;
  if (sqlite3_enable_load_extension(db, 1) != SQLITE_OK) {
    std::cerr << "Could not enable loading extensions" << std::endl;
  }
  else if (sqlite3_load_extension(db, "chemicalite", 0, &errmsg) != SQLITE_OK) {
    std::cerr << "An error occurred while loading chemicalite: "
	      << errmsg << std::endl;
    sqlite3_free(errmsg);
  }
  else if (sqlite3_enable_load_extension(db, 0) != SQLITE_OK) {
    std::cerr << "Could not enable loading extensions" << std::endl;
  }
}

void initialize_database(sqlite3 * db)
{
  char * errmsg = 0;
  if (sqlite3_exec(db,
 		   "PRAGMA page_size=4096; "
		   "CREATE TABLE chembl("
		   "id INTEGER PRIMARY KEY, chembl_id TEXT, smiles TEXT, "
		   "molecule MOL)",
		   NULL,  /* Callback function */
		   0,     /* 1st argument to callback */
		   &errmsg) != SQLITE_OK) {
    std::cerr << "An error occurred while initializing the db: "
	      << errmsg << std::endl;
    sqlite3_free(errmsg);
  }
}

void replace_substring(std::string & str,
		       const std::string & from, const std::string & to)
{
  if(from.empty())
    return;
  size_t start_pos = 0;
  while((start_pos = str.find(from, start_pos)) != std::string::npos) {
    str.replace(start_pos, from.length(), to);
    start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
  }
}

void fix_smiles(std::string & smiles)
{
  replace_substring(smiles, "=N#N", "=[N+]=[N-]");
  replace_substring(smiles, "N#N=", "[N-]=[N+]=");
}

void insert_molecules(sqlite3 * db, std::istream & input)
{
  char * errmsg = 0;

  if (sqlite3_exec(db, "BEGIN",
		   NULL,  /* Callback function */
		   0,     /* 1st argument to callback */
		   &errmsg) != SQLITE_OK) {
    std::cerr << "Could not begin transaction: " << errmsg << std::endl;
    sqlite3_free(errmsg);
  }

  const char * sql =
    "INSERT INTO chembl(chembl_id, smiles, molecule) VALUES(?, ?, mol(?))";

  sqlite3_stmt * stmt = 0;
  if (sqlite3_prepare_v2(db, sql, -1, & stmt, 0) != SQLITE_OK) {
    std::cerr << "Could not prepare sql statement" << std::endl;
  }

  // skip the header line
  static const int BUFFER_SIZE = 4096;
  char buffer[BUFFER_SIZE];
  input.getline(buffer, BUFFER_SIZE);

  if (!input) {
    std::cerr << "Unexpected end of input after header line" << std::endl;
  }

  int line_count = 0;

  while (input) {

    std::string chembl_id, smiles;
    input >> chembl_id >> smiles;
    input.getline(buffer, BUFFER_SIZE); // discard the rest of the line

    if (input) {

      ++line_count;

      if (smiles.size() > 300) {
	continue;
      }

      fix_smiles(smiles);

      // bind the query parameter
      if (sqlite3_bind_text(stmt, 1, chembl_id.c_str(), -1, SQLITE_STATIC)
	  != SQLITE_OK) {
	std::cerr << "Couldn't bind chembl_id parameter" << std::endl;
	break;
      }
      if (sqlite3_bind_text(stmt, 2, smiles.c_str(), -1, SQLITE_STATIC)
	  != SQLITE_OK) {
	std::cerr << "Couldn't bind smiles parameter" << std::endl;
	break;
      }
      if (sqlite3_bind_text(stmt, 3, smiles.c_str(), -1, SQLITE_STATIC)
	  != SQLITE_OK) {
   	std::cerr << "Couldn't bind mol() parameter" << std::endl;
	break;
      }

      // execute the query
      if (sqlite3_step(stmt) != SQLITE_DONE) {
   	std::cerr << "Couldn't execute sql statement: "
		  << line_count << std::endl;
	// don't break; just reset the statement and continue.
      }

      // reset the query
      if (sqlite3_reset(stmt) != SQLITE_OK) {
	// an error code is returned if the statement failed executing
	// so the output below may appear misleading
	//std::cerr << "Couldn't successfully reset sql statement" << std::endl;
      }

      // clear the bindings
      if (sqlite3_clear_bindings(stmt) != SQLITE_OK) {
	std::cerr << "Couldn't successfully clear the bindings" << std::endl;
      }
    }
  }

  if (sqlite3_finalize(stmt) != SQLITE_OK)  {
    //std::cerr << "Couldn't finalize statement" << std::endl;
  }

  if (sqlite3_exec(db, "COMMIT",
		   NULL,  /* Callback function */
		   0,     /* 1st argument to callback */
		   &errmsg) != SQLITE_OK) {
    std::cerr << "Could not commit transaction: " << errmsg << std::endl;
    sqlite3_free(errmsg);
  }
}

void create_index(sqlite3 * db)
{
  char * errmsg = 0;
  if (sqlite3_exec(db,
 		   "SELECT create_molecule_rdtree('chembl', 'molecule')",
		   NULL,  /* Callback function */
		   0,     /* 1st argument to callback */
		   &errmsg) != SQLITE_OK) {
    std::cerr << "An error occurred while indexing the mol column: "
	      << errmsg << std::endl;
    sqlite3_free(errmsg);
  }
}

void close_database(sqlite3 * db)
{
  if (sqlite3_close(db) != SQLITE_OK) {
    std::cerr << "An error occurred while closing the db" << std::endl;
  }
}

int main(int argc, char * argv[])
{
  const char * input_path = argv[1];
  const char * db_path = argv[2];

  std::ifstream input_file(input_path);

  if (!input_file) {
    std::cerr << "Couldn't open input file: " << input_path << std::endl;
    return 1;
  }

  sqlite3 * db = open_database(db_path);

  load_chemicalite(db);
  initialize_database(db);
  insert_molecules(db, input_file);
  create_index(db);

  close_database(db);
}
<|endoftext|>


<commit_before>#include <signal.h>				// for signal, SIGINT
#include <thread>
#include <string>
#include <cstring>
#include <limits.h>
#include <sys/stat.h>
#include <armadillo>
#include <zmq.h>
#include "zmq_packet.h"
#include <basedir.h>
#include <basedir_fs.h>
#include "lconf.h"
#include "util.h"
#include "artifact_subtract.h"

u64 g_ec_stim = UINT_MAX;
u64 g_ec_current = UINT_MAX;
u16 g_current = 0;

bool s_interrupted = false;
std::vector <void *> g_socks;

static void s_signal_handler(int)
{
	s_interrupted = true;
}

static void s_catch_signals(void)
{
	struct sigaction action;
	action.sa_handler = s_signal_handler;
	action.sa_flags = 0;
	sigemptyset(&action.sa_mask);
	sigaction(SIGINT, &action, NULL);
	sigaction(SIGQUIT, &action, NULL);
	sigaction(SIGTERM, &action, NULL);
}

static void die(void *ctx, int status)
{
	s_interrupted = true;
	for (auto &sock : g_socks) {
		zmq_close(sock);
	}
	zmq_ctx_term(ctx);
	exit(status);
}

int main(int argc, char *argv[])
{
	// subtr [zmq_sub_bb] [zmq_sub_ev] [zmq_pub_bb]

	if (argc < 4) {
		printf("\nsubtr - artifact subtraction\n");
		printf("usage: subtr [zmq_sub_bb] [zmq_sub_ev] [zmq_pub]\n\n");
		return 1;
	}

	std::string zbb 	= argv[1];
	std::string zev 	= argv[2];
	std::string zout 	= argv[3];

	debug("ZMQ SUB BROADBAND: %s", zbb.c_str());
	debug("ZMQ SUB EVENTS: %s", zev.c_str());
	debug("ZMQ PUB: %s", zout.c_str());

	s_catch_signals();

	xdgHandle xdg;
	xdgInitHandle(&xdg);
	char *confpath = xdgConfigFind("spk/spk.rc", &xdg);
	char *tmp = confpath;
	// confpath is "string1\0string2\0string3\0\0"

	luaConf conf;

	while (*tmp) {
		conf.loadConf(tmp);
		tmp += strlen(tmp) + 1;
	}
	if (confpath)
		free(confpath);
	xdgWipeHandle(&xdg);

	std::string zq = "ipc:///tmp/query.zmq";
	conf.getString("spk.query_socket", zq);

	void *zcontext = zmq_ctx_new();
	if (zcontext == NULL) {
		error("zmq: could not create context");
		return 1;
	}
	// we don't need 1024 sockets
	if (zmq_ctx_set(zcontext, ZMQ_MAX_SOCKETS, 64) != 0) {
		error("zmq: could not set max sockets");
		die(zcontext, 1);
	}

	void *query_sock = zmq_socket(zcontext, ZMQ_REQ);
	if (query_sock == NULL) {
		error("zmq: could not create socket");
		die(zcontext, 1);
	}
	g_socks.push_back(query_sock);
	if (zmq_connect(query_sock, zq.c_str()) != 0) {
		error("zmq: could not connect to socket");
		die(zcontext, 1);
	}

	u64 nnc; // num neural channels
	zmq_send(query_sock, "NNC", 3, 0);
	if (zmq_recv(query_sock, &nnc, sizeof(u64), 0) == -1) {
		error("zmq: could not recv from query sock");
		die(zcontext, 1);
	}

	u64 nec; // num events channels
	zmq_send(query_sock, "NEC", 3, 0);
	if (zmq_recv(query_sock, &nec, sizeof(u64), 0) == -1) {
		error("zmq: could not recv from query sock");
		die(zcontext, 1);
	}

	// nb we must not assume that the string is null terminated!
	auto is = [](zmq_msg_t *m, const char *c) {
		return strncmp((char *)zmq_msg_data(m), c, zmq_msg_size(m)) == 0;
	};

	for (u64 ch=0; ch<nec; ch++) {
		// EC : X : NAME
		zmq_send(query_sock, "EC", 2, ZMQ_SNDMORE);
		zmq_send(query_sock, &ch, sizeof(u64), ZMQ_SNDMORE);
		zmq_send(query_sock, "NAME", 4, 0);

		zmq_msg_t msg;
		zmq_msg_init(&msg);
		zmq_msg_recv(&msg, query_sock, 0);

		if (is(&msg, "stim")) {
			g_ec_stim = ch;
		}
		if (is(&msg, "current")) {
			g_ec_current = ch;
		}
		zmq_msg_close(&msg);
	}

	ArtifactSubtract subtr(16, nnc, 200, 64, 0.99);

	struct stat buf;
	if (stat("subtr.h5", &buf) == 0) { // ie file exists
		printf("loading subtr weights\n");
		subtr.loadWeights("subtr.h5");
	}

	int hwm = 8192;

	// subscribe to broadband messages from the po8e
	void *socket_bb = zmq_socket(zcontext, ZMQ_SUB);
	if (socket_bb == NULL) {
		error("zmq: could not create socket");
		die(zcontext, 1);
	}
	g_socks.push_back(socket_bb);
	zmq_setsockopt(socket_bb, ZMQ_RCVHWM, &hwm, sizeof(hwm));
	if (zmq_connect(socket_bb, zbb.c_str()) != 0) {
		error("zmq: could not connect to socket");
		die(zcontext, 1);
	}
	if (zmq_setsockopt(socket_bb, ZMQ_SUBSCRIBE, "", 0) != 0) {
		error("zmq: could not set socket options");
		die(zcontext, 1);
	}

	// same but for events messages
	void *socket_ev = zmq_socket(zcontext, ZMQ_SUB);
	if (socket_ev == NULL) {
		error("zmq: could not create socket");
		die(zcontext, 1);
	}
	g_socks.push_back(socket_ev);
	zmq_setsockopt(socket_ev, ZMQ_RCVHWM, &hwm, sizeof(hwm));
	if (zmq_connect(socket_ev, zev.c_str()) != 0) {
		error("zmq: could not connect to socket");
		die(zcontext, 1);
	}
	if (zmq_setsockopt(socket_ev, ZMQ_SUBSCRIBE, "", 0) != 0) {
		error("zmq: could not set socket options");
		die(zcontext, 1);
	}

	// publish SA subtracted data with this socket
	void *socket_out = zmq_socket(zcontext, ZMQ_PUB);
	if (socket_out == NULL) {
		error("zmq: could not create socket");
		die(zcontext, 1);
	}
	g_socks.push_back(socket_out);
	zmq_setsockopt(socket_out, ZMQ_SNDHWM, &hwm, sizeof(hwm));
	if (zmq_bind(socket_out, zout.c_str()) != 0) {
		error("zmq: could not bind to socket");
		die(zcontext, 1);
	}

	// init poll set
	zmq_pollitem_t items [] = {
		{ socket_bb, 0, ZMQ_POLLIN, 0 },
		{ socket_ev, 0, ZMQ_POLLIN, 0 }
	};

	zmq_msg_t bbh, evh;
	zmq_msg_t bb_body, ev_body;
	size_t nbh, neh;
	zmq_packet_header *bbp, *evp;
	size_t nb;
	float *f;
	i16 *ev;

	bool get_bb = true;
	bool get_ev = true;

	u64 bbtick_last = 0;
	u64 evtick_last = 0;

	bool ok_print_err = true;

	while (!s_interrupted) {

		if (zmq_poll(items, 2, -1) == -1) { //  -1 means block
			break;
		}

		if (	(items[0].revents & ZMQ_POLLIN || !get_bb) &&
		        (items[1].revents & ZMQ_POLLIN || !get_ev) ) {

			if (get_bb) {
				zmq_msg_init(&bbh);
				zmq_msg_recv(&bbh, socket_bb, 0);
				nbh = zmq_msg_size(&bbh);
				bbp = (zmq_packet_header *)zmq_msg_data(&bbh);

				if (bbp->tk - bbtick_last != bbp->ns && bbtick_last != 0) {
					warn("lost %ld bb samples", bbp->tk - bbtick_last - bbp->ns);
				}
				bbtick_last = bbp->tk;

				zmq_msg_init(&bb_body);
				zmq_msg_recv(&bb_body, socket_bb, 0);
				nb = zmq_msg_size(&bb_body);
				f = (float *)zmq_msg_data(&bb_body);
			}

			if (get_ev) {
				zmq_msg_init(&evh);
				zmq_msg_recv(&evh, socket_ev, 0);
				neh = zmq_msg_size(&evh);
				evp = (zmq_packet_header *)zmq_msg_data(&evh);

				if (evp->tk - evtick_last != evp->ns && evtick_last != 0) {
					warn("lost %ld ev samples", evp->tk - evtick_last - evp->ns);
				}
				evtick_last = evp->tk;

				zmq_msg_init(&ev_body);
				zmq_msg_recv(&ev_body, socket_ev, 0);
				ev = (i16 *)zmq_msg_data(&ev_body);
			}

			if (bbp->tk < evp->tk) {
				get_ev = false;
				if (ok_print_err) {
					printf("dropped bb\t%ld %ld %ld\n", bbp->tk, evp->tk, bbp->tk - evp->tk);
					ok_print_err = false;
				}
				zmq_msg_close(&bbh);
				zmq_msg_close(&bb_body);
			}

			if (bbp->tk > evp->tk) {
				get_bb = false;
				if (ok_print_err) {
					printf("dropped ev\t%ld %ld %ld\n", bbp->tk, evp->tk, bbp->tk - evp->tk);
					ok_print_err = false;
				}
				zmq_msg_close(&evh);
				zmq_msg_close(&ev_body);
			}

			if (bbp->tk == evp->tk) {	// ie packets are aligned

				ok_print_err = true;

				if (bbp->ns != evp->ns) {
					warn("bb/ev packet sample mismatch");
					break;
				}

				u64 ns  = bbp->ns;

				// xxx incidentally how will we handle multiple (different) currents??!

				auto sc = new u16[ns];
				memcpy(sc, &(ev[g_ec_stim*ns]), ns*sizeof(u16));
				auto cu = new u16[ns];
				memcpy(cu, &(ev[g_ec_current*ns]), ns*sizeof(u16));

				subtr.filter(f, sc, cu, ns);

				delete[] cu;
				delete[] sc;

				zmq_send(socket_out, bbp, nbh, ZMQ_SNDMORE);
				zmq_send(socket_out, f, nb, 0);

				zmq_msg_close(&bbh);
				zmq_msg_close(&evh);
				zmq_msg_close(&bb_body);
				zmq_msg_close(&ev_body);

				get_bb = true;
				get_ev = true;
			}
		}

	}

	subtr.saveWeights("subtr.h5");
	printf("\nsaving weights\n");

	die(zcontext, 0);
}
<commit_msg>subtr should check for uint_max for the stim chan and current chan<commit_after>#include <signal.h>				// for signal, SIGINT
#include <thread>
#include <string>
#include <cstring>
#include <limits.h>
#include <sys/stat.h>
#include <armadillo>
#include <zmq.h>
#include "zmq_packet.h"
#include <basedir.h>
#include <basedir_fs.h>
#include "lconf.h"
#include "util.h"
#include "artifact_subtract.h"

u64 g_ec_stim = UINT_MAX;
u64 g_ec_current = UINT_MAX;
u16 g_current = 0;

bool s_interrupted = false;
std::vector <void *> g_socks;

static void s_signal_handler(int)
{
	s_interrupted = true;
}

static void s_catch_signals(void)
{
	struct sigaction action;
	action.sa_handler = s_signal_handler;
	action.sa_flags = 0;
	sigemptyset(&action.sa_mask);
	sigaction(SIGINT, &action, NULL);
	sigaction(SIGQUIT, &action, NULL);
	sigaction(SIGTERM, &action, NULL);
}

static void die(void *ctx, int status)
{
	s_interrupted = true;
	for (auto &sock : g_socks) {
		zmq_close(sock);
	}
	zmq_ctx_term(ctx);
	exit(status);
}

int main(int argc, char *argv[])
{
	// subtr [zmq_sub_bb] [zmq_sub_ev] [zmq_pub_bb]

	if (argc < 4) {
		printf("\nsubtr - artifact subtraction\n");
		printf("usage: subtr [zmq_sub_bb] [zmq_sub_ev] [zmq_pub]\n\n");
		return 1;
	}

	std::string zbb 	= argv[1];
	std::string zev 	= argv[2];
	std::string zout 	= argv[3];

	debug("ZMQ SUB BROADBAND: %s", zbb.c_str());
	debug("ZMQ SUB EVENTS: %s", zev.c_str());
	debug("ZMQ PUB: %s", zout.c_str());

	s_catch_signals();

	xdgHandle xdg;
	xdgInitHandle(&xdg);
	char *confpath = xdgConfigFind("spk/spk.rc", &xdg);
	char *tmp = confpath;
	// confpath is "string1\0string2\0string3\0\0"

	luaConf conf;

	while (*tmp) {
		conf.loadConf(tmp);
		tmp += strlen(tmp) + 1;
	}
	if (confpath)
		free(confpath);
	xdgWipeHandle(&xdg);

	std::string zq = "ipc:///tmp/query.zmq";
	conf.getString("spk.query_socket", zq);

	void *zcontext = zmq_ctx_new();
	if (zcontext == NULL) {
		error("zmq: could not create context");
		return 1;
	}
	// we don't need 1024 sockets
	if (zmq_ctx_set(zcontext, ZMQ_MAX_SOCKETS, 64) != 0) {
		error("zmq: could not set max sockets");
		die(zcontext, 1);
	}

	void *query_sock = zmq_socket(zcontext, ZMQ_REQ);
	if (query_sock == NULL) {
		error("zmq: could not create socket");
		die(zcontext, 1);
	}
	g_socks.push_back(query_sock);
	if (zmq_connect(query_sock, zq.c_str()) != 0) {
		error("zmq: could not connect to socket");
		die(zcontext, 1);
	}

	u64 nnc; // num neural channels
	zmq_send(query_sock, "NNC", 3, 0);
	if (zmq_recv(query_sock, &nnc, sizeof(u64), 0) == -1) {
		error("zmq: could not recv from query sock");
		die(zcontext, 1);
	}

	u64 nec; // num events channels
	zmq_send(query_sock, "NEC", 3, 0);
	if (zmq_recv(query_sock, &nec, sizeof(u64), 0) == -1) {
		error("zmq: could not recv from query sock");
		die(zcontext, 1);
	}

	// nb we must not assume that the string is null terminated!
	auto is = [](zmq_msg_t *m, const char *c) {
		return strncmp((char *)zmq_msg_data(m), c, zmq_msg_size(m)) == 0;
	};

	for (u64 ch=0; ch<nec; ch++) {
		// EC : X : NAME
		zmq_send(query_sock, "EC", 2, ZMQ_SNDMORE);
		zmq_send(query_sock, &ch, sizeof(u64), ZMQ_SNDMORE);
		zmq_send(query_sock, "NAME", 4, 0);

		zmq_msg_t msg;
		zmq_msg_init(&msg);
		zmq_msg_recv(&msg, query_sock, 0);

		if (is(&msg, "stim")) {
			g_ec_stim = ch;
		}
		if (is(&msg, "current")) {
			g_ec_current = ch;
		}
		zmq_msg_close(&msg);
	}

	// it's implausible that either the stim eventchan or the current eventchan
	// would be the maxuint, so we use it as a sentinel value
	if (g_ec_stim == UINT_MAX || g_ec_current == UINT_MAX) {
		error("no stim or current event definied");
		die(zcontext, 1);
	}

	ArtifactSubtract subtr(16, nnc, 200, 64, 0.99);

	struct stat buf;
	if (stat("subtr.h5", &buf) == 0) { // ie file exists
		printf("loading subtr weights\n");
		subtr.loadWeights("subtr.h5");
	}

	int hwm = 8192;

	// subscribe to broadband messages from the po8e
	void *socket_bb = zmq_socket(zcontext, ZMQ_SUB);
	if (socket_bb == NULL) {
		error("zmq: could not create socket");
		die(zcontext, 1);
	}
	g_socks.push_back(socket_bb);
	zmq_setsockopt(socket_bb, ZMQ_RCVHWM, &hwm, sizeof(hwm));
	if (zmq_connect(socket_bb, zbb.c_str()) != 0) {
		error("zmq: could not connect to socket");
		die(zcontext, 1);
	}
	if (zmq_setsockopt(socket_bb, ZMQ_SUBSCRIBE, "", 0) != 0) {
		error("zmq: could not set socket options");
		die(zcontext, 1);
	}

	// same but for events messages
	void *socket_ev = zmq_socket(zcontext, ZMQ_SUB);
	if (socket_ev == NULL) {
		error("zmq: could not create socket");
		die(zcontext, 1);
	}
	g_socks.push_back(socket_ev);
	zmq_setsockopt(socket_ev, ZMQ_RCVHWM, &hwm, sizeof(hwm));
	if (zmq_connect(socket_ev, zev.c_str()) != 0) {
		error("zmq: could not connect to socket");
		die(zcontext, 1);
	}
	if (zmq_setsockopt(socket_ev, ZMQ_SUBSCRIBE, "", 0) != 0) {
		error("zmq: could not set socket options");
		die(zcontext, 1);
	}

	// publish SA subtracted data with this socket
	void *socket_out = zmq_socket(zcontext, ZMQ_PUB);
	if (socket_out == NULL) {
		error("zmq: could not create socket");
		die(zcontext, 1);
	}
	g_socks.push_back(socket_out);
	zmq_setsockopt(socket_out, ZMQ_SNDHWM, &hwm, sizeof(hwm));
	if (zmq_bind(socket_out, zout.c_str()) != 0) {
		error("zmq: could not bind to socket");
		die(zcontext, 1);
	}

	// init poll set
	zmq_pollitem_t items [] = {
		{ socket_bb, 0, ZMQ_POLLIN, 0 },
		{ socket_ev, 0, ZMQ_POLLIN, 0 }
	};

	zmq_msg_t bbh, evh;
	zmq_msg_t bb_body, ev_body;
	size_t nbh, neh;
	zmq_packet_header *bbp, *evp;
	size_t nb;
	float *f;
	i16 *ev;

	bool get_bb = true;
	bool get_ev = true;

	u64 bbtick_last = 0;
	u64 evtick_last = 0;

	bool ok_print_err = true;

	while (!s_interrupted) {

		if (zmq_poll(items, 2, -1) == -1) { //  -1 means block
			break;
		}

		if (	(items[0].revents & ZMQ_POLLIN || !get_bb) &&
		        (items[1].revents & ZMQ_POLLIN || !get_ev) ) {

			if (get_bb) {
				zmq_msg_init(&bbh);
				zmq_msg_recv(&bbh, socket_bb, 0);
				nbh = zmq_msg_size(&bbh);
				bbp = (zmq_packet_header *)zmq_msg_data(&bbh);

				if (bbp->tk - bbtick_last != bbp->ns && bbtick_last != 0) {
					warn("lost %ld bb samples", bbp->tk - bbtick_last - bbp->ns);
				}
				bbtick_last = bbp->tk;

				zmq_msg_init(&bb_body);
				zmq_msg_recv(&bb_body, socket_bb, 0);
				nb = zmq_msg_size(&bb_body);
				f = (float *)zmq_msg_data(&bb_body);
			}

			if (get_ev) {
				zmq_msg_init(&evh);
				zmq_msg_recv(&evh, socket_ev, 0);
				neh = zmq_msg_size(&evh);
				evp = (zmq_packet_header *)zmq_msg_data(&evh);

				if (evp->tk - evtick_last != evp->ns && evtick_last != 0) {
					warn("lost %ld ev samples", evp->tk - evtick_last - evp->ns);
				}
				evtick_last = evp->tk;

				zmq_msg_init(&ev_body);
				zmq_msg_recv(&ev_body, socket_ev, 0);
				ev = (i16 *)zmq_msg_data(&ev_body);
			}

			if (bbp->tk < evp->tk) {
				get_ev = false;
				if (ok_print_err) {
					printf("dropped bb\t%ld %ld %ld\n", bbp->tk, evp->tk, bbp->tk - evp->tk);
					ok_print_err = false;
				}
				zmq_msg_close(&bbh);
				zmq_msg_close(&bb_body);
			}

			if (bbp->tk > evp->tk) {
				get_bb = false;
				if (ok_print_err) {
					printf("dropped ev\t%ld %ld %ld\n", bbp->tk, evp->tk, bbp->tk - evp->tk);
					ok_print_err = false;
				}
				zmq_msg_close(&evh);
				zmq_msg_close(&ev_body);
			}

			if (bbp->tk == evp->tk) {	// ie packets are aligned

				ok_print_err = true;

				if (bbp->ns != evp->ns) {
					warn("bb/ev packet sample mismatch");
					break;
				}

				u64 ns  = bbp->ns;

				// xxx incidentally how will we handle multiple (different) currents??!

				auto sc = new u16[ns];
				memcpy(sc, &(ev[g_ec_stim*ns]), ns*sizeof(u16));
				auto cu = new u16[ns];
				memcpy(cu, &(ev[g_ec_current*ns]), ns*sizeof(u16));

				subtr.filter(f, sc, cu, ns);

				delete[] cu;
				delete[] sc;

				zmq_send(socket_out, bbp, nbh, ZMQ_SNDMORE);
				zmq_send(socket_out, f, nb, 0);

				zmq_msg_close(&bbh);
				zmq_msg_close(&evh);
				zmq_msg_close(&bb_body);
				zmq_msg_close(&ev_body);

				get_bb = true;
				get_ev = true;
			}
		}

	}

	subtr.saveWeights("subtr.h5");
	printf("\nsaving weights\n");

	die(zcontext, 0);
}
<|endoftext|>


<commit_before>/* Copyright 2015-2016 CyberTech Labs Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * This file was modified by Yurii Litvinov, Aleksei Alekseev and Mikhail Wall to make it comply with the requirements of trikRuntime
 * project. See git revision history for detailed changes. */

#include "gamepadForm.h"

#include "ui_gamepadForm.h"

#include <QtWidgets/QMessageBox>
#include <QtGui/QKeyEvent>

GamepadForm::GamepadForm()
		: QWidget()
		, mUi(new Ui::GamepadForm())
{
	// Here all GUI widgets are created and initialized.
	mUi->setupUi(this);
	this->installEventFilter(this);
	setUpGamepadForm();
}

GamepadForm::~GamepadForm()
{
	// Gracefully disconnecting from host.
	mSocket.disconnectFromHost();
}

void GamepadForm::setUpGamepadForm()
{
	createMenu();
	createTimer();
	createConnection();
	retranslate();
}

void GamepadForm::createConnection()
{
	mMapperPadPressed = new QSignalMapper(this);
	mMapperPadReleased = new QSignalMapper(this);
	mMapperDigitPressed = new QSignalMapper(this);

	mPadHashtable = {
			{mUi->buttonPad1Up, {1, 0, 100}}
			, {mUi->buttonPad1Down, {1, 0, -100}}
			, {mUi->buttonPad1Right, {1, 100, 0}}
			, {mUi->buttonPad1Left, {1, -100, 0}}
			, {mUi->buttonPad2Up, {2, 0, 100}}
			, {mUi->buttonPad2Down, {2, 0, -100}}
			, {mUi->buttonPad2Right, {2, 100 ,0}}
			, {mUi->buttonPad2Left, {2, -100, 0}}
	};

	for (auto button : mPadHashtable.keys()) {
		connect(button, SIGNAL(pressed()), mMapperPadPressed, SLOT(map()));
		mMapperPadPressed->setMapping(button, button);
		connect(button, SIGNAL(released()), mMapperPadReleased, SLOT(map()));
		mMapperPadReleased->setMapping(button, button);
	}

	connect(mMapperPadPressed, SIGNAL(mapped(QWidget *)), this, SLOT(handlePadPress(QWidget*)));
	connect(mMapperPadReleased, SIGNAL(mapped(QWidget *)), this, SLOT(handlePadRelease(QWidget*)));

	mDigitHashtable = {
			{mUi->button1, 1}
			, {mUi->button2, 2}
			, {mUi->button3, 3}
			, {mUi->button4, 4}
			, {mUi->button5, 5}
	};

	for (auto button : mDigitHashtable.keys()) {
		connect(button, SIGNAL(pressed()), mMapperDigitPressed, SLOT(map()));
		mMapperDigitPressed->setMapping(button, button);
	}

	connect(mMapperDigitPressed, SIGNAL(mapped(QWidget *)), this, SLOT(handleDigitPress(QWidget*)));

}

void GamepadForm::createMenu()
{
	// Path to your local directory. Set up if you don't put .qm files into your debug folder.
	const QString pathToDir = "languages/trikDesktopGamepad";

	const QString russian = pathToDir + "_ru";
	const QString english = pathToDir + "_en";
	const QString french = pathToDir + "_fr";
	const QString german = pathToDir + "_de";

	mMenuBar = new QMenuBar(this);

	mConnectionMenu = new QMenu(this);
	mMenuBar->addMenu(mConnectionMenu);

	mLanguageMenu=  new QMenu(this);
	mMenuBar->addMenu(mLanguageMenu);

	mConnectAction = new QAction(this);
	// Set to QKeySequence for Ctrl+N shortcut
	mConnectAction->setShortcuts(QKeySequence::New);
	connect(mConnectAction, &QAction::triggered, this, &GamepadForm::openConnectDialog);

	mExitAction = new QAction(this);
	mExitAction->setShortcuts(QKeySequence::Quit);
	connect(mExitAction, &QAction::triggered, this, &GamepadForm::exit);

	mRussianLanguageAction = new QAction(this);
	mEnglishLanguageAction = new QAction(this);
	mFrenchLanguageAction = new QAction(this);
	mGermanLanguageAction = new QAction(this);

	mLanguages = new QActionGroup(this);
	mLanguages->addAction(mRussianLanguageAction);
	mLanguages->addAction(mEnglishLanguageAction);
	mLanguages->addAction(mFrenchLanguageAction);
	mLanguages->addAction(mGermanLanguageAction);
	mLanguages->setExclusive(true);

	// Set up language actions checkable
	mEnglishLanguageAction->setCheckable(true);
	mRussianLanguageAction->setCheckable(true);
	mFrenchLanguageAction->setCheckable(true);
	mGermanLanguageAction->setCheckable(true);
	mEnglishLanguageAction->setChecked(true);

	// Connecting languages to menu items
	connect(mRussianLanguageAction, &QAction::triggered, this, [this, russian](){changeLanguage(russian);});
	connect(mEnglishLanguageAction, &QAction::triggered, this, [this, english](){changeLanguage(english);});
	connect(mFrenchLanguageAction, &QAction::triggered, this, [this, french](){changeLanguage(french);});
	connect(mGermanLanguageAction, &QAction::triggered, this, [this, german](){changeLanguage(german);});

	mAboutAction = new QAction(this);
	connect(mAboutAction, &QAction::triggered, this, &GamepadForm::about);

	mConnectionMenu->addAction(mConnectAction);
	mConnectionMenu->addAction(mExitAction);

	mLanguageMenu->addAction(mRussianLanguageAction);
	mLanguageMenu->addAction(mEnglishLanguageAction);
	mLanguageMenu->addAction(mFrenchLanguageAction);
	mLanguageMenu->addAction(mGermanLanguageAction);

	mMenuBar->addAction(mAboutAction);

	this->layout()->setMenuBar(mMenuBar);
}

void GamepadForm::createTimer()
{
	connect(&mTimer, &QTimer::timeout, this, &GamepadForm::checkConnection);
	mTimer.start(1000);
}

void GamepadForm::checkConnection()
{
	const QString successfulConnection = tr("Connected.\nButtons enabled.");
	const QString unsuccessfulConnection = tr("Disconnected.\nButtons disabled.");
	const QString colorRed = "QLabel {color : red; }";
	const QString colorGreen = "QLabel {color : green; }";

	if (mSocket.state() != QTcpSocket::ConnectedState) {
		mUi->connection->setText(unsuccessfulConnection);
		mUi->connection->setStyleSheet(colorRed);
		setButtonsEnabled(false);
	} else {
		mUi->connection->setText(successfulConnection);
		mUi->connection->setStyleSheet(colorGreen);
		setButtonsEnabled(true);
	}
}

void GamepadForm::setButtonsEnabled(bool enabled)
{
	// Here we enable or disable pads and "magic buttons" depending on given parameter.
	mUi->button1->setEnabled(enabled);
	mUi->button2->setEnabled(enabled);
	mUi->button3->setEnabled(enabled);
	mUi->button4->setEnabled(enabled);
	mUi->button5->setEnabled(enabled);

	mUi->buttonPad1Left->setEnabled(enabled);
	mUi->buttonPad1Right->setEnabled(enabled);
	mUi->buttonPad1Up->setEnabled(enabled);
	mUi->buttonPad1Down->setEnabled(enabled);

	mUi->buttonPad2Left->setEnabled(enabled);
	mUi->buttonPad2Right->setEnabled(enabled);
	mUi->buttonPad2Up->setEnabled(enabled);
	mUi->buttonPad2Down->setEnabled(enabled);
}

bool GamepadForm::eventFilter(QObject *obj, QEvent *event)
{
	Q_UNUSED(obj)

	int resultingPowerX1 = 0;
	int resultingPowerY1 = 0;
	int resultingPowerX2 = 0;
	int resultingPowerY2 = 0;

	// Handle key press event
	if(event->type() == QEvent::KeyPress) {

		// Handle W A S D buttons
		// Handle arrow buttons

		if (resultingPowerX1 != 0 || resultingPowerY1 != 0) {
			onPadPressed(QString("pad 1 %1 %2").arg(resultingPowerX1).arg(resultingPowerY1));
		} else if (resultingPowerX2 != 0 || resultingPowerY2 != 0) {
			onPadPressed(QString("pad 2 %1 %2").arg(resultingPowerX2).arg(resultingPowerY2));
		}

		// Handle 1 2 3 4 5 buttons
		QMap<int, QPushButton *> digits = {
				{Qt::Key_1, mUi->button1}
		};

		for (auto key : digits.keys()) {
				digits[key]->pressed();
			}
		}
	} else if(event->type() == QEvent::KeyRelease) {

		// Handle key release event
		QSet<int> pad1 = {Qt::Key_W, Qt::Key_A, Qt::Key_S, Qt::Key_D};
		QSet<int> pad2 = {Qt::Key_Left, Qt::Key_Right, Qt::Key_Up, Qt::Key_Down};

		auto releasedKey = ((QKeyEvent*) event)->key();

		if (pad1.contains(releasedKey)) {
			onPadReleased(1);
		} else if (pad2.contains(releasedKey)){
			onPadReleased(2);
		}
	}

	return false;
}

void GamepadForm::onButtonPressed(int buttonId)
{
	// Checking that we are still connected, just in case.
	if (mSocket.state() != QTcpSocket::ConnectedState) {
		return;
	}

	// Sending "btn <buttonId>" command to robot.
	if (mSocket.write(QString("btn %1\n").arg(buttonId).toLatin1()) == -1) {
		// If sending failed for some reason, we think that we lost connection and disable buttons.
		setButtonsEnabled(false);
	}
}

void GamepadForm::onPadPressed(const QString &action)
{
	// Here we send "pad <padId> <x> <y>" command.
	if (mSocket.state() != QTcpSocket::ConnectedState) {
		return;
	}

	if (mSocket.write((action + "\n").toLatin1()) == -1) {
		setButtonsEnabled(false);
	}
}

void GamepadForm::onPadReleased(int padId)
{
	// Here we send "pad <padId> up" command.
	if (mSocket.state() != QTcpSocket::ConnectedState) {
		return;
	}

	if (mSocket.write(QString("pad %1 up\n").arg(padId).toLatin1()) == -1) {
		setButtonsEnabled(false);
	}
}

void GamepadForm::openConnectDialog()
{
	mMyNewConnectForm = new ConnectForm(&mSocket);
	mMyNewConnectForm->show();
}

void GamepadForm::exit()
{
	qApp->exit();
}

void GamepadForm::changeEvent(QEvent *event)
{
	if (event->type() == QEvent::LanguageChange)
	{
		mUi->retranslateUi(this);

		retranslate();
	}

	QWidget::changeEvent(event);
}

void GamepadForm::handlePadRelease(QWidget *w)
{
	onPadReleased(mPadHashtable[w][0]);
}

void GamepadForm::handlePadPress(QWidget *w)
{
	auto vec = mPadHashtable[w];
	onPadPressed(QString("pad %1 %2 %3").arg(vec[0]).arg(vec[1]).arg(vec[2]));
}

void GamepadForm::handleDigitPress(QWidget *w)
{
	onButtonPressed(mDigitHashtable[w]);
}

void GamepadForm::retranslate()
{
	mConnectionMenu->setTitle(tr("&Connection"));
	mLanguageMenu->setTitle(tr("&Language"));
	mConnectAction->setText(tr("&Connect"));
	mExitAction->setText(tr("&Exit"));

	mRussianLanguageAction->setText(tr("&Russian"));
	mEnglishLanguageAction->setText(tr("&English"));
	mFrenchLanguageAction->setText(tr("&French"));
	mGermanLanguageAction->setText(tr("&German"));

	mAboutAction->setText(tr("&About"));

}

void GamepadForm::changeLanguage(const QString &language)
{
	mTranslator = new QTranslator(this);
	mTranslator->load(language);
	qApp->installTranslator(mTranslator);

	mUi->retranslateUi(this);
}

void GamepadForm::about()
{
	const QString title = tr("About TRIK Gamepad");
	const QString about =  tr("TRIK Gamepad 1.1.2\n\nThis is desktop gamepad for TRIK robots.");
	QMessageBox::about(this, title, about);
}
<commit_msg>Rewriting using another method<commit_after>/* Copyright 2015-2016 CyberTech Labs Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * This file was modified by Yurii Litvinov, Aleksei Alekseev and Mikhail Wall to make it comply with the requirements of trikRuntime
 * project. See git revision history for detailed changes. */

#include "gamepadForm.h"

#include "ui_gamepadForm.h"

#include <QtWidgets/QMessageBox>
#include <QtGui/QKeyEvent>

GamepadForm::GamepadForm()
		: QWidget()
		, mUi(new Ui::GamepadForm())
{
	// Here all GUI widgets are created and initialized.
	mUi->setupUi(this);
	this->installEventFilter(this);
	setUpGamepadForm();
}

GamepadForm::~GamepadForm()
{
	// Gracefully disconnecting from host.
	mSocket.disconnectFromHost();
}

void GamepadForm::setUpGamepadForm()
{
	createMenu();
	createTimer();
	createConnection();
	retranslate();
}

void GamepadForm::createConnection()
{
	mMapperPadPressed = new QSignalMapper(this);
	mMapperPadReleased = new QSignalMapper(this);
	mMapperDigitPressed = new QSignalMapper(this);

	mPadHashtable = {
			{mUi->buttonPad1Up, {1, 0, 100}}
			, {mUi->buttonPad1Down, {1, 0, -100}}
			, {mUi->buttonPad1Right, {1, 100, 0}}
			, {mUi->buttonPad1Left, {1, -100, 0}}
			, {mUi->buttonPad2Up, {2, 0, 100}}
			, {mUi->buttonPad2Down, {2, 0, -100}}
			, {mUi->buttonPad2Right, {2, 100 ,0}}
			, {mUi->buttonPad2Left, {2, -100, 0}}
	};

	for (auto button : mPadHashtable.keys()) {
		connect(button, SIGNAL(pressed()), mMapperPadPressed, SLOT(map()));
		mMapperPadPressed->setMapping(button, button);
		connect(button, SIGNAL(released()), mMapperPadReleased, SLOT(map()));
		mMapperPadReleased->setMapping(button, button);
	}

	connect(mMapperPadPressed, SIGNAL(mapped(QWidget *)), this, SLOT(handlePadPress(QWidget*)));
	connect(mMapperPadReleased, SIGNAL(mapped(QWidget *)), this, SLOT(handlePadRelease(QWidget*)));

	mDigitHashtable = {
			{mUi->button1, 1}
			, {mUi->button2, 2}
			, {mUi->button3, 3}
			, {mUi->button4, 4}
			, {mUi->button5, 5}
	};

	for (auto button : mDigitHashtable.keys()) {
		connect(button, SIGNAL(pressed()), mMapperDigitPressed, SLOT(map()));
		mMapperDigitPressed->setMapping(button, button);
	}

	connect(mMapperDigitPressed, SIGNAL(mapped(QWidget *)), this, SLOT(handleDigitPress(QWidget*)));

}

void GamepadForm::createMenu()
{
	// Path to your local directory. Set up if you don't put .qm files into your debug folder.
	const QString pathToDir = "languages/trikDesktopGamepad";

	const QString russian = pathToDir + "_ru";
	const QString english = pathToDir + "_en";
	const QString french = pathToDir + "_fr";
	const QString german = pathToDir + "_de";

	mMenuBar = new QMenuBar(this);

	mConnectionMenu = new QMenu(this);
	mMenuBar->addMenu(mConnectionMenu);

	mLanguageMenu=  new QMenu(this);
	mMenuBar->addMenu(mLanguageMenu);

	mConnectAction = new QAction(this);
	// Set to QKeySequence for Ctrl+N shortcut
	mConnectAction->setShortcuts(QKeySequence::New);
	connect(mConnectAction, &QAction::triggered, this, &GamepadForm::openConnectDialog);

	mExitAction = new QAction(this);
	mExitAction->setShortcuts(QKeySequence::Quit);
	connect(mExitAction, &QAction::triggered, this, &GamepadForm::exit);

	mRussianLanguageAction = new QAction(this);
	mEnglishLanguageAction = new QAction(this);
	mFrenchLanguageAction = new QAction(this);
	mGermanLanguageAction = new QAction(this);

	mLanguages = new QActionGroup(this);
	mLanguages->addAction(mRussianLanguageAction);
	mLanguages->addAction(mEnglishLanguageAction);
	mLanguages->addAction(mFrenchLanguageAction);
	mLanguages->addAction(mGermanLanguageAction);
	mLanguages->setExclusive(true);

	// Set up language actions checkable
	mEnglishLanguageAction->setCheckable(true);
	mRussianLanguageAction->setCheckable(true);
	mFrenchLanguageAction->setCheckable(true);
	mGermanLanguageAction->setCheckable(true);
	mEnglishLanguageAction->setChecked(true);

	// Connecting languages to menu items
	connect(mRussianLanguageAction, &QAction::triggered, this, [this, russian](){changeLanguage(russian);});
	connect(mEnglishLanguageAction, &QAction::triggered, this, [this, english](){changeLanguage(english);});
	connect(mFrenchLanguageAction, &QAction::triggered, this, [this, french](){changeLanguage(french);});
	connect(mGermanLanguageAction, &QAction::triggered, this, [this, german](){changeLanguage(german);});

	mAboutAction = new QAction(this);
	connect(mAboutAction, &QAction::triggered, this, &GamepadForm::about);

	mConnectionMenu->addAction(mConnectAction);
	mConnectionMenu->addAction(mExitAction);

	mLanguageMenu->addAction(mRussianLanguageAction);
	mLanguageMenu->addAction(mEnglishLanguageAction);
	mLanguageMenu->addAction(mFrenchLanguageAction);
	mLanguageMenu->addAction(mGermanLanguageAction);

	mMenuBar->addAction(mAboutAction);

	this->layout()->setMenuBar(mMenuBar);
}

void GamepadForm::createTimer()
{
	connect(&mTimer, &QTimer::timeout, this, &GamepadForm::checkConnection);
	mTimer.start(1000);
}

void GamepadForm::checkConnection()
{
	const QString successfulConnection = tr("Connected.\nButtons enabled.");
	const QString unsuccessfulConnection = tr("Disconnected.\nButtons disabled.");
	const QString colorRed = "QLabel {color : red; }";
	const QString colorGreen = "QLabel {color : green; }";

	if (mSocket.state() != QTcpSocket::ConnectedState) {
		mUi->connection->setText(unsuccessfulConnection);
		mUi->connection->setStyleSheet(colorRed);
		setButtonsEnabled(false);
	} else {
		mUi->connection->setText(successfulConnection);
		mUi->connection->setStyleSheet(colorGreen);
		setButtonsEnabled(true);
	}
}

void GamepadForm::setButtonsEnabled(bool enabled)
{
	// Here we enable or disable pads and "magic buttons" depending on given parameter.
	mUi->button1->setEnabled(enabled);
	mUi->button2->setEnabled(enabled);
	mUi->button3->setEnabled(enabled);
	mUi->button4->setEnabled(enabled);
	mUi->button5->setEnabled(enabled);

	mUi->buttonPad1Left->setEnabled(enabled);
	mUi->buttonPad1Right->setEnabled(enabled);
	mUi->buttonPad1Up->setEnabled(enabled);
	mUi->buttonPad1Down->setEnabled(enabled);

	mUi->buttonPad2Left->setEnabled(enabled);
	mUi->buttonPad2Right->setEnabled(enabled);
	mUi->buttonPad2Up->setEnabled(enabled);
	mUi->buttonPad2Down->setEnabled(enabled);
}

bool GamepadForm::eventFilter(QObject *obj, QEvent *event)
{
	Q_UNUSED(obj)

	int resultingPowerX1 = 0;
	int resultingPowerY1 = 0;
	int resultingPowerX2 = 0;
	int resultingPowerY2 = 0;

	// Handle key press event
	if(event->type() == QEvent::KeyPress) {

		mPressedKeys += ((QKeyEvent*) event)->key();

		// Handle W A S D buttons
		resultingPowerX1 = (mPressedKeys.contains(Qt::Key_D) ? 100 : 0) + (mPressedKeys.contains(Qt::Key_A) ? -100 : 0);
		resultingPowerY1 = (mPressedKeys.contains(Qt::Key_S) ? -100 : 0) + (mPressedKeys.contains(Qt::Key_W) ? 100 : 0);
		// Handle arrow buttons
		resultingPowerX2 = (mPressedKeys.contains(Qt::Key_Right) ? 100 : 0) + (mPressedKeys.contains(Qt::Key_Left) ? -100 : 0);
		resultingPowerY2 = (mPressedKeys.contains(Qt::Key_Down) ? -100 : 0) + (mPressedKeys.contains(Qt::Key_Up) ? 100 : 0);

		if (resultingPowerX1 != 0 || resultingPowerY1 != 0) {
			onPadPressed(QString("pad 1 %1 %2").arg(resultingPowerX1).arg(resultingPowerY1));
		} else if (resultingPowerX2 != 0 || resultingPowerY2 != 0) {
			onPadPressed(QString("pad 2 %1 %2").arg(resultingPowerX2).arg(resultingPowerY2));
		}

		// Handle 1 2 3 4 5 buttons
		QMap<int, QPushButton *> digits = {
				{Qt::Key_1, mUi->button1}
				, {Qt::Key_2, mUi->button2}
				, {Qt::Key_3, mUi->button3}
				, {Qt::Key_4, mUi->button4}
				, {Qt::Key_5, mUi->button5}
		};

		for (auto key : digits.keys()) {
			if (mPressedKeys.contains(key)) {
				digits[key]->pressed();
			}
		}
	} else if(event->type() == QEvent::KeyRelease) {

		// Handle key release event
		QSet<int> pad1 = {Qt::Key_W, Qt::Key_A, Qt::Key_S, Qt::Key_D};
		QSet<int> pad2 = {Qt::Key_Left, Qt::Key_Right, Qt::Key_Up, Qt::Key_Down};

		auto releasedKey = ((QKeyEvent*) event)->key();
		mPressedKeys -= releasedKey;

		if (pad1.contains(releasedKey)) {
			onPadReleased(1);
		} else if (pad2.contains(releasedKey)){
			onPadReleased(2);
		}
	}

	return false;
}

void GamepadForm::onButtonPressed(int buttonId)
{
	// Checking that we are still connected, just in case.
	if (mSocket.state() != QTcpSocket::ConnectedState) {
		return;
	}

	// Sending "btn <buttonId>" command to robot.
	if (mSocket.write(QString("btn %1\n").arg(buttonId).toLatin1()) == -1) {
		// If sending failed for some reason, we think that we lost connection and disable buttons.
		setButtonsEnabled(false);
	}
}

void GamepadForm::onPadPressed(const QString &action)
{
	// Here we send "pad <padId> <x> <y>" command.
	if (mSocket.state() != QTcpSocket::ConnectedState) {
		return;
	}

	if (mSocket.write((action + "\n").toLatin1()) == -1) {
		setButtonsEnabled(false);
	}
}

void GamepadForm::onPadReleased(int padId)
{
	// Here we send "pad <padId> up" command.
	if (mSocket.state() != QTcpSocket::ConnectedState) {
		return;
	}

	if (mSocket.write(QString("pad %1 up\n").arg(padId).toLatin1()) == -1) {
		setButtonsEnabled(false);
	}
}

void GamepadForm::openConnectDialog()
{
	mMyNewConnectForm = new ConnectForm(&mSocket);
	mMyNewConnectForm->show();
}

void GamepadForm::exit()
{
	qApp->exit();
}

void GamepadForm::changeEvent(QEvent *event)
{
	if (event->type() == QEvent::LanguageChange)
	{
		mUi->retranslateUi(this);

		retranslate();
	}

	QWidget::changeEvent(event);
}

void GamepadForm::handlePadRelease(QWidget *w)
{
	onPadReleased(mPadHashtable[w][0]);
}

void GamepadForm::handlePadPress(QWidget *w)
{
	auto vec = mPadHashtable[w];
	onPadPressed(QString("pad %1 %2 %3").arg(vec[0]).arg(vec[1]).arg(vec[2]));
}

void GamepadForm::handleDigitPress(QWidget *w)
{
	onButtonPressed(mDigitHashtable[w]);
}

void GamepadForm::retranslate()
{
	mConnectionMenu->setTitle(tr("&Connection"));
	mLanguageMenu->setTitle(tr("&Language"));
	mConnectAction->setText(tr("&Connect"));
	mExitAction->setText(tr("&Exit"));

	mRussianLanguageAction->setText(tr("&Russian"));
	mEnglishLanguageAction->setText(tr("&English"));
	mFrenchLanguageAction->setText(tr("&French"));
	mGermanLanguageAction->setText(tr("&German"));

	mAboutAction->setText(tr("&About"));

}

void GamepadForm::changeLanguage(const QString &language)
{
	mTranslator = new QTranslator(this);
	mTranslator->load(language);
	qApp->installTranslator(mTranslator);

	mUi->retranslateUi(this);
}

void GamepadForm::about()
{
	const QString title = tr("About TRIK Gamepad");
	const QString about =  tr("TRIK Gamepad 1.1.2\n\nThis is desktop gamepad for TRIK robots.");
	QMessageBox::about(this, title, about);
}
<|endoftext|>


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

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

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct SynthCoolrunner2Pass : public ScriptPass
{
	SynthCoolrunner2Pass() : ScriptPass("synth_coolrunner2", "synthesis for Xilinx Coolrunner-II CPLDs") { }

	virtual void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    synth_coolrunner2 [options]\n");
		log("\n");
		log("This command runs synthesis for Coolrunner-II CPLDs. This work is experimental.\n");
		log("It is intended to be used with https://github.com/azonenberg/openfpga as the\n");
		log("place-and-route.\n");
		log("\n");
		log("    -top <module>\n");
		log("        use the specified module as top module (default='top')\n");
		log("\n");
		log("    -json <file>\n");
		log("        write the design to the specified JSON file. writing of an output file\n");
		log("        is omitted if this parameter is not specified.\n");
		log("\n");
		log("    -run <from_label>:<to_label>\n");
		log("        only run the commands between the labels (see below). an empty\n");
		log("        from label is synonymous to 'begin', and empty to label is\n");
		log("        synonymous to the end of the command list.\n");
		log("\n");
		log("    -noflatten\n");
		log("        do not flatten design before synthesis\n");
		log("\n");
		log("    -retime\n");
		log("        run 'abc' with -dff option\n");
		log("\n");
		log("\n");
		log("The following commands are executed by this synthesis command:\n");
		help_script();
		log("\n");
	}

	string top_opt, json_file;
	bool flatten, retime;

	virtual void clear_flags() YS_OVERRIDE
	{
		top_opt = "-auto-top";
		json_file = "";
		flatten = true;
		retime = false;
	}

	virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		string run_from, run_to;
		clear_flags();

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			if (args[argidx] == "-top" && argidx+1 < args.size()) {
				top_opt = "-top " + args[++argidx];
				continue;
			}
			if (args[argidx] == "-json" && argidx+1 < args.size()) {
				json_file = args[++argidx];
				continue;
			}
			if (args[argidx] == "-run" && argidx+1 < args.size()) {
				size_t pos = args[argidx+1].find(':');
				if (pos == std::string::npos)
					break;
				run_from = args[++argidx].substr(0, pos);
				run_to = args[argidx].substr(pos+1);
				continue;
			}
			if (args[argidx] == "-noflatten") {
				flatten = false;
				continue;
			}
			if (args[argidx] == "-retime") {
				retime = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

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

		log_header(design, "Executing SYNTH_COOLRUNNER2 pass.\n");
		log_push();

		run_script(design, run_from, run_to);

		log_pop();
	}

	virtual void script() YS_OVERRIDE
	{
		if (check_label("begin"))
		{
			run("read_verilog -lib +/coolrunner2/cells_sim.v");
			run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
		}

		if (check_label("flatten", "(unless -noflatten)") && flatten)
		{
			run("proc");
			run("flatten");
			run("tribuf -logic");
		}

		if (check_label("coarse"))
		{
			run("synth -run coarse");
		}

		if (check_label("fine"))
		{
			run("opt -fast -full");
			run("techmap");
			run("techmap -map +/coolrunner2/cells_latch.v");
			run("dfflibmap -prepare -liberty +/coolrunner2/xc2_dff.lib");
		}

		if (check_label("map_pla"))
		{
			run("abc -sop -I 40 -P 56");
			run("coolrunner2_sop");
			run("opt -fast");
		}

		if (check_label("map_cells"))
		{
			run("dfflibmap -liberty +/coolrunner2/xc2_dff.lib");
			run("dffinit -ff FDCP Q INIT");
			run("dffinit -ff FDCP_N Q INIT");
			run("dffinit -ff LDCP Q INIT");
			run("dffinit -ff LDCP_N Q INIT");
			run("iopadmap -bits -inpad IBUF O:I -outpad IOBUFE I:IO -inoutpad IOBUFE O:IO -toutpad IOBUFE E:I:IO -tinoutpad IOBUFE E:O:I:IO");
		}

		if (check_label("check"))
		{
			run("hierarchy -check");
			run("stat");
			run("check -noinit");
		}

		if (check_label("json"))
		{
			if (!json_file.empty() || help_mode)
				run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
		}

		log_pop();
	}
} SynthCoolrunner2Pass;

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

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

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct SynthCoolrunner2Pass : public ScriptPass
{
	SynthCoolrunner2Pass() : ScriptPass("synth_coolrunner2", "synthesis for Xilinx Coolrunner-II CPLDs") { }

	virtual void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    synth_coolrunner2 [options]\n");
		log("\n");
		log("This command runs synthesis for Coolrunner-II CPLDs. This work is experimental.\n");
		log("It is intended to be used with https://github.com/azonenberg/openfpga as the\n");
		log("place-and-route.\n");
		log("\n");
		log("    -top <module>\n");
		log("        use the specified module as top module (default='top')\n");
		log("\n");
		log("    -json <file>\n");
		log("        write the design to the specified JSON file. writing of an output file\n");
		log("        is omitted if this parameter is not specified.\n");
		log("\n");
		log("    -run <from_label>:<to_label>\n");
		log("        only run the commands between the labels (see below). an empty\n");
		log("        from label is synonymous to 'begin', and empty to label is\n");
		log("        synonymous to the end of the command list.\n");
		log("\n");
		log("    -noflatten\n");
		log("        do not flatten design before synthesis\n");
		log("\n");
		log("    -retime\n");
		log("        run 'abc' with -dff option\n");
		log("\n");
		log("\n");
		log("The following commands are executed by this synthesis command:\n");
		help_script();
		log("\n");
	}

	string top_opt, json_file;
	bool flatten, retime;

	virtual void clear_flags() YS_OVERRIDE
	{
		top_opt = "-auto-top";
		json_file = "";
		flatten = true;
		retime = false;
	}

	virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		string run_from, run_to;
		clear_flags();

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			if (args[argidx] == "-top" && argidx+1 < args.size()) {
				top_opt = "-top " + args[++argidx];
				continue;
			}
			if (args[argidx] == "-json" && argidx+1 < args.size()) {
				json_file = args[++argidx];
				continue;
			}
			if (args[argidx] == "-run" && argidx+1 < args.size()) {
				size_t pos = args[argidx+1].find(':');
				if (pos == std::string::npos)
					break;
				run_from = args[++argidx].substr(0, pos);
				run_to = args[argidx].substr(pos+1);
				continue;
			}
			if (args[argidx] == "-noflatten") {
				flatten = false;
				continue;
			}
			if (args[argidx] == "-retime") {
				retime = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

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

		log_header(design, "Executing SYNTH_COOLRUNNER2 pass.\n");
		log_push();

		run_script(design, run_from, run_to);

		log_pop();
	}

	virtual void script() YS_OVERRIDE
	{
		if (check_label("begin"))
		{
			run("read_verilog -lib +/coolrunner2/cells_sim.v");
			run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
		}

		if (check_label("flatten", "(unless -noflatten)") && flatten)
		{
			run("proc");
			run("flatten");
			run("tribuf -logic");
		}

		if (check_label("coarse"))
		{
			run("synth -run coarse");
		}

		if (check_label("fine"))
		{
			run("opt -fast -full");
			run("techmap");
			run("techmap -map +/coolrunner2/cells_latch.v");
			run("dfflibmap -prepare -liberty +/coolrunner2/xc2_dff.lib");
		}

		if (check_label("map_pla"))
		{
			run("abc -sop -I 40 -P 56");
			run("coolrunner2_sop");
		}

		if (check_label("map_cells"))
		{
			run("dfflibmap -liberty +/coolrunner2/xc2_dff.lib");
			run("dffinit -ff FDCP Q INIT");
			run("dffinit -ff FDCP_N Q INIT");
			run("dffinit -ff LDCP Q INIT");
			run("dffinit -ff LDCP_N Q INIT");
			run("iopadmap -bits -inpad IBUF O:I -outpad IOBUFE I:IO -inoutpad IOBUFE O:IO -toutpad IOBUFE E:I:IO -tinoutpad IOBUFE E:O:I:IO");
		}

		if (check_label("check"))
		{
			run("hierarchy -check");
			run("stat");
			run("check -noinit");
		}

		if (check_label("json"))
		{
			if (!json_file.empty() || help_mode)
				run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
		}

		log_pop();
	}
} SynthCoolrunner2Pass;

PRIVATE_NAMESPACE_END
<|endoftext|>


<commit_before>/*-------------------------------
PASA LA CALCULADORA
Autores:
Jaime Sevilla Molina
Victor Gonzalez
Fecha
2014/11
Version: 2.0
---------------------------------*/

//BIBLIOTECAS
#include <iostream>
#include <cstdlib>
#include <string>
#include <ctime>
#include <fstream>
#include <iomanip>

using namespace std;

//TIPOS PROPIOS
typedef enum tJugador
{
	Nadie,
	Jugador,
	Automata
};

//FUNCIONES
//FUNCIONES DE JUEGO

string saludar ();

//Dependiendo de quien gane, la despedida sera distinta
int despedirse (tJugador ganador, string nombre);

//Muestra un menu que permite al jugador jugar, salir, o ver las reglas del juego
int menu();

//Muestra las instrucciones del juego, siempre que su archivo no contenga errores
bool acerca();

//Anota el numero de partidas ganadas y perdidas del jugador
bool stats(int ganadas, int perdidas);

//Conduce el desarrollo del juego y devuelve el ganador.
//Si se abandona, devuelve Nadie.
tJugador pasaCalculadora();

//Decide aleatoriamente quien empieza.
tJugador quienEmpieza();

//Devuelve true si nuevo esta en la misma fila que ultimo
bool mismaFila(int ultimo, int nuevo);

//Devuelve true si nuevo esta en la misma columna que ultimo
bool mismaColumna(int ultimo, int nuevo);

//Devuelve true si nuevo cumple las reglas del juego con respecto a ultimo
//Si ultimo == 0, este es el primer digito de la partida, y devuelve true
bool digitoValido(int ultimo, int nuevo);

//FUNCIONES DE IA NIVEL 1
//Devuelve un digito del 1 al 9
int digitoAleatorio();

//Devuelve un digito que cumpla las reglas del juego con respecto a ultimo.
int digitoAutomata(int ultimo);

//FUNCIONES DE JUGADOR
//Pide un digito al jugador. Solo devolvera un valor valido (entre 0 y 9).
//Para un valor no valido, mostrara un error.
int digitoPersona();

//Pide un digito al jugador mostrando el teclado. Solo devolvera un valor
//que cumpla las reglas del juego o 0. Para un valor no valido, mostrara un error.
int digitoPersona(int ultimo);

//Determina si el numero de la calculadora se muestra o no, en funcion de si es valido
char mNumero(int ultimo, int n);

//Muestra los botones de la calculadora (solo los que se pueden pulsar en cada turno)
void mostrarCalculadora(int ultimo);

/* Las funciones a continuacion se implementaran en un futuro
//FUNCIONES DE INFORME
//Actualiza el archivo informePC.txt con los tres argumentos. En caso de no encontrar
//el archivo, lo crea y devuelve false; en otro caso devuelve true.
bool actInforme(int jugadas, int ganadas, int abandonos);

//FUNCIONES DE DIFICULTAD AVANZADA
int botDificil(int ultimo);

-----------------------------------------------------------------------------------*/

int main()
{
	tJugador ganador;
	int opcion;

	string nombre = saludar();
	//Bucle Menu
	do
	{
		opcion = menu();
		if(opcion == 1){
			ganador = pasaCalculadora();
			despedirse(ganador, nombre);
		}
		else if(opcion == 2) acerca();

	}
	while(opcion != 0);

	cout << "Hasta la proxima " << nombre << "(pulsa enter)";
	cin;

	return 0;
}

//Saluda al jugador y le pregunta su nombre
string saludar()
{
	string nombre;
	cout << "Bienvenido a Pasa la calculadora!" << endl;
	cout << "Como te llamas? ";
	cin >> nombre;
	cout << "Hola " << nombre << endl << endl;
	return nombre;
}

//Se despide del jugador, la despedida varia segun gane el jugador, el automata o ninguno de ellos (el jugador abandone)
int despedirse(tJugador ganador, string nombre)
{
	int ganadas = 0, perdidas = 0;
	if (ganador == Nadie){
		cout << "Abandonas, " << nombre << "? Ohhh..." << endl << endl;
	}
	else if (ganador == Jugador){
		cout << "Enhorabuena " << nombre << ", has ganado!" << endl << endl;
		ganadas = ganadas++;
	}
	else /*if (ganador == Automata)*/{
		cout << "Lo siento " << nombre << ", he ganado" << endl << endl;
		perdidas = perdidas++;
	}
	return ganadas, perdidas;
}

//Proporciona al jugador la posibilidad de jugar, ver las instrucciones del juego o salir.
int menu()
{
	int seleccionar = -1; //Error flag
	cout << "1 - Jugar" << endl;
	cout << "2 - Acerca de" << endl;
	cout << "0 - Salir" << endl;

	do
	{
		cin.sync(); //Por si quedan datos basura en el buffer
		cin >> seleccionar;

		if(cin.fail())
		{
			cout << "Error! Introduce un digito" << endl;
			cin.clear();
		}

		else if (seleccionar < 0 || seleccionar > 2)
		{
			cout << "Error! Introduce un digito entre 0 y 2" << endl;
			seleccionar = -1;
		}

	}
	while (seleccionar == -1);

	return seleccionar;
}

//Muestra el archivo "acerca.txt" siempre que este no contenga errores
bool acerca()
{

	bool ok;
	ifstream acerca;
	char c;

	acerca.open("acerca.txt");

	if(acerca.is_open())
	{
		acerca.get(c); //Lee el primer caracter

		while(!acerca.fail()) //Mientras la lectura no falle
		{
			cout << c;
			acerca.get(c); //Lee el siguiente caracter
		}

		ok = true;
		acerca.close();

	}
	else
	{
		ok = false;
		cout << "Error, el archivo 'acerca.txt' no existe" << endl;
	}

	return ok;
}

bool stats(int ganadas, int perdidas)
{

	bool ok;
	ofstream stats;

	stats.open("stats.txt");

	if(stats.is_open())
	{
		stats << "Partidas Jugadas: " << (ganadas + perdidas) << endl;
		stats << "	Partidas Ganadas: " << ganadas << endl;
		stats << "	Partidas Perdidas: " << perdidas << endl;

		ok = true;
		stats.close();

	}
	else
	{
		ok = false;
		cout << "Error, el archivo 'stats.txt' no existe" << endl;
	}

	return ok;
}

//Conduce el desarrollo del juego y devuelve el ganador.
//Si se abandona, devuelve Nadie.
tJugador pasaCalculadora()
{
	//Variables
	tJugador turno;
	int total = 0, ultimoDigito = 0;
	const int META=31;
		//Inicializar partida
	srand(time(NULL));//Semilla
	turno = quienEmpieza();

	//Bucle de juego
	do
	{
		//Turno jugador
		if (turno == Jugador)
		{
			ultimoDigito = digitoPersona(ultimoDigito);
			turno = Automata;
		}
		//Turno bot
		else /*if (turno == Automata)*/
		{
			ultimoDigito = digitoAutomata(ultimoDigito);
			turno = Jugador;
		}
		total += ultimoDigito;
		cout << "Total = " << total << endl;
	}
	while ((total < META) && (ultimoDigito != 0));

	if (ultimoDigito == 0) turno = Nadie;
	//Si el jugador abandona, no gana nadie

	return turno;
}

//Decide aleatoriamente quien empieza la partida, si el automata o el jugador
tJugador quienEmpieza()
{
	if (rand() % 2)
	{
		cout << "Tu empiezas" << endl;
		return Jugador;
	}
	else
	{
		cout << "Empiezo yo" << endl;
		return Automata;
	}
}

//Define que numeros se encuentran en la misma fila que el ultimo pulsado
bool mismaFila(int ultimo, int nuevo)
{
	int filaUltimo, filaNuevo;
	filaUltimo = ((ultimo - 1)/3);
	filaNuevo = ((nuevo - 1)/3);
	return (filaUltimo) == (filaNuevo);
}

//Define que numeros se encuentran en la misma columna que el ultimo
bool mismaColumna(int ultimo, int nuevo)
{
	int columnaUltimo, columnaNuevo;
	columnaUltimo = (ultimo % 3);
	columnaNuevo = (nuevo % 3);
	return columnaUltimo == columnaNuevo;
}

//Determina que digitos se pueden pulsar en funcion de las reglas del juego
bool digitoValido(int ultimo, int nuevo)  //hay un bug
{
	if (ultimo == 0) return true;//Si es el primer turno, todos los numeros valen

	return ((mismaFila(ultimo, nuevo))||(mismaColumna(ultimo, nuevo)))&&(ultimo!=nuevo);
}

//Genera un digito aleatorio
int digitoAleatorio()
{
	return (rand() % 9) + 1;
}

//Devuelve un digito que cumpla las reglas del juego con respecto a ultimo.
int digitoAutomata(int ultimo)
{
	int digito;

	do
	{
	digito = digitoAleatorio();
	}
	while (!digitoValido(ultimo, digito));

	cout << "Elijo el numero " << digito << endl;

	return digito;
}

//Pide un digito al jugador. Solo devolvera un valor valido (entre 0 y 9).
//Para un valor no valido, mostrara un error.
int digitoPersona()
{
	int digito = -1;

	do
	{
		cin.sync(); //Por si quedan datos basura en el buffer
		cin >> digito;

		if (cin.fail())
		{
			cout << "Error! Introduce un digito" << endl;
			cin.clear();
		}

		else if (digito < 0 || digito > 9)
		{
		cout << "Error! Introduce un digito entre 0 y 9" << endl;
		digito = -1;
		}

	}
	while (digito == -1);

	return digito;
}

//Pide un digito al jugador mostrando el teclado. Solo devolvera un valor
//que cumpla las reglas del juego o 0. Para un valor no valido, mostrara un error.
int digitoPersona(int ultimo)
{
	int digito = -1; //-1 es mi error flag

	mostrarCalculadora(ultimo);

	do
	{
		digito = digitoPersona();
		if (!digitoValido(ultimo, digito))
		{
			cout << "Error! El digito debe estar en la misma fila y columna que el ultimo" << endl;
			digito = -1;
		}
	}
	while (digito == -1);

	cout << "Has elegido el " << digito << endl;

	return digito;
}

//Determina si el numero de la calculadora se muestra o no, en funcion de si es valido
char mNumero(int ultimo, int n)
{
	if(digitoValido(ultimo, n))
	{
		//system ("color 02");
		return char (n+int('0'));

	}
	else
	{
		//system ("color 04");
		return ' ';
	}
}

//Muestra los botones de la calculadora (solo los que se pueden pulsar en cada turno)
void mostrarCalculadora(int ultimo)
{
	for (int i = 7; i<10; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	for (int i = 4; i<7; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	for (int i = 1; i<4; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	//system ("color 07");
}
<commit_msg>Update Pasa_la_calculadora.cpp<commit_after>/*-------------------------------
PASA LA CALCULADORA
Autores:
Jaime Sevilla Molina
Victor Gonzalez
Fecha
2014/11
Version: 2.0
---------------------------------*/

//BIBLIOTECAS
#include <iostream>
#include <cstdlib>
#include <string>
#include <ctime>
#include <fstream>
#include <iomanip>

using namespace std;

//TIPOS PROPIOS
typedef enum tJugador
{
	Nadie,
	Jugador,
	Automata
};

//FUNCIONES
//FUNCIONES DE JUEGO

string saludar ();

//Dependiendo de quien gane, la despedida sera distinta
int despedirse (tJugador ganador, string nombre);

//Muestra un menu que permite al jugador jugar, salir, o ver las reglas del juego
int menu();

//Muestra las instrucciones del juego, siempre que su archivo no contenga errores
bool acerca();

//Anota el numero de partidas ganadas y perdidas del jugador
bool stats(int ganadas, int perdidas);

//Conduce el desarrollo del juego y devuelve el ganador.
//Si se abandona, devuelve Nadie.
tJugador pasaCalculadora();

//Decide aleatoriamente quien empieza.
tJugador quienEmpieza();

//Devuelve true si nuevo esta en la misma fila que ultimo
bool mismaFila(int ultimo, int nuevo);

//Devuelve true si nuevo esta en la misma columna que ultimo
bool mismaColumna(int ultimo, int nuevo);

//Devuelve true si nuevo cumple las reglas del juego con respecto a ultimo
//Si ultimo == 0, este es el primer digito de la partida, y devuelve true
bool digitoValido(int ultimo, int nuevo);

//FUNCIONES DE IA NIVEL 1
//Devuelve un digito del 1 al 9
int digitoAleatorio();

//Devuelve un digito que cumpla las reglas del juego con respecto a ultimo.
int digitoAutomata(int ultimo);

//FUNCIONES DE JUGADOR
//Pide un digito al jugador. Solo devolvera un valor valido (entre 0 y 9).
//Para un valor no valido, mostrara un error.
int digitoPersona();

//Pide un digito al jugador mostrando el teclado. Solo devolvera un valor
//que cumpla las reglas del juego o 0. Para un valor no valido, mostrara un error.
int digitoPersona(int ultimo);

//Determina si el numero de la calculadora se muestra o no, en funcion de si es valido
char mNumero(int ultimo, int n);

//Muestra los botones de la calculadora (solo los que se pueden pulsar en cada turno)
void mostrarCalculadora(int ultimo);

/* Las funciones a continuacion se implementaran en un futuro
//FUNCIONES DE INFORME
//Actualiza el archivo informePC.txt con los tres argumentos. En caso de no encontrar
//el archivo, lo crea y devuelve false; en otro caso devuelve true.
bool actInforme(int jugadas, int ganadas, int abandonos);

//FUNCIONES DE DIFICULTAD AVANZADA
int botDificil(int ultimo);

-----------------------------------------------------------------------------------*/

int main()
{
	tJugador ganador;
	int opcion;

	string nombre = saludar();
	//Bucle Menu
	do
	{
		opcion = menu();
		if(opcion == 1){
			ganador = pasaCalculadora();
			despedirse(ganador, nombre);
		}
		else if(opcion == 2) acerca();

	}
	while(opcion != 0);

	cout << "Hasta la proxima " << nombre << "(pulsa enter)";
	cin;

	return 0;
}

//Saluda al jugador y le pregunta su nombre
string saludar()
{
	string nombre;
	cout << "Bienvenido a Pasa la calculadora!" << endl;
	cout << "Como te llamas? ";
	cin >> nombre;
	cout << "Hola " << nombre << endl << endl;
	return nombre;
}

//Se despide del jugador, la despedida varia segun gane el jugador, el automata o ninguno de ellos (el jugador abandone)
int despedirse(tJugador ganador, string nombre)
{
	int ganadas = 0, perdidas = 0;
	if (ganador == Nadie){
		cout << "Abandonas, " << nombre << "? Ohhh..." << endl << endl;
	}
	else if (ganador == Jugador){
		cout << "Enhorabuena " << nombre << ", has ganado!" << endl << endl;
		ganadas = ganadas++;
	}
	else /*if (ganador == Automata)*/{
		cout << "Lo siento " << nombre << ", he ganado" << endl << endl;
		perdidas = perdidas++;
	}
	return ganadas, perdidas;
}

//Proporciona al jugador la posibilidad de jugar, ver las instrucciones del juego o salir.
int menu()
{
	int seleccionar = -1; //Error flag
	cout << "1 - Jugar" << endl;
	cout << "2 - Acerca de" << endl;
	cout << "0 - Salir" << endl;

	do
	{
		cin.sync(); //Por si quedan datos basura en el buffer
		cin >> seleccionar;

		if(cin.fail())
		{
			cout << "Error! Introduce un digito" << endl;
			cin.clear();
		}

		else if (seleccionar < 0 || seleccionar > 2)
		{
			cout << "Error! Introduce un digito entre 0 y 2" << endl;
			seleccionar = -1;
		}

	}
	while (seleccionar == -1);

	return seleccionar;
}

//Muestra el archivo "acerca.txt" siempre que este no contenga errores
bool acerca()
{

	bool ok;
	ifstream acerca;
	char c;

	acerca.open("acerca.txt");

	if(acerca.is_open())
	{
		acerca.get(c); //Lee el primer caracter

		while(!acerca.fail()) //Mientras la lectura no falle
		{
			cout << c;
			acerca.get(c); //Lee el siguiente caracter
		}

		ok = true;
		acerca.close();

	}
	else
	{
		ok = false;
		cout << "Error, el archivo 'acerca.txt' no existe" << endl;
	}

	return ok;
}

bool stats(int ganadas, int perdidas)
{

	bool ok;
	ofstream stats;

	stats.open("stats.txt");

	if(stats.is_open())
	{
		stats << "Partidas Jugadas: " << (ganadas + perdidas) << endl;
		stats << "	Partidas Ganadas: " << ganadas << endl;
		stats << "	Partidas Perdidas: " << perdidas << endl;

		ok = true;
		stats.close();

	}
	else
	{
		ok = false;
		cout << "Error, el archivo 'stats.txt' no existe" << endl;
	}

	return ok;
}

//Conduce el desarrollo del juego y devuelve el ganador.
//Si se abandona, devuelve Nadie.
tJugador pasaCalculadora()
{
	//Variables
	tJugador turno;
	int total = 0, ultimoDigito = 0;
	const int META=31;
		//Inicializar partida
	srand(time(NULL));//Semilla
	turno = quienEmpieza();

	//Bucle de juego
	do
	{
		//Turno jugador
		if (turno == Jugador)
		{
			ultimoDigito = digitoPersona(ultimoDigito);
			turno = Automata;
		}
		//Turno bot
		else /*if (turno == Automata)*/
		{
			ultimoDigito = digitoAutomata(ultimoDigito);
			turno = Jugador;
		}
		total += ultimoDigito;
		cout << "Total = " << total << endl;
	}
	while ((total < META) && (ultimoDigito != 0));

	if (ultimoDigito == 0) turno = Nadie;
	//Si el jugador abandona, no gana nadie

	return turno;
}

//Decide aleatoriamente quien empieza la partida, si el automata o el jugador
tJugador quienEmpieza()
{
	if (rand() % 2)
	{
		cout << "Tu empiezas" << endl;
		return Jugador;
	}
	else
	{
		cout << "Empiezo yo" << endl;
		return Automata;
	}
}

//Define que numeros se encuentran en la misma fila que el ultimo pulsado
bool mismaFila(int ultimo, int nuevo)
{
	int filaUltimo, filaNuevo;
	filaUltimo = ((ultimo - 1)/3);
	filaNuevo = ((nuevo - 1)/3);
	return (filaUltimo) == (filaNuevo);
}

//Define que numeros se encuentran en la misma columna que el ultimo
bool mismaColumna(int ultimo, int nuevo)
{
	int columnaUltimo, columnaNuevo;
	columnaUltimo = (ultimo % 3);
	columnaNuevo = (nuevo % 3);
	return columnaUltimo == columnaNuevo;
}

//Determina que digitos se pueden pulsar en funcion de las reglas del juego
bool digitoValido(int ultimo, int nuevo)  //hay un bug
{
	if (ultimo == 0) return true;//Si es el primer turno, todos los numeros valen

	return ((mismaFila(ultimo, nuevo))||(mismaColumna(ultimo, nuevo)))&&(ultimo!=nuevo);
}

//Genera un digito aleatorio
int digitoAleatorio()
{
	return (rand() % 9) + 1;
}

//Devuelve un digito que cumpla las reglas del juego con respecto a ultimo.
int digitoAutomata(int ultimo)
{
	int digito;

	do
	{
	digito = digitoAleatorio();
	}
	while (!digitoValido(ultimo, digito));

	cout << "Elijo el numero " << digito << endl;

	return digito;
}

//Pide un digito al jugador. Solo devolvera un valor valido (entre 0 y 9).
//Para un valor no valido, mostrara un error.
int digitoPersona()
{
	int digito = -1;

	do
	{
		cin.sync(); //Por si quedan datos basura en el buffer
		cin >> digito;

		if (cin.fail())
		{
			cout << "Error! Introduce un digito" << endl;
			cin.clear();
		}

		else if (digito < 0 || digito > 9)
		{
		cout << "Error! Introduce un digito entre 0 y 9" << endl;
		digito = -1;
		}

	}
	while (digito == -1);

	return digito;
}

//Pide un digito al jugador mostrando el teclado. Solo devolvera un valor
//que cumpla las reglas del juego o 0. Para un valor no valido, mostrara un error.
int digitoPersona(int ultimo)
{
	int digito = -1; //-1 es mi error flag

	mostrarCalculadora(ultimo);

	do
	{
		digito = digitoPersona();
		if (!digitoValido(ultimo, digito))
		{
			cout << "Error! El digito debe estar en la misma fila y columna que el ultimo" << endl;
			digito = -1;
		}
	}
	while (digito == -1);

	cout << "Has elegido el " << digito << endl;

	return digito;
}

//Determina si el numero de la calculadora se muestra o no, en funcion de si es valido
char mNumero(int ultimo, int n)
{
	if(digitoValido(ultimo, n))
	{
		return char (n+int('0'));

	}
	else
	{
		return ' ';
	}
}

//Muestra los botones de la calculadora (solo los que se pueden pulsar en cada turno)
void mostrarCalculadora(int ultimo)
{
	for (int i = 7; i<10; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	for (int i = 4; i<7; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	for (int i = 1; i<4; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
}
<|endoftext|>


<commit_before>// Copyright 2009, Google Inc.
// 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.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// 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
// OWNER 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.
//
// Author: wan@google.com (Zhanyong Wan)
//
// Tests for Google C++ Testing Framework (Google Test)
//
// Sometimes it's desirable to build most of Google Test's own tests
// by compiling a single file.  This file serves this purpose.
#include "test/gtest-filepath_test.cc"
#include "test/gtest-linked_ptr_test.cc"
#include "test/gtest-message_test.cc"
#include "test/gtest-options_test.cc"
#include "test/gtest-port_test.cc"
#include "test/gtest_pred_impl_unittest.cc"
#include "test/gtest_prod_test.cc"
#include "test/gtest-test-part_test.cc"
#include "test/gtest-typed-test_test.cc"
#include "test/gtest-typed-test2_test.cc"
#include "test/gtest_unittest.cc"
#include "test/production.cc"
<commit_msg>merging, cleaning up<commit_after>// Copyright 2009, Google Inc.
// 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.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// 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
// OWNER 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.
//
// Author: wan@google.com (Zhanyong Wan)
//
// Tests for Google C++ Testing Framework (Google Test)
//
// Sometimes it's desirable to build most of Google Test's own tests
// by compiling a single file.  This file serves this purpose.
#include "gtest-filepath_test.cc"
#include "gtest-linked_ptr_test.cc"
#include "gtest-message_test.cc"
#include "gtest-options_test.cc"
#include "gtest-port_test.cc"
#include "gtest_pred_impl_unittest.cc"
#include "gtest_prod_test.cc"
#include "gtest-test-part_test.cc"
#include "gtest-typed-test_test.cc"
#include "gtest-typed-test2_test.cc"
#include "gtest_unittest.cc"
#include "production.cc"
<|endoftext|>